-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[mlir][core|ptr] Add PtrLikeTypeInterface
and casting ops to the ptr
dialect
#137469
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
base: main
Are you sure you want to change the base?
Changes from all commits
fe22487
afac5f4
d9fd27e
634d03b
f090320
5b1a2ad
105bcec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,72 @@ include "mlir/Interfaces/SideEffectInterfaces.td" | |
include "mlir/Interfaces/ViewLikeInterface.td" | ||
include "mlir/IR/OpAsmInterface.td" | ||
|
||
//===----------------------------------------------------------------------===// | ||
// FromPtrOp | ||
//===----------------------------------------------------------------------===// | ||
|
||
def Ptr_FromPtrOp : Pointer_Op<"from_ptr", [ | ||
fabianmcg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Pure, OptionalTypesMatchWith<"metadata type", "result", "metadata", | ||
"PtrMetadataType::get(cast<PtrLikeTypeInterface>($_self))"> | ||
]> { | ||
let summary = "Casts a `!ptr.ptr` value to a ptr-like value."; | ||
let description = [{ | ||
The `from_ptr` operation casts a `ptr` value to a ptr-like object. It's | ||
important to note that: | ||
- The ptr-like object cannot be a `!ptr.ptr`. | ||
- The memory-space of both the `ptr` and ptr-like object must match. | ||
- The cast is Pure (no UB and side-effect free). | ||
|
||
The optional `metadata` operand exists to provide any ptr-like metadata | ||
that might be required to perform the cast. | ||
|
||
Example: | ||
|
||
```mlir | ||
%typed_ptr = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> !my.ptr<f32, #ptr.generic_space> | ||
%memref = ptr.from_ptr %ptr metadata %md : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space> | ||
|
||
// Cast the `%ptr` to a memref without utilizing metadata. | ||
%memref = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space> | ||
``` | ||
}]; | ||
|
||
let arguments = (ins Ptr_PtrType:$ptr, Optional<Ptr_PtrMetadata>:$metadata); | ||
let results = (outs PtrLikeTypeInterface:$result); | ||
let assemblyFormat = [{ | ||
$ptr (`metadata` $metadata^)? attr-dict `:` type($ptr) `->` type($result) | ||
}]; | ||
let hasFolder = 1; | ||
let hasVerifier = 1; | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// GetMetadataOp | ||
//===----------------------------------------------------------------------===// | ||
|
||
def Ptr_GetMetadataOp : Pointer_Op<"get_metadata", [ | ||
fabianmcg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Pure, TypesMatchWith<"metadata type", "ptr", "result", | ||
"PtrMetadataType::get(cast<PtrLikeTypeInterface>($_self))"> | ||
]> { | ||
let summary = "SSA value representing pointer metadata."; | ||
let description = [{ | ||
The `get_metadata` operation produces an opaque value that encodes the | ||
metadata of the ptr-like type. | ||
|
||
Example: | ||
|
||
```mlir | ||
%metadata = ptr.get_metadata %memref : memref<?x?xf32> | ||
fabianmcg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
}]; | ||
|
||
let arguments = (ins PtrLikeTypeInterface:$ptr); | ||
let results = (outs Ptr_PtrMetadata:$result); | ||
let assemblyFormat = [{ | ||
$ptr attr-dict `:` type($ptr) | ||
}]; | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// PtrAddOp | ||
//===----------------------------------------------------------------------===// | ||
|
@@ -32,8 +98,8 @@ def Ptr_PtrAddOp : Pointer_Op<"ptr_add", [ | |
Example: | ||
|
||
```mlir | ||
%x_off = ptr.ptr_add %x, %off : !ptr.ptr<0>, i32 | ||
%x_off0 = ptr.ptr_add nusw %x, %off : !ptr.ptr<0>, i32 | ||
%x_off = ptr.ptr_add %x, %off : !ptr.ptr<#ptr.generic_space>, i32 | ||
%x_off0 = ptr.ptr_add nusw %x, %off : !ptr.ptr<#ptr.generic_space>, i32 | ||
``` | ||
}]; | ||
|
||
|
@@ -52,6 +118,36 @@ def Ptr_PtrAddOp : Pointer_Op<"ptr_add", [ | |
}]; | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// ToPtrOp | ||
//===----------------------------------------------------------------------===// | ||
|
||
def Ptr_ToPtrOp : Pointer_Op<"to_ptr", [Pure]> { | ||
fabianmcg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let summary = "Casts a ptr-like value to a `!ptr.ptr` value."; | ||
let description = [{ | ||
The `to_ptr` operation casts a ptr-like object to a `!ptr.ptr`. It's | ||
important to note that: | ||
- The ptr-like object cannot be a `!ptr.ptr`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not for this PR, but I wonder why this restriction is needed. We could allow it and have the op fold away. This may fall out of type conversion during progressive lowering and will be annoying to handle. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea is that any |
||
- The memory-space of both the `ptr` and ptr-like object must match. | ||
- The cast is side-effect free. | ||
|
||
Example: | ||
|
||
```mlir | ||
%ptr0 = ptr.to_ptr %my_ptr : !my.ptr<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space> | ||
%ptr1 = ptr.to_ptr %memref : memref<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space> | ||
``` | ||
}]; | ||
|
||
let arguments = (ins PtrLikeTypeInterface:$ptr); | ||
fabianmcg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let results = (outs Ptr_PtrType:$result); | ||
let assemblyFormat = [{ | ||
$ptr attr-dict `:` type($ptr) `->` type($result) | ||
}]; | ||
let hasFolder = 1; | ||
let hasVerifier = 1; | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// TypeOffsetOp | ||
//===----------------------------------------------------------------------===// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,6 +110,59 @@ def MemRefElementTypeInterface : TypeInterface<"MemRefElementTypeInterface"> { | |
}]; | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// PtrLikeTypeInterface | ||
//===----------------------------------------------------------------------===// | ||
|
||
def PtrLikeTypeInterface : TypeInterface<"PtrLikeTypeInterface"> { | ||
let cppNamespace = "::mlir"; | ||
let description = [{ | ||
A ptr-like type represents an object storing a memory address. This object | ||
is constituted by: | ||
- A memory address called the base pointer. This pointer is treated as a | ||
bag of bits without any assumed structure. The bit-width of the base | ||
pointer must be a compile-time constant. However, the bit-width may remain | ||
opaque or unavailable during transformations that do not depend on the | ||
base pointer. Finally, it is considered indivisible in the sense that as | ||
a `PtrLikeTypeInterface` value, it has no metadata. | ||
- Optional metadata about the pointer. For example, the size of the memory | ||
region associated with the pointer. | ||
|
||
Furthermore, all ptr-like types have two properties: | ||
- The memory space associated with the address held by the pointer. | ||
- An optional element type. If the element type is not specified, the | ||
pointer is considered opaque. | ||
}]; | ||
let methods = [ | ||
InterfaceMethod<[{ | ||
Returns the memory space of this ptr-like type. | ||
}], | ||
"::mlir::Attribute", "getMemorySpace">, | ||
InterfaceMethod<[{ | ||
Returns the element type of this ptr-like type. Note: this method can | ||
return `::mlir::Type()`, in which case the pointer is considered opaque. | ||
}], | ||
"::mlir::Type", "getElementType">, | ||
InterfaceMethod<[{ | ||
Returns whether this ptr-like type has non-empty metadata. | ||
}], | ||
"bool", "hasPtrMetadata">, | ||
Comment on lines
+146
to
+149
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit for bikeshedding, not blocking for PR: are we afraid of empty metadata because that would be equivalent to having a value of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's one of the main reasons. Also, from a impl point of view it allows having the |
||
InterfaceMethod<[{ | ||
Returns a clone of this type with the given memory space and element type, | ||
or `failure` if the type cannot be cloned with the specified arguments. | ||
If the pointer is opaque and `elementType` is not `std::nullopt` the | ||
method will return `failure`. | ||
|
||
If no `elementType` is provided and ptr is not opaque, the `elementType` | ||
of this type is used. | ||
}], | ||
"::llvm::FailureOr<::mlir::PtrLikeTypeInterface>", "clonePtrWith", (ins | ||
"::mlir::Attribute":$memorySpace, | ||
"::std::optional<::mlir::Type>":$elementType | ||
)> | ||
]; | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// ShapedType | ||
//===----------------------------------------------------------------------===// | ||
|
Uh oh!
There was an error while loading. Please reload this page.