Hoist spills within a basic block.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Sat, 9 Jul 2011 00:25:03 +0000 (00:25 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Sat, 9 Jul 2011 00:25:03 +0000 (00:25 +0000)
Try to move spills as early as possible in their basic block. This can
help eliminate interferences by shortening the live range being
spilled.

This fixes PR10221.

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

lib/CodeGen/InlineSpiller.cpp
test/CodeGen/X86/reghinting.ll [new file with mode: 0644]

index 4bd35c3812aa8ab932303357ca4125e7c2ad3d8f..44e87ae97235d09b5552e8388ce3d57af9a7949c 100644 (file)
@@ -303,7 +303,8 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
   // Best spill candidate seen so far. This must dominate UseVNI.
   SibValueInfo SVI(UseReg, UseVNI);
   MachineBasicBlock *UseMBB = LIS.getMBBFromIndex(UseVNI->def);
-  unsigned SpillDepth = Loops.getLoopDepth(UseMBB);
+  MachineBasicBlock *SpillMBB = UseMBB;
+  unsigned SpillDepth = Loops.getLoopDepth(SpillMBB);
   bool SeenOrigPHI = false; // Original PHI met.
 
   do {
@@ -316,15 +317,39 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
     // Is this value a better spill candidate?
     if (!isRegToSpill(Reg)) {
       MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def);
-      if (MBB != UseMBB && MDT.dominates(MBB, UseMBB)) {
+      if (MBB == SpillMBB) {
+        // This is an alternative def earlier in the same MBB.
+        // Hoist the spill as far as possible in SpillMBB. This can ease
+        // register pressure:
+        //
+        //   x = def
+        //   y = use x
+        //   s = copy x
+        //
+        // Hoisting the spill of s to immediately after the def removes the
+        // interference between x and y:
+        //
+        //   x = def
+        //   spill x
+        //   y = use x<kill>
+        //
+        if (VNI->def < SVI.SpillVNI->def) {
+          DEBUG(dbgs() << "  hoist in BB#" << MBB->getNumber() << ": "
+                       << PrintReg(Reg) << ':' << VNI->id << '@' << VNI->def
+                       << '\n');
+          SVI.SpillReg = Reg;
+          SVI.SpillVNI = VNI;
+        }
+      } else if (MBB != UseMBB && MDT.dominates(MBB, UseMBB)) {
         // This is a valid spill location dominating UseVNI.
         // Prefer to spill at a smaller loop depth.
         unsigned Depth = Loops.getLoopDepth(MBB);
-        if (Depth < SpillDepth) {
+        if (Depth <= SpillDepth) {
           DEBUG(dbgs() << "  spill depth " << Depth << ": " << PrintReg(Reg)
                        << ':' << VNI->id << '@' << VNI->def << '\n');
           SVI.SpillReg = Reg;
           SVI.SpillVNI = VNI;
+          SpillMBB = MBB;
           SpillDepth = Depth;
         }
       }
diff --git a/test/CodeGen/X86/reghinting.ll b/test/CodeGen/X86/reghinting.ll
new file mode 100644 (file)
index 0000000..87f65ed
--- /dev/null
@@ -0,0 +1,35 @@
+; RUN: llc < %s -mtriple=x86_64-apple-macosx | FileCheck %s
+; PR10221
+
+;; The registers %x and %y must both spill across the finit call.
+;; Check that they are spilled early enough that not copies are needed for the
+;; fadd and fpext.
+
+; CHECK: pr10221
+; CHECK-NOT: movaps
+; CHECK:      movss
+; CHECK-NEXT: movss
+; CHECK-NEXT: addss
+; CHECK-NEXT: cvtss2sd
+; CHECK-NEXT: finit
+
+define i32 @pr10221(float %x, float %y, i8** nocapture %_retval) nounwind uwtable ssp {
+entry:
+  %add = fadd float %x, %y
+  %conv = fpext float %add to double
+  %call = tail call i32 @finit(double %conv) nounwind
+  %tobool = icmp eq i32 %call, 0
+  br i1 %tobool, label %return, label %if.end
+
+if.end:                                           ; preds = %entry
+  tail call void @foo(float %x, float %y) nounwind
+  br label %return
+
+return:                                           ; preds = %entry, %if.end
+  %retval.0 = phi i32 [ 0, %if.end ], [ 5, %entry ]
+  ret i32 %retval.0
+}
+
+declare i32 @finit(double)
+
+declare void @foo(float, float)