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

--- Comment #7 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:e6c1e90930a6cb65664ab8c066514079244f8a44

commit r17-5803-ge6c1e90930a6cb65664ab8c066514079244f8a44
Author: Kyrylo Tkachov <[email protected]>
Date:   Thu Oct 15 20:01:58 2026 +0200

    cfgrtl: Allow duplicated tablejumps to share a dispatch table [PR
middle-end/126236]

    An RTL basic block that ends in a tablejump cannot normally be duplicated.
    The instructions that compute the table address can be outside the block,
so
    copying and retargeting the table is not reliable.

    Let an opted-in pass keep one table instead.  Before duplication, one jump
    owns the adjacent table:

      jump A -> label T -> addr_diff_vec

    After duplication, both jumps name the same label and table:

      jump A --\
                 label T -> addr_diff_vec
      jump B --/

    Mark the table with the sticky JUMP_TABLE_SHARED_P flag.  A shared table is
    immutable because each entry describes a successor of every dispatch that
    uses it.  Block deletion can remove one dispatch but must retain the table
for
    the others.

    The table still follows one of the jumps through it.  When the block that
    the table follows is deleted, move the table after another jump through it:

      jump A; label T; addr_diff_vec        (A deleted)
      ...                             ->    ...
      jump B                                jump B; label T; addr_diff_vec

    So the insn before a table in use is still a jump through it, which is what
    code that looks back from a table, or for the last insn of a function,
    expects.  get_last_bb_insn includes a shared table only when the table
    follows the block.  If no other jump uses the table, leave it to
    delete_dead_jumptables.

    Add PROP_rtl_allow_tablejump_duplication as a function property.  The RTL
hook
    uses it to permit the copy, retain JUMP_LABEL, and mark the table.  A pass
can
    set the property while it is prepared for the table to become immutable.

    Guard the RTL redirection, deletion, fall-through, merge, and cross-jump
paths
    that assume one owner or physical adjacency.  Add checking assertions for
    bulk deletion and verify every shared dispatch against the table
successors.

    Treat shared tablejumps as nonregular for interblock scheduling.  This
prevents
    selective scheduling from splitting shared-table edges to create loop
    preheaders or bookkeeping blocks.  Likewise, do not let hw-doloop redirect
    the entry edges of a hardware loop when one of them comes from a shared
    tablejump.  Add shared_tablejump_p for these checks.

    No pass opts in in this patch, so it does not change generated code by
    itself.

    gcc/ChangeLog:

            PR middle-end/126236
            * tree-pass.h (PROP_rtl_allow_tablejump_duplication): New property.
            * cfgcleanup.cc (outgoing_edges_match): Reject matches involving a
            shared jump table.
            * cfgrtl.cc (shared_jump_table_component_p): New function.
            (shared_jump_table_between_p): Likewise.
            (hosted_shared_table): Likewise.
            (other_table_user): Likewise.
            (move_table_after): Likewise.
            (delete_insn_chain): Assert that the range does not contain a
shared
            jump table.
            (rtl_delete_block): Move a shared table that follows the block
after
            another jump through it.
            (can_fallthru, rtl_can_merge_blocks, rtl_tidy_fallthru_edge): Do
not
            remove or cross a shared jump table between basic blocks.
            (cfg_layout_can_duplicate_bb_p): Allow a tablejump when the new
            property is set.
            (duplicate_insn_chain): Retain a copied tablejump's table and mark
it
            shared.
            (patch_jump_insn): Refuse to redirect through a shared table before
            creating a label for the new destination.
            (try_redirect_by_replacing_jump): Do not delete a shared table.
            (get_last_bb_insn): Include a shared table only if it follows the
            block.
            (force_nonfallthru_and_redirect): Likewise.
            (rtl_verify_edges): Check each shared table against the successors
of
            each dispatch that uses it.
            * hw-doloop.cc (discover_loop): Reject a loop that is entered from
a
            shared tablejump.
            * jump.cc (delete_related_insns): Do not delete a shared table.
            * rtl.h (JUMP_TABLE_SHARED_P): New macro.
            (rtx_def): Document the shared-table use of the unchanging flag.
            (shared_tablejump_p): Declare.
            * rtlanal.cc (shared_tablejump_p): New function.
            * sched-rgn.cc (is_cfg_nonregular): Reject shared tablejumps.
            * doc/cfg.texi: Document shared jump tables.
            * doc/md.texi: Likewise.
            * doc/rtl.texi (Flags): Document JUMP_TABLE_SHARED_P.
            (Insns): Document shared jump tables.

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

Reply via email to