diff options
author | Florian Hahn <flo@fhahn.com> | 2024-02-01 11:01:29 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-01 11:01:29 +0000 |
commit | da437330beca0411912ca46f2d5ef1e46403acbd (patch) | |
tree | c1feee861d2ff13c775b381db2e5b08c900ace47 /llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | |
parent | b5c0b67bc270936c8fa254dc42d920e867adef54 (diff) | |
download | llvm-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.cpp | 29 |
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'); |