Skip to content

Commit 2585e32

Browse files
committed
[mlir][memref][vectpr] Add alignment attribute to memory access ops
1 parent 01f9dff commit 2585e32

File tree

4 files changed

+170
-6
lines changed

4 files changed

+170
-6
lines changed

mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,11 @@ def LoadOp : MemRef_Op<"load",
12171217
be reused in the cache. For details, refer to the
12181218
[https://llvm.org/docs/LangRef.html#load-instruction](LLVM load instruction).
12191219

1220+
An optional `alignment` attribute allows to specify the byte alignment of the
1221+
load operation. It must be a positive power of 2. The operation must access
1222+
memory at an address aligned to this boundary. Violations may lead to
1223+
architecture-specific faults or performance penalties.
1224+
A value of 0 indicates no specific alignment requirement.
12201225
Example:
12211226

12221227
```mlir
@@ -1227,7 +1232,39 @@ def LoadOp : MemRef_Op<"load",
12271232
let arguments = (ins Arg<AnyMemRef, "the reference to load from",
12281233
[MemRead]>:$memref,
12291234
Variadic<Index>:$indices,
1230-
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal);
1235+
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal,
1236+
ConfinedAttr<OptionalAttr<I64Attr>,
1237+
[IntMinValue<0>]>:$alignment);
1238+
1239+
let builders = [
1240+
OpBuilder<(ins "Value":$memref,
1241+
"ValueRange":$indices,
1242+
CArg<"bool", "false">:$nontemporal,
1243+
CArg<"uint64_t", "0">:$alignment), [{
1244+
return build($_builder, $_state, memref, indices, nontemporal,
1245+
alignment != 0 ? $_builder.getI64IntegerAttr(alignment) :
1246+
nullptr);
1247+
}]>,
1248+
OpBuilder<(ins "Type":$resultType,
1249+
"Value":$memref,
1250+
"ValueRange":$indices,
1251+
CArg<"bool", "false">:$nontemporal,
1252+
CArg<"uint64_t", "0">:$alignment), [{
1253+
return build($_builder, $_state, resultType, memref, indices, nontemporal,
1254+
alignment != 0 ? $_builder.getI64IntegerAttr(alignment) :
1255+
nullptr);
1256+
}]>,
1257+
OpBuilder<(ins "TypeRange":$resultTypes,
1258+
"Value":$memref,
1259+
"ValueRange":$indices,
1260+
CArg<"bool", "false">:$nontemporal,
1261+
CArg<"uint64_t", "0">:$alignment), [{
1262+
return build($_builder, $_state, resultTypes, memref, indices, nontemporal,
1263+
alignment != 0 ? $_builder.getI64IntegerAttr(alignment) :
1264+
nullptr);
1265+
}]>
1266+
];
1267+
12311268
let results = (outs AnyType:$result);
12321269

12331270
let extraClassDeclaration = [{
@@ -1913,6 +1950,11 @@ def MemRef_StoreOp : MemRef_Op<"store",
19131950
be reused in the cache. For details, refer to the
19141951
[https://llvm.org/docs/LangRef.html#store-instruction](LLVM store instruction).
19151952

1953+
An optional `alignment` attribute allows to specify the byte alignment of the
1954+
store operation. It must be a positive power of 2. The operation must access
1955+
memory at an address aligned to this boundary. Violations may lead to
1956+
architecture-specific faults or performance penalties.
1957+
A value of 0 indicates no specific alignment requirement.
19161958
Example:
19171959

19181960
```mlir
@@ -1924,13 +1966,32 @@ def MemRef_StoreOp : MemRef_Op<"store",
19241966
Arg<AnyMemRef, "the reference to store to",
19251967
[MemWrite]>:$memref,
19261968
Variadic<Index>:$indices,
1927-
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal);
1969+
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal,
1970+
ConfinedAttr<OptionalAttr<I64Attr>,
1971+
[IntMinValue<0>]>:$alignment);
19281972

