[Mlir-commits] [mlir] e936c3b - [mlir][ods] Allow custom directives in optional groups
Jeff Niu
llvmlistbot at llvm.org
Wed Oct 12 17:56:00 PDT 2022
Author: Jeff Niu
Date: 2022-10-12T17:55:51-07:00
New Revision: e936c3bb48c758ff4f490367d80db5a04170a9e8
URL: https://github.com/llvm/llvm-project/commit/e936c3bb48c758ff4f490367d80db5a04170a9e8
DIFF: https://github.com/llvm/llvm-project/commit/e936c3bb48c758ff4f490367d80db5a04170a9e8.diff
LOG: [mlir][ods] Allow custom directives in optional groups
Attributes and types only (so far). Since `struct` and `params` are
allowed, it makes sense to allow custom directives as long as their
arguments contain at least one bound argument.
Reviewed By: rriddle
Differential Revision: https://reviews.llvm.org/D135001
Added:
Modified:
mlir/docs/AttributesAndTypes.md
mlir/test/lib/Dialect/Test/TestAttrDefs.td
mlir/test/lib/Dialect/Test/TestAttributes.cpp
mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir
mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
Removed:
################################################################################
diff --git a/mlir/docs/AttributesAndTypes.md b/mlir/docs/AttributesAndTypes.md
index 8d1307f08e612..7e54c2ee0cd1b 100644
--- a/mlir/docs/AttributesAndTypes.md
+++ b/mlir/docs/AttributesAndTypes.md
@@ -656,11 +656,16 @@ default-constructed value for the C++ storage type. For example, `Optional<int>`
will be set to `llvm::None` and `Attribute` will be set to `nullptr`. The
presence of these parameters is tested by comparing them to their "null" values.
-Only optional parameters or directives that only capture optional parameters can
-be used in optional groups. An optional group is a set of elements optionally
-printed based on the presence of an anchor. The group in which the anchor is
-placed is printed if it is present, otherwise the other one is printed. Suppose
-parameter `a` is an `IntegerAttr`.
+An optional group is a set of elements optionally printed based on the presence
+of an anchor. Only optional parameters or directives that only capture optional
+parameters can be used in optional groups. The group in which the anchor is
+placed is printed if it is present, otherwise the other one is printed. If a
+directive that captures more than one optional parameter is used as the anchor,
+the optional group is printed if any of the captured parameters is present. For
+example, a `custom` directive may only be used as an optional group anchor if it
+captures at least one optional parameter.
+
+Suppose parameter `a` is an `IntegerAttr`.
```
( `(` $a^ `)` ) : (`x`)?
diff --git a/mlir/test/lib/Dialect/Test/TestAttrDefs.td b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
index 5ffcbccfc3963..07cfca121f62d 100644
--- a/mlir/test/lib/Dialect/Test/TestAttrDefs.td
+++ b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
@@ -291,4 +291,11 @@ def TestSimpleEnumAttr : EnumAttr<Test_Dialect, TestSimpleEnum, "simple_enum"> {
def TestArrayOfEnums : ArrayOfAttr<Test_Dialect, "ArrayOfEnums",
"array_of_enums", "SimpleEnumAttr">;
+// Test custom directive as optional group anchor.
+def TestCustomAnchor : Test_Attr<"TestCustomAnchor"> {
+ let parameters = (ins "int":$a, OptionalParameter<"mlir::Optional<int>">:$b);
+ let mnemonic = "custom_anchor";
+ let assemblyFormat = "`<` $a (`>`) : (`,` ` ` custom<TrueFalse>($b)^ `>`)?";
+}
+
#endif // TEST_ATTRDEFS
diff --git a/mlir/test/lib/Dialect/Test/TestAttributes.cpp b/mlir/test/lib/Dialect/Test/TestAttributes.cpp
index 1cbc4df06aa9d..28fde0987ac09 100644
--- a/mlir/test/lib/Dialect/Test/TestAttributes.cpp
+++ b/mlir/test/lib/Dialect/Test/TestAttributes.cpp
@@ -174,6 +174,23 @@ ArrayRef<uint64_t> TestExtern1DI64ElementsAttr::getElements() const {
return llvm::None;
}
+//===----------------------------------------------------------------------===//
+// TestCustomAnchorAttr
+//===----------------------------------------------------------------------===//
+
+static ParseResult parseTrueFalse(AsmParser &p,
+ FailureOr<Optional<int>> &result) {
+ bool b;
+ if (p.parseInteger(b))
+ return failure();
+ result = Optional<int>(b);
+ return success();
+}
+
+static void printTrueFalse(AsmPrinter &p, Optional<int> result) {
+ p << (*result ? "true" : "false");
+}
+
//===----------------------------------------------------------------------===//
// Tablegen Generated Definitions
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td b/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
index f1c481f00df27..d3be4d8b8022a 100644
--- a/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
+++ b/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
@@ -132,3 +132,15 @@ def InvalidTypeR : InvalidType<"InvalidTypeR", "invalid_r"> {
// CHECK: `struct` can only be used at the top-level context
let assemblyFormat = "custom<Foo>(struct(params))";
}
+
+def InvalidTypeS : InvalidType<"InvalidTypeS", "invalid_s"> {
+ let parameters = (ins OptionalParameter<"int">:$a, "int":$b);
+ // CHECK: `custom` is only allowed in an optional group if all captured parameters are optional
+ let assemblyFormat = "(`(` custom<Foo>($a, $b)^ `)`)?";
+}
+
+def InvalidTypeT : InvalidType<"InvalidTypeT", "invalid_t"> {
+ let parameters = (ins OptionalParameter<"int">:$a);
+ // CHECK: `custom` directive with no bound parameters cannot be used as optional group anchor
+ let assemblyFormat = "$a (`(` custom<Foo>(ref($a))^ `)`)?";
+}
diff --git a/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir b/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir
index 08e0a629f2cec..1abf362097160 100644
--- a/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir
+++ b/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir
@@ -16,7 +16,11 @@ attributes {
// CHECK: #test.attr_with_type<i32, vector<4xi32>>
attr4 = #test.attr_with_type<i32, vector<4xi32>>,
// CHECK: #test.attr_self_type_format<5> : i32
- attr5 = #test.attr_self_type_format<5> : i32
+ attr5 = #test.attr_self_type_format<5> : i32,
+ // CHECK: #test.custom_anchor<5>
+ attr6 = #test.custom_anchor<5>,
+ // CHECK: #test.custom_anchor<5, true>
+ attr7 = #test.custom_anchor<5, true>
}
// CHECK-LABEL: @test_roundtrip_default_parsers_struct
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
index 39bbdf31185d7..d094fcd70011b 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
@@ -849,9 +849,18 @@ void DefFormat::genOptionalGroupPrinter(OptionalElement *el, FmtContext &ctx,
guardOnAny(ctx, os, llvm::makeArrayRef(param), el->isInverted());
} else if (auto *params = dyn_cast<ParamsDirective>(anchor)) {
guardOnAny(ctx, os, params->getParams(), el->isInverted());
- } else {
- auto *strct = cast<StructDirective>(anchor);
+ } else if (auto *strct = dyn_cast<StructDirective>(anchor)) {
guardOnAny(ctx, os, strct->getParams(), el->isInverted());
+ } else {
+ auto *custom = cast<CustomDirective>(anchor);
+ guardOnAny(ctx, os,
+ llvm::make_filter_range(
+ llvm::map_range(custom->getArguments(),
+ [](FormatElement *el) {
+ return dyn_cast<ParameterElement>(el);
+ }),
+ [](ParameterElement *param) { return !!param; }),
+ el->isInverted());
}
// Generate the printer for the contained elements.
{
@@ -994,13 +1003,34 @@ DefFormatParser::verifyOptionalGroupElements(llvm::SMLoc loc,
return emitError(loc, "`struct` is only allowed in an optional group "
"if all captured parameters are optional");
}
+ } else if (auto *custom = dyn_cast<CustomDirective>(el)) {
+ for (FormatElement *el : custom->getArguments()) {
+ // If the custom argument is a variable, then it must be optional.
+ if (auto param = dyn_cast<ParameterElement>(el))
+ if (!param->isOptional())
+ return emitError(loc,
+ "`custom` is only allowed in an optional group if "
+ "all captured parameters are optional");
+ }
}
}
// The anchor must be a parameter or one of the aforementioned directives.
- if (anchor &&
- !isa<ParameterElement, ParamsDirective, StructDirective>(anchor)) {
- return emitError(loc,
- "optional group anchor must be a parameter or directive");
+ if (anchor) {
+ if (!isa<ParameterElement, ParamsDirective, StructDirective,
+ CustomDirective>(anchor)) {
+ return emitError(
+ loc, "optional group anchor must be a parameter or directive");
+ }
+ // If the anchor is a custom directive, make sure at least one of its
+ // arguments is a bound parameter.
+ if (auto custom = dyn_cast<CustomDirective>(anchor)) {
+ auto bound = llvm::find_if(custom->getArguments(), [](FormatElement *el) {
+ return isa<ParameterElement>(el);
+ });
+ if (bound == custom->getArguments().end())
+ return emitError(loc, "`custom` directive with no bound parameters "
+ "cannot be used as optional group anchor");
+ }
}
return success();
}
More information about the Mlir-commits
mailing list