llvm / llvm/llvm-project

[MLIR][SPIR-V] Miscompilation of zero-trip `scf.for` with `iter_args` after NVVM-targeted SPIR-V lowering

Open
#211,981 1 comment 0 reactions 1 assignee Claimed by @CoTinker 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 contains an `scf.for` operation whose lower bound is 1 and upper bound is 0. The loop executes zero iterations, so its loop-carried result should be the initial value 42.0.

After lowering through the SPIR-V pipeline and executing with the MLIR Vulkan runtime, the program produces 0 instead of 42.

### Input Program
**input.mlir**

```llvm
module attributes {
gpu.container_module,
spirv.target_env = #spirv.target_env<
#spirv.vce,
#spirv.resource_limits<>>
} {
gpu.module @kernels {
gpu.func @zero_trip(%out : memref<1xf32>) kernel
attributes {
spirv.entry_point_abi =
#spirv.entry_point_abi
} {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%init = arith.constant 42.0 : f32

%result = scf.for %i = %c1 to %c0 step %c1
iter_args(%acc = %init) -> (f32) {
%next = arith.addf %acc, %init : f32
scf.yield %next : f32
}

memref.store %result, %out[%c0] : memref<1xf32>
gpu.return
}
}

func.func @main() {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%out = memref.alloc() : memref<1xf32>
%initial = arith.constant 0.0 : f32
memref.store %initial, %out[%c0] : memref<1xf32>

gpu.launch_func @kernels::@zero_trip
blocks in (%c1, %c1, %c1) threads in (%c1, %c1, %c1)
args(%out : memref<1xf32>)

%unranked = memref.cast %out : memref<1xf32> to memref<*xf32>
call @printMemrefF32(%unranked) : (memref<*xf32>) -> ()
memref.dealloc %out : memref<1xf32>
return
}

func.func private @printMemrefF32(memref<*xf32>)
attributes {llvm.emit_c_interface}
}
```

### Lowering Command
```bash
mlir-opt \
input.mlir \
"--pass-pipeline=builtin.module(spirv-attach-target{ver=v1.3 caps=Shader exts=SPV_KHR_storage_buffer_storage_class},test-convert-to-spirv{convert-gpu-modules=true nest-in-gpu-module=true},gpu.module(spirv.module(spirv-lower-abi-attrs,spirv-update-vce)),gpu-module-to-binary,finalize-memref-to-llvm,func.func(llvm-request-c-wrappers),gpu-to-llvm{use-bare-pointers-for-kernels=true intersperse-sizes-for-kernels=true},reconcile-unrealized-casts)" \
-o lower.mlir
```

### Execution Command
```bash
export VK_LOADER_LAYERS_DISABLE="*"
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json

mlir-runner \
lower.mlir \
--shared-libs=$LLVM_BUILD/lib/libmlir_vulkan_runtime.so \
--shared-libs=$LLVM_BUILD/lib/libmlir_runner_utils.so \
--shared-libs=$LLVM_BUILD/lib/libmlir_c_runner_utils.so \
--entry-point-result=void
```

### Actual Result

```bash
[0]
```

### Expected Result

```bash
[42]
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.