ipa-cp.c (ipa_get_indirect_edge_target_1): Handle speculation.
authorJan Hubicka <hubicka@ucw.cz>
Mon, 17 Nov 2014 22:04:36 +0000 (23:04 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 17 Nov 2014 22:04:36 +0000 (22:04 +0000)
* ipa-cp.c (ipa_get_indirect_edge_target_1): Handle speculation.
(ipa_get_indirect_edge_target): Add SPECULATIVE argument.
(devirtualization_time_bonus): Use it.
(ipcp_discover_new_direct_edges): Likewise.
* ipa-inline-analysis.c (estimate_edge_devirt_benefit): Update.
* ipa-prop.h (ipa_get_indirect_edge_target): Update prototype.

From-SVN: r217675

gcc/ChangeLog
gcc/ipa-cp.c
gcc/ipa-inline-analysis.c
gcc/ipa-prop.h

index 5e2e1a19f798dbb422d37a422406b8bf0d868399..366be84ad34b155fbeff27971d6786335eed44e5 100644 (file)
@@ -1,3 +1,12 @@
+2014-11-17  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-cp.c (ipa_get_indirect_edge_target_1): Handle speculation.
+       (ipa_get_indirect_edge_target): Add SPECULATIVE argument.
+       (devirtualization_time_bonus): Use it.
+       (ipcp_discover_new_direct_edges): Likewise.
+       * ipa-inline-analysis.c (estimate_edge_devirt_benefit): Update.
+       * ipa-prop.h (ipa_get_indirect_edge_target): Update prototype.
+
 2014-11-17  Jan Hubicka  <hubicka@ucw.cz>
 
        * tree.c (free_lang_data_in_decl): Set DECL_FUNCTION_SPECIFIC_OPTIMIZATION
index 375b49e5f918ae52c69129f5815944f5569643d0..e598241c01d91e8dae3a7f6545753a545a9cb0b6 100644 (file)
@@ -1730,13 +1730,16 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
                                vec<tree> known_csts,
                                vec<ipa_polymorphic_call_context> known_contexts,
                                vec<ipa_agg_jump_function_p> known_aggs,
-                               struct ipa_agg_replacement_value *agg_reps)
+                               struct ipa_agg_replacement_value *agg_reps,
+                               bool *speculative)
 {
   int param_index = ie->indirect_info->param_index;
   HOST_WIDE_INT anc_offset;
   tree t;
   tree target = NULL;
 
+  *speculative = false;
+
   if (param_index == -1
       || known_csts.length () <= (unsigned int) param_index)
     return NULL_TREE;
@@ -1792,8 +1795,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
   t = NULL;
 
   /* Try to work out value of virtual table pointer value in replacemnets.  */
-  if (!t && agg_reps && !ie->indirect_info->by_ref
-      && !ie->indirect_info->vptr_changed)
+  if (!t && agg_reps && !ie->indirect_info->by_ref)
     {
       while (agg_reps)
        {
@@ -1811,8 +1813,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
   /* Try to work out value of virtual table pointer value in known
      aggregate values.  */
   if (!t && known_aggs.length () > (unsigned int) param_index
-      && !ie->indirect_info->by_ref
-      && !ie->indirect_info->vptr_changed)
+      && !ie->indirect_info->by_ref)
     {
        struct ipa_agg_jump_function *agg;
        agg = known_aggs[param_index];
@@ -1836,7 +1837,9 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
                  || !possible_polymorphic_call_target_p
                       (ie, cgraph_node::get (target)))
                target = ipa_impossible_devirt_target (ie, target);
-             return target;
+              *speculative = ie->indirect_info->vptr_changed;
+             if (!*speculative)
+               return target;
            }
        }
     }
@@ -1877,11 +1880,32 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
      ie->indirect_info->otr_token,
      context, &final);
   if (!final || targets.length () > 1)
