Skip to content

Commit 95f8135

Browse files
[mlir] Change vector.transfer_read/write "masked" attribute to "in_bounds".
This is in preparation for adding a new "mask" operand. The existing "masked" attribute was used to specify dimensions that may be out-of-bounds. Such transfers can be lowered to masked load/stores. The new "in_bounds" attribute is used to specify dimensions that are guaranteed to be within bounds. (Semantics is inverted.) Differential Revision: https://reviews.llvm.org/D99639
1 parent b5995fc commit 95f8135

26 files changed

+315
-302
lines changed

mlir/include/mlir/Dialect/Vector/VectorOps.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,18 @@ enum class VectorTransposeLowering {
121121
/// intrinsics.
122122
Flat = 1,
123123
};
124-
/// Enum to control the splitting of `vector.transfer` operations into masked
125-
/// and unmasked variants.
124+
/// Enum to control the splitting of `vector.transfer` operations into
125+
/// in-bounds and out-of-bounds variants.
126126
enum class VectorTransferSplit {
127127
/// Do not split vector transfer operations.
128128
None = 0,
129-
/// Split using masked + unmasked vector.transfer operations.
129+
/// Split using in-bounds + out-of-bounds vector.transfer operations.
130130
VectorTransfer = 1,
131-
/// Split using a unmasked vector.transfer + linalg.fill + linalg.copy
131+
/// Split using an in-bounds vector.transfer + linalg.fill + linalg.copy
132132
/// operations.
133133
LinalgCopy = 2,
134-
/// Do not split vector transfer operation but instead mark it as "unmasked".
135-
ForceUnmasked = 3
134+
/// Do not split vector transfer operation but instead mark it as "in-bounds".
135+
ForceInBounds = 3
136136
};
137137
/// Structure to control the behavior of vector transform patterns.
138138
struct VectorTransformsOptions {

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

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,7 @@ def Vector_TransferReadOp :
11391139
]>,
11401140
Arguments<(ins AnyShaped:$source, Variadic<Index>:$indices,
11411141
AffineMapAttr:$permutation_map, AnyType:$padding,
1142-
OptionalAttr<BoolArrayAttr>:$masked)>,
1142+
OptionalAttr<BoolArrayAttr>:$in_bounds)>,
11431143
Results<(outs AnyVector:$vector)> {
11441144

11451145
let summary = "Reads a supervector from memory into an SSA vector value.";
@@ -1166,15 +1166,14 @@ def Vector_TransferReadOp :
11661166
The size of the slice is specified by the size of the vector, given as the
11671167
return type.
11681168

1169-
An `ssa-value` of the same elemental type as the MemRef/Tensor is provided
1170-
as the last operand to specify padding in the case of out-of-bounds
1171-
accesses.
1169+
An SSA value `padding` of the same elemental type as the MemRef/Tensor is
1170+
provided to specify a fallback value in the case of out-of-bounds accesses.
11721171

11731172
An optional boolean array attribute is provided to specify which dimensions
1174-
of the transfer need masking. When a dimension is specified as not requiring
1175-
masking, the `vector.transfer_read` may be lowered to simple loads. The
1176-
absence of this `masked` attribute signifies that all dimensions of the
1177-
transfer need to be masked.
1173+
of the transfer are guaranteed to be within bounds. The absence of this
1174+
`in_bounds` attribute signifies that any dimension of the transfer may be
1175+
out-of-bounds. A `vector.transfer_read` can be lowered to a simple load if
1176+
all dimensions are specified to be within bounds.
11781177

11791178
This operation is called 'read' by opposition to 'load' because the
11801179
super-vector granularity is generally not representable with a single
@@ -1291,15 +1290,15 @@ def Vector_TransferReadOp :
12911290
// Builder that sets padding to zero.
12921291
OpBuilder<(ins "VectorType":$vector, "Value":$source,
12931292
"ValueRange":$indices, "AffineMap":$permutationMap,
1294-
CArg<"ArrayRef<bool>", "{}">:$maybeMasked)>,
1293+
CArg<"ArrayRef<bool>", "{}">:$inBounds)>,
12951294
// Builder that sets padding to 'getMinorIdentityMap'.
12961295
OpBuilder<(ins "VectorType":$vector, "Value":$source,
12971296
"ValueRange":$indices, "Value":$padding,
1298-
CArg<"ArrayRef<bool>", "{}">:$maybeMasked)>,
1297+
CArg<"ArrayRef<bool>", "{}">:$inBounds)>,
12991298
// Builder that sets permutation map (resp. padding) to
13001299
// 'getMinorIdentityMap' (resp. zero).
13011300
OpBuilder<(ins "VectorType":$vector, "Value":$source,
1302-
"ValueRange":$indices, CArg<"ArrayRef<bool>", "{}">:$maybeMasked)>
1301+
"ValueRange":$indices, CArg<"ArrayRef<bool>", "{}">:$inBounds)>,
13031302
];
13041303

