cgraph.h (struct cgraph_node): Add ipcp_clone flag.
authorJan Hubicka <hubicka@ucw.cz>
Sun, 10 Nov 2019 11:25:38 +0000 (12:25 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 10 Nov 2019 11:25:38 +0000 (11:25 +0000)
* cgraph.h (struct cgraph_node): Add ipcp_clone flag.
(cgraph_node::create_virtual_clone): Copy it.
* ipa-cp.c (ipcp_versionable_function_p): Watch for missing
summaries.
(ignore_edge_p): If caller has ipa-cp disabled, skip the edge, too.
(ipcp_verify_propagated_values): Do not verify nodes where ipcp
is disabled.
(propagate_constants_across_call): If callee is not analyzed, give up.
(propagate_constants_topo): Lower to bottom latties of all callees of
functions with ipa-cp disabled.
(ipcp_propagate_stage): Skip functions with ipa-cp disabled.
(cgraph_edge_brings_value_p): Check for availability first.
(create_specialized_node): Set ipcp_clone.
(ipcp_store_bits_results): Check that info is present.
* ipa-fnsummary.c (evaluate_properties_for_edge): Do not analyze
thunks.
(ipa_call_context::duplicate_from, ipa_call_context::equal_to): Be
conservative when callee summary is missing.
(remap_edge_summaries): Lookup call summary only when needed.
* ipa-icf.c (sem_function::param_used_p): Be ready for missing summary.
* ipa-prpo.c (ipa_alloc_node_params, ipa_initialize_node_params):
Use get_create.
(ipa_analyze_node): Use get_create.
(propagate_controlled_uses): Do not propagate when function is not
analyzed.
(ipa_propagate_indirect_call_infos): Remove summary of inline clone.
(ipa_read_node_info): Use get_create.
* ipa-prop.h (IPA_NODE_REF): Use get.
(IPA_NODE_REF_GET_CREATE): New.

From-SVN: r278016

gcc/ChangeLog
gcc/cgraph.h
gcc/cgraphclones.c
gcc/ipa-cp.c
gcc/ipa-fnsummary.c
gcc/ipa-icf.c
gcc/ipa-prop.c
gcc/ipa-prop.h

index eb80b71668df5e142af39bf5e0b52b017f5ea5bb..280f87804349c80ec335d252775505fa5a64f1a8 100644 (file)
@@ -1,3 +1,35 @@
+2019-11-09  Jan Hubicka  <hubicka@ucw.cz>
+
+       * cgraph.h (struct cgraph_node): Add ipcp_clone flag.
+       (cgraph_node::create_virtual_clone): Copy it.
+       * ipa-cp.c (ipcp_versionable_function_p): Watch for missing
+       summaries.
+       (ignore_edge_p): If caller has ipa-cp disabled, skip the edge, too.
+       (ipcp_verify_propagated_values): Do not verify nodes where ipcp
+       is disabled.
+       (propagate_constants_across_call): If callee is not analyzed, give up.
+       (propagate_constants_topo): Lower to bottom latties of all callees of
+       functions with ipa-cp disabled.
+       (ipcp_propagate_stage): Skip functions with ipa-cp disabled.
+       (cgraph_edge_brings_value_p): Check for availability first.
+       (create_specialized_node): Set ipcp_clone.
+       (ipcp_store_bits_results): Check that info is present.
+       * ipa-fnsummary.c (evaluate_properties_for_edge): Do not analyze
+       thunks.
+       (ipa_call_context::duplicate_from, ipa_call_context::equal_to): Be
+       conservative when callee summary is missing.
+       (remap_edge_summaries): Lookup call summary only when needed.
+       * ipa-icf.c (sem_function::param_used_p): Be ready for missing summary.
+       * ipa-prpo.c (ipa_alloc_node_params, ipa_initialize_node_params):
+       Use get_create.
+       (ipa_analyze_node): Use get_create.
+       (propagate_controlled_uses): Do not propagate when function is not
+       analyzed.
+       (ipa_propagate_indirect_call_infos): Remove summary of inline clone.
+       (ipa_read_node_info): Use get_create.
+       * ipa-prop.h (IPA_NODE_REF): Use get.
+       (IPA_NODE_REF_GET_CREATE): New.
+
 2019-11-09  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-fnsummary.c (evaluate_properties_for_edge): Call IPA_NODE_REF
index 0abde3d8f91c2800f7ce1a42e53a87106bb17acd..a4f14743f00882d921672ba6542d8e0338bc61ad 100644 (file)
@@ -1484,6 +1484,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
   unsigned redefined_extern_inline : 1;
   /* True if the function may enter serial irrevocable mode.  */
   unsigned tm_may_enter_irr : 1;
+  /* True if this was a clone created by ipa-cp.  */
+  unsigned ipcp_clone : 1;
 
 private:
   /* Unique id of the node.  */
index 41a600e64a54f5fad793a367e4b2e11b3de12a48..bfcebb20495b6918e58af5f6abd12f9fbff5bf79 100644 (file)
@@ -570,6 +570,7 @@ cgraph_node::create_virtual_clone (vec<cgraph_edge *> redirect_callers,
      ??? We cannot use COMDAT linkage because there is no
      ABI support for this.  */
   set_new_clone_decl_and_node_flags (new_node);
+  new_node->ipcp_clone = ipcp_clone;
   new_node->clone.tree_map = tree_map;
   if (!implicit_section)
     new_node->set_section (get_section ());
index c6bd265f5933fe49adaedff45a0effc141790fc4..b1d899976e80ff73e13f73dc88492c093b5559d8 100644 (file)
@@ -656,7 +656,7 @@ determine_versionability (struct cgraph_node *node,
 static bool
 ipcp_versionable_function_p (struct cgraph_node *node)
 {
-  return IPA_NODE_REF (node)->versionable;
+  return IPA_NODE_REF (node) && IPA_NODE_REF (node)->versionable;
 }
 
 /* Structure holding accumulated information about callers of a node.  */
@@ -817,6 +817,7 @@ ignore_edge_p (cgraph_edge *e)
     = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
 
   return (avail <= AVAIL_INTERPOSABLE
+         || !opt_for_fn (e->caller->decl, flag_ipa_cp)
          || !opt_for_fn (ultimate_target->decl, flag_ipa_cp));
 }
 
@@ -1471,6 +1472,8 @@ ipcp_verify_propagated_values (void)
   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
     {
       class ipa_node_params *info = IPA_NODE_REF (node);
+      if (!opt_for_fn (node->decl, flag_ipa_cp))
+       continue;
       int i, count = ipa_get_param_count (info);
 
       for (i = 0; i < count; i++)
@@ -2307,6 +2310,8 @@ propagate_constants_across_call (struct cgraph_edge *cs)
     return false;
   gcc_checking_assert (callee->has_gimple_body_p ());
   callee_info = IPA_NODE_REF (callee);
+  if (!callee_info)
+    return false;
 
   args = IPA_EDGE_REF (cs);
   parms_count = ipa_get_param_count (callee_info);
@@ -3233,7 +3238,17 @@ propagate_constants_topo (class ipa_topo_info *topo)
         until all lattices stabilize.  */
       FOR_EACH_VEC_ELT (cycle_nodes, j, v)
        if (v->has_gimple_body_p ())
-         push_node_to_stack (topo, v);
+         {
+           if (opt_for_fn (v->decl, flag_ipa_cp))
+             push_node_to_stack (topo, v);
+           /* When V is not optimized, we can not push it to stac, but
+              still we need to set all its callees lattices to bottom.  */
+           else
+             {
+               for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
+                  propagate_constants_across_call (cs);
+             }
+         }
 
       v = pop_node_from_stack (topo);
       while (v)
@@ -3254,7 +3269,8 @@ propagate_constants_topo (class ipa_topo_info *topo)
         the local effects of the discovered constants and all valid values to
         their topological sort.  */
       FOR_EACH_VEC_ELT (cycle_nodes, j, v)
-       if (v->has_gimple_body_p ())
+       if (v->has_gimple_body_p ()
+           && opt_for_fn (v->decl, flag_ipa_cp))
          {
            struct cgraph_edge *cs;
 
@@ -3333,11 +3349,10 @@ ipcp_propagate_stage (class ipa_topo_info *topo)
 
   FOR_EACH_DEFINED_FUNCTION (node)
   {
-    class ipa_node_params *info = IPA_NODE_REF (node);
-
-    determine_versionability (node, info);
-    if (node->has_gimple_body_p ())
+    if (node->has_gimple_body_p () && opt_for_fn (node->decl, flag_ipa_cp))
       {
+        class ipa_node_params *info = IPA_NODE_REF (node);
+        determine_versionability (node, info);
        info->lattices = XCNEWVEC (class ipcp_param_lattices,
                                   ipa_get_param_count (info));
        initialize_node_lattices (node);
@@ -3526,8 +3541,8 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
   enum availability availability;
   cgraph_node *real_dest = cs->callee->function_symbol (&availability);
 
-  if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
-      || availability <= AVAIL_INTERPOSABLE
+  if (availability <= AVAIL_INTERPOSABLE
+      || !same_node_or_its_all_contexts_clone_p (real_dest, dest)
       || caller_info->node_dead)
     return false;
 
@@ -3583,9 +3598,11 @@ cgraph_edge_brings_value_p (cgraph_edge *cs,
                            ipcp_value<ipa_polymorphic_call_context> *)
 {
   class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
-  cgraph_node *real_dest = cs->callee->function_symbol ();
+  enum availability avail;
+  cgraph_node *real_dest = cs->callee->function_symbol (&avail);
 
-  if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
+  if (avail <= AVAIL_INTERPOSABLE
+      || !same_node_or_its_all_contexts_clone_p (real_dest, dest)
       || caller_info->node_dead)
     return false;
   if (!src->val)
@@ -4018,6 +4035,7 @@ create_specialized_node (struct cgraph_node *node,
   update_profiling_info (node, new_node);
   new_info = IPA_NODE_REF (new_node);
   new_info->ipcp_orig_node = node;
+  new_node->ipcp_clone = true;
   new_info->known_csts = known_csts;
   new_info->known_contexts = known_contexts;
 
@@ -5053,7 +5071,7 @@ ipcp_store_bits_results (void)
       bool dumped_sth = false;
       bool found_useful_result = false;
 
-      if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
+      if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
        {
          if (dump_file)
            fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
index 7b8182766eed7850f15253913d1fb739e8bfa6d0..686d960f75be71b216030cc2b130f3776b750504 100644 (file)
@@ -483,36 +483,39 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
       if (count && known_contexts_ptr)
        known_contexts_ptr->safe_grow_cleared (count);
 
-      for (i = 0; i < count; i++)
-       {
-         struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
-         tree cst = ipa_value_from_jfunc (caller_parms_info, jf,
-                                          ipa_get_type (callee_pi, i));
-
-         if (!cst && e->call_stmt
-             && i < (int)gimple_call_num_args (e->call_stmt))
-           {
-             cst = gimple_call_arg (e->call_stmt, i);
-             if (!is_gimple_min_invariant (cst))
-               cst = NULL;
-           }
-         if (cst)
-           {
-             gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO);
-             if (known_vals.exists ())
-               known_vals[i] = cst;
-           }
-         else if (inline_p && !es->param[i].change_prob)
-           known_vals[i] = error_mark_node;
-
-         if (known_contexts_ptr)
-           (*known_contexts_ptr)[i]
-             = ipa_context_from_jfunc (caller_parms_info, e, i, jf);
-         /* TODO: When IPA-CP starts propagating and merging aggregate jump
-            functions, use its knowledge of the caller too, just like the
-            scalar case above.  */
-         known_aggs[i] = &jf->agg;
-       }
+      if (callee_pi)
+       for (i = 0; i < count; i++)
+         {
+           struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
+           tree cst = ipa_value_from_jfunc (caller_parms_info, jf,
+                                            ipa_get_type (callee_pi, i));
+
+           if (!cst && e->call_stmt
+               && i < (int)gimple_call_num_args (e->call_stmt))
+             {
+               cst = gimple_call_arg (e->call_stmt, i);
+               if (!is_gimple_min_invariant (cst))
+                 cst = NULL;
+             }
+           if (cst)
+             {
+               gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO);
+               if (known_vals.exists ())
+                 known_vals[i] = cst;
+             }
+           else if (inline_p && !es->param[i].change_prob)
+             known_vals[i] = error_mark_node;
+
+           if (known_contexts_ptr)
+             (*known_contexts_ptr)[i]
+               = ipa_context_from_jfunc (caller_parms_info, e, i, jf);
+           /* TODO: When IPA-CP starts propagating and merging aggregate jump
+              functions, use its knowledge of the caller too, just like the
+              scalar case above.  */
+           known_aggs[i] = &jf->agg;
+         }
+       else
+         gcc_assert (callee->thunk.thunk_p);
     }
   else if (e->call_stmt && !e->call_stmt_cannot_inline_p
           && ((clause_ptr && info->conds) || known_vals_ptr))
@@ -3004,7 +3007,8 @@ ipa_call_context::duplicate_from (const ipa_call_context &ctx)
   m_possible_truths = ctx.m_possible_truths;
   m_nonspec_possible_truths = ctx.m_nonspec_possible_truths;
   class ipa_node_params *params_summary = IPA_NODE_REF (m_node);
-  unsigned int nargs = ipa_get_param_count (params_summary);
+  unsigned int nargs = params_summary
+                      ? ipa_get_param_count (params_summary) : 0;
 
   m_inline_param_summary = vNULL;
   /* Copy the info only if there is at least one useful entry.  */
@@ -3093,7 +3097,8 @@ ipa_call_context::equal_to (const ipa_call_context &ctx)
     return false;
 
   class ipa_node_params *params_summary = IPA_NODE_REF (m_node);
-  unsigned int nargs = ipa_get_param_count (params_summary);
+  unsigned int nargs = params_summary
+                      ? ipa_get_param_count (params_summary) : 0;
 
   if (m_inline_param_summary.exists () || ctx.m_inline_param_summary.exists ())
     {
@@ -3404,7 +3409,7 @@ inline_update_callee_summaries (struct cgraph_node *node, int depth)
 }
 
 /* Update change_prob of EDGE after INLINED_EDGE has been inlined.
-   When functoin A is inlined in B and A calls C with parameter that
+   When function A is inlined in B and A calls C with parameter that
    changes with probability PROB1 and C is known to be passthroug
    of argument if B that change with probability PROB2, the probability
    of change is now PROB1*PROB2.  */
@@ -3472,12 +3477,12 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
   struct cgraph_edge *e, *next;
   for (e = node->callees; e; e = next)
     {
-      class ipa_call_summary *es = ipa_call_summaries->get (e);
       predicate p;
       next = e->next_callee;
 
       if (e->inline_failed)
        {
+          class ipa_call_summary *es = ipa_call_summaries->get (e);
          remap_edge_change_prob (inlined_edge, e);
 
          if (es->predicate)
index 67dd56f3f172434c183f488814c3bf06ffd53bff..10aa4b764638817c871c10fc221ea1d842db782f 100644 (file)
@@ -484,7 +484,7 @@ sem_function::param_used_p (unsigned int i)
 
   class ipa_node_params *parms_info = IPA_NODE_REF (get_node ());
 
-  if (vec_safe_length (parms_info->descriptors) <= i)
+  if (!parms_info || vec_safe_length (parms_info->descriptors) <= i)
     return true;
 
   return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
index ff6f25a94eac668130868967b98ca808e79f4e5e..eb783e66926e95b6d940c6c3843650990ecc9da9 100644 (file)
@@ -271,7 +271,7 @@ ipa_dump_param (FILE *file, class ipa_node_params *info, int i)
 static bool
 ipa_alloc_node_params (struct cgraph_node *node, int param_count)
 {
-  class ipa_node_params *info = IPA_NODE_REF (node);
+  class ipa_node_params *info = IPA_NODE_REF_GET_CREATE (node);
 
   if (!info->descriptors && param_count)
     {
@@ -289,7 +289,7 @@ ipa_alloc_node_params (struct cgraph_node *node, int param_count)
 void
 ipa_initialize_node_params (struct cgraph_node *node)
 {
-  class ipa_node_params *info = IPA_NODE_REF (node);
+  class ipa_node_params *info = IPA_NODE_REF_GET_CREATE (node);
 
   if (!info->descriptors
       && ipa_alloc_node_params (node, count_formal_params (node->decl)))
@@ -2605,7 +2605,7 @@ ipa_analyze_node (struct cgraph_node *node)
 
   ipa_check_create_node_params ();
   ipa_check_create_edge_args ();
-  info = IPA_NODE_REF (node);
+  info = IPA_NODE_REF_GET_CREATE (node);
 
   if (info->analysis_done)
     return;
@@ -3601,6 +3601,9 @@ propagate_controlled_uses (struct cgraph_edge *cs)
   class ipa_node_params *old_root_info = IPA_NODE_REF (cs->callee);
   int count, i;
 
+  if (!old_root_info)
+    return;
+
   count = MIN (ipa_get_cs_argument_count (args),
               ipa_get_param_count (old_root_info));
   for (i = 0; i < count; i++)
@@ -3662,8 +3665,8 @@ propagate_controlled_uses (struct cgraph_edge *cs)
 
                  clone = cs->caller;
                  while (clone->inlined_to
-                        && clone != rdesc->cs->caller
-                        && IPA_NODE_REF (clone)->ipcp_orig_node)
+                        && clone->ipcp_clone
+                        && clone != rdesc->cs->caller)
                    {
                      struct ipa_ref *ref;
                      ref = clone->find_reference (n, NULL, 0);
@@ -3722,6 +3725,7 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
 
   propagate_controlled_uses (cs);
   changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
+  ipa_node_params_sum->remove (cs->callee);
 
   return changed;
 }
@@ -4507,7 +4511,8 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node,
   struct cgraph_edge *e;
   struct bitpack_d bp;
   bool prevails = node->prevailing_p ();
-  class ipa_node_params *info = prevails ? IPA_NODE_REF (node) : NULL;
+  class ipa_node_params *info = prevails
+                               ? IPA_NODE_REF_GET_CREATE (node) : NULL;
 
   int param_count = streamer_read_uhwi (ib);
   if (prevails)
index 7a9e4bc591601e7235c61a53fd9f64a025ac53a6..952c01209f535d717b7c5633a4fb71a7eb3068ed 100644 (file)
@@ -766,7 +766,8 @@ extern GTY(()) function_summary <ipcp_transformation *> *ipcp_transformation_sum
 
 /* Return the associated parameter/argument info corresponding to the given
    node/edge.  */
-#define IPA_NODE_REF(NODE) (ipa_node_params_sum->get_create (NODE))
+#define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE))
+#define IPA_NODE_REF_GET_CREATE(NODE) (ipa_node_params_sum->get_create (NODE))
 #define IPA_EDGE_REF(EDGE) (ipa_edge_args_sum->get (EDGE))
 #define IPA_EDGE_REF_GET_CREATE(EDGE) (ipa_edge_args_sum->get_create (EDGE))
 /* This macro checks validity of index returned by