]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-param-manipulation.h
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / ipa-param-manipulation.h
CommitLineData
4d99a848
MJ
1/* Manipulation of formal and actual parameters of functions and function
2 calls.
99dee823 3 Copyright (C) 2017-2021 Free Software Foundation, Inc.
4d99a848
MJ
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
ff6686d2
MJ
19<http://www.gnu.org/licenses/>.
20
21
22
23This file defines classes and other data structures that are used to manipulate
24the prototype of a function, especially to create, remove or split its formal
25parameters, but also to remove its return value, and also its call statements
26correspondingly.
27
28The most basic one is a vector of structures ipa_adjusted_param. It is simply
29a description how the new parameters should look like after the transformation
30in what way they relate to the previous ones (if in any). Such relation to an
31old parameter can be an outright copy or an IPA-SRA replacement. If an old
32parameter is not listed or otherwise mentioned, it is removed as unused or at
33least unnecessary. Note that this most basic structure does not work for
34modifying calls of functions with variable number of arguments.
35
36Class ipa_param_adjustments is only a little more than a thin encapsulation of
37a vector of ipa_param_adjustments. Along with this vector it contains an index
38of the first potential vararg argument and a boolean flag whether the return
39value should be removed or not. Moreover, the class contains method
40modify_call which can transform a call statement so that it correctly calls a
41modified function. These two data structures were designed to have a small
42memory footprint because they are allocated for each clone of a call graph node
43that has its prototype changed and live until the end of IPA clone
44materialization and call redirection phase.
45
46On the other hand, class ipa_param_body_adjustments can afford to allocate more
47data because its life span is much smaller, it is allocated and destroyed in
48the course of materialization of each single clone that needs it or only when a
49particular pass needs to change a function it is operating on. This class has
50various methods required to change function declaration and the body of the
51function according to instructions given either by class ipa_param_adjustments
52or only a vector of ipa_adjusted_params.
53
54When these classes are used in the context of call graph clone materialization
55and subsequent call statement redirection - which is the point at which we
56modify arguments in call statements - they need to cooperate with each other in
87467f45 57order to handle what we refer to as pass-through (IPA-SRA) splits. These are
ff6686d2
MJ
58situations when a formal parameter of one function is split into several
59smaller ones and some of them are then passed on in a call to another function
60because the formal parameter of this callee has also been split.
61
62Consider a simple example:
63
64struct S {int a, b, c;};
65struct Z {int x; S s;};
66
67foo (S s)
68{
69 use (s.b);
70}
71
72bar (Z z)
73{
74 use (z.s.a);
75 foo (z.s);
76}
77
78baz ()
79{
80 bar (*global);
81}
82
83Both bar and foo would have their parameter split. Foo would receive one
84replacement representing s.b. Function bar would see its parameter split into
85one replacement representing z.s.a and another representing z.s.b which would
87467f45 86be passed on to foo. It would be a so called pass-through split IPA-SRA
ff6686d2
MJ
87replacement, one which is passed in a call as an actual argument to another
88IPA-SRA replacement in another function.
89
90Note that the call chain the example can be arbitrarily long and recursive and
91that any function in it can be cloned by another IPA pass and any number of
92adjacent functions in the call chain can be inlined into each other. Call
93redirection takes place only after bodies of the function have been modified by
94all of the above.
95
96Call redirection has to be able to find the right decl or SSA_NAME that
97corresponds to the transitive split in the caller. The SSA names are assigned
87467f45
MJ
98right after clone materialization/ modification and cannot be "added" to call
99arguments at any later point. Moreover, if the caller has been inlined the
100SSA_NAMEs in question no longer belong to PARM_DECLs but to VAR_DECLs,
101indistinguishable from any others.
ff6686d2
MJ
102
103Therefore, when clone materialization finds a call statement which it knows is
87467f45
MJ
104a part of a transitive split, it will simply add as arguments all new "split"
105replacements (that have grater or equal offset than the original call
106argument):
ff6686d2 107
87467f45 108 foo (repl_for_a, repl_for_b, <rest of original arguments>);
ff6686d2 109
87467f45
MJ
110It will also store into ipa_edge_modification_info (which is internal to
111ipa-param-modification.c) information about which replacement is which and
112where original arguments are. Call redirection will then invoke
113ipa_param_adjustments::modify_call which will access this information and
114eliminate all replacements which the callee does not expect (repl_for_a in our
115example above). In between these two steps, however, a call statement might
116have extraneous arguments. */
4d99a848
MJ
117
118#ifndef IPA_PARAM_MANIPULATION_H
119#define IPA_PARAM_MANIPULATION_H
120
ff6686d2
MJ
121/* Indices into ipa_param_prefixes to identify a human-readable prefix for newly
122 synthesized parameters. Keep in sync with the array. */
123enum 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
4d99a848
MJ
136/* Operation to be performed for the parameter in ipa_parm_adjustment
137 below. */
4d99a848 138
ff6686d2
MJ
139enum ipa_parm_op
140{
141 /* Do not use or you will trigger an assert. */
142 IPA_PARAM_OP_UNDEFINED,
4d99a848
MJ
143
144 /* This new parameter is an unmodified parameter at index base_index. */
ff6686d2
MJ
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,
4d99a848 150
ff6686d2
MJ
151 /* Split parameter as indicated by fields base_index, offset and type. */
152 IPA_PARAM_OP_SPLIT
4d99a848
MJ
153};
154
ff6686d2
MJ
155/* Structure that describes one parameter of a function after transformation.
156 Omitted parameters will be removed. */
4d99a848 157
ff6686d2
MJ
158struct 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. */
4d99a848
MJ
162 tree type;
163
ff6686d2
MJ
164 /* Alias reference type to be used in MEM_REFs when adjusting caller
165 arguments. Required for IPA_PARM_OP_SPLIT operation. */
4d99a848
MJ
166 tree alias_ptr_type;
167
ff6686d2
MJ
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;
4d99a848 172
ff6686d2
MJ
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;
4d99a848 178
ff6686d2
MJ
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;
4d99a848 182
ff6686d2
MJ
183 /* Specify the operation, if any, to be performed on the parameter. */
184 enum ipa_parm_op op : 2;
4d99a848 185
ff6686d2
MJ
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;
4d99a848 189
ff6686d2
MJ
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;
4d99a848
MJ
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
ff6686d2
MJ
198 /* A bit free for the user. */
199 unsigned user_flag : 1;
200};
201
202void ipa_dump_adjusted_parameters (FILE *f,
203 vec<ipa_adjusted_param, va_gc> *adj_params);
204
ff6686d2
MJ
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
210class GTY(()) ipa_param_adjustments
211{
212public:
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. */
87467f45 227 gcall *modify_call (cgraph_edge *cs, bool update_references);
ff6686d2
MJ
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);
c7ac9a0c
JH
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);
ff6686d2
MJ
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
257private:
258 ipa_param_adjustments () {}
259
260 void init (vec<tree> *cur_params);
261 int get_max_base_index ();
262 bool method2func_p (tree orig_type);
263};
264
265/* Structure used to map expressions accessing split or replaced parameters to
266 new PARM_DECLs. */
267
268struct ipa_param_body_replacement
269{
270 /* The old decl of the original parameter. */
271 tree base;
272 /* The new decl it should be replaced with. */
273 tree repl;
87467f45
MJ
274 /* Users of ipa_param_body_adjustments that modify standalone functions
275 outside of IPA clone materialization can use the following field for their
276 internal purposes. */
ff6686d2
MJ
277 tree dummy;
278 /* The offset within BASE that REPL represents. */
279 unsigned unit_offset;
280};
281
282struct ipa_replace_map;
283
284/* Class used when actually performing adjustments to formal parameters of a
285 function to map accesses that need to be replaced to replacements. The
286 class attempts to work in two very different sets of circumstances: as a
287 part of tree-inine.c's tree_function_versioning machinery to clone functions
288 (when M_ID is not NULL) and in s standalone fashion, modifying an existing
289 function in place (when M_ID is NULL). While a lot of stuff handled in a
290 unified way in both modes, there are many aspects of the processs that
291 requires distinct paths. */
292
293class ipa_param_body_adjustments
294{
295public:
296 /* Constructor to use from within tree-inline. */
297 ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
298 tree fndecl, tree old_fndecl,
299 struct copy_body_data *id, tree *vars,
300 vec<ipa_replace_map *, va_gc> *tree_map);
301 /* Constructor to use for modifying a function outside of tree-inline from an
302 instance of ipa_param_adjustments. */
303 ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
304 tree fndecl);
305 /* Constructor to use for modifying a function outside of tree-inline from a
306 simple vector of desired parameter modification. */
307 ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
308 tree fndecl);
309
310 /* The do-it-all function for modifying a function outside of
311 tree-inline. */
312 bool perform_cfun_body_modifications ();
313
314 /* Change the PARM_DECLs. */
315 void modify_formal_parameters ();
316 /* Register a replacement decl for the transformation done in APM. */
87467f45 317 void register_replacement (ipa_adjusted_param *apm, tree replacement);
ff6686d2
MJ
318 /* Lookup a replacement for a given offset within a given parameter. */
319 tree lookup_replacement (tree base, unsigned unit_offset);
320 /* Lookup a replacement for an expression, if there is one. */
321 ipa_param_body_replacement *get_expr_replacement (tree expr,
322 bool ignore_default_def);
323 /* Lookup the new base for surviving names previously belonging to a
324 parameter. */
325 tree get_replacement_ssa_base (tree old_decl);
326 /* Modify a statement. */
87467f45
MJ
327 bool modify_gimple_stmt (gimple **stmt, gimple_seq *extra_stmts,
328 gimple *orig_stmt);
ff6686d2
MJ
329 /* Return the new chain of parameters. */
330 tree get_new_param_chain ();
331
332 /* Pointers to data structures defining how the function should be
333 modified. */
334 vec<ipa_adjusted_param, va_gc> *m_adj_params;
335 ipa_param_adjustments *m_adjustments;
336
337 /* Vector of old parameter declarations that must have their debug bind
338 statements re-mapped and debug decls created. */
339
340 auto_vec<tree, 16> m_reset_debug_decls;
341
342 /* Set to true if there are any IPA_PARAM_OP_SPLIT adjustments among stored
343 adjustments. */
344 bool m_split_modifications_p;
2902991a
MJ
345
346 /* Sets of statements and SSA_NAMEs that only manipulate data from parameters
347 removed because they are not necessary. */
348 hash_set<gimple *> m_dead_stmts;
349 hash_set<tree> m_dead_ssas;
350
ff6686d2
MJ
351private:
352 void common_initialization (tree old_fndecl, tree *vars,
353 vec<ipa_replace_map *, va_gc> *tree_map);
231f7546 354 tree carry_over_param (tree t);
ff6686d2
MJ
355 unsigned get_base_index (ipa_adjusted_param *apm);
356 ipa_param_body_replacement *lookup_replacement_1 (tree base,
357 unsigned unit_offset);
358 tree replace_removed_params_ssa_names (tree old_name, gimple *stmt);
359 bool modify_expression (tree *expr_p, bool convert);
360 bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts);
87467f45 361 bool modify_call_stmt (gcall **stmt_p, gimple *orig_stmt);
ff6686d2
MJ
362 bool modify_cfun_body ();
363 void reset_debug_stmts ();
87467f45 364 void mark_dead_statements (tree dead_param);
ff6686d2
MJ
365
366 /* Declaration of the function that is being transformed. */
367
368 tree m_fndecl;
369
370 /* If non-NULL, the tree-inline master data structure guiding materialization
371 of the current clone. */
372 struct copy_body_data *m_id;
373
374 /* Vector of old parameter declarations (before changing them). */
375
376 auto_vec<tree, 16> m_oparms;
377
378 /* Vector of parameter declarations the function will have after
379 transformation. */
380
381 auto_vec<tree, 16> m_new_decls;
382
383 /* If the function type has non-NULL TYPE_ARG_TYPES, this is the vector of
384 these types after transformation, otherwise an empty one. */
385
386 auto_vec<tree, 16> m_new_types;
387
700d4cb0 388 /* Vector of structures telling how to replace old parameters in the
ff6686d2
MJ
389 function body. TODO: Even though there usually be only few, but should we
390 use a hash? */
391
392 auto_vec<ipa_param_body_replacement, 16> m_replacements;
393
394 /* Vector for remapping SSA_BASES from old parameter declarations that are
395 being removed as a part of the transformation. Before a new VAR_DECL is
396 created, it holds the old PARM_DECL, once the variable is built it is
397 stored here. */
398
399 auto_vec<tree> m_removed_decls;
400
401 /* Hash to quickly lookup the item in m_removed_decls given the old decl. */
402
403 hash_map<tree, unsigned> m_removed_map;
404
405 /* True iff the transformed function is a class method that is about to loose
406 its this pointer and must be converted to a normal function. */
407
408 bool m_method2func;
4d99a848
MJ
409};
410
ff6686d2
MJ
411void push_function_arg_decls (vec<tree> *args, tree fndecl);
412void push_function_arg_types (vec<tree> *types, tree fntype);
87467f45
MJ
413void ipa_verify_edge_has_no_modifications (cgraph_edge *cs);
414void ipa_edge_modifications_finalize ();
415
4d99a848
MJ
416
417#endif /* IPA_PARAM_MANIPULATION_H */