13051304
let hasFolder = 1;
@@ -1314,7 +1313,7 @@ def Vector_TransferWriteOp :
13141313
Arguments<(ins AnyVector:$vector, AnyShaped:$source,
13151314
Variadic<Index>:$indices,
13161315
AffineMapAttr:$permutation_map,
1317-
OptionalAttr<BoolArrayAttr>:$masked)>,
1316+
OptionalAttr<BoolArrayAttr>:$in_bounds)>,
13181317
Results<(outs Optional<AnyRankedTensor>:$result)> {
13191318

13201319
let summary = "The vector.transfer_write op writes a supervector to memory.";
@@ -1343,10 +1342,10 @@ def Vector_TransferWriteOp :
13431342
The size of the slice is specified by the size of the vector.
13441343

13451344
An optional boolean array attribute is provided to specify which dimensions
1346-
of the transfer need masking. When a dimension is specified as not requiring
1347-
masking, the `vector.transfer_write` may be lowered to simple stores. The
1348-
absence of this `mask` attribute signifies that all dimensions of the
1349-
transfer need to be masked.
1345+
of the transfer are guaranteed to be within bounds. The absence of this
1346+
`in_bounds` attribute signifies that any dimension of the transfer may be
1347+
out-of-bounds. A `vector.transfer_write` can be lowered to a simple store
1348+
if all dimensions are specified to be within bounds.
13501349

13511350
This operation is called 'write' by opposition to 'store' because the
13521351
super-vector granularity is generally not representable with a single
@@ -1387,13 +1386,13 @@ def Vector_TransferWriteOp :
13871386
let builders = [
13881387
// Builder that sets permutation map to 'getMinorIdentityMap'.
13891388
OpBuilder<(ins "Value":$vector, "Value":$source, "ValueRange":$indices,
1390-
CArg<"ArrayRef<bool>", "{}">:$maybeMasked)>,
1389+
CArg<"ArrayRef<bool>", "{}">:$inBounds)>,
13911390
OpBuilder<(ins "Value":$vector, "Value":$source, "ValueRange":$indices,
13921391
"AffineMap":$permutationMap)>,
13931392
OpBuilder<(ins "Value":$vector, "Value":$source, "ValueRange":$indices,
1394-
"AffineMapAttr":$permutationMap, "ArrayAttr":$masked)>,
1393+
"AffineMapAttr":$permutationMap, "ArrayAttr":$inBounds)>,
13951394
OpBuilder<(ins "Value":$vector, "Value":$source, "ValueRange":$indices,
1396-
"AffineMap":$permutationMap, "ArrayAttr":$masked)>,
1395+
"AffineMap":$permutationMap, "ArrayAttr":$inBounds)>,
13971396
];
13981397

13991398
let hasFolder = 1;

mlir/include/mlir/Dialect/Vector/VectorTransforms.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ struct UnrollVectorPattern : public RewritePattern {
166166
UnrollVectorOptions options;
167167
};
168168

