Skip to content

Commit fab6386

Browse files
committed
[mlir][vector] Make the in_bounds attribute mandatory
At the moment, the in_bounds attribute has two confusing/contradicting properties: 1. It is both optional _and_ has an effective default-value. 2. The default value is "out-of-bounds" for non-broadcast dims, and "in-bounds" for broadcast dims. (see the `isDimInBounds` vector interface method for an example of this "default" behaviour [1]). This PR aims to clarify the logic surrounding the `in_bounds` attribute by: * making the attribute it mandatory (i.e. it is always present), * always setting the default value to "out of bounds" (that's consistent with the current behaviour for the most common cases). 1. Broadcast dimensions in tests As per [2], the broadcast dimensions requires the corresponding `in_bounds` attribute to be `true`: ``` vector.transfer_read op requires broadcast dimensions to be in-bounds ``` The changes in this PR mean that we can no longer rely on the default value in cases like the following (dim 0 is a broadcast dim): ```mlir %read = vector.transfer_read %A[%base1, %base2], %f, %mask {permutation_map = affine_map<(d0, d1) -> (0, d1)>} : memref<?x?xf32>, vector<4x9xf32> ``` Instead, the broadcast dimension has to explicitly be marked as "in bounds: ```mlir %read = vector.transfer_read %A[%base1, %base2], %f, %mask {in_bounds = [true, false], permutation_map = affine_map<(d0, d1) -> (0, d1)>} : memref<?x?xf32>, vector<4x9xf32> ``` All tests with broadcast dims are updated accordingly. 2. Changes in "SuperVectorize.cpp" and "Vectorization.cpp" The following patterns in "Vectorization.cpp" are updated to explicitly set the `in_bounds` attribute to `false`: * `LinalgCopyVTRForwardingPattern` and `LinalgCopyVTWForwardingPattern` Also, `vectorizeAffineLoad` (from "SuperVectorize.cpp") and `vectorizeAsLinalgGeneric` (from "Vectorization.cpp") are updated to make sure that xfer Ops created by these hooks set the dimension corresponding to broadcast dims as "in bounds". Otherwise, the Op verifier would complain Note that there is no mechanism to verify whether the corresponding memory access are indeed in bounds. Still, this is consistent with the current behaviour where the broadcast dim would be implicitly assumed to be "in bounds". [1] https://github.com/llvm/llvm-project/blob/4145ad2bac4bb99d5034d60c74bb2789f6c6e802/mlir/include/mlir/Interfaces/VectorInterfaces.td#L243-L246 [2] https://mlir.llvm.org/docs/Dialects/Vector/#vectortransfer_read-vectortransferreadop
1 parent e29022d commit fab6386

File tree

101 files changed

+653
-649
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+653
-649
lines changed

mlir/include/mlir/IR/AffineMap.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,12 @@ class AffineMap {
155155
bool isMinorIdentityWithBroadcasting(
156156
SmallVectorImpl<unsigned> *broadcastedDims = nullptr) const;
157157

158-
// TODO: Document
159-
void
160-
getBroadcastDims(SmallVectorImpl<unsigned> *broadcastedDims = nullptr) const;
158+
/// Returns the list of broadcast dimensions.
159+
/// Ex:
160+
/// * (d0, d1, d2) -> (0, d1) gives [0]
161+
/// * (d0, d1, d2) -> (d2, d1) gives []
162+
/// * (d0, d1, d2, d4) -> (d0, 0, d1, 0) gives [1, 3]
163+
SmallVector<unsigned> getBroadcastDims() const;
161164

162165
/// Return true if this affine map can be converted to a minor identity with
163166
/// broadcast by doing a permute. Return a permutation (there may be

mlir/include/mlir/Interfaces/VectorInterfaces.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,6 @@ def VectorTransferOpInterface : OpInterface<"VectorTransferOpInterface"> {
240240
bool isDimInBounds(unsigned dim) {
241241
if ($_op.isBroadcastDim(dim))
242242
return true;
243-
if (!$_op.getInBounds())
244-
return false;
245243
auto inBounds = $_op.getInBounds();
246244
return ::llvm::cast<::mlir::BoolAttr>(inBounds[dim]).getValue();
247245
}

mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,8 +1227,7 @@ static Operation *vectorizeAffineLoad(AffineLoadOp loadOp,
12271227
// is set to `true` - that's required by the xfer Op.
12281228
// FIXME: We're not veryfying whether the corresponding access is in bounds.
12291229
// TODO: Use masking instead.
1230-
SmallVector<unsigned> broadcastedDims = {};
1231-
permutationMap.getBroadcastDims(&broadcastedDims);
1230+
SmallVector<unsigned> broadcastedDims = permutationMap.getBroadcastDims();
12321231
SmallVector<bool> inBounds(vectorType.getRank(), false);
12331232

12341233
for (auto idx : broadcastedDims)

mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,8 +1345,7 @@ vectorizeAsLinalgGeneric(RewriterBase &rewriter, VectorizationState &state,
13451345

13461346
// Make sure that the in_bounds attribute corresponding to a broadcast dim
13471347
// is `true`
1348-
SmallVector<unsigned> broadcastedDims = {};
1349-
readMap.getBroadcastDims(&broadcastedDims);
1348+
SmallVector<unsigned> broadcastedDims = readMap.getBroadcastDims();
13501349
SmallVector<bool> inBounds(readType.getRank(), false);
13511350

13521351
for (auto idx : broadcastedDims)

mlir/lib/Dialect/Vector/IR/VectorOps.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3971,6 +3971,9 @@ static void printTransferAttrs(OpAsmPrinter &p, VectorTransferOpInterface op) {
39713971
elidedAttrs.push_back(TransferReadOp::getOperandSegmentSizeAttr());
39723972
if (op.getPermutationMap().isMinorIdentity())
39733973
elidedAttrs.push_back(op.getPermutationMapAttrName());
3974+
// Elide in_bounds attribute if all dims are out-of-bounds.
3975+
if (llvm::none_of(op.getInBoundsValues(), [](bool b) { return b; }))
3976+
elidedAttrs.push_back(op.getInBoundsAttrName());
39743977
p.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
39753978
}
39763979

@@ -4034,6 +4037,13 @@ ParseResult TransferReadOp::parse(OpAsmParser &parser, OperationState &result) {
40344037
} else {
40354038
permMap = llvm::cast<AffineMapAttr>(permMapAttr).getValue();
40364039
}
4040+
auto inBoundsAttrName = TransferReadOp::getInBoundsAttrName(result.name);
4041+
Attribute inBoundsAttr = result.attributes.get(inBoundsAttrName);
4042+
if (!inBoundsAttr) {
4043+
result.addAttribute(inBoundsAttrName,
4044+
builder.getBoolArrayAttr(
4045+
SmallVector<bool>(permMap.getNumResults(), false)));
4046+
}
40374047
if (parser.resolveOperand(sourceInfo, shapedType, result.operands) ||
40384048
parser.resolveOperands(indexInfo, indexType, result.operands) ||
40394049
parser.resolveOperand(paddingInfo, shapedType.getElementType(),
@@ -4408,6 +4418,13 @@ ParseResult TransferWriteOp::parse(OpAsmParser &parser,
44084418
} else {
44094419
permMap = llvm::cast<AffineMapAttr>(permMapAttr).getValue();
44104420
}
4421+
auto inBoundsAttrName = TransferWriteOp::getInBoundsAttrName(result.name);
4422+
Attribute inBoundsAttr = result.attributes.get(inBoundsAttrName);
4423+
if (!inBoundsAttr) {
4424+
result.addAttribute(inBoundsAttrName,
4425+
builder.getBoolArrayAttr(
4426+
SmallVector<bool>(permMap.getNumResults(), false)));
4427+
}
44114428
if (parser.resolveOperand(vectorInfo, vectorType, result.operands) ||
44124429
parser.resolveOperand(sourceInfo, shapedType, result.operands) ||
44134430
parser.resolveOperands(indexInfo, indexType, result.operands))

mlir/lib/IR/AffineMap.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,21 +187,20 @@ bool AffineMap::isMinorIdentityWithBroadcasting(
187187
return true;
188188
}
189189

190-
void AffineMap::getBroadcastDims(
191-
SmallVectorImpl<unsigned> *broadcastedDims) const {
192-
if (broadcastedDims)
193-
broadcastedDims->clear();
190+
SmallVector<unsigned> AffineMap::getBroadcastDims() const {
191+
SmallVector<unsigned> broadcastedDims = {};
194192
for (const auto &idxAndExpr : llvm::enumerate(getResults())) {
195193
unsigned resIdx = idxAndExpr.index();
196194
AffineExpr expr = idxAndExpr.value();
197195
if (auto constExpr = dyn_cast<AffineConstantExpr>(expr)) {
198196
// Each result may be either a constant 0 (broadcasted dimension).
199197
if (constExpr.getValue() != 0)
200198
continue;
201-
if (broadcastedDims)
202-
broadcastedDims->push_back(resIdx);
199+
broadcastedDims.push_back(resIdx);
203200
}
204201
}
202+
203+
return broadcastedDims;
205204
}
206205

207206
/// Return true if this affine map can be converted to a minor identity with

mlir/test/Conversion/VectorToLLVM/vector-mask-to-llvm.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,6 @@ func.func @genbool_var_1d_scalable(%arg0: index) -> vector<[11]xi1> {
7373

7474
func.func @transfer_read_1d(%A : memref<?xf32>, %i: index) -> vector<16xf32> {
7575
%d = arith.constant -1.0: f32
76-
%f = vector.transfer_read %A[%i], %d {in_bounds = [false], permutation_map = affine_map<(d0) -> (d0)>} : memref<?xf32>, vector<16xf32>
76+
%f = vector.transfer_read %A[%i], %d {permutation_map = affine_map<(d0) -> (d0)>} : memref<?xf32>, vector<16xf32>
7777
return %f : vector<16xf32>
7878
}

mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,10 +1689,10 @@ func.func @matrix_ops_index(%A: vector<64xindex>, %B: vector<48xindex>) -> vecto
16891689
func.func @transfer_read_1d(%A : memref<?xf32>, %base: index) -> vector<17xf32> {
16901690
%f7 = arith.constant 7.0: f32
16911691
%f = vector.transfer_read %A[%base], %f7
1692-
{in_bounds = [false], permutation_map = affine_map<(d0) -> (d0)>} :
1692+
{permutation_map = affine_map<(d0) -> (d0)>} :
16931693
memref<?xf32>, vector<17xf32>
16941694
vector.transfer_write %f, %A[%base]
1695-
{in_bounds = [false], permutation_map = affine_map<(d0) -> (d0)>} :
1695+
{permutation_map = affine_map<(d0) -> (d0)>} :
16961696
vector<17xf32>, memref<?xf32>
16971697
return %f: vector<17xf32>
16981698
}
@@ -1763,10 +1763,10 @@ func.func @transfer_read_1d(%A : memref<?xf32>, %base: index) -> vector<17xf32>
17631763
func.func @transfer_read_index_1d(%A : memref<?xindex>, %base: index) -> vector<17xindex> {
17641764
%f7 = arith.constant 7: index
17651765
%f = vector.transfer_read %A[%base], %f7
1766-
{in_bounds = [false], permutation_map = affine_map<(d0) -> (d0)>} :
1766+
{permutation_map = affine_map<(d0) -> (d0)>} :
17671767
memref<?xindex>, vector<17xindex>
17681768
vector.transfer_write %f, %A[%base]
1769-
{in_bounds = [false], permutation_map = affine_map<(d0) -> (d0)>} :
1769+
{permutation_map = affine_map<(d0) -> (d0)>} :
17701770
vector<17xindex>, memref<?xindex>
17711771
return %f: vector<17xindex>
17721772
}
@@ -1786,7 +1786,7 @@ func.func @transfer_read_index_1d(%A : memref<?xindex>, %base: index) -> vector<
17861786
func.func @transfer_read_2d_to_1d(%A : memref<?x?xf32>, %base0: index, %base1: index) -> vector<17xf32> {
17871787
%f7 = arith.constant 7.0: f32
17881788
%f = vector.transfer_read %A[%base0, %base1], %f7
1789-
{in_bounds = [false], permutation_map = affine_map<(d0, d1) -> (d1)>} :
1789+
{permutation_map = affine_map<(d0, d1) -> (d1)>} :
17901790
memref<?x?xf32>, vector<17xf32>
17911791
return %f: vector<17xf32>
17921792
}
@@ -1815,10 +1815,10 @@ func.func @transfer_read_2d_to_1d(%A : memref<?x?xf32>, %base0: index, %base1: i
18151815
func.func @transfer_read_1d_non_zero_addrspace(%A : memref<?xf32, 3>, %base: index) -> vector<17xf32> {
18161816
%f7 = arith.constant 7.0: f32
18171817
%f = vector.transfer_read %A[%base], %f7
1818-
{in_bounds = [false], permutation_map = affine_map<(d0) -> (d0)>} :
1818+
{permutation_map = affine_map<(d0) -> (d0)>} :
18191819
memref<?xf32, 3>, vector<17xf32>
18201820
vector.transfer_write %f, %A[%base]
1821-
{in_bounds = [false], permutation_map = affine_map<(d0) -> (d0)>} :
1821+
{permutation_map = affine_map<(d0) -> (d0)>} :
18221822
vector<17xf32>, memref<?xf32, 3>
18231823
return %f: vector<17xf32>
18241824
}
@@ -1866,7 +1866,7 @@ func.func @transfer_read_1d_inbounds(%A : memref<?xf32>, %base: index) -> vector
18661866
func.func @transfer_read_1d_mask(%A : memref<?xf32>, %base : index) -> vector<5xf32> {
18671867
%m = arith.constant dense<[0, 0, 1, 0, 1]> : vector<5xi1>
18681868
%f7 = arith.constant 7.0: f32
1869-
%f = vector.transfer_read %A[%base], %f7, %m {in_bounds=[false]} : memref<?xf32>, vector<5xf32>
1869+
%f = vector.transfer_read %A[%base], %f7, %m : memref<?xf32>, vector<5xf32>
18701870
return %f: vector<5xf32>
18711871
}
18721872

mlir/test/Conversion/VectorToSCF/unrolled-vector-to-loops.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func.func @transfer_read_out_of_bounds(%A : memref<?x?x?xf32>) -> (vector<2x3x4x
5151
// CHECK: vector.transfer_read {{.*}} : memref<?x?x?xf32>, vector<4xf32>
5252
// CHECK: vector.insert {{.*}} [1, 2] : vector<4xf32> into vector<2x3x4xf32>
5353
// CHECK-NOT: scf.for
54-
%vec = vector.transfer_read %A[%c0, %c0, %c0], %f0 {in_bounds=[false, false, false]} : memref<?x?x?xf32>, vector<2x3x4xf32>
54+
%vec = vector.transfer_read %A[%c0, %c0, %c0], %f0 : memref<?x?x?xf32>, vector<2x3x4xf32>
5555
return %vec : vector<2x3x4xf32>
5656
}
5757

mlir/test/Conversion/VectorToSCF/vector-to-scf-mask-and-permutation-map.mlir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// CHECK: scf.for {{.*}} {
1313
// CHECK: scf.if {{.*}} {
1414
// CHECK: %[[MASK_LOADED:.*]] = memref.load %[[MASK_CASTED]][%{{.*}}] : memref<4xvector<9xi1>>
15-
// CHECK: %[[READ:.*]] = vector.transfer_read %{{.*}}, %{{.*}}, %[[MASK_LOADED]] {in_bounds = [false]} : memref<?x?xf32>, vector<9xf32>
15+
// CHECK: %[[READ:.*]] = vector.transfer_read %{{.*}}, %{{.*}}, %[[MASK_LOADED]] : memref<?x?xf32>, vector<9xf32>
1616
// CHECK: memref.store %[[READ]], %{{.*}} : memref<4xvector<9xf32>>
1717
// CHECK: }
1818
// CHECK: }
@@ -29,7 +29,7 @@ func.func @transfer_read_2d_mask_transposed(
2929
[1, 1, 1, 1, 1, 1, 1, 0, 1],
3030
[0, 0, 1, 0, 1, 1, 1, 0, 1]]> : vector<4x9xi1>
3131
%f = vector.transfer_read %A[%base1, %base2], %fm42, %mask
32-
{permutation_map = affine_map<(d0, d1) -> (d1, d0)>, in_bounds = [false, false]} :
32+
{permutation_map = affine_map<(d0, d1) -> (d1, d0)>} :
3333
memref<?x?xf32>, vector<9x4xf32>
3434
return %f : vector<9x4xf32>
3535
}

0 commit comments

Comments
 (0)