Evict local live ranges if they can be reassigned.
authorAndrew Trick <atrick@apple.com>
Thu, 25 Jul 2013 18:35:19 +0000 (18:35 +0000)
committerAndrew Trick <atrick@apple.com>
Thu, 25 Jul 2013 18:35:19 +0000 (18:35 +0000)
The previous change to local live range allocation also suppressed
eviction of local ranges. In rare cases, this could result in more
expensive register choices. This commit actually revives a feature
that I added long ago: check if live ranges can be reassigned before
eviction. But now it only happens in rare cases of evicting a local
live range because another local live range wants a cheaper register.

The benefit is improved code size for some benchmarks on x86 and armv7.

I measured no significant compile time increase and performance
changes are noise.

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

lib/CodeGen/RegAllocGreedy.cpp
test/CodeGen/ARM/avoid-cpsr-rmw.ll
test/CodeGen/X86/StackColoring.ll
test/CodeGen/X86/legalize-shift-64.ll
test/CodeGen/X86/misched-matmul.ll

index 55f2fc68a752c42561d7633cf2c15e84b2a21158..79253715c337ad1285f7183341f15b7e164672e8 100644 (file)
@@ -261,6 +261,7 @@ private:
   bool calcCompactRegion(GlobalSplitCandidate&);
   void splitAroundRegion(LiveRangeEdit&, ArrayRef<unsigned>);
   void calcGapWeights(unsigned, SmallVectorImpl<float>&);
+  unsigned canReassign(LiveInterval &VirtReg, unsigned PhysReg);
   bool shouldEvict(LiveInterval &A, bool, LiveInterval &B, bool);
   bool canEvictInterference(LiveInterval&, unsigned, bool, EvictionCost&);
   void evictInterference(LiveInterval&, unsigned,
@@ -494,6 +495,31 @@ unsigned RAGreedy::tryAssign(LiveInterval &VirtReg,
 //                         Interference eviction
 //===----------------------------------------------------------------------===//
 
+unsigned RAGreedy::canReassign(LiveInterval &VirtReg, unsigned PrevReg) {
+  AllocationOrder Order(VirtReg.reg, *VRM, RegClassInfo);
+  unsigned PhysReg;
+  while ((PhysReg = Order.next())) {
+    if (PhysReg == PrevReg)
+      continue;
+
+    MCRegUnitIterator Units(PhysReg, TRI);
+    for (; Units.isValid(); ++Units) {
+      // Instantiate a "subquery", not to be confused with the Queries array.
+      LiveIntervalUnion::Query subQ(&VirtReg, &Matrix->getLiveUnions()[*Units]);
+      if (subQ.checkInterference())
+        break;
+    }
+    // If no units have interference, break out with the current PhysReg.
+    if (!Units.isValid())
+      break;
+  }
+  if (PhysReg)
+    DEBUG(dbgs() << "can reassign: " << VirtReg << " from "
+          << PrintReg(PrevReg, TRI) << " to " << PrintReg(PhysReg, TRI)
+          << '\n');
+  return PhysReg;
+}
+
 /// shouldEvict - determine if A should evict the assigned live range B. The
 /// eviction policy defined by this function together with the allocation order
 /// defined by enqueue() decides which registers ultimately end up being split
@@ -594,8 +620,10 @@ bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg,
       // If !MaxCost.isMax(), then we're just looking for a cheap register.
       // Evicting another local live range in this case could lead to suboptimal
       // coloring.
-      if (!MaxCost.isMax() && IsLocal && LIS->intervalIsInOneMBB(*Intf))
+      if (!MaxCost.isMax() && IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
+          !canReassign(*Intf, PhysReg)) {
         return false;
+      }
       // Finally, apply the eviction policy for non-urgent evictions.
       if (!shouldEvict(VirtReg, IsHint, *Intf, BreaksHint))
         return false;
index 13d8da67a53d591f91f6297b4688c3c4a014011c..0217a4a8fb833c66ae6560c0dece3f53b2d5e55e 100644 (file)
@@ -1,7 +1,5 @@
-; RUN: true
-; Disabled for a single commit only.
-; disabled: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a9 | FileCheck %s
-; disabled: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=swift     | FileCheck %s
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a9 | FileCheck %s
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=swift     | FileCheck %s
 ; Avoid some 's' 16-bit instruction which partially update CPSR (and add false
 ; dependency) when it isn't dependent on last CPSR defining instruction.
 ; rdar://8928208
index fd2ad91dd6f9b7d022eb57b6d72ef5db6dac758c..f1d92965c496e907d624c2baeaae792b050d6446 100644 (file)
@@ -1,7 +1,5 @@
-; RUN: true
-; Disabled for a single commit only
-; disabled: llc -mcpu=corei7 -no-stack-coloring=false < %s | FileCheck %s --check-prefix=YESCOLOR
-; disabled: llc -mcpu=corei7 -no-stack-coloring=true  < %s | FileCheck %s --check-prefix=NOCOLOR
+; RUN: llc -mcpu=corei7 -no-stack-coloring=false < %s | FileCheck %s --check-prefix=YESCOLOR
+; RUN: llc -mcpu=corei7 -no-stack-coloring=true  < %s | FileCheck %s --check-prefix=NOCOLOR
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
 target triple = "x86_64-apple-macosx10.8.0"
index 3cdd49412a84195930317aebdc816af1f2ce333d..77364688afe4391360e92c8163a8beec46123249 100644 (file)
@@ -1,6 +1,4 @@
-; RUN: true
-; disabled: llc -mcpu=generic -mtriple=i686-unknown-unknown < %s | FileCheck %s
-; Disabled for a single commit only.
+; RUN: llc -mcpu=generic -mtriple=i686-unknown-unknown < %s | FileCheck %s
 define i64 @test1(i32 %xx, i32 %test) nounwind {
   %conv = zext i32 %xx to i64
   %and = and i32 %test, 7
index 7fd78824e789d0a6346d58110f01914b89369eb6..6b676071152aa9d6d569a740ebeb0522b705136c 100644 (file)
@@ -7,7 +7,7 @@
 ; flag to disable it for this test case.
 ;
 ; CHECK: @wrap_mul4
-; CHECK: 21 regalloc - Number of spills inserted
+; CHECK: 22 regalloc - Number of spills inserted
 
 define void @wrap_mul4(double* nocapture %Out, [4 x double]* nocapture %A, [4 x double]* nocapture %B) #0 {
 entry: