[llvm] 26223af - [SCEV] Split isSCEVExprNeverPoison reasoning explicitly into scope and mustexecute parts [NFC]

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 2 13:10:56 PDT 2021


Author: Philip Reames
Date: 2021-10-02T13:10:38-07:00
New Revision: 26223af256bb8f0aa1a82989882c81ffae44c6d1

URL: https://github.com/llvm/llvm-project/commit/26223af256bb8f0aa1a82989882c81ffae44c6d1
DIFF: https://github.com/llvm/llvm-project/commit/26223af256bb8f0aa1a82989882c81ffae44c6d1.diff

LOG: [SCEV] Split isSCEVExprNeverPoison reasoning explicitly into scope and mustexecute parts [NFC]

Inspired by the needs to D111001 and D109845.  The seperation of concerns also amakes it easier to reason about correctness and completeness.

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ScalarEvolution.h
    llvm/lib/Analysis/ScalarEvolution.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index e098cdf9ce89f..b9b5450bc9e2a 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -1920,6 +1920,16 @@ class ScalarEvolution {
   /// would trigger undefined behavior on overflow.
   SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
 
+  /// If S trivially defines a scope (without needing to recurse through
+  /// operands), return the first instruction in it.  Else, return nullptr.
+  /// (See scope definition rules associated with flag discussion above)
+  const Instruction *getDefinedScopeRoot(const SCEV *S);
+
+  /// Given two instructions in the same function, return true if we can
+  /// prove B must execute given A executes.
+  bool isGuaranteedToTransferExecutionTo(const Instruction *A,
+                                         const Instruction *B);
+
   /// Return true if the SCEV corresponding to \p I is never poison.  Proving
   /// this is more complex than proving that just \p I is never poison, since
   /// SCEV commons expressions across control flow, and you can have cases

diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index dacfbbd750d6a..53cf590468dd0 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6569,6 +6569,31 @@ SCEV::NoWrapFlags ScalarEvolution::getNoWrapFlagsFromUB(const Value *V) {
   return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap;
 }
 
+const Instruction *ScalarEvolution::getDefinedScopeRoot(const SCEV *S) {
+  if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S))
+    return &*AddRec->getLoop()->getHeader()->begin();
+  // TODO: add SCEVConstant and SCEVUnknown caxes here
+  return nullptr;
+}
+
+static bool
+isGuaranteedToTransferExecutionToSuccessor(BasicBlock::const_iterator Begin,
+                                           BasicBlock::const_iterator End) {
+  return llvm::all_of( make_range(Begin, End), [](const Instruction &I) {
+    return isGuaranteedToTransferExecutionToSuccessor(&I);
+  });
+}
+
+bool ScalarEvolution::isGuaranteedToTransferExecutionTo(const Instruction *A,
+                                                        const Instruction *B) {
+  if (A->getParent() == B->getParent() &&
+      ::isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
+                                                   B->getIterator()))
+    return true;
+  return false;
+}
+
+
 bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
   // Here we check that I is in the header of the innermost loop containing I,
   // since we only deal with instructions in the loop header. The actual loop we
@@ -6600,11 +6625,9 @@ bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
     // TODO: We can do better here in some cases.
     if (!isSCEVable(Op->getType()))
       return false;
-    const SCEV *OpS = getSCEV(Op);
-    if (auto *AddRecS = dyn_cast<SCEVAddRecExpr>(OpS)) {
-      if (isGuaranteedToExecuteForEveryIteration(I, AddRecS->getLoop()))
+    if (auto *DefI = getDefinedScopeRoot(getSCEV(Op)))
+      if (isGuaranteedToTransferExecutionTo(DefI, I))
         return true;
-    }
   }
   return false;
 }


        


More information about the llvm-commits mailing list