# Plumbing spirv lowering path

**URL:** <https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131>\
**Category:** MLIR\
**Created:** [January 8, 2024, 5:24pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131 "2024-01-08T17:24:24Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jungpark](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/jungpark/32/1495_2.png) [@jungpark](https://discourse.llvm.org/u/jungpark)\
**Post date:** [January 8, 2024, 5:24pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/1 "2024-01-08T17:24:24Z")

</div>

Hi,

I had an issue using `spirv.branch` with `index` type operand.  
First problem was, I can’t tell mlir it’s 64 bit and the second problem was the conversion between integer and index for it remains as unrealized\_conversion\_cast.

I’ve got a [patch](https://github.com/llvm/llvm-project/pull/77344) for my use case, please let me know if there’s another way to address it.  
@antiagainst @kuhar @Hardcode84

---

<div class="post-metadata">

**Author:** ![kuhar](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/kuhar/32/573_2.png) [@kuhar](https://discourse.llvm.org/u/kuhar)\
**Post date:** [January 8, 2024, 5:38pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/2 "2024-01-08T17:38:19Z")

</div>

In general, we shouldn’t need any patterns to handle unrealized conversion casts – if we set up the pipeline correctly, everything should cancel out.

index to the exact integer type should be handled by the SPIR-V type converter. We had a related patch recently: [[mlir][spirv][cf] legalize block arguments when convert cf to spirv by python3kgae · Pull Request #71288 · llvm/llvm-project · GitHub](https://github.com/llvm/llvm-project/pull/71288) – maybe we missed something related?

---

<div class="post-metadata">

**Author:** ![jungpark](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/jungpark/32/1495_2.png) [@jungpark](https://discourse.llvm.org/u/jungpark)\
**Post date:** [January 9, 2024, 12:58pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/3 "2024-01-09T12:58:39Z")

</div>

Thanks for the response @kuhar, I’m having another look.

> [@kuhar](#):
>
> index to the exact integer type should be handled by the SPIR-V type converter.

Yes, [type converter](https://github.com/llvm/llvm-project/blob/e7636b1094ba53fe4edc16dd52ef981c01e35ceb/mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp#L124) references `options.use64bitIndex` which I can’t find an interface to set for the `cf-to-spirv` pass. Currently it only converts to `i32` because the option is false by default.

> [@kuhar](#):
>
> In general, we shouldn’t need any patterns to handle unrealized conversion casts – if we set up the pipeline correctly, everything should cancel out.

I’m trying to lower the `gpu.func` which has `index` type argument used by `spirv.branch`. The argument is converted into integer type using unrealized conversion cast and doesn’t seem to be cancelled before `gpu-to-spirv` which can’t handle it either.

These two issues are connected and probably there’s another (correct) way to address this, I’d appreciate if I can find it.

Here’s an IR snippet,

```auto
module attributes {gpu.container_module, spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, #spirv.resource_limits<>>} {
  gpu.module @forward_kernel_1 [#spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, #spirv.resource_limits<>>] attributes {spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, api=OpenCL, #spirv.resource_limits<>>} {
    gpu.func @forward_kernel_1_forward_kernel(%arg0: index, %arg1: memref<f32>, %arg2: index, %arg3: memref<f32>, %arg4: index, %arg5: memref<f32>, %arg6: index, %arg7: memref<f32>, %arg8: index, %arg9: index, %arg10: index) kernel attributes {gpu.known_block_size = array<i32: 1, 1, 1>, spirv.entry_point_abi = #spirv.entry_point_abi<>} {
      %0 = gpu.block_id x
      %1 = gpu.block_id y
      cf.br ^bb1(%arg8 : index)
    ^bb1(%2: index): // 2 preds: ^bb0, ^bb2
      %3 = arith.cmpi slt, %2, %arg9 : index
      cf.cond_br %3, ^bb2, ^bb3
    ^bb2: // pred: ^bb1
      %4 = arith.muli %0, %arg0 : index
      %5 = arith.addi %4, %2 : index
      %reinterpret_cast = memref.reinterpret_cast %arg1 to offset: [%5], sizes: [], strides: [] : memref<f32> to memref<f32>
      %6 = memref.load %reinterpret_cast[] : memref<f32>
      %7 = arith.muli %2, %arg2 : index
      %8 = arith.addi %7, %1 : index
      %reinterpret_cast_0 = memref.reinterpret_cast %arg3 to offset: [%8], sizes: [], strides: [] : memref<f32> to memref<f32>
      %9 = memref.load %reinterpret_cast_0[] : memref<f32>
      %10 = arith.muli %0, %arg4 : index
      %11 = arith.addi %10, %1 : index
      %reinterpret_cast_1 = memref.reinterpret_cast %arg5 to offset: [%11], sizes: [], strides: [] : memref<f32> to memref<f32>
      %12 = memref.load %reinterpret_cast_1[] : memref<f32>
      %13 = arith.mulf %6, %9 : f32
      %14 = arith.addf %12, %13 : f32
      %15 = arith.muli %0, %arg6 : index
      %16 = arith.addi %15, %1 : index
      %reinterpret_cast_2 = memref.reinterpret_cast %arg7 to offset: [%16], sizes: [], strides: [] : memref<f32> to memref<f32>
      memref.store %14, %reinterpret_cast_2[] : memref<f32>
      %17 = arith.addi %2, %arg10 : index
      cf.br ^bb1(%17 : index)
    ^bb3: // pred: ^bb1
      gpu.return
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![kuhar](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/kuhar/32/573_2.png) [@kuhar](https://discourse.llvm.org/u/kuhar)\
**Post date:** [January 9, 2024, 7:51pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/4 "2024-01-09T19:51:14Z")

</div>

> [@jungpark](#):
>
> Yes, [type converter](https://github.com/llvm/llvm-project/blob/e7636b1094ba53fe4edc16dd52ef981c01e35ceb/mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp#L124) references `options.use64bitIndex` which I can’t find an interface to set for the `cf-to-spirv` pass. Currently it only converts to `i32` because the option is false by default.

Adding this as a pass option that propagates to the type converter makes sense to me. If some block arguments don’t convert properly, it’s a bug.

Keep in mind though that in general these conversion passes are more for development / testing – in a real conversion pipeline, you’d create your own type converter and add multiple sets of conversion patterns at once, instead of running each conversion pass one by one. You can see how we set it up in IREE here: [iree/compiler/src/iree/compiler/Codegen/SPIRV/ConvertToSPIRVPass.cpp at c8ecc1c32c49fe5605a8492619527216303b4fd3 · openxla/iree · GitHub](https://github.com/openxla/iree/blob/c8ecc1c32c49fe5605a8492619527216303b4fd3/compiler/src/iree/compiler/Codegen/SPIRV/ConvertToSPIRVPass.cpp#L455-L492)

Another question that comes to mind is why the input uses `cf` instead of `scf` – is this by design?

---

<div class="post-metadata">

**Author:** ![jungpark](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/jungpark/32/1495_2.png) [@jungpark](https://discourse.llvm.org/u/jungpark)\
**Post date:** [January 10, 2024, 1:29pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/5 "2024-01-10T13:29:34Z")

</div>

Thanks again, it’s very helpful.

> [@kuhar](#):
>
> If some block arguments don’t convert properly, it’s a bug.

It looks, `legalizeBlockArguments` handles the block arguments of the `cf` op itself, it doesn’t convert the arguments of the block it belongs to.  
I just borrowed the pattern from `func-to-llvm` assuming it’s possible to see leftover `unrealized conversion cast` and need to clean up as like in the llvm conversion.

> [@kuhar](#):
>
> you’d create your own type converter and add multiple sets of conversion patterns at once, instead of running each conversion pass one by one

Thanks for the pointer, that looks the right way. Currently I’m trying to build the pipeline using python-API but will do that way in the future.

> [@kuhar](#):
>
> Another question that comes to mind is why the input uses `cf` instead of `scf` – is this by design?

I used to have the pipeline targetting `LLVM` and recently switched to use `spirv`. It’s just from `scf-to-cf` → `cf-to-llvm`. Currently `scf-to-spirv` has some problems with my test cases but haven’t yet investigated.

---

<div class="post-metadata">

**Author:** ![kuhar](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/kuhar/32/573_2.png) [@kuhar](https://discourse.llvm.org/u/kuhar)\
**Post date:** [January 10, 2024, 4:14pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/6 "2024-01-10T16:14:03Z")

</div>

> [@jungpark](#):
>
> I used to have the pipeline targetting `LLVM` and recently switched to use `spirv`. It’s just from `scf-to-cf` → `cf-to-llvm`. Currently `scf-to-spirv` has some problems with my test cases but haven’t yet investigated.

The `scf` lowering is generally preferred because [SPIR-V requires structured control flow](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_structured_control_flow) and going to `cf` loses some of that information. In practice, I’d also expect it to be more robust because we’ve been using `scf` → `spirv` in IREE for a while now. If there are any issues with that, feel free to open github issues and ping me there.

---

<div class="post-metadata">

**Author:** ![kuhar](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/kuhar/32/573_2.png) [@kuhar](https://discourse.llvm.org/u/kuhar)\
**Post date:** [January 10, 2024, 4:32pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/7 "2024-01-10T16:32:12Z")

</div>

> [@jungpark](#):
>
> It looks, `legalizeBlockArguments` handles the block arguments of the `cf` op itself, it doesn’t convert the arguments of the block it belongs to.

This sounds like a legitimate bug. Feel free to file an issue on github too – I found these to generally help with making sure things don’t fall through the cracks.

---

<div class="post-metadata">

**Author:** ![jungpark](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/jungpark/32/1495_2.png) [@jungpark](https://discourse.llvm.org/u/jungpark)\
**Post date:** [January 10, 2024, 5:39pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/8 "2024-01-10T17:39:17Z")

</div>

> [@kuhar](#):
>
> This sounds like a legitimate bug.

I’m going to file an issue but just one thing to avoid any confusion.  
It doesn’t seem to be a specific bug in the control-flow conversion but more like a general missing feature.

For example, this can’t be lowered.

```auto
module attributes {gpu.container_module, spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, #spirv.resource_limits<>>} {
  gpu.module @forward_kernel_1 [#spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, #spirv.resource_limits<>>] attributes {spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, api=OpenCL, #spirv.resource_limits<>>} {
    gpu.func @test_kernel(%arg0: index, %arg1: index, %arg2: memref<3x3xi32>) kernel attributes {gpu.known_block_size = array<i32: 1, 1, 1>, gpu.known_grid_size = array<i32: 3, 3, 1>, spirv.entry_point_abi = #spirv.entry_point_abi<>} {
      %0 = gpu.block_id x
      %1 = gpu.block_id y
      %2 = arith.addi %arg0, %arg1 : index
      %3 = index.casts %2 : index to i32
      memref.store %3, %arg2[%0, %1] : memref<3x3xi32>
      gpu.return
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![kuhar](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/kuhar/32/573_2.png) [@kuhar](https://discourse.llvm.org/u/kuhar)\
**Post date:** [January 10, 2024, 6:02pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/9 "2024-01-10T18:02:12Z")

</div>

+cc @antiagainst for the historical context here. To me this sounds like a lowering flow that is not used anywhere else so there may not be a general pattern to handle arbitrary function ops / etc.

---

<div class="post-metadata">

**Author:** ![jungpark](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/jungpark/32/1495_2.png) [@jungpark](https://discourse.llvm.org/u/jungpark)\
**Post date:** [January 10, 2024, 6:29pm UTC](https://discourse.llvm.org/t/plumbing-spirv-lowering-path/76131/10 "2024-01-10T18:29:58Z")

</div>

Opened [[mlir][spirv] Investigate legalization of the func argument. · Issue #77664 · llvm/llvm-project · GitHub](https://github.com/llvm/llvm-project/issues/77664)  
with examples with `scf` and `arith` to replicate the issue.
