Skip to content

[mlir] Add a ValueSemantics trait. #99493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 21, 2024
Merged

[mlir] Add a ValueSemantics trait. #99493

merged 1 commit into from
Jul 21, 2024

Conversation

pifon2a
Copy link
Contributor

@pifon2a pifon2a commented Jul 18, 2024

We need to distinguish ShapedTypes with and without value semantics. This is needed for downstream users to define their custom vector and tensor
types that can work with the arith/math dialect.

RFC https://discourse.llvm.org/t/rfc-mlir-types-with-encoding/80189

@pifon2a pifon2a requested review from ftynse and ThomasRaoux July 18, 2024 13:41
@llvmbot llvmbot added mlir:core MLIR Core Infrastructure mlir mlir:ods labels Jul 18, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 18, 2024

@llvm/pr-subscribers-mlir-ods
@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-core

Author: Alexander Belyaev (pifon2a)

Changes

This is needed for downstream users to define their custom vector and tensor types that can work with the arith/math dialect.

RFC https://discourse.llvm.org/t/rfc-mlir-types-with-encoding/80189


Full diff: https://github.com/llvm/llvm-project/pull/99493.diff

3 Files Affected:

  • (modified) mlir/include/mlir/IR/BuiltinTypes.h (+5)
  • (modified) mlir/include/mlir/IR/BuiltinTypes.td (+12-2)
  • (modified) mlir/include/mlir/IR/CommonTypeConstraints.td (+16-4)
diff --git a/mlir/include/mlir/IR/BuiltinTypes.h b/mlir/include/mlir/IR/BuiltinTypes.h
index 5579b138668d2..ab01ea2293f3d 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.h
+++ b/mlir/include/mlir/IR/BuiltinTypes.h
@@ -39,6 +39,11 @@ struct IntegerTypeStorage;
 struct TupleTypeStorage;
 } // namespace detail
 
+/// Type trait indicating that the type can be an operand to an elementwise op.
+template <typename ConcreteType>
+class MappableContainer
+    : public TypeTrait::TraitBase<ConcreteType, MappableContainer> {};
+
 //===----------------------------------------------------------------------===//
 // FloatType
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td
index 4cade83dd3c32..9e93593bb45d4 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -30,6 +30,15 @@ class Builtin_Type<string name, string typeMnemonic, list<Trait> traits = [],
   let typeName = "builtin." # typeMnemonic;
 }
 
+//===----------------------------------------------------------------------===//
+// Traits
+//===----------------------------------------------------------------------===//
+
+/// Type trait indicating that the type can be an operand to an elementwise op.
+def MappableContainer : NativeTypeTrait<"MappableContainer"> {
+  let cppNamespace = "::mlir";
+}
+
 //===----------------------------------------------------------------------===//
 // ComplexType
 //===----------------------------------------------------------------------===//
