Skip to content

Commit 2f54230

Browse files
committed
[mlir][ptr] Add the ptradd and type_offset ops, and int_space attr
This patch adds the `ptr.ptradd` and `ptr.type_offset` operations. Given a `ptr` value these operations can be used to compute new addresses. For example: ```mlir func.func @OPS0(%ptr: !ptr.ptr<#ptr.int_space>) -> !ptr.ptr<#ptr.int_space> { %off = ptr.type_offset f32 : index %res = ptr.ptradd %ptr, %off : !ptr.ptr<#ptr.int_space>, index return %res : !ptr.ptr<#ptr.int_space> } ``` Additionally, this patch also adds the `#ptr.int_space`, a memory space that is identified by a integer. This memory space allows loading and storing values to all types.
1 parent f91df0d commit 2f54230

File tree

8 files changed

+218
-0
lines changed

8 files changed

+218
-0
lines changed

mlir/include/mlir/Dialect/Ptr/IR/PtrAttrDefs.td

+33
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define PTR_ATTRDEFS
1111

1212
include "mlir/Dialect/Ptr/IR/PtrDialect.td"
13+
include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
1314
include "mlir/IR/AttrTypeBase.td"
1415

1516
// All of the attributes will extend this class.
@@ -20,6 +21,38 @@ class Ptr_Attr<string name, string attrMnemonic,
2021
let mnemonic = attrMnemonic;
2122
}
2223

24+
//===----------------------------------------------------------------------===//
25+
// IAddressSpaceAttr
26+
//===----------------------------------------------------------------------===//
27+
28+
def Ptr_IAddressSpaceAttr :
29+
Ptr_Attr<"IAddressSpace", "int_space", [
30+
DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
31+
]> {
32+
let summary = "Int memory space";
33+
let description = [{
34+
The `int_as` attribute defines a memory space attribute with the following
35+
properties:
36+
- Load and store operations are always valid, regardless of the type.
37+
- Atomic operations are always valid, regardless of the type.
38+
- Cast operations are valid between pointers with `int_space` memory space,
39+
or between non-scalable `vector` of pointers with `int_space` memory space.
40+
41+
The default address spaces is 0.
42+
43+
Example:
44+
45+
```mlir
46+
// Default address space: 0.
47+
#ptr.int_space
48+
// Address space 3.
49+
#ptr.int_space<3>
50+
```
51+
}];
52+
let parameters = (ins DefaultValuedParameter<"int64_t", "0">:$value);
53+
let assemblyFormat = "(`<` $value^ `>`)?";
54+
}
55+
2356
//===----------------------------------------------------------------------===//
2457
// SpecAttr
2558
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "mlir/IR/OpImplementation.h"
1717

18+
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
19+
1820
#define GET_ATTRDEF_CLASSES
1921
#include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.h.inc"
2022

mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "mlir/Dialect/Ptr/IR/PtrDialect.h"
1919
#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
2020
#include "mlir/IR/OpDefinition.h"
21+
#include "mlir/Interfaces/SideEffectInterfaces.h"
2122

2223
#define GET_OP_CLASSES
2324
#include "mlir/Dialect/Ptr/IR/PtrOps.h.inc"

mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td

+63
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,69 @@
1212
include "mlir/Dialect/Ptr/IR/PtrDialect.td"
1313
include "mlir/Dialect/Ptr/IR/PtrAttrDefs.td"
1414
include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
15+
include "mlir/Interfaces/SideEffectInterfaces.td"
1516
include "mlir/IR/OpAsmInterface.td"
1617

