llvm / llvm/llvm-project

[MLIR]GPU default pipeline leaves `vector.transfer_read` and an unreconciled memref descriptor cast

Open
#214,404 2 comments 0 reactions 0 assignees View on GitHub
mlir
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

The default `gpu-lower-to-nvvm-pipeline` does not fully lower a rank-1 `vector.transfer_read` inside a `gpu.module`. During `convert-gpu-to-nvvm`, the memref argument is converted to an LLVM descriptor, but the surviving vector operation still expects a memref.

A descriptor-to- memref `builtin.unrealized_conversion_cast` is inserted and cannot be reconciled because it remains consumed by the vector operation. GPU binary serialization later fails during LLVM translation. This appears to be a rejects-valid bug.

### Input Program
input.mlir
```llvm
module attributes {gpu.container_module} {
gpu.module @kernels {
gpu.func @transfer_read(%input : memref, %output : memref) kernel {
%c0 = arith.constant 0 : index
%padding = arith.constant 0.0 : f32
%value = vector.transfer_read %input[%c0], %padding
: memref, vector<4xf32>
%first = vector.extract %value[0] : f32 from vector<4xf32>
memref.store %first, %output[%c0] : memref
gpu.return
}
}

func.func @main() {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c4 = arith.constant 4 : index
%input = gpu.alloc host_shared (%c4) : memref
%output = gpu.alloc host_shared (%c1) : memref
%one = arith.constant 1.0 : f32
%zero = arith.constant 0.0 : f32
scf.for %i = %c0 to %c4 step %c1 {
memref.store %one, %input[%i] : memref
}
memref.store %zero, %output[%c0] : memref
gpu.launch_func @kernels::@transfer_read
blocks in (%c1, %c1, %c1) threads in (%c1, %c1, %c1)
args(%input : memref, %output : memref)
%unranked = memref.cast %output : memref to memref<*xf32>
call @printMemrefF32(%unranked) : (memref<*xf32>) -> ()
return
}

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

### Used Command
```bash
mlir-opt input.mlir \
--gpu-lower-to-nvvm-pipeline='cubin-chip=sm_89 cubin-features=+ptx80 opt-level=3 allow-pattern-rollback=0' \
-o /tmp/lower.mlir
```

### Actual result
mlir-opt exits with code 1:
```bash
error: LLVM Translation failed for operation:
builtin.unrealized_conversion_cast
note: see current operation: %9 = "builtin.unrealized_conversion_cast"(%8)
: (!llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>)
-> memref
error: Failed creating the llvm::Module.
```

The relevant cast first appears in the output of the nested convert-gpu-to-nvvm pass. The preceding default convert-vector-to-scf pass leaves the rank-1 transfer operation unchanged.

### Expected result
The pipeline should fully lower this legal rank-1 transfer operation and should not leave an unreconciled materialization cast.

Contributor guide

Open the contributing guide

Research direction

Start with input.mlir and reproduce the failure using the shown mlir-opt gpu-lower-to-nvvm-pipeline command. Inspect the default convert-vector-to-scf and nested convert-gpu-to-nvvm stages, focusing on the rank-1 vector.transfer_read and the resulting memref descriptor cast; done means the legal transfer lowers fully without an unreconciled cast or LLVM translation failure.

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
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.