llvm / llvm/llvm-project

[AMDGPU] Debug instructions consume the redundant GPR-index scan window

Open
#224,271 2 comments 0 reactions 0 assignees View on GitHub
backend:AMDGPU debuginfo
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.