ggreif edited PR #13458.
ggreif edited PR #13458:
Extends #13343's
simplify_skeletonfold so the existing
brif (ctz X)/brif (clz X)rules also fire when anireduce
(i.e.i32.wrap_i64at the wasm level) sits between the count and
the branch.Why this matters: non-Rust frontends targeting wasm-EOP often emit
i64.ctz; i32.wrap_i64; br_iffor boolean-context LSB tests. The
wrap is harmless (the count is in [0, 64]) but it currently blocks
the fold, so cranelift falls back to materializing the full count
before the branch. With this PR, the i64-wrap form lowers to the
sametestq \$1, %rdx; jeshape as the i32 case.Test coverage mirrors the existing patterns:
cranelift/filetests/.../brif-cnt-cond.clifgets two new
brif (ireduce (ctz/clz X))functions.
tests/disas/ctz-clz-bool-condition.watgets a new
\`\$if_clz_bare_i64\` and the existing \`\$if_ctz_bare_i64\`
is reblessed - both now lower to the optimal shape.Source pattern in the wild: Motoko/
moc's EOP peephole
(motoko PR #6117)
emits exactly \`i64.ctz; i32.wrap_i64; br_if\` for
\`(value & 1) == 0\`-as-branch-condition.
ggreif edited PR #13458:
Extends #13343's
simplify_skeletonfold so the existing
brif (ctz X)/brif (clz X)rules also fire when anireduce
(i.e.i32.wrap_i64at the wasm level) sits between the count and
the branch.Why this matters: non-Rust frontends targeting wasm-EOP often emit
i64.ctz; i32.wrap_i64; br_iffor boolean-context LSB tests. The
wrap is harmless (the count is in [0, 64]) but it currently blocks
the fold, so cranelift falls back to materializing the full count
before the branch. With this PR, the i64-wrap form lowers to the
sametestq $1, %rdx; jeshape as the i32 case.Test coverage mirrors the existing patterns:
cranelift/filetests/.../brif-cnt-cond.clifgets two new
brif (ireduce (ctz/clz X))functions.
tests/disas/ctz-clz-bool-condition.watgets a new
$if_clz_bare_i64and the existing$if_ctz_bare_i64
is reblessed - both now lower to the optimal shape.Source pattern in the wild: motoko/moc's EOP peephole
(motoko PR #6117)
emits exactlyi64.ctz; i32.wrap_i64; br_iffor
(value & 1) == 0-as-branch-condition.
ggreif edited PR #13458:
Extends #13343's
simplify_skeletonfold so the existing
brif (ctz X)/brif (clz X)rules also fire when anireduce
(i.e.i32.wrap_i64at the wasm level) sits between the count and
the branch.Why this matters: non-Rust frontends targeting wasm-EOP often emit
i64.ctz; i32.wrap_i64; br_iffor boolean-context LSB tests. The
wrap is harmless (the count is in [0, 64]) but it currently blocks
the fold, so cranelift falls back to materializing the full count
before the branch. With this PR, the i64-wrap form lowers to the
sametestq $1, %rdx; jeshape as the i32 case.Test coverage mirrors the existing patterns:
cranelift/filetests/.../brif-cnt-cond.clifgets two new
brif (ireduce (ctz/clz X))functions.
tests/disas/ctz-clz-bool-condition.watgets a new
$if_clz_bare_i64and the existing$if_ctz_bare_i64
is reblessed - both now lower to the optimal shape.Source pattern in the wild: Motoko/
moc's EOP peephole
(motoko PR #6117)
emits exactlyi64.ctz; i32.wrap_i64; br_iffor
(value & 1) == 0-as-branch-condition.
:speech_balloon: cfallin created PR review comment:
let's use lowercase bindings (here
X->x) -- no particular syntactic rules against uppercase but it's not our style.
:thumbs_up: cfallin submitted PR review:
Thanks! New rule looks good; just some style comments.
:speech_balloon: cfallin created PR review comment:
No need for the verbose comment here -- and we don't want to pollute the ruleset with discussion about particular use-cases ("motoko/moc's EOP peephole" etc) as that isn't needed to justify straightforward simplifications.
:speech_balloon: cfallin created PR review comment:
Likewise here, let's not pollute with comments about particular other projects' code emission patterns. Actually most of the other tests don't have comments justifying their existence (more tests are always fine!) so no need to add them here.
ggreif updated PR #13458.
ggreif edited PR #13458:
Extends #13343's
simplify_skeletonfold so the existing
brif (ctz X)/brif (clz X)rules also fire when anireduce
(i.e.i32.wrap_i64at the wasm level) sits between the count and
the branch.Why this matters: non-Rust frontends targeting wasm-EOP often emit
i64.ctz; i32.wrap_i64; br_iffor boolean-context LSB tests. The
wrap is harmless (the count is in [0, 64]) but it currently blocks
the fold, so cranelift falls back to materializing the full count
before the branch. With this PR, the i64-wrap form lowers to the
sametestq $1, %rdx; jeshape as the i32 case.Test coverage mirrors the existing patterns:
cranelift/filetests/.../brif-cnt-cond.clifgets two new
brif (ireduce (ctz/clz X))functions.
tests/disas/ctz-clz-bool-condition.watgets a new
$if_clz_bare_i64and the existing$if_ctz_bare_i64
is reblessed - both now lower to the optimal shape.
ggreif edited PR #13458:
Extends #13343's
simplify_skeletonfold so the existing
brif (ctz X)/brif (clz X)rules also fire when anireduce
(i.e.i32.wrap_i64at the wasm level) sits between the count and
the branch.Why this matters: non-Rust frontends targeting wasm64 often emit
i64.ctz; i32.wrap_i64; br_iffor boolean-context LSB tests. The
wrap is harmless (the count is in [0, 64]) but it currently blocks
the fold, so cranelift falls back to materializing the full count
before the branch. With this PR, the i64-wrap form lowers to the
sametestq $1, %rdx; jeshape as the i32 case.Test coverage mirrors the existing patterns:
cranelift/filetests/.../brif-cnt-cond.clifgets two new
brif (ireduce (ctz/clz X))functions.
tests/disas/ctz-clz-bool-condition.watgets a new
$if_clz_bare_i64and the existing$if_ctz_bare_i64
is reblessed - both now lower to the optimal shape.
ggreif edited PR #13458:
Extends #13343's
simplify_skeletonfold so the existing
brif (ctz x)/brif (clz x)rules also fire when anireduce
(i.e.i32.wrap_i64at the wasm level) sits between the count and
the branch.Why this matters: non-Rust frontends targeting wasm64 often emit
i64.ctz; i32.wrap_i64; br_iffor boolean-context LSB tests. The
wrap is harmless (the count is in [0, 64]) but it currently blocks
the fold, so cranelift falls back to materializing the full count
before the branch. With this PR, the i64-wrap form lowers to the
sametestq $1, %rdx; jeshape as the i32 case.Test coverage mirrors the existing patterns:
cranelift/filetests/.../brif-cnt-cond.clifgets two new
brif (ireduce (ctz/clz x))functions.
tests/disas/ctz-clz-bool-condition.watgets a new
$if_clz_bare_i64and the existing$if_ctz_bare_i64
is reblessed - both now lower to the optimal shape.
ggreif edited PR #13458:
Extends #13343's
simplify_skeletonfold so the existing
brif (ctz X)/brif (clz X)rules also fire when anireduce
(i.e.i32.wrap_i64at the wasm level) sits between the count and
the branch.Why this matters: non-Rust frontends targeting wasm64 often emit
i64.ctz; i32.wrap_i64; br_iffor boolean-context LSB tests. The
wrap is harmless (the count is in [0, 64]) but it currently blocks
the fold, so cranelift falls back to materializing the full count
before the branch. With this PR, the i64-wrap form lowers to the
sametestq $1, %rdx; jeshape as the i32 case.Test coverage mirrors the existing patterns:
cranelift/filetests/.../brif-cnt-cond.clifgets two new
brif (ireduce (ctz/clz X))functions.
tests/disas/ctz-clz-bool-condition.watgets a new
$if_clz_bare_i64and the existing$if_ctz_bare_i64
is reblessed - both now lower to the optimal shape.
:memo: ggreif submitted PR review.
:speech_balloon: ggreif created PR review comment:
I think I used line 466 as a precedent.
:speech_balloon: ggreif edited PR review comment.
:memo: ggreif submitted PR review.
:speech_balloon: ggreif created PR review comment:
Comment minimised, but kept.
ggreif updated PR #13458.
:thumbs_up: cfallin submitted PR review.
cfallin added PR #13458 egraph: peer through ireduce in brif (ctz/clz) skeleton fold to the merge queue.
github-merge-queue[bot] removed PR #13458 egraph: peer through ireduce in brif (ctz/clz) skeleton fold from the merge queue.
cfallin added PR #13458 egraph: peer through ireduce in brif (ctz/clz) skeleton fold to the merge queue.
:check: cfallin merged PR #13458.
cfallin removed PR #13458 egraph: peer through ireduce in brif (ctz/clz) skeleton fold from the merge queue.
Last updated: Jun 01 2026 at 09:49 UTC