aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgexpand.cc
diff options
context:
space:
mode:
authorAlexandre Oliva <oliva@adacore.com>2024-12-20 18:02:08 -0300
committerAlexandre Oliva <oliva@gnu.org>2025-01-06 18:59:00 -0300
commit1b1a33f76879dae3e6c2c1e8fb3656b0adb52ad5 (patch)
tree47d129e84c85418fb1e750924e566ca2d96ba4ca /gcc/cfgexpand.cc
parent6069f02a486054484ad638b083cb3b9486bb4321 (diff)
downloadgcc-1b1a33f76879dae3e6c2c1e8fb3656b0adb52ad5.zip
gcc-1b1a33f76879dae3e6c2c1e8fb3656b0adb52ad5.tar.gz
gcc-1b1a33f76879dae3e6c2c1e8fb3656b0adb52ad5.tar.bz2
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.
Diffstat (limited to 'gcc/cfgexpand.cc')
-rw-r--r--gcc/cfgexpand.cc12
1 files changed, 11 insertions, 1 deletions
diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 8b6ed0d..abab385 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. */