aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgcleanup.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-11-20 09:38:11 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2012-11-20 09:38:11 +0100
commit206604dccdcd6b054c1c81d4e058b9ca4db8f1f0 (patch)
tree3f976d8db947ec504470f76bc3ab56713f7f77aa /gcc/cfgcleanup.c
parent1b845c6e70049828a6732f60e2eb03042cc6ff1b (diff)
downloadgcc-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.c28
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)
{