18+
//===----------------------------------------------------------------------===//
19+
// PtrAddOp
20+
//===----------------------------------------------------------------------===//
21+
22+
def Ptr_PtrAddOp : Pointer_Op<"ptradd", [
23+
Pure, AllTypesMatch<["base", "result"]>
24+
]> {
25+
let summary = "Pointer add operation";
26+
let description = [{
27+
The `ptradd` operation adds an integer offset to a pointer to produce a new
28+
pointer. The input and output pointer types are always the same.
29+
30+
Example:
31+
32+
```mlir
33+
%x_off = ptr.ptradd %x, %off : !ptr.ptr<0>, i32
34+
```
35+
}];
36+
37+
let arguments = (ins Ptr_PtrType:$base, AnySignlessIntegerOrIndex:$offset);
38+
let results = (outs Ptr_PtrType:$result);
39+
let assemblyFormat = [{
40+
$base `,` $offset attr-dict `:` type($base) `,` type($offset)
41+
}];
42+
let hasFolder = 1;
43+
}
44+
45+
//===----------------------------------------------------------------------===//
46+
// TypeOffsetOp
47+
//===----------------------------------------------------------------------===//
48+
49+
def Ptr_TypeOffsetOp : Pointer_Op<"type_offset", [ConstantLike, Pure]> {
50+
let summary = "Type offset operation";
51+
let description = [{
52+
The `type_offset` operation produces an int or index-typed SSA value
53+
equal to a target-specific constant representing the offset of a single
54+
element of the given type.
55+
56+
Example:
57+
58+
```mlir
59+
%0 = ptr.type_offset f32 : index
60+
%1 = ptr.type_offset memref<12 x f64> : i32
61+
```
62+
}];
63+
64+
let arguments = (ins TypeAttr:$element_type);
65+
let results = (outs AnySignlessIntegerOrIndex:$result);
66+
let builders = [
67+
OpBuilder<(ins "TypeAttr":$element_type)>
68+
];
69+
let assemblyFormat = [{
70+
$element_type attr-dict `:` type($result)
71+
}];
72+
let extraClassDeclaration = [{
73+
/// Returns the type offset according to `maybeLayout`. If `maybeLayout` is
74+
/// `nullopt` the nearest layout the op will be used for the computation.
75+
llvm::TypeSize getTypeSize(std::optional<DataLayout> layout = std::nullopt);
76+
}];
77+
let hasFolder = 1;
78+
}
79+
1780
#endif // PTR_OPS

mlir/lib/Dialect/Ptr/IR/PtrAttrs.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,59 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "mlir/Dialect/Ptr/IR/PtrAttrs.h"
14+
#include "mlir/IR/BuiltinTypes.h"
1415
#include "llvm/ADT/TypeSwitch.h"
1516

1617
using namespace mlir;
1718
using namespace mlir::ptr;
1819

1920
constexpr const static unsigned kBitsInByte = 8;
2021

22+
//===----------------------------------------------------------------------===//
23+
// IAddressSpaceAttr
24+
//===----------------------------------------------------------------------===//
25+
26+
LogicalResult IAddressSpaceAttr::isValidLoad(
27+
Type type, ptr::AtomicOrdering ordering, IntegerAttr alignment,
28+
function_ref<InFlightDiagnostic()> emitError) const {
29+
return success();
30+
}
31+
32+
LogicalResult IAddressSpaceAttr::isValidStore(
33+
Type type, ptr::AtomicOrdering ordering, IntegerAttr alignment,
34+
function_ref<InFlightDiagnostic()> emitError) const {
35+
return success();
36+
}
37+
38+
LogicalResult IAddressSpaceAttr::isValidAtomicOp(
39+
ptr::AtomicBinOp op, Type type, ptr::AtomicOrdering ordering,
40+
IntegerAttr alignment, function_ref<InFlightDiagnostic()> emitError) const {
41+
return success();
42+
}
43+
44+
LogicalResult IAddressSpaceAttr::isValidAtomicXchg(
45+
Type type, ptr::AtomicOrdering successOrdering,
46+
ptr::AtomicOrdering failureOrdering, IntegerAttr alignment,
47+
function_ref<InFlightDiagnostic()> emitError) const {
48+
return success();
49+
}
50+
51+
LogicalResult IAddressSpaceAttr::isValidAddrSpaceCast(
52+
Type tgt, Type src, function_ref<InFlightDiagnostic()> emitError) const {
53+
// TODO: update this method once the `addrspace_cast` op is added to the
54+
// dialect.
55+
assert(false && "unimplemented, see TODO in the source.");
56+
return failure();
57+
}
58+
59+
LogicalResult IAddressSpaceAttr::isValidPtrIntCast(
60+
Type intLikeTy, Type ptrLikeTy,
61+
function_ref<InFlightDiagnostic()> emitError) const {
62+
// TODO: update this method once the int-cast ops are added to the dialect.
63+
assert(false && "unimplemented, see TODO in the source.");
64+
return failure();
65+
}
66+
2167
//===----------------------------------------------------------------------===//
2268
// SpecAttr
2369
//===----------------------------------------------------------------------===//

mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
#include "mlir/Dialect/Ptr/IR/PtrOps.h"
1414
#include "mlir/IR/DialectImplementation.h"
15+
#include "mlir/IR/Matchers.h"
1516
#include "mlir/IR/PatternMatch.h"
17+
#include "mlir/Interfaces/DataLayoutInterfaces.h"
1618
#include "mlir/Transforms/InliningUtils.h"
1719
#include "llvm/ADT/SmallString.h"
1820
#include "llvm/ADT/TypeSwitch.h"
@@ -39,6 +41,35 @@ void PtrDialect::initialize() {
3941
>();
4042
}
4143

