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]> Diff: --- gcc/config/arc/arc.cc | 12 ++++++++++++ gcc/config/arm/arm.cc | 6 ++++++ gcc/config/c6x/c6x.cc | 12 ++++++++++++ gcc/config/cris/cris.cc | 4 ++++ gcc/config/csky/csky.cc | 12 ++++++++++++ gcc/config/m68k/m68k.cc | 5 +++++ gcc/config/mips/mips.cc | 13 +++++++++++++ gcc/config/pa/pa.cc | 15 +++++++++++++++ gcc/config/rx/rx.cc | 12 ++++++++++++ gcc/config/sh/sh.cc | 4 ++++ gcc/config/stormy16/stormy16.cc | 4 ++++ gcc/config/vax/vax.cc | 4 ++++ 12 files changed, 103 insertions(+) diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index e1a4aa6cfc26..3a24f903092d 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -691,6 +691,9 @@ static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode); #undef TARGET_CAN_FOLLOW_JUMP #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P arc_can_share_jump_table_p + #undef TARGET_DELEGITIMIZE_ADDRESS #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address @@ -10150,6 +10153,15 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee) return true; } +/* Implement TARGET_CAN_SHARE_JUMP_TABLE_P. The bi and bih dispatches branch + into a table of branches that has to follow them. */ + +static bool +arc_can_share_jump_table_p (rtx_insn *) +{ + return !TARGET_BI_BIH; +} + /* Implement EPILOGUE_USES. Return true if REGNO should be added to the deemed uses of the epilogue. diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 940c689b21e0..454ba690cff9 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -627,6 +627,12 @@ static const scoped_attribute_specs *const arm_attribute_table[] = #undef TARGET_CANNOT_COPY_INSN_P #define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p +/* The dispatch sequences find the table through the PC or LR, or define a + base label of their own, and arm_reorg expects every table to follow its + jump. */ +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P hook_bool_rtx_insn_false + #ifdef HAVE_AS_TLS #undef TARGET_HAVE_TLS #define TARGET_HAVE_TLS true diff --git a/gcc/config/c6x/c6x.cc b/gcc/config/c6x/c6x.cc index c96a405ba7d5..87279475e91e 100644 --- a/gcc/config/c6x/c6x.cc +++ b/gcc/config/c6x/c6x.cc @@ -6670,6 +6670,15 @@ c6x_modes_tieable_p (machine_mode mode1, machine_mode mode2) && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD)); } +/* Implement TARGET_CAN_SHARE_JUMP_TABLE_P. With PIC, the dispatch finds the + table with addkpc, which only reaches a table close to the jump. */ + +static bool +c6x_can_share_jump_table_p (rtx_insn *) +{ + return !flag_pic; +} + /* Implement REGNO_REG_CLASS. */ enum reg_class @@ -6821,6 +6830,9 @@ c6x_regno_reg_class (int reg) #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG c6x_reorg +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P c6x_can_share_jump_table_p + #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START c6x_file_start diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc index 2112ceb0e66b..41ebd9ecd802 100644 --- a/gcc/config/cris/cris.cc +++ b/gcc/config/cris/cris.cc @@ -215,6 +215,10 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION; #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall +/* The casesi dispatch reads the table at its own PC. */ +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P hook_bool_rtx_insn_false + #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START cris_file_start diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc index f266ad53b5d1..f5f67ca149ea 100644 --- a/gcc/config/csky/csky.cc +++ b/gcc/config/csky/csky.cc @@ -658,6 +658,9 @@ csky_default_logical_op_non_short_circuit (void) #undef TARGET_CANNOT_COPY_INSN_P #define TARGET_CANNOT_COPY_INSN_P csky_cannot_copy_insn_p +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P csky_can_share_jump_table_p + /****************************************************************** * Assembler Format * @@ -1697,6 +1700,15 @@ csky_reorg (void) csky_emit_constant_pools (); } +/* Implement TARGET_CAN_SHARE_JUMP_TABLE_P. The -mconstpool scan in + csky_emit_constant_pools expects every table to follow its jump. */ + +static bool +csky_can_share_jump_table_p (rtx_insn *) +{ + return !TARGET_CONSTANT_POOL; +} + /* Check to see if the current function contains a branch insn with the far jump attribute set. Such a function uses the LR register. */ diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc index 074d82efb25f..8291a58073f4 100644 --- a/gcc/config/m68k/m68k.cc +++ b/gcc/config/m68k/m68k.cc @@ -236,6 +236,11 @@ static bool m68k_use_lra_p (void); #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true +/* The relative dispatch forms find the table at a fixed offset from the PC + of the jump. */ +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P hook_bool_rtx_insn_false + #undef TARGET_ASM_FILE_START_APP_OFF #define TARGET_ASM_FILE_START_APP_OFF true diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index e54a310b2b4b..6e75f69add19 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -23133,6 +23133,16 @@ mips_case_values_threshold (void) return default_case_values_threshold (); } +/* Implement TARGET_CAN_SHARE_JUMP_TABLE_P. The MIPS16 casesi dispatch + loads the address of a table in the text section with a PC-relative + la, whose length assumes that the table follows the jump. */ + +static bool +mips_can_share_jump_table_p (rtx_insn *) +{ + return !TARGET_MIPS16_SHORT_JUMP_TABLES; +} + /* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */ static void @@ -23630,6 +23640,9 @@ mips_print_patchable_function_entry (FILE *file ATTRIBUTE_UNUSED, #undef TARGET_CASE_VALUES_THRESHOLD #define TARGET_CASE_VALUES_THRESHOLD mips_case_values_threshold +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P mips_can_share_jump_table_p + #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV mips_atomic_assign_expand_fenv diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc index d65768125746..98215edbd11e 100644 --- a/gcc/config/pa/pa.cc +++ b/gcc/config/pa/pa.cc @@ -213,6 +213,7 @@ static section* pa_elf_select_rtx_section(machine_mode, rtx, unsigned HOST_WIDE_ static void pa_atomic_assign_expand_fenv (tree *, tree *, tree *); static bool pa_use_lra_p (void); static bool pa_frame_pointer_required (void); +static bool pa_can_share_jump_table_p (rtx_insn *); /* The following extra sections are only used for SOM. */ static GTY(()) section *som_readonly_data_section; @@ -337,6 +338,9 @@ static size_t n_deferred_plabels = 0; #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG pa_reorg +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P pa_can_share_jump_table_p + #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS pa_init_libfuncs @@ -11383,6 +11387,17 @@ pa_legitimize_reload_address (rtx ad, machine_mode mode, return NULL_RTX; } +/* Implement TARGET_CAN_SHARE_JUMP_TABLE_P. casesi32 loads the address of + the table. The PIC dispatches add the distance to the table to their + own address with one ldo, which only reaches a table close to the + jump. */ + +static bool +pa_can_share_jump_table_p (rtx_insn *insn) +{ + return recog_memoized (insn) == CODE_FOR_casesi32; +} + /* Output address vector. */ void diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc index a7ddfead32cf..082611d70c4d 100644 --- a/gcc/config/rx/rx.cc +++ b/gcc/config/rx/rx.cc @@ -2368,6 +2368,15 @@ rx_select_section (tree decl, return default_elf_select_section (decl, reloc, align); } + +/* Implement TARGET_CAN_SHARE_JUMP_TABLE_P. The entries of a PID or PIC + table are relative to a local label that the dispatch defines. */ + +static bool +rx_can_share_jump_table_p (rtx_insn *) +{ + return !TARGET_PID && !flag_pic; +} enum rx_builtin { @@ -3759,6 +3768,9 @@ rx_relax_double_operands(rtx * operands, machine_mode mode) #undef TARGET_ASM_SELECT_SECTION #define TARGET_ASM_SELECT_SECTION rx_select_section +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P rx_can_share_jump_table_p + #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS rx_init_builtins diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc index 713421538746..410f1f37ee2c 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -489,6 +489,10 @@ TARGET_GNU_ATTRIBUTES (sh_attribute_table, #undef TARGET_CANNOT_COPY_INSN_P #define TARGET_CANNOT_COPY_INSN_P sh_cannot_copy_insn_p +/* The table entries are relative to the braf of one dispatch, and sh_reorg + pairs every table with one mova. */ +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P hook_bool_rtx_insn_false #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS sh_rtx_costs #undef TARGET_ADDRESS_COST diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc index 7ea8327aa415..f64ac17aac8b 100644 --- a/gcc/config/stormy16/stormy16.cc +++ b/gcc/config/stormy16/stormy16.cc @@ -2847,6 +2847,10 @@ xstormy16_push_rounding (poly_int64 bytes) #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall +/* The table is a run of jmpf insns that the dispatch branches into. */ +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P hook_bool_rtx_insn_false + #undef TARGET_PRINT_OPERAND #define TARGET_PRINT_OPERAND xstormy16_print_operand #undef TARGET_PRINT_OPERAND_ADDRESS diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc index 47bdfadfde17..1d301a90dbb9 100644 --- a/gcc/config/vax/vax.cc +++ b/gcc/config/vax/vax.cc @@ -88,6 +88,10 @@ static HOST_WIDE_INT vax_starting_frame_offset (void); #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall +/* The casel table is part of the instruction. */ +#undef TARGET_CAN_SHARE_JUMP_TABLE_P +#define TARGET_CAN_SHARE_JUMP_TABLE_P hook_bool_rtx_insn_false + /* Enable compare elimination pass. */ #undef TARGET_FLAGS_REGNUM #define TARGET_FLAGS_REGNUM VAX_PSL_REGNUM
