Patchwork [PR,56988] Honor by_ref in IPA-CP transformation phase

login
register
mail settings
Submitter Martin Jambor
Date April 19, 2013, 9:05 a.m.
Message ID <20130419090558.GB5129@virgil.suse>
Download mbox | patch
Permalink /patch/237878/
State New
Headers show

Comments

Martin Jambor - April 19, 2013, 9:05 a.m.
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  <mjambor@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.

Patch

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;
+}
+