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]>
