llvm / llvm/llvm-project

[MLIR] `scf.if` miscompiled after OpenCL SPIR-V lowering on Intel GPU

Open
#211,980 1 comment 0 reactions 0 assignees View on GitHub
miscompilation mlir
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.