This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [middle-end, patch, committed] Indirect inlining cleanups


I have bootstrapped and tested the following on linux-x86_64, revision
140272 and committed it as revision 140293.

Except for what was necessary to change to make the patches apply
cleanly to changing trunk, I have only changed the vector parameter
types in the second patch to avoid the bug Jakub discovered.

Martin

2008-09-11  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h (struct ipa_param_flags): Removed.
	(struct ipa_param_descriptor): New structure.
	(struct ipa_node_params): ipcp_lattices, param_decls and
	param_flags moved to ipa_param_description.
	(ipa_get_ith_param): Renamed to ipa_get_param, changed to access
	descriptors.  Renamed all users.
	(ipa_is_ith_param_modified): Renamed to ipa_is_param_modified,
	changed to access descriptors.  Renamed all users.
	(ipa_is_ith_param_called): Renamed to ipa_is_param_called, changed
	to access descriptors. Renamed all users.
	* ipa-cp.c (ipcp_init_cloned_node): Call
	ipa_initialize_node_params instead of ipa_count_formal_params and
	ipa_create_param_decls_array.
	(ipcp_analyze_node): Likewise.
	(ipcp_get_ith_lattice): Renamed to ipcp_get_lattice, changed to access
	descriptors.  Renamed all users.
	(ipcp_initialize_node_lattices): Remove allocation.
	* ipa-inline.c (inline_indirect_intraprocedural_analysis): Call
	ipa_initialize_node_params instead of ipa_count_formal_params and
	ipa_create_param_decls_array.
	* ipa-prop.c (ipa_create_param_decls_array): Renamed to
	ipa_populate_param_decls, made static, added parameter info,
	renamed mt to node, removed allocation, changed to use
	descriptors.
	(ipa_count_formal_params): Made static, added parameter info,
	renamed mt to node.
	(ipa_initialize_node_params): New function.
	(ipa_check_stmt_modifications): Changed to use descriptors.
	(ipa_detect_param_modifications): Removed allocation, changed to
	use descriptors.
	(ipa_note_param_call): Changed to use descriptors.
	(ipa_analyze_params_uses): Removed allocation.
	(ipa_free_node_params_substructures): Changed to use descriptors.
	(ipa_edge_duplication_hook): Use the unused attribute.
	(ipa_node_duplication_hook): Use the unused attribute, changed to
	use descriptors, changed to duplicate descriptors.

	* ipa-inline.c (cgraph_mark_inline_edge): New parameter new_edges,
	changed all callers.  Call ipa_propagate_indirect_call_infos if doing
	indirect inlining.  Made static.
        (cgraph_decide_inlining): Freeing ipa-prop structures after inlining
	functions called only once.
	(cgraph_decide_recursive_inlining): Don't call
	ipa_propagate_indirect_call_infos, pass new_edges to
	cgraph_mark_inline_edge instead.
	(cgraph_decide_inlining_of_small_functions): Don't call
	ipa_propagate_indirect_call_infos, pass new_edges to
	cgraph_mark_inline_edge instead.
	(cgraph_decide_inlining): Don't call
	ipa_propagate_indirect_call_infos.
	* ipa-prop.c: Check that vectors are allocated.

	* ipa-inline.c (cgraph_mark_inline_edge): Returns boolean, true
	iff a new cgraph edges have been created.
	(cgraph_decide_inlining): New variable redo_always_inline.
	Flattening and always_inlining loop until callgraph stabilizes.
	* ipa-prop.c (update_call_notes_after_inlining): Returns boolean,
	true iff new cgraph edges have been created.
	(propagate_info_to_inlined_callees): Likewise.
	(ipa_propagate_indirect_call_infos): Likewise.

Index: gcc/cgraph.h
===================================================================
--- gcc/cgraph.h	(revision 140291)
+++ gcc/cgraph.h	(working copy)
@@ -452,7 +452,6 @@
 
 /* In ipa-inline.c  */
 void cgraph_clone_inlined_nodes (struct cgraph_edge *, bool, bool);
-void cgraph_mark_inline_edge (struct cgraph_edge *, bool);
 bool cgraph_default_inline_p (struct cgraph_node *, const char **);
 unsigned int compute_inline_parameters (struct cgraph_node *);
 
Index: gcc/ipa-cp.c
===================================================================
--- gcc/ipa-cp.c	(revision 140291)
+++ gcc/ipa-cp.c	(working copy)
@@ -171,9 +171,8 @@
 		       struct cgraph_node *new_node)
 {
   ipa_check_create_node_params ();
+  ipa_initialize_node_params (new_node);
   IPA_NODE_REF (new_node)->ipcp_orig_node = orig_node;
-  ipa_count_formal_params (new_node);
-  ipa_create_param_decls_array (new_node);
 }
 
 /* Perform intraprocedrual analysis needed for ipcp.  */
@@ -183,8 +182,7 @@
   /* Unreachable nodes should have been eliminated before ipcp.  */
   gcc_assert (node->needed || node->reachable);
 
-  ipa_count_formal_params (node);
-  ipa_create_param_decls_array (node);
+  ipa_initialize_node_params (node);
   ipa_detect_param_modifications (node);
 }
 
@@ -300,9 +298,9 @@
 /* Return the lattice corresponding to the Ith formal parameter of the function
    described by INFO.  */
 static inline struct ipcp_lattice *
-ipcp_get_ith_lattice (struct ipa_node_params *info, int i)
+ipcp_get_lattice (struct ipa_node_params *info, int i)
 {
-  return &(info->ipcp_lattices[i]);
+  return &(info->params[i].ipcp_lattice);
 }
 
 /* Given the jump function JFUNC, compute the lattice LAT that describes the
@@ -321,7 +319,7 @@
     {
       struct ipcp_lattice *caller_lat;
 
-      caller_lat = ipcp_get_ith_lattice (info, jfunc->value.formal_id);
+      caller_lat = ipcp_get_lattice (info, jfunc->value.formal_id);
       lat->type = caller_lat->type;
       lat->constant = caller_lat->constant;
     }
@@ -364,7 +362,7 @@
       count = ipa_get_param_count (info);
       for (i = 0; i < count; i++)
 	{
-	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
+	  struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
 
 	  fprintf (f, "    param [%d]: ", i);
 	  if (lat->type == IPA_CONST_VALUE)
@@ -485,9 +483,6 @@
   struct ipa_node_params *info = IPA_NODE_REF (node);
   enum ipa_lattice_type type;
 
-  info->ipcp_lattices = XCNEWVEC (struct ipcp_lattice,
-				  ipa_get_param_count (info));
-  
   if (ipa_is_called_with_var_arguments (info))
     type = IPA_BOTTOM;
   else if (!node->needed)
@@ -500,7 +495,7 @@
     type = IPA_BOTTOM;
 
   for (i = 0; i < ipa_get_param_count (info) ; i++)
-    ipcp_get_ith_lattice (info, i)->type = type;
+    ipcp_get_lattice (info, i)->type = type;
 }
 
 /* build INTEGER_CST tree with type TREE_TYPE and value according to LAT.
@@ -596,14 +591,14 @@
       count = ipa_get_param_count (info);
       for (i = 0; i < count; i++)
 	{
-	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
+	  struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
 	  if (lat->type == IPA_TOP)
 	    {
 	      prop_again = true;
 	      if (dump_file)
 		{
 		  fprintf (dump_file, "Forcing param ");
-		  print_generic_expr (dump_file, ipa_get_ith_param (info, i), 0);
+		  print_generic_expr (dump_file, ipa_get_param (info, i), 0);
 		  fprintf (dump_file, " of node %s to bottom.\n",
 			   cgraph_node_name (node));
 		}
@@ -651,7 +646,7 @@
 	    {
 	      jump_func = ipa_get_ith_jump_func (args, i);
 	      ipcp_lattice_from_jfunc (info, &inc_lat, jump_func);
-	      dest_lat = ipcp_get_ith_lattice (callee_info, i);
+	      dest_lat = ipcp_get_lattice (callee_info, i);
 	      ipa_lattice_meet (&new_lat, &inc_lat, dest_lat);
 	      if (ipcp_lattice_changed (&new_lat, dest_lat))
 		{
@@ -917,7 +912,7 @@
   count = ipa_get_param_count (orig_callee_info);
   for (i = 0; i < count; i++)
     {
-      struct ipcp_lattice *lat = ipcp_get_ith_lattice (orig_callee_info, i);
+      struct ipcp_lattice *lat = ipcp_get_lattice (orig_callee_info, i);
       if (ipcp_lat_is_const (lat))
 	{
 	  jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
@@ -946,8 +941,8 @@
 
 	for (i = 0; i < count; i++)
 	  {
-	    struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-	    tree parm_tree = ipa_get_ith_param (info, i);
+	    struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+	    tree parm_tree = ipa_get_param (info, i);
 
 	    /* We can proactively remove obviously unused arguments.  */
 	    if (is_gimple_reg (parm_tree)
@@ -1069,8 +1064,8 @@
   count = ipa_get_param_count (info);
   for (i = 0; i < count; i++)
     {
-      struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-      tree parm_tree = ipa_get_ith_param (info, i);
+      struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+      tree parm_tree = ipa_get_param (info, i);
 
       /* We can proactively remove obviously unused arguments.  */
       if (is_gimple_reg (parm_tree)
@@ -1142,8 +1137,8 @@
 
   for (i = 0; i < count; i++)
     {
-      struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-      tree parm_tree = ipa_get_ith_param (info, i);
+      struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+      tree parm_tree = ipa_get_param (info, i);
       if (ipcp_lat_is_insertable (lat)
 	  /* Do not count obviously unused arguments.  */
 	  && (!is_gimple_reg (parm_tree)
@@ -1242,8 +1237,8 @@
       args_to_skip = BITMAP_ALLOC (NULL);
       for (i = 0; i < count; i++)
 	{
-	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-	  parm_tree = ipa_get_ith_param (info, i);
+	  struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+	  parm_tree = ipa_get_param (info, i);
 
 	  /* We can proactively remove obviously unused arguments.  */
 	  if (is_gimple_reg (parm_tree)
Index: gcc/ipa-inline.c
===================================================================
--- gcc/ipa-inline.c	(revision 140291)
+++ gcc/ipa-inline.c	(working copy)
@@ -243,15 +243,19 @@
       cgraph_clone_inlined_nodes (e, duplicate, update_original);
 }
 
-/* Mark edge E as inlined and update callgraph accordingly. 
-   UPDATE_ORIGINAL specify whether profile of original function should be
-   updated. */
+/* Mark edge E as inlined and update callgraph accordingly.  UPDATE_ORIGINAL
+   specify whether profile of original function should be updated.  If any new
+   indirect edges are discovered in the process, add them to NEW_EDGES, unless
+   it is NULL.  Return true iff any new callgraph edges were discovered as a
+   result of inlining.  */
 
-void
-cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original)
+static bool
+cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original,
+			 VEC (cgraph_edge_p, heap) **new_edges)
 {
   int old_insns = 0, new_insns = 0;
   struct cgraph_node *to = NULL, *what;
+  struct cgraph_edge *curr = e;
 
   if (e->callee->inline_decl)
     cgraph_redirect_edge_callee (e, cgraph_node (e->callee->inline_decl));
@@ -281,6 +285,11 @@
   if (new_insns > old_insns)
     overall_insns += new_insns - old_insns;
   ncalls_inlined++;
+
+  if (flag_indirect_inlining)
+    return ipa_propagate_indirect_call_infos (curr, new_edges);
+  else
+    return false;
 }
 
 /* Mark all calls of EDGE->CALLEE inlined into EDGE->CALLER.
@@ -302,7 +311,7 @@
       next = e->next_caller;
       if (e->caller == to && e->inline_failed)
 	{
-          cgraph_mark_inline_edge (e, true);
+          cgraph_mark_inline_edge (e, true, NULL);
 	  if (e == edge)
 	    edge = next;
 	}
@@ -747,9 +756,7 @@
 	  fprintf (dump_file, "\n");
 	}
       cgraph_redirect_edge_callee (curr, master_clone);
-      cgraph_mark_inline_edge (curr, false);
-      if (flag_indirect_inlining)
-	ipa_propagate_indirect_call_infos (curr, new_edges);
+      cgraph_mark_inline_edge (curr, false, new_edges);
       lookup_recursive_calls (node, curr->callee, heap);
       n++;
     }
@@ -1002,12 +1009,10 @@
 	      continue;
 	    }
 	  callee = edge->callee;
-	  cgraph_mark_inline_edge (edge, true);
+	  cgraph_mark_inline_edge (edge, true, &new_indirect_edges);
 	  if (flag_indirect_inlining)
-	    {
-	      ipa_propagate_indirect_call_infos (edge, &new_indirect_edges);
-	      add_new_edges_to_heap (heap, new_indirect_edges);
-	    }
+	    add_new_edges_to_heap (heap, new_indirect_edges);
+
 	  update_callee_keys (heap, callee, updated_nodes);
 	}
       where = edge->caller;
@@ -1070,6 +1075,7 @@
   int old_insns = 0;
   int i;
   int initial_insns = 0;
+  bool redo_always_inline = true;
 
   cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
 
@@ -1103,69 +1109,70 @@
 
   /* In the first pass mark all always_inline edges.  Do this with a priority
      so none of our later choices will make this impossible.  */
-  for (i = nnodes - 1; i >= 0; i--)
+  while (redo_always_inline)
     {
-      struct cgraph_edge *e, *next;
+      redo_always_inline = false;
+      for (i = nnodes - 1; i >= 0; i--)
+	{
+	  struct cgraph_edge *e, *next;
 
-      node = order[i];
+	  node = order[i];
 
-      /* Handle nodes to be flattened, but don't update overall unit size.  */
-      if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL)
-        {
-  	  if (dump_file)
-    	    fprintf (dump_file,
-	     	     "Flattening %s\n", cgraph_node_name (node));
-	  cgraph_decide_inlining_incrementally (node, INLINE_ALL, 0);
-        }
+	  /* Handle nodes to be flattened, but don't update overall unit
+	     size.  */
+	  if (lookup_attribute ("flatten",
+				DECL_ATTRIBUTES (node->decl)) != NULL)
+	    {
+	      if (dump_file)
+		fprintf (dump_file,
+			 "Flattening %s\n", cgraph_node_name (node));
+	      cgraph_decide_inlining_incrementally (node, INLINE_ALL, 0);
+	    }
 
-      if (!node->local.disregard_inline_limits)
-	continue;
-      if (dump_file)
-	fprintf (dump_file,
-		 "\nConsidering %s %i insns (always inline)\n",
-		 cgraph_node_name (node), node->global.insns);
-      old_insns = overall_insns;
-      for (e = node->callers; e; e = next)
-	{
-	  next = e->next_caller;
-	  if (!e->inline_failed || gimple_call_cannot_inline_p (e->call_stmt))
+	  if (!node->local.disregard_inline_limits)
 	    continue;
-	  if (cgraph_recursive_inlining_p (e->caller, e->callee,
-				  	   &e->inline_failed))
-	    continue;
-	  if (!tree_can_inline_p (e->caller->decl, e->callee->decl))
+	  if (dump_file)
+	    fprintf (dump_file,
+		     "\nConsidering %s %i insns (always inline)\n",
+		     cgraph_node_name (node), node->global.insns);
+	  old_insns = overall_insns;
+	  for (e = node->callers; e; e = next)
 	    {
-	      gimple_call_set_cannot_inline (e->call_stmt, true);
-	      continue;
+	      next = e->next_caller;
+	      if (!e->inline_failed
+		  || gimple_call_cannot_inline_p (e->call_stmt))
+		continue;
+	      if (cgraph_recursive_inlining_p (e->caller, e->callee,
+					       &e->inline_failed))
+		continue;
+	      if (!tree_can_inline_p (e->caller->decl, e->callee->decl))
+		{
+		  gimple_call_set_cannot_inline (e->call_stmt, true);
+		  continue;
+		}
+	      if (cgraph_mark_inline_edge (e, true, NULL))
+		redo_always_inline = true;
+	      if (dump_file)
+		fprintf (dump_file,
+			 " Inlined into %s which now has %i insns.\n",
+			 cgraph_node_name (e->caller),
+			 e->caller->global.insns);
 	    }
-	  cgraph_mark_inline_edge (e, true);
-	  if (flag_indirect_inlining)
-	    ipa_propagate_indirect_call_infos (e, NULL);
+	  /* Inlining self recursive function might introduce new calls to
+	     themselves we didn't see in the loop above.  Fill in the proper
+	     reason why inline failed.  */
+	  for (e = node->callers; e; e = e->next_caller)
+	    if (e->inline_failed)
+	      e->inline_failed = N_("recursive inlining");
 	  if (dump_file)
 	    fprintf (dump_file, 
-		     " Inlined into %s which now has %i insns.\n",
-		     cgraph_node_name (e->caller),
-		     e->caller->global.insns);
+		     " Inlined for a net change of %+i insns.\n",
+		     overall_insns - old_insns);
 	}
-      /* Inlining self recursive function might introduce new calls to
-	 themselves we didn't see in the loop above.  Fill in the proper
-	 reason why inline failed.  */
-      for (e = node->callers; e; e = e->next_caller)
-	if (e->inline_failed)
-	  e->inline_failed = N_("recursive inlining");
-      if (dump_file)
-	fprintf (dump_file, 
-		 " Inlined for a net change of %+i insns.\n",
-		 overall_insns - old_insns);
     }
 
   cgraph_decide_inlining_of_small_functions ();
 
-  /* After this point, any edge discovery performed by indirect inlining is no
-     good so let's give up. */
-  if (flag_indirect_inlining)
-    free_all_ipa_structures_after_iinln ();
-
   if (flag_inline_functions_called_once)
     {
       if (dump_file)
@@ -1220,6 +1227,10 @@
 	}
     }
 
+  /* Free ipa-prop structures if they are no longer needed.  */
+  if (flag_indirect_inlining)
+    free_all_ipa_structures_after_iinln ();
+
   if (dump_file)
     fprintf (dump_file,
 	     "\nInlined %i calls, eliminated %i functions, "
@@ -1635,8 +1646,7 @@
 
   if (!flag_ipa_cp)
     {
-      ipa_count_formal_params (node);
-      ipa_create_param_decls_array (node);
+      ipa_initialize_node_params (node);
       ipa_detect_param_modifications (node);
     }
   ipa_analyze_params_uses (node);
Index: gcc/ipa-prop.c
===================================================================
--- gcc/ipa-prop.c	(revision 140291)
+++ gcc/ipa-prop.c	(working copy)
@@ -102,54 +102,69 @@
 
   count = ipa_get_param_count (info);
   for (i = 0; i < count; i++)
-    if (ipa_get_ith_param(info, i) == ptree)
+    if (ipa_get_param(info, i) == ptree)
       return i;
 
   return -1;
 }
 
-/* Insert the formal trees to the param_decls array in function MT.  */
-void
-ipa_create_param_decls_array (struct cgraph_node *mt)
+/* Populate the param_decl field in parameter descriptors of INFO that
+   corresponds to NODE.  */
+static void
+ipa_populate_param_decls (struct cgraph_node *node,
+			  struct ipa_node_params *info)
 {
   tree fndecl;
   tree fnargs;
   tree parm;
   int param_num;
-  struct ipa_node_params *info = IPA_NODE_REF (mt);
 
-  if (info->param_decls)
-    return;
-
-  info->param_decls = XCNEWVEC (tree, ipa_get_param_count (info));
-  fndecl = mt->decl;
+  fndecl = node->decl;
   fnargs = DECL_ARGUMENTS (fndecl);
   param_num = 0;
   for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
     {
-      info->param_decls[param_num] = parm;
+      info->params[param_num].decl = parm;
       param_num++;
     }
 }
 
-/* Count number of formals in MT. Insert the result to the 
-   ipa_node_params.  */
-void
-ipa_count_formal_params (struct cgraph_node *mt)
+/* Count number of formal parameters in NOTE. Store the result to the
+   appropriate field of INFO.  */
+static void
+ipa_count_formal_params (struct cgraph_node *node,
+			 struct ipa_node_params *info)
 {
   tree fndecl;
   tree fnargs;
   tree parm;
   int param_num;
 
-  fndecl = mt->decl;
+  fndecl = node->decl;
   fnargs = DECL_ARGUMENTS (fndecl);
   param_num = 0;
   for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
     param_num++;
-  ipa_set_param_count (IPA_NODE_REF (mt), param_num);
+  ipa_set_param_count (info, param_num);
 }
 
+/* Initialize the ipa_node_params structure associated with NODE by counting
+   the function parameters, creating the descriptors and populating their
+   param_decls.  */
+void
+ipa_initialize_node_params (struct cgraph_node *node)
+{
+  struct ipa_node_params *info = IPA_NODE_REF (node);
+
+  if (!info->params)
+    {
+      ipa_count_formal_params (node, info);
+      info->params = XCNEWVEC (struct ipa_param_descriptor,
+				    ipa_get_param_count (info));
+      ipa_populate_param_decls (node, info);
+    }
+}
+
 /* Check STMT to detect whether a formal parameter is directly modified within
    STMT, the appropriate entry is updated in the modified flags of INFO.
    Directly means that this function does not check for modifications through
@@ -173,13 +188,13 @@
 	lhs = SSA_NAME_VAR (lhs);
       index = ipa_get_param_decl_index (info, lhs);
       if (index >= 0)
-	info->param_flags[index].modified = true;
+	info->params[index].modified = true;
       break;
 
     case GIMPLE_ASM:
       /* Asm code could modify any of the parameters.  */
       for (j = 0; j < ipa_get_param_count (info); j++)
-	info->param_flags[j].modified = true;
+	info->params[j].modified = true;
       break;
 
     default:
@@ -205,10 +220,6 @@
   if (ipa_get_param_count (info) == 0 || info->modification_analysis_done)
     return;
 
-  if (!info->param_flags)
-    info->param_flags = XCNEWVEC (struct ipa_param_flags,
-				  ipa_get_param_count (info));
-
   func = DECL_STRUCT_FUNCTION (decl);
   FOR_EACH_BB_FN (bb, func)
     {
@@ -221,8 +232,8 @@
 
   count = ipa_get_param_count (info);
   for (i = 0; i < count; i++)
-    if (TREE_ADDRESSABLE (ipa_get_ith_param (info, i)))
-      info->param_flags[i].modified = true;
+    if (TREE_ADDRESSABLE (ipa_get_param (info, i)))
+      info->params[i].modified = true;
 
   info->modification_analysis_done = 1;
 }
@@ -402,7 +413,7 @@
 	      int index = ipa_get_param_decl_index (info, arg);
 
 	      gcc_assert (index >=0);
-	      if (!ipa_is_ith_param_modified (info, index))
+	      if (!ipa_is_param_modified (info, index))
 		{
 		  functions[num].type = IPA_PASS_THROUGH;
 		  functions[num].value.formal_id = index;
@@ -613,7 +624,7 @@
   struct ipa_param_call_note *note;
   basic_block bb = gimple_bb (stmt);
 
-  info->param_flags[formal_id].called = 1;
+  info->params[formal_id].called = 1;
 
   note = XCNEW (struct ipa_param_call_note);
   note->formal_id = formal_id;
@@ -788,7 +799,7 @@
     return;
 
   index = ipa_get_param_decl_index (info, rec);
-  if (index >= 0 && !ipa_is_ith_param_modified (info, index))
+  if (index >= 0 && !ipa_is_param_modified (info, index))
     ipa_note_param_call (info, index, call);
 
   return;
@@ -818,9 +829,6 @@
 
   if (ipa_get_param_count (info) == 0 || info->uses_analysis_done)
     return;
-  if (!info->param_flags)
-    info->param_flags = XCNEWVEC (struct ipa_param_flags,
-				  ipa_get_param_count (info));
 
   func = DECL_STRUCT_FUNCTION (decl);
   FOR_EACH_BB_FN (bb, func)
@@ -891,8 +899,8 @@
    assuming NODE is (potentially indirectly) inlined into CS->callee.
    Moreover, if the callee is discovered to be constant, create a new cgraph
    edge for it.  Newly discovered indirect edges will be added to *NEW_EDGES,
-   unless NEW_EDGES is NULL.  */
-static void
+   unless NEW_EDGES is NULL.  Return true iff a new edge(s) were created.  */
+static bool
 update_call_notes_after_inlining (struct cgraph_edge *cs,
 				  struct cgraph_node *node,
 				  VEC (cgraph_edge_p, heap) **new_edges)
@@ -900,6 +908,7 @@
   struct ipa_node_params *info = IPA_NODE_REF (node);
   struct ipa_edge_args *top = IPA_EDGE_REF (cs);
   struct ipa_param_call_note *nt;
+  bool res = false;
 
   for (nt = info->param_calls; nt; nt = nt->next)
     {
@@ -940,6 +949,7 @@
 	  if (!callee || !callee->local.inlinable)
 	    continue;
 
+	  res = true;
 	  if (dump_file)
 	    print_edge_addition_message (dump_file, nt, jfunc, node);
 
@@ -953,6 +963,7 @@
 	  top = IPA_EDGE_REF (cs);
 	}
     }
+  return res;
 }
 
 /* Recursively traverse subtree of NODE (including node) made of inlined
@@ -960,32 +971,43 @@
    update_call_notes_after_inlining on all nodes and
    update_jump_functions_after_inlining on all non-inlined edges that lead out
    of this subtree.  Newly discovered indirect edges will be added to
-   *NEW_EDGES, unless NEW_EDGES is NULL.  */
-static void
+   *NEW_EDGES, unless NEW_EDGES is NULL.  Return true iff a new edge(s) were
+   created.  */
+static bool
 propagate_info_to_inlined_callees (struct cgraph_edge *cs,
 				   struct cgraph_node *node,
 				   VEC (cgraph_edge_p, heap) **new_edges)
 {
   struct cgraph_edge *e;
+  bool res;
 
-  update_call_notes_after_inlining (cs, node, new_edges);
+  res = update_call_notes_after_inlining (cs, node, new_edges);
 
   for (e = node->callees; e; e = e->next_callee)
     if (!e->inline_failed)
-      propagate_info_to_inlined_callees (cs, e->callee, new_edges);
+      res |= propagate_info_to_inlined_callees (cs, e->callee, new_edges);
     else
       update_jump_functions_after_inlining (cs, e);
+
+  return res;
 }
 
 /* Update jump functions and call note functions on inlining the call site CS.
    CS is expected to lead to a node already cloned by
    cgraph_clone_inline_nodes.  Newly discovered indirect edges will be added to
-   *NEW_EDGES, unless NEW_EDGES is NULL.  */
-void
+   *NEW_EDGES, unless NEW_EDGES is NULL.  Return true iff a new edge(s) were +
+   created.  */
+bool
 ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
 				   VEC (cgraph_edge_p, heap) **new_edges)
 {
-  propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
+  /* Do nothing if the preparation phase has not been carried out yet
+     (i.e. during early inlining).  */
+  if (!ipa_node_params_vector)
+    return false;
+  gcc_assert (ipa_edge_args_vector);
+
+  return propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
 }
 
 /* Frees all dynamically allocated structures that the argument info points
@@ -1020,12 +1042,8 @@
 void
 ipa_free_node_params_substructures (struct ipa_node_params *info)
 {
-  if (info->ipcp_lattices)
-    free (info->ipcp_lattices);
-  if (info->param_decls)
-    free (info->param_decls);
-  if (info->param_flags)
-    free (info->param_flags);
+  if (info->params)
+    free (info->params);
 
   while (info->param_calls)
     {
@@ -1091,7 +1109,7 @@
 /* Hook that is called by cgraph.c when a node is duplicated.  */
 static void
 ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
-			   void *data)
+			   __attribute__((unused)) void *data)
 {
   struct ipa_edge_args *old_args, *new_args;
   int arg_count;
@@ -1106,13 +1124,12 @@
   new_args->jump_functions = (struct ipa_jump_func *)
     duplicate_array (old_args->jump_functions,
 		     sizeof (struct ipa_jump_func) * arg_count);
-  data = data; 			/* Suppressing compiler warning.  */
 }
 
 /* Hook that is called by cgraph.c when a node is duplicated.  */
 static void
 ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
-			   void *data)
+			   __attribute__((unused)) void *data)
 {
   struct ipa_node_params *old_info, *new_info;
   struct ipa_param_call_note *note;
@@ -1124,15 +1141,9 @@
   param_count = ipa_get_param_count (old_info);
 
   ipa_set_param_count (new_info, param_count);
-  new_info->ipcp_lattices = (struct ipcp_lattice *)
-    duplicate_array (old_info->ipcp_lattices,
-		     sizeof (struct ipcp_lattice) * param_count);
-  new_info->param_decls = (tree *)
-    duplicate_array (old_info->param_decls, sizeof (tree) * param_count);
-  new_info->param_flags = (struct ipa_param_flags *)
-    duplicate_array (old_info->param_flags,
-		     sizeof (struct ipa_param_flags) * param_count);
-
+  new_info->params = (struct ipa_param_descriptor *)
+    duplicate_array (old_info->params,
+		     sizeof (struct ipa_param_descriptor) * param_count);
   new_info->ipcp_orig_node = old_info->ipcp_orig_node;
   new_info->count_scale = old_info->count_scale;
 
@@ -1146,8 +1157,6 @@
       nn->next = new_info->param_calls;
       new_info->param_calls = nn;
     }
-
-  data = data; 			/* Suppressing compiler warning.  */
 }
 
 /* Register our cgraph hooks if they are not already there.  */
@@ -1221,13 +1230,13 @@
   count = ipa_get_param_count (info);
   for (i = 0; i < count; i++)
     {
-      temp = ipa_get_ith_param (info, i);
+      temp = ipa_get_param (info, i);
       if (TREE_CODE (temp) == PARM_DECL)
 	fprintf (f, "    param %d : %s", i,
 		 (*lang_hooks.decl_printable_name) (temp, 2));
-      if (ipa_is_ith_param_modified (info, i))
+      if (ipa_is_param_modified (info, i))
 	fprintf (f, " modified");
-      if (ipa_is_ith_param_called (info, i))
+      if (ipa_is_param_called (info, i))
 	fprintf (f, " called");
       fprintf (f, "\n");
     }
Index: gcc/ipa-prop.h
===================================================================
--- gcc/ipa-prop.h	(revision 140291)
+++ gcc/ipa-prop.h	(working copy)
@@ -110,16 +110,6 @@
   bool ref_p;
 };
 
-/* ipa_param_flags contains various flags that describe how the associated
-   parameter is treated within a function. */
-struct ipa_param_flags
-{
-  /* Whether the value parameter has been modified within the function.  */
-  unsigned modified : 1;
-  /* Whether the parameter has been used as a call destination. */
-  unsigned called : 1;
-};
-
 /* Each instance of the following  structure describes a statement that calls a
    function parameter.  Those referring  to statements within the same function
    are linked in a list.  */
