The in_bounds attribute specifies which dimensions of a vector transfer are in-bounds and which are out-of-bounds. Until now, it was expressed in terms of transfer dimensions. This was confusing because "in-bounds" is a property of shaped value indexing.
With this change, in_bounds is expressed in terms of shaped value ("source") dimensions. I.e.:
- The number of in_bounds bools must match the rank of the shaped value (and not the rank of the vector).
- Special rules around broadcast dimensions are no longer needed. (Previously, broadcast dimensions had to be "in-bounds".)
This change is in preparation of allowing the starting offsets to be out-of-bounds (in a future change). This rule is *not* changed yet with this revision: starting points must be in-bounds and that is verified for non-transfer dimensions. (It cannot be verified statically for transfer dimensions of size >1.)
The following examples illustrate how transfer ops are changing.
Example 1:
// previously: %0 = vector.transfer_read %m[%i, %j], %cst {in_bounds = [true, false], permutation_map = affine_map<(d0, d1) -> (d1, d0)>} : memref<?x?xf32>, vector<5x6xf32> // now: in_bounds is swapped because it is now expressed in terms of shaped value dimensions %0 = vector.transfer_read %m[%i, %j], %cst {in_bounds = [false, true], permutation_map = affine_map<(d0, d1) -> (d1, d0)>} : memref<?x?xf32>, vector<5x6xf32>
Example 2:
// previously: %0 = vector.transfer_read %t[%i, %j, %k], %cst {in_bounds = [false]} : tensor<?x?x?xf32>, vector<5xf32> // now: There are 3 in_bounds values. The first two in_bounds must be "true" because they are non-transfer dimensions. %0 = vector.transfer_read %t[%i, %j, %k], %cst {in_bounds = [true, true, false]} : tensor<?x?x?xf32>, vector<5xf32>
Note that in the above example, in_bounds used to be optional. In the absence of in_bounds, all dimension are considered out-of-bounds. But this would be incorrect with the new op semantics because the non-transfer dimensions would be out-of-bounds.
Depends On: D155277