[llvm] r363619 - Teach getSCEVAtScope how to handle loop phis w/invariant operands in loops w/taken backedges

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 17 14:06:17 PDT 2019


Author: reames
Date: Mon Jun 17 14:06:17 2019
New Revision: 363619

URL: http://llvm.org/viewvc/llvm-project?rev=363619&view=rev
Log:
Teach getSCEVAtScope how to handle loop phis w/invariant operands in loops w/taken backedges

This patch really contains two pieces:
    Teach SCEV how to fold a phi in the header of a loop to the value on the backedge when a) the backedge is known to execute at least once, and b) the value is safe to use globally within the scope dominated by the original phi.
    Teach IndVarSimplify's rewriteLoopExitValues to allow loop invariant expressions which already exist (and thus don't need new computation inserted) even in loops where we can't optimize away other uses.

Differential Revision: https://reviews.llvm.org/D63224


Modified:
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll
    llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=363619&r1=363618&r2=363619&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Jun 17 14:06:17 2019
@@ -8122,27 +8122,35 @@ const SCEV *ScalarEvolution::computeSCEV
           // count.  If so, we may be able to force computation of the exit
           // value.
           const SCEV *BackedgeTakenCount = getBackedgeTakenCount(LI);
-          if (const SCEVConstant *BTCC =
-                dyn_cast<SCEVConstant>(BackedgeTakenCount)) {
-
-            // This trivial case can show up in some degenerate cases where
-            // the incoming IR has not yet been fully simplified.
-            if (BTCC->getValue()->isZero()) {
-              Value *InitValue = nullptr;
-              bool MultipleInitValues = false;
-              for (unsigned i = 0; i < PN->getNumIncomingValues(); i++) {
-                if (!LI->contains(PN->getIncomingBlock(i))) {
-                  if (!InitValue)
-                    InitValue = PN->getIncomingValue(i);
-                  else if (InitValue != PN->getIncomingValue(i)) {
-                    MultipleInitValues = true;
-                    break;
-                  }
+          // This trivial case can show up in some degenerate cases where
+          // the incoming IR has not yet been fully simplified.
+          if (BackedgeTakenCount->isZero()) {
+            Value *InitValue = nullptr;
+            bool MultipleInitValues = false;
+            for (unsigned i = 0; i < PN->getNumIncomingValues(); i++) {
+              if (!LI->contains(PN->getIncomingBlock(i))) {
+                if (!InitValue)
+                  InitValue = PN->getIncomingValue(i);
+                else if (InitValue != PN->getIncomingValue(i)) {
+                  MultipleInitValues = true;
+                  break;
                 }
               }
-              if (!MultipleInitValues && InitValue)
-                return getSCEV(InitValue);
             }
+            if (!MultipleInitValues && InitValue)
+              return getSCEV(InitValue);
+          }
+          // Do we have a loop invariant value flowing around the backedge
+          // for a loop which must execute the backedge?
+          if (!isa<SCEVCouldNotCompute>(BackedgeTakenCount) &&
+              isKnownPositive(BackedgeTakenCount) &&
+              PN->getNumIncomingValues() == 2) {
+            unsigned InLoopPred = LI->contains(PN->getIncomingBlock(0)) ? 0 : 1;
+            const SCEV *OnBackedge = getSCEV(PN->getIncomingValue(InLoopPred));
+            if (IsAvailableOnEntry(LI, DT, OnBackedge, PN->getParent()))
+              return OnBackedge;
+          }
+          if (auto *BTCC = dyn_cast<SCEVConstant>(BackedgeTakenCount)) {
             // Okay, we know how many times the containing loop executes.  If
             // this is a constant evolving PHI node, get the final value at
             // the specified iteration number.

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=363619&r1=363618&r2=363619&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Mon Jun 17 14:06:17 2019
@@ -635,9 +635,12 @@ bool IndVarSimplify::rewriteLoopExitValu
 
         // Computing the value outside of the loop brings no benefit if it is
         // definitely used inside the loop in a way which can not be optimized
-        // away.
+        // away.  Avoid doing so unless we know we have a value which computes
+        // the ExitValue already.  TODO: This should be merged into SCEV
+        // expander to leverage its knowledge of existing expressions.
         if (ReplaceExitValue != AlwaysRepl &&
-            !isa<SCEVConstant>(ExitValue) && hasHardUserWithinLoop(L, Inst))
+            !isa<SCEVConstant>(ExitValue) && !isa<SCEVUnknown>(ExitValue) &&
+            hasHardUserWithinLoop(L, Inst))
           continue;
 
         bool HighCost = Rewriter.isHighCostExpansion(ExitValue, L, Inst);

Modified: llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll?rev=363619&r1=363618&r2=363619&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll Mon Jun 17 14:06:17 2019
@@ -153,10 +153,34 @@ loopexit:		; preds = %loop
 define i32 @unroll_phi_select_constant_nonzero(i32 %arg1, i32 %arg2) {
 ; CHECK-LABEL: @unroll_phi_select_constant_nonzero(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 [[ARG2:%.*]]
+;
+entry:
+  br label %loop
+
+loop:
+  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
+  %selector = phi i32 [%arg1, %entry], [%arg2, %loop]
+  %i.next = add nsw nuw i32 %i, 1
+  %c = icmp ult i32 %i, 4
+  br i1 %c, label %loop, label %loopexit
+
+loopexit:
+  ret i32 %selector
+}
+
+declare i32 @f()
+
+; After LCSSA formation, there's no LCSSA phi for %f since it isn't directly
+; used outside the loop, and thus we can't directly replace %selector w/ %f.
+define i32 @neg_unroll_phi_select_constant_nonzero(i32 %arg) {
+; CHECK-LABEL: @neg_unroll_phi_select_constant_nonzero(
+; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT:    [[SELECTOR:%.*]] = phi i32 [ [[ARG1:%.*]], [[ENTRY]] ], [ [[ARG2:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[SELECTOR:%.*]] = phi i32 [ [[ARG:%.*]], [[ENTRY]] ], [ [[F:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[F]] = call i32 @f()
 ; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I]], 1
 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[I]], 4
 ; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[LOOPEXIT:%.*]]
@@ -169,7 +193,8 @@ entry:
 
 loop:
   %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
-  %selector = phi i32 [%arg1, %entry], [%arg2, %loop]
+  %selector = phi i32 [%arg, %entry], [%f, %loop]
+  %f = call i32 @f()
   %i.next = add nsw nuw i32 %i, 1
   %c = icmp ult i32 %i, 4
   br i1 %c, label %loop, label %loopexit
@@ -178,6 +203,7 @@ loopexit:
   ret i32 %selector
 }
 
+
 define i32 @unroll_phi_select_constant_zero(i32 %arg1, i32 %arg2) {
 ; CHECK-LABEL: @unroll_phi_select_constant_zero(
 ; CHECK-NEXT:  entry:
@@ -201,16 +227,7 @@ define i32 @unroll_phi_select(i32 %arg1,
 ; CHECK-LABEL: @unroll_phi_select(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LENGTH:%.*]] = zext i16 [[LEN:%.*]] to i32
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[I:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT:    [[SELECTOR:%.*]] = phi i32 [ [[ARG1:%.*]], [[ENTRY]] ], [ [[ARG2:%.*]], [[LOOP]] ]
-; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[I]], [[LENGTH]]
-; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[LOOPEXIT:%.*]]
-; CHECK:       loopexit:
-; CHECK-NEXT:    [[SELECTOR_LCSSA:%.*]] = phi i32 [ [[SELECTOR]], [[LOOP]] ]
-; CHECK-NEXT:    ret i32 [[SELECTOR_LCSSA]]
+; CHECK-NEXT:    ret i32 [[ARG2:%.*]]
 ;
 entry:
   %length = zext i16 %len to i32

Modified: llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll?rev=363619&r1=363618&r2=363619&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll Mon Jun 17 14:06:17 2019
@@ -58,15 +58,13 @@ define i16 @dom_argument(i16 %arg1, i16
 ; CHECK-NEXT:    br label [[LOOP1:%.*]]
 ; CHECK:       loop1:
 ; CHECK-NEXT:    [[L1:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[L1_ADD:%.*]], [[LOOP1]] ]
-; CHECK-NEXT:    [[SELECTOR:%.*]] = phi i16 [ [[ARG1:%.*]], [[ENTRY]] ], [ [[ARG2:%.*]], [[LOOP1]] ]
 ; CHECK-NEXT:    [[L1_ADD]] = add nuw nsw i16 [[L1]], 1
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i16 [[L1_ADD]], 2
 ; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP1]], label [[LOOP2_PREHEADER:%.*]]
 ; CHECK:       loop2.preheader:
-; CHECK-NEXT:    [[K1_ADD_LCSSA:%.*]] = phi i16 [ [[SELECTOR]], [[LOOP1]] ]
 ; CHECK-NEXT:    br label [[LOOP2:%.*]]
 ; CHECK:       loop2:
-; CHECK-NEXT:    [[K2:%.*]] = phi i16 [ [[K2_ADD:%.*]], [[LOOP2]] ], [ [[K1_ADD_LCSSA]], [[LOOP2_PREHEADER]] ]
+; CHECK-NEXT:    [[K2:%.*]] = phi i16 [ [[K2_ADD:%.*]], [[LOOP2]] ], [ [[ARG2:%.*]], [[LOOP2_PREHEADER]] ]
 ; CHECK-NEXT:    [[L2:%.*]] = phi i16 [ [[L2_ADD:%.*]], [[LOOP2]] ], [ 0, [[LOOP2_PREHEADER]] ]
 ; CHECK-NEXT:    [[L2_ADD]] = add nuw nsw i16 [[L2]], 1
 ; CHECK-NEXT:    tail call void @foo(i16 [[K2]])




More information about the llvm-commits mailing list