aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2024-02-01 11:01:29 +0000
committerGitHub <noreply@github.com>2024-02-01 11:01:29 +0000
commitda437330beca0411912ca46f2d5ef1e46403acbd (patch)
treec1feee861d2ff13c775b381db2e5b08c900ace47 /llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
parentb5c0b67bc270936c8fa254dc42d920e867adef54 (diff)
downloadllvm-da437330beca0411912ca46f2d5ef1e46403acbd.zip
llvm-da437330beca0411912ca46f2d5ef1e46403acbd.tar.gz
llvm-da437330beca0411912ca46f2d5ef1e46403acbd.tar.bz2
[SCEVExp] Keep NUW/NSW if both original inc and isomporphic inc agree. (#79512)
We are replacing with a wider increment. If both OrigInc and IsomorphicInc are NUW/NSW, then we can preserve them on the wider increment; the narrower IsomorphicInc would wrap before the wider OrigInc, so the replacement won't make IsomorphicInc's uses more poisonous. PR: https://github.com/llvm/llvm-project/pull/79512
Diffstat (limited to 'llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp29
1 files changed, 27 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 2cff57f..ed55a13 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -1604,11 +1604,36 @@ void SCEVExpander::replaceCongruentIVInc(
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,
+ !SE.LI.replacementPreservesLCSSAForm(IsomorphicInc, OrigInc))
+ return;
+
+ bool BothHaveNUW = false;
+ bool BothHaveNSW = false;
+ auto *OBOIncV = dyn_cast<OverflowingBinaryOperator>(OrigInc);
+ auto *OBOIsomorphic = dyn_cast<OverflowingBinaryOperator>(IsomorphicInc);
+ if (OBOIncV && OBOIsomorphic) {
+ BothHaveNUW =
+ OBOIncV->hasNoUnsignedWrap() && OBOIsomorphic->hasNoUnsignedWrap();
+ BothHaveNSW =
+ OBOIncV->hasNoSignedWrap() && OBOIsomorphic->hasNoSignedWrap();
+ }
+
+ if (!hoistIVInc(OrigInc, IsomorphicInc,
/*RecomputePoisonFlags*/ true))
return;
+ // We are replacing with a wider increment. If both OrigInc and IsomorphicInc
+ // are NUW/NSW, then we can preserve them on the wider increment; the narrower
+ // IsomorphicInc would wrap before the wider OrigInc, so the replacement won't
+ // make IsomorphicInc's uses more poisonous.
+ assert(OrigInc->getType()->getScalarSizeInBits() >=
+ IsomorphicInc->getType()->getScalarSizeInBits() &&
+ "Should only replace an increment with a wider one.");
+ if (BothHaveNUW || BothHaveNSW) {
+ OrigInc->setHasNoUnsignedWrap(OBOIncV->hasNoUnsignedWrap() || BothHaveNUW);
+ OrigInc->setHasNoSignedWrap(OBOIncV->hasNoSignedWrap() || BothHaveNSW);
+ }
+
SCEV_DEBUG_WITH_TYPE(DebugType,
dbgs() << "INDVARS: Eliminated congruent iv.inc: "
<< *IsomorphicInc << '\n');