Hi, the following patch fixes PR 56988 by distinguishing between by reference and by value aggregate replacement value. While it is OK to ignore the difference in the last phases of propagation/decision making because any discrepancies have already been weeded out there, the testcase clearly shows we have to make sure we do not confuse the two when looking at the statements again.
Bootstrapped and tested on trunk on x86_64-linux. OK for trunk now and for the 4.8 branch after a round of testing there? Thanks, Martin 2013-04-18 Martin Jambor <mjam...@suse.cz> PR middle-end/56988 * ipa-prop.h (ipa_agg_replacement_value): New flag by_ref. * ipa-cp.c (ipa_get_indirect_edge_target_1): Also check that by_ref flags match. (find_aggregate_values_for_callers_subset): Fill in the by_ref flag of ipa_agg_replacement_value structures. (known_aggs_to_agg_replacement_list): Likewise. * ipa-prop.c (write_agg_replacement_chain): Stream by_ref flag. (read_agg_replacement_chain): Likewise. (ipcp_transform_function): Also check that by_ref flags match. testsuite/ * gcc.dg/ipa/pr56988.c: New test. Index: src/gcc/ipa-cp.c =================================================================== --- src.orig/gcc/ipa-cp.c +++ src/gcc/ipa-cp.c @@ -1508,7 +1508,8 @@ ipa_get_indirect_edge_target_1 (struct c while (agg_reps) { if (agg_reps->index == param_index - && agg_reps->offset == ie->indirect_info->offset) + && agg_reps->offset == ie->indirect_info->offset + && agg_reps->by_ref == ie->indirect_info->by_ref) { t = agg_reps->value; break; @@ -3042,11 +3043,12 @@ find_aggregate_values_for_callers_subset struct cgraph_edge *cs; vec<ipa_agg_jf_item_t> inter = vNULL; struct ipa_agg_jf_item *item; + struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); int j; /* Among other things, the following check should deal with all by_ref mismatches. */ - if (ipa_get_parm_lattices (dest_info, i)->aggs_bottom) + if (plats->aggs_bottom) continue; FOR_EACH_VEC_ELT (callers, j, cs) @@ -3068,6 +3070,7 @@ find_aggregate_values_for_callers_subset v->index = i; v->offset = item->offset; v->value = item->value; + v->by_ref = plats->aggs_by_ref; v->next = res; res = v; } @@ -3097,6 +3100,7 @@ known_aggs_to_agg_replacement_list (vec< v->index = i; v->offset = item->offset; v->value = item->value; + v->by_ref = aggjf->by_ref; v->next = res; res = v; } Index: src/gcc/ipa-prop.c =================================================================== --- src.orig/gcc/ipa-prop.c +++ src/gcc/ipa-prop.c @@ -3674,9 +3674,15 @@ write_agg_replacement_chain (struct outp for (av = aggvals; av; av = av->next) { + struct bitpack_d bp; + streamer_write_uhwi (ob, av->offset); streamer_write_uhwi (ob, av->index); stream_write_tree (ob, av->value, true); + + bp = bitpack_create (ob->main_stream); + bp_pack_value (&bp, av->by_ref, 1); + streamer_write_bitpack (&bp); } } @@ -3694,11 +3700,14 @@ read_agg_replacement_chain (struct lto_i for (i = 0; i <count; i++) { struct ipa_agg_replacement_value *av; + struct bitpack_d bp; av = ggc_alloc_ipa_agg_replacement_value (); av->offset = streamer_read_uhwi (ib); av->index = streamer_read_uhwi (ib); av->value = stream_read_tree (ib, data_in); + bp = streamer_read_bitpack (ib); + av->by_ref = bp_unpack_value (&bp, 1); av->next = aggvals; aggvals = av; } @@ -3917,7 +3926,7 @@ ipcp_transform_function (struct cgraph_n if (v->index == index && v->offset == offset) break; - if (!v) + if (!v || v->by_ref != by_ref) continue; gcc_checking_assert (is_gimple_ip_invariant (v->value)); Index: src/gcc/ipa-prop.h =================================================================== --- src.orig/gcc/ipa-prop.h +++ src/gcc/ipa-prop.h @@ -386,6 +386,8 @@ struct GTY(()) ipa_agg_replacement_value tree value; /* The paramter index. */ int index; + /* Whether the value was passed by reference. */ + bool by_ref; }; typedef struct ipa_agg_replacement_value *ipa_agg_replacement_value_p; Index: src/gcc/testsuite/gcc.dg/ipa/pr56988.c =================================================================== --- /dev/null +++ src/gcc/testsuite/gcc.dg/ipa/pr56988.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O3" } */ +/* { dg-add-options bind_pic_locally } */ + +struct S +{ + int a, b, c; +}; + +volatile int g; + +static void __attribute__ ((noinline, noclone)) +bar (struct S **p) +{ + g = 5; +}; + +static void __attribute__ ((noinline)) +foo (struct S *p) +{ + int i = p->a; + if (i != 1) + __builtin_abort (); + bar (&p); +} + +int +main (int argc, char *argv[]) +{ + struct S s; + s.a = 1; + s.b = 64; + s.c = 32; + foo (&s); + + return 0; +} +