[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:
River Riddle 2020-10-18 13:43:09 -07:00
parent 9d23224bf6
commit a8feeee15f
3 changed files with 76 additions and 9 deletions

View File

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

View File

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

View File

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