[llvm-branch-commits] [mlir] 665d0a1 - Revert "[MLIR][ODS] Parse prop-dict fields with custom parsers (#217590)"

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Aug 21 11:47:23 PDT 2026


Author: Thurston Dang
Date: 2026-08-21T11:47:18-07:00
New Revision: 665d0a137fc2b79c1d686ad2b5843e0aeb17ef2f

URL: https://github.com/llvm/llvm-project/commit/665d0a137fc2b79c1d686ad2b5843e0aeb17ef2f
DIFF: https://github.com/llvm/llvm-project/commit/665d0a137fc2b79c1d686ad2b5843e0aeb17ef2f.diff

LOG: Revert "[MLIR][ODS] Parse prop-dict fields with custom parsers (#217590)"

This reverts commit d829d331449316ef4e19e63ca189f4c84067264b.

Added: 
    

Modified: 
    mlir/docs/DefiningDialects/Operations.md
    mlir/include/mlir/IR/DialectImplementation.h
    mlir/include/mlir/IR/OpDefinition.h
    mlir/include/mlir/TableGen/Property.h
    mlir/lib/TableGen/Property.cpp
    mlir/test/IR/properties.mlir
    mlir/test/lib/Dialect/Test/TestOps.h
    mlir/test/lib/Dialect/Test/TestOps.td
    mlir/test/mlir-tblgen/enums-gen.td
    mlir/tools/mlir-tblgen/EnumsGen.cpp
    mlir/tools/mlir-tblgen/OpFormatGen.cpp

Removed: 
    mlir/test/IR/properties-invalid.mlir


################################################################################
diff  --git a/mlir/docs/DefiningDialects/Operations.md b/mlir/docs/DefiningDialects/Operations.md
index 419041a52b0da..1ef96130d836d 100644
--- a/mlir/docs/DefiningDialects/Operations.md
+++ b/mlir/docs/DefiningDialects/Operations.md
@@ -760,17 +760,9 @@ The available directives are as follows:
 
 *   `prop-dict`
 
-    -   Represents the properties of the operation. The generated parser
-        accepts a `<key = value, ...>` list. Explicit property parsers and
-        inherent-attribute parsers must consume exactly one value and leave the
-        comma separating it from the next entry unconsumed. Properties relying
-        on the default parser use attribute conversion instead when no
-        `FieldParser` specialization is available or when the selected
-        specialization declares `isKeyValueCompositional = false`.
-    -   The legacy `<{key = attribute, ...}>` dictionary spelling is also
-        accepted when parsing and is used by the generated printer.
-    -   Any property or inherent attribute that is not used elsewhere in the
-        format is parsed and printed as part of this list.
+    -   Represents the properties of the operation converted to a dictionary.
+    -   Any property or inherent attribute that are not used elsewhere in the
+        format are parsed and printed as part of this dictionary.
     -   If present, the `attr-dict` will not contain any inherent attributes.
 
 *   `custom < UserDirective > ( Params )`

