diff options
Diffstat (limited to 'llvm/lib/Transforms/Scalar/IndVarSimplify.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 60 |
1 files changed, 47 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index e977dd18be9f..a9ca0bdc8f7b 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -106,13 +106,18 @@ static cl::opt<bool> VerifyIndvars( static cl::opt<ReplaceExitVal> ReplaceExitValue( "replexitval", cl::Hidden, cl::init(OnlyCheapRepl), cl::desc("Choose the strategy to replace exit value in IndVarSimplify"), - cl::values(clEnumValN(NeverRepl, "never", "never replace exit value"), - clEnumValN(OnlyCheapRepl, "cheap", - "only replace exit value when the cost is cheap"), - clEnumValN(NoHardUse, "noharduse", - "only replace exit values when loop def likely dead"), - clEnumValN(AlwaysRepl, "always", - "always replace exit value whenever possible"))); + cl::values( + clEnumValN(NeverRepl, "never", "never replace exit value"), + clEnumValN(OnlyCheapRepl, "cheap", + "only replace exit value when the cost is cheap"), + clEnumValN( + UnusedIndVarInLoop, "unusedindvarinloop", + "only replace exit value when it is an unused " + "induction variable in the loop and has cheap replacement cost"), + clEnumValN(NoHardUse, "noharduse", + "only replace exit values when loop def likely dead"), + clEnumValN(AlwaysRepl, "always", + "always replace exit value whenever possible"))); static cl::opt<bool> UsePostIncrementRanges( "indvars-post-increment-ranges", cl::Hidden, @@ -1302,15 +1307,39 @@ static void foldExit(const Loop *L, BasicBlock *ExitingBB, bool IsTaken, } static void replaceLoopPHINodesWithPreheaderValues( - Loop *L, SmallVectorImpl<WeakTrackingVH> &DeadInsts) { + LoopInfo *LI, Loop *L, SmallVectorImpl<WeakTrackingVH> &DeadInsts) { assert(L->isLoopSimplifyForm() && "Should only do it in simplify form!"); auto *LoopPreheader = L->getLoopPreheader(); auto *LoopHeader = L->getHeader(); + SmallVector<Instruction *> Worklist; for (auto &PN : LoopHeader->phis()) { auto *PreheaderIncoming = PN.getIncomingValueForBlock(LoopPreheader); + for (User *U : PN.users()) + Worklist.push_back(cast<Instruction>(U)); PN.replaceAllUsesWith(PreheaderIncoming); DeadInsts.emplace_back(&PN); } + + // Replacing with the preheader value will often allow IV users to simplify + // (especially if the preheader value is a constant). + SmallPtrSet<Instruction *, 16> Visited; + while (!Worklist.empty()) { + auto *I = cast<Instruction>(Worklist.pop_back_val()); + if (!Visited.insert(I).second) + continue; + + // Don't simplify instructions outside the loop. + if (!L->contains(I)) + continue; + + Value *Res = simplifyInstruction(I, I->getModule()->getDataLayout()); + if (Res && LI->replacementPreservesLCSSAForm(I, Res)) { + for (User *U : I->users()) + Worklist.push_back(cast<Instruction>(U)); + I->replaceAllUsesWith(Res); + DeadInsts.emplace_back(I); + } + } } static void replaceWithInvariantCond( @@ -1549,14 +1578,19 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) { if (!BI) return true; - // If already constant, nothing to do. - if (isa<Constant>(BI->getCondition())) - return true; - // Likewise, the loop latch must be dominated by the exiting BB. if (!DT->dominates(ExitingBB, L->getLoopLatch())) return true; + if (auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) { + // If already constant, nothing to do. However, if this is an + // unconditional exit, we can still replace header phis with their + // preheader value. + if (!L->contains(BI->getSuccessor(CI->isNullValue()))) + replaceLoopPHINodesWithPreheaderValues(LI, L, DeadInsts); + return true; + } + return false; }); @@ -1640,7 +1674,7 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) { // the header PHIs with values coming from the preheader. if (ExitCount->isZero()) { foldExit(L, ExitingBB, true, DeadInsts); - replaceLoopPHINodesWithPreheaderValues(L, DeadInsts); + replaceLoopPHINodesWithPreheaderValues(LI, L, DeadInsts); Changed = true; continue; } |
