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