LCOV - code coverage report
Current view: top level - gcc - ipa-sra.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.7 % 2198 2059
Test Date: 2024-04-20 14:03:02 Functions: 94.6 % 92 87
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Interprocedural scalar replacement of aggregates
       2                 :             :    Copyright (C) 2019-2024 Free Software Foundation, Inc.
       3                 :             :    Contributed by Martin Jambor <mjambor@suse.cz>
       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                 :             : /* IPA-SRA is an interprocedural pass that removes unused function return
      22                 :             :    values (turning functions returning a value which is never used into void
      23                 :             :    functions) and removes unused function parameters.  It can also replace an
      24                 :             :    aggregate parameter by a set of other parameters representing part of the
      25                 :             :    original, turning those passed by reference into new ones which pass the
      26                 :             :    value directly.
      27                 :             : 
      28                 :             :    The pass is a true IPA one, which means that it works in three stages in
      29                 :             :    order to be able to take advantage of LTO.  First, summaries about functions
      30                 :             :    and each calls are generated.  Function summaries (often called call graph
      31                 :             :    node summaries) contain mainly information about which parameters are
      32                 :             :    potential transformation candidates and which bits of candidates are
      33                 :             :    accessed.  We differentiate between accesses done as a part of a call
      34                 :             :    statement (which might be not necessary if the callee is also transformed)
      35                 :             :    and others (which are mandatory).  Call summaries (often called call graph
      36                 :             :    edge summaries) contain information about which function formal parameters
      37                 :             :    feed into which actual call arguments so that if two parameters are only
      38                 :             :    used in a sum which is then passed to another function which then however
      39                 :             :    does not use this parameter, all three parameters of the two functions can
      40                 :             :    be eliminated.  Edge summaries also have flags whether the return value is
      41                 :             :    used or if it is only returned in the caller too.  In LTO mode these
      42                 :             :    summaries are then streamed to the object file in the compilation phase and
      43                 :             :    streamed back in in the WPA analysis stage.
      44                 :             : 
      45                 :             :    The interprocedural analysis phase traverses the graph in topological order
      46                 :             :    in two sweeps, one in each direction.  First, from callees to callers for
      47                 :             :    parameter removal and splitting.  Each strongly-connected component is
      48                 :             :    processed iteratively until the situation in it stabilizes.  The pass from
      49                 :             :    callers to callees is then carried out to remove unused return values in a
      50                 :             :    very similar fashion.
      51                 :             : 
      52                 :             :    Because parameter manipulation has big implications for call redirection
      53                 :             :    which is done only after all call graph nodes materialize, the
      54                 :             :    transformation phase is not part of this patch but is carried out by the
      55                 :             :    clone materialization and edge redirection itself, see comments in
      56                 :             :    ipa-param-manipulation.h for more details.  */
      57                 :             : 
      58                 :             : 
      59                 :             : #include "config.h"
      60                 :             : #include "system.h"
      61                 :             : #include "coretypes.h"
      62                 :             : #include "backend.h"
      63                 :             : #include "tree.h"
      64                 :             : #include "gimple.h"
      65                 :             : #include "predict.h"
      66                 :             : #include "tree-pass.h"
      67                 :             : #include "ssa.h"
      68                 :             : #include "cgraph.h"
      69                 :             : #include "gimple-pretty-print.h"
      70                 :             : #include "alias.h"
      71                 :             : #include "tree-eh.h"
      72                 :             : #include "gimple-iterator.h"
      73                 :             : #include "gimple-walk.h"
      74                 :             : #include "tree-dfa.h"
      75                 :             : #include "tree-sra.h"
      76                 :             : #include "alloc-pool.h"
      77                 :             : #include "symbol-summary.h"
      78                 :             : #include "dbgcnt.h"
      79                 :             : #include "tree-inline.h"
      80                 :             : #include "ipa-utils.h"
      81                 :             : #include "builtins.h"
      82                 :             : #include "cfganal.h"
      83                 :             : #include "tree-streamer.h"
      84                 :             : #include "internal-fn.h"
      85                 :             : #include "symtab-clones.h"
      86                 :             : #include "attribs.h"
      87                 :             : #include "sreal.h"
      88                 :             : #include "ipa-cp.h"
      89                 :             : #include "ipa-prop.h"
      90                 :             : 
      91                 :             : static void ipa_sra_summarize_function (cgraph_node *);
      92                 :             : 
      93                 :             : /* Bits used to track size of an aggregate in bytes interprocedurally.  */
      94                 :             : #define ISRA_ARG_SIZE_LIMIT_BITS 16
      95                 :             : #define ISRA_ARG_SIZE_LIMIT (1 << ISRA_ARG_SIZE_LIMIT_BITS)
      96                 :             : /* How many parameters can feed into a call actual argument and still be
      97                 :             :    tracked.  */
      98                 :             : #define IPA_SRA_MAX_PARAM_FLOW_LEN 7
      99                 :             : 
     100                 :             : /* Structure describing accesses to a specific portion of an aggregate
     101                 :             :    parameter, as given by the offset and size.  Any smaller accesses that occur
     102                 :             :    within a function that fall within another access form a tree.  The pass
     103                 :             :    cannot analyze parameters with only partially overlapping accesses.  */
     104                 :             : 
     105                 :             : struct GTY(()) param_access
     106                 :             : {
     107                 :             :   /* Type that a potential replacement should have.  This field only has
     108                 :             :      meaning in the summary building and transformation phases, when it is
     109                 :             :      reconstructed from the body.  Must not be touched in IPA analysis
     110                 :             :      stage.  */
     111                 :             :   tree type;
     112                 :             : 
     113                 :             :   /* Alias reference type to be used in MEM_REFs when adjusting caller
     114                 :             :      arguments.  */
     115                 :             :   tree alias_ptr_type;
     116                 :             : 
     117                 :             :   /* Values returned by get_ref_base_and_extent but converted to bytes and
     118                 :             :      stored as unsigned ints.  */
     119                 :             :   unsigned unit_offset;
     120                 :             :   unsigned unit_size : ISRA_ARG_SIZE_LIMIT_BITS;
     121                 :             : 
     122                 :             :   /* Set once we are sure that the access will really end up in a potentially
     123                 :             :      transformed function - initially not set for portions of formal parameters
     124                 :             :      that are only used as actual function arguments passed to callees.  */
     125                 :             :   unsigned certain : 1;
     126                 :             :   /* Set if the access has reverse scalar storage order.  */
     127                 :             :   unsigned reverse : 1;
     128                 :             : };
     129                 :             : 
     130                 :             : /* This structure has the same purpose as the one above and additionally it
     131                 :             :    contains some fields that are only necessary in the summary generation
     132                 :             :    phase.  */
     133                 :             : 
     134                 :             : struct gensum_param_access
     135                 :             : {
     136                 :             :   /* Values returned by get_ref_base_and_extent.  */
     137                 :             :   HOST_WIDE_INT offset;
     138                 :             :   HOST_WIDE_INT size;
     139                 :             : 
     140                 :             :   /* if this access has any children (in terms of the definition above), this
     141                 :             :      points to the first one.  */
     142                 :             :   struct gensum_param_access *first_child;
     143                 :             :   /* In intraprocedural SRA, pointer to the next sibling in the access tree as
     144                 :             :      described above.  */
     145                 :             :   struct gensum_param_access *next_sibling;
     146                 :             : 
     147                 :             :   /* Type that a potential replacement should have.  This field only has
     148                 :             :      meaning in the summary building and transformation phases, when it is
     149                 :             :      reconstructed from the body.  Must not be touched in IPA analysis
     150                 :             :      stage.  */
     151                 :             :   tree type;
     152                 :             :   /* Alias reference type to be used in MEM_REFs when adjusting caller
     153                 :             :      arguments.  */
     154                 :             :   tree alias_ptr_type;
     155                 :             : 
     156                 :             :   /* Cumulative count of all loads. */
     157                 :             :   profile_count load_count;
     158                 :             :   /* Have there been writes to or reads from this exact location except for as
     159                 :             :      arguments to a function call that can be tracked.  */
     160                 :             :   bool nonarg;
     161                 :             : 
     162                 :             :   /* Set if the access has reverse scalar storage order.  */
     163                 :             :   bool reverse;
     164                 :             : };
     165                 :             : 
     166                 :             : /* Summary describing a parameter in the IPA stages.  */
     167                 :             : 
     168                 :             : struct GTY(()) isra_param_desc
     169                 :             : {
     170                 :             :   /* List of access representatives to the parameters, sorted according to
     171                 :             :      their offset.  */
     172                 :             :   vec <param_access *, va_gc> *accesses;
     173                 :             : 
     174                 :             :   /* Unit size limit of total size of all replacements.  */
     175                 :             :   unsigned param_size_limit : ISRA_ARG_SIZE_LIMIT_BITS;
     176                 :             :   /* Sum of unit sizes of all certain replacements.  */
     177                 :             :   unsigned size_reached : ISRA_ARG_SIZE_LIMIT_BITS;
     178                 :             :   /* Minimum offset that is known to be safe to dereference because of callers
     179                 :             :      pass pointers to DECLs of at least this size or because of dereferences in
     180                 :             :      callers.  */
     181                 :             :   unsigned safe_size : ISRA_ARG_SIZE_LIMIT_BITS;
     182                 :             : 
     183                 :             :   /* A parameter that is used only in call arguments and can be removed if all
     184                 :             :      concerned actual arguments are removed.  */
     185                 :             :   unsigned locally_unused : 1;
     186                 :             :   /* An aggregate that is a candidate for breaking up or complete removal.  */
     187                 :             :   unsigned split_candidate : 1;
     188                 :             :   /* Is this a parameter passing stuff by reference?  */
     189                 :             :   unsigned by_ref : 1;
     190                 :             :   /* If set, this parameter can only be a candidate for removal if the function
     191                 :             :      is going to loose its return value.  */
     192                 :             :   unsigned remove_only_when_retval_removed : 1;
     193                 :             :   /* If set, this parameter can only be a candidate for splitting if the
     194                 :             :      function is going to loose its return value.  Can only be meaningfully set
     195                 :             :      for by_ref parameters.  */
     196                 :             :   unsigned split_only_when_retval_removed : 1;
     197                 :             :   /* Parameter hint set during IPA analysis when there is a caller which does
     198                 :             :      not construct the argument just to pass it to calls.  Only meaningful for
     199                 :             :      by_ref parameters.  */
     200                 :             :   unsigned not_specially_constructed : 1;
     201                 :             :   /* Only meaningful for by_ref parameters.  If set, this parameter can only be
     202                 :             :      a split candidate if all callers pass pointers that are known to point to
     203                 :             :      a chunk of memory large enough to contain all accesses.  */
     204                 :             :   unsigned conditionally_dereferenceable : 1;
     205                 :             :   /* Set when safe_size has been updated from at least one caller.  */
     206                 :             :   unsigned safe_size_set : 1;
     207                 :             : };
     208                 :             : 
     209                 :             : /* Structure used when generating summaries that describes a parameter.  */
     210                 :             : 
     211                 :             : struct gensum_param_desc
     212                 :             : {
     213                 :             :   /* Roots of param_accesses.  */
     214                 :             :   gensum_param_access *accesses;
     215                 :             :   /* Number of accesses in the access tree rooted in field accesses.  */
     216                 :             :   unsigned access_count;
     217                 :             : 
     218                 :             :   /* If the below is non-zero, this is the number of uses as actual
     219                 :             :      arguments.  */
     220                 :             :   int call_uses;
     221                 :             :   /* Number of times this parameter has been directly passed to.  */
     222                 :             :   unsigned ptr_pt_count;
     223                 :             : 
     224                 :             :   /* Size limit of total size of all replacements.  */
     225                 :             :   unsigned param_size_limit;
     226                 :             :   /* Sum of sizes of nonarg accesses.  */
     227                 :             :   unsigned nonarg_acc_size;
     228                 :             : 
     229                 :             :   /* A parameter that is used only in call arguments and can be removed if all
     230                 :             :      concerned actual arguments are removed.  */
     231                 :             :   bool locally_unused;
     232                 :             :   /* An aggregate that is a candidate for breaking up or a pointer passing data
     233                 :             :      by reference that is a candidate for being converted to a set of
     234                 :             :      parameters passing those data by value.  */
     235                 :             :   bool split_candidate;
     236                 :             :   /* Is this a parameter passing stuff by reference (either a pointer or a
     237                 :             :      source language reference type)?  */
     238                 :             :   bool by_ref;
     239                 :             :   /* If this parameter passes stuff by reference, can it be safely dereferenced
     240                 :             :      without performing further checks (for example because it is a
     241                 :             :      REFERENCE_TYPE)?  */
     242                 :             :   bool safe_ref;
     243                 :             :   /* If set, this parameter can only be a candidate for removal if the function
     244                 :             :      is going to loose its return value.  */
     245                 :             :   bool remove_only_when_retval_removed;
     246                 :             :   /* If set, this parameter can only be a candidate for splitting if the
     247                 :             :      function is going to loose its return value.  Can only be meaningfully set
     248                 :             :      for by_ref parameters.  */
     249                 :             :   bool split_only_when_retval_removed;
     250                 :             :   /* Only meaningful for by_ref parameters.  If set, this parameter can only be
     251                 :             :      a split candidate if all callers pass pointers that are known to point to
     252                 :             :      a chunk of memory large enough to contain all accesses.  */
     253                 :             :   bool conditionally_dereferenceable;
     254                 :             : 
     255                 :             :   /* The number of this parameter as they are ordered in function decl.  */
     256                 :             :   int param_number;
     257                 :             :   /* For parameters passing data by reference, this is parameter index to
     258                 :             :      compute indices to bb_dereferences.  */
     259                 :             :   int deref_index;
     260                 :             : };
     261                 :             : 
     262                 :             : /* Properly deallocate accesses of DESC.  TODO: Since this data structure is
     263                 :             :    allocated in GC memory, this is not necessary and we can consider removing
     264                 :             :    the function.  */
     265                 :             : 
     266                 :             : static void
     267                 :     2557529 : free_param_decl_accesses (isra_param_desc *desc)
     268                 :             : {
     269                 :     2557529 :   unsigned len = vec_safe_length (desc->accesses);
     270                 :     3085670 :   for (unsigned i = 0; i < len; ++i)
     271                 :      528141 :     ggc_free ((*desc->accesses)[i]);
     272                 :     2557529 :   vec_free (desc->accesses);
     273                 :     2557529 : }
     274                 :             : 
     275                 :             : /* Class used to convey information about functions from the
     276                 :             :    intra-procedural analysis stage to inter-procedural one.  */
     277                 :             : 
     278                 :             : class GTY((for_user)) isra_func_summary
     279                 :             : {
     280                 :             : public:
     281                 :             :   /* initialize the object.  */
     282                 :             : 
     283                 :     1104335 :   isra_func_summary ()
     284                 :     1104335 :     : m_parameters (NULL), m_candidate (false), m_returns_value (false),
     285                 :     1104335 :     m_return_ignored (false), m_queued (false)
     286                 :             :   {}
     287                 :             : 
     288                 :             :   /* Destroy m_parameters.  */
     289                 :             : 
     290                 :             :   ~isra_func_summary ();
     291                 :             : 
     292                 :             :   /* Mark the function as not a candidate for any IPA-SRA transformation.
     293                 :             :      Return true if it was a candidate until now.  */
     294                 :             : 
     295                 :             :   bool zap ();
     296                 :             : 
     297                 :             :   /* Vector of parameter descriptors corresponding to the function being
     298                 :             :      analyzed.  */
     299                 :             :   vec<isra_param_desc, va_gc> *m_parameters;
     300                 :             : 
     301                 :             :   /* Whether the node is even a candidate for any IPA-SRA transformation at
     302                 :             :      all.  */
     303                 :             :   unsigned m_candidate : 1;
     304                 :             : 
     305                 :             :   /* Whether the original function returns any value.  */
     306                 :             :   unsigned m_returns_value : 1;
     307                 :             : 
     308                 :             :   /* Set to true if all call statements do not actually use the returned
     309                 :             :      value.  */
     310                 :             : 
     311                 :             :   unsigned m_return_ignored : 1;
     312                 :             : 
     313                 :             :   /* Whether the node is already queued in IPA SRA stack during processing of
     314                 :             :      call graphs SCCs.  */
     315                 :             : 
     316                 :             :   unsigned m_queued : 1;
     317                 :             : };
     318                 :             : 
     319                 :             : /* Deallocate the memory pointed to by isra_func_summary.  TODO: Since this
     320                 :             :    data structure is allocated in GC memory, this is not necessary and we can
     321                 :             :    consider removing the destructor.  */
     322                 :             : 
     323                 :     1104334 : isra_func_summary::~isra_func_summary ()
     324                 :             : {
     325                 :     1104334 :   unsigned len = vec_safe_length (m_parameters);
     326                 :     2209234 :   for (unsigned i = 0; i < len; ++i)
     327                 :     1104900 :     free_param_decl_accesses (&(*m_parameters)[i]);
     328                 :     1104334 :   vec_free (m_parameters);
     329                 :     1104334 : }
     330                 :             : 
     331                 :             : /* Mark the function as not a candidate for any IPA-SRA transformation.  Return
     332                 :             :    true if it was a candidate until now.  */
     333                 :             : 
     334                 :             : bool
     335                 :      629609 : isra_func_summary::zap ()
     336                 :             : {
     337                 :      629609 :   bool ret = m_candidate;
     338                 :      629609 :   m_candidate = false;
     339                 :             : 
     340                 :             :   /* TODO: see the destructor above.  */
     341                 :      629609 :   unsigned len = vec_safe_length (m_parameters);
     342                 :     2082238 :   for (unsigned i = 0; i < len; ++i)
     343                 :     1452629 :     free_param_decl_accesses (&(*m_parameters)[i]);
     344                 :      629609 :   vec_free (m_parameters);
     345                 :             : 
     346                 :      629609 :   return ret;
     347                 :             : }
     348                 :             : 
     349                 :             : /* Structure to describe which formal parameters feed into a particular actual
     350                 :             :    argument.  */
     351                 :             : 
     352                 :             : struct isra_param_flow
     353                 :             : {
     354                 :             :   /* Number of elements in array inputs that contain valid data.  */
     355                 :             :   char length;
     356                 :             :   /* Indices of formal parameters that feed into the described actual argument.
     357                 :             :      If aggregate_pass_through or pointer_pass_through below are true, it must
     358                 :             :      contain exactly one element which is passed through from a formal
     359                 :             :      parameter if the given number.  Otherwise, the array contains indices of
     360                 :             :      callee's formal parameters which are used to calculate value of this
     361                 :             :      actual argument. */
     362                 :             :   unsigned char inputs[IPA_SRA_MAX_PARAM_FLOW_LEN];
     363                 :             : 
     364                 :             :   /* Offset within the formal parameter.  */
     365                 :             :   unsigned unit_offset;
     366                 :             :   /* When aggregate_pass_through is set, this is the size of the portion of an
     367                 :             :      aggregate formal parameter that is being passed.  Otherwise, this is size
     368                 :             :      of pointed to memory that is known to be valid be dereferenced.  */
     369                 :             :   unsigned unit_size : ISRA_ARG_SIZE_LIMIT_BITS;
     370                 :             : 
     371                 :             :   /* True when the value of this actual argument is a portion of a formal
     372                 :             :      parameter.  */
     373                 :             :   unsigned aggregate_pass_through : 1;
     374                 :             :   /* True when the value of this actual copy is a verbatim pass through of an
     375                 :             :      obtained pointer.  */
     376                 :             :   unsigned pointer_pass_through : 1;
     377                 :             :   /* True when it is safe to copy access candidates here from the callee, which
     378                 :             :      would mean introducing dereferences into callers of the caller.  */
     379                 :             :   unsigned safe_to_import_accesses : 1;
     380                 :             :   /* True when the passed value is an address of a structure that has been
     381                 :             :      constructed in the caller just to be passed by reference to functions
     382                 :             :      (i.e. is never read).  */
     383                 :             :   unsigned constructed_for_calls : 1;
     384                 :             : };
     385                 :             : 
     386                 :             : /* Structure used to convey information about calls from the intra-procedural
     387                 :             :    analysis stage to inter-procedural one.  */
     388                 :             : 
     389                 :     5514532 : class isra_call_summary
     390                 :             : {
     391                 :             : public:
     392                 :     5514532 :   isra_call_summary ()
     393                 :           0 :     : m_arg_flow (), m_return_ignored (false), m_return_returned (false),
     394                 :           0 :       m_bit_aligned_arg (false), m_before_any_store (false)
     395                 :             :   {}
     396                 :             : 
     397                 :             :   void init_inputs (unsigned arg_count);
     398                 :             :   void dump (FILE *f);
     399                 :             : 
     400                 :             :   /* Information about what formal parameters of the caller are used to compute
     401                 :             :      individual actual arguments of this call.  */
     402                 :             :   auto_vec <isra_param_flow> m_arg_flow;
     403                 :             : 
     404                 :             :   /* Set to true if the call statement does not have a LHS.  */
     405                 :             :   unsigned m_return_ignored : 1;
     406                 :             : 
     407                 :             :   /* Set to true if the LHS of call statement is only used to construct the
     408                 :             :      return value of the caller.  */
     409                 :             :   unsigned m_return_returned : 1;
     410                 :             : 
     411                 :             :   /* Set when any of the call arguments are not byte-aligned.  */
     412                 :             :   unsigned m_bit_aligned_arg : 1;
     413                 :             : 
     414                 :             :   /* Set to true if the call happend before any (other) store to memory in the
     415                 :             :      caller.  */
     416                 :             :   unsigned m_before_any_store : 1;
     417                 :             : };
     418                 :             : 
     419                 :             : /* Class to manage function summaries.  */
     420                 :             : 
     421                 :             : class GTY((user)) ipa_sra_function_summaries
     422                 :             :   : public function_summary <isra_func_summary *>
     423                 :             : {
     424                 :             : public:
     425                 :      128396 :   ipa_sra_function_summaries (symbol_table *table, bool ggc):
     426                 :      256792 :     function_summary<isra_func_summary *> (table, ggc) { }
     427                 :             : 
     428                 :             :   void duplicate (cgraph_node *, cgraph_node *,
     429                 :             :                   isra_func_summary *old_sum,
     430                 :             :                   isra_func_summary *new_sum) final override;
     431                 :             :   void insert (cgraph_node *, isra_func_summary *) final override;
     432                 :             : };
     433                 :             : 
     434                 :             : /* Hook that is called by summary when a node is duplicated.  */
     435                 :             : 
     436                 :             : void
     437                 :      110624 : ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *,
     438                 :             :                                        isra_func_summary *old_sum,
     439                 :             :                                        isra_func_summary *new_sum)
     440                 :             : {
     441                 :             :   /* TODO: Somehow stop copying when ISRA is doing the cloning, it is
     442                 :             :      useless.  */
     443                 :      110624 :   new_sum->m_candidate  = old_sum->m_candidate;
     444                 :      110624 :   new_sum->m_returns_value = old_sum->m_returns_value;
     445                 :      110624 :   new_sum->m_return_ignored = old_sum->m_return_ignored;
     446                 :      110624 :   gcc_assert (!old_sum->m_queued);
     447                 :      110624 :   new_sum->m_queued = false;
     448                 :             : 
     449                 :      110624 :   unsigned param_count = vec_safe_length (old_sum->m_parameters);
     450                 :      109924 :   if (!param_count)
     451                 :             :     return;
     452                 :      109924 :   vec_safe_reserve_exact (new_sum->m_parameters, param_count);
     453                 :      109924 :   new_sum->m_parameters->quick_grow_cleared (param_count);
     454                 :      415102 :   for (unsigned i = 0; i < param_count; i++)
     455                 :             :     {
     456                 :      305178 :       isra_param_desc *s = &(*old_sum->m_parameters)[i];
     457                 :      305178 :       isra_param_desc *d = &(*new_sum->m_parameters)[i];
     458                 :             : 
     459                 :      305178 :       d->param_size_limit = s->param_size_limit;
     460                 :      305178 :       d->size_reached = s->size_reached;
     461                 :      305178 :       d->safe_size = s->safe_size;
     462                 :      305178 :       d->locally_unused = s->locally_unused;
     463                 :      305178 :       d->split_candidate = s->split_candidate;
     464                 :      305178 :       d->by_ref = s->by_ref;
     465                 :      305178 :       d->remove_only_when_retval_removed = s->remove_only_when_retval_removed;
     466                 :      305178 :       d->split_only_when_retval_removed = s->split_only_when_retval_removed;
     467                 :      305178 :       d->not_specially_constructed = s->not_specially_constructed;
     468                 :      305178 :       d->conditionally_dereferenceable = s->conditionally_dereferenceable;
     469                 :      305178 :       d->safe_size_set = s->safe_size_set;
     470                 :             : 
     471                 :      305178 :       unsigned acc_count = vec_safe_length (s->accesses);
     472                 :      305178 :       vec_safe_reserve_exact (d->accesses, acc_count);
     473                 :      431136 :       for (unsigned j = 0; j < acc_count; j++)
     474                 :             :         {
     475                 :      125958 :           param_access *from = (*s->accesses)[j];
     476                 :      125958 :           param_access *to = ggc_cleared_alloc<param_access> ();
     477                 :      125958 :           to->type = from->type;
     478                 :      125958 :           to->alias_ptr_type = from->alias_ptr_type;
     479                 :      125958 :           to->unit_offset = from->unit_offset;
     480                 :      125958 :           to->unit_size = from->unit_size;
     481                 :      125958 :           to->certain = from->certain;
     482                 :      125958 :           to->reverse = from->reverse;
     483                 :      125958 :           d->accesses->quick_push (to);
     484                 :             :         }
     485                 :             :     }
     486                 :             : }
     487                 :             : 
     488                 :             : /* Pointer to the pass function summary holder.  */
     489                 :             : 
     490                 :             : static GTY(()) ipa_sra_function_summaries *func_sums;
     491                 :             : 
     492                 :             : /* Hook that is called by summary when new node appears.  */
     493                 :             : 
     494                 :             : void
     495                 :       17088 : ipa_sra_function_summaries::insert (cgraph_node *node, isra_func_summary *)
     496                 :             : {
     497                 :       17088 :   if (opt_for_fn (node->decl, flag_ipa_sra))
     498                 :             :     {
     499                 :       17088 :       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
     500                 :       17088 :       ipa_sra_summarize_function (node);
     501                 :       17088 :       pop_cfun ();
     502                 :             :     }
     503                 :             :   else
     504                 :           0 :     func_sums->remove (node);
     505                 :       17088 : }
     506                 :             : 
     507                 :             : /* Class to manage call summaries.  */
     508                 :             : 
     509                 :             : class ipa_sra_call_summaries: public call_summary <isra_call_summary *>
     510                 :             : {
     511                 :             : public:
     512                 :      128396 :   ipa_sra_call_summaries (symbol_table *table):
     513                 :      256792 :     call_summary<isra_call_summary *> (table) { }
     514                 :             : 
     515                 :             :   /* Duplicate info when an edge is cloned.  */
     516                 :             :   void duplicate (cgraph_edge *, cgraph_edge *,
     517                 :             :                   isra_call_summary *old_sum,
     518                 :             :                   isra_call_summary *new_sum) final override;
     519                 :             : };
     520                 :             : 
     521                 :             : static ipa_sra_call_summaries *call_sums;
     522                 :             : 
     523                 :             : 
     524                 :             : /* Initialize m_arg_flow of a particular instance of isra_call_summary.
     525                 :             :    ARG_COUNT is the number of actual arguments passed.  */
     526                 :             : 
     527                 :             : void
     528                 :     6472314 : isra_call_summary::init_inputs (unsigned arg_count)
     529                 :             : {
     530                 :     6472314 :   if (arg_count == 0)
     531                 :             :     {
     532                 :      270386 :       gcc_checking_assert (m_arg_flow.length () == 0);
     533                 :             :       return;
     534                 :             :     }
     535                 :     6201928 :   if (m_arg_flow.length () == 0)
     536                 :             :     {
     537                 :     3051021 :       m_arg_flow.reserve_exact (arg_count);
     538                 :     3051021 :       m_arg_flow.quick_grow_cleared (arg_count);
     539                 :             :     }
     540                 :             :   else
     541                 :     3150907 :     gcc_checking_assert (arg_count == m_arg_flow.length ());
     542                 :             : }
     543                 :             : 
     544                 :             : /* Dump all information in call summary to F.  */
     545                 :             : 
     546                 :             : void
     547                 :         192 : isra_call_summary::dump (FILE *f)
     548                 :             : {
     549                 :         192 :   if (m_return_ignored)
     550                 :         138 :     fprintf (f, "    return value ignored\n");
     551                 :         192 :   if (m_return_returned)
     552                 :          39 :     fprintf (f, "    return value used only to compute caller return value\n");
     553                 :         192 :   if (m_before_any_store)
     554                 :          18 :     fprintf (f, "    happens before any store to memory\n");
     555                 :         786 :   for (unsigned i = 0; i < m_arg_flow.length (); i++)
     556                 :             :     {
     557                 :         238 :       fprintf (f, "    Parameter %u:\n", i);
     558                 :         238 :       isra_param_flow *ipf = &m_arg_flow[i];
     559                 :             : 
     560                 :         238 :       if (ipf->length)
     561                 :             :         {
     562                 :         164 :           bool first = true;
     563                 :         164 :           fprintf (f, "      Scalar param sources: ");
     564                 :         331 :           for (int j = 0; j < ipf->length; j++)
     565                 :             :             {
     566                 :         167 :               if (!first)
     567                 :           3 :                 fprintf (f, ", ");
     568                 :             :               else
     569                 :             :                 first = false;
     570                 :         167 :               fprintf (f, "%i", (int) ipf->inputs[j]);
     571                 :             :             }
     572                 :         164 :           fprintf (f, "\n");
     573                 :             :         }
     574                 :         238 :       if (ipf->aggregate_pass_through)
     575                 :          12 :         fprintf (f, "      Aggregate pass through from the param given above, "
     576                 :             :                  "unit offset: %u , unit size: %u\n",
     577                 :          12 :                  ipf->unit_offset, ipf->unit_size);
     578                 :         226 :       else if (ipf->unit_size > 0)
     579                 :          53 :         fprintf (f, "      Known dereferenceable size: %u\n", ipf->unit_size);
     580                 :         238 :       if (ipf->pointer_pass_through)
     581                 :          20 :         fprintf (f, "      Pointer pass through from the param given above, "
     582                 :          20 :                  "safe_to_import_accesses: %u\n", ipf->safe_to_import_accesses);
     583                 :         238 :       if (ipf->constructed_for_calls)
     584                 :          28 :         fprintf (f, "      Variable constructed just to be passed to "
     585                 :             :                  "calls.\n");
     586                 :             :     }
     587                 :         192 : }
     588                 :             : 
     589                 :             : /* Duplicate edge summary when an edge is cloned.  */
     590                 :             : 
     591                 :             : void
     592                 :      537887 : ipa_sra_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
     593                 :             :                                    isra_call_summary *old_sum,
     594                 :             :                                    isra_call_summary *new_sum)
     595                 :             : {
     596                 :      537887 :   unsigned arg_count = old_sum->m_arg_flow.length ();
     597                 :      537887 :   new_sum->init_inputs (arg_count);
     598                 :     1647249 :   for (unsigned i = 0; i < arg_count; i++)
     599                 :     1109362 :     new_sum->m_arg_flow[i] = old_sum->m_arg_flow[i];
     600                 :             : 
     601                 :      537887 :   new_sum->m_return_ignored = old_sum->m_return_ignored;
     602                 :      537887 :   new_sum->m_return_returned = old_sum->m_return_returned;
     603                 :      537887 :   new_sum->m_bit_aligned_arg = old_sum->m_bit_aligned_arg;
     604                 :      537887 :   new_sum->m_before_any_store = old_sum->m_before_any_store;
     605                 :      537887 : }
     606                 :             : 
     607                 :             : 
     608                 :             : /* With all GTY stuff done, we can move to anonymous namespace.  */
     609                 :             : namespace {
     610                 :             : /* Quick mapping from a decl to its param descriptor.  */
     611                 :             : 
     612                 :             : hash_map<tree, gensum_param_desc *> *decl2desc;
     613                 :             : 
     614                 :             : /* All local DECLs ever loaded from of and of those that have their address
     615                 :             :    assigned to a variable.  */
     616                 :             : 
     617                 :             : hash_set <tree> *loaded_decls;
     618                 :             : 
     619                 :             : /* Countdown of allowed Alias Analysis steps during summary building.  */
     620                 :             : 
     621                 :             : int aa_walking_limit;
     622                 :             : 
     623                 :             : /* This is a table in which for each basic block and parameter there is a
     624                 :             :    distance (offset + size) in that parameter which is dereferenced and
     625                 :             :    accessed in that BB.  */
     626                 :             : HOST_WIDE_INT *bb_dereferences = NULL;
     627                 :             : /* How many by-reference parameters there are in the current function.  */
     628                 :             : int unsafe_by_ref_count;
     629                 :             : 
     630                 :             : /* Bitmap of BBs that can cause the function to "stop" progressing by
     631                 :             :    returning, throwing externally, looping infinitely or calling a function
     632                 :             :    which might abort etc.. */
     633                 :             : bitmap final_bbs;
     634                 :             : 
     635                 :             : /* Obstack to allocate various small structures required only when generating
     636                 :             :    summary for a function.  */
     637                 :             : struct obstack gensum_obstack;
     638                 :             : 
     639                 :             : /* Return false the function is apparently unsuitable for IPA-SRA based on it's
     640                 :             :    attributes, return true otherwise.  NODE is the cgraph node of the current
     641                 :             :    function.  */
     642                 :             : 
     643                 :             : static bool
     644                 :     1183850 : ipa_sra_preliminary_function_checks (cgraph_node *node)
     645                 :             : {
     646                 :     1183850 :   if (!node->can_change_signature)
     647                 :             :     {
     648                 :       34383 :       if (dump_file)
     649                 :           0 :         fprintf (dump_file, "Function cannot change signature.\n");
     650                 :       34383 :       return false;
     651                 :             :     }
     652                 :             : 
     653                 :     1149467 :   if (!tree_versionable_function_p (node->decl))
     654                 :             :     {
     655                 :      114326 :       if (dump_file)
     656                 :           7 :         fprintf (dump_file, "Function is not versionable.\n");
     657                 :      114326 :       return false;
     658                 :             :     }
     659                 :             : 
     660                 :     1035141 :   if (!opt_for_fn (node->decl, optimize)
     661                 :     1035141 :       || !opt_for_fn (node->decl, flag_ipa_sra))
     662                 :             :     {
     663                 :         118 :       if (dump_file)
     664                 :           0 :         fprintf (dump_file, "Not optimizing or IPA-SRA turned off for this "
     665                 :             :                  "function.\n");
     666                 :         118 :       return false;
     667                 :             :     }
     668                 :             : 
     669                 :     1035023 :   if (DECL_VIRTUAL_P (node->decl))
     670                 :             :     {
     671                 :       31387 :       if (dump_file)
     672                 :           0 :         fprintf (dump_file, "Function is a virtual method.\n");
     673                 :       31387 :       return false;
     674                 :             :     }
     675                 :             : 
     676                 :     1003636 :   struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
     677                 :     1003636 :   if (fun->stdarg)
     678                 :             :     {
     679                 :         122 :       if (dump_file)
     680                 :           0 :         fprintf (dump_file, "Function uses stdarg. \n");
     681                 :         122 :       return false;
     682                 :             :     }
     683                 :             : 
     684                 :     1003514 :   if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
     685                 :             :     {
     686                 :       43942 :       if (dump_file)
     687                 :           0 :         fprintf (dump_file, "Always inline function will be inlined "
     688                 :             :                  "anyway. \n");
     689                 :       43942 :       return false;
     690                 :             :     }
     691                 :             : 
     692                 :             :   return true;
     693                 :             : }
     694                 :             : 
     695                 :             : /* Print access tree starting at ACCESS to F.  */
     696                 :             : 
     697                 :             : static void
     698                 :          70 : dump_gensum_access (FILE *f, gensum_param_access *access, unsigned indent)
     699                 :             : {
     700                 :          70 :   fprintf (f, "  ");
     701                 :         214 :   for (unsigned i = 0; i < indent; i++)
     702                 :         144 :     fprintf (f, " ");
     703                 :          70 :   fprintf (f, "    * Access to offset: " HOST_WIDE_INT_PRINT_DEC,
     704                 :             :            access->offset);
     705                 :          70 :   fprintf (f, ", size: " HOST_WIDE_INT_PRINT_DEC, access->size);
     706                 :          70 :   fprintf (f, ", type: ");
     707                 :          70 :   print_generic_expr (f, access->type);
     708                 :          70 :   fprintf (f, ", alias_ptr_type: ");
     709                 :          70 :   print_generic_expr (f, access->alias_ptr_type);
     710                 :          70 :   fprintf (f, ", load_count: ");
     711                 :          70 :   access->load_count.dump (f);
     712                 :          70 :   fprintf (f, ", nonarg: %u, reverse: %u\n", access->nonarg, access->reverse);
     713                 :          70 :   for (gensum_param_access *ch = access->first_child;
     714                 :          72 :        ch;
     715                 :           2 :        ch = ch->next_sibling)
     716                 :           2 :     dump_gensum_access (f, ch, indent + 2);
     717                 :          70 : }
     718                 :             : 
     719                 :             : 
     720                 :             : /* Print access tree starting at ACCESS to F.  */
     721                 :             : 
     722                 :             : static void
     723                 :         154 : dump_isra_access (FILE *f, param_access *access)
     724                 :             : {
     725                 :         154 :   fprintf (f, "    * Access to unit offset: %u", access->unit_offset);
     726                 :         154 :   fprintf (f, ", unit size: %u", access->unit_size);
     727                 :         154 :   fprintf (f, ", type: ");
     728                 :         154 :   print_generic_expr (f, access->type);
     729                 :         154 :   fprintf (f, ", alias_ptr_type: ");
     730                 :         154 :   print_generic_expr (f, access->alias_ptr_type);
     731                 :         154 :   if (access->certain)
     732                 :         132 :     fprintf (f, ", certain");
     733                 :             :   else
     734                 :          22 :     fprintf (f, ", not certain");
     735                 :         154 :   if (access->reverse)
     736                 :           0 :     fprintf (f, ", reverse");
     737                 :         154 :   fprintf (f, "\n");
     738                 :         154 : }
     739                 :             : 
     740                 :             : /* Dump access tree starting at ACCESS to stderr.  */
     741                 :             : 
     742                 :             : DEBUG_FUNCTION void
     743                 :           0 : debug_isra_access (param_access *access)
     744                 :             : {
     745                 :           0 :   dump_isra_access (stderr, access);
     746                 :           0 : }
     747                 :             : 
     748                 :             : /* Dump DESC to F.  */
     749                 :             : 
     750                 :             : static void
     751                 :         350 : dump_gensum_param_descriptor (FILE *f, gensum_param_desc *desc)
     752                 :             : {
     753                 :         350 :   if (desc->locally_unused)
     754                 :         176 :     fprintf (f, "    unused with %i call_uses%s\n", desc->call_uses,
     755                 :         176 :              desc->remove_only_when_retval_removed ?
     756                 :             :              " remove_only_when_retval_removed" : "");
     757                 :         350 :   if (!desc->split_candidate)
     758                 :             :     {
     759                 :         258 :       fprintf (f, "    not a candidate\n");
     760                 :         258 :       return;
     761                 :             :     }
     762                 :          92 :   if (desc->by_ref)
     763                 :          77 :     fprintf (f, "    %s%s%s by_ref with %u pass throughs\n",
     764                 :          77 :              desc->safe_ref ? "safe" : "unsafe",
     765                 :          77 :              desc->conditionally_dereferenceable
     766                 :             :              ? " conditionally_dereferenceable" : "",
     767                 :          77 :              desc->split_only_when_retval_removed
     768                 :             :              ? " split_only_when_retval_removed" : "",
     769                 :             :              desc->ptr_pt_count);
     770                 :             : 
     771                 :         160 :   for (gensum_param_access *acc = desc->accesses; acc; acc = acc->next_sibling)
     772                 :          68 :     dump_gensum_access (f, acc, 2);
     773                 :             : }
     774                 :             : 
     775                 :             : /* Dump all parameter descriptors in IFS, assuming it describes FNDECL, to
     776                 :             :    F.  */
     777                 :             : 
     778                 :             : static void
     779                 :         143 : dump_gensum_param_descriptors (FILE *f, tree fndecl,
     780                 :             :                                vec<gensum_param_desc> *param_descriptions)
     781                 :             : {
     782                 :         143 :   tree parm = DECL_ARGUMENTS (fndecl);
     783                 :         143 :   for (unsigned i = 0;
     784                 :         986 :        i < param_descriptions->length ();
     785                 :         350 :        ++i, parm = DECL_CHAIN (parm))
     786                 :             :     {
     787                 :         350 :       fprintf (f, "  Descriptor for parameter %i ", i);
     788                 :         350 :       print_generic_expr (f, parm, TDF_UID);
     789                 :         350 :       fprintf (f, "\n");
     790                 :         350 :       dump_gensum_param_descriptor (f, &(*param_descriptions)[i]);
     791                 :             :     }
     792                 :         143 : }
     793                 :             : 
     794                 :             : 
     795                 :             : /* Dump DESC to F.  If HINTS is true, also dump IPA-analysis computed
     796                 :             :    hints.  */
     797                 :             : 
     798                 :             : static void
     799                 :         677 : dump_isra_param_descriptor (FILE *f, isra_param_desc *desc, bool hints)
     800                 :             : {
     801                 :         677 :   if (desc->locally_unused)
     802                 :             :     {
     803                 :         350 :       fprintf (f, "    (locally) unused\n");
     804                 :             :     }
     805                 :         677 :   if (!desc->split_candidate)
     806                 :             :     {
     807                 :         495 :       fprintf (f, "    not a candidate for splitting");
     808                 :         495 :       if (hints && desc->by_ref && desc->safe_size_set)
     809                 :           9 :         fprintf (f, ", safe_size: %u", (unsigned) desc->safe_size);
     810                 :         495 :       fprintf (f, "\n");
     811                 :         495 :       return;
     812                 :             :     }
     813                 :         364 :   fprintf (f, "    param_size_limit: %u, size_reached: %u%s",
     814                 :         182 :            desc->param_size_limit, desc->size_reached,
     815                 :         182 :            desc->by_ref ? ", by_ref" : "");
     816                 :         182 :   if (desc->remove_only_when_retval_removed)
     817                 :          12 :     fprintf (f, ", remove_only_when_retval_removed");
     818                 :         182 :   if (desc->split_only_when_retval_removed)
     819                 :           4 :     fprintf (f, ", split_only_when_retval_removed");
     820                 :         182 :   if (desc->by_ref && desc->conditionally_dereferenceable)
     821                 :          33 :     fprintf (f, ", conditionally_dereferenceable");
     822                 :         182 :   if (hints)
     823                 :             :     {
     824                 :           6 :       if (desc->by_ref && !desc->not_specially_constructed)
     825                 :           3 :         fprintf (f, ", args_specially_constructed");
     826                 :           6 :       if (desc->by_ref && desc->safe_size_set)
     827                 :           5 :         fprintf (f, ", safe_size: %u", (unsigned) desc->safe_size);
     828                 :             :     }
     829                 :         182 :   fprintf (f, "\n");
     830                 :             : 
     831                 :         604 :   for (unsigned i = 0; i < vec_safe_length (desc->accesses); ++i)
     832                 :             :     {
     833                 :         154 :       param_access *access = (*desc->accesses)[i];
     834                 :         154 :       dump_isra_access (f, access);
     835                 :             :     }
     836                 :             : }
     837                 :             : 
     838                 :             : /* Dump all parameter descriptors in IFS, assuming it describes FNDECL, to F.
     839                 :             :    If HINTS is true, also dump IPA-analysis computed hints.  */
     840                 :             : 
     841                 :             : static void
     842                 :         143 : dump_isra_param_descriptors (FILE *f, tree fndecl, isra_func_summary *ifs,
     843                 :             :                              bool hints)
     844                 :             : {
     845                 :         143 :   tree parm = DECL_ARGUMENTS (fndecl);
     846                 :         143 :   if (!ifs->m_parameters)
     847                 :             :     {
     848                 :           0 :       fprintf (f, "  parameter descriptors not available\n");
     849                 :           0 :       return;
     850                 :             :     }
     851                 :             : 
     852                 :             :   for (unsigned i = 0;
     853                 :         493 :        i < ifs->m_parameters->length ();
     854                 :         350 :        ++i, parm = DECL_CHAIN (parm))
     855                 :             :     {
     856                 :         350 :       fprintf (f, "  Descriptor for parameter %i ", i);
     857                 :         350 :       print_generic_expr (f, parm, TDF_UID);
     858                 :         350 :       fprintf (f, "\n");
     859                 :         350 :       dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i], hints);
     860                 :             :     }
     861                 :             : }
     862                 :             : 
     863                 :             : /* Add SRC to inputs of PARAM_FLOW, unless it would exceed storage.  If the
     864                 :             :    function fails return false, otherwise return true.  SRC must fit into an
     865                 :             :    unsigned char.  Used for purposes of transitive unused parameter
     866                 :             :    removal.  */
     867                 :             : 
     868                 :             : static bool
     869                 :     1270977 : add_src_to_param_flow (isra_param_flow *param_flow, int src)
     870                 :             : {
     871                 :     1270977 :   gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
     872                 :     1270977 :   if (param_flow->length == IPA_SRA_MAX_PARAM_FLOW_LEN)
     873                 :             :     return false;
     874                 :             : 
     875                 :     1270974 :   param_flow->inputs[(int) param_flow->length] = src;
     876                 :     1270974 :   param_flow->length++;
     877                 :     1270974 :   return true;
     878                 :             : }
     879                 :             : 
     880                 :             : /* Add a SRC to the inputs of PARAM_FLOW unless it is already there and assert
     881                 :             :    it is the only input.  Used for purposes of transitive parameter
     882                 :             :    splitting.  */
     883                 :             : 
     884                 :             : static void
     885                 :      768825 : set_single_param_flow_source (isra_param_flow *param_flow, int src)
     886                 :             : {
     887                 :      768825 :   gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
     888                 :      768825 :   if (param_flow->length == 0)
     889                 :             :     {
     890                 :      110724 :       param_flow->inputs[0] = src;
     891                 :      110724 :       param_flow->length = 1;
     892                 :             :     }
     893                 :      658101 :   else if (param_flow->length == 1)
     894                 :      658101 :     gcc_assert (param_flow->inputs[0] == src);
     895                 :             :   else
     896                 :           0 :     gcc_unreachable ();
     897                 :      768825 : }
     898                 :             : 
     899                 :             : /* Assert that there is only a single value in PARAM_FLOW's inputs and return
     900                 :             :    it.  */
     901                 :             : 
     902                 :             : static unsigned
     903                 :     1277023 : get_single_param_flow_source (const isra_param_flow *param_flow)
     904                 :             : {
     905                 :     1277023 :   gcc_assert (param_flow->length == 1);
     906                 :     1277023 :   return param_flow->inputs[0];
     907                 :             : }
     908                 :             : 
     909                 :             : /* Inspect all uses of NAME and simple arithmetic calculations involving NAME
     910                 :             :    in FUN represented with NODE and return a negative number if any of them is
     911                 :             :    used for something else than either an actual call argument, simple return,
     912                 :             :    simple arithmetic operation or debug statement.  If there are no such uses,
     913                 :             :    return the number of actual arguments that this parameter eventually feeds
     914                 :             :    to (or zero if there is none).  If there are any simple return uses, set
     915                 :             :    DESC->remove_only_when_retval_removed.  For any such parameter, mark
     916                 :             :    PARM_NUM as one of its sources.  ANALYZED is a bitmap that tracks which SSA
     917                 :             :    names we have already started investigating.  */
     918                 :             : 
     919                 :             : static int
     920                 :     3148065 : isra_track_scalar_value_uses (function *fun, cgraph_node *node, tree name,
     921                 :             :                               int parm_num, bitmap analyzed,
     922                 :             :                               gensum_param_desc *desc)
     923                 :             : {
     924                 :     3148065 :   int res = 0;
     925                 :     3148065 :   imm_use_iterator imm_iter;
     926                 :     3148065 :   gimple *stmt;
     927                 :             : 
     928                 :     6498733 :   FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
     929                 :             :     {
     930                 :     4795452 :       if (is_gimple_debug (stmt)
     931                 :     4795452 :           || gimple_clobber_p (stmt))
     932                 :      749810 :         continue;
     933                 :             : 
     934                 :             :       /* TODO: We could handle at least const builtin functions like arithmetic
     935                 :             :          operations below.  */
     936                 :     4045642 :       if (is_gimple_call (stmt))
     937                 :             :         {
     938                 :     1280768 :           int all_uses = 0;
     939                 :     1280768 :           use_operand_p use_p;
     940                 :     2575294 :           FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
     941                 :     1294526 :             all_uses++;
     942                 :             : 
     943                 :     1280768 :           gcall *call = as_a <gcall *> (stmt);
     944                 :     1280768 :           unsigned arg_count;
     945                 :     1280768 :           if (gimple_call_internal_p (call)
     946                 :     1280768 :               || (arg_count = gimple_call_num_args (call)) == 0)
     947                 :             :             {
     948                 :             :               res = -1;
     949                 :             :               break;
     950                 :             :             }
     951                 :             : 
     952                 :     1276837 :           cgraph_edge *cs = node->get_edge (stmt);
     953                 :     1276837 :           gcc_checking_assert (cs);
     954                 :     1276837 :           isra_call_summary *csum = call_sums->get_create (cs);
     955                 :     1276837 :           csum->init_inputs (arg_count);
     956                 :             : 
     957                 :     1276837 :           int simple_uses = 0;
     958                 :     5877424 :           for (unsigned i = 0; i < arg_count; i++)
     959                 :     4600590 :             if (gimple_call_arg (call, i) == name)
     960                 :             :               {
     961                 :     1270977 :                 if (!add_src_to_param_flow (&csum->m_arg_flow[i], parm_num))
     962                 :             :                   {
     963                 :             :                     simple_uses = -1;
     964                 :             :                     break;
     965                 :             :                   }
     966                 :     1270974 :                 simple_uses++;
     967                 :             :               }
     968                 :             : 
     969                 :     1276837 :           if (simple_uses < 0
     970                 :     1276837 :               || all_uses != simple_uses)
     971                 :             :             {
     972                 :             :               res = -1;
     973                 :             :               break;
     974                 :             :             }
     975                 :     1257587 :           res += all_uses;
     976                 :             :         }
     977                 :     2764874 :       else if (!stmt_unremovable_because_of_non_call_eh_p (fun, stmt)
     978                 :     2764874 :                && ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
     979                 :      605926 :                    || gimple_code (stmt) == GIMPLE_PHI))
     980                 :             :         {
     981                 :     2204374 :           tree lhs;
     982                 :     2204374 :           if (gimple_code (stmt) == GIMPLE_PHI)
     983                 :      152565 :             lhs = gimple_phi_result (stmt);
     984                 :             :           else
     985                 :     2051809 :             lhs = gimple_assign_lhs (stmt);
     986                 :             : 
     987                 :     2204374 :           if (TREE_CODE (lhs) != SSA_NAME)
     988                 :             :             {
     989                 :             :               res = -1;
     990                 :             :               break;
     991                 :             :             }
     992                 :     1862769 :           gcc_assert (!gimple_vdef (stmt));
     993                 :     1862769 :           if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs)))
     994                 :             :             {
     995                 :     1778651 :               int tmp = isra_track_scalar_value_uses (fun, node, lhs, parm_num,
     996                 :             :                                                       analyzed, desc);
     997                 :     1778651 :               if (tmp < 0)
     998                 :             :                 {
     999                 :             :                   res = tmp;
    1000                 :             :                   break;
    1001                 :             :                 }
    1002                 :     1103792 :               res += tmp;
    1003                 :             :             }
    1004                 :             :         }
    1005                 :      560500 :       else if (greturn *gr = dyn_cast<greturn *>(stmt))
    1006                 :             :         {
    1007                 :      155361 :           tree rv = gimple_return_retval (gr);
    1008                 :      155361 :           if (rv != name)
    1009                 :             :             {
    1010                 :             :               res = -1;
    1011                 :             :               break;
    1012                 :             :             }
    1013                 :      155361 :           desc->remove_only_when_retval_removed = true;
    1014                 :             :         }
    1015                 :             :       else
    1016                 :             :         {
    1017                 :             :           res = -1;
    1018                 :             :           break;
    1019                 :             :         }
    1020                 :     3148065 :     }
    1021                 :     3148065 :   return res;
    1022                 :             : }
    1023                 :             : 
    1024                 :             : /* Inspect all uses of PARM, which must be a gimple register, in FUN (which is
    1025                 :             :    also described by NODE) and simple arithmetic calculations involving PARM
    1026                 :             :    and return false if any of them is used for something else than either an
    1027                 :             :    actual call argument, simple return, simple arithmetic operation or debug
    1028                 :             :    statement.  If there are no such uses, return true and store the number of
    1029                 :             :    actual arguments that this parameter eventually feeds to (or zero if there
    1030                 :             :    is none) to DESC->call_uses and set DESC->remove_only_when_retval_removed if
    1031                 :             :    there are any uses in return statemens.  For any such parameter, mark
    1032                 :             :    PARM_NUM as one of its sources.
    1033                 :             : 
    1034                 :             :    This function is similar to ptr_parm_has_nonarg_uses but its results are
    1035                 :             :    meant for unused parameter removal, as opposed to splitting of parameters
    1036                 :             :    passed by reference or converting them to passed by value.  */
    1037                 :             : 
    1038                 :             : static bool
    1039                 :     2044765 : isra_track_scalar_param_local_uses (function *fun, cgraph_node *node, tree parm,
    1040                 :             :                                     int parm_num, gensum_param_desc *desc)
    1041                 :             : {
    1042                 :     2044765 :   gcc_checking_assert (is_gimple_reg (parm));
    1043                 :             : 
    1044                 :     2044765 :   tree name = ssa_default_def (fun, parm);
    1045                 :     2044765 :   if (!name || has_zero_uses (name))
    1046                 :             :     {
    1047                 :      675351 :       desc->call_uses = 0;
    1048                 :      675351 :       return false;
    1049                 :             :     }
    1050                 :             : 
    1051                 :             :   /* Edge summaries can only handle callers with fewer than 256 parameters.  */
    1052                 :     1369414 :   if (parm_num > UCHAR_MAX)
    1053                 :             :     return true;
    1054                 :             : 
    1055                 :     1369414 :   bitmap analyzed = BITMAP_ALLOC (NULL);
    1056                 :     1369414 :   int call_uses = isra_track_scalar_value_uses (fun, node, name, parm_num,
    1057                 :             :                                                 analyzed, desc);
    1058                 :     1369414 :   BITMAP_FREE (analyzed);
    1059                 :     1369414 :   if (call_uses < 0)
    1060                 :             :     return true;
    1061                 :      599489 :   desc->call_uses = call_uses;
    1062                 :      599489 :   return false;
    1063                 :             : }
    1064                 :             : 
    1065                 :             : /* Scan immediate uses of a default definition SSA name of a parameter PARM and
    1066                 :             :    examine whether there are any nonarg uses that are not actual arguments or
    1067                 :             :    otherwise infeasible uses.  If so, return true, otherwise return false.
    1068                 :             :    Create pass-through IPA flow records for any direct uses as argument calls
    1069                 :             :    and if returning false, store their number into DESC->ptr_pt_count.  If
    1070                 :             :    removal of return value would still allow splitting, return true but set
    1071                 :             :    DESC->split_only_when_retval_removed.  NODE and FUN must represent the
    1072                 :             :    function that is currently analyzed, PARM_NUM must be the index of the
    1073                 :             :    analyzed parameter.
    1074                 :             : 
    1075                 :             :    This function is similar to isra_track_scalar_param_local_uses but its
    1076                 :             :    results are meant for splitting of parameters passed by reference or turning
    1077                 :             :    them into bits passed by value, as opposed to generic unused parameter
    1078                 :             :    removal.  */
    1079                 :             : 
    1080                 :             : static bool
    1081                 :     1065553 : ptr_parm_has_nonarg_uses (cgraph_node *node, function *fun, tree parm,
    1082                 :             :                           int parm_num, gensum_param_desc *desc)
    1083                 :             : {
    1084                 :     1065553 :   imm_use_iterator ui;
    1085                 :     1065553 :   gimple *stmt;
    1086                 :     1065553 :   tree name = ssa_default_def (fun, parm);
    1087                 :     1065553 :   bool ret = false;
    1088                 :     1065553 :   unsigned pt_count = 0;
    1089                 :             : 
    1090                 :     1065553 :   if (!name || has_zero_uses (name))
    1091                 :             :     return false;
    1092                 :             : 
    1093                 :             :   /* Edge summaries can only handle callers with fewer than 256 parameters.  */
    1094                 :      968012 :   if (parm_num > UCHAR_MAX)
    1095                 :             :     return true;
    1096                 :             : 
    1097                 :     2629514 :   FOR_EACH_IMM_USE_STMT (stmt, ui, name)
    1098                 :             :     {
    1099                 :     2151675 :       unsigned uses_ok = 0;
    1100                 :     2151675 :       use_operand_p use_p;
    1101                 :             : 
    1102                 :     2151675 :       if (is_gimple_debug (stmt)
    1103                 :     2151675 :           || gimple_clobber_p (stmt))
    1104                 :      506004 :         continue;
    1105                 :             : 
    1106                 :     1645671 :       if (gimple_assign_single_p (stmt))
    1107                 :             :         {
    1108                 :      800506 :           tree rhs = gimple_assign_rhs1 (stmt);
    1109                 :      800506 :           if (!TREE_THIS_VOLATILE (rhs))
    1110                 :             :             {
    1111                 :     1520593 :               while (handled_component_p (rhs))
    1112                 :      720405 :                 rhs = TREE_OPERAND (rhs, 0);
    1113                 :      800188 :               if (TREE_CODE (rhs) == MEM_REF
    1114                 :      556130 :                   && TREE_OPERAND (rhs, 0) == name
    1115                 :      552369 :                   && integer_zerop (TREE_OPERAND (rhs, 1))
    1116                 :     1313202 :                   && types_compatible_p (TREE_TYPE (rhs),
    1117                 :      513014 :                                          TREE_TYPE (TREE_TYPE (name))))
    1118                 :             :                 uses_ok++;
    1119                 :             :             }
    1120                 :             :         }
    1121                 :      845165 :       else if (is_gimple_call (stmt))
    1122                 :             :         {
    1123                 :      703200 :           gcall *call = as_a <gcall *> (stmt);
    1124                 :      703200 :           unsigned arg_count;
    1125                 :      703200 :           if (gimple_call_internal_p (call)
    1126                 :      703200 :               || (arg_count = gimple_call_num_args (call)) == 0)
    1127                 :             :             {
    1128                 :             :               ret = true;
    1129                 :             :               break;
    1130                 :             :             }
    1131                 :             : 
    1132                 :      702455 :           cgraph_edge *cs = node->get_edge (stmt);
    1133                 :      702455 :           gcc_checking_assert (cs);
    1134                 :      702455 :           isra_call_summary *csum = call_sums->get_create (cs);
    1135                 :      702455 :           csum->init_inputs (arg_count);
    1136                 :             : 
    1137                 :     2697124 :           for (unsigned i = 0; i < arg_count; ++i)
    1138                 :             :             {
    1139                 :     1994669 :               tree arg = gimple_call_arg (stmt, i);
    1140                 :             : 
    1141                 :     1994669 :               if (arg == name)
    1142                 :             :                 {
    1143                 :             :                   /* TODO: Allow &MEM_REF[name + offset] here,
    1144                 :             :                      ipa_param_body_adjustments::modify_call_stmt has to be
    1145                 :             :                      adjusted too.  */
    1146                 :      693211 :                   csum->m_arg_flow[i].pointer_pass_through = true;
    1147                 :      693211 :                   set_single_param_flow_source (&csum->m_arg_flow[i], parm_num);
    1148                 :      693211 :                   pt_count++;
    1149                 :      693211 :                   uses_ok++;
    1150                 :      693211 :                   continue;
    1151                 :             :                 }
    1152                 :             : 
    1153                 :     1301458 :               if (!TREE_THIS_VOLATILE (arg))
    1154                 :             :                 {
    1155                 :     1324269 :                   while (handled_component_p (arg))
    1156                 :       22811 :                     arg = TREE_OPERAND (arg, 0);
    1157                 :     1301458 :                   if (TREE_CODE (arg) == MEM_REF
    1158                 :       17634 :                       && TREE_OPERAND (arg, 0) == name
    1159                 :        9149 :                       && integer_zerop (TREE_OPERAND (arg, 1))
    1160                 :     1310607 :                       && types_compatible_p (TREE_TYPE (arg),
    1161                 :        9149 :                                              TREE_TYPE (TREE_TYPE (name))))
    1162                 :        6346 :                     uses_ok++;
    1163                 :             :                 }
    1164                 :             :             }
    1165                 :             :         }
    1166                 :      141965 :       else if (greturn *gr = dyn_cast<greturn *>(stmt))
    1167                 :             :         {
    1168                 :        6955 :           tree rv = gimple_return_retval (gr);
    1169                 :        6955 :           if (rv == name)
    1170                 :             :             {
    1171                 :        6955 :               uses_ok++;
    1172                 :             :               /* Analysis for feasibility of removal must have already reached
    1173                 :             :                  the conclusion that the flag must be set if it completed.  */
    1174                 :        6955 :               gcc_assert (!desc->locally_unused
    1175                 :             :                           || desc->remove_only_when_retval_removed);
    1176                 :        6955 :               desc->split_only_when_retval_removed = true;
    1177                 :             :             }
    1178                 :             :         }
    1179                 :             : 
    1180                 :             :       /* If the number of valid uses does not match the number of
    1181                 :             :          uses in this stmt there is an unhandled use.  */
    1182                 :     1644926 :       unsigned all_uses = 0;
    1183                 :     3297287 :       FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
    1184                 :     1652361 :         all_uses++;
    1185                 :             : 
    1186                 :     1644926 :       gcc_checking_assert (uses_ok <= all_uses);
    1187                 :     1644926 :       if (uses_ok != all_uses)
    1188                 :             :         {
    1189                 :             :           ret = true;
    1190                 :             :           break;
    1191                 :             :         }
    1192                 :      968012 :     }
    1193                 :             : 
    1194                 :      968012 :   desc->ptr_pt_count = pt_count;
    1195                 :      968012 :   return ret;
    1196                 :             : }
    1197                 :             : 
    1198                 :             : /* Initialize vector of parameter descriptors of NODE.  Return true if there
    1199                 :             :    are any candidates for splitting or unused aggregate parameter removal (the
    1200                 :             :    function may return false if there are candidates for removal of register
    1201                 :             :    parameters).  */
    1202                 :             : 
    1203                 :             : static bool
    1204                 :      777378 : create_parameter_descriptors (cgraph_node *node,
    1205                 :             :                               vec<gensum_param_desc> *param_descriptions)
    1206                 :             : {
    1207                 :      777378 :   function *fun = DECL_STRUCT_FUNCTION (node->decl);
    1208                 :      777378 :   bool ret = false;
    1209                 :             : 
    1210                 :      777378 :   int num = 0;
    1211                 :      777378 :   for (tree parm = DECL_ARGUMENTS (node->decl);
    1212                 :     3004559 :        parm;
    1213                 :     2227181 :        parm = DECL_CHAIN (parm), num++)
    1214                 :             :     {
    1215                 :     2227181 :       const char *msg;
    1216                 :     2227181 :       gensum_param_desc *desc = &(*param_descriptions)[num];
    1217                 :             :       /* param_descriptions vector is grown cleared in the caller.  */
    1218                 :     2227181 :       desc->param_number = num;
    1219                 :     2227181 :       decl2desc->put (parm, desc);
    1220                 :             : 
    1221                 :     2227181 :       if (dump_file && (dump_flags & TDF_DETAILS))
    1222                 :          39 :         print_generic_expr (dump_file, parm, TDF_UID);
    1223                 :             : 
    1224                 :     2227181 :       tree type = TREE_TYPE (parm);
    1225                 :     2227181 :       if (TREE_THIS_VOLATILE (parm))
    1226                 :             :         {
    1227                 :          18 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1228                 :           0 :             fprintf (dump_file, " not a candidate, is volatile\n");
    1229                 :     1675110 :           continue;
    1230                 :             :         }
    1231                 :     2227163 :       if (!is_gimple_reg_type (type) && is_va_list_type (type))
    1232                 :             :         {
    1233                 :           0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1234                 :           0 :             fprintf (dump_file, " not a candidate, is a va_list type\n");
    1235                 :           0 :           continue;
    1236                 :             :         }
    1237                 :     2227163 :       if (TREE_ADDRESSABLE (parm))
    1238                 :             :         {
    1239                 :       28663 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1240                 :           0 :             fprintf (dump_file, " not a candidate, is addressable\n");
    1241                 :       28663 :           continue;
    1242                 :             :         }
    1243                 :     2198500 :       if (TREE_ADDRESSABLE (type))
    1244                 :             :         {
    1245                 :           0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1246                 :           0 :             fprintf (dump_file, " not a candidate, type cannot be split\n");
    1247                 :           0 :           continue;
    1248                 :             :         }
    1249                 :             : 
    1250                 :     2198500 :       if (is_gimple_reg (parm)
    1251                 :     2198500 :           && !isra_track_scalar_param_local_uses (fun, node, parm, num, desc))
    1252                 :             :         {
    1253                 :     1274840 :           desc->locally_unused = true;
    1254                 :             : 
    1255                 :     1274840 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1256                 :          19 :             fprintf (dump_file, " is a scalar with only %i call uses%s\n",
    1257                 :             :                      desc->call_uses,
    1258                 :          19 :                      desc->remove_only_when_retval_removed
    1259                 :             :                      ? " and return uses": "");
    1260                 :             :         }
    1261                 :             : 
    1262                 :     2198500 :       if (POINTER_TYPE_P (type))
    1263                 :             :         {
    1264                 :     1072022 :           desc->by_ref = true;
    1265                 :     1072022 :           if (TREE_CODE (type) == REFERENCE_TYPE
    1266                 :     1072022 :               || (num == 0
    1267                 :      525570 :                   && TREE_CODE (TREE_TYPE (node->decl)) == METHOD_TYPE))
    1268                 :      428618 :             desc->safe_ref = true;
    1269                 :             :           else
    1270                 :      643404 :             desc->safe_ref = false;
    1271                 :     1072022 :           type = TREE_TYPE (type);
    1272                 :             : 
    1273                 :     1076802 :           if (TREE_CODE (type) == FUNCTION_TYPE
    1274                 :     1072022 :               || TREE_CODE (type) == METHOD_TYPE)
    1275                 :             :             {
    1276                 :        4780 :               if (dump_file && (dump_flags & TDF_DETAILS))
    1277                 :           0 :                 fprintf (dump_file, " not a candidate, reference to "
    1278                 :             :                          "a function\n");
    1279                 :        4780 :               continue;
    1280                 :             :             }
    1281                 :     1067242 :           if (TYPE_VOLATILE (type))
    1282                 :             :             {
    1283                 :        1310 :               if (dump_file && (dump_flags & TDF_DETAILS))
    1284                 :           0 :                 fprintf (dump_file, " not a candidate, reference to "
    1285                 :             :                          "a volatile type\n");
    1286                 :        1310 :               continue;
    1287                 :             :             }
    1288                 :     1065932 :           if (TREE_CODE (type) == ARRAY_TYPE
    1289                 :     1065932 :               && TYPE_NONALIASED_COMPONENT (type))
    1290                 :             :             {
    1291                 :           0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    1292                 :           0 :                 fprintf (dump_file, " not a candidate, reference to "
    1293                 :             :                          "a nonaliased component array\n");
    1294                 :           0 :               continue;
    1295                 :             :             }
    1296                 :     1065932 :           if (!is_gimple_reg (parm))
    1297                 :             :             {
    1298                 :           6 :               if (dump_file && (dump_flags & TDF_DETAILS))
    1299                 :           0 :                 fprintf (dump_file, " not a candidate, a reference which is "
    1300                 :             :                          "not a gimple register (probably addressable)\n");
    1301                 :           6 :               continue;
    1302                 :             :             }
    1303                 :     1065926 :           if (is_va_list_type (type))
    1304                 :             :             {
    1305                 :         373 :               if (dump_file && (dump_flags & TDF_DETAILS))
    1306                 :           0 :                 fprintf (dump_file, " not a candidate, reference to "
    1307                 :             :                          "a va list\n");
    1308                 :         373 :               continue;
    1309                 :             :             }
    1310                 :     1065553 :           if (ptr_parm_has_nonarg_uses (node, fun, parm, num, desc))
    1311                 :             :             {
    1312                 :      490173 :               if (dump_file && (dump_flags & TDF_DETAILS))
    1313                 :           7 :                 fprintf (dump_file, " not a candidate, reference has "
    1314                 :             :                          "nonarg uses\n");
    1315                 :      490173 :               continue;
    1316                 :             :             }
    1317                 :             :         }
    1318                 :     1126478 :       else if (!AGGREGATE_TYPE_P (type))
    1319                 :             :         {
    1320                 :             :           /* This is in an else branch because scalars passed by reference are
    1321                 :             :              still candidates to be passed by value.  */
    1322                 :      972941 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1323                 :          17 :             fprintf (dump_file, " not a candidate, not an aggregate\n");
    1324                 :      972941 :           continue;
    1325                 :             :         }
    1326                 :             : 
    1327                 :      728917 :       if (!COMPLETE_TYPE_P (type))
    1328                 :             :         {
    1329                 :      165316 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1330                 :           0 :             fprintf (dump_file, " not a candidate, not a complete type\n");
    1331                 :      165316 :           continue;
    1332                 :             :         }
    1333                 :      563601 :       if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
    1334                 :             :         {
    1335                 :           3 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1336                 :           0 :             fprintf (dump_file, " not a candidate, size not representable\n");
    1337                 :           3 :           continue;
    1338                 :             :         }
    1339                 :      563598 :       unsigned HOST_WIDE_INT type_size
    1340                 :      563598 :         = tree_to_uhwi (TYPE_SIZE (type)) / BITS_PER_UNIT;
    1341                 :      566801 :       if (type_size == 0
    1342                 :      563598 :           || type_size >= ISRA_ARG_SIZE_LIMIT)
    1343                 :             :         {
    1344                 :        3203 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1345                 :           0 :             fprintf (dump_file, " not a candidate, has zero or huge size\n");
    1346                 :        3203 :           continue;
    1347                 :             :         }
    1348                 :      560395 :       if (type_internals_preclude_sra_p (type, &msg))
    1349                 :             :         {
    1350                 :        8324 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1351                 :           0 :               fprintf (dump_file, " not a candidate, %s\n", msg);
    1352                 :        8324 :           continue;
    1353                 :             :         }
    1354                 :             : 
    1355                 :      552071 :       if (dump_file && (dump_flags & TDF_DETAILS))
    1356                 :          15 :         fprintf (dump_file, " is a candidate\n");
    1357                 :             : 
    1358                 :      552071 :       ret = true;
    1359                 :      552071 :       desc->split_candidate = true;
    1360                 :      552071 :       if (desc->by_ref && !desc->safe_ref)
    1361                 :      188694 :         desc->deref_index = unsafe_by_ref_count++;
    1362                 :             :     }
    1363                 :      777378 :   return ret;
    1364                 :             : }
    1365                 :             : 
    1366                 :             : /* Return pointer to descriptor of parameter DECL or NULL if it cannot be
    1367                 :             :    found, which happens if DECL is for a static chain.  */
    1368                 :             : 
    1369                 :             : static gensum_param_desc *
    1370                 :     2226263 : get_gensum_param_desc (tree decl)
    1371                 :             : {
    1372                 :     2226263 :   if (!decl2desc)
    1373                 :             :     return NULL;
    1374                 :     2057480 :   gcc_checking_assert (TREE_CODE (decl) == PARM_DECL);
    1375                 :     2057480 :   gensum_param_desc **slot = decl2desc->get (decl);
    1376                 :     2057480 :   if (!slot)
    1377                 :             :     /* This can happen for static chains which we cannot handle so far.  */
    1378                 :             :     return NULL;
    1379                 :     2032463 :   gcc_checking_assert (*slot);
    1380                 :             :   return *slot;
    1381                 :             : }
    1382                 :             : 
    1383                 :             : 
    1384                 :             : /* Remove parameter described by DESC from candidates for IPA-SRA splitting and
    1385                 :             :    write REASON to the dump file if there is one.  */
    1386                 :             : 
    1387                 :             : static void
    1388                 :      143669 : disqualify_split_candidate (gensum_param_desc *desc, const char *reason)
    1389                 :             : {
    1390                 :      143669 :   if (!desc->split_candidate)
    1391                 :             :     return;
    1392                 :             : 
    1393                 :      143640 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1394                 :           0 :     fprintf (dump_file, "! Disqualifying parameter number %i - %s\n",
    1395                 :             :              desc->param_number, reason);
    1396                 :             : 
    1397                 :      143640 :   desc->split_candidate = false;
    1398                 :             : }
    1399                 :             : 
    1400                 :             : /* Remove DECL from candidates for IPA-SRA and write REASON to the dump file if
    1401                 :             :    there is one.  */
    1402                 :             : 
    1403                 :             : static void
    1404                 :         177 : disqualify_split_candidate (tree decl, const char *reason)
    1405                 :             : {
    1406                 :         177 :   gensum_param_desc *desc = get_gensum_param_desc (decl);
    1407                 :         177 :   if (desc)
    1408                 :          29 :     disqualify_split_candidate (desc, reason);
    1409                 :         177 : }
    1410                 :             : 
    1411                 :             : /* Allocate a new access to DESC and fill it in with OFFSET and SIZE.  But
    1412                 :             :    first, check that there are not too many of them already.  If so, do not
    1413                 :             :    allocate anything and return NULL.  */
    1414                 :             : 
    1415                 :             : static gensum_param_access *
    1416                 :      395406 : allocate_access (gensum_param_desc *desc,
    1417                 :             :                  HOST_WIDE_INT offset, HOST_WIDE_INT size)
    1418                 :             : {
    1419                 :      395406 :   if (desc->access_count
    1420                 :      395406 :       == (unsigned) param_ipa_sra_max_replacements)
    1421                 :             :     {
    1422                 :           0 :       disqualify_split_candidate (desc, "Too many replacement candidates");
    1423                 :           0 :       return NULL;
    1424                 :             :     }
    1425                 :             : 
    1426                 :      395406 :   gensum_param_access *access
    1427                 :      395406 :     = (gensum_param_access *) obstack_alloc (&gensum_obstack,
    1428                 :             :                                              sizeof (gensum_param_access));
    1429                 :      395406 :   memset (access, 0, sizeof (*access));
    1430                 :      395406 :   access->offset = offset;
    1431                 :      395406 :   access->size = size;
    1432                 :      395406 :   access->load_count = profile_count::zero ();
    1433                 :      395406 :   return access;
    1434                 :             : }
    1435                 :             : 
    1436                 :             : /* In what context scan_expr_access has been called, whether it deals with a
    1437                 :             :    load, a function argument, or a store.  Please note that in rare
    1438                 :             :    circumstances when it is not clear if the access is a load or store,
    1439                 :             :    ISRA_CTX_STORE is used too.  */
    1440                 :             : 
    1441                 :             : enum isra_scan_context {ISRA_CTX_LOAD, ISRA_CTX_ARG, ISRA_CTX_STORE};
    1442                 :             : 
    1443                 :             : /* Return an access describing memory access to the variable described by DESC
    1444                 :             :    at OFFSET with SIZE in context CTX, starting at pointer to the linked list
    1445                 :             :    at a certain tree level FIRST.  Attempt to create it and put into the
    1446                 :             :    appropriate place in the access tree if does not exist, but fail and return
    1447                 :             :    NULL if there are already too many accesses, if it would create a partially
    1448                 :             :    overlapping access or if an access would end up within a pre-existing
    1449                 :             :    non-call access.  */
    1450                 :             : 
    1451                 :             : static gensum_param_access *
    1452                 :      459758 : get_access_1 (gensum_param_desc *desc, gensum_param_access **first,
    1453                 :             :               HOST_WIDE_INT offset, HOST_WIDE_INT size, isra_scan_context ctx)
    1454                 :             : {
    1455                 :      468505 :   gensum_param_access *access = *first, **ptr = first;
    1456                 :             : 
    1457                 :      468505 :   if (!access)
    1458                 :             :     {
    1459                 :             :       /* No pre-existing access at this level, just create it.  */
    1460                 :      258910 :       gensum_param_access *a = allocate_access (desc, offset, size);
    1461                 :      258910 :       if (!a)
    1462                 :             :         return NULL;
    1463                 :      258910 :       *first = a;
    1464                 :      258910 :       return *first;
    1465                 :             :     }
    1466                 :             : 
    1467                 :      209595 :   if (access->offset >= offset + size)
    1468                 :             :     {
    1469                 :             :       /* We want to squeeze it in front of the very first access, just do
    1470                 :             :          it.  */
    1471                 :       37803 :       gensum_param_access *r = allocate_access (desc, offset, size);
    1472                 :       37803 :       if (!r)
    1473                 :             :         return NULL;
    1474                 :       37803 :       r->next_sibling = access;
    1475                 :       37803 :       *first = r;
    1476                 :       37803 :       return r;
    1477                 :             :     }
    1478                 :             : 
    1479                 :             :   /* Skip all accesses that have to come before us until the next sibling is
    1480                 :             :      already too far.  */
    1481                 :      245226 :   while (offset >= access->offset + access->size
    1482                 :      162080 :          && access->next_sibling
    1483                 :      327088 :          && access->next_sibling->offset < offset + size)
    1484                 :             :     {
    1485                 :       73434 :       ptr = &access->next_sibling;
    1486                 :       73434 :       access = access->next_sibling;
    1487                 :             :     }
    1488                 :             : 
    1489                 :             :   /* At this point we know we do not belong before access.  */
    1490                 :      171792 :   gcc_assert (access->offset < offset + size);
    1491                 :             : 
    1492                 :      171792 :   if (access->offset == offset && access->size == size)
    1493                 :             :     /* We found what we were looking for.  */
    1494                 :             :     return access;
    1495                 :             : 
    1496                 :      113705 :   if (access->offset <= offset
    1497                 :      110554 :       && access->offset + access->size >= offset + size)
    1498                 :             :     {
    1499                 :             :     /* We fit into access which is larger than us.  We need to find/create
    1500                 :             :        something below access.  But we only allow nesting in call
    1501                 :             :        arguments.  */
    1502                 :       11555 :       if (access->nonarg)
    1503                 :             :         return NULL;
    1504                 :             : 
    1505                 :        8747 :       return get_access_1 (desc, &access->first_child, offset, size, ctx);
    1506                 :             :     }
    1507                 :             : 
    1508                 :      102150 :   if (offset <= access->offset
    1509                 :       13504 :       && offset + size  >= access->offset + access->size)
    1510                 :             :     /* We are actually bigger than access, which fully fits into us, take its
    1511                 :             :        place and make all accesses fitting into it its children.  */
    1512                 :             :     {
    1513                 :             :       /* But first, we only allow nesting in call arguments so check if that is
    1514                 :             :          what we are trying to represent.  */
    1515                 :       13504 :       if (ctx != ISRA_CTX_ARG)
    1516                 :             :         return NULL;
    1517                 :             : 
    1518                 :       10047 :       gensum_param_access *r = allocate_access (desc, offset, size);
    1519                 :       10047 :       if (!r)
    1520                 :             :         return NULL;
    1521                 :       10047 :       r->first_child = access;
    1522                 :             : 
    1523                 :       10047 :       while (access->next_sibling
    1524                 :       18279 :              && access->next_sibling->offset < offset + size)
    1525                 :             :         access = access->next_sibling;
    1526                 :       10047 :       if (access->offset + access->size > offset + size)
    1527                 :             :         {
    1528                 :             :           /* This must be a different access, which are sorted, so the
    1529                 :             :              following must be true and this signals a partial overlap.  */
    1530                 :           0 :           gcc_assert (access->offset > offset);
    1531                 :             :           return NULL;
    1532                 :             :         }
    1533                 :             : 
    1534                 :       10047 :       r->next_sibling = access->next_sibling;
    1535                 :       10047 :       access->next_sibling = NULL;
    1536                 :       10047 :       *ptr = r;
    1537                 :       10047 :       return r;
    1538                 :             :     }
    1539                 :             : 
    1540                 :       88646 :   if (offset >= access->offset + access->size)
    1541                 :             :     {
    1542                 :             :       /* We belong after access.  */
    1543                 :       88646 :       gensum_param_access *r = allocate_access (desc, offset, size);
    1544                 :       88646 :       if (!r)
    1545                 :             :         return NULL;
    1546                 :       88646 :       r->next_sibling = access->next_sibling;
    1547                 :       88646 :       access->next_sibling = r;
    1548                 :       88646 :       return r;
    1549                 :             :     }
    1550                 :             : 
    1551                 :           0 :   if (offset < access->offset)
    1552                 :             :     {
    1553                 :             :       /* We know the following, otherwise we would have created a
    1554                 :             :          super-access. */
    1555                 :           0 :       gcc_checking_assert (offset + size < access->offset + access->size);
    1556                 :             :       return NULL;
    1557                 :             :     }
    1558                 :             : 
    1559                 :           0 :   if (offset + size > access->offset + access->size)
    1560                 :             :     {
    1561                 :             :       /* Likewise.  */
    1562                 :           0 :       gcc_checking_assert (offset > access->offset);
    1563                 :             :       return NULL;
    1564                 :             :     }
    1565                 :             : 
    1566                 :           0 :   gcc_unreachable ();
    1567                 :             : }
    1568                 :             : 
    1569                 :             : /* Return an access describing memory access to the variable described by DESC
    1570                 :             :    at OFFSET with SIZE in context CTX, mark it as used in context CTX.  Attempt
    1571                 :             :    to create if it does not exist, but fail and return NULL if there are
    1572                 :             :    already too many accesses, if it would create a partially overlapping access
    1573                 :             :    or if an access would end up in a non-call access.  */
    1574                 :             : 
    1575                 :             : static gensum_param_access *
    1576                 :      459758 : get_access (gensum_param_desc *desc, HOST_WIDE_INT offset, HOST_WIDE_INT size,
    1577                 :             :             isra_scan_context ctx)
    1578                 :             : {
    1579                 :      459758 :   gcc_checking_assert (desc->split_candidate);
    1580                 :             : 
    1581                 :      459758 :   gensum_param_access *access = get_access_1 (desc, &desc->accesses, offset,
    1582                 :             :                                               size, ctx);
    1583                 :      459758 :   if (!access)
    1584                 :             :     {
    1585                 :        6265 :       disqualify_split_candidate (desc,
    1586                 :             :                                   "Bad access overlap or too many accesses");
    1587                 :        6265 :       return NULL;
    1588                 :             :     }
    1589                 :             : 
    1590                 :      453493 :   switch (ctx)
    1591                 :             :     {
    1592                 :       11624 :     case ISRA_CTX_STORE:
    1593                 :       11624 :       gcc_assert (!desc->by_ref);
    1594                 :             :       /* Fall-through */
    1595                 :      375472 :     case ISRA_CTX_LOAD:
    1596                 :      375472 :       access->nonarg = true;
    1597                 :      375472 :       break;
    1598                 :             :     case ISRA_CTX_ARG:
    1599                 :             :       break;
    1600                 :             :     }
    1601                 :             : 
    1602                 :             :   return access;
    1603                 :             : }
    1604                 :             : 
    1605                 :             : /* Verify that parameter access tree starting with ACCESS is in good shape.
    1606                 :             :    PARENT_OFFSET and PARENT_SIZE are the corresponding fields of parent of
    1607                 :             :    ACCESS or zero if there is none.  */
    1608                 :             : 
    1609                 :             : static bool
    1610                 :      833918 : verify_access_tree_1 (gensum_param_access *access, HOST_WIDE_INT parent_offset,
    1611                 :             :                       HOST_WIDE_INT parent_size)
    1612                 :             : {
    1613                 :     1186034 :   while (access)
    1614                 :             :     {
    1615                 :      352116 :       gcc_assert (access->offset >= 0 && access->size >= 0);
    1616                 :             : 
    1617                 :      352116 :       if (parent_size != 0)
    1618                 :             :         {
    1619                 :       20609 :           if (access->offset < parent_offset)
    1620                 :             :             {
    1621                 :           0 :               error ("Access offset before parent offset");
    1622                 :           0 :               return true;
    1623                 :             :             }
    1624                 :       20609 :           if (access->size >= parent_size)
    1625                 :             :             {
    1626                 :           0 :               error ("Access size greater or equal to its parent size");
    1627                 :           0 :               return true;
    1628                 :             :             }
    1629                 :       20609 :           if (access->offset + access->size > parent_offset + parent_size)
    1630                 :             :             {
    1631                 :           0 :               error ("Access terminates outside of its parent");
    1632                 :           0 :               return true;
    1633                 :             :             }
    1634                 :             :         }
    1635                 :             : 
    1636                 :      352116 :       if (verify_access_tree_1 (access->first_child, access->offset,
    1637                 :             :                                 access->size))
    1638                 :             :         return true;
    1639                 :             : 
    1640                 :      352116 :       if (access->next_sibling
    1641                 :      114706 :           && (access->next_sibling->offset < access->offset + access->size))
    1642                 :             :         {
    1643                 :           0 :           error ("Access overlaps with its sibling");
    1644                 :           0 :           return true;
    1645                 :             :         }
    1646                 :             : 
    1647                 :             :       access = access->next_sibling;
    1648                 :             :     }
    1649                 :             :   return false;
    1650                 :             : }
    1651                 :             : 
    1652                 :             : /* Verify that parameter access tree starting with ACCESS is in good shape,
    1653                 :             :    halt compilation and dump the tree to stderr if not.  */
    1654                 :             : 
    1655                 :             : DEBUG_FUNCTION void
    1656                 :      481802 : isra_verify_access_tree (gensum_param_access *access)
    1657                 :             : {
    1658                 :      481802 :   if (verify_access_tree_1 (access, 0, 0))
    1659                 :             :     {
    1660                 :           0 :       for (; access; access = access->next_sibling)
    1661                 :           0 :         dump_gensum_access (stderr, access, 2);
    1662                 :           0 :       internal_error ("IPA-SRA access verification failed");
    1663                 :             :     }
    1664                 :      481802 : }
    1665                 :             : 
    1666                 :             : 
    1667                 :             : /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
    1668                 :             :    GIMPLE_ASM operands with memory constrains which cannot be scalarized.  */
    1669                 :             : 
    1670                 :             : static bool
    1671                 :        6896 : asm_visit_addr (gimple *, tree op, tree, void *)
    1672                 :             : {
    1673                 :        6896 :   op = get_base_address (op);
    1674                 :        6896 :   if (op
    1675                 :        6896 :       && TREE_CODE (op) == PARM_DECL)
    1676                 :         177 :     disqualify_split_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
    1677                 :             : 
    1678                 :        6896 :   return false;
    1679                 :             : }
    1680                 :             : 
    1681                 :             : /* Mark a dereference of parameter identified by DESC of distance DIST in a
    1682                 :             :    basic block BB, unless the BB has already been marked as a potentially
    1683                 :             :    final.  */
    1684                 :             : 
    1685                 :             : static void
    1686                 :      217721 : mark_param_dereference (gensum_param_desc *desc, HOST_WIDE_INT dist,
    1687                 :             :                         basic_block bb)
    1688                 :             : {
    1689                 :      217721 :   gcc_assert (desc->by_ref);
    1690                 :      217721 :   gcc_checking_assert (desc->split_candidate);
    1691                 :             : 
    1692                 :      217721 :   if (desc->safe_ref
    1693                 :      217721 :       || bitmap_bit_p (final_bbs, bb->index))
    1694                 :      194370 :     return;
    1695                 :             : 
    1696                 :       23351 :   int idx = bb->index * unsafe_by_ref_count + desc->deref_index;
    1697                 :       23351 :   if (bb_dereferences[idx] < dist)
    1698                 :       21873 :     bb_dereferences[idx] = dist;
    1699                 :             : }
    1700                 :             : 
    1701                 :             : /* Return true, if any potential replacements should use NEW_TYPE as opposed to
    1702                 :             :    previously recorded OLD_TYPE.  */
    1703                 :             : 
    1704                 :             : static bool
    1705                 :       52892 : type_prevails_p (tree old_type, tree new_type)
    1706                 :             : {
    1707                 :       52892 :   if (old_type == new_type)
    1708                 :             :     return false;
    1709                 :             : 
    1710                 :             :   /* Non-aggregates are always better.  */
    1711                 :          87 :   if (!is_gimple_reg_type (old_type)
    1712                 :          87 :       && is_gimple_reg_type (new_type))
    1713                 :             :     return true;
    1714                 :          83 :   if (is_gimple_reg_type (old_type)
    1715                 :          83 :       && !is_gimple_reg_type (new_type))
    1716                 :             :     return false;
    1717                 :             : 
    1718                 :             :   /* Prefer any complex or vector type over any other scalar type.  */
    1719                 :          73 :   if (TREE_CODE (old_type) != COMPLEX_TYPE
    1720                 :          73 :       && TREE_CODE (old_type) != VECTOR_TYPE
    1721                 :          60 :       && (TREE_CODE (new_type) == COMPLEX_TYPE
    1722                 :          60 :           || VECTOR_TYPE_P (new_type)))
    1723                 :             :     return true;
    1724                 :          73 :   if ((TREE_CODE (old_type) == COMPLEX_TYPE
    1725                 :             :        || VECTOR_TYPE_P (old_type))
    1726                 :          13 :       && TREE_CODE (new_type) != COMPLEX_TYPE
    1727                 :           0 :       && TREE_CODE (new_type) != VECTOR_TYPE)
    1728                 :             :     return false;
    1729                 :             : 
    1730                 :             :   /* Use the integral type with the bigger precision.  */
    1731                 :          73 :   if (INTEGRAL_TYPE_P (old_type)
    1732                 :          29 :       && INTEGRAL_TYPE_P (new_type))
    1733                 :          29 :     return (TYPE_PRECISION (new_type) > TYPE_PRECISION (old_type));
    1734                 :             : 
    1735                 :             :   /* Attempt to disregard any integral type with non-full precision.  */
    1736                 :          44 :   if (INTEGRAL_TYPE_P (old_type)
    1737                 :          44 :       && (TREE_INT_CST_LOW (TYPE_SIZE (old_type))
    1738                 :           0 :           != TYPE_PRECISION (old_type)))
    1739                 :             :     return true;
    1740                 :          44 :   if (INTEGRAL_TYPE_P (new_type)
    1741                 :          44 :       && (TREE_INT_CST_LOW (TYPE_SIZE (new_type))
    1742                 :           6 :           != TYPE_PRECISION (new_type)))
    1743                 :             :     return false;
    1744                 :             :   /* Stabilize the selection.  */
    1745                 :          44 :   return TYPE_UID (old_type) < TYPE_UID (new_type);
    1746                 :             : }
    1747                 :             : 
    1748                 :             : /* When scanning an expression which is a call argument, this structure
    1749                 :             :    specifies the call and the position of the argument.  */
    1750                 :             : 
    1751                 :             : struct scan_call_info
    1752                 :             : {
    1753                 :             :   /* Call graph edge representing the call. */
    1754                 :             :   cgraph_edge *cs;
    1755                 :             :   /* Total number of arguments in the call.  */
    1756                 :             :   unsigned argument_count;
    1757                 :             :   /* Number of the actual argument being scanned.  */
    1758                 :             :   unsigned arg_idx;
    1759                 :             : };
    1760                 :             : 
    1761                 :             : /* Record use of ACCESS which belongs to a parameter described by DESC in a
    1762                 :             :    call argument described by CALL_INFO.  */
    1763                 :             : 
    1764                 :             : static void
    1765                 :       75614 : record_nonregister_call_use (gensum_param_desc *desc,
    1766                 :             :                              scan_call_info *call_info,
    1767                 :             :                              unsigned unit_offset, unsigned unit_size)
    1768                 :             : {
    1769                 :       75614 :   isra_call_summary *csum = call_sums->get_create (call_info->cs);
    1770                 :       75614 :   csum->init_inputs (call_info->argument_count);
    1771                 :             : 
    1772                 :       75614 :   isra_param_flow *param_flow = &csum->m_arg_flow[call_info->arg_idx];
    1773                 :       75614 :   param_flow->aggregate_pass_through = true;
    1774                 :       75614 :   set_single_param_flow_source (param_flow, desc->param_number);
    1775                 :       75614 :   param_flow->unit_offset = unit_offset;
    1776                 :       75614 :   param_flow->unit_size = unit_size;
    1777                 :       75614 :   desc->call_uses++;
    1778                 :       75614 : }
    1779                 :             : 
    1780                 :             : /* Callback of walk_aliased_vdefs, just mark that there was a possible
    1781                 :             :    modification.  */
    1782                 :             : 
    1783                 :             : static bool
    1784                 :       58296 : mark_maybe_modified (ao_ref *, tree, void *data)
    1785                 :             : {
    1786                 :       58296 :   bool *maybe_modified = (bool *) data;
    1787                 :       58296 :   *maybe_modified = true;
    1788                 :       58296 :   return true;
    1789                 :             : }
    1790                 :             : 
    1791                 :             : /* Analyze expression EXPR from GIMPLE for accesses to parameters. CTX
    1792                 :             :    specifies whether EXPR is used in a load, store or as an argument call. BB
    1793                 :             :    must be the basic block in which expr resides.  If CTX specifies call
    1794                 :             :    argument context, CALL_INFO must describe that call and argument position,
    1795                 :             :    otherwise it is ignored.  */
    1796                 :             : 
    1797                 :             : static void
    1798                 :    33220145 : scan_expr_access (tree expr, gimple *stmt, isra_scan_context ctx,
    1799                 :             :                   basic_block bb, scan_call_info *call_info = NULL)
    1800                 :             : {
    1801                 :    33220145 :   poly_int64 poffset, psize, pmax_size;
    1802                 :    33220145 :   HOST_WIDE_INT offset, size, max_size;
    1803                 :    33220145 :   tree base;
    1804                 :    33220145 :   bool deref = false;
    1805                 :    33220145 :   bool reverse;
    1806                 :             : 
    1807                 :    33220145 :   if (TREE_CODE (expr) == ADDR_EXPR)
    1808                 :             :     {
    1809                 :     3957718 :       if (ctx == ISRA_CTX_ARG)
    1810                 :             :         return;
    1811                 :     1070349 :       tree t = get_base_address (TREE_OPERAND (expr, 0));
    1812                 :     1070349 :       if (VAR_P (t) && !TREE_STATIC (t))
    1813                 :      181552 :         loaded_decls->add (t);
    1814                 :     1070349 :       return;
    1815                 :             :     }
    1816                 :    29262427 :   if (TREE_CODE (expr) == SSA_NAME
    1817                 :    16128581 :       || CONSTANT_CLASS_P (expr))
    1818                 :             :     return;
    1819                 :             : 
    1820                 :    11647536 :   if (TREE_CODE (expr) == BIT_FIELD_REF
    1821                 :    11647536 :       || TREE_CODE (expr) == IMAGPART_EXPR
    1822                 :    11548413 :       || TREE_CODE (expr) == REALPART_EXPR)
    1823                 :      151284 :     expr = TREE_OPERAND (expr, 0);
    1824                 :             : 
    1825                 :    11647536 :   base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size, &reverse);
    1826                 :             : 
    1827                 :    11647536 :   if (TREE_CODE (base) == MEM_REF)
    1828                 :             :     {
    1829                 :     3635394 :       tree op = TREE_OPERAND (base, 0);
    1830                 :     3635394 :       if (TREE_CODE (op) != SSA_NAME
    1831                 :     3635394 :           || !SSA_NAME_IS_DEFAULT_DEF (op))
    1832                 :             :         return;
    1833                 :     1903181 :       base = SSA_NAME_VAR (op);
    1834                 :     1903181 :       if (!base)
    1835                 :             :         return;
    1836                 :             :       deref = true;
    1837                 :             :     }
    1838                 :     8012142 :   else if (VAR_P (base)
    1839                 :     8012142 :            && !TREE_STATIC (base)
    1840                 :     6033679 :            && (ctx == ISRA_CTX_ARG
    1841                 :             :                || ctx == ISRA_CTX_LOAD))
    1842                 :     2300870 :     loaded_decls->add (base);
    1843                 :             : 
    1844                 :     9915323 :   if (TREE_CODE (base) != PARM_DECL)
    1845                 :             :     return;
    1846                 :             : 
    1847                 :     2226086 :   gensum_param_desc *desc = get_gensum_param_desc (base);
    1848                 :     2226086 :   if (!desc || !desc->split_candidate)
    1849                 :             :     return;
    1850                 :             : 
    1851                 :      518559 :   if (!poffset.is_constant (&offset)
    1852                 :      518559 :       || !psize.is_constant (&size)
    1853                 :      518559 :       || !pmax_size.is_constant (&max_size))
    1854                 :             :     {
    1855                 :             :       disqualify_split_candidate (desc, "Encountered a polynomial-sized "
    1856                 :             :                                   "access.");
    1857                 :             :       return;
    1858                 :             :     }
    1859                 :      518559 :   if (size < 0 || size != max_size)
    1860                 :             :     {
    1861                 :        5472 :       disqualify_split_candidate (desc, "Encountered a variable sized access.");
    1862                 :        5472 :       return;
    1863                 :             :     }
    1864                 :      513087 :   if (TREE_CODE (expr) == COMPONENT_REF
    1865                 :      513087 :       && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
    1866                 :             :     {
    1867                 :        1305 :       disqualify_split_candidate (desc, "Encountered a bit-field access.");
    1868                 :        1305 :       return;
    1869                 :             :     }
    1870                 :      511782 :   if (offset < 0)
    1871                 :             :     {
    1872                 :           4 :       disqualify_split_candidate (desc, "Encountered an access at a "
    1873                 :             :                                   "negative offset.");
    1874                 :           4 :       return;
    1875                 :             :     }
    1876                 :      511778 :   gcc_assert ((offset % BITS_PER_UNIT) == 0);
    1877                 :      511778 :   gcc_assert ((size % BITS_PER_UNIT) == 0);
    1878                 :      511778 :   if ((offset / BITS_PER_UNIT) >= (UINT_MAX - ISRA_ARG_SIZE_LIMIT)
    1879                 :      511778 :       || (size / BITS_PER_UNIT) >= ISRA_ARG_SIZE_LIMIT)
    1880                 :             :     {
    1881                 :           0 :       disqualify_split_candidate (desc, "Encountered an access with too big "
    1882                 :             :                                   "offset or size");
    1883                 :           0 :       return;
    1884                 :             :     }
    1885                 :             : 
    1886                 :      511778 :   tree type = TREE_TYPE (expr);
    1887                 :      511778 :   unsigned int exp_align = get_object_alignment (expr);
    1888                 :             : 
    1889                 :      511778 :   if (exp_align < TYPE_ALIGN (type))
    1890                 :             :     {
    1891                 :        1325 :       disqualify_split_candidate (desc, "Underaligned access.");
    1892                 :        1325 :       return;
    1893                 :             :     }
    1894                 :             : 
    1895                 :      510453 :   if (deref)
    1896                 :             :     {
    1897                 :      268416 :       if (!desc->by_ref)
    1898                 :             :         {
    1899                 :           0 :           disqualify_split_candidate (desc, "Dereferencing a non-reference.");
    1900                 :       50695 :           return;
    1901                 :             :         }
    1902                 :      268416 :       else if (ctx == ISRA_CTX_STORE)
    1903                 :             :         {
    1904                 :           0 :           disqualify_split_candidate (desc, "Storing to data passed by "
    1905                 :             :                                       "reference.");
    1906                 :           0 :           return;
    1907                 :             :         }
    1908                 :             : 
    1909                 :      268416 :       if (!aa_walking_limit)
    1910                 :             :         {
    1911                 :           0 :           disqualify_split_candidate (desc, "Out of alias analysis step "
    1912                 :             :                                       "limit.");
    1913                 :           0 :           return;
    1914                 :             :         }
    1915                 :             : 
    1916                 :      536832 :       gcc_checking_assert (gimple_vuse (stmt));
    1917                 :      268416 :       bool maybe_modified = false;
    1918                 :      268416 :       ao_ref ar;
    1919                 :             : 
    1920                 :      268416 :       ao_ref_init (&ar, expr);
    1921                 :      268416 :       bitmap visited = BITMAP_ALLOC (NULL);
    1922                 :      536832 :       int walked = walk_aliased_vdefs (&ar, gimple_vuse (stmt),
    1923                 :             :                                        mark_maybe_modified, &maybe_modified,
    1924                 :             :                                        &visited, NULL, aa_walking_limit);
    1925                 :      268416 :       BITMAP_FREE (visited);
    1926                 :      268416 :       if (walked > 0)
    1927                 :             :         {
    1928                 :       89342 :           gcc_assert (aa_walking_limit > walked);
    1929                 :       89342 :           aa_walking_limit = aa_walking_limit - walked;
    1930                 :             :         }
    1931                 :      268416 :       if (walked < 0)
    1932                 :           0 :         aa_walking_limit = 0;
    1933                 :      268416 :       if (maybe_modified || walked < 0)
    1934                 :             :         {
    1935                 :       50695 :           disqualify_split_candidate (desc, "Data passed by reference possibly "
    1936                 :             :                                       "modified through an alias.");
    1937                 :       50695 :           return;
    1938                 :             :         }
    1939                 :             :       else
    1940                 :      217721 :         mark_param_dereference (desc, offset + size, bb);
    1941                 :             :     }
    1942                 :             :   else
    1943                 :             :     /* Pointer parameters with direct uses should have been ruled out by
    1944                 :             :        analyzing SSA default def when looking at the parameters.  */
    1945                 :      242037 :     gcc_assert (!desc->by_ref);
    1946                 :             : 
    1947                 :      459758 :   gensum_param_access *access = get_access (desc, offset, size, ctx);
    1948                 :      459758 :   if (!access)
    1949                 :             :     return;
    1950                 :             : 
    1951                 :      453493 :   if (ctx == ISRA_CTX_ARG)
    1952                 :             :     {
    1953                 :       78021 :       gcc_checking_assert (call_info);
    1954                 :             : 
    1955                 :       78021 :       if (!deref)
    1956                 :       75614 :         record_nonregister_call_use (desc, call_info, offset / BITS_PER_UNIT,
    1957                 :       75614 :                                      size / BITS_PER_UNIT);
    1958                 :             :       else
    1959                 :             :         /* This is not a pass-through of a pointer, this is a use like any
    1960                 :             :            other.  */
    1961                 :        2407 :         access->nonarg = true;
    1962                 :             :     }
    1963                 :      375472 :   else if (ctx == ISRA_CTX_LOAD && bb->count.initialized_p ())
    1964                 :      363762 :     access->load_count += bb->count;
    1965                 :             : 
    1966                 :      453493 :   if (!access->type)
    1967                 :             :     {
    1968                 :      395406 :       access->type = type;
    1969                 :      395406 :       access->alias_ptr_type = reference_alias_ptr_type (expr);
    1970                 :      395406 :       access->reverse = reverse;
    1971                 :             :     }
    1972                 :             :   else
    1973                 :             :     {
    1974                 :       58087 :       if (exp_align < TYPE_ALIGN (access->type))
    1975                 :             :         {
    1976                 :           0 :           disqualify_split_candidate (desc, "Reference has lower alignment "
    1977                 :             :                                       "than a previous one.");
    1978                 :           0 :           return;
    1979                 :             :         }
    1980                 :       58087 :       if (access->alias_ptr_type != reference_alias_ptr_type (expr))
    1981                 :             :         {
    1982                 :        2516 :           disqualify_split_candidate (desc, "Multiple alias pointer types.");
    1983                 :        2516 :           return;
    1984                 :             :         }
    1985                 :       55571 :       if (access->reverse != reverse)
    1986                 :             :         {
    1987                 :           0 :           disqualify_split_candidate (desc, "Both normal and reverse "
    1988                 :             :                                       "scalar storage order.");
    1989                 :           0 :           return;
    1990                 :             :         }
    1991                 :       55571 :       if (!deref
    1992                 :       42606 :           && (AGGREGATE_TYPE_P (type) || AGGREGATE_TYPE_P (access->type))
    1993                 :       87050 :           && (TYPE_MAIN_VARIANT (access->type) != TYPE_MAIN_VARIANT (type)))
    1994                 :             :         {
    1995                 :             :           /* We need the same aggregate type on all accesses to be able to
    1996                 :             :              distinguish transformation spots from pass-through arguments in
    1997                 :             :              the transformation phase.  */
    1998                 :        2679 :           disqualify_split_candidate (desc, "We do not support aggregate "
    1999                 :             :                                       "type punning.");
    2000                 :        2679 :           return;
    2001                 :             :         }
    2002                 :             : 
    2003                 :       52892 :       if (type_prevails_p (access->type, type))
    2004                 :          29 :          access->type = type;
    2005                 :             :     }
    2006                 :             : }
    2007                 :             : 
    2008                 :             : /* Scan body function described by NODE and FUN and create access trees for
    2009                 :             :    parameters.  */
    2010                 :             : 
    2011                 :             : static void
    2012                 :     1183850 : scan_function (cgraph_node *node, struct function *fun)
    2013                 :             : {
    2014                 :     1183850 :   basic_block bb;
    2015                 :             : 
    2016                 :     9454133 :   FOR_EACH_BB_FN (bb, fun)
    2017                 :             :     {
    2018                 :     8270283 :       gimple_stmt_iterator gsi;
    2019                 :    62376832 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    2020                 :             :         {
    2021                 :    45836266 :           gimple *stmt = gsi_stmt (gsi);
    2022                 :             : 
    2023                 :    45836266 :           if (final_bbs && stmt_can_throw_external (fun, stmt))
    2024                 :     1257585 :             bitmap_set_bit (final_bbs, bb->index);
    2025                 :    45836266 :           switch (gimple_code (stmt))
    2026                 :             :             {
    2027                 :     1153899 :             case GIMPLE_RETURN:
    2028                 :     1153899 :               {
    2029                 :     1153899 :                 tree t = gimple_return_retval (as_a <greturn *> (stmt));
    2030                 :     1153899 :                 if (t != NULL_TREE)
    2031                 :      635440 :                   scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
    2032                 :     1153899 :                 if (final_bbs)
    2033                 :      379209 :                   bitmap_set_bit (final_bbs, bb->index);
    2034                 :             :               }
    2035                 :             :               break;
    2036                 :             : 
    2037                 :    16854956 :             case GIMPLE_ASSIGN:
    2038                 :    16854956 :               if (gimple_assign_single_p (stmt)
    2039                 :    16854956 :                   && !gimple_clobber_p (stmt))
    2040                 :             :                 {
    2041                 :    10274837 :                   tree rhs = gimple_assign_rhs1 (stmt);
    2042                 :    10274837 :                   scan_expr_access (rhs, stmt, ISRA_CTX_LOAD, bb);
    2043                 :    10274837 :                   tree lhs = gimple_assign_lhs (stmt);
    2044                 :    10274837 :                   scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
    2045                 :             :                 }
    2046                 :             :               break;
    2047                 :             : 
    2048                 :     4877012 :             case GIMPLE_CALL:
    2049                 :     4877012 :               {
    2050                 :     4877012 :                 unsigned argument_count = gimple_call_num_args (stmt);
    2051                 :     4877012 :                 isra_scan_context ctx = ISRA_CTX_ARG;
    2052                 :     4877012 :                 scan_call_info call_info, *call_info_p = &call_info;
    2053                 :     4877012 :                 if (gimple_call_internal_p (stmt))
    2054                 :             :                   {
    2055                 :      149190 :                     call_info_p = NULL;
    2056                 :      149190 :                     ctx = ISRA_CTX_LOAD;
    2057                 :      149190 :                     internal_fn ifn = gimple_call_internal_fn (stmt);
    2058                 :      149190 :                     if (internal_store_fn_p (ifn))
    2059                 :           0 :                       ctx = ISRA_CTX_STORE;
    2060                 :             :                   }
    2061                 :             :                 else
    2062                 :             :                   {
    2063                 :     4727822 :                     call_info.cs = node->get_edge (stmt);
    2064                 :     4727822 :                     call_info.argument_count = argument_count;
    2065                 :             :                   }
    2066                 :             : 
    2067                 :    14782020 :                 for (unsigned i = 0; i < argument_count; i++)
    2068                 :             :                   {
    2069                 :     9905008 :                     call_info.arg_idx = i;
    2070                 :     9905008 :                     scan_expr_access (gimple_call_arg (stmt, i), stmt,
    2071                 :             :                                       ctx, bb, call_info_p);
    2072                 :             :                   }
    2073                 :             : 
    2074                 :     4877012 :                 tree lhs = gimple_call_lhs (stmt);
    2075                 :     4877012 :                 if (lhs)
    2076                 :     2021292 :                   scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
    2077                 :     4877012 :                 int flags = gimple_call_flags (stmt);
    2078                 :     4877012 :                 if (final_bbs
    2079                 :     1926767 :                     && (((flags & (ECF_CONST | ECF_PURE)) == 0)
    2080                 :      266351 :                         || (flags & ECF_LOOPING_CONST_OR_PURE)))
    2081                 :     1679450 :                   bitmap_set_bit (final_bbs, bb->index);
    2082                 :             :               }
    2083                 :     4877012 :               break;
    2084                 :             : 
    2085                 :       53266 :             case GIMPLE_ASM:
    2086                 :       53266 :               {
    2087                 :       53266 :                 gasm *asm_stmt = as_a <gasm *> (stmt);
    2088                 :       53266 :                 walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
    2089                 :             :                                                asm_visit_addr);
    2090                 :       53266 :                 if (final_bbs)
    2091                 :        1361 :                   bitmap_set_bit (final_bbs, bb->index);
    2092                 :             : 
    2093                 :       94198 :                 for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
    2094                 :             :                   {
    2095                 :       40932 :                     tree t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
    2096                 :       40932 :                     scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
    2097                 :             :                   }
    2098                 :      121065 :                 for (unsigned i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
    2099                 :             :                   {
    2100                 :       67799 :                     tree t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
    2101                 :       67799 :                     scan_expr_access (t, stmt, ISRA_CTX_STORE, bb);
    2102                 :             :                   }
    2103                 :             :               }
    2104                 :             :               break;
    2105                 :             : 
    2106                 :             :             default:
    2107                 :             :               break;
    2108                 :             :             }
    2109                 :             :         }
    2110                 :             :     }
    2111                 :     1183850 : }
    2112                 :             : 
    2113                 :             : /* Return true if SSA_NAME NAME of function described by FUN is only used in
    2114                 :             :    return statements, or if results of any operations it is involved in are
    2115                 :             :    only used in return statements.  ANALYZED is a bitmap that tracks which SSA
    2116                 :             :    names we have already started investigating.  */
    2117                 :             : 
    2118                 :             : static bool
    2119                 :     2299365 : ssa_name_only_returned_p (function *fun, tree name, bitmap analyzed)
    2120                 :             : {
    2121                 :     2299365 :   bool res = true;
    2122                 :     2299365 :   imm_use_iterator imm_iter;
    2123                 :     2299365 :   gimple *stmt;
    2124                 :             : 
    2125                 :     2906066 :   FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
    2126                 :             :     {
    2127                 :     2510969 :       if (is_gimple_debug (stmt))
    2128                 :      172440 :         continue;
    2129                 :             : 
    2130                 :     2338529 :       if (gimple_code (stmt) == GIMPLE_RETURN)
    2131                 :             :         {
    2132                 :      236077 :           tree t = gimple_return_retval (as_a <greturn *> (stmt));
    2133                 :      236077 :           if (t != name)
    2134                 :             :             {
    2135                 :             :               res = false;
    2136                 :             :               break;
    2137                 :             :             }
    2138                 :             :         }
    2139                 :     2102452 :       else if (!stmt_unremovable_because_of_non_call_eh_p (fun, stmt)
    2140                 :     2102452 :                && ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
    2141                 :     1083802 :                    || gimple_code (stmt) == GIMPLE_PHI))
    2142                 :             :         {
    2143                 :             :           /* TODO: And perhaps for const function calls too?  */
    2144                 :     1128794 :           tree lhs;
    2145                 :     1128794 :           if (gimple_code (stmt) == GIMPLE_PHI)
    2146                 :      198319 :             lhs = gimple_phi_result (stmt);
    2147                 :             :           else
    2148                 :      930475 :             lhs = gimple_assign_lhs (stmt);
    2149                 :             : 
    2150                 :     1128794 :           if (TREE_CODE (lhs) != SSA_NAME)
    2151                 :             :             {
    2152                 :             :               res = false;
    2153                 :             :               break;
    2154                 :             :             }
    2155                 :      790773 :           gcc_assert (!gimple_vdef (stmt));
    2156                 :      790773 :           if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs))
    2157                 :      790773 :               && !ssa_name_only_returned_p (fun, lhs, analyzed))
    2158                 :             :             {
    2159                 :             :               res = false;
    2160                 :             :               break;
    2161                 :             :             }
    2162                 :             :         }
    2163                 :             :       else
    2164                 :             :         {
    2165                 :             :           res = false;
    2166                 :             :           break;
    2167                 :             :         }
    2168                 :     2299365 :     }
    2169                 :     2299365 :   return res;
    2170                 :             : }
    2171                 :             : 
    2172                 :             : /* Inspect the uses of the return value of the call associated with CS, and if
    2173                 :             :    it is not used or if it is only used to construct the return value of the
    2174                 :             :    caller, mark it as such in call or caller summary.  Also check for
    2175                 :             :    misaligned arguments.  */
    2176                 :             : 
    2177                 :             : static void
    2178                 :     4727822 : isra_analyze_call (cgraph_edge *cs)
    2179                 :             : {
    2180                 :     4727822 :   gcall *call_stmt = cs->call_stmt;
    2181                 :     4727822 :   unsigned count = gimple_call_num_args (call_stmt);
    2182                 :     4727822 :   isra_call_summary *csum = call_sums->get_create (cs);
    2183                 :             : 
    2184                 :    14132860 :   for (unsigned i = 0; i < count; i++)
    2185                 :             :     {
    2186                 :     9405038 :       tree arg = gimple_call_arg (call_stmt, i);
    2187                 :     9405038 :       if (TREE_CODE (arg) == ADDR_EXPR)
    2188                 :             :         {
    2189                 :     2887369 :           poly_int64 poffset, psize, pmax_size;
    2190                 :     2887369 :           bool reverse;
    2191                 :     2887369 :           tree base = get_ref_base_and_extent (TREE_OPERAND (arg, 0), &poffset,
    2192                 :     2887369 :                                                &psize, &pmax_size, &reverse);
    2193                 :     2887369 :           HOST_WIDE_INT offset;
    2194                 :     2887369 :           unsigned HOST_WIDE_INT ds;
    2195                 :     2887369 :           if (DECL_P (base)
    2196                 :     2106161 :               && (poffset.is_constant (&offset))
    2197                 :     2106161 :               && tree_fits_uhwi_p (DECL_SIZE (base))
    2198                 :     4873193 :               && ((ds = tree_to_uhwi (DECL_SIZE (base)) - offset)
    2199                 :             :                   < ISRA_ARG_SIZE_LIMIT * BITS_PER_UNIT))
    2200                 :             :             {
    2201                 :     1852370 :               csum->init_inputs (count);
    2202                 :     1852370 :               gcc_assert (!csum->m_arg_flow[i].aggregate_pass_through);
    2203                 :     1852370 :               csum->m_arg_flow[i].unit_size = ds / BITS_PER_UNIT;
    2204                 :             :             }
    2205                 :             : 
    2206                 :     2887369 :           if (TREE_CODE (base) == VAR_DECL
    2207                 :     2887369 :               && !TREE_STATIC (base)
    2208                 :     2887369 :               && !loaded_decls->contains (base))
    2209                 :             :             {
    2210                 :      779853 :               csum->init_inputs (count);
    2211                 :      779853 :               csum->m_arg_flow[i].constructed_for_calls = true;
    2212                 :             :             }
    2213                 :             :         }
    2214                 :             : 
    2215                 :     9405038 :       if (is_gimple_reg (arg))
    2216                 :     3805887 :         continue;
    2217                 :             : 
    2218                 :     5599151 :       tree offset;
    2219                 :     5599151 :       poly_int64 bitsize, bitpos;
    2220                 :     5599151 :       machine_mode mode;
    2221                 :     5599151 :       int unsignedp, reversep, volatilep = 0;
    2222                 :     5599151 :       get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
    2223                 :             :                            &unsignedp, &reversep, &volatilep);
    2224                 :    11198302 :       if (!multiple_p (bitpos, BITS_PER_UNIT))
    2225                 :             :         {
    2226                 :           0 :           csum->m_bit_aligned_arg = true;
    2227                 :           0 :           break;
    2228                 :             :         }
    2229                 :             :     }
    2230                 :             : 
    2231                 :     4727822 :   tree lhs = gimple_call_lhs (call_stmt);
    2232                 :     4727822 :   if (lhs)
    2233                 :             :     {
    2234                 :             :       /* TODO: Also detect aggregates on a LHS of a call that are only returned
    2235                 :             :          from this function (without being read anywhere).  */
    2236                 :     1888345 :       if (TREE_CODE (lhs) == SSA_NAME)
    2237                 :             :         {
    2238                 :     1527869 :           bitmap analyzed = BITMAP_ALLOC (NULL);
    2239                 :     1527869 :           if (ssa_name_only_returned_p (DECL_STRUCT_FUNCTION (cs->caller->decl),
    2240                 :             :                                         lhs, analyzed))
    2241                 :      216190 :             csum->m_return_returned = true;
    2242                 :     1527869 :           BITMAP_FREE (analyzed);
    2243                 :             :         }
    2244                 :             :     }
    2245                 :             :   else
    2246                 :     2839477 :     csum->m_return_ignored = true;
    2247                 :     4727822 : }
    2248                 :             : 
    2249                 :             : /* Look at all calls going out of NODE, described also by IFS and perform all
    2250                 :             :    analyses necessary for IPA-SRA that are not done at body scan time or done
    2251                 :             :    even when body is not scanned because the function is not a candidate.  */
    2252                 :             : 
    2253                 :             : static void
    2254                 :     1183850 : isra_analyze_all_outgoing_calls (cgraph_node *node)
    2255                 :             : {
    2256                 :     5779200 :   for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
    2257                 :     4595350 :     isra_analyze_call (cs);
    2258                 :     1316322 :   for (cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
    2259                 :      132472 :     isra_analyze_call (cs);
    2260                 :     1183850 : }
    2261                 :             : 
    2262                 :             : /* Dump a dereferences table with heading STR to file F.  */
    2263                 :             : 
    2264                 :             : static void
    2265                 :          10 : dump_dereferences_table (FILE *f, struct function *fun, const char *str)
    2266                 :             : {
    2267                 :          10 :   basic_block bb;
    2268                 :             : 
    2269                 :          10 :   fprintf (dump_file, "%s", str);
    2270                 :          52 :   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (fun),
    2271                 :             :                   EXIT_BLOCK_PTR_FOR_FN (fun), next_bb)
    2272                 :             :     {
    2273                 :          42 :       fprintf (f, "%4i  %i   ", bb->index, bitmap_bit_p (final_bbs, bb->index));
    2274                 :          42 :       if (bb != EXIT_BLOCK_PTR_FOR_FN (fun))
    2275                 :             :         {
    2276                 :             :           int i;
    2277                 :         104 :           for (i = 0; i < unsafe_by_ref_count; i++)
    2278                 :             :             {
    2279                 :          62 :               int idx = bb->index * unsafe_by_ref_count + i;
    2280                 :          62 :               fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", bb_dereferences[idx]);
    2281                 :             :             }
    2282                 :             :         }
    2283                 :          42 :       fprintf (f, "\n");
    2284                 :             :     }
    2285                 :          10 :   fprintf (dump_file, "\n");
    2286                 :          10 : }
    2287                 :             : 
    2288                 :             : /* Propagate distances in bb_dereferences in the opposite direction than the
    2289                 :             :    control flow edges, in each step storing the maximum of the current value
    2290                 :             :    and the minimum of all successors.  These steps are repeated until the table
    2291                 :             :    stabilizes.  Note that BBs which might terminate the functions (according to
    2292                 :             :    final_bbs bitmap) never updated in this way.  */
    2293                 :             : 
    2294                 :             : static void
    2295                 :       24540 : propagate_dereference_distances (struct function *fun)
    2296                 :             : {
    2297                 :       24540 :   basic_block bb;
    2298                 :             : 
    2299                 :       24540 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2300                 :           5 :     dump_dereferences_table (dump_file, fun,
    2301                 :             :                              "Dereference table before propagation:\n");
    2302                 :             : 
    2303                 :       24540 :   auto_vec<basic_block> queue (last_basic_block_for_fn (fun));
    2304                 :       24540 :   queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (fun));
    2305                 :      195355 :   FOR_EACH_BB_FN (bb, fun)
    2306                 :             :     {
    2307                 :      170815 :       queue.quick_push (bb);
    2308                 :      170815 :       bb->aux = bb;
    2309                 :             :     }
    2310                 :             : 
    2311                 :      220694 :   while (!queue.is_empty ())
    2312                 :             :     {
    2313                 :      196154 :       edge_iterator ei;
    2314                 :      196154 :       edge e;
    2315                 :      196154 :       bool change = false;
    2316                 :      196154 :       int i;
    2317                 :             : 
    2318                 :      196154 :       bb = queue.pop ();
    2319                 :      196154 :       bb->aux = NULL;
    2320                 :             : 
    2321                 :      196154 :       if (bitmap_bit_p (final_bbs, bb->index))
    2322                 :       62240 :         continue;
    2323                 :             : 
    2324                 :     5920492 :       for (i = 0; i < unsafe_by_ref_count; i++)
    2325                 :             :         {
    2326                 :     5786578 :           int idx = bb->index * unsafe_by_ref_count + i;
    2327                 :     5786578 :           bool first = true;
    2328                 :     5786578 :           HOST_WIDE_INT inh = 0;
    2329                 :             : 
    2330                 :    13539754 :           FOR_EACH_EDGE (e, ei, bb->succs)
    2331                 :             :           {
    2332                 :     7753176 :             int succ_idx = e->dest->index * unsafe_by_ref_count + i;
    2333                 :             : 
    2334                 :     7753176 :             if (e->dest == EXIT_BLOCK_PTR_FOR_FN (fun))
    2335                 :           0 :               continue;
    2336                 :             : 
    2337                 :     7753176 :             if (first)
    2338                 :             :               {
    2339                 :     5786573 :                 first = false;
    2340                 :     5786573 :                 inh = bb_dereferences [succ_idx];
    2341                 :             :               }
    2342                 :     1966603 :             else if (bb_dereferences [succ_idx] < inh)
    2343                 :             :               inh = bb_dereferences [succ_idx];
    2344                 :             :           }
    2345                 :             : 
    2346                 :     5786578 :           if (!first && bb_dereferences[idx] < inh)
    2347                 :             :             {
    2348                 :        9649 :               bb_dereferences[idx] = inh;
    2349                 :        9649 :               change = true;
    2350                 :             :             }
    2351                 :             :         }
    2352                 :             : 
    2353                 :      133914 :       if (change)
    2354                 :       10774 :         FOR_EACH_EDGE (e, ei, bb->preds)
    2355                 :             :           {
    2356                 :        1688 :             if (e->src->aux)
    2357                 :         889 :               continue;
    2358                 :             : 
    2359                 :         799 :             e->src->aux = e->src;
    2360                 :         799 :             queue.quick_push (e->src);
    2361                 :             :           }
    2362                 :             :     }
    2363                 :             : 
    2364                 :       24540 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2365                 :           5 :     dump_dereferences_table (dump_file, fun,
    2366                 :             :                              "Dereference table after propagation:\n");
    2367                 :       24540 : }
    2368                 :             : 
    2369                 :             : /* Return true if the ACCESS loads happen frequently enough in FUN to risk
    2370                 :             :    moving them to the caller and only pass the result.  */
    2371                 :             : 
    2372                 :             : static bool
    2373                 :      154667 : dereference_probable_p (struct function *fun, gensum_param_access *access)
    2374                 :             : {
    2375                 :      154667 :   int threshold = opt_for_fn (fun->decl, param_ipa_sra_deref_prob_threshold);
    2376                 :      154667 :   return access->load_count
    2377                 :      154667 :     >= ENTRY_BLOCK_PTR_FOR_FN (fun)->count.apply_scale (threshold, 100);
    2378                 :             : }
    2379                 :             : 
    2380                 :             : /* Perform basic checks on ACCESS to PARM (of FUN) described by DESC and all
    2381                 :             :    its children, return true if the parameter cannot be split, otherwise return
    2382                 :             :    false and update *NONARG_ACC_SIZE and *ONLY_CALLS.  ENTRY_BB_INDEX must be
    2383                 :             :    the index of the entry BB in the function of PARM.  */
    2384                 :             : 
    2385                 :             : static bool
    2386                 :      346137 : check_gensum_access (struct function *fun, tree parm, gensum_param_desc *desc,
    2387                 :             :                      gensum_param_access *access,
    2388                 :             :                      HOST_WIDE_INT *nonarg_acc_size, bool *only_calls,
    2389                 :             :                      int entry_bb_index)
    2390                 :             : {
    2391                 :      346137 :   if (access->nonarg)
    2392                 :             :     {
    2393                 :      298204 :       *only_calls = false;
    2394                 :      298204 :       *nonarg_acc_size += access->size;
    2395                 :             : 
    2396                 :      298204 :       if (access->first_child)
    2397                 :             :         {
    2398                 :         373 :           disqualify_split_candidate (desc, "Overlapping non-call uses.");
    2399                 :         373 :           return true;
    2400                 :             :         }
    2401                 :             :     }
    2402                 :             :   /* Do not decompose a non-BLKmode param in a way that would create
    2403                 :             :      BLKmode params.  Especially for by-reference passing (thus,
    2404                 :             :      pointer-type param) this is hardly worthwhile.  */
    2405                 :      345764 :   if (DECL_MODE (parm) != BLKmode
    2406                 :      345764 :       && TYPE_MODE (access->type) == BLKmode)
    2407                 :             :     {
    2408                 :        2787 :       disqualify_split_candidate (desc, "Would convert a non-BLK to a BLK.");
    2409                 :        2787 :       return true;
    2410                 :             :     }
    2411                 :             : 
    2412                 :      342977 :   if (desc->by_ref)
    2413                 :             :     {
    2414                 :      164521 :       if (desc->safe_ref)
    2415                 :             :         {
    2416                 :      133127 :           if (!dereference_probable_p (fun, access))
    2417                 :             :             {
    2418                 :        5828 :               disqualify_split_candidate (desc, "Dereferences in callers "
    2419                 :             :                                           "would happen much more frequently.");
    2420                 :        5828 :               return true;
    2421                 :             :             }
    2422                 :             :         }
    2423                 :             :       else
    2424                 :             :         {
    2425                 :       31394 :           int idx = (entry_bb_index * unsafe_by_ref_count + desc->deref_index);
    2426                 :       31394 :           if ((access->offset + access->size) > bb_dereferences[idx])
    2427                 :             :             {
    2428                 :       21540 :               if (!dereference_probable_p (fun, access))
    2429                 :             :                 {
    2430                 :        1509 :                   disqualify_split_candidate (desc, "Would create a possibly "
    2431                 :             :                                               "illegal dereference in a "
    2432                 :             :                                               "caller.");
    2433                 :        1509 :                   return true;
    2434                 :             :                 }
    2435                 :       20031 :               desc->conditionally_dereferenceable = true;
    2436                 :             :             }
    2437                 :             :         }
    2438                 :             :     }
    2439                 :             : 
    2440                 :      335640 :   for (gensum_param_access *ch = access->first_child;
    2441                 :      355503 :        ch;
    2442                 :       19863 :        ch = ch->next_sibling)
    2443                 :       19870 :     if (check_gensum_access (fun, parm, desc, ch, nonarg_acc_size, only_calls,
    2444                 :             :                              entry_bb_index))
    2445                 :             :       return true;
    2446                 :             : 
    2447                 :             :   return false;
    2448                 :             : }
    2449                 :             : 
    2450                 :             : /* Copy data from FROM and all of its children to a vector of accesses in IPA
    2451                 :             :    descriptor DESC.  */
    2452                 :             : 
    2453                 :             : static void
    2454                 :      395406 : copy_accesses_to_ipa_desc (gensum_param_access *from, isra_param_desc *desc)
    2455                 :             : {
    2456                 :      395406 :   param_access *to = ggc_cleared_alloc<param_access> ();
    2457                 :      395406 :   gcc_checking_assert ((from->offset % BITS_PER_UNIT) == 0);
    2458                 :      395406 :   gcc_checking_assert ((from->size % BITS_PER_UNIT) == 0);
    2459                 :      395406 :   to->unit_offset = from->offset / BITS_PER_UNIT;
    2460                 :      395406 :   to->unit_size = from->size / BITS_PER_UNIT;
    2461                 :      395406 :   to->type = from->type;
    2462                 :      395406 :   to->alias_ptr_type = from->alias_ptr_type;
    2463                 :      395406 :   to->certain = from->nonarg;
    2464                 :      395406 :   to->reverse = from->reverse;
    2465                 :      395406 :   vec_safe_push (desc->accesses, to);
    2466                 :             : 
    2467                 :      395406 :   for (gensum_param_access *ch = from->first_child;
    2468                 :      417684 :        ch;
    2469                 :       22278 :        ch = ch->next_sibling)
    2470                 :       22278 :     copy_accesses_to_ipa_desc (ch, desc);
    2471                 :      395406 : }
    2472                 :             : 
    2473                 :             : /* Analyze function body scan results stored in param_accesses and
    2474                 :             :    param_accesses, detect possible transformations and store information of
    2475                 :             :    those in function summary.  NODE, FUN and IFS are all various structures
    2476                 :             :    describing the currently analyzed function.  */
    2477                 :             : 
    2478                 :             : static void
    2479                 :      777378 : process_scan_results (cgraph_node *node, struct function *fun,
    2480                 :             :                       isra_func_summary *ifs,
    2481                 :             :                       vec<gensum_param_desc> *param_descriptions)
    2482                 :             : {
    2483                 :      777378 :   bool check_pass_throughs = false;
    2484                 :      777378 :   bool dereferences_propagated = false;
    2485                 :      777378 :   tree parm = DECL_ARGUMENTS (node->decl);
    2486                 :      777378 :   unsigned param_count = param_descriptions->length();
    2487                 :             : 
    2488                 :      777378 :   for (unsigned desc_index = 0;
    2489                 :     3004559 :        desc_index < param_count;
    2490                 :     2227181 :        desc_index++, parm = DECL_CHAIN (parm))
    2491                 :             :     {
    2492                 :     2227181 :       gensum_param_desc *desc = &(*param_descriptions)[desc_index];
    2493                 :     2227181 :       if (!desc->split_candidate)
    2494                 :     1755868 :         continue;
    2495                 :             : 
    2496                 :      481810 :       if (flag_checking)
    2497                 :      481802 :         isra_verify_access_tree (desc->accesses);
    2498                 :             : 
    2499                 :      481810 :       if (!dereferences_propagated
    2500                 :      476426 :           && desc->by_ref
    2501                 :      337461 :           && !desc->safe_ref
    2502                 :      158662 :           && desc->accesses)
    2503                 :             :         {
    2504                 :       24540 :           propagate_dereference_distances (fun);
    2505                 :       24540 :           dereferences_propagated = true;
    2506                 :             :         }
    2507                 :             : 
    2508                 :      481810 :       HOST_WIDE_INT nonarg_acc_size = 0;
    2509                 :      481810 :       bool only_calls = true;
    2510                 :      481810 :       bool check_failed = false;
    2511                 :             : 
    2512                 :      481810 :       int entry_bb_index = ENTRY_BLOCK_PTR_FOR_FN (fun)->index;
    2513                 :      481810 :       for (gensum_param_access *acc = desc->accesses;
    2514                 :      797580 :            acc;
    2515                 :      315770 :            acc = acc->next_sibling)
    2516                 :      326267 :         if (check_gensum_access (fun, parm, desc, acc, &nonarg_acc_size,
    2517                 :             :                                  &only_calls, entry_bb_index))
    2518                 :             :           {
    2519                 :             :             check_failed = true;
    2520                 :             :             break;
    2521                 :             :           }
    2522                 :      481810 :       if (check_failed)
    2523                 :       10497 :         continue;
    2524                 :             : 
    2525                 :      471313 :       if (only_calls)
    2526                 :      292588 :         desc->locally_unused = true;
    2527                 :             : 
    2528                 :      471313 :       HOST_WIDE_INT cur_param_size
    2529                 :      471313 :         = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
    2530                 :      471313 :       HOST_WIDE_INT param_size_limit, optimistic_limit;
    2531                 :      471313 :       if (!desc->by_ref || optimize_function_for_size_p (fun))
    2532                 :             :         {
    2533                 :             :           param_size_limit = cur_param_size;
    2534                 :             :           optimistic_limit = cur_param_size;
    2535                 :             :         }
    2536                 :             :       else
    2537                 :             :         {
    2538                 :      311842 :           param_size_limit
    2539                 :      311842 :             = opt_for_fn (node->decl,
    2540                 :             :                           param_ipa_sra_ptr_growth_factor) * cur_param_size;
    2541                 :      311842 :           optimistic_limit
    2542                 :      311842 :             = (opt_for_fn (node->decl, param_ipa_sra_ptrwrap_growth_factor)
    2543                 :             :                * param_size_limit);
    2544                 :             :         }
    2545                 :             : 
    2546                 :      471313 :       if (nonarg_acc_size > optimistic_limit
    2547                 :      469449 :           || (!desc->by_ref && nonarg_acc_size == param_size_limit))
    2548                 :             :         {
    2549                 :       62882 :           disqualify_split_candidate (desc, "Would result into a too big set "
    2550                 :             :                                       "of replacements even in best "
    2551                 :             :                                       "scenarios.");
    2552                 :             :         }
    2553                 :             :       else
    2554                 :             :         {
    2555                 :             :           /* create_parameter_descriptors makes sure unit sizes of all
    2556                 :             :              candidate parameters fit unsigned integers restricted to
    2557                 :             :              ISRA_ARG_SIZE_LIMIT.  */
    2558                 :      408431 :           desc->param_size_limit = param_size_limit / BITS_PER_UNIT;
    2559                 :      408431 :           desc->nonarg_acc_size = nonarg_acc_size / BITS_PER_UNIT;
    2560                 :      408431 :           if (desc->split_candidate && desc->ptr_pt_count)
    2561                 :             :             {
    2562                 :      180986 :               gcc_assert (desc->by_ref);
    2563                 :             :               check_pass_throughs = true;
    2564                 :             :             }
    2565                 :             :         }
    2566                 :             :     }
    2567                 :             : 
    2568                 :             :   /* When a pointer parameter is passed-through to a callee, in which it is
    2569                 :             :      only used to read only one or a few items, we can attempt to transform it
    2570                 :             :      to obtaining and passing through the items instead of the pointer.  But we
    2571                 :             :      must take extra care that 1) we do not introduce any segfault by moving
    2572                 :             :      dereferences above control flow and that 2) the data is not modified
    2573                 :             :      through an alias in this function.  The IPA analysis must not introduce
    2574                 :             :      any accesses candidates unless it can prove both.
    2575                 :             : 
    2576                 :             :      The current solution is very crude as it consists of ensuring that the
    2577                 :             :      call postdominates entry BB and that the definition of VUSE of the call is
    2578                 :             :      default definition.  TODO: For non-recursive callees in the same
    2579                 :             :      compilation unit we could do better by doing analysis in topological order
    2580                 :             :      an looking into access candidates of callees, using their alias_ptr_types
    2581                 :             :      to attempt real AA.  We could also use the maximum known dereferenced
    2582                 :             :      offset in this function at IPA level.
    2583                 :             : 
    2584                 :             :      TODO: Measure the overhead and the effect of just being pessimistic.
    2585                 :             :      Maybe this is only -O3 material?  */
    2586                 :             : 
    2587                 :      777378 :   hash_map<gimple *, bool> analyzed_stmts;
    2588                 :      777378 :   bitmap always_executed_bbs = NULL;
    2589                 :      777378 :   if (check_pass_throughs)
    2590                 :     1142408 :     for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
    2591                 :             :       {
    2592                 :      998475 :         gcall *call_stmt = cs->call_stmt;
    2593                 :      998475 :         tree vuse = gimple_vuse (call_stmt);
    2594                 :             : 
    2595                 :             :         /* If the callee is a const function, we don't get a VUSE.  In such
    2596                 :             :            case there will be no memory accesses in the called function (or the
    2597                 :             :            const attribute is wrong) and then we just don't care.  */
    2598                 :     1983100 :         bool uses_memory_as_obtained = vuse && SSA_NAME_IS_DEFAULT_DEF (vuse);
    2599                 :             : 
    2600                 :      998475 :         unsigned count = gimple_call_num_args (call_stmt);
    2601                 :      998475 :         isra_call_summary *csum = call_sums->get_create (cs);
    2602                 :      998475 :         csum->init_inputs (count);
    2603                 :      998475 :         csum->m_before_any_store = uses_memory_as_obtained;
    2604                 :     3239710 :         for (unsigned argidx = 0; argidx < count; argidx++)
    2605                 :             :           {
    2606                 :     2241235 :             if (!csum->m_arg_flow[argidx].pointer_pass_through)
    2607                 :     4061183 :               continue;
    2608                 :      421287 :             unsigned pidx
    2609                 :      421287 :               = get_single_param_flow_source (&csum->m_arg_flow[argidx]);
    2610                 :      421287 :             gensum_param_desc *desc = &(*param_descriptions)[pidx];
    2611                 :      421287 :             if (!desc->split_candidate)
    2612                 :             :               {
    2613                 :       34637 :                 csum->m_arg_flow[argidx].pointer_pass_through = false;
    2614                 :       34637 :                 continue;
    2615                 :             :               }
    2616                 :      386650 :             if (!uses_memory_as_obtained)
    2617                 :      139384 :               continue;
    2618                 :             : 
    2619                 :      247266 :             if (desc->safe_ref)
    2620                 :             :               {
    2621                 :       47156 :                 csum->m_arg_flow[argidx].safe_to_import_accesses = true;
    2622                 :       47156 :                 continue;
    2623                 :             :               }
    2624                 :             : 
    2625                 :             :             /* Walk basic block and see if its execution can terminate earlier.
    2626                 :             :                Keep the info for later re-use to avoid quadratic behavoiur here.  */
    2627                 :      200110 :             gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
    2628                 :      200110 :             bool safe = true;
    2629                 :      200110 :             int n = 0;
    2630                 :      598634 :             for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
    2631                 :             :               {
    2632                 :      113767 :                 bool *b = analyzed_stmts.get (gsi_stmt (gsi));
    2633                 :      113767 :                 if (b)
    2634                 :             :                   {
    2635                 :        8786 :                     safe = *b;
    2636                 :        8786 :                     gsi_next (&gsi);
    2637                 :        8786 :                     break;
    2638                 :             :                   }
    2639                 :      104981 :                 n++;
    2640                 :      104981 :                 if (stmt_may_terminate_function_p (fun, gsi_stmt (gsi), false))
    2641                 :             :                   {
    2642                 :             :                     safe = false;
    2643                 :             :                     break;
    2644                 :             :                   }
    2645                 :             :               }
    2646                 :      200110 :             if (n)
    2647                 :             :               {
    2648                 :       32741 :                 if (gsi_end_p (gsi))
    2649                 :       53934 :                   gsi = gsi_start_bb (gimple_bb (call_stmt));
    2650                 :      137722 :                 for (; gsi_stmt (gsi) != call_stmt; gsi_next (&gsi))
    2651                 :      104981 :                   analyzed_stmts.get_or_insert (gsi_stmt (gsi)) = safe;
    2652                 :             :               }
    2653                 :             : 
    2654                 :      200110 :             if (safe && !always_executed_bbs)
    2655                 :             :               {
    2656                 :       54381 :                 mark_dfs_back_edges ();
    2657                 :       54381 :                 always_executed_bbs = find_always_executed_bbs (fun, false);
    2658                 :             :               }
    2659                 :      200110 :             if (safe && bitmap_bit_p (always_executed_bbs, gimple_bb (call_stmt)->index))
    2660                 :       44471 :               csum->m_arg_flow[argidx].safe_to_import_accesses = true;
    2661                 :             :           }
    2662                 :             : 
    2663                 :             :       }
    2664                 :      777378 :   BITMAP_FREE (always_executed_bbs);
    2665                 :             : 
    2666                 :             :   /* TODO: Add early exit if we disqualified everything.  This also requires
    2667                 :             :      that we either relax the restriction that
    2668                 :             :      ipa_param_adjustments.m_always_copy_start must be the number of PARM_DECLs
    2669                 :             :      or store the number of parameters to IPA-SRA function summary and use that
    2670                 :             :      when just removing params.  */
    2671                 :             : 
    2672                 :      777378 :   vec_safe_reserve_exact (ifs->m_parameters, param_count);
    2673                 :      777378 :   ifs->m_parameters->quick_grow_cleared (param_count);
    2674                 :     3004559 :   for (unsigned desc_index = 0; desc_index < param_count; desc_index++)
    2675                 :             :     {
    2676                 :     2227181 :       gensum_param_desc *s = &(*param_descriptions)[desc_index];
    2677                 :     2227181 :       isra_param_desc *d = &(*ifs->m_parameters)[desc_index];
    2678                 :             : 
    2679                 :     2227181 :       d->param_size_limit = s->param_size_limit;
    2680                 :     2227181 :       d->size_reached = s->nonarg_acc_size;
    2681                 :     2227181 :       d->locally_unused = s->locally_unused;
    2682                 :     2227181 :       d->split_candidate = s->split_candidate;
    2683                 :     2227181 :       d->by_ref = s->by_ref;
    2684                 :     2227181 :       d->remove_only_when_retval_removed = s->remove_only_when_retval_removed;
    2685                 :     2227181 :       d->split_only_when_retval_removed = s->split_only_when_retval_removed;
    2686                 :     2227181 :       d->conditionally_dereferenceable = s->conditionally_dereferenceable;
    2687                 :             : 
    2688                 :     2227181 :       for (gensum_param_access *acc = s->accesses;
    2689                 :     2600309 :            acc;
    2690                 :      373128 :            acc = acc->next_sibling)
    2691                 :      373128 :         copy_accesses_to_ipa_desc (acc, d);
    2692                 :             :     }
    2693                 :             : 
    2694                 :      777378 :   if (dump_file)
    2695                 :         143 :     dump_isra_param_descriptors (dump_file, node->decl, ifs, false);
    2696                 :      777378 : }
    2697                 :             : 
    2698                 :             : /* Return true if there are any overlaps among certain accesses of DESC.  If
    2699                 :             :    non-NULL, set *CERTAIN_ACCESS_PRESENT_P upon encountering a certain access
    2700                 :             :    too.  DESC is assumed to be a split candidate that is not locally
    2701                 :             :    unused.  */
    2702                 :             : 
    2703                 :             : static bool
    2704                 :      151189 : overlapping_certain_accesses_p (isra_param_desc *desc,
    2705                 :             :                                 bool *certain_access_present_p)
    2706                 :             : {
    2707                 :      151189 :   unsigned pclen = vec_safe_length (desc->accesses);
    2708                 :      395371 :   for (unsigned i = 0; i < pclen; i++)
    2709                 :             :     {
    2710                 :      245423 :       param_access *a1 = (*desc->accesses)[i];
    2711                 :             : 
    2712                 :      245423 :       if (!a1->certain)
    2713                 :        5182 :         continue;
    2714                 :      240241 :       if (certain_access_present_p)
    2715                 :      227792 :         *certain_access_present_p = true;
    2716                 :      382409 :       for (unsigned j = i + 1; j < pclen; j++)
    2717                 :             :         {
    2718                 :      143409 :           param_access *a2 = (*desc->accesses)[j];
    2719                 :      143409 :           if (a2->certain
    2720                 :      143330 :               && a1->unit_offset < a2->unit_offset + a2->unit_size
    2721                 :      142700 :               && a1->unit_offset + a1->unit_size > a2->unit_offset)
    2722                 :             :             return true;
    2723                 :             :         }
    2724                 :             :     }
    2725                 :             :   return false;
    2726                 :             : }
    2727                 :             : 
    2728                 :             : /* Check for any overlaps of certain param accesses among splitting candidates
    2729                 :             :    and signal an ICE if there are any.  If CERTAIN_MUST_EXIST is set, also
    2730                 :             :    check that used splitting candidates have at least one certain access.  */
    2731                 :             : 
    2732                 :             : static void
    2733                 :     2438981 : verify_splitting_accesses (cgraph_node *node, bool certain_must_exist)
    2734                 :             : {
    2735                 :     2438981 :   isra_func_summary *ifs = func_sums->get (node);
    2736                 :     2438981 :   if (!ifs || !ifs->m_candidate)
    2737                 :             :     return;
    2738                 :     1281592 :   unsigned param_count = vec_safe_length (ifs->m_parameters);
    2739                 :     4164545 :   for (unsigned pidx = 0; pidx < param_count; pidx++)
    2740                 :             :     {
    2741                 :     2882953 :       isra_param_desc *desc = &(*ifs->m_parameters)[pidx];
    2742                 :     2882953 :       if (!desc->split_candidate || desc->locally_unused)
    2743                 :     2744145 :         continue;
    2744                 :             : 
    2745                 :      138808 :       bool certain_access_present = !certain_must_exist;
    2746                 :      138808 :       if (overlapping_certain_accesses_p (desc, &certain_access_present))
    2747                 :           0 :         internal_error ("function %qs, parameter %u, has IPA-SRA accesses "
    2748                 :             :                         "which overlap", node->dump_name (), pidx);
    2749                 :      138808 :       if (!certain_access_present)
    2750                 :           0 :         internal_error ("function %qs, parameter %u, is used but does not "
    2751                 :             :                         "have any certain IPA-SRA access",
    2752                 :             :                         node->dump_name (), pidx);
    2753                 :             :     }
    2754                 :             : }
    2755                 :             : 
    2756                 :             : /* Intraprocedural part of IPA-SRA analysis.  Scan bodies of all functions in
    2757                 :             :    this compilation unit and create summary structures describing IPA-SRA
    2758                 :             :    opportunities and constraints in them.  */
    2759                 :             : 
    2760                 :             : static void
    2761                 :      119112 : ipa_sra_generate_summary (void)
    2762                 :             : {
    2763                 :      119112 :   struct cgraph_node *node;
    2764                 :             : 
    2765                 :      119112 :   gcc_checking_assert (!func_sums);
    2766                 :      119112 :   gcc_checking_assert (!call_sums);
    2767                 :      119112 :   func_sums
    2768                 :      119112 :     = (new (ggc_alloc_no_dtor <ipa_sra_function_summaries> ())
    2769                 :      119112 :        ipa_sra_function_summaries (symtab, true));
    2770                 :      119112 :   call_sums = new ipa_sra_call_summaries (symtab);
    2771                 :             : 
    2772                 :     1285874 :   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
    2773                 :     1166762 :     ipa_sra_summarize_function (node);
    2774                 :      119112 :   return;
    2775                 :             : }
    2776                 :             : 
    2777                 :             : /* Write intraprocedural analysis information about E and all of its outgoing
    2778                 :             :    edges into a stream for LTO WPA.  */
    2779                 :             : 
    2780                 :             : static void
    2781                 :      275605 : isra_write_edge_summary (output_block *ob, cgraph_edge *e)
    2782                 :             : {
    2783                 :      275605 :   isra_call_summary *csum = call_sums->get (e);
    2784                 :      275605 :   unsigned input_count = csum->m_arg_flow.length ();
    2785                 :      275605 :   streamer_write_uhwi (ob, input_count);
    2786                 :      748429 :   for (unsigned i = 0; i < input_count; i++)
    2787                 :             :     {
    2788                 :      472824 :       isra_param_flow *ipf = &csum->m_arg_flow[i];
    2789                 :      472824 :       streamer_write_hwi (ob, ipf->length);
    2790                 :      472824 :       bitpack_d bp = bitpack_create (ob->main_stream);
    2791                 :      548404 :       for (int j = 0; j < ipf->length; j++)
    2792                 :       75580 :         bp_pack_value (&bp, ipf->inputs[j], 8);
    2793                 :      472824 :       bp_pack_value (&bp, ipf->aggregate_pass_through, 1);
    2794                 :      472824 :       bp_pack_value (&bp, ipf->pointer_pass_through, 1);
    2795                 :      472824 :       bp_pack_value (&bp, ipf->safe_to_import_accesses, 1);
    2796                 :      472824 :       bp_pack_value (&bp, ipf->constructed_for_calls, 1);
    2797                 :      472824 :       streamer_write_bitpack (&bp);
    2798                 :      472824 :       streamer_write_uhwi (ob, ipf->unit_offset);
    2799                 :      472824 :       streamer_write_uhwi (ob, ipf->unit_size);
    2800                 :             :     }
    2801                 :      275605 :   bitpack_d bp = bitpack_create (ob->main_stream);
    2802                 :      275605 :   bp_pack_value (&bp, csum->m_return_ignored, 1);
    2803                 :      275605 :   bp_pack_value (&bp, csum->m_return_returned, 1);
    2804                 :      275605 :   bp_pack_value (&bp, csum->m_bit_aligned_arg, 1);
    2805                 :      275605 :   bp_pack_value (&bp, csum->m_before_any_store, 1);
    2806                 :      275605 :   streamer_write_bitpack (&bp);
    2807                 :      275605 : }
    2808                 :             : 
    2809                 :             : /* Write intraprocedural analysis information about NODE and all of its outgoing
    2810                 :             :    edges into a stream for LTO WPA.  */
    2811                 :             : 
    2812                 :             : static void
    2813                 :       45133 : isra_write_node_summary (output_block *ob, cgraph_node *node)
    2814                 :             : {
    2815                 :       45133 :   isra_func_summary *ifs = func_sums->get (node);
    2816                 :       45133 :   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
    2817                 :       45133 :   int node_ref = lto_symtab_encoder_encode (encoder, node);
    2818                 :       45133 :   streamer_write_uhwi (ob, node_ref);
    2819                 :             : 
    2820                 :       45133 :   unsigned param_desc_count = vec_safe_length (ifs->m_parameters);
    2821                 :       45133 :   streamer_write_uhwi (ob, param_desc_count);
    2822                 :      290849 :   for (unsigned i = 0; i < param_desc_count; i++)
    2823                 :             :     {
    2824                 :      245716 :       isra_param_desc *desc = &(*ifs->m_parameters)[i];
    2825                 :      245716 :       unsigned access_count = vec_safe_length (desc->accesses);
    2826                 :      245716 :       streamer_write_uhwi (ob, access_count);
    2827                 :      248571 :       for (unsigned j = 0; j < access_count; j++)
    2828                 :             :         {
    2829                 :        2855 :           param_access *acc = (*desc->accesses)[j];
    2830                 :        2855 :           stream_write_tree (ob, acc->type, true);
    2831                 :        2855 :           stream_write_tree (ob, acc->alias_ptr_type, true);
    2832                 :        2855 :           streamer_write_uhwi (ob, acc->unit_offset);
    2833                 :        2855 :           streamer_write_uhwi (ob, acc->unit_size);
    2834                 :        2855 :           bitpack_d bp = bitpack_create (ob->main_stream);
    2835                 :        2855 :           bp_pack_value (&bp, acc->certain, 1);
    2836                 :        2855 :           bp_pack_value (&bp, acc->reverse, 1);
    2837                 :        2855 :           streamer_write_bitpack (&bp);
    2838                 :             :         }
    2839                 :      245716 :       streamer_write_uhwi (ob, desc->param_size_limit);
    2840                 :      245716 :       streamer_write_uhwi (ob, desc->size_reached);
    2841                 :      245716 :       gcc_assert (desc->safe_size == 0);
    2842                 :      245716 :       bitpack_d bp = bitpack_create (ob->main_stream);
    2843                 :      245716 :       bp_pack_value (&bp, desc->locally_unused, 1);
    2844                 :      245716 :       bp_pack_value (&bp, desc->split_candidate, 1);
    2845                 :      245716 :       bp_pack_value (&bp, desc->by_ref, 1);
    2846                 :      245716 :       gcc_assert (!desc->not_specially_constructed);
    2847                 :      245716 :       bp_pack_value (&bp, desc->remove_only_when_retval_removed, 1);
    2848                 :      245716 :       bp_pack_value (&bp, desc->split_only_when_retval_removed, 1);
    2849                 :      245716 :       bp_pack_value (&bp, desc->conditionally_dereferenceable, 1);
    2850                 :      245716 :       gcc_assert (!desc->safe_size_set);
    2851                 :      245716 :       streamer_write_bitpack (&bp);
    2852                 :             :     }
    2853                 :       45133 :   bitpack_d bp = bitpack_create (ob->main_stream);
    2854                 :       45133 :   bp_pack_value (&bp, ifs->m_candidate, 1);
    2855                 :       45133 :   bp_pack_value (&bp, ifs->m_returns_value, 1);
    2856                 :       45133 :   bp_pack_value (&bp, ifs->m_return_ignored, 1);
    2857                 :       45133 :   gcc_assert (!ifs->m_queued);
    2858                 :       45133 :   streamer_write_bitpack (&bp);
    2859                 :             : 
    2860                 :      319161 :   for (cgraph_edge *e = node->callees; e; e = e->next_callee)
    2861                 :      274028 :     isra_write_edge_summary (ob, e);
    2862                 :       46710 :   for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
    2863                 :        1577 :     isra_write_edge_summary (ob, e);
    2864                 :       45133 : }
    2865                 :             : 
    2866                 :             : /* Write intraprocedural analysis information into a stream for LTO WPA.  */
    2867                 :             : 
    2868                 :             : static void
    2869                 :       18319 : ipa_sra_write_summary (void)
    2870                 :             : {
    2871                 :       18319 :   if (!func_sums || !call_sums)
    2872                 :           0 :     return;
    2873                 :             : 
    2874                 :       18319 :   struct output_block *ob = create_output_block (LTO_section_ipa_sra);
    2875                 :       18319 :   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
    2876                 :       18319 :   ob->symbol = NULL;
    2877                 :             : 
    2878                 :       18319 :   unsigned int count = 0;
    2879                 :       18319 :   lto_symtab_encoder_iterator lsei;
    2880                 :       18319 :   for (lsei = lsei_start_function_in_partition (encoder);
    2881                 :      213728 :        !lsei_end_p (lsei);
    2882                 :       88642 :        lsei_next_function_in_partition (&lsei))
    2883                 :             :     {
    2884                 :       88642 :       cgraph_node *node = lsei_cgraph_node (lsei);
    2885                 :       88642 :       if (node->has_gimple_body_p ()
    2886                 :       88642 :           && func_sums->get (node) != NULL)
    2887                 :       45133 :         count++;
    2888                 :             :     }
    2889                 :       18319 :   streamer_write_uhwi (ob, count);
    2890                 :             : 
    2891                 :             :   /* Process all of the functions.  */
    2892                 :      213728 :   for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
    2893                 :       88642 :        lsei_next_function_in_partition (&lsei))
    2894                 :             :     {
    2895                 :       88642 :       cgraph_node *node = lsei_cgraph_node (lsei);
    2896                 :       88642 :       if (node->has_gimple_body_p ()
    2897                 :       88642 :           && func_sums->get (node) != NULL)
    2898                 :       45133 :         isra_write_node_summary (ob, node);
    2899                 :             :     }
    2900                 :       18319 :   streamer_write_char_stream (ob->main_stream, 0);
    2901                 :       18319 :   produce_asm (ob, NULL);
    2902                 :       18319 :   destroy_output_block (ob);
    2903                 :             : }
    2904                 :             : 
    2905                 :             : /* Read intraprocedural analysis information about E and all of its outgoing
    2906                 :             :    edges into a stream for LTO WPA.  */
    2907                 :             : 
    2908                 :             : static void
    2909                 :      248823 : isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs)
    2910                 :             : {
    2911                 :      248823 :   isra_call_summary *csum = call_sums->get_create (cs);
    2912                 :      248823 :   unsigned input_count = streamer_read_uhwi (ib);
    2913                 :      248823 :   csum->init_inputs (input_count);
    2914                 :      696439 :   for (unsigned i = 0; i < input_count; i++)
    2915                 :             :     {
    2916                 :      447616 :       isra_param_flow *ipf = &csum->m_arg_flow[i];
    2917                 :      447616 :       ipf->length = streamer_read_hwi (ib);
    2918                 :      447616 :       bitpack_d bp = streamer_read_bitpack (ib);
    2919                 :      516098 :       for (int j = 0; j < ipf->length; j++)
    2920                 :       68482 :         ipf->inputs[j] = bp_unpack_value (&bp, 8);
    2921                 :      447616 :       ipf->aggregate_pass_through = bp_unpack_value (&bp, 1);
    2922                 :      447616 :       ipf->pointer_pass_through = bp_unpack_value (&bp, 1);
    2923                 :      447616 :       ipf->safe_to_import_accesses = bp_unpack_value (&bp, 1);
    2924                 :      447616 :       ipf->constructed_for_calls = bp_unpack_value (&bp, 1);
    2925                 :      447616 :       ipf->unit_offset = streamer_read_uhwi (ib);
    2926                 :      447616 :       ipf->unit_size = streamer_read_uhwi (ib);
    2927                 :             :     }
    2928                 :      248823 :   bitpack_d bp = streamer_read_bitpack (ib);
    2929                 :      248823 :   csum->m_return_ignored = bp_unpack_value (&bp, 1);
    2930                 :      248823 :   csum->m_return_returned = bp_unpack_value (&bp, 1);
    2931                 :      248823 :   csum->m_bit_aligned_arg = bp_unpack_value (&bp, 1);
    2932                 :      248823 :   csum->m_before_any_store = bp_unpack_value (&bp, 1);
    2933                 :      248823 : }
    2934                 :             : 
    2935                 :             : /* Read intraprocedural analysis information about NODE and all of its outgoing
    2936                 :             :    edges into a stream for LTO WPA.  */
    2937                 :             : 
    2938                 :             : static void
    2939                 :       31599 : isra_read_node_info (struct lto_input_block *ib, cgraph_node *node,
    2940                 :             :                      struct data_in *data_in)
    2941                 :             : {
    2942                 :       31599 :   isra_func_summary *ifs = func_sums->get_create (node);
    2943                 :       31599 :   unsigned param_desc_count = streamer_read_uhwi (ib);
    2944                 :       31599 :   if (param_desc_count > 0)
    2945                 :             :     {
    2946                 :       15922 :       vec_safe_reserve_exact (ifs->m_parameters, param_desc_count);
    2947                 :       15922 :       ifs->m_parameters->quick_grow_cleared (param_desc_count);
    2948                 :             :     }
    2949                 :       56770 :   for (unsigned i = 0; i < param_desc_count; i++)
    2950                 :             :     {
    2951                 :       25171 :       isra_param_desc *desc = &(*ifs->m_parameters)[i];
    2952                 :       25171 :       unsigned access_count = streamer_read_uhwi (ib);
    2953                 :       26713 :       for (unsigned j = 0; j < access_count; j++)
    2954                 :             :         {
    2955                 :        1542 :           param_access *acc = ggc_cleared_alloc<param_access> ();
    2956                 :        1542 :           acc->type = stream_read_tree (ib, data_in);
    2957                 :        1542 :           acc->alias_ptr_type = stream_read_tree (ib, data_in);
    2958                 :        1542 :           acc->unit_offset = streamer_read_uhwi (ib);
    2959                 :        1542 :           acc->unit_size = streamer_read_uhwi (ib);
    2960                 :        1542 :           bitpack_d bp = streamer_read_bitpack (ib);
    2961                 :        1542 :           acc->certain = bp_unpack_value (&bp, 1);
    2962                 :        1542 :           acc->reverse = bp_unpack_value (&bp, 1);
    2963                 :        1542 :           vec_safe_push (desc->accesses, acc);
    2964                 :             :         }
    2965                 :       25171 :       desc->param_size_limit = streamer_read_uhwi (ib);
    2966                 :       25171 :       desc->size_reached = streamer_read_uhwi (ib);
    2967                 :       25171 :       desc->safe_size = 0;
    2968                 :       25171 :       bitpack_d bp = streamer_read_bitpack (ib);
    2969                 :       25171 :       desc->locally_unused = bp_unpack_value (&bp, 1);
    2970                 :       25171 :       desc->split_candidate = bp_unpack_value (&bp, 1);
    2971                 :       25171 :       desc->by_ref = bp_unpack_value (&bp, 1);
    2972                 :       25171 :       desc->not_specially_constructed = 0;
    2973                 :       25171 :       desc->remove_only_when_retval_removed = bp_unpack_value (&bp, 1);
    2974                 :       25171 :       desc->split_only_when_retval_removed = bp_unpack_value (&bp, 1);
    2975                 :       25171 :       desc->conditionally_dereferenceable = bp_unpack_value (&bp, 1);
    2976                 :       25171 :       desc->safe_size_set = 0;
    2977                 :             :     }
    2978                 :       31599 :   bitpack_d bp = streamer_read_bitpack (ib);
    2979                 :       31599 :   ifs->m_candidate = bp_unpack_value (&bp, 1);
    2980                 :       31599 :   ifs->m_returns_value = bp_unpack_value (&bp, 1);
    2981                 :       31599 :   ifs->m_return_ignored = bp_unpack_value (&bp, 1);
    2982                 :       31599 :   ifs->m_queued = 0;
    2983                 :             : 
    2984                 :      279190 :   for (cgraph_edge *e = node->callees; e; e = e->next_callee)
    2985                 :      247591 :     isra_read_edge_summary (ib, e);
    2986                 :       32831 :   for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
    2987                 :        1232 :     isra_read_edge_summary (ib, e);
    2988                 :       31599 : }
    2989                 :             : 
    2990                 :             : /* Read IPA-SRA summaries from a section in file FILE_DATA of length LEN with
    2991                 :             :    data DATA.  TODO: This function was copied almost verbatim from ipa-prop.cc,
    2992                 :             :    it should be possible to unify them somehow.  */
    2993                 :             : 
    2994                 :             : static void
    2995                 :        9924 : isra_read_summary_section (struct lto_file_decl_data *file_data,
    2996                 :             :                            const char *data, size_t len)
    2997                 :             : {
    2998                 :        9924 :   const struct lto_function_header *header =
    2999                 :             :     (const struct lto_function_header *) data;
    3000                 :        9924 :   const int cfg_offset = sizeof (struct lto_function_header);
    3001                 :        9924 :   const int main_offset = cfg_offset + header->cfg_size;
    3002                 :        9924 :   const int string_offset = main_offset + header->main_size;
    3003                 :        9924 :   struct data_in *data_in;
    3004                 :        9924 :   unsigned int i;
    3005                 :        9924 :   unsigned int count;
    3006                 :             : 
    3007                 :        9924 :   lto_input_block ib_main ((const char *) data + main_offset,
    3008                 :        9924 :                            header->main_size, file_data);
    3009                 :             : 
    3010                 :        9924 :   data_in =
    3011                 :       19848 :     lto_data_in_create (file_data, (const char *) data + string_offset,
    3012                 :        9924 :                         header->string_size, vNULL);
    3013                 :        9924 :   count = streamer_read_uhwi (&ib_main);
    3014                 :             : 
    3015                 :       41523 :   for (i = 0; i < count; i++)
    3016                 :             :     {
    3017                 :       31599 :       unsigned int index;
    3018                 :       31599 :       struct cgraph_node *node;
    3019                 :       31599 :       lto_symtab_encoder_t encoder;
    3020                 :             : 
    3021                 :       31599 :       index = streamer_read_uhwi (&ib_main);
    3022                 :       31599 :       encoder = file_data->symtab_node_encoder;
    3023                 :       31599 :       node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
    3024                 :             :                                                                 index));
    3025                 :       31599 :       gcc_assert (node->definition);
    3026                 :       31599 :       isra_read_node_info (&ib_main, node, data_in);
    3027                 :             :     }
    3028                 :        9924 :   lto_free_section_data (file_data, LTO_section_ipa_sra, NULL, data,
    3029                 :             :                          len);
    3030                 :        9924 :   lto_data_in_delete (data_in);
    3031                 :        9924 : }
    3032                 :             : 
    3033                 :             : /* Read intraprocedural analysis information into a stream for LTO WPA.  */
    3034                 :             : 
    3035                 :             : static void
    3036                 :        9284 : ipa_sra_read_summary (void)
    3037                 :             : {
    3038                 :        9284 :   struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
    3039                 :        9284 :   struct lto_file_decl_data *file_data;
    3040                 :        9284 :   unsigned int j = 0;
    3041                 :             : 
    3042                 :        9284 :   gcc_checking_assert (!func_sums);
    3043                 :        9284 :   gcc_checking_assert (!call_sums);
    3044                 :        9284 :   func_sums
    3045                 :        9284 :     = (new (ggc_alloc_no_dtor <ipa_sra_function_summaries> ())
    3046                 :        9284 :        ipa_sra_function_summaries (symtab, true));
    3047                 :        9284 :   call_sums = new ipa_sra_call_summaries (symtab);
    3048                 :             : 
    3049                 :       19219 :   while ((file_data = file_data_vec[j++]))
    3050                 :             :     {
    3051                 :        9935 :       size_t len;
    3052                 :        9935 :       const char *data
    3053                 :        9935 :         = lto_get_summary_section_data (file_data, LTO_section_ipa_sra, &len);
    3054                 :        9935 :       if (data)
    3055                 :        9924 :         isra_read_summary_section (file_data, data, len);
    3056                 :             :     }
    3057                 :        9284 : }
    3058                 :             : 
    3059                 :             : /* Dump all IPA-SRA summary data for all cgraph nodes and edges to file F.  If
    3060                 :             :    HINTS is true, also dump IPA-analysis computed hints.  */
    3061                 :             : 
    3062                 :             : static void
    3063                 :          67 : ipa_sra_dump_all_summaries (FILE *f, bool hints)
    3064                 :             : {
    3065                 :          67 :   cgraph_node *node;
    3066                 :         276 :   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
    3067                 :             :     {
    3068                 :         209 :       fprintf (f, "\nSummary for node %s:\n", node->dump_name ());
    3069                 :             : 
    3070                 :         209 :       isra_func_summary *ifs = func_sums->get (node);
    3071                 :         209 :       if (!ifs)
    3072                 :          10 :         fprintf (f, "  Function does not have any associated IPA-SRA "
    3073                 :             :                  "summary\n");
    3074                 :         199 :       else if (!ifs->m_candidate)
    3075                 :          12 :         fprintf (f, "  Not a candidate function\n");
    3076                 :             :       else
    3077                 :             :         {
    3078                 :         187 :           if (ifs->m_returns_value)
    3079                 :          98 :             fprintf (f, "  Returns value\n");
    3080                 :         187 :           if (vec_safe_is_empty (ifs->m_parameters))
    3081                 :          49 :             fprintf (f, "  No parameter information. \n");
    3082                 :             :           else
    3083                 :         465 :             for (unsigned i = 0; i < ifs->m_parameters->length (); ++i)
    3084                 :             :               {
    3085                 :         327 :                 fprintf (f, "  Descriptor for parameter %i:\n", i);
    3086                 :         327 :                 dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i], hints);
    3087                 :             :               }
    3088                 :         187 :           fprintf (f, "\n");
    3089                 :             :         }
    3090                 :             : 
    3091                 :         209 :       struct cgraph_edge *cs;
    3092                 :         401 :       for (cs = node->callees; cs; cs = cs->next_callee)
    3093                 :             :         {
    3094                 :         192 :           fprintf (f, "  Summary for edge %s->%s:\n", cs->caller->dump_name (),
    3095                 :         192 :                    cs->callee->dump_name ());
    3096                 :         192 :           isra_call_summary *csum = call_sums->get (cs);
    3097                 :         192 :           if (csum)
    3098                 :         192 :             csum->dump (f);
    3099                 :             :           else
    3100                 :           0 :             fprintf (f, "    Call summary is MISSING!\n");
    3101                 :             :         }
    3102                 :             : 
    3103                 :             :     }
    3104                 :          67 :   fprintf (f, "\n\n");
    3105                 :          67 : }
    3106                 :             : 
    3107                 :             : /* Perform function-scope viability tests that can be only made at IPA level
    3108                 :             :    and return false if the function is deemed unsuitable for IPA-SRA.  */
    3109                 :             : 
    3110                 :             : static bool
    3111                 :      951651 : ipa_sra_ipa_function_checks (cgraph_node *node)
    3112                 :             : {
    3113                 :      951651 :   if (!node->can_be_local_p ())
    3114                 :             :     {
    3115                 :      627906 :       if (dump_file)
    3116                 :          93 :         fprintf (dump_file, "Function %s disqualified because it cannot be "
    3117                 :             :                  "made local.\n", node->dump_name ());
    3118                 :      627906 :       return false;
    3119                 :             :     }
    3120                 :      323745 :   if (!node->can_change_signature)
    3121                 :             :     {
    3122                 :           0 :       if (dump_file)
    3123                 :           0 :         fprintf (dump_file, "Function can not change signature.\n");
    3124                 :           0 :       return false;
    3125                 :             :     }
    3126                 :             : 
    3127                 :             :   return true;
    3128                 :             : }
    3129                 :             : 
    3130                 :             : /* Issues found out by check_callers_for_issues.  */
    3131                 :             : 
    3132                 :             : struct caller_issues
    3133                 :             : {
    3134                 :             :   /* The candidate being considered.  */
    3135                 :             :   cgraph_node *candidate;
    3136                 :             :   /* There is a thunk among callers.  */
    3137                 :             :   bool thunk;
    3138                 :             :   /* Set if there is at least one caller that is OK.  */
    3139                 :             :   bool there_is_one;
    3140                 :             :   /* Call site with no available information.  */
    3141                 :             :   bool unknown_callsite;
    3142                 :             :   /* Call from outside the candidate's comdat group.  */
    3143                 :             :   bool call_from_outside_comdat;
    3144                 :             :   /* There is a bit-aligned load into one of non-gimple-typed arguments. */
    3145                 :             :   bool bit_aligned_aggregate_argument;
    3146                 :             : };
    3147                 :             : 
    3148                 :             : /* Worker for call_for_symbol_and_aliases, set any flags of passed caller_issues
    3149                 :             :    that apply.  */
    3150                 :             : 
    3151                 :             : static bool
    3152                 :      329372 : check_for_caller_issues (struct cgraph_node *node, void *data)
    3153                 :             : {
    3154                 :      329372 :   struct caller_issues *issues = (struct caller_issues *) data;
    3155                 :             : 
    3156                 :     1245356 :   for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
    3157                 :             :     {
    3158                 :      916176 :       if (cs->caller->thunk)
    3159                 :             :         {
    3160                 :           0 :           issues->thunk = true;
    3161                 :             :           /* TODO: We should be able to process at least some types of
    3162                 :             :              thunks.  */
    3163                 :           0 :           return true;
    3164                 :             :         }
    3165                 :      916176 :       if (issues->candidate->calls_comdat_local
    3166                 :          12 :           && issues->candidate->same_comdat_group
    3167                 :      916188 :           && !issues->candidate->in_same_comdat_group_p (cs->caller))
    3168                 :             :         {
    3169                 :           0 :           issues->call_from_outside_comdat = true;
    3170                 :           0 :           return true;
    3171                 :             :         }
    3172                 :             : 
    3173                 :      916176 :       isra_call_summary *csum = call_sums->get (cs);
    3174                 :      916176 :       if (!csum)
    3175                 :             :         {
    3176                 :         192 :           issues->unknown_callsite = true;
    3177                 :         192 :           return true;
    3178                 :             :         }
    3179                 :             : 
    3180                 :      915984 :       if (csum->m_bit_aligned_arg)
    3181                 :           0 :         issues->bit_aligned_aggregate_argument = true;
    3182                 :             : 
    3183                 :      915984 :       issues->there_is_one = true;
    3184                 :             :     }
    3185                 :             :   return false;
    3186                 :             : }
    3187                 :             : 
    3188                 :             : /* Look at all incoming edges to NODE, including aliases and thunks and look
    3189                 :             :    for problems.  Return true if NODE type should not be modified at all.  */
    3190                 :             : 
    3191                 :             : static bool
    3192                 :      323745 : check_all_callers_for_issues (cgraph_node *node)
    3193                 :             : {
    3194                 :      323745 :   struct caller_issues issues;
    3195                 :      323745 :   memset (&issues, 0, sizeof (issues));
    3196                 :      323745 :   issues.candidate = node;
    3197                 :             : 
    3198                 :      323745 :   node->call_for_symbol_and_aliases (check_for_caller_issues, &issues, true);
    3199                 :      323745 :   if (issues.unknown_callsite)
    3200                 :             :     {
    3201                 :         192 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3202                 :           0 :         fprintf (dump_file, "A call of %s has not been analyzed.  Disabling "
    3203                 :             :                  "all modifications.\n", node->dump_name ());
    3204                 :         192 :       return true;
    3205                 :             :     }
    3206                 :             :   /* TODO: We should be able to process at least some types of thunks.  */
    3207                 :      323553 :   if (issues.thunk)
    3208                 :             :     {
    3209                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3210                 :           0 :         fprintf (dump_file, "A call of %s is through thunk, which are not"
    3211                 :             :                  " handled yet.  Disabling all modifications.\n",
    3212                 :             :                  node->dump_name ());
    3213                 :           0 :       return true;
    3214                 :             :     }
    3215                 :      323553 :   if (issues.call_from_outside_comdat)
    3216                 :             :     {
    3217                 :           0 :       if (dump_file)
    3218                 :           0 :         fprintf (dump_file, "Function would become private comdat called "
    3219                 :             :                  "outside of its comdat group.\n");
    3220                 :           0 :       return true;
    3221                 :             :     }
    3222                 :             : 
    3223                 :      323553 :   if (issues.bit_aligned_aggregate_argument)
    3224                 :             :     {
    3225                 :             :       /* Let's only remove parameters/return values from such functions.
    3226                 :             :          TODO: We could only prevent splitting the problematic parameters if
    3227                 :             :          anybody thinks it is worth it.  */
    3228                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3229                 :           0 :         fprintf (dump_file, "A call of %s has bit-aligned aggregate argument,"
    3230                 :             :                  " disabling parameter splitting.\n", node->dump_name ());
    3231                 :             : 
    3232                 :           0 :       isra_func_summary *ifs = func_sums->get (node);
    3233                 :           0 :       gcc_checking_assert (ifs);
    3234                 :           0 :       unsigned param_count = vec_safe_length (ifs->m_parameters);
    3235                 :           0 :       for (unsigned i = 0; i < param_count; i++)
    3236                 :           0 :         (*ifs->m_parameters)[i].split_candidate = false;
    3237                 :             :     }
    3238                 :      323553 :   if (!issues.there_is_one)
    3239                 :             :     {
    3240                 :        1511 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3241                 :           0 :         fprintf (dump_file, "There is no call to %s that we can modify.  "
    3242                 :             :                  "Disabling all modifications.\n", node->dump_name ());
    3243                 :        1511 :       return true;
    3244                 :             :     }
    3245                 :             :   return false;
    3246                 :             : }
    3247                 :             : 
    3248                 :             : /* Find the access with corresponding OFFSET and SIZE among accesses in
    3249                 :             :    PARAM_DESC and return it or NULL if such an access is not there.  */
    3250                 :             : 
    3251                 :             : static param_access *
    3252                 :       13592 : find_param_access (isra_param_desc *param_desc, unsigned offset, unsigned size)
    3253                 :             : {
    3254                 :       13592 :   unsigned pclen = vec_safe_length (param_desc->accesses);
    3255                 :             : 
    3256                 :             :   /* The search is linear but the number of stored accesses is bound by
    3257                 :             :      PARAM_IPA_SRA_MAX_REPLACEMENTS, so most probably 8.  */
    3258                 :             : 
    3259                 :       13667 :   for (unsigned i = 0; i < pclen; i++)
    3260                 :       13621 :     if ((*param_desc->accesses)[i]->unit_offset == offset
    3261                 :       13621 :         && (*param_desc->accesses)[i]->unit_size == size)
    3262                 :             :       return (*param_desc->accesses)[i];
    3263                 :             : 
    3264                 :             :   return NULL;
    3265                 :             : }
    3266                 :             : 
    3267                 :             : /* Return iff the total size of definite replacement SIZE would violate the
    3268                 :             :    limit set for it in PARAM.  */
    3269                 :             : 
    3270                 :             : static bool
    3271                 :      195405 : size_would_violate_limit_p (isra_param_desc *desc, unsigned size)
    3272                 :             : {
    3273                 :      195405 :   unsigned limit = desc->param_size_limit;
    3274                 :           0 :   if (size > limit
    3275                 :      192395 :       || (!desc->by_ref && size == limit))
    3276                 :           0 :     return true;
    3277                 :             :   return false;
    3278                 :             : }
    3279                 :             : 
    3280                 :             : /* Increase reached size of DESC by SIZE or disqualify it if it would violate
    3281                 :             :    the set limit.  IDX is the parameter number which is dumped when
    3282                 :             :    disqualifying.  */
    3283                 :             : 
    3284                 :             : static void
    3285                 :       11140 : bump_reached_size (isra_param_desc *desc, unsigned size, unsigned idx)
    3286                 :             : {
    3287                 :       11140 :   unsigned after = desc->size_reached + size;
    3288                 :       11140 :   if (size_would_violate_limit_p (desc, after))
    3289                 :             :     {
    3290                 :       11109 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3291                 :           0 :         fprintf (dump_file, "    ...size limit reached, disqualifying "
    3292                 :             :                  "candidate parameter %u\n", idx);
    3293                 :       11109 :       desc->split_candidate = false;
    3294                 :       11109 :       return;
    3295                 :             :     }
    3296                 :          31 :   desc->size_reached = after;
    3297                 :             : }
    3298                 :             : 
    3299                 :             : /* Take all actions required to deal with an edge CS that represents a call to
    3300                 :             :    an unknown or un-analyzed function, for both parameter removal and
    3301                 :             :    splitting.  */
    3302                 :             : 
    3303                 :             : static void
    3304                 :      452283 : process_edge_to_unknown_caller (cgraph_edge *cs)
    3305                 :             : {
    3306                 :      452283 :   isra_func_summary *from_ifs = func_sums->get (cs->caller);
    3307                 :      452283 :   gcc_checking_assert (from_ifs);
    3308                 :      452283 :   isra_call_summary *csum = call_sums->get (cs);
    3309                 :             : 
    3310                 :      452283 :   if (dump_file && (dump_flags & TDF_DETAILS))
    3311                 :           4 :     fprintf (dump_file, "Processing an edge to an unknown caller from %s:\n",
    3312                 :             :              cs->caller->dump_name ());
    3313                 :             : 
    3314                 :      452283 :   unsigned args_count = csum->m_arg_flow.length ();
    3315                 :     1135365 :   for (unsigned i = 0; i < args_count; i++)
    3316                 :             :     {
    3317                 :      683082 :       isra_param_flow *ipf = &csum->m_arg_flow[i];
    3318                 :             : 
    3319                 :      683082 :      if (ipf->pointer_pass_through)
    3320                 :             :        {
    3321                 :      196660 :          isra_param_desc *param_desc
    3322                 :      196660 :            = &(*from_ifs->m_parameters)[get_single_param_flow_source (ipf)];
    3323                 :      196660 :          param_desc->locally_unused = false;
    3324                 :      196660 :          param_desc->split_candidate = false;
    3325                 :      196660 :         continue;
    3326                 :      196660 :        }
    3327                 :      486422 :       if (ipf->aggregate_pass_through)
    3328                 :             :         {
    3329                 :        6507 :           unsigned idx = get_single_param_flow_source (ipf);
    3330                 :        6507 :           isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
    3331                 :             : 
    3332                 :        6507 :           param_desc->locally_unused = false;
    3333                 :        6507 :           if (!param_desc->split_candidate)
    3334                 :        1672 :             continue;
    3335                 :        4835 :           gcc_assert (!param_desc->by_ref);
    3336                 :        9670 :           param_access *pacc = find_param_access (param_desc, ipf->unit_offset,
    3337                 :        4835 :                                                   ipf->unit_size);
    3338                 :        4835 :           gcc_checking_assert (pacc);
    3339                 :        4835 :           pacc->certain = true;
    3340                 :        4835 :           if (overlapping_certain_accesses_p (param_desc, NULL))
    3341                 :             :             {
    3342                 :         555 :               if (dump_file && (dump_flags & TDF_DETAILS))
    3343                 :           0 :                 fprintf (dump_file, "    ...leading to overlap, "
    3344                 :             :                          " disqualifying candidate parameter %u\n",
    3345                 :             :                          idx);
    3346                 :         555 :               param_desc->split_candidate = false;
    3347                 :             :             }
    3348                 :             :           else
    3349                 :        4280 :             bump_reached_size (param_desc, pacc->unit_size, idx);
    3350                 :        4835 :           ipf->aggregate_pass_through = false;
    3351                 :        4835 :           continue;
    3352                 :        4835 :         }
    3353                 :             : 
    3354                 :      564880 :       for (int j = 0; j < ipf->length; j++)
    3355                 :             :         {
    3356                 :       84965 :           int input_idx = ipf->inputs[j];
    3357                 :       84965 :           (*from_ifs->m_parameters)[input_idx].locally_unused = false;
    3358                 :             :         }
    3359                 :             :     }
    3360                 :      452283 : }
    3361                 :             : 
    3362                 :             : /* Propagate parameter removal information through cross-SCC edge CS,
    3363                 :             :    i.e. decrease the use count in the caller parameter descriptor for each use
    3364                 :             :    in this call.  */
    3365                 :             : 
    3366                 :             : static void
    3367                 :      741027 : param_removal_cross_scc_edge (cgraph_edge *cs)
    3368                 :             : {
    3369                 :      741027 :   enum availability availability;
    3370                 :      741027 :   cgraph_node *callee = cs->callee->function_symbol (&availability);
    3371                 :      741027 :   isra_func_summary *to_ifs = func_sums->get (callee);
    3372                 :      351629 :   if (!to_ifs || !to_ifs->m_candidate
    3373                 :      312716 :       || (availability < AVAIL_AVAILABLE)
    3374                 :     1053743 :       || vec_safe_is_empty (to_ifs->m_parameters))
    3375                 :             :     {
    3376                 :      437418 :       process_edge_to_unknown_caller (cs);
    3377                 :      437418 :       return;
    3378                 :             :     }
    3379                 :      303609 :   isra_func_summary *from_ifs = func_sums->get (cs->caller);
    3380                 :      303609 :   gcc_checking_assert (from_ifs);
    3381                 :             : 
    3382                 :      303609 :   isra_call_summary *csum = call_sums->get (cs);
    3383                 :      303609 :   unsigned args_count = csum->m_arg_flow.length ();
    3384                 :      303609 :   unsigned param_count = vec_safe_length (to_ifs->m_parameters);
    3385                 :             : 
    3386                 :     1065930 :   for (unsigned i = 0; i < args_count; i++)
    3387                 :             :     {
    3388                 :      762321 :       bool unused_in_callee;
    3389                 :      762321 :       if (i < param_count)
    3390                 :      762317 :         unused_in_callee = (*to_ifs->m_parameters)[i].locally_unused;
    3391                 :             :       else
    3392                 :             :         unused_in_callee = false;
    3393                 :             : 
    3394                 :      762317 :       if (!unused_in_callee)
    3395                 :             :         {
    3396                 :      728397 :           isra_param_flow *ipf = &csum->m_arg_flow[i];
    3397                 :      943621 :           for (int j = 0; j < ipf->length; j++)
    3398                 :             :             {
    3399                 :      215224 :               int input_idx = ipf->inputs[j];
    3400                 :      215224 :               (*from_ifs->m_parameters)[input_idx].locally_unused = false;
    3401                 :             :             }
    3402                 :             :         }
    3403                 :             :     }
    3404                 :             : }
    3405                 :             : 
    3406                 :             : /* Unless it is already there, push NODE which is also described by IFS to
    3407                 :             :    STACK.  */
    3408                 :             : 
    3409                 :             : static void
    3410                 :      141136 : isra_push_node_to_stack (cgraph_node *node, isra_func_summary *ifs,
    3411                 :             :                     vec<cgraph_node *> *stack)
    3412                 :             : {
    3413                 :           0 :   if (!ifs->m_queued)
    3414                 :             :     {
    3415                 :      140321 :       ifs->m_queued = true;
    3416                 :      140321 :       stack->safe_push (node);
    3417                 :             :     }
    3418                 :           0 : }
    3419                 :             : 
    3420                 :             : /* If parameter with index INPUT_IDX is marked as locally unused, mark it as
    3421                 :             :    used and push CALLER on STACK.  */
    3422                 :             : 
    3423                 :             : static void
    3424                 :       25745 : isra_mark_caller_param_used (isra_func_summary *from_ifs, int input_idx,
    3425                 :             :                              cgraph_node *caller, vec<cgraph_node *> *stack)
    3426                 :             : {
    3427                 :       25745 :   if ((*from_ifs->m_parameters)[input_idx].locally_unused)
    3428                 :             :     {
    3429                 :        3110 :       (*from_ifs->m_parameters)[input_idx].locally_unused = false;
    3430                 :        5452 :       isra_push_node_to_stack (caller, from_ifs, stack);
    3431                 :             :     }
    3432                 :       25745 : }
    3433                 :             : 
    3434                 :             : /* Combine safe_size of DESC with SIZE and return true if it has changed.  */
    3435                 :             : 
    3436                 :             : static bool
    3437                 :     2112552 : update_safe_size (isra_param_desc *desc, unsigned size)
    3438                 :             : {
    3439                 :           0 :   if (!desc->safe_size_set)
    3440                 :             :     {
    3441                 :      682442 :       desc->safe_size_set = 1;
    3442                 :      682442 :       desc->safe_size = size;
    3443                 :      682442 :       return true;
    3444                 :             :     }
    3445                 :     1430110 :   if (desc->safe_size <= size)
    3446                 :             :     return false;
    3447                 :       19084 :   desc->safe_size = size;
    3448                 :       19084 :   return true;
    3449                 :             : }
    3450                 :             : 
    3451                 :             : /* Set all param hints in DESC to the pessimistic values.  Return true if any
    3452                 :             :    hints that need to potentially trigger further propagation have changed.  */
    3453                 :             : 
    3454                 :             : static bool
    3455                 :      651550 : flip_all_hints_pessimistic (isra_param_desc *desc)
    3456                 :             : {
    3457                 :      651550 :   desc->not_specially_constructed = true;
    3458                 :           0 :   return update_safe_size (desc, 0);
    3459                 :             : }
    3460                 :             : 
    3461                 :             : /* Because we have not analyzed or otherwise problematic caller, go over all
    3462                 :             :    parameter int flags of IFS describing a call graph node of a calllee and
    3463                 :             :    turn them pessimistic.  Return true if any hints that need to potentially
    3464                 :             :    trigger further propagation have changed.  */
    3465                 :             : 
    3466                 :             : static bool
    3467                 :      402942 : flip_all_param_hints_pessimistic (isra_func_summary *ifs)
    3468                 :             : {
    3469                 :      402942 :   if (!ifs || !ifs->m_candidate)
    3470                 :             :     return false;
    3471                 :             : 
    3472                 :       23203 :   bool ret = false;
    3473                 :       23203 :   unsigned param_count = vec_safe_length (ifs->m_parameters);
    3474                 :             : 
    3475                 :       64904 :   for (unsigned i = 0; i < param_count; i++)
    3476                 :       83402 :     ret |= flip_all_hints_pessimistic (&(*ifs->m_parameters)[i]);
    3477                 :             : 
    3478                 :             :   return ret;
    3479                 :             : }
    3480                 :             : 
    3481                 :             : /* Propagate hints accross edge CS which ultimately leads to a node described
    3482                 :             :    by TO_IFS.  Return true if any hints of the callee which should potentially
    3483                 :             :    trigger further propagation have changed.  */
    3484                 :             : 
    3485                 :             : static bool
    3486                 :     4425885 : propagate_param_hints_accross_call (cgraph_edge *cs, isra_func_summary *to_ifs)
    3487                 :             : {
    3488                 :     4425885 :   if (!to_ifs || !to_ifs->m_candidate)
    3489                 :             :     return false;
    3490                 :             : 
    3491                 :     1444819 :   isra_call_summary *csum = call_sums->get (cs);
    3492                 :     1444819 :   bool ret = false;
    3493                 :     1444819 :   unsigned args_count = csum->m_arg_flow.length ();
    3494                 :     1444819 :   unsigned param_count = vec_safe_length (to_ifs->m_parameters);
    3495                 :             : 
    3496                 :     4631751 :   for (unsigned i = 0; i < param_count; i++)
    3497                 :             :     {
    3498                 :     3186932 :       isra_param_desc *desc = &(*to_ifs->m_parameters)[i];
    3499                 :     3186932 :       if (i >= args_count)
    3500                 :             :         {
    3501                 :      609849 :           ret |= flip_all_hints_pessimistic (desc);
    3502                 :      609849 :           continue;
    3503                 :             :         }
    3504                 :             : 
    3505                 :     2577083 :       if (desc->by_ref)
    3506                 :             :         {
    3507                 :     1461010 :           isra_param_flow *ipf = &csum->m_arg_flow[i];
    3508                 :             : 
    3509                 :     1461010 :           if (!ipf->constructed_for_calls)
    3510                 :     1119909 :             desc->not_specially_constructed = true;
    3511                 :             : 
    3512                 :     1461010 :           if (ipf->pointer_pass_through)
    3513                 :             :             {
    3514                 :      259712 :               isra_func_summary *from_ifs = func_sums->get (cs->caller);
    3515                 :      259712 :               int srcidx = get_single_param_flow_source (ipf);
    3516                 :      419825 :               if (vec_safe_length (from_ifs->m_parameters) > (unsigned) srcidx)
    3517                 :             :                 {
    3518                 :      160113 :                   isra_param_desc *src_d = &(*from_ifs->m_parameters)[srcidx];
    3519                 :      160113 :                   if (src_d->safe_size_set)
    3520                 :      320210 :                     ret |= update_safe_size (desc, src_d->safe_size);
    3521                 :             :                 }
    3522                 :             :               else
    3523                 :      199198 :                 ret |= update_safe_size (desc, 0);
    3524                 :             :             }
    3525                 :     1201298 :           else if (!ipf->aggregate_pass_through)
    3526                 :     2402594 :             ret |= update_safe_size (desc, ipf->unit_size);
    3527                 :             :           else
    3528                 :             :             /* LTOing type-mismatched programs can end up here.  */
    3529                 :           2 :             ret |= update_safe_size (desc, 0);
    3530                 :             :         }
    3531                 :             :     }
    3532                 :             :   return ret;
    3533                 :             : }
    3534                 :             : 
    3535                 :             : /* Propagate hints from NODE described by FROM_IFS to all its (dorect) callees,
    3536                 :             :    push those that may need re-visiting onto STACK.  */
    3537                 :             : 
    3538                 :             : static void
    3539                 :     1259149 : propagate_hints_to_all_callees (cgraph_node *node, isra_func_summary *from_ifs,
    3540                 :             :                                 vec<cgraph_node *> *stack)
    3541                 :             : {
    3542                 :     6087976 :   for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
    3543                 :             :     {
    3544                 :     4828827 :       enum availability availability;
    3545                 :     4828827 :       cgraph_node *callee = cs->callee->function_symbol (&availability);
    3546                 :     4828827 :       isra_func_summary *to_ifs = func_sums->get (callee);
    3547                 :     4828827 :       if (!from_ifs)
    3548                 :             :         {
    3549                 :      402942 :           if (flip_all_param_hints_pessimistic (to_ifs)
    3550                 :      402942 :               && ipa_edge_within_scc (cs))
    3551                 :          28 :             isra_push_node_to_stack (callee, to_ifs, stack);
    3552                 :             :         }
    3553                 :     4425885 :       else if (propagate_param_hints_accross_call (cs, to_ifs)
    3554                 :     4425885 :                && ipa_edge_within_scc (cs))
    3555                 :        7969 :         isra_push_node_to_stack (callee, to_ifs, stack);
    3556                 :             :     }
    3557                 :     1259149 : }
    3558                 :             : 
    3559                 :             : /* Propagate information that any parameter is not used only locally within a
    3560                 :             :    SCC across CS to the caller, which must be in the same SCC as the
    3561                 :             :    callee.  Push any callers that need to be re-processed to STACK.  */
    3562                 :             : 
    3563                 :             : static void
    3564                 :       33275 : propagate_used_across_scc_edge (cgraph_edge *cs, vec<cgraph_node *> *stack)
    3565                 :             : {
    3566                 :       33275 :   isra_func_summary *from_ifs = func_sums->get (cs->caller);
    3567                 :       33275 :   if (!from_ifs || vec_safe_is_empty (from_ifs->m_parameters))
    3568                 :       15073 :     return;
    3569                 :             : 
    3570                 :       18202 :   isra_call_summary *csum = call_sums->get (cs);
    3571                 :       18202 :   gcc_checking_assert (csum);
    3572                 :       18202 :   unsigned args_count = csum->m_arg_flow.length ();
    3573                 :       18202 :   enum availability availability;
    3574                 :       18202 :   cgraph_node *callee = cs->callee->function_symbol (&availability);
    3575                 :       18202 :   isra_func_summary *to_ifs = func_sums->get (callee);
    3576                 :             : 
    3577                 :       18202 :   unsigned param_count
    3578                 :       18113 :     = (to_ifs && (availability >= AVAIL_AVAILABLE))
    3579                 :       36055 :     ? vec_safe_length (to_ifs->m_parameters) : 0;
    3580                 :       59732 :   for (unsigned i = 0; i < args_count; i++)
    3581                 :             :     {
    3582                 :       44691 :       if (i < param_count
    3583                 :       41530 :           && (*to_ifs->m_parameters)[i].locally_unused)
    3584                 :        3161 :             continue;
    3585                 :             : 
    3586                 :             :       /* The argument is needed in the callee it, we must mark the parameter as
    3587                 :             :          used also in the caller and its callers within this SCC.  */
    3588                 :       38369 :       isra_param_flow *ipf = &csum->m_arg_flow[i];
    3589                 :       64114 :       for (int j = 0; j < ipf->length; j++)
    3590                 :             :         {
    3591                 :       25745 :           int input_idx = ipf->inputs[j];
    3592                 :       25745 :           isra_mark_caller_param_used (from_ifs, input_idx, cs->caller, stack);
    3593                 :             :         }
    3594                 :             :     }
    3595                 :             : }
    3596                 :             : 
    3597                 :             : /* Propagate information that any parameter is not used only locally within a
    3598                 :             :    SCC (i.e. is used also elsewhere) to all callers of NODE that are in the
    3599                 :             :    same SCC.  Push any callers that need to be re-processed to STACK.  */
    3600                 :             : 
    3601                 :             : static bool
    3602                 :     1331941 : propagate_used_to_scc_callers (cgraph_node *node, void *data)
    3603                 :             : {
    3604                 :     1331941 :   vec<cgraph_node *> *stack = (vec<cgraph_node *> *) data;
    3605                 :     1331941 :   cgraph_edge *cs;
    3606                 :     3167511 :   for (cs = node->callers; cs; cs = cs->next_caller)
    3607                 :     1835570 :     if (ipa_edge_within_scc (cs))
    3608                 :       33275 :       propagate_used_across_scc_edge (cs, stack);
    3609                 :     1331941 :   return false;
    3610                 :             : }
    3611                 :             : 
    3612                 :             : /* Return true iff all certain accesses in ARG_DESC are also present as
    3613                 :             :    certain accesses in PARAM_DESC.  */
    3614                 :             : 
    3615                 :             : static bool
    3616                 :          71 : all_callee_accesses_present_p (isra_param_desc *param_desc,
    3617                 :             :                                isra_param_desc *arg_desc)
    3618                 :             : {
    3619                 :          71 :   unsigned aclen = vec_safe_length (arg_desc->accesses);
    3620                 :          75 :   for (unsigned j = 0; j < aclen; j++)
    3621                 :             :     {
    3622                 :          51 :       param_access *argacc = (*arg_desc->accesses)[j];
    3623                 :          51 :       if (!argacc->certain)
    3624                 :           0 :         continue;
    3625                 :         102 :       param_access *pacc = find_param_access (param_desc, argacc->unit_offset,
    3626                 :          51 :                                               argacc->unit_size);
    3627                 :          51 :       if (!pacc
    3628                 :           5 :           || !pacc->certain
    3629                 :          56 :           || !types_compatible_p (argacc->type, pacc->type))
    3630                 :          47 :         return false;
    3631                 :             :     }
    3632                 :             :   return true;
    3633                 :             : }
    3634                 :             : 
    3635                 :             : /* Type internal to function pull_accesses_from_callee.  Unfortunately gcc 4.8
    3636                 :             :    does not allow instantiating an auto_vec with a type defined within a
    3637                 :             :    function so it is a global type.   */
    3638                 :             : enum acc_prop_kind {ACC_PROP_DONT, ACC_PROP_COPY, ACC_PROP_CERTAIN};
    3639                 :             : 
    3640                 :             : 
    3641                 :             : /* Attempt to propagate all definite accesses from ARG_DESC to PARAM_DESC,
    3642                 :             :    (which belongs to CALLER) if they would not violate some constraint there.
    3643                 :             :    If successful, return NULL, otherwise return the string reason for failure
    3644                 :             :    (which can be written to the dump file).  DELTA_OFFSET is the known offset
    3645                 :             :    of the actual argument withing the formal parameter (so of ARG_DESCS within
    3646                 :             :    PARAM_DESCS), ARG_SIZE is the size of the actual argument or zero, if not
    3647                 :             :    known. In case of success, set *CHANGE_P to true if propagation actually
    3648                 :             :    changed anything.  */
    3649                 :             : 
    3650                 :             : static const char *
    3651                 :        7349 : pull_accesses_from_callee (cgraph_node *caller, isra_param_desc *param_desc,
    3652                 :             :                            isra_param_desc *arg_desc,
    3653                 :             :                            unsigned delta_offset, unsigned arg_size,
    3654                 :             :                            bool *change_p)
    3655                 :             : {
    3656                 :        7349 :   unsigned pclen = vec_safe_length (param_desc->accesses);
    3657                 :        7349 :   unsigned aclen = vec_safe_length (arg_desc->accesses);
    3658                 :        7349 :   unsigned prop_count = 0;
    3659                 :        7349 :   unsigned prop_size = 0;
    3660                 :        7349 :   bool change = false;
    3661                 :             : 
    3662                 :        7349 :   auto_vec <enum acc_prop_kind, 8> prop_kinds (aclen);
    3663                 :       17753 :   for (unsigned j = 0; j < aclen; j++)
    3664                 :             :     {
    3665                 :       10459 :       param_access *argacc = (*arg_desc->accesses)[j];
    3666                 :       10459 :       prop_kinds.safe_push (ACC_PROP_DONT);
    3667                 :             : 
    3668                 :       10459 :       if (arg_size > 0
    3669                 :        2736 :           && argacc->unit_offset + argacc->unit_size > arg_size)
    3670                 :             :         return "callee access outsize size boundary";
    3671                 :             : 
    3672                 :       10459 :       if (!argacc->certain)
    3673                 :         345 :         continue;
    3674                 :             : 
    3675                 :       10114 :       unsigned offset = argacc->unit_offset + delta_offset;
    3676                 :             :       /* Given that accesses are initially stored according to increasing
    3677                 :             :          offset and decreasing size in case of equal offsets, the following
    3678                 :             :          searches could be written more efficiently if we kept the ordering
    3679                 :             :          when copying. But the number of accesses is capped at
    3680                 :             :          PARAM_IPA_SRA_MAX_REPLACEMENTS (so most likely 8) and the code gets
    3681                 :             :          messy quickly, so let's improve on that only if necessary.  */
    3682                 :             : 
    3683                 :       10114 :       bool exact_match = false;
    3684                 :       22250 :       for (unsigned i = 0; i < pclen; i++)
    3685                 :             :         {
    3686                 :             :           /* Check for overlaps.  */
    3687                 :       12191 :           param_access *pacc = (*param_desc->accesses)[i];
    3688                 :       12191 :           if (pacc->unit_offset == offset
    3689                 :        5283 :               && pacc->unit_size == argacc->unit_size)
    3690                 :             :             {
    3691                 :        4199 :               if (argacc->alias_ptr_type != pacc->alias_ptr_type
    3692                 :        4145 :                   || !types_compatible_p (argacc->type, pacc->type)
    3693                 :        8344 :                   || argacc->reverse != pacc->reverse)
    3694                 :          54 :                 return "propagated access types would not match existing ones";
    3695                 :             : 
    3696                 :        4145 :               exact_match = true;
    3697                 :        4145 :               if (!pacc->certain)
    3698                 :             :                 {
    3699                 :           0 :                   prop_kinds[j] = ACC_PROP_CERTAIN;
    3700                 :           0 :                   prop_size += argacc->unit_size;
    3701                 :           0 :                   change = true;
    3702                 :             :                 }
    3703                 :        4145 :               continue;
    3704                 :             :             }
    3705                 :             : 
    3706                 :        7992 :           if (offset < pacc->unit_offset + pacc->unit_size
    3707                 :        5516 :               && offset + argacc->unit_size > pacc->unit_offset)
    3708                 :             :             {
    3709                 :             :               /* None permissible with load accesses, possible to fit into
    3710                 :             :                  argument ones.  */
    3711                 :        2392 :               if (pacc->certain
    3712                 :        2391 :                   || offset < pacc->unit_offset
    3713                 :        2391 :                   || (offset + argacc->unit_size
    3714                 :             :                       > pacc->unit_offset + pacc->unit_size))
    3715                 :             :                 return "a propagated access would conflict in caller";
    3716                 :             :             }
    3717                 :             :         }
    3718                 :             : 
    3719                 :       10059 :       if (!exact_match)
    3720                 :             :         {
    3721                 :        5914 :           prop_kinds[j] = ACC_PROP_COPY;
    3722                 :        5914 :           prop_count++;
    3723                 :        5914 :           prop_size += argacc->unit_size;
    3724                 :        5914 :           change = true;
    3725                 :             :         }
    3726                 :             :     }
    3727                 :             : 
    3728                 :        7294 :     if (!change)
    3729                 :             :       return NULL;
    3730                 :             : 
    3731                 :        4431 :     if ((prop_count + pclen
    3732                 :        4431 :          > (unsigned) opt_for_fn (caller->decl, param_ipa_sra_max_replacements))
    3733                 :       11780 :         || size_would_violate_limit_p (param_desc,
    3734                 :        4431 :                                        param_desc->size_reached + prop_size))
    3735                 :             :       return "propagating accesses would violate the count or size limit";
    3736                 :             : 
    3737                 :        4083 :   *change_p = true;
    3738                 :       10043 :   for (unsigned j = 0; j < aclen; j++)
    3739                 :             :     {
    3740                 :        5960 :       if (prop_kinds[j] == ACC_PROP_COPY)
    3741                 :             :         {
    3742                 :        5235 :           param_access *argacc = (*arg_desc->accesses)[j];
    3743                 :             : 
    3744                 :        5235 :           param_access *copy = ggc_cleared_alloc<param_access> ();
    3745                 :        5235 :           copy->unit_offset = argacc->unit_offset + delta_offset;
    3746                 :        5235 :           copy->unit_size = argacc->unit_size;
    3747                 :        5235 :           copy->type = argacc->type;
    3748                 :        5235 :           copy->alias_ptr_type = argacc->alias_ptr_type;
    3749                 :        5235 :           copy->certain = true;
    3750                 :        5235 :           copy->reverse = argacc->reverse;
    3751                 :        5235 :           vec_safe_push (param_desc->accesses, copy);
    3752                 :             :         }
    3753                 :         725 :       else if (prop_kinds[j] == ACC_PROP_CERTAIN)
    3754                 :             :         {
    3755                 :           0 :           param_access *argacc = (*arg_desc->accesses)[j];
    3756                 :           0 :           param_access *csp
    3757                 :           0 :             = find_param_access (param_desc, argacc->unit_offset + delta_offset,
    3758                 :           0 :                                  argacc->unit_size);
    3759                 :           0 :           csp->certain = true;
    3760                 :             :         }
    3761                 :             :     }
    3762                 :             : 
    3763                 :        4083 :   param_desc->size_reached += prop_size;
    3764                 :             : 
    3765                 :        4083 :   return NULL;
    3766                 :        7349 : }
    3767                 :             : 
    3768                 :             : /* Propagate parameter splitting information through call graph edge CS.
    3769                 :             :    Return true if any changes that might need to be propagated within SCCs have
    3770                 :             :    been made.  The function also clears the aggregate_pass_through and
    3771                 :             :    pointer_pass_through in call summaries which do not need to be processed
    3772                 :             :    again if this CS is revisited when iterating while changes are propagated
    3773                 :             :    within an SCC.  */
    3774                 :             : 
    3775                 :             : static bool
    3776                 :     1335031 : param_splitting_across_edge (cgraph_edge *cs)
    3777                 :             : {
    3778                 :     1335031 :   bool res = false;
    3779                 :     1335031 :   bool cross_scc = !ipa_edge_within_scc (cs);
    3780                 :     1335031 :   enum availability availability;
    3781                 :     1335031 :   cgraph_node *callee = cs->callee->function_symbol (&availability);
    3782                 :     1335031 :   isra_func_summary *from_ifs = func_sums->get (cs->caller);
    3783                 :     1335031 :   gcc_checking_assert (from_ifs && from_ifs->m_parameters);
    3784                 :             : 
    3785                 :     1335031 :   isra_call_summary *csum = call_sums->get (cs);
    3786                 :     1335031 :   gcc_checking_assert (csum);
    3787                 :     1335031 :   unsigned args_count = csum->m_arg_flow.length ();
    3788                 :     1335031 :   isra_func_summary *to_ifs = func_sums->get (callee);
    3789                 :     1335031 :   unsigned param_count
    3790                 :      716426 :     = ((to_ifs && to_ifs->m_candidate && (availability >= AVAIL_AVAILABLE))
    3791                 :     1971548 :        ? vec_safe_length (to_ifs->m_parameters)
    3792                 :     1335031 :        : 0);
    3793                 :             : 
    3794                 :     1335031 :   if (dump_file && (dump_flags & TDF_DETAILS))
    3795                 :          18 :     fprintf (dump_file, "Splitting across %s->%s:\n",
    3796                 :           9 :              cs->caller->dump_name (), callee->dump_name ());
    3797                 :             : 
    3798                 :             :   unsigned i;
    3799                 :     2655388 :   for (i = 0; (i < args_count) && (i < param_count); i++)
    3800                 :             :     {
    3801                 :     1320357 :       isra_param_desc *arg_desc = &(*to_ifs->m_parameters)[i];
    3802                 :     1320357 :       isra_param_flow *ipf = &csum->m_arg_flow[i];
    3803                 :             : 
    3804                 :     1320357 :       if (arg_desc->locally_unused)
    3805                 :             :         {
    3806                 :       60130 :           if (dump_file && (dump_flags & TDF_DETAILS))
    3807                 :           0 :             fprintf (dump_file, "    ->%u: unused in callee\n", i);
    3808                 :       60130 :           ipf->pointer_pass_through = false;
    3809                 :       60130 :           continue;
    3810                 :             :         }
    3811                 :             : 
    3812                 :     1260227 :       if (ipf->pointer_pass_through)
    3813                 :             :         {
    3814                 :      163398 :           int idx = get_single_param_flow_source (ipf);
    3815                 :      163398 :           isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
    3816                 :      163398 :           if (!param_desc->split_candidate)
    3817                 :      113220 :             continue;
    3818                 :       50178 :           gcc_assert (param_desc->by_ref);
    3819                 :             : 
    3820                 :       50178 :           if (!arg_desc->split_candidate || !arg_desc->by_ref)
    3821                 :             :             {
    3822                 :       42932 :               if (dump_file && (dump_flags & TDF_DETAILS))
    3823                 :           2 :                 fprintf (dump_file, "  %u->%u: not candidate or not by "
    3824                 :             :                          "reference in callee\n", idx, i);
    3825                 :       42932 :               param_desc->split_candidate = false;
    3826                 :       42932 :               ipf->pointer_pass_through = false;
    3827                 :       42932 :               res = true;
    3828                 :             :             }
    3829                 :        7246 :           else if (!ipf->safe_to_import_accesses)
    3830                 :             :             {
    3831                 :        1113 :               if (!csum->m_before_any_store
    3832                 :        1113 :                   || !all_callee_accesses_present_p (param_desc, arg_desc))
    3833                 :             :                 {
    3834                 :        1089 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    3835                 :           0 :                     fprintf (dump_file, "  %u->%u: cannot import accesses.\n",
    3836                 :             :                              idx, i);
    3837                 :        1089 :                   param_desc->split_candidate = false;
    3838                 :        1089 :                   ipf->pointer_pass_through = false;
    3839                 :        1089 :                   res = true;
    3840                 :             : 
    3841                 :             :                 }
    3842                 :             :               else
    3843                 :             :                 {
    3844                 :          24 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    3845                 :           0 :                     fprintf (dump_file, "  %u->%u: verified callee accesses "
    3846                 :             :                              "present.\n", idx, i);
    3847                 :          24 :                   if (cross_scc)
    3848                 :           0 :                     ipf->pointer_pass_through = false;
    3849                 :             :                 }
    3850                 :             :             }
    3851                 :             :           else
    3852                 :             :             {
    3853                 :        6133 :               const char *pull_failure
    3854                 :        6133 :                 = pull_accesses_from_callee (cs->caller, param_desc, arg_desc,
    3855                 :             :                                              0, 0, &res);
    3856                 :        6133 :               if (pull_failure)
    3857                 :             :                 {
    3858                 :         347 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    3859                 :           0 :                     fprintf (dump_file, "  %u->%u: by_ref access pull "
    3860                 :             :                              "failed: %s.\n", idx, i, pull_failure);
    3861                 :         347 :                   param_desc->split_candidate = false;
    3862                 :         347 :                   ipf->pointer_pass_through = false;
    3863                 :         347 :                   res = true;
    3864                 :             :                 }
    3865                 :             :               else
    3866                 :             :                 {
    3867                 :        5786 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    3868                 :           1 :                     fprintf (dump_file, "  %u->%u: by_ref access pull "
    3869                 :             :                              "succeeded.\n", idx, i);
    3870                 :        5786 :                   if (cross_scc)
    3871                 :        5773 :                     ipf->pointer_pass_through = false;
    3872                 :             :                 }
    3873                 :             :             }
    3874                 :             :         }
    3875                 :     1096829 :       else if (ipf->aggregate_pass_through)
    3876                 :             :         {
    3877                 :       26827 :           int idx = get_single_param_flow_source (ipf);
    3878                 :       26827 :           isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
    3879                 :       26827 :           if (!param_desc->split_candidate)
    3880                 :       18121 :             continue;
    3881                 :        8706 :           gcc_assert (!param_desc->by_ref);
    3882                 :       17412 :           param_access *pacc = find_param_access (param_desc, ipf->unit_offset,
    3883                 :        8706 :                                                   ipf->unit_size);
    3884                 :        8706 :           gcc_checking_assert (pacc);
    3885                 :             : 
    3886                 :        8706 :           if (pacc->certain)
    3887                 :             :             {
    3888                 :           0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    3889                 :           0 :                 fprintf (dump_file, "  %u->%u: already certain\n", idx, i);
    3890                 :           0 :               ipf->aggregate_pass_through = false;
    3891                 :             :             }
    3892                 :        8706 :           else if (!arg_desc->split_candidate || arg_desc->by_ref)
    3893                 :             :             {
    3894                 :        7490 :               if (dump_file && (dump_flags & TDF_DETAILS))
    3895                 :           0 :                 fprintf (dump_file, "  %u->%u: not candidate or by "
    3896                 :             :                          "reference in callee\n", idx, i);
    3897                 :             : 
    3898                 :        7490 :               pacc->certain = true;
    3899                 :        7490 :               if (overlapping_certain_accesses_p (param_desc, NULL))
    3900                 :             :                 {
    3901                 :         630 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    3902                 :           0 :                     fprintf (dump_file, "    ...leading to overlap, "
    3903                 :             :                              " disqualifying candidate parameter %u\n",
    3904                 :             :                              idx);
    3905                 :         630 :                   param_desc->split_candidate = false;
    3906                 :             :                 }
    3907                 :             :               else
    3908                 :        6860 :                 bump_reached_size (param_desc, pacc->unit_size, idx);
    3909                 :             : 
    3910                 :        7490 :               ipf->aggregate_pass_through = false;
    3911                 :        7490 :               res = true;
    3912                 :             :             }
    3913                 :             :           else
    3914                 :             :             {
    3915                 :        1216 :               const char *pull_failure
    3916                 :        1216 :                 = pull_accesses_from_callee (cs->caller, param_desc, arg_desc,
    3917                 :             :                                              ipf->unit_offset,
    3918                 :             :                                              ipf->unit_size, &res);
    3919                 :        1216 :               if (pull_failure)
    3920                 :             :                 {
    3921                 :          56 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    3922                 :           0 :                     fprintf (dump_file, "  %u->%u: arg access pull "
    3923                 :             :                              "failed: %s.\n", idx, i, pull_failure);
    3924                 :             : 
    3925                 :          56 :                   ipf->aggregate_pass_through = false;
    3926                 :          56 :                   pacc->certain = true;
    3927                 :             : 
    3928                 :          56 :                   if (overlapping_certain_accesses_p (param_desc, NULL))
    3929                 :             :                     {
    3930                 :          56 :                       if (dump_file && (dump_flags & TDF_DETAILS))
    3931                 :           0 :                         fprintf (dump_file, "    ...leading to overlap, "
    3932                 :             :                                  " disqualifying candidate parameter %u\n",
    3933                 :             :                                  idx);
    3934                 :          56 :                       param_desc->split_candidate = false;
    3935                 :             :                     }
    3936                 :             :                   else
    3937                 :           0 :                     bump_reached_size (param_desc, pacc->unit_size, idx);
    3938                 :             : 
    3939                 :          56 :                   res = true;
    3940                 :             :                 }
    3941                 :             :               else
    3942                 :             :                 {
    3943                 :        1160 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    3944                 :           0 :                     fprintf (dump_file, "  %u->%u: arg access pull "
    3945                 :             :                              "succeeded.\n", idx, i);
    3946                 :        1160 :                   if (cross_scc)
    3947                 :        1030 :                     ipf->aggregate_pass_through = false;
    3948                 :             :                 }
    3949                 :             :             }
    3950                 :             :         }
    3951                 :             :     }
    3952                 :             : 
    3953                 :             :   /* Handle argument-parameter count mismatches. */
    3954                 :     2229334 :   for (; (i < args_count); i++)
    3955                 :             :     {
    3956                 :      894303 :       isra_param_flow *ipf = &csum->m_arg_flow[i];
    3957                 :             : 
    3958                 :      894303 :       if (ipf->pointer_pass_through || ipf->aggregate_pass_through)
    3959                 :             :         {
    3960                 :      202632 :           int idx = get_single_param_flow_source (ipf);
    3961                 :      202632 :           ipf->pointer_pass_through = false;
    3962                 :      202632 :           ipf->aggregate_pass_through = false;
    3963                 :      202632 :           isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
    3964                 :      202632 :           if (!param_desc->split_candidate)
    3965                 :      202551 :             continue;
    3966                 :             : 
    3967                 :          81 :           if (dump_file && (dump_flags & TDF_DETAILS))
    3968                 :           0 :             fprintf (dump_file, "  %u->%u: no corresponding formal parameter\n",
    3969                 :             :                      idx, i);
    3970                 :          81 :           param_desc->split_candidate = false;
    3971                 :          81 :           res = true;
    3972                 :             :         }
    3973                 :             :     }
    3974                 :     1335031 :   return res;
    3975                 :             : }
    3976                 :             : 
    3977                 :             : /* Worker for call_for_symbol_and_aliases, look at all callers and if all their
    3978                 :             :    callers ignore the return value, or come from the same SCC and use the
    3979                 :             :    return value only to compute their return value, return false, otherwise
    3980                 :             :    return true.  */
    3981                 :             : 
    3982                 :             : static bool
    3983                 :      158283 : retval_used_p (cgraph_node *node, void *)
    3984                 :             : {
    3985                 :      229138 :   for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
    3986                 :             :     {
    3987                 :      204541 :       isra_call_summary *csum = call_sums->get (cs);
    3988                 :      204541 :       gcc_checking_assert (csum);
    3989                 :      204541 :       if (csum->m_return_ignored)
    3990                 :       66895 :         continue;
    3991                 :      137646 :       if (!csum->m_return_returned)
    3992                 :             :         return true;
    3993                 :             : 
    3994                 :       22907 :       isra_func_summary *from_ifs = func_sums->get (cs->caller);
    3995                 :       22907 :       if (!from_ifs || !from_ifs->m_candidate)
    3996                 :             :         return true;
    3997                 :             : 
    3998                 :       17167 :       if (!ipa_edge_within_scc (cs)
    3999                 :       17167 :           && !from_ifs->m_return_ignored)
    4000                 :             :             return true;
    4001                 :             :     }
    4002                 :             : 
    4003                 :             :   return false;
    4004                 :             : }
    4005                 :             : 
    4006                 :             : /* Push into NEW_PARAMS all required parameter adjustment entries to copy or
    4007                 :             :    modify parameter which originally had index BASE_INDEX, in the adjustment
    4008                 :             :    vector of parent clone (if any) had PREV_CLONE_INDEX and was described by
    4009                 :             :    PREV_ADJUSTMENT.  If IPA-CP has created a transformation summary for the
    4010                 :             :    original node, it needs to be passed in IPCP_TS, otherwise it should be
    4011                 :             :    NULL.  If the parent clone is the original function, PREV_ADJUSTMENT is NULL
    4012                 :             :    and PREV_CLONE_INDEX is equal to BASE_INDEX.  */
    4013                 :             : 
    4014                 :             : static void
    4015                 :      257134 : push_param_adjustments_for_index (isra_func_summary *ifs, unsigned base_index,
    4016                 :             :                                   unsigned prev_clone_index,
    4017                 :             :                                   ipa_adjusted_param *prev_adjustment,
    4018                 :             :                                   ipcp_transformation *ipcp_ts,
    4019                 :             :                                   vec<ipa_adjusted_param, va_gc> **new_params)
    4020                 :             : {
    4021                 :      257134 :   isra_param_desc *desc = &(*ifs->m_parameters)[base_index];
    4022                 :      257134 :   if (desc->locally_unused)
    4023                 :             :     {
    4024                 :       46807 :       if (dump_file)
    4025                 :          27 :         fprintf (dump_file, "  Will remove parameter %u\n", base_index);
    4026                 :       46807 :       return;
    4027                 :             :     }
    4028                 :             : 
    4029                 :      210327 :   if (!desc->split_candidate)
    4030                 :             :     {
    4031                 :      163713 :       ipa_adjusted_param adj;
    4032                 :      163713 :       if (prev_adjustment)
    4033                 :             :         {
    4034                 :        1293 :           adj = *prev_adjustment;
    4035                 :        1293 :           adj.prev_clone_adjustment = true;
    4036                 :        1293 :           adj.prev_clone_index = prev_clone_index;
    4037                 :             :         }
    4038                 :             :       else
    4039                 :             :         {
    4040                 :      162420 :           memset (&adj, 0, sizeof (adj));
    4041                 :      162420 :           adj.op = IPA_PARAM_OP_COPY;
    4042                 :      162420 :           adj.base_index = base_index;
    4043                 :      162420 :           adj.prev_clone_index = prev_clone_index;
    4044                 :             :         }
    4045                 :      163713 :       vec_safe_push ((*new_params), adj);
    4046                 :      163713 :       return;
    4047                 :             :     }
    4048                 :             : 
    4049                 :       46614 :   if (dump_file)
    4050                 :          41 :     fprintf (dump_file, "  Will split parameter %u\n", base_index);
    4051                 :             : 
    4052                 :       46614 :   gcc_assert (!prev_adjustment || prev_adjustment->op == IPA_PARAM_OP_COPY);
    4053                 :       46614 :   unsigned aclen = vec_safe_length (desc->accesses);
    4054                 :      126978 :   for (unsigned j = 0; j < aclen; j++)
    4055                 :             :     {
    4056                 :       80364 :       param_access *pa = (*desc->accesses)[j];
    4057                 :       80364 :       if (!pa->certain)
    4058                 :        4810 :         continue;
    4059                 :             : 
    4060                 :       79433 :       if (ipcp_ts)
    4061                 :             :         {
    4062                 :       10456 :           ipa_argagg_value_list avl (ipcp_ts);
    4063                 :       10456 :           tree value = avl.get_value (base_index, pa->unit_offset);
    4064                 :       10456 :           if (value && !AGGREGATE_TYPE_P (pa->type))
    4065                 :             :             {
    4066                 :        3879 :               if (dump_file)
    4067                 :          20 :                 fprintf (dump_file, "    - omitting component at byte "
    4068                 :             :                          "offset %u which is known to have a constant value\n ",
    4069                 :             :                          pa->unit_offset);
    4070                 :        3879 :               continue;
    4071                 :             :             }
    4072                 :             :         }
    4073                 :             : 
    4074                 :       75554 :       if (dump_file)
    4075                 :          40 :         fprintf (dump_file, "    - component at byte offset %u, "
    4076                 :          40 :                  "size %u\n", pa->unit_offset, pa->unit_size);
    4077                 :             : 
    4078                 :       75554 :       ipa_adjusted_param adj;
    4079                 :       75554 :       memset (&adj, 0, sizeof (adj));
    4080                 :       75554 :       adj.op = IPA_PARAM_OP_SPLIT;
    4081                 :       75554 :       adj.base_index = base_index;
    4082                 :       75554 :       adj.prev_clone_index = prev_clone_index;
    4083                 :       75554 :       adj.param_prefix_index = IPA_PARAM_PREFIX_ISRA;
    4084                 :       75554 :       adj.reverse = pa->reverse;
    4085                 :       75554 :       adj.type = pa->type;
    4086                 :       75554 :       adj.alias_ptr_type = pa->alias_ptr_type;
    4087                 :       75554 :       adj.unit_offset = pa->unit_offset;
    4088                 :       75554 :       vec_safe_push ((*new_params), adj);
    4089                 :             :     }
    4090                 :             : }
    4091                 :             : 
    4092                 :             : /* Worker for all call_for_symbol_thunks_and_aliases.  Set calls_comdat_local
    4093                 :             :    flag of all callers of NODE.  */
    4094                 :             : 
    4095                 :             : static bool
    4096                 :           1 : mark_callers_calls_comdat_local (struct cgraph_node *node, void *)
    4097                 :             : {
    4098                 :           3 :   for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
    4099                 :           2 :     cs->caller->calls_comdat_local = true;
    4100                 :           1 :   return false;
    4101                 :             : }
    4102                 :             : 
    4103                 :             : /* Remove any IPA-CP results stored in TS that are associated with removed
    4104                 :             :    parameters as marked in IFS. */
    4105                 :             : 
    4106                 :             : static void
    4107                 :        6626 : zap_useless_ipcp_results (const isra_func_summary *ifs, ipcp_transformation *ts)
    4108                 :             : {
    4109                 :        6626 :   ts->remove_argaggs_if ([ifs](const ipa_argagg_value &v)
    4110                 :             :   {
    4111                 :        8992 :     return (*ifs->m_parameters)[v.index].locally_unused;
    4112                 :             :   });
    4113                 :             : 
    4114                 :        6626 :   bool useful_vr = false;
    4115                 :        6626 :   unsigned count = vec_safe_length (ts->m_vr);
    4116                 :       22226 :   for (unsigned i = 0; i < count; i++)
    4117                 :       15600 :     if ((*ts->m_vr)[i].known_p ())
    4118                 :             :       {
    4119                 :       11120 :         const isra_param_desc *desc = &(*ifs->m_parameters)[i];
    4120                 :       11120 :         if (desc->locally_unused)
    4121                 :        1449 :           (*ts->m_vr)[i].set_unknown ();
    4122                 :             :         else
    4123                 :             :           useful_vr = true;
    4124                 :             :       }
    4125                 :        6626 :   if (!useful_vr)
    4126                 :        1176 :     ts->m_vr = NULL;
    4127                 :        6626 : }
    4128                 :             : 
    4129                 :             : /* Do final processing of results of IPA propagation regarding NODE, clone it
    4130                 :             :    if appropriate.  */
    4131                 :             : 
    4132                 :             : static void
    4133                 :     1182146 : process_isra_node_results (cgraph_node *node,
    4134                 :             :                            hash_map<const char *, unsigned> *clone_num_suffixes)
    4135                 :             : {
    4136                 :     1182146 :   isra_func_summary *ifs = func_sums->get (node);
    4137                 :     1182146 :   if (!ifs || !ifs->m_candidate)
    4138                 :     1088288 :     return;
    4139                 :             : 
    4140                 :      322042 :   auto_vec<bool, 16> surviving_params;
    4141                 :      322042 :   bool check_surviving = false;
    4142                 :      322042 :   clone_info *cinfo = clone_info::get (node);
    4143                 :      322042 :   if (cinfo && cinfo->param_adjustments)
    4144                 :             :     {
    4145                 :       12742 :       check_surviving = true;
    4146                 :       12742 :       cinfo->param_adjustments->get_surviving_params (&surviving_params);
    4147                 :             :     }
    4148                 :             : 
    4149                 :      322042 :   unsigned param_count = vec_safe_length (ifs->m_parameters);
    4150                 :      322042 :   bool will_change_function = false;
    4151                 :      322042 :   if (ifs->m_returns_value && ifs->m_return_ignored)
    4152                 :             :     will_change_function = true;
    4153                 :             :   else
    4154                 :      761034 :     for (unsigned i = 0; i < param_count; i++)
    4155                 :             :       {
    4156                 :      532850 :         isra_param_desc *desc = &(*ifs->m_parameters)[i];
    4157                 :      532850 :         if ((desc->locally_unused || desc->split_candidate)
    4158                 :             :             /* Make sure we do not clone just to attempt to remove an already
    4159                 :             :                removed unused argument.  */
    4160                 :      532850 :             && (!check_surviving
    4161                 :      465987 :                 || (i < surviving_params.length ()
    4162                 :        2727 :                     && surviving_params[i])))
    4163                 :             :           {
    4164                 :             :             will_change_function = true;
    4165                 :             :             break;
    4166                 :             :           }
    4167                 :             :       }
    4168                 :      297774 :   if (!will_change_function)
    4169                 :      228184 :     return;
    4170                 :             : 
    4171                 :       93858 :   if (dump_file)
    4172                 :             :     {
    4173                 :          63 :       fprintf (dump_file, "\nEvaluating analysis results for %s\n",
    4174                 :             :                node->dump_name ());
    4175                 :          63 :       if (ifs->m_returns_value && ifs->m_return_ignored)
    4176                 :          15 :         fprintf (dump_file, "  Will remove return value.\n");
    4177                 :             :     }
    4178                 :             : 
    4179                 :       93858 :   ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node);
    4180                 :       93858 :   if (ipcp_ts)
    4181                 :        6626 :     zap_useless_ipcp_results (ifs, ipcp_ts);
    4182                 :       93858 :   vec<ipa_adjusted_param, va_gc> *new_params = NULL;
    4183                 :       93858 :   if (ipa_param_adjustments *old_adjustments
    4184                 :       93858 :          = cinfo ? cinfo->param_adjustments : NULL)
    4185                 :             :     {
    4186                 :        1896 :       unsigned old_adj_len = vec_safe_length (old_adjustments->m_adj_params);
    4187                 :        4396 :       for (unsigned i = 0; i < old_adj_len; i++)
    4188                 :             :         {
    4189                 :        2500 :           ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
    4190                 :        2500 :           push_param_adjustments_for_index (ifs, old_adj->base_index, i,
    4191                 :             :                                             old_adj, ipcp_ts, &new_params);
    4192                 :             :         }
    4193                 :             :     }
    4194                 :             :   else
    4195                 :      346596 :     for (unsigned i = 0; i < param_count; i++)
    4196                 :      254634 :       push_param_adjustments_for_index (ifs, i, i, NULL, ipcp_ts, &new_params);
    4197                 :             : 
    4198                 :       93858 :   ipa_param_adjustments *new_adjustments
    4199                 :       93858 :     = (new (ggc_alloc <ipa_param_adjustments> ())
    4200                 :             :        ipa_param_adjustments (new_params, param_count,
    4201                 :       93858 :                               ifs->m_returns_value && ifs->m_return_ignored));
    4202                 :             : 
    4203                 :       93858 :   if (dump_file && (dump_flags & TDF_DETAILS))
    4204                 :             :     {
    4205                 :           9 :       fprintf (dump_file, "\n  Created adjustments:\n");
    4206                 :           9 :       new_adjustments->dump (dump_file);
    4207                 :             :     }
    4208                 :             : 
    4209                 :      281574 :   unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
    4210                 :       93858 :                                IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
    4211                 :             :                                  node->decl)));
    4212                 :       93858 :   auto_vec<cgraph_edge *> callers = node->collect_callers ();
    4213                 :       93858 :   cgraph_node *new_node
    4214                 :       93858 :     = node->create_virtual_clone (callers, NULL, new_adjustments, "isra",
    4215                 :             :                                   suffix_counter);
    4216                 :       93858 :   suffix_counter++;
    4217                 :       93858 :   if (node->calls_comdat_local && node->same_comdat_group)
    4218                 :             :     {
    4219                 :           1 :       new_node->add_to_same_comdat_group (node);
    4220                 :           1 :       new_node->call_for_symbol_and_aliases (mark_callers_calls_comdat_local,
    4221                 :             :                                              NULL, true);
    4222                 :             :     }
    4223                 :       93858 :   new_node->calls_comdat_local = node->calls_comdat_local;
    4224                 :             : 
    4225                 :       93858 :   if (dump_file)
    4226                 :          63 :     fprintf (dump_file, "  Created new node %s\n", new_node->dump_name ());
    4227                 :       93858 :   callers.release ();
    4228                 :      322042 : }
    4229                 :             : 
    4230                 :             : /* If INDICES is not empty, dump a combination of NODE's dump_name and MSG
    4231                 :             :    followed by the list of numbers in INDICES.  */
    4232                 :             : 
    4233                 :             : static void
    4234                 :      551892 : dump_list_of_param_indices (const cgraph_node *node, const char* msg,
    4235                 :             :                             const vec<unsigned> &indices)
    4236                 :             : {
    4237                 :      551892 :   if (indices.is_empty ())
    4238                 :             :     return;
    4239                 :           1 :   fprintf (dump_file, "The following parameters of %s %s:", node->dump_name (),
    4240                 :             :            msg);
    4241                 :           4 :   for (unsigned i : indices)
    4242                 :           1 :     fprintf (dump_file, " %u", i);
    4243                 :           1 :   fprintf (dump_file, "\n");
    4244                 :             : }
    4245                 :             : 
    4246                 :             : /* Check which parameters of NODE described by IFS have survived until IPA-SRA
    4247                 :             :    and disable transformations for those which have not or which should not
    4248                 :             :    transformed because the associated debug counter reached its limit.  Return
    4249                 :             :    true if none survived or if there were no candidates to begin with.
    4250                 :             :    Additionally, also adjust parameter descriptions based on debug counters and
    4251                 :             :    hints propagated earlier.  */
    4252                 :             : 
    4253                 :             : static bool
    4254                 :      322042 : adjust_parameter_descriptions (cgraph_node *node, isra_func_summary *ifs)
    4255                 :             : {
    4256                 :      322042 :   bool ret = true;
    4257                 :      322042 :   unsigned len = vec_safe_length (ifs->m_parameters);
    4258                 :      275946 :   if (!len)
    4259                 :             :     return true;
    4260                 :             : 
    4261                 :      275946 :   auto_vec<bool, 16> surviving_params;
    4262                 :      275946 :   bool check_surviving = false;
    4263                 :      275946 :   clone_info *cinfo = clone_info::get (node);
    4264                 :      275946 :   if (cinfo && cinfo->param_adjustments)
    4265                 :             :     {
    4266                 :       12742 :       check_surviving = true;
    4267                 :       12742 :       cinfo->param_adjustments->get_surviving_params (&surviving_params);
    4268                 :             :     }
    4269                 :      275946 :   ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node);
    4270                 :      275946 :   auto_vec <unsigned> dump_dead_indices;
    4271                 :      275946 :   auto_vec <unsigned> dump_bad_cond_indices;
    4272                 :      931736 :   for (unsigned i = 0; i < len; i++)
    4273                 :             :     {
    4274                 :      655790 :       isra_param_desc *desc = &(*ifs->m_parameters)[i];
    4275                 :      655790 :       if (!dbg_cnt (ipa_sra_params))
    4276                 :             :         {
    4277                 :           0 :           desc->locally_unused = false;
    4278                 :           0 :           desc->split_candidate = false;
    4279                 :           0 :           continue;
    4280                 :             :         }
    4281                 :             : 
    4282                 :      655790 :       if (desc->split_only_when_retval_removed
    4283                 :        4570 :                && !ifs->m_return_ignored)
    4284                 :             :         {
    4285                 :           0 :           if (dump_file && (dump_flags & TDF_DETAILS)
    4286                 :        1227 :               && (desc->locally_unused || desc->split_candidate))
    4287                 :           0 :             dump_bad_cond_indices.safe_push (i);
    4288                 :             : 
    4289                 :        1227 :           gcc_checking_assert (!desc->locally_unused
    4290                 :             :                                || desc->remove_only_when_retval_removed);
    4291                 :        1227 :           desc->locally_unused = false;
    4292                 :        1227 :           desc->split_candidate = false;
    4293                 :        1227 :           continue;
    4294                 :             :         }
    4295                 :      654563 :       if (desc->remove_only_when_retval_removed
    4296                 :       37781 :                && !ifs->m_return_ignored)
    4297                 :             :         {
    4298                 :           6 :           if (dump_file && (dump_flags & TDF_DETAILS)
    4299                 :       30629 :               && (desc->locally_unused || desc->split_candidate))
    4300                 :           0 :             dump_bad_cond_indices.safe_push (i);
    4301                 :             : 
    4302                 :       30629 :           desc->locally_unused = false;
    4303                 :             :         }
    4304                 :      654563 :       if (check_surviving
    4305                 :      691502 :                && (i >= surviving_params.length ()
    4306                 :       18090 :                    || !surviving_params[i]))
    4307                 :             :         {
    4308                 :             :           /* Even if the parameter was removed by a previous IPA pass, we do
    4309                 :             :              not clear locally_unused because if it really is unused, this
    4310                 :             :              information might be useful in callers.  */
    4311                 :       23044 :           desc->split_candidate = false;
    4312                 :             : 
    4313                 :       23044 :           if (dump_file && (dump_flags & TDF_DETAILS))
    4314                 :           0 :             dump_dead_indices.safe_push (i);
    4315                 :             :         }
    4316                 :             : 
    4317                 :      654563 :       if (desc->split_candidate && desc->conditionally_dereferenceable)
    4318                 :             :         {
    4319                 :         701 :           gcc_assert (desc->safe_size_set);
    4320                 :        1225 :           for (param_access *pa : *desc->accesses)
    4321                 :        1097 :             if ((pa->unit_offset + pa->unit_size) > desc->safe_size)
    4322                 :             :               {
    4323                 :         573 :                 if (dump_file && (dump_flags & TDF_DETAILS))
    4324                 :           1 :                   dump_bad_cond_indices.safe_push (i);
    4325                 :         573 :                 desc->split_candidate = false;
    4326                 :         573 :                 break;
    4327                 :             :               }
    4328                 :             :         }
    4329                 :             : 
    4330                 :      654563 :       if (desc->split_candidate)
    4331                 :             :         {
    4332                 :      179834 :           if (desc->by_ref && !desc->not_specially_constructed)
    4333                 :             :             {
    4334                 :       23537 :               int extra_factor
    4335                 :       23537 :                 = opt_for_fn (node->decl,
    4336                 :             :                               param_ipa_sra_ptrwrap_growth_factor);
    4337                 :       23537 :               desc->param_size_limit = extra_factor * desc->param_size_limit;
    4338                 :             :             }
    4339                 :      179834 :           if (size_would_violate_limit_p (desc, desc->size_reached))
    4340                 :        2670 :             desc->split_candidate = false;
    4341                 :             :         }
    4342                 :             : 
    4343                 :             :       /* Avoid ICEs on size-mismatched VIEW_CONVERT_EXPRs when callers and
    4344                 :             :          callees don't agree on types in aggregates and we try to do both
    4345                 :             :          IPA-CP and IPA-SRA.  */
    4346                 :      654563 :       if (ipcp_ts && desc->split_candidate)
    4347                 :             :         {
    4348                 :       20436 :           ipa_argagg_value_list avl (ipcp_ts);
    4349                 :       46332 :           for (const param_access *pa : desc->accesses)
    4350                 :             :             {
    4351                 :       12238 :               if (!pa->certain)
    4352                 :         865 :                 continue;
    4353                 :       11373 :               tree value = avl.get_value (i, pa->unit_offset);
    4354                 :       11373 :               if (value
    4355                 :       11373 :                   && ((tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value)))
    4356                 :        3941 :                        / BITS_PER_UNIT)
    4357                 :        3941 :                       != pa->unit_size))
    4358                 :             :                 {
    4359                 :          20 :                   desc->split_candidate = false;
    4360                 :          20 :                   if (dump_file && (dump_flags & TDF_DETAILS))
    4361                 :           0 :                     dump_dead_indices.safe_push (i);
    4362                 :             :                   break;
    4363                 :             :                 }
    4364                 :             :             }
    4365                 :             :         }
    4366                 :             : 
    4367                 :      654563 :       if (desc->locally_unused || desc->split_candidate)
    4368                 :      655790 :         ret = false;
    4369                 :             :     }
    4370                 :             : 
    4371                 :      275946 :   dump_list_of_param_indices (node, "are dead on arrival or have a type "
    4372                 :             :                               "mismatch with IPA-CP", dump_dead_indices);
    4373                 :      275946 :   dump_list_of_param_indices (node, "fail additional requirements ",
    4374                 :             :                               dump_bad_cond_indices);
    4375                 :             : 
    4376                 :      275946 :   return ret;
    4377                 :      275946 : }
    4378                 :             : 
    4379                 :             : 
    4380                 :             : /* Run the interprocedural part of IPA-SRA. */
    4381                 :             : 
    4382                 :             : static unsigned int
    4383                 :      119928 : ipa_sra_analysis (void)
    4384                 :             : {
    4385                 :      119928 :   if (dump_file)
    4386                 :             :     {
    4387                 :          58 :       fprintf (dump_file, "\n========== IPA-SRA IPA stage ==========\n");
    4388                 :          58 :       ipa_sra_dump_all_summaries (dump_file, false);
    4389                 :             :     }
    4390                 :             : 
    4391                 :      119928 :   gcc_checking_assert (func_sums);
    4392                 :      119928 :   gcc_checking_assert (call_sums);
    4393                 :      119928 :   cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count);
    4394                 :      119928 :   auto_vec <cgraph_node *, 16> stack;
    4395                 :      119928 :   int node_scc_count = ipa_reduced_postorder (order, true, NULL);
    4396                 :             : 
    4397                 :             :   /* One sweep from callers to callees for return value removal.  */
    4398                 :     1368198 :   for (int i = node_scc_count - 1; i >= 0 ; i--)
    4399                 :             :     {
    4400                 :     1248270 :       cgraph_node *scc_rep = order[i];
    4401                 :     1248270 :       vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
    4402                 :             : 
    4403                 :             :       /* Preliminary IPA function level checks.  */
    4404                 :     4999984 :       for (cgraph_node *v : cycle_nodes)
    4405                 :             :         {
    4406                 :     1255174 :           isra_func_summary *ifs = func_sums->get (v);
    4407                 :     1255174 :           if (!ifs || !ifs->m_candidate)
    4408                 :      303523 :             continue;
    4409                 :      951651 :           if (!ipa_sra_ipa_function_checks (v)
    4410                 :      951651 :               || check_all_callers_for_issues (v))
    4411                 :      629609 :             ifs->zap ();
    4412                 :             :         }
    4413                 :             : 
    4414                 :     3751714 :       for (cgraph_node *v : cycle_nodes)
    4415                 :             :         {
    4416                 :     1255174 :           isra_func_summary *ifs = func_sums->get (v);
    4417                 :     1255174 :           if (!ifs || !ifs->m_candidate)
    4418                 :      933132 :             continue;
    4419                 :      322042 :           bool return_needed
    4420                 :      322042 :             = (ifs->m_returns_value
    4421                 :      322042 :                && (!dbg_cnt (ipa_sra_retvalues)
    4422                 :      158272 :                    || v->call_for_symbol_and_aliases (retval_used_p,
    4423                 :      322042 :                                                       NULL, true)));
    4424                 :      322042 :           ifs->m_return_ignored = !return_needed;
    4425                 :      322042 :           if (return_needed)
    4426                 :      267372 :             isra_push_node_to_stack (v, ifs, &stack);
    4427                 :             :         }
    4428                 :             : 
    4429                 :     1382274 :       while (!stack.is_empty ())
    4430                 :             :         {
    4431                 :      134004 :           cgraph_node *node = stack.pop ();
    4432                 :      134004 :           isra_func_summary *ifs = func_sums->get (node);
    4433                 :      134004 :           gcc_checking_assert (ifs && ifs->m_queued);
    4434                 :      134004 :           ifs->m_queued = false;
    4435                 :             : 
    4436                 :      803298 :           for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
    4437                 :      669294 :             if (ipa_edge_within_scc (cs)
    4438                 :      669294 :                 && call_sums->get (cs)->m_return_returned)
    4439                 :             :               {
    4440                 :         836 :                 enum availability av;
    4441                 :         836 :                 cgraph_node *callee = cs->callee->function_symbol (&av);
    4442                 :         836 :                 isra_func_summary *to_ifs = func_sums->get (callee);
    4443                 :         836 :                 if (to_ifs && to_ifs->m_return_ignored)
    4444                 :             :                   {
    4445                 :         318 :                     to_ifs->m_return_ignored = false;
    4446                 :         636 :                     isra_push_node_to_stack (callee, to_ifs, &stack);
    4447                 :             :                   }
    4448                 :             :               }
    4449                 :             :         }
    4450                 :             : 
    4451                 :             :       /* Parameter hint propagation.  */
    4452                 :     3751714 :       for (cgraph_node *v : cycle_nodes)
    4453                 :             :         {
    4454                 :     1255174 :           isra_func_summary *ifs = func_sums->get (v);
    4455                 :     1255174 :           propagate_hints_to_all_callees (v, ifs, &stack);
    4456                 :             :         }
    4457                 :             : 
    4458                 :     1252245 :       while (!stack.is_empty ())
    4459                 :             :         {
    4460                 :        3975 :           cgraph_node *node = stack.pop ();
    4461                 :        3975 :           isra_func_summary *ifs = func_sums->get (node);
    4462                 :        3975 :           gcc_checking_assert (ifs && ifs->m_queued);
    4463                 :        3975 :           ifs->m_queued = false;
    4464                 :        3975 :           propagate_hints_to_all_callees (node, ifs, &stack);
    4465                 :             :         }
    4466                 :             : 
    4467                 :     1248270 :       cycle_nodes.release ();
    4468                 :             :     }
    4469                 :             : 
    4470                 :             :   /* One sweep from callees to callers for parameter removal and splitting.  */
    4471                 :     1368198 :   for (int i = 0; i < node_scc_count; i++)
    4472                 :             :     {
    4473                 :     1248270 :       cgraph_node *scc_rep = order[i];
    4474                 :     1248270 :       vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
    4475                 :             : 
    4476                 :             :       /* First step of parameter removal.  */
    4477                 :     4999984 :       for (cgraph_node *v : cycle_nodes)
    4478                 :             :         {
    4479                 :     1255174 :           isra_func_summary *ifs = func_sums->get (v);
    4480                 :     1255174 :           if (!ifs || !ifs->m_candidate)
    4481                 :      933132 :             continue;
    4482                 :      322042 :           if (adjust_parameter_descriptions (v, ifs))
    4483                 :      164255 :             continue;
    4484                 :      172652 :           for (cgraph_edge *cs = v->indirect_calls; cs; cs = cs->next_callee)
    4485                 :       14865 :             process_edge_to_unknown_caller (cs);
    4486                 :      908000 :           for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
    4487                 :      750213 :             if (!ipa_edge_within_scc (cs))
    4488                 :      741027 :               param_removal_cross_scc_edge (cs);
    4489                 :             :         }
    4490                 :             : 
    4491                 :             :       /* Look at edges within the current SCC and propagate used-ness across
    4492                 :             :          them, pushing onto the stack all notes which might need to be
    4493                 :             :          revisited.  */
    4494                 :     3751714 :       for (cgraph_node *v : cycle_nodes)
    4495                 :     1255174 :         v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers,
    4496                 :             :                                                &stack, true);
    4497                 :             : 
    4498                 :             :       /* Keep revisiting and pushing until nothing changes.  */
    4499                 :     1250612 :       while (!stack.is_empty ())
    4500                 :             :         {
    4501                 :        2342 :           cgraph_node *v = stack.pop ();
    4502                 :        2342 :           isra_func_summary *ifs = func_sums->get (v);
    4503                 :        2342 :           gcc_checking_assert (ifs && ifs->m_queued);
    4504                 :        2342 :           ifs->m_queued = false;
    4505                 :             : 
    4506                 :        2342 :           v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers,
    4507                 :             :                                                  &stack, true);
    4508                 :             :         }
    4509                 :             : 
    4510                 :             :       /* Parameter splitting.  */
    4511                 :     1288689 :       bool repeat_scc_access_propagation;
    4512                 :     1288689 :       do
    4513                 :             :         {
    4514                 :     1288689 :           repeat_scc_access_propagation = false;
    4515                 :     3877351 :           for (cgraph_node *v : cycle_nodes)
    4516                 :             :             {
    4517                 :     1299973 :               isra_func_summary *ifs = func_sums->get (v);
    4518                 :     2279921 :               if (!ifs
    4519                 :      998987 :                   || !ifs->m_candidate
    4520                 :     1666094 :                   || vec_safe_is_empty (ifs->m_parameters))
    4521                 :      979948 :                 continue;
    4522                 :     1655056 :               for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
    4523                 :     1335031 :                 if (param_splitting_across_edge (cs))
    4524                 :       46315 :                   repeat_scc_access_propagation = true;
    4525                 :             :             }
    4526                 :             :         }
    4527                 :             :       while (repeat_scc_access_propagation);
    4528                 :             : 
    4529                 :     1248270 :       if (flag_checking)
    4530                 :     3751651 :         for (cgraph_node *v : cycle_nodes)
    4531                 :     1255153 :           verify_splitting_accesses (v, true);
    4532                 :             : 
    4533                 :     1248270 :       cycle_nodes.release ();
    4534                 :             :     }
    4535                 :             : 
    4536                 :      119928 :   ipa_free_postorder_info ();
    4537                 :      119928 :   free (order);
    4538                 :             : 
    4539                 :      119928 :   if (dump_file)
    4540                 :             :     {
    4541                 :          58 :       if (dump_flags & TDF_DETAILS)
    4542                 :             :         {
    4543                 :           9 :           fprintf (dump_file, "\n========== IPA-SRA propagation final state "
    4544                 :             :                    " ==========\n");
    4545                 :           9 :           ipa_sra_dump_all_summaries (dump_file, true);
    4546                 :             :         }
    4547                 :          58 :       fprintf (dump_file, "\n========== IPA-SRA decisions ==========\n");
    4548                 :             :     }
    4549                 :             : 
    4550                 :      119928 :   hash_map<const char *, unsigned> *clone_num_suffixes
    4551                 :      119928 :     = new hash_map<const char *, unsigned>;
    4552                 :             : 
    4553                 :      119928 :   cgraph_node *node;
    4554                 :     1302074 :   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
    4555                 :     1182146 :     process_isra_node_results (node, clone_num_suffixes);
    4556                 :             : 
    4557                 :      119928 :   delete clone_num_suffixes;
    4558                 :      119928 :   ggc_delete (func_sums);
    4559                 :      119928 :   func_sums = NULL;
    4560                 :      119928 :   delete call_sums;
    4561                 :      119928 :   call_sums = NULL;
    4562                 :             : 
    4563                 :      119928 :   if (dump_file)
    4564                 :          58 :     fprintf (dump_file, "\n========== IPA SRA IPA analysis done "
    4565                 :             :              "==========\n\n");
    4566                 :      119928 :   return 0;
    4567                 :      119928 : }
    4568                 :             : 
    4569                 :             : 
    4570                 :             : const pass_data pass_data_ipa_sra =
    4571                 :             : {
    4572                 :             :   IPA_PASS, /* type */
    4573                 :             :   "sra", /* name */
    4574                 :             :   OPTGROUP_NONE, /* optinfo_flags */
    4575                 :             :   TV_IPA_SRA, /* tv_id */
    4576                 :             :   0, /* properties_required */
    4577                 :             :   0, /* properties_provided */
    4578                 :             :   0, /* properties_destroyed */
    4579                 :             :   0, /* todo_flags_start */
    4580                 :             :   ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
    4581                 :             : };
    4582                 :             : 
    4583                 :             : class pass_ipa_sra : public ipa_opt_pass_d
    4584                 :             : {
    4585                 :             : public:
    4586                 :      281914 :   pass_ipa_sra (gcc::context *ctxt)
    4587                 :             :     : ipa_opt_pass_d (pass_data_ipa_sra, ctxt,
    4588                 :             :                       ipa_sra_generate_summary, /* generate_summary */
    4589                 :             :                       ipa_sra_write_summary, /* write_summary */
    4590                 :             :                       ipa_sra_read_summary, /* read_summary */
    4591                 :             :                       NULL , /* write_optimization_summary */
    4592                 :             :                       NULL, /* read_optimization_summary */
    4593                 :             :                       NULL, /* stmt_fixup */
    4594                 :             :                       0, /* function_transform_todo_flags_start */
    4595                 :             :                       NULL, /* function_transform */
    4596                 :      281914 :                       NULL) /* variable_transform */
    4597                 :      281914 :   {}
    4598                 :             : 
    4599                 :             :   /* opt_pass methods: */
    4600                 :      579463 :   bool gate (function *) final override
    4601                 :             :     {
    4602                 :             :       /* TODO: We should remove the optimize check after we ensure we never run
    4603                 :             :          IPA passes when not optimizing.  */
    4604                 :      579463 :       return (flag_ipa_sra && optimize);
    4605                 :             :     }
    4606                 :             : 
    4607                 :      119928 :   unsigned int execute (function *)  final override
    4608                 :             :   {
    4609                 :      119928 :     return ipa_sra_analysis ();
    4610                 :             :   }
    4611                 :             : 
    4612                 :             : }; // class pass_ipa_sra
    4613                 :             : 
    4614                 :             : } // anon namespace
    4615                 :             : 
    4616                 :             : /* Intraprocedural part of IPA-SRA analysis.  Scan function body of NODE and
    4617                 :             :    create a summary structure describing IPA-SRA opportunities and constraints
    4618                 :             :    in it.  */
    4619                 :             : 
    4620                 :             : static void
    4621                 :     1183850 : ipa_sra_summarize_function (cgraph_node *node)
    4622                 :             : {
    4623                 :     1183850 :   if (dump_file)
    4624                 :         202 :     fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
    4625                 :             :              node->order);
    4626                 :     1183850 :   gcc_obstack_init (&gensum_obstack);
    4627                 :     1183850 :   loaded_decls = new hash_set<tree>;
    4628                 :             : 
    4629                 :     1183850 :   isra_func_summary *ifs = NULL;
    4630                 :     1183850 :   unsigned count = 0;
    4631                 :     1183850 :   if (ipa_sra_preliminary_function_checks (node))
    4632                 :             :     {
    4633                 :      959572 :       ifs = func_sums->get_create (node);
    4634                 :      959572 :       ifs->m_candidate = true;
    4635                 :      959572 :       tree ret = TREE_TYPE (TREE_TYPE (node->decl));
    4636                 :      959572 :       ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
    4637                 :      959572 :       for (tree parm = DECL_ARGUMENTS (node->decl);
    4638                 :     3186753 :            parm;
    4639                 :     2227181 :            parm = DECL_CHAIN (parm))
    4640                 :     2227181 :         count++;
    4641                 :             :     }
    4642                 :     1183850 :   auto_vec<gensum_param_desc, 16> param_descriptions (count);
    4643                 :             : 
    4644                 :     1183850 :   struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
    4645                 :     1183850 :   bool cfun_pushed = false;
    4646                 :     1183850 :   if (count > 0)
    4647                 :             :     {
    4648                 :      777378 :       decl2desc = new hash_map<tree, gensum_param_desc *>;
    4649                 :      777378 :       param_descriptions.reserve_exact (count);
    4650                 :      777378 :       param_descriptions.quick_grow_cleared (count);
    4651                 :             : 
    4652                 :      777378 :       if (create_parameter_descriptors (node, &param_descriptions))
    4653                 :             :         {
    4654                 :      382622 :           push_cfun (fun);
    4655                 :      382622 :           cfun_pushed = true;
    4656                 :      382622 :           final_bbs = BITMAP_ALLOC (NULL);
    4657                 :      382622 :           bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
    4658                 :             :                                       unsafe_by_ref_count
    4659                 :             :                                       * last_basic_block_for_fn (fun));
    4660                 :      382622 :           aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
    4661                 :             :         }
    4662                 :             :     }
    4663                 :             :   /* Scan function is run even when there are no removal or splitting
    4664                 :             :      candidates so that we can calculate hints on call edges which can be
    4665                 :             :      useful in callees. */
    4666                 :     1183850 :   scan_function (node, fun);
    4667                 :             : 
    4668                 :     1183850 :   if (count > 0)
    4669                 :             :     {
    4670                 :      777378 :       if (dump_file)
    4671                 :             :         {
    4672                 :         143 :           dump_gensum_param_descriptors (dump_file, node->decl,
    4673                 :             :                                          &param_descriptions);
    4674                 :         143 :           fprintf (dump_file, "----------------------------------------\n");
    4675                 :             :         }
    4676                 :             : 
    4677                 :      777378 :       process_scan_results (node, fun, ifs, &param_descriptions);
    4678                 :             : 
    4679                 :      777378 :       if (cfun_pushed)
    4680                 :      382622 :         pop_cfun ();
    4681                 :      777378 :       if (bb_dereferences)
    4682                 :             :         {
    4683                 :      382622 :           free (bb_dereferences);
    4684                 :      382622 :           bb_dereferences = NULL;
    4685                 :      382622 :           BITMAP_FREE (final_bbs);
    4686                 :      382622 :           final_bbs = NULL;
    4687                 :             :         }
    4688                 :             :     }
    4689                 :     1183850 :   isra_analyze_all_outgoing_calls (node);
    4690                 :             : 
    4691                 :     2367700 :   delete loaded_decls;
    4692                 :     1183850 :   loaded_decls = NULL;
    4693                 :     1183850 :   if (decl2desc)
    4694                 :             :     {
    4695                 :      777378 :       delete decl2desc;
    4696                 :      777378 :       decl2desc = NULL;
    4697                 :             :     }
    4698                 :     1183850 :   obstack_free (&gensum_obstack, NULL);
    4699                 :     1183850 :   if (dump_file)
    4700                 :         202 :     fprintf (dump_file, "\n\n");
    4701                 :     1183850 :   if (flag_checking)
    4702                 :     1183828 :     verify_splitting_accesses (node, false);
    4703                 :     1183850 :   return;
    4704                 :     1183850 : }
    4705                 :             : 
    4706                 :             : ipa_opt_pass_d *
    4707                 :      281914 : make_pass_ipa_sra (gcc::context *ctxt)
    4708                 :             : {
    4709                 :      281914 :   return new pass_ipa_sra (ctxt);
    4710                 :             : }
    4711                 :             : 
    4712                 :             : /* Reset all state within ipa-sra.cc so that we can rerun the compiler
    4713                 :             :    within the same process.  For use by toplev::finalize.  */
    4714                 :             : 
    4715                 :             : void
    4716                 :      253805 : ipa_sra_cc_finalize (void)
    4717                 :             : {
    4718                 :      253805 :   if (func_sums)
    4719                 :        8467 :     ggc_delete (func_sums);
    4720                 :      253805 :   func_sums = NULL;
    4721                 :      253805 :   delete call_sums;
    4722                 :      253805 :   call_sums = NULL;
    4723                 :      253805 : }
    4724                 :             : 
    4725                 :             : #include "gt-ipa-sra.h"
        

Generated by: LCOV version 2.1-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.