Skip to content

Commit e112dcc

Browse files
fabianmcgjoker-ephgysit
authored
[mlir][ptr] Add the ptradd and type_offset ops, and generic_space attr (#136434)
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.generic_space`. This memory space allows loading and storing values to all types. --------- Co-authored-by: Mehdi Amini <joker.eph@gmail.com> Co-authored-by: Tobias Gysi <tobias.gysi@nextsilicon.com>
1 parent 09147b4 commit e112dcc

File tree

10 files changed

+227
-0
lines changed

10 files changed

+227
-0
lines changed

Diff for: mlir/include/mlir/Dialect/Ptr/IR/PtrAttrDefs.td

+27
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
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"
15+
include "mlir/IR/BuiltinAttributeInterfaces.td"
1416

1517
// All of the attributes will extend this class.
1618
class Ptr_Attr<string name, string attrMnemonic,
@@ -20,6 +22,31 @@ class Ptr_Attr<string name, string attrMnemonic,
2022
let mnemonic = attrMnemonic;
2123
}
2224

25+
//===----------------------------------------------------------------------===//
26+
// GenericSpaceAttr
27+
//===----------------------------------------------------------------------===//
28+
29+
def Ptr_GenericSpaceAttr :
30+
Ptr_Attr<"GenericSpace", "generic_space", [
31+
DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
32+
]> {
33+
let summary = "Generic memory space";
34+
let description = [{
35+
The `generic_space` attribute defines a memory space attribute with the
36+
following properties:
37+
- Load and store operations are always valid, regardless of the type.
38+
- Atomic operations are always valid, regardless of the type.
39+
- Cast operations to `generic_space` are always valid.
40+
41+
Example:
42+
43+
```mlir
44+
#ptr.generic_space
45+
```
46+
}];
47+
let assemblyFormat = "";
48+
}
49+
2350
//===----------------------------------------------------------------------===//
2451
// SpecAttr
2552
//===----------------------------------------------------------------------===//

Diff for: mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h

+5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@
1313
#ifndef MLIR_DIALECT_PTR_IR_PTRATTRS_H
1414
#define MLIR_DIALECT_PTR_IR_PTRATTRS_H
1515

16+
#include "mlir/IR/BuiltinAttributeInterfaces.h"
1617
#include "mlir/IR/OpImplementation.h"
18+
#include "mlir/Interfaces/DataLayoutInterfaces.h"
19+
#include "llvm/Support/TypeSize.h"
20+
21+
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
1722

1823
#define GET_ATTRDEF_CLASSES
1924
#include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.h.inc"

Diff for: mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td

+11
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,15 @@ def AtomicOrdering : I64EnumAttr<
6666
let cppNamespace = "::mlir::ptr";
6767
}
6868

69+
//===----------------------------------------------------------------------===//
70+
// Ptr add flags enum properties.
71+
//===----------------------------------------------------------------------===//
72+
73+
def Ptr_PtrAddFlags : I32Enum<"PtrAddFlags", "Pointer add flags", [
74+
I32EnumCase<"none", 0>, I32EnumCase<"nusw", 1>, I32EnumCase<"nuw", 2>,
75+
I32EnumCase<"inbounds", 3>
76+
]> {
77+
let cppNamespace = "::mlir::ptr";
78+
}
79+
6980
#endif // PTR_ENUMS

Diff for: mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
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"
22+
#include "mlir/Interfaces/ViewLikeInterface.h"
2123

2224
#define GET_OP_CLASSES
2325
#include "mlir/Dialect/Ptr/IR/PtrOps.h.inc"

Diff for: mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td

+74
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,81 @@
1111

1212
include "mlir/Dialect/Ptr/IR/PtrDialect.td"
1313
include "mlir/Dialect/Ptr/IR/PtrAttrDefs.td"
14+
include "mlir/Dialect/Ptr/IR/PtrEnums.td"
1415
include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
16+
include "mlir/Interfaces/SideEffectInterfaces.td"
17+
include "mlir/Interfaces/ViewLikeInterface.td"
1518
include "mlir/IR/OpAsmInterface.td"
1619

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

Diff for: mlir/lib/Dialect/Ptr/IR/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ add_mlir_dialect_library(
1414
MLIRIR
1515
MLIRDataLayoutInterfaces
1616
MLIRMemorySlotInterfaces
17+
MLIRViewLikeInterface
1718
)

Diff for: 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+
// GenericSpaceAttr
24+
//===----------------------------------------------------------------------===//
25+
26+
LogicalResult GenericSpaceAttr::isValidLoad(
27+
Type type, ptr::AtomicOrdering ordering, IntegerAttr alignment,
28+
function_ref<InFlightDiagnostic()> emitError) const {
29+
return success();
30+
}
31+
32+
LogicalResult GenericSpaceAttr::isValidStore(
33+
Type type, ptr::AtomicOrdering ordering, IntegerAttr alignment,
34+
function_ref<InFlightDiagnostic()> emitError) const {
35+
return success();
36+
}
37+
38+
LogicalResult GenericSpaceAttr::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 GenericSpaceAttr::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 GenericSpaceAttr::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 GenericSpaceAttr::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
//===----------------------------------------------------------------------===//

Diff for: mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp

+27
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,31 @@ void PtrDialect::initialize() {
3941
>();
4042
}
4143

44+
//===----------------------------------------------------------------------===//
45+
// PtrAddOp
46+
//===----------------------------------------------------------------------===//
47+
48+
/// Fold: ptradd ptr + 0 -> ptr
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+
llvm::TypeSize TypeOffsetOp::getTypeSize(std::optional<DataLayout> layout) {
63+
if (layout)
64+
return layout->getTypeSize(getElementType());
65+
DataLayout dl = DataLayout::closest(*this);
66+
return dl.getTypeSize(getElementType());
67+
}
68+
4269
//===----------------------------------------------------------------------===//
4370
// Pointer API.
4471
//===----------------------------------------------------------------------===//

Diff for: mlir/test/Dialect/Ptr/canonicalize.mlir

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: mlir-opt --canonicalize %s | FileCheck %s
2+
3+
/// Check `ptr_add` canonicalizer patterns.
4+
5+
// CHECK-LABEL: @zero_offset
6+
// CHECK-SAME: (%[[PTR_0:.*]]: !ptr.ptr<#ptr.generic_space>)
7+
func.func @zero_offset(%ptr: !ptr.ptr<#ptr.generic_space>) -> !ptr.ptr<#ptr.generic_space> {
8+
// CHECK-NOT: index.constant
9+
// CHECK-NOT: ptr.ptr_add
10+
// CHECK: return %[[PTR_0]] : !ptr.ptr<#ptr.generic_space>
11+
// CHECK: }
12+
%off = index.constant 0
13+
%res0 = ptr.ptr_add %ptr, %off : !ptr.ptr<#ptr.generic_space>, index
14+
return %res0 : !ptr.ptr<#ptr.generic_space>
15+
}

Diff for: mlir/test/Dialect/Ptr/ops.mlir

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: mlir-opt %s --verify-roundtrip | FileCheck %s
2+
3+
/// Check op assembly.
4+
// CHECK-LABEL: @ptr_add_type_offset
5+
func.func @ptr_add_type_offset(%ptr: !ptr.ptr<#ptr.generic_space>) -> !ptr.ptr<#ptr.generic_space> {
6+
// CHECK: ptr.type_offset f32 : index
7+
// CHECK-NEXT: ptr.ptr_add %{{.*}}, %{{.*}} : <#ptr.generic_space>, index
8+
// CHECK-NEXT: ptr.ptr_add %{{.*}}, %{{.*}} : <#ptr.generic_space>, index
9+
// CHECK-NEXT: ptr.ptr_add nusw %{{.*}}, %{{.*}} : <#ptr.generic_space>, index
10+
// CHECK-NEXT: ptr.ptr_add nuw %{{.*}}, %{{.*}} : <#ptr.generic_space>, index
11+
// CHECK-NEXT: ptr.ptr_add inbounds %{{.*}}, %{{.*}} : <#ptr.generic_space>, index
12+
%off = ptr.type_offset f32 : index
13+
%res = ptr.ptr_add %ptr, %off : !ptr.ptr<#ptr.generic_space>, index
14+
%res0 = ptr.ptr_add none %ptr, %off : !ptr.ptr<#ptr.generic_space>, index
15+
%res1 = ptr.ptr_add nusw %ptr, %off : !ptr.ptr<#ptr.generic_space>, index
16+
%res2 = ptr.ptr_add nuw %ptr, %off : !ptr.ptr<#ptr.generic_space>, index
17+
%res3 = ptr.ptr_add inbounds %ptr, %off : !ptr.ptr<#ptr.generic_space>, index
18+
return %res : !ptr.ptr<#ptr.generic_space>
19+
}

0 commit comments

Comments
 (0)