<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<p>I submitted a speculative fix for this in rL366241, but I'd
really appreciate someone familiar with the bot extracting IR so
that I can confirm the diagnosis. <br>
</p>
<p>Philip<br>
</p>
<div class="moz-cite-prefix">On 7/15/19 9:34 PM, Amara Emerson
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:4DB0C231-2392-4A69-A214-87EF9FFD8BA2@apple.com">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
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="" moz-do-not-send="true">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=""
moz-do-not-send="true">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="" moz-do-not-send="true">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=""
moz-do-not-send="true">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="" moz-do-not-send="true">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="" moz-do-not-send="true">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=""
moz-do-not-send="true">llvm-commits@lists.llvm.org</a><br
class="">
<a class="moz-txt-link-freetext" href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="">
</div>
</div>
</blockquote>
</div>
<br class="">
</div>
</blockquote>
</body>
</html>