[llvm-commits] [llvm] r122445 - /llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp

Jakob Stoklund Olesen stoklund at 2pi.dk
Wed Dec 22 14:01:31 PST 2010


Author: stoklund
Date: Wed Dec 22 16:01:30 2010
New Revision: 122445

URL: http://llvm.org/viewvc/llvm-project?rev=122445&view=rev
Log:
When RegAllocGreedy decides to spill the interferences of the current register,
pick the victim with the lowest total spill weight.

Modified:
    llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp

Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=122445&r1=122444&r2=122445&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Wed Dec 22 16:01:30 2010
@@ -94,10 +94,13 @@
   bool reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg);
   unsigned findInterferenceFreeReg(MachineLoopRange*,
                                    LiveInterval&, AllocationOrder&);
+  float calcInterferenceWeight(LiveInterval&, unsigned);
 
   unsigned tryReassign(LiveInterval&, AllocationOrder&);
   unsigned trySplit(LiveInterval&, AllocationOrder&,
                     SmallVectorImpl<LiveInterval*>&);
+  unsigned trySpillInterferences(LiveInterval&, AllocationOrder&,
+                                 SmallVectorImpl<LiveInterval*>&);
 };
 } // end anonymous namespace
 
@@ -164,6 +167,11 @@
   return Priority;
 }
 
+
+//===----------------------------------------------------------------------===//
+//                         Register Reassignment
+//===----------------------------------------------------------------------===//
+
 // Check interference without using the cache.
 bool RAGreedy::checkUncachedInterference(LiveInterval &VirtReg,
                                          unsigned PhysReg) {
@@ -263,6 +271,11 @@
   return 0;
 }
 
+
+//===----------------------------------------------------------------------===//
+//                              Loop Splitting
+//===----------------------------------------------------------------------===//
+
 /// findInterferenceFreeReg - Find a physical register in Order where Loop has
 /// no interferences with VirtReg.
 unsigned RAGreedy::findInterferenceFreeReg(MachineLoopRange *Loop,
@@ -338,29 +351,81 @@
   return 0;
 }
 
-unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
-                                SmallVectorImpl<LiveInterval*> &SplitVRegs) {
-  // Populate a list of physical register spill candidates.
-  SmallVector<unsigned, 8> PhysRegSpillCands;
 
-  // Check for an available register in this class.
+//===----------------------------------------------------------------------===//
+//                                Spilling
+//===----------------------------------------------------------------------===//
+
+/// calcInterferenceWeight - Calculate the combined spill weight of
+/// interferences when assigning VirtReg to PhysReg.
+float RAGreedy::calcInterferenceWeight(LiveInterval &VirtReg, unsigned PhysReg){
+  float Sum = 0;
+  for (const unsigned *AI = TRI->getOverlaps(PhysReg); *AI; ++AI) {
+    LiveIntervalUnion::Query &Q = query(VirtReg, *AI);
+    Q.collectInterferingVRegs();
+    if (Q.seenUnspillableVReg())
+      return HUGE_VALF;
+    for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i)
+      Sum += Q.interferingVRegs()[i]->weight;
+  }
+  return Sum;
+}
+
+/// trySpillInterferences - Try to spill interfering registers instead of the
+/// current one. Only do it if the accumulated spill weight is smaller than the
+/// current spill weight.
+unsigned RAGreedy::trySpillInterferences(LiveInterval &VirtReg,
+                                         AllocationOrder &Order,
+                                     SmallVectorImpl<LiveInterval*> &NewVRegs) {
+  NamedRegionTimer T("Spill Interference", TimerGroupName, TimePassesIsEnabled);
+  unsigned BestPhys = 0;
+  float BestWeight;
+
+  Order.rewind();
+  while (unsigned PhysReg = Order.next()) {
+    float Weight = calcInterferenceWeight(VirtReg, PhysReg);
+    if (Weight == HUGE_VALF || Weight >= VirtReg.weight)
+      continue;
+    if (!BestPhys || Weight < BestWeight)
+      BestPhys = PhysReg, BestWeight = Weight;
+  }
+
+  // No candidates found.
+  if (!BestPhys)
+    return 0;
+
+  // Collect all interfering registers.
+  SmallVector<LiveInterval*, 8> Spills;
+  for (const unsigned *AI = TRI->getOverlaps(BestPhys); *AI; ++AI) {
+    LiveIntervalUnion::Query &Q = query(VirtReg, *AI);
+    Spills.append(Q.interferingVRegs().begin(), Q.interferingVRegs().end());
+    for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) {
+      LiveInterval *VReg = Q.interferingVRegs()[i];
+      PhysReg2LiveUnion[*AI].extract(*VReg);
+      VRM->clearVirt(VReg->reg);
+    }
+  }
+
+  // Spill them all.
+  DEBUG(dbgs() << "spilling " << Spills.size() << " interferences with weight "
+               << BestWeight << '\n');
+  for (unsigned i = 0, e = Spills.size(); i != e; ++i)
+    spiller().spill(Spills[i], NewVRegs, Spills);
+  return BestPhys;
+}
+
+
+//===----------------------------------------------------------------------===//
+//                            Main Entry Point
+//===----------------------------------------------------------------------===//
+
+unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
+                                 SmallVectorImpl<LiveInterval*> &SplitVRegs) {
+  // First try assigning a free register.
   AllocationOrder Order(VirtReg.reg, *VRM, ReservedRegs);
   while (unsigned PhysReg = Order.next()) {
-    // Check interference and as a side effect, intialize queries for this
-    // VirtReg and its aliases.
-    unsigned InterfReg = checkPhysRegInterference(VirtReg, PhysReg);
-    if (InterfReg == 0) {
-      // Found an available register.
+    if (!checkPhysRegInterference(VirtReg, PhysReg))
       return PhysReg;
-    }
-    assert(!VirtReg.empty() && "Empty VirtReg has interference");
-    LiveInterval *InterferingVirtReg =
-      Queries[InterfReg].firstInterference().liveUnionPos().value();
-
-    // The current VirtReg must either be spillable, or one of its interferences
-    // must have less spill weight.
-    if (InterferingVirtReg->weight < VirtReg.weight )
-      PhysRegSpillCands.push_back(PhysReg);
   }
 
   // Try to reassign interferences.
@@ -373,26 +438,13 @@
     return PhysReg;
 
   // Try to spill another interfering reg with less spill weight.
-  NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled);
-  //
-  // FIXME: do this in two steps: (1) check for unspillable interferences while
-  // accumulating spill weight; (2) spill the interferences with lowest
-  // aggregate spill weight.
-  for (SmallVectorImpl<unsigned>::iterator PhysRegI = PhysRegSpillCands.begin(),
-         PhysRegE = PhysRegSpillCands.end(); PhysRegI != PhysRegE; ++PhysRegI) {
-
-    if (!spillInterferences(VirtReg, *PhysRegI, SplitVRegs)) continue;
-
-    assert(checkPhysRegInterference(VirtReg, *PhysRegI) == 0 &&
-           "Interference after spill.");
-    // Tell the caller to allocate to this newly freed physical register.
-    return *PhysRegI;
-  }
+  PhysReg = trySpillInterferences(VirtReg, Order, SplitVRegs);
+  if (PhysReg)
+    return PhysReg;
 
-  // No other spill candidates were found, so spill the current VirtReg.
-  DEBUG(dbgs() << "spilling: " << VirtReg << '\n');
+  // Finally spill VirtReg itself.
+  NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled);
   SmallVector<LiveInterval*, 1> pendingSpills;
-
   spiller().spill(&VirtReg, SplitVRegs, pendingSpills);
 
   // The live virtual register requesting allocation was spilled, so tell





More information about the llvm-commits mailing list