diff options
author | Florian Hahn <flo@fhahn.com> | 2024-01-25 21:39:14 +0000 |
---|---|---|
committer | Florian Hahn <flo@fhahn.com> | 2024-01-25 21:40:31 +0000 |
commit | d88e3658cebbfa1533619de514495a67c81df7c0 (patch) | |
tree | 64832aae945b93a254aff60409bf89d0395bf3e2 /llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | |
parent | 3b762891826192ded07286852d326f9c9060f52e (diff) | |
download | llvm-d88e3658cebbfa1533619de514495a67c81df7c0.zip llvm-d88e3658cebbfa1533619de514495a67c81df7c0.tar.gz llvm-d88e3658cebbfa1533619de514495a67c81df7c0.tar.bz2 |
[SCEVExp] Move logic to replace congruent IV increments to helper (NFC).
Move logic to replace congruent IV increments to helper function, to
reduce the indentation by using early returns. This is in preparation
for a follow-up patch.
Diffstat (limited to 'llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | 118 |
1 files changed, 64 insertions, 54 deletions
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp index a1d7f0f..cf8cea9 100644 --- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -1569,6 +1569,69 @@ void SCEVExpander::rememberInstruction(Value *I) { DoInsert(I); } +void SCEVExpander::replaceCongruentIVInc( + PHINode *&Phi, PHINode *&OrigPhi, Loop *L, const DominatorTree *DT, + SmallVectorImpl<WeakTrackingVH> &DeadInsts) { + BasicBlock *LatchBlock = L->getLoopLatch(); + if (!LatchBlock) + return; + + Instruction *OrigInc = + dyn_cast<Instruction>(OrigPhi->getIncomingValueForBlock(LatchBlock)); + Instruction *IsomorphicInc = + dyn_cast<Instruction>(Phi->getIncomingValueForBlock(LatchBlock)); + if (!OrigInc || !IsomorphicInc) + return; + + // If this phi has the same width but is more canonical, replace the + // original with it. As part of the "more canonical" determination, + // respect a prior decision to use an IV chain. + if (OrigPhi->getType() == Phi->getType() && + !(ChainedPhis.count(Phi) || + isExpandedAddRecExprPHI(OrigPhi, OrigInc, L)) && + (ChainedPhis.count(Phi) || + isExpandedAddRecExprPHI(Phi, IsomorphicInc, L))) { + std::swap(OrigPhi, Phi); + std::swap(OrigInc, IsomorphicInc); + } + + // Replacing the congruent phi is sufficient because acyclic + // redundancy elimination, CSE/GVN, should handle the + // rest. However, once SCEV proves that a phi is congruent, + // it's often the head of an IV user cycle that is isomorphic + // 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, + /*RecomputePoisonFlags*/ true)) + return; + + SCEV_DEBUG_WITH_TYPE(DebugType, + dbgs() << "INDVARS: Eliminated congruent iv.inc: " + << *IsomorphicInc << '\n'); + Value *NewInc = OrigInc; + if (OrigInc->getType() != IsomorphicInc->getType()) { + BasicBlock::iterator IP; + if (PHINode *PN = dyn_cast<PHINode>(OrigInc)) + IP = PN->getParent()->getFirstInsertionPt(); + else + IP = OrigInc->getNextNonDebugInstruction()->getIterator(); + + IRBuilder<> Builder(IP->getParent(), IP); + Builder.SetCurrentDebugLocation(IsomorphicInc->getDebugLoc()); + NewInc = + Builder.CreateTruncOrBitCast(OrigInc, IsomorphicInc->getType(), IVName); + } + IsomorphicInc->replaceAllUsesWith(NewInc); + DeadInsts.emplace_back(IsomorphicInc); +} + /// replaceCongruentIVs - Check for congruent phis in this loop header and /// replace them with their most canonical representative. Return the number of /// phis eliminated. @@ -1654,60 +1717,7 @@ SCEVExpander::replaceCongruentIVs(Loop *L, const DominatorTree *DT, if (OrigPhiRef->getType()->isPointerTy() != Phi->getType()->isPointerTy()) continue; - if (BasicBlock *LatchBlock = L->getLoopLatch()) { - Instruction *OrigInc = dyn_cast<Instruction>( - OrigPhiRef->getIncomingValueForBlock(LatchBlock)); - Instruction *IsomorphicInc = - dyn_cast<Instruction>(Phi->getIncomingValueForBlock(LatchBlock)); - - if (OrigInc && IsomorphicInc) { - // If this phi has the same width but is more canonical, replace the - // original with it. As part of the "more canonical" determination, - // respect a prior decision to use an IV chain. - if (OrigPhiRef->getType() == Phi->getType() && - !(ChainedPhis.count(Phi) || - isExpandedAddRecExprPHI(OrigPhiRef, OrigInc, L)) && - (ChainedPhis.count(Phi) || - isExpandedAddRecExprPHI(Phi, IsomorphicInc, L))) { - std::swap(OrigPhiRef, Phi); - std::swap(OrigInc, IsomorphicInc); - } - // Replacing the congruent phi is sufficient because acyclic - // redundancy elimination, CSE/GVN, should handle the - // rest. However, once SCEV proves that a phi is congruent, - // it's often the head of an IV user cycle that is isomorphic - // 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, /*RecomputePoisonFlags*/ true)) { - SCEV_DEBUG_WITH_TYPE( - DebugType, dbgs() << "INDVARS: Eliminated congruent iv.inc: " - << *IsomorphicInc << '\n'); - Value *NewInc = OrigInc; - if (OrigInc->getType() != IsomorphicInc->getType()) { - BasicBlock::iterator IP; - if (PHINode *PN = dyn_cast<PHINode>(OrigInc)) - IP = PN->getParent()->getFirstInsertionPt(); - else - IP = OrigInc->getNextNonDebugInstruction()->getIterator(); - - IRBuilder<> Builder(IP->getParent(), IP); - Builder.SetCurrentDebugLocation(IsomorphicInc->getDebugLoc()); - NewInc = Builder.CreateTruncOrBitCast( - OrigInc, IsomorphicInc->getType(), IVName); - } - IsomorphicInc->replaceAllUsesWith(NewInc); - DeadInsts.emplace_back(IsomorphicInc); - } - } - } + replaceCongruentIVInc(Phi, OrigPhiRef, L, DT, DeadInsts); SCEV_DEBUG_WITH_TYPE(DebugType, dbgs() << "INDVARS: Eliminated congruent iv: " << *Phi << '\n'); |