[Mlir-commits] [mlir] [mlir][tblgen] Define enum `FieldParser` specializations out-of-line (PR #233730)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Oct 20 00:47:50 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-core

Author: Markus Böck (zero9178)

<details>
<summary>Changes</summary>

The `FieldParser` specializations generated for every enum were defined inline in the enum declarations header. Since their bodies do not depend on the `ParserT` template parameter, they are type-checked eagerly in every translation unit including the header, which instantiates `FailureOr<E>`, `FailureOr<std::optional<E>>` and their `std::optional` bases and type traits for every enum. Only a small fraction of these specializations is ever used, and only from the generated attribute and op parsers of the dialect itself.

This patch changes `parse` to a non-template taking an `AsmParser &`, declares it in the header and emits its definition into the enum definitions file instead.

Compiling all of MLIR (clang 18 with 64 cores) takes 4.5% less CPU time, with the median translation unit compiling 2.8% faster and some up to 15% faster. The summed peak memory usage of all translation units drops by 4.5% and the largest peak memory usage of a single translation unit (`mlir/lib/CAPI/Conversion/Passes.cpp`) drops by 13% (1710 MB -> 1492 MB). A translation unit only including `NVVMDialect.h` compiles 12% faster with 14% lower peak memory usage.

---

Patch is 25.28 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/233730.diff


7 Files Affected:

- (modified) mlir/include/mlir/TableGen/EnumInfo.h (+10) 
- (modified) mlir/lib/TableGen/EnumInfo.cpp (+14) 
- (modified) mlir/test/mlir-tblgen/enums-gen.td (+42-31) 
- (modified) mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp (+1-1) 
- (modified) mlir/tools/mlir-tblgen/EnumsGen.cpp (+188-150) 
- (modified) mlir/tools/mlir-tblgen/OpFormatGen.cpp (+1-1) 
- (modified) mlir/unittests/TableGen/EnumsGenTest.cpp (+1) 


``````````diff
diff --git a/mlir/include/mlir/TableGen/EnumInfo.h b/mlir/include/mlir/TableGen/EnumInfo.h
index aea76c01e7e7a..d8dfd3489cf6b 100644
--- a/mlir/include/mlir/TableGen/EnumInfo.h
+++ b/mlir/include/mlir/TableGen/EnumInfo.h
@@ -72,12 +72,22 @@ class EnumInfo {
   // Returns true if this is a bit enum.
   bool isBitEnum() const;
 
+  // Returns true if this is a bit enum whose cases are parsed and printed as
+  // separate, unquoted keywords.
+  bool isNewStyleBitEnum() const;
+
+  // Returns true if a 'FieldParser' and a printer are generated for the enum.
+  bool hasParserPrinter() const;
+
   // Returns the enum class name.
   StringRef getEnumClassName() const;
 
   // Returns the C++ namespaces this enum class should be placed in.
   StringRef getCppNamespace() const;
 
+  // Returns the fully qualified C++ name of the enum class.
+  std::string getQualifiedName() const;
+
   // Returns the summary of the enum.
   StringRef getSummary() const;
 
diff --git a/mlir/lib/TableGen/EnumInfo.cpp b/mlir/lib/TableGen/EnumInfo.cpp
index 6128c53557cc4..99960c8df29d2 100644
--- a/mlir/lib/TableGen/EnumInfo.cpp
+++ b/mlir/lib/TableGen/EnumInfo.cpp
@@ -57,6 +57,16 @@ std::optional<Attribute> EnumInfo::asEnumAttr() const {
 
 bool EnumInfo::isBitEnum() const { return isSubClassOf("BitEnumBase"); }
 
+bool EnumInfo::isNewStyleBitEnum() const {
+  return isBitEnum() && !printBitEnumQuoted();
+}
+
+bool EnumInfo::hasParserPrinter() const {
+  std::optional<Attribute> enumAttrInfo = asEnumAttr();
+  return !getUnderlyingType().empty() &&
+         (!enumAttrInfo || !enumAttrInfo->getConstBuilderTemplate().empty());
+}
+
 StringRef EnumInfo::getEnumClassName() const {
   return def->getValueAsString("className");
 }
@@ -73,6 +83,10 @@ StringRef EnumInfo::getCppNamespace() const {
   return def->getValueAsString("cppNamespace");
 }
 
+std::string EnumInfo::getQualifiedName() const {
+  return (getCppNamespace() + "::" + getEnumClassName()).str();
+}
+
 int64_t EnumInfo::getBitwidth() const { return def->getValueAsInt("bitwidth"); }
 
 StringRef EnumInfo::getUnderlyingType() const {
diff --git a/mlir/test/mlir-tblgen/enums-gen.td b/mlir/test/mlir-tblgen/enums-gen.td
index e64e50b2382cb..dc0caab3652d9 100644
--- a/mlir/test/mlir-tblgen/enums-gen.td
+++ b/mlir/test/mlir-tblgen/enums-gen.td
@@ -32,21 +32,13 @@ def MyBitEnum: I32BitEnumAttr<"MyBitEnum", "An example bit enum",
 // DECL: ::std::optional<MyBitEnum> symbolizeMyBitEnum(::llvm::StringRef);
 
 // DECL: struct FieldParser<::MyBitEnum, ::MyBitEnum> {
-// DECL:   template <typename ParserT>
-// DECL:   static FailureOr<::MyBitEnum> parse(ParserT &parser) {
-// DECL:     // Parse the keyword/string containing the enum.
-// DECL:     std::string enumKeyword;
-// DECL:     auto loc = parser.getCurrentLocation();
-// DECL:     if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
-// DECL:       return parser.emitError(loc, "expected keyword for An example bit enum");
-// DECL:     // Symbolize the keyword.
-// DECL:     if (::std::optional<::MyBitEnum> attr = ::symbolizeEnum<::MyBitEnum>(enumKeyword))
-// DECL:       return *attr;
-// DECL:     return parser.emitError(loc, "expected one of [none, tagged, Bit1, Bit2, Bit3, BitGroup] for An example bit enum, got: ") << enumKeyword;
-// DECL:   }
+// DECL-NEXT:   static FailureOr<::MyBitEnum> parse(AsmParser &parser);
+// DECL-NEXT: };
 
 // DECL: struct FieldParser<std::optional<::MyBitEnum>, std::optional<::MyBitEnum>> {
 // DECL:   static constexpr bool isKeyValueCompositional = false;
+// DECL:   static FailureOr<std::optional<::MyBitEnum>> parse(AsmParser &parser);
+// DECL-NEXT: };
 
 // DECL: inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::MyBitEnum value) {
 // DECL:   auto valueStr = stringifyEnum(value);
@@ -101,6 +93,23 @@ def MyBitEnum: I32BitEnumAttr<"MyBitEnum", "An example bit enum",
 // DEF: .Case("tagged", 1)
 // DEF: .Case("Bit1", 2)
 
+// DEF-LABEL: FailureOr<::MyBitEnum> FieldParser<::MyBitEnum, ::MyBitEnum>::parse(AsmParser &parser) {
+// DEF:   // Parse the keyword/string containing the enum.
+// DEF:   std::string enumKeyword;
+// DEF:   auto loc = parser.getCurrentLocation();
+// DEF:   if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
+// DEF:     return parser.emitError(loc, "expected keyword for An example bit enum");
+// DEF:   // Symbolize the keyword.
+// DEF:   if (::std::optional<::MyBitEnum> attr = ::symbolizeEnum<::MyBitEnum>(enumKeyword))
+// DEF:     return *attr;
+// DEF:   return parser.emitError(loc, "expected one of [none, tagged, Bit1, Bit2, Bit3, BitGroup] for An example bit enum, got: ") << enumKeyword;
+// DEF: }
+
+// DEF-LABEL: FailureOr<std::optional<::MyBitEnum>>
+// DEF-NEXT: FieldParser<std::optional<::MyBitEnum>, std::optional<::MyBitEnum>>::parse(AsmParser &parser) {
+// DEF:   if (failed(parser.parseOptionalKeywordOrString(&enumKeyword, {"none", "tagged", "Bit1", "Bit2", "Bit3", "BitGroup"})))
+// DEF-NEXT:     return std::optional<::MyBitEnum>{};
+
 // Test enum printer generation for non non-keyword enums.
 
 def NonKeywordBit: I32BitEnumCaseBit<"Bit0", 0, "tag-ged">;
@@ -138,25 +147,27 @@ def MyNonQuotedPrintBitEnum
 
 // DECL: struct FieldParser<::MyNonQuotedPrintBitEnum, ::MyNonQuotedPrintBitEnum> {
 // DECL:   static constexpr bool isKeyValueCompositional = true;
-// DECL:   template <typename ParserT>
-// DECL:   static FailureOr<::MyNonQuotedPrintBitEnum> parse(ParserT &parser) {
-// DECL:     ::MyNonQuotedPrintBitEnum flags = {};
-// DECL:     do {
-  // DECL:     // Parse the keyword containing a part of the enum.
-// DECL:       ::llvm::StringRef enumKeyword;
-// DECL:       auto loc = parser.getCurrentLocation();
-// DECL:       if (failed(parser.parseOptionalKeyword(&enumKeyword))) {
-// DECL:         return parser.emitError(loc, "expected keyword for Example new-style bit enum");
-// DECL:       }
-// DECL:       // Symbolize the keyword.
-// DECL:       if (::std::optional<::MyNonQuotedPrintBitEnum> flag = ::symbolizeEnum<::MyNonQuotedPrintBitEnum>(enumKeyword))
-// DECL:         flags = flags | *flag;
-// DECL:       } else {
-// DECL:         return parser.emitError(loc, "expected one of [none, tagged, Bit1, Bit2, Bit3, BitGroup] for Example new-style bit enum, got: ") << enumKeyword;
-// DECL:       }
-// DECL:     } while (::mlir::succeeded(parser.parseOptionalVerticalBar()));
-// DECL:     return flags;
-// DECL:   }
+// DECL:   static FailureOr<::MyNonQuotedPrintBitEnum> parse(AsmParser &parser);
+// DECL-NEXT: };
+
+// DEF-LABEL: FailureOr<::MyNonQuotedPrintBitEnum> FieldParser<::MyNonQuotedPrintBitEnum, ::MyNonQuotedPrintBitEnum>::parse(AsmParser &parser) {
+// DEF:   ::MyNonQuotedPrintBitEnum flags = {};
+// DEF:   do {
+// DEF:     // Parse the keyword containing a part of the enum.
+// DEF:     ::llvm::StringRef enumKeyword;
+// DEF:     auto loc = parser.getCurrentLocation();
+// DEF:     if (failed(parser.parseOptionalKeyword(&enumKeyword))) {
+// DEF:       return parser.emitError(loc, "expected keyword for Example new-style bit enum");
+// DEF:     }
+// DEF:     // Symbolize the keyword.
+// DEF:     if (::std::optional<::MyNonQuotedPrintBitEnum> flag = ::symbolizeEnum<::MyNonQuotedPrintBitEnum>(enumKeyword)) {
+// DEF:       flags = flags | *flag;
+// DEF:     } else {
+// DEF:       return parser.emitError(loc, "expected one of [none, tagged, Bit1, Bit2, Bit3, BitGroup] for Example new-style bit enum, got: ") << enumKeyword;
+// DEF:     }
+// DEF:   } while (::mlir::succeeded(parser.parseOptionalVerticalBar()));
+// DEF:   return flags;
+// DEF: }
 
 def MyCommaSeparatedBitEnum
   : I32BitEnum<"MyCommaSeparatedBitEnum", "Comma-separated bit enum",
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
index eed05558447de..853ba5b0d0c71 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
@@ -125,7 +125,7 @@ static bool isUndelimitedCommaBitEnumParam(const ParameterElement *el) {
   if (!enumAttr)
     return false;
   EnumInfo enumInfo(enumAttr->getValueAsDef("enum"));
-  return enumInfo.isBitEnum() && !enumInfo.printBitEnumQuoted() &&
+  return enumInfo.isNewStyleBitEnum() &&
          enumInfo.getDef().getValueAsString("separator").trim() == ",";
 }
 
diff --git a/mlir/tools/mlir-tblgen/EnumsGen.cpp b/mlir/tools/mlir-tblgen/EnumsGen.cpp
index 845f1ef46cf35..c83ed3cf42fcd 100644
--- a/mlir/tools/mlir-tblgen/EnumsGen.cpp
+++ b/mlir/tools/mlir-tblgen/EnumsGen.cpp
@@ -66,26 +66,71 @@ static void emitEnumClass(const Record &enumDef, StringRef enumName,
   os << "};\n\n";
 }
 
-static void emitParserPrinter(const EnumInfo &enumInfo, StringRef qualName,
-                              StringRef cppNamespace, raw_ostream &os) {
-  std::optional<Attribute> enumAttrInfo = enumInfo.asEnumAttr();
-  if (enumInfo.getUnderlyingType().empty() ||
-      (enumAttrInfo && enumAttrInfo->getConstBuilderTemplate().empty()))
-    return;
+/// Returns a bit vector with a bit set for every case that cannot be printed
+/// as a keyword.
+static BitVector getNonKeywordCases(ArrayRef<EnumCase> cases) {
+  BitVector nonKeywordCases(cases.size());
+  for (auto [index, enumerant] : llvm::enumerate(cases))
+    if (!tblgen::canFormatStringAsKeyword(enumerant.getStr()))
+      nonKeywordCases.set(index);
+  return nonKeywordCases;
+}
+
+/// Emits the declarations of the 'FieldParser' specializations of the enum.
+/// The definitions are emitted by 'emitFieldParserDefs' into the enum
+/// definitions file instead of inline in the header. The bodies would otherwise
+/// be type-checked and require instantiating the 'FailureOr' and
+/// 'std::optional' types in every translation unit including the header,
+/// despite rarely being used. The forward declarations of 'AsmParser' and
+/// 'FieldParser' are emitted once per file by 'emitEnumDecls'.
+static void emitFieldParserDecls(const EnumInfo &enumInfo, StringRef qualName,
+                                 raw_ostream &os) {
+  const char *const fieldParserDecls = R"(
+namespace mlir {
+template<>
+struct FieldParser<{0}, {0}> {{{1}
+  static FailureOr<{0}> parse(AsmParser &parser);
+};
+
+/// Support for std::optional, useful in attribute/type definition where the enum is
+/// used as:
+///
+///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
+template<>
+struct FieldParser<std::optional<{0}>, std::optional<{0}>> {{
+  static constexpr bool isKeyValueCompositional = false;
+
+  static FailureOr<std::optional<{0}>> parse(AsmParser &parser);
+};
+} // namespace mlir
+)";
+
+  std::string isKeyValueCompositional;
+  if (enumInfo.isNewStyleBitEnum()) {
+    StringRef separator = enumInfo.getDef().getValueAsString("separator");
+    isKeyValueCompositional =
+        formatv("\n  static constexpr bool isKeyValueCompositional = {0};\n",
+                separator.trim() == "," ? "false" : "true");
+  }
+  os << formatv(fieldParserDecls, qualName, isKeyValueCompositional);
+}
+
+/// Emits the definitions of the 'FieldParser' specializations declared by
+/// 'emitFieldParserDecls'.
+static void emitFieldParserDefs(const EnumInfo &enumInfo, raw_ostream &os) {
+  std::string qualName = enumInfo.getQualifiedName();
+  StringRef cppNamespace = enumInfo.getCppNamespace();
   auto cases = enumInfo.getAllCases();
+  BitVector nonKeywordCases = getNonKeywordCases(cases);
 
-  // Check which cases shouldn't be printed using a keyword.
-  llvm::BitVector nonKeywordCases(cases.size());
   std::string casesList;
   llvm::raw_string_ostream caseListOs(casesList);
   caseListOs << "[";
   llvm::interleaveComma(llvm::enumerate(cases), caseListOs,
                         [&](auto enumerant) {
                           StringRef name = enumerant.value().getStr();
-                          if (!mlir::tblgen::canFormatStringAsKeyword(name)) {
-                            nonKeywordCases.set(enumerant.index());
+                          if (nonKeywordCases.test(enumerant.index()))
                             caseListOs << "\\\"" << name << "\\\"";
-                          }
                           caseListOs << name;
                         });
   caseListOs << "]";
@@ -99,151 +144,125 @@ static void emitParserPrinter(const EnumInfo &enumInfo, StringRef qualName,
                         });
   casesInitListOs << "}";
 
-  // Generate the parser and the start of the printer for the enum, excluding
-  // non-quoted bit enums.
-  const char *parsedAndPrinterStart = R"(
+  // Generate the parser for the enum, excluding non-quoted bit enums.
+  const char *const fieldParserDefs = R"(
 namespace mlir {
-template <typename T, typename>
-struct FieldParser;
+FailureOr<{0}> FieldParser<{0}, {0}>::parse(AsmParser &parser) {{
+  // Parse the keyword/string containing the enum.
+  std::string enumKeyword;
+  auto loc = parser.getCurrentLocation();
+  if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
+    return parser.emitError(loc, "expected keyword for {2}");
+
+  // Symbolize the keyword.
+  if (::std::optional<{0}> attr = {1}::symbolizeEnum<{0}>(enumKeyword))
+    return *attr;
+  return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
+}
 
-template<>
-struct FieldParser<{0}, {0}> {{
-  template <typename ParserT>
-  static FailureOr<{0}> parse(ParserT &parser) {{
-    // Parse the keyword/string containing the enum.
-    std::string enumKeyword;
+FailureOr<std::optional<{0}>>
+FieldParser<std::optional<{0}>, std::optional<{0}>>::parse(AsmParser &parser) {{
+  // Parse the keyword/string containing the enum.
+  std::string enumKeyword;
+  auto loc = parser.getCurrentLocation();
+  if (failed(parser.parseOptionalKeywordOrString(&enumKeyword, {4})))
+    return std::optional<{0}>{{};
+
+  // Symbolize the keyword.
+  if (::std::optional<{0}> attr = {1}::symbolizeEnum<{0}>(enumKeyword))
+    return attr;
+  return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
+}
+} // namespace mlir
+)";
+
+  const char *const fieldParserDefsUnquotedBitEnum = R"(
+namespace mlir {
+FailureOr<{0}> FieldParser<{0}, {0}>::parse(AsmParser &parser) {{
+  {0} flags = {{};
+  do {{
+    // Parse the keyword containing a part of the enum.
+    ::llvm::StringRef enumKeyword;
     auto loc = parser.getCurrentLocation();
-    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
+    if (failed(parser.parseOptionalKeyword(&enumKeyword))) {{
       return parser.emitError(loc, "expected keyword for {2}");
+    }
 
     // Symbolize the keyword.
-    if (::std::optional<{0}> attr = {1}::symbolizeEnum<{0}>(enumKeyword))
-      return *attr;
-    return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
-  }
-};
-
-/// Support for std::optional, useful in attribute/type definition where the enum is
-/// used as:
-///
-///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
-template<>
-struct FieldParser<std::optional<{0}>, std::optional<{0}>> {{
-  static constexpr bool isKeyValueCompositional = false;
+    if (::std::optional<{0}> flag = {1}::symbolizeEnum<{0}>(enumKeyword)) {{
+      flags = flags | *flag;
+    } else {{
+      return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
+    }
+  } while (::mlir::succeeded(parser.{5}()));
+  return flags;
+}
 
-  template <typename ParserT>
-  static FailureOr<std::optional<{0}>> parse(ParserT &parser) {{
-    // Parse the keyword/string containing the enum.
-    std::string enumKeyword;
+FailureOr<std::optional<{0}>>
+FieldParser<std::optional<{0}>, std::optional<{0}>>::parse(AsmParser &parser) {{
+  {0} flags = {{};
+  bool firstIter = true;
+  do {{
+    // Parse the keyword containing a part of the enum.
+    ::llvm::StringRef enumKeyword;
     auto loc = parser.getCurrentLocation();
-    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword, {4})))
-      return std::optional<{0}>{{};
+    if (failed(parser.parseOptionalKeyword(&enumKeyword, {6}))) {{
+      if (firstIter)
+        return std::optional<{0}>{{};
+      return parser.emitError(loc, "expected keyword for {2} after '{4}'");
+    }
+    firstIter = false;
 
     // Symbolize the keyword.
-    if (::std::optional<{0}> attr = {1}::symbolizeEnum<{0}>(enumKeyword))
-      return attr;
-    return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
-  }
-};
+    if (::std::optional<{0}> flag = {1}::symbolizeEnum<{0}>(enumKeyword)) {{
+      flags = flags | *flag;
+    } else {{
+      return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
+    }
+  } while(::mlir::succeeded(parser.{5}()));
+  return std::optional<{0}>{{flags};
+}
 } // namespace mlir
-
-namespace llvm {
-inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, {0} value) {{
-  auto valueStr = stringifyEnum(value);
 )";
 
-  const char *parsedAndPrinterStartUnquotedBitEnum = R"(
-  namespace mlir {
-  template <typename T, typename>
-  struct FieldParser;
-
-  template<>
-  struct FieldParser<{0}, {0}> {{
-    static constexpr bool isKeyValueCompositional = {7};
-
-    template <typename ParserT>
-    static FailureOr<{0}> parse(ParserT &parser) {{
-      {0} flags = {{};
-      do {{
-        // Parse the keyword containing a part of the enum.
-        ::llvm::StringRef enumKeyword;
-        auto loc = parser.getCurrentLocation();
-        if (failed(parser.parseOptionalKeyword(&enumKeyword))) {{
-          return parser.emitError(loc, "expected keyword for {2}");
-        }
-
-        // Symbolize the keyword.
-        if (::std::optional<{0}> flag = {1}::symbolizeEnum<{0}>(enumKeyword)) {{
-          flags = flags | *flag;
-        } else {{
-          return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
-        }
-      } while (::mlir::succeeded(parser.{5}()));
-      return flags;
-    }
-  };
-
-  /// Support for std::optional, useful in attribute/type definition where the enum is
-  /// used as:
-  ///
-  ///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
-  template<>
-  struct FieldParser<std::optional<{0}>, std::optional<{0}>> {{
-    static constexpr bool isKeyValueCompositional = false;
-
-    template <typename ParserT>
-    static FailureOr<std::optional<{0}>> parse(ParserT &parser) {{
-      {0} flags = {{};
-      bool firstIter = true;
-      do {{
-        // Parse the keyword containing a part of the enum.
-        ::llvm::StringRef enumKeyword;
-        auto loc = parser.getCurrentLocation();
-        if (failed(parser.parseOptionalKeyword(&enumKeyword, {6}))) {{
-          if (firstIter)
-            return std::optional<{0}>{{};
-          return parser.emitError(loc, "expected keyword for {2} after '{4}'");
-        }
-        firstIter = false;
-
-        // Symbolize the keyword.
-        if (::std::optional<{0}> flag = {1}::symbolizeEnum<{0}>(enumKeyword)) {{
-          flags = flags | *flag;
-        } else {{
-          return parser.emitError(loc, "expected one of {3} for {2}, got: ") << enumKeyword;
-        }
-      } while(::mlir::succeeded(parser.{5}()));
-      return std::optional<{0}>{{flags};
-    }
-  };
-  } // namespace mlir
-
-  namespace llvm {
-  inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, {0} value) {{
-    auto valueStr = stringifyEnum(value);
-  )";
-
-  bool isNewStyleBitEnum =
-      enumInfo.isBitEnum() && !enumInfo.printBitEnumQuoted();
-
-  if (isNewStyleBitEnum) {
-    if (nonKeywordCases.any())
-      return PrintFatalError(
-          "bit enum " + qualName +
-          " cannot be printed unquoted with cases that cannot be keywords");
+  if (enumInfo.isNewStyleBitEnum()) {
     StringRef separator = enumInfo.getDef().getValueAsString("separator");
     StringRef parseSeparatorFn =
         llvm::StringSwitch<StringRef>(separator.trim())
             .Case("|", "parseOptionalVerticalBar")
             .Case(",", "parseOptionalComma")
             .Default("error, enum separator must be '|' or ','");
-    os << formatv(parsedAndPrinterStartUnquotedBitEnum, qualName, cppNamespace,
+    os << formatv(fieldParserDefsUnquotedBitEnum, qualName, cppNamespace,
                   enumInfo.getSummary(), casesList, separator, parseSeparatorFn,
-                  casesInitList, separator.trim() == "," ? "false" : "true");
+                  casesInitList);...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/233730


More information about the Mlir-commits mailing list