diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -2718,7 +2718,10 @@ if (auto opPrinter = dialect->getOperationPrinter(op)) { // Print the op name first. StringRef name = op->getName().getStringRef(); - name.consume_front((defaultDialectStack.back() + ".").str()); + // Only drop the default dialect prefix when it cannot lead to + // ambiguities. + if (name.count('.') == 1) + name.consume_front((defaultDialectStack.back() + ".").str()); printEscapedString(name, os); // Print the rest of the op now. opPrinter(op, *this); diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -624,11 +624,12 @@ } } -/// Print an operation name, eliding the dialect prefix if necessary. +/// Print an operation name, eliding the dialect prefix if necessary and doesn't +/// lead to ambiguities. void OpState::printOpName(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) { StringRef name = op->getName().getStringRef(); - if (name.startswith((defaultDialect + ".").str())) + if (name.startswith((defaultDialect + ".").str()) && name.count('.') == 1) name = name.drop_front(defaultDialect.size() + 1); p.getStream() << name; } diff --git a/mlir/test/IR/parser.mlir b/mlir/test/IR/parser.mlir --- a/mlir/test/IR/parser.mlir +++ b/mlir/test/IR/parser.mlir @@ -1282,6 +1282,14 @@ // example. // CHECK: "test.op_with_attr"() {test.attr = "test.value"} : () -> () "test.op_with_attr"() {test.attr = "test.value"} : () -> () + // Verify that the prefix is not stripped when it can lead to ambiguity. + // CHECK: test.op.with_dot_in_name + test.op.with_dot_in_name + // This is an unregistered operation, the printing/parsing is handled by the + // dialect, and the dialect prefix should not be stripped while printing + // because of potential ambiguity. + // CHECK: test.dialect_custom_printer.with.dot + test.dialect_custom_printer.with.dot "test.terminator"() : ()->() } // The same operation outside of the region does not have an func. prefix. diff --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp --- a/mlir/test/lib/Dialect/Test/TestDialect.cpp +++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp @@ -371,6 +371,11 @@ return parser.parseKeyword("custom_format_fallback"); }}; } + if (opName == "test.dialect_custom_printer.with.dot") { + return ParseOpHook{[](OpAsmParser &parser, OperationState &state) { + return ParseResult::success(); + }}; + } return None; } 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 @@ -810,6 +810,12 @@ let assemblyFormat = "regions attr-dict-with-keyword"; } +// This is used to test that the default dialect is not elided when printing an +// op with dots in the name to avoid parsing ambiguity. +def OpWithDotInNameOp : TEST_Op<"op.with_dot_in_name"> { + let assemblyFormat = "attr-dict"; +} + // This is used to test the OpAsmOpInterface::getAsmBlockName() feature: // blocks nested in a region under this op will have a name defined by the // interface.