diff --git a/lib/Transforms/Scalar/LoopDeletion.cpp b/lib/Transforms/Scalar/LoopDeletion.cpp index 4d7925e066b..a287f687af3 100644 --- a/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/lib/Transforms/Scalar/LoopDeletion.cpp @@ -245,23 +245,25 @@ static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT, MarkLiveEdge(BB, Succ); }; - // Check if there is only one predecessor on 1st iteration. Note that because - // we iterate in RPOT, we have already visited all its (non-latch) - // predecessors. - auto GetSolePredecessorOnFirstIteration = [&](BasicBlock * BB)->BasicBlock * { + // Check if there is only one value coming from all live predecessor blocks. + // Note that because we iterate in RPOT, we have already visited all its + // (non-latch) predecessors. + auto GetSoleInputOnFirstIteration = [&](PHINode & PN)->Value * { + BasicBlock *BB = PN.getParent(); if (BB == Header) - return L->getLoopPredecessor(); - BasicBlock *OnlyPred = nullptr; + return PN.getIncomingValueForBlock(L->getLoopPredecessor()); + Value *OnlyInput = nullptr; for (auto *Pred : predecessors(BB)) - if (OnlyPred != Pred && LiveEdges.count({ Pred, BB })) { - // 2 live preds. - if (OnlyPred) + if (LiveEdges.count({ Pred, BB })) { + Value *Incoming = PN.getIncomingValueForBlock(Pred); + // Two inputs. + if (OnlyInput && OnlyInput != Incoming) return nullptr; - OnlyPred = Pred; + OnlyInput = Incoming; } - assert(OnlyPred && "No live predecessors?"); - return OnlyPred; + assert(OnlyInput && "No live predecessors?"); + return OnlyInput; }; DenseMap FirstIterValue; @@ -290,18 +292,17 @@ static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT, continue; } - // If this block has only one live pred, map its phis onto their SCEVs. - if (auto *OnlyPred = GetSolePredecessorOnFirstIteration(BB)) - for (auto &PN : BB->phis()) { - if (!PN.getType()->isIntegerTy()) - continue; - auto *Incoming = PN.getIncomingValueForBlock(OnlyPred); - if (DT.dominates(Incoming, BB->getTerminator())) { - Value *FirstIterV = - getValueOnFirstIteration(Incoming, FirstIterValue, SQ); - FirstIterValue[&PN] = FirstIterV; - } + // If Phi has only one input from all live input blocks, use it. + for (auto &PN : BB->phis()) { + if (!PN.getType()->isIntegerTy()) + continue; + auto *Incoming = GetSoleInputOnFirstIteration(PN); + if (Incoming && DT.dominates(Incoming, BB->getTerminator())) { + Value *FirstIterV = + getValueOnFirstIteration(Incoming, FirstIterValue, SQ); + FirstIterValue[&PN] = FirstIterV; } + } using namespace PatternMatch; ICmpInst::Predicate Pred; diff --git a/test/Transforms/LoopDeletion/eval_first_iteration.ll b/test/Transforms/LoopDeletion/eval_first_iteration.ll index 612228a8bce..744853e23a2 100644 --- a/test/Transforms/LoopDeletion/eval_first_iteration.ll +++ b/test/Transforms/LoopDeletion/eval_first_iteration.ll @@ -655,20 +655,19 @@ failure: unreachable } -; TODO: We can break the backedge here. define i32 @test_multiple_pred_2() { ; CHECK-LABEL: @test_multiple_pred_2( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]] ; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0 ; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] ; CHECK: if.true: ; CHECK-NEXT: br i1 undef, label [[IF_TRUE_1:%.*]], label [[IF_TRUE_2:%.*]] ; CHECK: if.true.1: -; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK-NEXT: br label [[BACKEDGE:%.*]] ; CHECK: if.true.2: ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: if.false: @@ -679,9 +678,11 @@ define i32 @test_multiple_pred_2() { ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: backedge: ; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE_1]] ], [ 0, [[IF_FALSE_2]] ], [ [[SUB]], [[IF_TRUE_1]] ], [ [[SUB]], [[IF_TRUE_2]] ] -; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]] +; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]] ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[SUM_NEXT]], 4 -; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]] +; CHECK: backedge.loop_crit_edge: +; CHECK-NEXT: unreachable ; CHECK: done: ; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]