-    return NULL_TREE;
-  if (targets.length () == 1)
-    target = targets[0]->decl;
+    {
+      struct cgraph_node *node;
+      if (*speculative)
+       return target;
+      if (!flag_devirtualize_speculatively || ie->speculative
+         || !ie->maybe_hot_p ())
+       return NULL;
+      node = try_speculative_devirtualization (ie->indirect_info->otr_type,
+                                              ie->indirect_info->otr_token,
+                                              context);
+      if (node)
+       {
+         *speculative = true;
+         target = node->decl;
+       }
+      else
+       return NULL;
+    }
   else
-    target = ipa_impossible_devirt_target (ie, NULL_TREE);
+    {
+      *speculative = false;
+      if (targets.length () == 1)
+       target = targets[0]->decl;
+      else
+       target = ipa_impossible_devirt_target (ie, NULL_TREE);
+    }
 
   if (target && !possible_polymorphic_call_target_p (ie,
                                                     cgraph_node::get (target)))
@@ -1899,10 +1923,11 @@ tree
 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
                              vec<tree> known_csts,
                              vec<ipa_polymorphic_call_context> known_contexts,
-                             vec<ipa_agg_jump_function_p> known_aggs)
+                             vec<ipa_agg_jump_function_p> known_aggs,
+                             bool *speculative)
 {
   return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
-                                        known_aggs, NULL);
+                                        known_aggs, NULL, speculative);
 }
 
 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
@@ -1923,9 +1948,10 @@ devirtualization_time_bonus (struct cgraph_node *node,
       struct inline_summary *isummary;
       enum availability avail;
       tree target;
+      bool speculative;
 
       target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
-                                            known_aggs);
+                                            known_aggs, &speculative);
       if (!target)
        continue;
 
@@ -1944,12 +1970,12 @@ devirtualization_time_bonus (struct cgraph_node *node,
       /* FIXME: The values below need re-considering and perhaps also
         integrating into the cost metrics, at lest in some very basic way.  */
       if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
-       res += 31;
+       res += 31 / ((int)speculative + 1);
       else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
-       res += 15;
+       res += 15 / ((int)speculative + 1);
       else if (isummary->size <= MAX_INLINE_INSNS_AUTO
               || DECL_DECLARED_INLINE_P (callee->decl))
-       res += 7;
+       res += 7 / ((int)speculative + 1);
     }
 
   return res;
@@ -2645,16 +2671,18 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
   for (ie = node->indirect_calls; ie; ie = next_ie)
     {
       tree target;
+      bool speculative;
 
       next_ie = ie->next_callee;
       target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
-                                              vNULL, aggvals);
+                                              vNULL, aggvals, &speculative);
       if (target)
        {
          bool agg_contents = ie->indirect_info->agg_contents;
          bool polymorphic = ie->indirect_info->polymorphic;
          int param_index = ie->indirect_info->param_index;
-         struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target);
+         struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
+                                                                  speculative);
          found = true;
 
          if (cs && !agg_contents && !polymorphic)
index 69e06123fee0575921a22edcc4c0af2f3414f273..dace2fc78bebd9ae3549a83e704d3b46acbf3aa8 100644 (file)
@@ -2986,6 +2986,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
   struct cgraph_node *callee;
   struct inline_summary *isummary;
   enum availability avail;
+  bool speculative;
 
   if (!known_vals.exists () && !known_contexts.exists ())
     return false;
@@ -2993,8 +2994,8 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
     return false;
 
   target = ipa_get_indirect_edge_target (ie, known_vals, known_contexts,
-                                        known_aggs);
-  if (!target)
+                                        known_aggs, &speculative);
+  if (!target || speculative)
     return false;
 
   /* Account for difference in cost between indirect and direct calls.  */
index 9e0ce359983548b3af38ee694e3d429619ea71b3..6adb8d4d9c7aec4b7115858c713f8665f707719e 100644 (file)
@@ -529,7 +529,8 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
 tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
                                   vec<tree> ,
                                   vec<ipa_polymorphic_call_context>,
-                                  vec<ipa_agg_jump_function_p> );
+                                  vec<ipa_agg_jump_function_p>,
+                                  bool *);
 struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
                                                    bool speculative = false);
 tree ipa_impossible_devirt_target (struct cgraph_edge *, tree);