← board

imm-fold: constant BINOP operand into the instruction immediate (-O1, x86-64)

What

Pass 1 already loads a constant right operand into rcx (mov rcx, imm; <op> rax, rcx). For arithmetic/logic ops that have an rax, imm32 encoding, fold the constant straight into the instruction and drop the rcx load entirely:

mov rcx, imm32 ; add rax, rcx      ->     add rax, imm32

Removes one instruction (5-7 bytes) per constant arithmetic/logic operand. Frequent in the compiler (x + k, x - k, masks, pointer+offset), so it should show on the self-compile.

Scope (safe subset)

Fast path at the top of IR_BINOP (ir_codegen.inc), gated OptLevel >= 1, when the right operand is IR_CONST_INT fitting imm32 and the op is one of:

op encoding
+ add rax, imm32 = 48 05 id
- sub rax, imm32 = 48 2D id
and and rax, imm32 = 48 25 id
or or rax, imm32 = 48 0D id
xor xor rax, imm32 = 48 35 id
* imul rax, rax, imm32 = 48 69 C0 id

All sign-extend imm32 to 64 bits, exactly matching pass 1's mov rcx, imm32 (sign-ext); <op> rax, rcx — so the result is bit-identical, no width fixup needed (these ops operate on the full rax and downstream truncates to the result type, unchanged).

Excluded: float and tyAnsiString results (guarded — those take the ucomisd / concat paths); comparisons (leave to the cmp rax,rcx / compare-into- branch-fusion path); div/mod (no imm form); shifts (the shift path's <8-byte width fixup would have to be replicated — separate work, same hazard noted for strength reduction).

Gates

Log