LCOV - code coverage report
Current view: top level - gcc - ipa-param-manipulation.h Coverage Total Hit
Test: gcc.info Lines: 100.0 % 3 3
Test Date: 2026-02-28 14:20:25 Functions: - 0 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Manipulation of formal and actual parameters of functions and function
       2              :    calls.
       3              :    Copyright (C) 2017-2026 Free Software Foundation, Inc.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.
      20              : 
      21              : 
      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       171212 :   ipa_param_adjustments (vec<ipa_adjusted_param, va_gc> *new_params,
     220              :                          int always_copy_start, bool skip_return)
     221       171212 :     : m_adj_params (new_params), m_always_copy_start (always_copy_start),
     222       171212 :     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              :                       hash_set <tree> *killed_ssas);
     229              :   /* Return if the first parameter is left intact.  */
     230              :   bool first_param_intact_p ();
     231              :   /* Build a function type corresponding to the modified call.  */
     232              :   tree build_new_function_type (tree old_type, bool type_is_original_p,
     233              :                                 bool *args_modified = NULL);
     234              :   /* Build a declaration corresponding to the target of the modified call.  */
     235              :   tree adjust_decl (tree orig_decl);
     236              :   /* Fill a vector marking which parameters are intact by the described
     237              :      modifications. */
     238              :   void get_surviving_params (vec<bool> *surviving_params);
     239              :   /* Fill a vector with new indices of surviving original parameters.  */
     240              :   void get_updated_indices (vec<int> *new_indices);
     241              :   /* Return the original index for the given new parameter index.  Return a
     242              :      negative number if not available.  */
     243              :   int get_original_index (int newidx);
     244              : 
     245              :   void dump (FILE *f);
     246              :   void debug ();
     247              : 
     248              :   /* How the known part of arguments should look like.  */
     249              :   vec<ipa_adjusted_param, va_gc> *m_adj_params;
     250              : 
     251              :   /* If non-negative, copy any arguments starting at this offset without any
     252              :      modifications so that functions with variable number of arguments can be
     253              :      modified. This number should be equal to the number of original forma
     254              :      parameters.  */
     255              :   int m_always_copy_start;
     256              :   /* If true, make the function not return any value.  */
     257              :   bool m_skip_return;
     258              : 
     259              :   static bool type_attribute_allowed_p (tree);
     260              : private:
     261              :   ipa_param_adjustments () {}
     262              : 
     263              :   void init (vec<tree> *cur_params);
     264              :   int get_max_base_index ();
     265              :   bool method2func_p (tree orig_type);
     266              : };
     267              : 
     268              : /* Structure used to map expressions accessing split or replaced parameters to
     269              :    new PARM_DECLs.  */
     270              : 
     271              : struct ipa_param_body_replacement
     272              : {
     273              :   /* The old decl of the original parameter.   */
     274              :   tree base;
     275              :   /* The new decl it should be replaced with.  */
     276              :   tree repl;
     277              :   /* Users of ipa_param_body_adjustments that modify standalone functions
     278              :      outside of IPA clone materialization can use the following field for their
     279              :      internal purposes.  */
     280              :   tree dummy;
     281              :   /* The offset within BASE that REPL represents.  */
     282              :   unsigned unit_offset;
     283              : };
     284              : 
     285              : struct ipa_replace_map;
     286              : 
     287              : /* Class used when actually performing adjustments to formal parameters of a
     288              :    function to map accesses that need to be replaced to replacements.  The
     289              :    class attempts to work in two very different sets of circumstances: as a
     290              :    part of tree-inine.c's tree_function_versioning machinery to clone functions
     291              :    (when M_ID is not NULL) and in s standalone fashion, modifying an existing
     292              :    function in place (when M_ID is NULL).  While a lot of stuff handled in a
     293              :    unified way in both modes, there are many aspects of the processs that
     294              :    requires distinct paths.  */
     295              : 
     296              : class ipa_param_body_adjustments
     297              : {
     298              : public:
     299              :   /* Constructor to use from within tree-inline.  */
     300              :   ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
     301              :                               tree fndecl, tree old_fndecl,
     302              :                               struct copy_body_data *id, tree *vars,
     303              :                               vec<ipa_replace_map *, va_gc> *tree_map);
     304              :   /* Constructor to use for modifying a function outside of tree-inline from an
     305              :      instance of ipa_param_adjustments.  */
     306              :   ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
     307              :                               tree fndecl);
     308              :   /* Constructor to use for modifying a function outside of tree-inline from a
     309              :      simple vector of desired parameter modification.  */
     310              :   ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
     311              :                               tree fndecl);
     312              : 
     313              :   /* The do-it-all function for modifying a function outside of
     314              :      tree-inline.  */
     315              :   bool perform_cfun_body_modifications ();
     316              : 
     317              :   /* Change the PARM_DECLs.  */
     318              :   void modify_formal_parameters ();
     319              :   /* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET.  */
     320              :   void register_replacement (tree base, unsigned unit_offset, tree replacement);
     321              :   /* Register a replacement decl for the transformation done in APM.  */
     322              :   void register_replacement (ipa_adjusted_param *apm, tree replacement);
     323              :   /* Sort m_replacements and set m_sorted_replacements_p to true.  Users that
     324              :      call register_replacement themselves must call the method before any
     325              :      lookup and thus also any statement or expression modification.  */
     326              :   void sort_replacements ();
     327              :   /* Lookup a replacement for a given offset within a given parameter.  */
     328              :   tree lookup_replacement (tree base, unsigned unit_offset);
     329              :   /* Lookup a replacement for an expression, if there is one.  */
     330              :   ipa_param_body_replacement *get_expr_replacement (tree expr,
     331              :                                                     bool ignore_default_def);
     332              :   /* Lookup the new base for surviving names previously belonging to a
     333              :      parameter. */
     334              :   tree get_replacement_ssa_base (tree old_decl);
     335              :   /* Modify a statement.  */
     336              :   bool modify_gimple_stmt (gimple **stmt, gimple_seq *extra_stmts,
     337              :                            gimple *orig_stmt);
     338              :   /* Return the new chain of parameters.  */
     339              :   tree get_new_param_chain ();
     340              :   /* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what
     341              :      they are mapped to.  */
     342              :   void remap_with_debug_expressions (tree *t);
     343              : 
     344              :   /* If there are any initialization statements that need to be emitted into
     345              :      the basic block BB right at ther start of the new function, do so.  */
     346              :   void append_init_stmts (basic_block bb);
     347              : 
     348              :   /* Pointers to data structures defining how the function should be
     349              :      modified.  */
     350              :   vec<ipa_adjusted_param, va_gc> *m_adj_params;
     351              :   ipa_param_adjustments *m_adjustments;
     352              : 
     353              :   /* Vector of old parameter declarations that must have their debug bind
     354              :      statements re-mapped and debug decls created.  */
     355              : 
     356              :   auto_vec<tree, 16> m_reset_debug_decls;
     357              : 
     358              :   /* Sets of statements and SSA_NAMEs that only manipulate data from parameters
     359              :      removed because they are not necessary.  */
     360              :   hash_set<gimple *> m_dead_stmts;
     361              :   hash_set<tree> m_dead_ssas;
     362              : 
     363              :   /* Mapping from DCEd SSAs to what their potential debug_binds should be.  */
     364              :   hash_map<tree, tree> m_dead_ssa_debug_equiv;
     365              :   /* Mapping from DCEd statements to debug expressions that will be placed on
     366              :      the RHS of debug statement that will replace this one.  */
     367              :   hash_map<gimple *, tree> m_dead_stmt_debug_equiv;
     368              : 
     369              : private:
     370              :   void common_initialization (tree old_fndecl, tree *vars,
     371              :                               vec<ipa_replace_map *, va_gc> *tree_map);
     372              :   tree carry_over_param (tree t);
     373              :   unsigned get_base_index (ipa_adjusted_param *apm);
     374              :   ipa_param_body_replacement *lookup_replacement_1 (tree base,
     375              :                                                     unsigned unit_offset);
     376              :   ipa_param_body_replacement *lookup_first_base_replacement (tree base);
     377              :   tree replace_removed_params_ssa_names (tree old_name, gimple *stmt);
     378              :   bool modify_expression (tree *expr_p, bool convert, gimple_seq * = nullptr);
     379              :   bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts);
     380              :   bool modify_call_stmt (gcall **stmt_p, gimple *orig_stmt);
     381              :   bool modify_cfun_body ();
     382              :   void reset_debug_stmts ();
     383              :   tree get_ddef_if_exists_and_is_used (tree decl);
     384              :   void mark_dead_statements (tree dead_param, vec<tree> *debugstack);
     385              :   void mark_clobbers_dead (tree dead_param);
     386              :   bool prepare_debug_expressions (tree dead_ssa);
     387              : 
     388              :   /* Declaration of the function that is being transformed.  */
     389              : 
     390              :   tree m_fndecl;
     391              : 
     392              :   /* If non-NULL, the tree-inline master data structure guiding materialization
     393              :      of the current clone.  */
     394              :   struct copy_body_data *m_id;
     395              : 
     396              :   /* Vector of old parameter declarations (before changing them).  */
     397              : 
     398              :   auto_vec<tree, 16> m_oparms;
     399              : 
     400              :   /* Vector of parameter declarations the function will have after
     401              :      transformation.  */
     402              : 
     403              :   auto_vec<tree, 16> m_new_decls;
     404              : 
     405              :   /* If the function type has non-NULL TYPE_ARG_TYPES, this is the vector of
     406              :      these types after transformation, otherwise an empty one.  */
     407              : 
     408              :   auto_vec<tree, 16> m_new_types;
     409              : 
     410              :   /* Vector of structures telling how to replace old parameters in the
     411              :      function body.  TODO: Even though there usually be only few, but should we
     412              :      use a hash?  */
     413              : 
     414              :   auto_vec<ipa_param_body_replacement, 16> m_replacements;
     415              : 
     416              :   /* List of initialization assignments to be put at the beginning of the
     417              :      cloned function to deal with split aggregates which however have known
     418              :      constant value and so their PARM_DECL disappears.  */
     419              : 
     420              :   auto_vec<gimple *, 8> m_split_agg_csts_inits;
     421              : 
     422              :   /* Vector for remapping SSA_BASES from old parameter declarations that are
     423              :      being removed as a part of the transformation.  Before a new VAR_DECL is
     424              :      created, it holds the old PARM_DECL, once the variable is built it is
     425              :      stored here.  */
     426              : 
     427              :   auto_vec<tree> m_removed_decls;
     428              : 
     429              :   /* Hash to quickly lookup the item in m_removed_decls given the old decl.  */
     430              : 
     431              :   hash_map<tree, unsigned> m_removed_map;
     432              : 
     433              :   /* True iff the transformed function is a class method that is about to loose
     434              :      its this pointer and must be converted to a normal function.  */
     435              : 
     436              :   bool m_method2func;
     437              : 
     438              :   /* True if m_replacements have ben sorted since the last insertion.  */
     439              : 
     440              :   bool m_sorted_replacements_p;
     441              : };
     442              : 
     443              : void push_function_arg_decls (vec<tree> *args, tree fndecl);
     444              : void push_function_arg_types (vec<tree> *types, tree fntype);
     445              : void ipa_verify_edge_has_no_modifications (cgraph_edge *cs);
     446              : void ipa_edge_modifications_finalize ();
     447              : void ipa_release_ssas_in_hash (hash_set <tree> *killed_ssas);
     448              : 
     449              : #endif  /* IPA_PARAM_MANIPULATION_H */
        

Generated by: LCOV version 2.4-beta

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