ipa-cp.c (ipa_get_indirect_edge_target): Renamed to ipa_get_indirect_edge_target_1...
authorMartin Jambor <mjambor@suse.cz>
Mon, 25 Mar 2013 16:42:41 +0000 (17:42 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Mon, 25 Mar 2013 16:42:41 +0000 (17:42 +0100)
2013-03-25  Martin Jambor  <mjambor@suse.cz>

* ipa-cp.c (ipa_get_indirect_edge_target): Renamed to
ipa_get_indirect_edge_target_1, added parameter agg_reps and ability to
process it.
(ipa_get_indirect_edge_target): New function.
(devirtualization_time_bonus): New parameter known_aggs, pass it to
ipa_get_indirect_edge_target.  Update all callers.
(ipcp_discover_new_direct_edges): New parameter aggvals.  Pass it to
ipa_get_indirect_edge_target_1 instead of calling
ipa_get_indirect_edge_target.
(create_specialized_node): Pass aggvlas to
ipcp_discover_new_direct_edges.

testsuite/
* gcc.dg/ipa/ipcp-agg-9.c: New test.

From-SVN: r197054

gcc/ChangeLog
gcc/ipa-cp.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c [new file with mode: 0644]

index fe32837..6a9293c 100644 (file)
@@ -1,3 +1,17 @@
+2013-03-25  Martin Jambor  <mjambor@suse.cz>
+
+       * ipa-cp.c (ipa_get_indirect_edge_target): Renamed to
+       ipa_get_indirect_edge_target_1, added parameter agg_reps and ability to
+       process it.
+       (ipa_get_indirect_edge_target): New function.
+       (devirtualization_time_bonus): New parameter known_aggs, pass it to
+       ipa_get_indirect_edge_target.  Update all callers.
+       (ipcp_discover_new_direct_edges): New parameter aggvals.  Pass it to
+       ipa_get_indirect_edge_target_1 instead of calling
+       ipa_get_indirect_edge_target.
+       (create_specialized_node): Pass aggvlas to
+       ipcp_discover_new_direct_edges.
+
 2013-03-25  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/arm/arm.md (f_sels, f_seld): New types.
index 69d7d23..3545ed1 100644 (file)
@@ -1493,14 +1493,16 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
 }
 
 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
-   (which can contain both constants and binfos) or KNOWN_BINFOS (which can be
-   NULL) return the destination.  */
+   (which can contain both constants and binfos), KNOWN_BINFOS, KNOWN_AGGS or
+   AGG_REPS return the destination.  The latter three can be NULL.  If AGG_REPS
+   is not NULL, KNOWN_AGGS is ignored.  */
 
-tree
-ipa_get_indirect_edge_target (struct cgraph_edge *ie,
-                             vec<tree> known_vals,
-                             vec<tree> known_binfos,
-                             vec<ipa_agg_jump_function_p> known_aggs)
+static tree
+ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
+                               vec<tree> known_vals,
+                               vec<tree> known_binfos,
+                               vec<ipa_agg_jump_function_p> known_aggs,
+                               struct ipa_agg_replacement_value *agg_reps)
 {
   int param_index = ie->indirect_info->param_index;
   HOST_WIDE_INT token, anc_offset;
@@ -1516,8 +1518,21 @@ ipa_get_indirect_edge_target (struct cgraph_edge *ie,
 
       if (ie->indirect_info->agg_contents)
        {
-         if (known_aggs.length ()
-             > (unsigned int) param_index)
+         if (agg_reps)
+           {
+             t = NULL;
+             while (agg_reps)
+               {
+                 if (agg_reps->index == param_index
+                     && agg_reps->offset == ie->indirect_info->offset)
+                   {
+                     t = agg_reps->value;
+                     break;
+                   }
+                 agg_reps = agg_reps->next;
+               }
+           }
+         else if (known_aggs.length () > (unsigned int) param_index)
            {
              struct ipa_agg_jump_function *agg;
              agg = known_aggs[param_index];
@@ -1572,13 +1587,29 @@ ipa_get_indirect_edge_target (struct cgraph_edge *ie,
     }
 }
 
+
+/* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
+   (which can contain both constants and binfos), KNOWN_BINFOS (which can be
+   NULL) or KNOWN_AGGS (which also can be NULL) return the destination.  */
+
+tree
+ipa_get_indirect_edge_target (struct cgraph_edge *ie,
+                             vec<tree> known_vals,
+                             vec<tree> known_binfos,
+                             vec<ipa_agg_jump_function_p> known_aggs)
+{
+  return ipa_get_indirect_edge_target_1 (ie, known_vals, known_binfos,
+                                        known_aggs, NULL);
+}
+
 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
    and KNOWN_BINFOS.  */
 
 static int
 devirtualization_time_bonus (struct cgraph_node *node,
                             vec<tree> known_csts,
-                            vec<tree> known_binfos)
+                            vec<tree> known_binfos,
+                            vec<ipa_agg_jump_function_p> known_aggs)
 {
   struct cgraph_edge *ie;
   int res = 0;
@@ -1590,7 +1621,7 @@ devirtualization_time_bonus (struct cgraph_node *node,
       tree target;
 
       target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos,
-                                       vNULL);
+                                            known_aggs);
       if (!target)
        continue;
 
@@ -1834,7 +1865,8 @@ estimate_local_effects (struct cgraph_node *node)
       cgraph_for_node_and_aliases (node, gather_caller_stats, &stats, false);
       estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
                                         known_aggs_ptrs, &size, &time, &hints);
-      time -= devirtualization_time_bonus (node, known_csts, known_binfos);
+      time -= devirtualization_time_bonus (node, known_csts, known_binfos,
+                                          known_aggs_ptrs);
       time -= hint_time_bonus (hints);
       time -= removable_params_cost;
       size -= stats.n_calls * removable_params_cost;
@@ -1911,7 +1943,8 @@ estimate_local_effects (struct cgraph_node *node)
                                             known_aggs_ptrs, &size, &time,
                                             &hints);
          time_benefit = base_time - time
