]>
Commit | Line | Data |
---|---|---|
4d99a848 MJ |
1 | /* Manipulation of formal and actual parameters of functions and function |
2 | calls. | |
8d9254fc | 3 | Copyright (C) 2017-2020 Free Software Foundation, Inc. |
4d99a848 MJ |
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 | |
ff6686d2 MJ |
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>); */ | |
4d99a848 MJ |
122 | |
123 | #ifndef IPA_PARAM_MANIPULATION_H | |
124 | #define IPA_PARAM_MANIPULATION_H | |
125 | ||
ff6686d2 MJ |
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 | ||
4d99a848 MJ |
141 | /* Operation to be performed for the parameter in ipa_parm_adjustment |
142 | below. */ | |
4d99a848 | 143 | |
ff6686d2 MJ |
144 | enum ipa_parm_op |
145 | { | |
146 | /* Do not use or you will trigger an assert. */ | |
147 | IPA_PARAM_OP_UNDEFINED, | |
4d99a848 MJ |
148 | |
149 | /* This new parameter is an unmodified parameter at index base_index. */ | |
ff6686d2 MJ |
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, | |
4d99a848 | 155 | |
ff6686d2 MJ |
156 | /* Split parameter as indicated by fields base_index, offset and type. */ |
157 | IPA_PARAM_OP_SPLIT | |
4d99a848 MJ |
158 | }; |
159 | ||
ff6686d2 MJ |
160 | /* Structure that describes one parameter of a function after transformation. |
161 | Omitted parameters will be removed. */ | |
4d99a848 | 162 | |
ff6686d2 MJ |
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. */ | |
4d99a848 MJ |
167 | tree type; |
168 | ||
ff6686d2 MJ |
169 | /* Alias reference type to be used in MEM_REFs when adjusting caller |
170 | arguments. Required for IPA_PARM_OP_SPLIT operation. */ | |
4d99a848 MJ |
171 | tree alias_ptr_type; |
172 | ||
ff6686d2 MJ |
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; | |
4d99a848 | 177 | |
ff6686d2 MJ |
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; | |
4d99a848 | 183 | |
ff6686d2 MJ |
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; | |
4d99a848 | 187 | |
ff6686d2 MJ |
188 | /* Specify the operation, if any, to be performed on the parameter. */ |
189 | enum ipa_parm_op op : 2; | |
4d99a848 | 190 | |
ff6686d2 MJ |
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; | |
4d99a848 | 194 | |
ff6686d2 MJ |
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; | |
4d99a848 MJ |
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 | ||
ff6686d2 MJ |
203 | /* A bit free for the user. */ |
204 | unsigned user_flag : 1; | |
205 | }; | |
206 | ||
207 | void ipa_dump_adjusted_parameters (FILE *f, | |
208 | vec<ipa_adjusted_param, va_gc> *adj_params); | |
209 | ||
210 | /* Structure to remember the split performed on a node so that edge redirection | |
211 | (i.e. splitting arguments of call statements) know how split formal | |
212 | parameters of the caller are represented. */ | |
213 | ||
214 | struct GTY(()) ipa_param_performed_split | |
215 | { | |
216 | /* The dummy VAR_DECL that was created instead of the split parameter that | |
217 | sits in the call in the meantime between clone materialization and call | |
218 | redirection. All entries in a vector of performed splits that correspond | |
219 | to the same dumy decl must be grouped together. */ | |
220 | tree dummy_decl; | |
221 | /* Offset into the original parameter. */ | |
222 | unsigned unit_offset; | |
223 | }; | |
224 | ||
225 | /* Class used to record planned modifications to parameters of a function and | |
226 | also to perform necessary modifications at the caller side at the gimple | |
227 | level. Used to describe all cgraph node clones that have their parameters | |
228 | changed, therefore the class should only have a small memory footprint. */ | |
229 | ||
230 | class GTY(()) ipa_param_adjustments | |
231 | { | |
232 | public: | |
233 | /* Constructor from NEW_PARAMS showing how new parameters should look like | |
234 | plus copying any pre-existing actual arguments starting from argument | |
235 | with index ALWAYS_COPY_START (if non-negative, negative means do not copy | |
236 | anything beyond what is described in NEW_PARAMS), and SKIP_RETURN, which | |
237 | indicates that the function should return void after transformation. */ | |
238 | ||
239 | 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); | |
c7ac9a0c JH |
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); | |
ff6686d2 MJ |
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); | |
231f7546 | 376 | tree carry_over_param (tree t); |
ff6686d2 MJ |
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 | ||
700d4cb0 | 409 | /* Vector of structures telling how to replace old parameters in the |
ff6686d2 MJ |
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; | |
4d99a848 MJ |
430 | }; |
431 | ||
ff6686d2 MJ |
432 | void push_function_arg_decls (vec<tree> *args, tree fndecl); |
433 | void push_function_arg_types (vec<tree> *types, tree fntype); | |
4d99a848 MJ |
434 | |
435 | #endif /* IPA_PARAM_MANIPULATION_H */ |