Hi,
this is preparation work to move DECL_ARGUMENTS and DECL_RESULT into function
sections during WPA.  Even with some work to release unused ones, there are 4M
of PARM_DECLs and 2M of RESULT_DECLs streamed during LTO (for 6M of
function_decls) making them one of the most common nodes.

This patch makes ipa-cp and ipa-prop to not use DECL_ARGUMENTS during WPA
stage.  this only needed to tamn debug info, move logic doing casts from
get_replacement_map to tree_function_versioning and stream move_cost that is
computed form parm type.

Martin, does this patch look OK?

Honza

        * ipa-cp.c (gather_context_independent_values): Use 
ipa_get_param_move_cost.
        (get_replacement_map): Remove PARAM; move parameter folding into 
tree-inline.c
        (create_specialized_node): Update.
        * ipa-prop.c (ipa_populate_param_decls): Do not look for origins;
        assert that we have gimple body; update move_cost.
        (count_formal_params): Assert that we have gimple body.
        (ipa_alloc_node_params): Break out from ...
        (ipa_initialize_node_params): ... here.
        (ipa_get_vector_of_formal_parms): ICE when used in WPA.
        (ipa_write_node_info): Stream move costs.
        (ipa_read_node_info): Read move costs.
        (ipa_update_after_lto_read): Do not recompute node params.
        * ipa-prop.h (ipa_param_descriptor): Add move_cost.
        (ipa_get_param): Check we are not in WPA.
        (ipa_get_param_move_cost): New.
        * tree-inline.c (tree_function_versioning): Fold replacement as needed.
Index: ipa-cp.c
===================================================================
*** ipa-cp.c    (revision 201291)
--- ipa-cp.c    (working copy)
*************** gather_context_independent_values (struc
*** 1758,1770 ****
            }
          else if (removable_params_cost
                   && !ipa_is_param_used (info, i))
!           *removable_params_cost
!             += estimate_move_cost (TREE_TYPE (ipa_get_param (info, i)));
        }
        else if (removable_params_cost
               && !ipa_is_param_used (info, i))
        *removable_params_cost
!         += estimate_move_cost (TREE_TYPE (ipa_get_param (info, i)));
  
        if (known_aggs)
        {
--- 1758,1769 ----
            }
          else if (removable_params_cost
                   && !ipa_is_param_used (info, i))
!           *removable_params_cost += ipa_get_param_move_cost (info, i);
        }
        else if (removable_params_cost
               && !ipa_is_param_used (info, i))
        *removable_params_cost
