[llvm] 35ab211 - [SCEV] Use trivial bound on defining scope of all SCEVs when computing flags
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 3 16:16:00 PDT 2021
Author: Philip Reames
Date: 2021-10-03T16:01:30-07:00
New Revision: 35ab211c37534fda0288acda510ee5bc6b85f96a
URL: https://github.com/llvm/llvm-project/commit/35ab211c37534fda0288acda510ee5bc6b85f96a
DIFF: https://github.com/llvm/llvm-project/commit/35ab211c37534fda0288acda510ee5bc6b85f96a.diff
LOG: [SCEV] Use trivial bound on defining scope of all SCEVs when computing flags
This addresses a comment from review on D109845. Even for SCEVs which we can't find true bounds without recursing through operands, entry to the function forms a trivial upper bound. In some cases, this trivial bound is enough to prove safety of flag inference.
Added:
Modified:
llvm/include/llvm/Analysis/ScalarEvolution.h
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index b9b5450bc9e2a..c3ee802342a50 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -1920,10 +1920,10 @@ 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.
+ /// Return a scope which provides an upper bound on the defining scope of
+ /// 'S'. Specifically, return the first instruction in said bounding scope.
/// (See scope definition rules associated with flag discussion above)
- const Instruction *getDefinedScopeRoot(const SCEV *S);
+ const Instruction *getDefiningScopeBound(const SCEV *S);
/// Given two instructions in the same function, return true if we can
/// prove B must execute given A executes.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 70bf9aee6e0a7..f9d7ff2ca276d 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2804,10 +2804,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
// in the outer scope.
const bool CanPropagateFlags = llvm::any_of(LIOps, [&](const SCEV *S) {
auto *ReachI = &*AddRecLoop->getHeader()->begin();
- if (auto *DefI = getDefinedScopeRoot(S))
- if (isGuaranteedToTransferExecutionTo(DefI, ReachI))
- return true;
- return false;
+ auto *DefI = getDefiningScopeBound(S);
+ return isGuaranteedToTransferExecutionTo(DefI, ReachI);
});
auto AddFlags = CanPropagateFlags ? Flags : SCEV::FlagAnyWrap;
AddRecOps[0] = getAddExpr(LIOps, AddFlags, Depth + 1);
@@ -6586,17 +6584,14 @@ SCEV::NoWrapFlags ScalarEvolution::getNoWrapFlagsFromUB(const Value *V) {
return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap;
}
-const Instruction *ScalarEvolution::getDefinedScopeRoot(const SCEV *S) {
+const Instruction *ScalarEvolution::getDefiningScopeBound(const SCEV *S) {
if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S))
return &*AddRec->getLoop()->getHeader()->begin();
- if (isa<SCEVConstant>(S))
- return &*F.getEntryBlock().begin();
- if (auto *U = dyn_cast<SCEVUnknown>(S)) {
+ if (auto *U = dyn_cast<SCEVUnknown>(S))
if (auto *I = dyn_cast<Instruction>(U->getValue()))
return I;
- return &*F.getEntryBlock().begin();
- }
- return nullptr;
+ // All SCEVs are bound by the entry to F
+ return &*F.getEntryBlock().begin();
}
static bool
@@ -6657,9 +6652,9 @@ bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
// TODO: We can do better here in some cases.
if (!isSCEVable(Op->getType()))
return false;
- if (auto *DefI = getDefinedScopeRoot(getSCEV(Op)))
- if (isGuaranteedToTransferExecutionTo(DefI, I))
- return true;
+ auto *DefI = getDefiningScopeBound(getSCEV(Op));
+ if (isGuaranteedToTransferExecutionTo(DefI, I))
+ return true;
}
return false;
}
diff --git a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
index 5ab24159c2507..43194757b323a 100644
--- a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
+++ b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
@@ -1328,7 +1328,7 @@ define void @test-sub-no-nsw(float* %input, i32 %start, i32 %sub, i32 %numIterat
; CHECK-NEXT: %index32 = sub nsw i32 %i, %sub
; CHECK-NEXT: --> {((-1 * %sub) + %start),+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + (-1 * %sub) + %numIterations) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
-; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %sub to i64))<nsw>),+,1}<nsw><%loop> U: [-4294967295,8589934591) S: [-4294967295,8589934591) Exits: ((zext i32 (-1 + (-1 * %start) + %numIterations) to i64) + (sext i32 %start to i64) + (-1 * (sext i32 %sub to i64))<nsw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %sub to i64))<nsw>)<nsw>,+,1}<nsw><%loop> U: [-4294967295,8589934591) S: [-4294967295,8589934591) Exits: ((zext i32 (-1 + (-1 * %start) + %numIterations) to i64) + (sext i32 %start to i64) + (-1 * (sext i32 %sub to i64))<nsw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
; CHECK-NEXT: --> {((4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %sub to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %sub to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
@@ -1369,7 +1369,7 @@ define void @test-sub-nsw(float* %input, i32 %start, i32 %sub, i32 %numIteration
; CHECK-NEXT: %index32 = sub nsw i32 %i, %halfsub
; CHECK-NEXT: --> {((-1 * %halfsub)<nsw> + %start)<nsw>,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + (-1 * %halfsub)<nsw> + %numIterations) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
-; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %halfsub to i64))<nsw>),+,1}<nsw><%loop> U: [-3221225471,7516192767) S: [-3221225471,7516192767) Exits: ((zext i32 (-1 + (-1 * %start) + %numIterations) to i64) + (sext i32 %start to i64) + (-1 * (sext i32 %halfsub to i64))<nsw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %halfsub to i64))<nsw>)<nsw>,+,1}<nsw><%loop> U: [-3221225471,7516192767) S: [-3221225471,7516192767) Exits: ((zext i32 (-1 + (-1 * %start) + %numIterations) to i64) + (sext i32 %start to i64) + (-1 * (sext i32 %halfsub to i64))<nsw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
; CHECK-NEXT: --> {((4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %halfsub to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %halfsub to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
More information about the llvm-commits
mailing list