[RFC] Instruction API changes needed to eliminate debug intrinsics from IR

Hi,

We’re now at the cusp of turning this on. When that switch flips, it’s going to cause LLVM to use non-instruction debug-info /only in the context of the pass manager/. That means all optimisation passes will be exposed to this, and we believe we have them all instrumented to act identically to the past. However the rest of LLVM will act as before, printing intrinsics in the output, and in bitcode.

We had a couple of abortive attempts to draw a line through LLVM so that we could stage these changes incrementally, and this is what we’ve come up with. The other paths we’ve explored all involve a “big bang” where a lot of the edges of the compiler change and cause friction. If this works for everyone in the pass manager, we’ll be able to incrementally push outwards from there and loop in other parts of LLVM. Plus, this is allowing us to avoid changing the textual IR for the moment, which is going to be a chore.

Flipping this switch is going to expose downstream tests to RemoveDIs, and I imagine people will encounter some variation in their tests, so I thought I’d summarise the kind of variation we’re expecting see. These come in the forms of “inconsequential output variation”, “Your downstream code might need updating” and “definitely a bug”.,

You can keep your merge going by pinning tests to intrinsic-mode temporarily. Add “–experimental-debuginfo-iterators=false” to your RUN lines. You can also open github issues and link them to [DebugInfo][RemoveDIs] Umbrella ticket for problems with "new" non-instr debug-info · Issue #74735 · llvm/llvm-project · GitHub , and we can give you a hand.

The inconsequential variations we’d expect to see:

  • Attributes attached to the declarations of debugging intrinsics may change, because the declarations aren’t present during the optimisation pipeline. There’s no functional consequence to this change.
  • Debug intrinsic calls in the output may grow the “tail” flag. The flag is meaningless for debug intrinsics, usually attached eagerly during optimisation. We’ve canonicalized the output to always be marked “tail” now as it breaks the fewest tests, with CHECK lines that don’t expect “tail” safely ignoring it.
  • Some tests examine the output of passes printed with the “-debug” flag, and won’t show any intrinsics as they’re not present any more. Unless it’s a debug-info pass, variation here is fine.
  • Numerous issues where debug-info affects the code generated by LLVM are going to fix themselves: if you see codegen changes, check whether your test accidentally relies on such a bug by passing -strip-debug to opt, to obtain the correct code to be generated.
  • Source locations from debug-intrinsics often leak into “real” instructions, something that won’t happen any more. This can cause metadata node-numbers to re-order: if your test relies on hardcoded numbers, use FileCheck variable captures instead.

Issues with downstream code might cause some variation too – there’s some documentation here What’s all this then? — LLVM 19.0.0git documentation about what’s going on.

  • The most likely cause of any meaningful test variation is using instruction pointers to express an insertion position: you now need to use a BasicBlock::iterator instead. This can present itself as dbg.value intrinsics shifting around.
  • Assertions firing saying that PHI nodes are not grouped at the start of a block are caused by the above bullet point too. Not using an iterator can cause PHIs to be inserted after debug-info records instead of before them, which then causes issues when the IR is converted back to intrinsic form.
  • Assertions about “IsNewDbgInfoFormat” having a mismatched value indicates your code has ended up mixing intrinsic-form and non-intrinsic-form debug-info. If you’re creating and using Functions and BasicBlocks before inserting them into a parent, they’ll default to “IsNewDbgInfoFormat=false”.

Any crashes aside from the two assertion-failures mentioned above means something is definitely wrong. Any scenarios where there are too many debug intrinsics printed in the output or too few means something’s very wrong too. We’ve tried to reduce test-changes involved in apply the switch-throwing patch, so it should be an easy revert if it becomes necessary.

2 Likes