diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -1660,6 +1660,24 @@ $x), (TestEitherOpB $arg2, $x)>; +def TestEitherHelperOpA : TEST_Op<"either_helper_op_a"> { + let arguments = (ins I32:$arg0); + let results = (outs I32:$output); +} + +def TestEitherHelperOpB : TEST_Op<"either_helper_op_b"> { + let arguments = (ins I32:$arg0); + let results = (outs I32:$output); +} + +// This test case ensures `emitOpMatch` doesn't redefine `castedOp{0}` local +// variables. To trigger this, we must ensure the matcher for +// `TestEitherHelperOpA` and `TestEitherHelperOpB` are not lifted as a static +// matcher. +def : Pat<(TestEitherOpB (either (TestEitherHelperOpA I32:$either_helper_0), + (TestEitherHelperOpB I32:$either_helper_1))), + (TestEitherOpB $either_helper_0, $either_helper_1)>; + //===----------------------------------------------------------------------===// // Test Patterns (Location) diff --git a/mlir/tools/mlir-tblgen/RewriterGen.cpp b/mlir/tools/mlir-tblgen/RewriterGen.cpp --- a/mlir/tools/mlir-tblgen/RewriterGen.cpp +++ b/mlir/tools/mlir-tblgen/RewriterGen.cpp @@ -715,11 +715,20 @@ os << formatv("auto {0} = (*v{1}.begin()).getDefiningOp();\n", argName, i); + + // Indent emitMatchCheck and emitMatch because they declare local + // variables. + os << "{\n"; + os.indent(); + emitMatchCheck( opName, /*matchStr=*/argName, formatv("\"There's no operation that defines operand {0} of {1}\"", operandIndex++, opName)); emitMatch(argTree, argName, depth + 1); + + os.unindent() << "}\n"; + // `tblgen_ops` is used to collect the matched operations. In either, we // need to queue the operation only if the matching success. Thus we emit // the code at the end.