[Mlir-commits] [mlir] [mlir][spirv] Handle signedness casts (PR #155388)

Michael Platings llvmlistbot at llvm.org
Tue Aug 26 09:13:56 PDT 2025


mplatings wrote:

> > One instance is #141096.
> 
> This fix looks fishy to me, I wouldn't not expect any unrealized_casts as an input for conversion to spirv.
> 
> A motivating example at the level of arith/vector/sfc or the test dialect. would help me understand if this needs handling.

I can create an arith example by running `mlir-opt -pass-pipeline="builtin.module(func.func(tosa-to-linalg))"` on this test from #141096:
```
func.func @rescale_i8_unsigned_output_explicit(%arg0 : tensor<2xui8>) -> () {
  %multiplier = "tosa.const"() {values = dense<19689> : tensor<1xi16> } : () -> tensor<1xi16>
  %shift = "tosa.const"() {values = dense<15> : tensor<1xi8> } : () -> tensor<1xi8>
  %input_zp = "tosa.const"() {values = dense<17> : tensor<1xui8>} : () -> tensor<1xui8>
  %output_zp = "tosa.const"() {values = dense<-22> : tensor<1xi8>} : () -> tensor<1xi8>
  %1 = tosa.rescale %arg0, %multiplier, %shift, %input_zp, %output_zp {scale32 = false, rounding_mode = "SINGLE_ROUND", per_channel = false, input_unsigned = true, output_unsigned = true} : (tensor<2xui8>, tensor<1xi16>, tensor<1xi8>, tensor<1xui8>, tensor<1xi8>) -> tensor<2xui8>
  return
}
```
which gives you:
```
#map = affine_map<(d0) -> (d0)>
module {
  func.func @rescale_i8_unsigned_output_explicit(%arg0: tensor<2xui8>) {
    %0 = "tosa.const"() <{values = dense<19689> : tensor<1xi16>}> : () -> tensor<1xi16>
    %1 = "tosa.const"() <{values = dense<15> : tensor<1xi8>}> : () -> tensor<1xi8>
    %2 = "tosa.const"() <{values = dense<17> : tensor<1xui8>}> : () -> tensor<1xui8>
    %3 = "tosa.const"() <{values = dense<-22> : tensor<1xi8>}> : () -> tensor<1xi8>
    %c19689_i32 = arith.constant 19689 : i32
    %c15_i8 = arith.constant 15 : i8
    %4 = tensor.empty() : tensor<2xui8>
    %5 = linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel"]} ins(%arg0 : tensor<2xui8>) outs(%4 : tensor<2xui8>) {
    ^bb0(%in: ui8, %out: ui8):
      %c17_i32 = arith.constant 17 : i32
      %c234_i32 = arith.constant 234 : i32
      %6 = builtin.unrealized_conversion_cast %in : ui8 to i8
      %7 = arith.extui %6 : i8 to i32
      %8 = arith.subi %7, %c17_i32 : i32
      %9 = tosa.apply_scale %8, %c19689_i32, %c15_i8 {rounding_mode = "SINGLE_ROUND"} : (i32, i32, i8) -> i32
      %10 = arith.addi %9, %c234_i32 : i32
      %c0_i32 = arith.constant 0 : i32
      %c255_i32 = arith.constant 255 : i32
      %11 = arith.maxsi %c0_i32, %10 : i32
      %12 = arith.minsi %c255_i32, %11 : i32
      %13 = arith.trunci %12 : i32 to i8
      %14 = builtin.unrealized_conversion_cast %13 : i8 to ui8
      linalg.yield %14 : ui8
    } -> tensor<2xui8>
    return
  }
}
```
Converting that with `mlir-opt -convert-arith-to-spirv` gives you:
```#map = affine_map<(d0) -> (d0)>
module attributes {spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64, Shader], []>, #spirv.resource_limits<>>} {
  func.func @rescale_i8_unsigned_output_explicit(%arg0: tensor<2xui8>) {
    %0 = "tosa.const"() <{values = dense<19689> : tensor<1xi16>}> : () -> tensor<1xi16>
    %1 = "tosa.const"() <{values = dense<15> : tensor<1xi8>}> : () -> tensor<1xi8>
    %2 = "tosa.const"() <{values = dense<17> : tensor<1xui8>}> : () -> tensor<1xui8>
    %3 = "tosa.const"() <{values = dense<-22> : tensor<1xi8>}> : () -> tensor<1xi8>
    %cst19689_i32 = spirv.Constant 19689 : i32
    %cst15_i8 = spirv.Constant 15 : i8
    %4 = tensor.empty() : tensor<2xui8>
    %5 = linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel"]} ins(%arg0 : tensor<2xui8>) outs(%4 : tensor<2xui8>) {
    ^bb0(%in: ui8, %out: ui8):
      %cst17_i32 = spirv.Constant 17 : i32
      %cst234_i32 = spirv.Constant 234 : i32
      %6 = builtin.unrealized_conversion_cast %in : ui8 to i8
      %7 = spirv.UConvert %6 : i8 to i32
      %8 = spirv.ISub %7, %cst17_i32 : i32
      %9 = tosa.apply_scale %8, %cst19689_i32, %cst15_i8 {rounding_mode = "SINGLE_ROUND"} : (i32, i32, i8) -> i32
      %10 = spirv.IAdd %9, %cst234_i32 : i32
      %cst0_i32 = spirv.Constant 0 : i32
      %cst255_i32 = spirv.Constant 255 : i32
      %11 = spirv.GL.SMax %10, %cst0_i32 : i32
      %12 = spirv.GL.SMin %11, %cst255_i32 : i32
      %13 = spirv.SConvert %12 : i32 to i8
      %14 = builtin.unrealized_conversion_cast %13 : i8 to ui8
      linalg.yield %14 : ui8
    } -> tensor<2xui8>
    return
  }
}
```
So there's a problem at `%6 = builtin.unrealized_conversion_cast %in : ui8 to i8` because that should have been lowered to `spirv.Bitcast`

(Apologies if I've misunderstood you, I'm relatively new to MLIR)

https://github.com/llvm/llvm-project/pull/155388


More information about the Mlir-commits mailing list