Hi, PR 66616 happens because in find_more_scalar_values_for_callers_subset we do not do the same thunk checks like we do in propagate_constants_accross_call. I am in the process of bootstrapping and testing the following patch to fix it. OK if it passes?
Thanks, Martin 2015-12-11 Martin Jambor <mjam...@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. testsuite/ * g++.dg/ipa/pr66616.C: New test. --- gcc/ipa-cp.c | 25 +++++++++++++----- gcc/testsuite/g++.dg/ipa/pr66616.C | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/pr66616.C diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 6ba2f14..f0dcdf5 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)); @@ -3493,7 +3502,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/g++.dg/ipa/pr66616.C b/gcc/testsuite/g++.dg/ipa/pr66616.C new file mode 100644 index 0000000..440ea6c --- /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; +} -- 2.6.3