Hi, community!
Recently, I’m working on calling the external library function and user’s self-defined function in linalg IR. And I find we have the field of library_call
in Linalg’s generic operation. some code like these are generated automatically:
module attributes {torch.debug_module_name = "ExternCallModule"} {
func @forward(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
%c1 = arith.constant 1 : index
%c0 = arith.constant 0 : index
%0 = tensor.dim %arg0, %c0 : tensor<?x?xf32>
%1 = tensor.dim %arg0, %c1 : tensor<?x?xf32>
%2 = linalg.init_tensor [%0, %1] : tensor<?x?xf32>
%3 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0, d1)>], iterator_types = ["parallel", "parallel"], library_call = "external_function_2xf32"} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%2 : tensor<?x?xf32>) {
^bb0(%arg2: f32, %arg3: f32, %arg4: f32): // no predecessors
linalg.yield %arg4 : f32
} -> tensor<?x?xf32>
return %3 : tensor<?x?xf32>
}
}
You see there’s only a yield
in the linalg.generic
, which will be erased in the canonicalization:
module attributes {torch.debug_module_name = "ExternCallModule"} {
func @forward(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
%c1 = arith.constant 1 : index
%c0 = arith.constant 0 : index
%0 = tensor.dim %arg0, %c0 : tensor<?x?xf32>
%1 = tensor.dim %arg0, %c1 : tensor<?x?xf32>
%2 = linalg.init_tensor [%0, %1] : tensor<?x?xf32>
return %2 : tensor<?x?xf32>
}
}
I modified it by editing EraseIdentityGenericOp
in LinalgOps.cpp
, the patch is: ⚙ D115871 Do not erase identity generic op with library_call field.
Btw, thank you in advance for your review. @gysit
Does it modification make sense? Any advice would be very grateful!