On 9/22/26 3:33 AM, [email protected] wrote:
From: Kyrylo Tkachov <[email protected]>
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.
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.
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.
(delete_insn_chain): Assert that the range does not contain a shared
jump table.
(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.
(try_redirect_by_replacing_jump): Do not delete a shared table.
(get_last_bb_insn): Do not treat a shared table as part of one block.
(force_nonfallthru_and_redirect): Likewise.
(rtl_verify_edges): Check each shared table against the successors of
each dispatch that uses it.
* 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.
* sched-rgn.cc (is_cfg_nonregular): Reject shared tablejumps.
* doc/cfg.texi: Document shared jump tables.
* doc/md.texi: Likewise.
* doc/rtl.texi: Likewise.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
So high level question. For ADDR_DIFF_VEC, I think we also have to be
careful that the implementation doesn't use a pc-relative jump under the
hood. The PA used to work like that until circa 2013 (I didn't realize
it'd been rewritten until I started looking at it's code and didn't see
what I expected to see). I can't speak for other ports. I probably
should have included this in the audit request I did the first time
around. However the PA may be using mfia rather than a blr which may
result in it still being pc-relative, just not in the way I expected to
find.
I think the assumption is the we're doing a pc-relative jump using the
table element to get hte difference between the jump site and the final
label (with some minor delta). That has worked because the table
follows the pc-relative indirect jump immediately in the insn stream. I
don't think it's going to work if we share jump tables on targets that
use ADDR_DIFF_VEC.
I would look very closely at cris, vax, sh, stormy16, hppa, c6x, nds32,
s390, ft32, mips (16), arm/thumb2, csky, mn103 and csky. Using
pc-relative in and of itself isn't a problem, but instead a signal that
there may be some implicit dependency on the jump table immediately
following the jump itself.
Jeff