We hit a hard fatal error with this minimal IR reproducer:
define void @trigger_certain(i64 %x, i128 %a, i128 %b) {
entry:
%v1 = add i64 %x, 1
%v2 = add i64 %x, 2
%v3 = add i64 %x, 3
%v4 = add i64 %x, 4
%v5 = add i64 %x, 5
; 5 fixed assignments now live (rbx, r12, r13, r14, r15 — all callee-saved GP regs)
%r = call { i128, i1 } @llvm.smul.with.overflow.i128(i128 %a, i128 %b)
br label %exit
exit:
call void @use(i64 %v1, i64 %v2, i64 %v3, i64 %v4, i64 %v5)
ret void
}
declare void @use(i64, i64, i64, i64, i64)
declare { i128, i1 } @llvm.smul.with.overflow.i128(i128, i128)
./tpde-llc reproducer.ll
[2026-07-22 11:53:44.687] [error] TPDE FATAL ERROR: ran out of registers for scratch registers
Aborted (core dumped)
The problem seems to be, that the encoding function encode_of_mul_i128 uses 10 general purpose registers. If we have 5 fixed registers beforehand, we exceed the 14 GPRs on x86 (not sure if the problem also exists on AArch64).
I tried to manually reduce NUM_FIXED_ASSIGNMENTS from 5 (for register bank 0) to 4. Then the above IR gets compiled fine.
We hit a hard fatal error with this minimal IR reproducer:
The problem seems to be, that the encoding function
encode_of_mul_i128uses 10 general purpose registers. If we have 5 fixed registers beforehand, we exceed the 14 GPRs on x86 (not sure if the problem also exists on AArch64).I tried to manually reduce
NUM_FIXED_ASSIGNMENTSfrom 5 (for register bank 0) to 4. Then the above IR gets compiled fine.