@@ -144,6 +134,19 @@
   bool processed;
 };
 
+/* Structure describing a single formal parameter.  */
+struct ipa_param_descriptor
+{
+  /* IPA-CP lattice.  */
+  struct ipcp_lattice ipcp_lattice;
+  /* PARAM_DECL of this parameter.  */
+  tree decl;
+  /* Whether the value parameter has been modified within the function.  */
+  unsigned modified : 1;
+  /* Whether the parameter has been used as a call destination. */
+  unsigned called : 1;
+};
+
 /* ipa_node_params stores information related to formal parameters of functions
    and some other information for interprocedural passes that operate on
    parameters (such as ipa-cp).  */
@@ -153,12 +156,9 @@
      this function's parameters would not be analyzed by the different
      stages of IPA CP.  */
   int param_count;
-  /* Array of lattices.  */
-  struct ipcp_lattice *ipcp_lattices;
-  /* Mapping each parameter to its PARM_DECL tree.  */
-  tree *param_decls;
-  /* Various flags describing individual parameters.  */
-  struct ipa_param_flags *param_flags;
+  /* Pointer to an array of structures describing individual formal
+     parameters.  */
+  struct ipa_param_descriptor *params;
   /* List of structures enumerating calls to a formal parameter.  */
   struct ipa_param_call_note *param_calls;
   /* Only for versioned nodes this field would not be NULL,
@@ -197,31 +197,33 @@
   return info->param_count;
 }
 
-/* Returns the declaration of ith param of the corresponding node.  Note there
-   is no setter function as this array is built just once using
-   ipa_create_param_decls_array. */
+/* Return the declaration of Ith formal parameter of the function corresponding
+   to INFO.  Note there is no setter function as this array is built just once
+   using ipa_initialize_node_params. */
 static inline tree
