Skip to content

Commit 8615d8a

Browse files
committed
[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.
1 parent 4d22468 commit 8615d8a

File tree

15 files changed

+592
-2
lines changed

15 files changed

+592
-2
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
11
add_mlir_dialect(PtrOps ptr)
22
add_mlir_doc(PtrOps PtrOps Dialects/ -gen-op-doc)
3+
4+
set(LLVM_TARGET_DEFINITIONS MemorySpaceInterfaces.td)
5+
mlir_tablegen(MemorySpaceInterfaces.h.inc -gen-op-interface-decls)
6+
mlir_tablegen(MemorySpaceInterfaces.cpp.inc -gen-op-interface-defs)
7+
mlir_tablegen(MemorySpaceAttrInterfaces.h.inc -gen-attr-interface-decls)
8+
mlir_tablegen(MemorySpaceAttrInterfaces.cpp.inc -gen-attr-interface-defs)
9+
add_public_tablegen_target(MLIRPtrMemorySpaceInterfacesIncGen)
10+
11+
set(LLVM_TARGET_DEFINITIONS PtrOps.td)
12+
mlir_tablegen(PtrOpsEnums.h.inc -gen-enum-decls)
13+
mlir_tablegen(PtrOpsEnums.cpp.inc -gen-enum-defs)
14+
add_public_tablegen_target(MLIRPtrOpsEnumsGen)
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//===-- MemorySpace.h - ptr dialect memory space ---------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the ptr's dialect memory space class and related
10+
// interfaces.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef MLIR_DIALECT_PTR_IR_MEMORYSPACE_H
15+
#define MLIR_DIALECT_PTR_IR_MEMORYSPACE_H
16+
17+
#include "mlir/IR/Attributes.h"
18+
#include "mlir/IR/BuiltinAttributes.h"
19+
#include "mlir/IR/OpDefinition.h"
20+
21+
namespace mlir {
22+
class Operation;
23+
namespace ptr {
24+
/// This method checks if it's valid to perform an `addrspacecast` op in the
25+
/// memory space.
26+
/// Compatible types are:
27+
/// Vectors of rank 1, or scalars of `ptr` type.
28+
LogicalResult isValidAddrSpaceCastImpl(Type tgt, Type src,
29+
Operation *diagnosticOp);
30+
31+
/// This method checks if it's valid to perform a `ptrtoint` or `inttoptr` op in
32+
/// the memory space.
33+
/// Compatible types are:
34+
/// IntLikeTy: Vectors of rank 1, or scalars of integer types or `index` type.
35+
/// PtrLikeTy: Vectors of rank 1, or scalars of `ptr` type.
36+
LogicalResult isValidPtrIntCastImpl(Type intLikeTy, Type ptrLikeTy,
37+
Operation *diagnosticOp);
38+
39+
enum class AtomicBinOp : uint64_t;
40+
enum class AtomicOrdering : uint64_t;
41+
} // namespace ptr
42+
} // namespace mlir
43+
44+
#include "mlir/Dialect/Ptr/IR/MemorySpaceAttrInterfaces.h.inc"
45+
46+
namespace mlir {
47+
namespace ptr {
48+
/// This class wraps the `MemorySpaceAttrInterface` interface, providing a safe
49+
/// mechanism to specify the default behavior assumed by the ptr dialect.
50+
class MemorySpace {
51+
public:
52+
MemorySpace() = default;
53+
MemorySpace(std::nullptr_t) {}
54+
MemorySpace(MemorySpaceAttrInterface memorySpace)
55+
: memorySpaceAttr(memorySpace), memorySpace(memorySpace) {}
56+
MemorySpace(Attribute memorySpace)
57+
: memorySpaceAttr(memorySpace),
58+
memorySpace(dyn_cast_or_null<MemorySpaceAttrInterface>(memorySpace)) {}
59+
60+
operator Attribute() const { return memorySpaceAttr; }
61+
operator MemorySpaceAttrInterface() const { return memorySpace; }
62+
bool operator==(const MemorySpace &memSpace) const {
63+
return memSpace.memorySpaceAttr == memorySpaceAttr;
64+
}
65+
66+
/// Returns the underlying memory space.
67+
Attribute getUnderlyingSpace() const { return memorySpaceAttr; }
68+
69+
/// Returns true if the underlying memory space is null.
70+
bool isDefaultModel() const { return memorySpace == nullptr; }
71+
72+
/// Returns the memory space as an integer, or 0 if using the default space.
73+
unsigned getAddressSpace() const {
74+
if (memorySpace)
75+
return memorySpace.getAddressSpace();
76+
if (auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(memorySpaceAttr))
77+
return intAttr.getInt();
78+
return 0;
79+
}
80+
81+
/// Returns the default memory space as an attribute, or nullptr if using the
82+
/// default model.
83+
Attribute getDefaultMemorySpace() const {
84+
return memorySpace ? memorySpace.getDefaultMemorySpace() : nullptr;
85+
}
86+
87+
/// This method checks if it's valid to load a value from the memory space
88+
/// with a specific type, alignment, and atomic ordering. The default model
89+
/// assumes all values are loadable.
90+
LogicalResult isValidLoad(Type type, AtomicOrdering ordering,
91+
IntegerAttr alignment,
92+
Operation *diagnosticOp = nullptr) const {
93+
return memorySpace ? memorySpace.isValidLoad(type, ordering, alignment,
94+
diagnosticOp)
95+
: success();
96+
}
97+
98+
/// This method checks if it's valid to store a value in the memory space with
99+
/// a specific type, alignment, and atomic ordering. The default model assumes
100+
/// all values are loadable.
101+
LogicalResult isValidStore(Type type, AtomicOrdering ordering,
102+
IntegerAttr alignment,
103+
Operation *diagnosticOp = nullptr) const {
104+
return memorySpace ? memorySpace.isValidStore(type, ordering, alignment,
105+
diagnosticOp)
106+
: success();
107+
}
108+
109+
/// This method checks if it's valid to perform an atomic operation in the
110+
/// memory space with a specific type, alignment, and atomic ordering.
111+
LogicalResult isValidAtomicOp(AtomicBinOp op, Type type,
112+
AtomicOrdering ordering, IntegerAttr alignment,
113+
Operation *diagnosticOp = nullptr) const {
114+
return memorySpace ? memorySpace.isValidAtomicOp(op, type, ordering,
115+
alignment, diagnosticOp)
116+
: success();
117+
}
118+
119+
/// This method checks if it's valid to perform an atomic operation in the
120+
/// memory space with a specific type, alignment, and atomic ordering.
121+
LogicalResult isValidAtomicXchg(Type type, AtomicOrdering successOrdering,
122+
AtomicOrdering failureOrdering,
123+
IntegerAttr alignment,
124+
Operation *diagnosticOp = nullptr) const {
125+
return memorySpace ? memorySpace.isValidAtomicXchg(type, successOrdering,
126+
failureOrdering,
127+
alignment, diagnosticOp)
128+
: success();
129+
}
130+
131+
/// This method checks if it's valid to perform an `addrspacecast` op in the
132+
/// memory space.
133+
LogicalResult isValidAddrSpaceCast(Type tgt, Type src,
134+
Operation *diagnosticOp = nullptr) const {
135+
return memorySpace
136+
? memorySpace.isValidAddrSpaceCast(tgt, src, diagnosticOp)
137+
: isValidAddrSpaceCastImpl(tgt, src, diagnosticOp);
138+
}
139+
140+
/// This method checks if it's valid to perform a `ptrtoint` or `inttoptr` op
141+
/// in the memory space.
142+
LogicalResult isValidPtrIntCast(Type intLikeTy, Type ptrLikeTy,
143+
Operation *diagnosticOp = nullptr) const {
144+
return memorySpace
145+
? memorySpace.isValidPtrIntCast(intLikeTy, ptrLikeTy,
146+
diagnosticOp)
147+
: isValidPtrIntCastImpl(intLikeTy, ptrLikeTy, diagnosticOp);
148+
}
149+
150+
protected:
151+
/// Underlying memory space.
152+
Attribute memorySpaceAttr{};
153+
/// Memory space.
154+
MemorySpaceAttrInterface memorySpace{};
155+
};
156+
} // namespace ptr
157+
} // namespace mlir
158+
159+
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h.inc"
160+
161+
#endif // MLIR_DIALECT_PTR_IR_MEMORYSPACE_H
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
//===-- MemorySpaceInterfaces.td - Memory space interfaces ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines memory space attribute interfaces.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef PTR_MEMORYSPACEINTERFACES
14+
#define PTR_MEMORYSPACEINTERFACES
15+
16+
include "mlir/IR/AttrTypeBase.td"
17+
include "mlir/IR/OpBase.td"
18+
19+
//===----------------------------------------------------------------------===//
20+
// Memory space attribute interface.
21+
//===----------------------------------------------------------------------===//
22+
23+
def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
24+
let description = [{
25+
This interface defines a common API for interacting with the memory model of
26+
a memory space and the operations in the pointer dialect, giving proper
27+
semantical meaning to the ops.
28+
29+
Furthermore, this interface allows concepts such as read-only memory to be
30+
adequately modeled and enforced.
31+
}];
32+
let cppNamespace = "::mlir::ptr";
33+
let methods = [
34+
InterfaceMethod<
35+
/*desc=*/ [{
36+
Returns the dialect implementing the memory space.
37+
}],
38+
/*returnType=*/ "::mlir::Dialect*",
39+
/*methodName=*/ "getMemorySpaceDialect",
40+
/*args=*/ (ins),
41+
/*methodBody=*/ [{}],
42+
/*defaultImpl=*/ [{ return nullptr; }]
43+
>,
44+
InterfaceMethod<
45+
/*desc=*/ [{
46+
Returns the default memory space as an attribute.
47+
}],
48+
/*returnType=*/ "::mlir::Attribute",
49+
/*methodName=*/ "getDefaultMemorySpace",
50+
/*args=*/ (ins),
51+
/*methodBody=*/ [{}],
52+
/*defaultImpl=*/ [{}]
53+
>,
54+
InterfaceMethod<
55+
/*desc=*/ [{
56+
Returns the memory space as an integer, or 0 if using the default model.
57+
}],
58+
/*returnType=*/ "unsigned",
59+
/*methodName=*/ "getAddressSpace",
60+
/*args=*/ (ins),
61+
/*methodBody=*/ [{}],
62+
/*defaultImpl=*/ [{ return 0; }]
63+
>,
64+
InterfaceMethod<
65+
/*desc=*/ [{
66+
This method checks if it's valid to load a value from the memory space
67+
with a specific type, alignment, and atomic ordering.
68+
If `diagnosticOp` is non-null then the method might emit diagnostics.
69+
}],
70+
/*returnType=*/ "::mlir::LogicalResult",
71+
/*methodName=*/ "isValidLoad",
72+
/*args=*/ (ins "::mlir::Type":$type,
73+
"::mlir::ptr::AtomicOrdering":$ordering,
74+
"::mlir::IntegerAttr":$alignment,
75+
"::mlir::Operation*":$diagnosticOp),
76+
/*methodBody=*/ [{}],
77+
/*defaultImpl=*/ [{}]
78+
>,
79+
InterfaceMethod<
80+
/*desc=*/ [{
81+
This method checks if it's valid to store a value in the memory space
82+
with a specific type, alignment, and atomic ordering.
83+
If `diagnosticOp` is non-null then the method might emit diagnostics.
84+
}],
85+
/*returnType=*/ "::mlir::LogicalResult",
86+
/*methodName=*/ "isValidStore",
87+
/*args=*/ (ins "::mlir::Type":$type,
88+
"::mlir::ptr::AtomicOrdering":$ordering,
89+
"::mlir::IntegerAttr":$alignment,
90+
"::mlir::Operation*":$diagnosticOp),
91+
/*methodBody=*/ [{}],
92+
/*defaultImpl=*/ [{}]
93+
>,
94+
InterfaceMethod<
95+
/*desc=*/ [{
96+
This method checks if it's valid to perform an atomic operation in the
97+
memory space with a specific type, alignment, and atomic ordering.
98+
If `diagnosticOp` is non-null then the method might emit diagnostics.
99+
}],
100+
/*returnType=*/ "::mlir::LogicalResult",
101+
/*methodName=*/ "isValidAtomicOp",
102+
/*args=*/ (ins "::mlir::ptr::AtomicBinOp":$op,
103+
"::mlir::Type":$type,
104+
"::mlir::ptr::AtomicOrdering":$ordering,
105+
"::mlir::IntegerAttr":$alignment,
106+
"::mlir::Operation*":$diagnosticOp),
107+
/*methodBody=*/ [{}],
108+
/*defaultImpl=*/ [{}]
109+
>,
110+
InterfaceMethod<
111+
/*desc=*/ [{
112+
This method checks if it's valid to perform an atomic exchange operation
113+
in the memory space with a specific type, alignment, and atomic
114+
orderings.
115+
If `diagnosticOp` is non-null then the method might emit diagnostics.
116+
}],
117+
/*returnType=*/ "::mlir::LogicalResult",
118+
/*methodName=*/ "isValidAtomicXchg",
119+
/*args=*/ (ins "::mlir::Type":$type,
120+
"::mlir::ptr::AtomicOrdering":$successOrdering,
121+
"::mlir::ptr::AtomicOrdering":$failureOrdering,
122+
"::mlir::IntegerAttr":$alignment,
123+
"::mlir::Operation*":$diagnosticOp),
124+
/*methodBody=*/ [{}],
125+
/*defaultImpl=*/ [{}]
126+
>,
127+
InterfaceMethod<
128+
/*desc=*/ [{
129+
This method checks if it's valid to perform an `addrspacecast` op
130+
in the memory space.
131+
Both types are expected to be vectors of rank 1, or scalars of `ptr`
132+
type.
133+
If `diagnosticOp` is non-null then the method might emit diagnostics.
134+
}],
135+
/*returnType=*/ "::mlir::LogicalResult",
136+
/*methodName=*/ "isValidAddrSpaceCast",
137+
/*args=*/ (ins "::mlir::Type":$tgt,
138+
"::mlir::Type":$src,
139+
"::mlir::Operation*":$diagnosticOp),
140+
/*methodBody=*/ [{}],
141+
/*defaultImpl=*/ [{}]
142+
>,
143+
InterfaceMethod<
144+
/*desc=*/ [{
145+
This method checks if it's valid to perform a `ptrtoint` or `inttoptr`
146+
op in the memory space. `CastValidity::InvalidSourceType` always refers
147+
to the 'ptr-like' type and `CastValidity::InvalidTargetType` always
148+
refers to the `int-like` type.
149+
The first type is expected to be integer-like, while the second must be a
150+
ptr-like type.
151+
If `diagnosticOp` is non-null then the method might emit diagnostics.
152+
}],
153+
/*returnType=*/ "::mlir::LogicalResult",
154+
/*methodName=*/ "isValidPtrIntCast",
155+
/*args=*/ (ins "::mlir::Type":$intLikeTy,
156+
"::mlir::Type":$ptrLikeTy,
157+
"::mlir::Operation*":$diagnosticOp),
158+
/*methodBody=*/ [{}],
159+
/*defaultImpl=*/ [{}]
160+
>,
161+
];
162+
}
163+
164+
def MemorySpaceOpInterface : OpInterface<"MemorySpaceOpInterface"> {
165+
let description = [{
166+
An interface for operations with a memory space.
167+
}];
168+
169+
let cppNamespace = "::mlir::ptr";
170+
171+
let methods = [
172+
InterfaceMethod<
173+
/*desc=*/ "Returns the memory space of the op.",
174+
/*returnType=*/ "::mlir::ptr::MemorySpace",
175+
/*methodName=*/ "getMemorySpace",
176+
/*args=*/ (ins),
177+
/*methodBody=*/ [{}],
178+
/*defaultImpl=*/ [{}]
179+
>,
180+
];
181+
}
182+
#endif // PTR_MEMORYSPACEINTERFACES
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===- PtrAttrs.h - Pointer dialect attributes ------------------*- C++ -*-===//
2+
//
3+
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file declares the Ptr dialect attributes.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_DIALECT_PTR_IR_PTRATTRS_H
14+
#define MLIR_DIALECT_PTR_IR_PTRATTRS_H
15+
16+
#include "mlir/IR/OpImplementation.h"
17+
18+
#include "mlir/Dialect/Ptr/IR/PtrOpsEnums.h.inc"
19+
20+
#endif // MLIR_DIALECT_PTR_IR_PTRATTRS_H

0 commit comments

Comments
 (0)