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 
class()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   ipa_param_adjustments (vec<ipa_adjusted_param, va_gc> *new_params,
240 			 int always_copy_start, bool skip_return)
241     : m_adj_params (new_params), m_always_copy_start (always_copy_start),
242     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 */
436