Skip to content

Fatal Error in register allocation with llvm.smul.with.overflow.i128 intrinsic and 5 fixed registers #45

Description

@marcauberer

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions