https://gcc.gnu.org/g:1b1a33f76879dae3e6c2c1e8fb3656b0adb52ad5

commit r15-6610-g1b1a33f76879dae3e6c2c1e8fb3656b0adb52ad5
Author: Alexandre Oliva <ol...@adacore.com>
Date:   Fri Dec 20 18:02:08 2024 -0300

    expand: drop stack adjustments after barrier [PR118006]
    
    A gimple 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, expand will
    emit that after the barrier, and then rtl checkers rightfully
    complain.  Arrange to discard adjustments after a barrier.
    
    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                               | 12 +++++++++++-
 gcc/testsuite/gcc.target/i386/strub-pr118006.c | 17 +++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 8b6ed0dcb8bf..abab385293a5 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -6216,7 +6216,17 @@ 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 ();
+  else
+    discard_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..6337ce10df31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/strub-pr118006.c
@@ -0,0 +1,17 @@
+/* { 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);
+}
+
+void privileged_traced_raise() {
+  privileged_traced_syscall();
+  __builtin_unreachable ();
+}

Reply via email to