From: Kyrylo Tkachov <[email protected]>

This series implements PR middle-end/126236 by extending the existing
pass_duplicate_computed_gotos pass to loop switches lowered to tablejumps.
Eligible predecessors receive copies of the dispatch sequence, but all
copies use one jump table.  This gives opcode transitions separate indirect
branch sites without duplicating the table.

The transformation copies a short fall-through chain:

  handler -> fetch and range check -> tablejump

It requires a direct DFS back edge into the chain head before the first
copy and uses the existing max-goto-duplication-insns budget.  Functions
with hot and cold partitions or stack-register use are excluded from
tablejump duplication.  Patch 4 enables the option at -O2 and higher speed
optimization levels, but not at -Os, -Oz or in size-optimized functions.

Following Jeff's review, I audited generic RTL tablejump consumers and
the targets for single-owner and adjacency assumptions.  This resulted
in small fixes in selective scheduling and stack-register handling in bbro.

Patch 5 adds shared-table checks to the existing RTL verification path.
It checks live table references, label-to-table adjacency, shared markers
and exact CFG successor sets.  Structural checks continue after CFG
teardown.  Positive and deliberate-failure plugin tests cover these checks.

Patch 2 adds TARGET_ASM_JUMP_TABLE_BASE to emit a table's base once and
TARGET_CAN_SHARE_JUMP_TABLE_P to decide whether a particular dispatch can
share its table under the current function's target options.  The default
predicate tests whether the output hook exists.  AArch64 is the only backend
enabled by this series.  Its unshared dispatch sequence is unchanged.

For the earlier audit, test-only hooks enabled sharing on x86, PowerPC,
RISC-V and s390.  Those hooks are not included here, as I used an AI agents
to implement a minimal working version, but I don't know enough about those
backends to vouch for them. 
The audit found stack-register conversion and RISC-V vector-PRE
edge-splitting problems, and repeated x86 CET landing instructions.
The fixes are included as patches 6 and 7, but they are AI-generated and marked
as such with the relevant tag. I guess it's up to the target maintainers
whether they look ok.

The series has been bootstrapped on aarch64-none-linux-gnu with
--enable-checking=yes,rtl,extra.

Earlier AArch64 performance measurements recorded these runtime and text
size changes:

  Workload                       Runtime change    Text change
  714.cpython_r, SPEC CPU2026          -7.688%          +0.203%
  QuickJS-ng, switch mode            -25.159%          +0.896%
  mawk, -O2                          -5.660%          +3.734%

Ok for trunk?
Thanks,
Kyrill

