[clang] [llvm] [CodeGen] Fix inline asm clobber-list registers incorrectly marked Ea… (PR #206222)

Jessica Clarke via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 27 19:32:14 PDT 2026


jrtc27 wrote:

> …rlyClobber
> 
> Clobber-list registers specified via `~{reg}` in inline asm constraints are modified _during_ the asm body, not before inputs are read. As such they must NOT carry the EarlyClobber flag — inputs are permitted to use them, matching GCC's behaviour.
> 
> Before this fix, `InlineAsm::Kind::Clobber` fell through into the `InlineAsm::Kind::RegDefEarlyClobber` case in `InstrEmitter::EmitSpecialNode`, causing every clobbered register to receive `RegState::EarlyClobber` in the generated INLINEASM MachineInstr. This prevented the register allocator from ever assigning a clobbered register to any input operand.
> 
> With a heavy clobber list (e.g. rax, rbx, rcx, rdx, r8-r11, r13-r15 — 11 registers), `-fno-omit-frame-pointer` (rbp reserved), and a gcov counter increment between two inlined asm calls (adding register pressure), the allocator ran out of registers and emitted: "inline assembly requires more registers than available"
> 
> The bug was first observed in the Linux kernel's Curve25519 field arithmetic: `fsqr()`/`fsqr2()` in `arch/x86/crypto/curve25519-x86_64.c` use this exact pattern — 11-register clobber lists with `+&r` early-clobber outputs — and fail to compile with clang under CONFIG_GCOV_KERNEL + frame pointer builds. The bug is reproducible with clang 17 through 22 but not with clang 10 or GCC.
> 
> Fix: give `Kind::Clobber` its own case that emits `RegState::Define` only, without `RegState::EarlyClobber`.

Given the style of this commit message is of a certain nature, was an LLM used in the creation of this PR? Please see https://llvm.org/docs/AIToolPolicy.html if so.

https://github.com/llvm/llvm-project/pull/206222


More information about the llvm-commits mailing list