Remove ipa-prop node summaries for inline clones
diff mbox series

Message ID 20191110113026.lbm3soybhsrw44pu@kam.mff.cuni.cz
State New
Headers show
Series
  • Remove ipa-prop node summaries for inline clones
Related show

Commit Message

Jan Hubicka Nov. 10, 2019, 11:30 a.m. UTC
Hi,
this patch makes creation of IPA_NODE_REF summaries explicit and fixes
the fallout. It also removes the summaries after stuff is propagated
into caller when function is inlined.

Martin, I had to add flag ipcp_clone_p into cgraph_node since that was
used while resolving cloned references.  I do not see why this flag is
needed at all. I understand it is about chain of references when
multiple thinkgs was cloned first and inlined later, but it seems to me
that we have all the info and there can not me non-clones in chain.

Also it seems to me that ipa-cp should simply remove those parameters
earlier and not get multiplied references then.

Honza

	* 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.

Patch
diff mbox series

Index: cgraph.h
===================================================================
--- cgraph.h	(revision 278009)
+++ cgraph.h	(working copy)
@@ -1484,6 +1484,8 @@  struct GTY((tag ("SYMTAB_FUNCTION"))) cg
   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: cgraphclones.c
===================================================================
--- cgraphclones.c	(revision 278009)
+++ cgraphclones.c	(working copy)
@@ -570,6 +570,7 @@  cgraph_node::create_virtual_clone (vec<c
      ??? 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: ipa-cp.c
===================================================================
--- ipa-cp.c	(revision 278009)
+++ ipa-cp.c	(working copy)
@@ -656,7 +656,7 @@  determine_versionability (struct cgraph_
 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
     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
 	 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
 	 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_inf
 
   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
   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
 			    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_n
   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: ipa-fnsummary.c
===================================================================
--- ipa-fnsummary.c	(revision 278009)
+++ ipa-fnsummary.c	(working copy)
@@ -483,36 +483,39 @@  evaluate_properties_for_edge (struct cgr
       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
   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_ca
     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 c
 }
 
 /* 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
   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: ipa-icf.c
===================================================================
--- ipa-icf.c	(revision 278009)
+++ ipa-icf.c	(working copy)
@@ -484,7 +484,7 @@  sem_function::param_used_p (unsigned int
 
   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: ipa-prop.c
===================================================================
--- ipa-prop.c	(revision 278009)
+++ ipa-prop.c	(working copy)
@@ -271,7 +271,7 @@  ipa_dump_param (FILE *file, class ipa_no
 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_nod
 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 *no
 
   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
   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
 
 		  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 (struc
 
   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_bloc
   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: ipa-prop.h
===================================================================
--- ipa-prop.h	(revision 278009)
+++ ipa-prop.h	(working copy)
@@ -766,7 +766,8 @@  extern GTY(()) function_summary <ipcp_tr
 
 /* 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