[backport gcc-4.8/trunk r193649 ] gcc/ 2012-11-20 Jakub Jelinek 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/testsuite/ 2012-11-20 Jakub Jelinek PR middle-end/55094 * gcc.dg/pr55094.c: New test. --- gcc-4.7.2/gcc/builtins.c.~1~ 2012-09-05 18:29:42.000000000 +0200 +++ gcc-4.7.2/gcc/builtins.c 2012-11-24 15:02:39.000000000 +0100 @@ -4721,7 +4721,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-4.7.2/gcc/cfgcleanup.c.~1~ 2011-10-05 14:59:23.000000000 +0200 +++ gcc-4.7.2/gcc/cfgcleanup.c 2012-11-24 15:02:39.000000000 +0100 @@ -1695,9 +1695,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 @@ -1706,10 +1712,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++; @@ -1727,6 +1737,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-4.7.2/gcc/testsuite/gcc.dg/pr55094.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.7.2/gcc/testsuite/gcc.dg/pr55094.c 2012-11-24 15:02:39.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 (); +}