19291973
let builders = [
1974+
OpBuilder<(ins "Value":$valueToStore,
1975+
"Value":$memref,
1976+
"ValueRange":$indices,
1977+
CArg<"bool", "false">:$nontemporal,
1978+
CArg<"uint64_t", "0">:$alignment), [{
1979+
return build($_builder, $_state, valueToStore, memref, indices, nontemporal,
1980+
alignment != 0 ? $_builder.getI64IntegerAttr(alignment) :
1981+
nullptr);
1982+
}]>,
1983+
// OpBuilder<(ins "Value":$valueToStore,
1984+
// "Value":$memref,
1985+
// "ValueRange":$indices,
1986+
// "uint64_t":$alignment), [{
1987+
// return build($_builder, $_state, valueToStore, memref, indices, false,
1988+
// $_builder.getI64IntegerAttr(alignment));
1989+
// }]>,
19301990
OpBuilder<(ins "Value":$valueToStore, "Value":$memref), [{
19311991
$_state.addOperands(valueToStore);
19321992
$_state.addOperands(memref);
1933-
}]>];
1993+
}]>
1994+
];
19341995

19351996
let extraClassDeclaration = [{
19361997
Value getValueToStore() { return getOperand(0); }

mlir/include/mlir/Dialect/Vector/IR/VectorOps.td

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,12 +1734,42 @@ def Vector_LoadOp : Vector_Op<"load"> {
17341734
```mlir
17351735
%result = vector.load %memref[%c0] : memref<7xf32>, vector<8xf32>
17361736
```
1737+
1738+
An optional `alignment` attribute allows to specify the byte alignment of the
1739+
load operation. It must be a positive power of 2. The operation must access
1740+
memory at an address aligned to this boundary. Violations may lead to
1741+
architecture-specific faults or performance penalties.
1742+
A value of 0 indicates no specific alignment requirement.
17371743
}];
17381744

17391745
let arguments = (ins Arg<AnyMemRef, "the reference to load from",
17401746
[MemRead]>:$base,
17411747
Variadic<Index>:$indices,
1742-
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal);
1748+
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal,
1749+
ConfinedAttr<OptionalAttr<I64Attr>,
1750+
[IntMinValue<0>]>:$alignment);
1751+
1752+
let builders = [
1753+
OpBuilder<(ins "VectorType":$resultType,
1754+
"Value":$base,
1755+
"ValueRange":$indices,
1756+
CArg<"bool", "false">:$nontemporal,
1757+
CArg<"uint64_t", "0">:$alignment), [{
1758+
return build($_builder, $_state, resultType, base, indices, nontemporal,
1759+
alignment != 0 ? $_builder.getI64IntegerAttr(alignment) :
1760+
nullptr);
1761+
}]>,
1762+
OpBuilder<(ins "TypeRange":$resultTypes,
1763+
"Value":$base,
1764+
"ValueRange":$indices,
1765+
CArg<"bool", "false">:$nontemporal,
1766+
CArg<"uint64_t", "0">:$alignment), [{
1767+
return build($_builder, $_state, resultTypes, base, indices, nontemporal,
1768+
alignment != 0 ? $_builder.getI64IntegerAttr(alignment) :
1769+
nullptr);
1770+
}]>
1771+
];
1772+
17431773
let results = (outs AnyVectorOfAnyRank:$result);
17441774

