https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126236

--- Comment #9 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Kyrylo Tkachov <[email protected]>:

https://gcc.gnu.org/g:b38631a6013f872940857bcc935f56db0b5f427a

commit r17-5805-gb38631a6013f872940857bcc935f56db0b5f427a
Author: Kyrylo Tkachov <[email protected]>
Date:   Thu Oct 15 20:06:37 2026 +0200

    config: Opt out of shared jump tables where dispatch needs adjacency [PR
middle-end/126236]

    Several ports dispatch through a table that has to follow the jump, or
    compute the table entries from the address of the jump.  A copy of such a
    dispatch elsewhere in the function would branch to the wrong place, fail
    to assemble or break a machine reorg pass.  These ports refuse to share
    jump tables:

    - arm: Thumb-2 tbb and tbh read the table at the PC, the Thumb-1 casesi
      helpers find it from LR, and the Arm casesi sequence defines a base label
      after each dispatch.  arm_reorg also expects every table to follow its
      jump.
    - cris: casesi reads the table at its own PC, and cris_asm_output_case_end
      expects the jump right before the table label.
    - m68k: the relative dispatch forms read the table at a fixed offset from
      the PC.
    - sh: fixup_addr_diff_vecs makes the entries relative to the braf of one
      dispatch, and sh_reorg pairs every table with one mova.
    - xstormy16: the dispatch branches into a table of jmpf insns that follows
      it.
    - vax: the casel table is part of the instruction.

    These ports refuse only some forms:

    - pa: with PIC, which includes all 64-bit code, casesi32p and casesi64p
      reach the table with one ldo from their own address.  Its displacement
      only reaches a table close to the jump.  casesi32 loads the address of
      the table and can share it.
    - c6x: with PIC, casesi_internal reaches the table with addkpc, which only
      covers about 256 bytes.
    - mips: with MIPS16 short jump tables, the length of the casesi dispatch
      assumes the short ADDIUPC form of the la of the table, which only a
      nearby table guarantees.
    - csky: with -mconstpool, which CK801 and CK802 require, the constant pool
      scan steps from every tablejump to the table that follows it.
    - arc: the bi and bih dispatches of -mbranch-index branch into a table of
      branches that follows them.
    - rx: with -mpid or -fpic, the table entries are relative to a local label
      that the dispatch defines.

    The port maintainers can refine these predicates later.

    gcc/ChangeLog:

            PR middle-end/126236
            * config/arc/arc.cc (arc_can_share_jump_table_p): New function.
            (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/arm/arm.cc (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/c6x/c6x.cc (c6x_can_share_jump_table_p): New function.
            (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/cris/cris.cc (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/csky/csky.cc (csky_can_share_jump_table_p): New function.
            (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/m68k/m68k.cc (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/mips/mips.cc (mips_can_share_jump_table_p): New function.
            (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/pa/pa.cc (pa_can_share_jump_table_p): New function.
            (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/rx/rx.cc (rx_can_share_jump_table_p): New function.
            (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/sh/sh.cc (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.
            * config/stormy16/stormy16.cc (TARGET_CAN_SHARE_JUMP_TABLE_P):
Define.
            * config/vax/vax.cc (TARGET_CAN_SHARE_JUMP_TABLE_P): Define.

    Signed-off-by: Kyrylo Tkachov <[email protected]>

--- Comment #10 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Kyrylo Tkachov <[email protected]>:

https://gcc.gnu.org/g:87b07d2a5edc6b97f816b8b2f16bc3d13031f439

commit r17-5806-g87b07d2a5edc6b97f816b8b2f16bc3d13031f439
Author: Kyrylo Tkachov <[email protected]>
Date:   Thu Oct 15 20:11:38 2026 +0200

    bb-reorder: Unfactor loop switch dispatches [PR middle-end/126236]

    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.  Take a block into the chain only through a plain
fall-through
    edge: a jump at its end that also targets the next block would still name
    the original block after the edge moves to the copy.  The copies share the
    table through the representation added by the cfgrtl 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 budget unit and every other instruction at its size, as for computed
    gotos.  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.

    switch-dispatch-run-5.c sends every dispatch copy to every case and to
    out-of-range values, and checks the exact path with a trace.  run-6.c and
    run-7.c give handlers enough code that some copies are far from the table,
    with and without PIC.  run-8.c has an asm goto that targets its own
    fall-through block above the switch.  switch-dispatch-hwloop.c and the bfin
    and xtensa tests reach a hardware loop through a shared table.  In
    switch-dispatch-placement.c the original dispatch is deleted after a
noreturn
    call or a return, so its table has to move.  switch-dispatch-4.c checks
that
    both tables of the trace test are shared on the targets that the new
    shared_jump_tables effective target lists.  Plugin tests check per-function
    target options, the default hook result, existing instruction-copy vetoes,
    and output after eligibility becomes false.

    On an NVIDIA 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.
            * doc/params.texi (max-goto-duplication-insns): Mention switch
            dispatches.
            * doc/sourcebuild.texi (shared_jump_tables): Document.
            * params.opt (max-goto-duplication-insns): Mention switch
dispatches.
            * common.opt.urls: Regenerate.
            * bb-reorder.cc (dispatch_jump_p): New function.
            (can_attach_dispatch_copy_p): New function.
            (fallthru_unified_with_branch_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
            * lib/target-supports.exp
            (check_effective_target_shared_jump_tables): New.
            * 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/switch-dispatch-4.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.dg/torture/switch-dispatch-run-5.c: New test.
            * gcc.dg/torture/switch-dispatch-run-6.c: New test.
            * gcc.dg/torture/switch-dispatch-run-7.c: New test.
            * gcc.dg/torture/switch-dispatch-run-8.c: New test.
            * gcc.dg/torture/switch-dispatch-hwloop.c: New test.
            * gcc.dg/torture/switch-dispatch-placement.c: New test.
            * gcc.target/bfin/switch-dispatch-1.c: New test.
            * gcc.target/xtensa/switch-dispatch-1.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]>

Reply via email to