https://gcc.gnu.org/g:d03e12672200b90972cb0f6f592ac01be1ca6b7d

commit d03e12672200b90972cb0f6f592ac01be1ca6b7d
Author: Alexandre Oliva <ol...@adacore.com>
Date:   Wed Dec 18 16:28:48 2024 -0300

    expand: drop stack adjustments after barrier [PR118006]
    
    A block with __builtin_unreachable () can't have code after it, and
    gimple optimizers ensure there isn't any, even without optimization.
    But if the block requires stack adjustments, e.g. because of a call
    that passes arguments on the stack, we will emit that after the
    barrier, and then rtl checkers rightfully complain.
    
    Strub expanders seem to be necessary to bring about the exact
    conditions that require stack adjustments after the block that ends
    with a __builtin_unreachable call.
    
    
    for  gcc/ChangeLog
    
            PR middle-end/118006
            * cfgexpand.cc (expand_gimple_basic_block): Do not emit
            pending stack adjustments after a barrier.
    
    for  gcc/testsuite/ChangeLog
    
            PR middle-end/118006
            * gcc.target/i386/strub-pr118006.c: New.

Diff:
---
 gcc/cfgexpand.cc                               | 10 +++++++++-
 gcc/testsuite/gcc.target/i386/strub-pr118006.c | 16 ++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index ea08810df045..aaca6a781e0c 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -6216,7 +6216,15 @@ expand_gimple_basic_block (basic_block bb, bool 
disable_tail_calls)
       emit_insn_after_noloc (gen_move_insn (dummy, dummy), last, NULL);
     }
 
-  do_pending_stack_adjust ();
+  /* A __builtin_unreachable () will insert a barrier that should end
+     the basic block.  In gimple, any code after it will have already
+     deleted, even without optimization.  If we emit additional code
+     here, as we would to adjust the stack after a call, it should be
+     eventually deleted, but it confuses internal checkers (PR118006)
+     and optimizers before it does, because we don't expect to find
+     barriers inside basic blocks.  */
+  if (!BARRIER_P (get_last_insn ()))
+    do_pending_stack_adjust ();
 
   /* Find the block tail.  The last insn in the block is the insn
      before a barrier and/or table jump insn.  */
diff --git a/gcc/testsuite/gcc.target/i386/strub-pr118006.c 
b/gcc/testsuite/gcc.target/i386/strub-pr118006.c
new file mode 100644
index 000000000000..62aa63c08c62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/strub-pr118006.c
@@ -0,0 +1,16 @@
+/* { dg-require-effective-target strub } */
+/* { dg-do compile } */
+/* { dg-options "-fstrub=all -O2 -m32 -mno-accumulate-outgoing-args" } */
+
+__attribute__((noipa))
+long _raw_syscall(void *, long, long) {
+  __builtin_abort();
+}
+
+static int privileged_traced_syscall() {
+  return _raw_syscall(0, 0, 0);
+}
+
+__attribute__((noreturn)) void privileged_traced_raise() {
+  privileged_traced_syscall();
+}

Reply via email to