Skip to content

x64: lower isub by a constant to lea - #14015

Open
darmie wants to merge 2 commits into
bytecodealliance:mainfrom
darmie:x64-isub-const-lea
Open

x64: lower isub by a constant to lea#14015
darmie wants to merge 2 commits into
bytecodealliance:mainfrom
darmie:x64-isub-const-lea

Conversation

@darmie

@darmie darmie commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

iadd of a value and a 32/64-bit constant already lowers to lea, folding
the constant into the address displacement and computing the result in a
different register than the input without a separate mov. isub by a
constant did not have a matching rule: it fell through to the two-operand
sub, which forces a mov+sub pair whenever the destination register
differs from the source.

This adds a rule that lowers x - C (for a 32- or 64-bit integer constant
C) to lea -C(x), mirroring the existing iadd path. The rule fires only
when the negated constant fits in an Offset32 (i.e. C is not i32::MIN);
register/register isub is unchanged.

Example

function %isub_c2(i64) -> i64 {
block0(v0: i64):
    v1 = iconst.i64 2
    v2 = isub v0, v1
    return v2
}

Before:

movq %rdi, %rax
subq $2, %rax

After:

leaq -2(%rdi), %rax

One instruction instead of two, and no flags clobbered.

Testing

  • New precise-output filetest (isub-const-lea.clif) asserting the lea
    lowering for i64 and i32, and that register/register isub still lowers
    to sub.
  • New runtest exercising x - C (including a negative constant) on the
    interpreter and every native target.
  • The existing isa/x64 filetests pass unchanged.

I found this while profiling a call/arithmetic-heavy workload where every
argument setup was an x - C; folding the mov away was a measurable win.

@darmie
darmie requested a review from a team as a code owner July 29, 2026 09:19
@darmie
darmie requested review from cfallin and removed request for a team July 29, 2026 09:19
@darmie
darmie force-pushed the x64-isub-const-lea branch from 8888063 to 39c2a52 Compare July 29, 2026 09:30
@darmie
darmie requested a review from a team as a code owner July 29, 2026 09:30
@darmie

darmie commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a fixup: refreshed the 12 load-store/x64 disas goldens that the CLI disas test flagged. Those are dynamic-memory bounds checks that compute bound - access_size in place; with this rule that sub $C now goes through lea and degenerates to add $-C — the same instruction count, and identical to how iadd by a constant already lowers today (verified isub v, C and iadd v, -C produce byte-identical output). The win over the old mov+sub shows up when the result lands in a different register than the input.

@github-actions github-actions Bot added cranelift Issues related to the Cranelift code generator cranelift:area:x64 Issues related to x64 codegen isle Related to the ISLE domain-specific language labels Jul 29, 2026
@github-actions

Copy link
Copy Markdown

Subscribe to Label Action

cc @cfallin, @fitzgen

Details This issue or pull request has been labeled: "cranelift", "cranelift:area:x64", "isle"

Thus the following users have been cc'd because of the following labels:

  • cfallin: isle
  • fitzgen: isle

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@cfallin

cfallin commented Jul 29, 2026

Copy link
Copy Markdown
Member

Hi @darmie -- are you aware of the add-vs-lea performance discussion thread we had recently (#13325)? I ask because at the very least, we should benchmark this change with the full Sightglass suite. I am also pretty leery in general of introducing more uses of LEA given the performance variability that we've seen on different systems. I'm not surprised that you saw a speedup on one particular benchmark since LEA is "non-destructive" (doesn't clobber the source) but I'd be curious to know how this looks overall. Thanks!

@darmie

darmie commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Hi @cfallin! Actually I am not aware of that thread, I should have searched first. Yes I saw a performance improvement on my alderlake x86_64 box, but it's only ~6.9% so far. I'll read through the thread now.

darmie added 2 commits August 1, 2026 09:22
`iadd` of a value and a constant already lowers to `lea`, folding the
constant into the address displacement and avoiding a register copy when the
result lands in a different register than the input. `isub` by a constant
did not: it fell to the two-operand `sub`, which forces a `mov`+`sub` pair
whenever the destination differs from the source.

Lower `x - C` to `lea -C(x)` for 32- and 64-bit types, mirroring the `iadd`
path. The rule fires only when the negated constant fits in an `Offset32`
(i.e. `C` is not `i32::MIN`); register/register `isub` is unchanged.
- Precise-output filetest asserting `x - C` lowers to a single `lea`, and
  that register/register `isub` still lowers to `sub`.
- Runtest exercising the result on the interpreter and every native target.
- Refresh the `load-store/x64` disas goldens: the in-place bounds-check
  `sub $C` now lowers via `lea` to `add $-C`, identical to how `iadd` by a
  constant already lowers (same instruction count).
@darmie
darmie force-pushed the x64-isub-const-lea branch from 39c2a52 to 10bdb3b Compare August 1, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cranelift:area:x64 Issues related to x64 codegen cranelift Issues related to the Cranelift code generator isle Related to the ISLE domain-specific language

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants