aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2024-01-25 21:39:14 +0000
committerFlorian Hahn <flo@fhahn.com>2024-01-25 21:40:31 +0000
commitd88e3658cebbfa1533619de514495a67c81df7c0 (patch)
tree64832aae945b93a254aff60409bf89d0395bf3e2 /llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
parent3b762891826192ded07286852d326f9c9060f52e (diff)
downloadllvm-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.cpp118
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');