[llvm] 24cde2f - [SCEV] Remove invariant requirement from isSCEVExprNeverPoison

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 1 15:58:56 PDT 2021


Author: Philip Reames
Date: 2021-10-01T15:57:37-07:00
New Revision: 24cde2f6023a765b66923f4a4ac033a91878b856

URL: https://github.com/llvm/llvm-project/commit/24cde2f6023a765b66923f4a4ac033a91878b856
DIFF: https://github.com/llvm/llvm-project/commit/24cde2f6023a765b66923f4a4ac033a91878b856.diff

LOG: [SCEV] Remove invariant requirement from isSCEVExprNeverPoison

This code is attempting to prove that I must execute if we enter the defining scope of the SCEV which will be created from I. In the case where it found a defining addrec scope, it had a rather odd restriction that all of the other operands must be loop invariant in that addrec's loop.

As near as I can tell here, we really only need a upper bound on the defining scope. If we can prove the stronger property, then we must also have proven the property on the exact defining scope as well.

In practice, the actual effect of this change is narrow. The compile time restriction at the top of the routine basically limits us to I being an arithmetic in some loop L with both an addrec operand in L, and a unknown operands in L. Possible to demonstrate, but the main value of the change is removing unneeded code.

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

Added: 
    

Modified: 
    llvm/lib/Analysis/ScalarEvolution.cpp
    llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 5c5ca477fd553..ed929654967d4 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6582,15 +6582,11 @@ bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
   // instructions can map to the same SCEV. If we apply NSW or NUW from I to
   // the SCEV, we must guarantee no wrapping for that SCEV also when it is
   // derived from other instructions that map to the same SCEV. We cannot make
-  // that guarantee for cases where I is not executed. So we need to find the
-  // loop that I is considered in relation to and prove that I is executed for
-  // every iteration of that loop. That implies that the value that I
-  // calculates does not wrap anywhere in the loop, so then we can apply the
-  // flags to the SCEV.
-  //
-  // We check isLoopInvariant to disambiguate in case we are adding recurrences
-  // from 
diff erent loops, so that we know which loop to prove that I is
-  // executed in.
+  // that guarantee for cases where I is not executed. So we need to find a
+  // upper bound on the defining scope for the SCEV, and prove that I is
+  // executed every time we enter that scope.  When the bounding scope is a
+  // loop (the common case), this is equivalent to proving I executes on every
+  // iteration of that loop.
   for (const Use &Op : I->operands()) {
     // I could be an extractvalue from a call to an overflow intrinsic.
     // TODO: We can do better here in some cases.
@@ -6598,15 +6594,7 @@ bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
       return false;
     const SCEV *OpS = getSCEV(Op);
     if (auto *AddRecS = dyn_cast<SCEVAddRecExpr>(OpS)) {
-      const bool AllOtherOpsLoopInvariant =
-        llvm::all_of(I->operands(), [&](const Use &Op2) -> bool {
-          if (Op.getOperandNo() == Op2.getOperandNo())
-            return true;
-          const SCEV *OtherOp = getSCEV(Op2);
-          return isLoopInvariant(OtherOp, AddRecS->getLoop());
-        });
-      if (AllOtherOpsLoopInvariant &&
-          isGuaranteedToExecuteForEveryIteration(I, AddRecS->getLoop()))
+      if (isGuaranteedToExecuteForEveryIteration(I, AddRecS->getLoop()))
         return true;
     }
   }

diff  --git a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
index 7aa2002c736fa..57aacbe536c87 100644
--- a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
+++ b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
@@ -142,9 +142,9 @@ define void @test-add-scope-bound(i32* %input, i32 %needle) {
 ; CHECK-NEXT:    %i.next = add nuw i32 %i, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %of_interest = add nuw nsw i32 %i.next, %offset
-; CHECK-NEXT:    --> ({1,+,1}<nuw><%loop> + %offset) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT:    --> ({1,+,1}<nuw><%loop> + %offset)<nuw><nsw> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
 ; CHECK-NEXT:    %gep2 = getelementptr i32, i32* %input, i32 %of_interest
-; CHECK-NEXT:    --> ((4 * (sext i32 ({1,+,1}<nuw><%loop> + %offset) to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT:    --> ((4 * ((sext i32 {1,+,1}<nuw><%loop> to i64) + (sext i32 %offset to i64))<nsw>)<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test-add-scope-bound
 ; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
 ; CHECK-NEXT:  Loop %loop: Unpredictable max backedge-taken count.


        


More information about the llvm-commits mailing list