[LoopDeletion] Handle Phis with similar inputs from different blocks

This patch lifts the requirement to have the only incoming live block
for Phis. There can be multiple live blocks if the same value comes to
phi from all of them.

Differential Revision: https://reviews.llvm.org/D103959
Reviewed By: nikic, lebedev.ri
This commit is contained in:
Max Kazantsev 2021-06-21 11:37:06 +07:00
parent 735ad67a4c
commit bb1dc876eb
2 changed files with 30 additions and 28 deletions

View File

@ -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<Value *, Value *> 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;

View File

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