<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>