diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 15a55c069f4..458773eea48 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-11-12 Jakub Jelinek + + PR ipa/63838 + * ipa-pure-const.c (propagate_nothrow): Walk w->indirect_calls + chain instead of node->indirect_calls. Put !can_throw into + conditions of all the loops. + 2014-11-12 H.J. Lu * config/i386/i386.c (x86_output_mi_thunk): Use gen_rtx_REG to diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index d6999fa6712..6f7b32c12bc 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -1448,7 +1448,7 @@ propagate_nothrow (void) /* Find the worst state for any node in the cycle. */ w = node; - while (w) + while (w && !can_throw) { struct cgraph_edge *e, *ie; funct_state w_l = get_function_state (w); @@ -1457,10 +1457,7 @@ propagate_nothrow (void) || w->get_availability () == AVAIL_INTERPOSABLE) can_throw = true; - if (can_throw) - break; - - for (e = w->callees; e; e = e->next_callee) + for (e = w->callees; e && !can_throw; e = e->next_callee) { enum availability avail; struct cgraph_node *y = e->callee->function_symbol (&avail); @@ -1469,8 +1466,6 @@ propagate_nothrow (void) { funct_state y_l = get_function_state (y); - if (can_throw) - break; if (y_l->can_throw && !TREE_NOTHROW (w->decl) && e->can_throw_external) can_throw = true; @@ -1478,12 +1473,9 @@ propagate_nothrow (void) else if (e->can_throw_external && !TREE_NOTHROW (y->decl)) can_throw = true; } - for (ie = node->indirect_calls; ie; ie = ie->next_callee) + for (ie = w->indirect_calls; ie && !can_throw; ie = ie->next_callee) if (ie->can_throw_external) - { - can_throw = true; - break; - } + can_throw = true; w_info = (struct ipa_dfs_info *) w->aux; w = w_info->next_cycle; } @@ -1794,5 +1786,3 @@ make_pass_warn_function_noreturn (gcc::context *ctxt) { return new pass_warn_function_noreturn (ctxt); } - - diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c2cbfe80aed..66c66c49231 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-11-12 Jakub Jelinek + + PR ipa/63838 + * g++.dg/ipa/pr63838.C: New test. + 2014-11-12 Matthew Fortune * gcc.target/mips/args-1.c: Handle __mips_fpr == 0. diff --git a/gcc/testsuite/g++.dg/ipa/pr63838.C b/gcc/testsuite/g++.dg/ipa/pr63838.C new file mode 100644 index 00000000000..d6736490080 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr63838.C @@ -0,0 +1,56 @@ +// PR ipa/63838 +// { dg-do run } +// { dg-options "-O2 -fdump-ipa-pure-const" } +// { dg-final { scan-ipa-dump-not "Function found to be nothrow: void foo" "pure-const" } } +// { dg-final { scan-ipa-dump-not "Function found to be nothrow: void bar" "pure-const" } } +// { dg-final { cleanup-ipa-dump "pure-const" } } + +__attribute__((noinline, noclone)) static void bar (int); +volatile int v; +void (*fn) (); +struct S { S () { v++; } ~S () { v++; } }; + +__attribute__((noinline, noclone)) static void +foo (int x) +{ + v++; + if (x == 5) + bar (x); +} + +__attribute__((noinline, noclone)) static void +bar (int x) +{ + v++; + if (x == 6) + foo (x); + else if (x == 5) + fn (); +} + +__attribute__((noinline, noclone)) int +baz (int x) +{ + S s; + foo (x); +} + +void +throw0 () +{ + throw 0; +} + +int +main () +{ + fn = throw0; + asm volatile ("" : : : "memory"); + try + { + baz (5); + } + catch (int) + { + } +}