-           + devirtualization_time_bonus (node, known_csts, known_binfos)
+           + devirtualization_time_bonus (node, known_csts, known_binfos,
+                                          known_aggs_ptrs)
            + hint_time_bonus (hints)
            + removable_params_cost + emc;
 
@@ -1973,7 +2006,8 @@ estimate_local_effects (struct cgraph_node *node)
                                                 known_aggs_ptrs, &size, &time,
                                                 &hints);
              time_benefit = base_time - time
-               + devirtualization_time_bonus (node, known_csts, known_binfos)
+               + devirtualization_time_bonus (node, known_csts, known_binfos,
+                                              known_aggs_ptrs)
                + hint_time_bonus (hints);
              gcc_checking_assert (size >=0);
              if (size == 0)
@@ -2256,7 +2290,8 @@ ipcp_propagate_stage (struct topo_info *topo)
 
 static void
 ipcp_discover_new_direct_edges (struct cgraph_node *node,
-                               vec<tree> known_vals)
+                               vec<tree> known_vals,
+                               struct ipa_agg_replacement_value *aggvals)
 {
   struct cgraph_edge *ie, *next_ie;
   bool found = false;
@@ -2266,7 +2301,8 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
       tree target;
 
       next_ie = ie->next_callee;
-      target = ipa_get_indirect_edge_target (ie, known_vals, vNULL, vNULL);
+      target = ipa_get_indirect_edge_target_1 (ie, known_vals, vNULL, vNULL,
+                                              aggvals);
       if (target)
        {
          ipa_make_edge_direct_to_target (ie, target);
@@ -2676,7 +2712,7 @@ create_specialized_node (struct cgraph_node *node,
   new_info->ipcp_orig_node = node;
   new_info->known_vals = known_vals;
 
-  ipcp_discover_new_direct_edges (new_node, known_vals);
+  ipcp_discover_new_direct_edges (new_node, known_vals, aggvals);
 
   callers.release ();
   return new_node;
index 7fef606..36552cc 100644 (file)
@@ -1,3 +1,7 @@
+2013-03-25  Martin Jambor  <mjambor@suse.cz>
+
+       * gcc.dg/ipa/ipcp-agg-9.c: New test.
+
 2013-03-25  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/38536
diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c
new file mode 100644 (file)
index 0000000..e6b4b96
--- /dev/null
@@ -0,0 +1,45 @@
+/* Verify that IPA-CP can make edges direct based on aggregate contents.  */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-cp -fdump-ipa-inline"  } */
+
+struct S
+{
+  int i;
+  void (*f)(struct S *);
+  unsigned u;
+};
+
+struct U
+{
+  struct U *next;
+  struct S s;
+  short a[8];
+};
+
+extern void non_existent(struct S *p, int);
+
+static void hooray1 (struct S *p)
+{
+  non_existent (p, 1);
+}
+
+static __attribute__ ((noinline))
+void hiphip1 (struct S *p)
+{
+  p->f (p);
+}
+
+int test1 (void)
+{
+  struct S s;
+  s.i = 1234;
+  s.f = hooray1;
+  s.u = 1001;
+  hiphip1 (&s);
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "ipa-prop: Discovered an indirect call to a known target"  "cp"  } } */
+/* { dg-final { scan-ipa-dump "hooray1\[^\\n\]*inline copy in hiphip1"  "inline"  } } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */