diff --git a/mlir/lib/Transforms/CSE.cpp b/mlir/lib/Transforms/CSE.cpp --- a/mlir/lib/Transforms/CSE.cpp +++ b/mlir/lib/Transforms/CSE.cpp @@ -50,7 +50,11 @@ // If op has no regions, operation equivalence w.r.t operands alone is // enough. - if (lhs->getNumRegions() == 0 && rhs->getNumRegions() == 0) { + auto hasNoOrEmptyRegion = [](Operation *op) { + return op->getNumRegions() == 0 || + (op->getNumRegions() == 1 && op->getRegion(0).empty()); + }; + if (hasNoOrEmptyRegion(lhs) && hasNoOrEmptyRegion(rhs)) { return OperationEquivalence::isEquivalentTo( const_cast(lhsC), const_cast(rhsC), OperationEquivalence::exactValueMatch, @@ -264,7 +268,8 @@ // equality comparisons correctly among other things. It is also unclear // whether we would want to CSE such operations. if (op->getNumRegions() != 0 && - (op->getNumRegions() != 1 || !llvm::hasSingleElement(op->getRegion(0)))) + (op->getNumRegions() != 1 || + !(llvm::hasSingleElement(op->getRegion(0)) || op->getRegion(0).empty()))) return failure(); // Some simple use case of operation with memory side-effect are dealt with diff --git a/mlir/test/Transforms/cse.mlir b/mlir/test/Transforms/cse.mlir --- a/mlir/test/Transforms/cse.mlir +++ b/mlir/test/Transforms/cse.mlir @@ -468,3 +468,17 @@ // CHECK: %[[OP:.+]] = test.cse_of_single_block_op // CHECK: test.region_yield %[[TRUE]] // CHECK: return %[[OP]], %[[OP]] + +// Operations with empty region CSE +// CHECK-LABEL: func @cse_ops_with_empty_region +// CHECK: %[[OP0:.*[0]]] = "test.any_cond" +// CHECK-NOT: %[[OP1:.*[0]]] = "test.any_cond" +// CHECK: return %[[OP0]], %[[OP0]] +func.func @cse_ops_with_empty_region() + -> (i32, i32) { + %0 = "test.any_cond"() ({ + }) : () -> i32 + %1 = "test.any_cond"() ({ + }) : () -> i32 + return %0, %1 : i32, i32 +} \ No newline at end of file