GCC Middle and Back End API Reference
ipa-param-manipulation.h
Go to the documentation of this file.
1/* Manipulation of formal and actual parameters of functions and function
2 calls.
3 Copyright (C) 2017-2025 Free Software Foundation, Inc.
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
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
57order to handle what we refer to as pass-through (IPA-SRA) splits. These are
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
86be passed on to foo. It would be a so called pass-through split IPA-SRA
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
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.
102
103Therefore, when clone materialization finds a call statement which it knows is
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):
107
108 foo (repl_for_a, repl_for_b, <rest of original arguments>);
109
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. */
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. */
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
140{
141 /* Do not use or you will trigger an assert. */
143
144 /* This new parameter is an unmodified parameter at index base_index. */
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. */
150
151 /* Split parameter as indicated by fields base_index, offset and type. */
153};
154
155/* Structure that describes one parameter of a function after transformation.
156 Omitted parameters will be removed. */
157
159{
160 /* Type of the new parameter. Required for all operations except
161 IPA_PARM_OP_COPY when the original type will be preserved. */
163
164 /* Alias reference type to be used in MEM_REFs when adjusting caller
165 arguments. Required for IPA_PARM_OP_SPLIT operation. */
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. */
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. */
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. */
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
202void ipa_dump_adjusted_parameters (FILE *f,
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
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
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 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. */
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. */
256 /* If true, make the function not return any value. */
258
259 static bool type_attribute_allowed_p (tree);
260private:
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
272{
273 /* The old decl of the original parameter. */
275 /* The new decl it should be replaced with. */
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. */
281 /* The offset within BASE that REPL represents. */
282 unsigned unit_offset;
283};
284
285struct 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
297{
298public:
299 /* Constructor to use from within tree-inline. */
301 tree fndecl, tree old_fndecl,
302 struct copy_body_data *id, tree *vars,
304 /* Constructor to use for modifying a function outside of tree-inline from an
305 instance of ipa_param_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. */
311 tree fndecl);
312
313 /* The do-it-all function for modifying a function outside of
314 tree-inline. */
316
317 /* Change the PARM_DECLs. */
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. */
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. */
331 bool ignore_default_def);
332 /* Lookup the new base for surviving names previously belonging to a
333 parameter. */
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. */
340 /* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what
341 they are mapped to. */
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. */
347
348 /* Pointers to data structures defining how the function should be
349 modified. */
352
353 /* Vector of old parameter declarations that must have their debug bind
354 statements re-mapped and debug decls created. */
355
357
358 /* Sets of statements and SSA_NAMEs that only manipulate data from parameters
359 removed because they are not necessary. */
362
363 /* Mapping from DCEd SSAs to what their potential debug_binds should be. */
365 /* Mapping from DCEd statements to debug expressions that will be placed on
366 the RHS of debug statement that will replace this one. */
368
369private:
370 void common_initialization (tree old_fndecl, tree *vars,
375 unsigned unit_offset);
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 ();
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
391
392 /* If non-NULL, the tree-inline master data structure guiding materialization
393 of the current clone. */
395
396 /* Vector of old parameter declarations (before changing them). */
397
399
400 /* Vector of parameter declarations the function will have after
401 transformation. */
402
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
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
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
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
428
429 /* Hash to quickly lookup the item in m_removed_decls given the old decl. */
430
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
437
438 /* True if m_replacements have ben sorted since the last insertion. */
439
441};
442
443void push_function_arg_decls (vec<tree> *args, tree fndecl);
444void push_function_arg_types (vec<tree> *types, tree fntype);
447void ipa_release_ssas_in_hash (hash_set <tree> *killed_ssas);
448
449#endif /* IPA_PARAM_MANIPULATION_H */
Definition vec.h:1667
Definition cgraph.h:1745
Definition genmatch.cc:1506
Definition hash-map.h:40
Definition hash-set.h:37
Definition ipa-param-manipulation.h:211
bool first_param_intact_p()
Definition ipa-param-manipulation.cc:482
bool m_skip_return
Definition ipa-param-manipulation.h:257
int get_max_base_index()
Definition ipa-param-manipulation.cc:402
ipa_param_adjustments(vec< ipa_adjusted_param, va_gc > *new_params, int always_copy_start, bool skip_return)
Definition ipa-param-manipulation.h:219
void get_updated_indices(vec< int > *new_indices)
Definition ipa-param-manipulation.cc:447
tree build_new_function_type(tree old_type, bool type_is_original_p, bool *args_modified=NULL)
Definition ipa-param-manipulation.cc:506
ipa_param_adjustments()
Definition ipa-param-manipulation.h:261
vec< ipa_adjusted_param, va_gc > * m_adj_params
Definition ipa-param-manipulation.h:249
void get_surviving_params(vec< bool > *surviving_params)
Definition ipa-param-manipulation.cc:424
void dump(FILE *f)
Definition ipa-param-manipulation.cc:1054
static bool type_attribute_allowed_p(tree)
Definition ipa-param-manipulation.cc:289
int get_original_index(int newidx)
Definition ipa-param-manipulation.cc:470
void debug()
Definition ipa-param-manipulation.cc:1065
int m_always_copy_start
Definition ipa-param-manipulation.h:255
gcall * modify_call(cgraph_edge *cs, bool update_references, hash_set< tree > *killed_ssas)
Definition ipa-param-manipulation.cc:683
tree adjust_decl(tree orig_decl)
Definition ipa-param-manipulation.cc:549
bool method2func_p(tree orig_type)
Definition ipa-param-manipulation.cc:493
void init(vec< tree > *cur_params)
unsigned get_base_index(ipa_adjusted_param *apm)
void remap_with_debug_expressions(tree *t)
Definition ipa-param-manipulation.cc:1322
bool perform_cfun_body_modifications()
Definition ipa-param-manipulation.cc:2617
ipa_param_body_replacement * get_expr_replacement(tree expr, bool ignore_default_def)
Definition ipa-param-manipulation.cc:1875
bool modify_cfun_body()
Definition ipa-param-manipulation.cc:2452
ipa_param_body_replacement * lookup_first_base_replacement(tree base)
Definition ipa-param-manipulation.cc:1813
ipa_param_body_adjustments(ipa_param_adjustments *adjustments, tree fndecl, tree old_fndecl, struct copy_body_data *id, tree *vars, vec< ipa_replace_map *, va_gc > *tree_map)
Definition ipa-param-manipulation.cc:1709
auto_vec< tree, 16 > m_new_types
Definition ipa-param-manipulation.h:408
hash_map< tree, tree > m_dead_ssa_debug_equiv
Definition ipa-param-manipulation.h:364
bool modify_assignment(gimple *stmt, gimple_seq *extra_stmts)
Definition ipa-param-manipulation.cc:2022
auto_vec< gimple *, 8 > m_split_agg_csts_inits
Definition ipa-param-manipulation.h:420
auto_vec< tree, 16 > m_oparms
Definition ipa-param-manipulation.h:398
tree get_new_param_chain()
Definition ipa-param-manipulation.cc:1726
ipa_param_body_replacement * lookup_replacement_1(tree base, unsigned unit_offset)
Definition ipa-param-manipulation.cc:1786
tree carry_over_param(tree t)
Definition ipa-param-manipulation.cc:1135
bool modify_gimple_stmt(gimple **stmt, gimple_seq *extra_stmts, gimple *orig_stmt)
Definition ipa-param-manipulation.cc:2400
bool modify_expression(tree *expr_p, bool convert, gimple_seq *=nullptr)
Definition ipa-param-manipulation.cc:1964
bool modify_call_stmt(gcall **stmt_p, gimple *orig_stmt)
Definition ipa-param-manipulation.cc:2207
void common_initialization(tree old_fndecl, tree *vars, vec< ipa_replace_map *, va_gc > *tree_map)
Definition ipa-param-manipulation.cc:1440
auto_vec< tree > m_removed_decls
Definition ipa-param-manipulation.h:427
bool m_method2func
Definition ipa-param-manipulation.h:436
vec< ipa_adjusted_param, va_gc > * m_adj_params
Definition ipa-param-manipulation.h:350
void mark_dead_statements(tree dead_param, vec< tree > *debugstack)
Definition ipa-param-manipulation.cc:1174
hash_set< tree > m_dead_ssas
Definition ipa-param-manipulation.h:361
auto_vec< ipa_param_body_replacement, 16 > m_replacements
Definition ipa-param-manipulation.h:414
void append_init_stmts(basic_block bb)
Definition ipa-param-manipulation.cc:2631
bool m_sorted_replacements_p
Definition ipa-param-manipulation.h:440
void mark_clobbers_dead(tree dead_param)
Definition ipa-param-manipulation.cc:1270
auto_vec< tree, 16 > m_new_decls
Definition ipa-param-manipulation.h:403
hash_set< gimple * > m_dead_stmts
Definition ipa-param-manipulation.h:360
bool prepare_debug_expressions(tree dead_ssa)
Definition ipa-param-manipulation.cc:1352
tree m_fndecl
Definition ipa-param-manipulation.h:390
void sort_replacements()
Definition ipa-param-manipulation.cc:1122
void register_replacement(tree base, unsigned unit_offset, tree replacement)
Definition ipa-param-manipulation.cc:1073
auto_vec< tree, 16 > m_reset_debug_decls
Definition ipa-param-manipulation.h:356
tree get_replacement_ssa_base(tree old_decl)
Definition ipa-param-manipulation.cc:1896
void reset_debug_stmts()
Definition ipa-param-manipulation.cc:2520
struct copy_body_data * m_id
Definition ipa-param-manipulation.h:394
tree lookup_replacement(tree base, unsigned unit_offset)
Definition ipa-param-manipulation.cc:1839
tree replace_removed_params_ssa_names(tree old_name, gimple *stmt)
Definition ipa-param-manipulation.cc:1922
tree get_ddef_if_exists_and_is_used(tree decl)
Definition ipa-param-manipulation.cc:1158
ipa_param_adjustments * m_adjustments
Definition ipa-param-manipulation.h:351
hash_map< tree, unsigned > m_removed_map
Definition ipa-param-manipulation.h:431
void modify_formal_parameters()
Definition ipa-param-manipulation.cc:1748
hash_map< gimple *, tree > m_dead_stmt_debug_equiv
Definition ipa-param-manipulation.h:367
bool debug
Definition collect-utils.cc:34
struct basic_block_def * basic_block
Definition coretypes.h:372
gimple * gimple_seq
Definition coretypes.h:100
#define GTY(x)
Definition coretypes.h:41
union tree_node * tree
Definition coretypes.h:97
ipa_param_name_prefix_indices
Definition ipa-param-manipulation.h:124
@ IPA_PARAM_PREFIX_ISRA
Definition ipa-param-manipulation.h:126
@ IPA_PARAM_PREFIX_COUNT
Definition ipa-param-manipulation.h:129
@ IPA_PARAM_PREFIX_SYNTH
Definition ipa-param-manipulation.h:125
@ IPA_PARAM_PREFIX_SIMD
Definition ipa-param-manipulation.h:127
@ IPA_PARAM_PREFIX_MASK
Definition ipa-param-manipulation.h:128
void ipa_verify_edge_has_no_modifications(cgraph_edge *cs)
Definition ipa-param-manipulation.cc:141
ipa_parm_op
Definition ipa-param-manipulation.h:140
@ IPA_PARAM_OP_COPY
Definition ipa-param-manipulation.h:145
@ IPA_PARAM_OP_UNDEFINED
Definition ipa-param-manipulation.h:142
@ IPA_PARAM_OP_NEW
Definition ipa-param-manipulation.h:149
@ IPA_PARAM_OP_SPLIT
Definition ipa-param-manipulation.h:152
void push_function_arg_types(vec< tree > *types, tree fntype)
Definition ipa-param-manipulation.cc:175
void push_function_arg_decls(vec< tree > *args, tree fndecl)
Definition ipa-param-manipulation.cc:151
#define IPA_PARAM_MAX_INDEX_BITS
Definition ipa-param-manipulation.h:134
void ipa_dump_adjusted_parameters(FILE *f, vec< ipa_adjusted_param, va_gc > *adj_params)
Definition ipa-param-manipulation.cc:192
void ipa_edge_modifications_finalize()
Definition ipa-param-manipulation.cc:2642
void ipa_release_ssas_in_hash(hash_set< tree > *killed_ssas)
Definition ipa-param-manipulation.cc:2668
Definition tree-inline.h:43
Definition genautomata.cc:499
Definition gimple.h:352
Definition gimple.h:221
Definition ipa-param-manipulation.h:159
unsigned user_flag
Definition ipa-param-manipulation.h:199
unsigned param_prefix_index
Definition ipa-param-manipulation.h:192
unsigned unit_offset
Definition ipa-param-manipulation.h:171
enum ipa_parm_op op
Definition ipa-param-manipulation.h:184
tree type
Definition ipa-param-manipulation.h:162
unsigned base_index
Definition ipa-param-manipulation.h:177
unsigned prev_clone_index
Definition ipa-param-manipulation.h:181
tree alias_ptr_type
Definition ipa-param-manipulation.h:166
unsigned prev_clone_adjustment
Definition ipa-param-manipulation.h:188
unsigned reverse
Definition ipa-param-manipulation.h:196
Definition ipa-param-manipulation.h:272
tree repl
Definition ipa-param-manipulation.h:276
tree base
Definition ipa-param-manipulation.h:274
tree dummy
Definition ipa-param-manipulation.h:280
unsigned unit_offset
Definition ipa-param-manipulation.h:282
Definition cgraph.h:735
Definition reload.cc:154
Definition vec.h:450
#define NULL
Definition system.h:50
tree convert(tree, tree)