[Mlir-commits] [mlir] [mlir][Ptr] Add the `MemorySpaceAttrInterface` interface and dependencies. (PR #86870)

Fabian Mora llvmlistbot at llvm.org
Tue Aug 20 07:55:12 PDT 2024


https://github.com/fabianmcg updated https://github.com/llvm/llvm-project/pull/86870

>From e7e93cad71bf764b42cea3d41d255e89a4ddb98f Mon Sep 17 00:00:00 2001
From: Fabian Mora <fmora.dev at gmail.com>
Date: Wed, 27 Mar 2024 20:31:55 +0000
Subject: [PATCH 1/2] [mlir][Ptr] Add the `MemorySpaceAttrInterface` interface
 and dependencies.

This patch introduces the `MemorySpaceAttrInterface` interface. This
interface is responsible for handling the semantics of `ptr` operations.
For example, this interface can be used to create read-only memory spaces,
making any other operation other than a load a verification error, see
`TestConstMemorySpaceAttr` for a possible implementation of this concept.

This patch also introduces Enum depedencies `AtomicOrdering`, and `AtomicBinOp`,
both enumerations are clones of the Enums with same name in the LLVM Dialect.
---
 .../mlir/Dialect/Ptr/IR/CMakeLists.txt        |  12 ++
 .../Dialect/Ptr/IR/MemorySpaceInterfaces.h    |  32 ++++
 .../Dialect/Ptr/IR/MemorySpaceInterfaces.td   | 162 ++++++++++++++++++
 mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h   |   2 +
 .../include/mlir/Dialect/Ptr/IR/PtrDialect.td |   8 +-
 mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td  |  69 ++++++++
 mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td    |   1 +
 mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h   |   1 +
 mlir/lib/Dialect/Ptr/IR/CMakeLists.txt        |   3 +-
 mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp        |   6 +
 mlir/lib/Dialect/Ptr/IR/PtrTypes.cpp          |   4 +-
 mlir/test/Dialect/Ptr/layout.mlir             |  24 +--
 mlir/test/Dialect/Ptr/types.mlir              |  21 ++-
 mlir/test/lib/Dialect/Test/CMakeLists.txt     |   1 +
 mlir/test/lib/Dialect/Test/TestAttrDefs.td    |   9 +
 mlir/test/lib/Dialect/Test/TestAttributes.cpp |  48 ++++++
 mlir/test/lib/Dialect/Test/TestAttributes.h   |   1 +
 17 files changed, 379 insertions(+), 25 deletions(-)
 create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h
 create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
 create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td

diff --git a/mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt
index 82938962fb9391..7c94d52d38299b 100644
--- a/mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt
@@ -5,3 +5,15 @@ set(LLVM_TARGET_DEFINITIONS PtrOps.td)
 mlir_tablegen(PtrOpsAttrs.h.inc -gen-attrdef-decls -attrdefs-dialect=ptr)
 mlir_tablegen(PtrOpsAttrs.cpp.inc -gen-attrdef-defs -attrdefs-dialect=ptr)
 add_public_tablegen_target(MLIRPtrOpsAttributesIncGen)
+
+set(LLVM_TARGET_DEFINITIONS MemorySpaceInterfaces.td)
+mlir_tablegen(MemorySpaceInterfaces.h.inc -gen-op-interface-decls)
+mlir_tablegen(MemorySpaceInterfaces.cpp.inc -gen-op-interface-defs)
+mlir_tablegen(MemorySpaceAttrInterfaces.h.inc -gen-attr-interface-decls)
+mlir_tablegen(MemorySpaceAttrInterfaces.cpp.inc -gen-attr-interface-defs)
+add_public_tablegen_target(MLIRPtrMemorySpaceInterfacesIncGen)
+
+set(LLVM_TARGET_DEFINITIONS PtrOps.td)
+mlir_tablegen(PtrOpsEnums.h.inc -gen-enum-decls)
+mlir_tablegen(PtrOpsEnums.cpp.inc -gen-enum-defs)
+add_public_tablegen_target(MLIRPtrOpsEnumsGen)
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h
new file mode 100644
index 00000000000000..a0467550c4623d
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h
@@ -0,0 +1,32 @@
+//===-- MemorySpaceInterfaces.h - ptr memory space interfaces ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ptr dialect memory space interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_PTR_IR_MEMORYSPACEINTERFACES_H
+#define MLIR_DIALECT_PTR_IR_MEMORYSPACEINTERFACES_H
+
+#include "mlir/IR/Attributes.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/OpDefinition.h"
+
+namespace mlir {
+class Operation;
+namespace ptr {
+enum class AtomicBinOp : uint64_t;
+enum class AtomicOrdering : uint64_t;
+} // namespace ptr
+} // namespace mlir
+
+#include "mlir/Dialect/Ptr/IR/MemorySpaceAttrInterfaces.h.inc"
+
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h.inc"
+
+#endif // MLIR_DIALECT_PTR_IR_MEMORYSPACEINTERFACES_H
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
new file mode 100644
index 00000000000000..8b71721e0b6011
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
@@ -0,0 +1,162 @@
+//===-- MemorySpaceInterfaces.td - Memory space interfaces ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines memory space attribute interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTR_MEMORYSPACEINTERFACES
+#define PTR_MEMORYSPACEINTERFACES
+
+include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/OpBase.td"
+
+//===----------------------------------------------------------------------===//
+// Memory space attribute interface.
+//===----------------------------------------------------------------------===//
+
+def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
+  let description = [{
+    This interface defines a common API for interacting with the memory model of
+    a memory space and the operations in the pointer dialect, giving proper
+    semantical meaning to the ops.
+
+    Furthermore, this interface allows concepts such as read-only memory to be
+    adequately modeled and enforced.
+  }];
+  let cppNamespace = "::mlir::ptr";
+  let methods = [
+    InterfaceMethod<
+      /*desc=*/        [{
+        Returns the default memory space as an attribute.
+      }],
+      /*returnType=*/  "::mlir::ptr::MemorySpaceAttrInterface",
+      /*methodName=*/  "getDefaultMemorySpace",
+      /*args=*/        (ins),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+    >,
+    InterfaceMethod<
+      /*desc=*/        [{
+        This method checks if it's valid to load a value from the memory space
+        with a specific type, alignment, and atomic ordering.
+        If `emitError` is non-null then the method is allowed to emit errors.
+      }],
+      /*returnType=*/  "::mlir::LogicalResult",
+      /*methodName=*/  "isValidLoad",
+      /*args=*/        (ins "::mlir::Type":$type,
+                            "::mlir::ptr::AtomicOrdering":$ordering,
+                            "::mlir::IntegerAttr":$alignment,
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+    >,
+    InterfaceMethod<
+      /*desc=*/        [{
+        This method checks if it's valid to store a value in the memory space
+        with a specific type, alignment, and atomic ordering.
+        If `emitError` is non-null then the method is allowed to emit errors.
+      }],
+      /*returnType=*/  "::mlir::LogicalResult",
+      /*methodName=*/  "isValidStore",
+      /*args=*/        (ins "::mlir::Type":$type,
+                            "::mlir::ptr::AtomicOrdering":$ordering,
+                            "::mlir::IntegerAttr":$alignment,
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+    >,
+    InterfaceMethod<
+      /*desc=*/        [{
+        This method checks if it's valid to perform an atomic operation in the
+        memory space with a specific type, alignment, and atomic ordering.
+        If `emitError` is non-null then the method is allowed to emit errors.
+      }],
+      /*returnType=*/  "::mlir::LogicalResult",
+      /*methodName=*/  "isValidAtomicOp",
+      /*args=*/        (ins "::mlir::ptr::AtomicBinOp":$op,
+                            "::mlir::Type":$type,
+                            "::mlir::ptr::AtomicOrdering":$ordering,
+                            "::mlir::IntegerAttr":$alignment,
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+    >,
+    InterfaceMethod<
+      /*desc=*/        [{
+        This method checks if it's valid to perform an atomic exchange operation
+        in the memory space with a specific type, alignment, and atomic
+        orderings.
+        If `emitError` is non-null then the method is allowed to emit errors.
+      }],
+      /*returnType=*/  "::mlir::LogicalResult",
+      /*methodName=*/  "isValidAtomicXchg",
+      /*args=*/        (ins "::mlir::Type":$type,
+                            "::mlir::ptr::AtomicOrdering":$successOrdering,
+                            "::mlir::ptr::AtomicOrdering":$failureOrdering,
+                            "::mlir::IntegerAttr":$alignment,
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+    >,
+    InterfaceMethod<
+      /*desc=*/        [{
+        This method checks if it's valid to perform an `addrspacecast` op
+        in the memory space.
+        Both types are expected to be vectors of rank 1, or scalars of `ptr`
+        type.
+        If `emitError` is non-null then the method is allowed to emit errors.
+      }],
+      /*returnType=*/  "::mlir::LogicalResult",
+      /*methodName=*/  "isValidAddrSpaceCast",
+      /*args=*/        (ins "::mlir::Type":$tgt,
+                            "::mlir::Type":$src,
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+    >,
+    InterfaceMethod<
+      /*desc=*/        [{
+        This method checks if it's valid to perform a `ptrtoint` or `inttoptr`
+        op in the memory space. `CastValidity::InvalidSourceType` always refers
+        to the 'ptr-like' type and `CastValidity::InvalidTargetType` always
+        refers to the `int-like` type.
+        The first type is expected to be integer-like, while the second must be a
+        ptr-like type.
+        If `emitError` is non-null then the method is allowed to emit errors.
+      }],
+      /*returnType=*/  "::mlir::LogicalResult",
+      /*methodName=*/  "isValidPtrIntCast",
+      /*args=*/        (ins "::mlir::Type":$intLikeTy,
+                            "::mlir::Type":$ptrLikeTy,
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+    >,
+  ];
+}
+
+def MemorySpaceOpInterface : OpInterface<"MemorySpaceOpInterface"> {
+  let description = [{
+    An interface for operations with a memory space.
+  }];
+
+  let cppNamespace = "::mlir::ptr";
+
+  let methods = [
+    InterfaceMethod<
+      /*desc=*/        "Returns the memory space of the op.",
+      /*returnType=*/  "::mlir::ptr::MemorySpaceAttrInterface",
+      /*methodName=*/  "getMemorySpace",
+      /*args=*/        (ins),
+      /*methodBody=*/  [{}],
+      /*defaultImpl=*/ [{}]
+      >,
+  ];
+}
+#endif // PTR_MEMORYSPACEINTERFACES
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h b/mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h
index 72e767764d98b2..5ffe23e45fe12c 100644
--- a/mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h
@@ -18,4 +18,6 @@
 #define GET_ATTRDEF_CLASSES
 #include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.h.inc"
 
+#include "mlir/Dialect/Ptr/IR/PtrOpsEnums.h.inc"
+
 #endif // MLIR_DIALECT_PTR_IR_PTRATTRS_H
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td b/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td
index 14d72c3001d919..8d5b68b89d31df 100644
--- a/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td
@@ -44,7 +44,7 @@ def Ptr_PtrType : Ptr_Type<"Ptr", "ptr", [
   let description = [{
     The `ptr` type is an opaque pointer type. This type typically represents a
     handle to an object in memory or target-dependent values like `nullptr`.
-    Pointers are optionally parameterized by a memory space.
+    Pointers are parameterized by a memory space.
 
     Syntax:
 
@@ -53,10 +53,10 @@ def Ptr_PtrType : Ptr_Type<"Ptr", "ptr", [
     memory-space ::= attribute-value
     ```
   }];
-  let parameters = (ins OptionalParameter<"Attribute">:$memorySpace);
-  let assemblyFormat = "(`<` $memorySpace^ `>`)?";
+  let parameters = (ins "MemorySpaceAttrInterface":$memorySpace);
+  let assemblyFormat = "`<` $memorySpace `>`";
   let builders = [
-    TypeBuilder<(ins CArg<"Attribute", "nullptr">:$memorySpace), [{
+    TypeBuilder<(ins CArg<"MemorySpaceAttrInterface", "nullptr">:$memorySpace), [{
       return $_get($_ctxt, memorySpace);
     }]>
   ];
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td b/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
new file mode 100644
index 00000000000000..3a921e4de08d8d
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
@@ -0,0 +1,69 @@
+//===-- PtrEnums.td - Ptr dialect enumerations -------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTR_ENUMS
+#define PTR_ENUMS
+
+include "mlir/IR/EnumAttr.td"
+
+//===----------------------------------------------------------------------===//
+// Atomic binary op enum attribute
+//===----------------------------------------------------------------------===//
+
+def AtomicBinOpXchg : I64EnumAttrCase<"xchg", 0, "xchg">;
+def AtomicBinOpAdd  : I64EnumAttrCase<"add", 1, "add">;
+def AtomicBinOpSub  : I64EnumAttrCase<"sub", 2, "sub">;
+def AtomicBinOpAnd  : I64EnumAttrCase<"_and", 3, "_and">;
+def AtomicBinOpNand : I64EnumAttrCase<"nand", 4, "nand">;
+def AtomicBinOpOr   : I64EnumAttrCase<"_or", 5, "_or">;
+def AtomicBinOpXor  : I64EnumAttrCase<"_xor", 6, "_xor">;
+def AtomicBinOpMax  : I64EnumAttrCase<"max", 7, "max">;
+def AtomicBinOpMin  : I64EnumAttrCase<"min", 8, "min">;
+def AtomicBinOpUMax : I64EnumAttrCase<"umax", 9, "umax">;
+def AtomicBinOpUMin : I64EnumAttrCase<"umin", 10, "umin">;
+def AtomicBinOpFAdd : I64EnumAttrCase<"fadd", 11, "fadd">;
+def AtomicBinOpFSub : I64EnumAttrCase<"fsub", 12, "fsub">;
+def AtomicBinOpFMax : I64EnumAttrCase<"fmax", 13, "fmax">;
+def AtomicBinOpFMin : I64EnumAttrCase<"fmin", 14, "fmin">;
+def AtomicBinOpUIncWrap : I64EnumAttrCase<"uinc_wrap", 15, "uinc_wrap">;
+def AtomicBinOpUDecWrap : I64EnumAttrCase<"udec_wrap", 16, "udec_wrap">;
+
+def AtomicBinOp : I64EnumAttr<
+    "AtomicBinOp",
+    "ptr.atomicrmw binary operations",
+    [AtomicBinOpXchg, AtomicBinOpAdd, AtomicBinOpSub, AtomicBinOpAnd,
+     AtomicBinOpNand, AtomicBinOpOr, AtomicBinOpXor, AtomicBinOpMax,
+     AtomicBinOpMin, AtomicBinOpUMax, AtomicBinOpUMin, AtomicBinOpFAdd,
+     AtomicBinOpFSub, AtomicBinOpFMax, AtomicBinOpFMin, AtomicBinOpUIncWrap,
+     AtomicBinOpUDecWrap]> {
+  let cppNamespace = "::mlir::ptr";
+}
+
+//===----------------------------------------------------------------------===//
+// Atomic ordering enum attribute
+//===----------------------------------------------------------------------===//
+
+def AtomicOrderingNotAtomic : I64EnumAttrCase<"not_atomic", 0, "not_atomic">;
+def AtomicOrderingUnordered : I64EnumAttrCase<"unordered", 1, "unordered">;
+def AtomicOrderingMonotonic : I64EnumAttrCase<"monotonic", 2, "monotonic">;
+def AtomicOrderingAcquire   : I64EnumAttrCase<"acquire", 3, "acquire">;
+def AtomicOrderingRelease   : I64EnumAttrCase<"release", 4, "release">;
+def AtomicOrderingAcqRel    : I64EnumAttrCase<"acq_rel", 5, "acq_rel">;
+def AtomicOrderingSeqCst    : I64EnumAttrCase<"seq_cst", 6, "seq_cst">;
+
+def AtomicOrdering : I64EnumAttr<
+    "AtomicOrdering",
+    "Atomic ordering for LLVM's memory model",
+    [AtomicOrderingNotAtomic, AtomicOrderingUnordered, AtomicOrderingMonotonic,
+     AtomicOrderingAcquire, AtomicOrderingRelease, AtomicOrderingAcqRel,
+     AtomicOrderingSeqCst
+    ]> {
+  let cppNamespace = "::mlir::ptr";
+}
+
+#endif // PTR_ENUMS
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td b/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td
index c63a0b220e501c..313c9f8eb09ac5 100644
--- a/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td
@@ -11,6 +11,7 @@
 
 include "mlir/Dialect/Ptr/IR/PtrDialect.td"
 include "mlir/Dialect/Ptr/IR/PtrAttrDefs.td"
+include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
 include "mlir/IR/OpAsmInterface.td"
 
 #endif // PTR_OPS
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h b/mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h
index 264a97c80722a2..4fe1b5a1aa4230 100644
--- a/mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h
@@ -13,6 +13,7 @@
 #ifndef MLIR_DIALECT_PTR_IR_PTRTYPES_H
 #define MLIR_DIALECT_PTR_IR_PTRTYPES_H
 
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/IR/Types.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
 
diff --git a/mlir/lib/Dialect/Ptr/IR/CMakeLists.txt b/mlir/lib/Dialect/Ptr/IR/CMakeLists.txt
index 9cf3643c73d3ed..ba32a76273ed41 100644
--- a/mlir/lib/Dialect/Ptr/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/Ptr/IR/CMakeLists.txt
@@ -7,7 +7,8 @@ add_mlir_dialect_library(
   DEPENDS
   MLIRPtrOpsAttributesIncGen
   MLIRPtrOpsIncGen
-
+  MLIRPtrOpsEnumsGen
+  MLIRPtrMemorySpaceInterfacesIncGen
   LINK_LIBS
   PUBLIC
   MLIRIR
diff --git a/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp b/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
index 7830ffe893dfd1..ff231dae60c275 100644
--- a/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
+++ b/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
@@ -48,6 +48,12 @@ void PtrDialect::initialize() {
 #define GET_ATTRDEF_CLASSES
 #include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.cpp.inc"
 
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.cpp.inc"
+
+#include "mlir/Dialect/Ptr/IR/MemorySpaceAttrInterfaces.cpp.inc"
+
+#include "mlir/Dialect/Ptr/IR/PtrOpsEnums.cpp.inc"
+
 #define GET_TYPEDEF_CLASSES
 #include "mlir/Dialect/Ptr/IR/PtrOpsTypes.cpp.inc"
 
diff --git a/mlir/lib/Dialect/Ptr/IR/PtrTypes.cpp b/mlir/lib/Dialect/Ptr/IR/PtrTypes.cpp
index 2866d4eb10feb1..ac67f2ab9a76fd 100644
--- a/mlir/lib/Dialect/Ptr/IR/PtrTypes.cpp
+++ b/mlir/lib/Dialect/Ptr/IR/PtrTypes.cpp
@@ -25,7 +25,9 @@ constexpr const static unsigned kDefaultPointerSizeBits = 64;
 constexpr const static unsigned kBitsInByte = 8;
 constexpr const static unsigned kDefaultPointerAlignment = 8;
 
-static Attribute getDefaultMemorySpace(PtrType ptr) { return nullptr; }
+static MemorySpaceAttrInterface getDefaultMemorySpace(PtrType ptr) {
+  return ptr.getMemorySpace().getDefaultMemorySpace();
+}
 
 /// Searches the data layout for the pointer spec, returns nullptr if it is not
 /// found.
diff --git a/mlir/test/Dialect/Ptr/layout.mlir b/mlir/test/Dialect/Ptr/layout.mlir
index 73189a388942ac..64d7b2d78ef8e9 100644
--- a/mlir/test/Dialect/Ptr/layout.mlir
+++ b/mlir/test/Dialect/Ptr/layout.mlir
@@ -1,9 +1,9 @@
 // RUN: mlir-opt --test-data-layout-query --split-input-file --verify-diagnostics %s | FileCheck %s
 
 module attributes { dlti.dl_spec = #dlti.dl_spec<
-  #dlti.dl_entry<!ptr.ptr, #ptr.spec<size = 32, abi = 32, preferred = 64>>,
-  #dlti.dl_entry<!ptr.ptr<5>,#ptr.spec<size = 64, abi = 64, preferred = 64>>,
-  #dlti.dl_entry<!ptr.ptr<4>, #ptr.spec<size = 32, abi = 64, preferred = 64, index = 24>>,
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space>, #ptr.spec<size = 32, abi = 32, preferred = 64>>,
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space<5>>,#ptr.spec<size = 64, abi = 64, preferred = 64>>,
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space<4>>, #ptr.spec<size = 32, abi = 64, preferred = 64, index = 24>>,
   #dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui64>,
   #dlti.dl_entry<"dlti.global_memory_space", 2 : ui64>,
   #dlti.dl_entry<"dlti.program_memory_space", 3 : ui64>,
@@ -20,7 +20,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
     // CHECK: program_memory_space = 3
     // CHECK: size = 4
     // CHECK: stack_alignment = 128
-    "test.data_layout_query"() : () -> !ptr.ptr
+    "test.data_layout_query"() : () -> !ptr.ptr<#test.const_memory_space>
     // CHECK: alignment = 4
     // CHECK: alloca_memory_space = 5
     // CHECK: bitsize = 32
@@ -30,7 +30,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
     // CHECK: program_memory_space = 3
     // CHECK: size = 4
     // CHECK: stack_alignment = 128
-    "test.data_layout_query"() : () -> !ptr.ptr<3>
+    "test.data_layout_query"() : () -> !ptr.ptr<#test.const_memory_space<3>>
     // CHECK: alignment = 8
     // CHECK: alloca_memory_space = 5
     // CHECK: bitsize = 64
@@ -40,7 +40,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
     // CHECK: program_memory_space = 3
     // CHECK: size = 8
     // CHECK: stack_alignment = 128
-    "test.data_layout_query"() : () -> !ptr.ptr<5>
+    "test.data_layout_query"() : () -> !ptr.ptr<#test.const_memory_space<5>>
     // CHECK: alignment = 8
     // CHECK: alloca_memory_space = 5
     // CHECK: bitsize = 32
@@ -50,7 +50,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
     // CHECK: program_memory_space = 3
     // CHECK: size = 4
     // CHECK: stack_alignment = 128
-    "test.data_layout_query"() : () -> !ptr.ptr<4>
+    "test.data_layout_query"() : () -> !ptr.ptr<#test.const_memory_space<4>>
     return
   }
 }
@@ -59,7 +59,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
 
 // expected-error at +2 {{preferred alignment is expected to be at least as large as ABI alignment}}
 module attributes { dlti.dl_spec = #dlti.dl_spec<
-  #dlti.dl_entry<!ptr.ptr, #ptr.spec<size = 64, abi = 64, preferred = 32>>
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space>, #ptr.spec<size = 64, abi = 64, preferred = 32>>
 >} {
   func.func @pointer() {
     return
@@ -70,7 +70,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
 
 // expected-error at +2 {{size entry must be divisible by 8}}
 module attributes { dlti.dl_spec = #dlti.dl_spec<
-  #dlti.dl_entry<!ptr.ptr, #ptr.spec<size = 33, abi = 32, preferred = 32>>
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space>, #ptr.spec<size = 33, abi = 32, preferred = 32>>
 >} {
   func.func @pointer() {
     return
@@ -82,7 +82,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
 
 // expected-error at +2 {{abi entry must be divisible by 8}}
 module attributes { dlti.dl_spec = #dlti.dl_spec<
-  #dlti.dl_entry<!ptr.ptr, #ptr.spec<size = 32, abi = 33, preferred = 64>>
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space>, #ptr.spec<size = 32, abi = 33, preferred = 64>>
 >} {
   func.func @pointer() {
     return
@@ -94,7 +94,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
 
 // expected-error at +2 {{preferred entry must be divisible by 8}}
 module attributes { dlti.dl_spec = #dlti.dl_spec<
-  #dlti.dl_entry<!ptr.ptr, #ptr.spec<size = 32, abi = 32, preferred = 33>>
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space>, #ptr.spec<size = 32, abi = 32, preferred = 33>>
 >} {
   func.func @pointer() {
     return
@@ -106,7 +106,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
 
 // expected-error at +2 {{index entry must be divisible by 8}}
 module attributes { dlti.dl_spec = #dlti.dl_spec<
-  #dlti.dl_entry<!ptr.ptr, #ptr.spec<size = 32, abi = 32, preferred = 32, index = 33>>
+  #dlti.dl_entry<!ptr.ptr<#test.const_memory_space>, #ptr.spec<size = 32, abi = 32, preferred = 32, index = 33>>
 >} {
   func.func @pointer() {
     return
diff --git a/mlir/test/Dialect/Ptr/types.mlir b/mlir/test/Dialect/Ptr/types.mlir
index 279213bd6fc3e5..6f4e89eb3e19b3 100644
--- a/mlir/test/Dialect/Ptr/types.mlir
+++ b/mlir/test/Dialect/Ptr/types.mlir
@@ -1,17 +1,24 @@
 // RUN: mlir-opt %s -split-input-file | mlir-opt | FileCheck %s
 
 // CHECK-LABEL: func @ptr_test
-// CHECK: (%[[ARG0:.*]]: !ptr.ptr, %[[ARG1:.*]]: !ptr.ptr<1 : i32>)
-// CHECK: -> (!ptr.ptr<1 : i32>, !ptr.ptr)
-func.func @ptr_test(%arg0: !ptr.ptr, %arg1: !ptr.ptr<1 : i32>) -> (!ptr.ptr<1 : i32>, !ptr.ptr) {
-  // CHECK: return %[[ARG1]], %[[ARG0]] : !ptr.ptr<1 : i32>, !ptr.ptr
-  return %arg1, %arg0 : !ptr.ptr<1 : i32>, !ptr.ptr
+// CHECK: (%[[ARG0:.*]]: !ptr.ptr<#test.const_memory_space>, %[[ARG1:.*]]: !ptr.ptr<#test.const_memory_space<1>>)
+// CHECK: -> (!ptr.ptr<#test.const_memory_space<1>>, !ptr.ptr<#test.const_memory_space>)
+func.func @ptr_test(%arg0: !ptr.ptr<#test.const_memory_space>, %arg1: !ptr.ptr<#test.const_memory_space<1>>) -> (!ptr.ptr<#test.const_memory_space<1>>, !ptr.ptr<#test.const_memory_space>) {
+  // CHECK: return %[[ARG1]], %[[ARG0]] : !ptr.ptr<#test.const_memory_space<1>>, !ptr.ptr<#test.const_memory_space>
+  return %arg1, %arg0 : !ptr.ptr<#test.const_memory_space<1>>, !ptr.ptr<#test.const_memory_space>
 }
 
 // -----
 
 // CHECK-LABEL: func @ptr_test
-// CHECK: %[[ARG:.*]]: memref<!ptr.ptr>
-func.func @ptr_test(%arg0: memref<!ptr.ptr>) {
+// CHECK: %[[ARG:.*]]: memref<!ptr.ptr<#test.const_memory_space>>
+func.func @ptr_test(%arg0: memref<!ptr.ptr<#test.const_memory_space>>) {
+  return
+}
+
+// CHECK-LABEL: func @ptr_test_1
+// CHECK: (%[[ARG0:.*]]: !ptr.ptr<#test.const_memory_space>, %[[ARG1:.*]]: !ptr.ptr<#test.const_memory_space<3>>)
+func.func @ptr_test_1(%arg0: !ptr.ptr<#test.const_memory_space>,
+                      %arg1: !ptr.ptr<#test.const_memory_space<3>>) {
   return
 }
diff --git a/mlir/test/lib/Dialect/Test/CMakeLists.txt b/mlir/test/lib/Dialect/Test/CMakeLists.txt
index 967101242e26b5..e083b654d1041a 100644
--- a/mlir/test/lib/Dialect/Test/CMakeLists.txt
+++ b/mlir/test/lib/Dialect/Test/CMakeLists.txt
@@ -84,6 +84,7 @@ add_mlir_library(MLIRTestDialect
   MLIRInferTypeOpInterface
   MLIRLinalgDialect
   MLIRLinalgTransforms
+  MLIRPtrDialect
   MLIRLLVMDialect
   MLIRPass
   MLIRPolynomialDialect
diff --git a/mlir/test/lib/Dialect/Test/TestAttrDefs.td b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
index b3b94bd0ffea31..ad3e7ad8b6cfc3 100644
--- a/mlir/test/lib/Dialect/Test/TestAttrDefs.td
+++ b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
@@ -17,6 +17,7 @@
 include "TestDialect.td"
 include "TestEnumDefs.td"
 include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.td"
+include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
 include "mlir/Dialect/Utils/StructuredOpsUtils.td"
 include "mlir/IR/AttrTypeBase.td"
 include "mlir/IR/BuiltinAttributeInterfaces.td"
@@ -376,5 +377,13 @@ def NestedPolynomialAttr2 : Test_Attr<"NestedPolynomialAttr2"> {
   }];
 }
 
+// Test a ptr constant memory space.
+def TestConstMemorySpaceAttr : Test_Attr<"TestConstMemorySpace", [
+    DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
+  ]> {
+  let mnemonic = "const_memory_space";
+  let parameters = (ins DefaultValuedParameter<"unsigned", "0">:$addressSpace);
+  let assemblyFormat = "(`<` $addressSpace^ `>`)?";
+}
 
 #endif // TEST_ATTRDEFS
diff --git a/mlir/test/lib/Dialect/Test/TestAttributes.cpp b/mlir/test/lib/Dialect/Test/TestAttributes.cpp
index e09ea109061648..23dcb3736e75bc 100644
--- a/mlir/test/lib/Dialect/Test/TestAttributes.cpp
+++ b/mlir/test/lib/Dialect/Test/TestAttributes.cpp
@@ -316,6 +316,54 @@ static ParseResult parseCustomFloatAttr(AsmParser &p, StringAttr &typeStrAttr,
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// TestConstMemorySpaceAttr
+//===----------------------------------------------------------------------===//
+
+ptr::MemorySpaceAttrInterface
+TestConstMemorySpaceAttr::getDefaultMemorySpace() const {
+  return TestConstMemorySpaceAttr::get(getContext(), 0);
+}
+
+LogicalResult TestConstMemorySpaceAttr::isValidLoad(
+    Type type, mlir::ptr::AtomicOrdering ordering, IntegerAttr alignment,
+    function_ref<InFlightDiagnostic()> emitError) const {
+  return success();
+}
+
+LogicalResult TestConstMemorySpaceAttr::isValidStore(
+    Type type, mlir::ptr::AtomicOrdering ordering, IntegerAttr alignment,
+    function_ref<InFlightDiagnostic()> emitError) const {
+  return emitError ? (emitError() << "memory space is read-only") : failure();
+}
+
+LogicalResult TestConstMemorySpaceAttr::isValidAtomicOp(
+    mlir::ptr::AtomicBinOp binOp, Type type, mlir::ptr::AtomicOrdering ordering,
+    IntegerAttr alignment, function_ref<InFlightDiagnostic()> emitError) const {
+  return emitError ? (emitError() << "memory space is read-only") : failure();
+}
+
+LogicalResult TestConstMemorySpaceAttr::isValidAtomicXchg(
+    Type type, mlir::ptr::AtomicOrdering successOrdering,
+    mlir::ptr::AtomicOrdering failureOrdering, IntegerAttr alignment,
+    function_ref<InFlightDiagnostic()> emitError) const {
+  return emitError ? (emitError() << "memory space is read-only") : failure();
+}
+
+LogicalResult TestConstMemorySpaceAttr::isValidAddrSpaceCast(
+    Type tgt, Type src, function_ref<InFlightDiagnostic()> emitError) const {
+  return emitError
+             ? (emitError() << "memory space doesn't allow addrspace casts")
+             : failure();
+}
+
+LogicalResult TestConstMemorySpaceAttr::isValidPtrIntCast(
+    Type intLikeTy, Type ptrLikeTy,
+    function_ref<InFlightDiagnostic()> emitError) const {
+  return emitError ? (emitError() << "memory space doesn't allow int-ptr casts")
+                   : failure();
+}
+
 //===----------------------------------------------------------------------===//
 // Tablegen Generated Definitions
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Dialect/Test/TestAttributes.h b/mlir/test/lib/Dialect/Test/TestAttributes.h
index 7099bcf3172948..bcbc360758eeca 100644
--- a/mlir/test/lib/Dialect/Test/TestAttributes.h
+++ b/mlir/test/lib/Dialect/Test/TestAttributes.h
@@ -18,6 +18,7 @@
 
 #include "TestTraits.h"
 #include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/Dialect/Utils/StructuredOpsUtils.h"
 #include "mlir/IR/Attributes.h"
 #include "mlir/IR/Diagnostics.h"

>From 832c41b3fa8c252d555f9912378755c15a7eca03 Mon Sep 17 00:00:00 2001
From: Fabian Mora <fmora.dev at gmail.com>
Date: Tue, 20 Aug 2024 13:26:20 +0000
Subject: [PATCH 2/2] address reviewer comments

---
 .../Dialect/Ptr/IR/MemorySpaceInterfaces.td   | 38 +++++--------------
 mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td  |  4 +-
 2 files changed, 11 insertions(+), 31 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
index 8b71721e0b6011..09d389b07c7ebb 100644
--- a/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
+++ b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
@@ -36,10 +36,7 @@ def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
         Returns the default memory space as an attribute.
       }],
       /*returnType=*/  "::mlir::ptr::MemorySpaceAttrInterface",
-      /*methodName=*/  "getDefaultMemorySpace",
-      /*args=*/        (ins),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+      /*methodName=*/  "getDefaultMemorySpace"
     >,
     InterfaceMethod<
       /*desc=*/        [{
@@ -52,9 +49,7 @@ def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
       /*args=*/        (ins "::mlir::Type":$type,
                             "::mlir::ptr::AtomicOrdering":$ordering,
                             "::mlir::IntegerAttr":$alignment,
-                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError)
     >,
     InterfaceMethod<
       /*desc=*/        [{
@@ -67,9 +62,7 @@ def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
       /*args=*/        (ins "::mlir::Type":$type,
                             "::mlir::ptr::AtomicOrdering":$ordering,
                             "::mlir::IntegerAttr":$alignment,
-                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError)
     >,
     InterfaceMethod<
       /*desc=*/        [{
@@ -83,9 +76,7 @@ def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
                             "::mlir::Type":$type,
                             "::mlir::ptr::AtomicOrdering":$ordering,
                             "::mlir::IntegerAttr":$alignment,
-                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError)
     >,
     InterfaceMethod<
       /*desc=*/        [{
@@ -100,9 +91,7 @@ def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
                             "::mlir::ptr::AtomicOrdering":$successOrdering,
                             "::mlir::ptr::AtomicOrdering":$failureOrdering,
                             "::mlir::IntegerAttr":$alignment,
-                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError)
     >,
     InterfaceMethod<
       /*desc=*/        [{
@@ -116,16 +105,12 @@ def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
       /*methodName=*/  "isValidAddrSpaceCast",
       /*args=*/        (ins "::mlir::Type":$tgt,
                             "::mlir::Type":$src,
-                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError)
     >,
     InterfaceMethod<
       /*desc=*/        [{
         This method checks if it's valid to perform a `ptrtoint` or `inttoptr`
-        op in the memory space. `CastValidity::InvalidSourceType` always refers
-        to the 'ptr-like' type and `CastValidity::InvalidTargetType` always
-        refers to the `int-like` type.
+        op in the memory space.
         The first type is expected to be integer-like, while the second must be a
         ptr-like type.
         If `emitError` is non-null then the method is allowed to emit errors.
@@ -134,9 +119,7 @@ def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
       /*methodName=*/  "isValidPtrIntCast",
       /*args=*/        (ins "::mlir::Type":$intLikeTy,
                             "::mlir::Type":$ptrLikeTy,
-                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+                            "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError)
     >,
   ];
 }
@@ -152,10 +135,7 @@ def MemorySpaceOpInterface : OpInterface<"MemorySpaceOpInterface"> {
     InterfaceMethod<
       /*desc=*/        "Returns the memory space of the op.",
       /*returnType=*/  "::mlir::ptr::MemorySpaceAttrInterface",
-      /*methodName=*/  "getMemorySpace",
-      /*args=*/        (ins),
-      /*methodBody=*/  [{}],
-      /*defaultImpl=*/ [{}]
+      /*methodName=*/  "getMemorySpace"
       >,
   ];
 }
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td b/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
index 3a921e4de08d8d..0a8a7ede5d1ff6 100644
--- a/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
@@ -12,7 +12,7 @@
 include "mlir/IR/EnumAttr.td"
 
 //===----------------------------------------------------------------------===//
-// Atomic binary op enum attribute
+// Atomic binary op enum attribute.
 //===----------------------------------------------------------------------===//
 
 def AtomicBinOpXchg : I64EnumAttrCase<"xchg", 0, "xchg">;
@@ -45,7 +45,7 @@ def AtomicBinOp : I64EnumAttr<
 }
 
 //===----------------------------------------------------------------------===//
-// Atomic ordering enum attribute
+// Atomic ordering enum attribute.
 //===----------------------------------------------------------------------===//
 
 def AtomicOrderingNotAtomic : I64EnumAttrCase<"not_atomic", 0, "not_atomic">;



More information about the Mlir-commits mailing list