[backport gcc-4.9/trunk r198540 ] gcc/ 2013-05-02 Martin Jambor PR middle-end/56988 * ipa-prop.h (ipa_agg_replacement_value): New flag by_ref. * ipa-cp.c (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. gcc/testsuite/ 2013-05-02 Martin Jambor PR middle-end/56988 * gcc.dg/ipa/pr56988.c: New test. --- gcc-4.8.0/gcc/ipa-cp.c.~1~ 2013-02-27 22:34:27.000000000 +0100 +++ gcc-4.8.0/gcc/ipa-cp.c 2013-05-04 11:59:26.050839211 +0200 @@ -3014,11 +3014,12 @@ find_aggregate_values_for_callers_subset struct cgraph_edge *cs; vec 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) @@ -3040,6 +3041,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; } @@ -3069,6 +3071,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; } --- gcc-4.8.0/gcc/ipa-prop.c.~1~ 2013-02-20 16:47:21.000000000 +0100 +++ gcc-4.8.0/gcc/ipa-prop.c 2013-05-04 11:59:26.050839211 +0200 @@ -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 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)); --- gcc-4.8.0/gcc/ipa-prop.h.~1~ 2013-01-10 21:38:27.000000000 +0100 +++ gcc-4.8.0/gcc/ipa-prop.h 2013-05-04 11:59:26.050839211 +0200 @@ -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; --- gcc-4.8.0/gcc/testsuite/gcc.dg/ipa/pr56988.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.8.0/gcc/testsuite/gcc.dg/ipa/pr56988.c 2013-05-04 11:59:26.050839211 +0200 @@ -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; +} +