forked from OSchip/llvm-project
[mlir] Add canonicalization for cond_br that feed into a cond_br on the same condition
``` ... cond_br %cond, ^bb1(...), ^bb2(...) ... ^bb1: // has single predecessor ... cond_br %cond, ^bb3(...), ^bb4(...) ``` -> ``` ... cond_br %cond, ^bb1(...), ^bb2(...) ... ^bb1: // has single predecessor ... br ^bb3(...) ``` Differential Revision: https://reviews.llvm.org/D89604
This commit is contained in:
parent
9d23224bf6
commit
a8feeee15f
|
@ -1063,12 +1063,58 @@ struct SimplifyCondBranchIdenticalSuccessors
|
|||
return success();
|
||||
}
|
||||
};
|
||||
|
||||
/// ...
|
||||
/// cond_br %cond, ^bb1(...), ^bb2(...)
|
||||
/// ...
|
||||
/// ^bb1: // has single predecessor
|
||||
/// ...
|
||||
/// cond_br %cond, ^bb3(...), ^bb4(...)
|
||||
///
|
||||
/// ->
|
||||
///
|
||||
/// ...
|
||||
/// cond_br %cond, ^bb1(...), ^bb2(...)
|
||||
/// ...
|
||||
/// ^bb1: // has single predecessor
|
||||
/// ...
|
||||
/// br ^bb3(...)
|
||||
///
|
||||
struct SimplifyCondBranchFromCondBranchOnSameCondition
|
||||
: public OpRewritePattern<CondBranchOp> {
|
||||
using OpRewritePattern<CondBranchOp>::OpRewritePattern;
|
||||
|
||||
LogicalResult matchAndRewrite(CondBranchOp condbr,
|
||||
PatternRewriter &rewriter) const override {
|
||||
// Check that we have a single distinct predecessor.
|
||||
Block *currentBlock = condbr.getOperation()->getBlock();
|
||||
Block *predecessor = currentBlock->getSinglePredecessor();
|
||||
if (!predecessor)
|
||||
return failure();
|
||||
|
||||
// Check that the predecessor terminates with a conditional branch to this
|
||||
// block and that it branches on the same condition.
|
||||
auto predBranch = dyn_cast<CondBranchOp>(predecessor->getTerminator());
|
||||
if (!predBranch || condbr.getCondition() != predBranch.getCondition())
|
||||
return failure();
|
||||
|
||||
// Fold this branch to an unconditional branch.
|
||||
if (currentBlock == predBranch.trueDest())
|
||||
rewriter.replaceOpWithNewOp<BranchOp>(condbr, condbr.trueDest(),
|
||||
condbr.trueDestOperands());
|
||||
else
|
||||
rewriter.replaceOpWithNewOp<BranchOp>(condbr, condbr.falseDest(),
|
||||
condbr.falseDestOperands());
|
||||
return success();
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void CondBranchOp::getCanonicalizationPatterns(
|
||||
OwningRewritePatternList &results, MLIRContext *context) {
|
||||
results.insert<SimplifyConstCondBranchPred, SimplifyPassThroughCondBranch,
|
||||
SimplifyCondBranchIdenticalSuccessors>(context);
|
||||
SimplifyCondBranchIdenticalSuccessors,
|
||||
SimplifyCondBranchFromCondBranchOnSameCondition>(context);
|
||||
}
|
||||
|
||||
Optional<MutableOperandRange>
|
||||
|
|
|
@ -139,6 +139,27 @@ func @cond_br_pass_through_fail(%cond : i1) {
|
|||
return
|
||||
}
|
||||
|
||||
/// Test folding conditional branches that are successors of conditional
|
||||
/// branches with the same condition.
|
||||
|
||||
// CHECK-LABEL: func @cond_br_from_cond_br_with_same_condition
|
||||
func @cond_br_from_cond_br_with_same_condition(%cond : i1) {
|
||||
// CHECK: cond_br %{{.*}}, ^bb1, ^bb2
|
||||
// CHECK: ^bb1:
|
||||
// CHECK: return
|
||||
|
||||
cond_br %cond, ^bb1, ^bb2
|
||||
|
||||
^bb1:
|
||||
cond_br %cond, ^bb3, ^bb2
|
||||
|
||||
^bb2:
|
||||
"foo.terminator"() : () -> ()
|
||||
|
||||
^bb3:
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Erase assertion if condition is known to be true at compile time.
|
||||
|
|
|
@ -178,23 +178,23 @@ func @contains_regions(%cond : i1) {
|
|||
// block is used in another.
|
||||
|
||||
// CHECK-LABEL: func @mismatch_loop(
|
||||
// CHECK-SAME: %[[ARG:.*]]: i1
|
||||
func @mismatch_loop(%cond : i1) {
|
||||
// CHECK: cond_br %{{.*}}, ^bb1(%[[ARG]] : i1), ^bb2
|
||||
// CHECK-SAME: %[[ARG:.*]]: i1, %[[ARG2:.*]]: i1
|
||||
func @mismatch_loop(%cond : i1, %cond2 : i1) {
|
||||
// CHECK: cond_br %{{.*}}, ^bb1(%[[ARG2]] : i1), ^bb2
|
||||
|
||||
cond_br %cond, ^bb2, ^bb3
|
||||
|
||||
^bb1:
|
||||
// CHECK: ^bb1(%[[ARG2:.*]]: i1):
|
||||
// CHECK: ^bb1(%[[ARG3:.*]]: i1):
|
||||
// CHECK-NEXT: %[[LOOP_CARRY:.*]] = "foo.op"
|
||||
// CHECK-NEXT: cond_br %[[ARG2]], ^bb1(%[[LOOP_CARRY]] : i1), ^bb2
|
||||
// CHECK-NEXT: cond_br %[[ARG3]], ^bb1(%[[LOOP_CARRY]] : i1), ^bb2
|
||||
|
||||
%ignored = "foo.op"() : () -> (i1)
|
||||
cond_br %cond2, ^bb1, ^bb3
|
||||
cond_br %cond3, ^bb1, ^bb3
|
||||
|
||||
^bb2:
|
||||
%cond2 = "foo.op"() : () -> (i1)
|
||||
cond_br %cond, ^bb1, ^bb3
|
||||
%cond3 = "foo.op"() : () -> (i1)
|
||||
cond_br %cond2, ^bb1, ^bb3
|
||||
|
||||
^bb3:
|
||||
// CHECK: ^bb2:
|
||||
|
|
Loading…
Reference in New Issue