]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-param-manipulation.h
[PR 91832] Do not ICE on negative offsets in ipa-sra
[thirdparty/gcc.git] / gcc / ipa-param-manipulation.h
CommitLineData
4d99a848
MJ
1/* Manipulation of formal and actual parameters of functions and function
2 calls.
a5544970 3 Copyright (C) 2017-2019 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
57order to handle what we refer to as transitive (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 transitive 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"
99afterwards. Moreover, if the caller has been inlined the SSA_NAMEs in question
100no longer belong to PARM_DECLs but to VAR_DECLs, indistinguishable from any
101others.
102
103Therefore, when clone materialization finds a call statement which it knows is
104a 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
108It will also store {DUMMY_S_VAR, 32} and {DUMMY_S_VAR, 64} representing offsets
109of z.s.a and z.s.b (assuming a 32-bit int) into foo's cgraph node
110clone->performed_splits vector (which is storing structures of type
111ipa_param_performed_split also defined in this header file).
112
113Call redirection will identify that expression DUMMY_Z_VAR.s is based on a
114variable stored in performed_splits vector and learn that the following
115arguments, already in SSA form, represent offsets 32 and 64 in a split original
116parameter. It subtracts offset of DUMMY_Z_VAR.s from 32 and 64 and arrives at
117offsets 0 and 32 within callee's original parameter. At this point it also
118knows from the call graph that only the bit with offset 32 is needed and so
119changes the call statement into final:
120
121bar (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. */
128enum 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
144enum 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
163struct 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
207void 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
214struct 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
230class GTY(()) ipa_param_adjustments
231{
232public:
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
262 void dump (FILE *f);
263 void debug ();
264
265 /* How the known part of arguments should look like. */
266 vec<ipa_adjusted_param, va_gc> *m_adj_params;
267
268 /* If non-negative, copy any arguments starting at this offset without any
269 modifications so that functions with variable number of arguments can be
270 modified. This number should be equal to the number of original forma
271 parameters. */
272 int m_always_copy_start;
273 /* If true, make the function not return any value. */
274 bool m_skip_return;
275
276private:
277 ipa_param_adjustments () {}
278
279 void init (vec<tree> *cur_params);
280 int get_max_base_index ();
281 bool method2func_p (tree orig_type);
282};
283
284/* Structure used to map expressions accessing split or replaced parameters to
285 new PARM_DECLs. */
286
287struct ipa_param_body_replacement
288{
289 /* The old decl of the original parameter. */
290 tree base;
291 /* The new decl it should be replaced with. */
292 tree repl;
293 /* When modifying clones during IPA clone materialization, this is a dummy
294 decl used to mark calls in which we need to apply transitive splitting,
295 these dummy delcls are inserted as arguments to such calls and then
296 followed by all the replacements with offset info stored in
297 ipa_param_performed_split.
298
299 Users of ipa_param_body_adjustments that modify standalone functions
300 outside of IPA clone materialization can use this field for their internal
301 purposes. */
302 tree dummy;
303 /* The offset within BASE that REPL represents. */
304 unsigned unit_offset;
305};
306
307struct ipa_replace_map;
308
309/* Class used when actually performing adjustments to formal parameters of a
310 function to map accesses that need to be replaced to replacements. The
311 class attempts to work in two very different sets of circumstances: as a
312 part of tree-inine.c's tree_function_versioning machinery to clone functions
313 (when M_ID is not NULL) and in s standalone fashion, modifying an existing
314 function in place (when M_ID is NULL). While a lot of stuff handled in a
315 unified way in both modes, there are many aspects of the processs that
316 requires distinct paths. */
317
318class ipa_param_body_adjustments
319{
320public:
321 /* Constructor to use from within tree-inline. */
322 ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
323 tree fndecl, tree old_fndecl,
324 struct copy_body_data *id, tree *vars,
325 vec<ipa_replace_map *, va_gc> *tree_map);
326 /* Constructor to use for modifying a function outside of tree-inline from an
327 instance of ipa_param_adjustments. */
328 ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
329 tree fndecl);
330 /* Constructor to use for modifying a function outside of tree-inline from a
331 simple vector of desired parameter modification. */
332 ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
333 tree fndecl);
334
335 /* The do-it-all function for modifying a function outside of
336 tree-inline. */
337 bool perform_cfun_body_modifications ();
338
339 /* Change the PARM_DECLs. */
340 void modify_formal_parameters ();
341 /* Register a replacement decl for the transformation done in APM. */
342 void register_replacement (ipa_adjusted_param *apm, tree replacement,
343 tree dummy = NULL_TREE);
344 /* Lookup a replacement for a given offset within a given parameter. */
345 tree lookup_replacement (tree base, unsigned unit_offset);
346 /* Lookup a replacement for an expression, if there is one. */
347 ipa_param_body_replacement *get_expr_replacement (tree expr,
348 bool ignore_default_def);
349 /* Lookup the new base for surviving names previously belonging to a
350 parameter. */
351 tree get_replacement_ssa_base (tree old_decl);
352 /* Modify a statement. */
353 bool modify_gimple_stmt (gimple **stmt, gimple_seq *extra_stmts);
354 /* Return the new chain of parameters. */
355 tree get_new_param_chain ();
356
357 /* Pointers to data structures defining how the function should be
358 modified. */
359 vec<ipa_adjusted_param, va_gc> *m_adj_params;
360 ipa_param_adjustments *m_adjustments;
361
362 /* Vector of old parameter declarations that must have their debug bind
363 statements re-mapped and debug decls created. */
364
365 auto_vec<tree, 16> m_reset_debug_decls;
366
367 /* Set to true if there are any IPA_PARAM_OP_SPLIT adjustments among stored
368 adjustments. */
369 bool m_split_modifications_p;
370private:
371 void common_initialization (tree old_fndecl, tree *vars,
372 vec<ipa_replace_map *, va_gc> *tree_map);
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);
380 bool modify_cfun_body ();
381 void reset_debug_stmts ();
382
383 /* Declaration of the function that is being transformed. */
384
385 tree m_fndecl;
386
387 /* If non-NULL, the tree-inline master data structure guiding materialization
388 of the current clone. */
389 struct copy_body_data *m_id;
390
391 /* Vector of old parameter declarations (before changing them). */
392
393 auto_vec<tree, 16> m_oparms;
394
395 /* Vector of parameter declarations the function will have after
396 transformation. */
397
398 auto_vec<tree, 16> m_new_decls;
399
400 /* If the function type has non-NULL TYPE_ARG_TYPES, this is the vector of
401 these types after transformation, otherwise an empty one. */
402
403 auto_vec<tree, 16> m_new_types;
404
405 /* Vector of structures telling how to replace old parameters in in the
406 function body. TODO: Even though there usually be only few, but should we
407 use a hash? */
408
409 auto_vec<ipa_param_body_replacement, 16> m_replacements;
410
411 /* Vector for remapping SSA_BASES from old parameter declarations that are
412 being removed as a part of the transformation. Before a new VAR_DECL is
413 created, it holds the old PARM_DECL, once the variable is built it is
414 stored here. */
415
416 auto_vec<tree> m_removed_decls;
417
418 /* Hash to quickly lookup the item in m_removed_decls given the old decl. */
419
420 hash_map<tree, unsigned> m_removed_map;
421
422 /* True iff the transformed function is a class method that is about to loose
423 its this pointer and must be converted to a normal function. */
424
425 bool m_method2func;
4d99a848
MJ
426};
427
ff6686d2
MJ
428void push_function_arg_decls (vec<tree> *args, tree fndecl);
429void push_function_arg_types (vec<tree> *types, tree fntype);
4d99a848
MJ
430
431#endif /* IPA_PARAM_MANIPULATION_H */