Kyrylo Tkachov (7):
  cfgrtl: Allow duplicated tablejumps to share a dispatch table
  target, aarch64: Emit a jump table base once per table
  bb-reorder: Unfactor loop switch dispatches [PR middle-end/126236]
  common: Enable -fduplicate-switch-dispatch at -O2
  rtl: Verify shared jump tables after each pass [PR middle-end/126236]
  RISC-V: Avoid vsetvl insertion on shared table edges [PR
    middle-end/126236]
  i386: Avoid duplicate ENDBR at switch destinations

 gcc/bb-reorder.cc                             | 245 +++++++++++++++---
 gcc/cfgcleanup.cc                             |   6 +
 gcc/cfgrtl.cc                                 | 157 +++++++++--
 gcc/common.opt                                |   4 +
 gcc/config/aarch64/aarch64-protos.h           |   1 +
 gcc/config/aarch64/aarch64.cc                 |  68 ++++-
 gcc/config/aarch64/aarch64.md                 |   8 +
 gcc/config/i386/i386-features.cc              |   4 +
 gcc/config/riscv/riscv-vsetvl.cc              |  13 +-
 gcc/doc/cfg.texi                              |   7 +-
 gcc/doc/invoke.texi                           |  18 ++
 gcc/doc/md.texi                               |  11 +-
 gcc/doc/rtl.texi                              |  15 +-
 gcc/doc/tm.texi                               |  34 +++
 gcc/doc/tm.texi.in                            |   4 +
 gcc/final.cc                                  |   9 +
 gcc/jump.cc                                   |   6 +-
 gcc/opts.cc                                   |   1 +
 gcc/params.opt                                |   2 +-
 gcc/passes.cc                                 |   6 +
 gcc/rtl.h                                     |  10 +
 gcc/rtlanal.cc                                | 112 ++++++++
 gcc/sched-rgn.cc                              |   7 +
 gcc/target.def                                |  41 +++
 gcc/targhooks.cc                              |   8 +
 gcc/targhooks.h                               |   1 +
 gcc/testsuite/gcc.dg/plugin/plugin.exp        |  15 ++
 .../gcc.dg/plugin/tablejump-base-label.c      |  10 +
 .../gcc.dg/plugin/tablejump-capability.c      |  25 ++
 .../gcc.dg/plugin/tablejump-case-label.c      |  10 +
 .../gcc.dg/plugin/tablejump-deleted-table.c   |  10 +
 .../gcc.dg/plugin/tablejump-detached-label.c  |  10 +
 .../gcc.dg/plugin/tablejump-detached-pair.c   |  10 +
 .../gcc.dg/plugin/tablejump-detached-table.c  |  10 +
 .../gcc.dg/plugin/tablejump-extra-edge.c      |  10 +
 .../gcc.dg/plugin/tablejump-missing-edge.c    |  10 +
 .../gcc.dg/plugin/tablejump-missing-ref.c     |  10 +
 .../gcc.dg/plugin/tablejump-null-label.c      |  10 +
 .../gcc.dg/plugin/tablejump-stale-label.c     |  10 +
 gcc/testsuite/gcc.dg/plugin/tablejump-test.h  |  24 ++
 .../gcc.dg/plugin/tablejump-unmarked.c        |  10 +
 gcc/testsuite/gcc.dg/plugin/tablejump-valid.c |   6 +
 .../plugin/tablejump_capability_plugin.cc     | 180 +++++++++++++
 .../gcc.dg/plugin/tablejump_plugin.cc         | 231 +++++++++++++++++
 gcc/testsuite/gcc.dg/switch-dispatch-2.c      |  33 +++
 gcc/testsuite/gcc.dg/switch-dispatch-3.c      |   7 +
 .../gcc.dg/torture/switch-dispatch-run-1.c    |  63 +++++
 .../gcc.dg/torture/switch-dispatch-run-2.c    |  67 +++++
 .../gcc.dg/torture/switch-dispatch-run-3.c    |  33 +++
 .../gcc.dg/torture/switch-dispatch-run-4.c    |  62 +++++
 .../gcc.target/aarch64/switch-dispatch-1.c    |  39 +++
 .../gcc.target/aarch64/switch-dispatch-2.c    |  32 +++
 .../gcc.target/aarch64/switch-dispatch-3.c    |  30 +++
 .../gcc.target/aarch64/switch-dispatch-4.c    |  10 +
 .../gcc.target/aarch64/switch-dispatch-5.c    |  10 +
 .../gcc.target/aarch64/switch-dispatch-6.c    |  10 +
 .../gcc.target/aarch64/switch-dispatch-7.c    |  11 +
 gcc/testsuite/gcc.target/i386/cet-switch-4.c  |  56 ++++
 .../gcc.target/riscv/rvv/vsetvl/pr126236.c    | 114 ++++++++
 gcc/tree-pass.h                               |   2 +
 60 files changed, 1903 insertions(+), 75 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-base-label.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-capability.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-case-label.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-deleted-table.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-detached-label.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-detached-pair.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-detached-table.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-extra-edge.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-missing-edge.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-missing-ref.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-null-label.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-stale-label.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-test.h
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-unmarked.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump-valid.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump_capability_plugin.cc
 create mode 100644 gcc/testsuite/gcc.dg/plugin/tablejump_plugin.cc
 create mode 100644 gcc/testsuite/gcc.dg/switch-dispatch-2.c
 create mode 100644 gcc/testsuite/gcc.dg/switch-dispatch-3.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/switch-dispatch-run-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/switch-dispatch-run-2.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/switch-dispatch-run-3.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/switch-dispatch-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/switch-dispatch-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/switch-dispatch-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/switch-dispatch-3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/switch-dispatch-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/switch-dispatch-5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/switch-dispatch-6.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/switch-dispatch-7.c
 create mode 100644 gcc/testsuite/gcc.target/i386/cet-switch-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr126236.c


base-commit: a0b77a14fed845f742ef378d6cb911c8d78ed625

Reply via email to