diff options
author | Max Kazantsev <mkazantsev@azul.com> | 2022-09-13 12:31:07 +0700 |
---|---|---|
committer | Max Kazantsev <mkazantsev@azul.com> | 2022-09-13 12:56:35 +0700 |
commit | 86d5586d78d813a6921d786f7ddb1a41c6fb56e0 (patch) | |
tree | a020b9964f25d0f3210d936ebe78bb4816f13e75 /llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | |
parent | 4531f5385125dd6448004a16cd80a94484ca68b7 (diff) | |
download | llvm-86d5586d78d813a6921d786f7ddb1a41c6fb56e0.zip llvm-86d5586d78d813a6921d786f7ddb1a41c6fb56e0.tar.gz llvm-86d5586d78d813a6921d786f7ddb1a41c6fb56e0.tar.bz2 |
[SCEVExpander] Recompute poison-generating flags on hoisting. PR57187
Instruction being hoisted could have nuw/nsw flags inferred from the old
context, and we cannot simply move it to the new location keeping them
because we are going to introduce new uses to them that didn't exist before.
Example in https://github.com/llvm/llvm-project/issues/57187 shows how
this can produce branch by poison from initially well-defined program.
This patch forcefully recomputes poison-generating flag in the new context.
Differential Revision: https://reviews.llvm.org/D132022
Reviewed By: fhahn, nikic
Diffstat (limited to 'llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp index 3e7e016..568c6b5 100644 --- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -1024,7 +1024,8 @@ void SCEVExpander::fixupInsertPoints(Instruction *I) { /// hoistStep - Attempt to hoist a simple IV increment above InsertPos to make /// it available to other uses in this loop. Recursively hoist any operands, /// until we reach a value that dominates InsertPos. -bool SCEVExpander::hoistIVInc(Instruction *IncV, Instruction *InsertPos) { +bool SCEVExpander::hoistIVInc(Instruction *IncV, Instruction *InsertPos, + bool RecomputePoisonFlags) { if (SE.DT.dominates(IncV, InsertPos)) return true; @@ -1052,6 +1053,19 @@ bool SCEVExpander::hoistIVInc(Instruction *IncV, Instruction *InsertPos) { for (Instruction *I : llvm::reverse(IVIncs)) { fixupInsertPoints(I); I->moveBefore(InsertPos); + if (!RecomputePoisonFlags) + continue; + // Drop flags that are potentially inferred from old context and infer flags + // in new context. + I->dropPoisonGeneratingFlags(); + if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(I)) + if (auto Flags = SE.getStrengthenedNoWrapFlagsFromBinOp(OBO)) { + auto *BO = cast<BinaryOperator>(I); + BO->setHasNoUnsignedWrap( + ScalarEvolution::maskFlags(*Flags, SCEV::FlagNUW) == SCEV::FlagNUW); + BO->setHasNoSignedWrap( + ScalarEvolution::maskFlags(*Flags, SCEV::FlagNSW) == SCEV::FlagNSW); + } } return true; } @@ -2006,12 +2020,14 @@ SCEVExpander::replaceCongruentIVs(Loop *L, const DominatorTree *DT, // with the original phi. It's worth eagerly cleaning up the // common case of a single IV increment so that DeleteDeadPHIs // can remove cycles that had postinc uses. + // Because we may potentially introduce a new use of OrigIV that didn't + // exist before at this point, its poison flags need readjustment. const SCEV *TruncExpr = SE.getTruncateOrNoop(SE.getSCEV(OrigInc), IsomorphicInc->getType()); if (OrigInc != IsomorphicInc && TruncExpr == SE.getSCEV(IsomorphicInc) && SE.LI.replacementPreservesLCSSAForm(IsomorphicInc, OrigInc) && - hoistIVInc(OrigInc, IsomorphicInc)) { + hoistIVInc(OrigInc, IsomorphicInc, /*RecomputePoisonFlags*/ true)) { SCEV_DEBUG_WITH_TYPE( DebugType, dbgs() << "INDVARS: Eliminated congruent iv.inc: " << *IsomorphicInc << '\n'); |