1 | /* Interprocedural analyses. |
2 | Copyright (C) 2005-2023 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 | const vrange_storage *storage () const { return m_storage; } |
312 | void streamer_read (lto_input_block *, data_in *); |
313 | void streamer_write (output_block *) const; |
314 | void dump (FILE *) const; |
315 | |
316 | private: |
317 | friend void gt_pch_nx (struct ipa_vr &); |
318 | friend void gt_ggc_mx (struct ipa_vr &); |
319 | friend void gt_pch_nx (struct ipa_vr *, gt_pointer_operator, void *); |
320 | friend void gt_ggc_mx_ipa_vr (void *); |
321 | friend void gt_pch_nx_ipa_vr (void*); |
322 | friend void gt_pch_p_6ipa_vr(void*, void*, gt_pointer_operator, void*); |
323 | |
324 | vrange_storage *m_storage; |
325 | tree m_type; |
326 | }; |
327 | |
328 | /* A jump function for a callsite represents the values passed as actual |
329 | arguments of the callsite. See enum jump_func_type for the various |
330 | types of jump functions supported. */ |
331 | struct GTY (()) ipa_jump_func |
332 | { |
333 | /* Aggregate jump function description. See struct ipa_agg_jump_function |
334 | and its description. */ |
335 | struct ipa_agg_jump_function agg; |
336 | |
337 | /* Information about value range, containing valid data only when vr_known is |
338 | true. The pointed to structure is shared betweed different jump |
339 | functions. Use ipa_set_jfunc_vr to set this field. */ |
340 | ipa_vr *m_vr; |
341 | |
342 | enum jump_func_type type; |
343 | /* Represents a value of a jump function. pass_through is used only in jump |
344 | function context. constant represents the actual constant in constant jump |
345 | functions and member_cst holds constant c++ member functions. */ |
346 | union jump_func_value |
347 | { |
348 | struct ipa_constant_data GTY ((tag ("IPA_JF_CONST" ))) constant; |
349 | struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH" ))) pass_through; |
350 | struct ipa_ancestor_jf_data GTY ((tag ("IPA_JF_ANCESTOR" ))) ancestor; |
351 | } GTY ((desc ("%1.type" ))) value; |
352 | }; |
353 | |
354 | |
355 | /* Return the constant stored in a constant jump functin JFUNC. */ |
356 | |
357 | inline tree |
358 | ipa_get_jf_constant (struct ipa_jump_func *jfunc) |
359 | { |
360 | gcc_checking_assert (jfunc->type == IPA_JF_CONST); |
361 | return jfunc->value.constant.value; |
362 | } |
363 | |
364 | inline struct ipa_cst_ref_desc * |
365 | ipa_get_jf_constant_rdesc (struct ipa_jump_func *jfunc) |
366 | { |
367 | gcc_checking_assert (jfunc->type == IPA_JF_CONST); |
368 | return jfunc->value.constant.rdesc; |
369 | } |
370 | |
371 | /* Make JFUNC not participate in any further reference counting. */ |
372 | |
373 | inline void |
374 | ipa_zap_jf_refdesc (ipa_jump_func *jfunc) |
375 | { |
376 | gcc_checking_assert (jfunc->type == IPA_JF_CONST); |
377 | jfunc->value.constant.rdesc = NULL; |
378 | } |
379 | |
380 | /* Return the operand of a pass through jmp function JFUNC. */ |
381 | |
382 | inline tree |
383 | ipa_get_jf_pass_through_operand (struct ipa_jump_func *jfunc) |
384 | { |
385 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
386 | return jfunc->value.pass_through.operand; |
387 | } |
388 | |
389 | /* Return the number of the caller's formal parameter that a pass through jump |
390 | function JFUNC refers to. */ |
391 | |
392 | inline int |
393 | ipa_get_jf_pass_through_formal_id (struct ipa_jump_func *jfunc) |
394 | { |
395 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
396 | return jfunc->value.pass_through.formal_id; |
397 | } |
398 | |
399 | /* Return operation of a pass through jump function JFUNC. */ |
400 | |
401 | inline enum tree_code |
402 | ipa_get_jf_pass_through_operation (struct ipa_jump_func *jfunc) |
403 | { |
404 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
405 | return jfunc->value.pass_through.operation; |
406 | } |
407 | |
408 | /* Return the agg_preserved flag of a pass through jump function JFUNC. */ |
409 | |
410 | inline bool |
411 | ipa_get_jf_pass_through_agg_preserved (struct ipa_jump_func *jfunc) |
412 | { |
413 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
414 | return jfunc->value.pass_through.agg_preserved; |
415 | } |
416 | |
417 | /* Return the refdesc_decremented flag of a pass through jump function |
418 | JFUNC. */ |
419 | |
420 | inline bool |
421 | ipa_get_jf_pass_through_refdesc_decremented (struct ipa_jump_func *jfunc) |
422 | { |
423 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
424 | return jfunc->value.pass_through.refdesc_decremented; |
425 | } |
426 | |
427 | /* Set the refdesc_decremented flag of a pass through jump function JFUNC to |
428 | VALUE. */ |
429 | |
430 | inline void |
431 | ipa_set_jf_pass_through_refdesc_decremented (ipa_jump_func *jfunc, bool value) |
432 | { |
433 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
434 | jfunc->value.pass_through.refdesc_decremented = value; |
435 | } |
436 | |
437 | /* Return true if pass through jump function JFUNC preserves type |
438 | information. */ |
439 | |
440 | inline bool |
441 | ipa_get_jf_pass_through_type_preserved (struct ipa_jump_func *jfunc) |
442 | { |
443 | gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH); |
444 | return jfunc->value.pass_through.agg_preserved; |
445 | } |
446 | |
447 | /* Return the offset of an ancestor jump function JFUNC. */ |
448 | |
449 | inline HOST_WIDE_INT |
450 | ipa_get_jf_ancestor_offset (struct ipa_jump_func *jfunc) |
451 | { |
452 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
453 | return jfunc->value.ancestor.offset; |
454 | } |
455 | |
456 | /* Return the number of the caller's formal parameter that an ancestor jump |
457 | function JFUNC refers to. */ |
458 | |
459 | inline int |
460 | ipa_get_jf_ancestor_formal_id (struct ipa_jump_func *jfunc) |
461 | { |
462 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
463 | return jfunc->value.ancestor.formal_id; |
464 | } |
465 | |
466 | /* Return the agg_preserved flag of an ancestor jump function JFUNC. */ |
467 | |
468 | inline bool |
469 | ipa_get_jf_ancestor_agg_preserved (struct ipa_jump_func *jfunc) |
470 | { |
471 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
472 | return jfunc->value.ancestor.agg_preserved; |
473 | } |
474 | |
475 | /* Return true if ancestor jump function JFUNC presrves type information. */ |
476 | |
477 | inline bool |
478 | ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc) |
479 | { |
480 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
481 | return jfunc->value.ancestor.agg_preserved; |
482 | } |
483 | |
484 | /* Return if jfunc represents an operation whether we first check the formal |
485 | parameter for non-NULLness unless it does not matter because the offset is |
486 | zero anyway. */ |
487 | |
488 | inline bool |
489 | ipa_get_jf_ancestor_keep_null (struct ipa_jump_func *jfunc) |
490 | { |
491 | gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR); |
492 | return jfunc->value.ancestor.keep_null; |
493 | } |
494 | |
495 | /* Class for allocating a bundle of various potentially known properties about |
496 | actual arguments of a particular call on stack for the usual case and on |
497 | heap only if there are unusually many arguments. The data is deallocated |
498 | when the instance of this class goes out of scope or is otherwise |
499 | destructed. */ |
500 | |
501 | class ipa_auto_call_arg_values |
502 | { |
503 | public: |
504 | /* If m_known_vals (vector of known "scalar" values) is sufficiantly long, |
505 | return its element at INDEX, otherwise return NULL. */ |
506 | tree safe_sval_at (int index) |
507 | { |
508 | if ((unsigned) index < m_known_vals.length ()) |
509 | return m_known_vals[index]; |
510 | return NULL; |
511 | } |
512 | |
513 | /* Vector describing known values of parameters. */ |
514 | auto_vec<tree, 32> m_known_vals; |
515 | |
516 | /* Vector describing known polymorphic call contexts. */ |
517 | auto_vec<ipa_polymorphic_call_context, 32> m_known_contexts; |
518 | |
519 | /* Vector describing known aggregate values. */ |
520 | auto_vec<ipa_argagg_value, 32> m_known_aggs; |
521 | |
522 | /* Vector describing known value ranges of arguments. */ |
523 | auto_vec<Value_Range, 32> m_known_value_ranges; |
524 | }; |
525 | |
526 | inline |
527 | ipa_argagg_value_list |
528 | ::ipa_argagg_value_list (const ipa_auto_call_arg_values *aavals) |
529 | : m_elts (aavals->m_known_aggs) |
530 | {} |
531 | |
532 | /* Class bundling the various potentially known properties about actual |
533 | arguments of a particular call. This variant does not deallocate the |
534 | bundled data in any way as the vectors can either be pointing to vectors in |
535 | ipa_auto_call_arg_values or be allocated independently. */ |
536 | |
537 | class ipa_call_arg_values |
538 | { |
539 | public: |
540 | /* Default constructor, setting the vectors to empty ones. */ |
541 | ipa_call_arg_values () |
542 | {} |
543 | |
544 | /* Construct this general variant of the bundle from the variant which uses |
545 | auto_vecs to hold the vectors. This means that vectors of objects |
546 | constructed with this constructor should not be changed because if they |
547 | get reallocated, the member vectors and the underlying auto_vecs would get |
548 | out of sync. */ |
549 | ipa_call_arg_values (ipa_auto_call_arg_values *aavals) |
550 | : m_known_vals (aavals->m_known_vals.to_vec_legacy ()), |
551 | m_known_contexts (aavals->m_known_contexts.to_vec_legacy ()), |
552 | m_known_aggs (aavals->m_known_aggs.to_vec_legacy ()), |
553 | m_known_value_ranges (aavals->m_known_value_ranges.to_vec_legacy ()) |
554 | {} |
555 | |
556 | /* If m_known_vals (vector of known "scalar" values) is sufficiantly long, |
557 | return its element at INDEX, otherwise return NULL. */ |
558 | tree safe_sval_at (int index) |
559 | { |
560 | if ((unsigned) index < m_known_vals.length ()) |
561 | return m_known_vals[index]; |
562 | return NULL; |
563 | } |
564 | |
565 | /* Vector describing known values of parameters. */ |
566 | vec<tree> m_known_vals = vNULL; |
567 | |
568 | /* Vector describing known polymorphic call contexts. */ |
569 | vec<ipa_polymorphic_call_context> m_known_contexts = vNULL; |
570 | |
571 | /* Vector describing known aggregate values. */ |
572 | vec<ipa_argagg_value> m_known_aggs = vNULL; |
573 | |
574 | /* Vector describing known value ranges of arguments. */ |
575 | vec<Value_Range> m_known_value_ranges = vNULL; |
576 | }; |
577 | |
578 | inline |
579 | ipa_argagg_value_list |
580 | ::ipa_argagg_value_list (const ipa_call_arg_values *gavals) |
581 | : m_elts (gavals->m_known_aggs) |
582 | {} |
583 | |
584 | /* Summary describing a single formal parameter. */ |
585 | |
586 | struct GTY(()) ipa_param_descriptor |
587 | { |
588 | /* In analysis and modification phase, this is the PARAM_DECL of this |
589 | parameter, in IPA LTO phase, this is the type of the described |
590 | parameter or NULL if not known. Do not read this field directly but |
591 | through ipa_get_param and ipa_get_type as appropriate. */ |
592 | tree decl_or_type; |
593 | /* If all uses of the parameter are described by ipa-prop structures, this |
594 | says how many there are. If any use could not be described by means of |
595 | ipa-prop structures (which include flag dereferenced below), this is |
596 | IPA_UNDESCRIBED_USE. */ |
597 | int controlled_uses; |
598 | unsigned int move_cost : 27; |
599 | /* The parameter is used. */ |
600 | unsigned used : 1; |
601 | unsigned used_by_ipa_predicates : 1; |
602 | unsigned used_by_indirect_call : 1; |
603 | unsigned used_by_polymorphic_call : 1; |
604 | /* Set to true when in addition to being used in call statements, the |
605 | parameter has also been used for loads (but not for writes, does not |
606 | escape, etc.). This allows us to identify parameters p which are only |
607 | used as *p, and so when we propagate a constant to them, we can generate a |
608 | LOAD and not ADDR reference to them. */ |
609 | unsigned load_dereferenced : 1; |
610 | }; |
611 | |
612 | /* ipa_node_params stores information related to formal parameters of functions |
613 | and some other information for interprocedural passes that operate on |
614 | parameters (such as ipa-cp). */ |
615 | |
616 | class GTY((for_user)) ipa_node_params |
617 | { |
618 | public: |
619 | /* Default constructor. */ |
620 | ipa_node_params (); |
621 | |
622 | /* Default destructor. */ |
623 | ~ipa_node_params (); |
624 | |
625 | /* Information about individual formal parameters that are gathered when |
626 | summaries are generated. */ |
627 | vec<ipa_param_descriptor, va_gc> *descriptors; |
628 | /* Pointer to an array of structures describing individual formal |
629 | parameters. */ |
630 | class ipcp_param_lattices * GTY((skip)) lattices; |
631 | /* Only for versioned nodes this field would not be NULL, |
632 | it points to the node that IPA cp cloned from. */ |
633 | struct cgraph_node * GTY((skip)) ipcp_orig_node; |
634 | /* If this node is an ipa-cp clone, these are the known constants that |
635 | describe what it has been specialized for. */ |
636 | vec<tree> GTY((skip)) known_csts; |
637 | /* If this node is an ipa-cp clone, these are the known polymorphic contexts |
638 | that describe what it has been specialized for. */ |
639 | vec<ipa_polymorphic_call_context> GTY((skip)) known_contexts; |
640 | /* Whether the param uses analysis and jump function computation has already |
641 | been performed. */ |
642 | unsigned analysis_done : 1; |
643 | /* Whether the function is enqueued in ipa-cp propagation stack. */ |
644 | unsigned node_enqueued : 1; |
645 | /* Whether we should create a specialized version based on values that are |
646 | known to be constant in all contexts. */ |
647 | unsigned do_clone_for_all_contexts : 1; |
648 | /* Set if this is an IPA-CP clone for all contexts. */ |
649 | unsigned is_all_contexts_clone : 1; |
650 | /* Node has been completely replaced by clones and will be removed after |
651 | ipa-cp is finished. */ |
652 | unsigned node_dead : 1; |
653 | /* Node is involved in a recursion, potentionally indirect. */ |
654 | unsigned node_within_scc : 1; |
655 | /* Node contains only direct recursion. */ |
656 | unsigned node_is_self_scc : 1; |
657 | /* Node is calling a private function called only once. */ |
658 | unsigned node_calling_single_call : 1; |
659 | /* False when there is something makes versioning impossible. */ |
660 | unsigned versionable : 1; |
661 | }; |
662 | |
663 | inline |
664 | ipa_node_params::ipa_node_params () |
665 | : descriptors (NULL), lattices (NULL), ipcp_orig_node (NULL), |
666 | known_csts (vNULL), known_contexts (vNULL), analysis_done (0), |
667 | node_enqueued (0), do_clone_for_all_contexts (0), is_all_contexts_clone (0), |
668 | node_dead (0), node_within_scc (0), node_is_self_scc (0), |
669 | node_calling_single_call (0), versionable (0) |
670 | { |
671 | } |
672 | |
673 | inline |
674 | ipa_node_params::~ipa_node_params () |
675 | { |
676 | free (ptr: lattices); |
677 | vec_free (v&: descriptors); |
678 | known_csts.release (); |
679 | known_contexts.release (); |
680 | } |
681 | |
682 | /* Intermediate information that we get from alias analysis about a particular |
683 | parameter in a particular basic_block. When a parameter or the memory it |
684 | references is marked modified, we use that information in all dominated |
685 | blocks without consulting alias analysis oracle. */ |
686 | |
687 | struct ipa_param_aa_status |
688 | { |
689 | /* Set when this structure contains meaningful information. If not, the |
690 | structure describing a dominating BB should be used instead. */ |
691 | bool valid; |
692 | |
693 | /* Whether we have seen something which might have modified the data in |
694 | question. PARM is for the parameter itself, REF is for data it points to |
695 | but using the alias type of individual accesses and PT is the same thing |
696 | but for computing aggregate pass-through functions using a very inclusive |
697 | ao_ref. */ |
698 | bool parm_modified, ref_modified, pt_modified; |
699 | }; |
700 | |
701 | /* Information related to a given BB that used only when looking at function |
702 | body. */ |
703 | |
704 | struct ipa_bb_info |
705 | { |
706 | /* Call graph edges going out of this BB. */ |
707 | vec<cgraph_edge *> cg_edges; |
708 | /* Alias analysis statuses of each formal parameter at this bb. */ |
709 | vec<ipa_param_aa_status> param_aa_statuses; |
710 | }; |
711 | |
712 | /* Structure with global information that is only used when looking at function |
713 | body. */ |
714 | |
715 | struct ipa_func_body_info |
716 | { |
717 | /* The node that is being analyzed. */ |
718 | cgraph_node *node; |
719 | |
720 | /* Its info. */ |
721 | class ipa_node_params *info; |
722 | |
723 | /* Information about individual BBs. */ |
724 | vec<ipa_bb_info> bb_infos; |
725 | |
726 | /* Number of parameters. */ |
727 | int param_count; |
728 | |
729 | /* Number of statements we are still allowed to walked by when analyzing this |
730 | function. */ |
731 | unsigned int aa_walk_budget; |
732 | }; |
733 | |
734 | /* ipa_node_params access functions. Please use these to access fields that |
735 | are or will be shared among various passes. */ |
736 | |
737 | /* Return the number of formal parameters. */ |
738 | |
739 | inline int |
740 | ipa_get_param_count (class ipa_node_params *info) |
741 | { |
742 | return vec_safe_length (v: info->descriptors); |
743 | } |
744 | |
745 | /* Return the parameter declaration in DESCRIPTORS at index I and assert it is |
746 | indeed a PARM_DECL. */ |
747 | |
748 | inline tree |
749 | ipa_get_param (const vec<ipa_param_descriptor, va_gc> &descriptors, int i) |
750 | { |
751 | tree t = descriptors[i].decl_or_type; |
752 | gcc_checking_assert (TREE_CODE (t) == PARM_DECL); |
753 | return t; |
754 | } |
755 | |
756 | /* Return the declaration of Ith formal parameter of the function corresponding |
757 | to INFO. Note there is no setter function as this array is built just once |
758 | using ipa_initialize_node_params. This function should not be called in |
759 | WPA. */ |
760 | |
761 | inline tree |
762 | ipa_get_param (class ipa_node_params *info, int i) |
763 | { |
764 | gcc_checking_assert (info->descriptors); |
765 | return ipa_get_param (descriptors: *info->descriptors, i); |
766 | } |
767 | |
768 | /* Return the type of Ith formal parameter of the function corresponding |
769 | to INFO if it is known or NULL if not. */ |
770 | |
771 | inline tree |
772 | ipa_get_type (class ipa_node_params *info, int i) |
773 | { |
774 | if (vec_safe_length (v: info->descriptors) <= (unsigned) i) |
775 | return NULL; |
776 | tree t = (*info->descriptors)[i].decl_or_type; |
777 | if (!t) |
778 | return NULL; |
779 | if (TYPE_P (t)) |
780 | return t; |
781 | gcc_checking_assert (TREE_CODE (t) == PARM_DECL); |
782 | return TREE_TYPE (t); |
783 | } |
784 | |
785 | /* Return the move cost of Ith formal parameter of the function corresponding |
786 | to INFO. */ |
787 | |
788 | inline int |
789 | ipa_get_param_move_cost (class ipa_node_params *info, int i) |
790 | { |
791 | gcc_checking_assert (info->descriptors); |
792 | return (*info->descriptors)[i].move_cost; |
793 | } |
794 | |
795 | /* Set the used flag corresponding to the Ith formal parameter of the function |
796 | associated with INFO to VAL. */ |
797 | |
798 | inline void |
799 | ipa_set_param_used (class ipa_node_params *info, int i, bool val) |
800 | { |
801 | gcc_checking_assert (info->descriptors); |
802 | (*info->descriptors)[i].used = val; |
803 | } |
804 | |
805 | /* Set the used_by_ipa_predicates flag corresponding to the Ith formal |
806 | parameter of the function associated with INFO to VAL. */ |
807 | |
808 | inline void |
809 | ipa_set_param_used_by_ipa_predicates (class ipa_node_params *info, int i, bool val) |
810 | { |
811 | gcc_checking_assert (info->descriptors); |
812 | (*info->descriptors)[i].used_by_ipa_predicates = val; |
813 | } |
814 | |
815 | /* Set the used_by_indirect_call flag corresponding to the Ith formal |
816 | parameter of the function associated with INFO to VAL. */ |
817 | |
818 | inline void |
819 | ipa_set_param_used_by_indirect_call (class ipa_node_params *info, int i, bool val) |
820 | { |
821 | gcc_checking_assert (info->descriptors); |
822 | (*info->descriptors)[i].used_by_indirect_call = val; |
823 | } |
824 | |
825 | /* Set the .used_by_polymorphic_call flag corresponding to the Ith formal |
826 | parameter of the function associated with INFO to VAL. */ |
827 | |
828 | inline void |
829 | ipa_set_param_used_by_polymorphic_call (class ipa_node_params *info, int i, bool val) |
830 | { |
831 | gcc_checking_assert (info->descriptors); |
832 | (*info->descriptors)[i].used_by_polymorphic_call = val; |
833 | } |
834 | |
835 | /* Return how many uses described by ipa-prop a parameter has or |
836 | IPA_UNDESCRIBED_USE if there is a use that is not described by these |
837 | structures. */ |
838 | inline int |
839 | ipa_get_controlled_uses (class ipa_node_params *info, int i) |
840 | { |
841 | /* FIXME: introducing speculation causes out of bounds access here. */ |
842 | if (vec_safe_length (v: info->descriptors) > (unsigned)i) |
843 | return (*info->descriptors)[i].controlled_uses; |
844 | return IPA_UNDESCRIBED_USE; |
845 | } |
846 | |
847 | /* Set the controlled counter of a given parameter. */ |
848 | |
849 | inline void |
850 | ipa_set_controlled_uses (class ipa_node_params *info, int i, int val) |
851 | { |
852 | gcc_checking_assert (info->descriptors); |
853 | (*info->descriptors)[i].controlled_uses = val; |
854 | } |
855 | |
856 | /* Assuming a parameter does not have IPA_UNDESCRIBED_USE controlled uses, |
857 | return flag which indicates it has been dereferenced but only in a load. */ |
858 | inline int |
859 | ipa_get_param_load_dereferenced (class ipa_node_params *info, int i) |
860 | { |
861 | gcc_assert (ipa_get_controlled_uses (info, i) != IPA_UNDESCRIBED_USE); |
862 | return (*info->descriptors)[i].load_dereferenced; |
863 | } |
864 | |
865 | /* Set the load_dereferenced flag of a given parameter. */ |
866 | |
867 | inline void |
868 | ipa_set_param_load_dereferenced (class ipa_node_params *info, int i, bool val) |
869 | { |
870 | gcc_checking_assert (info->descriptors); |
871 | (*info->descriptors)[i].load_dereferenced = val; |
872 | } |
873 | |
874 | /* Return the used flag corresponding to the Ith formal parameter of the |
875 | function associated with INFO. */ |
876 | |
877 | inline bool |
878 | ipa_is_param_used (class ipa_node_params *info, int i) |
879 | { |
880 | gcc_checking_assert (info->descriptors); |
881 | return (*info->descriptors)[i].used; |
882 | } |
883 | |
884 | /* Return the used_by_ipa_predicates flag corresponding to the Ith formal |
885 | parameter of the function associated with INFO. */ |
886 | |
887 | inline bool |
888 | ipa_is_param_used_by_ipa_predicates (class ipa_node_params *info, int i) |
889 | { |
890 | gcc_checking_assert (info->descriptors); |
891 | return (*info->descriptors)[i].used_by_ipa_predicates; |
892 | } |
893 | |
894 | /* Return the used_by_indirect_call flag corresponding to the Ith formal |
895 | parameter of the function associated with INFO. */ |
896 | |
897 | inline bool |
898 | ipa_is_param_used_by_indirect_call (class ipa_node_params *info, int i) |
899 | { |
900 | gcc_checking_assert (info->descriptors); |
901 | return (*info->descriptors)[i].used_by_indirect_call; |
902 | } |
903 | |
904 | /* Return the used_by_polymorphic_call flag corresponding to the Ith formal |
905 | parameter of the function associated with INFO. */ |
906 | |
907 | inline bool |
908 | ipa_is_param_used_by_polymorphic_call (class ipa_node_params *info, int i) |
909 | { |
910 | gcc_checking_assert (info->descriptors); |
911 | return (*info->descriptors)[i].used_by_polymorphic_call; |
912 | } |
913 | |
914 | /* GTY-marked structure used to map DECL_UIDs of APRAMs to their indices in |
915 | their DECL_ARGUMENTs chain. */ |
916 | struct GTY(()) ipa_uid_to_idx_map_elt |
917 | { |
918 | /* DECL_UID of the PARAM. */ |
919 | unsigned uid; |
920 | /* Its index in the DECL_ARGUMETs chain. */ |
921 | unsigned index; |
922 | }; |
923 | |
924 | /* Structure holding information for the transformation phase of IPA-CP. */ |
925 | |
926 | struct GTY(()) ipcp_transformation |
927 | { |
928 | /* Default constructor. */ |
929 | ipcp_transformation () |
930 | : m_agg_values (nullptr), m_vr (nullptr), m_uid_to_idx (nullptr) |
931 | { } |
932 | |
933 | /* Default destructor. */ |
934 | ~ipcp_transformation () |
935 | { |
936 | vec_free (v&: m_agg_values); |
937 | vec_free (v&: m_vr); |
938 | } |
939 | |
940 | /* Given PARAM which must be a parameter of function FNDECL described by |
941 | THIS, return its index in the DECL_ARGUMENTS chain, using a pre-computed |
942 | DECL_UID-sorted vector if available (which is pre-computed only if there |
943 | are many parameters). Can return -1 if param is static chain not |
944 | represented among DECL_ARGUMENTS. */ |
945 | |
946 | int get_param_index (const_tree fndecl, const_tree param) const; |
947 | |
948 | /* Assuming THIS describes FNDECL and it has sufficiently many parameters to |
949 | justify the overhead, create a DECL_UID-sorted vector to speed up mapping |
950 | from parameters to their indices in DECL_ARGUMENTS chain. */ |
951 | |
952 | void maybe_create_parm_idx_map (tree fndecl); |
953 | |
954 | /* Remove all elements in m_agg_values on which PREDICATE returns true. */ |
955 | |
956 | template<typename pred_function> |
957 | void remove_argaggs_if (pred_function &&predicate) |
958 | { |
959 | unsigned ts_len = vec_safe_length (v: m_agg_values); |
960 | if (ts_len == 0) |
961 | return; |
962 | |
963 | bool removed_item = false; |
964 | unsigned dst_index = 0; |
965 | |
966 | for (unsigned i = 0; i < ts_len; i++) |
967 | { |
968 | ipa_argagg_value *v = &(*m_agg_values)[i]; |
969 | if (!predicate (*v)) |
970 | { |
971 | if (removed_item) |
972 | (*m_agg_values)[dst_index] = *v; |
973 | dst_index++; |
974 | } |
975 | else |
976 | removed_item = true; |
977 | } |
978 | if (dst_index == 0) |
979 | { |
980 | ggc_free (m_agg_values); |
981 | m_agg_values = NULL; |
982 | } |
983 | else if (removed_item) |
984 | m_agg_values->truncate (dst_index); |
985 | } |
986 | |
987 | /* Known aggregate values. */ |
988 | vec<ipa_argagg_value, va_gc> *m_agg_values; |
989 | /* Value range information. */ |
990 | vec<ipa_vr, va_gc> *m_vr; |
991 | /* If there are many parameters, this is a vector sorted by their DECL_UIDs |
992 | to map them to their indices in the DECL_ARGUMENT chain. */ |
993 | vec<ipa_uid_to_idx_map_elt, va_gc> *m_uid_to_idx; |
994 | }; |
995 | |
996 | inline |
997 | ipa_argagg_value_list::ipa_argagg_value_list (const ipcp_transformation *tinfo) |
998 | : m_elts (tinfo->m_agg_values) |
999 | {} |
1000 | |
1001 | void ipa_set_node_agg_value_chain (struct cgraph_node *node, |
1002 | vec<ipa_argagg_value, va_gc> *aggs); |
1003 | void ipcp_transformation_initialize (void); |
1004 | void ipcp_free_transformation_sum (void); |
1005 | |
1006 | /* ipa_edge_args stores information related to a callsite and particularly its |
1007 | arguments. It can be accessed by the IPA_EDGE_REF macro. */ |
1008 | |
1009 | class GTY((for_user)) ipa_edge_args |
1010 | { |
1011 | public: |
1012 | |
1013 | /* Default constructor. */ |
1014 | ipa_edge_args () : jump_functions (NULL), polymorphic_call_contexts (NULL) |
1015 | {} |
1016 | |
1017 | /* Destructor. */ |
1018 | ~ipa_edge_args () |
1019 | { |
1020 | unsigned int i; |
1021 | ipa_jump_func *jf; |
1022 | FOR_EACH_VEC_SAFE_ELT (jump_functions, i, jf) |
1023 | vec_free (v&: jf->agg.items); |
1024 | vec_free (v&: jump_functions); |
1025 | vec_free (v&: polymorphic_call_contexts); |
1026 | } |
1027 | |
1028 | /* Vectors of the callsite's jump function and polymorphic context |
1029 | information of each parameter. */ |
1030 | vec<ipa_jump_func, va_gc> *jump_functions; |
1031 | vec<ipa_polymorphic_call_context, va_gc> *polymorphic_call_contexts; |
1032 | }; |
1033 | |
1034 | /* ipa_edge_args access functions. Please use these to access fields that |
1035 | are or will be shared among various passes. */ |
1036 | |
1037 | /* Return the number of actual arguments. */ |
1038 | |
1039 | inline int |
1040 | ipa_get_cs_argument_count (class ipa_edge_args *args) |
1041 | { |
1042 | return vec_safe_length (v: args->jump_functions); |
1043 | } |
1044 | |
1045 | /* Returns a pointer to the jump function for the ith argument. Please note |
1046 | there is no setter function as jump functions are all set up in |
1047 | ipa_compute_jump_functions. */ |
1048 | |
1049 | inline struct ipa_jump_func * |
1050 | ipa_get_ith_jump_func (class ipa_edge_args *args, int i) |
1051 | { |
1052 | return &(*args->jump_functions)[i]; |
1053 | } |
1054 | |
1055 | /* Returns a pointer to the polymorphic call context for the ith argument. |
1056 | NULL if contexts are not computed. */ |
1057 | inline class ipa_polymorphic_call_context * |
1058 | ipa_get_ith_polymorhic_call_context (class ipa_edge_args *args, int i) |
1059 | { |
1060 | if (!args->polymorphic_call_contexts) |
1061 | return NULL; |
1062 | return &(*args->polymorphic_call_contexts)[i]; |
1063 | } |
1064 | |
1065 | /* Function summary for ipa_node_params. */ |
1066 | class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *> |
1067 | { |
1068 | public: |
1069 | ipa_node_params_t (symbol_table *table, bool ggc): |
1070 | function_summary<ipa_node_params *> (table, ggc) |
1071 | { |
1072 | disable_insertion_hook (); |
1073 | } |
1074 | |
1075 | /* Hook that is called by summary when a node is duplicated. */ |
1076 | void duplicate (cgraph_node *node, |
1077 | cgraph_node *node2, |
1078 | ipa_node_params *data, |
1079 | ipa_node_params *data2) final override; |
1080 | }; |
1081 | |
1082 | /* Summary to manange ipa_edge_args structures. */ |
1083 | |
1084 | class GTY((user)) ipa_edge_args_sum_t : public call_summary <ipa_edge_args *> |
1085 | { |
1086 | public: |
1087 | ipa_edge_args_sum_t (symbol_table *table, bool ggc) |
1088 | : call_summary<ipa_edge_args *> (table, ggc) { } |
1089 | |
1090 | void remove (cgraph_edge *edge) |
1091 | { |
1092 | call_summary <ipa_edge_args *>::remove (edge); |
1093 | } |
1094 | |
1095 | /* Hook that is called by summary when an edge is removed. */ |
1096 | void remove (cgraph_edge *cs, ipa_edge_args *args) final override; |
1097 | /* Hook that is called by summary when an edge is duplicated. */ |
1098 | void duplicate (cgraph_edge *src, |
1099 | cgraph_edge *dst, |
1100 | ipa_edge_args *old_args, |
1101 | ipa_edge_args *new_args) final override; |
1102 | }; |
1103 | |
1104 | /* Function summary where the parameter infos are actually stored. */ |
1105 | extern GTY(()) ipa_node_params_t * ipa_node_params_sum; |
1106 | /* Call summary to store information about edges such as jump functions. */ |
1107 | extern GTY(()) ipa_edge_args_sum_t *ipa_edge_args_sum; |
1108 | |
1109 | /* Function summary for IPA-CP transformation. */ |
1110 | class ipcp_transformation_t |
1111 | : public function_summary<ipcp_transformation *> |
1112 | { |
1113 | public: |
1114 | ipcp_transformation_t (symbol_table *table, bool ggc): |
1115 | function_summary<ipcp_transformation *> (table, ggc) {} |
1116 | |
1117 | ~ipcp_transformation_t () {} |
1118 | |
1119 | static ipcp_transformation_t *create_ggc (symbol_table *symtab) |
1120 | { |
1121 | ipcp_transformation_t *summary |
1122 | = new (ggc_alloc_no_dtor <ipcp_transformation_t> ()) |
1123 | ipcp_transformation_t (symtab, true); |
1124 | return summary; |
1125 | } |
1126 | /* Hook that is called by summary when a node is duplicated. */ |
1127 | void duplicate (cgraph_node *node, |
1128 | cgraph_node *node2, |
1129 | ipcp_transformation *data, |
1130 | ipcp_transformation *data2) final override; |
1131 | }; |
1132 | |
1133 | /* Function summary where the IPA CP transformations are actually stored. */ |
1134 | extern GTY(()) function_summary <ipcp_transformation *> *ipcp_transformation_sum; |
1135 | |
1136 | /* Creating and freeing ipa_node_params and ipa_edge_args. */ |
1137 | void ipa_create_all_node_params (void); |
1138 | void ipa_create_all_edge_args (void); |
1139 | void ipa_check_create_edge_args (void); |
1140 | void ipa_free_all_node_params (void); |
1141 | void ipa_free_all_edge_args (void); |
1142 | void ipa_free_all_structures_after_ipa_cp (void); |
1143 | void ipa_free_all_structures_after_iinln (void); |
1144 | |
1145 | void ipa_register_cgraph_hooks (void); |
1146 | int count_formal_params (tree fndecl); |
1147 | |
1148 | /* This function ensures the array of node param infos is big enough to |
1149 | accommodate a structure for all nodes and reallocates it if not. */ |
1150 | |
1151 | inline void |
1152 | ipa_check_create_node_params (void) |
1153 | { |
1154 | if (!ipa_node_params_sum) |
1155 | ipa_node_params_sum |
1156 | = (new (ggc_alloc_no_dtor <ipa_node_params_t> ()) |
1157 | ipa_node_params_t (symtab, true)); |
1158 | } |
1159 | |
1160 | /* Returns true if edge summary contains a record for EDGE. The main purpose |
1161 | of this function is that debug dumping function can check info availability |
1162 | without causing allocations. */ |
1163 | |
1164 | inline bool |
1165 | ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge) |
1166 | { |
1167 | return ipa_edge_args_sum->exists (edge); |
1168 | } |
1169 | |
1170 | inline ipcp_transformation * |
1171 | ipcp_get_transformation_summary (cgraph_node *node) |
1172 | { |
1173 | if (ipcp_transformation_sum == NULL) |
1174 | return NULL; |
1175 | |
1176 | return ipcp_transformation_sum->get (node); |
1177 | } |
1178 | |
1179 | /* Function formal parameters related computations. */ |
1180 | void ipa_initialize_node_params (struct cgraph_node *node); |
1181 | bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, |
1182 | vec<cgraph_edge *> *new_edges); |
1183 | |
1184 | /* Indirect edge processing and target discovery. */ |
1185 | tree ipa_get_indirect_edge_target (struct cgraph_edge *ie, |
1186 | ipa_call_arg_values *avals, |
1187 | bool *speculative); |
1188 | struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree, |
1189 | bool speculative = false); |
1190 | tree ipa_impossible_devirt_target (struct cgraph_edge *, tree); |
1191 | |
1192 | |
1193 | /* Functions related to both. */ |
1194 | void ipa_analyze_node (struct cgraph_node *); |
1195 | |
1196 | /* Aggregate jump function related functions. */ |
1197 | tree ipa_find_agg_cst_from_init (tree scalar, HOST_WIDE_INT offset, |
1198 | bool by_ref); |
1199 | bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, |
1200 | vec<ipa_param_descriptor, va_gc> *descriptors, |
1201 | gimple *stmt, tree op, int *index_p, |
1202 | HOST_WIDE_INT *offset_p, poly_int64 *size_p, |
1203 | bool *by_ref, bool *guaranteed_unmodified = NULL); |
1204 | |
1205 | /* Debugging interface. */ |
1206 | void ipa_print_node_params (FILE *, struct cgraph_node *node); |
1207 | void ipa_print_all_params (FILE *); |
1208 | void ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node); |
1209 | void ipa_print_all_jump_functions (FILE * f); |
1210 | void ipcp_verify_propagated_values (void); |
1211 | |
1212 | template <typename value> |
1213 | class ipcp_value; |
1214 | |
1215 | extern object_allocator<ipcp_value<tree> > ipcp_cst_values_pool; |
1216 | extern object_allocator<ipcp_value<ipa_polymorphic_call_context> > |
1217 | ipcp_poly_ctx_values_pool; |
1218 | |
1219 | template <typename valtype> |
1220 | struct ipcp_value_source; |
1221 | |
1222 | extern object_allocator<ipcp_value_source<tree> > ipcp_sources_pool; |
1223 | |
1224 | struct ipcp_agg_lattice; |
1225 | |
1226 | extern object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool; |
1227 | |
1228 | void ipa_prop_write_jump_functions (void); |
1229 | void ipa_prop_read_jump_functions (void); |
1230 | void ipcp_write_transformation_summaries (void); |
1231 | void ipcp_read_transformation_summaries (void); |
1232 | int ipa_get_param_decl_index (class ipa_node_params *, tree); |
1233 | tree ipa_value_from_jfunc (class ipa_node_params *info, |
1234 | struct ipa_jump_func *jfunc, tree type); |
1235 | tree ipa_agg_value_from_jfunc (ipa_node_params *info, cgraph_node *node, |
1236 | const ipa_agg_jf_item *item); |
1237 | unsigned int ipcp_transform_function (struct cgraph_node *node); |
1238 | ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *, |
1239 | cgraph_edge *, |
1240 | int, |
1241 | ipa_jump_func *); |
1242 | void ipa_value_range_from_jfunc (vrange &, ipa_node_params *, cgraph_edge *, |
1243 | ipa_jump_func *, tree); |
1244 | void ipa_push_agg_values_from_jfunc (ipa_node_params *info, cgraph_node *node, |
1245 | ipa_agg_jump_function *agg_jfunc, |
1246 | unsigned dst_index, |
1247 | vec<ipa_argagg_value> *res); |
1248 | void ipa_dump_param (FILE *, class ipa_node_params *info, int i); |
1249 | void ipa_release_body_info (struct ipa_func_body_info *); |
1250 | tree ipa_get_callee_param_type (struct cgraph_edge *e, int i); |
1251 | bool ipcp_get_parm_bits (tree, tree *, widest_int *); |
1252 | tree ipcp_get_aggregate_const (struct function *func, tree parm, bool by_ref, |
1253 | HOST_WIDE_INT bit_offset, |
1254 | HOST_WIDE_INT bit_size); |
1255 | bool unadjusted_ptr_and_unit_offset (tree op, tree *ret, |
1256 | poly_int64 *offset_ret); |
1257 | |
1258 | /* From tree-sra.cc: */ |
1259 | tree build_ref_for_offset (location_t, tree, poly_int64, bool, tree, |
1260 | gimple_stmt_iterator *, bool); |
1261 | |
1262 | /* In ipa-cp.cc */ |
1263 | void ipa_cp_cc_finalize (void); |
1264 | |
1265 | /* Set R to the range of [VAL, VAL] while normalizing addresses to |
1266 | non-zero. */ |
1267 | |
1268 | inline void |
1269 | ipa_range_set_and_normalize (vrange &r, tree val) |
1270 | { |
1271 | if (TREE_CODE (val) == ADDR_EXPR) |
1272 | r.set_nonzero (TREE_TYPE (val)); |
1273 | else |
1274 | r.set (val, val); |
1275 | } |
1276 | |
1277 | #endif /* IPA_PROP_H */ |
1278 | |