<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Philip,<div class=""><br class=""></div><div class="">This commit looks like (from the assertion, I haven’t bisected it completely) it broke a green dragon ThinLTO stage2 bot: <a href="http://green.lab.llvm.org/green/job/clang-stage2-Rthinlto/" class="">http://green.lab.llvm.org/green/job/clang-stage2-Rthinlto/</a></div><div class=""><br class=""></div><div class="">Could you take a look?</div><div class=""><br class=""></div><div class="">Amara<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jul 12, 2019, at 10:05 AM, Philip Reames via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Author: reames<br class="">Date: Fri Jul 12 10:05:35 2019<br class="">New Revision: 365920<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=365920&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=365920&view=rev</a><br class="">Log:<br class="">[IndVars] Use exit count reasoning to discharge obviously untaken exits<br class=""><br class="">Continue in the spirit of D63618, and use exit count reasoning to prove away loop exits which can not be taken since the backedge taken count of the loop as a whole is provably less than the minimal BE count required to take this particular loop exit.<br class=""><br class="">As demonstrated in the newly added tests, this triggers in a number of cases where IndVars was previously unable to discharge obviously redundant exit tests. And some not so obvious ones.<br class=""><br class="">Differential Revision: <a href="https://reviews.llvm.org/D63733" class="">https://reviews.llvm.org/D63733</a><br class=""><br class=""><br class="">Modified:<br class=""> llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<br class=""> llvm/trunk/test/Transforms/IndVarSimplify/eliminate-exit.ll<br class=""><br class="">Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=365920&r1=365919&r2=365920&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=365920&r1=365919&r2=365920&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)<br class="">+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Fri Jul 12 10:05:35 2019<br class="">@@ -144,6 +144,7 @@ class IndVarSimplify {<br class=""> bool rewriteNonIntegerIVs(Loop *L);<br class=""><br class=""> bool simplifyAndExtend(Loop *L, SCEVExpander &Rewriter, LoopInfo *LI);<br class="">+ bool optimizeLoopExits(Loop *L);<br class=""><br class=""> bool canLoopBeDeleted(Loop *L, SmallVector<RewritePhi, 8> &RewritePhiSet);<br class=""> bool rewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter);<br class="">@@ -2623,6 +2624,112 @@ bool IndVarSimplify::sinkUnusedInvariant<br class=""> return MadeAnyChanges;<br class=""> }<br class=""><br class="">+bool IndVarSimplify::optimizeLoopExits(Loop *L) {<br class="">+ SmallVector<BasicBlock*, 16> ExitingBlocks;<br class="">+ L->getExitingBlocks(ExitingBlocks);<br class="">+ BasicBlock * const Latch = L->getLoopLatch();<br class="">+<br class="">+ // Form an expression for the maximum exit count possible for this loop. We<br class="">+ // merge the max and exact information to approximate a version of<br class="">+ // getMaxBackedgeTakenInfo which isn't restricted to just constants.<br class="">+ // TODO: factor this out as a version of getMaxBackedgeTakenCount which<br class="">+ // isn't guaranteed to return a constant.<br class="">+ SmallVector<const SCEV*, 4> ExitCounts;<br class="">+ const SCEV *MaxConstEC = SE->getMaxBackedgeTakenCount(L);<br class="">+ if (!isa<SCEVCouldNotCompute>(MaxConstEC))<br class="">+ ExitCounts.push_back(MaxConstEC);<br class="">+ for (BasicBlock *ExitingBB : ExitingBlocks) {<br class="">+ const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);<br class="">+ if (!isa<SCEVCouldNotCompute>(ExitCount)) {<br class="">+ assert(DT->dominates(ExitingBB, Latch) &&<br class="">+ "We should only have known counts for exiting blocks that "<br class="">+ "dominate latch!");<br class="">+ ExitCounts.push_back(ExitCount);<br class="">+ }<br class="">+ }<br class="">+ if (ExitCounts.empty())<br class="">+ return false;<br class="">+ const SCEV *MaxExitCount = SE->getUMinFromMismatchedTypes(ExitCounts);<br class="">+<br class="">+ bool Changed = false;<br class="">+ for (BasicBlock *ExitingBB : ExitingBlocks) {<br class="">+ // If our exitting block exits multiple loops, we can only rewrite the<br class="">+ // innermost one. Otherwise, we're changing how many times the innermost<br class="">+ // loop runs before it exits. <br class="">+ if (LI->getLoopFor(ExitingBB) != L)<br class="">+ continue;<br class="">+<br class="">+ // Can't rewrite non-branch yet.<br class="">+ BranchInst *BI = dyn_cast<BranchInst>(ExitingBB->getTerminator());<br class="">+ if (!BI)<br class="">+ continue;<br class="">+<br class="">+ // If already constant, nothing to do.<br class="">+ if (isa<Constant>(BI->getCondition()))<br class="">+ continue;<br class="">+ <br class="">+ const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);<br class="">+ if (isa<SCEVCouldNotCompute>(ExitCount))<br class="">+ continue;<br class="">+<br class="">+ // If we know we'd exit on the first iteration, rewrite the exit to<br class="">+ // reflect this. This does not imply the loop must exit through this<br class="">+ // exit; there may be an earlier one taken on the first iteration.<br class="">+ // TODO: Given we know the backedge can't be taken, we should go ahead<br class="">+ // and break it. Or at least, kill all the header phis and simplify.<br class="">+ if (ExitCount->isZero()) {<br class="">+ bool ExitIfTrue = !L->contains(*succ_begin(ExitingBB));<br class="">+ auto *OldCond = BI->getCondition();<br class="">+ auto *NewCond = ExitIfTrue ? ConstantInt::getTrue(OldCond->getType()) :<br class="">+ ConstantInt::getFalse(OldCond->getType());<br class="">+ BI->setCondition(NewCond);<br class="">+ if (OldCond->use_empty())<br class="">+ DeadInsts.push_back(OldCond);<br class="">+ Changed = true;<br class="">+ continue;<br class="">+ }<br class="">+<br class="">+ // If we end up with a pointer exit count, bail.<br class="">+ if (!ExitCount->getType()->isIntegerTy() ||<br class="">+ !MaxExitCount->getType()->isIntegerTy())<br class="">+ return false;<br class="">+ <br class="">+ Type *WiderType =<br class="">+ SE->getWiderType(MaxExitCount->getType(), ExitCount->getType());<br class="">+ ExitCount = SE->getNoopOrZeroExtend(ExitCount, WiderType);<br class="">+ MaxExitCount = SE->getNoopOrZeroExtend(MaxExitCount, WiderType);<br class="">+ assert(MaxExitCount->getType() == ExitCount->getType());<br class="">+ <br class="">+ // Can we prove that some other exit must be taken strictly before this<br class="">+ // one? TODO: handle cases where ule is known, and equality is covered<br class="">+ // by a dominating exit<br class="">+ if (SE->isLoopEntryGuardedByCond(L, CmpInst::ICMP_ULT,<br class="">+ MaxExitCount, ExitCount)) {<br class="">+ bool ExitIfTrue = !L->contains(*succ_begin(ExitingBB));<br class="">+ auto *OldCond = BI->getCondition();<br class="">+ auto *NewCond = ExitIfTrue ? ConstantInt::getFalse(OldCond->getType()) :<br class="">+ ConstantInt::getTrue(OldCond->getType());<br class="">+ BI->setCondition(NewCond);<br class="">+ if (OldCond->use_empty())<br class="">+ DeadInsts.push_back(OldCond);<br class="">+ Changed = true;<br class="">+ continue;<br class="">+ }<br class="">+<br class="">+ // TODO: If we can prove that the exiting iteration is equal to the exit<br class="">+ // count for this exit and that no previous exit oppurtunities exist within<br class="">+ // the loop, then we can discharge all other exits. (May fall out of<br class="">+ // previous TODO.) <br class="">+ <br class="">+ // TODO: If we can't prove any relation between our exit count and the<br class="">+ // loops exit count, but taking this exit doesn't require actually running<br class="">+ // the loop (i.e. no side effects, no computed values used in exit), then<br class="">+ // we can replace the exit test with a loop invariant test which exits on<br class="">+ // the first iteration. <br class="">+ }<br class="">+ return Changed;<br class="">+}<br class="">+<br class=""> //===----------------------------------------------------------------------===//<br class=""> // IndVarSimplify driver. Manage several subpasses of IV simplification.<br class=""> //===----------------------------------------------------------------------===//<br class="">@@ -2679,6 +2786,8 @@ bool IndVarSimplify::run(Loop *L) {<br class=""> // Eliminate redundant IV cycles.<br class=""> NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts);<br class=""><br class="">+ Changed |= optimizeLoopExits(L);<br class="">+<br class=""> // If we have a trip count expression, rewrite the loop's exit condition<br class=""> // using it. <br class=""> if (!DisableLFTR) {<br class="">@@ -2702,23 +2811,7 @@ bool IndVarSimplify::run(Loop *L) {<br class=""> if (isa<SCEVCouldNotCompute>(ExitCount))<br class=""> continue;<br class=""><br class="">- // If we know we'd exit on the first iteration, rewrite the exit to<br class="">- // reflect this. This does not imply the loop must exit through this<br class="">- // exit; there may be an earlier one taken on the first iteration.<br class="">- // TODO: Given we know the backedge can't be taken, we should go ahead<br class="">- // and break it. Or at least, kill all the header phis and simplify.<br class="">- if (ExitCount->isZero()) {<br class="">- auto *BI = cast<BranchInst>(ExitingBB->getTerminator());<br class="">- bool ExitIfTrue = !L->contains(*succ_begin(ExitingBB));<br class="">- auto *OldCond = BI->getCondition();<br class="">- auto *NewCond = ExitIfTrue ? ConstantInt::getTrue(OldCond->getType()) :<br class="">- ConstantInt::getFalse(OldCond->getType());<br class="">- BI->setCondition(NewCond);<br class="">- if (OldCond->use_empty())<br class="">- DeadInsts.push_back(OldCond);<br class="">- Changed = true;<br class="">- continue;<br class="">- }<br class="">+ assert(!ExitCount->isZero() && "Should have been folded above");<br class=""><br class=""> PHINode *IndVar = FindLoopCounter(L, ExitingBB, ExitCount, SE, DT);<br class=""> if (!IndVar)<br class=""><br class="">Modified: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-exit.ll<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-exit.ll?rev=365920&r1=365919&r2=365920&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-exit.ll?rev=365920&r1=365919&r2=365920&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-exit.ll (original)<br class="">+++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-exit.ll Fri Jul 12 10:05:35 2019<br class="">@@ -15,8 +15,7 @@ define void @ult(i64 %n, i64 %m) {<br class=""> ; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]<br class=""> ; CHECK: latch:<br class=""> ; CHECK-NEXT: call void @side_effect()<br class="">-; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IV]], [[M]]<br class="">-; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP]], label [[EXIT_LOOPEXIT]]<br class="">+; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT_LOOPEXIT]]<br class=""> ; CHECK: exit.loopexit:<br class=""> ; CHECK-NEXT: br label [[EXIT]]<br class=""> ; CHECK: exit:<br class="">@@ -48,8 +47,7 @@ define void @ugt(i64 %n, i64 %m) {<br class=""> ; CHECK: loop:<br class=""> ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]<br class=""> ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1<br class="">-; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], [[N]]<br class="">-; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]<br class="">+; CHECK-NEXT: br i1 true, label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]<br class=""> ; CHECK: latch:<br class=""> ; CHECK-NEXT: call void @side_effect()<br class=""> ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IV]], [[M]]<br class="">@@ -160,9 +158,7 @@ define void @ult_const_max(i64 %n) {<br class=""> ; CHECK: loop:<br class=""> ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]<br class=""> ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1<br class="">-; CHECK-NEXT: [[UDIV:%.*]] = udiv i64 [[IV]], 10<br class="">-; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[UDIV]], 2<br class="">-; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]<br class="">+; CHECK-NEXT: br i1 true, label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]<br class=""> ; CHECK: latch:<br class=""> ; CHECK-NEXT: call void @side_effect()<br class=""> ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IV]], [[N]]<br class=""><br class=""><br class="">_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a><br class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits<br class=""></div></div></blockquote></div><br class=""></div></body></html>