[MLIR] `scf.if` miscompiled after OpenCL SPIR-V lowering on Intel GPU
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The following MLIR program writes 1 for local thread IDs 0 through 5 and 0 for the remaining thread IDs. After lowering through the MLIR OpenCL-targeted SPIR-V pipeline and executing the generated program through the MLIR SYCL runtime on an Intel GPU, the program produces all zeros instead of the expected first six ones.
Replacing only the `scf.if` with an equivalent `arith.select` produces the expected output on the same device.
### Input Program
**input.mlir**
```llvm
module attributes {
gpu.container_module,
spirv.target_env = #spirv.target_env<
#spirv.vce,
api=OpenCL, #spirv.resource_limits<>>
} {
gpu.module @kernels {
gpu.func @scf_if(%out : memref<32xi32>) kernel
attributes {
spirv.entry_point_abi =
#spirv.entry_point_abi
} {
%x = gpu.thread_id x
%x_i32 = arith.index_cast %x : index to i32
%x_f32 = arith.sitofp %x_i32 : i32 to f32
%five = arith.constant 5.0 : f32
%outside = arith.cmpf ogt, %x_f32, %five : f32
%result = scf.if %outside -> i32 {
%zero = arith.constant 0 : i32
scf.yield %zero : i32
} else {
%one = arith.constant 1 : i32
scf.yield %one : i32
}
memref.store %result, %out[%x] : memref<32xi32>
gpu.return
}
}
func.func @main() {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c32 = arith.constant 32 : index
%out = gpu.alloc host_shared () : memref<32xi32>
%zero = arith.constant 0 : i32
scf.for %i = %c0 to %c32 step %c1 {
memref.store %zero, %out[%i] : memref<32xi32>
}
gpu.launch_func @kernels::@scf_if
blocks in (%c1, %c1, %c1) threads in (%c32, %c1, %c1)
args(%out : memref<32xi32>)
%unranked = memref.cast %out : memref<32xi32> to memref<*xi32>
call @printMemrefI32(%unranked) : (memref<*xi32>) -> ()
return
}
func.func private @printMemrefI32(memref<*xi32>)
attributes {llvm.emit_c_interface}
}
```
### Lowering Command
```bash
mlir-opt input.mlir \
'--pass-pipeline=builtin.module(
lower-affine,
convert-math-to-spirv,
gpu.module(
gpu.func(lower-affine)
),
func.func(convert-scf-to-cf),
gpu-kernel-outlining,
fold-memref-alias-ops,
gpu.module(
gpu.func(lower-affine)
),
spirv-attach-target{
ver=v1.0
caps=Addresses,Int8,Int16,Int64,Float16,Float64,Kernel
client_api=OpenCL
},
convert-gpu-to-spirv{
use-64bit-index=true
},
gpu.module(
spirv.module(
spirv-lower-abi-attrs,
spirv-update-vce
)
),
func.func(llvm-request-c-wrappers),
convert-scf-to-cf,
convert-cf-to-llvm,
convert-arith-to-llvm,
convert-math-to-llvm,
convert-func-to-llvm,
gpu-to-llvm{
use-bare-pointers-for-kernels=true
},
gpu-module-to-binary,
expand-strided-metadata,
lower-affine,
finalize-memref-to-llvm,
reconcile-unrealized-casts
)' \
-o lower.mlir
```
### Execution Command
```bash
export ONEAPI_DEVICE_SELECTOR=level_zero:gpu
mlir-runner lower.mlir -e main \
--shared-libs=$LLVM_BUILD/lib/libmlir_sycl_runtime.so \
--shared-libs=$LLVM_BUILD/lib/libmlir_runner_utils.so \
--entry-point-result=void
```
### Actual Result
```bash
Unranked Memref rank = 1 offset = 0 sizes = [32] strides = [1] data =
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
```
### Expected Result
```bash
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
```
Version: fdbbcba77d625a5c403aea78b5b7fc64547fa558
Contributor guide
Research direction
Start with the supplied input.mlir and reproduce the failure using the listed mlir-opt lowering pipeline and mlir-runner command on an Intel GPU. Compare the scf.if path with the arith.select variant and trace the OpenCL-targeted SPIR-V lowering; done means the first six output elements are 1 and the remaining elements are 0.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100