[RegAlloc] Machine scheduler sinks COPY of physreg live-in past inline asm, causing "inline assembly requires more registers than available"
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
This is an issue might relate to RA, I encountered this issue while compiling linux kernel code arch/x86/crypto/curve25519-x86_64.c
Where gcc give correct results but clang fail with
error: inline assembly requires more registers than available
Since I don't have enough understanding about RA/scheduler in X86 so I am submitting this as a bug report with a poc patch and hope someone have deep understanding about RA/scheduler could pick it and see if there is anything could be done.
**Minimal reproducer** (x86-64, `-O2 -fno-omit-frame-pointer -fprofile-arcs`):
```c
/* 11 clobbers + frame pointer = only {rsi, rdi, r12} remain */
static void op1(long out, long f, long tmp) {
__asm__ volatile ("nop"
: "+r"(out), "+r"(f), "+r"(tmp)
: : "rax","rbx","rcx","rdx","r8","r9","r10","r11","r13","r14","r15",
"memory","cc","dirflag","fpsr","flags");
}
void test3(long q) {
op1(0x1234, 0xabcd, 0xef); /* first call */
op1(0x1a2b, 0x3c4d, q); /* second call uses arg q */
}
```
```
$ clang -std=gnu89 -O2 -fno-omit-frame-pointer -fprofile-arcs -c test3.c
error: inline assembly requires more registers than available
```
GCC compiles this successfully, producing one stack spill for `q`.
for clang debug output I got shows:
```
liveins: $rdi
%3 = MOV32ri64 0x1234
%1 = MOV32ri64 0xabcd
%2 = MOV32ri64 0xef
INLINEASM "nop" <11 clobbers> <- first asm
%8 = COPY $rdi <- scheduler sinks this here
INLINEASM "nop" <11 clobbers> <- second asm uses %8
```
my best guess about the root cause of this problem is that after inlining function op1, a COPY is placed after the first inline asm and somehow it caused rdi to be live across the 2nd inline asm. and the workaround I currently can think of is to mimic what gcc does --- breaking the live range of rdi and store it to stack then load it back later so that the inline asm could have enough registers to use(avoid register runout problem)
I have pushed this poc patch to here for reference: https://github.com/lzto/llvm-project/tree/fix/pre-ra-inline-asm-copy-hoist
Contributor guide
Research direction
Start by running the clang command against the minimal reproducer in test3.c and compare the debug output around the sunk COPY and the two INLINEASM instructions. Then inspect the register-allocation and machine-scheduler behavior for the x86 inline-assembly case, using arch/x86/crypto/curve25519-x86_64.c as context. Done means the reproducer no longer fails with register exhaustion while preserving the reported inline-assembly behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100