]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ipa-prop.h (struct ipa_param_flags): Removed.
authorMartin Jambor <mjambor@suse.cz>
Thu, 11 Sep 2008 17:03:23 +0000 (19:03 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Thu, 11 Sep 2008 17:03:23 +0000 (19:03 +0200)
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.

From-SVN: r140293

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

index 33de0138db08b747c059d38d0c0f6057cf62e31c..aaec4d73a8b7f5abc565fb259cdbff1000461b0b 100644 (file)
@@ -1,3 +1,66 @@
+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.
+
 2008-09-11  Richard Guenther  <rguenther@suse.de>
 
        * tree-vectorizer.c (slpeel_add_loop_guard): Fix types.
index eec56a5390306d6ad29b8ad7db8579cd484aa33e..a6018dc89101ecfc3d5a70aaf8121e2cdff680e4 100644 (file)
@@ -452,7 +452,6 @@ varpool_next_static_initializer (struct varpool_node *node)
 
 /* 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 8f1c1614cd8f227d74f0469cb2c735acb83c13f6..8dbc9f87f99b27d9523c26f2d33ea9ab6066eb2c 100644 (file)
@@ -171,9 +171,8 @@ ipcp_init_cloned_node (struct cgraph_node *orig_node,
                       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 @@ ipcp_analyze_node (struct cgraph_node *node)
   /* 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 @@ ipa_lattice_meet (struct ipcp_lattice *res, struct ipcp_lattice *lat1,
 /* 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 @@ ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
     {
       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 @@ ipcp_print_all_lattices (FILE * f)
       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 @@ ipcp_initialize_node_lattices (struct cgraph_node *node)
   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 @@ ipcp_initialize_node_lattices (struct cgraph_node *node)
     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 @@ ipcp_change_tops_to_bottom (void)
       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 @@ ipcp_propagate_stage (void)
            {
              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 @@ ipcp_need_redirect_p (struct cgraph_edge *cs)
   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 @@ ipcp_update_callgraph (void)
 
        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 @@ ipcp_estimate_growth (struct cgraph_node *node)
   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 @@ ipcp_const_param_count (struct cgraph_node *node)
 
   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 @@ ipcp_insert_stage (void)
       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 88566fed007d8817546b15c56eadc263b4f64bcc..662cff60b507ea0a30edd9e026083c3b1dae6552 100644 (file)
@@ -243,15 +243,19 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
       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 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original)
   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 @@ cgraph_mark_inline (struct cgraph_edge *edge)
       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 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node,
          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 @@ cgraph_decide_inlining_of_small_functions (void)
              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 @@ cgraph_decide_inlining (void)
   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 @@ cgraph_decide_inlining (void)
 
   /* 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 @@ cgraph_decide_inlining (void)
        }
     }
 
+  /* 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 @@ inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
 
   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 f8b73439ed903806d6d08010e45e12aa2a0bb734..90b0333e7836db412ae150c838b2efd0dfc328d7 100644 (file)
@@ -102,52 +102,67 @@ ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree)
 
   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
@@ -173,13 +188,13 @@ ipa_check_stmt_modifications (struct ipa_node_params *info, gimple stmt)
        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 @@ ipa_detect_param_modifications (struct cgraph_node *node)
   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 @@ ipa_detect_param_modifications (struct cgraph_node *node)
 
   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 @@ compute_pass_through_member_ptrs (struct ipa_node_params *info,
              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 @@ ipa_note_param_call (struct ipa_node_params *info, int formal_id,
   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 @@ ipa_analyze_call_uses (struct ipa_node_params *info, gimple call)
     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 @@ ipa_analyze_params_uses (struct cgraph_node *node)
 
   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 @@ print_edge_addition_message (FILE *f, struct ipa_param_call_note *nt,
    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 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
   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 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
          if (!callee || !callee->local.inlinable)
            continue;
 
+         res = true;
          if (dump_file)
            print_edge_addition_message (dump_file, nt, jfunc, node);
 
@@ -953,6 +963,7 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
          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 (struct cgraph_edge *cs,
    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 @@ ipa_free_all_edge_args (void)
 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 @@ duplicate_array (void *src, size_t n)
 /* 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 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
   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 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
   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 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
       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 @@ ipa_print_node_params (FILE * f, struct cgraph_node *node)
   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 c1bc1a2003a2c6c74b7e2be78a5e925506ec0efb..47010e1ab5930bd8c9d51b5cb39cc77e7d707c39 100644 (file)
@@ -110,16 +110,6 @@ struct ipa_replace_map
   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 @@ struct ipa_param_call_note
   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 @@ struct ipa_node_params
      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 @@ ipa_get_param_count (struct ipa_node_params *info)
   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 @@ struct cgraph_node *ipa_pop_func_from_list (struct ipa_func_list **);
 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.  */