17451775
let extraClassDeclaration = [{
@@ -1818,15 +1848,34 @@ def Vector_StoreOp : Vector_Op<"store"> {
18181848
```mlir
18191849
vector.store %valueToStore, %memref[%c0] : memref<7xf32>, vector<8xf32>
18201850
```
1851+
1852+
An optional `alignment` attribute allows to specify the byte alignment of the
1853+
store operation. It must be a positive power of 2. The operation must access
1854+
memory at an address aligned to this boundary. Violations may lead to
1855+
architecture-specific faults or performance penalties.
1856+
A value of 0 indicates no specific alignment requirement.
18211857
}];
18221858

18231859
let arguments = (ins
18241860
AnyVectorOfAnyRank:$valueToStore,
18251861
Arg<AnyMemRef, "the reference to store to",
18261862
[MemWrite]>:$base,
18271863
Variadic<Index>:$indices,
1828-
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal
1829-
);
1864+
DefaultValuedOptionalAttr<BoolAttr, "false">:$nontemporal,
1865+
ConfinedAttr<OptionalAttr<I64Attr>,
1866+
[IntMinValue<0>]>:$alignment);
1867+
1868+
let builders = [
1869+
OpBuilder<(ins "Value":$valueToStore,
1870+
"Value":$base,
1871+
"ValueRange":$indices,
1872+
CArg<"bool", "false">:$nontemporal,
1873+
CArg<"uint64_t", "0">:$alignment), [{
1874+
return build($_builder, $_state, valueToStore, base, indices, nontemporal,
1875+
alignment != 0 ? $_builder.getI64IntegerAttr(alignment) :
1876+
nullptr);
1877+
}]>
1878+
];
18301879

18311880
let extraClassDeclaration = [{
18321881
MemRefType getMemRefType() {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
2+
3+
// CHECK-LABEL: func @test_load_store_alignment
4+
// CHECK: memref.load {{.*}} {alignment = 16 : i64}
5+
// CHECK: memref.store {{.*}} {alignment = 16 : i64}
6+
func.func @test_load_store_alignment(%memref: memref<4xi32>) {
7+
%c0 = arith.constant 0 : index
8+
%val = memref.load %memref[%c0] { alignment = 16 } : memref<4xi32>
9+
memref.store %val, %memref[%c0] { alignment = 16 } : memref<4xi32>
10+
return
11+
}
12+
13+
// -----
14+
15+
func.func @test_invalid_load_alignment(%memref: memref<4xi32>) {
16+
// expected-error @+1 {{custom op 'memref.load' 'memref.load' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute whose minimum value is 0}}
17+
%val = memref.load %memref[%c0] { alignment = -1 } : memref<4xi32>
18+
return
19+
}
20+
21+
// -----
22+
23+
func.func @test_invalid_store_alignment(%memref: memref<4xi32>, %val: memref<4xi32>) {
24+
// expected-error @+1 {{custom op 'memref.store' 'memref.store' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute whose minimum value is 0}}
25+
memref.store %val, %memref[%c0] { alignment = -1 } : memref<4xi32>
26+
return
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
2+
3+
// CHECK-LABEL: func @test_load_store_alignment
4+
// CHECK: vector.load {{.*}} {alignment = 16 : i64}
5+
// CHECK: vector.store {{.*}} {alignment = 16 : i64}
6+
func.func @test_load_store_alignment(%memref: memref<4xi32>) {
7+
%c0 = arith.constant 0 : index
8+
%val = vector.load %memref[%c0] { alignment = 16 } : memref<4xi32>, vector<4xi32>
9+
vector.store %val, %memref[%c0] { alignment = 16 } : memref<4xi32>, vector<4xi32>
10+
return
11+
}
12+
13+
// -----
14+
15+
func.func @test_invalid_load_alignment(%memref: memref<4xi32>) {
16+
// expected-error @+1 {{custom op 'vector.load' 'vector.load' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute whose minimum value is 0}}
17+
%val = vector.load %memref[%c0] { alignment = -1 } : memref<4xi32>, vector<4xi32>
18+
return
19+
}
20+
21+
// -----
22+
23+
func.func @test_invalid_store_alignment(%memref: memref<4xi32>, %val: vector<4xi32>) {
24+
// expected-error @+1 {{custom op 'vector.store' 'vector.store' op attribute 'alignment' failed to satisfy constraint: 64-bit signless integer attribute whose minimum value is 0}}
25+
vector.store %val, %memref[%c0] { alignment = -1 } : memref<4xi32>, vector<4xi32>
26+
return
27+
}

0 commit comments

Comments
 (0)