(root)/
gcc-13.2.0/
gcc/
ipa-param-manipulation.h
       1  /* Manipulation of formal and actual parameters of functions and function
       2     calls.
       3     Copyright (C) 2017-2023 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 pass-through (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 pass-through 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" to call
      99  arguments at any later point.  Moreover, if the caller has been inlined the
     100  SSA_NAMEs in question no longer belong to PARM_DECLs but to VAR_DECLs,
     101  indistinguishable from any others.
     102  
     103  Therefore, when clone materialization finds a call statement which it knows is
     104  a part of a transitive split, it will simply add as arguments all new "split"
     105  replacements (that have grater or equal offset than the original call
     106  argument):
     107  
     108    foo (repl_for_a, repl_for_b, <rest of original arguments>);
     109  
     110  It will also store into ipa_edge_modification_info (which is internal to
     111  ipa-param-modification.c) information about which replacement is which and
     112  where original arguments are.  Call redirection will then invoke
     113  ipa_param_adjustments::modify_call which will access this information and
     114  eliminate all replacements which the callee does not expect (repl_for_a in our
     115  example above).  In between these two steps, however, a call statement might
     116  have extraneous arguments.  */
     117  
     118  #ifndef IPA_PARAM_MANIPULATION_H
     119  #define IPA_PARAM_MANIPULATION_H
     120  
     121  /* Indices into ipa_param_prefixes to identify a human-readable prefix for newly
     122     synthesized parameters.  Keep in sync with the array.  */
     123  enum ipa_param_name_prefix_indices
     124    {
     125     IPA_PARAM_PREFIX_SYNTH,
     126     IPA_PARAM_PREFIX_ISRA,
     127     IPA_PARAM_PREFIX_SIMD,
     128     IPA_PARAM_PREFIX_MASK,
     129     IPA_PARAM_PREFIX_COUNT
     130  };
     131  
     132  /* We do not support manipulating functions with more than
     133     1<<IPA_PARAM_MAX_INDEX_BITS parameters.  */
     134  #define IPA_PARAM_MAX_INDEX_BITS 16
     135  
     136  /* Operation to be performed for the parameter in ipa_parm_adjustment
     137     below.  */
     138  
     139  enum ipa_parm_op
     140  {
     141    /* Do not use or you will trigger an assert.  */
     142    IPA_PARAM_OP_UNDEFINED,
     143  
     144    /* This new parameter is an unmodified parameter at index base_index. */
     145    IPA_PARAM_OP_COPY,
     146  
     147    /* This describes a brand new parameter.  If it somehow relates to any
     148       original parameters, the user needs to manage the transition itself.  */
     149    IPA_PARAM_OP_NEW,
     150  
     151      /* Split parameter as indicated by fields base_index, offset and type.  */
     152    IPA_PARAM_OP_SPLIT
     153  };
     154  
     155  /* Structure that describes one parameter of a function after transformation.
     156     Omitted parameters will be removed.  */
     157  
     158  struct GTY(()) ipa_adjusted_param
     159  {
     160    /* Type of the new parameter.  Required for all operations except
     161       IPA_PARM_OP_COPY when the original type will be preserved.  */
     162    tree type;
     163  
     164    /* Alias reference type to be used in MEM_REFs when adjusting caller
     165       arguments.  Required for IPA_PARM_OP_SPLIT operation.  */
     166    tree alias_ptr_type;
     167  
     168    /* Offset into the original parameter (for the cases when the new parameter
     169       is a component of an original one).  Required for IPA_PARM_OP_SPLIT
     170       operation.  */
     171    unsigned unit_offset;
     172  
     173    /* Zero based index of the original parameter this one is based on.  Required
     174       for IPA_PARAM_OP_COPY and IPA_PARAM_OP_SPLIT, users of IPA_PARAM_OP_NEW
     175       only need to specify it if they use replacement lookup provided by
     176       ipa_param_body_adjustments.  */
     177    unsigned base_index : IPA_PARAM_MAX_INDEX_BITS;
     178  
     179    /* Zero based index of the parameter this one is based on in the previous
     180       clone.  If there is no previous clone, it must be equal to base_index.  */
     181    unsigned prev_clone_index : IPA_PARAM_MAX_INDEX_BITS;
     182  
     183    /* Specify the operation, if any, to be performed on the parameter.  */
     184    enum ipa_parm_op op : 2;
     185  
     186    /* If set, this structure describes a parameter copied over from a previous
     187       IPA clone, any transformations are thus not to be re-done.  */
     188    unsigned prev_clone_adjustment : 1;
     189  
     190    /* Index into ipa_param_prefixes specifying a prefix to be used with
     191       DECL_NAMEs of newly synthesized parameters.  */
     192    unsigned param_prefix_index : 2;
     193  
     194    /* Storage order of the original parameter (for the cases when the new
     195       parameter is a component of an original one).  */
     196    unsigned reverse : 1;
     197  
     198    /* A bit free for the user.  */
     199    unsigned user_flag : 1;
     200  };
     201  
     202  void ipa_dump_adjusted_parameters (FILE *f,
     203  				   vec<ipa_adjusted_param, va_gc> *adj_params);
     204  
     205  /* Class used to record planned modifications to parameters of a function and
     206     also to perform necessary modifications at the caller side at the gimple
     207     level.  Used to describe all cgraph node clones that have their parameters
     208     changed, therefore the class should only have a small memory footprint.  */
     209  
     210  class GTY(()) ipa_param_adjustments
     211  {
     212  public:
     213    /* Constructor from NEW_PARAMS showing how new parameters should look like
     214        plus copying any pre-existing actual arguments starting from argument
     215        with index ALWAYS_COPY_START (if non-negative, negative means do not copy
     216        anything beyond what is described in NEW_PARAMS), and SKIP_RETURN, which
     217        indicates that the function should return void after transformation.  */
     218  
     219    ipa_param_adjustments (vec<ipa_adjusted_param, va_gc> *new_params,
     220  			 int always_copy_start, bool skip_return)
     221      : m_adj_params (new_params), m_always_copy_start (always_copy_start),
     222      m_skip_return (skip_return)
     223      {}
     224  
     225    /* Modify a call statement arguments (and possibly remove the return value)
     226       as described in the data fields of this class.  */
     227    gcall *modify_call (cgraph_edge *cs, bool update_references);
     228    /* Return if the first parameter is left intact.  */
     229    bool first_param_intact_p ();
     230    /* Build a function type corresponding to the modified call.  */
     231    tree build_new_function_type (tree old_type, bool type_is_original_p);
     232    /* Build a declaration corresponding to the target of the modified call.  */
     233    tree adjust_decl (tree orig_decl);
     234    /* Fill a vector marking which parameters are intact by the described
     235       modifications. */
     236    void get_surviving_params (vec<bool> *surviving_params);
     237    /* Fill a vector with new indices of surviving original parameters.  */
     238    void get_updated_indices (vec<int> *new_indices);
     239    /* Return the original index for the given new parameter index.  Return a
     240       negative number if not available.  */
     241    int get_original_index (int newidx);
     242  
     243    void dump (FILE *f);
     244    void debug ();
     245  
     246    /* How the known part of arguments should look like.  */
     247    vec<ipa_adjusted_param, va_gc> *m_adj_params;
     248  
     249    /* If non-negative, copy any arguments starting at this offset without any
     250       modifications so that functions with variable number of arguments can be
     251       modified. This number should be equal to the number of original forma
     252       parameters.  */
     253    int m_always_copy_start;
     254    /* If true, make the function not return any value.  */
     255    bool m_skip_return;
     256  
     257    static bool type_attribute_allowed_p (tree);
     258  private:
     259    ipa_param_adjustments () {}
     260  
     261    void init (vec<tree> *cur_params);
     262    int get_max_base_index ();
     263    bool method2func_p (tree orig_type);
     264  };
     265  
     266  /* Structure used to map expressions accessing split or replaced parameters to
     267     new PARM_DECLs.  */
     268  
     269  struct ipa_param_body_replacement
     270  {
     271    /* The old decl of the original parameter.   */
     272    tree base;
     273    /* The new decl it should be replaced with.  */
     274    tree repl;
     275    /* Users of ipa_param_body_adjustments that modify standalone functions
     276       outside of IPA clone materialization can use the following field for their
     277       internal purposes.  */
     278    tree dummy;
     279    /* The offset within BASE that REPL represents.  */
     280    unsigned unit_offset;
     281  };
     282  
     283  struct ipa_replace_map;
     284  
     285  /* Class used when actually performing adjustments to formal parameters of a
     286     function to map accesses that need to be replaced to replacements.  The
     287     class attempts to work in two very different sets of circumstances: as a
     288     part of tree-inine.c's tree_function_versioning machinery to clone functions
     289     (when M_ID is not NULL) and in s standalone fashion, modifying an existing
     290     function in place (when M_ID is NULL).  While a lot of stuff handled in a
     291     unified way in both modes, there are many aspects of the processs that
     292     requires distinct paths.  */
     293  
     294  class ipa_param_body_adjustments
     295  {
     296  public:
     297    /* Constructor to use from within tree-inline.  */
     298    ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
     299  			      tree fndecl, tree old_fndecl,
     300  			      struct copy_body_data *id, tree *vars,
     301  			      vec<ipa_replace_map *, va_gc> *tree_map);
     302    /* Constructor to use for modifying a function outside of tree-inline from an
     303       instance of ipa_param_adjustments.  */
     304    ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
     305  			      tree fndecl);
     306    /* Constructor to use for modifying a function outside of tree-inline from a
     307       simple vector of desired parameter modification.  */
     308    ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
     309  			      tree fndecl);
     310  
     311    /* The do-it-all function for modifying a function outside of
     312       tree-inline.  */
     313    bool perform_cfun_body_modifications ();
     314  
     315    /* Change the PARM_DECLs.  */
     316    void modify_formal_parameters ();
     317    /* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET.  */
     318    void register_replacement (tree base, unsigned unit_offset, tree replacement);
     319    /* Register a replacement decl for the transformation done in APM.  */
     320    void register_replacement (ipa_adjusted_param *apm, tree replacement);
     321    /* Sort m_replacements and set m_sorted_replacements_p to true.  Users that
     322       call register_replacement themselves must call the method before any
     323       lookup and thus also any statement or expression modification.  */
     324    void sort_replacements ();
     325    /* Lookup a replacement for a given offset within a given parameter.  */
     326    tree lookup_replacement (tree base, unsigned unit_offset);
     327    /* Lookup a replacement for an expression, if there is one.  */
     328    ipa_param_body_replacement *get_expr_replacement (tree expr,
     329  						    bool ignore_default_def);
     330    /* Lookup the new base for surviving names previously belonging to a
     331       parameter. */
     332    tree get_replacement_ssa_base (tree old_decl);
     333    /* Modify a statement.  */
     334    bool modify_gimple_stmt (gimple **stmt, gimple_seq *extra_stmts,
     335  			   gimple *orig_stmt);
     336    /* Return the new chain of parameters.  */
     337    tree get_new_param_chain ();
     338    /* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what
     339       they are mapped to.  */
     340    void remap_with_debug_expressions (tree *t);
     341  
     342    /* If there are any initialization statements that need to be emitted into
     343       the basic block BB right at ther start of the new function, do so.  */
     344    void append_init_stmts (basic_block bb);
     345  
     346    /* Pointers to data structures defining how the function should be
     347       modified.  */
     348    vec<ipa_adjusted_param, va_gc> *m_adj_params;
     349    ipa_param_adjustments *m_adjustments;
     350  
     351    /* Vector of old parameter declarations that must have their debug bind
     352       statements re-mapped and debug decls created.  */
     353  
     354    auto_vec<tree, 16> m_reset_debug_decls;
     355  
     356    /* Sets of statements and SSA_NAMEs that only manipulate data from parameters
     357       removed because they are not necessary.  */
     358    hash_set<gimple *> m_dead_stmts;
     359    hash_set<tree> m_dead_ssas;
     360  
     361    /* Mapping from DCEd SSAs to what their potential debug_binds should be.  */
     362    hash_map<tree, tree> m_dead_ssa_debug_equiv;
     363    /* Mapping from DCEd statements to debug expressions that will be placed on
     364       the RHS of debug statement that will replace this one.  */
     365    hash_map<gimple *, tree> m_dead_stmt_debug_equiv;
     366  
     367  private:
     368    void common_initialization (tree old_fndecl, tree *vars,
     369  			      vec<ipa_replace_map *, va_gc> *tree_map);
     370    tree carry_over_param (tree t);
     371    unsigned get_base_index (ipa_adjusted_param *apm);
     372    ipa_param_body_replacement *lookup_replacement_1 (tree base,
     373  						    unsigned unit_offset);
     374    ipa_param_body_replacement *lookup_first_base_replacement (tree base);
     375    tree replace_removed_params_ssa_names (tree old_name, gimple *stmt);
     376    bool modify_expression (tree *expr_p, bool convert);
     377    bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts);
     378    bool modify_call_stmt (gcall **stmt_p, gimple *orig_stmt);
     379    bool modify_cfun_body ();
     380    void reset_debug_stmts ();
     381    void mark_dead_statements (tree dead_param, vec<tree> *debugstack);
     382    bool prepare_debug_expressions (tree dead_ssa);
     383  
     384    /* Declaration of the function that is being transformed.  */
     385  
     386    tree m_fndecl;
     387  
     388    /* If non-NULL, the tree-inline master data structure guiding materialization
     389       of the current clone.  */
     390    struct copy_body_data *m_id;
     391  
     392    /* Vector of old parameter declarations (before changing them).  */
     393  
     394    auto_vec<tree, 16> m_oparms;
     395  
     396    /* Vector of parameter declarations the function will have after
     397       transformation.  */
     398  
     399    auto_vec<tree, 16> m_new_decls;
     400  
     401    /* If the function type has non-NULL TYPE_ARG_TYPES, this is the vector of
     402       these types after transformation, otherwise an empty one.  */
     403  
     404    auto_vec<tree, 16> m_new_types;
     405  
     406    /* Vector of structures telling how to replace old parameters in the
     407       function body.  TODO: Even though there usually be only few, but should we
     408       use a hash?  */
     409  
     410    auto_vec<ipa_param_body_replacement, 16> m_replacements;
     411  
     412    /* List of initialization assignments to be put at the beginning of the
     413       cloned function to deal with split aggregates which however have known
     414       constant value and so their PARM_DECL disappears.  */
     415  
     416    auto_vec<gimple *, 8> m_split_agg_csts_inits;
     417  
     418    /* Vector for remapping SSA_BASES from old parameter declarations that are
     419       being removed as a part of the transformation.  Before a new VAR_DECL is
     420       created, it holds the old PARM_DECL, once the variable is built it is
     421       stored here.  */
     422  
     423    auto_vec<tree> m_removed_decls;
     424  
     425    /* Hash to quickly lookup the item in m_removed_decls given the old decl.  */
     426  
     427    hash_map<tree, unsigned> m_removed_map;
     428  
     429    /* True iff the transformed function is a class method that is about to loose
     430       its this pointer and must be converted to a normal function.  */
     431  
     432    bool m_method2func;
     433  
     434    /* True if m_replacements have ben sorted since the last insertion.  */
     435  
     436    bool m_sorted_replacements_p;
     437  };
     438  
     439  void push_function_arg_decls (vec<tree> *args, tree fndecl);
     440  void push_function_arg_types (vec<tree> *types, tree fntype);
     441  void ipa_verify_edge_has_no_modifications (cgraph_edge *cs);
     442  void ipa_edge_modifications_finalize ();
     443  
     444  
     445  #endif	/* IPA_PARAM_MANIPULATION_H */