diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e6a2763e6e87cccbd01da5c73c54dc7794a927ed..39bbf199f0d678d0ad2188e405e51a48a7c9aaf2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-12-14 Martin Jambor <mjambor@suse.cz> + + PR ipa/66616 + * ipa-cp.c (propagate_constants_accross_call): Move thuk check... + (call_passes_through_thunk_p): ...here. + (find_more_scalar_values_for_callers_subset): Perform thunk checks + like propagate_constants_accross_call does. + 2015-12-14 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/68730 diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index ee285500608664720a8b617761db8403b5c0f50b..8087f661d3e8bbb8df036a3d71c874e528b5b295 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1877,6 +1877,18 @@ propagate_aggs_accross_jump_function (struct cgraph_edge *cs, return ret; } +/* Return true if on the way cfrom CS->caller to the final (non-alias and + non-thunk) destination, the call passes through a thunk. */ + +static bool +call_passes_through_thunk_p (cgraph_edge *cs) +{ + cgraph_node *alias_or_thunk = cs->callee; + while (alias_or_thunk->alias) + alias_or_thunk = alias_or_thunk->get_alias_target (); + return alias_or_thunk->thunk.thunk_p; +} + /* Propagate constants from the caller to the callee of CS. INFO describes the caller. */ @@ -1885,7 +1897,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs) { struct ipa_node_params *callee_info; enum availability availability; - struct cgraph_node *callee, *alias_or_thunk; + cgraph_node *callee; struct ipa_edge_args *args; bool ret = false; int i, args_count, parms_count; @@ -1923,10 +1935,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs) /* If this call goes through a thunk we must not propagate to the first (0th) parameter. However, we might need to uncover a thunk from below a series of aliases first. */ - alias_or_thunk = cs->callee; - while (alias_or_thunk->alias) - alias_or_thunk = alias_or_thunk->get_alias_target (); - if (alias_or_thunk->thunk.thunk_p) + if (call_passes_through_thunk_p (cs)) { ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, 0)); @@ -3499,7 +3508,11 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node, struct ipa_jump_func *jump_func; tree t; - if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))) + if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) + || (i == 0 + && call_passes_through_thunk_p (cs)) + || (!cs->callee->instrumentation_clone + && cs->callee->function_symbol ()->instrumentation_clone)) { newval = NULL_TREE; break; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2b900bfabac3f38d24095674375407ffd3150c76..cc8b9e2bdba1d3aa99b6fbce5491b2131bb722e0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-12-14 Martin Jambor <mjambor@suse.cz> + + PR ipa/66616 + * g++.dg/ipa/pr66616.C: New test. + 2015-12-14 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/68730 diff --git a/gcc/testsuite/g++.dg/ipa/pr66616.C b/gcc/testsuite/g++.dg/ipa/pr66616.C new file mode 100644 index 0000000000000000000000000000000000000000..440ea6c6bfc1b75d370882bdf5415fa712541c2b --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr66616.C @@ -0,0 +1,54 @@ +// { dg-do run } +// { dg-options "-O2 -fipa-cp-clone" } + +struct Distraction +{ + char fc[8]; + virtual Distraction * return_self () + { return this; } +}; + +static int go; + +struct A; + +struct A +{ + int fi; + + A () : fi(0) {} + A (int pi) : fi (pi) {} + virtual void foo (int p) = 0; +}; + +struct B; + +struct B : public Distraction, A +{ + B () : Distraction(), A() { } + B (int pi) : Distraction (), A (pi) {} + virtual void foo (int p) + { + int o = fi; + for (int i = 0; i < p; i++) + o += i + i * i; + go = o; + } +}; + +struct B gb2 (2); + +extern "C" void abort (void); + +int +main (void) +{ + for (int i = 0; i < 2; i++) + { + struct A *p = &gb2; + p->foo (0); + if (go != 2) + abort (); + } + return 0; +}