Stream: cranelift

Topic: Can constants be propagated to jump tables in cranelift IR?


view this post on Zulip Stanley (Apr 14 2026 at 05:55):

Hello, I am working on a JIT compiler for a stack-based language similar to Forth.

I have noticed that Cranelift seems to be generating this IR (after calling Context::optimize):

block6:
    v32 = iconst.i32 0
    br_table v32, block1, [block2, block3, block4, block5]  ; v32 = 0

And, Cranelift is emitting x86 instructions for the jump table, even though it knows at compile time which branch will be taken, since the value of v32 is known at compile time. Is this an optimization that the cranelift compiler cannot make, or am I doing something incorrectly? Thanks.

view this post on Zulip Notification Bot (Apr 14 2026 at 13:21):

This topic was moved here from #general > Can constants be propagated to jump tables in cranelift IR? by fitzgen (he/him).

view this post on Zulip fitzgen (he/him) (Apr 14 2026 at 13:37):

Cranelift will not currently do branch folding or rewriting conditional jumps to unconditional jumps in the mid-end

we do some branch folding in the backend but I don't think we will ever rewrite conditional jumps on constant conditions to unconditional jumps at this point, which is what would be necessary for the branch-folding to happen here

I think we could do that during isel/lowering, and I suspect we just haven't done it for br_table yet

view this post on Zulip fitzgen (he/him) (Apr 14 2026 at 13:51):

hm actually it looks like we don't ever try to turn conditional jumps of constants into unconditional jumps during lowering:

I don;t think there is a reason we couldn't though? cc @Chris Fallin

view this post on Zulip Chris Fallin (Apr 14 2026 at 14:48):

right, the only reason we don't do this is "no one has done it" :-)

The more complete solution would do it as part of the same fixpoint that optimizes code in the mid-end because this can interact in a recursive way with const propagation -- when we trim the CFG, unreachable paths go away and no longer affect the merged possibility-space, possibly leading to more known constants -- and in fullness of time it'd be great to implement that (the general algorithm to at least draw inspiration from is known as SCCP or sparse conditional constant propagation, though it'd need to be adapted a bit to our egraph framework). But I could see us landing a separate (post-opt) version in the meantime, where brif/br_table-of-constant gets folded to a direct branch

view this post on Zulip fitzgen (he/him) (Apr 14 2026 at 14:51):

yeah doing we have this comment about simplifying branching instructions in the mid-end, figured that was a slightly longer-term thing than just pattern matching during lowering tho

view this post on Zulip Chris Fallin (Apr 14 2026 at 14:54):

Right, I guess there's always the conservative approach of actually switching to a direct branch in the CLIF post-mid-end (as a pass after the aegraph before we do lowering) -- we don't have any remaining cached analysis results at that point we'd need to worry about. I think that comment mostly applies to doing anything in the main fixpoint loop

view this post on Zulip fitzgen (he/him) (Apr 14 2026 at 15:32):

yeah but I wouldn't want to add a new pass just for this, that doesn't seem like an incremental step towards our desired end state -- it feels like work that would be wasted bc we'd throw it away as soon as we made the next improvement

I guess I imagine the useful incremental steps that ~don't waste work being something like this:

The first step is (a) pretty easy and (b) still useful even with the other things, since it will still fire for ~"free" when we are doing non-optimized compilation and skip the egraphs pass. (As opposed to a whole new pass, which we would throw away by doing the second step.)


Anyways @Stanley if you are interested in implementing that first easy/short-term step, I can explain some more and give you some more code pointers and such

view this post on Zulip Chris Fallin (Apr 14 2026 at 15:51):

eh, I think a single pass over IR terminators isn't so bad and is probably better than making that change in each individual backend -- the latter is also something we won't need long-term (if the mid-end handles this eventually) but is duplicated 5x, plus potentially more if we have special-case lowerings and have to reason about how the priorities interact...

view this post on Zulip fitzgen (he/him) (Apr 14 2026 at 15:59):

yeah I guess so

even better would be to do it in the same backwards pass we use when lowering

but this is all a bit less of a good-first-issue material

view this post on Zulip Stanley (Apr 14 2026 at 15:59):

fitzgen (he/him) said:

Anyways @Stanley if you are interested in implementing that first easy/short-term step, I can explain some more and give you some more code pointers and such

I am very new to Cranelift, and admittedly know very little about its design or the codegen process, but if you believe it to be useful I would be happy to try implementing this. If you could provide some pointers that would be really helpful.

view this post on Zulip fitzgen (he/him) (Apr 15 2026 at 14:49):

@Stanley unfortunately I think the direction we moved towards in the design discussion made it less amenable to being a good-first issue, so I don't think it would be a good place to dive into Cranelift development for the first time anymore

view this post on Zulip Stanley (Apr 15 2026 at 17:36):

fitzgen (he/him) said:

Stanley unfortunately I think the direction we moved towards in the design discussion made it less amenable to being a good-first issue, so I don't think it would be a good place to dive into Cranelift development for the first time anymore

I see. I suppose I will try my best to work around this until it is implemented. Do you know if is there an issue tracking this? I would like to stay updated on it. Thanks.

view this post on Zulip fitzgen (he/him) (Apr 15 2026 at 18:23):

I think https://github.com/bytecodealliance/wasmtime/issues/6106 is probably the best issue to follow

view this post on Zulip Stanley (Apr 15 2026 at 20:05):

I see, thanks.


Last updated: May 03 2026 at 21:15 UTC