Skip to content

Commit

Permalink
[InstCombine] Support phi to cond fold with more than two preds
Browse files Browse the repository at this point in the history
This transform can still be applied if there are more than two
phi inputs, as long as phi inputs with the same value are dominated
by the same idom edge.
  • Loading branch information
nikic committed Mar 1, 2022
1 parent a84a8c9 commit a1f442b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 36 deletions.
66 changes: 32 additions & 34 deletions llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
Expand Up @@ -1264,9 +1264,6 @@ static Value *simplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
if (!PN.getType()->isIntegerTy(1))
return nullptr;

if (PN.getNumOperands() != 2)
return nullptr;

// Make sure all inputs are constants.
if (!all_of(PN.operands(), [](Value *V) { return isa<ConstantInt>(V); }))
return nullptr;
Expand All @@ -1276,22 +1273,7 @@ static Value *simplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
if (!DT.isReachableFromEntry(BB))
return nullptr;

// Same inputs.
if (PN.getOperand(0) == PN.getOperand(1))
return PN.getOperand(0);

BasicBlock *TruePred = nullptr, *FalsePred = nullptr;
for (auto *Pred : predecessors(BB)) {
auto *Input = cast<ConstantInt>(PN.getIncomingValueForBlock(Pred));
if (Input->isAllOnesValue())
TruePred = Pred;
else
FalsePred = Pred;
}
assert(TruePred && FalsePred && "Must be!");

// Check which edge of the dominator dominates the true input. If it is the
// false edge, we should invert the condition.
// Check that the immediate dominator has a conditional branch.
auto *IDom = DT.getNode(BB)->getIDom()->getBlock();
auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
if (!BI || BI->isUnconditional())
Expand All @@ -1302,24 +1284,40 @@ static Value *simplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
BasicBlockEdge TrueOutEdge(IDom, BI->getSuccessor(0));
BasicBlockEdge FalseOutEdge(IDom, BI->getSuccessor(1));

BasicBlockEdge TrueIncEdge(TruePred, BB);
BasicBlockEdge FalseIncEdge(FalsePred, BB);
Optional<bool> Invert;
for (auto Pair : zip(PN.incoming_values(), PN.blocks())) {
auto *Input = cast<ConstantInt>(std::get<0>(Pair));
BasicBlock *Pred = std::get<1>(Pair);
BasicBlockEdge Edge(Pred, BB);

// The input needs to be dominated by one of the edges of the idom.
// Depending on the constant, the condition may need to be inverted.
bool NeedsInvert;
if (DT.dominates(TrueOutEdge, Edge))
NeedsInvert = Input->isZero();
else if (DT.dominates(FalseOutEdge, Edge))
NeedsInvert = Input->isOne();
else
return nullptr;

// Make sure the inversion requirement is always the same.
if (Invert && *Invert != NeedsInvert)
return nullptr;

Invert = NeedsInvert;
}

auto *Cond = BI->getCondition();
if (DT.dominates(TrueOutEdge, TrueIncEdge) &&
DT.dominates(FalseOutEdge, FalseIncEdge))
// This Phi is actually equivalent to branching condition of IDom.
if (!*Invert)
return Cond;
if (DT.dominates(TrueOutEdge, FalseIncEdge) &&
DT.dominates(FalseOutEdge, TrueIncEdge)) {
// This Phi is actually opposite to branching condition of IDom. We invert
// the condition that will potentially open up some opportunities for
// sinking.
auto InsertPt = BB->getFirstInsertionPt();
if (InsertPt != BB->end()) {
Self.Builder.SetInsertPoint(&*InsertPt);
return Self.Builder.CreateNot(Cond);
}

// This Phi is actually opposite to branching condition of IDom. We invert
// the condition that will potentially open up some opportunities for
// sinking.
auto InsertPt = BB->getFirstInsertionPt();
if (InsertPt != BB->end()) {
Self.Builder.SetInsertPoint(&*InsertPt);
return Self.Builder.CreateNot(Cond);
}

return nullptr;
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/Transforms/InstCombine/simple_phi_condition.ll
Expand Up @@ -168,8 +168,7 @@ define i1 @test_multiple_predecessors(i1 %cond, i1 %cond2) {
; CHECK: if2.false:
; CHECK-NEXT: br label [[MERGE]]
; CHECK: merge:
; CHECK-NEXT: [[RET:%.*]] = phi i1 [ true, [[IF_TRUE]] ], [ false, [[IF2_TRUE]] ], [ false, [[IF2_FALSE]] ]
; CHECK-NEXT: ret i1 [[RET]]
; CHECK-NEXT: ret i1 [[COND]]
;
entry:
br i1 %cond, label %if.true, label %if.false
Expand Down

0 comments on commit a1f442b

Please sign in to comment.