169-
/// Split a vector.transfer operation into an unmasked fastpath and a slowpath.
169+
/// Split a vector.transfer operation into an in-bounds (i.e., no out-of-bounds
170+
/// masking) fastpath and a slowpath.
170171
/// If `ifOp` is not null and the result is `success, the `ifOp` points to the
171172
/// newly created conditional upon function return.
172173
/// To accomodate for the fact that the original vector.transfer indexing may be
@@ -185,11 +186,11 @@ struct UnrollVectorPattern : public RewritePattern {
185186
/// memref.cast %A: memref<A...> to compatibleMemRefType
186187
/// scf.yield %view : compatibleMemRefType, index, index
187188
/// } else {
188-
/// // slowpath, masked vector.transfer or linalg.copy.
189+
/// // slowpath, not in-bounds vector.transfer or linalg.copy.
189190
/// memref.cast %alloc: memref<B...> to compatibleMemRefType
190191
/// scf.yield %4 : compatibleMemRefType, index, index
191192
// }
192-
/// %0 = vector.transfer_read %1#0[%1#1, %1#2] {masked = [false ... false]}
193+
/// %0 = vector.transfer_read %1#0[%1#1, %1#2] {in_bounds = [true ... true]}
193194
/// ```
194195
/// where `alloc` is a top of the function alloca'ed buffer of one vector.
195196
///

mlir/include/mlir/Interfaces/VectorInterfaces.td

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ def VectorTransferOpInterface : OpInterface<"VectorTransferOpInterface"> {
5353

5454
let methods = [
5555
StaticInterfaceMethod<
56-
/*desc=*/"Return the `masked` attribute name.",
56+
/*desc=*/"Return the `in_bounds` attribute name.",
5757
/*retTy=*/"StringRef",
58-
/*methodName=*/"getMaskedAttrName",
58+
/*methodName=*/"getInBoundsAttrName",
5959
/*args=*/(ins),
6060
/*methodBody=*/"",
61-
/*defaultImplementation=*/ [{ return "masked"; }]
61+
/*defaultImplementation=*/ [{ return "in_bounds"; }]
6262
>,
6363
StaticInterfaceMethod<
6464
/*desc=*/"Return the `permutation_map` attribute name.",
@@ -70,16 +70,16 @@ def VectorTransferOpInterface : OpInterface<"VectorTransferOpInterface"> {
7070
>,
7171
InterfaceMethod<
7272
/*desc=*/[{
73-
Return `false` when the `masked` attribute at dimension
74-
`dim` is set to `false`. Return `true` otherwise.}],
73+
Return `true` when the `in_bounds` attribute at dimension
74+
`dim` is set to `true`. Return `false` otherwise.}],
7575
/*retTy=*/"bool",
76-
/*methodName=*/"isMaskedDim",
76+
/*methodName=*/"isDimInBounds",
7777
/*args=*/(ins "unsigned":$dim),
7878
/*methodBody=*/"",
7979
/*defaultImplementation=*/[{
80-
return !$_op.masked() ||
81-
$_op.masked()->template cast<ArrayAttr>()[dim]
82-
.template cast<BoolAttr>().getValue();
80+
return $_op.in_bounds() &&
81+
$_op.in_bounds()->template cast<ArrayAttr>()[dim]
82+
.template cast<BoolAttr>().getValue();
8383
}]
8484
>,
8585
InterfaceMethod<
@@ -115,11 +115,11 @@ def VectorTransferOpInterface : OpInterface<"VectorTransferOpInterface"> {
115115
/*defaultImplementation=*/
116116
>,
117117
InterfaceMethod<
118-
/*desc=*/"Return the `masked` boolean ArrayAttr.",
118+
/*desc=*/"Return the `in_bounds` boolean ArrayAttr.",
119119
/*retTy=*/"Optional<ArrayAttr>",
120-
/*methodName=*/"masked",
120+
/*methodName=*/"in_bounds",
121121
/*args=*/(ins),
122-
/*methodBody=*/"return $_op.masked();"
122+
/*methodBody=*/"return $_op.in_bounds();"
123123
/*defaultImplementation=*/
124124
>,
125125
InterfaceMethod<
@@ -162,14 +162,15 @@ def VectorTransferOpInterface : OpInterface<"VectorTransferOpInterface"> {
162162
"return $_op.getShapedType().getRank() - $_op.getTransferRank();"
163163
>,
164164
InterfaceMethod<
165-
/*desc=*/[{ Returns true if at least one of the dimensions is masked.}],
165+
/*desc=*/[{ Returns true if at least one of the dimensions may be
166+
out-of-bounds.}],
166167
/*retTy=*/"bool",
167-
/*methodName=*/"hasMaskedDim",
168+
/*methodName=*/"hasOutOfBoundsDim",
168169
/*args=*/(ins),
169170
/*methodBody=*/"",
170171
/*defaultImplementation=*/[{
171172
for (unsigned idx = 0, e = $_op.getTransferRank(); idx < e; ++idx)
172-
if ($_op.isMaskedDim(idx))
173+
if (!$_op.isDimInBounds(idx))
173174
return true;
174175
return false;
175176
}]

mlir/lib/Conversion/StandardToSPIRV/LegalizeStandardForSPIRV.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void LoadOpOfSubViewFolder<vector::TransferReadOp>::replaceOp(
7979
ArrayRef<Value> sourceIndices, PatternRewriter &rewriter) const {
8080
rewriter.replaceOpWithNewOp<vector::TransferReadOp>(
8181
loadOp, loadOp.getVectorType(), subViewOp.source(), sourceIndices,
82-
loadOp.permutation_map(), loadOp.padding(), loadOp.maskedAttr());
82+
loadOp.permutation_map(), loadOp.padding(), loadOp.in_boundsAttr());
8383
}
8484

8585
template <>
@@ -92,12 +92,12 @@ void StoreOpOfSubViewFolder<memref::StoreOp>::replaceOp(
9292

9393
template <>
9494
void StoreOpOfSubViewFolder<vector::TransferWriteOp>::replaceOp(
95-
vector::TransferWriteOp tranferWriteOp, memref::SubViewOp subViewOp,
95+
vector::TransferWriteOp transferWriteOp, memref::SubViewOp subViewOp,
9696
ArrayRef<Value> sourceIndices, PatternRewriter &rewriter) const {
9797
rewriter.replaceOpWithNewOp<vector::TransferWriteOp>(
98-
tranferWriteOp, tranferWriteOp.vector(), subViewOp.source(),
99-
sourceIndices, tranferWriteOp.permutation_map(),
100-
tranferWriteOp.maskedAttr());
98+
transferWriteOp, transferWriteOp.vector(), subViewOp.source(),
99+
sourceIndices, transferWriteOp.permutation_map(),
100+
transferWriteOp.in_boundsAttr());
101101
}
102102
} // namespace
103103

mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,14 +1248,15 @@ class VectorTransferConversion : public ConvertOpToLLVMPattern<ConcreteOp> {
12481248
Value vectorDataPtr =
12491249
castDataPtr(rewriter, loc, dataPtr, memRefType, toLLVMTy(vtp));
12501250

1251-
if (!xferOp.isMaskedDim(0))
1251+
if (xferOp.isDimInBounds(0))
12521252
return replaceTransferOpWithLoadOrStore(rewriter,
12531253
*this->getTypeConverter(), loc,
12541254
xferOp, operands, vectorDataPtr);
12551255

12561256
// 2. Create a vector with linear indices [ 0 .. vector_length - 1 ].
12571257
// 3. Create offsetVector = [ offset + 0 .. offset + vector_length - 1 ].
1258-
// 4. Let dim the memref dimension, compute the vector comparison mask:
1258+
// 4. Let dim the memref dimension, compute the vector comparison mask
1259+
// (in-bounds mask):
12591260
// [ offset + 0 .. offset + vector_length - 1 ] < [ dim .. dim ]
12601261
//
12611262
// TODO: when the leaf transfer rank is k > 1, we need the last `k`

mlir/lib/Conversion/VectorToROCDL/VectorToROCDL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class VectorTransferConversion : public ConvertOpToLLVMPattern<ConcreteOp> {
7272
return failure();
7373

7474
// Have it handled in vector->llvm conversion pass.
75-
if (!xferOp.isMaskedDim(0))
75+
if (xferOp.isDimInBounds(0))
7676
return failure();
7777

7878
auto toLLVMTy = [&](Type t) {

mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ emitInBoundsCondition(PatternRewriter &rewriter,
230230
Value iv = std::get<0>(it), off = std::get<1>(it), ub = std::get<2>(it);
231231
using namespace mlir::edsc::op;
232232
majorIvsPlusOffsets.push_back(iv + off);
233-
if (xferOp.isMaskedDim(leadingRank + idx)) {
233+
if (!xferOp.isDimInBounds(leadingRank + idx)) {
234234
Value inBoundsCond = onTheFlyFoldSLT(majorIvsPlusOffsets.back(), ub);
235235
if (inBoundsCond)
236236
inBoundsCondition = (inBoundsCondition)
@@ -276,14 +276,14 @@ LogicalResult NDTransferOpHelper<TransferReadOp>::doReplace() {
276276
Value memref = xferOp.source();
277277
auto map =
278278
getTransferMinorIdentityMap(xferOp.getShapedType(), minorVectorType);
279-
ArrayAttr masked;
280-
if (!xferOp.isMaskedDim(xferOp.getVectorType().getRank() - 1)) {
279+
ArrayAttr inBounds;
280+
if (xferOp.isDimInBounds(xferOp.getVectorType().getRank() - 1)) {
281281
OpBuilder &b = ScopedContext::getBuilderRef();
282-
masked = b.getBoolArrayAttr({false});
282+
inBounds = b.getBoolArrayAttr({true});
283283
}
284284
return vector_transfer_read(minorVectorType, memref, indexing,
285285
AffineMapAttr::get(map), xferOp.padding(),
286-
masked);
286+
inBounds);
287287
};
288288

289289
// 1. Compute the inBoundsCondition in the current loops ivs + offset
@@ -382,13 +382,13 @@ LogicalResult NDTransferOpHelper<TransferWriteOp>::doReplace() {
382382
result = memref_load(alloc, majorIvs);
383383
auto map =
384384
getTransferMinorIdentityMap(xferOp.getShapedType(), minorVectorType);
385-
ArrayAttr masked;
386-
if (!xferOp.isMaskedDim(xferOp.getVectorType().getRank() - 1)) {
385+
ArrayAttr inBounds;
386+
if (xferOp.isDimInBounds(xferOp.getVectorType().getRank() - 1)) {
387387
OpBuilder &b = ScopedContext::getBuilderRef();
388-
masked = b.getBoolArrayAttr({false});
388+
inBounds = b.getBoolArrayAttr({true});
389389
}
390390
vector_transfer_write(result, xferOp.source(), indexing,
391-
AffineMapAttr::get(map), masked);
391+
AffineMapAttr::get(map), inBounds);
392392
};
393393

394394
// 1. Compute the inBoundsCondition in the current loops ivs + offset

0 commit comments

Comments
 (0)