[AMDGPU] Debug instructions consume the redundant GPR-index scan window
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Adding debug-only instructions can prevent `SIPreEmitPeephole` from removing a
redundant pair of GPR-index mode transitions. The two verifier-valid MIR inputs
attached below have the same ordinary machine instructions. The debug variant
only adds eighteen `DBG_VALUE $noreg, 0` instructions, but its final `.text`
section is eight bytes larger.
This reproduces with an assertions-enabled LLVM 24.0.0git build at revision
`2fd31faf6ec53ad7fc0c92355856367b9c5f3ad8` on x86-64 Linux, targeting
`amdgpu9.00`. On 2026-09-17, LLVM main at
`66ae28fd8f686b6b558796f70ca388523158a20c` still used the same
`SIPreEmitPeephole.cpp` Git blob as the tested revision.
## Reproducer
The following files are attached individually. The MIR inputs have a final
`.txt` suffix only because GitHub does not accept `.mir` uploads:
- [reproduce-issue.sh](https://github.com/user-attachments/files/32334702/reproduce-issue.sh)
- [with-debug.mir.txt](https://github.com/user-attachments/files/32334704/with-debug.mir.txt)
- [without-debug.mir.txt](https://github.com/user-attachments/files/32334703/without-debug.mir.txt)
Run:
```bash
bash reproduce.sh
```
Both inputs are accepted with `-verify-machineinstrs`. The script first runs
the exact `si-pre-emit-peephole` pass and then emits an object from the
post-pass MIR.
## Actual behavior
```text
without-debug: S_SET_GPR_IDX_ON=1 S_SET_GPR_IDX_OFF=1 .text=16 bytes
with-debug: S_SET_GPR_IDX_ON=2 S_SET_GPR_IDX_OFF=2 .text=24 bytes
70f6c65ed9d0035c9761d7e03bbe0dfc3b63294ae63db0fc7060ec6fd45334fa without-debug.text
763c28793abb11a03f98f5a7fe4f6feb0ae6b020865d318c839f886d5ff79547 with-debug.text
```
The extra eight bytes encode an additional `s_set_gpr_idx_off` followed by
`s_set_gpr_idx_on`.
## Expected behavior
Debug-only instructions should not consume the compile-time search budget used
to find redundant GPR-index mode transitions. Both inputs should retain the
same ordinary post-pass MIR and emit the same 16-byte `.text` section.
## Cause analysis
`SIPreEmitPeephole::run()` limits the search to 20 instructions for compile
time reasons. The outer loop walks the raw `MBB.instrs()` range and updates
`Count` before checking the opcode:
```cpp
for (auto &MI : make_early_inc_range(MBB.instrs())) {
if (Count == Threshold)
SetGPRMI = nullptr;
else
++Count;
```
Consequently, `DBG_VALUE` instructions exhaust the window. With seventeen
debug instructions, the redundant transition is removed. With eighteen, the
remembered `S_SET_GPR_IDX_ON` is cleared before the second transition is
visited.
As a diagnostic intervention, skipping `MI.isDebugInstr()` before updating
`Count` restores identical post-pass MIR and final `.text` for both inputs.
## Scope
The reproducer was reduced from LLVM's upstream
`llvm/test/CodeGen/AMDGPU/set-gpr-idx-peephole.mir` test. A natural frontend or
LLVM IR input producing this exact late-machine-instruction shape is not
currently known. This is a missed peephole optimization rather than a crash or
wrong-code issue.
Contributor guide
Research direction
Start by running the attached reproduce-issue.sh with the two MIR inputs, then read SIPreEmitPeephole.cpp and the existing llvm/test/CodeGen/AMDGPU/set-gpr-idx-peephole.mir test. Trace how the pass counts instructions and compare its post-pass MIR for both inputs. Done means debug instructions no longer change the ordinary post-pass MIR or the emitted .text size.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100