diff  --git a/mlir/include/mlir/IR/DialectImplementation.h b/mlir/include/mlir/IR/DialectImplementation.h
index 2652114b508e3..0b4f91cd750b8 100644
--- a/mlir/include/mlir/IR/DialectImplementation.h
+++ b/mlir/include/mlir/IR/DialectImplementation.h
@@ -70,15 +70,6 @@ class DialectAsmParser : public AsmParser {
 /// Provide a template class that can be specialized by users to dispatch to
 /// parsers. Auto-generated parsers generate calls to `FieldParser<T>::parse`,
 /// where `T` is the parameter storage type, to parse custom types.
-///
-/// A parser is key-value compositional only if it consumes exactly one value
-/// and leaves the comma separating the next key unconsumed. For example, an
-/// undelimited array parser for `values = 1, 2, next = 9` cannot distinguish
-/// its element commas from the comma before `next` and may try to parse `next`
-/// as another element. Marking it non-compositional lets a keyed property list
-/// use a self-delimiting attribute such as `array<i64: 1, 2>` instead.
-/// Specializations with this behavior, or that may succeed without consuming a
-/// token, should define `isKeyValueCompositional` as false.
 template <typename T, typename = T>
 struct FieldParser;
 
@@ -140,8 +131,6 @@ struct FieldParser<
     std::optional<AttributeT>,
     std::enable_if_t<std::is_base_of<Attribute, AttributeT>::value,
                      std::optional<AttributeT>>> {
-  static constexpr bool isKeyValueCompositional = false;
-
   static FailureOr<std::optional<AttributeT>> parse(AsmParser &parser) {
     if constexpr (HasStaticDialectName<AttributeT>::value) {
       parser.getContext()->getOrLoadDialect(AttributeT::dialectName);
@@ -162,8 +151,6 @@ template <typename IntT>
 struct FieldParser<
     std::optional<IntT>,
     std::enable_if_t<std::is_integral<IntT>::value, std::optional<IntT>>> {
-  static constexpr bool isKeyValueCompositional = false;
-
   static FailureOr<std::optional<IntT>> parse(AsmParser &parser) {
     IntT value;
     OptionalParseResult result = parser.parseOptionalInteger(value);
@@ -180,51 +167,14 @@ namespace detail {
 template <typename T>
 using has_push_back_t = decltype(std::declval<T>().push_back(
     std::declval<typename T::value_type &&>()));
-
-template <typename StorageType, typename = void>
-struct HasFieldParser : std::false_type {};
-
-template <typename StorageType>
-struct HasFieldParser<StorageType,
-                      std::void_t<decltype(sizeof(FieldParser<StorageType>)),
-                                  decltype(FieldParser<StorageType>::parse(
-                                      std::declval<OpAsmParser &>()))>>
-    : std::true_type {};
-
-template <typename ContainerT, typename = void>
-struct HasFieldParserContainer : std::false_type {};
-
-template <typename ContainerT>
-struct HasFieldParserContainer<ContainerT,
-                               std::void_t<has_push_back_t<ContainerT>>>
-    : HasFieldParser<typename ContainerT::value_type> {};
-
-template <typename Parser, typename = void>
-struct IsKeyValueCompositional : std::true_type {};
-
-template <typename Parser>
-struct IsKeyValueCompositional<
-    Parser, std::void_t<decltype(Parser::isKeyValueCompositional)>>
-    : std::bool_constant<Parser::isKeyValueCompositional> {};
-
-/// Whether the selected FieldParser consumes exactly one value in a keyed
-/// property list. Parser specializations may set isKeyValueCompositional to
-/// false if they can succeed without consuming a token or consume an
-/// undelimited comma-separated list.
-template <typename StorageType>
-struct HasKeyValueFieldParser
-    : std::conjunction<HasFieldParser<StorageType>,
-                       IsKeyValueCompositional<FieldParser<StorageType>>> {};
 } // namespace detail
 
 /// Parse any container that supports back insertion as a list.
 template <typename ContainerT>
-struct FieldParser<
-    ContainerT,
-    std::enable_if_t<detail::HasFieldParserContainer<ContainerT>::value,
-                     ContainerT>> {
-  static constexpr bool isKeyValueCompositional = false;
-
+struct FieldParser<ContainerT,
+                   std::enable_if_t<llvm::is_detected<detail::has_push_back_t,
+                                                      ContainerT>::value,
+                                    ContainerT>> {
   using ElementT = typename ContainerT::value_type;
   static FailureOr<ContainerT> parse(AsmParser &parser) {
     ContainerT elements;
@@ -252,28 +202,6 @@ struct FieldParser<AffineMap> {
   }
 };
 
-namespace detail {
-/// Parse a property with its FieldParser when one is available, otherwise
-/// fall back to the property's attribute conversion.
-template <typename StorageType, typename ConvertFromAttribute>
-ParseResult
-parsePropertyWithFallback(OpAsmParser &parser, StorageType &storage,
-                          ConvertFromAttribute convertFromAttribute) {
-  if constexpr (HasKeyValueFieldParser<StorageType>::value) {
-    auto value = FieldParser<StorageType>::parse(parser);
-    if (failed(value))
-      return failure();
-    storage = std::move(*value);
-    return success();
-  } else {
-    Attribute attr;
-    if (parser.parseAttribute(attr))
-      return failure();
-    return convertFromAttribute(storage, attr);
-  }
-}
-} // namespace detail
-
 } // namespace mlir
 
 #endif // MLIR_IR_DIALECTIMPLEMENTATION_H

diff  --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h
index 075d39194ed97..fe2fa0a0ccd23 100644
--- a/mlir/include/mlir/IR/OpDefinition.h
+++ b/mlir/include/mlir/IR/OpDefinition.h
@@ -1872,16 +1872,6 @@ class Op : public OpState, public Traits<ConcreteType>... {
   using detect_has_parse_properties =
       llvm::is_detected<has_parse_properties, T>;
 
-  /// Trait to check if T provides a generated parser for the key-value
-  /// spelling of `prop-dict`.
-  template <typename T, typename... Args>
-  using has_parse_properties_from_key_value_list =
-      decltype(T::parsePropertiesFromKeyValueList(
-          std::declval<OpAsmParser &>(), std::declval<OperationState &>()));
-  template <typename T>
-  using detect_has_parse_properties_from_key_value_list =
-      llvm::is_detected<has_parse_properties_from_key_value_list, T>;
-
   /// Trait to check if T provides a 'ConcreteEntity' type alias.
   template <typename T>
   using has_concrete_entity_t = typename T::ConcreteEntity;
@@ -2049,11 +2039,10 @@ class Op : public OpState, public Traits<ConcreteType>... {
         p, ConcreteType::getPropertiesAsAttr(ctx, properties), elidedProps);
   }
 
-  /// Parses 'prop-dict' for the operation. Generated parsers accept a keyed
-  /// list whose values use their custom assembly parsers, as well as the
-  /// legacy generic '<{ ... }>' dictionary syntax. The resulting properties
-  /// are stored within the property structure of 'result', accessible via
-  /// 'getOrAddProperties'.
+  /// Parses 'prop-dict' for the operation. Unless overridden, the method will
+  /// parse the properties using the generic property dictionary using the
+  /// '<{ ... }>' syntax. The resulting properties are stored within the
+  /// property structure of 'result', accessible via 'getOrAddProperties'.
   template <typename T = ConcreteType>
   static ParseResult parseProperties(OpAsmParser &parser,
                                      OperationState &result) {
@@ -2062,9 +2051,6 @@ class Op : public OpState, public Traits<ConcreteType>... {
           parser, result.getOrAddProperties<InferredProperties<T>>());
     }
 
-    if constexpr (detect_has_parse_properties_from_key_value_list<T>::value)
-      return T::parsePropertiesFromKeyValueList(parser, result);
-
     Attribute propertyDictionary;
     if (genericParseProperties(parser, propertyDictionary))
       return failure();

diff  --git a/mlir/include/mlir/TableGen/Property.h b/mlir/include/mlir/TableGen/Property.h
index 5877b54147f99..81e6d85720829 100644
--- a/mlir/include/mlir/TableGen/Property.h
+++ b/mlir/include/mlir/TableGen/Property.h
@@ -94,10 +94,6 @@ class Property : public PropConstraint {
   // Returns the method call which parses this property from textual MLIR.
   StringRef getParserCall() const { return parserCall; }
 
-  // Returns true if this property uses the parser inherited from the base
-  // Property class.
-  bool usesDefaultParser() const;
-
   // Returns true if this property has defined an optional parser.
   bool hasOptionalParser() const { return !optionalParserCall.empty(); }
 

diff  --git a/mlir/lib/TableGen/Property.cpp b/mlir/lib/TableGen/Property.cpp
index 88a64891b8b86..b003d74c7bdee 100644
--- a/mlir/lib/TableGen/Property.cpp
+++ b/mlir/lib/TableGen/Property.cpp
@@ -104,21 +104,6 @@ Pred Property::getPredicate() const {
   return Pred(maybePred->getValue());
 }
 
-bool Property::usesDefaultParser() const {
-  const Record *propertyClass = def->getRecords().getClass("Property");
-  if (const auto *baseInit =
-          llvm::dyn_cast<DefInit>(def->getValueInit("baseProperty"))) {
-    Property baseProperty(baseInit);
-    if (getParserCall() == baseProperty.getParserCall())
-      return baseProperty.usesDefaultParser();
-  }
-  // RecordVal retains the source location of the initializer that supplied a
-  // field. An inherited parser therefore points at Property::parser, while an
-  // explicit `let parser` points at the override without inspecting its text.
-  return def->getValue("parser")->getLoc().getPointer() ==
-         propertyClass->getValue("parser")->getLoc().getPointer();
-}
-
 Property Property::getBaseProperty() const {
   if (const auto *defInit =
           llvm::dyn_cast<llvm::DefInit>(def->getValueInit("baseProperty"))) {

diff  --git a/mlir/test/IR/properties-invalid.mlir b/mlir/test/IR/properties-invalid.mlir
deleted file mode 100644
index a6adf7ed98f8a..0000000000000
--- a/mlir/test/IR/properties-invalid.mlir
+++ /dev/null
@@ -1,79 +0,0 @@
-// RUN: mlir-opt %s -split-input-file -verify-diagnostics
-
-// expected-error @below {{properties dictionary is missing required property: prop}}
-test.with_custom_prop_dict <attr = 1>
-
-// -----
-
-// expected-error @below {{properties dictionary is missing required attribute: attr}}
-test.with_custom_prop_dict <prop = 2>
-
-// -----
-
-// expected-error @below {{duplicate or unknown property in properties dictionary: prop}}
-test.with_custom_prop_dict <attr = 1, prop = 2, prop = 3>
-
-// -----
-
-// expected-error @below {{duplicate or unknown property in properties dictionary: unknown}}
-test.with_custom_prop_dict <attr = 1, prop = 2, unknown = 3>
-
-// -----
-
-// A required property dictionary cannot be omitted entirely.
-// expected-error @below {{properties dictionary is missing required property: prop}}
-test.with_custom_prop_dict
-
-// -----
-
-// expected-error @below {{expected integer value}}
-test.with_custom_prop_dict <attr = 1, prop = bad>
-
-// -----
-
-// expected-error @below {{invalid value for property prop}}
-test.with_wrapped_properties <prop = 1 : i64>
-
-// -----
-
-// A required keyed value may not succeed without consuming a token.
-// expected-error @below {{expected attribute value}}
-test.with_key_value_parser_boundaries <values = array<i64: 1>, maybe = >
-
-// -----
-
-%c0 = arith.constant 0 : i64
-// A segment-size property inferred later in the parser must not be accepted
-// and then silently overwritten.
-// expected-error @below {{unknown property in properties dictionary: operandSegmentSizes}}
-test.variadic_segment_prop %c0 : %c0 : i64 : i64 <operandSegmentSizes = [1, 1]> end
-
-// -----
-
-%c0 = arith.constant 0 : i64
-// expected-error @below {{unknown property in properties dictionary: resultSegmentSizes}}
-test.variadic_segment_prop %c0 : %c0 : i64 : i64 <resultSegmentSizes = [1, 1]> end
-
-// -----
-
-%c0 = arith.constant 0 : i64
-// expected-error @below {{properties dictionary is missing required property: operandSegmentSizes}}
-test.variadic_segment_prop_bulk_type(%c0, %c0, %c0) : (i64, i64, i64) -> (i64, i64, i64) <resultSegmentSizes = [2, 1]>
-
-// -----
-
-%c0 = arith.constant 0 : i64
-// expected-error @below {{properties dictionary is missing required property: resultSegmentSizes}}
-test.variadic_segment_prop_bulk_type(%c0, %c0, %c0) : (i64, i64, i64) -> (i64, i64, i64) <operandSegmentSizes = [2, 1]>
-
-// -----
-
-%c0 = arith.constant 0 : i64
-// expected-error @below {{expected 2 entries for operandSegmentSizes}}
-test.variadic_segment_prop_bulk_type(%c0, %c0, %c0) : (i64, i64, i64) -> (i64, i64, i64) <operandSegmentSizes = [3], resultSegmentSizes = [2, 1]>
-
-// -----
-
-%c0 = arith.constant 0 : i64
-// expected-error @below {{expected 2 entries for resultSegmentSizes}}
-test.variadic_segment_prop_bulk_type(%c0, %c0, %c0) : (i64, i64, i64) -> (i64, i64, i64) <operandSegmentSizes = [2, 1], resultSegmentSizes = [3]>

diff  --git a/mlir/test/IR/properties.mlir b/mlir/test/IR/properties.mlir
index 64548e41dc111..4d83038f31cdd 100644
--- a/mlir/test/IR/properties.mlir
+++ b/mlir/test/IR/properties.mlir
@@ -23,85 +23,6 @@ test.with_wrapped_properties <{prop = "content for properties"}>
 // GENERIC: "test.empty_properties"()
 test.empty_properties
 
-// An explicitly empty key-value list is also accepted.
-// CHECK: test.empty_properties
-// GENERIC: "test.empty_properties"()
-test.empty_properties <>
-
-// The key-value spelling uses the custom parsers for both attributes and
-// properties. Until the custom printer is enabled, it round-trips to the
-// generic DictionaryAttr spelling.
-// CHECK: test.with_custom_prop_dict <{attr = 1 : i32, prop = 2 : i64}>
-// GENERIC: "test.with_custom_prop_dict"()
-// GENERIC-SAME: <{attr = 1 : i32, defaulted = 42 : i64, prop = 2 : i64, unit = false}>
-test.with_custom_prop_dict <attr = 1, prop = 2>
-
-// The generic DictionaryAttr spelling remains accepted for compatibility.
-// CHECK: test.with_custom_prop_dict <{attr = 3 : i32, prop = 4 : i64}>
-// GENERIC: "test.with_custom_prop_dict"()
-// GENERIC-SAME: <{attr = 3 : i32, defaulted = 42 : i64, prop = 4 : i64, unit = false}>
-test.with_custom_prop_dict <{attr = 3 : i32, prop = 4 : i64}>
-
-// Entries are order-independent, and optional/default-valued entries use
-// their custom parsers when present.
-// CHECK: test.with_custom_prop_dict <{attr = 5 : i32, defaulted = 43 : i64, optional = "set", prop = 6 : i64}>
-// GENERIC: "test.with_custom_prop_dict"()
-// GENERIC-SAME: <{attr = 5 : i32, defaulted = 43 : i64, optional = "set", prop = 6 : i64, unit = false}>
-test.with_custom_prop_dict <optional = "set", defaulted = 43, prop = 6, attr = 5>
-
-// A field name that is also the start of an attribute must not be consumed by
-// the legacy DictionaryAttr compatibility probe.
-// CHECK: test.with_custom_prop_dict <{attr = 7 : i32, prop = 8 : i64, unit}>
-// GENERIC: "test.with_custom_prop_dict"()
-// GENERIC-SAME: <{attr = 7 : i32, defaulted = 42 : i64, prop = 8 : i64, unit}>
-test.with_custom_prop_dict <unit = unit, attr = 7, prop = 8>
-
-// Properties bound elsewhere in the assembly format are excluded from the
-// key-value list.
-// CHECK: test.with_properties_and_attr 7 <{rhs = 8 : i64}>
-// GENERIC: "test.with_properties_and_attr"()
-// GENERIC-SAME: <{lhs = 7 : i32, rhs = 8 : i64}>
-test.with_properties_and_attr 7 <rhs = 8>
-
-// A property without a usable custom parser falls back to its attribute
-// conversion for this compatibility spelling.
-// CHECK: test.with_wrapped_properties <{prop = "custom spelling"}>
-// GENERIC: "test.with_wrapped_properties"()
-// GENERIC-SAME: <{prop = "custom spelling"}>
-test.with_wrapped_properties <prop = "custom spelling">
-
-// Forwarding property wrappers preserve whether their base uses the default
-// FieldParser, so a wrapped custom storage type still uses attribute fallback.
-// CHECK: test.with_default_wrapped_properties
-// GENERIC: "test.with_default_wrapped_properties"()
-// GENERIC-SAME: <{prop = "wrapped default spelling"}>
-test.with_default_wrapped_properties <prop = "wrapped default spelling">
-
-// A container FieldParser is unavailable when its element parser is
-// unavailable, so the complete property also falls back to conversion.
-// CHECK: test.with_wrapped_array_properties
-// GENERIC: "test.with_wrapped_array_properties"()
-// GENERIC-SAME: <{prop = ["first", "second"]}>
-test.with_wrapped_array_properties <prop = ["first", "second"]>
-
-// Default optional and container FieldParsers do not delimit exactly one
-// property value, so they use attribute conversion in a key-value list. The
-// following scalar key also checks that the container does not consume the
-// outer comma.
-// CHECK: test.with_key_value_parser_boundaries
-// CHECK-SAME: <{maybe = [], maybeEnum = [], next = 9 : i64, specializedMaybe = [7 : i16], specializedValues = array<i32: 3, 4>, values = array<i64: 1, 2>}>
-// GENERIC: "test.with_key_value_parser_boundaries"()
-// GENERIC-SAME: <{maybe = [], maybeEnum = [], next = 9 : i64, specializedMaybe = [7 : i16], specializedValues = array<i32: 3, 4>, values = array<i64: 1, 2>}>
-test.with_key_value_parser_boundaries <specializedValues = [3, 4], specializedMaybe = some<7>, values = array<i64: 1, 2>, maybe = [], maybeEnum = [], next = 9>
-
-// A comma-separated bit-enum FieldParser is not compositional with the outer
-// list, so prop-dict uses its attribute conversion before parsing another key.
-// CHECK: test.op_with_bit_enum_prop_dict
-// CHECK-SAME: <{flags = 3 : i32, next = 9 : i64}>
-// GENERIC: "test.op_with_bit_enum_prop_dict"()
-// GENERIC-SAME: <{flags = 3 : i32, next = 9 : i64}>
-test.op_with_bit_enum_prop_dict <flags = 3 : i32, next = 9>
-
 // CHECK: test.using_property_in_custom
 // CHECK-SAME: [1, 4, 20]{{$}}
 // GENERIC: "test.using_property_in_custom"()
@@ -134,7 +55,7 @@ test.variadic_segment_prop %ci64, %ci64 : %ci64 : i64, i64 : i64 end
 // key 'operandSegmentSizes' in dictionary attribute".
 // CHECK: test.variadic_segment_prop_bulk_type(%[[CI64]], %[[CI64]], %[[CI64]]) : (i64, i64, i64) -> (i64, i64, i64) <{operandSegmentSizes = array<i32: 2, 1>, resultSegmentSizes = array<i32: 2, 1>}>
 // GENERIC: "test.variadic_segment_prop_bulk_type"(%[[CI64]], %[[CI64]], %[[CI64]]) <{operandSegmentSizes = array<i32: 2, 1>, resultSegmentSizes = array<i32: 2, 1>}> : (i64, i64, i64) -> (i64, i64, i64)
-test.variadic_segment_prop_bulk_type(%ci64, %ci64, %ci64) : (i64, i64, i64) -> (i64, i64, i64) <operandSegmentSizes = [2, 1], resultSegmentSizes = [2, 1]>
+test.variadic_segment_prop_bulk_type(%ci64, %ci64, %ci64) : (i64, i64, i64) -> (i64, i64, i64) <{operandSegmentSizes = array<i32: 2, 1>, resultSegmentSizes = array<i32: 2, 1>}>
 
 // CHECK:   test.with_default_valued_properties na{{$}}
 // GENERIC: "test.with_default_valued_properties"()
@@ -200,20 +121,6 @@ test.op_with_property_predicates <{
   non_empty_constrained = [1],
   unconstrained = 0 : i64}>
 
-// Keyed parsing composes optional and aggregate property parsers with a
-// following outer dictionary entry.
-// CHECK: test.op_with_property_predicates
-// CHECK-SAME: array = [3, 4]
-// CHECK-SAME: optional = [2]
-test.op_with_property_predicates <
-  scalar = 1,
-  optional = 2,
-  more_constrained = 1,
-  array = [3, 4],
-  non_empty_unconstrained = [1],
-  non_empty_constrained = [1],
-  unconstrained = 0>
-
 // Tests that DefaultValuedProp is printed when value 
diff ers from default.
 // CHECK: test.op_with_property_predicates
 // CHECK-SAME: defaulted = 3

diff  --git a/mlir/test/lib/Dialect/Test/TestOps.h b/mlir/test/lib/Dialect/Test/TestOps.h
index 6320d39138f5f..b4cc2cd6cf569 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.h
+++ b/mlir/test/lib/Dialect/Test/TestOps.h
@@ -43,40 +43,6 @@
 #include "mlir/Interfaces/ViewLikeInterface.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
-#include <optional>
-
-namespace mlir {
-// Self-delimiting full specializations remain usable in a keyed prop-dict even
-// when their storage type is optional or container-like.
-template <>
-struct FieldParser<llvm::SmallVector<int32_t>> {
-  static FailureOr<llvm::SmallVector<int32_t>> parse(AsmParser &parser) {
-    llvm::SmallVector<int32_t> values;
-    if (parser.parseCommaSeparatedList(AsmParser::Delimiter::Square, [&]() {
-          int32_t value;
-          if (parser.parseInteger(value))
-            return failure();
-          values.push_back(value);
-          return success();
-        }))
-      return failure();
-    return values;
-  }
-};
-
-template <>
-struct FieldParser<std::optional<int16_t>> {
-  static FailureOr<std::optional<int16_t>> parse(AsmParser &parser) {
-    if (succeeded(parser.parseOptionalKeyword("none")))
-      return std::optional<int16_t>{};
-    int16_t value;
-    if (parser.parseKeyword("some") || parser.parseLess() ||
-        parser.parseInteger(value) || parser.parseGreater())
-      return failure();
-    return std::optional<int16_t>{value};
-  }
-};
-} // namespace mlir
 
 namespace test {
 class TestDialect;

diff  --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 0bd7fe401c3c9..3cb7f6ce2a054 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -534,12 +534,6 @@ def OpWithTestBitEnum : TEST_Op<"op_with_bit_enum_prop"> {
   let assemblyFormat = "$value1 ($value2^)? attr-dict `:` `(``)`";
 }
 
-def OpWithTestBitEnumPropDict
-    : TEST_Op<"op_with_bit_enum_prop_dict"> {
-  let arguments = (ins TestBitEnumProp:$flags, I64Prop:$next);
-  let assemblyFormat = "prop-dict attr-dict";
-}
-
 def TestBitEnumPropNamed : NamedEnumProp<TestBitEnum, "bit_enum"> {
   let defaultValue = TestBitEnum.cppType # "::Read";
 }
@@ -3633,18 +3627,6 @@ def TestOpWithPropertiesAndAttr
   let arguments = (ins I32Attr:$lhs, IntProp<"int64_t">:$rhs);
 }
 
-def TestOpWithCustomPropDict : TEST_Op<"with_custom_prop_dict"> {
-  let assemblyFormat = "prop-dict attr-dict";
-
-  let arguments = (ins
-    I32Attr:$attr,
-    I64Prop:$prop,
-    DefaultValuedProp<I64Prop, "42">:$defaulted,
-    OptionalAttr<StrAttr>:$optional,
-    UnitProp:$unit
-  );
-}
-
 def TestOpWithPropertiesAndInferredType
   : TEST_Op<"with_properties_and_inferred_type", [
     DeclareOpInterfaceMethods<InferTypeOpInterface>
@@ -3660,9 +3642,6 @@ def MyStructProperty : Property<"MyPropStruct"> {
   let convertToAttribute = "return $_storage.asAttribute($_ctxt);";
   let convertFromAttribute = "return MyPropStruct::setFromAttr($_storage, $_attr, $_diag);";
   let hashProperty = "$_storage.hash();";
-  // An optional parser does not imply that the default required FieldParser is
-  // available. `prop-dict` must still use attribute conversion as its fallback.
-  let optionalParser = "return std::nullopt;";
 }
 
 def TestOpWithWrappedProperties : TEST_Op<"with_wrapped_properties"> {
@@ -3672,249 +3651,6 @@ def TestOpWithWrappedProperties : TEST_Op<"with_wrapped_properties"> {
   );
 }
 
-def TestOpWithDefaultWrappedProperties
-    : TEST_Op<"with_default_wrapped_properties"> {
-  let assemblyFormat = "prop-dict attr-dict";
-  let arguments = (ins
-    DefaultValuedProp<MyStructProperty, "MyPropStruct{}">:$prop
-  );
-}
-
-def MyStructArrayProperty
-    : Property<"::llvm::SmallVector<MyPropStruct>"> {
-  let hashProperty =
-      "::llvm::hash_combine_range($_storage.begin(), $_storage.end())";
-  let readFromMlirBytecode = [{
-    uint64_t size;
-    if (::mlir::failed($_reader.readVarInt(size)))
-      return ::mlir::failure();
-    $_storage.clear();
-    while (size--) {
-      MyPropStruct value;
-      if (::mlir::failed(readFromMlirBytecode($_reader, value)))
-        return ::mlir::failure();
-      $_storage.push_back(std::move(value));
-    }
-  }];
-  let writeToMlirBytecode = [{
-    $_writer.writeVarInt($_storage.size());
-    for (MyPropStruct &value : $_storage)
-      writeToMlirBytecode($_writer, value);
-  }];
-  let convertToAttribute = [{
-    ::llvm::SmallVector<::mlir::Attribute> attrs;
-    for (const MyPropStruct &value : $_storage)
-      attrs.push_back(value.asAttribute($_ctxt));
-    return ::mlir::ArrayAttr::get($_ctxt, attrs);
-  }];
-  let convertFromAttribute = [{
-    auto array = ::llvm::dyn_cast<::mlir::ArrayAttr>($_attr);
-    if (!array)
-      return ::mlir::failure();
-    $_storage.clear();
-    for (::mlir::Attribute attr : array) {
-      MyPropStruct value;
-      if (::mlir::failed(MyPropStruct::setFromAttr(value, attr, $_diag)))
-        return ::mlir::failure();
-      $_storage.push_back(std::move(value));
-    }
-    return ::mlir::success();
-  }];
-}
-
-def TestOpWithWrappedArrayProperties
-    : TEST_Op<"with_wrapped_array_properties"> {
-  let assemblyFormat = "prop-dict attr-dict";
-  let arguments = (ins MyStructArrayProperty:$prop);
-}
-
-// The default FieldParser specializations for optional integers and generic
-// containers do not consume exactly one value in an outer comma-separated
-// list. The generated prop-dict parser must use attribute conversion for
-// these storage types instead.
-def KeyValueListProperty : Property<"::llvm::SmallVector<int64_t>"> {
-  let convertToAttribute =
-      "return ::mlir::DenseI64ArrayAttr::get($_ctxt, $_storage);";
-  let convertFromAttribute = [{
-    auto array = ::llvm::dyn_cast<::mlir::DenseI64ArrayAttr>($_attr);
-    if (!array)
-      return $_diag() << "expected a dense i64 array";
-    auto values = array.asArrayRef();
-    $_storage.assign(values.begin(), values.end());
-    return ::mlir::success();
-  }];
-  let hashProperty =
-      "::llvm::hash_combine_range($_storage.begin(), $_storage.end())";
-  let readFromMlirBytecode = readMlirBytecodeUsingConvertFromAttribute;
-  let writeToMlirBytecode = writeMlirBytecodeWithConvertToAttribute;
-}
-
-def KeyValueOptionalProperty : Property<"std::optional<int64_t>"> {
-  let convertToAttribute = [{
-    if (!$_storage)
-      return ::mlir::ArrayAttr::get($_ctxt, {});
-    auto value = ::mlir::IntegerAttr::get(
-        ::mlir::IntegerType::get($_ctxt, 64), *$_storage);
-    return ::mlir::ArrayAttr::get($_ctxt, {value});
-  }];
-  let convertFromAttribute = [{
-    auto array = ::llvm::dyn_cast<::mlir::ArrayAttr>($_attr);
-    if (!array || array.size() > 1)
-      return $_diag() << "expected a zero- or one-element array";
-    if (array.empty()) {
-      $_storage = std::nullopt;
-      return ::mlir::success();
-    }
-    auto value = ::llvm::dyn_cast<::mlir::IntegerAttr>(array[0]);
-    if (!value)
-      return $_diag() << "expected an integer element";
-    $_storage = value.getInt();
-    return ::mlir::success();
-  }];
-  let hashProperty = "::llvm::hash_value($_storage.value_or(0))";
-  let readFromMlirBytecode = [{
-    bool isPresent;
-    if (::mlir::failed($_reader.readBool(isPresent)))
-      return ::mlir::failure();
-    if (!isPresent) {
-      $_storage = std::nullopt;
-      return ::mlir::success();
-    }
-    int64_t value;
-    if (::mlir::failed($_reader.readSignedVarInt(value)))
-      return ::mlir::failure();
-    $_storage = value;
-  }];
-  let writeToMlirBytecode = [{
-    $_writer.writeOwnedBool($_storage.has_value());
-    if ($_storage)
-      $_writer.writeSignedVarInt(*$_storage);
-  }];
-}
-
-def KeyValueOptionalEnumProperty
-    : Property<"std::optional<test::TestEnum>"> {
-  let convertToAttribute = [{
-    if (!$_storage)
-      return ::mlir::ArrayAttr::get($_ctxt, {});
-    auto value = ::mlir::IntegerAttr::get(
-        ::mlir::IntegerType::get($_ctxt, 32),
-        static_cast<uint32_t>(*$_storage));
-    return ::mlir::ArrayAttr::get($_ctxt, {value});
-  }];
-  let convertFromAttribute = [{
-    auto array = ::llvm::dyn_cast<::mlir::ArrayAttr>($_attr);
-    if (!array || array.size() > 1)
-      return $_diag() << "expected a zero- or one-element array";
-    if (array.empty()) {
-      $_storage = std::nullopt;
-      return ::mlir::success();
-    }
-    auto value = ::llvm::dyn_cast<::mlir::IntegerAttr>(array[0]);
-    if (!value)
-      return $_diag() << "expected an integer element";
-    $_storage = static_cast<test::TestEnum>(value.getInt());
-    return ::mlir::success();
-  }];
-  let hashProperty = [{
-    ::llvm::hash_value(static_cast<uint32_t>(
-        $_storage.value_or(test::TestEnum::First)))
-  }];
-  let readFromMlirBytecode = [{
-    bool isPresent;
-    if (::mlir::failed($_reader.readBool(isPresent)))
-      return ::mlir::failure();
-    if (!isPresent) {
-      $_storage = std::nullopt;
-      return ::mlir::success();
-    }
-    uint64_t value;
-    if (::mlir::failed($_reader.readVarInt(value)))
-      return ::mlir::failure();
-    $_storage = static_cast<test::TestEnum>(value);
-  }];
-  let writeToMlirBytecode = [{
-    $_writer.writeOwnedBool($_storage.has_value());
-    if ($_storage)
-      $_writer.writeVarInt(static_cast<uint64_t>(*$_storage));
-  }];
-}
-
-def KeyValueSpecializedListProperty
-    : Property<"::llvm::SmallVector<int32_t>"> {
-  let convertToAttribute =
-      "return ::mlir::DenseI32ArrayAttr::get($_ctxt, $_storage);";
-  let convertFromAttribute = [{
-    auto array = ::llvm::dyn_cast<::mlir::DenseI32ArrayAttr>($_attr);
-    if (!array)
-      return $_diag() << "expected a dense i32 array";
-    auto values = array.asArrayRef();
-    $_storage.assign(values.begin(), values.end());
-    return ::mlir::success();
-  }];
-  let hashProperty =
-      "::llvm::hash_combine_range($_storage.begin(), $_storage.end())";
-  let readFromMlirBytecode = readMlirBytecodeUsingConvertFromAttribute;
-  let writeToMlirBytecode = writeMlirBytecodeWithConvertToAttribute;
-}
-
-def KeyValueSpecializedOptionalProperty
-    : Property<"std::optional<int16_t>"> {
-  let convertToAttribute = [{
-    if (!$_storage)
-      return ::mlir::ArrayAttr::get($_ctxt, {});
-    auto value = ::mlir::IntegerAttr::get(
-        ::mlir::IntegerType::get($_ctxt, 16), *$_storage);
-    return ::mlir::ArrayAttr::get($_ctxt, {value});
-  }];
-  let convertFromAttribute = [{
-    auto array = ::llvm::dyn_cast<::mlir::ArrayAttr>($_attr);
-    if (!array || array.size() > 1)
-      return $_diag() << "expected a zero- or one-element array";
-    if (array.empty()) {
-      $_storage = std::nullopt;
-      return ::mlir::success();
-    }
-    auto value = ::llvm::dyn_cast<::mlir::IntegerAttr>(array[0]);
-    if (!value)
-      return $_diag() << "expected an integer element";
-    $_storage = static_cast<int16_t>(value.getInt());
-    return ::mlir::success();
-  }];
-  let hashProperty = "::llvm::hash_value($_storage.value_or(0))";
-  let readFromMlirBytecode = [{
-    bool isPresent;
-    if (::mlir::failed($_reader.readBool(isPresent)))
-      return ::mlir::failure();
-    if (!isPresent) {
-      $_storage = std::nullopt;
-      return ::mlir::success();
-    }
-    int64_t value;
-    if (::mlir::failed($_reader.readSignedVarInt(value)))
-      return ::mlir::failure();
-    $_storage = static_cast<int16_t>(value);
-  }];
-  let writeToMlirBytecode = [{
-    $_writer.writeOwnedBool($_storage.has_value());
-    if ($_storage)
-      $_writer.writeSignedVarInt(*$_storage);
-  }];
-}
-
-def TestOpWithKeyValueParserBoundaries
-    : TEST_Op<"with_key_value_parser_boundaries"> {
-  let assemblyFormat = "prop-dict attr-dict";
-  let arguments = (ins
-    KeyValueListProperty:$values,
-    KeyValueOptionalProperty:$maybe,
-    KeyValueOptionalEnumProperty:$maybeEnum,
-    KeyValueSpecializedListProperty:$specializedValues,
-    KeyValueSpecializedOptionalProperty:$specializedMaybe,
-    I64Prop:$next
-  );
-}
-
 // Same as above, but without a custom `hashProperty` field, checking
 // that ADL is correctly working.
 def MyStructProperty2 : Property<"MyPropStruct"> {

diff  --git a/mlir/test/mlir-tblgen/enums-gen.td b/mlir/test/mlir-tblgen/enums-gen.td
index e64e50b2382cb..cf66ad46ad24b 100644
--- a/mlir/test/mlir-tblgen/enums-gen.td
+++ b/mlir/test/mlir-tblgen/enums-gen.td
@@ -45,9 +45,6 @@ def MyBitEnum: I32BitEnumAttr<"MyBitEnum", "An example bit enum",
 // DECL:     return parser.emitError(loc, "expected one of [none, tagged, Bit1, Bit2, Bit3, BitGroup] for An example bit enum, got: ") << enumKeyword;
 // DECL:   }
 
-// DECL: struct FieldParser<std::optional<::MyBitEnum>, std::optional<::MyBitEnum>> {
-// DECL:   static constexpr bool isKeyValueCompositional = false;
-
 // DECL: inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::MyBitEnum value) {
 // DECL:   auto valueStr = stringifyEnum(value);
 // DECL:   switch (value) {
@@ -61,11 +58,6 @@ def MyBitEnum: I32BitEnumAttr<"MyBitEnum", "An example bit enum",
 // DECL:     return p << '"' << valueStr << '"';
 // DECL:   return p << valueStr;
 
-// DECL: struct FieldParser<::MyCommaSeparatedBitEnum, ::MyCommaSeparatedBitEnum> {
-// DECL:   static constexpr bool isKeyValueCompositional = false;
-// DECL: struct FieldParser<std::optional<::MyCommaSeparatedBitEnum>, std::optional<::MyCommaSeparatedBitEnum>> {
-// DECL:   static constexpr bool isKeyValueCompositional = false;
-
 // DECL: enum class MyI8Enum : uint8_t {
 // DECL:   a = 254,
 // DECL:   b = 255,
@@ -137,7 +129,6 @@ def MyNonQuotedPrintBitEnum
     [None, Bit0, Bit1, Bit2, Bit3, BitGroup]>;
 
 // 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 = {};
@@ -158,12 +149,6 @@ def MyNonQuotedPrintBitEnum
 // DECL:     return flags;
 // DECL:   }
 
-def MyCommaSeparatedBitEnum
-  : I32BitEnum<"MyCommaSeparatedBitEnum", "Comma-separated bit enum",
-    [None, Bit0, Bit1]> {
-  let separator = ", ";
-}
-
 // DECL: inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::MyNonQuotedPrintBitEnum value) {
 // DECL:   auto valueStr = stringifyEnum(value);
 // DECL-NEXT:   return p << valueStr;

diff  --git a/mlir/tools/mlir-tblgen/EnumsGen.cpp b/mlir/tools/mlir-tblgen/EnumsGen.cpp
index 845f1ef46cf35..4b90082176dc0 100644
--- a/mlir/tools/mlir-tblgen/EnumsGen.cpp
+++ b/mlir/tools/mlir-tblgen/EnumsGen.cpp
@@ -129,8 +129,6 @@ struct FieldParser<{0}, {0}> {{
 ///    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) {{
     // Parse the keyword/string containing the enum.
@@ -159,8 +157,6 @@ inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, {0} value) {{
 
   template<>
   struct FieldParser<{0}, {0}> {{
-    static constexpr bool isKeyValueCompositional = {7};
-
     template <typename ParserT>
     static FailureOr<{0}> parse(ParserT &parser) {{
       {0} flags = {{};
@@ -189,8 +185,6 @@ inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, {0} value) {{
   ///    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 = {{};
@@ -239,7 +233,7 @@ inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, {0} value) {{
             .Default("error, enum separator must be '|' or ','");
     os << formatv(parsedAndPrinterStartUnquotedBitEnum, qualName, cppNamespace,
                   enumInfo.getSummary(), casesList, separator, parseSeparatorFn,
-                  casesInitList, separator.trim() == "," ? "false" : "true");
+                  casesInitList);
   } else {
     os << formatv(parsedAndPrinterStart, qualName, cppNamespace,
                   enumInfo.getSummary(), casesList, casesInitList);

diff  --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
index 5c97d2345051d..f4080948db10a 100644
--- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
@@ -1494,223 +1494,6 @@ return ::mlir::success();
 )decl";
 }
 
-/// Generate the parser for the key-value spelling of `prop-dict`. The generic
-/// DictionaryAttr spelling remains supported as a compatibility path.
-static void genKeyValuePropDictParser(OperationFormat &fmt, Operator &op,
-                                      OpClass &opClass) {
-  if (!fmt.hasPropDict || !fmt.useProperties)
-    return;
-
-  SmallVector<MethodParameter> paramList;
-  paramList.emplace_back("::mlir::OpAsmParser &", "parser");
-  paramList.emplace_back("::mlir::OperationState &", "result");
-
-  Method *method = opClass.addStaticMethod("::mlir::ParseResult",
-                                           "parsePropertiesFromKeyValueList",
-                                           std::move(paramList));
-  MethodBody &body = method->body().indent();
-
-  body << R"decl(
-auto &prop = result.getOrAddProperties<Properties>();
-(void)prop;
-)decl";
-
-  bool parseOperandSegmentSizes =
-      op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments") &&
-      fmt.allOperands;
-  bool parseResultSegmentSizes =
-      op.getTrait("::mlir::OpTrait::AttrSizedResultSegments") &&
-      fmt.allResultTypes;
-
-  if (parseOperandSegmentSizes)
-    body << "bool seen_operandSegmentSizes = false;\n";
-  if (parseResultSegmentSizes)
-    body << "bool seen_resultSegmentSizes = false;\n";
-
-  auto shouldParseProperty = [&](const NamedProperty &property) {
-    return !fmt.usedProperties.contains(&property) &&
-           !fmt.inferredAttributes.contains(property.name);
-  };
-  auto shouldParseAttribute = [&](const NamedAttribute &attribute) {
-    return !attribute.attr.isDerivedAttr() &&
-           !fmt.usedAttributes.contains(&attribute) &&
-           !fmt.inferredAttributes.contains(attribute.name);
-  };
-
-  for (const NamedProperty &property : op.getProperties())
-    if (shouldParseProperty(property))
-      body << "bool seen_" << property.name << " = false;\n";
-  for (const NamedAttribute &attribute : op.getAttributes())
-    if (shouldParseAttribute(attribute))
-      body << "bool seen_" << attribute.name << " = false;\n";
-
-  body << R"decl(
-if (succeeded(parser.parseOptionalLess())) {
-  ::llvm::SMLoc dictionaryLoc = parser.getCurrentLocation();
-  ::mlir::NamedAttrList propertyAttributes;
-  if (parser.parseOptionalAttrDict(propertyAttributes))
-    return ::mlir::failure();
-  if (dictionaryLoc != parser.getCurrentLocation()) {
-    if (parser.parseGreater())
-      return ::mlir::failure();
-    auto propertyDictionary =
-        ::mlir::DictionaryAttr::get(parser.getContext(), propertyAttributes);
-    return setPropertiesFromParsedAttr(prop, propertyDictionary, [&]() {
-      return parser.emitError(dictionaryLoc)
-             << "invalid properties " << propertyDictionary << ": ";
-    });
-  }
-
-  bool reachedEnd = succeeded(parser.parseOptionalGreater());
-  while (!reachedEnd) {
-    ::llvm::SMLoc keyLoc = parser.getCurrentLocation();
-    ::llvm::StringRef key;
-    if (parser.parseKeyword(&key) || parser.parseEqual())
-      return ::mlir::failure();
-)decl";
-
-  bool isFirst = true;
-  FmtContext attrTypeCtx;
-  attrTypeCtx.withBuilder("parser.getBuilder()");
-
-  auto genSegmentSizesParser = [&](StringRef name) {
-    body << (isFirst ? "    if" : "    else if") << " (!seen_" << name
-         << " && key == \"" << name << "\") {\n"
-         << "      seen_" << name << " = true;\n"
-         << R"decl(
-      ::llvm::SmallVector<int32_t> parsedSegmentSizes;
-      if (parser.parseCommaSeparatedList(
-              ::mlir::AsmParser::Delimiter::Square, [&]() {
-                int32_t size;
-                if (parser.parseInteger(size))
-                  return ::mlir::failure();
-                parsedSegmentSizes.push_back(size);
-                return ::mlir::success();
-              }))
-        return ::mlir::failure();
-)decl"
-         << "      if (parsedSegmentSizes.size() != prop." << name
-         << ".size())\n"
-         << "        return parser.emitError(keyLoc, \"expected "
-         << (name == "operandSegmentSizes" ? op.getNumOperands()
-                                           : op.getNumResults())
-         << " entries for " << name << "\");\n"
-         << "      ::llvm::copy(parsedSegmentSizes, prop." << name
-         << ".begin());\n"
-         << "    }\n";
-    isFirst = false;
-  };
-
-  if (parseOperandSegmentSizes)
-    genSegmentSizesParser("operandSegmentSizes");
-  if (parseResultSegmentSizes)
-    genSegmentSizesParser("resultSegmentSizes");
-
-  for (const NamedProperty &property : op.getProperties()) {
-    if (!shouldParseProperty(property))
-      continue;
-    body << (isFirst ? "    if" : "    else if") << " (!seen_" << property.name
-         << " && key == \"" << property.name << "\") {\n"
-         << "      seen_" << property.name << " = true;\n";
-    if (!property.prop.usesDefaultParser()) {
-      PropertyVariable propertyVariable(&property);
-      genPropertyParser(&propertyVariable, body.indent(), fmt.opCppClassName);
-    } else {
-      FmtContext fctx;
-      fctx.addSubst("_attr", "propertyAttr");
-      fctx.addSubst("_storage", "propStorage");
-      fctx.addSubst("_diag", "emitError");
-      body.indent() << R"decl(
-auto parseResult = ::mlir::detail::parsePropertyWithFallback(
-    parser, prop.)decl"
-                    << property.name << R"decl(,
-    [&](auto &propStorage,
-        ::mlir::Attribute propertyAttr) -> ::mlir::LogicalResult {
-  auto emitError = [&]() {
-    return parser.emitError(parser.getCurrentLocation())
-           << "invalid value for property " << key << ": ";
-  };
-)decl";
-      body << tgfmt(property.prop.getConvertFromAttributeCall(), &fctx)
-           << ";\n";
-      body << "});\n"
-           << "if (failed(parseResult))\n"
-           << "  return ::mlir::failure();\n";
-      body.unindent();
-    }
-    body.unindent() << "    }\n";
-    isFirst = false;
-  }
-  for (const NamedAttribute &attribute : op.getAttributes()) {
-    if (!shouldParseAttribute(attribute))
-      continue;
-    body << (isFirst ? "    if" : "    else if") << " (!seen_" << attribute.name
-         << " && key == \"" << attribute.name << "\") {\n"
-         << "      seen_" << attribute.name << " = true;\n"
-         << "      " << attribute.attr.getStorageType() << " " << attribute.name
-         << "Attr;\n";
-    AttributeVariable attributeVariable(&attribute);
-    genAttrParser(&attributeVariable, body.indent(), attrTypeCtx,
-                  /*parseAsOptional=*/false, /*useProperties=*/true,
-                  fmt.opCppClassName);
-    body.unindent() << "    }\n";
-    isFirst = false;
-  }
-
-  if (isFirst) {
-    body << R"decl(
-    return parser.emitError(keyLoc,
-                            "unknown property in properties dictionary: ")
-           << key;
-)decl";
-  } else {
-    body << R"decl(
-    else {
-      return parser.emitError(
-                 keyLoc,
-                 "duplicate or unknown property in properties dictionary: ")
-             << key;
-    }
-)decl";
-  }
-
-  body << R"decl(
-    reachedEnd = succeeded(parser.parseOptionalGreater());
-    if (!reachedEnd && parser.parseComma())
-      return ::mlir::failure();
-  }
-}
-)decl";
-
-  if (parseOperandSegmentSizes)
-    body << "if (!seen_operandSegmentSizes)\n"
-            "  return ::mlir::emitError(result.location, \"properties "
-            "dictionary is missing required property: "
-            "operandSegmentSizes\");\n";
-  if (parseResultSegmentSizes)
-    body << "if (!seen_resultSegmentSizes)\n"
-            "  return ::mlir::emitError(result.location, \"properties "
-            "dictionary is missing required property: "
-            "resultSegmentSizes\");\n";
-
-  for (const NamedProperty &property : op.getProperties()) {
-    if (shouldParseProperty(property) && !property.prop.hasDefaultValue())
-      body << "if (!seen_" << property.name
-           << ")\n  return ::mlir::emitError(result.location, "
-              "\"properties dictionary is missing required property: "
-           << property.name << "\");\n";
-  }
-  for (const NamedAttribute &attribute : op.getAttributes()) {
-    if (shouldParseAttribute(attribute) && !attribute.attr.isOptional() &&
-        !attribute.attr.hasDefaultValue())
-      body << "if (!seen_" << attribute.name
-           << ")\n  return ::mlir::emitError(result.location, "
-              "\"properties dictionary is missing required attribute: "
-           << attribute.name << "\");\n";
-  }
-  body << "return ::mlir::success();\n";
-}
-
 void OperationFormat::genParser(Operator &op, OpClass &opClass) {
   SmallVector<MethodParameter> paramList;
   paramList.emplace_back("::mlir::OpAsmParser &", "parser");
@@ -1744,7 +1527,6 @@ void OperationFormat::genParser(Operator &op, OpClass &opClass) {
   body << "  return ::mlir::success();\n";
 
   genParsedAttrPropertiesSetter(*this, op, opClass);
-  genKeyValuePropDictParser(*this, op, opClass);
 }
 
 void OperationFormat::genElementParser(FormatElement *element, MethodBody &body,


        


More information about the llvm-branch-commits mailing list