[mlir][NFC] Make Property a subclass of PropConstraint (#140848)
In preparation for allowing non-attribute properties in the declaritive rewrite pattern system, make `Property` a subclass of `PropConstraint` in tablegen and add a CK_Prop to the Constraint class for tablegen. Like `TypeConstraint` but unlike other constraints, a `PropConstraint` has an additional field - the C++ interface type of the property being constraint (if it's known).
This commit is contained in:
parent
07ce57ffcb
commit
a236dc63bf
@ -109,8 +109,8 @@ The source pattern is for matching a DAG of operations. Arguments in the `dag`
|
|||||||
object are intended to **capture** the op arguments. They can also be used to
|
object are intended to **capture** the op arguments. They can also be used to
|
||||||
**further limit** the match criteria. The capturing is done by specifying a
|
**further limit** the match criteria. The capturing is done by specifying a
|
||||||
symbol starting with the `$` sign, while further constraints are introduced by
|
symbol starting with the `$` sign, while further constraints are introduced by
|
||||||
specifying a `TypeConstraint` (for an operand) or a `AttrConstraint` (for an
|
specifying a `TypeConstraint` (for an operand), an `AttrConstraint` (for an
|
||||||
attribute).
|
attribute, or a `PropConstraint` for a property).
|
||||||
|
|
||||||
#### Binding op arguments and limiting the match
|
#### Binding op arguments and limiting the match
|
||||||
|
|
||||||
|
@ -104,7 +104,8 @@ their semantics via a special [TableGen backend][TableGenBackend]:
|
|||||||
* The `Property` class hierarchy: They are used to specify non-attribute-backed
|
* The `Property` class hierarchy: They are used to specify non-attribute-backed
|
||||||
properties that are inherent to operations. These properties can have
|
properties that are inherent to operations. These properties can have
|
||||||
constraints imposed on them using the `predicate` field or the
|
constraints imposed on them using the `predicate` field or the
|
||||||
`ConfinedProp` class.
|
`ConfinedProp` class. The `PropConstraint` superclass of `Property` is used
|
||||||
|
to describe constraints on properties in rewrite patterns.
|
||||||
|
|
||||||
An operation is defined by specializing the `Op` class with concrete contents
|
An operation is defined by specializing the `Op` class with concrete contents
|
||||||
for all the fields it requires. For example, `tf.AvgPool` is defined as
|
for all the fields it requires. For example, `tf.AvgPool` is defined as
|
||||||
@ -213,7 +214,7 @@ hierarchy. Similarly, `<attr-constraint>` is a TableGen `def` from the
|
|||||||
of `Property` (constraints can be imposed onto it using its `predicate` field
|
of `Property` (constraints can be imposed onto it using its `predicate` field
|
||||||
or the `ConfinedProp` subclass).
|
or the `ConfinedProp` subclass).
|
||||||
|
|
||||||
There is no requirements on the relative order of operands and attributes; they
|
There are no requirements on the relative order of operands and attributes; they
|
||||||
can mix freely. The relative order of operands themselves matters. From each
|
can mix freely. The relative order of operands themselves matters. From each
|
||||||
named argument a named getter will be generated that returns the argument with
|
named argument a named getter will be generated that returns the argument with
|
||||||
the return type (in the case of attributes the return type will be constructed
|
the return type (in the case of attributes the return type will be constructed
|
||||||
|
@ -169,6 +169,16 @@ class TypeConstraint<Pred predicate, string summary = "",
|
|||||||
class AttrConstraint<Pred predicate, string summary = ""> :
|
class AttrConstraint<Pred predicate, string summary = ""> :
|
||||||
Constraint<predicate, summary>;
|
Constraint<predicate, summary>;
|
||||||
|
|
||||||
|
// Subclass for constraints on a property.
|
||||||
|
class PropConstraint<Pred predicate, string summary = "", string interfaceTypeParam = ""> :
|
||||||
|
Constraint<predicate, summary> {
|
||||||
|
// The name of the C++ type of $_self, which will be the interface type of the
|
||||||
|
// property being constrained, or "" if it is to be inferred from context.
|
||||||
|
// Note, that leaving the interface type unspecified prevents the constraint from
|
||||||
|
// being uniqued.
|
||||||
|
code interfaceType = interfaceTypeParam;
|
||||||
|
}
|
||||||
|
|
||||||
// Subclass for constraints on a region.
|
// Subclass for constraints on a region.
|
||||||
class RegionConstraint<Pred predicate, string summary = ""> :
|
class RegionConstraint<Pred predicate, string summary = ""> :
|
||||||
Constraint<predicate, summary>;
|
Constraint<predicate, summary>;
|
||||||
@ -183,10 +193,15 @@ class SuccessorConstraint<Pred predicate, string summary = ""> :
|
|||||||
// * Constraints on an op's operand/result definition
|
// * Constraints on an op's operand/result definition
|
||||||
// * Further constraints to match an op's operand/result in source pattern
|
// * Further constraints to match an op's operand/result in source pattern
|
||||||
//
|
//
|
||||||
// * Use Attr (a subclass for AttrConstraint) for
|
// * Use Attr (a subclass of AttrConstraint) for
|
||||||
// * Constraints on an op's attribute definition
|
// * Constraints on an op's attribute definitions
|
||||||
// * Use AttrConstraint to specify
|
// * Use AttrConstraint to specify
|
||||||
// * Further constraints to match an op's attribute in source pattern
|
// * Further constraints to match an op's attribute in rewrite source patterns.
|
||||||
|
//
|
||||||
|
// * Use Prop (a subclass of PropConstraint) for
|
||||||
|
// * Defining an op's properties or constraining them
|
||||||
|
// * Use Prop constraint to specify
|
||||||
|
// * Further constraints to match an op's property in rewrite source patterns.
|
||||||
//
|
//
|
||||||
// * Use uncategorized constraint to specify
|
// * Use uncategorized constraint to specify
|
||||||
// * Multi-entity constraints in rewrite rules
|
// * Multi-entity constraints in rewrite rules
|
||||||
|
@ -17,14 +17,21 @@ include "mlir/IR/Constraints.td"
|
|||||||
include "mlir/IR/Utils.td"
|
include "mlir/IR/Utils.td"
|
||||||
|
|
||||||
// Base class for defining properties.
|
// Base class for defining properties.
|
||||||
class Property<string storageTypeParam = "", string desc = ""> {
|
// `desc` is the summary, a user-readable one-line description of the property
|
||||||
// User-readable one line summary used in error reporting messages. If empty,
|
// used in error messages. If empty, a generic message will be used.
|
||||||
// a generic message will be used.
|
// `storageTypeParam` is the type which will be used to store the property in
|
||||||
string summary = desc;
|
// a property struct, while `interfaceTypeParam` (which defaults to `storageTypeParam`)
|
||||||
|
// is the type returned from the getter of the property and used as an argument
|
||||||
|
// to the property's builder.
|
||||||
|
// Properties have a `predicate` field. It defaults to the true predicate since
|
||||||
|
// properties always hold their C++ type. Within these predicates, $_self is the
|
||||||
|
// **interface** type of the property.
|
||||||
|
class Property<string storageTypeParam = "", string desc = "", string interfaceTypeParam = storageTypeParam>
|
||||||
|
: PropConstraint<TruePred, desc, interfaceTypeParam> {
|
||||||
// The full description of this property.
|
// The full description of this property.
|
||||||
string description = "";
|
string description = "";
|
||||||
code storageType = storageTypeParam;
|
code storageType = storageTypeParam;
|
||||||
code interfaceType = storageTypeParam;
|
// Note: the interface type is a field on PropConstraint.
|
||||||
|
|
||||||
// The expression to convert from the storage type to the Interface
|
// The expression to convert from the storage type to the Interface
|
||||||
// type. For example, an enum can be stored as an int but returned as an
|
// type. For example, an enum can be stored as an int but returned as an
|
||||||
@ -66,13 +73,6 @@ class Property<string storageTypeParam = "", string desc = ""> {
|
|||||||
return convertFromAttribute($_storage, $_attr, $_diag);
|
return convertFromAttribute($_storage, $_attr, $_diag);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// The verification predicate for this property. Defaults to the true predicate,
|
|
||||||
// since properties are always their expected type.
|
|
||||||
// Within the predicate, `$_self` is an instance of the **interface**
|
|
||||||
// type of the property. Setting this field to ? will also result in a
|
|
||||||
// true predicate but is not recommended, as it breaks composability.
|
|
||||||
Pred predicate = TruePred;
|
|
||||||
|
|
||||||
// The call expression to hash the property.
|
// The call expression to hash the property.
|
||||||
//
|
//
|
||||||
// Format:
|
// Format:
|
||||||
@ -240,8 +240,7 @@ def I32Property : IntProp<"int32_t">, Deprecated<"moved to shorter name I32Prop"
|
|||||||
def I64Property : IntProp<"int64_t">, Deprecated<"moved to shorter name I64Prop">;
|
def I64Property : IntProp<"int64_t">, Deprecated<"moved to shorter name I64Prop">;
|
||||||
|
|
||||||
// Note: only a class so we can deprecate the old name
|
// Note: only a class so we can deprecate the old name
|
||||||
class _cls_StringProp : Property<"std::string", "string"> {
|
class _cls_StringProp : Property<"std::string", "string", "::llvm::StringRef"> {
|
||||||
let interfaceType = "::llvm::StringRef";
|
|
||||||
let convertFromStorage = "::llvm::StringRef{$_storage}";
|
let convertFromStorage = "::llvm::StringRef{$_storage}";
|
||||||
let assignToStorage = "$_storage = $_value.str()";
|
let assignToStorage = "$_storage = $_value.str()";
|
||||||
let optionalParser = [{
|
let optionalParser = [{
|
||||||
@ -347,7 +346,8 @@ def UnitProperty : _cls_UnitProp, Deprecated<"moved to shorter name UnitProp">;
|
|||||||
/// Class for giving a property a default value.
|
/// Class for giving a property a default value.
|
||||||
/// This doesn't change anything about the property other than giving it a default
|
/// This doesn't change anything about the property other than giving it a default
|
||||||
/// which can be used by ODS to elide printing.
|
/// which can be used by ODS to elide printing.
|
||||||
class DefaultValuedProp<Property p, string default = "", string storageDefault = ""> : Property<p.storageType, p.summary> {
|
class DefaultValuedProp<Property p, string default = "", string storageDefault = "">
|
||||||
|
: Property<p.storageType, p.summary, p.interfaceType> {
|
||||||
let defaultValue = default;
|
let defaultValue = default;
|
||||||
let storageTypeValueOverride = storageDefault;
|
let storageTypeValueOverride = storageDefault;
|
||||||
let baseProperty = p;
|
let baseProperty = p;
|
||||||
@ -375,7 +375,7 @@ class DefaultValuedProperty<Property p, string default = "", string storageDefau
|
|||||||
/// predicates it may already have. If `newSummary` is provided, replace the
|
/// predicates it may already have. If `newSummary` is provided, replace the
|
||||||
/// summary of `p` with `newSummary`.
|
/// summary of `p` with `newSummary`.
|
||||||
class ConfinedProp<Property p, Pred pred, string newSummary = "">
|
class ConfinedProp<Property p, Pred pred, string newSummary = "">
|
||||||
: Property<p.storageType, !if(!empty(newSummary), p.summary, newSummary)> {
|
: Property<p.storageType, !if(!empty(newSummary), p.summary, newSummary), p.interfaceType> {
|
||||||
let predicate = !if(!ne(p.predicate, TruePred), And<[p.predicate, pred]>, pred);
|
let predicate = !if(!ne(p.predicate, TruePred), And<[p.predicate, pred]>, pred);
|
||||||
let baseProperty = p;
|
let baseProperty = p;
|
||||||
// Keep up to date with `Property` above.
|
// Keep up to date with `Property` above.
|
||||||
@ -441,8 +441,8 @@ class _makeStorageWrapperPred<Property wrappedProp> {
|
|||||||
/// subclass `ArrayProp`.
|
/// subclass `ArrayProp`.
|
||||||
class ArrayProp<Property elem = Property<>, string newSummary = ""> :
|
class ArrayProp<Property elem = Property<>, string newSummary = ""> :
|
||||||
Property<"::llvm::SmallVector<" # elem.storageType # ">",
|
Property<"::llvm::SmallVector<" # elem.storageType # ">",
|
||||||
!if(!empty(newSummary), "array of " # elem.summary, newSummary)> {
|
!if(!empty(newSummary), "array of " # elem.summary, newSummary),
|
||||||
let interfaceType = "::llvm::ArrayRef<" # elem.storageType # ">";
|
"::llvm::ArrayRef<" # elem.storageType # ">"> {
|
||||||
let convertFromStorage = "::llvm::ArrayRef<" # elem.storageType # ">{$_storage}";
|
let convertFromStorage = "::llvm::ArrayRef<" # elem.storageType # ">{$_storage}";
|
||||||
let assignToStorage = "$_storage.assign($_value.begin(), $_value.end())";
|
let assignToStorage = "$_storage.assign($_value.begin(), $_value.end())";
|
||||||
|
|
||||||
@ -585,7 +585,8 @@ class IntArrayProperty<Property elem, string newSummary="">
|
|||||||
/// syntax of the underlying property, or the keyword `none` in the rare cases that
|
/// syntax of the underlying property, or the keyword `none` in the rare cases that
|
||||||
/// it is needed. This behavior can be disabled by setting `canDelegateParsing` to 0.
|
/// it is needed. This behavior can be disabled by setting `canDelegateParsing` to 0.
|
||||||
class OptionalProp<Property p, bit canDelegateParsing = 1>
|
class OptionalProp<Property p, bit canDelegateParsing = 1>
|
||||||
: Property<"std::optional<" # p.storageType # ">", "optional " # p.summary> {
|
: Property<"std::optional<" # p.storageType # ">",
|
||||||
|
"optional " # p.summary, "std::optional<" # p.interfaceType # ">"> {
|
||||||
|
|
||||||
// In the cases where the underlying attribute is plain old data that's passed by
|
// In the cases where the underlying attribute is plain old data that's passed by
|
||||||
// value, the conversion code is trivial.
|
// value, the conversion code is trivial.
|
||||||
@ -596,7 +597,6 @@ class OptionalProp<Property p, bit canDelegateParsing = 1>
|
|||||||
defvar delegatesParsing = !and(!empty(p.defaultValue),
|
defvar delegatesParsing = !and(!empty(p.defaultValue),
|
||||||
!not(!empty(p.optionalParser)), canDelegateParsing);
|
!not(!empty(p.optionalParser)), canDelegateParsing);
|
||||||
|
|
||||||
let interfaceType = "std::optional<" # p.interfaceType # ">";
|
|
||||||
let defaultValue = "std::nullopt";
|
let defaultValue = "std::nullopt";
|
||||||
|
|
||||||
let convertFromStorage = !if(hasTrivialStorage,
|
let convertFromStorage = !if(hasTrivialStorage,
|
||||||
|
@ -30,7 +30,14 @@ namespace tblgen {
|
|||||||
class Constraint {
|
class Constraint {
|
||||||
public:
|
public:
|
||||||
// Constraint kind
|
// Constraint kind
|
||||||
enum Kind { CK_Attr, CK_Region, CK_Successor, CK_Type, CK_Uncategorized };
|
enum Kind {
|
||||||
|
CK_Attr,
|
||||||
|
CK_Prop,
|
||||||
|
CK_Region,
|
||||||
|
CK_Successor,
|
||||||
|
CK_Type,
|
||||||
|
CK_Uncategorized
|
||||||
|
};
|
||||||
|
|
||||||
// Create a constraint with a TableGen definition and a kind.
|
// Create a constraint with a TableGen definition and a kind.
|
||||||
Constraint(const llvm::Record *record, Kind kind) : def(record), kind(kind) {}
|
Constraint(const llvm::Record *record, Kind kind) : def(record), kind(kind) {}
|
||||||
|
@ -26,6 +26,8 @@ Constraint::Constraint(const llvm::Record *record)
|
|||||||
kind = CK_Type;
|
kind = CK_Type;
|
||||||
} else if (def->isSubClassOf("AttrConstraint")) {
|
} else if (def->isSubClassOf("AttrConstraint")) {
|
||||||
kind = CK_Attr;
|
kind = CK_Attr;
|
||||||
|
} else if (def->isSubClassOf("PropConstraint")) {
|
||||||
|
kind = CK_Prop;
|
||||||
} else if (def->isSubClassOf("RegionConstraint")) {
|
} else if (def->isSubClassOf("RegionConstraint")) {
|
||||||
kind = CK_Region;
|
kind = CK_Region;
|
||||||
} else if (def->isSubClassOf("SuccessorConstraint")) {
|
} else if (def->isSubClassOf("SuccessorConstraint")) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user