!         += ipa_get_param_move_cost (info, i);
  
        if (known_aggs)
        {
*************** gather_edges_for_value (struct ipcp_valu
*** 2480,2515 ****
     Return it or NULL if for some reason it cannot be created.  */
  
  static struct ipa_replace_map *
! get_replacement_map (tree value, tree parm, int parm_num)
  {
-   tree req_type = TREE_TYPE (parm);
    struct ipa_replace_map *replace_map;
  
-   if (!useless_type_conversion_p (req_type, TREE_TYPE (value)))
-     {
-       if (fold_convertible_p (req_type, value))
-       value = fold_build1 (NOP_EXPR, req_type, value);
-       else if (TYPE_SIZE (req_type) == TYPE_SIZE (TREE_TYPE (value)))
-       value = fold_build1 (VIEW_CONVERT_EXPR, req_type, value);
-       else
-       {
-         if (dump_file)
-           {
-             fprintf (dump_file, "    const ");
-             print_generic_expr (dump_file, value, 0);
-             fprintf (dump_file, "  can't be converted to param ");
-             print_generic_expr (dump_file, parm, 0);
-             fprintf (dump_file, "\n");
-           }
-         return NULL;
-       }
-     }
  
    replace_map = ggc_alloc_ipa_replace_map ();
    if (dump_file)
      {
!       fprintf (dump_file, "    replacing param ");
!       print_generic_expr (dump_file, parm, 0);
        fprintf (dump_file, " with const ");
        print_generic_expr (dump_file, value, 0);
        fprintf (dump_file, "\n");
--- 2479,2494 ----
     Return it or NULL if for some reason it cannot be created.  */
  
  static struct ipa_replace_map *
! get_replacement_map (tree value, int parm_num)
  {
    struct ipa_replace_map *replace_map;
  
  
    replace_map = ggc_alloc_ipa_replace_map ();
    if (dump_file)
      {
!       fprintf (dump_file, "    replacing param %i", parm_num);
!   
        fprintf (dump_file, " with const ");
        print_generic_expr (dump_file, value, 0);
        fprintf (dump_file, "\n");
*************** create_specialized_node (struct cgraph_n
*** 2697,2703 ****
        {
          struct ipa_replace_map *replace_map;
  
!         replace_map = get_replacement_map (t, ipa_get_param (info, i), i);
          if (replace_map)
            vec_safe_push (replace_trees, replace_map);
        }
--- 2676,2682 ----
        {
          struct ipa_replace_map *replace_map;
  
!         replace_map = get_replacement_map (t, i);
          if (replace_map)
            vec_safe_push (replace_trees, replace_map);
        }
Index: ipa-prop.c
===================================================================
*** ipa-prop.c  (revision 201291)
--- ipa-prop.c  (working copy)
*************** ipa_populate_param_decls (struct cgraph_
*** 130,145 ****
    tree parm;
    int param_num;
  
-   /* We do not copy DECL_ARGUMENTS to virtual clones.  */
-   while (node->clone_of)
-     node = node->clone_of;
- 
    fndecl = node->symbol.decl;
    fnargs = DECL_ARGUMENTS (fndecl);
    param_num = 0;
    for (parm = fnargs; parm; parm = DECL_CHAIN (parm))
      {
        descriptors[param_num].decl = parm;
        param_num++;
      }
  }
--- 130,143 ----
    tree parm;
    int param_num;
  
    fndecl = node->symbol.decl;
+   gcc_assert (gimple_has_body_p (fndecl));
    fnargs = DECL_ARGUMENTS (fndecl);
    param_num = 0;
    for (parm = fnargs; parm; parm = DECL_CHAIN (parm))
      {
        descriptors[param_num].decl = parm;
+       descriptors[param_num].move_cost = estimate_move_cost (TREE_TYPE 
(parm));
        param_num++;
      }
  }
*************** count_formal_params (tree fndecl)
*** 151,156 ****
--- 149,155 ----
  {
    tree parm;
    int count = 0;
+   gcc_assert (gimple_has_body_p (fndecl));
  
    for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
      count++;
*************** count_formal_params (tree fndecl)
*** 158,163 ****
--- 157,174 ----
    return count;
  }
  
+ /* Initialize the ipa_node_params structure associated with NODE 
+    to hold PARAM_COUNT parameters.  */
+ 
+ void
+ ipa_alloc_node_params (struct cgraph_node *node, int param_count)
+ {
+   struct ipa_node_params *info = IPA_NODE_REF (node);
+ 
+   if (!info->descriptors.exists () && param_count)
+     info->descriptors.safe_grow_cleared (param_count);
+ }
+ 
  /* Initialize the ipa_node_params structure associated with NODE by counting
     the function parameters, creating the descriptors and populating their
     param_decls.  */
*************** ipa_initialize_node_params (struct cgrap
*** 169,183 ****
  
    if (!info->descriptors.exists ())
      {
!       int param_count;
!       gcc_assert (!node->clone_of);
! 
!       param_count = count_formal_params (node->symbol.decl);
!       if (param_count)
!       {
!         info->descriptors.safe_grow_cleared (param_count);
!         ipa_populate_param_decls (node, info->descriptors);
!       }
      }
  }
  
--- 180,187 ----
  
    if (!info->descriptors.exists ())
      {
!       ipa_alloc_node_params (node, count_formal_params (node->symbol.decl));
!       ipa_populate_param_decls (node, info->descriptors);
      }
  }
  
*************** ipa_get_vector_of_formal_parms (tree fnd
*** 3064,3069 ****
--- 3068,3074 ----
    int count;
    tree parm;
  
+   gcc_assert (!flag_wpa);
    count = count_formal_params (fndecl);
    args.create (count);
    for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
*************** ipa_write_node_info (struct output_block
*** 3856,3861 ****
--- 3861,3869 ----
    node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
    streamer_write_uhwi (ob, node_ref);
  
+   streamer_write_uhwi (ob, ipa_get_param_count (info));
+   for (j = 0; j < ipa_get_param_count (info); j++)
+     streamer_write_uhwi (ob, ipa_get_param_move_cost (info, j));
    bp = bitpack_create (ob->main_stream);
    gcc_assert (info->uses_analysis_done
              || ipa_get_param_count (info) == 0);
*************** ipa_read_node_info (struct lto_input_blo
*** 3896,3903 ****
    struct cgraph_edge *e;
    struct bitpack_d bp;
  
!   ipa_initialize_node_params (node);
  
    bp = streamer_read_bitpack (ib);
    if (ipa_get_param_count (info) != 0)
      info->uses_analysis_done = true;
--- 3904,3914 ----
    struct cgraph_edge *e;
    struct bitpack_d bp;
  
!   ipa_alloc_node_params (node, streamer_read_uhwi (ib));
  
+   for (k = 0; k < ipa_get_param_count (info); k++)
+     info->descriptors[k].move_cost = streamer_read_uhwi (ib);
+     
    bp = streamer_read_bitpack (ib);
    if (ipa_get_param_count (info) != 0)
      info->uses_analysis_done = true;
*************** ipa_prop_read_jump_functions (void)
*** 4049,4061 ****
  void
  ipa_update_after_lto_read (void)
  {
-   struct cgraph_node *node;
- 
    ipa_check_create_node_params ();
    ipa_check_create_edge_args ();
- 
-   FOR_EACH_DEFINED_FUNCTION (node)
-     ipa_initialize_node_params (node);
  }
  
  void
--- 4060,4067 ----
Index: ipa-prop.h
===================================================================
*** ipa-prop.h  (revision 201291)
--- ipa-prop.h  (working copy)
*************** struct ipa_param_descriptor
*** 320,325 ****
--- 320,326 ----
       says how many there are.  If any use could not be described by means of
       ipa-prop structures, this is IPA_UNDESCRIBED_USE.  */
    int controlled_uses;
+   unsigned int move_cost : 31;
    /* The parameter is used.  */
    unsigned used : 1;
  };
*************** ipa_get_param_count (struct ipa_node_par
*** 377,385 ****
--- 378,396 ----
  static inline tree
  ipa_get_param (struct ipa_node_params *info, int i)
  {
+   gcc_checking_assert (!flag_wpa);
    return info->descriptors[i].decl;
  }
  
+ /* Return the move cost of Ith formal parameter of the function corresponding
+    to INFO.  */
+ 
+ static inline int
+ ipa_get_param_move_cost (struct ipa_node_params *info, int i)
+ {
+   return info->descriptors[i].move_cost;
+ }
+ 
  /* Set the used flag corresponding to the Ith formal parameter of the function
     associated with INFO to VAL.  */
  
Index: tree-inline.c
===================================================================
*** tree-inline.c       (revision 201291)
--- tree-inline.c       (working copy)
*************** tree_function_versioning (tree old_decl,
*** 5146,5162 ****
              {
                int i = replace_info->parm_num;
                tree parm;
                for (parm = DECL_ARGUMENTS (old_decl); i; parm = DECL_CHAIN 
(parm))
                  i --;
                replace_info->old_tree = parm;
              }
-           gcc_assert (TREE_CODE (replace_info->old_tree) == PARM_DECL);
-           init = setup_one_parameter (&id, replace_info->old_tree,
-                                       replace_info->new_tree, id.src_fn,
-                                       NULL,
-                                       &vars);
-           if (init)
-             init_stmts.safe_push (init);
          }
        }
    /* Copy the function's arguments.  */
--- 5150,5192 ----
              {
                int i = replace_info->parm_num;
                tree parm;
+               tree req_type;
+ 
                for (parm = DECL_ARGUMENTS (old_decl); i; parm = DECL_CHAIN 
(parm))
                  i --;
                replace_info->old_tree = parm;
+               req_type = TREE_TYPE (parm);
+               if (!useless_type_conversion_p (req_type, TREE_TYPE 
(replace_info->new_tree)))
+                 {
+                   if (fold_convertible_p (req_type, replace_info->new_tree))
+                     replace_info->new_tree = fold_build1 (NOP_EXPR, req_type, 
replace_info->new_tree);
+                   else if (TYPE_SIZE (req_type) == TYPE_SIZE (TREE_TYPE 
(replace_info->new_tree)))
+                     replace_info->new_tree = fold_build1 (VIEW_CONVERT_EXPR, 
req_type, replace_info->new_tree);
+                   else
+                     {
+                       if (dump_file)
+                         {
+                           fprintf (dump_file, "    const ");
+                           print_generic_expr (dump_file, 
replace_info->new_tree, 0);
+                           fprintf (dump_file, "  can't be converted to param 
");
+                           print_generic_expr (dump_file, parm, 0);
+                           fprintf (dump_file, "\n");
+                         }
+                       replace_info->old_tree = NULL;
+                     }
+                 }
+             }
+           else
+             gcc_assert (TREE_CODE (replace_info->old_tree) == PARM_DECL);
+           if (replace_info->old_tree)
+             {
+               init = setup_one_parameter (&id, replace_info->old_tree,
+                                           replace_info->new_tree, id.src_fn,
+                                           NULL,
+                                           &vars);
+               if (init)
+                 init_stmts.safe_push (init);
              }
          }
        }
    /* Copy the function's arguments.  */

Reply via email to