[MLIR] Miscompilation of workgroup reduction produces incorrect results after XeVM lowering
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The following MLIR program performs a reduction of eight `1.0` values using workgroup memory and `gpu.barrier`. After lowering through the XeVM pipeline with `zebin-chip=mtl_s` and executing the generated program through the MLIR Level Zero runtime on an Intel GPU platform, the program produces 0 instead of the expected result 8.
### Input Program
```llvm
module attributes {gpu.container_module} {
gpu.module @kernels {
gpu.func @reduce_sum(%in: memref<8xf32>, %out: memref<1xf32>)
workgroup(%scratch: memref<8xf32, 3>) kernel {
%tid = gpu.thread_id x
%zero_i = arith.constant 0 : index
%one_i = arith.constant 1 : index
%eight_i = arith.constant 8 : index
%zero_f = arith.constant 0.0 : f32
%v = memref.load %in[%tid] : memref<8xf32>
memref.store %v, %scratch[%tid] : memref<8xf32, 3>
gpu.barrier
%leader = arith.cmpi eq, %tid, %zero_i : index
scf.if %leader {
%sum = scf.for %i = %zero_i to %eight_i step %one_i iter_args(%acc = %zero_f) -> (f32) {
%item = memref.load %scratch[%i] : memref<8xf32, 3>
%next = arith.addf %acc, %item : f32
scf.yield %next : f32
}
memref.store %sum, %out[%zero_i] : memref<1xf32>
}
gpu.barrier
gpu.return
}
}
func.func @main() {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c2 = arith.constant 2 : index
%c3 = arith.constant 3 : index
%c4 = arith.constant 4 : index
%c5 = arith.constant 5 : index
%c6 = arith.constant 6 : index
%c7 = arith.constant 7 : index
%in_host = memref.alloc() : memref<8xf32>
%in_buffer = gpu.alloc() : memref<8xf32>
%in_init = arith.constant 1.0 : f32
memref.store %in_init, %in_host[%c0] : memref<8xf32>
memref.store %in_init, %in_host[%c1] : memref<8xf32>
memref.store %in_init, %in_host[%c2] : memref<8xf32>
memref.store %in_init, %in_host[%c3] : memref<8xf32>
memref.store %in_init, %in_host[%c4] : memref<8xf32>
memref.store %in_init, %in_host[%c5] : memref<8xf32>
memref.store %in_init, %in_host[%c6] : memref<8xf32>
memref.store %in_init, %in_host[%c7] : memref<8xf32>
gpu.memcpy %in_buffer, %in_host : memref<8xf32>, memref<8xf32>
%out_host = memref.alloc() : memref<1xf32>
%out_buffer = gpu.alloc() : memref<1xf32>
%out_init = arith.constant 0.0 : f32
memref.store %out_init, %out_host[%c0] : memref<1xf32>
gpu.memcpy %out_buffer, %out_host : memref<1xf32>, memref<1xf32>
%bx = arith.constant 1 : index
%by = arith.constant 1 : index
%bz = arith.constant 1 : index
%tx = arith.constant 8 : index
%ty = arith.constant 1 : index
%tz = arith.constant 1 : index
gpu.launch_func @kernels::@reduce_sum blocks in (%bx, %by, %bz) threads in (%tx, %ty, %tz) args(%in_buffer : memref<8xf32>, %out_buffer : memref<1xf32>)
gpu.memcpy %out_host, %out_buffer : memref<1xf32>, memref<1xf32>
%print = memref.cast %out_host : memref<1xf32> to memref<*xf32>
call @printMemrefF32(%print) : (memref<*xf32>) -> ()
gpu.dealloc %out_buffer : memref<1xf32>
memref.dealloc %out_host : memref<1xf32>
gpu.dealloc %in_buffer : memref<8xf32>
memref.dealloc %in_host : memref<8xf32>
return
}
func.func private @printMemrefF32(memref<*xf32>)
}
```
### Lowering Command
```bash
mlir-opt input.mlir "-gpu-lower-to-xevm-pipeline=xegpu-op-level=lane zebin-triple=spirv64-unknown-unknown zebin-chip=mtl_s opt-level=2 binary-format=fatbin" -o lower.mlir
```
### Execution Command
```bash
export ONEAPI_DEVICE_SELECTOR=level_zero:gpu
mlir-runner lower.mlir --shared-libs=$LLVM_BUILD/lib/libmlir_levelzero_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 = [1] strides = [1] data =
[0]
```
### Expected Result
```bash
[8]
```
Version: 195df3d4654b43ecf35927e574a8061bfaecbb78
Contributor guide
Assessment
This issue has not been assessed yet.