[llvm] r231064 - During PHI elimination, split critical edges that move copies out of loops.

Daniel Jasper djasper at google.com
Tue Mar 3 02:23:12 PST 2015


Author: djasper
Date: Tue Mar  3 04:23:11 2015
New Revision: 231064

URL: http://llvm.org/viewvc/llvm-project?rev=231064&view=rev
Log:
During PHI elimination, split critical edges that move copies out of loops.

This prevents the behavior observed in llvm.org/PR22369. I am not sure
whether I am reading the code correctly, but the early exit based on
isLiveOutPastPHIs() seems to make the wrong assumption that
RegisterCoalescer won't be able to coalesce those copies later.

This change hides the new behavior behind -no-phi-elim-live-out-early-exit
as it currently breaks four tests:
 * Assertion in:
     CodeGen/Hexagon/hwloop-cleanup.ll
 * Worse code in:
     CodeGen/X86/coalescer-commute4.ll
     CodeGen/X86/phys_subreg_coalesce-2.ll
     CodeGen/X86/zlib-longest-match.ll
   The root cause here seems to be that the heuristic that determines
   the visitation order in RegisterCoalescer gets less lucky.

Modified:
    llvm/trunk/lib/CodeGen/PHIElimination.cpp
    llvm/trunk/test/CodeGen/X86/phielim-split.ll

Modified: llvm/trunk/lib/CodeGen/PHIElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PHIElimination.cpp?rev=231064&r1=231063&r2=231064&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PHIElimination.cpp (original)
+++ llvm/trunk/lib/CodeGen/PHIElimination.cpp Tue Mar  3 04:23:11 2015
@@ -46,6 +46,10 @@ SplitAllCriticalEdges("phi-elim-split-al
                       cl::Hidden, cl::desc("Split all critical edges during "
                                            "PHI elimination"));
 
+static cl::opt<bool> NoPhiElimLiveOutEarlyExit(
+    "no-phi-elim-live-out-early-exit", cl::init(false), cl::Hidden,
+    cl::desc("Do not use an early exit if isLiveOutPastPHIs returns true."));
+
 namespace {
   class PHIElimination : public MachineFunctionPass {
     MachineRegisterInfo *MRI; // Machine register information
@@ -573,12 +577,14 @@ bool PHIElimination::SplitPHIEdges(Machi
       // there is a risk it may not be coalesced away.
       //
       // If the copy would be a kill, there is no need to split the edge.
-      if (!isLiveOutPastPHIs(Reg, PreMBB) && !SplitAllCriticalEdges)
+      bool ShouldSplit = isLiveOutPastPHIs(Reg, PreMBB);
+      if (!ShouldSplit && !NoPhiElimLiveOutEarlyExit)
         continue;
-
-      DEBUG(dbgs() << PrintReg(Reg) << " live-out before critical edge BB#"
-                   << PreMBB->getNumber() << " -> BB#" << MBB.getNumber()
-                   << ": " << *BBI);
+      if (ShouldSplit) {
+        DEBUG(dbgs() << PrintReg(Reg) << " live-out before critical edge BB#"
+                     << PreMBB->getNumber() << " -> BB#" << MBB.getNumber()
+                     << ": " << *BBI);
+      }
 
       // If Reg is not live-in to MBB, it means it must be live-in to some
       // other PreMBB successor, and we can avoid the interference by splitting
@@ -588,7 +594,7 @@ bool PHIElimination::SplitPHIEdges(Machi
       // is likely to be left after coalescing. If we are looking at a loop
       // exiting edge, split it so we won't insert code in the loop, otherwise
       // don't bother.
-      bool ShouldSplit = !isLiveIn(Reg, &MBB) || SplitAllCriticalEdges;
+      ShouldSplit = ShouldSplit && !isLiveIn(Reg, &MBB);
 
       // Check for a loop exiting edge.
       if (!ShouldSplit && CurLoop != PreLoop) {
@@ -603,7 +609,7 @@ bool PHIElimination::SplitPHIEdges(Machi
         // Split unless this edge is entering CurLoop from an outer loop.
         ShouldSplit = PreLoop && !PreLoop->contains(CurLoop);
       }
-      if (!ShouldSplit)
+      if (!ShouldSplit && !SplitAllCriticalEdges)
         continue;
       if (!PreMBB->SplitCriticalEdge(&MBB, this)) {
         DEBUG(dbgs() << "Failed to split critical edge.\n");

Modified: llvm/trunk/test/CodeGen/X86/phielim-split.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/phielim-split.ll?rev=231064&r1=231063&r2=231064&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/phielim-split.ll (original)
+++ llvm/trunk/test/CodeGen/X86/phielim-split.ll Tue Mar  3 04:23:11 2015
@@ -1,4 +1,4 @@
-; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs -no-phi-elim-live-out-early-exit | FileCheck %s
 target triple = "x86_64-apple-macosx10.8.0"
 
 ; The critical edge from for.cond to if.end2 should be split to avoid injecting
@@ -28,3 +28,40 @@ if.end2:
   %add = add nsw i32 %r.0, %b
   ret i32 %add
 }
+
+; CHECK: split_live_out
+; CHECK: %while.body
+; CHECK: cmp
+; CHECK-NEXT: ja
+define i8* @split_live_out(i32 %value, i8* %target) nounwind uwtable readonly ssp {
+entry:
+  %cmp10 = icmp ugt i32 %value, 127
+  br i1 %cmp10, label %while.body.preheader, label %while.end
+
+while.body.preheader:                             ; preds = %entry
+  br label %while.body
+
+while.body:                                       ; preds = %while.body.preheader, %while.body
+  %target.addr.012 = phi i8* [ %incdec.ptr, %while.body ], [ %target, %while.body.preheader ]
+  %value.addr.011 = phi i32 [ %shr, %while.body ], [ %value, %while.body.preheader ]
+  %or = or i32 %value.addr.011, 128
+  %conv = trunc i32 %or to i8
+  store i8 %conv, i8* %target.addr.012, align 1
+  %shr = lshr i32 %value.addr.011, 7
+  %incdec.ptr = getelementptr inbounds i8, i8* %target.addr.012, i64 1
+  %cmp = icmp ugt i32 %value.addr.011, 16383
+  br i1 %cmp, label %while.body, label %while.end.loopexit
+
+while.end.loopexit:                               ; preds = %while.body
+  %incdec.ptr.lcssa = phi i8* [ %incdec.ptr, %while.body ]
+  %shr.lcssa = phi i32 [ %shr, %while.body ]
+  br label %while.end
+
+while.end:                                        ; preds = %while.end.loopexit, %entry
+  %target.addr.0.lcssa = phi i8* [ %target, %entry ], [ %incdec.ptr.lcssa, %while.end.loopexit ]
+  %value.addr.0.lcssa = phi i32 [ %value, %entry ], [ %shr.lcssa, %while.end.loopexit ]
+  %conv1 = trunc i32 %value.addr.0.lcssa to i8
+  store i8 %conv1, i8* %target.addr.0.lcssa, align 1
+  %incdec.ptr3 = getelementptr inbounds i8, i8* %target.addr.0.lcssa, i64 1
+  ret i8* %incdec.ptr3
+}





More information about the llvm-commits mailing list