-ipa_get_ith_param (struct ipa_node_params *info, int i)
+ipa_get_param (struct ipa_node_params *info, int i)
 {
-  return info->param_decls[i];
+  return info->params[i].decl;
 }
 
-/* Returns the modification flag corresponding to the ith parameter.  Note
-   there is no setter method as the goal is to set all flags when building the
-   array in ipa_detect_param_modifications.  */
+/* Return the modification flag corresponding to the Ith formal parameter of
+   the function associated with INFO.  Note that there is no setter method as
+   the goal is to set all flags when building the array in
+   ipa_detect_param_modifications.  */
 static inline bool
-ipa_is_ith_param_modified (struct ipa_node_params *info, int i)
+ipa_is_param_modified (struct ipa_node_params *info, int i)
 {
-  return info->param_flags[i].modified;
+  return info->params[i].modified;
 }
 
-/* Returns the called flag corresponding o the ith paramterer.  Note there is
-   no setter method as the goal is to set all flags when building the array in
+/* Return the called flag corresponding to the Ith formal parameter of the
+   function associated with INFO.  Note that there is no setter method as the
+   goal is to set all flags when building the array in
    ipa_detect_called_params.  */
 static inline bool
-ipa_is_ith_param_called (struct ipa_node_params *info, int i)
+ipa_is_param_called (struct ipa_node_params *info, int i)
 {
-  return info->param_flags[i].called;
+  return info->params[i].called;
 }
 
 /* Flag this node as having callers with variable number of arguments.  */
@@ -372,12 +374,11 @@
 void ipa_compute_jump_functions (struct cgraph_edge *);
 void ipa_count_arguments (struct cgraph_edge *);
 
-/* Function parameters related computations.  */
-void ipa_count_formal_params (struct cgraph_node *);
-void ipa_create_param_decls_array (struct cgraph_node *);
+/* Function formal parameters related computations.  */
+void ipa_initialize_node_params (struct cgraph_node *node);
 void ipa_detect_param_modifications (struct cgraph_node *);
 void ipa_analyze_params_uses (struct cgraph_node *);
-void ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
+bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
 					VEC (cgraph_edge_p, heap) **new_edges);
 
 /* Debugging interface.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]