From 1b1a33f76879dae3e6c2c1e8fb3656b0adb52ad5 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva <oliva@adacore.com> Date: Fri, 20 Dec 2024 18:02:08 -0300 Subject: [PATCH] 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. --- gcc/cfgexpand.cc | 12 +++++++++++- gcc/testsuite/gcc.target/i386/strub-pr118006.c | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/strub-pr118006.c 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 (); +} -- GitLab