This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix up cross-jumping with __builtin_trap or __builtin_unreachable (PR middle-end/55094)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 19 Nov 2012 21:46:29 +0100
- Subject: [PATCH] Fix up cross-jumping with __builtin_trap or __builtin_unreachable (PR middle-end/55094)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
As the following testcase (with disabled LRA) shows, cross-jumping
sometimes leads into dwarf2cfi ICEs, because traps or even arbitrary insns
followed by __builtin_unreachable () with different args size depth can be
cross-jumped together.
Fixed by emitting REG_ARGS_SIZE notes on traps, and for
__builtin_unreachable where we have nothing to attach it to just giving up
cross-jumping if there is no REG_ARGS_SIZE note and
!ACCUMULATE_OUTGOING_ARGS. Additionally it fixes a -fcompare-debug insn,
because with __builtin_unreachable the block might not end up with any
jump/call/trap insn, but e.g. debug insns.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and
after a while for 4.7 too?
2012-11-19 Jakub Jelinek <jakub@redhat.com>
PR middle-end/55094
* builtins.c (expand_builtin_trap): Add REG_ARGS_SIZE note
on the trap insn for !ACCUMULATE_OUTGOING_ARGS.
* cfgcleanup.c (outgoing_edges_match): Don't look at debug insns
on the first old_insns_match_p call. For !ACCUMULATE_OUTGOING_ARGS
fail if the last real insn doesn't have REG_ARGS_SIZE note.
* gcc.dg/pr55094.c: New test.
--- gcc/builtins.c.jj 2012-11-19 14:41:14.000000000 +0100
+++ gcc/builtins.c 2012-11-19 18:21:30.324047247 +0100
@@ -4666,7 +4666,14 @@ expand_builtin_trap (void)
{
#ifdef HAVE_trap
if (HAVE_trap)
- emit_insn (gen_trap ());
+ {
+ rtx insn = emit_insn (gen_trap ());
+ /* For trap insns when not accumulating outgoing args force
+ REG_ARGS_SIZE note to prevent crossjumping of calls with
+ different args sizes. */
+ if (!ACCUMULATE_OUTGOING_ARGS)
+ add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
+ }
else
#endif
emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
--- gcc/cfgcleanup.c.jj 2012-11-19 14:41:24.000000000 +0100
+++ gcc/cfgcleanup.c 2012-11-19 18:21:30.324047247 +0100
@@ -1702,9 +1702,15 @@ outgoing_edges_match (int mode, basic_bl
}
}
+ rtx last1 = BB_END (bb1);
+ rtx last2 = BB_END (bb2);
+ if (DEBUG_INSN_P (last1))
+ last1 = prev_nondebug_insn (last1);
+ if (DEBUG_INSN_P (last2))
+ last2 = prev_nondebug_insn (last2);
/* First ensure that the instructions match. There may be many outgoing
edges so this test is generally cheaper. */
- if (old_insns_match_p (mode, BB_END (bb1), BB_END (bb2)) != dir_both)
+ if (old_insns_match_p (mode, last1, last2) != dir_both)
return false;
/* Search the outgoing edges, ensure that the counts do match, find possible
@@ -1713,10 +1719,14 @@ outgoing_edges_match (int mode, basic_bl
if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
return false;
+ bool nonfakeedges = false;
FOR_EACH_EDGE (e1, ei, bb1->succs)
{
e2 = EDGE_SUCC (bb2, ei.index);
+ if ((e1->flags & EDGE_FAKE) == 0)
+ nonfakeedges = true;
+
if (e1->flags & EDGE_EH)
nehedges1++;
@@ -1734,6 +1744,18 @@ outgoing_edges_match (int mode, basic_bl
|| (fallthru1 != 0) != (fallthru2 != 0))
return false;
+ /* If !ACCUMULATE_OUTGOING_ARGS, bb1 (and bb2) have no successors
+ and the last real insn doesn't have REG_ARGS_SIZE note, don't
+ attempt to optimize, as the two basic blocks might have different
+ REG_ARGS_SIZE depths. For noreturn calls and unconditional
+ traps there should be REG_ARG_SIZE notes, they could be missing
+ for __builtin_unreachable () uses though. */
+ if (!nonfakeedges
+ && !ACCUMULATE_OUTGOING_ARGS
+ && (!INSN_P (last1)
+ || !find_reg_note (last1, REG_ARGS_SIZE, NULL)))
+ return false;
+
/* fallthru edges must be forwarded to the same destination. */
if (fallthru1)
{
--- gcc/testsuite/gcc.dg/pr55094.c.jj 2012-11-19 18:21:56.120897505 +0100
+++ gcc/testsuite/gcc.dg/pr55094.c 2012-11-19 18:20:52.000000000 +0100
@@ -0,0 +1,45 @@
+/* PR middle-end/55094 */
+/* { dg-do compile } */
+/* { dg-options "-fcompare-debug -Os" } */
+/* { dg-additional-options "-fomit-frame-pointer -fno-asynchronous-unwind-tables -mpreferred-stack-boundary=2" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
+
+extern int fn (long);
+int v;
+
+int
+foo (int x, long *y)
+{
+ if (x)
+ {
+ fn (y[0]);
+ __builtin_trap ();
+ }
+ __builtin_trap ();
+}
+
+int
+bar (int x, long *y)
+{
+ if (x)
+ {
+ fn (y[0]);
+ v = 1;
+ __builtin_unreachable ();
+ }
+ v = 1;
+ __builtin_unreachable ();
+}
+
+int
+baz (int x, long *y)
+{
+ if (x)
+ {
+ fn (y[0]);
+ v = 1;
+ __builtin_unreachable ();
+ }
+ v = 1;
+ int w = 1;
+ __builtin_unreachable ();
+}
Jakub