xref: /netbsd-src/external/gpl3/gcc/dist/gcc/ipa-param-manipulation.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /* Manipulation of formal and actual parameters of functions and function
2    calls.
3    Copyright (C) 2017-2022 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 
class()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 		      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   /* Build a declaration corresponding to the target of the modified call.  */
234   tree adjust_decl (tree orig_decl);
235   /* Fill a vector marking which parameters are intact by the described
236      modifications. */
237   void get_surviving_params (vec<bool> *surviving_params);
238   /* Fill a vector with new indices of surviving original parameters.  */
239   void get_updated_indices (vec<int> *new_indices);
240   /* If a parameter with original INDEX has survived intact, return its new
241      index.  Otherwise return -1.  In that case, if it has been split and there
242      is a new parameter representing a portion at UNIT_OFFSET for which a value
243      of a TYPE can be substituted, store its new index into SPLIT_INDEX,
244      otherwise store -1 there.  */
245   int get_updated_index_or_split (int index, unsigned unit_offset, tree type,
246 				  int *split_index);
247   /* Return the original index for the given new parameter index.  Return a
248      negative number if not available.  */
249   int get_original_index (int newidx);
250 
251   void dump (FILE *f);
252   void debug ();
253 
254   /* How the known part of arguments should look like.  */
255   vec<ipa_adjusted_param, va_gc> *m_adj_params;
256 
257   /* If non-negative, copy any arguments starting at this offset without any
258      modifications so that functions with variable number of arguments can be
259      modified. This number should be equal to the number of original forma
260      parameters.  */
261   int m_always_copy_start;
262   /* If true, make the function not return any value.  */
263   bool m_skip_return;
264 
265   static bool type_attribute_allowed_p (tree);
266 private:
267   ipa_param_adjustments () {}
268 
269   void init (vec<tree> *cur_params);
270   int get_max_base_index ();
271   bool method2func_p (tree orig_type);
272 };
273 
274 /* Structure used to map expressions accessing split or replaced parameters to
275    new PARM_DECLs.  */
276 
277 struct ipa_param_body_replacement
278 {
279   /* The old decl of the original parameter.   */
280   tree base;
281   /* The new decl it should be replaced with.  */
282   tree repl;
283   /* Users of ipa_param_body_adjustments that modify standalone functions
284      outside of IPA clone materialization can use the following field for their
285      internal purposes.  */
286   tree dummy;
287   /* The offset within BASE that REPL represents.  */
288   unsigned unit_offset;
289 };
290 
291 struct ipa_replace_map;
292 
293 /* Class used when actually performing adjustments to formal parameters of a
294    function to map accesses that need to be replaced to replacements.  The
295    class attempts to work in two very different sets of circumstances: as a
296    part of tree-inine.c's tree_function_versioning machinery to clone functions
297    (when M_ID is not NULL) and in s standalone fashion, modifying an existing
298    function in place (when M_ID is NULL).  While a lot of stuff handled in a
299    unified way in both modes, there are many aspects of the processs that
300    requires distinct paths.  */
301 
302 class ipa_param_body_adjustments
303 {
304 public:
305   /* Constructor to use from within tree-inline.  */
306   ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
307 			      tree fndecl, tree old_fndecl,
308 			      struct copy_body_data *id, tree *vars,
309 			      vec<ipa_replace_map *, va_gc> *tree_map);
310   /* Constructor to use for modifying a function outside of tree-inline from an
311      instance of ipa_param_adjustments.  */
312   ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
313 			      tree fndecl);
314   /* Constructor to use for modifying a function outside of tree-inline from a
315      simple vector of desired parameter modification.  */
316   ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
317 			      tree fndecl);
318 
319   /* The do-it-all function for modifying a function outside of
320      tree-inline.  */
321   bool perform_cfun_body_modifications ();
322 
323   /* Change the PARM_DECLs.  */
324   void modify_formal_parameters ();
325   /* Register a replacement decl for the transformation done in APM.  */
326   void register_replacement (ipa_adjusted_param *apm, tree replacement);
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   /* Pointers to data structures defining how the function should be
345      modified.  */
346   vec<ipa_adjusted_param, va_gc> *m_adj_params;
347   ipa_param_adjustments *m_adjustments;
348 
349   /* Vector of old parameter declarations that must have their debug bind
350      statements re-mapped and debug decls created.  */
351 
352   auto_vec<tree, 16> m_reset_debug_decls;
353 
354   /* Set to true if there are any IPA_PARAM_OP_SPLIT adjustments among stored
355      adjustments.  */
356   bool m_split_modifications_p;
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   tree replace_removed_params_ssa_names (tree old_name, gimple *stmt);
377   bool modify_expression (tree *expr_p, bool convert);
378   bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts);
379   bool modify_call_stmt (gcall **stmt_p, gimple *orig_stmt);
380   bool modify_cfun_body ();
381   void reset_debug_stmts ();
382   void mark_dead_statements (tree dead_param, vec<tree> *debugstack);
383   bool prepare_debug_expressions (tree dead_ssa);
384 
385   /* Declaration of the function that is being transformed.  */
386 
387   tree m_fndecl;
388 
389   /* If non-NULL, the tree-inline master data structure guiding materialization
390      of the current clone.  */
391   struct copy_body_data *m_id;
392 
393   /* Vector of old parameter declarations (before changing them).  */
394 
395   auto_vec<tree, 16> m_oparms;
396 
397   /* Vector of parameter declarations the function will have after
398      transformation.  */
399 
400   auto_vec<tree, 16> m_new_decls;
401 
402   /* If the function type has non-NULL TYPE_ARG_TYPES, this is the vector of
403      these types after transformation, otherwise an empty one.  */
404 
405   auto_vec<tree, 16> m_new_types;
406 
407   /* Vector of structures telling how to replace old parameters in the
408      function body.  TODO: Even though there usually be only few, but should we
409      use a hash?  */
410 
411   auto_vec<ipa_param_body_replacement, 16> m_replacements;
412 
413   /* Vector for remapping SSA_BASES from old parameter declarations that are
414      being removed as a part of the transformation.  Before a new VAR_DECL is
415      created, it holds the old PARM_DECL, once the variable is built it is
416      stored here.  */
417 
418   auto_vec<tree> m_removed_decls;
419 
420   /* Hash to quickly lookup the item in m_removed_decls given the old decl.  */
421 
422   hash_map<tree, unsigned> m_removed_map;
423 
424   /* True iff the transformed function is a class method that is about to loose
425      its this pointer and must be converted to a normal function.  */
426 
427   bool m_method2func;
428 };
429 
430 void push_function_arg_decls (vec<tree> *args, tree fndecl);
431 void push_function_arg_types (vec<tree> *types, tree fntype);
432 void ipa_verify_edge_has_no_modifications (cgraph_edge *cs);
433 void ipa_edge_modifications_finalize ();
434 void ipa_release_ssas_in_hash (hash_set <tree> *killed_ssas);
435 
436 #endif	/* IPA_PARAM_MANIPULATION_H */
437