LCOV - code coverage report
Current view: top level - gcc - ipa-param-manipulation.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.9 % 1295 1086
Test Date: 2026-02-28 14:20:25 Functions: 91.8 % 61 56
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Manipulation of formal and actual parameters of functions and function
       2              :    calls.
       3              :    Copyright (C) 2017-2026 Free Software Foundation, Inc.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #define INCLUDE_ALGORITHM
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "backend.h"
      26              : #include "tree.h"
      27              : #include "gimple.h"
      28              : #include "ssa.h"
      29              : #include "cgraph.h"
      30              : #include "fold-const.h"
      31              : #include "tree-eh.h"
      32              : #include "stor-layout.h"
      33              : #include "gimplify.h"
      34              : #include "gimple-iterator.h"
      35              : #include "gimplify-me.h"
      36              : #include "tree-cfg.h"
      37              : #include "tree-dfa.h"
      38              : #include "ipa-param-manipulation.h"
      39              : #include "print-tree.h"
      40              : #include "gimple-pretty-print.h"
      41              : #include "builtins.h"
      42              : #include "tree-ssa.h"
      43              : #include "tree-inline.h"
      44              : #include "alloc-pool.h"
      45              : #include "symbol-summary.h"
      46              : #include "symtab-clones.h"
      47              : #include "tree-phinodes.h"
      48              : #include "cfgexpand.h"
      49              : #include "attribs.h"
      50              : #include "sreal.h"
      51              : #include "ipa-cp.h"
      52              : #include "ipa-prop.h"
      53              : #include "attr-callback.h"
      54              : 
      55              : /* Actual prefixes of different newly synthetized parameters.  Keep in sync
      56              :    with IPA_PARAM_PREFIX_* defines.  */
      57              : 
      58              : static const char *ipa_param_prefixes[IPA_PARAM_PREFIX_COUNT]
      59              :   = {"SYNTH",
      60              :      "ISRA",
      61              :      "simd",
      62              :      "mask"};
      63              : 
      64              : /* Names of parameters for dumping.  Keep in sync with enum ipa_parm_op.  */
      65              : 
      66              : static const char *ipa_param_op_names[IPA_PARAM_PREFIX_COUNT]
      67              :   = {"IPA_PARAM_OP_UNDEFINED",
      68              :      "IPA_PARAM_OP_COPY",
      69              :      "IPA_PARAM_OP_NEW",
      70              :      "IPA_PARAM_OP_SPLIT"};
      71              : 
      72              : /* Structure to hold declarations representing pass-through IPA-SRA splits.  In
      73              :    essence, it tells new index for a combination of original index and
      74              :    offset.  */
      75              : 
      76              : struct pass_through_split_map
      77              : {
      78              :   /* Original argument index.  */
      79              :   unsigned base_index;
      80              :   /* Offset of the split part in the original argument.  */
      81              :   unsigned unit_offset;
      82              :   /* Index of the split part in the call statement - where clone
      83              :      materialization put it.  */
      84              :   int new_index;
      85              : };
      86              : 
      87              : /* Information about some call statements that needs to be conveyed from clone
      88              :    materialization to edge redirection. */
      89              : 
      90        60827 : class ipa_edge_modification_info
      91              : {
      92              :  public:
      93        60827 :   ipa_edge_modification_info ()
      94        60827 :     {}
      95              : 
      96              :   /* Mapping of original argument indices to where those arguments sit in the
      97              :      call statement now or to a negative index if they were removed.  */
      98              :   auto_vec<int> index_map;
      99              :   /* Information about ISRA replacements put into the call statement at the
     100              :      clone materialization stages.  */
     101              :   auto_vec<pass_through_split_map> pass_through_map;
     102              :   /* Necessary adjustment to ipa_param_adjustments::m_always_copy_start when
     103              :      redirecting the call.  */
     104              :   int always_copy_delta = 0;
     105              : };
     106              : 
     107              : /* Class for storing and retrieving summaries about cal statement
     108              :    modifications.  */
     109              : 
     110              : class ipa_edge_modification_sum
     111              :   : public call_summary <ipa_edge_modification_info *>
     112              : {
     113              :  public:
     114         2884 :   ipa_edge_modification_sum (symbol_table *table)
     115         5768 :     : call_summary<ipa_edge_modification_info *> (table)
     116              :   {
     117              :   }
     118              : 
     119              :   /* Hook that is called by summary when an edge is duplicated.  */
     120              : 
     121        28445 :   void duplicate (cgraph_edge *,
     122              :                   cgraph_edge *,
     123              :                   ipa_edge_modification_info *old_info,
     124              :                   ipa_edge_modification_info *new_info) final override
     125              :   {
     126        28445 :     new_info->index_map.safe_splice (old_info->index_map);
     127        28445 :     new_info->pass_through_map.safe_splice (old_info->pass_through_map);
     128        28445 :     new_info->always_copy_delta = old_info->always_copy_delta;
     129        28445 :   }
     130              : };
     131              : 
     132              : /* Call summary to store information about edges which have had their arguments
     133              :    partially modified already.  */
     134              : 
     135              : static ipa_edge_modification_sum *ipa_edge_modifications;
     136              : 
     137              : /* Fail compilation if CS has any summary associated with it in
     138              :    ipa_edge_modifications.  */
     139              : 
     140              : DEBUG_FUNCTION void
     141       344544 : ipa_verify_edge_has_no_modifications (cgraph_edge *cs)
     142              : {
     143       344544 :   gcc_assert (!ipa_edge_modifications || !ipa_edge_modifications->get (cs));
     144       344544 : }
     145              : 
     146              : /* Fill an empty vector ARGS with PARM_DECLs representing formal parameters of
     147              :    FNDECL.  The function should not be called during LTO WPA phase except for
     148              :    thunks (or functions with bodies streamed in). */
     149              : 
     150              : void
     151       182827 : push_function_arg_decls (vec<tree> *args, tree fndecl)
     152              : {
     153       182827 :   int count;
     154       182827 :   tree parm;
     155              : 
     156              :   /* Safety check that we do not attempt to use the function in WPA, except
     157              :      when the function is a thunk and then we have DECL_ARGUMENTS or when we
     158              :      have already explicitly loaded its body.  */
     159       182829 :   gcc_assert (!flag_wpa
     160              :               || DECL_ARGUMENTS (fndecl)
     161              :               || gimple_has_body_p (fndecl));
     162       182827 :   count = 0;
     163       659698 :   for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
     164       476871 :     count++;
     165              : 
     166       182827 :   args->reserve_exact (count);
     167       659698 :   for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
     168       476871 :     args->quick_push (parm);
     169       182827 : }
     170              : 
     171              : /* Fill an empty vector TYPES with trees representing formal parameters of
     172              :    function type FNTYPE.  */
     173              : 
     174              : void
     175       411841 : push_function_arg_types (vec<tree> *types, tree fntype)
     176              : {
     177       411841 :   int count = 0;
     178       411841 :   tree t;
     179              : 
     180      1948625 :   for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
     181      1536784 :     count++;
     182              : 
     183       411841 :   types->reserve_exact (count);
     184      1948625 :   for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
     185      1536784 :     types->quick_push (TREE_VALUE (t));
     186       411841 : }
     187              : 
     188              : /* Dump the adjustments in the vector ADJUSTMENTS to dump_file in a human
     189              :    friendly way, assuming they are meant to be applied to FNDECL.  */
     190              : 
     191              : void
     192            9 : ipa_dump_adjusted_parameters (FILE *f,
     193              :                               vec<ipa_adjusted_param, va_gc> *adj_params)
     194              : {
     195            9 :   unsigned i, len = vec_safe_length (adj_params);
     196           17 :   bool first = true;
     197              : 
     198            8 :   if (!len)
     199              :     return;
     200              : 
     201            8 :   fprintf (f, "    IPA adjusted parameters: ");
     202           29 :   for (i = 0; i < len; i++)
     203              :     {
     204           21 :       struct ipa_adjusted_param *apm;
     205           21 :       apm = &(*adj_params)[i];
     206              : 
     207           21 :       if (!first)
     208           13 :         fprintf (f, "                             ");
     209              :       else
     210              :         first = false;
     211              : 
     212           21 :       fprintf (f, "%i. %s %s", i, ipa_param_op_names[apm->op],
     213           21 :                apm->prev_clone_adjustment ? "prev_clone_adjustment " : "");
     214           21 :       switch (apm->op)
     215              :         {
     216              :         case IPA_PARAM_OP_UNDEFINED:
     217              :           break;
     218              : 
     219            8 :         case IPA_PARAM_OP_COPY:
     220            8 :           fprintf (f, ", base_index: %u", apm->base_index);
     221            8 :           fprintf (f, ", prev_clone_index: %u", apm->prev_clone_index);
     222            8 :           break;
     223              : 
     224           13 :         case IPA_PARAM_OP_SPLIT:
     225           13 :           fprintf (f, ", offset: %u", apm->unit_offset);
     226              :           /* fall-through */
     227           13 :         case IPA_PARAM_OP_NEW:
     228           13 :           fprintf (f, ", base_index: %u", apm->base_index);
     229           13 :           fprintf (f, ", prev_clone_index: %u", apm->prev_clone_index);
     230           13 :           print_node_brief (f, ", type: ", apm->type, 0);
     231           13 :           print_node_brief (f, ", alias type: ", apm->alias_ptr_type, 0);
     232           13 :           fprintf (f, " prefix: %s",
     233           13 :                    ipa_param_prefixes[apm->param_prefix_index]);
     234           13 :           if (apm->reverse)
     235            0 :             fprintf (f, ", reverse");
     236              :           break;
     237              :         }
     238           21 :       fprintf (f, "\n");
     239              :     }
     240              : }
     241              : 
     242              : /* Fill NEW_TYPES with types of a function after its current OTYPES have been
     243              :    modified as described in ADJ_PARAMS.  When USE_PREV_INDICES is true, use
     244              :    prev_clone_index from ADJ_PARAMS as opposed to base_index when the parameter
     245              :    is false.  */
     246              : 
     247              : static void
     248       407314 : fill_vector_of_new_param_types (vec<tree> *new_types, vec<tree> *otypes,
     249              :                                 vec<ipa_adjusted_param, va_gc> *adj_params,
     250              :                                 bool use_prev_indices)
     251              : {
     252       407314 :   unsigned adj_len = vec_safe_length (adj_params);
     253       407314 :   new_types->reserve_exact (adj_len);
     254      1290838 :   for (unsigned i = 0; i < adj_len ; i++)
     255              :     {
     256       883524 :       ipa_adjusted_param *apm = &(*adj_params)[i];
     257       883524 :       if (apm->op == IPA_PARAM_OP_COPY)
     258              :         {
     259      1332236 :           unsigned index
     260       666118 :             = use_prev_indices ? apm->prev_clone_index : apm->base_index;
     261              :           /* The following needs to be handled gracefully because of type
     262              :              mismatches.  This happens with LTO but apparently also in Fortran
     263              :              with -fcoarray=lib -O2 -lcaf_single -latomic.  */
     264       666118 :           if (index >= otypes->length ())
     265            0 :             continue;
     266       666118 :           new_types->quick_push ((*otypes)[index]);
     267              :         }
     268       217406 :       else if (apm->op == IPA_PARAM_OP_NEW
     269       217406 :                || apm->op == IPA_PARAM_OP_SPLIT)
     270              :         {
     271       217406 :           tree ntype = apm->type;
     272       217406 :           if (is_gimple_reg_type (ntype)
     273       217406 :               && TYPE_MODE (ntype) != BLKmode)
     274              :             {
     275       215590 :               unsigned malign = GET_MODE_ALIGNMENT (TYPE_MODE (ntype));
     276       215590 :               if (TYPE_ALIGN (ntype) != malign)
     277         2101 :                 ntype = build_aligned_type (ntype, malign);
     278              :             }
     279       217406 :           new_types->quick_push (ntype);
     280              :         }
     281              :       else
     282            0 :         gcc_unreachable ();
     283              :     }
     284       407314 : }
     285              : 
     286              : /* Return false if given attribute should prevent type adjustments.  */
     287              : 
     288              : bool
     289       388146 : ipa_param_adjustments::type_attribute_allowed_p (tree name)
     290              : {
     291       629414 :   if ((is_attribute_p ("fn spec", name) && flag_ipa_modref)
     292       172657 :       || is_attribute_p ("access", name)
     293       159305 :       || is_attribute_p ("returns_nonnull", name)
     294       157928 :       || is_attribute_p ("assume_aligned", name)
     295       157928 :       || is_attribute_p ("nocf_check", name)
     296       546025 :       || is_attribute_p ("warn_unused_result", name))
     297              :     return true;
     298              :   return false;
     299              : }
     300              : 
     301              : /* Return true if attribute should be dropped if parameter changed.  */
     302              : 
     303              : static bool
     304         5064 : drop_type_attribute_if_params_changed_p (tree name)
     305              : {
     306         5064 :   if (is_attribute_p ("fn spec", name)
     307         5064 :       || is_attribute_p ("access", name))
     308              :     return true;
     309              :   return false;
     310              : }
     311              : 
     312              : /* Return TRUE if the attribute should be dropped in the decl it is sitting on
     313              :    changes.  Primarily affects attributes working with the decls arguments.  */
     314              : static bool
     315        29510 : drop_decl_attribute_if_params_changed_p (tree name)
     316              : {
     317            0 :   if (is_attribute_p (CALLBACK_ATTR_IDENT, name))
     318              :     return true;
     319              :   return false;
     320              : }
     321              : 
     322              : /* Build and return a function type just like ORIG_TYPE but with parameter
     323              :    types given in NEW_PARAM_TYPES - which can be NULL if, but only if,
     324              :    ORIG_TYPE itself has NULL TREE_ARG_TYPEs.  If METHOD2FUNC is true, also make
     325              :    it a FUNCTION_TYPE instead of FUNCTION_TYPE.
     326              :    If ARG_MODIFIED is true drop attributes that are no longer up to date.  */
     327              : 
     328              : static tree
     329       256517 : build_adjusted_function_type (tree orig_type, vec<tree> *new_param_types,
     330              :                               bool method2func, bool skip_return,
     331              :                               bool args_modified)
     332              : {
     333       256517 :   tree new_arg_types = NULL;
     334       256517 :   if (TYPE_ARG_TYPES (orig_type))
     335              :     {
     336       256249 :       gcc_checking_assert (new_param_types);
     337       256249 :       bool last_parm_void = (TREE_VALUE (tree_last (TYPE_ARG_TYPES (orig_type)))
     338       256249 :                              == void_type_node);
     339       256249 :       unsigned len = new_param_types->length ();
     340       822516 :       for (unsigned i = 0; i < len; i++)
     341       566267 :         new_arg_types = tree_cons (NULL_TREE, (*new_param_types)[i],
     342              :                                    new_arg_types);
     343              : 
     344       256249 :       tree new_reversed = nreverse (new_arg_types);
     345       256249 :       if (last_parm_void)
     346              :         {
     347       256240 :           if (new_reversed)
     348       231287 :             TREE_CHAIN (new_arg_types) = void_list_node;
     349              :           else
     350        24953 :             new_reversed = void_list_node;
     351              :         }
     352              :       new_arg_types = new_reversed;
     353              :     }
     354              : 
     355              :   /* Use build_distinct_type_copy to preserve as much as possible from original
     356              :      type (debug info, attribute lists etc.).  The one exception is
     357              :      METHOD_TYPEs which must have THIS argument and when we are asked to remove
     358              :      it, we need to build new FUNCTION_TYPE instead.  */
     359       256517 :   tree new_type = NULL;
     360       256517 :   if (method2func)
     361              :     {
     362        99325 :       tree ret_type;
     363        99325 :       if (skip_return)
     364        12518 :         ret_type = void_type_node;
     365              :       else
     366        86807 :         ret_type = TREE_TYPE (orig_type);
     367              : 
     368        99325 :       new_type
     369        99325 :         = build_distinct_type_copy (build_function_type (ret_type,
     370              :                                                          new_arg_types));
     371        99325 :       TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
     372              :     }
     373              :   else
     374              :     {
     375       157192 :       new_type = build_distinct_type_copy (orig_type);
     376       157192 :       TYPE_ARG_TYPES (new_type) = new_arg_types;
     377       157192 :       if (skip_return)
     378        57415 :         TREE_TYPE (new_type) = void_type_node;
     379              :     }
     380       256517 :   if (args_modified && TYPE_ATTRIBUTES (new_type))
     381              :     {
     382         5064 :       tree t = TYPE_ATTRIBUTES (new_type);
     383         5064 :       tree *last = &TYPE_ATTRIBUTES (new_type);
     384         5064 :       TYPE_ATTRIBUTES (new_type) = NULL;
     385        10128 :       for (;t; t = TREE_CHAIN (t))
     386         5064 :         if (!drop_type_attribute_if_params_changed_p
     387         5064 :                 (get_attribute_name (t)))
     388              :           {
     389            8 :             *last = copy_node (t);
     390            8 :             TREE_CHAIN (*last) = NULL;
     391            8 :             last = &TREE_CHAIN (*last);
     392              :           }
     393              :     }
     394              : 
     395       256517 :   return new_type;
     396              : }
     397              : 
     398              : /* Return the maximum index in any IPA_PARAM_OP_COPY adjustment or -1 if there
     399              :    is none.  */
     400              : 
     401              : int
     402        48574 : ipa_param_adjustments::get_max_base_index ()
     403              : {
     404        48574 :   unsigned adj_len = vec_safe_length (m_adj_params);
     405        48574 :   int max_index = -1;
     406       111424 :   for (unsigned i = 0; i < adj_len ; i++)
     407              :     {
     408        62850 :       ipa_adjusted_param *apm = &(*m_adj_params)[i];
     409        62850 :       if (apm->op == IPA_PARAM_OP_COPY
     410        57602 :           && max_index < apm->base_index)
     411        62850 :         max_index = apm->base_index;
     412              :     }
     413        48574 :   return max_index;
     414              : }
     415              : 
     416              : 
     417              : /* Fill SURVIVING_PARAMS with an array of bools where each one says whether a
     418              :    parameter that originally was at that position still survives in the given
     419              :    clone or is removed/replaced.  If the final array is smaller than an index
     420              :    of an original parameter, that parameter also did not survive.  That a
     421              :    parameter survives does not mean it has the same index as before.  */
     422              : 
     423              : void
     424        30812 : ipa_param_adjustments::get_surviving_params (vec<bool> *surviving_params)
     425              : {
     426        30812 :   unsigned adj_len = vec_safe_length (m_adj_params);
     427        30812 :   int max_index = get_max_base_index ();
     428              : 
     429        30812 :   if (max_index < 0)
     430              :     return;
     431        17646 :   surviving_params->reserve_exact (max_index + 1);
     432        17646 :   surviving_params->quick_grow_cleared (max_index + 1);
     433        50646 :   for (unsigned i = 0; i < adj_len ; i++)
     434              :     {
     435        33000 :       ipa_adjusted_param *apm = &(*m_adj_params)[i];
     436        33000 :       if (apm->op == IPA_PARAM_OP_COPY)
     437        33000 :         (*surviving_params)[apm->base_index] = true;
     438              :     }
     439              : }
     440              : 
     441              : /* Fill NEW_INDICES with new indices of each surviving parameter or -1 for
     442              :    those which do not survive.  Any parameter outside of lenght of the vector
     443              :    does not survive.  There is currently no support for a parameter to be
     444              :    copied to two distinct new parameters.  */
     445              : 
     446              : void
     447        17762 : ipa_param_adjustments::get_updated_indices (vec<int> *new_indices)
     448              : {
     449        17762 :   unsigned adj_len = vec_safe_length (m_adj_params);
     450        17762 :   int max_index = get_max_base_index ();
     451              : 
     452        17762 :   if (max_index < 0)
     453              :     return;
     454        12564 :   unsigned res_len = max_index + 1;
     455        12564 :   new_indices->reserve_exact (res_len);
     456        44022 :   for (unsigned i = 0; i < res_len ; i++)
     457        31458 :     new_indices->quick_push (-1);
     458        40403 :   for (unsigned i = 0; i < adj_len ; i++)
     459              :     {
     460        27839 :       ipa_adjusted_param *apm = &(*m_adj_params)[i];
     461        27839 :       if (apm->op == IPA_PARAM_OP_COPY)
     462        24602 :         (*new_indices)[apm->base_index] = i;
     463              :     }
     464              : }
     465              : 
     466              : /* Return the original index for the given new parameter index.  Return a
     467              :    negative number if not available.  */
     468              : 
     469              : int
     470       615188 : ipa_param_adjustments::get_original_index (int newidx)
     471              : {
     472       615188 :   const ipa_adjusted_param *adj = &(*m_adj_params)[newidx];
     473       615188 :   if (adj->op != IPA_PARAM_OP_COPY)
     474              :     return -1;
     475       497396 :   return adj->base_index;
     476              : }
     477              : 
     478              : /* Return true if the first parameter (assuming there was one) survives the
     479              :    transformation intact and remains the first one.  */
     480              : 
     481              : bool
     482       257751 : ipa_param_adjustments::first_param_intact_p ()
     483              : {
     484       257751 :   return (!vec_safe_is_empty (m_adj_params)
     485       241530 :           && (*m_adj_params)[0].op == IPA_PARAM_OP_COPY
     486       187218 :           && (*m_adj_params)[0].base_index == 0);
     487              : }
     488              : 
     489              : /* Return true if we have to change what has formerly been a method into a
     490              :    function.  */
     491              : 
     492              : bool
     493       403636 : ipa_param_adjustments::method2func_p (tree orig_type)
     494              : {
     495       403636 :   return ((TREE_CODE (orig_type) == METHOD_TYPE) && !first_param_intact_p ());
     496              : }
     497              : 
     498              : /* Given function type OLD_TYPE, return a new type derived from it after
     499              :    performing all atored modifications.  TYPE_ORIGINAL_P should be true when
     500              :    OLD_TYPE refers to the type before any IPA transformations, as opposed to a
     501              :    type that can be an intermediate one in between various IPA
     502              :    transformations.  Set pointee of ARGS_MODIFIED (if provided) to TRUE if the
     503              :    type's arguments were changed.  */
     504              : 
     505              : tree
     506       252013 : ipa_param_adjustments::build_new_function_type (
     507              :   tree old_type, bool type_original_p, bool *args_modified /* = NULL */)
     508              : {
     509       252013 :   auto_vec<tree,16> new_param_types, *new_param_types_p;
     510       252013 :   if (prototype_p (old_type))
     511              :     {
     512       251809 :       auto_vec<tree, 16> otypes;
     513       251809 :       push_function_arg_types (&otypes, old_type);
     514       251809 :       fill_vector_of_new_param_types (&new_param_types, &otypes, m_adj_params,
     515       251809 :                                       !type_original_p);
     516       251809 :       new_param_types_p = &new_param_types;
     517       251809 :     }
     518              :   else
     519              :     new_param_types_p = NULL;
     520              : 
     521              :   /* Check if any params type cares about are modified.  In this case will
     522              :      need to drop some type attributes.  */
     523       252013 :   bool modified = false;
     524       252013 :   size_t index = 0;
     525       252013 :   if (m_adj_params)
     526       227333 :     for (tree t = TYPE_ARG_TYPES (old_type);
     527       676521 :          t && (int)index < m_always_copy_start && !modified;
     528       449188 :          t = TREE_CHAIN (t), index++)
     529       449188 :       if (index >= m_adj_params->length ()
     530       449188 :           || get_original_index (index) != (int)index)
     531              :         modified = true;
     532              : 
     533       252013 :   if (args_modified)
     534       151558 :     *args_modified = modified;
     535              : 
     536       252013 :   return build_adjusted_function_type (old_type, new_param_types_p,
     537       252013 :                                        method2func_p (old_type), m_skip_return,
     538       252013 :                                        modified);
     539       252013 : }
     540              : 
     541              : /* Build variant of function decl ORIG_DECL which has no return value if
     542              :    M_SKIP_RETURN is true and, if ORIG_DECL's types or parameters is known, has
     543              :    this type adjusted as indicated in M_ADJ_PARAMS. Arguments from
     544              :    DECL_ARGUMENTS list are not processed now, since they are linked by
     545              :    TREE_CHAIN directly and not accessible in LTO during WPA.  The caller is
     546              :    responsible for eliminating them when clones are properly materialized.  */
     547              : 
     548              : tree
     549       151623 : ipa_param_adjustments::adjust_decl (tree orig_decl)
     550              : {
     551       151623 :   tree new_decl = copy_node (orig_decl);
     552       151623 :   tree orig_type = TREE_TYPE (orig_decl);
     553       151623 :   bool args_modified = false;
     554       151623 :   if (prototype_p (orig_type)
     555       151623 :       || (m_skip_return && !VOID_TYPE_P (TREE_TYPE (orig_type))))
     556              :     {
     557       151558 :       tree new_type = build_new_function_type (orig_type, false, &args_modified);
     558       151558 :       TREE_TYPE (new_decl) = new_type;
     559              :     }
     560       151623 :   if (method2func_p (orig_type))
     561        47303 :     DECL_VINDEX (new_decl) = NULL_TREE;
     562              : 
     563              :   /* When signature changes, we need to clear builtin info.  */
     564       151623 :   if (fndecl_built_in_p (new_decl))
     565           97 :     set_decl_built_in_function (new_decl, NOT_BUILT_IN, 0);
     566              : 
     567       151623 :   DECL_VIRTUAL_P (new_decl) = 0;
     568       151623 :   DECL_LANG_SPECIFIC (new_decl) = NULL;
     569              : 
     570              :   /* Drop MALLOC attribute for a void function.  */
     571       151623 :   if (m_skip_return)
     572        47045 :     DECL_IS_MALLOC (new_decl) = 0;
     573              : 
     574              :   /* If the decl's arguments changed, we might need to drop some attributes.  */
     575       151623 :   if (args_modified && DECL_ATTRIBUTES (new_decl))
     576              :     {
     577        22892 :       tree t = DECL_ATTRIBUTES (new_decl);
     578        22892 :       tree *last = &DECL_ATTRIBUTES (new_decl);
     579        22892 :       DECL_ATTRIBUTES (new_decl) = NULL;
     580        52402 :       for (; t; t = TREE_CHAIN (t))
     581        29510 :         if (!drop_decl_attribute_if_params_changed_p (get_attribute_name (t)))
     582              :           {
     583        29510 :             *last = copy_node (t);
     584        29510 :             TREE_CHAIN (*last) = NULL;
     585        29510 :             last = &TREE_CHAIN (*last);
     586              :           }
     587              :     }
     588       151623 :   return new_decl;
     589              : }
     590              : 
     591              : /* Wrapper around get_base_ref_and_offset for cases interesting for IPA-SRA
     592              :    transformations.  Return true if EXPR has an interesting form and fill in
     593              :    *BASE_P and *UNIT_OFFSET_P with the appropriate info.  */
     594              : 
     595              : static bool
     596      1161364 : isra_get_ref_base_and_offset (tree expr, tree *base_p, unsigned *unit_offset_p)
     597              : {
     598      1161364 :   HOST_WIDE_INT offset, size;
     599      1161364 :   bool reverse;
     600      1161364 :   tree base
     601      1161364 :     = get_ref_base_and_extent_hwi (expr, &offset, &size, &reverse);
     602      1161364 :   if (!base || size < 0)
     603              :     return false;
     604              : 
     605      1155892 :   if ((offset % BITS_PER_UNIT) != 0)
     606              :     return false;
     607              : 
     608      1155008 :   if (TREE_CODE (base) == MEM_REF)
     609              :     {
     610       173044 :       poly_int64 plmoff = mem_ref_offset (base).force_shwi ();
     611       173044 :       HOST_WIDE_INT moff;
     612       173044 :       bool is_cst = plmoff.is_constant (&moff);
     613       173044 :       if (!is_cst)
     614              :         return false;
     615       173044 :       offset += moff * BITS_PER_UNIT;
     616       173044 :       base = TREE_OPERAND (base, 0);
     617              :     }
     618              : 
     619      1155008 :   if (offset < 0 || (offset / BITS_PER_UNIT) > UINT_MAX)
     620              :     return false;
     621              : 
     622      1154814 :   *base_p = base;
     623      1154814 :   *unit_offset_p = offset / BITS_PER_UNIT;
     624      1154814 :   return true;
     625              : }
     626              : 
     627              : /* Remove all statements that use NAME directly or indirectly.  KILLED_SSAS
     628              :    contains the SSA_NAMEs that are already being or have been processed and new
     629              :    ones need to be added to it.  The function only has to process situations
     630              :    handled by ssa_name_only_returned_p in ipa-sra.cc with the exception that it
     631              :    can assume it must never reach a use in a return statement.  */
     632              : 
     633              : static void
     634        13795 : purge_all_uses (tree name, hash_set <tree> *killed_ssas)
     635              : {
     636        13795 :   imm_use_iterator imm_iter;
     637        13795 :   gimple *stmt;
     638        13795 :   auto_vec <tree, 4> worklist;
     639        13795 :   auto_vec <gimple *, 4> kill_list;
     640              : 
     641        13795 :   worklist.safe_push (name);
     642        44089 :   while (!worklist.is_empty ())
     643              :     {
     644        16499 :       tree cur_name = worklist.pop ();
     645        19368 :       FOR_EACH_IMM_USE_STMT (stmt, imm_iter, cur_name)
     646              :         {
     647         2869 :           if (gimple_debug_bind_p (stmt))
     648              :             {
     649              :               /* When runing within tree-inline, we will never end up here but
     650              :                  adding the SSAs to killed_ssas will do the trick in this case
     651              :                  and the respective debug statements will get reset. */
     652           74 :               gimple_debug_bind_reset_value (stmt);
     653           74 :               update_stmt (stmt);
     654           74 :               continue;
     655              :             }
     656              : 
     657         2795 :           tree lhs = NULL_TREE;
     658         2795 :           if (is_gimple_assign (stmt))
     659          767 :             lhs = gimple_assign_lhs (stmt);
     660         2028 :           else if (gimple_code (stmt) == GIMPLE_PHI)
     661         2028 :             lhs = gimple_phi_result (stmt);
     662         3562 :           gcc_assert (lhs
     663              :                       && (TREE_CODE (lhs) == SSA_NAME)
     664              :                       && !gimple_vdef (stmt));
     665         2795 :           if (!killed_ssas->add (lhs))
     666              :             {
     667         2704 :               worklist.safe_push (lhs);
     668         2704 :               kill_list.safe_push (stmt);
     669              :             }
     670        16499 :         }
     671              :     }
     672              : 
     673              :   /* Remove stmts in reverse and afterwards to properly handle debug stmt
     674              :      generation and to not interfere with immediate use iteration.  */
     675        30294 :   while (!kill_list.is_empty ())
     676              :     {
     677         2704 :       stmt = kill_list.pop ();
     678         2704 :       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     679         2704 :       gsi_remove (&gsi, true);
     680              :     }
     681        13795 : }
     682              : 
     683              : /* Modify actual arguments of a function call in statement currently belonging
     684              :    to CS, and make it call CS->callee->decl.  Return the new statement that
     685              :    replaced the old one.  When invoked, cfun and current_function_decl have to
     686              :    be set to the caller.  When called from within tree-inline, KILLED_SSAs has
     687              :    to contain the pointer to killed_new_ssa_names within the copy_body_data
     688              :    structure and SSAs discovered to be useless (if LHS is removed) will be
     689              :    added to it, otherwise it needs to be NULL.  */
     690              : 
     691              : gcall *
     692       531921 : ipa_param_adjustments::modify_call (cgraph_edge *cs,
     693              :                                     bool update_references,
     694              :                                     hash_set <tree> *killed_ssas)
     695              : {
     696       531921 :   gcall *stmt = cs->call_stmt;
     697       531921 :   tree callee_decl = cs->callee->decl;
     698              : 
     699       531921 :   ipa_edge_modification_info *mod_info
     700       531921 :     = ipa_edge_modifications ? ipa_edge_modifications->get (cs) : NULL;
     701       299409 :   if (mod_info && symtab->dump_file)
     702              :     {
     703            0 :       fprintf (symtab->dump_file, "Information about pre-exiting "
     704              :                "modifications.\n  Index map:");
     705            0 :       unsigned idx_len = mod_info->index_map.length ();
     706            0 :       for (unsigned i = 0; i < idx_len; i++)
     707            0 :         fprintf (symtab->dump_file, " %i", mod_info->index_map[i]);
     708            0 :       fprintf (symtab->dump_file, "\n  Pass-through split map: ");
     709            0 :       unsigned ptm_len = mod_info->pass_through_map.length ();
     710            0 :       for (unsigned i = 0; i < ptm_len; i++)
     711            0 :         fprintf (symtab->dump_file,
     712              :                  " (base_index: %u, offset: %u, new_index: %i)",
     713            0 :                  mod_info->pass_through_map[i].base_index,
     714            0 :                  mod_info->pass_through_map[i].unit_offset,
     715            0 :                  mod_info->pass_through_map[i].new_index);
     716            0 :       fprintf (symtab->dump_file, "\n  Always-copy delta: %i\n",
     717              :                mod_info->always_copy_delta);
     718              :     }
     719              : 
     720       531921 :   unsigned len = vec_safe_length (m_adj_params);
     721       531921 :   auto_vec<tree, 16> vargs (len);
     722       531921 :   unsigned old_nargs = gimple_call_num_args (stmt);
     723       531921 :   unsigned orig_nargs = mod_info ? mod_info->index_map.length () : old_nargs;
     724       531921 :   auto_vec<bool, 16> kept (old_nargs);
     725       531921 :   kept.quick_grow_cleared (old_nargs);
     726              : 
     727       531921 :   cgraph_node *current_node = cgraph_node::get (current_function_decl);
     728       531921 :   if (update_references)
     729            0 :     current_node->remove_stmt_references (stmt);
     730              : 
     731       531921 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     732       531921 :   gimple_stmt_iterator prev_gsi = gsi;
     733       531921 :   gsi_prev (&prev_gsi);
     734      1827733 :   for (unsigned i = 0; i < len; i++)
     735              :     {
     736      1295812 :       ipa_adjusted_param *apm = &(*m_adj_params)[i];
     737      1295812 :       if (apm->op == IPA_PARAM_OP_COPY)
     738              :         {
     739      1012453 :           int index = apm->base_index;
     740      1012453 :           if ((unsigned) index >= orig_nargs)
     741              :             /* Can happen if the original call has argument mismatch,
     742              :                ignore.  */
     743            1 :             continue;
     744      1012452 :           if (mod_info)
     745              :             {
     746        45583 :               index = mod_info->index_map[apm->base_index];
     747        45583 :               gcc_assert (index >= 0);
     748              :             }
     749              : 
     750      1012452 :           tree arg = gimple_call_arg (stmt, index);
     751              : 
     752      1012452 :           vargs.quick_push (arg);
     753      1012452 :           kept[index] = true;
     754      1012452 :           continue;
     755      1012452 :         }
     756              : 
     757              :       /* At the moment the only user of IPA_PARAM_OP_NEW modifies calls itself.
     758              :          If we ever want to support it during WPA IPA stage, we'll need a
     759              :          mechanism to call into the IPA passes that introduced them.  Currently
     760              :          we simply mandate that IPA infrastructure understands all argument
     761              :          modifications.  Remember, edge redirection/modification is done only
     762              :          once, not in steps for each pass modifying the callee like clone
     763              :          materialization.  */
     764       283359 :       gcc_assert (apm->op == IPA_PARAM_OP_SPLIT);
     765              : 
     766              :       /* We have to handle pass-through changes differently using the map
     767              :          clone materialziation might have left behind.  */
     768       283359 :       tree repl = NULL_TREE;
     769       283359 :       unsigned ptm_len = mod_info ? mod_info->pass_through_map.length () : 0;
     770       306187 :       for (unsigned j = 0; j < ptm_len; j++)
     771        44135 :         if (mod_info->pass_through_map[j].base_index == apm->base_index
     772        44135 :             && mod_info->pass_through_map[j].unit_offset == apm->unit_offset)
     773              :           {
     774        21307 :             int repl_idx = mod_info->pass_through_map[j].new_index;
     775        21307 :             gcc_assert (repl_idx >= 0);
     776        21307 :             repl = gimple_call_arg (stmt, repl_idx);
     777        21307 :             break;
     778              :           }
     779       283359 :       if (repl)
     780              :         {
     781        21307 :           if (!useless_type_conversion_p(apm->type, repl->typed.type))
     782              :             {
     783            0 :               repl = force_value_to_type (apm->type, repl);
     784            0 :               repl = force_gimple_operand_gsi (&gsi, repl,
     785              :                                                true, NULL, true, GSI_SAME_STMT);
     786              :             }
     787        21307 :           vargs.quick_push (repl);
     788        21307 :           continue;
     789              :         }
     790              : 
     791       262052 :       int index = apm->base_index;
     792       262052 :       if ((unsigned) index >= orig_nargs)
     793              :         /* Can happen if the original call has argument mismatch, ignore.  */
     794            1 :         continue;
     795       262051 :       if (mod_info)
     796              :         {
     797         4493 :           index = mod_info->index_map[apm->base_index];
     798         4493 :           gcc_assert (index >= 0);
     799              :         }
     800       262051 :       tree base = gimple_call_arg (stmt, index);
     801              : 
     802              :       /* We create a new parameter out of the value of the old one, we can
     803              :          do the following kind of transformations:
     804              : 
     805              :          - A scalar passed by reference, potentially as a part of a larger
     806              :          aggregate, is converted to a scalar passed by value.
     807              : 
     808              :          - A part of an aggregate is passed instead of the whole aggregate.  */
     809              : 
     810       262051 :       location_t loc = gimple_location (stmt);
     811       262051 :       tree off;
     812       262051 :       bool deref_base = false;
     813       262051 :       unsigned int deref_align = 0;
     814       262051 :       if (TREE_CODE (base) != ADDR_EXPR
     815       262051 :           && is_gimple_reg_type (TREE_TYPE (base)))
     816              :         {
     817              :           /* Detect type mismatches in calls in invalid programs and make a
     818              :              poor attempt to gracefully convert them so that we don't ICE.  */
     819        76813 :           if (!POINTER_TYPE_P (TREE_TYPE (base)))
     820           11 :             base = force_value_to_type (ptr_type_node, base);
     821              : 
     822        76813 :           off = build_int_cst (apm->alias_ptr_type, apm->unit_offset);
     823              :         }
     824              :       else
     825              :         {
     826       185238 :           bool addrof;
     827       185238 :           if (TREE_CODE (base) == ADDR_EXPR)
     828              :             {
     829       147390 :               base = TREE_OPERAND (base, 0);
     830       147390 :               addrof = true;
     831              :             }
     832              :           else
     833              :             addrof = false;
     834              : 
     835       185238 :           tree prev_base = base;
     836       185238 :           poly_int64 base_offset;
     837       185238 :           base = get_addr_base_and_unit_offset (base, &base_offset);
     838              : 
     839              :           /* Aggregate arguments can have non-invariant addresses.  */
     840       185238 :           if (!base)
     841              :             {
     842            0 :               base = build_fold_addr_expr (prev_base);
     843            0 :               off = build_int_cst (apm->alias_ptr_type, apm->unit_offset);
     844              :             }
     845       185238 :           else if (TREE_CODE (base) == MEM_REF)
     846              :             {
     847         5638 :               if (!addrof)
     848              :                 {
     849         5638 :                   deref_base = true;
     850         5638 :                   deref_align = TYPE_ALIGN (TREE_TYPE (base));
     851              :                 }
     852        11276 :               off = build_int_cst (apm->alias_ptr_type,
     853         5638 :                                    base_offset + apm->unit_offset);
     854         5638 :               off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1),
     855              :                                      off);
     856         5638 :               base = TREE_OPERAND (base, 0);
     857              :             }
     858              :           else
     859              :             {
     860       359200 :               off = build_int_cst (apm->alias_ptr_type,
     861       179600 :                                    base_offset + apm->unit_offset);
     862       179600 :               base = build_fold_addr_expr (base);
     863              :             }
     864              :         }
     865              : 
     866       262051 :       tree type = apm->type;
     867       262051 :       unsigned int align;
     868       262051 :       unsigned HOST_WIDE_INT misalign;
     869              : 
     870       262051 :       if (deref_base)
     871              :         {
     872         5638 :           align = deref_align;
     873         5638 :           misalign = 0;
     874              :         }
     875              :       else
     876              :         {
     877       256413 :           get_pointer_alignment_1 (base, &align, &misalign);
     878              :           /* All users must make sure that we can be optimistic when it
     879              :              comes to alignment in this case (by inspecting the final users
     880              :              of these new parameters).  */
     881       256413 :           if (TYPE_ALIGN (type) > align)
     882        75516 :             align = TYPE_ALIGN (type);
     883              :         }
     884       262051 :       misalign
     885       262051 :         += (offset_int::from (wi::to_wide (off), SIGNED).to_short_addr ()
     886       262051 :             * BITS_PER_UNIT);
     887       262051 :       misalign = misalign & (align - 1);
     888       262051 :       if (misalign != 0)
     889         2928 :         align = least_bit_hwi (misalign);
     890       262051 :       if (align < TYPE_ALIGN (type))
     891            0 :         type = build_aligned_type (type, align);
     892       262051 :       base = force_gimple_operand_gsi (&gsi, base,
     893              :                                        true, NULL, true, GSI_SAME_STMT);
     894       262051 :       tree expr = fold_build2_loc (loc, MEM_REF, type, base, off);
     895       262051 :       REF_REVERSE_STORAGE_ORDER (expr) = apm->reverse;
     896              :       /* If expr is not a valid gimple call argument emit
     897              :          a load into a temporary.  */
     898       262051 :       if (is_gimple_reg_type (TREE_TYPE (expr)))
     899              :         {
     900       260099 :           gimple *tem = gimple_build_assign (NULL_TREE, expr);
     901       260099 :           if (gimple_in_ssa_p (cfun))
     902              :             {
     903       520198 :               gimple_set_vuse (tem, gimple_vuse (stmt));
     904       260099 :               expr = make_ssa_name (TREE_TYPE (expr), tem);
     905              :             }
     906              :           else
     907            0 :             expr = create_tmp_reg (TREE_TYPE (expr));
     908       260099 :           gimple_assign_set_lhs (tem, expr);
     909       260099 :           gsi_insert_before (&gsi, tem, GSI_SAME_STMT);
     910              :         }
     911       262051 :       vargs.quick_push (expr);
     912              :     }
     913              : 
     914       531921 :   if (m_always_copy_start >= 0)
     915              :     {
     916       531921 :       int always_copy_start = m_always_copy_start;
     917       531921 :       if (mod_info)
     918              :         {
     919        32353 :           always_copy_start += mod_info->always_copy_delta;
     920        32353 :           gcc_assert (always_copy_start >= 0);
     921              :         }
     922       531928 :       for (unsigned i = always_copy_start; i < old_nargs; i++)
     923            7 :         vargs.safe_push (gimple_call_arg (stmt, i));
     924              :     }
     925              : 
     926              :   /* For optimized away parameters, add on the caller side
     927              :      before the call
     928              :      DEBUG D#X => parm_Y(D)
     929              :      stmts and associate D#X with parm in decl_debug_args_lookup
     930              :      vector to say for debug info that if parameter parm had been passed,
     931              :      it would have value parm_Y(D).  */
     932       531921 :   tree old_decl = gimple_call_fndecl (stmt);
     933       531921 :   if (MAY_HAVE_DEBUG_BIND_STMTS && old_decl && callee_decl)
     934              :     {
     935       401691 :       vec<tree, va_gc> **debug_args = NULL;
     936       401691 :       unsigned i = 0;
     937       401691 :       cgraph_node *callee_node = cgraph_node::get (callee_decl);
     938              : 
     939              :       /* FIXME: we don't seem to be able to insert debug args before clone
     940              :          is materialized.  Materializing them early leads to extra memory
     941              :          use.  */
     942       401691 :       if (callee_node->clone_of)
     943            0 :         callee_node->get_untransformed_body ();
     944       401691 :       for (tree old_parm = DECL_ARGUMENTS (old_decl);
     945      1398103 :            old_parm && i < old_nargs && ((int) i) < m_always_copy_start;
     946       996412 :            old_parm = DECL_CHAIN (old_parm), i++)
     947              :         {
     948      1815358 :           if (!is_gimple_reg (old_parm) || kept[i])
     949       758177 :             continue;
     950       244862 :           tree arg;
     951       244862 :           if (mod_info)
     952              :             {
     953        16020 :               if (mod_info->index_map[i] < 0)
     954         6626 :                 continue;
     955         9394 :               arg = gimple_call_arg (stmt, mod_info->index_map[i]);
     956              :             }
     957              :           else
     958       228842 :             arg = gimple_call_arg (stmt, i);
     959              : 
     960       238236 :           tree origin = DECL_ORIGIN (old_parm);
     961       238236 :           if (!useless_type_conversion_p (TREE_TYPE (origin), TREE_TYPE (arg)))
     962              :             {
     963            8 :               if (!fold_convertible_p (TREE_TYPE (origin), arg))
     964            1 :                 continue;
     965            7 :               tree rhs1;
     966            7 :               if (TREE_CODE (arg) == SSA_NAME
     967            0 :                   && gimple_assign_cast_p (SSA_NAME_DEF_STMT (arg))
     968            0 :                   && (rhs1
     969            0 :                       = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (arg)))
     970            7 :                   && useless_type_conversion_p (TREE_TYPE (origin),
     971            0 :                                                 TREE_TYPE (rhs1)))
     972              :                 arg = rhs1;
     973              :               else
     974            7 :                 arg = fold_convert_loc (gimple_location (stmt),
     975            7 :                                         TREE_TYPE (origin), arg);
     976              :             }
     977       238235 :           if (debug_args == NULL)
     978       192217 :             debug_args = decl_debug_args_insert (callee_decl);
     979       238235 :           unsigned int ix;
     980       238235 :           tree ddecl = NULL_TREE;
     981       310053 :           for (ix = 0; vec_safe_iterate (*debug_args, ix, &ddecl); ix += 2)
     982       302217 :             if (ddecl == origin)
     983              :               {
     984       230399 :                 ddecl = (**debug_args)[ix + 1];
     985       230399 :                 break;
     986              :               }
     987       238235 :           if (ddecl == NULL)
     988              :             {
     989         7836 :               ddecl = build_debug_expr_decl (TREE_TYPE (origin));
     990              :               /* FIXME: Is setting the mode really necessary? */
     991         7836 :               SET_DECL_MODE (ddecl, DECL_MODE (origin));
     992              : 
     993         7836 :               vec_safe_push (*debug_args, origin);
     994         7836 :               vec_safe_push (*debug_args, ddecl);
     995              :             }
     996       238235 :           gimple *def_temp = gimple_build_debug_bind (ddecl,
     997              :                                                       unshare_expr (arg), stmt);
     998       238235 :           gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
     999              :         }
    1000              :     }
    1001              : 
    1002       531921 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1003              :     {
    1004           10 :       fprintf (dump_file, "replacing stmt:");
    1005           10 :       print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
    1006              :     }
    1007              : 
    1008       531921 :   gcall *new_stmt = gimple_build_call_vec (callee_decl, vargs);
    1009              : 
    1010       531921 :   hash_set <tree> *ssas_to_remove = NULL;
    1011       531921 :   if (tree lhs = gimple_call_lhs (stmt))
    1012              :     {
    1013       211918 :       if (!m_skip_return)
    1014       198123 :         gimple_call_set_lhs (new_stmt, lhs);
    1015        13795 :       else if (TREE_CODE (lhs) == SSA_NAME)
    1016              :         {
    1017        13795 :           if (!killed_ssas)
    1018              :             {
    1019          767 :               ssas_to_remove = new hash_set<tree> (8);
    1020          767 :               killed_ssas = ssas_to_remove;
    1021              :             }
    1022        13795 :           killed_ssas->add (lhs);
    1023        13795 :           purge_all_uses (lhs, killed_ssas);
    1024              :         }
    1025              :     }
    1026              : 
    1027       531921 :   gimple_set_block (new_stmt, gimple_block (stmt));
    1028       531921 :   if (gimple_has_location (stmt))
    1029      1008307 :     gimple_set_location (new_stmt, gimple_location (stmt));
    1030       531921 :   gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
    1031       531921 :   gimple_call_copy_flags (new_stmt, stmt);
    1032       531921 :   if (gimple_in_ssa_p (cfun))
    1033       531921 :     gimple_move_vops (new_stmt, stmt);
    1034              : 
    1035       531921 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1036              :     {
    1037           10 :       fprintf (dump_file, "with stmt:");
    1038           10 :       print_gimple_stmt (dump_file, new_stmt, 0);
    1039           10 :       fprintf (dump_file, "\n");
    1040              :     }
    1041       531921 :   gsi_replace (&gsi, new_stmt, true);
    1042       531921 :   if (ssas_to_remove)
    1043              :     {
    1044          767 :       ipa_release_ssas_in_hash (ssas_to_remove);
    1045          767 :       delete ssas_to_remove;
    1046              :     }
    1047       531921 :   if (update_references)
    1048            0 :     do
    1049              :       {
    1050            0 :         current_node->record_stmt_references (gsi_stmt (gsi));
    1051            0 :         gsi_prev (&gsi);
    1052              :       }
    1053            0 :     while (gsi_stmt (gsi) != gsi_stmt (prev_gsi));
    1054              : 
    1055       531921 :   if (mod_info)
    1056        32353 :     ipa_edge_modifications->remove (cs);
    1057       531921 :   return new_stmt;
    1058       531921 : }
    1059              : 
    1060              : /* Dump information contained in the object in textual form to F.  */
    1061              : 
    1062              : void
    1063            9 : ipa_param_adjustments::dump (FILE *f)
    1064              : {
    1065            9 :   fprintf (f, "    m_always_copy_start: %i\n", m_always_copy_start);
    1066            9 :   ipa_dump_adjusted_parameters (f, m_adj_params);
    1067            9 :   if (m_skip_return)
    1068            5 :     fprintf (f, "    Will SKIP return.\n");
    1069            9 : }
    1070              : 
    1071              : /* Dump information contained in the object in textual form to stderr.  */
    1072              : 
    1073              : void
    1074            0 : ipa_param_adjustments::debug ()
    1075              : {
    1076            0 :   dump (stderr);
    1077            0 : }
    1078              : 
    1079              : /* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET.  */
    1080              : 
    1081              : void
    1082        92381 : ipa_param_body_adjustments::register_replacement (tree base,
    1083              :                                                   unsigned unit_offset,
    1084              :                                                   tree replacement)
    1085              : {
    1086        92381 :   ipa_param_body_replacement psr;
    1087        92381 :   psr.base = base;
    1088        92381 :   psr.repl = replacement;
    1089        92381 :   psr.dummy = NULL_TREE;
    1090        92381 :   psr.unit_offset = unit_offset;
    1091        92381 :   m_replacements.safe_push (psr);
    1092        92381 :   m_sorted_replacements_p = false;
    1093        92381 : }
    1094              : 
    1095              : /* Register that REPLACEMENT should replace parameter described in APM.  */
    1096              : 
    1097              : void
    1098        80355 : ipa_param_body_adjustments::register_replacement (ipa_adjusted_param *apm,
    1099              :                                                   tree replacement)
    1100              : {
    1101        80355 :   gcc_checking_assert (apm->op == IPA_PARAM_OP_SPLIT
    1102              :                        || apm->op == IPA_PARAM_OP_NEW);
    1103        80355 :   gcc_checking_assert (!apm->prev_clone_adjustment);
    1104        80355 :   register_replacement (m_oparms[apm->prev_clone_index], apm->unit_offset,
    1105              :                         replacement);
    1106        80355 : }
    1107              : 
    1108              : /* Comparator for sorting and searching
    1109              :    ipa_param_body_adjustments::m_replacements.  */
    1110              : 
    1111              : static int
    1112      1780754 : compare_param_body_replacement (const void *va, const void *vb)
    1113              : {
    1114      1780754 :   const ipa_param_body_replacement *a = (const ipa_param_body_replacement *) va;
    1115      1780754 :   const ipa_param_body_replacement *b = (const ipa_param_body_replacement *) vb;
    1116              : 
    1117      1780754 :   if (DECL_UID (a->base) < DECL_UID (b->base))
    1118              :     return -1;
    1119      1459597 :   if (DECL_UID (a->base) > DECL_UID (b->base))
    1120              :     return 1;
    1121      1103499 :   if (a->unit_offset < b->unit_offset)
    1122              :     return -1;
    1123       605720 :   if (a->unit_offset > b->unit_offset)
    1124       517939 :     return 1;
    1125              :   return 0;
    1126              : }
    1127              : 
    1128              : /* Sort m_replacements and set m_sorted_replacements_p to true.  */
    1129              : 
    1130              : void
    1131       170655 : ipa_param_body_adjustments::sort_replacements ()
    1132              : {
    1133       170655 :   if (m_sorted_replacements_p)
    1134              :     return;
    1135        50507 :   m_replacements.qsort (compare_param_body_replacement);
    1136        50507 :   m_sorted_replacements_p = true;
    1137              : }
    1138              : 
    1139              : /* Copy or not, as appropriate given m_id and decl context, a pre-existing
    1140              :    PARM_DECL T so that it can be included in the parameters of the modified
    1141              :    function.  */
    1142              : 
    1143              : tree
    1144       244719 : ipa_param_body_adjustments::carry_over_param (tree t)
    1145              : {
    1146       244719 :   tree new_parm;
    1147       244719 :   if (m_id)
    1148              :     {
    1149       240787 :       new_parm = remap_decl (t, m_id);
    1150       240787 :       if (TREE_CODE (new_parm) != PARM_DECL)
    1151            0 :         new_parm = m_id->copy_decl (t, m_id);
    1152              :     }
    1153         3932 :   else if (DECL_CONTEXT (t) != m_fndecl)
    1154              :     {
    1155           34 :       new_parm = copy_node (t);
    1156           34 :       DECL_CONTEXT (new_parm) = m_fndecl;
    1157              :     }
    1158              :   else
    1159              :     new_parm = t;
    1160       244719 :   return new_parm;
    1161              : }
    1162              : 
    1163              : /* If DECL is a gimple register that has a default definition SSA name and that
    1164              :    has some uses, return the default definition, otherwise return NULL_TREE.  */
    1165              : 
    1166              : tree
    1167       145076 : ipa_param_body_adjustments::get_ddef_if_exists_and_is_used (tree decl)
    1168              : {
    1169       145076 :  if (!is_gimple_reg (decl))
    1170              :     return NULL_TREE;
    1171       117075 :   tree ddef = ssa_default_def (m_id->src_cfun, decl);
    1172       117075 :   if (!ddef || has_zero_uses (ddef))
    1173              :     return NULL_TREE;
    1174              :   return ddef;
    1175              : }
    1176              : 
    1177              : /* Populate m_dead_stmts given that DEAD_PARAM is going to be removed without
    1178              :    any replacement or splitting.  REPL is the replacement VAR_SECL to base any
    1179              :    remaining uses of a removed parameter on.  Push all removed SSA names that
    1180              :    are used within debug statements to DEBUGSTACK.  */
    1181              : 
    1182              : void
    1183       106001 : ipa_param_body_adjustments::mark_dead_statements (tree dead_param,
    1184              :                                                   vec<tree> *debugstack)
    1185              : {
    1186              :   /* Current IPA analyses which remove unused parameters never remove a
    1187              :      non-gimple register ones which have any use except as parameters in other
    1188              :      calls, so we can safely leve them as they are.  */
    1189       106001 :   tree parm_ddef = get_ddef_if_exists_and_is_used (dead_param);
    1190       106001 :   if (!parm_ddef)
    1191        77974 :     return;
    1192              : 
    1193        32922 :   auto_vec<tree, 4> stack;
    1194        32922 :   hash_set<tree> used_in_debug;
    1195        32922 :   m_dead_ssas.add (parm_ddef);
    1196        32922 :   stack.safe_push (parm_ddef);
    1197       101101 :   while (!stack.is_empty ())
    1198              :     {
    1199        35257 :       imm_use_iterator imm_iter;
    1200        35257 :       use_operand_p use_p;
    1201        35257 :       tree t = stack.pop ();
    1202              : 
    1203        35257 :       insert_decl_map (m_id, t, error_mark_node);
    1204       167298 :       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, t)
    1205              :         {
    1206        96784 :           gimple *stmt = USE_STMT (use_p);
    1207              : 
    1208              :           /* Calls containing dead arguments cannot be deleted,
    1209              :              modify_call_stmt will instead remove just the argument later on.
    1210              :              If isra_track_scalar_value_uses in ipa-sra.cc is extended to look
    1211              :              through const functions, we will need to do so here too.  */
    1212        96784 :           if (is_gimple_call (stmt)
    1213        96784 :               || (m_id->blocks_to_copy
    1214        66449 :                   && !bitmap_bit_p (m_id->blocks_to_copy,
    1215        66449 :                                     gimple_bb (stmt)->index)))
    1216        84658 :             continue;
    1217              : 
    1218        12126 :           if (is_gimple_debug (stmt))
    1219              :             {
    1220         9291 :               m_dead_stmts.add (stmt);
    1221         9291 :               gcc_assert (gimple_debug_bind_p (stmt));
    1222         9291 :               if (!used_in_debug.contains (t))
    1223              :                 {
    1224         4237 :                   used_in_debug.add (t);
    1225         4237 :                   debugstack->safe_push (t);
    1226              :                 }
    1227              :             }
    1228         2835 :           else if (gimple_code (stmt) == GIMPLE_PHI)
    1229              :             {
    1230          404 :               gphi *phi = as_a <gphi *> (stmt);
    1231          404 :               int ix = PHI_ARG_INDEX_FROM_USE (use_p);
    1232              : 
    1233          404 :               if (!m_id->blocks_to_copy
    1234          446 :                   || bitmap_bit_p (m_id->blocks_to_copy,
    1235           42 :                                    gimple_phi_arg_edge (phi, ix)->src->index))
    1236              :                 {
    1237          362 :                   m_dead_stmts.add (phi);
    1238          362 :                   tree res = gimple_phi_result (phi);
    1239          362 :                   if (!m_dead_ssas.add (res))
    1240          246 :                     stack.safe_push (res);
    1241              :                 }
    1242              :             }
    1243         2431 :           else if (is_gimple_assign (stmt))
    1244              :             {
    1245         2347 :               m_dead_stmts.add (stmt);
    1246         2347 :               if (!gimple_clobber_p (stmt))
    1247              :                 {
    1248         2331 :                   tree lhs = gimple_assign_lhs (stmt);
    1249         2331 :                   gcc_assert (TREE_CODE (lhs) == SSA_NAME);
    1250         2331 :                   if (!m_dead_ssas.add (lhs))
    1251         2089 :                     stack.safe_push (lhs);
    1252              :                 }
    1253              :             }
    1254           84 :           else if (gimple_code (stmt) == GIMPLE_RETURN)
    1255           84 :             gcc_assert (m_adjustments && m_adjustments->m_skip_return);
    1256              :           else
    1257              :             /* IPA-SRA does not analyze other types of statements.  */
    1258            0 :             gcc_unreachable ();
    1259        35257 :         }
    1260              :     }
    1261              : 
    1262        32922 :   if (!MAY_HAVE_DEBUG_STMTS)
    1263              :     {
    1264         4895 :       gcc_assert (debugstack->is_empty ());
    1265         4895 :       return;
    1266              :     }
    1267              : 
    1268        28027 :   tree dp_ddecl = build_debug_expr_decl (TREE_TYPE (dead_param));
    1269              :   /* FIXME: Is setting the mode really necessary? */
    1270        28027 :   SET_DECL_MODE (dp_ddecl, DECL_MODE (dead_param));
    1271        28027 :   m_dead_ssa_debug_equiv.put (parm_ddef, dp_ddecl);
    1272        32922 : }
    1273              : 
    1274              : /* Put all clobbers of of dereference of default definition of PARAM into
    1275              :    m_dead_stmts.  If there are returns among uses of the default definition of
    1276              :    PARAM, verify they will be stripped off the return value.  */
    1277              : 
    1278              : void
    1279        45938 : ipa_param_body_adjustments::mark_clobbers_dead (tree param)
    1280              : {
    1281        45938 :   if (!is_gimple_reg (param))
    1282         6863 :     return;
    1283        39075 :   tree ddef = get_ddef_if_exists_and_is_used (param);
    1284        39075 :   if (!ddef)
    1285              :     return;
    1286              : 
    1287        39075 :  imm_use_iterator imm_iter;
    1288        39075 :  use_operand_p use_p;
    1289       217407 :  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ddef)
    1290              :    {
    1291       139257 :      gimple *stmt = USE_STMT (use_p);
    1292       139257 :      if (gimple_clobber_p (stmt))
    1293          271 :        m_dead_stmts.add (stmt);
    1294       138986 :      else if (gimple_code (stmt) == GIMPLE_RETURN)
    1295          167 :        gcc_assert (m_adjustments && m_adjustments->m_skip_return);
    1296        39075 :    }
    1297              : }
    1298              : 
    1299              : /* Callback to walk_tree.  If REMAP is an SSA_NAME that is present in hash_map
    1300              :    passed in DATA, replace it with unshared version of what it was mapped to.
    1301              :    If an SSA argument would be remapped to NULL, the whole operation needs to
    1302              :    abort which is signaled by returning error_mark_node.  */
    1303              : 
    1304              : static tree
    1305        15812 : replace_with_mapped_expr (tree *remap, int *walk_subtrees, void *data)
    1306              : {
    1307        15812 :   if (TYPE_P (*remap))
    1308              :     {
    1309            0 :       *walk_subtrees = 0;
    1310            0 :       return 0;
    1311              :     }
    1312        15812 :   if (TREE_CODE (*remap) != SSA_NAME)
    1313              :     return 0;
    1314              : 
    1315         2764 :   *walk_subtrees = 0;
    1316              : 
    1317         2764 :   hash_map<tree, tree> *equivs = (hash_map<tree, tree> *) data;
    1318         2764 :   if (tree *p = equivs->get (*remap))
    1319              :     {
    1320         2711 :       if (!*p)
    1321            1 :         return error_mark_node;
    1322         2710 :       *remap = unshare_expr (*p);
    1323              :     }
    1324              :   return 0;
    1325              : }
    1326              : 
    1327              : /* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what they
    1328              :    are mapped to.  */
    1329              : 
    1330              : void
    1331        10587 : ipa_param_body_adjustments::remap_with_debug_expressions (tree *t)
    1332              : {
    1333              :   /* If *t is an SSA_NAME which should have its debug statements reset, it is
    1334              :      mapped to NULL in the hash_map.
    1335              : 
    1336              :      It is perhaps simpler to handle the SSA_NAME cases directly and only
    1337              :      invoke walk_tree on more complex expressions.  When
    1338              :      remap_with_debug_expressions is called from tree-inline.cc, a to-be-reset
    1339              :      SSA_NAME can be an operand to such expressions and the entire debug
    1340              :      variable we are remapping should be reset.  This is signaled by walk_tree
    1341              :      returning error_mark_node and done by setting *t to NULL.  */
    1342        10587 :   if (TREE_CODE (*t) == SSA_NAME)
    1343              :     {
    1344         7934 :       if (tree *p = m_dead_ssa_debug_equiv.get (*t))
    1345         7934 :         *t = *p;
    1346              :     }
    1347         2653 :   else if (walk_tree (t, replace_with_mapped_expr,
    1348         2653 :                       &m_dead_ssa_debug_equiv, NULL) == error_mark_node)
    1349            1 :     *t = NULL_TREE;
    1350        10587 : }
    1351              : 
    1352              : /* For an SSA_NAME DEAD_SSA which is about to be DCEd because it is based on a
    1353              :    useless parameter, prepare an expression that should represent it in
    1354              :    debug_binds in the cloned function and add a mapping from DEAD_SSA to
    1355              :    m_dead_ssa_debug_equiv.  That mapping is to NULL when the associated
    1356              :    debug_statement has to be reset instead.  In such case return false,
    1357              :    ottherwise return true.  If DEAD_SSA comes from a basic block which is not
    1358              :    about to be copied, ignore it and return true.  */
    1359              : 
    1360              : bool
    1361         5825 : ipa_param_body_adjustments::prepare_debug_expressions (tree dead_ssa)
    1362              : {
    1363         5825 :   gcc_checking_assert (m_dead_ssas.contains (dead_ssa));
    1364         5825 :   if (tree *d = m_dead_ssa_debug_equiv.get (dead_ssa))
    1365         4178 :     return (*d != NULL_TREE);
    1366              : 
    1367         1647 :   gcc_assert (!SSA_NAME_IS_DEFAULT_DEF (dead_ssa));
    1368         1647 :   gimple *def = SSA_NAME_DEF_STMT (dead_ssa);
    1369         1647 :   if (m_id->blocks_to_copy
    1370         1647 :       && !bitmap_bit_p (m_id->blocks_to_copy, gimple_bb (def)->index))
    1371              :     return true;
    1372              : 
    1373         1647 :   if (gimple_code (def) == GIMPLE_PHI)
    1374              :     {
    1375              :       /* In theory, we could ignore all SSAs coming from BBs not in
    1376              :          m_id->blocks_to_copy but at the time of the writing this code that
    1377              :          should never really be the case because only fnsplit uses that bitmap,
    1378              :          so don't bother.  */
    1379          169 :       tree value = degenerate_phi_result (as_a <gphi *> (def));
    1380          169 :       if (!value
    1381          169 :           || (m_dead_ssas.contains (value)
    1382            0 :               && !prepare_debug_expressions (value)))
    1383              :         {
    1384          169 :           m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
    1385          169 :           return false;
    1386              :         }
    1387              : 
    1388            0 :       gcc_assert (TREE_CODE (value) == SSA_NAME);
    1389            0 :       tree *d = m_dead_ssa_debug_equiv.get (value);
    1390            0 :       m_dead_ssa_debug_equiv.put (dead_ssa, *d);
    1391            0 :       return true;
    1392              :     }
    1393              : 
    1394         1478 :   bool lost = false;
    1395         1478 :   use_operand_p use_p;
    1396         1478 :   ssa_op_iter oi;
    1397         2961 :   FOR_EACH_PHI_OR_STMT_USE (use_p, def, oi, SSA_OP_USE)
    1398              :     {
    1399         1665 :       tree use = USE_FROM_PTR (use_p);
    1400         1665 :       if (m_dead_ssas.contains (use)
    1401         1665 :           && !prepare_debug_expressions (use))
    1402              :         {
    1403          182 :           lost = true;
    1404          182 :           break;
    1405              :         }
    1406              :     }
    1407              : 
    1408         1478 :   if (lost)
    1409              :     {
    1410          182 :       m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
    1411          182 :       return false;
    1412              :     }
    1413              : 
    1414         1296 :   if (is_gimple_assign (def))
    1415              :     {
    1416         1296 :       gcc_assert (!gimple_clobber_p (def));
    1417         1296 :       if (gimple_assign_copy_p (def)
    1418         1296 :           && TREE_CODE (gimple_assign_rhs1 (def)) == SSA_NAME)
    1419              :         {
    1420            0 :           tree d = *m_dead_ssa_debug_equiv.get (gimple_assign_rhs1 (def));
    1421            0 :           gcc_assert (d);
    1422            0 :           m_dead_ssa_debug_equiv.put (dead_ssa, d);
    1423            0 :           return true;
    1424              :         }
    1425              : 
    1426         1296 :       tree val
    1427         1296 :         = unshare_expr_without_location (gimple_assign_rhs_to_tree (def));
    1428         1296 :       remap_with_debug_expressions (&val);
    1429              : 
    1430         1296 :       tree vexpr = build_debug_expr_decl (TREE_TYPE (val));
    1431         1296 :       m_dead_stmt_debug_equiv.put (def, val);
    1432         1296 :       m_dead_ssa_debug_equiv.put (dead_ssa, vexpr);
    1433         1296 :       return true;
    1434              :     }
    1435              :   else
    1436            0 :     gcc_unreachable ();
    1437              : }
    1438              : 
    1439              : /* Common initialization performed by all ipa_param_body_adjustments
    1440              :    constructors.  OLD_FNDECL is the declaration we take original arguments
    1441              :    from, (it may be the same as M_FNDECL).  VARS, if non-NULL, is a pointer to
    1442              :    a chained list of new local variables.  TREE_MAP is the IPA-CP produced
    1443              :    mapping of trees to constants.
    1444              : 
    1445              :    The function is rather long but it really onlu initializes all data members
    1446              :    of the class.  It creates new param DECLs, finds their new types,   */
    1447              : 
    1448              : void
    1449       155505 : ipa_param_body_adjustments::common_initialization (tree old_fndecl,
    1450              :                                                    tree *vars,
    1451              :                                                    vec<ipa_replace_map *,
    1452              :                                                        va_gc> *tree_map)
    1453              : {
    1454       155505 :   push_function_arg_decls (&m_oparms, old_fndecl);
    1455       155505 :   auto_vec<tree,16> otypes;
    1456       155505 :   if (TYPE_ARG_TYPES (TREE_TYPE (old_fndecl)) != NULL_TREE)
    1457       155338 :     push_function_arg_types (&otypes, TREE_TYPE (old_fndecl));
    1458              :   else
    1459              :     {
    1460          167 :       auto_vec<tree,16> oparms;
    1461          167 :       push_function_arg_decls (&oparms, old_fndecl);
    1462          167 :       unsigned ocount = oparms.length ();
    1463          167 :       otypes.reserve_exact (ocount);
    1464          451 :       for (unsigned i = 0; i < ocount; i++)
    1465          284 :         otypes.quick_push (TREE_TYPE (oparms[i]));
    1466          167 :     }
    1467       155505 :   fill_vector_of_new_param_types (&m_new_types, &otypes, m_adj_params, true);
    1468              : 
    1469       155505 :   auto_vec<bool, 16> kept;
    1470       311010 :   kept.reserve_exact (m_oparms.length ());
    1471       311010 :   kept.quick_grow_cleared (m_oparms.length ());
    1472       155505 :   auto_vec<bool, 16> split;
    1473       155505 :   split.reserve_exact (m_oparms.length ());
    1474       311010 :   split.quick_grow_cleared (m_oparms.length ());
    1475              : 
    1476       155505 :   unsigned adj_len = vec_safe_length (m_adj_params);
    1477       155505 :   m_method2func = ((TREE_CODE (TREE_TYPE (m_fndecl)) == METHOD_TYPE)
    1478       155505 :                    && (adj_len == 0
    1479        40283 :                        || (*m_adj_params)[0].op != IPA_PARAM_OP_COPY
    1480        40163 :                        || (*m_adj_params)[0].base_index != 0));
    1481              : 
    1482              :   /* The main job of the this function is to go over the vector of adjusted
    1483              :      parameters and create declarations or find corresponding old ones and push
    1484              :      them to m_new_decls.  For IPA-SRA replacements it also creates
    1485              :      corresponding m_id->dst_node->clone.performed_splits entries.  */
    1486              : 
    1487       155505 :   m_new_decls.reserve_exact (adj_len);
    1488       484922 :   for (unsigned i = 0; i < adj_len ; i++)
    1489              :     {
    1490       329417 :       ipa_adjusted_param *apm = &(*m_adj_params)[i];
    1491       329417 :       unsigned prev_index = apm->prev_clone_index;
    1492       329417 :       tree new_parm;
    1493       329417 :       if (apm->op == IPA_PARAM_OP_COPY
    1494        84698 :           || apm->prev_clone_adjustment)
    1495              :         {
    1496       244719 :           kept[prev_index] = true;
    1497       244719 :           new_parm = carry_over_param (m_oparms[prev_index]);
    1498       244719 :           m_new_decls.quick_push (new_parm);
    1499              :         }
    1500        84698 :       else if (apm->op == IPA_PARAM_OP_NEW
    1501        84698 :                || apm->op == IPA_PARAM_OP_SPLIT)
    1502              :         {
    1503        84698 :           tree new_type = m_new_types[i];
    1504        84698 :           gcc_checking_assert (new_type);
    1505        84698 :           new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE,
    1506              :                                  new_type);
    1507        84698 :           const char *prefix = ipa_param_prefixes[apm->param_prefix_index];
    1508        84698 :           DECL_NAME (new_parm) = create_tmp_var_name (prefix);
    1509        84698 :           DECL_ARTIFICIAL (new_parm) = 1;
    1510        84698 :           DECL_ARG_TYPE (new_parm) = new_type;
    1511        84698 :           DECL_CONTEXT (new_parm) = m_fndecl;
    1512        84698 :           TREE_USED (new_parm) = 1;
    1513        84698 :           DECL_IGNORED_P (new_parm) = 1;
    1514        84698 :           layout_decl (new_parm, 0);
    1515        84698 :           m_new_decls.quick_push (new_parm);
    1516              : 
    1517        84698 :           if (apm->op == IPA_PARAM_OP_SPLIT)
    1518              :             {
    1519        75884 :               split[prev_index] = true;
    1520        75884 :               register_replacement (apm, new_parm);
    1521              :             }
    1522              :         }
    1523              :       else
    1524            0 :         gcc_unreachable ();
    1525              :     }
    1526              : 
    1527       155505 :   auto_vec <int, 16> index_mapping;
    1528       155505 :   bool need_remap = false;
    1529       155505 :   if (m_id)
    1530              :     {
    1531       151001 :       clone_info *cinfo = clone_info::get (m_id->src_node);
    1532       151001 :       if (cinfo && cinfo->param_adjustments)
    1533              :         {
    1534         2616 :           cinfo->param_adjustments->get_updated_indices (&index_mapping);
    1535         2616 :           need_remap = true;
    1536              :         }
    1537              : 
    1538       151001 :       if (ipcp_transformation *ipcp_ts
    1539       151001 :           = ipcp_get_transformation_summary (m_id->src_node))
    1540              :         {
    1541        40558 :           for (const ipa_argagg_value &av : ipcp_ts->m_agg_values)
    1542              :             {
    1543        15303 :               int parm_num = av.index;
    1544              : 
    1545        15303 :               if (need_remap)
    1546              :                 {
    1547              :                   /* FIXME: We cannot handle the situation when IPA-CP
    1548              :                      identified that a parameter is a pointer to a global
    1549              :                      variable and at the same time the variable has some known
    1550              :                      constant contents (PR 107640).  The best place to make
    1551              :                      sure we don't drop such constants on the floor probably is
    1552              :                      not here, but we have to make sure that it does not
    1553              :                      confuse the remapping.  */
    1554        13290 :                   if (parm_num >= (int) index_mapping.length ())
    1555           35 :                     continue;
    1556         6610 :                   parm_num = index_mapping[parm_num];
    1557         6610 :                   if (parm_num < 0)
    1558           30 :                     continue;
    1559              :                 }
    1560              : 
    1561        15238 :               if (!kept[parm_num])
    1562              :                 {
    1563              :                   /* IPA-CP has detected an aggregate constant in a parameter
    1564              :                      that will not be kept, which means that IPA-SRA would have
    1565              :                      split it if there wasn't a constant.  Because we are about
    1566              :                      to remove the original, this is the last chance where we
    1567              :                      can substitute the uses with a constant (for values passed
    1568              :                      by reference) or do the split but initialize the
    1569              :                      replacement with a constant (for split aggregates passed
    1570              :                      by value).  */
    1571              : 
    1572        12029 :                   if (split[parm_num])
    1573              :                     {
    1574              :                       /* We must be careful not to add a duplicate
    1575              :                          replacement. */
    1576        10678 :                       sort_replacements ();
    1577        10678 :                       ipa_param_body_replacement *pbr
    1578        10678 :                         = lookup_replacement_1 (m_oparms[parm_num],
    1579        10678 :                                                 av.unit_offset);
    1580        10678 :                       if (pbr)
    1581              :                         {
    1582              :                           /* Otherwise IPA-SRA should have bailed out.  */
    1583            3 :                           gcc_assert (AGGREGATE_TYPE_P (TREE_TYPE (pbr->repl)));
    1584            3 :                           continue;
    1585              :                         }
    1586              :                     }
    1587              : 
    1588        12026 :                   tree repl;
    1589        12026 :                   if (av.by_ref)
    1590        10732 :                     repl = av.value;
    1591              :                   else
    1592              :                     {
    1593         1294 :                       repl = create_tmp_var (TREE_TYPE (av.value),
    1594              :                                              "removed_ipa_cp");
    1595         1294 :                       gimple *init_stmt = gimple_build_assign (repl, av.value);
    1596         1294 :                       m_split_agg_csts_inits.safe_push (init_stmt);
    1597              :                     }
    1598        12026 :                   register_replacement (m_oparms[parm_num], av.unit_offset,
    1599              :                                         repl);
    1600        12026 :                   split[parm_num] = true;
    1601              :                 }
    1602              :             }
    1603              :         }
    1604              :     }
    1605       155505 :   sort_replacements ();
    1606              : 
    1607       155505 :   if (tree_map)
    1608              :     {
    1609              :       /* Do not treat parameters which were replaced with a constant as
    1610              :          completely vanished.  */
    1611        34512 :       for (unsigned i = 0; i < tree_map->length (); i++)
    1612              :         {
    1613        21272 :           int parm_num = (*tree_map)[i]->parm_num;
    1614        21272 :           gcc_assert (parm_num >= 0);
    1615        21272 :           if (need_remap)
    1616            0 :             parm_num = index_mapping[parm_num];
    1617        21272 :           kept[parm_num] = true;
    1618              :         }
    1619              :     }
    1620              : 
    1621              :   /* As part of body modifications, we will also have to replace remaining uses
    1622              :      of remaining uses of removed PARM_DECLs (which do not however use the
    1623              :      initial value) with their VAR_DECL copies.
    1624              : 
    1625              :      We do this differently with and without m_id.  With m_id, we rely on its
    1626              :      mapping and create a replacement straight away.  Without it, we have our
    1627              :      own mechanism for which we have to populate m_removed_decls vector.  Just
    1628              :      don't mix them, that is why you should not call
    1629              :      replace_removed_params_ssa_names or perform_cfun_body_modifications when
    1630              :      you construct with ID not equal to NULL.  */
    1631              : 
    1632       155505 :   auto_vec<tree, 8> ssas_to_process_debug;
    1633       155505 :   unsigned op_len = m_oparms.length ();
    1634       577962 :   for (unsigned i = 0; i < op_len; i++)
    1635       422457 :     if (!kept[i])
    1636              :       {
    1637       156466 :         if (m_id)
    1638              :           {
    1639       151939 :             gcc_assert (!m_id->decl_map->get (m_oparms[i]));
    1640       151939 :             tree var = copy_decl_to_var (m_oparms[i], m_id);
    1641       151939 :             insert_decl_map (m_id, m_oparms[i], var);
    1642              :             /* Declare this new variable.  */
    1643       151939 :             DECL_CHAIN (var) = *vars;
    1644       151939 :             *vars = var;
    1645              : 
    1646              :             /* If this is not a split but a real removal, init hash sets
    1647              :                that will guide what not to copy to the new body.  */
    1648       151939 :             if (!split[i])
    1649       106001 :               mark_dead_statements (m_oparms[i], &ssas_to_process_debug);
    1650              :             else
    1651        45938 :               mark_clobbers_dead (m_oparms[i]);
    1652        19965 :             if (MAY_HAVE_DEBUG_STMTS
    1653       151939 :                 && is_gimple_reg (m_oparms[i]))
    1654        99103 :               m_reset_debug_decls.safe_push (m_oparms[i]);
    1655              :           }
    1656              :         else
    1657              :           {
    1658         4527 :             m_removed_decls.safe_push (m_oparms[i]);
    1659         9054 :             m_removed_map.put (m_oparms[i], m_removed_decls.length () - 1);
    1660         4254 :             if (MAY_HAVE_DEBUG_STMTS
    1661          273 :                 && !kept[i]
    1662         4800 :                 && is_gimple_reg (m_oparms[i]))
    1663          233 :               m_reset_debug_decls.safe_push (m_oparms[i]);
    1664              :           }
    1665              :       }
    1666              : 
    1667       315247 :   while (!ssas_to_process_debug.is_empty ())
    1668         4237 :     prepare_debug_expressions (ssas_to_process_debug.pop ());
    1669       155505 : }
    1670              : 
    1671              : /* Constructor of ipa_param_body_adjustments from a simple list of
    1672              :    modifications to parameters listed in ADJ_PARAMS which will prepare ground
    1673              :    for modification of parameters of fndecl.  Return value of the function will
    1674              :    not be removed and the object will assume it does not run as a part of
    1675              :    tree-function_versioning.  */
    1676              : 
    1677         4472 : ipa_param_body_adjustments
    1678              : ::ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
    1679         4472 :                               tree fndecl)
    1680         4472 :   : m_adj_params (adj_params), m_adjustments (NULL), m_reset_debug_decls (),
    1681         4472 :     m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (),
    1682         4472 :     m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (),
    1683         4472 :     m_new_decls (), m_new_types (), m_replacements (),
    1684         4472 :     m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
    1685         4472 :     m_method2func (false), m_sorted_replacements_p (true)
    1686              : {
    1687         4472 :   common_initialization (fndecl, NULL, NULL);
    1688         4472 : }
    1689              : 
    1690              : /* Constructor of ipa_param_body_adjustments from ipa_param_adjustments in
    1691              :    ADJUSTMENTS which will prepare ground for modification of parameters of
    1692              :    fndecl.  The object will assume it does not run as a part of
    1693              :    tree-function_versioning.  */
    1694              : 
    1695           32 : ipa_param_body_adjustments
    1696              : ::ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
    1697           32 :                               tree fndecl)
    1698           32 :   : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
    1699           32 :     m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
    1700           32 :     m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
    1701           32 :     m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
    1702           32 :     m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
    1703           32 :     m_method2func (false), m_sorted_replacements_p (true)
    1704              : {
    1705           32 :   common_initialization (fndecl, NULL, NULL);
    1706           32 : }
    1707              : 
    1708              : /* Constructor of ipa_param_body_adjustments which sets it up as a part of
    1709              :    running tree_function_versioning.  Planned modifications to the function are
    1710              :    in ADJUSTMENTS.  FNDECL designates the new function clone which is being
    1711              :    modified.  OLD_FNDECL is the function of which FNDECL is a clone (and which
    1712              :    at the time of invocation still share DECL_ARGUMENTS).  ID is the
    1713              :    copy_body_data structure driving the whole body copying process.  VARS is a
    1714              :    pointer to the head of the list of new local variables, TREE_MAP is the map
    1715              :    that drives tree substitution in the cloning process.  */
    1716              : 
    1717       151001 : ipa_param_body_adjustments
    1718              : ::ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
    1719              :                               tree fndecl, tree old_fndecl,
    1720              :                               copy_body_data *id, tree *vars,
    1721       151001 :                               vec<ipa_replace_map *, va_gc> *tree_map)
    1722       151001 :   : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
    1723       151001 :     m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
    1724       151001 :     m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
    1725       151001 :     m_id (id), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
    1726       151001 :     m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
    1727       151001 :     m_method2func (false), m_sorted_replacements_p (true)
    1728              : {
    1729       151001 :   common_initialization (old_fndecl, vars, tree_map);
    1730       151001 : }
    1731              : 
    1732              : /* Chain new param decls up and return them.  */
    1733              : 
    1734              : tree
    1735       155505 : ipa_param_body_adjustments::get_new_param_chain ()
    1736              : {
    1737       155505 :   tree result;
    1738       155505 :   tree *link = &result;
    1739              : 
    1740       155505 :   unsigned len = vec_safe_length (m_adj_params);
    1741       484922 :   for (unsigned i = 0; i < len; i++)
    1742              :     {
    1743       329417 :       tree new_decl = m_new_decls[i];
    1744       329417 :       *link = new_decl;
    1745       329417 :       link = &DECL_CHAIN (new_decl);
    1746              :     }
    1747       155505 :   *link = NULL_TREE;
    1748       155505 :   return result;
    1749              : }
    1750              : 
    1751              : /* Modify the function parameters FNDECL and its type according to the plan in
    1752              :    ADJUSTMENTS.  This function needs to be called when the decl has not already
    1753              :    been processed with ipa_param_adjustments::adjust_decl, otherwise just
    1754              :    seting DECL_ARGUMENTS to whatever get_new_param_chain will do is enough.  */
    1755              : 
    1756              : void
    1757         4504 : ipa_param_body_adjustments::modify_formal_parameters ()
    1758              : {
    1759         4504 :   tree orig_type = TREE_TYPE (m_fndecl);
    1760         4504 :   DECL_ARGUMENTS (m_fndecl) = get_new_param_chain ();
    1761              : 
    1762              :   /* When signature changes, we need to clear builtin info.  */
    1763         4504 :   if (fndecl_built_in_p (m_fndecl))
    1764            0 :     set_decl_built_in_function (m_fndecl, NOT_BUILT_IN, 0);
    1765              : 
    1766         4504 :   bool modified = false;
    1767         4504 :   size_t index = 0;
    1768         4504 :   if (m_adj_params)
    1769         4144 :     for (tree t = TYPE_ARG_TYPES (orig_type);
    1770        10630 :          t && !modified;
    1771         6486 :          t = TREE_CHAIN (t), index++)
    1772         6486 :       if (index >= m_adj_params->length ()
    1773         5897 :           || (*m_adj_params)[index].op != IPA_PARAM_OP_COPY
    1774         8869 :           || (*m_adj_params)[index].base_index != index)
    1775              :         modified = true;
    1776              : 
    1777              :   /* At this point, removing return value is only implemented when going
    1778              :      through tree_function_versioning, not when modifying function body
    1779              :      directly.  */
    1780         4504 :   gcc_assert (!m_adjustments || !m_adjustments->m_skip_return);
    1781         9008 :   tree new_type = build_adjusted_function_type (orig_type, &m_new_types,
    1782         4504 :                                                 m_method2func, false, modified);
    1783              : 
    1784         4504 :   TREE_TYPE (m_fndecl) = new_type;
    1785         4504 :   DECL_VIRTUAL_P (m_fndecl) = 0;
    1786         4504 :   DECL_LANG_SPECIFIC (m_fndecl) = NULL;
    1787         4504 :   if (m_method2func)
    1788          120 :     DECL_VINDEX (m_fndecl) = NULL_TREE;
    1789         4504 : }
    1790              : 
    1791              : /* Given BASE and UNIT_OFFSET, find the corresponding record among replacement
    1792              :    structures.  */
    1793              : 
    1794              : ipa_param_body_replacement *
    1795       164588 : ipa_param_body_adjustments::lookup_replacement_1 (tree base,
    1796              :                                                   unsigned unit_offset)
    1797              : {
    1798       164588 :   gcc_assert (m_sorted_replacements_p);
    1799       164588 :   ipa_param_body_replacement key;
    1800       164588 :   key.base = base;
    1801       164588 :   key.unit_offset = unit_offset;
    1802       164588 :   ipa_param_body_replacement *res
    1803       329176 :     = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
    1804       323661 :                         [] (const ipa_param_body_replacement &elt,
    1805              :                             const ipa_param_body_replacement &val)
    1806              :                         {
    1807       323661 :                           return (compare_param_body_replacement (&elt, &val)
    1808              :                                   < 0);
    1809              :                         });
    1810              : 
    1811       164588 :   if (res == m_replacements.end ()
    1812       129304 :       || res->base != base
    1813       253501 :       || res->unit_offset != unit_offset)
    1814        76807 :     return NULL;
    1815              :   return res;
    1816              : }
    1817              : 
    1818              : /* Find the first replacement for BASE among m_replacements and return pointer
    1819              :    to it, or NULL if there is none.  */
    1820              : 
    1821              : ipa_param_body_replacement *
    1822        25954 : ipa_param_body_adjustments::lookup_first_base_replacement (tree base)
    1823              : {
    1824        25954 :   gcc_assert (m_sorted_replacements_p);
    1825        25954 :   ipa_param_body_replacement key;
    1826        25954 :   key.base = base;
    1827        25954 :   ipa_param_body_replacement *res
    1828        51908 :     = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
    1829        38527 :                         [] (const ipa_param_body_replacement &elt,
    1830              :                             const ipa_param_body_replacement &val)
    1831              :                         {
    1832        38527 :                           if (DECL_UID (elt.base) < DECL_UID (val.base))
    1833        14403 :                             return true;
    1834              :                           return false;
    1835              :                         });
    1836              : 
    1837        25954 :   if (res == m_replacements.end ()
    1838        25954 :       || res->base != base)
    1839        20753 :     return NULL;
    1840              :   return res;
    1841              : }
    1842              : 
    1843              : /* Given BASE and UNIT_OFFSET, find the corresponding replacement expression
    1844              :    and return it, assuming it is known it does not hold value by reference or
    1845              :    in reverse storage order.  */
    1846              : 
    1847              : tree
    1848         4051 : ipa_param_body_adjustments::lookup_replacement (tree base, unsigned unit_offset)
    1849              : {
    1850         4051 :   ipa_param_body_replacement *pbr = lookup_replacement_1 (base, unit_offset);
    1851         4051 :   if (!pbr)
    1852              :     return NULL;
    1853         4051 :   return pbr->repl;
    1854              : }
    1855              : 
    1856              : /* If T is an SSA_NAME, return NULL if it is not a default def or
    1857              :    return its base variable if it is.  If IGNORE_DEFAULT_DEF is true,
    1858              :    the base variable is always returned, regardless if it is a default
    1859              :    def.  Return T if it is not an SSA_NAME.  */
    1860              : 
    1861              : static tree
    1862       968422 : get_ssa_base_param (tree t, bool ignore_default_def)
    1863              : {
    1864       968422 :   if (TREE_CODE (t) == SSA_NAME)
    1865              :     {
    1866       593838 :       if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t))
    1867       127750 :         return SSA_NAME_VAR (t);
    1868              :       else
    1869              :         return NULL_TREE;
    1870              :     }
    1871              :   return t;
    1872              : }
    1873              : 
    1874              : /* Given an expression, return the structure describing how it should be
    1875              :    replaced if it accesses a part of a split parameter or NULL otherwise.
    1876              : 
    1877              :    Do not free the result, it will be deallocated when the object is destroyed.
    1878              : 
    1879              :    If IGNORE_DEFAULT_DEF is cleared, consider only SSA_NAMEs of PARM_DECLs
    1880              :    which are default definitions, if set, consider all SSA_NAMEs of
    1881              :    PARM_DECLs.  */
    1882              : 
    1883              : ipa_param_body_replacement *
    1884       974971 : ipa_param_body_adjustments::get_expr_replacement (tree expr,
    1885              :                                                   bool ignore_default_def)
    1886              : {
    1887       974971 :   tree base;
    1888       974971 :   unsigned unit_offset;
    1889              : 
    1890       974971 :   if (!isra_get_ref_base_and_offset (expr, &base, &unit_offset))
    1891              :     return NULL;
    1892              : 
    1893       968422 :   base = get_ssa_base_param (base, ignore_default_def);
    1894       968422 :   if (!base || TREE_CODE (base) != PARM_DECL)
    1895              :     return NULL;
    1896       148922 :   return lookup_replacement_1 (base, unit_offset);
    1897              : }
    1898              : 
    1899              : /* Given OLD_DECL, which is a PARM_DECL of a parameter that is being removed
    1900              :    (which includes it being split or replaced), return a new variable that
    1901              :    should be used for any SSA names that will remain in the function that
    1902              :    previously belonged to OLD_DECL.  */
    1903              : 
    1904              : tree
    1905         7937 : ipa_param_body_adjustments::get_replacement_ssa_base (tree old_decl)
    1906              : {
    1907         7937 :   unsigned *idx = m_removed_map.get (old_decl);
    1908         7937 :   if (!idx)
    1909              :     return NULL;
    1910              : 
    1911         4483 :   tree repl;
    1912         4483 :   if (TREE_CODE (m_removed_decls[*idx]) == PARM_DECL)
    1913              :     {
    1914         4051 :       gcc_assert (m_removed_decls[*idx] == old_decl);
    1915         4051 :       repl = copy_var_decl (old_decl, DECL_NAME (old_decl),
    1916         4051 :                             TREE_TYPE (old_decl));
    1917         4051 :       m_removed_decls[*idx] = repl;
    1918              :     }
    1919              :   else
    1920              :     repl = m_removed_decls[*idx];
    1921              :   return repl;
    1922              : }
    1923              : 
    1924              : /* If OLD_NAME, which is being defined by statement STMT, is an SSA_NAME of a
    1925              :    parameter which is to be removed because its value is not used, create a new
    1926              :    SSA_NAME relating to a replacement VAR_DECL, replace all uses of the
    1927              :    original with it and return it.  If there is no need to re-map, return NULL.
    1928              :    ADJUSTMENTS is a pointer to a vector of IPA-SRA adjustments.  */
    1929              : 
    1930              : tree
    1931            0 : ipa_param_body_adjustments::replace_removed_params_ssa_names (tree old_name,
    1932              :                                                               gimple *stmt)
    1933              : {
    1934            0 :   gcc_assert (!m_id);
    1935            0 :   if (TREE_CODE (old_name) != SSA_NAME)
    1936              :     return NULL;
    1937              : 
    1938            0 :   tree decl = SSA_NAME_VAR (old_name);
    1939            0 :   if (decl == NULL_TREE
    1940            0 :       || TREE_CODE (decl) != PARM_DECL)
    1941              :     return NULL;
    1942              : 
    1943            0 :   tree repl = get_replacement_ssa_base (decl);
    1944            0 :   if (!repl)
    1945              :     return NULL;
    1946              : 
    1947            0 :   tree new_name = make_ssa_name (repl, stmt);
    1948            0 :   SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_name)
    1949            0 :     = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (old_name);
    1950              : 
    1951            0 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1952              :     {
    1953            0 :       fprintf (dump_file, "replacing an SSA name of a removed param ");
    1954            0 :       print_generic_expr (dump_file, old_name);
    1955            0 :       fprintf (dump_file, " with ");
    1956            0 :       print_generic_expr (dump_file, new_name);
    1957            0 :       fprintf (dump_file, "\n");
    1958              :     }
    1959              : 
    1960            0 :   replace_uses_by (old_name, new_name);
    1961            0 :   return new_name;
    1962              : }
    1963              : 
    1964              : /* If the expression *EXPR_P should be replaced, do so.  CONVERT specifies
    1965              :    whether the function should care about type incompatibility of the current
    1966              :    and new expressions.  If it is false, the function will leave
    1967              :    incompatibility issues to the caller - note that when the function
    1968              :    encounters a BIT_FIELD_REF, IMAGPART_EXPR or REALPART_EXPR, it will modify
    1969              :    their bases instead of the expressions themselves and then also performs any
    1970              :    necessary conversions.  */
    1971              : 
    1972              : bool
    1973      2390167 : ipa_param_body_adjustments::modify_expression (tree *expr_p, bool convert,
    1974              :                                                gimple_seq *extra_stmts)
    1975              : {
    1976      2390167 :   tree expr = *expr_p;
    1977              : 
    1978      4698837 :   if (m_replacements.is_empty ())
    1979              :     return false;
    1980       972887 :   if (TREE_CODE (expr) == BIT_FIELD_REF
    1981       972887 :       || TREE_CODE (expr) == IMAGPART_EXPR
    1982       972309 :       || TREE_CODE (expr) == REALPART_EXPR)
    1983              :     {
    1984              :       /* For a BIT_FIELD_REF do not bother to VIEW_CONVERT the base,
    1985              :          instead reference the replacement directly.  */
    1986          967 :       convert = TREE_CODE (expr) != BIT_FIELD_REF;
    1987          967 :       expr_p = &TREE_OPERAND (expr, 0);
    1988          967 :       expr = *expr_p;
    1989              :     }
    1990              : 
    1991       972887 :   ipa_param_body_replacement *pbr = get_expr_replacement (expr, false);
    1992       972887 :   if (!pbr)
    1993              :     return false;
    1994              : 
    1995        81497 :   tree repl = pbr->repl;
    1996        81497 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1997              :     {
    1998            8 :       fprintf (dump_file, "About to replace expr ");
    1999            8 :       print_generic_expr (dump_file, expr);
    2000            8 :       fprintf (dump_file, " with ");
    2001            8 :       print_generic_expr (dump_file, repl);
    2002            8 :       fprintf (dump_file, "\n");
    2003              :     }
    2004              : 
    2005        81747 :   if (convert && !useless_type_conversion_p (TREE_TYPE (expr),
    2006          250 :                                              TREE_TYPE (repl)))
    2007              :     {
    2008            8 :       gcc_checking_assert (tree_to_shwi (TYPE_SIZE (TREE_TYPE (expr)))
    2009              :                            == tree_to_shwi (TYPE_SIZE (TREE_TYPE (repl))));
    2010            8 :       tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), repl);
    2011            8 :       if (is_gimple_reg (repl)
    2012            8 :           && is_gimple_reg_type (TREE_TYPE (expr)))
    2013              :         {
    2014            0 :           gcc_assert (extra_stmts);
    2015            0 :           vce = force_gimple_operand (vce, extra_stmts, true, NULL_TREE);
    2016              :         }
    2017            8 :       *expr_p = vce;
    2018              :     }
    2019              :   else
    2020        81489 :     *expr_p = repl;
    2021              :   return true;
    2022              : }
    2023              : 
    2024              : /* If the assignment statement STMT contains any expressions that need to
    2025              :    replaced with a different one as noted by ADJUSTMENTS, do so.  Handle any
    2026              :    potential type incompatibilities.  If any conversion sttements have to be
    2027              :    pre-pended to STMT, they will be added to EXTRA_STMTS.  Return true iff the
    2028              :    statement was modified.  */
    2029              : 
    2030              : bool
    2031      1881811 : ipa_param_body_adjustments::modify_assignment (gimple *stmt,
    2032              :                                                gimple_seq *extra_stmts)
    2033              : {
    2034      1881811 :   tree *lhs_p, *rhs_p;
    2035      1881811 :   bool any;
    2036              : 
    2037      2418429 :   if (m_replacements.is_empty () || !gimple_assign_single_p (stmt))
    2038              :     return false;
    2039              : 
    2040       362674 :   rhs_p = gimple_assign_rhs1_ptr (stmt);
    2041       362674 :   lhs_p = gimple_assign_lhs_ptr (stmt);
    2042              : 
    2043       362674 :   any = modify_expression (lhs_p, false);
    2044       362674 :   any |= modify_expression (rhs_p, false, extra_stmts);
    2045       362674 :   if (any
    2046       362674 :       && !useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
    2047              :     {
    2048            4 :       if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
    2049              :         {
    2050              :           /* V_C_Es of constructors can cause trouble (PR 42714).  */
    2051            0 :           if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
    2052            0 :             *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
    2053              :           else
    2054            0 :             *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
    2055              :                                         NULL);
    2056              :         }
    2057              :       else
    2058              :         {
    2059            4 :           gcc_checking_assert (tree_to_shwi (TYPE_SIZE (TREE_TYPE (*lhs_p)))
    2060              :                               == tree_to_shwi (TYPE_SIZE (TREE_TYPE (*rhs_p))));
    2061            4 :           tree new_rhs = fold_build1_loc (gimple_location (stmt),
    2062            4 :                                           VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
    2063              :                                           *rhs_p);
    2064            4 :           tree tmp = force_gimple_operand (new_rhs, extra_stmts, true,
    2065              :                                            NULL_TREE);
    2066            4 :           gimple_assign_set_rhs1 (stmt, tmp);
    2067              :         }
    2068            4 :       return true;
    2069              :     }
    2070              : 
    2071              :   return any;
    2072              : }
    2073              : 
    2074              : /* Record information about what modifications to call arguments have already
    2075              :    been done by clone materialization into a summary describing CS.  The
    2076              :    information is stored in NEW_INDEX_MAP, NEW_PT_MAP and NEW_ALWAYS_COPY_DELTA
    2077              :    and correspond to equivalent fields in ipa_edge_modification_info.  Return
    2078              :    the edge summary.  */
    2079              : 
    2080              : static ipa_edge_modification_info *
    2081        12027 : record_argument_state_1 (cgraph_edge *cs, const vec<int> &new_index_map,
    2082              :                          const vec<pass_through_split_map> &new_pt_map,
    2083              :                          int new_always_copy_delta)
    2084              : 
    2085              : {
    2086        12027 :   ipa_edge_modification_info *sum = ipa_edge_modifications->get_create (cs);
    2087              : 
    2088        12027 :   unsigned len = sum->pass_through_map.length ();
    2089        12027 :   for (unsigned i = 0; i < len; i++)
    2090              :     {
    2091            0 :       unsigned oldnew = sum->pass_through_map[i].new_index;
    2092            0 :       sum->pass_through_map[i].new_index = new_index_map[oldnew];
    2093              :     }
    2094              : 
    2095        12027 :   len = sum->index_map.length ();
    2096            0 :   if (len > 0)
    2097              :     {
    2098            0 :       unsigned nptlen = new_pt_map.length ();
    2099            0 :       for (unsigned j = 0; j < nptlen; j++)
    2100              :         {
    2101            0 :           int inverse = -1;
    2102            0 :           for (unsigned i = 0; i < len ; i++)
    2103            0 :             if ((unsigned) sum->index_map[i] == new_pt_map[j].base_index)
    2104              :             {
    2105            0 :               inverse = i;
    2106            0 :               break;
    2107              :             }
    2108            0 :           gcc_assert (inverse >= 0);
    2109            0 :           pass_through_split_map ptm_item;
    2110              : 
    2111            0 :           ptm_item.base_index = inverse;
    2112            0 :           ptm_item.unit_offset = new_pt_map[j].unit_offset;
    2113            0 :           ptm_item.new_index = new_pt_map[j].new_index;
    2114            0 :           sum->pass_through_map.safe_push (ptm_item);
    2115              :         }
    2116              : 
    2117            0 :       for (unsigned i = 0; i < len; i++)
    2118              :         {
    2119            0 :           int idx = sum->index_map[i];
    2120            0 :           if (idx < 0)
    2121            0 :             continue;
    2122            0 :           sum->index_map[i] = new_index_map[idx];
    2123              :         }
    2124              :     }
    2125              :   else
    2126              :     {
    2127        12027 :       sum->pass_through_map.safe_splice (new_pt_map);
    2128        12027 :       sum->index_map.safe_splice (new_index_map);
    2129              :     }
    2130        12027 :   sum->always_copy_delta += new_always_copy_delta;
    2131        12027 :   return sum;
    2132              : }
    2133              : 
    2134              : /* Record information about what modifications to call arguments have already
    2135              :    been done by clone materialization into a summary of an edge describing the
    2136              :    call in this clone and all its clones.  NEW_INDEX_MAP, NEW_PT_MAP and
    2137              :    NEW_ALWAYS_COPY_DELTA have the same meaning as record_argument_state_1.
    2138              : 
    2139              :    In order to associate the info with the right edge summaries, we need
    2140              :    address of the ORIG_STMT in the function from which we are cloning (because
    2141              :    the edges have not yet been re-assigned to the new statement that has just
    2142              :    been created) and ID, the structure governing function body copying.  */
    2143              : 
    2144              : static void
    2145        12027 : record_argument_state (copy_body_data *id, gimple *orig_stmt,
    2146              :                        const vec<int> &new_index_map,
    2147              :                        const vec<pass_through_split_map> &new_pt_map,
    2148              :                        int new_always_copy_delta)
    2149              : {
    2150        12027 :   if (!ipa_edge_modifications)
    2151         2884 :     ipa_edge_modifications = new ipa_edge_modification_sum (symtab);
    2152              : 
    2153        12027 :   struct cgraph_node *this_node = id->dst_node;
    2154        12027 :   ipa_edge_modification_info *first_sum = NULL;
    2155        12027 :   cgraph_edge *cs = this_node->get_edge (orig_stmt);
    2156        12027 :   if (cs)
    2157        12027 :     first_sum = record_argument_state_1 (cs, new_index_map, new_pt_map,
    2158              :                                          new_always_copy_delta);
    2159              :   else
    2160            0 :     gcc_assert (this_node->clones);
    2161              : 
    2162        12027 :   if (!this_node->clones)
    2163              :     return;
    2164        24246 :   for (cgraph_node *subclone = this_node->clones; subclone != this_node;)
    2165              :     {
    2166        20355 :       cs = subclone->get_edge (orig_stmt);
    2167        20355 :       if (cs)
    2168              :         {
    2169        20355 :           if (!first_sum)
    2170            0 :             first_sum = record_argument_state_1 (cs, new_index_map, new_pt_map,
    2171              :                                                  new_always_copy_delta);
    2172              :           else
    2173              :             {
    2174        20355 :               ipa_edge_modification_info *s2
    2175        20355 :                 = ipa_edge_modifications->get_create (cs);
    2176        20355 :               s2->index_map.truncate (0);
    2177        20355 :               s2->index_map.safe_splice (first_sum->index_map);
    2178        20355 :               s2->pass_through_map.truncate (0);
    2179        20355 :               s2->pass_through_map.safe_splice (first_sum->pass_through_map);
    2180        20355 :               s2->always_copy_delta = first_sum->always_copy_delta;
    2181              :             }
    2182              :         }
    2183              :       else
    2184            0 :         gcc_assert (subclone->clones);
    2185              : 
    2186        20355 :       if (subclone->clones)
    2187              :         subclone = subclone->clones;
    2188        19381 :       else if (subclone->next_sibling_clone)
    2189              :         subclone = subclone->next_sibling_clone;
    2190              :       else
    2191              :         {
    2192         9342 :           while (subclone != this_node && !subclone->next_sibling_clone)
    2193         4865 :             subclone = subclone->clone_of;
    2194         4477 :           if (subclone != this_node)
    2195          586 :             subclone = subclone->next_sibling_clone;
    2196              :         }
    2197              :     }
    2198              : }
    2199              : 
    2200              : /* If the call statement pointed at by STMT_P contains any expressions that
    2201              :    need to replaced with a different one as noted by ADJUSTMENTS, do so.  f the
    2202              :    statement needs to be rebuilt, do so.  Return true if any modifications have
    2203              :    been performed.  ORIG_STMT, if not NULL, is the original statement in the
    2204              :    function that is being cloned from, which at this point can be used to look
    2205              :    up call_graph edges.
    2206              : 
    2207              :    If the method is invoked as a part of IPA clone materialization and if any
    2208              :    parameter split is pass-through, i.e. it applies to the functin that is
    2209              :    being modified and also to the callee of the statement, replace the
    2210              :    parameter passed to old callee with all of the replacement a callee might
    2211              :    possibly want and record the performed argument modifications in
    2212              :    ipa_edge_modifications.  Likewise if any argument has already been left out
    2213              :    because it is not necessary.  */
    2214              : 
    2215              : bool
    2216       595634 : ipa_param_body_adjustments::modify_call_stmt (gcall **stmt_p,
    2217              :                                               gimple *orig_stmt)
    2218              : {
    2219       595634 :   auto_vec <unsigned, 4> pass_through_args;
    2220       595634 :   auto_vec <unsigned, 4> pass_through_pbr_indices;
    2221       595634 :   auto_vec <HOST_WIDE_INT, 4> pass_through_offsets;
    2222       595634 :   gcall *stmt = *stmt_p;
    2223       595634 :   unsigned nargs = gimple_call_num_args (stmt);
    2224       595634 :   bool recreate = false;
    2225       595634 :   gcc_assert (m_sorted_replacements_p);
    2226              : 
    2227      1999140 :   for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
    2228              :     {
    2229      1403506 :       tree t = gimple_call_arg (stmt, i);
    2230      1403506 :       gcc_assert (TREE_CODE (t) != BIT_FIELD_REF
    2231              :                   && TREE_CODE (t) != IMAGPART_EXPR
    2232              :                   && TREE_CODE (t) != REALPART_EXPR);
    2233              : 
    2234      1403506 :       if (TREE_CODE (t) == SSA_NAME
    2235      1403506 :           && m_dead_ssas.contains (t))
    2236              :         recreate = true;
    2237              : 
    2238      1403506 :       if (m_replacements.is_empty ())
    2239      1398305 :         continue;
    2240              : 
    2241       186393 :       tree base;
    2242       186393 :       unsigned agg_arg_offset;
    2243       186393 :       if (!isra_get_ref_base_and_offset (t, &base, &agg_arg_offset))
    2244            1 :         continue;
    2245              : 
    2246       186392 :       bool by_ref = false;
    2247       186392 :       if (TREE_CODE (base) == SSA_NAME)
    2248              :         {
    2249        96401 :           if (!SSA_NAME_IS_DEFAULT_DEF (base))
    2250        72260 :             continue;
    2251        24141 :           base = SSA_NAME_VAR (base);
    2252        24141 :           gcc_checking_assert (base);
    2253              :           by_ref = true;
    2254              :         }
    2255       114132 :       if (TREE_CODE (base) != PARM_DECL)
    2256        88178 :         continue;
    2257              : 
    2258        25954 :       ipa_param_body_replacement *first_rep
    2259        25954 :         = lookup_first_base_replacement (base);
    2260        25954 :       if (!first_rep)
    2261        20753 :         continue;
    2262         5201 :       unsigned first_rep_index = first_rep - m_replacements.begin ();
    2263              : 
    2264              :       /* We still have to distinguish between an end-use that we have to
    2265              :          transform now and a pass-through, which happens in the following
    2266              :          two cases.  */
    2267              : 
    2268              :       /* TODO: After we adjust ptr_parm_has_nonarg_uses to also consider
    2269              :          &MEM_REF[ssa_name + offset], we will also have to detect that case
    2270              :          here.    */
    2271              : 
    2272         5201 :       if (TREE_CODE (t) == SSA_NAME
    2273         4254 :           && SSA_NAME_IS_DEFAULT_DEF (t)
    2274         4254 :           && SSA_NAME_VAR (t)
    2275         9455 :           && TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL)
    2276              :         {
    2277              :           /* This must be a by_reference pass-through.  */
    2278         4254 :           recreate = true;
    2279         4254 :           gcc_assert (POINTER_TYPE_P (TREE_TYPE (t)));
    2280         4254 :           pass_through_args.safe_push (i);
    2281         4254 :           pass_through_pbr_indices.safe_push (first_rep_index);
    2282         4254 :           pass_through_offsets.safe_push (agg_arg_offset);
    2283              :         }
    2284          947 :       else if (!by_ref && AGGREGATE_TYPE_P (TREE_TYPE (t)))
    2285              :         {
    2286              :           /* Currently IPA-SRA guarantees the aggregate access type
    2287              :              exactly matches in this case.  So if it does not match, it is
    2288              :              a pass-through argument that will be sorted out at edge
    2289              :              redirection time.  */
    2290          937 :           ipa_param_body_replacement *pbr
    2291          937 :             = lookup_replacement_1 (base, agg_arg_offset);
    2292              : 
    2293          937 :           if (!pbr
    2294          937 :               || (TYPE_MAIN_VARIANT (TREE_TYPE (t))
    2295          926 :                   != TYPE_MAIN_VARIANT (TREE_TYPE (pbr->repl))))
    2296              :             {
    2297          916 :               recreate = true;
    2298          916 :               pass_through_args.safe_push (i);
    2299          916 :               pass_through_pbr_indices.safe_push (first_rep_index);
    2300          916 :               pass_through_offsets.safe_push (agg_arg_offset);
    2301              :             }
    2302              :         }
    2303              :     }
    2304              : 
    2305       595634 :   if (!recreate)
    2306              :     {
    2307              :       /* No need to rebuild the statement, let's just modify arguments
    2308              :          and the LHS if/as appropriate.  */
    2309              :       bool modified = false;
    2310      1945576 :       for (unsigned i = 0; i < nargs; i++)
    2311              :         {
    2312      1361969 :           tree *t = gimple_call_arg_ptr (stmt, i);
    2313      1361969 :           modified |= modify_expression (t, true);
    2314              :         }
    2315       583607 :       if (gimple_call_lhs (stmt))
    2316              :         {
    2317       204565 :           tree *t = gimple_call_lhs_ptr (stmt);
    2318       204565 :           modified |= modify_expression (t, false);
    2319              :         }
    2320       583607 :       return modified;
    2321              :     }
    2322              : 
    2323        12027 :   auto_vec<int, 16> index_map;
    2324        12027 :   auto_vec<pass_through_split_map, 4> pass_through_map;
    2325        12027 :   auto_vec<tree, 16> vargs;
    2326        12027 :   int always_copy_delta = 0;
    2327        12027 :   unsigned pt_idx = 0;
    2328        12027 :   int new_arg_idx = 0;
    2329        53564 :   for (unsigned i = 0; i < nargs; i++)
    2330              :     {
    2331        41537 :       if (pt_idx < pass_through_args.length ()
    2332        49218 :           && i == pass_through_args[pt_idx])
    2333              :         {
    2334         5170 :           unsigned j = pass_through_pbr_indices[pt_idx];
    2335         5170 :           unsigned agg_arg_offset = pass_through_offsets[pt_idx];
    2336         5170 :           pt_idx++;
    2337         5170 :           always_copy_delta--;
    2338         5170 :           tree base = m_replacements[j].base;
    2339              : 
    2340              :           /* In order to be put into SSA form, we have to push all replacements
    2341              :              pertaining to this parameter as parameters to the call statement.
    2342              :              Edge redirection will need to use edge summary to weed out the
    2343              :              unnecessary ones.  */
    2344         5170 :           unsigned repl_list_len = m_replacements.length ();
    2345        14217 :           for (; j < repl_list_len; j++)
    2346              :             {
    2347         9677 :               if (m_replacements[j].base != base)
    2348              :                 break;
    2349         9047 :               if (m_replacements[j].unit_offset < agg_arg_offset)
    2350            1 :                 continue;
    2351         9046 :               pass_through_split_map pt_map;
    2352         9046 :               pt_map.base_index = i;
    2353         9046 :               pt_map.unit_offset
    2354         9046 :                 = m_replacements[j].unit_offset - agg_arg_offset;
    2355         9046 :               pt_map.new_index = new_arg_idx;
    2356         9046 :               pass_through_map.safe_push (pt_map);
    2357         9046 :               vargs.safe_push (m_replacements[j].repl);
    2358         9046 :               new_arg_idx++;
    2359         9046 :               always_copy_delta++;
    2360              :             }
    2361         5170 :           index_map.safe_push (-1);
    2362              :         }
    2363              :       else
    2364              :         {
    2365        36367 :           tree t = gimple_call_arg (stmt, i);
    2366        36367 :           if (TREE_CODE (t) == SSA_NAME
    2367        36367 :               && m_dead_ssas.contains (t))
    2368              :             {
    2369         7708 :               always_copy_delta--;
    2370         7708 :               index_map.safe_push (-1);
    2371              :             }
    2372              :           else
    2373              :             {
    2374        28659 :               modify_expression (&t, true);
    2375        28659 :               vargs.safe_push (t);
    2376        28659 :               index_map.safe_push (new_arg_idx);
    2377        28659 :               new_arg_idx++;
    2378              :             }
    2379              :         }
    2380              :     }
    2381              : 
    2382        12027 :   gcall *new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
    2383        12027 :   if (gimple_has_location (stmt))
    2384        10979 :     gimple_set_location (new_stmt, gimple_location (stmt));
    2385        12027 :   gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
    2386        12027 :   gimple_call_copy_flags (new_stmt, stmt);
    2387        12027 :   if (tree lhs = gimple_call_lhs (stmt))
    2388              :     {
    2389         9376 :       modify_expression (&lhs, false);
    2390              :       /* Avoid adjusting SSA_NAME_DEF_STMT of a SSA lhs, SSA names
    2391              :          have not yet been remapped.  */
    2392         9376 :       *gimple_call_lhs_ptr (new_stmt) = lhs;
    2393              :     }
    2394        12027 :   *stmt_p = new_stmt;
    2395              : 
    2396        12027 :   if (orig_stmt)
    2397        12027 :     record_argument_state (m_id, orig_stmt, index_map, pass_through_map,
    2398              :                            always_copy_delta);
    2399        12027 :   return true;
    2400       607661 : }
    2401              : 
    2402              : /* If the statement STMT contains any expressions that need to replaced with a
    2403              :    different one as noted by ADJUSTMENTS, do so.  Handle any potential type
    2404              :    incompatibilities.  If any conversion sttements have to be pre-pended to
    2405              :    STMT, they will be added to EXTRA_STMTS.  Return true iff the statement was
    2406              :    modified.  */
    2407              : 
    2408              : bool
    2409      3155188 : ipa_param_body_adjustments::modify_gimple_stmt (gimple **stmt,
    2410              :                                                 gimple_seq *extra_stmts,
    2411              :                                                 gimple *orig_stmt)
    2412              : {
    2413      3155188 :   bool modified = false;
    2414      3155188 :   tree *t;
    2415              : 
    2416      3155188 :   switch (gimple_code (*stmt))
    2417              :     {
    2418       138314 :     case GIMPLE_RETURN:
    2419       138314 :       t = gimple_return_retval_ptr (as_a <greturn *> (*stmt));
    2420       138314 :       if (m_adjustments && m_adjustments->m_skip_return)
    2421        34563 :         *t = NULL_TREE;
    2422       103751 :       else if (*t != NULL_TREE)
    2423        57637 :         modified |= modify_expression (t, true);
    2424              :       break;
    2425              : 
    2426      1881811 :     case GIMPLE_ASSIGN:
    2427      1881811 :       modified |= modify_assignment (*stmt, extra_stmts);
    2428      1881811 :       break;
    2429              : 
    2430       595634 :     case GIMPLE_CALL:
    2431       595634 :       modified |= modify_call_stmt ((gcall **) stmt, orig_stmt);
    2432       595634 :       break;
    2433              : 
    2434          971 :     case GIMPLE_ASM:
    2435          971 :       {
    2436          971 :         gasm *asm_stmt = as_a <gasm *> (*stmt);
    2437         2044 :         for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
    2438              :           {
    2439         1073 :             t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
    2440         1073 :             modified |= modify_expression (t, true);
    2441              :           }
    2442         2511 :         for (unsigned i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
    2443              :           {
    2444         1540 :             t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
    2445         1540 :             modified |= modify_expression (t, false);
    2446              :           }
    2447              :       }
    2448              :       break;
    2449              : 
    2450              :     default:
    2451              :       break;
    2452              :     }
    2453      3155188 :   return modified;
    2454              : }
    2455              : 
    2456              : 
    2457              : /* Traverse body of the current function and perform the requested adjustments
    2458              :    on its statements.  Return true iff the CFG has been changed.  */
    2459              : 
    2460              : bool
    2461            0 : ipa_param_body_adjustments::modify_cfun_body ()
    2462              : {
    2463            0 :   bool cfg_changed = false;
    2464            0 :   basic_block bb;
    2465              : 
    2466            0 :   FOR_EACH_BB_FN (bb, cfun)
    2467              :     {
    2468            0 :       gimple_stmt_iterator gsi;
    2469              : 
    2470            0 :       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    2471              :         {
    2472            0 :           gphi *phi = as_a <gphi *> (gsi_stmt (gsi));
    2473            0 :           tree new_lhs, old_lhs = gimple_phi_result (phi);
    2474            0 :           new_lhs = replace_removed_params_ssa_names (old_lhs, phi);
    2475            0 :           if (new_lhs)
    2476              :             {
    2477            0 :               gimple_phi_set_result (phi, new_lhs);
    2478            0 :               release_ssa_name (old_lhs);
    2479              :             }
    2480              :         }
    2481              : 
    2482            0 :       gsi = gsi_start_bb (bb);
    2483            0 :       while (!gsi_end_p (gsi))
    2484              :         {
    2485            0 :           gimple *stmt = gsi_stmt (gsi);
    2486            0 :           gimple *stmt_copy = stmt;
    2487            0 :           gimple_seq extra_stmts = NULL;
    2488            0 :           bool modified = modify_gimple_stmt (&stmt, &extra_stmts, NULL);
    2489            0 :           if (stmt != stmt_copy)
    2490              :             {
    2491            0 :               gcc_checking_assert (modified);
    2492            0 :               gsi_replace (&gsi, stmt, false);
    2493              :             }
    2494            0 :           if (!gimple_seq_empty_p (extra_stmts))
    2495            0 :             gsi_insert_seq_before (&gsi, extra_stmts, GSI_SAME_STMT);
    2496              : 
    2497            0 :           def_operand_p defp;
    2498            0 :           ssa_op_iter iter;
    2499            0 :           FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF)
    2500              :             {
    2501            0 :               tree old_def = DEF_FROM_PTR (defp);
    2502            0 :               if (tree new_def = replace_removed_params_ssa_names (old_def,
    2503              :                                                                    stmt))
    2504              :                 {
    2505            0 :                   SET_DEF (defp, new_def);
    2506            0 :                   release_ssa_name (old_def);
    2507            0 :                   modified = true;
    2508              :                 }
    2509              :             }
    2510              : 
    2511            0 :           if (modified)
    2512              :             {
    2513            0 :               update_stmt (stmt);
    2514            0 :               if (maybe_clean_eh_stmt (stmt)
    2515            0 :                   && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
    2516              :                 cfg_changed = true;
    2517              :             }
    2518            0 :           gsi_next (&gsi);
    2519              :         }
    2520              :     }
    2521              : 
    2522            0 :   return cfg_changed;
    2523              : }
    2524              : 
    2525              : /* Call gimple_debug_bind_reset_value on all debug statements describing
    2526              :    gimple register parameters that are being removed or replaced.  */
    2527              : 
    2528              : void
    2529            0 : ipa_param_body_adjustments::reset_debug_stmts ()
    2530              : {
    2531            0 :   int i, len;
    2532            0 :   gimple_stmt_iterator *gsip = NULL, gsi;
    2533              : 
    2534            0 :   if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
    2535              :     {
    2536            0 :       gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
    2537            0 :       gsip = &gsi;
    2538              :     }
    2539            0 :   len = m_reset_debug_decls.length ();
    2540            0 :   for (i = 0; i < len; i++)
    2541              :     {
    2542            0 :       imm_use_iterator ui;
    2543            0 :       gimple *stmt;
    2544            0 :       gdebug *def_temp;
    2545            0 :       tree name, vexpr, copy = NULL_TREE;
    2546            0 :       use_operand_p use_p;
    2547            0 :       tree decl = m_reset_debug_decls[i];
    2548              : 
    2549            0 :       gcc_checking_assert (is_gimple_reg (decl));
    2550            0 :       name = ssa_default_def (cfun, decl);
    2551            0 :       vexpr = NULL;
    2552            0 :       if (name)
    2553            0 :         FOR_EACH_IMM_USE_STMT (stmt, ui, name)
    2554              :           {
    2555            0 :             if (gimple_clobber_p (stmt))
    2556              :               {
    2557            0 :                 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
    2558            0 :                 unlink_stmt_vdef (stmt);
    2559            0 :                 gsi_remove (&cgsi, true);
    2560            0 :                 release_defs (stmt);
    2561            0 :                 continue;
    2562            0 :               }
    2563              :             /* All other users must have been removed by function body
    2564              :                modification.  */
    2565            0 :             gcc_assert (is_gimple_debug (stmt));
    2566            0 :             if (vexpr == NULL && gsip != NULL)
    2567              :               {
    2568            0 :                 vexpr = build_debug_expr_decl (TREE_TYPE (name));
    2569              :                 /* FIXME: Is setting the mode really necessary? */
    2570            0 :                 SET_DECL_MODE (vexpr, DECL_MODE (decl));
    2571            0 :                 def_temp = gimple_build_debug_source_bind (vexpr, decl, NULL);
    2572            0 :                 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
    2573              :               }
    2574            0 :             if (vexpr)
    2575              :               {
    2576            0 :                 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
    2577            0 :                   SET_USE (use_p, vexpr);
    2578              :               }
    2579              :             else
    2580            0 :               gimple_debug_bind_reset_value (stmt);
    2581            0 :             update_stmt (stmt);
    2582            0 :           }
    2583              :       /* Create a VAR_DECL for debug info purposes.  */
    2584            0 :       if (!DECL_IGNORED_P (decl))
    2585              :         {
    2586            0 :           copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
    2587            0 :                              VAR_DECL, DECL_NAME (decl),
    2588            0 :                              TREE_TYPE (decl));
    2589            0 :           if (DECL_PT_UID_SET_P (decl))
    2590            0 :             SET_DECL_PT_UID (copy, DECL_PT_UID (decl));
    2591            0 :           TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
    2592            0 :           TREE_READONLY (copy) = TREE_READONLY (decl);
    2593            0 :           TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
    2594            0 :           DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
    2595            0 :           DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
    2596            0 :           DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
    2597            0 :           DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
    2598            0 :           DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
    2599            0 :           SET_DECL_RTL (copy, 0);
    2600            0 :           TREE_USED (copy) = 1;
    2601            0 :           DECL_CONTEXT (copy) = current_function_decl;
    2602            0 :           add_local_decl (cfun, copy);
    2603            0 :           DECL_CHAIN (copy)
    2604            0 :             = BLOCK_VARS (DECL_INITIAL (current_function_decl));
    2605            0 :           BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
    2606              :         }
    2607            0 :       if (gsip != NULL && copy && target_for_debug_bind (decl))
    2608              :         {
    2609            0 :           gcc_assert (TREE_CODE (decl) == PARM_DECL);
    2610            0 :           if (vexpr)
    2611            0 :             def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
    2612              :           else
    2613            0 :             def_temp = gimple_build_debug_source_bind (copy, decl,
    2614              :                                                        NULL);
    2615            0 :           gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
    2616              :         }
    2617              :     }
    2618            0 : }
    2619              : 
    2620              : /* Perform all necessary body changes to change signature, body and debug info
    2621              :    of fun according to adjustments passed at construction.  Return true if CFG
    2622              :    was changed in any way.  The main entry point for modification of standalone
    2623              :    functions that is not part of IPA clone materialization.  */
    2624              : 
    2625              : bool
    2626            0 : ipa_param_body_adjustments::perform_cfun_body_modifications ()
    2627              : {
    2628            0 :   bool cfg_changed;
    2629            0 :   modify_formal_parameters ();
    2630            0 :   cfg_changed = modify_cfun_body ();
    2631            0 :   reset_debug_stmts ();
    2632              : 
    2633            0 :   return cfg_changed;
    2634              : }
    2635              : 
    2636              : 
    2637              : /* If there are any initialization statements that need to be emitted into
    2638              :    the basic block BB right at ther start of the new function, do so.  */
    2639              : void
    2640       151001 : ipa_param_body_adjustments::append_init_stmts (basic_block bb)
    2641              : {
    2642       151001 :   gimple_stmt_iterator si = gsi_last_bb (bb);
    2643       152295 :   while (!m_split_agg_csts_inits.is_empty ())
    2644         1294 :     gsi_insert_after (&si, m_split_agg_csts_inits.pop (), GSI_NEW_STMT);
    2645       151001 : }
    2646              : 
    2647              : /* Deallocate summaries which otherwise stay alive until the end of
    2648              :    compilation.  */
    2649              : 
    2650              : void
    2651       256621 : ipa_edge_modifications_finalize ()
    2652              : {
    2653       256621 :   if (!ipa_edge_modifications)
    2654              :     return;
    2655         2884 :   delete ipa_edge_modifications;
    2656         2884 :   ipa_edge_modifications = NULL;
    2657              : }
    2658              : 
    2659              : /* Helper used to sort a vector of SSA_NAMES. */
    2660              : 
    2661              : static int
    2662        20523 : compare_ssa_versions (const void *va, const void *vb)
    2663              : {
    2664        20523 :   const_tree const a = *(const_tree const*)va;
    2665        20523 :   const_tree const b = *(const_tree const*)vb;
    2666              : 
    2667        20523 :   if (SSA_NAME_VERSION (a) < SSA_NAME_VERSION (b))
    2668              :     return -1;
    2669         8831 :   if (SSA_NAME_VERSION (a) > SSA_NAME_VERSION (b))
    2670         8831 :     return 1;
    2671              :   return 0;
    2672              : }
    2673              : 
    2674              : /* Call release_ssa_name on all elements in KILLED_SSAS in a defined order.  */
    2675              : 
    2676              : void
    2677      2057030 : ipa_release_ssas_in_hash (hash_set <tree> *killed_ssas)
    2678              : {
    2679      2057030 :   auto_vec<tree, 16> ssas_to_release;
    2680      2073529 :   for (tree sn : *killed_ssas)
    2681        16499 :     ssas_to_release.safe_push (sn);
    2682      2057030 :   ssas_to_release.qsort (compare_ssa_versions);
    2683      6187589 :   for (tree sn : ssas_to_release)
    2684        16499 :     release_ssa_name (sn);
    2685      2057030 : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.