@@ -745,7 +754,7 @@ def Builtin_Opaque : Builtin_Type<"Opaque", "opaque"> {
 //===----------------------------------------------------------------------===//
 
 def Builtin_RankedTensor : Builtin_Type<"RankedTensor", "tensor", [
-    ShapedTypeInterface
+    MappableContainer, ShapedTypeInterface
   ], "TensorType"> {
   let summary = "Multi-dimensional array with a fixed number of dimensions";
   let description = [{
@@ -1049,7 +1058,8 @@ def Builtin_UnrankedTensor : Builtin_Type<"UnrankedTensor", "unranked_tensor", [
 // VectorType
 //===----------------------------------------------------------------------===//
 
-def Builtin_Vector : Builtin_Type<"Vector", "vector", [ShapedTypeInterface], "Type"> {
+def Builtin_Vector : Builtin_Type<"Vector", "vector",
+    [MappableContainer, ShapedTypeInterface], "Type"> {
   let summary = "Multi-dimensional SIMD vector type";
   let description = [{
     Syntax:
diff --git a/mlir/include/mlir/IR/CommonTypeConstraints.td b/mlir/include/mlir/IR/CommonTypeConstraints.td
index af4f13dc09360..2284d59869a20 100644
--- a/mlir/include/mlir/IR/CommonTypeConstraints.td
+++ b/mlir/include/mlir/IR/CommonTypeConstraints.td
@@ -89,6 +89,9 @@ def HasStaticShapePred :
 // Whether a type is a TupleType.
 def IsTupleTypePred : CPred<"::llvm::isa<::mlir::TupleType>($_self)">;
 
+// Whether a type has a MappableContainer trait.
+def IsMappableContainerPred : CPred<"$_self.hasTrait<MappableContainer>()">;
+
 //===----------------------------------------------------------------------===//
 // Type definitions
 //===----------------------------------------------------------------------===//
@@ -403,6 +406,10 @@ class HasRankGreaterOrEqualPred<int rank> : And<[
     CPred<[{::llvm::cast<::mlir::ShapedType>($_self).getRank() >= }] # rank>
 ]>;
 
+// Mappable types.
+class MappableContainerOf<list<Type> allowedTypes> :
+  ShapedContainerType<allowedTypes, IsMappableContainerPred, "mapable container">;
+
 // Vector types.
 
 class VectorOf<list<Type> allowedTypes> :
@@ -842,10 +849,15 @@ class NestedTupleOf<list<Type> allowedTypes> :
 // Common type constraints
 //===----------------------------------------------------------------------===//
 // Type constraint for types that are "like" some type or set of types T, that is
-// they're either a T, a vector of Ts, or a tensor of Ts
+// they're either a T, a vector of Ts, or a tensor of Ts.
 class TypeOrContainer<Type allowedType, string name> : TypeConstraint<Or<[
-  allowedType.predicate, VectorOf<[allowedType]>.predicate,
-  TensorOf<[allowedType]>.predicate]>,
+  allowedType.predicate, MappableContainerOf<[allowedType]>.predicate]>,
+  name>;
+
+// Type constraint for types that are "like" some type or set of types T, that is
+// they're either a T or a mapable container of Ts.
+class TypeOrMappableContainer<Type allowedType, string name> : TypeConstraint<Or<[
+  allowedType.predicate, MappableContainerOf<[allowedType]>.predicate]>,
   name>;
 
 // Temporary constraint to allow gradual transition to supporting 0-D vectors.
@@ -864,7 +876,7 @@ def BoolLikeOfAnyRank : TypeOrContainerOfAnyRank<I1, "bool-like">;
 
 // Type constraint for signless-integer-like types: signless integers, indices,
 // vectors of signless integers or indices, tensors of signless integers.
-def SignlessIntegerLike : TypeOrContainer<AnySignlessIntegerOrIndex,
+def SignlessIntegerLike : TypeOrMappableContainer<AnySignlessIntegerOrIndex,
     "signless-integer-like">;
 
 def SignlessIntegerLikeOfAnyRank : TypeOrContainerOfAnyRank<

@@ -39,6 +39,11 @@ struct IntegerTypeStorage;
struct TupleTypeStorage;
} // namespace detail

/// Type trait indicating that the type can be an operand to an elementwise op.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description, as well as the name of the trait does not seem to be something that we couldn't apply to Memref.
However this isn't the intent right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it is not the intent. How would you phrase it better? I want this trait to be for value types like vector or tensor, but not for memrefs. MemRefs are just pointers, it is not clear what we actually map.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memref are more than pointers: they have a shape, which means you can actually iterate all the elements inside a memref. This makes it a candidate for a "map" function I believe (I understand this isn't what you want, which is why I'm picking on the name).
I think @jpienaar proposed something for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MappableValueBasedContainer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this conflating two different traits? For an arith op on a shaped type you want it to have value semantics and you want the right element type. Why does that need to be expressed in a single trait?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the second trait.

/// Type trait indicating that the type can be an operand to an elementwise op.
template <typename ConcreteType>
class MappableContainer
: public TypeTrait::TraitBase<ConcreteType, MappableContainer> {};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this right now knowing we have the ShapedTypeInterface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't. Good catch, Mehdi!

@pifon2a pifon2a changed the title [mlir] Add a MappableContainer trait. [mlir] Add a ValueSemantics trait. Jul 19, 2024
@ThomasRaoux
Copy link
Contributor

looks like there are some build errors on the bot:


In file included from /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-tvbq4-1/llvm-project/github-pull-requests/flang/lib/Optimizer/CodeGen/CGOps.cpp:33:
--
  | /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-tvbq4-1/llvm-project/github-pull-requests/build/tools/flang/include/flang/Optimizer/CodeGen/CGOps.cpp.inc:43:62: error: use of undeclared identifier 'ValueSemantics'; did you mean 'mlir::ValueSemantics'?
  | if (!((((type.isSignlessIntOrIndex())) \|\| (((type.hasTrait<ValueSemantics>())) && ([](::mlir::Type elementType) { return (elementType.isSignlessIntOrIndex()); }(::llvm::cast<::mlir::ShapedType>(type).getElementType())))) \|\| ((type.isSignedInteger())) \|\| ((::llvm::isa<::fir::IntegerType>(type))))) {
  | ^~~~~~~~~~~~~~
  | mlir::ValueSemantics


@pifon2a
Copy link
Contributor Author

pifon2a commented Jul 19, 2024

looks like there are some build errors on the bot:


In file included from /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-tvbq4-1/llvm-project/github-pull-requests/flang/lib/Optimizer/CodeGen/CGOps.cpp:33:
--
  | /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-tvbq4-1/llvm-project/github-pull-requests/build/tools/flang/include/flang/Optimizer/CodeGen/CGOps.cpp.inc:43:62: error: use of undeclared identifier 'ValueSemantics'; did you mean 'mlir::ValueSemantics'?
  | if (!((((type.isSignlessIntOrIndex())) \|\| (((type.hasTrait<ValueSemantics>())) && ([](::mlir::Type elementType) { return (elementType.isSignlessIntOrIndex()); }(::llvm::cast<::mlir::ShapedType>(type).getElementType())))) \|\| ((type.isSignedInteger())) \|\| ((::llvm::isa<::fir::IntegerType>(type))))) {
  | ^~~~~~~~~~~~~~
  | mlir::ValueSemantics

Should work now. Let's see.

@joker-eph joker-eph requested a review from jpienaar July 19, 2024 19:29
Copy link
Collaborator

@joker-eph joker-eph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but if @jpienaar has also time to review, it'd be better.

Copy link
Contributor

@ThomasRaoux ThomasRaoux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me as well

Copy link
Member

@jpienaar jpienaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, I think it reads simply and meaning is clear (I'm reminded we are missing doc generation for these, unrelated of course).

We need to distinguish ShapedTypes with and without value semantics. This is needed for downstream users to define their custom vector and tensor
types that can work with the arith/math dialect.

RFC https://discourse.llvm.org/t/rfc-mlir-types-with-encoding/80189
@pifon2a pifon2a merged commit 568845a into llvm:main Jul 21, 2024
7 checks passed
Copy link
Contributor

@stellaraccident stellaraccident left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Belated lgtm. Thanks.

yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
Summary:
We need to distinguish ShapedTypes with and without value semantics.
This is needed for downstream users to define their custom vector and
tensor
types that can work with the arith/math dialect.

RFC https://discourse.llvm.org/t/rfc-mlir-types-with-encoding/80189

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251327
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mlir:core MLIR Core Infrastructure mlir:ods mlir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants