1 | /* Interprocedural analyses. |
2 | Copyright (C) 2005-2024 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GCC. |
5 | |
6 | GCC is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free |
8 | Software Foundation; either version 3, or (at your option) any later |
9 | version. |
10 | |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ |
19 | |
20 | #ifndef IPA_PROP_H |
21 | #define IPA_PROP_H |
22 | |
23 | /* The following definitions and interfaces are used by |
24 | interprocedural analyses or parameters. */ |
25 | |
26 | #define IPA_UNDESCRIBED_USE -1 |
27 | |
28 | /* Index identifying an actualargument or a formal parameter may have only this |
29 | many bits. */ |
30 | |
31 | #define IPA_PROP_ARG_INDEX_LIMIT_BITS 16 |
32 | |
33 | /* ipa-prop.cc stuff (ipa-cp, indirect inlining): */ |
34 | |
35 | /* A jump function for a callsite represents the values passed as actual |
36 | arguments of the callsite. They were originally proposed in a paper called |
37 | "Interprocedural Constant Propagation", by David Callahan, Keith D Cooper, |
38 | Ken Kennedy, Linda Torczon in Comp86, pg 152-161. There are three main |
39 | types of values : |
40 | |
41 | Pass-through - the caller's formal parameter is passed as an actual |
42 | argument, possibly one simple operation performed on it. |
43 | Constant - a constant (is_gimple_ip_invariant)is passed as an actual |
44 | argument. |
45 | Unknown - neither of the above. |
46 | |
47 | IPA_JF_LOAD_AGG is a compound pass-through jump function, in which primary |
48 | operation on formal parameter is memory dereference that loads a value from |
49 | a part of an aggregate, which is represented or pointed to by the formal |
50 | parameter. Moreover, an additional unary/binary operation can be applied on |
51 | the loaded value, and final result is passed as actual argument of callee |
52 | (e.g. *(param_1(D) + 4) op 24 ). It is meant to describe usage of aggregate |
53 | parameter or by-reference parameter referenced in argument passing, commonly |
54 | found in C++ and Fortran. |
55 | |
56 | IPA_JF_ANCESTOR is a special pass-through jump function, which means that |
57 | the result is an address of a part of the object pointed to by the formal |
58 | parameter to which the function refers. It is mainly intended to represent |
59 | getting addresses of ancestor fields in C++ |
60 | (e.g. &this_1(D)->D.1766.D.1756). Note that if the original pointer is |
61 | NULL, ancestor jump function must behave like a simple pass-through. |
62 | |
63 | Other pass-through functions can either simply pass on an unchanged formal |
64 | parameter or can apply one simple binary operation to it (such jump |
65 | functions are called polynomial). |
66 | |
67 | Jump functions are computed in ipa-prop.cc by function |
68 | update_call_notes_after_inlining. Some information can be lost and jump |
69 | functions degraded accordingly when inlining, see |
70 | update_call_notes_after_inlining in the same file. */ |
71 | |
72 | enum jump_func_type |
73 | { |
74 | IPA_JF_UNKNOWN = 0, /* newly allocated and zeroed jump functions default */ |
75 | IPA_JF_CONST, /* represented by field costant */ |
76 | IPA_JF_PASS_THROUGH, /* represented by field pass_through */ |
77 | IPA_JF_LOAD_AGG, /* represented by field load_agg */ |
78 | IPA_JF_ANCESTOR /* represented by field ancestor */ |
79 | }; |
80 | |
81 | struct ipa_cst_ref_desc; |
82 | |
83 | /* Structure holding data required to describe a constant jump function. */ |
84 | struct GTY(()) ipa_constant_data |
85 | { |
86 | /* The value of the constant. */ |
87 | tree value; |
88 | /* Pointer to the structure that describes the reference. */ |
89 | struct ipa_cst_ref_desc GTY((skip)) *rdesc; |
90 | }; |
91 | |
92 | /* Structure holding data required to describe a pass-through jump function. */ |
93 | |
94 | struct GTY(()) ipa_pass_through_data |
95 | { |
96 | /* If an operation is to be performed on the original parameter, this is the |
97 | second (constant) operand. */ |
98 | tree operand; |
99 | /* Number of the caller's formal parameter being passed. */ |
100 | int formal_id; |
101 | /* Operation that is performed on the argument before it is passed on. |
102 | Special values which have other meaning than in normal contexts: |
103 | - NOP_EXPR means no operation, not even type conversion. |
104 | - ASSERT_EXPR means that only the value in operand is allowed to pass |
105 | through (without any change), for all other values the result is |
106 | unknown. |
107 | Otherwise operation must be a simple binary or unary arithmetic operation |
108 | where the caller's parameter is the first operand and (for binary |
109 | operations) the operand field from this structure is the second one. */ |
110 | enum tree_code operation; |
111 | /* When the passed value is a pointer, it is set to true only when we are |
112 | certain that no write to the object it points to has occurred since the |
113 | caller functions started execution, except for changes noted in the |
114 | aggregate part of the jump function (see description of |
115 | ipa_agg_jump_function). The flag is used only when the operation is |
116 | NOP_EXPR. */ |
117 | unsigned agg_preserved : 1; |
118 | /* Set when the edge has already been used to decrement an appropriate |
119 | reference description counter and should not be decremented again. */ |
120 | unsigned refdesc_decremented : 1; |
121 | }; |
122 | |
123 | /* Structure holding data required to describe a load-value-from-aggregate |
124 | jump function. */ |
125 | |
126 | struct GTY(()) ipa_load_agg_data |
127 | { |
128 | /* Inherit from pass through jump function, describing unary/binary |
129 | operation on the value loaded from aggregate that is represented or |
130 | pointed to by the formal parameter, specified by formal_id in this |
131 | pass_through jump function data structure. */ |
132 | struct ipa_pass_through_data pass_through; |
133 | /* Type of the value loaded from the aggregate. */ |
134 | tree type; |
135 | /* Offset at which the value is located within the aggregate. */ |
136 | HOST_WIDE_INT offset; |
137 | /* True if loaded by reference (the aggregate is pointed to by the formal |
138 | parameter) or false if loaded by value (the aggregate is represented |
139 | by the formal parameter). */ |
140 | bool by_ref; |
141 | }; |
142 | |
143 | /* Structure holding data required to describe an ancestor pass-through |
144 | jump function. */ |
145 | |
146 | struct GTY(()) ipa_ancestor_jf_data |
147 | { |
148 | /* Offset of the field representing the ancestor. */ |
149 | HOST_WIDE_INT offset; |
150 | /* Number of the caller's formal parameter being passed. */ |
151 | int formal_id; |
152 | /* Flag with the same meaning like agg_preserve in ipa_pass_through_data. */ |
153 | unsigned agg_preserved : 1; |
154 | /* When set, the operation should not have any effect on NULL pointers. */ |
155 | unsigned keep_null : 1; |
156 | }; |
157 | |
158 | /* A jump function for an aggregate part at a given offset, which describes how |
159 | it content value is generated. All unlisted positions are assumed to have a |
160 | value defined in an unknown way. */ |
161 | |
162 | struct GTY(()) ipa_agg_jf_item |
163 | { |
164 | /* The offset for the aggregate part. */ |
165 | HOST_WIDE_INT offset; |
166 | |
167 | /* Data type of the aggregate part. */ |
168 | tree type; |
169 | |
170 | /* Jump function type. */ |
171 | enum jump_func_type jftype; |
172 | |
173 | /* Represents a value of jump function. constant represents the actual constant |
174 | in constant jump function content. pass_through is used only in simple pass |
175 | through jump function context. load_agg is for load-value-from-aggregate |
176 | jump function context. */ |
177 | union jump_func_agg_value |
178 | { |
179 | tree GTY ((tag ("IPA_JF_CONST" ))) constant; |
180 | struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH" ))) pass_through; |
181 | struct ipa_load_agg_data GTY ((tag ("IPA_JF_LOAD_AGG" ))) load_agg; |
182 | } GTY ((desc ("%1.jftype" ))) value; |
183 | }; |
184 | |
185 | /* Jump functions describing a set of aggregate contents. */ |
186 | |
187 | struct GTY(()) ipa_agg_jump_function |
188 | { |
189 | /* Description of the individual jump function item. */ |
190 | vec<ipa_agg_jf_item, va_gc> *items; |
191 | /* True if the data was passed by reference (as opposed to by value). */ |
192 | bool by_ref; |
193 | }; |
194 | |
195 | class ipcp_transformation; |
196 | class ipa_auto_call_arg_values; |
197 | class ipa_call_arg_values; |
198 | |
199 | /* Element of a vector describing aggregate values for a number of arguments in |
200 | a particular context, be it a call or the aggregate constants that a node is |
201 | specialized for. */ |
202 | |
203 | struct GTY(()) ipa_argagg_value |
204 | { |
205 | /* The constant value. In the contexts where the list of known values is |
206 | being pruned, NULL means a variable value. */ |
207 | tree value; |
208 | /* Unit offset within the aggregate. */ |
209 | unsigned unit_offset; |
210 | /* Index of the parameter, as it was in the original function (i.e. needs |
211 | remapping after parameter modification is carried out as part of clone |
212 | materialization). */ |
213 | unsigned index : IPA_PROP_ARG_INDEX_LIMIT_BITS; |
214 | /* Whether the value was passed by reference. */ |
215 | unsigned by_ref : 1; |
216 | /* Set if the value should not be used after materialization in |
217 | value_numbering. It is kept around just so that clone materialization can |
218 | distinguish a combined IPA-CP and IPA-SRA from a deleted argument. */ |
219 | unsigned killed : 1; |
220 | }; |
221 | |
222 | /* A view into a sorted list of aggregate values in a particular context, be it |
223 | a call or the aggregate constants that a node is specialized for. The |
224 | actual data is stored in the vector this has been constructed from. */ |
225 | |
226 | class ipa_argagg_value_list |
227 | { |
228 | public: |
229 | ipa_argagg_value_list () = delete; |
230 | ipa_argagg_value_list (const vec<ipa_argagg_value, va_gc> *values) |
231 | : m_elts (values) |
232 | {} |
233 | ipa_argagg_value_list (const vec<ipa_argagg_value> *values) |
234 | : m_elts (*values) |
235 | {} |
236 | ipa_argagg_value_list (const ipa_auto_call_arg_values *aavals); |
237 | ipa_argagg_value_list (const ipa_call_arg_values *gavals); |
238 | ipa_argagg_value_list (const ipcp_transformation *tinfo); |
239 | |
240 | /* Return the aggregate constant stored for INDEX at UNIT_OFFSET, if it is |
241 | passed by reference or not according to BY_REF, or NULL_TREE |
242 | otherwise. */ |
243 | |
244 | tree get_value (int index, unsigned unit_offset, bool by_ref) const; |
245 | |
246 | /* Return the aggregate constant stored for INDEX at UNIT_OFFSET, not |
247 | performing any check of whether value is passed by reference. Return |
248 | NULL_TREE if there is no such constant. */ |
249 | |
250 | tree get_value (int index, unsigned unit_offset) const; |
251 | |
252 | /* Return the item describing a constant stored for INDEX at UNIT_OFFSET or |
253 | NULL if there is no such constant. */ |
254 | |
255 | const ipa_argagg_value *get_elt (int index, unsigned unit_offset) const; |
256 | |
257 | |
258 | /* Return the first item describing a constant stored for parameter with |
259 | INDEX, regardless of offset or reference, or NULL if there is no such |
260 | constant. */ |
261 | |
262 | const ipa_argagg_value *get_elt_for_index (int index) const; |
263 | |
264 | /* Return true if there is an aggregate constant referring to a value passed |
265 | in or by parameter with INDEX (at any offset, whether by reference or |
266 | not). */ |
267 | |
268 | bool value_for_index_p (int index) const |
269 | { |
270 | return !!get_elt_for_index (index); |
271 | } |
272 | |
273 | /* Return true if all elements present in OTHER are also present in this |
274 | list. */ |
275 | |
276 | bool superset_of_p (const ipa_argagg_value_list &other) const; |
277 | |
278 | /* Push all items in this list that describe parameter SRC_INDEX into RES as |
279 | ones describing DST_INDEX while subtracting UNIT_DELTA from their unit |
280 | offsets but skip those which would end up with a negative offset. */ |
281 | |
282 | void push_adjusted_values (unsigned src_index, unsigned dest_index, |
283 | unsigned unit_delta, |
284 | vec<ipa_argagg_value> *res) const; |
285 | |
286 | /* Dump aggregate constants to FILE. */ |
287 | |
288 | void dump (FILE *f); |
289 | |
290 | /* Dump aggregate constants to stderr. */ |
291 | |
292 | void DEBUG_FUNCTION debug (); |
293 | |
294 | /* Array slice pointing to the actual storage. */ |
295 | |
296 | array_slice<const ipa_argagg_value> m_elts; |
297 | }; |
298 | |
299 | /* Info about value ranges. */ |
300 | |
301 | class GTY(()) ipa_vr |
302 | { |
303 | public: |
304 | ipa_vr (); |
305 | ipa_vr (const vrange &); |
306 | void set_unknown (); |
307 | bool known_p () const { return m_storage != NULL; } |
308 | tree type () const { return m_type; } |
309 | void get_vrange (Value_Range &) const; |
310 | bool equal_p (const vrange &) const; |
311 | bool equal_p (const ipa_vr &) const; |
312 | const vrange_storage *storage () const { return m_storage; } |
313 | void streamer_read (lto_input_block *, class data_in *); |
314 | void streamer_write (output_block *) const; |
315 | void dump (FILE *) const; |
316 | |
317 | private: |
318 | friend void gt_pch_nx (struct ipa_vr &); |
319 | friend void gt_ggc_mx (struct ipa_vr &); |
320 | friend void gt_pch_nx (struct ipa_vr *, gt_pointer_operator, void *); |
321 | friend void gt_ggc_mx_ipa_vr (void *); |
322 | friend void gt_pch_nx_ipa_vr (void*); |
323 | friend void gt_pch_p_6ipa_vr(void*, void*, gt_pointer_operator, void*); |
324 | |
325 | vrange_storage *m_storage; |
326 | tree m_type; |
327 | }; |
328 | |
329 | /* A jump function for a callsite represents the values passed as actual |
330 | arguments of the callsite. See enum jump_func_type for the various |
331 | types of jump functions supported. */ |
332 | struct GTY (()) ipa_jump_func |
333 | { |
334 | /* Aggregate jump function description. See struct ipa_agg_jump_function |
335 | and its description. */ |
336 | struct ipa_agg_jump_function agg; |
337 | |
338 | /* Information about value range, containing valid data only when vr_known is |
339 | true. The pointed to structure is shared betweed different jump |
340 | functions. Use ipa_set_jfunc_vr to set this field. */ |
341 | ipa_vr *m_vr; |
342 | |
343 | enum jump_func_type type; |
344 | /* Represents a value of a jump function. pass_through is used only in jump |
345 | function context. constant represents the actual constant in constant jump |
346 | functions and member_cst holds constant c++ member functions. */ |
347 | union jump_func_value |
348 | { |
349 | struct ipa_constant_data GTY ((tag ("IPA_JF_CONST" ))) constant; |
350 | struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH" ))) pass_through; |
351 | struct ipa_ancestor_jf_data GTY ((tag ("IPA_JF_ANCESTOR" ))) ancestor; |
352 | } GTY ((desc ("%1.type" ))) value; |
353 | }; |
354 | |
355 | |
356 | /* Return the constant stored in a constant jump functin JFUNC. */ |
357 | |
358 | inline tree |
359 | ipa_get_jf_constant (struct ipa_jump_func *jfunc) |
360 | { |
361 | gcc_checking_assert (jfunc->type == IPA_JF_CONST); |
362 | return jfunc->value.constant.value; |
363 | } |
364 | |
365 | inline struct ipa_cst_ref_desc * |
366 | ipa_get_jf_constant_rdesc (struct ipa_jump_func *jfunc) |
367 | { |
368 | gcc_checking_assert (jfunc->type == IPA_JF_CONST); |
369 | return jfunc->value.constant.rdesc; |
370 | } |
371 | |
372 | /* Make JFUNC not participate in any further reference counting. */ |
373 | |
374 | inline void |
375 | ipa_zap_jf_refdesc (ipa_jump_func *jfunc) |
376 | { |
377 | gcc_checking_assert (jfunc->type == IPA_JF_CONST); |
378 | jfunc->value.constant.rdesc = NULL; |
379 | } |
380 | |
381 | /* Return the operand of a pass through jmp function JFUNC. */ |
382 | |
383 | inline tree |
384 | ipa_get_jf_pass_through_operand (struct ipa_jump_func *jfunc) |
385 | { |
386 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
387 | return jfunc->value.pass_through.operand; |
388 | } |
389 | |
390 | /* Return the number of the caller's formal parameter that a pass through jump |
391 | function JFUNC refers to. */ |
392 | |
393 | inline int |
394 | ipa_get_jf_pass_through_formal_id (struct ipa_jump_func *jfunc) |
395 | { |
396 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
397 | return jfunc->value.pass_through.formal_id; |
398 | } |
399 | |
400 | /* Return operation of a pass through jump function JFUNC. */ |
401 | |
402 | inline enum tree_code |
403 | ipa_get_jf_pass_through_operation (struct ipa_jump_func *jfunc) |
404 | { |
405 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
406 | return jfunc->value.pass_through.operation; |
407 | } |
408 | |
409 | /* Return the agg_preserved flag of a pass through jump function JFUNC. */ |
410 | |
411 | inline bool |
412 | ipa_get_jf_pass_through_agg_preserved (struct ipa_jump_func *jfunc) |
413 | { |
414 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
415 | return jfunc->value.pass_through.agg_preserved; |
416 | } |
417 | |
418 | /* Return the refdesc_decremented flag of a pass through jump function |
419 | JFUNC. */ |
420 | |
421 | inline bool |
422 | ipa_get_jf_pass_through_refdesc_decremented (struct ipa_jump_func *jfunc) |
423 | { |
424 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
425 | return jfunc->value.pass_through.refdesc_decremented; |
426 | } |
427 | |
428 | /* Set the refdesc_decremented flag of a pass through jump function JFUNC to |
429 | VALUE. */ |
430 | |
431 | inline void |
432 | ipa_set_jf_pass_through_refdesc_decremented (ipa_jump_func *jfunc, bool value) |
433 | { |
434 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
435 | jfunc->value.pass_through.refdesc_decremented = value; |
436 | } |
437 | |
438 | /* Return true if pass through jump function JFUNC preserves type |
439 | information. */ |
440 | |
441 | inline bool |
442 | ipa_get_jf_pass_through_type_preserved (struct ipa_jump_func *jfunc) |
443 | { |
444 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
445 | return jfunc->value.pass_through.agg_preserved; |
446 | } |
447 | |
448 | /* Return the offset of an ancestor jump function JFUNC. */ |
449 | |
450 | inline HOST_WIDE_INT |
451 | ipa_get_jf_ancestor_offset (struct ipa_jump_func *jfunc) |
452 | { |
453 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
454 | return jfunc->value.ancestor.offset; |
455 | } |
456 | |
457 | /* Return the number of the caller's formal parameter that an ancestor jump |
458 | function JFUNC refers to. */ |
459 | |
460 | inline int |
461 | ipa_get_jf_ancestor_formal_id (struct ipa_jump_func *jfunc) |
462 | { |
463 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
464 | return jfunc->value.ancestor.formal_id; |
465 | } |
466 | |
467 | /* Return the agg_preserved flag of an ancestor jump function JFUNC. */ |
468 | |
469 | inline bool |
470 | ipa_get_jf_ancestor_agg_preserved (struct ipa_jump_func *jfunc) |
471 | { |
472 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
473 | return jfunc->value.ancestor.agg_preserved; |
474 | } |
475 | |
476 | /* Return true if ancestor jump function JFUNC presrves type information. */ |
477 | |
478 | inline bool |
479 | ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc) |
480 | { |
481 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
482 | return jfunc->value.ancestor.agg_preserved; |
483 | } |
484 | |
485 | /* Return if jfunc represents an operation whether we first check the formal |
486 | parameter for non-NULLness unless it does not matter because the offset is |
487 | zero anyway. */ |
488 | |
489 | inline bool |
490 | ipa_get_jf_ancestor_keep_null (struct ipa_jump_func *jfunc) |
491 | { |
492 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
493 | return jfunc->value.ancestor.keep_null; |
494 | } |
495 | |
496 | /* Class for allocating a bundle of various potentially known properties about |
497 | actual arguments of a particular call on stack for the usual case and on |
498 | heap only if there are unusually many arguments. The data is deallocated |
499 | when the instance of this class goes out of scope or is otherwise |
500 | destructed. */ |
501 | |
502 | class ipa_auto_call_arg_values |
503 | { |
504 | public: |
505 | /* If m_known_vals (vector of known "scalar" values) is sufficiantly long, |
506 | return its element at INDEX, otherwise return NULL. */ |
507 | tree safe_sval_at (int index) |
508 | { |
509 | if ((unsigned) index < m_known_vals.length ()) |
510 | return m_known_vals[index]; |
511 | return NULL; |
512 | } |
513 | |
514 | /* Vector describing known values of parameters. */ |
515 | auto_vec<tree, 32> m_known_vals; |
516 | |
517 | /* Vector describing known polymorphic call contexts. */ |
518 | auto_vec<ipa_polymorphic_call_context, 32> m_known_contexts; |
519 | |
520 | /* Vector describing known aggregate values. */ |
521 | auto_vec<ipa_argagg_value, 32> m_known_aggs; |
522 | |
523 | /* Vector describing known value ranges of arguments. */ |
524 | auto_vec<Value_Range, 32> m_known_value_ranges; |
525 | }; |
526 | |
527 | inline |
528 | ipa_argagg_value_list |
529 | ::ipa_argagg_value_list (const ipa_auto_call_arg_values *aavals) |
530 | : m_elts (aavals->m_known_aggs) |
531 | {} |
532 | |
533 | /* Class bundling the various potentially known properties about actual |
534 | arguments of a particular call. This variant does not deallocate the |
535 | bundled data in any way as the vectors can either be pointing to vectors in |
536 | ipa_auto_call_arg_values or be allocated independently. */ |
537 | |
538 | class ipa_call_arg_values |
539 | { |
540 | public: |
541 | /* Default constructor, setting the vectors to empty ones. */ |
542 | ipa_call_arg_values () |
543 | {} |
544 | |
545 | /* Construct this general variant of the bundle from the variant which uses |
546 | auto_vecs to hold the vectors. This means that vectors of objects |
547 | constructed with this constructor should not be changed because if they |
548 | get reallocated, the member vectors and the underlying auto_vecs would get |
549 | out of sync. */ |
550 | ipa_call_arg_values (ipa_auto_call_arg_values *aavals) |
551 | : m_known_vals (aavals->m_known_vals.to_vec_legacy ()), |
552 | m_known_contexts (aavals->m_known_contexts.to_vec_legacy ()), |
553 | m_known_aggs (aavals->m_known_aggs.to_vec_legacy ()), |
554 | m_known_value_ranges (aavals->m_known_value_ranges.to_vec_legacy ()) |
555 | {} |
556 | |
557 | /* If m_known_vals (vector of known "scalar" values) is sufficiantly long, |
558 | return its element at INDEX, otherwise return NULL. */ |
559 | tree safe_sval_at (int index) |
560 | { |
561 | if ((unsigned) index < m_known_vals.length ()) |
562 | return m_known_vals[index]; |
563 | return NULL; |
564 | } |
565 | |
566 | /* Vector describing known values of parameters. */ |
567 | vec<tree> m_known_vals = vNULL; |
568 | |
569 | /* Vector describing known polymorphic call contexts. */ |
570 | vec<ipa_polymorphic_call_context> m_known_contexts = vNULL; |
571 | |
572 | /* Vector describing known aggregate values. */ |
573 | vec<ipa_argagg_value> m_known_aggs = vNULL; |
574 | |
575 | /* Vector describing known value ranges of arguments. */ |
576 | vec<Value_Range> m_known_value_ranges = vNULL; |
577 | }; |
578 | |
579 | inline |
580 | ipa_argagg_value_list |
581 | ::ipa_argagg_value_list (const ipa_call_arg_values *gavals) |
582 | : m_elts (gavals->m_known_aggs) |
583 | {} |
584 | |
585 | /* Summary describing a single formal parameter. */ |
586 | |
587 | struct GTY(()) ipa_param_descriptor |
588 | { |
589 | /* In analysis and modification phase, this is the PARAM_DECL of this |
590 | parameter, in IPA LTO phase, this is the type of the described |
591 | parameter or NULL if not known. Do not read this field directly but |
592 | through ipa_get_param and ipa_get_type as appropriate. */ |
593 | tree decl_or_type; |
594 | /* If all uses of the parameter are described by ipa-prop structures, this |
595 | says how many there are. If any use could not be described by means of |
596 | ipa-prop structures (which include flag dereferenced below), this is |
597 | IPA_UNDESCRIBED_USE. */ |
598 | int controlled_uses; |
599 | unsigned int move_cost : 27; |
600 | /* The parameter is used. */ |
601 | unsigned used : 1; |
602 | unsigned used_by_ipa_predicates : 1; |
603 | unsigned used_by_indirect_call : 1; |
604 | unsigned used_by_polymorphic_call : 1; |
605 | /* Set to true when in addition to being used in call statements, the |
606 | parameter has also been used for loads (but not for writes, does not |
607 | escape, etc.). This allows us to identify parameters p which are only |
608 | used as *p, and so when we propagate a constant to them, we can generate a |
609 | LOAD and not ADDR reference to them. */ |
610 | unsigned load_dereferenced : 1; |
611 | }; |
612 | |
613 | /* ipa_node_params stores information related to formal parameters of functions |
614 | and some other information for interprocedural passes that operate on |
615 | parameters (such as ipa-cp). */ |
616 | |
617 | class GTY((for_user)) ipa_node_params |
618 | { |
619 | public: |
620 | /* Default constructor. */ |
621 | ipa_node_params (); |
622 | |
623 | /* Default destructor. */ |
624 | ~ipa_node_params (); |
625 | |
626 | /* Information about individual formal parameters that are gathered when |
627 | summaries are generated. */ |
628 | vec<ipa_param_descriptor, va_gc> *descriptors; |
629 | /* Pointer to an array of structures describing individual formal |
630 | parameters. */ |
631 | vec<ipcp_param_lattices> GTY((skip)) lattices; |
632 | /* Only for versioned nodes this field would not be NULL, |
633 | it points to the node that IPA cp cloned from. */ |
634 | struct cgraph_node * GTY((skip)) ipcp_orig_node; |
635 | /* If this node is an ipa-cp clone, these are the known constants that |
636 | describe what it has been specialized for. */ |
637 | vec<tree> GTY((skip)) known_csts; |
638 | /* If this node is an ipa-cp clone, these are the known polymorphic contexts |
639 | that describe what it has been specialized for. */ |
640 | vec<ipa_polymorphic_call_context> GTY((skip)) known_contexts; |
641 | /* Whether the param uses analysis and jump function computation has already |
642 | been performed. */ |
643 | unsigned analysis_done : 1; |
644 | /* Whether the function is enqueued in ipa-cp propagation stack. */ |
645 | unsigned node_enqueued : 1; |
646 | /* Whether we should create a specialized version based on values that are |
647 | known to be constant in all contexts. */ |
648 | unsigned do_clone_for_all_contexts : 1; |
649 | /* Set if this is an IPA-CP clone for all contexts. */ |
650 | unsigned is_all_contexts_clone : 1; |
651 | /* Node has been completely replaced by clones and will be removed after |
652 | ipa-cp is finished. */ |
653 | unsigned node_dead : 1; |
654 | /* Node is involved in a recursion, potentionally indirect. */ |
655 | unsigned node_within_scc : 1; |
656 | /* Node contains only direct recursion. */ |
657 | unsigned node_is_self_scc : 1; |
658 | /* Node is calling a private function called only once. */ |
659 | unsigned node_calling_single_call : 1; |
660 | /* False when there is something makes versioning impossible. */ |
661 | unsigned versionable : 1; |
662 | }; |
663 | |
664 | inline |
665 | ipa_node_params::ipa_node_params () |
666 | : descriptors (NULL), lattices (vNULL), ipcp_orig_node (NULL), |
667 | known_csts (vNULL), known_contexts (vNULL), analysis_done (0), |
668 | node_enqueued (0), do_clone_for_all_contexts (0), is_all_contexts_clone (0), |
669 | node_dead (0), node_within_scc (0), node_is_self_scc (0), |
670 | node_calling_single_call (0), versionable (0) |
671 | { |
672 | } |
673 | |
674 | inline |
675 | ipa_node_params::~ipa_node_params () |
676 | { |
677 | vec_free (v&: descriptors); |
678 | lattices.release (); |
679 | known_csts.release (); |
680 | known_contexts.release (); |
681 | } |
682 | |
683 | /* Intermediate information that we get from alias analysis about a particular |
684 | parameter in a particular basic_block. When a parameter or the memory it |
685 | references is marked modified, we use that information in all dominated |
686 | blocks without consulting alias analysis oracle. */ |
687 | |
688 | struct ipa_param_aa_status |
689 | { |
690 | /* Set when this structure contains meaningful information. If not, the |
691 | structure describing a dominating BB should be used instead. */ |
692 | bool valid; |
693 | |
694 | /* Whether we have seen something which might have modified the data in |
695 | question. PARM is for the parameter itself, REF is for data it points to |
696 | but using the alias type of individual accesses and PT is the same thing |
697 | but for computing aggregate pass-through functions using a very inclusive |
698 | ao_ref. */ |
699 | bool parm_modified, ref_modified, pt_modified; |
700 | }; |
701 | |
702 | /* Information related to a given BB that used only when looking at function |
703 | body. */ |
704 | |
705 | struct ipa_bb_info |
706 | { |
707 | /* Call graph edges going out of this BB. */ |
708 | vec<cgraph_edge *> cg_edges; |
709 | /* Alias analysis statuses of each formal parameter at this bb. */ |
710 | vec<ipa_param_aa_status> param_aa_statuses; |
711 | }; |
712 | |
713 | /* Structure with global information that is only used when looking at function |
714 | body. */ |
715 | |
716 | struct ipa_func_body_info |
717 | { |
718 | /* The node that is being analyzed. */ |
719 | cgraph_node *node; |
720 | |
721 | /* Its info. */ |
722 | class ipa_node_params *info; |
723 | |
724 | /* Information about individual BBs. */ |
725 | vec<ipa_bb_info> bb_infos; |
726 | |
727 | /* Number of parameters. */ |
728 | int param_count; |
729 | |
730 | /* Number of statements we are still allowed to walked by when analyzing this |
731 | function. */ |
732 | unsigned int aa_walk_budget; |
733 | }; |
734 | |
735 | /* ipa_node_params access functions. Please use these to access fields that |
736 | are or will be shared among various passes. */ |
737 | |
738 | /* Return the number of formal parameters. */ |
739 | |
740 | inline int |
741 | ipa_get_param_count (class ipa_node_params *info) |
742 | { |
743 | return vec_safe_length (v: info->descriptors); |
744 | } |
745 | |
746 | /* Return the parameter declaration in DESCRIPTORS at index I and assert it is |
747 | indeed a PARM_DECL. */ |
748 | |
749 | inline tree |
750 | ipa_get_param (const vec<ipa_param_descriptor, va_gc> &descriptors, int i) |
751 | { |
752 | tree t = descriptors[i].decl_or_type; |
753 | gcc_checking_assert (TREE_CODE (t) == PARM_DECL); |
754 | return t; |
755 | } |
756 | |
757 | /* Return the declaration of Ith formal parameter of the function corresponding |
758 | to INFO. Note there is no setter function as this array is built just once |
759 | using ipa_initialize_node_params. This function should not be called in |
760 | WPA. */ |
761 | |
762 | inline tree |
763 | ipa_get_param (class ipa_node_params *info, int i) |
764 | { |
765 | gcc_checking_assert (info->descriptors); |
766 | return ipa_get_param (descriptors: *info->descriptors, i); |
767 | } |
768 | |
769 | /* Return the type of Ith formal parameter of the function corresponding |
770 | to INFO if it is known or NULL if not. */ |
771 | |
772 | inline tree |
773 | ipa_get_type (class ipa_node_params *info, int i) |
774 | { |
775 | if (vec_safe_length (v: info->descriptors) <= (unsigned) i) |
776 | return NULL; |
777 | tree t = (*info->descriptors)[i].decl_or_type; |
778 | if (!t) |
779 | return NULL; |
780 | if (TYPE_P (t)) |
781 | return t; |
782 | gcc_checking_assert (TREE_CODE (t) == PARM_DECL); |
783 | return TREE_TYPE (t); |
784 | } |
785 | |
786 | /* Return the move cost of Ith formal parameter of the function corresponding |
787 | to INFO. */ |
788 | |
789 | inline int |
790 | ipa_get_param_move_cost (class ipa_node_params *info, int i) |
791 | { |
792 | gcc_checking_assert (info->descriptors); |
793 | return (*info->descriptors)[i].move_cost; |
794 | } |
795 | |
796 | /* Set the used flag corresponding to the Ith formal parameter of the function |
797 | associated with INFO to VAL. */ |
798 | |
799 | inline void |
800 | ipa_set_param_used (class ipa_node_params *info, int i, bool val) |
801 | { |
802 | gcc_checking_assert (info->descriptors); |
803 | (*info->descriptors)[i].used = val; |
804 | } |
805 | |
806 | /* Set the used_by_ipa_predicates flag corresponding to the Ith formal |
807 | parameter of the function associated with INFO to VAL. */ |
808 | |
809 | inline void |
810 | ipa_set_param_used_by_ipa_predicates (class ipa_node_params *info, int i, bool val) |
811 | { |
812 | gcc_checking_assert (info->descriptors); |
813 | (*info->descriptors)[i].used_by_ipa_predicates = val; |
814 | } |
815 | |
816 | /* Set the used_by_indirect_call flag corresponding to the Ith formal |
817 | parameter of the function associated with INFO to VAL. */ |
818 | |
819 | inline void |
820 | ipa_set_param_used_by_indirect_call (class ipa_node_params *info, int i, bool val) |
821 | { |
822 | gcc_checking_assert (info->descriptors); |
823 | (*info->descriptors)[i].used_by_indirect_call = val; |
824 | } |
825 | |
826 | /* Set the .used_by_polymorphic_call flag corresponding to the Ith formal |
827 | parameter of the function associated with INFO to VAL. */ |
828 | |
829 | inline void |
830 | ipa_set_param_used_by_polymorphic_call (class ipa_node_params *info, int i, bool val) |
831 | { |
832 | gcc_checking_assert (info->descriptors); |
833 | (*info->descriptors)[i].used_by_polymorphic_call = val; |
834 | } |
835 | |
836 | /* Return how many uses described by ipa-prop a parameter has or |
837 | IPA_UNDESCRIBED_USE if there is a use that is not described by these |
838 | structures. */ |
839 | inline int |
840 | ipa_get_controlled_uses (class ipa_node_params *info, int i) |
841 | { |
842 | /* FIXME: introducing speculation causes out of bounds access here. */ |
843 | if (vec_safe_length (v: info->descriptors) > (unsigned)i) |
844 | return (*info->descriptors)[i].controlled_uses; |
845 | return IPA_UNDESCRIBED_USE; |
846 | } |
847 | |
848 | /* Set the controlled counter of a given parameter. */ |
849 | |
850 | inline void |
851 | ipa_set_controlled_uses (class ipa_node_params *info, int i, int val) |
852 | { |
853 | gcc_checking_assert (info->descriptors); |
854 | (*info->descriptors)[i].controlled_uses = val; |
855 | } |
856 | |
857 | /* Assuming a parameter does not have IPA_UNDESCRIBED_USE controlled uses, |
858 | return flag which indicates it has been dereferenced but only in a load. */ |
859 | inline int |
860 | ipa_get_param_load_dereferenced (class ipa_node_params *info, int i) |
861 | { |
862 | gcc_assert (ipa_get_controlled_uses (info, i) != IPA_UNDESCRIBED_USE); |
863 | return (*info->descriptors)[i].load_dereferenced; |
864 | } |
865 | |
866 | /* Set the load_dereferenced flag of a given parameter. */ |
867 | |
868 | inline void |
869 | ipa_set_param_load_dereferenced (class ipa_node_params *info, int i, bool val) |
870 | { |
871 | gcc_checking_assert (info->descriptors); |
872 | (*info->descriptors)[i].load_dereferenced = val; |
873 | } |
874 | |
875 | /* Return the used flag corresponding to the Ith formal parameter of the |
876 | function associated with INFO. */ |
877 | |
878 | inline bool |
879 | ipa_is_param_used (class ipa_node_params *info, int i) |
880 | { |
881 | gcc_checking_assert (info->descriptors); |
882 | return (*info->descriptors)[i].used; |
883 | } |
884 | |
885 | /* Return the used_by_ipa_predicates flag corresponding to the Ith formal |
886 | parameter of the function associated with INFO. */ |
887 | |
888 | inline bool |
889 | ipa_is_param_used_by_ipa_predicates (class ipa_node_params *info, int i) |
890 | { |
891 | gcc_checking_assert (info->descriptors); |
892 | return (*info->descriptors)[i].used_by_ipa_predicates; |
893 | } |
894 | |
895 | /* Return the used_by_indirect_call flag corresponding to the Ith formal |
896 | parameter of the function associated with INFO. */ |
897 | |
898 | inline bool |
899 | ipa_is_param_used_by_indirect_call (class ipa_node_params *info, int i) |
900 | { |
901 | gcc_checking_assert (info->descriptors); |
902 | return (*info->descriptors)[i].used_by_indirect_call; |
903 | } |
904 | |
905 | /* Return the used_by_polymorphic_call flag corresponding to the Ith formal |
906 | parameter of the function associated with INFO. */ |
907 | |
908 | inline bool |
909 | ipa_is_param_used_by_polymorphic_call (class ipa_node_params *info, int i) |
910 | { |
911 | gcc_checking_assert (info->descriptors); |
912 | return (*info->descriptors)[i].used_by_polymorphic_call; |
913 | } |
914 | |
915 | /* GTY-marked structure used to map DECL_UIDs of APRAMs to their indices in |
916 | their DECL_ARGUMENTs chain. */ |
917 | struct GTY(()) ipa_uid_to_idx_map_elt |
918 | { |
919 | /* DECL_UID of the PARAM. */ |
920 | unsigned uid; |
921 | /* Its index in the DECL_ARGUMETs chain. */ |
922 | unsigned index; |
923 | }; |
924 | |
925 | /* Structure holding information for the transformation phase of IPA-CP. */ |
926 | |
927 | struct GTY(()) ipcp_transformation |
928 | { |
929 | /* Default constructor. */ |
930 | ipcp_transformation () |
931 | : m_agg_values (nullptr), m_vr (nullptr), m_uid_to_idx (nullptr) |
932 | { } |
933 | |
934 | /* Default destructor. */ |
935 | ~ipcp_transformation () |
936 | { |
937 | vec_free (v&: m_agg_values); |
938 | vec_free (v&: m_vr); |
939 | } |
940 | |
941 | /* Given PARAM which must be a parameter of function FNDECL described by |
942 | THIS, return its index in the DECL_ARGUMENTS chain, using a pre-computed |
943 | DECL_UID-sorted vector if available (which is pre-computed only if there |
944 | are many parameters). Can return -1 if param is static chain not |
945 | represented among DECL_ARGUMENTS. */ |
946 | |
947 | int get_param_index (const_tree fndecl, const_tree param) const; |
948 | |
949 | /* Assuming THIS describes FNDECL and it has sufficiently many parameters to |
950 | justify the overhead, create a DECL_UID-sorted vector to speed up mapping |
951 | from parameters to their indices in DECL_ARGUMENTS chain. */ |
952 | |
953 | void maybe_create_parm_idx_map (tree fndecl); |
954 | |
955 | /* Remove all elements in m_agg_values on which PREDICATE returns true. */ |
956 | |
957 | template<typename pred_function> |
958 | void remove_argaggs_if (pred_function &&predicate) |
959 | { |
960 | unsigned ts_len = vec_safe_length (v: m_agg_values); |
961 | if (ts_len == 0) |
962 | return; |
963 | |
964 | bool removed_item = false; |
965 | unsigned dst_index = 0; |
966 | |
967 | for (unsigned i = 0; i < ts_len; i++) |
968 | { |
969 | ipa_argagg_value *v = &(*m_agg_values)[i]; |
970 | if (!predicate (*v)) |
971 | { |
972 | if (removed_item) |
973 | (*m_agg_values)[dst_index] = *v; |
974 | dst_index++; |
975 | } |
976 | else |
977 | removed_item = true; |
978 | } |
979 | if (dst_index == 0) |
980 | { |
981 | ggc_free (m_agg_values); |
982 | m_agg_values = NULL; |
983 | } |
984 | else if (removed_item) |
985 | m_agg_values->truncate (dst_index); |
986 | } |
987 | |
988 | /* Known aggregate values. */ |
989 | vec<ipa_argagg_value, va_gc> *m_agg_values; |
990 | /* Value range information. */ |
991 | vec<ipa_vr, va_gc> *m_vr; |
992 | /* If there are many parameters, this is a vector sorted by their DECL_UIDs |
993 | to map them to their indices in the DECL_ARGUMENT chain. */ |
994 | vec<ipa_uid_to_idx_map_elt, va_gc> *m_uid_to_idx; |
995 | }; |
996 | |
997 | inline |
998 | ipa_argagg_value_list::ipa_argagg_value_list (const ipcp_transformation *tinfo) |
999 | : m_elts (tinfo->m_agg_values) |
1000 | {} |
1001 | |
1002 | void ipa_set_node_agg_value_chain (struct cgraph_node *node, |
1003 | vec<ipa_argagg_value, va_gc> *aggs); |
1004 | void ipcp_transformation_initialize (void); |
1005 | void ipcp_free_transformation_sum (void); |
1006 | |
1007 | /* ipa_edge_args stores information related to a callsite and particularly its |
1008 | arguments. It can be accessed by the IPA_EDGE_REF macro. */ |
1009 | |
1010 | class GTY((for_user)) ipa_edge_args |
1011 | { |
1012 | public: |
1013 | |
1014 | /* Default constructor. */ |
1015 | ipa_edge_args () : jump_functions (NULL), polymorphic_call_contexts (NULL) |
1016 | {} |
1017 | |
1018 | /* Destructor. */ |
1019 | ~ipa_edge_args () |
1020 | { |
1021 | unsigned int i; |
1022 | ipa_jump_func *jf; |
1023 | FOR_EACH_VEC_SAFE_ELT (jump_functions, i, jf) |
1024 | vec_free (v&: jf->agg.items); |
1025 | vec_free (v&: jump_functions); |
1026 | vec_free (v&: polymorphic_call_contexts); |
1027 | } |
1028 | |
1029 | /* Vectors of the callsite's jump function and polymorphic context |
1030 | information of each parameter. */ |
1031 | vec<ipa_jump_func, va_gc> *jump_functions; |
1032 | vec<ipa_polymorphic_call_context, va_gc> *polymorphic_call_contexts; |
1033 | }; |
1034 | |
1035 | /* ipa_edge_args access functions. Please use these to access fields that |
1036 | are or will be shared among various passes. */ |
1037 | |
1038 | /* Return the number of actual arguments. */ |
1039 | |
1040 | inline int |
1041 | ipa_get_cs_argument_count (class ipa_edge_args *args) |
1042 | { |
1043 | return vec_safe_length (v: args->jump_functions); |
1044 | } |
1045 | |
1046 | /* Returns a pointer to the jump function for the ith argument. Please note |
1047 | there is no setter function as jump functions are all set up in |
1048 | ipa_compute_jump_functions. */ |
1049 | |
1050 | inline struct ipa_jump_func * |
1051 | ipa_get_ith_jump_func (class ipa_edge_args *args, int i) |
1052 | { |
1053 | return &(*args->jump_functions)[i]; |
1054 | } |
1055 | |
1056 | /* Returns a pointer to the polymorphic call context for the ith argument. |
1057 | NULL if contexts are not computed. */ |
1058 | inline class ipa_polymorphic_call_context * |
1059 | ipa_get_ith_polymorhic_call_context (class ipa_edge_args *args, int i) |
1060 | { |
1061 | if (!args->polymorphic_call_contexts) |
1062 | return NULL; |
1063 | return &(*args->polymorphic_call_contexts)[i]; |
1064 | } |
1065 | |
1066 | /* Function summary for ipa_node_params. */ |
1067 | class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *> |
1068 | { |
1069 | public: |
1070 | ipa_node_params_t (symbol_table *table, bool ggc): |
1071 | function_summary<ipa_node_params *> (table, ggc) |
1072 | { |
1073 | disable_insertion_hook (); |
1074 | } |
1075 | |
1076 | /* Hook that is called by summary when a node is duplicated. */ |
1077 | void duplicate (cgraph_node *node, |
1078 | cgraph_node *node2, |
1079 | ipa_node_params *data, |
1080 | ipa_node_params *data2) final override; |
1081 | }; |
1082 | |
1083 | /* Summary to manange ipa_edge_args structures. */ |
1084 | |
1085 | class GTY((user)) ipa_edge_args_sum_t : public call_summary <ipa_edge_args *> |
1086 | { |
1087 | public: |
1088 | ipa_edge_args_sum_t (symbol_table *table, bool ggc) |
1089 | : call_summary<ipa_edge_args *> (table, ggc) { } |
1090 | |
1091 | void remove (cgraph_edge *edge) |
1092 | { |
1093 | call_summary <ipa_edge_args *>::remove (edge); |
1094 | } |
1095 | |
1096 | /* Hook that is called by summary when an edge is removed. */ |
1097 | void remove (cgraph_edge *cs, ipa_edge_args *args) final override; |
1098 | /* Hook that is called by summary when an edge is duplicated. */ |
1099 | void duplicate (cgraph_edge *src, |
1100 | cgraph_edge *dst, |
1101 | ipa_edge_args *old_args, |
1102 | ipa_edge_args *new_args) final override; |
1103 | }; |
1104 | |
1105 | /* Function summary where the parameter infos are actually stored. */ |
1106 | extern GTY(()) ipa_node_params_t * ipa_node_params_sum; |
1107 | /* Call summary to store information about edges such as jump functions. */ |
1108 | extern GTY(()) ipa_edge_args_sum_t *ipa_edge_args_sum; |
1109 | |
1110 | /* Function summary for IPA-CP transformation. */ |
1111 | class ipcp_transformation_t |
1112 | : public function_summary<ipcp_transformation *> |
1113 | { |
1114 | public: |
1115 | ipcp_transformation_t (symbol_table *table, bool ggc): |
1116 | function_summary<ipcp_transformation *> (table, ggc) {} |
1117 | |
1118 | ~ipcp_transformation_t () {} |
1119 | |
1120 | static ipcp_transformation_t *create_ggc (symbol_table *symtab) |
1121 | { |
1122 | ipcp_transformation_t *summary |
1123 | = new (ggc_alloc_no_dtor <ipcp_transformation_t> ()) |
1124 | ipcp_transformation_t (symtab, true); |
1125 | return summary; |
1126 | } |
1127 | /* Hook that is called by summary when a node is duplicated. */ |
1128 | void duplicate (cgraph_node *node, |
1129 | cgraph_node *node2, |
1130 | ipcp_transformation *data, |
1131 | ipcp_transformation *data2) final override; |
1132 | }; |
1133 | |
1134 | /* Function summary where the IPA CP transformations are actually stored. */ |
1135 | extern GTY(()) function_summary <ipcp_transformation *> *ipcp_transformation_sum; |
1136 | |
1137 | /* Creating and freeing ipa_node_params and ipa_edge_args. */ |
1138 | void ipa_create_all_node_params (void); |
1139 | void ipa_create_all_edge_args (void); |
1140 | void ipa_check_create_edge_args (void); |
1141 | void ipa_free_all_node_params (void); |
1142 | void ipa_free_all_edge_args (void); |
1143 | void ipa_free_all_structures_after_ipa_cp (void); |
1144 | void ipa_free_all_structures_after_iinln (void); |
1145 | |
1146 | void ipa_register_cgraph_hooks (void); |
1147 | int count_formal_params (tree fndecl); |
1148 | |
1149 | /* This function ensures the array of node param infos is big enough to |
1150 | accommodate a structure for all nodes and reallocates it if not. */ |
1151 | |
1152 | inline void |
1153 | ipa_check_create_node_params (void) |
1154 | { |
1155 | if (!ipa_node_params_sum) |
1156 | ipa_node_params_sum |
1157 | = (new (ggc_alloc_no_dtor <ipa_node_params_t> ()) |
1158 | ipa_node_params_t (symtab, true)); |
1159 | } |
1160 | |
1161 | /* Returns true if edge summary contains a record for EDGE. The main purpose |
1162 | of this function is that debug dumping function can check info availability |
1163 | without causing allocations. */ |
1164 | |
1165 | inline bool |
1166 | ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge) |
1167 | { |
1168 | return ipa_edge_args_sum->exists (edge); |
1169 | } |
1170 | |
1171 | inline ipcp_transformation * |
1172 | ipcp_get_transformation_summary (cgraph_node *node) |
1173 | { |
1174 | if (ipcp_transformation_sum == NULL) |
1175 | return NULL; |
1176 | |
1177 | return ipcp_transformation_sum->get (node); |
1178 | } |
1179 | |
1180 | /* Function formal parameters related computations. */ |
1181 | void ipa_initialize_node_params (struct cgraph_node *node); |
1182 | bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, |
1183 | vec<cgraph_edge *> *new_edges); |
1184 | |
1185 | /* Indirect edge processing and target discovery. */ |
1186 | tree ipa_get_indirect_edge_target (struct cgraph_edge *ie, |
1187 | ipa_call_arg_values *avals, |
1188 | bool *speculative); |
1189 | struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree, |
1190 | bool speculative = false); |
1191 | tree ipa_impossible_devirt_target (struct cgraph_edge *, tree); |
1192 | |
1193 | |
1194 | /* Functions related to both. */ |
1195 | void ipa_analyze_node (struct cgraph_node *); |
1196 | |
1197 | /* Aggregate jump function related functions. */ |
1198 | tree ipa_find_agg_cst_from_init (tree scalar, HOST_WIDE_INT offset, |
1199 | bool by_ref); |
1200 | bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, |
1201 | vec<ipa_param_descriptor, va_gc> *descriptors, |
1202 | gimple *stmt, tree op, int *index_p, |
1203 | HOST_WIDE_INT *offset_p, poly_int64 *size_p, |
1204 | bool *by_ref, bool *guaranteed_unmodified = NULL); |
1205 | |
1206 | /* Debugging interface. */ |
1207 | void ipa_print_node_params (FILE *, struct cgraph_node *node); |
1208 | void ipa_print_all_params (FILE *); |
1209 | void ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node); |
1210 | void ipa_print_all_jump_functions (FILE * f); |
1211 | void ipcp_verify_propagated_values (void); |
1212 | |
1213 | template <typename value> |
1214 | class ipcp_value; |
1215 | |
1216 | extern object_allocator<ipcp_value<tree> > ipcp_cst_values_pool; |
1217 | extern object_allocator<ipcp_value<ipa_polymorphic_call_context> > |
1218 | ipcp_poly_ctx_values_pool; |
1219 | |
1220 | template <typename valtype> |
1221 | struct ipcp_value_source; |
1222 | |
1223 | extern object_allocator<ipcp_value_source<tree> > ipcp_sources_pool; |
1224 | |
1225 | struct ipcp_agg_lattice; |
1226 | |
1227 | extern object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool; |
1228 | |
1229 | void ipa_prop_write_jump_functions (void); |
1230 | void ipa_prop_read_jump_functions (void); |
1231 | void ipcp_write_transformation_summaries (void); |
1232 | void ipcp_read_transformation_summaries (void); |
1233 | int ipa_get_param_decl_index (class ipa_node_params *, tree); |
1234 | tree ipa_value_from_jfunc (class ipa_node_params *info, |
1235 | struct ipa_jump_func *jfunc, tree type); |
1236 | tree ipa_agg_value_from_jfunc (ipa_node_params *info, cgraph_node *node, |
1237 | const ipa_agg_jf_item *item); |
1238 | unsigned int ipcp_transform_function (struct cgraph_node *node); |
1239 | ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *, |
1240 | cgraph_edge *, |
1241 | int, |
1242 | ipa_jump_func *); |
1243 | void ipa_value_range_from_jfunc (vrange &, ipa_node_params *, cgraph_edge *, |
1244 | ipa_jump_func *, tree); |
1245 | void ipa_push_agg_values_from_jfunc (ipa_node_params *info, cgraph_node *node, |
1246 | ipa_agg_jump_function *agg_jfunc, |
1247 | unsigned dst_index, |
1248 | vec<ipa_argagg_value> *res); |
1249 | void ipa_dump_param (FILE *, class ipa_node_params *info, int i); |
1250 | void ipa_release_body_info (struct ipa_func_body_info *); |
1251 | tree ipa_get_callee_param_type (struct cgraph_edge *e, int i); |
1252 | bool ipcp_get_parm_bits (tree, tree *, widest_int *); |
1253 | tree ipcp_get_aggregate_const (struct function *func, tree parm, bool by_ref, |
1254 | HOST_WIDE_INT bit_offset, |
1255 | HOST_WIDE_INT bit_size); |
1256 | bool unadjusted_ptr_and_unit_offset (tree op, tree *ret, |
1257 | poly_int64 *offset_ret); |
1258 | |
1259 | void ipa_prop_cc_finalize (void); |
1260 | |
1261 | /* From tree-sra.cc: */ |
1262 | tree build_ref_for_offset (location_t, tree, poly_int64, bool, tree, |
1263 | gimple_stmt_iterator *, bool); |
1264 | |
1265 | /* In ipa-cp.cc */ |
1266 | void ipa_cp_cc_finalize (void); |
1267 | |
1268 | /* Set R to the range of [VAL, VAL] while normalizing addresses to |
1269 | non-zero. */ |
1270 | |
1271 | inline void |
1272 | ipa_range_set_and_normalize (vrange &r, tree val) |
1273 | { |
1274 | if (TREE_CODE (val) == ADDR_EXPR) |
1275 | r.set_nonzero (TREE_TYPE (val)); |
1276 | else |
1277 | r.set (val, val); |
1278 | } |
1279 | |
1280 | bool ipa_return_value_range (Value_Range &range, tree decl); |
1281 | void ipa_record_return_value_range (Value_Range val); |
1282 | bool ipa_jump_functions_equivalent_p (ipa_jump_func *jf1, ipa_jump_func *jf2); |
1283 | |
1284 | |
1285 | #endif /* IPA_PROP_H */ |
1286 | |