Problem with -convert-cf-to-llvm

Hi everyone! I’m trying to lower this code snippet in mlir/test/Dialect/Linalg/bufferize.mlir to llvm dialect.

#map0 = affine_map<(d0) -> (d0)>

func.func @basic(%arg0: tensor<4xf32>) -> tensor<4xf32> {
    %0 = linalg.generic {
      indexing_maps = [#map0, #map0],
      iterator_types = ["parallel"]
    } ins(%arg0 : tensor<4xf32>)
      outs(%arg0 : tensor<4xf32>) {
      ^bb0(%gen_arg1: f32, %out: f32):
        %tmp1 = math.exp %gen_arg1 : f32
        linalg.yield %tmp1 : f32
    } -> tensor<4xf32>
    return %0 : tensor<4xf32>
}

I’ve tried this lowering -linalg-bufferize -canonicalize -cse -convert-linalg-to-loops -convert-scf-to-cf -convert-cf-to-llvm. Till scf-to-cf everything is fine, but after cf-to-llvm there are still cf.br operations not lowered into llvm. But the cond_br operation is already lowered.

module {
  func.func @basic(%arg0: tensor<4xf32>) -> tensor<4xf32> {
    %c0 = arith.constant 0 : index
    %c4 = arith.constant 4 : index
    %c1 = arith.constant 1 : index
    %0 = bufferization.to_memref %arg0 : memref<4xf32>
    %alloc = memref.alloc() {alignment = 128 : i64} : memref<4xf32>
    cf.br ^bb1(%c0 : index)
  ^bb1(%1: index):  // 2 preds: ^bb0, ^bb2
    %2 = arith.cmpi slt, %1, %c4 : index
    llvm.cond_br %2, ^bb2, ^bb3
  ^bb2:  // pred: ^bb1
    %3 = memref.load %0[%1] : memref<4xf32>
    %4 = math.exp %3 : f32
    memref.store %4, %alloc[%1] : memref<4xf32>
    %5 = arith.addi %1, %c1 : index
    cf.br ^bb1(%5 : index)
  ^bb3:  // pred: ^bb1
    %6 = bufferization.to_tensor %alloc : memref<4xf32>
    return %6 : tensor<4xf32>
  }
}

In the debug info, there is this failure: mismatched types from operand # 0 'i64' not compatible with destination block argument type 'index' which should be converted with the parent op.. I’ve looked this problem up in Discourse and GitHub i.e. Lowering CF to LLVM and Only conditionally lower CF branching ops to LLVM.
I don’t understand why there is this failure for cf.br but for cf.cond_br it’s fine.

BTW adding -convert-func-to-llvm before using -convert-cf-to-llvm doesn’t work either.

The conditional branch is not passing any values to its destination blocks, so there is no possible type mismatch.

I believe your current issue is that the arith.constants are not being lowered. ArithToLLVM probably handles this, but I guess there is a chance it is IndexToLLVM. Math also looks like it still needs to be lowered, but that is not your current issue. I would recommend ensuring that every op except func+cf dialect is lowered to LLVM and then add on Func+CF->LLVM.

A later issue you’ll probably run into is that you probably need to bufferize the function boundaries, as you can see there are still tensor types there.

See the pass added here for guidance on what you might need. I think it would be better for this to be a single pass with many patterns instead of a sequence of passes when lowering to LLVM, but I don’t know if everyone would agree upon that and haven’t thought about it much (I’m mentioning this, as you will hit less issues if you create such a pass for yourself):

Sorry for the rather robotic response here, and I hope it’s clear. I just came across this while not working, so I’m trying to be fast :slight_smile:

Thanks so much! I’ve just added the -func-bufferize pass in the lowering pipeline and now the problem is solved. And thanks for the hints, I should definitely use the way you just told me;)

Hello, I am facing a similar issue where cf.br does not get lowered. What were the options that finally worked for you? Thanks!