[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