> On 15 Oct 2026, at 05:56, Jeff Law <[email protected]> wrote:
> 
> 
> 
> On 9/22/26 3:33 AM, [email protected] wrote:
>> From: Kyrylo Tkachov <[email protected]>
>> 
>> A bytecode interpreter written with a switch at its loop head normally has 
>> one
>> jump-table dispatch.  Every opcode transition returns to the same indirect
>> branch instruction.  This can make indirect target prediction less effective.
>> The existing compgotos pass already gives each eligible predecessor its own
>> computed goto.  Apply the same transformation to the jump-table form.
>> 
>> The guarded tablejump is a short chain rather than one block:
>> 
>>   handler -> fetch and range check -> tablejump
>> 
>> Collect the single-predecessor fall-through chain and copy it into eligible
>> predecessors.  The copies share the table through the representation added by
>> the first patch.  Require a direct DFS back edge into the collected chain 
>> head
>> before the first tablejump duplication.  This limits the new transformation
>> to a loop head.  Recursive copies do not repeat the test.  Computed gotos 
>> keep
>> their existing behavior.
>> 
>> Use the existing max-goto-duplication-insns budget.  Charge the tablejump as
>> one unconditional-jump unit and charge every accompanying RTL instruction at
>> its minimum length.  A zero budget rejects the transformation.  Require the
>> target's can_share_jump_table_p hook to permit sharing and reject
>> partitioned functions.
>> 
>> Reject functions that use stack registers.  Stack-register conversion can
>> split outgoing edges to reconcile different stack layouts, but a shared-table
>> edge cannot be changed for only one dispatch.
>> 
>> Set PROP_rtl_allow_tablejump_duplication only while the pass scans and copies
>> dispatches.  Clear it before CFG cleanup and before any later pass runs.
>> 
>> Plugin tests check per-function target options, both default hook results,
>> existing instruction-copy vetoes, and output after eligibility becomes false.
>> 
>> On an AArch64 Vera system, explicit enablement improves 714.cpython_r by
>> 10.3%, mawk by 6.9%, and QuickJS-ng by 24.9%.
>> 
>> gcc/ChangeLog:
>> 
>> PR middle-end/126236
>> * common.opt (fduplicate-switch-dispatch): New option.
>> * doc/invoke.texi: Document it.
>> * params.opt (max-goto-duplication-insns): Mention switch dispatches.
>> * bb-reorder.cc (dispatch_jump_p): New function.
>> (can_attach_dispatch_copy_p): New function.
>> (find_dispatch_chain): New function.
>> (maybe_duplicate_computed_goto): Rename to...
>> (maybe_duplicate_dispatch): ...this.  Copy a dispatch chain and
>> optionally require a DFS back edge into its head.
>> (duplicate_computed_gotos): Mark DFS back edges, select eligible
>> tablejumps, and scope PROP_rtl_allow_tablejump_duplication.
>> 
>> gcc/testsuite/ChangeLog:
>> 
>> PR middle-end/126236
>> * gcc.dg/plugin/plugin.exp: Register the capability test.
>> * gcc.dg/plugin/tablejump_capability_plugin.cc: New plugin.
>> * gcc.dg/plugin/tablejump-capability.c: New test.
>> * gcc.dg/plugin/tablejump-test.h: New test header.
>> * gcc.dg/switch-dispatch-2.c: New test.
>> * gcc.dg/switch-dispatch-3.c: New test.
>> * gcc.dg/torture/switch-dispatch-run-1.c: New test.
>> * gcc.dg/torture/switch-dispatch-run-2.c: New test.
>> * gcc.dg/torture/switch-dispatch-run-3.c: New test.
>> * gcc.dg/torture/switch-dispatch-run-4.c: New test.
>> * gcc.target/aarch64/switch-dispatch-1.c: New test.
>> * gcc.target/aarch64/switch-dispatch-2.c: New test.
>> * gcc.target/aarch64/switch-dispatch-3.c: New test.
>> * gcc.target/aarch64/switch-dispatch-4.c: New test.
>> * gcc.target/aarch64/switch-dispatch-5.c: New test.
>> * gcc.target/aarch64/switch-dispatch-6.c: New test.
>> * gcc.target/aarch64/switch-dispatch-7.c: New test.
>> 
>> Signed-off-by: Kyrylo Tkachov <[email protected]>
> So we've got an explicit opt-in.  I'd tend to lean towards opt-out since if 
> we do this right it should work on any target except those which implicitly 
> assume the jump table immediately follows the jump.   If we have good tests 
> which we strongly believe will test execution paths for a shared table, then 
> we can quickly evaluate how the majority of our targets behave in my tester 
> to catch targets we might have missed.  Targets which don't have real 
> execution testing we can opt-out and let the port owners know they may want 
> to re-evaluate.  The dispatch-run tests would seem to fit the need.
> 

Yes, we can do that. We’d need to take into account:

- On targets without a length attribute, get_attr_min_length returns 0. Then 
--param=max-goto-duplication-insns does not limit the copies, and 0 does not 
disable them. Computed gotos already behave like this. I would count one unit 
per insn on such targets.
- hw-doloop (arc, bfin, c6x, xtensa) must not redirect a hardware-loop entry 
edge that comes from a shared table.
- When every predecessor takes a copy, the original dispatch is deleted and its 
table can end up last in the function. alpha and ia64 look for a final call or 
trap with prev_active_insn, and the ia64 stop-bit code expects the insn before 
a table to be its jump. These must handle such a table. Or we opt these targets 
out initially ;)

I can flesh out the tests in the next revision.

> It never really occurred to me, does this muck up loop structure?  I guess 
> it's running late enough to not matter.  So call it curiosity rather than a 
> review concern.

There is no loop structure to update at that point.  compgotos runs after
the RTL loop passes have cleared PROP_loops and freed the loop tree.

The handlers now dispatch to each other directly, so the
dispatch loop becomes an irreducible region.  Unlike computed-goto
edges, tablejump edges are not abnormal, so a handler that can dispatch
to itself also becomes a small natural loop.  The later passes that look
at loops (if_after_reload, compute_alignments and some machine reorgs)
use AVOID_CFG_MODIFICATIONS.

On AArch64 the exception was selective
scheduling with pipelining.  It tried to create preheaders for those
small loops by redirecting shared-table edges.  That is why patch 1
makes is_cfg_nonregular reject shared tables, and switch-dispatch-7.c
covers it.  Under opt-out, hw-doloop is a second case (see above).

Thanks,
Kyrill

> 
> This is sensible.  OK if and when the prereqs are approve.d
> 
> jeff


Reply via email to