44+
//===----------------------------------------------------------------------===//
45+
// PtrAddOp
46+
//===----------------------------------------------------------------------===//
47+
48+
/// Fold the op to the base ptr when the offset is 0.
49+
OpFoldResult PtrAddOp::fold(FoldAdaptor adaptor) {
50+
Attribute attr = adaptor.getOffset();
51+
if (!attr)
52+
return nullptr;
53+
if (llvm::APInt value; m_ConstantInt(&value).match(attr) && value.isZero())
54+
return getBase();
55+
return nullptr;
56+
}
57+
58+
//===----------------------------------------------------------------------===//
59+
// TypeOffsetOp
60+
//===----------------------------------------------------------------------===//
61+
62+
OpFoldResult TypeOffsetOp::fold(FoldAdaptor adaptor) {
63+
return TypeAttr::get(getElementType());
64+
}
65+
66+
llvm::TypeSize TypeOffsetOp::getTypeSize(std::optional<DataLayout> layout) {
67+
if (layout)
68+
return layout->getTypeSize(getElementType());
69+
DataLayout dl = DataLayout::closest(*this);
70+
return dl.getTypeSize(getElementType());
71+
}
72+
4273
//===----------------------------------------------------------------------===//
4374
// Pointer API.
4475
//===----------------------------------------------------------------------===//
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: mlir-opt --canonicalize %s | FileCheck %s
2+
3+
/// Check `ptradd` and `type_offset` canonicalizer patterns.
4+
5+
// CHECK-LABEL: @ops0
6+
func.func @ops0(%ptr: !ptr.ptr<#ptr.int_space<3>>, %c: i1) -> !ptr.ptr<#ptr.int_space<3>> {
7+
// CHECK: (%[[PTR_0:.*]]: !ptr.ptr<#ptr.int_space<3>>,
8+
// CHECK: %[[F32_OFF:.*]] = ptr.type_offset f32 : index
9+
// CHECK: %[[PTR_1:.*]] = ptr.ptradd %[[PTR_0]], %[[F32_OFF]] : <#ptr.int_space<3>>, index
10+
// CHECK: %[[PTR_2:.*]] = ptr.ptradd %[[PTR_1]], %[[F32_OFF]] : <#ptr.int_space<3>>, index
11+
// CHECK: %[[PTR_3:.*]] = scf.if %{{.*}} -> (!ptr.ptr<#ptr.int_space<3>>) {
12+
// CHECK: %[[PTR_4:.*]] = ptr.ptradd %[[PTR_2]], %[[F32_OFF]] : <#ptr.int_space<3>>, index
13+
// CHECK: scf.yield %[[PTR_4]] : !ptr.ptr<#ptr.int_space<3>>
14+
// CHECK: } else {
15+
// CHECK: scf.yield %[[PTR_0]] : !ptr.ptr<#ptr.int_space<3>>
16+
// CHECK: }
17+
// CHECK: return %[[PTR_3]] : !ptr.ptr<#ptr.int_space<3>>
18+
// CHECK: }
19+
%off0 = ptr.type_offset f32 : index
20+
%res0 = ptr.ptradd %ptr, %off0 : !ptr.ptr<#ptr.int_space<3>>, index
21+
%off1 = ptr.type_offset f32 : index
22+
%res1 = ptr.ptradd %res0, %off1 : !ptr.ptr<#ptr.int_space<3>>, index
23+
%res = scf.if %c -> !ptr.ptr<#ptr.int_space<3>> {
24+
%off2 = ptr.type_offset f32 : index
25+
%res2 = ptr.ptradd %res1, %off2 : !ptr.ptr<#ptr.int_space<3>>, index
26+
scf.yield %res2 : !ptr.ptr<#ptr.int_space<3>>
27+
} else {
28+
scf.yield %ptr : !ptr.ptr<#ptr.int_space<3>>
29+
}
30+
return %res : !ptr.ptr<#ptr.int_space<3>>
31+
}

mlir/test/Dialect/Ptr/ops.mlir

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: mlir-opt %s | FileCheck %s
2+
3+
/// Check op assembly.
4+
func.func @ops0(%ptr: !ptr.ptr<#ptr.int_space>) -> !ptr.ptr<#ptr.int_space> {
5+
// CHECK-LABEL: @ops0
6+
// CHECK: ptr.type_offset f32 : index
7+
// CHECK-NEXT: ptr.ptradd %{{.*}}, %{{.*}} : <#ptr.int_space>, index
8+
%off = ptr.type_offset f32 : index
9+
%res = ptr.ptradd %ptr, %off : !ptr.ptr<#ptr.int_space>, index
10+
return %res : !ptr.ptr<#ptr.int_space>
11+
}

0 commit comments

Comments
 (0)