LCOV - code coverage report
Current view: top level - gcc - ipa-param-manipulation.h (source / functions) Hit Total Coverage
Test: gcc.info Lines: 3 3 100.0 %
Date: 2020-04-04 11:58:09 Functions: 0 0 -
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Manipulation of formal and actual parameters of functions and function
       2                 :            :    calls.
       3                 :            :    Copyright (C) 2017-2020 Free Software Foundation, Inc.
       4                 :            : 
       5                 :            : This file is part of GCC.
       6                 :            : 
       7                 :            : GCC is free software; you can redistribute it and/or modify it under
       8                 :            : the terms of the GNU General Public License as published by the Free
       9                 :            : Software Foundation; either version 3, or (at your option) any later
      10                 :            : version.
      11                 :            : 
      12                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13                 :            : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15                 :            : for more details.
      16                 :            : 
      17                 :            : You should have received a copy of the GNU General Public License
      18                 :            : along with GCC; see the file COPYING3.  If not see
      19                 :            : <http://www.gnu.org/licenses/>.
      20                 :            : 
      21                 :            : 
      22                 :            : 
      23                 :            : This file defines classes and other data structures that are used to manipulate
      24                 :            : the prototype of a function, especially to create, remove or split its formal
      25                 :            : parameters, but also to remove its return value, and also its call statements
      26                 :            : correspondingly.
      27                 :            : 
      28                 :            : The most basic one is a vector of structures ipa_adjusted_param.  It is simply
      29                 :            : a description how the new parameters should look like after the transformation
      30                 :            : in what way they relate to the previous ones (if in any).  Such relation to an
      31                 :            : old parameter can be an outright copy or an IPA-SRA replacement. If an old
      32                 :            : parameter is not listed or otherwise mentioned, it is removed as unused or at
      33                 :            : least unnecessary.  Note that this most basic structure does not work for
      34                 :            : modifying calls of functions with variable number of arguments.
      35                 :            : 
      36                 :            : Class ipa_param_adjustments is only a little more than a thin encapsulation of
      37                 :            : a vector of ipa_param_adjustments.  Along with this vector it contains an index
      38                 :            : of the first potential vararg argument and a boolean flag whether the return
      39                 :            : value should be removed or not.  Moreover, the class contains method
      40                 :            : modify_call which can transform a call statement so that it correctly calls a
      41                 :            : modified function.  These two data structures were designed to have a small
      42                 :            : memory footprint because they are allocated for each clone of a call graph node
      43                 :            : that has its prototype changed and live until the end of IPA clone
      44                 :            : materialization and call redirection phase.
      45                 :            : 
      46                 :            : On the other hand, class ipa_param_body_adjustments can afford to allocate more
      47                 :            : data because its life span is much smaller, it is allocated and destroyed in
      48                 :            : the course of materialization of each single clone that needs it or only when a
      49                 :            : particular pass needs to change a function it is operating on.  This class has
      50                 :            : various methods required to change function declaration and the body of the
      51                 :            : function according to instructions given either by class ipa_param_adjustments
      52                 :            : or only a vector of ipa_adjusted_params.
      53                 :            : 
      54                 :            : When these classes are used in the context of call graph clone materialization
      55                 :            : and subsequent call statement redirection - which is the point at which we
      56                 :            : modify arguments in call statements - they need to cooperate with each other in
      57                 :            : order to handle what we refer to as transitive (IPA-SRA) splits.  These are
      58                 :            : situations when a formal parameter of one function is split into several
      59                 :            : smaller ones and some of them are then passed on in a call to another function
      60                 :            : because the formal parameter of this callee has also been split.
      61                 :            : 
      62                 :            : Consider a simple example:
      63                 :            : 
      64                 :            : struct S {int a, b, c;};
      65                 :            : struct Z {int x; S s;};
      66                 :            : 
      67                 :            : foo (S s)
      68                 :            : {
      69                 :            :   use (s.b);
      70                 :            : }
      71                 :            : 
      72                 :            : bar (Z z)
      73                 :            : {
      74                 :            :   use (z.s.a);
      75                 :            :   foo (z.s);
      76                 :            : }
      77                 :            : 
      78                 :            : baz ()
      79                 :            : {
      80                 :            :   bar (*global);
      81                 :            : }
      82                 :            : 
      83                 :            : Both bar and foo would have their parameter split.  Foo would receive one
      84                 :            : replacement representing s.b.  Function bar would see its parameter split into
      85                 :            : one replacement representing z.s.a and another representing z.s.b which would
      86                 :            : be passed on to foo.  It would be a so called transitive split IPA-SRA
      87                 :            : replacement, one which is passed in a call as an actual argument to another
      88                 :            : IPA-SRA replacement in another function.
      89                 :            : 
      90                 :            : Note that the call chain the example can be arbitrarily long and recursive and
      91                 :            : that any function in it can be cloned by another IPA pass and any number of
      92                 :            : adjacent functions in the call chain can be inlined into each other.  Call
      93                 :            : redirection takes place only after bodies of the function have been modified by
      94                 :            : all of the above.
      95                 :            : 
      96                 :            : Call redirection has to be able to find the right decl or SSA_NAME that
      97                 :            : corresponds to the transitive split in the caller.  The SSA names are assigned
      98                 :            : right after clone materialization/ modification and cannot be "added"
      99                 :            : afterwards.  Moreover, if the caller has been inlined the SSA_NAMEs in question
     100                 :            : no longer belong to PARM_DECLs but to VAR_DECLs, indistinguishable from any
     101                 :            : others.
     102                 :            : 
     103                 :            : Therefore, when clone materialization finds a call statement which it knows is
     104                 :            : a part of a transitive split, it will modify it into:
     105                 :            : 
     106                 :            :   foo (DUMMY_Z_VAR.s, repl_for_a, repl_for_b, <rest of original arguments>);
     107                 :            : 
     108                 :            : It will also store {DUMMY_S_VAR, 32} and {DUMMY_S_VAR, 64} representing offsets
     109                 :            : of z.s.a and z.s.b (assuming a 32-bit int) into foo's cgraph node
     110                 :            : clone->performed_splits vector (which is storing structures of type
     111                 :            : ipa_param_performed_split also defined in this header file).
     112                 :            : 
     113                 :            : Call redirection will identify that expression DUMMY_Z_VAR.s is based on a
     114                 :            : variable stored in performed_splits vector and learn that the following
     115                 :            : arguments, already in SSA form, represent offsets 32 and 64 in a split original
     116                 :            : parameter.  It subtracts offset of DUMMY_Z_VAR.s from 32 and 64 and arrives at
     117                 :            : offsets 0 and 32 within callee's original parameter.  At this point it also
     118                 :            : knows from the call graph that only the bit with offset 32 is needed and so
     119                 :            : changes the call statement into final:
     120                 :            : 
     121                 :            : bar (repl_for_b, <rest of original arguments>);  */
     122                 :            : 
     123                 :            : #ifndef IPA_PARAM_MANIPULATION_H
     124                 :            : #define IPA_PARAM_MANIPULATION_H
     125                 :            : 
     126                 :            : /* Indices into ipa_param_prefixes to identify a human-readable prefix for newly
     127                 :            :    synthesized parameters.  Keep in sync with the array.  */
     128                 :            : enum ipa_param_name_prefix_indices
     129                 :            :   {
     130                 :            :    IPA_PARAM_PREFIX_SYNTH,
     131                 :            :    IPA_PARAM_PREFIX_ISRA,
     132                 :            :    IPA_PARAM_PREFIX_SIMD,
     133                 :            :    IPA_PARAM_PREFIX_MASK,
     134                 :            :    IPA_PARAM_PREFIX_COUNT
     135                 :            : };
     136                 :            : 
     137                 :            : /* We do not support manipulating functions with more than
     138                 :            :    1<<IPA_PARAM_MAX_INDEX_BITS parameters.  */
     139                 :            : #define IPA_PARAM_MAX_INDEX_BITS 16
     140                 :            : 
     141                 :            : /* Operation to be performed for the parameter in ipa_parm_adjustment
     142                 :            :    below.  */
     143                 :            : 
     144                 :            : enum ipa_parm_op
     145                 :            : {
     146                 :            :   /* Do not use or you will trigger an assert.  */
     147                 :            :   IPA_PARAM_OP_UNDEFINED,
     148                 :            : 
     149                 :            :   /* This new parameter is an unmodified parameter at index base_index. */
     150                 :            :   IPA_PARAM_OP_COPY,
     151                 :            : 
     152                 :            :   /* This describes a brand new parameter.  If it somehow relates to any
     153                 :            :      original parameters, the user needs to manage the transition itself.  */
     154                 :            :   IPA_PARAM_OP_NEW,
     155                 :            : 
     156                 :            :     /* Split parameter as indicated by fields base_index, offset and type.  */
     157                 :            :   IPA_PARAM_OP_SPLIT
     158                 :            : };
     159                 :            : 
     160                 :            : /* Structure that describes one parameter of a function after transformation.
     161                 :            :    Omitted parameters will be removed.  */
     162                 :            : 
     163                 :            : struct GTY(()) ipa_adjusted_param
     164                 :            : {
     165                 :            :   /* Type of the new parameter.  Required for all operations except
     166                 :            :      IPA_PARM_OP_COPY when the original type will be preserved.  */
     167                 :            :   tree type;
     168                 :            : 
     169                 :            :   /* Alias reference type to be used in MEM_REFs when adjusting caller
     170                 :            :      arguments.  Required for IPA_PARM_OP_SPLIT operation.  */
     171                 :            :   tree alias_ptr_type;
     172                 :            : 
     173                 :            :   /* Offset into the original parameter (for the cases when the new parameter
     174                 :            :      is a component of an original one).  Required for IPA_PARM_OP_SPLIT
     175                 :            :      operation.  */
     176                 :            :   unsigned unit_offset;
     177                 :            : 
     178                 :            :   /* Zero based index of the original parameter this one is based on.  Required
     179                 :            :      for IPA_PARAM_OP_COPY and IPA_PARAM_OP_SPLIT, users of IPA_PARAM_OP_NEW
     180                 :            :      only need to specify it if they use replacement lookup provided by
     181                 :            :      ipa_param_body_adjustments.  */
     182                 :            :   unsigned base_index : IPA_PARAM_MAX_INDEX_BITS;
     183                 :            : 
     184                 :            :   /* Zero based index of the parameter this one is based on in the previous
     185                 :            :      clone.  If there is no previous clone, it must be equal to base_index.  */
     186                 :            :   unsigned prev_clone_index : IPA_PARAM_MAX_INDEX_BITS;
     187                 :            : 
     188                 :            :   /* Specify the operation, if any, to be performed on the parameter.  */
     189                 :            :   enum ipa_parm_op op : 2;
     190                 :            : 
     191                 :            :   /* If set, this structure describes a parameter copied over from a previous
     192                 :            :      IPA clone, any transformations are thus not to be re-done.  */
     193                 :            :   unsigned prev_clone_adjustment : 1;
     194                 :            : 
     195                 :            :   /* Index into ipa_param_prefixes specifying a prefix to be used with
     196                 :            :      DECL_NAMEs of newly synthesized parameters.  */
     197                 :            :   unsigned param_prefix_index : 2;
     198                 :            : 
     199                 :            :   /* Storage order of the original parameter (for the cases when the new
     200                 :            :      parameter is a component of an original one).  */
     201                 :            :   unsigned reverse : 1;
     202                 :            : 
     203                 :            :   /* A bit free for the user.  */
     204                 :            :   unsigned user_flag : 1;
     205                 :            : };
     206                 :            : 
     207                 :            : void ipa_dump_adjusted_parameters (FILE *f,
     208                 :            :                                    vec<ipa_adjusted_param, va_gc> *adj_params);
     209                 :            : 
     210                 :            : /* Structure to remember the split performed on a node so that edge redirection
     211                 :            :    (i.e. splitting arguments of call statements) know how split formal
     212                 :            :    parameters of the caller are represented.  */
     213                 :            : 
     214                 :            : struct GTY(()) ipa_param_performed_split
     215                 :            : {
     216                 :            :   /* The dummy VAR_DECL that was created instead of the split parameter that
     217                 :            :      sits in the call in the meantime between clone materialization and call
     218                 :            :      redirection.  All entries in a vector of performed splits that correspond
     219                 :            :      to the same dumy decl must be grouped together.  */
     220                 :            :   tree dummy_decl;
     221                 :            :   /* Offset into the original parameter.  */
     222                 :            :   unsigned unit_offset;
     223                 :            : };
     224                 :            : 
     225                 :            : /* Class used to record planned modifications to parameters of a function and
     226                 :            :    also to perform necessary modifications at the caller side at the gimple
     227                 :            :    level.  Used to describe all cgraph node clones that have their parameters
     228                 :            :    changed, therefore the class should only have a small memory footprint.  */
     229                 :            : 
     230                 :            : class GTY(()) ipa_param_adjustments
     231                 :            : {
     232                 :            : public:
     233                 :            :   /* Constructor from NEW_PARAMS showing how new parameters should look like
     234                 :            :       plus copying any pre-existing actual arguments starting from argument
     235                 :            :       with index ALWAYS_COPY_START (if non-negative, negative means do not copy
     236                 :            :       anything beyond what is described in NEW_PARAMS), and SKIP_RETURN, which
     237                 :            :       indicates that the function should return void after transformation.  */
     238                 :            : 
     239                 :      80630 :   ipa_param_adjustments (vec<ipa_adjusted_param, va_gc> *new_params,
     240                 :            :                          int always_copy_start, bool skip_return)
     241                 :      80630 :     : m_adj_params (new_params), m_always_copy_start (always_copy_start),
     242                 :      80630 :     m_skip_return (skip_return)
     243                 :            :     {}
     244                 :            : 
     245                 :            :   /* Modify a call statement arguments (and possibly remove the return value)
     246                 :            :      as described in the data fields of this class.  */
     247                 :            :   gcall *modify_call (gcall *stmt,
     248                 :            :                       vec<ipa_param_performed_split, va_gc> *performed_splits,
     249                 :            :                       tree callee_decl, bool update_references);
     250                 :            :   /* Return if the first parameter is left intact.  */
     251                 :            :   bool first_param_intact_p ();
     252                 :            :   /* Build a function type corresponding to the modified call.  */
     253                 :            :   tree build_new_function_type (tree old_type, bool type_is_original_p);
     254                 :            :   /* Build a declaration corresponding to the target of the modified call.  */
     255                 :            :   tree adjust_decl (tree orig_decl);
     256                 :            :   /* Fill a vector marking which parameters are intact by the described
     257                 :            :      modifications. */
     258                 :            :   void get_surviving_params (vec<bool> *surviving_params);
     259                 :            :   /* Fill a vector with new indices of surviving original parameters.  */
     260                 :            :   void get_updated_indices (vec<int> *new_indices);
     261                 :            :   /* Return the original index for the given new parameter index.  Return a
     262                 :            :      negative number if not available.  */
     263                 :            :   int get_original_index (int newidx);
     264                 :            : 
     265                 :            :   void dump (FILE *f);
     266                 :            :   void debug ();
     267                 :            : 
     268                 :            :   /* How the known part of arguments should look like.  */
     269                 :            :   vec<ipa_adjusted_param, va_gc> *m_adj_params;
     270                 :            : 
     271                 :            :   /* If non-negative, copy any arguments starting at this offset without any
     272                 :            :      modifications so that functions with variable number of arguments can be
     273                 :            :      modified. This number should be equal to the number of original forma
     274                 :            :      parameters.  */
     275                 :            :   int m_always_copy_start;
     276                 :            :   /* If true, make the function not return any value.  */
     277                 :            :   bool m_skip_return;
     278                 :            : 
     279                 :            : private:
     280                 :            :   ipa_param_adjustments () {}
     281                 :            : 
     282                 :            :   void init (vec<tree> *cur_params);
     283                 :            :   int get_max_base_index ();
     284                 :            :   bool method2func_p (tree orig_type);
     285                 :            : };
     286                 :            : 
     287                 :            : /* Structure used to map expressions accessing split or replaced parameters to
     288                 :            :    new PARM_DECLs.  */
     289                 :            : 
     290                 :            : struct ipa_param_body_replacement
     291                 :            : {
     292                 :            :   /* The old decl of the original parameter.   */
     293                 :            :   tree base;
     294                 :            :   /* The new decl it should be replaced with.  */
     295                 :            :   tree repl;
     296                 :            :   /* When modifying clones during IPA clone materialization, this is a dummy
     297                 :            :      decl used to mark calls in which we need to apply transitive splitting,
     298                 :            :      these dummy delcls are inserted as arguments to such calls and then
     299                 :            :      followed by all the replacements with offset info stored in
     300                 :            :      ipa_param_performed_split.
     301                 :            : 
     302                 :            :      Users of ipa_param_body_adjustments that modify standalone functions
     303                 :            :      outside of IPA clone materialization can use this field for their internal
     304                 :            :      purposes.  */
     305                 :            :   tree dummy;
     306                 :            :   /* The offset within BASE that REPL represents.  */
     307                 :            :   unsigned unit_offset;
     308                 :            : };
     309                 :            : 
     310                 :            : struct ipa_replace_map;
     311                 :            : 
     312                 :            : /* Class used when actually performing adjustments to formal parameters of a
     313                 :            :    function to map accesses that need to be replaced to replacements.  The
     314                 :            :    class attempts to work in two very different sets of circumstances: as a
     315                 :            :    part of tree-inine.c's tree_function_versioning machinery to clone functions
     316                 :            :    (when M_ID is not NULL) and in s standalone fashion, modifying an existing
     317                 :            :    function in place (when M_ID is NULL).  While a lot of stuff handled in a
     318                 :            :    unified way in both modes, there are many aspects of the processs that
     319                 :            :    requires distinct paths.  */
     320                 :            : 
     321                 :            : class ipa_param_body_adjustments
     322                 :            : {
     323                 :            : public:
     324                 :            :   /* Constructor to use from within tree-inline.  */
     325                 :            :   ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
     326                 :            :                               tree fndecl, tree old_fndecl,
     327                 :            :                               struct copy_body_data *id, tree *vars,
     328                 :            :                               vec<ipa_replace_map *, va_gc> *tree_map);
     329                 :            :   /* Constructor to use for modifying a function outside of tree-inline from an
     330                 :            :      instance of ipa_param_adjustments.  */
     331                 :            :   ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
     332                 :            :                               tree fndecl);
     333                 :            :   /* Constructor to use for modifying a function outside of tree-inline from a
     334                 :            :      simple vector of desired parameter modification.  */
     335                 :            :   ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
     336                 :            :                               tree fndecl);
     337                 :            : 
     338                 :            :   /* The do-it-all function for modifying a function outside of
     339                 :            :      tree-inline.  */
     340                 :            :   bool perform_cfun_body_modifications ();
     341                 :            : 
     342                 :            :   /* Change the PARM_DECLs.  */
     343                 :            :   void modify_formal_parameters ();
     344                 :            :   /* Register a replacement decl for the transformation done in APM.  */
     345                 :            :   void register_replacement (ipa_adjusted_param *apm, tree replacement,
     346                 :            :                              tree dummy = NULL_TREE);
     347                 :            :   /* Lookup a replacement for a given offset within a given parameter.  */
     348                 :            :   tree lookup_replacement (tree base, unsigned unit_offset);
     349                 :            :   /* Lookup a replacement for an expression, if there is one.  */
     350                 :            :   ipa_param_body_replacement *get_expr_replacement (tree expr,
     351                 :            :                                                     bool ignore_default_def);
     352                 :            :   /* Lookup the new base for surviving names previously belonging to a
     353                 :            :      parameter. */
     354                 :            :   tree get_replacement_ssa_base (tree old_decl);
     355                 :            :   /* Modify a statement.  */
     356                 :            :   bool modify_gimple_stmt (gimple **stmt, gimple_seq *extra_stmts);
     357                 :            :   /* Return the new chain of parameters.  */
     358                 :            :   tree get_new_param_chain ();
     359                 :            : 
     360                 :            :   /* Pointers to data structures defining how the function should be
     361                 :            :      modified.  */
     362                 :            :   vec<ipa_adjusted_param, va_gc> *m_adj_params;
     363                 :            :   ipa_param_adjustments *m_adjustments;
     364                 :            : 
     365                 :            :   /* Vector of old parameter declarations that must have their debug bind
     366                 :            :      statements re-mapped and debug decls created.  */
     367                 :            : 
     368                 :            :   auto_vec<tree, 16> m_reset_debug_decls;
     369                 :            : 
     370                 :            :   /* Set to true if there are any IPA_PARAM_OP_SPLIT adjustments among stored
     371                 :            :      adjustments.  */
     372                 :            :   bool m_split_modifications_p;
     373                 :            : private:
     374                 :            :   void common_initialization (tree old_fndecl, tree *vars,
     375                 :            :                               vec<ipa_replace_map *, va_gc> *tree_map);
     376                 :            :   tree carry_over_param (tree t);
     377                 :            :   unsigned get_base_index (ipa_adjusted_param *apm);
     378                 :            :   ipa_param_body_replacement *lookup_replacement_1 (tree base,
     379                 :            :                                                     unsigned unit_offset);
     380                 :            :   tree replace_removed_params_ssa_names (tree old_name, gimple *stmt);
     381                 :            :   bool modify_expression (tree *expr_p, bool convert);
     382                 :            :   bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts);
     383                 :            :   bool modify_call_stmt (gcall **stmt_p);
     384                 :            :   bool modify_cfun_body ();
     385                 :            :   void reset_debug_stmts ();
     386                 :            : 
     387                 :            :   /* Declaration of the function that is being transformed.  */
     388                 :            : 
     389                 :            :   tree m_fndecl;
     390                 :            : 
     391                 :            :   /* If non-NULL, the tree-inline master data structure guiding materialization
     392                 :            :      of the current clone.  */
     393                 :            :   struct copy_body_data *m_id;
     394                 :            : 
     395                 :            :   /* Vector of old parameter declarations (before changing them).  */
     396                 :            : 
     397                 :            :   auto_vec<tree, 16> m_oparms;
     398                 :            : 
     399                 :            :   /* Vector of parameter declarations the function will have after
     400                 :            :      transformation.  */
     401                 :            : 
     402                 :            :   auto_vec<tree, 16> m_new_decls;
     403                 :            : 
     404                 :            :   /* If the function type has non-NULL TYPE_ARG_TYPES, this is the vector of
     405                 :            :      these types after transformation, otherwise an empty one.  */
     406                 :            : 
     407                 :            :   auto_vec<tree, 16> m_new_types;
     408                 :            : 
     409                 :            :   /* Vector of structures telling how to replace old parameters in the
     410                 :            :      function body.  TODO: Even though there usually be only few, but should we
     411                 :            :      use a hash?  */
     412                 :            : 
     413                 :            :   auto_vec<ipa_param_body_replacement, 16> m_replacements;
     414                 :            : 
     415                 :            :   /* Vector for remapping SSA_BASES from old parameter declarations that are
     416                 :            :      being removed as a part of the transformation.  Before a new VAR_DECL is
     417                 :            :      created, it holds the old PARM_DECL, once the variable is built it is
     418                 :            :      stored here.  */
     419                 :            : 
     420                 :            :   auto_vec<tree> m_removed_decls;
     421                 :            : 
     422                 :            :   /* Hash to quickly lookup the item in m_removed_decls given the old decl.  */
     423                 :            : 
     424                 :            :   hash_map<tree, unsigned> m_removed_map;
     425                 :            : 
     426                 :            :   /* True iff the transformed function is a class method that is about to loose
     427                 :            :      its this pointer and must be converted to a normal function.  */
     428                 :            : 
     429                 :            :   bool m_method2func;
     430                 :            : };
     431                 :            : 
     432                 :            : void push_function_arg_decls (vec<tree> *args, tree fndecl);
     433                 :            : void push_function_arg_types (vec<tree> *types, tree fntype);
     434                 :            : 
     435                 :            : #endif  /* IPA_PARAM_MANIPULATION_H */

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.