Fix a bug in spill weight computation. If the alias is a super-register, and the...
authorEvan Cheng <evan.cheng@apple.com>
Mon, 23 Mar 2009 22:57:19 +0000 (22:57 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Mon, 23 Mar 2009 22:57:19 +0000 (22:57 +0000)
e.g. allocating for GR32, bh is not used, updating bl spill weight.
     bl should get the same spill weight otherwise it will be choosen
     as a spill candidate since spilling bh doesn't make ebx available.
This fix PR2866.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67574 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/RegAllocLinearScan.cpp
test/CodeGen/X86/2009-03-23-LinearScanBug.ll [new file with mode: 0644]

index 912135a57f6cbedc1188ea0e0a7dac8cda111ffd..26af53ef83223aff385b85ab289c851ac10ef72d 100644 (file)
@@ -155,6 +155,10 @@ namespace {
     /// is available, or spill.
     void assignRegOrStackSlotAtInterval(LiveInterval* cur);
 
+    void updateSpillWeights(std::vector<float> &Weights,
+                            unsigned reg, float weight,
+                            const TargetRegisterClass *RC);
+
     /// findIntervalsToSpill - Determine the intervals to spill for the
     /// specified interval. It's passed the physical registers whose spill
     /// weight is the lowest among all the registers whose live intervals
@@ -515,12 +519,35 @@ void RALinScan::processInactiveIntervals(unsigned CurPoint)
 
 /// updateSpillWeights - updates the spill weights of the specifed physical
 /// register and its weight.
-static void updateSpillWeights(std::vector<float> &Weights,
-                               unsigned reg, float weight,
-                               const TargetRegisterInfo *TRI) {
+void RALinScan::updateSpillWeights(std::vector<float> &Weights,
+                                   unsigned reg, float weight,
+                                   const TargetRegisterClass *RC) {
+  SmallSet<unsigned, 4> Processed;
+  SmallSet<unsigned, 4> SuperAdded;
+  SmallVector<unsigned, 4> Supers;
   Weights[reg] += weight;
-  for (const unsigned* as = TRI->getAliasSet(reg); *as; ++as)
+  Processed.insert(reg);
+  for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) {
     Weights[*as] += weight;
+    Processed.insert(*as);
+    if (tri_->isSubRegister(*as, reg) &&
+        SuperAdded.insert(*as) &&
+        RC->contains(*as)) {
+      Supers.push_back(*as);
+    }
+  }
+
+  // If the alias is a super-register, and the super-register is in the
+  // register class we are trying to allocate. Then add the weight to all
+  // sub-registers of the super-register even if they are not aliases.
+  // e.g. allocating for GR32, bh is not used, updating bl spill weight.
+  //      bl should get the same spill weight otherwise it will be choosen
+  //      as a spill candidate since spilling bh doesn't make ebx available.
+  for (unsigned i = 0, e = Supers.size(); i != e; ++i) {
+      for (const unsigned *sr = tri_->getSubRegisters(Supers[i]); *sr; ++sr)
+        if (!Processed.count(*sr))
+          Weights[*sr] += weight;
+  }
 }
 
 static
@@ -817,7 +844,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
   std::vector<float> SpillWeights(tri_->getNumRegs(), 0.0f);
   for (std::vector<std::pair<unsigned, float> >::iterator
        I = SpillWeightsToAdd.begin(), E = SpillWeightsToAdd.end(); I != E; ++I)
-    updateSpillWeights(SpillWeights, I->first, I->second, tri_);
+    updateSpillWeights(SpillWeights, I->first, I->second, RC);
   
   // for each interval in active, update spill weights.
   for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end();
@@ -826,14 +853,14 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
     assert(TargetRegisterInfo::isVirtualRegister(reg) &&
            "Can only allocate virtual registers!");
     reg = vrm_->getPhys(reg);
-    updateSpillWeights(SpillWeights, reg, i->first->weight, tri_);
+    updateSpillWeights(SpillWeights, reg, i->first->weight, RC);
   }
  
   DOUT << "\tassigning stack slot at interval "<< *cur << ":\n";
 
   // Find a register to spill.
   float minWeight = HUGE_VALF;
-  unsigned minReg = 0; /*cur->preference*/;  // Try the preferred register first.
+  unsigned minReg = 0; /*cur->preference*/;  // Try the pref register first.
 
   bool Found = false;
   std::vector<std::pair<unsigned,float> > RegsWeights;
diff --git a/test/CodeGen/X86/2009-03-23-LinearScanBug.ll b/test/CodeGen/X86/2009-03-23-LinearScanBug.ll
new file mode 100644 (file)
index 0000000..0a4501e
--- /dev/null
@@ -0,0 +1,23 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -fast
+
+define fastcc void @optimize_bit_field() nounwind {
+bb4:
+        %a = load i32* null             ; <i32> [#uses=1]
+        %s = load i32* getelementptr (i32* null, i32 1)         ; <i32> [#uses=1]
+        %z = load i32* getelementptr (i32* null, i32 2)         ; <i32> [#uses=1]
+        %r = bitcast i32 0 to i32          ; <i32> [#uses=1]
+        %q = trunc i32 %z to i8            ; <i8> [#uses=1]
+        %b = icmp eq i8 0, %q              ; <i1> [#uses=1]
+        br i1 %b, label %bb73, label %bb72
+
+bb72:      ; preds = %bb4
+        %f = tail call fastcc i32 @gen_lowpart(i32 %r, i32 %a) nounwind              ; <i32> [#uses=1]
+        br label %bb73
+
+bb73:         ; preds = %bb72, %bb4
+        %y = phi i32 [ %f, %bb72 ], [ %s, %bb4 ]          ; <i32> [#uses=1]
+        store i32 %y, i32* getelementptr (i32* null, i32 3)
+        unreachable
+}
+
+declare fastcc i32 @gen_lowpart(i32, i32) nounwind