While working on some implementations with the linalg
dialect, I had the need to use some conditionals based on the indices of the iteration, linalg.indexed_generic
works great as long as I use the indeces with operations of scf
or std
dialects. If I try to use them with affine.if
I get an error.
Example to reproduce:
// True if in Upper Triangular region
#set0 = affine_set<(d0,d1) : (d0-d1>=0)>
#transpose_accesses = [
affine_map<(H,W)->(H,W)>,
affine_map<(H,W)->(W,H)>
]
#trans_trait = {
indexing_maps = #transpose_accesses,
iterator_types = ["parallel","parallel"]
}
// Transpose Matrix `out` inplace
func @transpose(%out: memref<?x?xf32>){
linalg.indexed_generic #trans_trait
outs(%out, %out : memref<?x?xf32>, memref<?x?xf32>) {
^bb0(%i: index, %j: index, %a: f32, %b:f32):
// This does not work: this region indeces cannot be used
// as inputs to the affine set. Check error below.
%r1, %r2 = affine.if #set0(%i,%j) -> (f32,f32) {
affine.yield %b,%a : f32, f32
} else {
affine.yield %a,%b : f32, f32
}
linalg.yield %r1, %r2 : f32 ,f32
}
return
}
Gives me the following error:
generic/transpose.mlir:123:16: error: 'affine.if' op operand cannot be used as a dimension id
%r1, %r2 = affine.if #set0(%i,%j) -> (f32,f32) {
^
generic/transpose.mlir:123:16: note: see current operation: %0:2 = "affine.if"(%arg1, %arg2) ( {
"affine.yield"(%arg4, %arg3) : (f32, f32) -> ()
}, {
"affine.yield"(%arg3, %arg4) : (f32, f32) -> ()
}) {condition = affine_set<(d0, d1) : (d0 - d1 >= 0)>} : (index, index) -> (f32, f32)
In constrast, these work ok:
// Transpose Matrix `out` inplace using scf operations
func @transpose2(%out: memref<?x?xf32>){
linalg.indexed_generic #trans_trait
outs(%out, %out : memref<?x?xf32>, memref<?x?xf32>) {
^bb0(%i: index, %j: index, %a: f32, %b:f32):
// Are the indexes on the diagonal/upper triangle?
%cond = cmpi ugt, %i, %j : index
%r1, %r2 = scf.if %cond -> (f32,f32) {
scf.yield %b,%a : f32, f32
} else {
scf.yield %a,%b : f32, f32
}
linalg.yield %r1, %r2 : f32 ,f32
}
return
}
// Transpose Matrix `out` inplace using std operations
func @transpose3(%out: memref<?x?xf32>){
// Transpose inplace
linalg.indexed_generic #trans_trait
outs(%out, %out : memref<?x?xf32>, memref<?x?xf32>) {
^bb0(%i: index, %j: index, %a: f32, %b:f32):
%1 = cmpi sge, %i, %j : index
%r1 = select %1, %b, %a : f32
%r2 = select %1, %a, %b : f32
linalg.yield %r1, %r2 : f32 ,f32
}
return
}
Shouldn’t linalg.indexed_generic
be marked with the AffineScope trait? If not, can you help me understand why there is a limitation?