[llvm] r365920 - [IndVars] Use exit count reasoning to discharge obviously untaken exits
Amara Emerson via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 15 21:34:51 PDT 2019
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/ <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> 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
> 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/20190715/5e77f75a/attachment.html>
More information about the llvm-commits
mailing list