[AMDGPU] hoistAndMergeSGPRInits merges m0 inits across call/regmask clobbers
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
hoistAndMergeSGPRInits in `SIFixSGPRCopies` deletes redundant `m0` immediate inits without treating call (and other **regmask**) clobbers as defs of `m0`.
ISel emits `s_mov_b32 m0, -1` before each pre-GFX9 LDS access. The merge pass then drops the post-call init because `MRI.def_instructions(M0)` never sees the call. `m0` is reserved and is not saved/restored, so the later `ds_*` / GDS / GWS / interp / `s_sendmsg` use can run with a clobbered value.
This is still present on current `main`. `llvm/test/CodeGen/AMDGPU/ds_read2.ll`.
Workaround: `-amdgpu-enable-merge-m0=false`.
## Reproducer
```llvm
target triple = "amdgcn-amd-amdhsa"
declare void @void_func_void()
declare i32 @llvm.amdgcn.workitem.id.x()
define amdgpu_kernel void @ds_read_call_read(ptr addrspace(1) %out, ptr addrspace(3) %arg) {
%x = call i32 @llvm.amdgcn.workitem.id.x()
%p0 = getelementptr i32, ptr addrspace(3) %arg, i32 %x
%p1 = getelementptr i32, ptr addrspace(3) %p0, i32 1
%v0 = load i32, ptr addrspace(3) %p0, align 4
call void @void_func_void()
%v1 = load i32, ptr addrspace(3) %p1, align 4
%r = add i32 %v0, %v1
store i32 %r, ptr addrspace(1) %out, align 4
ret void
}
```
```text
llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803
```
## Actual
```text
s_mov_b32 m0, -1
ds_read_b32 ...
s_swappc_b64 ...
ds_read_b32 ... offset:4 ; m0 not re-initialized
```
## Expected
```text
s_mov_b32 m0, -1
ds_read_b32 ...
s_swappc_b64 ...
s_mov_b32 m0, -1 ; required: call clobbers m0
ds_read_b32 ... offset:4
```
On GFX9+ this particular LDS example does not need `m0` (`ldsRequiresM0Init()` is false).
I am looking for any feedback on this, if this is still relevant?(I found it as relevant) if so what would be expected solution for this?
Ref:: LCOMPILER-2066
Assisted-by: Claude Opus 5
Contributor guide
Assessment
This issue has not been assessed yet.