From: Philip Reames Date: Sun, 3 Oct 2021 23:01:30 +0000 (-0700) Subject: [SCEV] Use trivial bound on defining scope of all SCEVs when computing flags X-Git-Tag: upstream/15.0.7~29763 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=35ab211c37534fda0288acda510ee5bc6b85f96a;p=platform%2Fupstream%2Fllvm.git [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. --- diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h index b9b5450..c3ee802 100644 --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -1920,10 +1920,10 @@ private: /// 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 70bf9ae..f9d7ff2 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -2804,10 +2804,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &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(S)) return &*AddRec->getLoop()->getHeader()->begin(); - if (isa(S)) - return &*F.getEntryBlock().begin(); - if (auto *U = dyn_cast(S)) { + if (auto *U = dyn_cast(S)) if (auto *I = dyn_cast(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 5ab2415..4319475 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}<%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))),+,1}<%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))) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %sub to i64))),+,1}<%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))) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64 ; CHECK-NEXT: --> {((4 * (sext i32 %start to i64)) + (-4 * (sext i32 %sub to i64)) + %input),+,4}<%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64)) + (4 * (sext i32 %start to i64)) + (-4 * (sext i32 %sub to i64)) + %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) + %start),+,1}<%loop> U: full-set S: full-set Exits: (-1 + (-1 * %halfsub) + %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))),+,1}<%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))) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %halfsub to i64))),+,1}<%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))) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64 ; CHECK-NEXT: --> {((4 * (sext i32 %start to i64)) + (-4 * (sext i32 %halfsub to i64)) + %input),+,4}<%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64)) + (4 * (sext i32 %start to i64)) + (-4 * (sext i32 %halfsub to i64)) + %input) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %nexti = add nsw i32 %i, 1