> On 23 Sep 2026, at 10:04, Uros Bizjak <[email protected]> wrote:
> 
> On Wed, Sep 23, 2026 at 8:45 AM Hongtao Liu <[email protected]> wrote:
>> 
>> On Tue Sep 22, 2026 at 3:07 AM PDT, Uros Bizjak wrote:
>>> 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)
>> NONDEBUG_INSN_P (next)?
> 
> next is found with:
> 
> rtx_insn *next = next_nonnote_nondebug_insn (insn);
> 
> so we are sure we are dealing with nondebug insn.
> 

Can one of the i386 maintainers take this up and push a version you’re happy 
with, please?
Thank you,
Kyrill

> Uros.
> 
>> 
>>>      && 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.
>> Yes, it's a nice optimization.
>> 
>>> 
>>> 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