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/cfgcleanup.c | |
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/cfgcleanup.c')
-rw-r--r-- | gcc/cfgcleanup.c | 28 |
1 files changed, 25 insertions, 3 deletions
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) { |