diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-11-20 09:38:11 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-11-20 09:38:11 +0100 |
commit | 206604dccdcd6b054c1c81d4e058b9ca4db8f1f0 (patch) | |
tree | 3f976d8db947ec504470f76bc3ab56713f7f77aa /gcc | |
parent | 1b845c6e70049828a6732f60e2eb03042cc6ff1b (diff) | |
download | gcc-206604dccdcd6b054c1c81d4e058b9ca4db8f1f0.zip gcc-206604dccdcd6b054c1c81d4e058b9ca4db8f1f0.tar.gz gcc-206604dccdcd6b054c1c81d4e058b9ca4db8f1f0.tar.bz2 |
re PR debug/55094 (ICE in maybe_record_trace_start, at dwarf2cfi.c:2224)
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.
From-SVN: r193649
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/builtins.c | 9 | ||||
-rw-r--r-- | gcc/cfgcleanup.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr55094.c | 45 |
5 files changed, 88 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d3b0200..9041558 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2012-11-20 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. + PR rtl-optimization/54921 * cselib.h (fp_setter_insn): New prototype. * cselib.c (fp_setter_insn): New function. diff --git a/gcc/builtins.c b/gcc/builtins.c index fbeac75..b0cab51 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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); diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index eccbb41..94267b6e 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -1,7 +1,7 @@ /* Control flow optimization code for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, + 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -1702,9 +1702,15 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2) } } + 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_block bb1, basic_block bb2) 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_block bb1, basic_block bb2) || (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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 46eb0cd..86659e9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2012-11-20 Jakub Jelinek <jakub@redhat.com> + PR middle-end/55094 + * gcc.dg/pr55094.c: New test. + PR rtl-optimization/54921 * gcc.dg/pr54921.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr55094.c b/gcc/testsuite/gcc.dg/pr55094.c new file mode 100644 index 0000000..c445b1a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr55094.c @@ -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 (); +} |