On Tue, Sep 22, 2026 at 11:34 AM <[email protected]> wrote:
>
> From: Kyrylo Tkachov <[email protected]>
>
> Different switch tables can reach the same case block. The CET pass
> inserts an ENDBR for each table, although the destination needs only one.
> This also affects dispatches that share a table.
>
> Reuse an existing ENDBR after the destination label. The x86 table-sharing
> hook remains disabled.
>
> The regression test has two ordinary tables with eight common destinations.
> It emits 17 ENDBR instructions before the fix and 9 after it, in both
> 32-bit and 64-bit code. Both outputs assemble. A 64-bit runtime check
> passes on x86_64.
>
> This patch was written by an AI agent as I'm not familiar enough with
> the x86 internals and can't vouch for it. But if the x86 maintainers
> want it I'm happy to push it.
>
> Assisted-by: OpenAI Codex 5.6 Sol
>
> gcc/ChangeLog:
>
>         * config/i386/i386-features.cc
>         (rest_of_insert_endbr_and_patchable_area): Reuse an existing
>         ENDBR at a switch destination.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/i386/cet-switch-4.c: New test.
>
> Cc: Uros Bizjak <[email protected]>
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
>  gcc/config/i386/i386-features.cc             |  4 ++
>  gcc/testsuite/gcc.target/i386/cet-switch-4.c | 56 ++++++++++++++++++++
>  2 files changed, 60 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/i386/cet-switch-4.c
>
> diff --git a/gcc/config/i386/i386-features.cc 
> b/gcc/config/i386/i386-features.cc
> index 1d26aa0c336..7c992eadf3c 100644
> --- a/gcc/config/i386/i386-features.cc
> +++ b/gcc/config/i386/i386-features.cc
> @@ -3274,6 +3274,10 @@ rest_of_insert_endbr_and_patchable_area (bool 
> need_endbr,
>                   dest_blk = e->dest;
>                   insn = BB_HEAD (dest_blk);
>                   gcc_assert (LABEL_P (insn));
> +                 rtx_insn *next = next_nonnote_nondebug_insn (insn);
> +                 if (next && INSN_P (next)
> +                     && recog_memoized (next) == CODE_FOR_nop_endbr)

The condition should read:

if (next && NONJUMP_INSN_P (next)
      && GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
      && XINT (PATTERN (next), 1) == UNSPECV_NOP_ENDBR)

IMO, this should prevent duplicate ENDBR insns during any reorg. CC
Hongtao and HJ.

Uros.

> +                   continue;
>                   endbr = gen_nop_endbr ();
>                   emit_insn_after (endbr, insn);
>                 }
> diff --git a/gcc/testsuite/gcc.target/i386/cet-switch-4.c 
> b/gcc/testsuite/gcc.target/i386/cet-switch-4.c
> new file mode 100644
> index 00000000000..53cb960f0d5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/cet-switch-4.c
> @@ -0,0 +1,56 @@
> +/* PR middle-end/126236 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fcf-protection=branch -mcet-switch -fno-pie -fno-pic" 
> } */
> +/* { dg-final { scan-assembler-times "endbr32" 9 { target ia32 } } } */
> +/* { dg-final { scan-assembler-times "endbr64" 9 { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-times "\[ \t]+jmp\[ \t]+\[*]" 2 } } */
> +
> +/* Both tables reach the same eight destinations.  */
> +
> +void f0 (void);
> +void f1 (void);
> +void f2 (void);
> +void f3 (void);
> +void f4 (void);
> +void f5 (void);
> +void f6 (void);
> +void f7 (void);
> +
> +void
> +foo (unsigned x, int which)
> +{
> +  if (which)
> +    switch (x)
> +      {
> +      case 0: goto a;
> +      case 1: goto b;
> +      case 2: goto c;
> +      case 3: goto d;
> +      case 4: goto e;
> +      case 5: goto f;
> +      case 6: goto g;
> +      case 7: goto h;
> +      default: return;
> +      }
> +  else
> +    switch (x)
> +      {
> +      case 0: goto h;
> +      case 1: goto g;
> +      case 2: goto f;
> +      case 3: goto e;
> +      case 4: goto d;
> +      case 5: goto c;
> +      case 6: goto b;
> +      case 7: goto a;
> +      default: return;
> +      }
> +a: f0 (); return;
> +b: f1 (); return;
> +c: f2 (); return;
> +d: f3 (); return;
> +e: f4 (); return;
> +f: f5 (); return;
> +g: f6 (); return;
> +h: f7 (); return;
> +}
> --
> 2.50.1 (Apple Git-155)
>

Reply via email to