Line data Source code
1 : /* Interprocedural analyses.
2 : Copyright (C) 2005-2026 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 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "backend.h"
24 : #include "rtl.h"
25 : #include "tree.h"
26 : #include "gimple.h"
27 : #include "alloc-pool.h"
28 : #include "tree-pass.h"
29 : #include "ssa.h"
30 : #include "tree-streamer.h"
31 : #include "cgraph.h"
32 : #include "diagnostic.h"
33 : #include "fold-const.h"
34 : #include "gimple-iterator.h"
35 : #include "gimple-fold.h"
36 : #include "tree-eh.h"
37 : #include "calls.h"
38 : #include "stor-layout.h"
39 : #include "print-tree.h"
40 : #include "gimplify.h"
41 : #include "gimplify-me.h"
42 : #include "gimple-walk.h"
43 : #include "symbol-summary.h"
44 : #include "sreal.h"
45 : #include "ipa-cp.h"
46 : #include "ipa-prop.h"
47 : #include "tree-cfg.h"
48 : #include "tree-dfa.h"
49 : #include "tree-inline.h"
50 : #include "ipa-fnsummary.h"
51 : #include "gimple-pretty-print.h"
52 : #include "ipa-utils.h"
53 : #include "dbgcnt.h"
54 : #include "domwalk.h"
55 : #include "builtins.h"
56 : #include "tree-cfgcleanup.h"
57 : #include "options.h"
58 : #include "symtab-clones.h"
59 : #include "attr-fnspec.h"
60 : #include "gimple-range.h"
61 : #include "value-range-storage.h"
62 : #include "vr-values.h"
63 : #include "lto-streamer.h"
64 : #include "attribs.h"
65 : #include "attr-callback.h"
66 : #include "callback-info.h"
67 :
68 : /* Function summary where the parameter infos are actually stored. */
69 : ipa_node_params_t *ipa_node_params_sum = NULL;
70 :
71 : function_summary <ipcp_transformation *> *ipcp_transformation_sum = NULL;
72 :
73 : /* Edge summary for IPA-CP edge information. */
74 : ipa_edge_args_sum_t *ipa_edge_args_sum;
75 :
76 : /* Traits for a hash table for reusing ranges. */
77 :
78 : struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <ipa_vr *>
79 : {
80 : typedef ipa_vr *value_type;
81 : typedef const vrange *compare_type;
82 : static hashval_t
83 26099320 : hash (const ipa_vr *p)
84 : {
85 : // This never get called, except in the verification code, as
86 : // ipa_get_value_range() calculates the hash itself. This
87 : // function is mostly here for completeness' sake.
88 26099320 : value_range vr;
89 26099320 : p->get_vrange (vr);
90 26099320 : inchash::hash hstate;
91 26099320 : add_vrange (vr, hstate);
92 26099320 : return hstate.end ();
93 26099320 : }
94 : static bool
95 30351106 : equal (const ipa_vr *a, const vrange *b)
96 : {
97 30351106 : return a->equal_p (*b);
98 : }
99 : static const bool empty_zero_p = true;
100 : static void
101 1964 : mark_empty (ipa_vr *&p)
102 : {
103 1964 : p = NULL;
104 : }
105 : static bool
106 : is_empty (const ipa_vr *p)
107 : {
108 : return p == NULL;
109 : }
110 : static bool
111 84869297 : is_deleted (const ipa_vr *p)
112 : {
113 84869297 : return p == reinterpret_cast<const ipa_vr *> (1);
114 : }
115 : static void
116 1435984 : mark_deleted (ipa_vr *&p)
117 : {
118 1435984 : p = reinterpret_cast<ipa_vr *> (1);
119 : }
120 : };
121 :
122 : /* Hash table for avoid repeated allocations of equal ranges. */
123 : static GTY ((cache)) hash_table<ipa_vr_ggc_hash_traits> *ipa_vr_hash_table;
124 :
125 : /* Holders of ipa cgraph hooks: */
126 : static struct cgraph_node_hook_list *function_insertion_hook_holder;
127 :
128 : /* Description of a reference to an IPA constant. */
129 : struct ipa_cst_ref_desc
130 : {
131 : /* Edge that corresponds to the statement which took the reference. */
132 : struct cgraph_edge *cs;
133 : /* Linked list of duplicates created when call graph edges are cloned. */
134 : struct ipa_cst_ref_desc *next_duplicate;
135 : /* Number of references in IPA structures, IPA_UNDESCRIBED_USE if the value
136 : is out of control. */
137 : int refcount;
138 : };
139 :
140 : /* Allocation pool for reference descriptions. */
141 :
142 : static object_allocator<ipa_cst_ref_desc> ipa_refdesc_pool
143 : ("IPA-PROP ref descriptions");
144 :
145 656695 : ipa_vr::ipa_vr ()
146 656695 : : m_storage (NULL),
147 656695 : m_type (NULL)
148 : {
149 656695 : }
150 :
151 2684804 : ipa_vr::ipa_vr (const vrange &r)
152 2684804 : : m_storage (ggc_alloc_vrange_storage (r, false /* shared_p */)),
153 2684804 : m_type (r.type ())
154 : {
155 2684804 : }
156 :
157 : bool
158 30351106 : ipa_vr::equal_p (const vrange &r) const
159 : {
160 30351106 : gcc_checking_assert (!r.undefined_p ());
161 30351106 : return (types_compatible_p (m_type, r.type ()) && m_storage->equal_p (r));
162 : }
163 :
164 : bool
165 63743 : ipa_vr::equal_p (const ipa_vr &o) const
166 : {
167 63743 : if (!known_p ())
168 0 : return !o.known_p ();
169 :
170 63743 : if (!types_compatible_p (m_type, o.m_type))
171 : return false;
172 :
173 63743 : value_range r;
174 63743 : o.get_vrange (r);
175 63743 : return m_storage->equal_p (r);
176 63743 : }
177 :
178 : void
179 37990180 : ipa_vr::get_vrange (value_range &r) const
180 : {
181 37990180 : r.set_range_class (m_type);
182 37990180 : m_storage->get_vrange (r, m_type);
183 37990180 : }
184 :
185 : void
186 1914 : ipa_vr::set_unknown ()
187 : {
188 1914 : if (m_storage)
189 1914 : ggc_free (m_storage);
190 :
191 1914 : m_storage = NULL;
192 1914 : }
193 :
194 : void
195 612734 : ipa_vr::streamer_read (lto_input_block *ib, data_in *data_in)
196 : {
197 612734 : struct bitpack_d bp = streamer_read_bitpack (ib);
198 612734 : bool known = bp_unpack_value (&bp, 1);
199 612734 : if (known)
200 : {
201 438679 : value_range vr;
202 438679 : streamer_read_value_range (ib, data_in, vr);
203 438679 : if (!m_storage || !m_storage->fits_p (vr))
204 : {
205 438679 : if (m_storage)
206 0 : ggc_free (m_storage);
207 438679 : m_storage = ggc_alloc_vrange_storage (vr);
208 : }
209 438679 : m_storage->set_vrange (vr);
210 438679 : m_type = vr.type ();
211 438679 : }
212 : else
213 : {
214 174055 : m_storage = NULL;
215 174055 : m_type = NULL;
216 : }
217 612734 : }
218 :
219 : void
220 469793 : ipa_vr::streamer_write (output_block *ob) const
221 : {
222 469793 : struct bitpack_d bp = bitpack_create (ob->main_stream);
223 469793 : bp_pack_value (&bp, !!m_storage, 1);
224 469793 : streamer_write_bitpack (&bp);
225 469793 : if (m_storage)
226 : {
227 467276 : value_range vr (m_type);
228 467276 : m_storage->get_vrange (vr, m_type);
229 467276 : streamer_write_vrange (ob, vr);
230 467276 : }
231 469793 : }
232 :
233 : void
234 741 : ipa_vr::dump (FILE *out) const
235 : {
236 741 : if (known_p ())
237 : {
238 741 : value_range vr (m_type);
239 741 : m_storage->get_vrange (vr, m_type);
240 741 : vr.dump (out);
241 741 : }
242 : else
243 0 : fprintf (out, "NO RANGE");
244 741 : }
245 :
246 : // These stubs are because we use an ipa_vr in a hash_traits and
247 : // hash-traits.h defines an extern of gt_ggc_mx (T &) instead of
248 : // picking up the gt_ggc_mx (T *) version.
249 : void
250 0 : gt_pch_nx (ipa_vr *&x)
251 : {
252 0 : return gt_pch_nx ((ipa_vr *) x);
253 : }
254 :
255 : void
256 0 : gt_ggc_mx (ipa_vr *&x)
257 : {
258 0 : return gt_ggc_mx ((ipa_vr *) x);
259 : }
260 :
261 : /* Analysis summery of function call return value. */
262 : struct GTY(()) ipa_return_value_summary
263 : {
264 : /* Known value range.
265 : This needs to be wrapped in struccture due to specific way
266 : we allocate ipa_vr. */
267 : ipa_vr *vr;
268 : };
269 :
270 : /* Function summary for return values. */
271 : class ipa_return_value_sum_t : public function_summary <ipa_return_value_summary *>
272 : {
273 : public:
274 88399 : ipa_return_value_sum_t (symbol_table *table, bool ggc):
275 176798 : function_summary <ipa_return_value_summary *> (table, ggc) { }
276 :
277 : /* Hook that is called by summary when a node is duplicated. */
278 582906 : void duplicate (cgraph_node *,
279 : cgraph_node *,
280 : ipa_return_value_summary *data,
281 : ipa_return_value_summary *data2) final override
282 : {
283 582906 : *data2=*data;
284 582906 : }
285 : };
286 :
287 : /* Structure holding the information that all stores to FLD_OFFSET (measured in
288 : bytes) of a particular record type REC_TYPE was storing a pointer to
289 : function FN or that there were multiple functions, which is denoted by fn
290 : being nullptr. */
291 :
292 : struct GTY((for_user)) noted_fnptr_store
293 : {
294 : tree rec_type;
295 : tree fn;
296 : unsigned fld_offset;
297 : };
298 :
299 : /* Hash traits to have a hash table of noted_fnptr_stores. */
300 :
301 : struct noted_fnptr_hasher : ggc_ptr_hash <noted_fnptr_store>
302 : {
303 : static hashval_t hash (noted_fnptr_store *);
304 : static bool equal (noted_fnptr_store *,
305 : noted_fnptr_store *);
306 : };
307 :
308 : hashval_t
309 604561 : noted_fnptr_hasher::hash (noted_fnptr_store *val)
310 : {
311 1209122 : return iterative_hash_host_wide_int (val->fld_offset,
312 604561 : TYPE_UID (val->rec_type));
313 : }
314 :
315 : bool
316 524102 : noted_fnptr_hasher::equal (noted_fnptr_store *v1,
317 : noted_fnptr_store *v2)
318 : {
319 524102 : return (v1->rec_type == v2->rec_type
320 524102 : && v1->fld_offset == v2->fld_offset);
321 : }
322 :
323 :
324 : /* Structure holding the information that all stores to OFFSET of a particular
325 : record type RECTYPE was storing a pointer to specific function or that there
326 : were multiple such functions. */
327 :
328 : static GTY(()) hash_table <noted_fnptr_hasher> *noted_fnptrs_in_records;
329 :
330 : /* Variable hoding the return value summary. */
331 : static GTY(()) function_summary <ipa_return_value_summary *> *ipa_return_value_sum;
332 :
333 :
334 : /* Return true if DECL_FUNCTION_SPECIFIC_OPTIMIZATION of the decl associated
335 : with NODE should prevent us from analyzing it for the purposes of IPA-CP. */
336 :
337 : static bool
338 4179381 : ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node)
339 : {
340 4179381 : tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->decl);
341 :
342 4179381 : if (!fs_opts)
343 : return false;
344 552139 : return !opt_for_fn (node->decl, optimize) || !opt_for_fn (node->decl, flag_ipa_cp);
345 : }
346 :
347 : /* Return index of the formal whose tree is PTREE in function which corresponds
348 : to INFO. */
349 :
350 : static int
351 43732700 : ipa_get_param_decl_index_1 (vec<ipa_param_descriptor, va_gc> *descriptors,
352 : tree ptree)
353 : {
354 43732700 : int i, count;
355 :
356 43732700 : count = vec_safe_length (descriptors);
357 89203988 : for (i = 0; i < count; i++)
358 78544626 : if ((*descriptors)[i].decl_or_type == ptree)
359 : return i;
360 :
361 : return -1;
362 : }
363 :
364 : /* Return index of the formal whose tree is PTREE in function which corresponds
365 : to INFO. */
366 :
367 : int
368 27364921 : ipa_get_param_decl_index (class ipa_node_params *info, tree ptree)
369 : {
370 27364921 : return ipa_get_param_decl_index_1 (info->descriptors, ptree);
371 : }
372 :
373 : static void
374 : ipa_duplicate_jump_function (cgraph_edge *src, cgraph_edge *dst,
375 : ipa_jump_func *src_jf, ipa_jump_func *dst_jf);
376 :
377 : /* Populate the param_decl field in parameter DESCRIPTORS that correspond to
378 : NODE. */
379 :
380 : static void
381 5717781 : ipa_populate_param_decls (struct cgraph_node *node,
382 : vec<ipa_param_descriptor, va_gc> &descriptors)
383 : {
384 5717781 : tree fndecl;
385 5717781 : tree fnargs;
386 5717781 : tree parm;
387 5717781 : int param_num;
388 :
389 5717781 : fndecl = node->decl;
390 5717781 : gcc_assert (gimple_has_body_p (fndecl));
391 5717781 : fnargs = DECL_ARGUMENTS (fndecl);
392 5717781 : param_num = 0;
393 18789922 : for (parm = fnargs; parm; parm = DECL_CHAIN (parm))
394 : {
395 13072141 : descriptors[param_num].decl_or_type = parm;
396 13072141 : unsigned int cost = estimate_move_cost (TREE_TYPE (parm), true);
397 13072141 : descriptors[param_num].move_cost = cost;
398 : /* Watch overflow, move_cost is a bitfield. */
399 13072141 : gcc_checking_assert (cost == descriptors[param_num].move_cost);
400 13072141 : param_num++;
401 : }
402 5717781 : }
403 :
404 : /* Return how many formal parameters FNDECL has. */
405 :
406 : int
407 15642321 : count_formal_params (tree fndecl)
408 : {
409 15642321 : tree parm;
410 15642321 : int count = 0;
411 15642321 : gcc_assert (gimple_has_body_p (fndecl));
412 :
413 48262913 : for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
414 32620592 : count++;
415 :
416 15642321 : return count;
417 : }
418 :
419 : /* Return the declaration of Ith formal parameter of the function corresponding
420 : to INFO. Note there is no setter function as this array is built just once
421 : using ipa_initialize_node_params. */
422 :
423 : void
424 739 : ipa_dump_param (FILE *file, class ipa_node_params *info, int i)
425 : {
426 739 : fprintf (file, "param #%i", i);
427 739 : if ((*info->descriptors)[i].decl_or_type)
428 : {
429 739 : fprintf (file, " ");
430 739 : print_generic_expr (file, (*info->descriptors)[i].decl_or_type);
431 : }
432 739 : }
433 :
434 : /* If necessary, allocate vector of parameter descriptors in info of NODE.
435 : Return true if they were allocated, false if not. */
436 :
437 : static bool
438 6613485 : ipa_alloc_node_params (struct cgraph_node *node, int param_count)
439 : {
440 6613485 : ipa_node_params *info = ipa_node_params_sum->get_create (node);
441 :
442 6613485 : if (!info->descriptors && param_count)
443 : {
444 5769918 : vec_safe_grow_cleared (info->descriptors, param_count, true);
445 5769918 : return true;
446 : }
447 : else
448 : return false;
449 : }
450 :
451 : /* Initialize the ipa_node_params structure associated with NODE by counting
452 : the function parameters, creating the descriptors and populating their
453 : param_decls. */
454 :
455 : void
456 6535371 : ipa_initialize_node_params (struct cgraph_node *node)
457 : {
458 6535371 : ipa_node_params *info = ipa_node_params_sum->get_create (node);
459 :
460 6535371 : if (!info->descriptors
461 6535371 : && ipa_alloc_node_params (node, count_formal_params (node->decl)))
462 5716456 : ipa_populate_param_decls (node, *info->descriptors);
463 6535371 : }
464 :
465 : /* Print VAL which is extracted from a jump function to F. */
466 :
467 : void
468 1342 : ipa_print_constant_value (FILE *f, tree val)
469 : {
470 1342 : print_generic_expr (f, val);
471 :
472 : /* This is in keeping with values_equal_for_ipcp_p. */
473 1342 : if (TREE_CODE (val) == ADDR_EXPR
474 1342 : && (TREE_CODE (TREE_OPERAND (val, 0)) == CONST_DECL
475 264 : || (TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
476 105 : && DECL_IN_CONSTANT_POOL (TREE_OPERAND (val, 0)))))
477 : {
478 0 : fputs (" -> ", f);
479 0 : print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (val, 0)));
480 : }
481 1342 : }
482 :
483 : /* Print contents of JFUNC to F. If CTX is non-NULL, dump it too. */
484 :
485 : DEBUG_FUNCTION void
486 1046 : ipa_dump_jump_function (FILE *f, ipa_jump_func *jump_func,
487 : class ipa_polymorphic_call_context *ctx)
488 : {
489 1046 : enum jump_func_type type = jump_func->type;
490 :
491 1046 : if (type == IPA_JF_UNKNOWN)
492 262 : fprintf (f, "UNKNOWN\n");
493 784 : else if (type == IPA_JF_CONST)
494 : {
495 313 : fprintf (f, "CONST: ");
496 313 : ipa_print_constant_value (f, jump_func->value.constant.value);
497 313 : fprintf (f, "\n");
498 : }
499 471 : else if (type == IPA_JF_PASS_THROUGH)
500 : {
501 410 : fprintf (f, "PASS THROUGH: ");
502 410 : fprintf (f, "%d, op %s",
503 : jump_func->value.pass_through.formal_id,
504 : get_tree_code_name(jump_func->value.pass_through.operation));
505 410 : if (jump_func->value.pass_through.operation != NOP_EXPR)
506 : {
507 31 : fprintf (f, " ");
508 31 : if (jump_func->value.pass_through.operand)
509 27 : print_generic_expr (f, jump_func->value.pass_through.operand);
510 31 : fprintf (f, " (in type ");
511 31 : print_generic_expr (f, jump_func->value.pass_through.op_type);
512 31 : fprintf (f, ")");
513 : }
514 410 : if (jump_func->value.pass_through.agg_preserved)
515 134 : fprintf (f, ", agg_preserved");
516 410 : if (jump_func->value.pass_through.refdesc_decremented)
517 0 : fprintf (f, ", refdesc_decremented");
518 410 : fprintf (f, "\n");
519 : }
520 61 : else if (type == IPA_JF_ANCESTOR)
521 : {
522 61 : fprintf (f, "ANCESTOR: ");
523 61 : fprintf (f, "%d, offset " HOST_WIDE_INT_PRINT_DEC,
524 : jump_func->value.ancestor.formal_id,
525 : jump_func->value.ancestor.offset);
526 61 : if (jump_func->value.ancestor.agg_preserved)
527 29 : fprintf (f, ", agg_preserved");
528 61 : if (jump_func->value.ancestor.keep_null)
529 4 : fprintf (f, ", keep_null");
530 61 : fprintf (f, "\n");
531 : }
532 :
533 1046 : if (jump_func->agg.items)
534 : {
535 99 : struct ipa_agg_jf_item *item;
536 99 : int j;
537 :
538 198 : fprintf (f, " Aggregate passed by %s:\n",
539 99 : jump_func->agg.by_ref ? "reference" : "value");
540 413 : FOR_EACH_VEC_ELT (*jump_func->agg.items, j, item)
541 : {
542 215 : fprintf (f, " offset: " HOST_WIDE_INT_PRINT_DEC ", ",
543 : item->offset);
544 215 : fprintf (f, "type: ");
545 215 : print_generic_expr (f, item->type);
546 215 : fprintf (f, ", ");
547 215 : if (item->jftype == IPA_JF_PASS_THROUGH)
548 27 : fprintf (f, "PASS THROUGH: %d,",
549 : item->value.pass_through.formal_id);
550 188 : else if (item->jftype == IPA_JF_LOAD_AGG)
551 : {
552 11 : fprintf (f, "LOAD AGG: %d",
553 : item->value.pass_through.formal_id);
554 11 : fprintf (f, " [offset: " HOST_WIDE_INT_PRINT_DEC ", by %s],",
555 : item->value.load_agg.offset,
556 11 : item->value.load_agg.by_ref ? "reference"
557 : : "value");
558 : }
559 :
560 215 : if (item->jftype == IPA_JF_PASS_THROUGH
561 215 : || item->jftype == IPA_JF_LOAD_AGG)
562 : {
563 38 : fprintf (f, " op %s",
564 : get_tree_code_name (item->value.pass_through.operation));
565 38 : if (item->value.pass_through.operation != NOP_EXPR)
566 : {
567 9 : fprintf (f, " ");
568 9 : if (item->value.pass_through.operand)
569 8 : print_generic_expr (f, item->value.pass_through.operand);
570 9 : fprintf (f, " (in type ");
571 9 : print_generic_expr (f, jump_func->value.pass_through.op_type);
572 9 : fprintf (f, ")");
573 : }
574 : }
575 177 : else if (item->jftype == IPA_JF_CONST)
576 : {
577 177 : fprintf (f, "CONST: ");
578 177 : ipa_print_constant_value (f, item->value.constant);
579 : }
580 0 : else if (item->jftype == IPA_JF_UNKNOWN)
581 0 : fprintf (f, "UNKNOWN: " HOST_WIDE_INT_PRINT_DEC " bits",
582 0 : tree_to_uhwi (TYPE_SIZE (item->type)));
583 215 : fprintf (f, "\n");
584 : }
585 : }
586 :
587 1046 : if (ctx && !ctx->useless_p ())
588 : {
589 384 : fprintf (f, " Context: ");
590 384 : ctx->dump (dump_file);
591 : }
592 :
593 1046 : if (jump_func->m_vr)
594 : {
595 741 : fprintf (f, " ");
596 741 : jump_func->m_vr->dump (f);
597 741 : fprintf (f, "\n");
598 : }
599 : else
600 305 : fprintf (f, " Unknown VR\n");
601 1046 : }
602 :
603 : /* Print the jump functions associated with call graph edge CS to file F. */
604 :
605 : static void
606 738 : ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
607 : {
608 738 : ipa_edge_args *args = ipa_edge_args_sum->get (cs);
609 738 : int count = ipa_get_cs_argument_count (args);
610 :
611 1784 : for (int i = 0; i < count; i++)
612 : {
613 1046 : struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
614 1046 : class ipa_polymorphic_call_context *ctx
615 1046 : = ipa_get_ith_polymorhic_call_context (args, i);
616 :
617 1046 : fprintf (f, " param %d: ", i);
618 1046 : ipa_dump_jump_function (f, jump_func, ctx);
619 : }
620 738 : }
621 :
622 :
623 : /* Print the jump functions of all arguments on all call graph edges going from
624 : NODE to file F. */
625 :
626 : void
627 1076 : ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
628 : {
629 1076 : struct cgraph_edge *cs;
630 :
631 1076 : fprintf (f, " Jump functions of caller %s:\n", node->dump_name ());
632 2159 : for (cs = node->callees; cs; cs = cs->next_callee)
633 : {
634 :
635 1083 : fprintf (f, " callsite %s -> %s : \n",
636 : node->dump_name (),
637 1083 : cs->callee->dump_name ());
638 1083 : if (!ipa_edge_args_info_available_for_edge_p (cs))
639 492 : fprintf (f, " no arg info\n");
640 : else
641 591 : ipa_print_node_jump_functions_for_edge (f, cs);
642 : }
643 :
644 1223 : for (cs = node->indirect_calls; cs; cs = cs->next_callee)
645 : {
646 147 : fprintf (f, " ");
647 147 : cs->indirect_info->dump (f, false);
648 147 : if (cs->call_stmt)
649 : {
650 131 : fprintf (f, ", for stmt ");
651 131 : print_gimple_stmt (f, cs->call_stmt, 0, TDF_SLIM);
652 : }
653 : else
654 16 : fprintf (f, "\n");
655 147 : if (!ipa_edge_args_info_available_for_edge_p (cs))
656 0 : fprintf (f, " no arg info\n");
657 : else
658 147 : ipa_print_node_jump_functions_for_edge (f, cs);
659 : }
660 1076 : }
661 :
662 : /* Print ipa_jump_func data structures of all nodes in the call graph to F. */
663 :
664 : void
665 162 : ipa_print_all_jump_functions (FILE *f)
666 : {
667 162 : struct cgraph_node *node;
668 :
669 162 : fprintf (f, "\nJump functions:\n");
670 1222 : FOR_EACH_FUNCTION (node)
671 : {
672 1060 : ipa_print_node_jump_functions (f, node);
673 : }
674 162 : }
675 :
676 : /* Set jfunc to be a know-really nothing jump function. */
677 :
678 : static void
679 561094 : ipa_set_jf_unknown (struct ipa_jump_func *jfunc)
680 : {
681 561094 : jfunc->type = IPA_JF_UNKNOWN;
682 0 : }
683 :
684 : /* Set DST to be a copy of another SRC. The two functions will share their
685 : rdesc. */
686 :
687 : static void
688 922779 : ipa_set_jf_cst_copy (struct ipa_jump_func *dst,
689 : struct ipa_jump_func *src)
690 :
691 : {
692 922779 : gcc_checking_assert (src->type == IPA_JF_CONST);
693 922779 : dst->type = IPA_JF_CONST;
694 922779 : dst->value.constant = src->value.constant;
695 922779 : }
696 :
697 : /* Set DST to be a copy of another jump function SRC but possibly adjust it to
698 : a new passed type PARM_TYPE. If the adjustment fails, the jump function can
699 : end up being set to the unknown type. If the conversion is not necessary or
700 : it succeeds and if the destination rdesc has not been already used, the two
701 : functions will share their rdesc. */
702 :
703 : static void
704 168518 : ipa_convert_prop_cst_jf (struct ipa_jump_func *dst,
705 : struct ipa_jump_func *src,
706 : tree parm_type)
707 :
708 : {
709 168518 : gcc_checking_assert (src->type == IPA_JF_CONST);
710 168518 : tree new_val = ipacp_value_safe_for_type (parm_type,
711 : ipa_get_jf_constant (src));
712 168518 : if (new_val)
713 : {
714 168517 : bool rd = ipa_get_jf_pass_through_refdesc_decremented (dst);
715 :
716 168517 : dst->type = IPA_JF_CONST;
717 168517 : dst->value.constant.value = new_val;
718 168517 : if (!rd)
719 168492 : dst->value.constant.rdesc = src->value.constant.rdesc;
720 : else
721 25 : ipa_zap_jf_refdesc (dst);
722 : }
723 : else
724 1 : ipa_set_jf_unknown (dst);
725 168518 : }
726 :
727 : /* Set JFUNC to be a constant jmp function. */
728 :
729 : static void
730 2797829 : ipa_set_jf_constant (struct ipa_jump_func *jfunc, tree constant,
731 : struct cgraph_edge *cs)
732 : {
733 2797829 : jfunc->type = IPA_JF_CONST;
734 2797829 : jfunc->value.constant.value = unshare_expr_without_location (constant);
735 :
736 2797829 : if (TREE_CODE (constant) == ADDR_EXPR
737 2797829 : && (TREE_CODE (TREE_OPERAND (constant, 0)) == FUNCTION_DECL
738 1004270 : || (VAR_P (TREE_OPERAND (constant, 0))
739 359609 : && TREE_STATIC (TREE_OPERAND (constant, 0)))))
740 : {
741 394755 : struct ipa_cst_ref_desc *rdesc;
742 :
743 394755 : rdesc = ipa_refdesc_pool.allocate ();
744 394755 : rdesc->cs = cs;
745 394755 : rdesc->next_duplicate = NULL;
746 394755 : rdesc->refcount = 1;
747 394755 : jfunc->value.constant.rdesc = rdesc;
748 : }
749 : else
750 2403074 : jfunc->value.constant.rdesc = NULL;
751 2797829 : }
752 :
753 : /* Set JFUNC to be a simple pass-through jump function. */
754 : static void
755 1422646 : ipa_set_jf_simple_pass_through (struct ipa_jump_func *jfunc, int formal_id,
756 : bool agg_preserved)
757 : {
758 1422646 : jfunc->type = IPA_JF_PASS_THROUGH;
759 1422646 : jfunc->value.pass_through.operand = NULL_TREE;
760 1422646 : jfunc->value.pass_through.op_type = NULL_TREE;
761 1422646 : jfunc->value.pass_through.formal_id = formal_id;
762 1422646 : jfunc->value.pass_through.operation = NOP_EXPR;
763 1422646 : jfunc->value.pass_through.agg_preserved = agg_preserved;
764 1422646 : jfunc->value.pass_through.refdesc_decremented = false;
765 0 : }
766 :
767 : /* Set JFUNC to be an unary pass through jump function. */
768 :
769 : static void
770 1028 : ipa_set_jf_unary_pass_through (struct ipa_jump_func *jfunc, int formal_id,
771 : enum tree_code operation, tree op_type)
772 : {
773 1028 : jfunc->type = IPA_JF_PASS_THROUGH;
774 1028 : jfunc->value.pass_through.operand = NULL_TREE;
775 1028 : jfunc->value.pass_through.op_type = op_type;
776 1028 : jfunc->value.pass_through.formal_id = formal_id;
777 1028 : jfunc->value.pass_through.operation = operation;
778 1028 : jfunc->value.pass_through.agg_preserved = false;
779 1028 : jfunc->value.pass_through.refdesc_decremented = false;
780 0 : }
781 : /* Set JFUNC to be an arithmetic pass through jump function. */
782 :
783 : static void
784 46553 : ipa_set_jf_arith_pass_through (struct ipa_jump_func *jfunc, int formal_id,
785 : tree operand, enum tree_code operation,
786 : tree op_type)
787 : {
788 46553 : jfunc->type = IPA_JF_PASS_THROUGH;
789 0 : jfunc->value.pass_through.operand = unshare_expr_without_location (operand);
790 46553 : jfunc->value.pass_through.op_type = op_type;
791 46553 : jfunc->value.pass_through.formal_id = formal_id;
792 46553 : jfunc->value.pass_through.operation = operation;
793 46553 : jfunc->value.pass_through.agg_preserved = false;
794 46553 : jfunc->value.pass_through.refdesc_decremented = false;
795 0 : }
796 :
797 : /* Set JFUNC to be an ancestor jump function. */
798 :
799 : static void
800 197458 : ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
801 : int formal_id, bool agg_preserved, bool keep_null)
802 : {
803 197458 : jfunc->type = IPA_JF_ANCESTOR;
804 197458 : jfunc->value.ancestor.formal_id = formal_id;
805 197458 : jfunc->value.ancestor.offset = offset;
806 197458 : jfunc->value.ancestor.agg_preserved = agg_preserved;
807 197458 : jfunc->value.ancestor.keep_null = keep_null;
808 0 : }
809 :
810 : /* Get IPA BB information about the given BB. FBI is the context of analysis
811 : of this function body. */
812 :
813 : static struct ipa_bb_info *
814 34378161 : ipa_get_bb_info (struct ipa_func_body_info *fbi, basic_block bb)
815 : {
816 28695674 : gcc_checking_assert (fbi);
817 34378161 : return &fbi->bb_infos[bb->index];
818 : }
819 :
820 : /* Structure to be passed in between detect_type_change and
821 : check_stmt_for_type_change. */
822 :
823 : struct prop_type_change_info
824 : {
825 : /* Offset into the object where there is the virtual method pointer we are
826 : looking for. */
827 : HOST_WIDE_INT offset;
828 : /* The declaration or SSA_NAME pointer of the base that we are checking for
829 : type change. */
830 : tree object;
831 : /* Set to true if dynamic type change has been detected. */
832 : bool type_maybe_changed;
833 : };
834 :
835 : /* Return true if STMT can modify a virtual method table pointer.
836 :
837 : This function makes special assumptions about both constructors and
838 : destructors which are all the functions that are allowed to alter the VMT
839 : pointers. It assumes that destructors begin with assignment into all VMT
840 : pointers and that constructors essentially look in the following way:
841 :
842 : 1) The very first thing they do is that they call constructors of ancestor
843 : sub-objects that have them.
844 :
845 : 2) Then VMT pointers of this and all its ancestors is set to new values
846 : corresponding to the type corresponding to the constructor.
847 :
848 : 3) Only afterwards, other stuff such as constructor of member sub-objects
849 : and the code written by the user is run. Only this may include calling
850 : virtual functions, directly or indirectly.
851 :
852 : There is no way to call a constructor of an ancestor sub-object in any
853 : other way.
854 :
855 : This means that we do not have to care whether constructors get the correct
856 : type information because they will always change it (in fact, if we define
857 : the type to be given by the VMT pointer, it is undefined).
858 :
859 : The most important fact to derive from the above is that if, for some
860 : statement in the section 3, we try to detect whether the dynamic type has
861 : changed, we can safely ignore all calls as we examine the function body
862 : backwards until we reach statements in section 2 because these calls cannot
863 : be ancestor constructors or destructors (if the input is not bogus) and so
864 : do not change the dynamic type (this holds true only for automatically
865 : allocated objects but at the moment we devirtualize only these). We then
866 : must detect that statements in section 2 change the dynamic type and can try
867 : to derive the new type. That is enough and we can stop, we will never see
868 : the calls into constructors of sub-objects in this code. Therefore we can
869 : safely ignore all call statements that we traverse.
870 : */
871 :
872 : static bool
873 9 : stmt_may_be_vtbl_ptr_store (gimple *stmt)
874 : {
875 9 : if (is_gimple_call (stmt))
876 : return false;
877 0 : if (gimple_clobber_p (stmt))
878 : return false;
879 0 : else if (is_gimple_assign (stmt))
880 : {
881 0 : tree lhs = gimple_assign_lhs (stmt);
882 :
883 0 : if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs)))
884 : {
885 0 : if (flag_strict_aliasing
886 0 : && !POINTER_TYPE_P (TREE_TYPE (lhs)))
887 : return false;
888 :
889 0 : if (TREE_CODE (lhs) == COMPONENT_REF
890 0 : && !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
891 0 : return false;
892 : /* In the future we might want to use get_ref_base_and_extent to find
893 : if there is a field corresponding to the offset and if so, proceed
894 : almost like if it was a component ref. */
895 : }
896 : }
897 : return true;
898 : }
899 :
900 : /* Callback of walk_aliased_vdefs and a helper function for detect_type_change
901 : to check whether a particular statement may modify the virtual table
902 : pointerIt stores its result into DATA, which points to a
903 : prop_type_change_info structure. */
904 :
905 : static bool
906 9 : check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
907 : {
908 9 : gimple *stmt = SSA_NAME_DEF_STMT (vdef);
909 9 : struct prop_type_change_info *tci = (struct prop_type_change_info *) data;
910 :
911 9 : if (stmt_may_be_vtbl_ptr_store (stmt))
912 : {
913 0 : tci->type_maybe_changed = true;
914 0 : return true;
915 : }
916 : else
917 : return false;
918 : }
919 :
920 : /* See if ARG is PARAM_DECl describing instance passed by pointer
921 : or reference in FUNCTION. Return false if the dynamic type may change
922 : in between beginning of the function until CALL is invoked.
923 :
924 : Generally functions are not allowed to change type of such instances,
925 : but they call destructors. We assume that methods cannot destroy the THIS
926 : pointer. Also as a special cases, constructor and destructors may change
927 : type of the THIS pointer. */
928 :
929 : static bool
930 9714 : param_type_may_change_p (tree function, tree arg, gimple *call)
931 : {
932 : /* Pure functions cannot do any changes on the dynamic type;
933 : that require writing to memory. */
934 9714 : if (flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
935 : return false;
936 : /* We need to check if we are within inlined constructor
937 : or destructor (ideally we would have way to check that the
938 : inline cdtor is actually working on ARG, but we don't have
939 : easy tie on this, so punt on all non-pure cdtors.
940 : We may also record the types of cdtors and once we know type
941 : of the instance match them.
942 :
943 : Also code unification optimizations may merge calls from
944 : different blocks making return values unreliable. So
945 : do nothing during late optimization. */
946 9714 : if (DECL_STRUCT_FUNCTION (function)->after_inlining)
947 : return true;
948 9714 : if (TREE_CODE (arg) == SSA_NAME
949 9714 : && SSA_NAME_IS_DEFAULT_DEF (arg)
950 19428 : && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL)
951 : {
952 : /* Normal (non-THIS) argument. */
953 9714 : if ((SSA_NAME_VAR (arg) != DECL_ARGUMENTS (function)
954 9034 : || TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE)
955 : /* THIS pointer of an method - here we want to watch constructors
956 : and destructors as those definitely may change the dynamic
957 : type. */
958 18154 : || (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE
959 8440 : && !DECL_CXX_CONSTRUCTOR_P (function)
960 8439 : && !DECL_CXX_DESTRUCTOR_P (function)
961 8438 : && (SSA_NAME_VAR (arg) == DECL_ARGUMENTS (function))))
962 : {
963 : /* Walk the inline stack and watch out for ctors/dtors. */
964 41598 : for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK;
965 15943 : block = BLOCK_SUPERCONTEXT (block))
966 15958 : if (inlined_polymorphic_ctor_dtor_block_p (block, false))
967 : return true;
968 : return false;
969 : }
970 : }
971 : return true;
972 : }
973 :
974 : /* Detect whether the dynamic type of ARG of COMP_TYPE has changed (before
975 : callsite CALL) by looking for assignments to its virtual table pointer. If
976 : it is, return true. ARG is the object itself (not a pointer
977 : to it, unless dereferenced). BASE is the base of the memory access as
978 : returned by get_ref_base_and_extent, as is the offset.
979 :
980 : This is helper function for detect_type_change and detect_type_change_ssa
981 : that does the heavy work which is usually unnecessary. */
982 :
983 : static bool
984 17 : detect_type_change_from_memory_writes (ipa_func_body_info *fbi, tree arg,
985 : tree base, tree comp_type, gcall *call,
986 : HOST_WIDE_INT offset)
987 : {
988 17 : struct prop_type_change_info tci;
989 17 : ao_ref ao;
990 :
991 17 : gcc_checking_assert (DECL_P (arg)
992 : || TREE_CODE (arg) == MEM_REF
993 : || handled_component_p (arg));
994 :
995 17 : comp_type = TYPE_MAIN_VARIANT (comp_type);
996 :
997 : /* Const calls cannot call virtual methods through VMT and so type changes do
998 : not matter. */
999 17 : if (!flag_devirtualize || !gimple_vuse (call)
1000 : /* Be sure expected_type is polymorphic. */
1001 17 : || !comp_type
1002 17 : || TREE_CODE (comp_type) != RECORD_TYPE
1003 17 : || !TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))
1004 34 : || !BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))))
1005 : return true;
1006 :
1007 17 : if (fbi->aa_walk_budget == 0)
1008 : return false;
1009 :
1010 17 : ao_ref_init (&ao, arg);
1011 17 : ao.base = base;
1012 17 : ao.offset = offset;
1013 17 : ao.size = POINTER_SIZE;
1014 17 : ao.max_size = ao.size;
1015 :
1016 17 : tci.offset = offset;
1017 17 : tci.object = get_base_address (arg);
1018 17 : tci.type_maybe_changed = false;
1019 :
1020 17 : int walked
1021 34 : = walk_aliased_vdefs (&ao, gimple_vuse (call), check_stmt_for_type_change,
1022 : &tci, NULL, NULL, fbi->aa_walk_budget);
1023 17 : if (walked >= 0)
1024 17 : fbi->aa_walk_budget -= walked;
1025 : else
1026 0 : fbi->aa_walk_budget = 0;
1027 :
1028 17 : if (walked >= 0 && !tci.type_maybe_changed)
1029 : return false;
1030 :
1031 : return true;
1032 : }
1033 :
1034 : /* Detect whether the dynamic type of ARG of COMP_TYPE may have changed.
1035 : If it is, return true. ARG is the object itself (not a pointer
1036 : to it, unless dereferenced). BASE is the base of the memory access as
1037 : returned by get_ref_base_and_extent, as is the offset. */
1038 :
1039 : static bool
1040 749 : detect_type_change (ipa_func_body_info *fbi, tree arg, tree base,
1041 : tree comp_type, gcall *call,
1042 : HOST_WIDE_INT offset)
1043 : {
1044 749 : if (!flag_devirtualize)
1045 : return false;
1046 :
1047 749 : if (TREE_CODE (base) == MEM_REF
1048 1498 : && !param_type_may_change_p (current_function_decl,
1049 749 : TREE_OPERAND (base, 0),
1050 : call))
1051 : return false;
1052 12 : return detect_type_change_from_memory_writes (fbi, arg, base, comp_type,
1053 12 : call, offset);
1054 : }
1055 :
1056 : /* Like detect_type_change but ARG is supposed to be a non-dereferenced pointer
1057 : SSA name (its dereference will become the base and the offset is assumed to
1058 : be zero). */
1059 :
1060 : static bool
1061 8965 : detect_type_change_ssa (ipa_func_body_info *fbi, tree arg, tree comp_type,
1062 : gcall *call)
1063 : {
1064 8965 : gcc_checking_assert (TREE_CODE (arg) == SSA_NAME);
1065 8965 : if (!flag_devirtualize
1066 8965 : || !POINTER_TYPE_P (TREE_TYPE (arg)))
1067 : return false;
1068 :
1069 8965 : if (!param_type_may_change_p (current_function_decl, arg, call))
1070 : return false;
1071 :
1072 5 : arg = build2 (MEM_REF, ptr_type_node, arg,
1073 : build_int_cst (ptr_type_node, 0));
1074 :
1075 5 : return detect_type_change_from_memory_writes (fbi, arg, arg, comp_type,
1076 5 : call, 0);
1077 : }
1078 :
1079 : /* Callback of walk_aliased_vdefs. Flags that it has been invoked to the
1080 : boolean variable pointed to by DATA. */
1081 :
1082 : static bool
1083 1636532 : mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
1084 : void *data)
1085 : {
1086 1636532 : bool *b = (bool *) data;
1087 1636532 : *b = true;
1088 1636532 : return true;
1089 : }
1090 :
1091 : /* Find the nearest valid aa status for parameter specified by INDEX that
1092 : dominates BB. */
1093 :
1094 : static struct ipa_param_aa_status *
1095 4524204 : find_dominating_aa_status (struct ipa_func_body_info *fbi, basic_block bb,
1096 : int index)
1097 : {
1098 13665981 : while (true)
1099 : {
1100 13665981 : bb = get_immediate_dominator (CDI_DOMINATORS, bb);
1101 13665981 : if (!bb)
1102 : return NULL;
1103 10597681 : struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
1104 12739807 : if (!bi->param_aa_statuses.is_empty ()
1105 2142126 : && bi->param_aa_statuses[index].valid)
1106 1455904 : return &bi->param_aa_statuses[index];
1107 : }
1108 : }
1109 :
1110 : /* Get AA status structure for the given BB and parameter with INDEX. Allocate
1111 : structures and/or initialize the result with a dominating description as
1112 : necessary. */
1113 :
1114 : static struct ipa_param_aa_status *
1115 6786252 : parm_bb_aa_status_for_bb (struct ipa_func_body_info *fbi, basic_block bb,
1116 : int index)
1117 : {
1118 6786252 : gcc_checking_assert (fbi);
1119 6786252 : struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
1120 6786252 : if (bi->param_aa_statuses.is_empty ())
1121 3894590 : bi->param_aa_statuses.safe_grow_cleared (fbi->param_count, true);
1122 6786252 : struct ipa_param_aa_status *paa = &bi->param_aa_statuses[index];
1123 6786252 : if (!paa->valid)
1124 : {
1125 4524204 : gcc_checking_assert (!paa->parm_modified
1126 : && !paa->ref_modified
1127 : && !paa->pt_modified);
1128 4524204 : struct ipa_param_aa_status *dom_paa;
1129 4524204 : dom_paa = find_dominating_aa_status (fbi, bb, index);
1130 4524204 : if (dom_paa)
1131 1455904 : *paa = *dom_paa;
1132 : else
1133 3068300 : paa->valid = true;
1134 : }
1135 :
1136 6786252 : return paa;
1137 : }
1138 :
1139 : /* Return true if a load from a formal parameter PARM_LOAD is known to retrieve
1140 : a value known not to be modified in this function before reaching the
1141 : statement STMT. FBI holds information about the function we have so far
1142 : gathered but do not survive the summary building stage. */
1143 :
1144 : static bool
1145 1184520 : parm_preserved_before_stmt_p (struct ipa_func_body_info *fbi, int index,
1146 : gimple *stmt, tree parm_load)
1147 : {
1148 1184520 : struct ipa_param_aa_status *paa;
1149 1184520 : bool modified = false;
1150 1184520 : ao_ref refd;
1151 :
1152 1184520 : tree base = get_base_address (parm_load);
1153 1184520 : gcc_assert (TREE_CODE (base) == PARM_DECL);
1154 1184520 : if (TREE_READONLY (base))
1155 : return true;
1156 :
1157 1097315 : gcc_checking_assert (fbi);
1158 1097315 : paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
1159 1097315 : if (paa->parm_modified || fbi->aa_walk_budget == 0)
1160 : return false;
1161 :
1162 1873122 : gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE);
1163 936561 : ao_ref_init (&refd, parm_load);
1164 1873122 : int walked = walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified,
1165 : &modified, NULL, NULL,
1166 : fbi->aa_walk_budget);
1167 936561 : if (walked < 0)
1168 : {
1169 8 : modified = true;
1170 8 : fbi->aa_walk_budget = 0;
1171 : }
1172 : else
1173 936553 : fbi->aa_walk_budget -= walked;
1174 936561 : if (paa && modified)
1175 100402 : paa->parm_modified = true;
1176 936561 : return !modified;
1177 : }
1178 :
1179 : /* If STMT is an assignment that loads a value from an parameter declaration,
1180 : return the index of the parameter in ipa_node_params which has not been
1181 : modified. Otherwise return -1. */
1182 :
1183 : static int
1184 6661074 : load_from_unmodified_param (struct ipa_func_body_info *fbi,
1185 : vec<ipa_param_descriptor, va_gc> *descriptors,
1186 : gimple *stmt)
1187 : {
1188 6661074 : int index;
1189 6661074 : tree op1;
1190 :
1191 6661074 : if (!gimple_assign_single_p (stmt))
1192 : return -1;
1193 :
1194 4438685 : op1 = gimple_assign_rhs1 (stmt);
1195 4438685 : if (TREE_CODE (op1) != PARM_DECL)
1196 : return -1;
1197 :
1198 69658 : index = ipa_get_param_decl_index_1 (descriptors, op1);
1199 69658 : if (index < 0
1200 69658 : || !parm_preserved_before_stmt_p (fbi, index, stmt, op1))
1201 23882 : return -1;
1202 :
1203 : return index;
1204 : }
1205 :
1206 : /* Return true if memory reference REF (which must be a load through parameter
1207 : with INDEX) loads data that are known to be unmodified in this function
1208 : before reaching statement STMT. */
1209 :
1210 : static bool
1211 4832151 : parm_ref_data_preserved_p (struct ipa_func_body_info *fbi,
1212 : int index, gimple *stmt, tree ref)
1213 : {
1214 4832151 : struct ipa_param_aa_status *paa;
1215 4832151 : bool modified = false;
1216 4832151 : ao_ref refd;
1217 :
1218 4832151 : gcc_checking_assert (fbi);
1219 4832151 : paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
1220 4832151 : if (paa->ref_modified || fbi->aa_walk_budget == 0)
1221 : return false;
1222 :
1223 7576092 : gcc_checking_assert (gimple_vuse (stmt));
1224 3788046 : ao_ref_init (&refd, ref);
1225 7576092 : int walked = walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified,
1226 : &modified, NULL, NULL,
1227 : fbi->aa_walk_budget);
1228 3788046 : if (walked < 0)
1229 : {
1230 8 : modified = true;
1231 8 : fbi->aa_walk_budget = 0;
1232 : }
1233 : else
1234 3788038 : fbi->aa_walk_budget -= walked;
1235 3788046 : if (modified)
1236 646301 : paa->ref_modified = true;
1237 3788046 : return !modified;
1238 : }
1239 :
1240 : /* Return true if the data pointed to by PARM (which is a parameter with INDEX)
1241 : is known to be unmodified in this function before reaching call statement
1242 : CALL into which it is passed. FBI describes the function body. */
1243 :
1244 : static bool
1245 1202301 : parm_ref_data_pass_through_p (struct ipa_func_body_info *fbi, int index,
1246 : gimple *call, tree parm)
1247 : {
1248 1202301 : bool modified = false;
1249 1202301 : ao_ref refd;
1250 :
1251 : /* It's unnecessary to calculate anything about memory contents for a const
1252 : function because it is not going to use it. But do not cache the result
1253 : either. Also, no such calculations for non-pointers. */
1254 1202301 : if (!gimple_vuse (call)
1255 1202301 : || !POINTER_TYPE_P (TREE_TYPE (parm)))
1256 : return false;
1257 :
1258 856786 : struct ipa_param_aa_status *paa = parm_bb_aa_status_for_bb (fbi,
1259 : gimple_bb (call),
1260 : index);
1261 856786 : if (paa->pt_modified || fbi->aa_walk_budget == 0)
1262 : return false;
1263 :
1264 738601 : ao_ref_init_from_ptr_and_size (&refd, parm, NULL_TREE);
1265 1477202 : int walked = walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
1266 : &modified, NULL, NULL,
1267 : fbi->aa_walk_budget);
1268 738601 : if (walked < 0)
1269 : {
1270 0 : fbi->aa_walk_budget = 0;
1271 0 : modified = true;
1272 : }
1273 : else
1274 738601 : fbi->aa_walk_budget -= walked;
1275 738601 : if (modified)
1276 274077 : paa->pt_modified = true;
1277 738601 : return !modified;
1278 : }
1279 :
1280 : /* Return true if we can prove that OP is a memory reference loading
1281 : data from an aggregate passed as a parameter.
1282 :
1283 : The function works in two modes. If GUARANTEED_UNMODIFIED is NULL, it return
1284 : false if it cannot prove that the value has not been modified before the
1285 : load in STMT. If GUARANTEED_UNMODIFIED is not NULL, it will return true even
1286 : if it cannot prove the value has not been modified, in that case it will
1287 : store false to *GUARANTEED_UNMODIFIED, otherwise it will store true there.
1288 :
1289 : INFO and PARMS_AINFO describe parameters of the current function (but the
1290 : latter can be NULL), STMT is the load statement. If function returns true,
1291 : *INDEX_P, *OFFSET_P and *BY_REF is filled with the parameter index, offset
1292 : within the aggregate and whether it is a load from a value passed by
1293 : reference respectively.
1294 :
1295 : Return false if the offset divided by BITS_PER_UNIT would not fit into an
1296 : unsigned int. */
1297 :
1298 : bool
1299 25908557 : ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
1300 : vec<ipa_param_descriptor, va_gc> *descriptors,
1301 : gimple *stmt, tree op, int *index_p,
1302 : HOST_WIDE_INT *offset_p, poly_int64 *size_p,
1303 : bool *by_ref_p, bool *guaranteed_unmodified)
1304 : {
1305 25908557 : int index;
1306 25908557 : HOST_WIDE_INT size;
1307 25908557 : bool reverse;
1308 25908557 : tree base = get_ref_base_and_extent_hwi (op, offset_p, &size, &reverse);
1309 :
1310 25908557 : if (!base
1311 24512243 : || (*offset_p / BITS_PER_UNIT) > UINT_MAX)
1312 : return false;
1313 :
1314 : /* We can not propagate across volatile loads. */
1315 24512212 : if (TREE_THIS_VOLATILE (op))
1316 : return false;
1317 :
1318 23297817 : if (DECL_P (base))
1319 : {
1320 11350477 : int index = ipa_get_param_decl_index_1 (descriptors, base);
1321 11350477 : if (index >= 0
1322 11350477 : && parm_preserved_before_stmt_p (fbi, index, stmt, op))
1323 : {
1324 811935 : *index_p = index;
1325 811935 : *by_ref_p = false;
1326 811935 : if (size_p)
1327 27041 : *size_p = size;
1328 811935 : if (guaranteed_unmodified)
1329 137 : *guaranteed_unmodified = true;
1330 : return true;
1331 : }
1332 : return false;
1333 : }
1334 :
1335 11947340 : if (TREE_CODE (base) != MEM_REF
1336 11062526 : || TREE_CODE (TREE_OPERAND (base, 0)) != SSA_NAME
1337 23006278 : || !integer_zerop (TREE_OPERAND (base, 1)))
1338 : return false;
1339 :
1340 10064805 : if (SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (base, 0)))
1341 : {
1342 4947644 : tree parm = SSA_NAME_VAR (TREE_OPERAND (base, 0));
1343 4947644 : index = ipa_get_param_decl_index_1 (descriptors, parm);
1344 : }
1345 : else
1346 : {
1347 : /* This branch catches situations where a pointer parameter is not a
1348 : gimple register, for example:
1349 :
1350 : void hip7(S*) (struct S * p)
1351 : {
1352 : void (*<T2e4>) (struct S *) D.1867;
1353 : struct S * p.1;
1354 :
1355 : <bb 2>:
1356 : p.1_1 = p;
1357 : D.1867_2 = p.1_1->f;
1358 : D.1867_2 ();
1359 : gdp = &p;
1360 : */
1361 :
1362 5117161 : gimple *def = SSA_NAME_DEF_STMT (TREE_OPERAND (base, 0));
1363 5117161 : index = load_from_unmodified_param (fbi, descriptors, def);
1364 : }
1365 :
1366 10064805 : if (index >= 0)
1367 : {
1368 4831848 : bool data_preserved = parm_ref_data_preserved_p (fbi, index, stmt, op);
1369 4831848 : if (!data_preserved && !guaranteed_unmodified)
1370 : return false;
1371 :
1372 3142046 : *index_p = index;
1373 3142046 : *by_ref_p = true;
1374 3142046 : if (size_p)
1375 29593 : *size_p = size;
1376 3142046 : if (guaranteed_unmodified)
1377 2172 : *guaranteed_unmodified = data_preserved;
1378 : return true;
1379 : }
1380 : return false;
1381 : }
1382 :
1383 : /* If STMT is an assignment that loads a value from a parameter declaration,
1384 : or from an aggregate passed as the parameter either by value or reference,
1385 : return the index of the parameter in ipa_node_params. Otherwise return -1.
1386 :
1387 : FBI holds gathered information about the function. INFO describes
1388 : parameters of the function, STMT is the assignment statement. If it is a
1389 : memory load from an aggregate, *OFFSET_P is filled with offset within the
1390 : aggregate, and *BY_REF_P specifies whether the aggregate is passed by
1391 : reference. */
1392 :
1393 : static int
1394 379500 : load_from_unmodified_param_or_agg (struct ipa_func_body_info *fbi,
1395 : class ipa_node_params *info,
1396 : gimple *stmt,
1397 : HOST_WIDE_INT *offset_p,
1398 : bool *by_ref_p)
1399 : {
1400 379500 : int index = load_from_unmodified_param (fbi, info->descriptors, stmt);
1401 379500 : poly_int64 size;
1402 :
1403 : /* Load value from a parameter declaration. */
1404 379500 : if (index >= 0)
1405 : {
1406 302 : *offset_p = -1;
1407 302 : return index;
1408 : }
1409 :
1410 379198 : if (!gimple_assign_load_p (stmt))
1411 : return -1;
1412 :
1413 193869 : tree rhs = gimple_assign_rhs1 (stmt);
1414 :
1415 : /* Skip memory reference containing VIEW_CONVERT_EXPR. */
1416 548136 : for (tree t = rhs; handled_component_p (t); t = TREE_OPERAND (t, 0))
1417 160513 : if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
1418 : return -1;
1419 :
1420 : /* Skip memory reference containing bit-field. */
1421 193754 : if (TREE_CODE (rhs) == BIT_FIELD_REF
1422 193754 : || contains_bitfld_component_ref_p (rhs))
1423 : return -1;
1424 :
1425 193694 : if (!ipa_load_from_parm_agg (fbi, info->descriptors, stmt, rhs, &index,
1426 : offset_p, &size, by_ref_p))
1427 : return -1;
1428 :
1429 53625 : gcc_assert (!maybe_ne (tree_to_poly_int64 (TYPE_SIZE (TREE_TYPE (rhs))),
1430 : size));
1431 53625 : if (!*by_ref_p)
1432 : {
1433 26394 : tree param_type = ipa_get_type (info, index);
1434 :
1435 26394 : if (!param_type || !AGGREGATE_TYPE_P (param_type))
1436 : return -1;
1437 : }
1438 27231 : else if (TREE_THIS_VOLATILE (rhs))
1439 : return -1;
1440 :
1441 51960 : return index;
1442 : }
1443 :
1444 : /* Walk pointer adjustemnts from OP (such as POINTER_PLUS and ADDR_EXPR)
1445 : to find original pointer. Initialize RET to the pointer which results from
1446 : the walk.
1447 : If offset is known return true and initialize OFFSET_RET. */
1448 :
1449 : bool
1450 16294744 : unadjusted_ptr_and_unit_offset (tree op, tree *ret, poly_int64 *offset_ret)
1451 : {
1452 16294744 : poly_int64 offset = 0;
1453 16294744 : bool offset_known = true;
1454 16294744 : int i;
1455 :
1456 21043862 : for (i = 0; i < param_ipa_jump_function_lookups; i++)
1457 : {
1458 21042848 : if (TREE_CODE (op) == ADDR_EXPR)
1459 : {
1460 1664378 : poly_int64 extra_offset;
1461 1664378 : tree base = get_addr_base_and_unit_offset (TREE_OPERAND (op, 0),
1462 : &extra_offset);
1463 1664378 : if (!base)
1464 : {
1465 27657 : base = get_base_address (TREE_OPERAND (op, 0));
1466 27657 : if (TREE_CODE (base) != MEM_REF)
1467 : break;
1468 : offset_known = false;
1469 : }
1470 : else
1471 : {
1472 1636721 : if (TREE_CODE (base) != MEM_REF)
1473 : break;
1474 276505 : offset += extra_offset;
1475 : }
1476 276505 : op = TREE_OPERAND (base, 0);
1477 276505 : if (mem_ref_offset (base).to_shwi (&extra_offset))
1478 276505 : offset += extra_offset;
1479 : else
1480 : offset_known = false;
1481 : }
1482 19378470 : else if (TREE_CODE (op) == SSA_NAME
1483 19378470 : && !SSA_NAME_IS_DEFAULT_DEF (op))
1484 : {
1485 6661766 : gimple *pstmt = SSA_NAME_DEF_STMT (op);
1486 :
1487 6661766 : if (gimple_assign_single_p (pstmt))
1488 3241951 : op = gimple_assign_rhs1 (pstmt);
1489 3419815 : else if (is_gimple_assign (pstmt)
1490 3419815 : && gimple_assign_rhs_code (pstmt) == POINTER_PLUS_EXPR)
1491 : {
1492 1230662 : poly_int64 extra_offset = 0;
1493 1230662 : if (ptrdiff_tree_p (gimple_assign_rhs2 (pstmt),
1494 : &extra_offset))
1495 1230662 : offset += extra_offset;
1496 : else
1497 : offset_known = false;
1498 1230662 : op = gimple_assign_rhs1 (pstmt);
1499 : }
1500 : else
1501 : break;
1502 : }
1503 : else
1504 : break;
1505 : }
1506 16294744 : *ret = op;
1507 16294744 : *offset_ret = offset;
1508 16294744 : return offset_known;
1509 : }
1510 :
1511 : /* Given that an actual argument is an SSA_NAME (given in NAME) and is a result
1512 : of an assignment statement STMT, try to determine whether we are actually
1513 : handling any of the following cases and construct an appropriate jump
1514 : function into JFUNC if so:
1515 :
1516 : 1) The passed value is loaded from a formal parameter which is not a gimple
1517 : register (most probably because it is addressable, the value has to be
1518 : scalar) and we can guarantee the value has not changed. This case can
1519 : therefore be described by a simple pass-through jump function. For example:
1520 :
1521 : foo (int a)
1522 : {
1523 : int a.0;
1524 :
1525 : a.0_2 = a;
1526 : bar (a.0_2);
1527 :
1528 : 2) The passed value can be described by a simple arithmetic pass-through
1529 : jump function. E.g.
1530 :
1531 : foo (int a)
1532 : {
1533 : int D.2064;
1534 :
1535 : D.2064_4 = a.1(D) + 4;
1536 : bar (D.2064_4);
1537 :
1538 : This case can also occur in combination of the previous one, e.g.:
1539 :
1540 : foo (int a, int z)
1541 : {
1542 : int a.0;
1543 : int D.2064;
1544 :
1545 : a.0_3 = a;
1546 : D.2064_4 = a.0_3 + 4;
1547 : foo (D.2064_4);
1548 :
1549 : 3) The passed value is an address of an object within another one (which
1550 : also passed by reference). Such situations are described by an ancestor
1551 : jump function and describe situations such as:
1552 :
1553 : B::foo() (struct B * const this)
1554 : {
1555 : struct A * D.1845;
1556 :
1557 : D.1845_2 = &this_1(D)->D.1748;
1558 : A::bar (D.1845_2);
1559 :
1560 : INFO is the structure describing individual parameters access different
1561 : stages of IPA optimizations. PARMS_AINFO contains the information that is
1562 : only needed for intraprocedural analysis. */
1563 :
1564 : static void
1565 1283723 : compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
1566 : class ipa_node_params *info,
1567 : struct ipa_jump_func *jfunc,
1568 : gcall *call, gimple *stmt, tree name,
1569 : tree param_type)
1570 : {
1571 1283723 : HOST_WIDE_INT offset, size;
1572 1283723 : tree op1, tc_ssa, base, ssa;
1573 1283723 : bool reverse;
1574 1283723 : int index;
1575 :
1576 1283723 : op1 = gimple_assign_rhs1 (stmt);
1577 :
1578 1283723 : if (TREE_CODE (op1) == SSA_NAME)
1579 : {
1580 409979 : if (SSA_NAME_IS_DEFAULT_DEF (op1))
1581 119310 : index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1));
1582 : else
1583 290669 : index = load_from_unmodified_param (fbi, info->descriptors,
1584 290669 : SSA_NAME_DEF_STMT (op1));
1585 : tc_ssa = op1;
1586 : }
1587 : else
1588 : {
1589 873744 : index = load_from_unmodified_param (fbi, info->descriptors, stmt);
1590 873744 : tc_ssa = gimple_assign_lhs (stmt);
1591 : }
1592 :
1593 1283723 : if (index >= 0)
1594 : {
1595 120929 : if (lto_variably_modified_type_p (TREE_TYPE (name)))
1596 1109456 : return;
1597 :
1598 120883 : switch (gimple_assign_rhs_class (stmt))
1599 : {
1600 72297 : case GIMPLE_BINARY_RHS:
1601 72297 : {
1602 72297 : tree op2 = gimple_assign_rhs2 (stmt);
1603 72297 : if (!is_gimple_ip_invariant (op2)
1604 72297 : || ((TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
1605 : != tcc_comparison)
1606 33377 : && !useless_type_conversion_p (TREE_TYPE (name),
1607 33377 : TREE_TYPE (op1))))
1608 : return;
1609 :
1610 44632 : ipa_set_jf_arith_pass_through (jfunc, index, op2,
1611 : gimple_assign_rhs_code (stmt),
1612 44632 : TREE_TYPE (name));
1613 44632 : break;
1614 : }
1615 1218 : case GIMPLE_SINGLE_RHS:
1616 1218 : {
1617 1218 : bool agg_p = parm_ref_data_pass_through_p (fbi, index, call,
1618 : tc_ssa);
1619 1218 : ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
1620 1218 : break;
1621 : }
1622 47366 : case GIMPLE_UNARY_RHS:
1623 47366 : if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)))
1624 1001 : ipa_set_jf_unary_pass_through (jfunc, index,
1625 : gimple_assign_rhs_code (stmt),
1626 1001 : TREE_TYPE (name));
1627 : default:;
1628 : }
1629 : return;
1630 : }
1631 :
1632 1162794 : if (TREE_CODE (op1) != ADDR_EXPR)
1633 : return;
1634 248653 : op1 = TREE_OPERAND (op1, 0);
1635 248653 : base = get_ref_base_and_extent_hwi (op1, &offset, &size, &reverse);
1636 248653 : offset_int mem_offset;
1637 248653 : if (!base
1638 221487 : || TREE_CODE (base) != MEM_REF
1639 470140 : || !mem_ref_offset (base).is_constant (&mem_offset))
1640 : return;
1641 210078 : offset += mem_offset.to_short_addr () * BITS_PER_UNIT;
1642 210078 : ssa = TREE_OPERAND (base, 0);
1643 210078 : if (TREE_CODE (ssa) != SSA_NAME
1644 210078 : || !SSA_NAME_IS_DEFAULT_DEF (ssa)
1645 384444 : || offset < 0)
1646 : return;
1647 :
1648 : /* Dynamic types are changed in constructors and destructors. */
1649 174267 : index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa));
1650 174267 : if (index >= 0 && param_type && POINTER_TYPE_P (param_type))
1651 171258 : ipa_set_ancestor_jf (jfunc, offset, index,
1652 : parm_ref_data_pass_through_p (fbi, index, call, ssa),
1653 : false);
1654 : }
1655 :
1656 : /* Extract the base, offset and MEM_REF expression from a statement ASSIGN if
1657 : it looks like:
1658 :
1659 : iftmp.1_3 = &obj_2(D)->D.1762;
1660 :
1661 : The base of the MEM_REF must be a default definition SSA NAME of a
1662 : parameter. Return NULL_TREE if it looks otherwise. If case of success, the
1663 : whole MEM_REF expression is returned and the offset calculated from any
1664 : handled components and the MEM_REF itself is stored into *OFFSET. The whole
1665 : RHS stripped off the ADDR_EXPR is stored into *OBJ_P. */
1666 :
1667 : static tree
1668 15699 : get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset)
1669 : {
1670 15699 : HOST_WIDE_INT size;
1671 15699 : tree expr, parm, obj;
1672 15699 : bool reverse;
1673 :
1674 15699 : if (!gimple_assign_single_p (assign))
1675 : return NULL_TREE;
1676 8814 : expr = gimple_assign_rhs1 (assign);
1677 :
1678 8814 : if (TREE_CODE (expr) != ADDR_EXPR)
1679 : return NULL_TREE;
1680 4459 : expr = TREE_OPERAND (expr, 0);
1681 4459 : obj = expr;
1682 4459 : expr = get_ref_base_and_extent_hwi (expr, offset, &size, &reverse);
1683 :
1684 4459 : offset_int mem_offset;
1685 4459 : if (!expr
1686 4455 : || TREE_CODE (expr) != MEM_REF
1687 8914 : || !mem_ref_offset (expr).is_constant (&mem_offset))
1688 : return NULL_TREE;
1689 4455 : parm = TREE_OPERAND (expr, 0);
1690 4455 : if (TREE_CODE (parm) != SSA_NAME
1691 4455 : || !SSA_NAME_IS_DEFAULT_DEF (parm)
1692 5230 : || TREE_CODE (SSA_NAME_VAR (parm)) != PARM_DECL)
1693 : return NULL_TREE;
1694 :
1695 775 : *offset += mem_offset.to_short_addr () * BITS_PER_UNIT;
1696 775 : *obj_p = obj;
1697 775 : return expr;
1698 : }
1699 :
1700 :
1701 : /* Given that an actual argument is an SSA_NAME that is a result of a phi
1702 : statement PHI, try to find out whether NAME is in fact a
1703 : multiple-inheritance typecast from a descendant into an ancestor of a formal
1704 : parameter and thus can be described by an ancestor jump function and if so,
1705 : write the appropriate function into JFUNC.
1706 :
1707 : Essentially we want to match the following pattern:
1708 :
1709 : if (obj_2(D) != 0B)
1710 : goto <bb 3>;
1711 : else
1712 : goto <bb 4>;
1713 :
1714 : <bb 3>:
1715 : iftmp.1_3 = &obj_2(D)->D.1762;
1716 :
1717 : <bb 4>:
1718 : # iftmp.1_1 = PHI <iftmp.1_3(3), 0B(2)>
1719 : D.1879_6 = middleman_1 (iftmp.1_1, i_5(D));
1720 : return D.1879_6; */
1721 :
1722 : static void
1723 93775 : compute_complex_ancestor_jump_func (struct ipa_func_body_info *fbi,
1724 : class ipa_node_params *info,
1725 : struct ipa_jump_func *jfunc,
1726 : gcall *call, gphi *phi)
1727 : {
1728 93775 : HOST_WIDE_INT offset;
1729 93775 : gimple *assign;
1730 93775 : basic_block phi_bb, assign_bb, cond_bb;
1731 93775 : tree tmp, parm, expr, obj;
1732 93775 : int index, i;
1733 :
1734 93775 : if (gimple_phi_num_args (phi) != 2)
1735 93761 : return;
1736 :
1737 78143 : if (integer_zerop (PHI_ARG_DEF (phi, 1)))
1738 4213 : tmp = PHI_ARG_DEF (phi, 0);
1739 73930 : else if (integer_zerop (PHI_ARG_DEF (phi, 0)))
1740 13034 : tmp = PHI_ARG_DEF (phi, 1);
1741 : else
1742 : return;
1743 17247 : if (TREE_CODE (tmp) != SSA_NAME
1744 15108 : || SSA_NAME_IS_DEFAULT_DEF (tmp)
1745 14997 : || !POINTER_TYPE_P (TREE_TYPE (tmp))
1746 19977 : || TREE_CODE (TREE_TYPE (TREE_TYPE (tmp))) != RECORD_TYPE)
1747 : return;
1748 :
1749 1026 : assign = SSA_NAME_DEF_STMT (tmp);
1750 1026 : assign_bb = gimple_bb (assign);
1751 94368 : if (!single_pred_p (assign_bb))
1752 : return;
1753 607 : expr = get_ancestor_addr_info (assign, &obj, &offset);
1754 607 : if (!expr)
1755 : return;
1756 26 : parm = TREE_OPERAND (expr, 0);
1757 26 : index = ipa_get_param_decl_index (info, SSA_NAME_VAR (parm));
1758 26 : if (index < 0)
1759 : return;
1760 :
1761 26 : cond_bb = single_pred (assign_bb);
1762 93813 : gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (cond_bb));
1763 26 : if (!cond
1764 26 : || gimple_cond_code (cond) != NE_EXPR
1765 26 : || gimple_cond_lhs (cond) != parm
1766 14 : || !integer_zerop (gimple_cond_rhs (cond)))
1767 : return;
1768 :
1769 14 : phi_bb = gimple_bb (phi);
1770 42 : for (i = 0; i < 2; i++)
1771 : {
1772 28 : basic_block pred = EDGE_PRED (phi_bb, i)->src;
1773 28 : if (pred != assign_bb && pred != cond_bb)
1774 : return;
1775 : }
1776 :
1777 14 : ipa_set_ancestor_jf (jfunc, offset, index,
1778 : parm_ref_data_pass_through_p (fbi, index, call, parm),
1779 : true);
1780 : }
1781 :
1782 : /* Inspect the given TYPE and return true iff it has the same structure (the
1783 : same number of fields of the same types) as a C++ member pointer. If
1784 : METHOD_PTR and DELTA are non-NULL, store the trees representing the
1785 : corresponding fields there. */
1786 :
1787 : static bool
1788 894 : type_like_member_ptr_p (tree type, tree *method_ptr, tree *delta)
1789 : {
1790 894 : tree fld;
1791 :
1792 894 : if (TREE_CODE (type) != RECORD_TYPE)
1793 : return false;
1794 :
1795 894 : fld = TYPE_FIELDS (type);
1796 894 : if (!fld || !POINTER_TYPE_P (TREE_TYPE (fld))
1797 894 : || TREE_CODE (TREE_TYPE (TREE_TYPE (fld))) != METHOD_TYPE
1798 1788 : || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
1799 : return false;
1800 :
1801 894 : if (method_ptr)
1802 894 : *method_ptr = fld;
1803 :
1804 894 : fld = DECL_CHAIN (fld);
1805 894 : if (!fld || INTEGRAL_TYPE_P (fld)
1806 1788 : || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
1807 : return false;
1808 894 : if (delta)
1809 894 : *delta = fld;
1810 :
1811 894 : if (DECL_CHAIN (fld))
1812 0 : return false;
1813 :
1814 : return true;
1815 : }
1816 :
1817 : /* If RHS is an SSA_NAME and it is defined by a simple copy assign statement,
1818 : return the rhs of its defining statement, and this statement is stored in
1819 : *RHS_STMT. Otherwise return RHS as it is. */
1820 :
1821 : static inline tree
1822 133560 : get_ssa_def_if_simple_copy (tree rhs, gimple **rhs_stmt)
1823 : {
1824 182228 : while (TREE_CODE (rhs) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (rhs))
1825 : {
1826 98266 : gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
1827 :
1828 98266 : if (gimple_assign_single_p (def_stmt))
1829 48668 : rhs = gimple_assign_rhs1 (def_stmt);
1830 : else
1831 : break;
1832 48668 : *rhs_stmt = def_stmt;
1833 : }
1834 133560 : return rhs;
1835 : }
1836 :
1837 : /* Simple linked list, describing contents of an aggregate before call. */
1838 :
1839 : struct ipa_known_agg_contents_list
1840 : {
1841 : /* Offset and size of the described part of the aggregate. */
1842 : HOST_WIDE_INT offset, size;
1843 :
1844 : /* Type of the described part of the aggregate. */
1845 : tree type;
1846 :
1847 : /* Known constant value or jump function data describing contents. */
1848 : struct ipa_load_agg_data value;
1849 :
1850 : /* Pointer to the next structure in the list. */
1851 : struct ipa_known_agg_contents_list *next;
1852 : };
1853 :
1854 : /* Add an aggregate content item into a linked list of
1855 : ipa_known_agg_contents_list structure, in which all elements
1856 : are sorted ascendingly by offset. */
1857 :
1858 : static inline void
1859 2844566 : add_to_agg_contents_list (struct ipa_known_agg_contents_list **plist,
1860 : struct ipa_known_agg_contents_list *item)
1861 : {
1862 2844566 : struct ipa_known_agg_contents_list *list = *plist;
1863 :
1864 5216611 : for (; list; list = list->next)
1865 : {
1866 3953967 : if (list->offset >= item->offset)
1867 : break;
1868 :
1869 2372045 : plist = &list->next;
1870 : }
1871 :
1872 2844566 : item->next = list;
1873 2844566 : *plist = item;
1874 : }
1875 :
1876 : /* Check whether a given aggregate content is clobbered by certain element in
1877 : a linked list of ipa_known_agg_contents_list. */
1878 :
1879 : static inline bool
1880 1105799 : clobber_by_agg_contents_list_p (struct ipa_known_agg_contents_list *list,
1881 : struct ipa_known_agg_contents_list *item)
1882 : {
1883 2330349 : for (; list; list = list->next)
1884 : {
1885 1872761 : if (list->offset >= item->offset)
1886 635545 : return list->offset < item->offset + item->size;
1887 :
1888 1237216 : if (list->offset + list->size > item->offset)
1889 : return true;
1890 : }
1891 :
1892 : return false;
1893 : }
1894 :
1895 : /* Build aggregate jump function from LIST, assuming there are exactly
1896 : VALUE_COUNT entries there and that offset of the passed argument
1897 : is ARG_OFFSET and store it into JFUNC. */
1898 :
1899 : static void
1900 364956 : build_agg_jump_func_from_list (struct ipa_known_agg_contents_list *list,
1901 : int value_count, HOST_WIDE_INT arg_offset,
1902 : struct ipa_jump_func *jfunc)
1903 : {
1904 364956 : vec_safe_reserve (jfunc->agg.items, value_count, true);
1905 1773617 : for (; list; list = list->next)
1906 : {
1907 1043705 : struct ipa_agg_jf_item item;
1908 1043705 : tree operand = list->value.pass_through.operand;
1909 :
1910 1043705 : if (list->value.pass_through.formal_id >= 0)
1911 : {
1912 : /* Content value is derived from some formal parameter. */
1913 93776 : if (list->value.offset >= 0)
1914 : item.jftype = IPA_JF_LOAD_AGG;
1915 : else
1916 43701 : item.jftype = IPA_JF_PASS_THROUGH;
1917 :
1918 93776 : item.value.load_agg = list->value;
1919 93776 : if (operand)
1920 9562 : item.value.pass_through.operand
1921 9562 : = unshare_expr_without_location (operand);
1922 : }
1923 949929 : else if (operand)
1924 : {
1925 : /* Content value is known constant. */
1926 949929 : item.jftype = IPA_JF_CONST;
1927 949929 : item.value.constant = unshare_expr_without_location (operand);
1928 : }
1929 : else
1930 0 : continue;
1931 :
1932 1043705 : item.type = list->type;
1933 1043705 : gcc_assert (tree_to_shwi (TYPE_SIZE (list->type)) == list->size);
1934 :
1935 1043705 : item.offset = list->offset - arg_offset;
1936 1043705 : gcc_assert ((item.offset % BITS_PER_UNIT) == 0);
1937 :
1938 1043705 : jfunc->agg.items->quick_push (item);
1939 : }
1940 364956 : }
1941 :
1942 : /* Given an assignment statement STMT, try to collect information into
1943 : AGG_VALUE that will be used to construct jump function for RHS of the
1944 : assignment, from which content value of an aggregate part comes.
1945 :
1946 : Besides constant and simple pass-through jump functions, also try to
1947 : identify whether it matches the following pattern that can be described by
1948 : a load-value-from-aggregate jump function, which is a derivative of simple
1949 : pass-through jump function.
1950 :
1951 : foo (int *p)
1952 : {
1953 : ...
1954 :
1955 : *(q_5 + 4) = *(p_3(D) + 28) op 1;
1956 : bar (q_5);
1957 : }
1958 :
1959 : Here IPA_LOAD_AGG_DATA data structure is informative enough to describe
1960 : constant, simple pass-through and load-vale-from-aggregate. If value
1961 : is constant, it will be kept in field OPERAND, and field FORMAL_ID is
1962 : set to -1. For simple pass-through and load-value-from-aggregate, field
1963 : FORMAL_ID specifies the related formal parameter index, and field
1964 : OFFSET can be used to distinguish them, -1 means simple pass-through,
1965 : otherwise means load-value-from-aggregate. */
1966 :
1967 : static void
1968 1803124 : analyze_agg_content_value (struct ipa_func_body_info *fbi,
1969 : struct ipa_load_agg_data *agg_value,
1970 : gimple *stmt)
1971 : {
1972 1803124 : tree lhs = gimple_assign_lhs (stmt);
1973 1803124 : tree rhs1 = gimple_assign_rhs1 (stmt);
1974 1803124 : enum tree_code code;
1975 1803124 : int index = -1;
1976 :
1977 : /* Initialize jump function data for the aggregate part. */
1978 1803124 : memset (agg_value, 0, sizeof (*agg_value));
1979 1803124 : agg_value->pass_through.operation = NOP_EXPR;
1980 1803124 : agg_value->pass_through.formal_id = -1;
1981 1803124 : agg_value->offset = -1;
1982 :
1983 1803124 : if (AGGREGATE_TYPE_P (TREE_TYPE (lhs)) /* TODO: Support aggregate type. */
1984 1606773 : || TREE_THIS_VOLATILE (lhs)
1985 1606103 : || TREE_CODE (lhs) == BIT_FIELD_REF
1986 1606095 : || contains_bitfld_component_ref_p (lhs))
1987 : return;
1988 :
1989 : /* Skip SSA copies. */
1990 1893651 : while (gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS)
1991 : {
1992 1803900 : if (TREE_CODE (rhs1) != SSA_NAME || SSA_NAME_IS_DEFAULT_DEF (rhs1))
1993 : break;
1994 :
1995 389457 : stmt = SSA_NAME_DEF_STMT (rhs1);
1996 389457 : if (!is_gimple_assign (stmt))
1997 : break;
1998 :
1999 297012 : lhs = gimple_assign_lhs (stmt);
2000 297012 : rhs1 = gimple_assign_rhs1 (stmt);
2001 : }
2002 :
2003 1596639 : if (gphi *phi = dyn_cast<gphi *> (stmt))
2004 : {
2005 : /* Also special case like the following (a is a formal parameter):
2006 :
2007 : _12 = *a_11(D).dim[0].stride;
2008 : ...
2009 : # iftmp.22_9 = PHI <_12(2), 1(3)>
2010 : ...
2011 : parm.6.dim[0].stride = iftmp.22_9;
2012 : ...
2013 : __x_MOD_foo (&parm.6, b_31(D));
2014 :
2015 : The aggregate function describing parm.6.dim[0].stride is encoded as a
2016 : PASS-THROUGH jump function with ASSERT_EXPR operation with operand 1
2017 : (the constant from the PHI node). */
2018 :
2019 35478 : if (gimple_phi_num_args (phi) != 2
2020 35478 : || lto_variably_modified_type_p (TREE_TYPE (lhs)))
2021 : return;
2022 28733 : tree arg0 = gimple_phi_arg_def (phi, 0);
2023 28733 : tree arg1 = gimple_phi_arg_def (phi, 1);
2024 28733 : tree operand;
2025 :
2026 28733 : if (is_gimple_ip_invariant (arg1))
2027 : {
2028 : operand = arg1;
2029 : rhs1 = arg0;
2030 : }
2031 23645 : else if (is_gimple_ip_invariant (arg0))
2032 : {
2033 : operand = arg0;
2034 : rhs1 = arg1;
2035 : }
2036 : else
2037 : return;
2038 :
2039 11299 : rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt);
2040 11299 : if (!is_gimple_assign (stmt))
2041 : return;
2042 :
2043 5742 : code = ASSERT_EXPR;
2044 5742 : agg_value->pass_through.operand = operand;
2045 5742 : agg_value->pass_through.op_type = TREE_TYPE (lhs);
2046 : }
2047 1561161 : else if (is_gimple_assign (stmt))
2048 : {
2049 1504194 : code = gimple_assign_rhs_code (stmt);
2050 1504194 : switch (gimple_assign_rhs_class (stmt))
2051 : {
2052 1414443 : case GIMPLE_SINGLE_RHS:
2053 1414443 : if (is_gimple_ip_invariant (rhs1))
2054 : {
2055 1009851 : agg_value->pass_through.operand = rhs1;
2056 1009851 : return;
2057 : }
2058 : code = NOP_EXPR;
2059 : break;
2060 :
2061 29183 : case GIMPLE_UNARY_RHS:
2062 : /* NOTE: A GIMPLE_UNARY_RHS operation might not be tcc_unary
2063 : (truth_not_expr is example), GIMPLE_BINARY_RHS does not imply
2064 : tcc_binary, this subtleness is somewhat misleading.
2065 :
2066 : Since tcc_unary is widely used in IPA-CP code to check an operation
2067 : with one operand, here we only allow tc_unary operation to avoid
2068 : possible problem. Then we can use (opclass == tc_unary) or not to
2069 : distinguish unary and binary. */
2070 29183 : if (TREE_CODE_CLASS (code) != tcc_unary || CONVERT_EXPR_CODE_P (code)
2071 31702 : || lto_variably_modified_type_p (TREE_TYPE (lhs)))
2072 : return;
2073 :
2074 2519 : rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt);
2075 2519 : agg_value->pass_through.op_type = TREE_TYPE (lhs);
2076 2519 : break;
2077 :
2078 59875 : case GIMPLE_BINARY_RHS:
2079 59875 : {
2080 59875 : gimple *rhs1_stmt = stmt;
2081 59875 : gimple *rhs2_stmt = stmt;
2082 59875 : tree rhs2 = gimple_assign_rhs2 (stmt);
2083 :
2084 59875 : if (lto_variably_modified_type_p (TREE_TYPE (lhs)))
2085 30939 : return;
2086 :
2087 59871 : rhs1 = get_ssa_def_if_simple_copy (rhs1, &rhs1_stmt);
2088 59871 : rhs2 = get_ssa_def_if_simple_copy (rhs2, &rhs2_stmt);
2089 :
2090 59871 : if (is_gimple_ip_invariant (rhs2))
2091 : {
2092 28936 : agg_value->pass_through.operand = rhs2;
2093 28936 : agg_value->pass_through.op_type = TREE_TYPE (lhs);
2094 28936 : stmt = rhs1_stmt;
2095 : }
2096 30935 : else if (is_gimple_ip_invariant (rhs1))
2097 : {
2098 2266 : if (TREE_CODE_CLASS (code) == tcc_comparison)
2099 0 : code = swap_tree_comparison (code);
2100 2266 : else if (!commutative_tree_code (code))
2101 : return;
2102 :
2103 0 : agg_value->pass_through.operand = rhs1;
2104 0 : agg_value->pass_through.op_type = TREE_TYPE (lhs);
2105 0 : stmt = rhs2_stmt;
2106 0 : rhs1 = rhs2;
2107 : }
2108 : else
2109 : return;
2110 :
2111 28936 : if (TREE_CODE_CLASS (code) != tcc_comparison
2112 57435 : && !useless_type_conversion_p (TREE_TYPE (lhs),
2113 28499 : TREE_TYPE (rhs1)))
2114 : return;
2115 : }
2116 28936 : break;
2117 :
2118 : default:
2119 : return;
2120 : }
2121 : }
2122 : else
2123 : return;
2124 :
2125 441789 : if (TREE_CODE (rhs1) != SSA_NAME)
2126 379500 : index = load_from_unmodified_param_or_agg (fbi, fbi->info, stmt,
2127 : &agg_value->offset,
2128 : &agg_value->by_ref);
2129 62289 : else if (SSA_NAME_IS_DEFAULT_DEF (rhs1))
2130 47502 : index = ipa_get_param_decl_index (fbi->info, SSA_NAME_VAR (rhs1));
2131 :
2132 427002 : if (index >= 0)
2133 : {
2134 95948 : if (agg_value->offset >= 0)
2135 51960 : agg_value->type = TREE_TYPE (rhs1);
2136 95948 : agg_value->pass_through.formal_id = index;
2137 95948 : agg_value->pass_through.operation = code;
2138 : }
2139 : else
2140 345841 : agg_value->pass_through.operand = NULL_TREE;
2141 : }
2142 :
2143 : /* If STMT is a memory store to the object whose address is BASE, extract
2144 : information (offset, size, and value) into CONTENT, and return true,
2145 : otherwise we conservatively assume the whole object is modified with
2146 : unknown content, and return false. CHECK_REF means that access to object
2147 : is expected to be in form of MEM_REF expression. */
2148 :
2149 : static bool
2150 2950019 : extract_mem_content (struct ipa_func_body_info *fbi,
2151 : gimple *stmt, tree base, bool check_ref,
2152 : struct ipa_known_agg_contents_list *content)
2153 : {
2154 2950019 : HOST_WIDE_INT lhs_offset, lhs_size;
2155 2950019 : bool reverse;
2156 :
2157 2950019 : if (!is_gimple_assign (stmt))
2158 : return false;
2159 :
2160 1921571 : tree lhs = gimple_assign_lhs (stmt);
2161 1921571 : tree lhs_base = get_ref_base_and_extent_hwi (lhs, &lhs_offset, &lhs_size,
2162 : &reverse);
2163 1921571 : if (!lhs_base)
2164 : return false;
2165 :
2166 1919885 : if (check_ref)
2167 : {
2168 154363 : if (TREE_CODE (lhs_base) != MEM_REF
2169 124307 : || TREE_OPERAND (lhs_base, 0) != base
2170 202988 : || !integer_zerop (TREE_OPERAND (lhs_base, 1)))
2171 : return false;
2172 : }
2173 1765522 : else if (lhs_base != base)
2174 : return false;
2175 :
2176 1803124 : content->offset = lhs_offset;
2177 1803124 : content->size = lhs_size;
2178 1803124 : content->type = TREE_TYPE (lhs);
2179 1803124 : content->next = NULL;
2180 :
2181 1803124 : analyze_agg_content_value (fbi, &content->value, stmt);
2182 1803124 : return true;
2183 : }
2184 :
2185 : /* Traverse statements from CALL backwards, scanning whether an aggregate given
2186 : in ARG is filled in constants or values that are derived from caller's
2187 : formal parameter in the way described by some kinds of jump functions. FBI
2188 : is the context of the caller function for interprocedural analysis. ARG can
2189 : either be an aggregate expression or a pointer to an aggregate. ARG_TYPE is
2190 : the type of the aggregate, JFUNC is the jump function for the aggregate. */
2191 :
2192 : static void
2193 3506827 : determine_known_aggregate_parts (struct ipa_func_body_info *fbi,
2194 : gcall *call, tree arg,
2195 : tree arg_type,
2196 : struct ipa_jump_func *jfunc)
2197 : {
2198 3506827 : struct ipa_known_agg_contents_list *list = NULL, *all_list = NULL;
2199 3506827 : bitmap visited = NULL;
2200 3506827 : int item_count = 0, value_count = 0;
2201 3506827 : HOST_WIDE_INT arg_offset, arg_size;
2202 3506827 : tree arg_base;
2203 3506827 : bool check_ref, by_ref;
2204 3506827 : ao_ref r;
2205 3506827 : int max_agg_items = opt_for_fn (fbi->node->decl, param_ipa_max_agg_items);
2206 :
2207 3506827 : if (max_agg_items == 0)
2208 858219 : return;
2209 :
2210 : /* The function operates in three stages. First, we prepare check_ref, r,
2211 : arg_base and arg_offset based on what is actually passed as an actual
2212 : argument. */
2213 :
2214 3506827 : if (POINTER_TYPE_P (arg_type))
2215 : {
2216 3122878 : by_ref = true;
2217 3122878 : if (TREE_CODE (arg) == SSA_NAME)
2218 : {
2219 1134949 : tree type_size;
2220 1134949 : if (!tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (arg_type)))
2221 1134949 : || !POINTER_TYPE_P (TREE_TYPE (arg)))
2222 : return;
2223 813243 : check_ref = true;
2224 813243 : arg_base = arg;
2225 813243 : arg_offset = 0;
2226 813243 : type_size = TYPE_SIZE (TREE_TYPE (arg_type));
2227 813243 : arg_size = tree_to_uhwi (type_size);
2228 813243 : ao_ref_init_from_ptr_and_size (&r, arg_base, NULL_TREE);
2229 : }
2230 1987929 : else if (TREE_CODE (arg) == ADDR_EXPR)
2231 : {
2232 1912425 : bool reverse;
2233 :
2234 1912425 : arg = TREE_OPERAND (arg, 0);
2235 1912425 : arg_base = get_ref_base_and_extent_hwi (arg, &arg_offset,
2236 : &arg_size, &reverse);
2237 1912425 : if (!arg_base)
2238 460933 : return;
2239 1911209 : if (DECL_P (arg_base))
2240 : {
2241 1451492 : check_ref = false;
2242 1451492 : ao_ref_init (&r, arg_base);
2243 : }
2244 : else
2245 : return;
2246 : }
2247 : else
2248 : return;
2249 : }
2250 : else
2251 : {
2252 383949 : bool reverse;
2253 :
2254 383949 : gcc_checking_assert (AGGREGATE_TYPE_P (TREE_TYPE (arg)));
2255 :
2256 383949 : by_ref = false;
2257 383949 : check_ref = false;
2258 383949 : arg_base = get_ref_base_and_extent_hwi (arg, &arg_offset,
2259 : &arg_size, &reverse);
2260 383949 : if (!arg_base)
2261 76 : return;
2262 :
2263 383873 : ao_ref_init (&r, arg);
2264 : }
2265 :
2266 : /* Second stage traverses virtual SSA web backwards starting from the call
2267 : statement, only looks at individual dominating virtual operand (its
2268 : definition dominates the call), as long as it is confident that content
2269 : of the aggregate is affected by definition of the virtual operand, it
2270 : builds a sorted linked list of ipa_agg_jf_list describing that. */
2271 :
2272 5297216 : for (tree dom_vuse = gimple_vuse (call);
2273 26493650 : dom_vuse && fbi->aa_walk_budget > 0;)
2274 : {
2275 25961655 : gimple *stmt = SSA_NAME_DEF_STMT (dom_vuse);
2276 :
2277 25961655 : if (gphi *phi = dyn_cast <gphi *> (stmt))
2278 : {
2279 2664706 : dom_vuse = get_continuation_for_phi (phi, &r, true,
2280 1332353 : fbi->aa_walk_budget,
2281 : &visited, false, NULL, NULL);
2282 1332353 : continue;
2283 : }
2284 :
2285 24629302 : fbi->aa_walk_budget--;
2286 24629302 : if (stmt_may_clobber_ref_p_1 (stmt, &r))
2287 : {
2288 2950019 : struct ipa_known_agg_contents_list *content
2289 2950019 : = XALLOCA (struct ipa_known_agg_contents_list);
2290 :
2291 2950019 : if (!extract_mem_content (fbi, stmt, arg_base, check_ref, content))
2292 : break;
2293 :
2294 : /* Now we get a dominating virtual operand, and need to check
2295 : whether its value is clobbered any other dominating one. */
2296 1803124 : if ((content->value.pass_through.formal_id >= 0
2297 1707176 : || content->value.pass_through.operand)
2298 1105799 : && !clobber_by_agg_contents_list_p (all_list, content)
2299 : /* Since IPA-CP stores results with unsigned int offsets, we can
2300 : discard those which would not fit now before we stream them to
2301 : WPA. */
2302 2846967 : && (content->offset + content->size - arg_offset
2303 : <= (HOST_WIDE_INT) UINT_MAX * BITS_PER_UNIT))
2304 : {
2305 1043705 : struct ipa_known_agg_contents_list *copy
2306 1043705 : = XALLOCA (struct ipa_known_agg_contents_list);
2307 :
2308 : /* Add to the list consisting of only dominating virtual
2309 : operands, whose definitions can finally reach the call. */
2310 1043705 : add_to_agg_contents_list (&list, (*copy = *content, copy));
2311 :
2312 1043705 : if (++value_count == max_agg_items)
2313 : break;
2314 : }
2315 :
2316 : /* Add to the list consisting of all dominating virtual operands. */
2317 1800861 : add_to_agg_contents_list (&all_list, content);
2318 :
2319 1800861 : if (++item_count == 2 * max_agg_items)
2320 : break;
2321 : }
2322 45991629 : dom_vuse = gimple_vuse (stmt);
2323 : }
2324 :
2325 2648608 : if (visited)
2326 663045 : BITMAP_FREE (visited);
2327 :
2328 : /* Third stage just goes over the list and creates an appropriate vector of
2329 : ipa_agg_jf_item structures out of it, of course only if there are
2330 : any meaningful items to begin with. */
2331 :
2332 2648608 : if (value_count)
2333 : {
2334 364956 : jfunc->agg.by_ref = by_ref;
2335 364956 : build_agg_jump_func_from_list (list, value_count, arg_offset, jfunc);
2336 : }
2337 : }
2338 :
2339 :
2340 : /* Return the Ith param type of callee associated with call graph
2341 : edge E. */
2342 :
2343 : tree
2344 6459689 : ipa_get_callee_param_type (struct cgraph_edge *e, int i)
2345 : {
2346 6459689 : int n;
2347 6459689 : tree type = (e->callee
2348 6459689 : ? TREE_TYPE (e->callee->decl)
2349 6459689 : : gimple_call_fntype (e->call_stmt));
2350 6459689 : tree t = TYPE_ARG_TYPES (type);
2351 :
2352 13255791 : for (n = 0; n < i; n++)
2353 : {
2354 7050051 : if (!t)
2355 : break;
2356 6796102 : t = TREE_CHAIN (t);
2357 : }
2358 6459689 : if (t && t != void_list_node)
2359 6111696 : return TREE_VALUE (t);
2360 347993 : if (!e->callee)
2361 : return NULL;
2362 324915 : t = DECL_ARGUMENTS (e->callee->decl);
2363 851732 : for (n = 0; n < i; n++)
2364 : {
2365 807179 : if (!t)
2366 : return NULL;
2367 526817 : t = TREE_CHAIN (t);
2368 : }
2369 44553 : if (t)
2370 2192 : return TREE_TYPE (t);
2371 : return NULL;
2372 : }
2373 :
2374 : /* Return a pointer to an ipa_vr just like TMP, but either find it in
2375 : ipa_vr_hash_table or allocate it in GC memory. */
2376 :
2377 : static ipa_vr *
2378 5951202 : ipa_get_value_range (const vrange &tmp)
2379 : {
2380 5951202 : inchash::hash hstate;
2381 5951202 : inchash::add_vrange (tmp, hstate);
2382 5951202 : hashval_t hash = hstate.end ();
2383 5951202 : ipa_vr **slot = ipa_vr_hash_table->find_slot_with_hash (&tmp, hash, INSERT);
2384 5951202 : if (*slot)
2385 : return *slot;
2386 :
2387 2568159 : ipa_vr *vr = new (ggc_alloc<ipa_vr> ()) ipa_vr (tmp);
2388 2568159 : *slot = vr;
2389 2568159 : return vr;
2390 : }
2391 :
2392 : /* Assign to JF a pointer to a range just like TMP but either fetch a
2393 : copy from ipa_vr_hash_table or allocate a new on in GC memory. */
2394 :
2395 : static void
2396 5178496 : ipa_set_jfunc_vr (ipa_jump_func *jf, const vrange &tmp)
2397 : {
2398 1966987 : jf->m_vr = ipa_get_value_range (tmp);
2399 0 : }
2400 :
2401 : static void
2402 613737 : ipa_set_jfunc_vr (ipa_jump_func *jf, const ipa_vr &vr)
2403 : {
2404 613737 : value_range tmp;
2405 613737 : vr.get_vrange (tmp);
2406 613737 : ipa_set_jfunc_vr (jf, tmp);
2407 613737 : }
2408 :
2409 : /* Given VAL that conforms to is_gimple_ip_invariant, produce a VRANGE that
2410 : represents it as a range. CONTEXT_NODE is the call graph node representing
2411 : the function for which optimization flags should be evaluated. */
2412 :
2413 : void
2414 1703558 : ipa_get_range_from_ip_invariant (vrange &r, tree val, cgraph_node *context_node)
2415 : {
2416 1703558 : if (TREE_CODE (val) == ADDR_EXPR)
2417 : {
2418 996 : symtab_node *symbol;
2419 996 : tree base = TREE_OPERAND (val, 0);
2420 996 : if (!DECL_P (base))
2421 : {
2422 182 : r.set_varying (TREE_TYPE (val));
2423 182 : return;
2424 : }
2425 814 : if (!decl_in_symtab_p (base))
2426 : {
2427 0 : r.set_nonzero (TREE_TYPE (val));
2428 0 : return;
2429 : }
2430 814 : if (!(symbol = symtab_node::get (base)))
2431 : {
2432 0 : r.set_varying (TREE_TYPE (val));
2433 0 : return;
2434 : }
2435 :
2436 814 : bool delete_null_pointer_checks
2437 814 : = opt_for_fn (context_node->decl, flag_delete_null_pointer_checks);
2438 814 : if (symbol->nonzero_address (delete_null_pointer_checks))
2439 814 : r.set_nonzero (TREE_TYPE (val));
2440 : else
2441 0 : r.set_varying (TREE_TYPE (val));
2442 : }
2443 : else
2444 1702562 : r.set (val, val);
2445 : }
2446 :
2447 : /* If T is an SSA_NAME that is the result of a simple type conversion statement
2448 : from an integer type to another integer type which is known to be able to
2449 : represent the values the operand of the conversion can hold, return the
2450 : operand of that conversion, otherwise return T. */
2451 :
2452 : static tree
2453 6459689 : skip_a_safe_conversion_op (tree t)
2454 : {
2455 6459689 : if (TREE_CODE (t) != SSA_NAME
2456 6459689 : || SSA_NAME_IS_DEFAULT_DEF (t))
2457 : return t;
2458 :
2459 1581002 : gimple *def = SSA_NAME_DEF_STMT (t);
2460 1581002 : if (!is_gimple_assign (def)
2461 1308478 : || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))
2462 258888 : || !INTEGRAL_TYPE_P (TREE_TYPE (t))
2463 1774689 : || !INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def))))
2464 : return t;
2465 :
2466 185643 : tree rhs1 = gimple_assign_rhs1 (def);
2467 185643 : if (TYPE_PRECISION (TREE_TYPE (t))
2468 185643 : >= TYPE_PRECISION (TREE_TYPE (rhs1)))
2469 : return gimple_assign_rhs1 (def);
2470 :
2471 9183 : value_range vr (TREE_TYPE (rhs1));
2472 18366 : if (!get_range_query (cfun)->range_of_expr (vr, rhs1, def)
2473 9183 : || vr.undefined_p ())
2474 : return t;
2475 :
2476 9165 : irange &ir = as_a <irange> (vr);
2477 9165 : if (range_fits_type_p (&ir, TYPE_PRECISION (TREE_TYPE (t)),
2478 9165 : TYPE_SIGN (TREE_TYPE (t))))
2479 4565 : return gimple_assign_rhs1 (def);
2480 :
2481 : return t;
2482 9183 : }
2483 :
2484 : /* Compute jump function for all arguments of callsite CS and insert the
2485 : information in the jump_functions array in the ipa_edge_args corresponding
2486 : to this callsite. */
2487 :
2488 : static void
2489 3055669 : ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
2490 : struct cgraph_edge *cs)
2491 : {
2492 3055669 : ipa_node_params *info = ipa_node_params_sum->get (cs->caller);
2493 3055669 : ipa_edge_args *args = ipa_edge_args_sum->get_create (cs);
2494 3055669 : gcall *call = cs->call_stmt;
2495 3055669 : int n, arg_num = gimple_call_num_args (call);
2496 3055669 : bool useful_context = false;
2497 :
2498 3055669 : if (arg_num == 0 || args->jump_functions)
2499 276194 : return;
2500 2779475 : vec_safe_grow_cleared (args->jump_functions, arg_num, true);
2501 2779475 : if (flag_devirtualize)
2502 2595969 : vec_safe_grow_cleared (args->polymorphic_call_contexts, arg_num, true);
2503 :
2504 2779475 : if (ipa_func_spec_opts_forbid_analysis_p (cs->caller))
2505 : return;
2506 :
2507 2779475 : auto_vec<cgraph_edge*> callback_edges;
2508 9239164 : for (n = 0; n < arg_num; n++)
2509 : {
2510 6459689 : struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, n);
2511 6459689 : tree arg = gimple_call_arg (call, n);
2512 6459689 : tree param_type = ipa_get_callee_param_type (cs, n);
2513 6459689 : if (flag_devirtualize && POINTER_TYPE_P (TREE_TYPE (arg)))
2514 : {
2515 3353608 : tree instance;
2516 3353608 : class ipa_polymorphic_call_context context (cs->caller->decl,
2517 3353608 : arg, cs->call_stmt,
2518 3353608 : &instance);
2519 3353608 : context.get_dynamic_type (instance, arg, NULL, cs->call_stmt,
2520 : &fbi->aa_walk_budget);
2521 3353608 : *ipa_get_ith_polymorhic_call_context (args, n) = context;
2522 6707216 : if (!context.useless_p ())
2523 293402 : useful_context = true;
2524 : }
2525 :
2526 6459689 : value_range vr (TREE_TYPE (arg));
2527 6459689 : if (POINTER_TYPE_P (TREE_TYPE (arg)))
2528 : {
2529 7225540 : if (!get_range_query (cfun)->range_of_expr (vr, arg, cs->call_stmt)
2530 3612770 : || vr.varying_p ()
2531 6339834 : || vr.undefined_p ())
2532 : {
2533 886122 : if (tree_single_nonzero_p (arg))
2534 0 : vr.set_nonzero (TREE_TYPE (arg));
2535 : else
2536 886122 : vr.set_varying (TREE_TYPE (arg));
2537 : }
2538 3612770 : gcc_assert (!vr.undefined_p ());
2539 3612770 : unsigned HOST_WIDE_INT bitpos;
2540 3612770 : unsigned align = BITS_PER_UNIT;
2541 :
2542 3612770 : if (!vr.singleton_p ())
2543 3537682 : get_pointer_alignment_1 (arg, &align, &bitpos);
2544 :
2545 3612770 : if (align > BITS_PER_UNIT
2546 3612770 : && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp))
2547 : {
2548 1353250 : unsigned prec = TYPE_PRECISION (TREE_TYPE (arg));
2549 1353250 : wide_int mask
2550 2706500 : = wi::bit_and_not (wi::mask (prec, false, prec),
2551 1353250 : wide_int::from (align / BITS_PER_UNIT - 1,
2552 1353250 : prec, UNSIGNED));
2553 1353250 : wide_int value = wide_int::from (bitpos / BITS_PER_UNIT, prec,
2554 1353250 : UNSIGNED);
2555 1353250 : irange_bitmask bm (value, mask);
2556 1353250 : vr.update_bitmask (bm);
2557 1353250 : ipa_set_jfunc_vr (jfunc, vr);
2558 1353250 : }
2559 2259520 : else if (!vr.varying_p ())
2560 1397285 : ipa_set_jfunc_vr (jfunc, vr);
2561 : else
2562 862235 : gcc_assert (!jfunc->m_vr);
2563 : }
2564 : else
2565 : {
2566 2846919 : if (param_type
2567 2535244 : && ipa_vr_supported_type_p (TREE_TYPE (arg))
2568 2847060 : && ipa_vr_supported_type_p (param_type)
2569 3765664 : && get_range_query (cfun)->range_of_expr (vr, arg, cs->call_stmt)
2570 4729751 : && !vr.undefined_p ())
2571 : {
2572 1882691 : value_range resvr (vr);
2573 1882691 : range_cast (resvr, param_type);
2574 1882691 : if (!resvr.undefined_p () && !resvr.varying_p ())
2575 1507398 : ipa_set_jfunc_vr (jfunc, resvr);
2576 : else
2577 375293 : gcc_assert (!jfunc->m_vr);
2578 1882691 : }
2579 : else
2580 964228 : gcc_assert (!jfunc->m_vr);
2581 : }
2582 :
2583 6459689 : arg = skip_a_safe_conversion_op (arg);
2584 6459689 : if (is_gimple_ip_invariant (arg)
2585 6459689 : || (VAR_P (arg) && is_global_var (arg) && TREE_READONLY (arg)))
2586 : {
2587 2349077 : ipa_set_jf_constant (jfunc, arg, cs);
2588 2349077 : if (TREE_CODE (arg) == ADDR_EXPR)
2589 : {
2590 889049 : tree pointee = TREE_OPERAND (arg, 0);
2591 889049 : if (TREE_CODE (pointee) == FUNCTION_DECL && !cs->callback
2592 44608 : && cs->callee)
2593 : {
2594 : /* Argument is a pointer to a function. Look for a callback
2595 : attribute describing this argument. */
2596 44254 : tree callback_attr
2597 44254 : = lookup_attribute ("callback_only",
2598 44254 : DECL_ATTRIBUTES (cs->callee->decl));
2599 88509 : for (; callback_attr;
2600 : callback_attr
2601 1 : = lookup_attribute ("callback_only",
2602 1 : TREE_CHAIN (callback_attr)))
2603 13358 : if (callback_get_fn_index (callback_attr) == n)
2604 : break;
2605 :
2606 : /* If no callback attribute is found, check if the function is
2607 : a special case. */
2608 44254 : if (!callback_attr
2609 44254 : && callback_is_special_cased (cs->callee->decl, call))
2610 : {
2611 1770 : callback_attr
2612 1770 : = callback_special_case_attr (cs->callee->decl);
2613 : /* Check if the special attribute describes the correct
2614 : attribute, as a special cased function might have
2615 : multiple callbacks. */
2616 1770 : if (callback_get_fn_index (callback_attr) != n)
2617 : callback_attr = NULL;
2618 : }
2619 :
2620 : /* If a callback attribute describing this pointer is found,
2621 : create a callback edge to the pointee function to
2622 : allow for further optimizations. */
2623 44254 : if (callback_attr)
2624 : {
2625 15127 : cgraph_node *kernel_node
2626 15127 : = cgraph_node::get_create (pointee);
2627 15127 : cgraph_edge *cbe
2628 15127 : = cs->make_callback (kernel_node, n, callback_attr);
2629 15127 : callback_edges.safe_push (cbe);
2630 : }
2631 : }
2632 : }
2633 : }
2634 4110612 : else if (!is_gimple_reg_type (TREE_TYPE (arg))
2635 4110612 : && TREE_CODE (arg) == PARM_DECL)
2636 : {
2637 80721 : int index = ipa_get_param_decl_index (info, arg);
2638 :
2639 80721 : gcc_assert (index >=0);
2640 : /* Aggregate passed by value, check for pass-through, otherwise we
2641 : will attempt to fill in aggregate contents later in this
2642 : for cycle. */
2643 80721 : if (parm_preserved_before_stmt_p (fbi, index, call, arg))
2644 : {
2645 65509 : ipa_set_jf_simple_pass_through (jfunc, index, false);
2646 65509 : continue;
2647 : }
2648 : }
2649 4029891 : else if (TREE_CODE (arg) == SSA_NAME)
2650 : {
2651 2610404 : if (SSA_NAME_IS_DEFAULT_DEF (arg))
2652 : {
2653 1040325 : int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg));
2654 1040325 : if (index >= 0)
2655 : {
2656 1029811 : bool agg_p;
2657 1029811 : agg_p = parm_ref_data_pass_through_p (fbi, index, call, arg);
2658 1029811 : ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
2659 : }
2660 : }
2661 : else
2662 : {
2663 1570079 : gimple *stmt = SSA_NAME_DEF_STMT (arg);
2664 1570079 : if (is_gimple_assign (stmt))
2665 1283723 : compute_complex_assign_jump_func (fbi, info, jfunc,
2666 : call, stmt, arg, param_type);
2667 286356 : else if (gimple_code (stmt) == GIMPLE_PHI)
2668 93775 : compute_complex_ancestor_jump_func (fbi, info, jfunc,
2669 : call,
2670 : as_a <gphi *> (stmt));
2671 : }
2672 : }
2673 :
2674 : /* If ARG is pointer, we cannot use its type to determine the type of aggregate
2675 : passed (because type conversions are ignored in gimple). Usually we can
2676 : safely get type from function declaration, but in case of K&R prototypes or
2677 : variadic functions we can try our luck with type of the pointer passed.
2678 : TODO: Since we look for actual initialization of the memory object, we may better
2679 : work out the type based on the memory stores we find. */
2680 6394180 : if (!param_type)
2681 345799 : param_type = TREE_TYPE (arg);
2682 :
2683 6394180 : if ((jfunc->type != IPA_JF_PASS_THROUGH
2684 1076662 : || !ipa_get_jf_pass_through_agg_preserved (jfunc))
2685 5996937 : && (jfunc->type != IPA_JF_ANCESTOR
2686 171272 : || !ipa_get_jf_ancestor_agg_preserved (jfunc))
2687 12323836 : && (AGGREGATE_TYPE_P (TREE_TYPE (arg))
2688 5545647 : || POINTER_TYPE_P (param_type)))
2689 3506827 : determine_known_aggregate_parts (fbi, call, arg, param_type, jfunc);
2690 6459689 : }
2691 :
2692 2779475 : if (!callback_edges.is_empty ())
2693 : {
2694 : /* For every callback edge, fetch jump functions of arguments
2695 : passed to them and copy them over to their respective summaries.
2696 : This avoids recalculating them for every callback edge, since their
2697 : arguments are just passed through. */
2698 : unsigned j;
2699 30253 : for (j = 0; j < callback_edges.length (); j++)
2700 : {
2701 15127 : cgraph_edge *callback_edge = callback_edges[j];
2702 15127 : ipa_edge_args *cb_summary
2703 15127 : = ipa_edge_args_sum->get_create (callback_edge);
2704 15127 : callback_info *ci = callback_info_sum->get (callback_edge);
2705 15127 : auto_vec<int> &arg_mapping = ci->arg_mapping;
2706 15127 : unsigned i;
2707 30255 : for (i = 0; i < arg_mapping.length (); i++)
2708 : {
2709 15128 : if (arg_mapping[i] == ARG_MAPPING_UNKNOWN_IDX)
2710 0 : continue;
2711 15128 : class ipa_jump_func *src
2712 15128 : = ipa_get_ith_jump_func (args, arg_mapping[i]);
2713 15128 : class ipa_jump_func *dst = ipa_get_ith_jump_func (cb_summary, i);
2714 15128 : ipa_duplicate_jump_function (cs, callback_edge, src, dst);
2715 : }
2716 : }
2717 : }
2718 :
2719 2779475 : if (!useful_context)
2720 4817874 : vec_free (args->polymorphic_call_contexts);
2721 2779475 : }
2722 :
2723 : /* Compute jump functions for all edges - both direct and indirect - outgoing
2724 : from BB. */
2725 :
2726 : static void
2727 11311741 : ipa_compute_jump_functions_for_bb (struct ipa_func_body_info *fbi, basic_block bb)
2728 : {
2729 11311741 : struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
2730 11311741 : int i;
2731 11311741 : struct cgraph_edge *cs;
2732 :
2733 21159213 : FOR_EACH_VEC_ELT_REVERSE (bi->cg_edges, i, cs)
2734 : {
2735 5682487 : struct cgraph_node *callee = cs->callee;
2736 :
2737 5682487 : if (callee)
2738 : {
2739 5542111 : callee = callee->ultimate_alias_target ();
2740 : /* We do not need to bother analyzing calls to unknown functions
2741 : unless they may become known during lto/whopr. */
2742 3604344 : if (!callee->definition && !flag_lto
2743 5557224 : && !gimple_call_fnspec (cs->call_stmt).known_p ()
2744 8184042 : && !callback_edge_callee_has_attr (cs))
2745 2626818 : continue;
2746 : }
2747 3055669 : ipa_compute_jump_functions_for_edge (fbi, cs);
2748 : }
2749 11311741 : }
2750 :
2751 : /* If REF is a memory access that loads a function pointer (but not a method
2752 : pointer) from a RECORD_TYPE, return true and store the type of the RECORD to
2753 : *REC_TYPE and the byte offset of the field to *FLD_OFFSET. Otherwise return
2754 : false. OHS es the "other hand side" which is used to check type
2755 : compatibility with field in question, when possible. */
2756 :
2757 : static bool
2758 120880 : is_func_ptr_from_record (tree ref, tree *rec_type, unsigned *fld_offset,
2759 : tree ohs)
2760 : {
2761 120894 : if (!POINTER_TYPE_P (TREE_TYPE (ref))
2762 120894 : || TREE_CODE (TREE_TYPE (TREE_TYPE (ref))) != FUNCTION_TYPE)
2763 : return false;
2764 :
2765 105772 : if (TREE_CODE (ref) == COMPONENT_REF
2766 105772 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
2767 : {
2768 56774 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (ohs)));
2769 56774 : ohs = TREE_TYPE (TREE_TYPE (ohs));
2770 56774 : tree ftype = TREE_TYPE (TREE_OPERAND (ref, 1));
2771 56774 : if (!POINTER_TYPE_P (ftype))
2772 : return false;
2773 56774 : ftype = TREE_TYPE (ftype);
2774 56774 : if (!types_compatible_p (ohs, ftype))
2775 : return false;
2776 :
2777 56645 : tree tree_off = bit_position (TREE_OPERAND (ref, 1));
2778 56645 : if (!tree_fits_shwi_p (tree_off))
2779 : return false;
2780 56645 : HOST_WIDE_INT bit_offset = tree_to_shwi (tree_off);
2781 56645 : if (bit_offset % BITS_PER_UNIT)
2782 : return false;
2783 56645 : HOST_WIDE_INT unit_offset = bit_offset / BITS_PER_UNIT;
2784 56645 : if (unit_offset > UINT_MAX)
2785 : return false;
2786 56645 : *rec_type = TREE_TYPE (TREE_OPERAND (ref, 0));
2787 56645 : *fld_offset = unit_offset;
2788 56645 : return true;
2789 : }
2790 48998 : else if (TREE_CODE (ref) == MEM_REF
2791 5440 : && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0)))
2792 5440 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref, 0))))
2793 : == RECORD_TYPE)
2794 51550 : && tree_fits_shwi_p (TREE_OPERAND (ref, 1)))
2795 : {
2796 2552 : HOST_WIDE_INT unit_offset = tree_to_shwi (TREE_OPERAND (ref, 1));
2797 2552 : if (unit_offset > UINT_MAX)
2798 : return false;
2799 2552 : *rec_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref, 0)));
2800 2552 : *fld_offset = unit_offset;
2801 2552 : return true;
2802 : }
2803 : return false;
2804 : }
2805 :
2806 : /* If STMT looks like a statement loading a value from a member pointer formal
2807 : parameter, return that parameter and store the offset of the field to
2808 : *OFFSET_P, if it is non-NULL. Otherwise return NULL (but *OFFSET_P still
2809 : might be clobbered). If USE_DELTA, then we look for a use of the delta
2810 : field rather than the pfn. */
2811 :
2812 : static tree
2813 2197 : ipa_get_stmt_member_ptr_load_param (gimple *stmt, bool use_delta,
2814 : HOST_WIDE_INT *offset_p)
2815 : {
2816 2197 : tree rhs, fld, ptr_field, delta_field;
2817 2197 : tree ref_field = NULL_TREE;
2818 2197 : tree ref_offset = NULL_TREE;
2819 :
2820 2197 : if (!gimple_assign_single_p (stmt))
2821 : return NULL_TREE;
2822 :
2823 2197 : rhs = gimple_assign_rhs1 (stmt);
2824 2197 : if (TREE_CODE (rhs) == COMPONENT_REF)
2825 : {
2826 1322 : ref_field = TREE_OPERAND (rhs, 1);
2827 1322 : rhs = TREE_OPERAND (rhs, 0);
2828 : }
2829 :
2830 2197 : if (TREE_CODE (rhs) == MEM_REF)
2831 : {
2832 1483 : ref_offset = TREE_OPERAND (rhs, 1);
2833 1483 : if (ref_field && integer_nonzerop (ref_offset))
2834 : return NULL_TREE;
2835 : }
2836 714 : else if (!ref_field)
2837 : return NULL_TREE;
2838 :
2839 2197 : if (TREE_CODE (rhs) == MEM_REF
2840 1483 : && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
2841 3680 : && SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (rhs, 0)))
2842 : {
2843 606 : rhs = TREE_OPERAND (rhs, 0);
2844 606 : if (TREE_CODE (SSA_NAME_VAR (rhs)) != PARM_DECL
2845 606 : || !type_like_member_ptr_p (TREE_TYPE (TREE_TYPE (rhs)), &ptr_field,
2846 : &delta_field))
2847 : return NULL_TREE;
2848 : }
2849 : else
2850 : {
2851 1591 : if (TREE_CODE (rhs) == MEM_REF
2852 1591 : && TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR)
2853 0 : rhs = TREE_OPERAND (TREE_OPERAND (rhs, 0), 0);
2854 1591 : if (TREE_CODE (rhs) != PARM_DECL
2855 1591 : || !type_like_member_ptr_p (TREE_TYPE (rhs), &ptr_field,
2856 : &delta_field))
2857 : return NULL_TREE;
2858 : }
2859 :
2860 894 : if (use_delta)
2861 0 : fld = delta_field;
2862 : else
2863 894 : fld = ptr_field;
2864 :
2865 894 : if (ref_field)
2866 : {
2867 894 : if (ref_field != fld)
2868 : return NULL_TREE;
2869 : }
2870 0 : else if (!tree_int_cst_equal (byte_position (fld), ref_offset))
2871 : return NULL_TREE;
2872 :
2873 894 : if (offset_p)
2874 447 : *offset_p = int_bit_position (fld);
2875 : return rhs;
2876 : }
2877 :
2878 : /* Returns true iff T is an SSA_NAME defined by a statement. */
2879 :
2880 : static bool
2881 3091 : ipa_is_ssa_with_stmt_def (tree t)
2882 : {
2883 3091 : if (TREE_CODE (t) == SSA_NAME
2884 3091 : && !SSA_NAME_IS_DEFAULT_DEF (t))
2885 : return true;
2886 : else
2887 0 : return false;
2888 : }
2889 :
2890 : /* Analyze the CALL and examine uses of formal parameters of the caller NODE
2891 : (described by INFO). PARMS_AINFO is a pointer to a vector containing
2892 : intermediate information about each formal parameter. Currently it checks
2893 : whether the call calls a pointer that is a formal parameter and if so, the
2894 : parameter is marked with the called flag and an indirect call graph edge
2895 : describing the call is created. This is very simple for ordinary pointers
2896 : represented in SSA but not-so-nice when it comes to member pointers. The
2897 : ugly part of this function does nothing more than trying to match the
2898 : pattern of such a call. Look up the documentation of macro
2899 : TARGET_PTRMEMFUNC_VBIT_LOCATION for details. An example of such a pattern
2900 : is the gimple dump below, the call is on the last line:
2901 :
2902 : <bb 2>:
2903 : f$__delta_5 = f.__delta;
2904 : f$__pfn_24 = f.__pfn;
2905 :
2906 : or
2907 : <bb 2>:
2908 : f$__delta_5 = MEM[(struct *)&f];
2909 : f$__pfn_24 = MEM[(struct *)&f + 4B];
2910 :
2911 : and a few lines below:
2912 :
2913 : <bb 5>
2914 : D.2496_3 = (int) f$__pfn_24;
2915 : D.2497_4 = D.2496_3 & 1;
2916 : if (D.2497_4 != 0)
2917 : goto <bb 3>;
2918 : else
2919 : goto <bb 4>;
2920 :
2921 : <bb 6>:
2922 : D.2500_7 = (unsigned int) f$__delta_5;
2923 : D.2501_8 = &S + D.2500_7;
2924 : D.2502_9 = (int (*__vtbl_ptr_type) (void) * *) D.2501_8;
2925 : D.2503_10 = *D.2502_9;
2926 : D.2504_12 = f$__pfn_24 + -1;
2927 : D.2505_13 = (unsigned int) D.2504_12;
2928 : D.2506_14 = D.2503_10 + D.2505_13;
2929 : D.2507_15 = *D.2506_14;
2930 : iftmp.11_16 = (String:: *) D.2507_15;
2931 :
2932 : <bb 7>:
2933 : # iftmp.11_1 = PHI <iftmp.11_16(3), f$__pfn_24(2)>
2934 : D.2500_19 = (unsigned int) f$__delta_5;
2935 : D.2508_20 = &S + D.2500_19;
2936 : D.2493_21 = iftmp.11_1 (D.2508_20, 4);
2937 :
2938 : Such patterns are results of simple calls to a member pointer:
2939 :
2940 : int doprinting (int (MyString::* f)(int) const)
2941 : {
2942 : MyString S ("somestring");
2943 :
2944 : return (S.*f)(4);
2945 : }
2946 :
2947 : Moreover, the function also looks for called pointers loaded from aggregates
2948 : passed by value or reference. */
2949 :
2950 : static void
2951 115612 : ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
2952 : tree target)
2953 : {
2954 115612 : class ipa_node_params *info = fbi->info;
2955 115612 : HOST_WIDE_INT offset;
2956 115612 : bool by_ref;
2957 :
2958 115612 : if (SSA_NAME_IS_DEFAULT_DEF (target))
2959 : {
2960 3760 : tree var = SSA_NAME_VAR (target);
2961 3760 : int index = ipa_get_param_decl_index (info, var);
2962 3760 : if (index >= 0)
2963 : {
2964 3758 : cgraph_edge *cs = fbi->node->get_edge (call);
2965 3758 : cgraph_simple_indirect_info *sii =
2966 3758 : as_a <cgraph_simple_indirect_info *> (cs->indirect_info);
2967 3758 : sii->param_index = index;
2968 3758 : gcc_assert (!sii->agg_contents && !sii->member_ptr);
2969 3758 : ipa_set_param_used_by_indirect_call (info, index, true);
2970 : }
2971 : return;
2972 : }
2973 :
2974 111852 : int index;
2975 111852 : gimple *def = SSA_NAME_DEF_STMT (target);
2976 111852 : bool guaranteed_unmodified;
2977 111852 : if (gimple_assign_single_p (def))
2978 : {
2979 89307 : cgraph_edge *cs = fbi->node->get_edge (call);
2980 89307 : cgraph_simple_indirect_info *sii =
2981 89307 : as_a <cgraph_simple_indirect_info *> (cs->indirect_info);
2982 89307 : tree rectype;
2983 89307 : unsigned fldoff;
2984 89307 : if (is_func_ptr_from_record (gimple_assign_rhs1 (def), &rectype, &fldoff,
2985 : target))
2986 : {
2987 47423 : sii->fnptr_loaded_from_record = 1;
2988 47423 : sii->fld_offset = fldoff;
2989 47423 : sii->rec_type = rectype;
2990 : }
2991 89307 : if (ipa_load_from_parm_agg (fbi, info->descriptors, def,
2992 : gimple_assign_rhs1 (def), &index, &offset,
2993 : NULL, &by_ref, &guaranteed_unmodified))
2994 : {
2995 2309 : sii->param_index = index;
2996 2309 : sii->offset = offset;
2997 2309 : sii->agg_contents = 1;
2998 2309 : sii->by_ref = by_ref;
2999 2309 : sii->guaranteed_unmodified = guaranteed_unmodified;
3000 2309 : ipa_set_param_used_by_indirect_call (info, index, true);
3001 2309 : return;
3002 : }
3003 : }
3004 :
3005 : /* Now we need to try to match the complex pattern of calling a member
3006 : pointer. */
3007 109543 : if (gimple_code (def) != GIMPLE_PHI
3008 1151 : || gimple_phi_num_args (def) != 2
3009 1147 : || !POINTER_TYPE_P (TREE_TYPE (target))
3010 110690 : || TREE_CODE (TREE_TYPE (TREE_TYPE (target))) != METHOD_TYPE)
3011 : return;
3012 :
3013 : /* First, we need to check whether one of these is a load from a member
3014 : pointer that is a parameter to this function. */
3015 875 : tree n1 = PHI_ARG_DEF (def, 0);
3016 875 : tree n2 = PHI_ARG_DEF (def, 1);
3017 1750 : if (!ipa_is_ssa_with_stmt_def (n1) || !ipa_is_ssa_with_stmt_def (n2))
3018 : return;
3019 875 : gimple *d1 = SSA_NAME_DEF_STMT (n1);
3020 875 : gimple *d2 = SSA_NAME_DEF_STMT (n2);
3021 :
3022 875 : tree rec;
3023 875 : basic_block bb, virt_bb;
3024 875 : basic_block join = gimple_bb (def);
3025 875 : if ((rec = ipa_get_stmt_member_ptr_load_param (d1, false, &offset)))
3026 : {
3027 0 : if (ipa_get_stmt_member_ptr_load_param (d2, false, NULL))
3028 : return;
3029 :
3030 0 : bb = EDGE_PRED (join, 0)->src;
3031 0 : virt_bb = gimple_bb (d2);
3032 : }
3033 875 : else if ((rec = ipa_get_stmt_member_ptr_load_param (d2, false, &offset)))
3034 : {
3035 447 : bb = EDGE_PRED (join, 1)->src;
3036 447 : virt_bb = gimple_bb (d1);
3037 : }
3038 : else
3039 : return;
3040 :
3041 : /* Second, we need to check that the basic blocks are laid out in the way
3042 : corresponding to the pattern. */
3043 :
3044 894 : if (!single_pred_p (virt_bb) || !single_succ_p (virt_bb)
3045 894 : || single_succ (virt_bb) != join)
3046 : return;
3047 :
3048 :
3049 447 : if (single_pred (virt_bb) != bb)
3050 : {
3051 : /* In cases when the distinction between a normal and a virtual
3052 : function is encoded in the delta field, the load of the
3053 : actual non-virtual function pointer can be in its own BB. */
3054 :
3055 0 : if (!single_pred_p (bb) || !single_succ_p (bb))
3056 : return;
3057 0 : bb = single_pred (bb);
3058 0 : if (bb != single_pred (virt_bb))
3059 : return;
3060 : }
3061 :
3062 : /* Third, let's see that the branching is done depending on the least
3063 : significant bit of the pfn. */
3064 :
3065 894 : gcond *branch = safe_dyn_cast <gcond *> (*gsi_last_bb (bb));
3066 447 : if (!branch)
3067 : return;
3068 :
3069 447 : if ((gimple_cond_code (branch) != NE_EXPR
3070 0 : && gimple_cond_code (branch) != EQ_EXPR)
3071 447 : || !integer_zerop (gimple_cond_rhs (branch)))
3072 : return;
3073 :
3074 447 : tree cond = gimple_cond_lhs (branch);
3075 447 : if (!ipa_is_ssa_with_stmt_def (cond))
3076 : return;
3077 :
3078 447 : def = SSA_NAME_DEF_STMT (cond);
3079 447 : if (!is_gimple_assign (def)
3080 447 : || gimple_assign_rhs_code (def) != BIT_AND_EXPR
3081 894 : || !integer_onep (gimple_assign_rhs2 (def)))
3082 : return;
3083 :
3084 447 : cond = gimple_assign_rhs1 (def);
3085 447 : if (!ipa_is_ssa_with_stmt_def (cond))
3086 : return;
3087 :
3088 447 : def = SSA_NAME_DEF_STMT (cond);
3089 :
3090 447 : if (is_gimple_assign (def)
3091 447 : && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
3092 : {
3093 447 : cond = gimple_assign_rhs1 (def);
3094 447 : if (!ipa_is_ssa_with_stmt_def (cond))
3095 : return;
3096 447 : def = SSA_NAME_DEF_STMT (cond);
3097 : }
3098 :
3099 447 : tree rec2;
3100 447 : rec2 = ipa_get_stmt_member_ptr_load_param (def,
3101 : (TARGET_PTRMEMFUNC_VBIT_LOCATION
3102 : == ptrmemfunc_vbit_in_delta),
3103 : NULL);
3104 447 : if (rec != rec2)
3105 : return;
3106 :
3107 447 : if (TREE_CODE (rec) == SSA_NAME)
3108 : {
3109 303 : index = ipa_get_param_decl_index (info, SSA_NAME_VAR (rec));
3110 303 : if (index < 0
3111 303 : || !parm_ref_data_preserved_p (fbi, index, call,
3112 : gimple_assign_rhs1 (def)))
3113 : return;
3114 299 : by_ref = true;
3115 : }
3116 : else
3117 : {
3118 144 : index = ipa_get_param_decl_index (info, rec);
3119 144 : if (index < 0
3120 144 : || !parm_preserved_before_stmt_p (fbi, index, call, rec))
3121 : return;
3122 144 : by_ref = false;
3123 : }
3124 :
3125 443 : cgraph_edge *cs = fbi->node->get_edge (call);
3126 443 : cgraph_simple_indirect_info *sii =
3127 443 : as_a <cgraph_simple_indirect_info *> (cs->indirect_info);
3128 443 : sii->param_index = index;
3129 443 : sii->offset = offset;
3130 443 : sii->agg_contents = 1;
3131 443 : sii->member_ptr = 1;
3132 443 : sii->by_ref = by_ref;
3133 443 : sii->guaranteed_unmodified = 1;
3134 443 : ipa_set_param_used_by_indirect_call (info, index, true);
3135 443 : return;
3136 : }
3137 :
3138 : /* Analyze a CALL to an OBJ_TYPE_REF which is passed in TARGET and if the
3139 : object referenced in the expression is a formal parameter of the caller
3140 : FBI->node (described by FBI->info), create a call note for the
3141 : statement. */
3142 :
3143 : static void
3144 24686 : ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi,
3145 : gcall *call, tree target)
3146 : {
3147 24686 : tree obj = OBJ_TYPE_REF_OBJECT (target);
3148 24686 : int index;
3149 24686 : HOST_WIDE_INT anc_offset;
3150 :
3151 24686 : if (!flag_devirtualize)
3152 14972 : return;
3153 :
3154 24416 : if (TREE_CODE (obj) != SSA_NAME)
3155 : return;
3156 :
3157 24057 : class ipa_node_params *info = fbi->info;
3158 24057 : if (SSA_NAME_IS_DEFAULT_DEF (obj))
3159 : {
3160 8965 : if (TREE_CODE (SSA_NAME_VAR (obj)) != PARM_DECL)
3161 : return;
3162 :
3163 8965 : anc_offset = 0;
3164 8965 : index = ipa_get_param_decl_index (info, SSA_NAME_VAR (obj));
3165 8965 : gcc_assert (index >= 0);
3166 8965 : if (detect_type_change_ssa (fbi, obj, obj_type_ref_class (target),
3167 : call))
3168 : return;
3169 : }
3170 : else
3171 : {
3172 15092 : gimple *stmt = SSA_NAME_DEF_STMT (obj);
3173 15092 : tree expr;
3174 :
3175 15092 : expr = get_ancestor_addr_info (stmt, &obj, &anc_offset);
3176 15092 : if (!expr)
3177 : return;
3178 749 : index = ipa_get_param_decl_index (info,
3179 749 : SSA_NAME_VAR (TREE_OPERAND (expr, 0)));
3180 749 : gcc_assert (index >= 0);
3181 749 : if (detect_type_change (fbi, obj, expr, obj_type_ref_class (target),
3182 : call, anc_offset))
3183 : return;
3184 : }
3185 :
3186 9714 : cgraph_edge *cs = fbi->node->get_edge (call);
3187 9714 : cgraph_polymorphic_indirect_info *pii =
3188 9714 : as_a <cgraph_polymorphic_indirect_info *> (cs->indirect_info);
3189 9714 : pii->param_index = index;
3190 9714 : pii->offset = anc_offset;
3191 9714 : gcc_assert (pii->otr_token == tree_to_shwi (OBJ_TYPE_REF_TOKEN (target)));
3192 9714 : gcc_assert (pii->otr_type = obj_type_ref_class (target));
3193 9714 : ipa_set_param_used_by_indirect_call (info, index, true);
3194 9714 : ipa_set_param_used_by_polymorphic_call (info, index, true);
3195 : }
3196 :
3197 : /* Analyze a call statement CALL whether and how it utilizes formal parameters
3198 : of the caller (described by INFO). PARMS_AINFO is a pointer to a vector
3199 : containing intermediate information about each formal parameter. */
3200 :
3201 : static void
3202 5913338 : ipa_analyze_call_uses (struct ipa_func_body_info *fbi, gcall *call)
3203 : {
3204 5913338 : tree target = gimple_call_fn (call);
3205 :
3206 5913338 : if (!target
3207 5913338 : || (TREE_CODE (target) != SSA_NAME
3208 5566875 : && !virtual_method_call_p (target)))
3209 : return;
3210 :
3211 140298 : struct cgraph_edge *cs = fbi->node->get_edge (call);
3212 : /* If we previously turned the call into a direct call, there is
3213 : no need to analyze. */
3214 140298 : if (cs && !cs->indirect_unknown_callee)
3215 : return;
3216 :
3217 140298 : cgraph_polymorphic_indirect_info *pii;
3218 140298 : if (flag_devirtualize
3219 140298 : && (pii
3220 135925 : = dyn_cast <cgraph_polymorphic_indirect_info *> (cs->indirect_info)))
3221 : {
3222 24416 : tree instance;
3223 24416 : tree target = gimple_call_fn (call);
3224 24416 : ipa_polymorphic_call_context context (current_function_decl,
3225 24416 : target, call, &instance);
3226 :
3227 24416 : gcc_checking_assert (pii->otr_type == obj_type_ref_class (target));
3228 24416 : gcc_checking_assert (pii->otr_token
3229 : == tree_to_shwi (OBJ_TYPE_REF_TOKEN (target)));
3230 :
3231 24416 : pii->vptr_changed
3232 48832 : = !context.get_dynamic_type (instance,
3233 24416 : OBJ_TYPE_REF_OBJECT (target),
3234 : obj_type_ref_class (target), call,
3235 : &fbi->aa_walk_budget);
3236 24416 : pii->context = context;
3237 : }
3238 :
3239 140298 : if (TREE_CODE (target) == SSA_NAME)
3240 115612 : ipa_analyze_indirect_call_uses (fbi, call, target);
3241 24686 : else if (virtual_method_call_p (target))
3242 24686 : ipa_analyze_virtual_call_uses (fbi, call, target);
3243 : }
3244 :
3245 : /* Store that that there was a store of FN to a record of type REC_TYPE and
3246 : FLD_OFFSET. */
3247 :
3248 : static void
3249 63653 : note_fnptr_in_record (tree rec_type, unsigned fld_offset, tree fn)
3250 : {
3251 63653 : gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
3252 63653 : gcc_assert (TREE_CODE (rec_type) == RECORD_TYPE);
3253 63653 : if (!noted_fnptrs_in_records)
3254 6728 : noted_fnptrs_in_records = hash_table<noted_fnptr_hasher>::create_ggc (37);
3255 :
3256 63653 : noted_fnptr_store repr;
3257 63653 : repr.rec_type = rec_type;
3258 63653 : repr.fld_offset = fld_offset;
3259 :
3260 63653 : noted_fnptr_store **slot = noted_fnptrs_in_records->find_slot (&repr,
3261 : NO_INSERT);
3262 63653 : if (slot)
3263 : {
3264 8075 : if ((*slot)->fn && (*slot)->fn != fn)
3265 823 : (*slot)->fn = nullptr;
3266 : return;
3267 : }
3268 :
3269 55578 : slot = noted_fnptrs_in_records->find_slot (&repr, INSERT);
3270 55578 : *slot = ggc_cleared_alloc<noted_fnptr_store> ();
3271 55578 : (*slot)->rec_type = rec_type;
3272 55578 : (*slot)->fn = fn;
3273 55578 : (*slot)->fld_offset = fld_offset;
3274 :
3275 55578 : return;
3276 : }
3277 :
3278 : /* Dump contents of noted_fnptrs_in_records to F in humad readable form. */
3279 :
3280 : void DEBUG_FUNCTION
3281 41 : ipa_dump_noted_record_fnptrs (FILE *f)
3282 : {
3283 41 : if (!noted_fnptrs_in_records)
3284 : {
3285 38 : fprintf (f, "No noted function pointers stored in records.\n\n");
3286 38 : return;
3287 : }
3288 :
3289 3 : fprintf (f, "Noted function pointers stored in records:\n");
3290 7 : for (auto iter = noted_fnptrs_in_records->begin ();
3291 7 : iter != noted_fnptrs_in_records->end ();
3292 4 : ++iter)
3293 : {
3294 4 : const noted_fnptr_store *elem = *iter;
3295 4 : fprintf (f, " Type:");
3296 4 : print_generic_expr (f, elem->rec_type);
3297 4 : fprintf (f, ", offset %ul, function: ", elem->fld_offset);
3298 4 : print_generic_expr (f, elem->fn);
3299 4 : fprintf (f, "\n");
3300 : }
3301 3 : fprintf (f, "\n");
3302 : }
3303 :
3304 : /* Dump contents of noted_fnptrs_in_records to stderr in humad readable
3305 : form. */
3306 :
3307 : void DEBUG_FUNCTION
3308 0 : ipa_debug_noted_record_fnptrs (void)
3309 : {
3310 0 : ipa_dump_noted_record_fnptrs (stderr);
3311 0 : }
3312 :
3313 :
3314 : /* If we have noticed a single function pointer stored into a record of type
3315 : REC_TYPE at the given FLD_OFFSET (measured in bytes), return its
3316 : declaration. Otherwise return NULL_TREE. */
3317 :
3318 : tree
3319 37917 : ipa_single_noted_fnptr_in_record (tree rec_type, unsigned fld_offset)
3320 : {
3321 37917 : if (!noted_fnptrs_in_records)
3322 : return NULL_TREE;
3323 :
3324 35705 : noted_fnptr_store repr;
3325 35705 : repr.rec_type = rec_type;
3326 35705 : repr.fld_offset = fld_offset;
3327 :
3328 35705 : noted_fnptr_store **slot = noted_fnptrs_in_records->find_slot (&repr,
3329 : NO_INSERT);
3330 35705 : if (!slot)
3331 : return NULL_TREE;
3332 3636 : return (*slot)->fn;
3333 : }
3334 :
3335 : /* Free the hash table storing the information about function pointers stored
3336 : to a particular position in record typed structures. */
3337 :
3338 : void
3339 130815 : ipa_free_noted_fnptr_calls ()
3340 : {
3341 130815 : if (noted_fnptrs_in_records)
3342 : {
3343 6359 : noted_fnptrs_in_records->empty ();
3344 6359 : noted_fnptrs_in_records = nullptr;
3345 : }
3346 130815 : }
3347 :
3348 : /* Analyze the call statement STMT with respect to formal parameters (described
3349 : in INFO) of caller given by FBI->NODE. Also note any stores of function
3350 : pointers to record typed memory. */
3351 :
3352 : static void
3353 32350586 : ipa_analyze_stmt_uses (struct ipa_func_body_info *fbi, gimple *stmt)
3354 : {
3355 32350586 : if (is_gimple_call (stmt))
3356 5913338 : ipa_analyze_call_uses (fbi, as_a <gcall *> (stmt));
3357 26437248 : else if (gimple_assign_single_p (stmt)
3358 13938317 : && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
3359 27717544 : && (TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (stmt), 0))
3360 : == FUNCTION_DECL))
3361 : {
3362 31573 : tree rec_type;
3363 31573 : unsigned fld_offset;
3364 31573 : if (is_func_ptr_from_record (gimple_assign_lhs (stmt), &rec_type,
3365 : &fld_offset, gimple_assign_rhs1 (stmt)))
3366 11774 : note_fnptr_in_record (rec_type, fld_offset,
3367 11774 : TREE_OPERAND (gimple_assign_rhs1 (stmt), 0));
3368 : }
3369 32350586 : }
3370 :
3371 : /* Callback of walk_stmt_load_store_addr_ops for the visit_load.
3372 : If OP is a parameter declaration, mark it as used in the info structure
3373 : passed in DATA. */
3374 :
3375 : static bool
3376 20256220 : visit_ref_for_mod_analysis (gimple *, tree op, tree, void *data)
3377 : {
3378 20256220 : class ipa_node_params *info = (class ipa_node_params *) data;
3379 :
3380 20256220 : op = get_base_address (op);
3381 20256220 : if (op
3382 20256220 : && TREE_CODE (op) == PARM_DECL)
3383 : {
3384 475565 : int index = ipa_get_param_decl_index (info, op);
3385 475565 : gcc_assert (index >= 0);
3386 475565 : ipa_set_param_used (info, index, true);
3387 : }
3388 :
3389 20256220 : return false;
3390 : }
3391 :
3392 : /* Scan the statements in BB and inspect the uses of formal parameters. Store
3393 : the findings in various structures of the associated ipa_node_params
3394 : structure, such as parameter flags, notes etc. FBI holds various data about
3395 : the function being analyzed. */
3396 :
3397 : static void
3398 11311741 : ipa_analyze_params_uses_in_bb (struct ipa_func_body_info *fbi, basic_block bb)
3399 : {
3400 11311741 : gimple_stmt_iterator gsi;
3401 80905461 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3402 : {
3403 58281979 : gimple *stmt = gsi_stmt (gsi);
3404 :
3405 58281979 : if (is_gimple_debug (stmt))
3406 25931393 : continue;
3407 :
3408 32350586 : ipa_analyze_stmt_uses (fbi, stmt);
3409 32350586 : walk_stmt_load_store_addr_ops (stmt, fbi->info,
3410 : visit_ref_for_mod_analysis,
3411 : visit_ref_for_mod_analysis,
3412 : visit_ref_for_mod_analysis);
3413 : }
3414 14350267 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3415 3038526 : walk_stmt_load_store_addr_ops (gsi_stmt (gsi), fbi->info,
3416 : visit_ref_for_mod_analysis,
3417 : visit_ref_for_mod_analysis,
3418 : visit_ref_for_mod_analysis);
3419 11311741 : }
3420 :
3421 : /* Return true EXPR is a load from a dereference of SSA_NAME NAME. */
3422 :
3423 : static bool
3424 4316587 : load_from_dereferenced_name (tree expr, tree name)
3425 : {
3426 4316587 : tree base = get_base_address (expr);
3427 4316587 : return (TREE_CODE (base) == MEM_REF
3428 4316587 : && TREE_OPERAND (base, 0) == name);
3429 : }
3430 :
3431 : /* Calculate controlled uses of parameters of NODE. */
3432 :
3433 : static void
3434 1398902 : ipa_analyze_controlled_uses (struct cgraph_node *node)
3435 : {
3436 1398902 : ipa_node_params *info = ipa_node_params_sum->get (node);
3437 :
3438 7659421 : for (int i = 0; i < ipa_get_param_count (info); i++)
3439 : {
3440 2560117 : tree parm = ipa_get_param (info, i);
3441 2560117 : int call_uses = 0;
3442 2560117 : bool load_dereferenced = false;
3443 :
3444 : /* For SSA regs see if parameter is used. For non-SSA we compute
3445 : the flag during modification analysis. */
3446 2560117 : if (is_gimple_reg (parm))
3447 : {
3448 2323076 : tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl),
3449 : parm);
3450 2323076 : if (ddef && !has_zero_uses (ddef))
3451 : {
3452 2037287 : imm_use_iterator imm_iter;
3453 2037287 : gimple *stmt;
3454 :
3455 2037287 : ipa_set_param_used (info, i, true);
3456 4994485 : FOR_EACH_IMM_USE_STMT (stmt, imm_iter, ddef)
3457 : {
3458 4122430 : if (is_gimple_debug (stmt))
3459 806800 : continue;
3460 :
3461 3315630 : int all_stmt_uses = 0;
3462 3315630 : use_operand_p use_p;
3463 6665354 : FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
3464 3349724 : all_stmt_uses++;
3465 :
3466 3315630 : if (is_gimple_call (stmt))
3467 : {
3468 1234819 : if (gimple_call_internal_p (stmt))
3469 : {
3470 : call_uses = IPA_UNDESCRIBED_USE;
3471 : break;
3472 : }
3473 1179796 : int recognized_stmt_uses;
3474 1179796 : if (gimple_call_fn (stmt) == ddef)
3475 : recognized_stmt_uses = 1;
3476 : else
3477 1176103 : recognized_stmt_uses = 0;
3478 1179796 : unsigned arg_count = gimple_call_num_args (stmt);
3479 6404546 : for (unsigned i = 0; i < arg_count; i++)
3480 : {
3481 4044954 : tree arg = gimple_call_arg (stmt, i);
3482 4044954 : if (arg == ddef)
3483 1166337 : recognized_stmt_uses++;
3484 2878617 : else if (load_from_dereferenced_name (arg, ddef))
3485 : {
3486 16029 : load_dereferenced = true;
3487 16029 : recognized_stmt_uses++;
3488 : }
3489 : }
3490 :
3491 1179796 : if (recognized_stmt_uses != all_stmt_uses)
3492 : {
3493 : call_uses = IPA_UNDESCRIBED_USE;
3494 : break;
3495 : }
3496 1171715 : if (call_uses >= 0)
3497 1171715 : call_uses += all_stmt_uses;
3498 : }
3499 2080811 : else if (gimple_assign_single_p (stmt))
3500 : {
3501 1438916 : tree rhs = gimple_assign_rhs1 (stmt);
3502 1438916 : if (all_stmt_uses != 1
3503 1438916 : || !load_from_dereferenced_name (rhs, ddef))
3504 : {
3505 : call_uses = IPA_UNDESCRIBED_USE;
3506 : break;
3507 : }
3508 : load_dereferenced = true;
3509 : }
3510 : else
3511 : {
3512 : call_uses = IPA_UNDESCRIBED_USE;
3513 : break;
3514 : }
3515 2037287 : }
3516 : }
3517 : else
3518 : call_uses = 0;
3519 : }
3520 : else
3521 : call_uses = IPA_UNDESCRIBED_USE;
3522 2560117 : ipa_set_controlled_uses (info, i, call_uses);
3523 2560117 : ipa_set_param_load_dereferenced (info, i, load_dereferenced);
3524 : }
3525 1398902 : }
3526 :
3527 : /* Free stuff in BI. */
3528 :
3529 : static void
3530 65247832 : free_ipa_bb_info (struct ipa_bb_info *bi)
3531 : {
3532 0 : bi->cg_edges.release ();
3533 65247832 : bi->param_aa_statuses.release ();
3534 0 : }
3535 :
3536 : /* Dominator walker driving the analysis. */
3537 :
3538 2797804 : class analysis_dom_walker : public dom_walker
3539 : {
3540 : public:
3541 1398902 : analysis_dom_walker (struct ipa_func_body_info *fbi)
3542 2797804 : : dom_walker (CDI_DOMINATORS), m_fbi (fbi) {}
3543 :
3544 : edge before_dom_children (basic_block) final override;
3545 :
3546 : private:
3547 : struct ipa_func_body_info *m_fbi;
3548 : };
3549 :
3550 : edge
3551 11311741 : analysis_dom_walker::before_dom_children (basic_block bb)
3552 : {
3553 11311741 : ipa_analyze_params_uses_in_bb (m_fbi, bb);
3554 11311741 : ipa_compute_jump_functions_for_bb (m_fbi, bb);
3555 11311741 : return NULL;
3556 : }
3557 :
3558 : /* Release body info FBI. */
3559 :
3560 : void
3561 8884776 : ipa_release_body_info (struct ipa_func_body_info *fbi)
3562 : {
3563 8884776 : int i;
3564 8884776 : struct ipa_bb_info *bi;
3565 :
3566 74108423 : FOR_EACH_VEC_ELT (fbi->bb_infos, i, bi)
3567 130447294 : free_ipa_bb_info (bi);
3568 8884776 : fbi->bb_infos.release ();
3569 8884776 : }
3570 :
3571 : /* Initialize the array describing properties of formal parameters
3572 : of NODE, analyze their uses and compute jump functions associated
3573 : with actual arguments of calls from within NODE. */
3574 :
3575 : void
3576 2744546 : ipa_analyze_node (struct cgraph_node *node)
3577 : {
3578 2744546 : struct ipa_func_body_info fbi;
3579 2744546 : class ipa_node_params *info;
3580 :
3581 2744546 : ipa_check_create_node_params ();
3582 2744546 : ipa_check_create_edge_args ();
3583 2744546 : callback_info_sum_t::check_create_info_sum ();
3584 2744546 : info = ipa_node_params_sum->get_create (node);
3585 :
3586 2744546 : if (info->analysis_done)
3587 1345644 : return;
3588 1399906 : info->analysis_done = 1;
3589 :
3590 1399906 : if (ipa_func_spec_opts_forbid_analysis_p (node)
3591 1399906 : || (count_formal_params (node->decl)
3592 : >= (1 << IPA_PROP_ARG_INDEX_LIMIT_BITS)))
3593 : {
3594 1345644 : gcc_assert (!ipa_get_param_count (info));
3595 : return;
3596 : }
3597 :
3598 1398902 : struct function *func = DECL_STRUCT_FUNCTION (node->decl);
3599 1398902 : push_cfun (func);
3600 1398902 : calculate_dominance_info (CDI_DOMINATORS);
3601 1398902 : ipa_initialize_node_params (node);
3602 1398902 : ipa_analyze_controlled_uses (node);
3603 :
3604 1398902 : fbi.node = node;
3605 1398902 : fbi.info = info;
3606 1398902 : fbi.bb_infos = vNULL;
3607 1398902 : fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun), true);
3608 1398902 : fbi.param_count = ipa_get_param_count (info);
3609 1398902 : fbi.aa_walk_budget = opt_for_fn (node->decl, param_ipa_max_aa_steps);
3610 :
3611 6941013 : for (struct cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
3612 : {
3613 5542111 : ipa_bb_info *bi = ipa_get_bb_info (&fbi, gimple_bb (cs->call_stmt));
3614 5542111 : bi->cg_edges.safe_push (cs);
3615 : }
3616 :
3617 1539278 : for (struct cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
3618 : {
3619 140376 : ipa_bb_info *bi = ipa_get_bb_info (&fbi, gimple_bb (cs->call_stmt));
3620 140376 : bi->cg_edges.safe_push (cs);
3621 : }
3622 :
3623 1398902 : enable_ranger (cfun, false);
3624 1398902 : analysis_dom_walker (&fbi).walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
3625 1398902 : disable_ranger (cfun);
3626 :
3627 1398902 : ipa_release_body_info (&fbi);
3628 1398902 : free_dominance_info (CDI_DOMINATORS);
3629 1398902 : pop_cfun ();
3630 : }
3631 :
3632 : /* Analyze NODE and note any function pointers in record-typed static
3633 : initializers.
3634 :
3635 : TODO: The current implementation does not traverse the initializers to scan
3636 : records nested inside other types. It should catch the most basic way of
3637 : writing "virtual functions" in C but can be extended, of course.
3638 : */
3639 :
3640 : void
3641 1681932 : ipa_analyze_var_static_initializer (varpool_node *node)
3642 : {
3643 1681932 : tree decl = node->decl;
3644 1681932 : tree rec_type = TREE_TYPE (decl);
3645 1681932 : if (TREE_CODE (rec_type) != RECORD_TYPE
3646 1681932 : || TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
3647 : return;
3648 :
3649 : unsigned ix;
3650 : tree index, val;
3651 3864167 : FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)), ix, index,
3652 : val)
3653 : {
3654 5393185 : if (TREE_CODE (val) != ADDR_EXPR
3655 1013433 : || TREE_CODE (TREE_OPERAND (val, 0)) != FUNCTION_DECL
3656 : /* ObjC can produce constructor elements with NULL indices. */
3657 2773412 : || !index)
3658 2670986 : continue;
3659 51213 : HOST_WIDE_INT elt_offset = int_bit_position (index);
3660 51213 : if ((elt_offset % BITS_PER_UNIT) != 0)
3661 0 : continue;
3662 51213 : elt_offset = elt_offset / BITS_PER_UNIT;
3663 51213 : if (elt_offset > UINT_MAX)
3664 0 : continue;
3665 51213 : note_fnptr_in_record (rec_type, elt_offset, TREE_OPERAND (val, 0));
3666 : }
3667 : }
3668 :
3669 : /* Update the jump functions associated with call graph edge E when the call
3670 : graph edge CS is being inlined, assuming that E->caller is already (possibly
3671 : indirectly) inlined into CS->callee and that E has not been inlined. */
3672 :
3673 : static void
3674 2831284 : update_jump_functions_after_inlining (struct cgraph_edge *cs,
3675 : struct cgraph_edge *e)
3676 : {
3677 2831284 : ipa_edge_args *top = ipa_edge_args_sum->get (cs);
3678 2831284 : ipa_edge_args *args = ipa_edge_args_sum->get (e);
3679 2831284 : if (!args)
3680 : return;
3681 1608208 : ipa_node_params *old_inline_root_info = ipa_node_params_sum->get (cs->callee);
3682 1608208 : ipa_node_params *new_inline_root_info
3683 1608208 : = ipa_node_params_sum->get (cs->caller->inlined_to
3684 : ? cs->caller->inlined_to : cs->caller);
3685 1608208 : int count = ipa_get_cs_argument_count (args);
3686 1608208 : int i;
3687 :
3688 4768201 : for (i = 0; i < count; i++)
3689 : {
3690 3159993 : struct ipa_jump_func *dst = ipa_get_ith_jump_func (args, i);
3691 3159993 : class ipa_polymorphic_call_context *dst_ctx
3692 3159993 : = ipa_get_ith_polymorhic_call_context (args, i);
3693 :
3694 3159993 : if (dst->agg.items)
3695 : {
3696 : struct ipa_agg_jf_item *item;
3697 : int j;
3698 :
3699 291103 : FOR_EACH_VEC_ELT (*dst->agg.items, j, item)
3700 : {
3701 197014 : int dst_fid;
3702 197014 : struct ipa_jump_func *src;
3703 :
3704 353034 : if (item->jftype != IPA_JF_PASS_THROUGH
3705 197014 : && item->jftype != IPA_JF_LOAD_AGG)
3706 156020 : continue;
3707 :
3708 40994 : dst_fid = item->value.pass_through.formal_id;
3709 81985 : if (!top || dst_fid >= ipa_get_cs_argument_count (top))
3710 : {
3711 3 : item->jftype = IPA_JF_UNKNOWN;
3712 3 : continue;
3713 : }
3714 :
3715 40991 : item->value.pass_through.formal_id = -1;
3716 40991 : src = ipa_get_ith_jump_func (top, dst_fid);
3717 40991 : if (src->type == IPA_JF_CONST)
3718 : {
3719 2655 : if (item->jftype == IPA_JF_PASS_THROUGH
3720 2244 : && item->value.pass_through.operation == NOP_EXPR)
3721 : {
3722 2177 : item->jftype = IPA_JF_CONST;
3723 2177 : item->value.constant = src->value.constant.value;
3724 2177 : continue;
3725 : }
3726 : }
3727 38336 : else if (src->type == IPA_JF_PASS_THROUGH
3728 5906 : && src->value.pass_through.operation == NOP_EXPR)
3729 : {
3730 5752 : if (item->jftype == IPA_JF_PASS_THROUGH
3731 3776 : || !item->value.load_agg.by_ref
3732 2360 : || src->value.pass_through.agg_preserved)
3733 4198 : item->value.pass_through.formal_id
3734 4198 : = src->value.pass_through.formal_id;
3735 : }
3736 32584 : else if (src->type == IPA_JF_ANCESTOR)
3737 : {
3738 4545 : if (item->jftype == IPA_JF_PASS_THROUGH)
3739 : {
3740 1024 : if (!src->value.ancestor.offset)
3741 715 : item->value.pass_through.formal_id
3742 715 : = src->value.ancestor.formal_id;
3743 : }
3744 3521 : else if (src->value.ancestor.agg_preserved)
3745 : {
3746 1467 : gcc_checking_assert (item->value.load_agg.by_ref);
3747 :
3748 1467 : item->value.pass_through.formal_id
3749 1467 : = src->value.ancestor.formal_id;
3750 1467 : item->value.load_agg.offset
3751 1467 : += src->value.ancestor.offset;
3752 : }
3753 : }
3754 :
3755 38814 : if (item->value.pass_through.formal_id < 0)
3756 32434 : item->jftype = IPA_JF_UNKNOWN;
3757 : }
3758 : }
3759 :
3760 3159993 : if (!top)
3761 : {
3762 13245 : ipa_set_jf_unknown (dst);
3763 13245 : continue;
3764 : }
3765 :
3766 3146748 : if (dst->type == IPA_JF_ANCESTOR)
3767 : {
3768 145462 : struct ipa_jump_func *src;
3769 145462 : int dst_fid = dst->value.ancestor.formal_id;
3770 145462 : class ipa_polymorphic_call_context *src_ctx
3771 145462 : = ipa_get_ith_polymorhic_call_context (top, dst_fid);
3772 :
3773 : /* Variable number of arguments can cause havoc if we try to access
3774 : one that does not exist in the inlined edge. So make sure we
3775 : don't. */
3776 290924 : if (dst_fid >= ipa_get_cs_argument_count (top))
3777 : {
3778 0 : ipa_set_jf_unknown (dst);
3779 0 : continue;
3780 : }
3781 :
3782 145462 : src = ipa_get_ith_jump_func (top, dst_fid);
3783 :
3784 145462 : if (src_ctx && !src_ctx->useless_p ())
3785 : {
3786 45477 : class ipa_polymorphic_call_context ctx = *src_ctx;
3787 :
3788 : /* TODO: Make type preserved safe WRT contexts. */
3789 45477 : if (!ipa_get_jf_ancestor_type_preserved (dst))
3790 31148 : ctx.possible_dynamic_type_change (e->in_polymorphic_cdtor);
3791 45477 : ctx.offset_by (dst->value.ancestor.offset);
3792 90954 : if (!ctx.useless_p ())
3793 : {
3794 39200 : if (!dst_ctx)
3795 : {
3796 4925 : vec_safe_grow_cleared (args->polymorphic_call_contexts,
3797 : count, true);
3798 4925 : dst_ctx = ipa_get_ith_polymorhic_call_context (args, i);
3799 : }
3800 :
3801 39200 : dst_ctx->combine_with (ctx);
3802 : }
3803 : }
3804 :
3805 : /* Parameter and argument in ancestor jump function must be pointer
3806 : type, which means access to aggregate must be by-reference. */
3807 145462 : gcc_assert (!src->agg.items || src->agg.by_ref);
3808 :
3809 145462 : if (src->agg.items && dst->value.ancestor.agg_preserved)
3810 : {
3811 2080 : struct ipa_agg_jf_item *item;
3812 2080 : int j;
3813 :
3814 : /* Currently we do not produce clobber aggregate jump functions,
3815 : replace with merging when we do. */
3816 2080 : gcc_assert (!dst->agg.items);
3817 :
3818 2080 : dst->agg.items = vec_safe_copy (src->agg.items);
3819 2080 : dst->agg.by_ref = src->agg.by_ref;
3820 6916 : FOR_EACH_VEC_SAFE_ELT (dst->agg.items, j, item)
3821 4836 : item->offset -= dst->value.ancestor.offset;
3822 : }
3823 :
3824 145462 : if (src->type == IPA_JF_PASS_THROUGH
3825 26606 : && src->value.pass_through.operation == NOP_EXPR)
3826 : {
3827 26602 : dst->value.ancestor.formal_id = src->value.pass_through.formal_id;
3828 26602 : dst->value.ancestor.agg_preserved &=
3829 26602 : src->value.pass_through.agg_preserved;
3830 : }
3831 118860 : else if (src->type == IPA_JF_ANCESTOR)
3832 : {
3833 9270 : dst->value.ancestor.formal_id = src->value.ancestor.formal_id;
3834 9270 : dst->value.ancestor.offset += src->value.ancestor.offset;
3835 9270 : dst->value.ancestor.agg_preserved &=
3836 9270 : src->value.ancestor.agg_preserved;
3837 9270 : dst->value.ancestor.keep_null |= src->value.ancestor.keep_null;
3838 : }
3839 : else
3840 109590 : ipa_set_jf_unknown (dst);
3841 : }
3842 3001286 : else if (dst->type == IPA_JF_PASS_THROUGH)
3843 : {
3844 839434 : struct ipa_jump_func *src;
3845 : /* We must check range due to calls with variable number of arguments
3846 : and we cannot combine jump functions with operations. */
3847 839434 : if (dst->value.pass_through.operation == NOP_EXPR
3848 839434 : && (top && dst->value.pass_through.formal_id
3849 801517 : < ipa_get_cs_argument_count (top)))
3850 : {
3851 801503 : int dst_fid = dst->value.pass_through.formal_id;
3852 801503 : src = ipa_get_ith_jump_func (top, dst_fid);
3853 801503 : bool dst_agg_p = ipa_get_jf_pass_through_agg_preserved (dst);
3854 801503 : class ipa_polymorphic_call_context *src_ctx
3855 929506 : = ipa_get_ith_polymorhic_call_context (top, dst_fid);
3856 :
3857 128003 : if (src_ctx && !src_ctx->useless_p ())
3858 : {
3859 71567 : class ipa_polymorphic_call_context ctx = *src_ctx;
3860 :
3861 : /* TODO: Make type preserved safe WRT contexts. */
3862 71567 : if (!ipa_get_jf_pass_through_type_preserved (dst))
3863 28766 : ctx.possible_dynamic_type_change (e->in_polymorphic_cdtor);
3864 143134 : if (!ctx.useless_p ())
3865 : {
3866 68308 : if (!dst_ctx)
3867 : {
3868 13694 : vec_safe_grow_cleared (args->polymorphic_call_contexts,
3869 : count, true);
3870 13694 : dst_ctx = ipa_get_ith_polymorhic_call_context (args, i);
3871 : }
3872 68308 : dst_ctx->combine_with (ctx);
3873 : }
3874 : }
3875 801503 : switch (src->type)
3876 : {
3877 348621 : case IPA_JF_UNKNOWN:
3878 348621 : ipa_set_jf_unknown (dst);
3879 348621 : break;
3880 168518 : case IPA_JF_CONST:
3881 168518 : ipa_convert_prop_cst_jf (dst, src,
3882 : ipa_get_type (old_inline_root_info,
3883 : dst_fid));
3884 168518 : break;
3885 :
3886 258852 : case IPA_JF_PASS_THROUGH:
3887 258852 : {
3888 258852 : int formal_id = ipa_get_jf_pass_through_formal_id (src);
3889 258852 : enum tree_code operation;
3890 258852 : operation = ipa_get_jf_pass_through_operation (src);
3891 :
3892 258852 : tree old_ir_ptype = ipa_get_type (old_inline_root_info,
3893 : dst_fid);
3894 258852 : tree new_ir_ptype = ipa_get_type (new_inline_root_info,
3895 : formal_id);
3896 258852 : if (!useless_type_conversion_p (old_ir_ptype, new_ir_ptype))
3897 : {
3898 : /* Jump-function construction now permits type-casts
3899 : from an integer to another if the latter can hold
3900 : all values or has at least the same precision.
3901 : However, as we're combining multiple pass-through
3902 : functions together, we are losing information about
3903 : signedness and thus if conversions should sign or
3904 : zero extend. Therefore we must prevent combining
3905 : such jump-function if signednesses do not match. */
3906 1811 : if (!INTEGRAL_TYPE_P (old_ir_ptype)
3907 951 : || !INTEGRAL_TYPE_P (new_ir_ptype)
3908 1902 : || (TYPE_UNSIGNED (new_ir_ptype)
3909 951 : != TYPE_UNSIGNED (old_ir_ptype)))
3910 : {
3911 860 : ipa_set_jf_unknown (dst);
3912 860 : continue;
3913 : }
3914 : }
3915 :
3916 257992 : if (operation == NOP_EXPR)
3917 : {
3918 256581 : bool agg_p;
3919 513162 : agg_p = dst_agg_p
3920 256581 : && ipa_get_jf_pass_through_agg_preserved (src);
3921 256581 : ipa_set_jf_simple_pass_through (dst, formal_id, agg_p);
3922 : }
3923 1411 : else if (TREE_CODE_CLASS (operation) == tcc_unary)
3924 : {
3925 8 : tree op_t = ipa_get_jf_pass_through_op_type (src);
3926 8 : ipa_set_jf_unary_pass_through (dst, formal_id, operation,
3927 : op_t);
3928 : }
3929 : else
3930 : {
3931 1403 : tree operand = ipa_get_jf_pass_through_operand (src);
3932 1403 : tree op_t = ipa_get_jf_pass_through_op_type (src);
3933 1403 : ipa_set_jf_arith_pass_through (dst, formal_id, operand,
3934 : operation, op_t);
3935 : }
3936 : break;
3937 : }
3938 25512 : case IPA_JF_ANCESTOR:
3939 25512 : {
3940 25512 : bool agg_p;
3941 51024 : agg_p = dst_agg_p
3942 25512 : && ipa_get_jf_ancestor_agg_preserved (src);
3943 25512 : ipa_set_ancestor_jf (dst,
3944 : ipa_get_jf_ancestor_offset (src),
3945 : ipa_get_jf_ancestor_formal_id (src),
3946 : agg_p,
3947 : ipa_get_jf_ancestor_keep_null (src));
3948 25512 : break;
3949 : }
3950 0 : default:
3951 0 : gcc_unreachable ();
3952 : }
3953 :
3954 800643 : if (src->m_vr && src->m_vr->known_p ())
3955 : {
3956 534652 : value_range svr (src->m_vr->type ());
3957 534652 : if (!dst->m_vr || !dst->m_vr->known_p ())
3958 214945 : ipa_set_jfunc_vr (dst, *src->m_vr);
3959 319707 : else if (ipa_vr_operation_and_type_effects (svr, *src->m_vr,
3960 : NOP_EXPR,
3961 319707 : dst->m_vr->type (),
3962 319707 : src->m_vr->type ()))
3963 : {
3964 319699 : value_range dvr;
3965 319699 : dst->m_vr->get_vrange (dvr);
3966 319699 : dvr.intersect (svr);
3967 319699 : if (!dvr.undefined_p ())
3968 306826 : ipa_set_jfunc_vr (dst, dvr);
3969 319699 : }
3970 534652 : }
3971 :
3972 800643 : if (src->agg.items
3973 32303 : && (dst_agg_p || !src->agg.by_ref))
3974 : {
3975 : /* Currently we do not produce clobber aggregate jump
3976 : functions, replace with merging when we do. */
3977 24121 : gcc_assert (!dst->agg.items);
3978 :
3979 24121 : dst->agg.by_ref = src->agg.by_ref;
3980 24121 : dst->agg.items = vec_safe_copy (src->agg.items);
3981 : }
3982 : }
3983 : else
3984 37931 : ipa_set_jf_unknown (dst);
3985 : }
3986 : }
3987 : }
3988 :
3989 : /* If TARGET is an addr_expr of a function declaration, make it the
3990 : (SPECULATIVE)destination of an indirect edge IE and return the edge.
3991 : Otherwise, return NULL. */
3992 :
3993 : struct cgraph_edge *
3994 4106 : ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target,
3995 : bool speculative)
3996 : {
3997 4106 : struct cgraph_node *callee;
3998 4106 : bool unreachable = false;
3999 :
4000 4106 : if (TREE_CODE (target) == ADDR_EXPR)
4001 1379 : target = TREE_OPERAND (target, 0);
4002 4106 : if (TREE_CODE (target) != FUNCTION_DECL)
4003 : {
4004 17 : target = canonicalize_constructor_val (target, NULL);
4005 17 : if (!target || TREE_CODE (target) != FUNCTION_DECL)
4006 : {
4007 17 : cgraph_simple_indirect_info *sii
4008 17 : = dyn_cast <cgraph_simple_indirect_info *> (ie->indirect_info);
4009 : /* Member pointer call that goes through a VMT lookup. */
4010 17 : if ((sii && sii->member_ptr)
4011 : /* Or if target is not an invariant expression and we do not
4012 : know if it will evaluate to function at runtime.
4013 : This can happen when folding through &VAR, where &VAR
4014 : is IP invariant, but VAR itself is not.
4015 :
4016 : TODO: It seems that we may try to fold the expression and see
4017 : if VAR is readonly. */
4018 11 : || !is_gimple_ip_invariant (target))
4019 : {
4020 6 : if (dump_enabled_p ())
4021 : {
4022 0 : dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, ie->call_stmt,
4023 : "discovered direct call non-invariant %s\n",
4024 0 : ie->caller->dump_name ());
4025 : }
4026 : return NULL;
4027 : }
4028 :
4029 :
4030 11 : if (dump_enabled_p ())
4031 : {
4032 0 : dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, ie->call_stmt,
4033 : "discovered direct call to non-function in %s, "
4034 : "making it __builtin_unreachable\n",
4035 0 : ie->caller->dump_name ());
4036 : }
4037 :
4038 11 : target = builtin_decl_unreachable ();
4039 11 : callee = cgraph_node::get_create (target);
4040 11 : unreachable = true;
4041 11 : }
4042 : else
4043 0 : callee = cgraph_node::get (target);
4044 : }
4045 : else
4046 4089 : callee = cgraph_node::get (target);
4047 :
4048 : /* Because may-edges are not explicitly represented and vtable may be external,
4049 : we may create the first reference to the object in the unit. */
4050 4100 : if (!callee || callee->inlined_to)
4051 : {
4052 :
4053 : /* We are better to ensure we can refer to it.
4054 : In the case of static functions we are out of luck, since we already
4055 : removed its body. In the case of public functions we may or may
4056 : not introduce the reference. */
4057 0 : if (!canonicalize_constructor_val (target, NULL)
4058 0 : || !TREE_PUBLIC (target))
4059 : {
4060 0 : if (dump_file)
4061 0 : fprintf (dump_file, "ipa-prop: Discovered call to a known target "
4062 : "(%s -> %s) but cannot refer to it. Giving up.\n",
4063 0 : ie->caller->dump_name (),
4064 0 : ie->callee->dump_name ());
4065 : return NULL;
4066 : }
4067 0 : callee = cgraph_node::get_create (target);
4068 : }
4069 :
4070 : /* If the edge is already speculated. */
4071 4100 : if (speculative && ie->speculative)
4072 : {
4073 2 : if (dump_file)
4074 : {
4075 0 : cgraph_edge *e2 = ie->speculative_call_for_target (callee);
4076 0 : if (!e2)
4077 : {
4078 0 : if (dump_file)
4079 0 : fprintf (dump_file, "ipa-prop: Discovered call to a "
4080 : "speculative target (%s -> %s) but the call is "
4081 : "already speculated to different target. "
4082 : "Giving up.\n",
4083 0 : ie->caller->dump_name (), callee->dump_name ());
4084 : }
4085 : else
4086 : {
4087 0 : if (dump_file)
4088 0 : fprintf (dump_file,
4089 : "ipa-prop: Discovered call to a speculative target "
4090 : "(%s -> %s) this agree with previous speculation.\n",
4091 0 : ie->caller->dump_name (), callee->dump_name ());
4092 : }
4093 : }
4094 : return NULL;
4095 : }
4096 :
4097 4098 : if (!dbg_cnt (devirt))
4098 : return NULL;
4099 :
4100 4098 : ipa_check_create_node_params ();
4101 :
4102 : /* We cannot make edges to inline clones. It is bug that someone removed
4103 : the cgraph node too early. */
4104 4098 : gcc_assert (!callee->inlined_to);
4105 :
4106 4098 : if (dump_file && !unreachable)
4107 : {
4108 402 : fprintf (dump_file, "ipa-prop: Discovered %s call to a %s target "
4109 : "(%s -> %s), for stmt ",
4110 402 : is_a <cgraph_polymorphic_indirect_info *> (ie->indirect_info)
4111 : ? "a virtual" : "an indirect",
4112 : speculative ? "speculative" : "known",
4113 201 : ie->caller->dump_name (),
4114 : callee->dump_name ());
4115 201 : if (ie->call_stmt)
4116 193 : print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM);
4117 : else
4118 8 : fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid);
4119 : }
4120 4098 : if (dump_enabled_p ())
4121 : {
4122 402 : dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, ie->call_stmt,
4123 : "converting indirect call in %s to direct call to %s\n",
4124 201 : ie->caller->dump_name (), callee->dump_name ());
4125 : }
4126 4098 : if (!speculative)
4127 : {
4128 4061 : struct cgraph_edge *orig = ie;
4129 4061 : ie = cgraph_edge::make_direct (ie, callee);
4130 : /* If we resolved speculative edge the cost is already up to date
4131 : for direct call (adjusted by inline_edge_duplication_hook). */
4132 4061 : if (ie == orig)
4133 : {
4134 3205 : ipa_call_summary *es = ipa_call_summaries->get (ie);
4135 3205 : es->call_stmt_size -= (eni_size_weights.indirect_call_cost
4136 3205 : - eni_size_weights.call_cost);
4137 3205 : es->call_stmt_time -= (eni_time_weights.indirect_call_cost
4138 3205 : - eni_time_weights.call_cost);
4139 : }
4140 : }
4141 : else
4142 : {
4143 37 : if (!callee->can_be_discarded_p ())
4144 : {
4145 4 : cgraph_node *alias;
4146 4 : alias = dyn_cast<cgraph_node *> (callee->noninterposable_alias ());
4147 : if (alias)
4148 37 : callee = alias;
4149 : }
4150 : /* make_speculative will update ie's cost to direct call cost. */
4151 37 : ie = ie->make_speculative
4152 37 : (callee, ie->count.apply_scale (8, 10));
4153 : }
4154 :
4155 : return ie;
4156 : }
4157 :
4158 : /* Attempt to locate an interprocedural constant at a given REQ_OFFSET in
4159 : CONSTRUCTOR and return it. Return NULL if the search fails for some
4160 : reason. */
4161 :
4162 : static tree
4163 15884 : find_constructor_constant_at_offset (tree constructor, HOST_WIDE_INT req_offset)
4164 : {
4165 22514 : tree type = TREE_TYPE (constructor);
4166 22514 : if (TREE_CODE (type) != ARRAY_TYPE
4167 22514 : && TREE_CODE (type) != RECORD_TYPE)
4168 : return NULL;
4169 :
4170 22502 : unsigned ix;
4171 22502 : tree index, val;
4172 28583 : FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (constructor), ix, index, val)
4173 : {
4174 27923 : HOST_WIDE_INT elt_offset;
4175 27923 : if (TREE_CODE (type) == ARRAY_TYPE)
4176 : {
4177 370 : offset_int off;
4178 370 : tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (type));
4179 370 : gcc_assert (TREE_CODE (unit_size) == INTEGER_CST);
4180 :
4181 370 : if (index)
4182 : {
4183 370 : if (TREE_CODE (index) == RANGE_EXPR)
4184 60 : off = wi::to_offset (TREE_OPERAND (index, 0));
4185 : else
4186 310 : off = wi::to_offset (index);
4187 370 : if (TYPE_DOMAIN (type) && TYPE_MIN_VALUE (TYPE_DOMAIN (type)))
4188 : {
4189 370 : tree low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
4190 370 : gcc_assert (TREE_CODE (unit_size) == INTEGER_CST);
4191 370 : off = wi::sext (off - wi::to_offset (low_bound),
4192 370 : TYPE_PRECISION (TREE_TYPE (index)));
4193 : }
4194 370 : off *= wi::to_offset (unit_size);
4195 : /* ??? Handle more than just the first index of a
4196 : RANGE_EXPR. */
4197 : }
4198 : else
4199 0 : off = wi::to_offset (unit_size) * ix;
4200 :
4201 370 : off = wi::lshift (off, LOG2_BITS_PER_UNIT);
4202 370 : if (!wi::fits_shwi_p (off) || wi::neg_p (off))
4203 0 : continue;
4204 370 : elt_offset = off.to_shwi ();
4205 : }
4206 27553 : else if (TREE_CODE (type) == RECORD_TYPE)
4207 : {
4208 27553 : gcc_checking_assert (index && TREE_CODE (index) == FIELD_DECL);
4209 27553 : if (DECL_BIT_FIELD (index))
4210 0 : continue;
4211 27553 : elt_offset = int_bit_position (index);
4212 : }
4213 : else
4214 0 : gcc_unreachable ();
4215 :
4216 27923 : if (elt_offset > req_offset)
4217 : return NULL;
4218 :
4219 27923 : if (TREE_CODE (val) == CONSTRUCTOR)
4220 6630 : return find_constructor_constant_at_offset (val,
4221 6630 : req_offset - elt_offset);
4222 :
4223 21293 : if (elt_offset == req_offset
4224 15872 : && is_gimple_reg_type (TREE_TYPE (val))
4225 37165 : && is_gimple_ip_invariant (val))
4226 : return val;
4227 : }
4228 : return NULL;
4229 : }
4230 :
4231 : /* Check whether SCALAR could be used to look up an aggregate interprocedural
4232 : invariant from a static constructor and if so, return it. Otherwise return
4233 : NULL. */
4234 :
4235 : tree
4236 14533264 : ipa_find_agg_cst_from_init (tree scalar, HOST_WIDE_INT offset, bool by_ref)
4237 : {
4238 14533264 : if (by_ref)
4239 : {
4240 14519408 : if (TREE_CODE (scalar) != ADDR_EXPR)
4241 : return NULL;
4242 4492767 : scalar = TREE_OPERAND (scalar, 0);
4243 : }
4244 :
4245 4506623 : if (!VAR_P (scalar)
4246 2964515 : || !is_global_var (scalar)
4247 377240 : || !TREE_READONLY (scalar)
4248 20486 : || !DECL_INITIAL (scalar)
4249 4524629 : || TREE_CODE (DECL_INITIAL (scalar)) != CONSTRUCTOR)
4250 : return NULL;
4251 :
4252 15884 : return find_constructor_constant_at_offset (DECL_INITIAL (scalar), offset);
4253 : }
4254 :
4255 : /* Retrieve value from AGG_JFUNC for the given OFFSET or return NULL if there
4256 : is none. BY_REF specifies whether the value has to be passed by reference
4257 : or by value. */
4258 :
4259 : static tree
4260 24460 : ipa_find_agg_cst_from_jfunc_items (struct ipa_agg_jump_function *agg_jfunc,
4261 : ipa_node_params *src_info,
4262 : cgraph_node *src_node,
4263 : HOST_WIDE_INT offset, bool by_ref)
4264 : {
4265 24460 : if (by_ref != agg_jfunc->by_ref)
4266 : return NULL_TREE;
4267 :
4268 4385 : for (const ipa_agg_jf_item &item : agg_jfunc->items)
4269 1552 : if (item.offset == offset)
4270 1144 : return ipa_agg_value_from_jfunc (src_info, src_node, &item);
4271 :
4272 : return NULL_TREE;
4273 : }
4274 :
4275 : /* Remove a reference to SYMBOL from the list of references of a node given by
4276 : reference description RDESC. Return true if the reference has been
4277 : successfully found and removed. */
4278 :
4279 : static bool
4280 9145 : remove_described_reference (symtab_node *symbol, struct ipa_cst_ref_desc *rdesc)
4281 : {
4282 9145 : struct ipa_ref *to_del;
4283 9145 : struct cgraph_edge *origin;
4284 :
4285 9145 : origin = rdesc->cs;
4286 9145 : if (!origin)
4287 : return false;
4288 9145 : to_del = origin->caller->find_reference (symbol, origin->call_stmt,
4289 : origin->lto_stmt_uid, IPA_REF_ADDR);
4290 9145 : if (!to_del)
4291 : return false;
4292 :
4293 9145 : to_del->remove_reference ();
4294 9145 : if (dump_file)
4295 26 : fprintf (dump_file, "ipa-prop: Removed a reference from %s to %s.\n",
4296 13 : origin->caller->dump_name (), symbol->dump_name ());
4297 : return true;
4298 : }
4299 :
4300 : /* If JFUNC has a reference description with refcount different from
4301 : IPA_UNDESCRIBED_USE, return the reference description, otherwise return
4302 : NULL. JFUNC must be a constant jump function. */
4303 :
4304 : static struct ipa_cst_ref_desc *
4305 1361782 : jfunc_rdesc_usable (struct ipa_jump_func *jfunc)
4306 : {
4307 1361782 : struct ipa_cst_ref_desc *rdesc = ipa_get_jf_constant_rdesc (jfunc);
4308 1361782 : if (rdesc && rdesc->refcount != IPA_UNDESCRIBED_USE)
4309 : return rdesc;
4310 : else
4311 1166411 : return NULL;
4312 : }
4313 :
4314 : /* If the value of constant jump function JFUNC is an address of a function
4315 : declaration, return the associated call graph node. Otherwise return
4316 : NULL. */
4317 :
4318 : static symtab_node *
4319 1822 : symtab_node_for_jfunc (struct ipa_jump_func *jfunc)
4320 : {
4321 1822 : gcc_checking_assert (jfunc->type == IPA_JF_CONST);
4322 1822 : tree cst = ipa_get_jf_constant (jfunc);
4323 1822 : if (TREE_CODE (cst) != ADDR_EXPR
4324 1822 : || (TREE_CODE (TREE_OPERAND (cst, 0)) != FUNCTION_DECL
4325 35 : && TREE_CODE (TREE_OPERAND (cst, 0)) != VAR_DECL))
4326 : return NULL;
4327 :
4328 1812 : return symtab_node::get (TREE_OPERAND (cst, 0));
4329 : }
4330 :
4331 :
4332 : /* If JFUNC is a constant jump function with a usable rdesc, decrement its
4333 : refcount and if it hits zero, remove reference to SYMBOL from the caller of
4334 : the edge specified in the rdesc. Return false if either the symbol or the
4335 : reference could not be found, otherwise return true. */
4336 :
4337 : static bool
4338 1001 : try_decrement_rdesc_refcount (struct ipa_jump_func *jfunc)
4339 : {
4340 1001 : struct ipa_cst_ref_desc *rdesc;
4341 1001 : if (jfunc->type == IPA_JF_CONST
4342 1001 : && (rdesc = jfunc_rdesc_usable (jfunc))
4343 1975 : && --rdesc->refcount == 0)
4344 : {
4345 782 : symtab_node *symbol = symtab_node_for_jfunc (jfunc);
4346 782 : if (!symbol)
4347 : return false;
4348 :
4349 782 : return remove_described_reference (symbol, rdesc);
4350 : }
4351 : return true;
4352 : }
4353 :
4354 : /* Try to find a destination for indirect edge IE that corresponds to a simple
4355 : call or a call of a member function pointer and where the destination is a
4356 : pointer formal parameter described by jump function JFUNC. TARGET_TYPE is
4357 : the type of the parameter to which the result of JFUNC is passed. If it can
4358 : be determined, return the newly direct edge, otherwise return NULL.
4359 : NEW_ROOT and NEW_ROOT_INFO is the node and its info that JFUNC lattices are
4360 : relative to. */
4361 :
4362 : static struct cgraph_edge *
4363 9690 : try_make_edge_direct_simple_call (struct cgraph_edge *ie,
4364 : struct ipa_jump_func *jfunc, tree target_type,
4365 : struct cgraph_node *new_root,
4366 : class ipa_node_params *new_root_info)
4367 : {
4368 9690 : tree target = NULL_TREE;
4369 9690 : cgraph_simple_indirect_info *sii
4370 9690 : = as_a <cgraph_simple_indirect_info *> (ie->indirect_info);
4371 9690 : bool agg_contents = sii->agg_contents;
4372 9690 : tree scalar = ipa_value_from_jfunc (new_root_info, jfunc, target_type);
4373 9690 : if (agg_contents)
4374 : {
4375 7469 : if (scalar)
4376 23 : target = ipa_find_agg_cst_from_init (scalar, sii->offset, sii->by_ref);
4377 7469 : if (!target && sii->guaranteed_unmodified)
4378 6086 : target = ipa_find_agg_cst_from_jfunc_items (&jfunc->agg, new_root_info,
4379 : new_root, sii->offset,
4380 : sii->by_ref);
4381 : }
4382 : else
4383 : target = scalar;
4384 9689 : if (!target)
4385 : return NULL;
4386 1396 : cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target);
4387 :
4388 1396 : if (cs && !agg_contents)
4389 : {
4390 1001 : bool ok;
4391 1001 : gcc_checking_assert (cs->callee
4392 : && (cs != ie
4393 : || jfunc->type != IPA_JF_CONST
4394 : || !symtab_node_for_jfunc (jfunc)
4395 : || cs->callee == symtab_node_for_jfunc (jfunc)));
4396 1001 : ok = try_decrement_rdesc_refcount (jfunc);
4397 1001 : gcc_checking_assert (ok);
4398 : }
4399 :
4400 : return cs;
4401 : }
4402 :
4403 : /* Return the target to be used in cases of impossible devirtualization. IE
4404 : and target (the latter can be NULL) are dumped when dumping is enabled. */
4405 :
4406 : tree
4407 508 : ipa_impossible_devirt_target (struct cgraph_edge *ie, tree target)
4408 : {
4409 508 : if (dump_file)
4410 : {
4411 57 : if (target)
4412 18 : fprintf (dump_file,
4413 : "Type inconsistent devirtualization: %s->%s\n",
4414 18 : ie->caller->dump_name (),
4415 18 : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
4416 : else
4417 39 : fprintf (dump_file,
4418 : "No devirtualization target in %s\n",
4419 39 : ie->caller->dump_name ());
4420 : }
4421 508 : tree new_target = builtin_decl_unreachable ();
4422 508 : cgraph_node::get_create (new_target);
4423 508 : return new_target;
4424 : }
4425 :
4426 : /* Try to find a destination for indirect edge IE that corresponds to a virtual
4427 : call based on a formal parameter which is described by jump function JFUNC
4428 : and if it can be determined, make it direct and return the direct edge.
4429 : Otherwise, return NULL. CTX describes the polymorphic context that the
4430 : parameter the call is based on brings along with it. NEW_ROOT and
4431 : NEW_ROOT_INFO is the node and its info that JFUNC lattices are relative
4432 : to. */
4433 :
4434 : static struct cgraph_edge *
4435 18377 : try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
4436 : struct ipa_jump_func *jfunc,
4437 : class ipa_polymorphic_call_context ctx,
4438 : struct cgraph_node *new_root,
4439 : class ipa_node_params *new_root_info)
4440 : {
4441 18377 : tree target = NULL;
4442 18377 : bool speculative = false;
4443 :
4444 18377 : if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
4445 : return NULL;
4446 18377 : cgraph_polymorphic_indirect_info *pii
4447 18377 : = as_a <cgraph_polymorphic_indirect_info *> (ie->indirect_info);
4448 18377 : if (!pii->usable_p ())
4449 : return nullptr;
4450 :
4451 : /* Try to do lookup via known virtual table pointer value. */
4452 18377 : if (!pii->vptr_changed
4453 18377 : || opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively))
4454 : {
4455 18377 : tree vtable;
4456 18377 : unsigned HOST_WIDE_INT offset;
4457 18377 : tree t = NULL_TREE;
4458 18377 : if (jfunc->type == IPA_JF_CONST)
4459 330 : t = ipa_find_agg_cst_from_init (ipa_get_jf_constant (jfunc),
4460 : pii->offset, true);
4461 330 : if (!t)
4462 18374 : t = ipa_find_agg_cst_from_jfunc_items (&jfunc->agg, new_root_info,
4463 : new_root, pii->offset, true);
4464 18377 : if (t && vtable_pointer_value_to_vtable (t, &vtable, &offset))
4465 : {
4466 732 : bool can_refer;
4467 732 : t = gimple_get_virt_method_for_vtable (pii->otr_token, vtable, offset,
4468 : &can_refer);
4469 732 : if (can_refer)
4470 : {
4471 715 : if (!t
4472 715 : || fndecl_built_in_p (t, BUILT_IN_UNREACHABLE,
4473 : BUILT_IN_UNREACHABLE_TRAP)
4474 1382 : || !possible_polymorphic_call_target_p
4475 667 : (ie, cgraph_node::get (t)))
4476 : {
4477 : /* Do not speculate builtin_unreachable, it is stupid! */
4478 90 : if (!pii->vptr_changed)
4479 90 : target = ipa_impossible_devirt_target (ie, target);
4480 : else
4481 : target = NULL;
4482 : }
4483 : else
4484 : {
4485 625 : target = t;
4486 625 : speculative = pii->vptr_changed;
4487 : }
4488 : }
4489 : }
4490 : }
4491 :
4492 18377 : ipa_polymorphic_call_context ie_context (ie);
4493 18377 : vec <cgraph_node *>targets;
4494 18377 : bool final;
4495 :
4496 18377 : ctx.offset_by (pii->offset);
4497 18377 : if (pii->vptr_changed)
4498 6234 : ctx.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
4499 : pii->otr_type);
4500 18377 : ctx.combine_with (ie_context, pii->otr_type);
4501 18377 : targets = possible_polymorphic_call_targets (pii->otr_type, pii->otr_token,
4502 : ctx, &final);
4503 20504 : if (final && targets.length () <= 1)
4504 : {
4505 2108 : speculative = false;
4506 2108 : if (targets.length () == 1)
4507 2057 : target = targets[0]->decl;
4508 : else
4509 51 : target = ipa_impossible_devirt_target (ie, NULL_TREE);
4510 : }
4511 16261 : else if (!target && opt_for_fn (ie->caller->decl,
4512 : flag_devirtualize_speculatively)
4513 32448 : && !ie->speculative && ie->maybe_hot_p ())
4514 : {
4515 8933 : cgraph_node *n;
4516 8933 : n = try_speculative_devirtualization (pii->otr_type, pii->otr_token,
4517 : pii->context);
4518 8933 : if (n)
4519 : {
4520 28 : target = n->decl;
4521 28 : speculative = true;
4522 : }
4523 : }
4524 :
4525 18377 : if (target)
4526 : {
4527 2144 : if (!possible_polymorphic_call_target_p
4528 2144 : (ie, cgraph_node::get_create (target)))
4529 : {
4530 51 : if (speculative)
4531 : return NULL;
4532 51 : target = ipa_impossible_devirt_target (ie, target);
4533 : }
4534 2144 : return ipa_make_edge_direct_to_target (ie, target, speculative);
4535 : }
4536 : else
4537 : return NULL;
4538 : }
4539 :
4540 : /* Update the param called notes associated with NODE when CS is being inlined,
4541 : assuming NODE is (potentially indirectly) inlined into CS->callee.
4542 : Moreover, if the callee is discovered to be constant, create a new cgraph
4543 : edge for it. Newly discovered indirect edges will be added to *NEW_EDGES,
4544 : unless NEW_EDGES is NULL. Return true iff a new edge(s) were created. */
4545 :
4546 : static bool
4547 1747637 : update_indirect_edges_after_inlining (struct cgraph_edge *cs,
4548 : struct cgraph_node *node,
4549 : vec<cgraph_edge *> *new_edges)
4550 : {
4551 1747637 : bool res = false;
4552 :
4553 1747637 : ipa_check_create_edge_args ();
4554 1747637 : class ipa_edge_args *top = ipa_edge_args_sum->get (cs);
4555 1187681 : cgraph_node *new_root
4556 1747637 : = cs->caller->inlined_to ? cs->caller->inlined_to : cs->caller;
4557 1747637 : ipa_node_params *new_root_info = ipa_node_params_sum->get (new_root);
4558 1747637 : ipa_node_params *inlined_node_info
4559 1747637 : = ipa_node_params_sum->get (cs->callee->function_symbol ());
4560 :
4561 1747637 : cgraph_edge *next_ie;
4562 1820948 : for (cgraph_edge *ie = node->indirect_calls; ie; ie = next_ie)
4563 : {
4564 73311 : next_ie = ie->next_callee;
4565 :
4566 118388 : if (!top
4567 73193 : || ie->indirect_info->param_index < 0
4568 129783 : || ie->indirect_info->param_index >= ipa_get_cs_argument_count (top))
4569 : {
4570 45077 : ie->indirect_info->param_index = -1;
4571 48575 : continue;
4572 : }
4573 :
4574 28234 : int param_index = ie->indirect_info->param_index;
4575 28234 : cgraph_polymorphic_indirect_info *pii
4576 28234 : = dyn_cast <cgraph_polymorphic_indirect_info *> (ie->indirect_info);
4577 28234 : cgraph_simple_indirect_info *sii
4578 28234 : = dyn_cast <cgraph_simple_indirect_info *> (ie->indirect_info);
4579 28234 : struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (top, param_index);
4580 :
4581 28234 : auto_vec<cgraph_node *, 4> spec_targets;
4582 28234 : if (ie->speculative)
4583 8208 : for (cgraph_edge *direct = ie->first_speculative_call_target ();
4584 20879 : direct;
4585 12671 : direct = direct->next_speculative_call_target ())
4586 12671 : spec_targets.safe_push (direct->callee);
4587 :
4588 28234 : cgraph_edge *new_direct_edge;
4589 28234 : if (!opt_for_fn (node->decl, flag_indirect_inlining))
4590 167 : new_direct_edge = NULL;
4591 28067 : else if (pii)
4592 : {
4593 18377 : ipa_polymorphic_call_context ctx;
4594 18377 : ctx = ipa_context_from_jfunc (new_root_info, cs, param_index, jfunc);
4595 18377 : new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc, ctx,
4596 : new_root,
4597 : new_root_info);
4598 : }
4599 9690 : else if (sii)
4600 : {
4601 9690 : tree target_type = ipa_get_type (inlined_node_info, param_index);
4602 9690 : new_direct_edge = try_make_edge_direct_simple_call (ie, jfunc,
4603 : target_type,
4604 : new_root,
4605 : new_root_info);
4606 : }
4607 : else
4608 0 : gcc_unreachable ();
4609 :
4610 : /* If speculation was removed, then we need to do nothing. */
4611 3532 : if (new_direct_edge && new_direct_edge != ie
4612 29029 : && spec_targets.contains (new_direct_edge->callee))
4613 : {
4614 761 : new_direct_edge->indirect_inlining_edge = 1;
4615 761 : res = true;
4616 761 : if (!new_direct_edge->speculative)
4617 761 : continue;
4618 : }
4619 27473 : else if (new_direct_edge)
4620 : {
4621 2771 : new_direct_edge->indirect_inlining_edge = 1;
4622 2771 : if (new_edges)
4623 : {
4624 2767 : new_edges->safe_push (new_direct_edge);
4625 2767 : res = true;
4626 : }
4627 : /* If speculative edge was introduced we still need to update
4628 : call info of the indirect edge. */
4629 2771 : if (!new_direct_edge->speculative)
4630 2737 : continue;
4631 : }
4632 24736 : if (jfunc->type == IPA_JF_PASS_THROUGH
4633 24736 : && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4634 : {
4635 5888 : if (!pii
4636 2693 : && sii->agg_contents
4637 7412 : && !ipa_get_jf_pass_through_agg_preserved (jfunc))
4638 991 : ie->indirect_info->param_index = -1;
4639 : else
4640 : {
4641 4897 : param_index = ipa_get_jf_pass_through_formal_id (jfunc);
4642 4897 : ie->indirect_info->param_index = param_index;
4643 4897 : ipa_set_param_used_by_indirect_call (new_root_info, param_index,
4644 : true);
4645 4897 : if (pii)
4646 : {
4647 3195 : if (!ipa_get_jf_pass_through_type_preserved (jfunc))
4648 2088 : pii->vptr_changed = true;
4649 3195 : ipa_set_param_used_by_polymorphic_call (new_root_info,
4650 : param_index, true);
4651 : }
4652 : }
4653 : }
4654 18848 : else if (jfunc->type == IPA_JF_ANCESTOR)
4655 : {
4656 556 : if (!pii
4657 192 : && sii->agg_contents
4658 748 : && !ipa_get_jf_ancestor_agg_preserved (jfunc))
4659 80 : ie->indirect_info->param_index = -1;
4660 : else
4661 : {
4662 476 : param_index = ipa_get_jf_ancestor_formal_id (jfunc);
4663 476 : ie->indirect_info->param_index = param_index;
4664 476 : ipa_set_param_used_by_indirect_call (new_root_info, param_index,
4665 : true);
4666 476 : if (pii)
4667 : {
4668 364 : pii->offset += ipa_get_jf_ancestor_offset (jfunc);
4669 364 : if (!ipa_get_jf_ancestor_type_preserved (jfunc))
4670 324 : pii->vptr_changed = true;
4671 364 : ipa_set_param_used_by_polymorphic_call (new_root_info,
4672 : param_index, true);
4673 : }
4674 : else
4675 112 : sii->offset += ipa_get_jf_ancestor_offset (jfunc);
4676 : }
4677 : }
4678 : else
4679 : /* Either we can find a destination for this edge now or never. */
4680 18292 : ie->indirect_info->param_index = -1;
4681 28234 : }
4682 :
4683 1747637 : return res;
4684 : }
4685 :
4686 : /* Recursively traverse subtree of NODE (including node) made of inlined
4687 : cgraph_edges when CS has been inlined and invoke
4688 : update_indirect_edges_after_inlining on all nodes and
4689 : update_jump_functions_after_inlining on all non-inlined edges that lead out
4690 : of this subtree. Newly discovered indirect edges will be added to
4691 : *NEW_EDGES, unless NEW_EDGES is NULL. Return true iff a new edge(s) were
4692 : created. */
4693 :
4694 : static bool
4695 1747637 : propagate_info_to_inlined_callees (struct cgraph_edge *cs,
4696 : struct cgraph_node *node,
4697 : vec<cgraph_edge *> *new_edges)
4698 : {
4699 1747637 : struct cgraph_edge *e;
4700 1747637 : bool res;
4701 :
4702 1747637 : res = update_indirect_edges_after_inlining (cs, node, new_edges);
4703 :
4704 5267663 : for (e = node->callees; e; e = e->next_callee)
4705 3520026 : if (!e->inline_failed)
4706 758555 : res |= propagate_info_to_inlined_callees (cs, e->callee, new_edges);
4707 : else
4708 2761471 : update_jump_functions_after_inlining (cs, e);
4709 1817450 : for (e = node->indirect_calls; e; e = e->next_callee)
4710 69813 : update_jump_functions_after_inlining (cs, e);
4711 :
4712 1747637 : return res;
4713 : }
4714 :
4715 : /* Combine two controlled uses counts as done during inlining. */
4716 :
4717 : static int
4718 408952 : combine_controlled_uses_counters (int c, int d)
4719 : {
4720 0 : if (c == IPA_UNDESCRIBED_USE || d == IPA_UNDESCRIBED_USE)
4721 : return IPA_UNDESCRIBED_USE;
4722 : else
4723 107417 : return c + d - 1;
4724 : }
4725 :
4726 : /* Propagate number of controlled users from CS->callee to the new root of the
4727 : tree of inlined nodes. */
4728 :
4729 : static void
4730 989082 : propagate_controlled_uses (struct cgraph_edge *cs)
4731 : {
4732 989082 : ipa_edge_args *args = ipa_edge_args_sum->get (cs);
4733 989082 : if (!args)
4734 : return;
4735 693996 : struct cgraph_node *new_root = cs->caller->inlined_to
4736 987328 : ? cs->caller->inlined_to : cs->caller;
4737 987328 : ipa_node_params *new_root_info = ipa_node_params_sum->get (new_root);
4738 987328 : ipa_node_params *old_root_info = ipa_node_params_sum->get (cs->callee);
4739 987328 : int count, i;
4740 :
4741 987328 : if (!old_root_info)
4742 : return;
4743 :
4744 1919217 : count = MIN (ipa_get_cs_argument_count (args),
4745 : ipa_get_param_count (old_root_info));
4746 3019728 : for (i = 0; i < count; i++)
4747 : {
4748 2032474 : struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
4749 2032474 : struct ipa_cst_ref_desc *rdesc;
4750 :
4751 2032474 : if (jf->type == IPA_JF_PASS_THROUGH
4752 2032474 : && !ipa_get_jf_pass_through_refdesc_decremented (jf))
4753 : {
4754 351165 : int src_idx, c, d;
4755 351165 : src_idx = ipa_get_jf_pass_through_formal_id (jf);
4756 351165 : c = ipa_get_controlled_uses (new_root_info, src_idx);
4757 351165 : d = ipa_get_controlled_uses (old_root_info, i);
4758 :
4759 351165 : gcc_checking_assert (ipa_get_jf_pass_through_operation (jf)
4760 : == NOP_EXPR || c == IPA_UNDESCRIBED_USE);
4761 351165 : c = combine_controlled_uses_counters (c, d);
4762 351165 : ipa_set_controlled_uses (new_root_info, src_idx, c);
4763 351165 : bool lderef = true;
4764 351165 : if (c != IPA_UNDESCRIBED_USE)
4765 : {
4766 94670 : lderef = (ipa_get_param_load_dereferenced (new_root_info, src_idx)
4767 94670 : || ipa_get_param_load_dereferenced (old_root_info, i));
4768 94670 : ipa_set_param_load_dereferenced (new_root_info, src_idx, lderef);
4769 : }
4770 :
4771 351165 : if (c == 0 && !lderef && new_root_info->ipcp_orig_node)
4772 : {
4773 182 : struct cgraph_node *n;
4774 182 : struct ipa_ref *ref;
4775 182 : tree t = new_root_info->known_csts[src_idx];
4776 :
4777 160 : if (t && TREE_CODE (t) == ADDR_EXPR
4778 140 : && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
4779 5 : && (n = cgraph_node::get (TREE_OPERAND (t, 0)))
4780 187 : && (ref = new_root->find_reference (n, NULL, 0,
4781 : IPA_REF_ADDR)))
4782 : {
4783 5 : if (dump_file)
4784 1 : fprintf (dump_file, "ipa-prop: Removing cloning-created "
4785 : "reference from %s to %s.\n",
4786 : new_root->dump_name (),
4787 : n->dump_name ());
4788 5 : ref->remove_reference ();
4789 : }
4790 : }
4791 : }
4792 1681309 : else if (jf->type == IPA_JF_CONST
4793 1681309 : && (rdesc = jfunc_rdesc_usable (jf)))
4794 : {
4795 57787 : int d = ipa_get_controlled_uses (old_root_info, i);
4796 57787 : int c = rdesc->refcount;
4797 57787 : tree cst = ipa_get_jf_constant (jf);
4798 57787 : rdesc->refcount = combine_controlled_uses_counters (c, d);
4799 57787 : if (rdesc->refcount != IPA_UNDESCRIBED_USE
4800 12747 : && ipa_get_param_load_dereferenced (old_root_info, i)
4801 2826 : && TREE_CODE (cst) == ADDR_EXPR
4802 60613 : && VAR_P (TREE_OPERAND (cst, 0)))
4803 : {
4804 2825 : symtab_node *n = symtab_node::get (TREE_OPERAND (cst, 0));
4805 2825 : new_root->create_reference (n, IPA_REF_LOAD, NULL);
4806 2825 : if (dump_file)
4807 7 : fprintf (dump_file, "ipa-prop: Address IPA constant will reach "
4808 : "a load so adding LOAD reference from %s to %s.\n",
4809 : new_root->dump_name (), n->dump_name ());
4810 : }
4811 57787 : if (rdesc->refcount == 0)
4812 : {
4813 8363 : gcc_checking_assert (TREE_CODE (cst) == ADDR_EXPR
4814 : && ((TREE_CODE (TREE_OPERAND (cst, 0))
4815 : == FUNCTION_DECL)
4816 : || VAR_P (TREE_OPERAND (cst, 0))));
4817 :
4818 8363 : symtab_node *n = symtab_node::get (TREE_OPERAND (cst, 0));
4819 8363 : if (n)
4820 : {
4821 8363 : remove_described_reference (n, rdesc);
4822 8363 : cgraph_node *clone = cs->caller;
4823 8363 : while (clone->inlined_to
4824 1650 : && clone->ipcp_clone
4825 8597 : && clone != rdesc->cs->caller)
4826 : {
4827 98 : struct ipa_ref *ref;
4828 98 : ref = clone->find_reference (n, NULL, 0, IPA_REF_ADDR);
4829 98 : if (ref)
4830 : {
4831 95 : if (dump_file)
4832 1 : fprintf (dump_file, "ipa-prop: Removing "
4833 : "cloning-created reference "
4834 : "from %s to %s.\n",
4835 : clone->dump_name (),
4836 : n->dump_name ());
4837 95 : ref->remove_reference ();
4838 : }
4839 98 : clone = clone->callers->caller;
4840 : }
4841 : }
4842 : }
4843 : }
4844 : }
4845 :
4846 1919311 : for (i = ipa_get_param_count (old_root_info);
4847 1919871 : i < ipa_get_cs_argument_count (args);
4848 : i++)
4849 : {
4850 327 : struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
4851 :
4852 327 : if (jf->type == IPA_JF_CONST)
4853 : {
4854 291 : struct ipa_cst_ref_desc *rdesc = jfunc_rdesc_usable (jf);
4855 291 : if (rdesc)
4856 235 : rdesc->refcount = IPA_UNDESCRIBED_USE;
4857 : }
4858 36 : else if (jf->type == IPA_JF_PASS_THROUGH)
4859 5 : ipa_set_controlled_uses (new_root_info,
4860 : jf->value.pass_through.formal_id,
4861 : IPA_UNDESCRIBED_USE);
4862 : }
4863 : }
4864 :
4865 : /* Update jump functions and call note functions on inlining the call site CS.
4866 : CS is expected to lead to a node already cloned by
4867 : cgraph_clone_inline_nodes. Newly discovered indirect edges will be added to
4868 : *NEW_EDGES, unless NEW_EDGES is NULL. Return true iff a new edge(s) were +
4869 : created. */
4870 :
4871 : bool
4872 4170608 : ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
4873 : vec<cgraph_edge *> *new_edges)
4874 : {
4875 4170608 : bool changed;
4876 : /* Do nothing if the preparation phase has not been carried out yet
4877 : (i.e. during early inlining). */
4878 4170608 : if (!ipa_node_params_sum)
4879 : return false;
4880 989082 : gcc_assert (ipa_edge_args_sum);
4881 :
4882 989082 : propagate_controlled_uses (cs);
4883 989082 : changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
4884 989082 : ipa_node_params_sum->remove (cs->callee);
4885 :
4886 989082 : ipa_edge_args *args = ipa_edge_args_sum->get (cs);
4887 989082 : if (args)
4888 : {
4889 987328 : bool ok = true;
4890 987328 : if (args->jump_functions)
4891 : {
4892 : struct ipa_jump_func *jf;
4893 : int i;
4894 2764291 : FOR_EACH_VEC_ELT (*args->jump_functions, i, jf)
4895 1893540 : if (jf->type == IPA_JF_CONST
4896 1893540 : && ipa_get_jf_constant_rdesc (jf))
4897 : {
4898 : ok = false;
4899 : break;
4900 : }
4901 : }
4902 932037 : if (ok)
4903 926042 : ipa_edge_args_sum->remove (cs);
4904 : }
4905 989082 : if (ipcp_transformation_sum)
4906 678204 : ipcp_transformation_sum->remove (cs->callee);
4907 :
4908 : return changed;
4909 : }
4910 :
4911 : /* Ensure that array of edge arguments infos is big enough to accommodate a
4912 : structure for all edges and reallocates it if not. Also, allocate
4913 : associated hash tables is they do not already exist. */
4914 :
4915 : void
4916 5024812 : ipa_check_create_edge_args (void)
4917 : {
4918 5024812 : if (!ipa_edge_args_sum)
4919 249620 : ipa_edge_args_sum
4920 249620 : = (new (ggc_alloc_no_dtor<ipa_edge_args_sum_t> ())
4921 249620 : ipa_edge_args_sum_t (symtab, true));
4922 5024812 : if (!ipa_vr_hash_table)
4923 175152 : ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
4924 5024812 : }
4925 :
4926 : /* Free all ipa_edge structures. */
4927 :
4928 : void
4929 474266 : ipa_free_all_edge_args (void)
4930 : {
4931 474266 : if (!ipa_edge_args_sum)
4932 : return;
4933 :
4934 237204 : ggc_delete (ipa_edge_args_sum);
4935 237204 : ipa_edge_args_sum = NULL;
4936 : }
4937 :
4938 : /* Free all ipa_node_params structures. */
4939 :
4940 : void
4941 5610721 : ipa_free_all_node_params (void)
4942 : {
4943 5610721 : if (ipa_node_params_sum)
4944 5373659 : ggc_delete (ipa_node_params_sum);
4945 5610721 : ipa_node_params_sum = NULL;
4946 5610721 : }
4947 :
4948 : /* Initialize IPA CP transformation summary and also allocate any necessary hash
4949 : tables if they do not already exist. */
4950 :
4951 : void
4952 92062 : ipcp_transformation_initialize (void)
4953 : {
4954 92062 : if (!ipa_vr_hash_table)
4955 1901 : ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
4956 92062 : if (ipcp_transformation_sum == NULL)
4957 : {
4958 18207 : ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
4959 18207 : ipcp_transformation_sum->disable_insertion_hook ();
4960 : }
4961 92062 : }
4962 :
4963 : /* Release the IPA CP transformation summary. */
4964 :
4965 : void
4966 264319 : ipcp_free_transformation_sum (void)
4967 : {
4968 264319 : if (!ipcp_transformation_sum)
4969 : return;
4970 :
4971 18198 : ipcp_transformation_sum->~function_summary<ipcp_transformation *> ();
4972 18198 : ggc_free (ipcp_transformation_sum);
4973 18198 : ipcp_transformation_sum = NULL;
4974 : }
4975 :
4976 : /* Set the aggregate replacements of NODE to be AGGVALS. */
4977 :
4978 : void
4979 19083 : ipa_set_node_agg_value_chain (struct cgraph_node *node,
4980 : vec<ipa_argagg_value, va_gc> *aggs)
4981 : {
4982 19083 : ipcp_transformation_initialize ();
4983 19083 : ipcp_transformation *s = ipcp_transformation_sum->get_create (node);
4984 19083 : s->m_agg_values = aggs;
4985 19083 : }
4986 :
4987 : /* Hook that is called by cgraph.cc when an edge is removed. Adjust reference
4988 : count data structures accordingly. */
4989 :
4990 : void
4991 0 : ipa_edge_args_sum_t::remove (cgraph_edge *cs, ipa_edge_args *args)
4992 : {
4993 0 : if (args->jump_functions)
4994 : {
4995 : struct ipa_jump_func *jf;
4996 : int i;
4997 0 : FOR_EACH_VEC_ELT (*args->jump_functions, i, jf)
4998 : {
4999 0 : struct ipa_cst_ref_desc *rdesc;
5000 0 : try_decrement_rdesc_refcount (jf);
5001 0 : if (jf->type == IPA_JF_CONST
5002 0 : && (rdesc = ipa_get_jf_constant_rdesc (jf))
5003 0 : && rdesc->cs == cs)
5004 0 : rdesc->cs = NULL;
5005 : }
5006 : }
5007 0 : }
5008 :
5009 : /* Copy information from SRC_JF to DST_JF which correstpond to call graph edges
5010 : SRC and DST. */
5011 :
5012 : static void
5013 2995593 : ipa_duplicate_jump_function (cgraph_edge *src, cgraph_edge *dst,
5014 : ipa_jump_func *src_jf, ipa_jump_func *dst_jf)
5015 : {
5016 2995593 : dst_jf->agg.items = vec_safe_copy (src_jf->agg.items);
5017 2995593 : dst_jf->agg.by_ref = src_jf->agg.by_ref;
5018 :
5019 : /* We can avoid calling ipa_set_jfunc_vr since it would only look up the
5020 : place in the hash_table where the source m_vr resides. */
5021 2995593 : dst_jf->m_vr = src_jf->m_vr;
5022 :
5023 2995593 : if (src_jf->type == IPA_JF_CONST)
5024 : {
5025 922779 : ipa_set_jf_cst_copy (dst_jf, src_jf);
5026 922779 : struct ipa_cst_ref_desc *src_rdesc = jfunc_rdesc_usable (src_jf);
5027 :
5028 922779 : if (!src_rdesc)
5029 786774 : dst_jf->value.constant.rdesc = NULL;
5030 136005 : else if (src->caller == dst->caller)
5031 : {
5032 : /* Creation of a speculative edge. If the source edge is the one
5033 : grabbing a reference, we must create a new (duplicate)
5034 : reference description. Otherwise they refer to the same
5035 : description corresponding to a reference taken in a function
5036 : src->caller is inlined to. In that case we just must
5037 : increment the refcount. */
5038 41 : if (src_rdesc->cs == src)
5039 : {
5040 41 : symtab_node *n = symtab_node_for_jfunc (src_jf);
5041 41 : gcc_checking_assert (n);
5042 41 : ipa_ref *ref
5043 41 : = src->caller->find_reference (n, src->call_stmt,
5044 : src->lto_stmt_uid,
5045 : IPA_REF_ADDR);
5046 41 : gcc_checking_assert (ref);
5047 41 : dst->caller->clone_reference (ref, ref->stmt);
5048 :
5049 41 : ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
5050 41 : dst_rdesc->cs = dst;
5051 41 : dst_rdesc->refcount = src_rdesc->refcount;
5052 41 : dst_rdesc->next_duplicate = NULL;
5053 41 : dst_jf->value.constant.rdesc = dst_rdesc;
5054 : }
5055 : else
5056 : {
5057 0 : src_rdesc->refcount++;
5058 0 : dst_jf->value.constant.rdesc = src_rdesc;
5059 : }
5060 : }
5061 135964 : else if (src_rdesc->cs == src)
5062 : {
5063 135642 : struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
5064 135642 : dst_rdesc->cs = dst;
5065 135642 : dst_rdesc->refcount = src_rdesc->refcount;
5066 135642 : dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
5067 135642 : src_rdesc->next_duplicate = dst_rdesc;
5068 135642 : dst_jf->value.constant.rdesc = dst_rdesc;
5069 : }
5070 : else
5071 : {
5072 322 : struct ipa_cst_ref_desc *dst_rdesc;
5073 : /* This can happen during inlining, when a JFUNC can refer to a
5074 : reference taken in a function up in the tree of inline clones.
5075 : We need to find the duplicate that refers to our tree of
5076 : inline clones. */
5077 :
5078 322 : gcc_assert (dst->caller->inlined_to);
5079 322 : for (dst_rdesc = src_rdesc->next_duplicate;
5080 322 : dst_rdesc;
5081 0 : dst_rdesc = dst_rdesc->next_duplicate)
5082 : {
5083 322 : struct cgraph_node *top;
5084 2 : top = dst_rdesc->cs->caller->inlined_to
5085 322 : ? dst_rdesc->cs->caller->inlined_to
5086 : : dst_rdesc->cs->caller;
5087 322 : if (dst->caller->inlined_to == top)
5088 : break;
5089 : }
5090 322 : gcc_assert (dst_rdesc);
5091 322 : dst_jf->value.constant.rdesc = dst_rdesc;
5092 : }
5093 : }
5094 2072814 : else if (src_jf->type == IPA_JF_PASS_THROUGH)
5095 : {
5096 744237 : dst_jf->type = IPA_JF_PASS_THROUGH;
5097 744237 : dst_jf->value.pass_through = src_jf->value.pass_through;
5098 744237 : if (src->caller == dst->caller)
5099 : {
5100 10578 : struct cgraph_node *inline_root = dst->caller->inlined_to
5101 10616 : ? dst->caller->inlined_to : dst->caller;
5102 10616 : ipa_node_params *root_info = ipa_node_params_sum->get (inline_root);
5103 10616 : int idx = ipa_get_jf_pass_through_formal_id (dst_jf);
5104 :
5105 10616 : int c = ipa_get_controlled_uses (root_info, idx);
5106 10616 : if (c != IPA_UNDESCRIBED_USE)
5107 : {
5108 2640 : c++;
5109 2640 : ipa_set_controlled_uses (root_info, idx, c);
5110 : }
5111 : }
5112 : }
5113 1328577 : else if (src_jf->type == IPA_JF_ANCESTOR)
5114 : {
5115 102238 : dst_jf->type = IPA_JF_ANCESTOR;
5116 102238 : dst_jf->value.ancestor = src_jf->value.ancestor;
5117 : }
5118 : else
5119 1226339 : gcc_assert (src_jf->type == IPA_JF_UNKNOWN);
5120 2995593 : }
5121 :
5122 : /* Method invoked when an edge is duplicated. Copy ipa_edge_args and adjust
5123 : reference count data structures accordingly. */
5124 :
5125 : void
5126 1376154 : ipa_edge_args_sum_t::duplicate (cgraph_edge *src, cgraph_edge *dst,
5127 : ipa_edge_args *old_args, ipa_edge_args *new_args)
5128 : {
5129 1376154 : unsigned int i;
5130 :
5131 1376154 : if (old_args->polymorphic_call_contexts)
5132 177243 : new_args->polymorphic_call_contexts
5133 177243 : = vec_safe_copy (old_args->polymorphic_call_contexts);
5134 :
5135 1376154 : if (!vec_safe_length (old_args->jump_functions))
5136 : {
5137 56762 : new_args->jump_functions = NULL;
5138 56762 : return;
5139 : }
5140 :
5141 1319392 : if (src->has_callback && dst->callback)
5142 : {
5143 15127 : gcc_assert (src->caller == dst->caller);
5144 15127 : tree attr = callback_fetch_attr_by_edge (dst, src);
5145 15127 : unsigned arg_count = callback_num_args (attr);
5146 15127 : vec_safe_grow_cleared (new_args->jump_functions, arg_count, true);
5147 : /* Duplication of jump functions is handled separately for callback
5148 : pairs. */
5149 15127 : return;
5150 : }
5151 :
5152 1304265 : vec_safe_grow_cleared (new_args->jump_functions,
5153 1304265 : old_args->jump_functions->length (), true);
5154 :
5155 5588995 : for (i = 0; i < vec_safe_length (old_args->jump_functions); i++)
5156 : {
5157 2980465 : struct ipa_jump_func *src_jf = ipa_get_ith_jump_func (old_args, i);
5158 2980465 : struct ipa_jump_func *dst_jf = ipa_get_ith_jump_func (new_args, i);
5159 :
5160 2980465 : ipa_duplicate_jump_function (src, dst, src_jf, dst_jf);
5161 : }
5162 : }
5163 :
5164 : /* Analyze newly added function into callgraph. */
5165 :
5166 : static void
5167 41321 : ipa_add_new_function (cgraph_node *node, void *data ATTRIBUTE_UNUSED)
5168 : {
5169 41321 : if (node->has_gimple_body_p ())
5170 41321 : ipa_analyze_node (node);
5171 41321 : }
5172 :
5173 : /* Hook that is called by summary when a node is duplicated. */
5174 :
5175 : void
5176 814564 : ipa_node_params_t::duplicate(cgraph_node *, cgraph_node *,
5177 : ipa_node_params *old_info,
5178 : ipa_node_params *new_info)
5179 : {
5180 814564 : new_info->descriptors = vec_safe_copy (old_info->descriptors);
5181 814564 : gcc_assert (new_info->lattices.is_empty ());
5182 814564 : new_info->ipcp_orig_node = old_info->ipcp_orig_node;
5183 814564 : new_info->known_csts = old_info->known_csts.copy ();
5184 814564 : new_info->known_contexts = old_info->known_contexts.copy ();
5185 :
5186 814564 : new_info->analysis_done = old_info->analysis_done;
5187 814564 : new_info->node_enqueued = old_info->node_enqueued;
5188 814564 : new_info->versionable = old_info->versionable;
5189 814564 : }
5190 :
5191 : /* Duplication of ipcp transformation summaries. */
5192 :
5193 : void
5194 45576 : ipcp_transformation_t::duplicate(cgraph_node *, cgraph_node *dst,
5195 : ipcp_transformation *src_trans,
5196 : ipcp_transformation *dst_trans)
5197 : {
5198 : /* Avoid redundant work of duplicating vectors we will never use. */
5199 45576 : if (dst->inlined_to)
5200 : return;
5201 8473 : dst_trans->m_agg_values = vec_safe_copy (src_trans->m_agg_values);
5202 15732 : dst_trans->m_vr = vec_safe_copy (src_trans->m_vr);
5203 : }
5204 :
5205 : /* Register our cgraph hooks if they are not already there. */
5206 :
5207 : void
5208 389390 : ipa_register_cgraph_hooks (void)
5209 : {
5210 389390 : ipa_check_create_node_params ();
5211 389390 : ipa_check_create_edge_args ();
5212 389390 : callback_info_sum_t::check_create_info_sum ();
5213 :
5214 778780 : function_insertion_hook_holder =
5215 389390 : symtab->add_cgraph_insertion_hook (&ipa_add_new_function, NULL);
5216 389390 : }
5217 :
5218 : /* Unregister our cgraph hooks if they are not already there. */
5219 :
5220 : static void
5221 474266 : ipa_unregister_cgraph_hooks (void)
5222 : {
5223 474266 : if (function_insertion_hook_holder)
5224 237204 : symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder);
5225 474266 : function_insertion_hook_holder = NULL;
5226 474266 : }
5227 :
5228 : /* Free all ipa_node_params and all ipa_edge_args structures if they are no
5229 : longer needed after ipa-cp. */
5230 :
5231 : void
5232 130859 : ipa_free_all_structures_after_ipa_cp (void)
5233 : {
5234 130859 : if (!optimize && !in_lto_p)
5235 : {
5236 0 : ipa_free_all_edge_args ();
5237 0 : ipa_free_all_node_params ();
5238 0 : ipcp_sources_pool.release ();
5239 0 : ipcp_cst_values_pool.release ();
5240 0 : ipcp_poly_ctx_values_pool.release ();
5241 0 : ipcp_agg_lattice_pool.release ();
5242 0 : ipa_unregister_cgraph_hooks ();
5243 0 : ipa_refdesc_pool.release ();
5244 : }
5245 130859 : }
5246 :
5247 : /* Free all ipa_node_params and all ipa_edge_args structures if they are no
5248 : longer needed after indirect inlining. */
5249 :
5250 : void
5251 474266 : ipa_free_all_structures_after_iinln (void)
5252 : {
5253 474266 : ipa_free_all_edge_args ();
5254 474266 : ipa_free_all_node_params ();
5255 474266 : ipa_unregister_cgraph_hooks ();
5256 474266 : ipcp_sources_pool.release ();
5257 474266 : ipcp_cst_values_pool.release ();
5258 474266 : ipcp_poly_ctx_values_pool.release ();
5259 474266 : ipcp_agg_lattice_pool.release ();
5260 474266 : ipa_refdesc_pool.release ();
5261 474266 : }
5262 :
5263 : /* Print ipa_tree_map data structures of all functions in the
5264 : callgraph to F. */
5265 :
5266 : void
5267 241 : ipa_print_node_params (FILE *f, struct cgraph_node *node)
5268 : {
5269 241 : int i, count;
5270 241 : class ipa_node_params *info;
5271 :
5272 241 : if (!node->definition)
5273 : return;
5274 183 : info = ipa_node_params_sum->get (node);
5275 183 : fprintf (f, " function %s parameter descriptors:\n", node->dump_name ());
5276 183 : if (!info)
5277 : {
5278 0 : fprintf (f, " no params return\n");
5279 0 : return;
5280 : }
5281 183 : count = ipa_get_param_count (info);
5282 371 : for (i = 0; i < count; i++)
5283 : {
5284 188 : int c;
5285 :
5286 188 : fprintf (f, " ");
5287 188 : ipa_dump_param (f, info, i);
5288 188 : if (ipa_is_param_used (info, i))
5289 181 : fprintf (f, " used");
5290 188 : if (ipa_is_param_used_by_ipa_predicates (info, i))
5291 109 : fprintf (f, " used_by_ipa_predicates");
5292 188 : if (ipa_is_param_used_by_indirect_call (info, i))
5293 10 : fprintf (f, " used_by_indirect_call");
5294 188 : if (ipa_is_param_used_by_polymorphic_call (info, i))
5295 0 : fprintf (f, " used_by_polymorphic_call");
5296 188 : c = ipa_get_controlled_uses (info, i);
5297 188 : if (c == IPA_UNDESCRIBED_USE)
5298 108 : fprintf (f, " undescribed_use");
5299 : else
5300 137 : fprintf (f, " controlled_uses=%i %s", c,
5301 80 : ipa_get_param_load_dereferenced (info, i)
5302 : ? "(load_dereferenced)" : "");
5303 188 : fprintf (f, "\n");
5304 : }
5305 : }
5306 :
5307 : /* Print ipa_tree_map data structures of all functions in the
5308 : callgraph to F. */
5309 :
5310 : void
5311 48 : ipa_print_all_params (FILE * f)
5312 : {
5313 48 : struct cgraph_node *node;
5314 :
5315 48 : fprintf (f, "\nFunction parameters:\n");
5316 273 : FOR_EACH_FUNCTION (node)
5317 225 : ipa_print_node_params (f, node);
5318 48 : }
5319 :
5320 : /* Stream out jump function JUMP_FUNC to OB. */
5321 :
5322 : static void
5323 609844 : ipa_write_jump_function (struct output_block *ob,
5324 : struct ipa_jump_func *jump_func)
5325 : {
5326 609844 : struct ipa_agg_jf_item *item;
5327 609844 : struct bitpack_d bp;
5328 609844 : int i, count;
5329 609844 : int flag = 0;
5330 :
5331 : /* ADDR_EXPRs are very common IP invariants; save some streamer data
5332 : as well as WPA memory by handling them specially. */
5333 609844 : if (jump_func->type == IPA_JF_CONST
5334 465156 : && TREE_CODE (jump_func->value.constant.value) == ADDR_EXPR)
5335 609844 : flag = 1;
5336 :
5337 609844 : streamer_write_uhwi (ob, jump_func->type * 2 + flag);
5338 609844 : switch (jump_func->type)
5339 : {
5340 : case IPA_JF_UNKNOWN:
5341 : break;
5342 465156 : case IPA_JF_CONST:
5343 465156 : gcc_assert (
5344 : EXPR_LOCATION (jump_func->value.constant.value) == UNKNOWN_LOCATION);
5345 465156 : stream_write_tree (ob,
5346 : flag
5347 : ? TREE_OPERAND (jump_func->value.constant.value, 0)
5348 : : jump_func->value.constant.value, true);
5349 465156 : break;
5350 76946 : case IPA_JF_PASS_THROUGH:
5351 76946 : streamer_write_uhwi (ob, jump_func->value.pass_through.operation);
5352 76946 : if (jump_func->value.pass_through.operation == NOP_EXPR)
5353 : {
5354 76122 : streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
5355 76122 : bp = bitpack_create (ob->main_stream);
5356 76122 : bp_pack_value (&bp, jump_func->value.pass_through.agg_preserved, 1);
5357 76122 : gcc_assert (!jump_func->value.pass_through.refdesc_decremented);
5358 76122 : streamer_write_bitpack (&bp);
5359 : }
5360 824 : else if (TREE_CODE_CLASS (jump_func->value.pass_through.operation)
5361 : == tcc_unary)
5362 : {
5363 39 : stream_write_tree (ob, jump_func->value.pass_through.op_type, true);
5364 39 : streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
5365 : }
5366 : else
5367 : {
5368 785 : stream_write_tree (ob, jump_func->value.pass_through.op_type, true);
5369 785 : stream_write_tree (ob, jump_func->value.pass_through.operand, true);
5370 785 : streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
5371 : }
5372 : break;
5373 1343 : case IPA_JF_ANCESTOR:
5374 1343 : streamer_write_uhwi (ob, jump_func->value.ancestor.offset);
5375 1343 : streamer_write_uhwi (ob, jump_func->value.ancestor.formal_id);
5376 1343 : bp = bitpack_create (ob->main_stream);
5377 1343 : bp_pack_value (&bp, jump_func->value.ancestor.agg_preserved, 1);
5378 1343 : bp_pack_value (&bp, jump_func->value.ancestor.keep_null, 1);
5379 1343 : streamer_write_bitpack (&bp);
5380 1343 : break;
5381 0 : default:
5382 0 : fatal_error (UNKNOWN_LOCATION, "invalid jump function in LTO stream");
5383 : }
5384 :
5385 609844 : count = vec_safe_length (jump_func->agg.items);
5386 609844 : streamer_write_uhwi (ob, count);
5387 609844 : if (count)
5388 : {
5389 3318 : bp = bitpack_create (ob->main_stream);
5390 3318 : bp_pack_value (&bp, jump_func->agg.by_ref, 1);
5391 3318 : streamer_write_bitpack (&bp);
5392 : }
5393 :
5394 616490 : FOR_EACH_VEC_SAFE_ELT (jump_func->agg.items, i, item)
5395 : {
5396 6646 : stream_write_tree (ob, item->type, true);
5397 6646 : streamer_write_uhwi (ob, item->offset);
5398 6646 : streamer_write_uhwi (ob, item->jftype);
5399 6646 : switch (item->jftype)
5400 : {
5401 : case IPA_JF_UNKNOWN:
5402 : break;
5403 6131 : case IPA_JF_CONST:
5404 6131 : stream_write_tree (ob, item->value.constant, true);
5405 6131 : break;
5406 515 : case IPA_JF_PASS_THROUGH:
5407 515 : case IPA_JF_LOAD_AGG:
5408 515 : streamer_write_uhwi (ob, item->value.pass_through.operation);
5409 515 : streamer_write_uhwi (ob, item->value.pass_through.formal_id);
5410 515 : if (item->value.pass_through.operation != NOP_EXPR)
5411 4 : stream_write_tree (ob, item->value.pass_through.op_type, true);
5412 515 : if (TREE_CODE_CLASS (item->value.pass_through.operation)
5413 : != tcc_unary)
5414 4 : stream_write_tree (ob, item->value.pass_through.operand, true);
5415 515 : if (item->jftype == IPA_JF_LOAD_AGG)
5416 : {
5417 79 : stream_write_tree (ob, item->value.load_agg.type, true);
5418 79 : streamer_write_uhwi (ob, item->value.load_agg.offset);
5419 79 : bp = bitpack_create (ob->main_stream);
5420 79 : bp_pack_value (&bp, item->value.load_agg.by_ref, 1);
5421 79 : streamer_write_bitpack (&bp);
5422 : }
5423 : break;
5424 0 : default:
5425 0 : fatal_error (UNKNOWN_LOCATION,
5426 : "invalid jump function in LTO stream");
5427 : }
5428 : }
5429 :
5430 609844 : bp = bitpack_create (ob->main_stream);
5431 609844 : if (jump_func->m_vr)
5432 423834 : jump_func->m_vr->streamer_write (ob);
5433 : else
5434 : {
5435 186010 : bp_pack_value (&bp, false, 1);
5436 186010 : streamer_write_bitpack (&bp);
5437 : }
5438 609844 : }
5439 :
5440 : /* Read in jump function JUMP_FUNC from IB. */
5441 :
5442 : static void
5443 570336 : ipa_read_jump_function (class lto_input_block *ib,
5444 : struct ipa_jump_func *jump_func,
5445 : struct cgraph_edge *cs,
5446 : class data_in *data_in,
5447 : bool prevails)
5448 : {
5449 570336 : enum jump_func_type jftype;
5450 570336 : enum tree_code operation;
5451 570336 : int i, count;
5452 570336 : int val = streamer_read_uhwi (ib);
5453 570336 : bool flag = val & 1;
5454 :
5455 570336 : jftype = (enum jump_func_type) (val / 2);
5456 570336 : switch (jftype)
5457 : {
5458 50846 : case IPA_JF_UNKNOWN:
5459 50846 : ipa_set_jf_unknown (jump_func);
5460 50846 : break;
5461 448752 : case IPA_JF_CONST:
5462 448752 : {
5463 448752 : tree t = stream_read_tree (ib, data_in);
5464 448752 : if (flag && prevails)
5465 161685 : t = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
5466 448752 : ipa_set_jf_constant (jump_func, t, cs);
5467 : }
5468 448752 : break;
5469 70064 : case IPA_JF_PASS_THROUGH:
5470 70064 : operation = (enum tree_code) streamer_read_uhwi (ib);
5471 70064 : if (operation == NOP_EXPR)
5472 : {
5473 69527 : int formal_id = streamer_read_uhwi (ib);
5474 69527 : struct bitpack_d bp = streamer_read_bitpack (ib);
5475 69527 : bool agg_preserved = bp_unpack_value (&bp, 1);
5476 69527 : ipa_set_jf_simple_pass_through (jump_func, formal_id, agg_preserved);
5477 : }
5478 537 : else if (TREE_CODE_CLASS (operation) == tcc_unary)
5479 : {
5480 19 : tree op_type = stream_read_tree (ib, data_in);
5481 19 : int formal_id = streamer_read_uhwi (ib);
5482 19 : ipa_set_jf_unary_pass_through (jump_func, formal_id, operation,
5483 : op_type);
5484 : }
5485 : else
5486 : {
5487 518 : tree op_type = stream_read_tree (ib, data_in);
5488 518 : tree operand = stream_read_tree (ib, data_in);
5489 518 : int formal_id = streamer_read_uhwi (ib);
5490 518 : ipa_set_jf_arith_pass_through (jump_func, formal_id, operand,
5491 : operation, op_type);
5492 : }
5493 : break;
5494 674 : case IPA_JF_ANCESTOR:
5495 674 : {
5496 674 : HOST_WIDE_INT offset = streamer_read_uhwi (ib);
5497 674 : int formal_id = streamer_read_uhwi (ib);
5498 674 : struct bitpack_d bp = streamer_read_bitpack (ib);
5499 674 : bool agg_preserved = bp_unpack_value (&bp, 1);
5500 674 : bool keep_null = bp_unpack_value (&bp, 1);
5501 674 : ipa_set_ancestor_jf (jump_func, offset, formal_id, agg_preserved,
5502 : keep_null);
5503 674 : break;
5504 : }
5505 0 : default:
5506 0 : fatal_error (UNKNOWN_LOCATION, "invalid jump function in LTO stream");
5507 : }
5508 :
5509 570336 : count = streamer_read_uhwi (ib);
5510 570336 : if (prevails)
5511 : {
5512 570330 : jump_func->agg.items = NULL;
5513 570330 : vec_safe_reserve (jump_func->agg.items, count, true);
5514 : }
5515 570336 : if (count)
5516 : {
5517 2962 : struct bitpack_d bp = streamer_read_bitpack (ib);
5518 2962 : jump_func->agg.by_ref = bp_unpack_value (&bp, 1);
5519 : }
5520 576372 : for (i = 0; i < count; i++)
5521 : {
5522 6036 : struct ipa_agg_jf_item item;
5523 6036 : item.type = stream_read_tree (ib, data_in);
5524 6036 : item.offset = streamer_read_uhwi (ib);
5525 6036 : item.jftype = (enum jump_func_type) streamer_read_uhwi (ib);
5526 :
5527 6036 : switch (item.jftype)
5528 : {
5529 : case IPA_JF_UNKNOWN:
5530 : break;
5531 5601 : case IPA_JF_CONST:
5532 5601 : item.value.constant = stream_read_tree (ib, data_in);
5533 5601 : break;
5534 435 : case IPA_JF_PASS_THROUGH:
5535 435 : case IPA_JF_LOAD_AGG:
5536 435 : operation = (enum tree_code) streamer_read_uhwi (ib);
5537 435 : item.value.pass_through.operation = operation;
5538 435 : item.value.pass_through.formal_id = streamer_read_uhwi (ib);
5539 435 : if (operation != NOP_EXPR)
5540 0 : item.value.pass_through.op_type = stream_read_tree (ib, data_in);
5541 : else
5542 : item.value.pass_through.op_type = NULL_TREE;
5543 435 : if (TREE_CODE_CLASS (operation) == tcc_unary)
5544 : item.value.pass_through.operand = NULL_TREE;
5545 : else
5546 0 : item.value.pass_through.operand = stream_read_tree (ib, data_in);
5547 435 : if (item.jftype == IPA_JF_LOAD_AGG)
5548 : {
5549 43 : struct bitpack_d bp;
5550 43 : item.value.load_agg.type = stream_read_tree (ib, data_in);
5551 43 : item.value.load_agg.offset = streamer_read_uhwi (ib);
5552 43 : bp = streamer_read_bitpack (ib);
5553 43 : item.value.load_agg.by_ref = bp_unpack_value (&bp, 1);
5554 : }
5555 : break;
5556 0 : default:
5557 0 : fatal_error (UNKNOWN_LOCATION,
5558 : "invalid jump function in LTO stream");
5559 : }
5560 6036 : if (prevails)
5561 6036 : jump_func->agg.items->quick_push (item);
5562 : }
5563 :
5564 570336 : ipa_vr vr;
5565 570336 : vr.streamer_read (ib, data_in);
5566 570336 : if (vr.known_p ())
5567 : {
5568 398798 : if (prevails)
5569 398792 : ipa_set_jfunc_vr (jump_func, vr);
5570 : }
5571 : else
5572 171538 : jump_func->m_vr = NULL;
5573 570336 : }
5574 :
5575 : /* Stream out parts of cgraph_indirect_call_info corresponding to CS that are
5576 : relevant to indirect inlining to OB. */
5577 :
5578 : static void
5579 2624 : ipa_write_indirect_edge_info (struct output_block *ob,
5580 : struct cgraph_edge *cs)
5581 : {
5582 2624 : struct bitpack_d bp;
5583 :
5584 2624 : bp = bitpack_create (ob->main_stream);
5585 2624 : bp_pack_enum (&bp, cgraph_indirect_info_kind, CIIK_N_KINDS,
5586 : cs->indirect_info->kind);
5587 2624 : streamer_write_bitpack (&bp);
5588 :
5589 2624 : if (cgraph_polymorphic_indirect_info *pii
5590 2624 : = dyn_cast <cgraph_polymorphic_indirect_info *> (cs->indirect_info))
5591 : {
5592 1025 : bp = bitpack_create (ob->main_stream);
5593 1025 : bp_pack_value (&bp, pii->vptr_changed, 1);
5594 1025 : streamer_write_bitpack (&bp);
5595 :
5596 1025 : streamer_write_hwi (ob, pii->param_index);
5597 1025 : pii->context.stream_out (ob);
5598 1025 : streamer_write_hwi (ob, pii->otr_token);
5599 1025 : stream_write_tree (ob, pii->otr_type, true);
5600 1025 : streamer_write_hwi (ob, pii->offset);
5601 : }
5602 1599 : else if (cgraph_simple_indirect_info *sii
5603 1599 : = dyn_cast <cgraph_simple_indirect_info *> (cs->indirect_info))
5604 : {
5605 1576 : bp = bitpack_create (ob->main_stream);
5606 1576 : bp_pack_value (&bp, sii->agg_contents, 1);
5607 1576 : bp_pack_value (&bp, sii->member_ptr, 1);
5608 1576 : bp_pack_value (&bp, sii->fnptr_loaded_from_record, 1);
5609 1576 : bp_pack_value (&bp, sii->by_ref, 1);
5610 1576 : bp_pack_value (&bp, sii->guaranteed_unmodified, 1);
5611 1576 : streamer_write_bitpack (&bp);
5612 :
5613 1576 : streamer_write_hwi (ob, sii->param_index);
5614 1576 : if (sii->agg_contents)
5615 56 : streamer_write_hwi (ob, sii->offset);
5616 : else
5617 1520 : gcc_assert (sii->offset == 0);
5618 1576 : if (sii->fnptr_loaded_from_record)
5619 : {
5620 132 : stream_write_tree (ob, sii->rec_type, true);
5621 132 : streamer_write_uhwi (ob, sii->fld_offset);
5622 : }
5623 : }
5624 : else
5625 23 : gcc_assert (cs->indirect_info->param_index == -1);
5626 2624 : }
5627 :
5628 : /* Read in parts of cgraph_indirect_call_info corresponding to CS that are
5629 : relevant to indirect inlining from IB. */
5630 :
5631 : static void
5632 1427 : ipa_read_indirect_edge_info (class lto_input_block *ib,
5633 : class data_in *data_in,
5634 : struct cgraph_edge *cs,
5635 : class ipa_node_params *info)
5636 : {
5637 1427 : struct bitpack_d bp;
5638 :
5639 1427 : bp = streamer_read_bitpack (ib);
5640 1427 : enum cgraph_indirect_info_kind ii_kind
5641 1427 : = bp_unpack_enum (&bp, cgraph_indirect_info_kind, CIIK_N_KINDS);
5642 1427 : gcc_assert (ii_kind == cs->indirect_info->kind);
5643 :
5644 1427 : if (cgraph_polymorphic_indirect_info *pii
5645 1427 : = dyn_cast <cgraph_polymorphic_indirect_info *> (cs->indirect_info))
5646 : {
5647 95 : bp = streamer_read_bitpack (ib);
5648 95 : pii->vptr_changed = bp_unpack_value (&bp, 1);
5649 :
5650 95 : pii->param_index = (int) streamer_read_hwi (ib);
5651 95 : pii->context.stream_in (ib, data_in);
5652 95 : pii->otr_token = (HOST_WIDE_INT) streamer_read_hwi (ib);
5653 95 : pii->otr_type = stream_read_tree (ib, data_in);
5654 95 : pii->offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
5655 :
5656 95 : if (info && pii->param_index >= 0)
5657 : {
5658 72 : ipa_set_param_used_by_polymorphic_call (info, pii->param_index, true);
5659 72 : ipa_set_param_used_by_indirect_call (info, pii->param_index, true);
5660 : }
5661 : }
5662 1332 : else if (cgraph_simple_indirect_info *sii
5663 1332 : = dyn_cast <cgraph_simple_indirect_info *> (cs->indirect_info))
5664 : {
5665 1323 : bp = streamer_read_bitpack (ib);
5666 1323 : sii->agg_contents = bp_unpack_value (&bp, 1);
5667 1323 : sii->member_ptr = bp_unpack_value (&bp, 1);
5668 1323 : sii->fnptr_loaded_from_record = bp_unpack_value (&bp, 1);
5669 1323 : sii->by_ref = bp_unpack_value (&bp, 1);
5670 1323 : sii->guaranteed_unmodified = bp_unpack_value (&bp, 1);
5671 :
5672 1323 : sii->param_index = (int) streamer_read_hwi (ib);
5673 1323 : if (sii->agg_contents)
5674 32 : sii->offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
5675 : else
5676 1291 : sii->offset = 0;
5677 1323 : if (sii->fnptr_loaded_from_record)
5678 : {
5679 70 : sii->rec_type = stream_read_tree (ib, data_in);
5680 70 : sii->fld_offset = (unsigned) streamer_read_uhwi (ib);
5681 : }
5682 1323 : if (info && sii->param_index >= 0)
5683 264 : ipa_set_param_used_by_indirect_call (info, sii->param_index, true);
5684 : }
5685 : else
5686 9 : cs->indirect_info->param_index = -1;
5687 1427 : }
5688 :
5689 : /* Stream out NODE info to OB. */
5690 :
5691 : static void
5692 93691 : ipa_write_node_info (struct output_block *ob, struct cgraph_node *node)
5693 : {
5694 93691 : int node_ref;
5695 93691 : lto_symtab_encoder_t encoder;
5696 93691 : ipa_node_params *info = ipa_node_params_sum->get (node);
5697 93691 : int j;
5698 93691 : struct cgraph_edge *e;
5699 93691 : struct bitpack_d bp;
5700 :
5701 93691 : encoder = ob->decl_state->symtab_node_encoder;
5702 93691 : node_ref = lto_symtab_encoder_encode (encoder, node);
5703 93691 : streamer_write_uhwi (ob, node_ref);
5704 :
5705 93691 : streamer_write_uhwi (ob, ipa_get_param_count (info));
5706 454219 : for (j = 0; j < ipa_get_param_count (info); j++)
5707 101883 : streamer_write_uhwi (ob, ipa_get_param_move_cost (info, j));
5708 93691 : bp = bitpack_create (ob->main_stream);
5709 93691 : gcc_assert (info->analysis_done
5710 : || ipa_get_param_count (info) == 0);
5711 93691 : gcc_assert (!info->node_enqueued);
5712 93691 : gcc_assert (!info->ipcp_orig_node);
5713 360528 : for (j = 0; j < ipa_get_param_count (info); j++)
5714 : {
5715 : /* TODO: We could just not stream the bit in the undescribed case. */
5716 101883 : bool d = (ipa_get_controlled_uses (info, j) != IPA_UNDESCRIBED_USE)
5717 101883 : ? ipa_get_param_load_dereferenced (info, j) : true;
5718 101883 : bp_pack_value (&bp, d, 1);
5719 101883 : bp_pack_value (&bp, ipa_is_param_used (info, j), 1);
5720 : }
5721 93691 : streamer_write_bitpack (&bp);
5722 454219 : for (j = 0; j < ipa_get_param_count (info); j++)
5723 : {
5724 101883 : streamer_write_hwi (ob, ipa_get_controlled_uses (info, j));
5725 101883 : stream_write_tree (ob, ipa_get_type (info, j), true);
5726 : }
5727 457489 : for (e = node->callees; e; e = e->next_callee)
5728 : {
5729 363798 : ipa_edge_args *args = ipa_edge_args_sum->get (e);
5730 :
5731 363798 : if (!args)
5732 : {
5733 806 : streamer_write_uhwi (ob, 0);
5734 806 : continue;
5735 : }
5736 :
5737 362992 : streamer_write_uhwi (ob,
5738 362992 : ipa_get_cs_argument_count (args) * 2
5739 362992 : + (args->polymorphic_call_contexts != NULL));
5740 2193120 : for (j = 0; j < ipa_get_cs_argument_count (args); j++)
5741 : {
5742 606692 : ipa_write_jump_function (ob, ipa_get_ith_jump_func (args, j));
5743 606692 : if (args->polymorphic_call_contexts != NULL)
5744 2456 : ipa_get_ith_polymorhic_call_context (args, j)->stream_out (ob);
5745 : }
5746 : }
5747 96315 : for (e = node->indirect_calls; e; e = e->next_callee)
5748 : {
5749 2624 : ipa_edge_args *args = ipa_edge_args_sum->get (e);
5750 2624 : if (!args)
5751 6 : streamer_write_uhwi (ob, 0);
5752 : else
5753 : {
5754 2618 : streamer_write_uhwi (ob,
5755 2618 : ipa_get_cs_argument_count (args) * 2
5756 2618 : + (args->polymorphic_call_contexts != NULL));
5757 14018 : for (j = 0; j < ipa_get_cs_argument_count (args); j++)
5758 : {
5759 3152 : ipa_write_jump_function (ob, ipa_get_ith_jump_func (args, j));
5760 3152 : if (args->polymorphic_call_contexts != NULL)
5761 1327 : ipa_get_ith_polymorhic_call_context (args, j)->stream_out (ob);
5762 : }
5763 : }
5764 2624 : ipa_write_indirect_edge_info (ob, e);
5765 : }
5766 93691 : }
5767 :
5768 : /* Stream in edge E from IB. */
5769 :
5770 : static void
5771 335418 : ipa_read_edge_info (class lto_input_block *ib,
5772 : class data_in *data_in,
5773 : struct cgraph_edge *e, bool prevails)
5774 : {
5775 335418 : int count = streamer_read_uhwi (ib);
5776 335418 : bool contexts_computed = count & 1;
5777 :
5778 335418 : count /= 2;
5779 335418 : if (!count)
5780 : return;
5781 234728 : if (prevails
5782 234728 : && (e->possibly_call_in_translation_unit_p ()
5783 : /* Also stream in jump functions to builtins in hope that they
5784 : will get fnspecs. */
5785 115939 : || fndecl_built_in_p (e->callee->decl, BUILT_IN_NORMAL)))
5786 : {
5787 223453 : ipa_edge_args *args = ipa_edge_args_sum->get_create (e);
5788 223453 : vec_safe_grow_cleared (args->jump_functions, count, true);
5789 223453 : if (contexts_computed)
5790 646 : vec_safe_grow_cleared (args->polymorphic_call_contexts, count, true);
5791 775720 : for (int k = 0; k < count; k++)
5792 : {
5793 552267 : ipa_read_jump_function (ib, ipa_get_ith_jump_func (args, k), e,
5794 : data_in, prevails);
5795 552267 : if (contexts_computed)
5796 1011 : ipa_get_ith_polymorhic_call_context (args, k)->stream_in
5797 1011 : (ib, data_in);
5798 : }
5799 : }
5800 : else
5801 : {
5802 29344 : for (int k = 0; k < count; k++)
5803 : {
5804 18069 : struct ipa_jump_func dummy;
5805 18069 : ipa_read_jump_function (ib, &dummy, e,
5806 : data_in, prevails);
5807 18069 : if (contexts_computed)
5808 : {
5809 452 : class ipa_polymorphic_call_context ctx;
5810 452 : ctx.stream_in (ib, data_in);
5811 : }
5812 : }
5813 : }
5814 : }
5815 :
5816 : /* Stream in NODE info from IB. */
5817 :
5818 : static void
5819 78132 : ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node,
5820 : class data_in *data_in)
5821 : {
5822 78132 : int k;
5823 78132 : struct cgraph_edge *e;
5824 78132 : struct bitpack_d bp;
5825 78132 : bool prevails = node->prevailing_p ();
5826 78132 : ipa_node_params *info
5827 78132 : = prevails ? ipa_node_params_sum->get_create (node) : NULL;
5828 :
5829 78132 : int param_count = streamer_read_uhwi (ib);
5830 78132 : if (prevails)
5831 : {
5832 78114 : ipa_alloc_node_params (node, param_count);
5833 235094 : for (k = 0; k < param_count; k++)
5834 78866 : (*info->descriptors)[k].move_cost = streamer_read_uhwi (ib);
5835 78114 : if (ipa_get_param_count (info) != 0)
5836 53462 : info->analysis_done = true;
5837 78114 : info->node_enqueued = false;
5838 : }
5839 : else
5840 27 : for (k = 0; k < param_count; k++)
5841 9 : streamer_read_uhwi (ib);
5842 :
5843 78132 : bp = streamer_read_bitpack (ib);
5844 157007 : for (k = 0; k < param_count; k++)
5845 : {
5846 78875 : bool load_dereferenced = bp_unpack_value (&bp, 1);
5847 78875 : bool used = bp_unpack_value (&bp, 1);
5848 :
5849 78875 : if (prevails)
5850 : {
5851 78866 : ipa_set_param_load_dereferenced (info, k, load_dereferenced);
5852 78866 : ipa_set_param_used (info, k, used);
5853 : }
5854 : }
5855 157007 : for (k = 0; k < param_count; k++)
5856 : {
5857 78875 : int nuses = streamer_read_hwi (ib);
5858 78875 : tree type = stream_read_tree (ib, data_in);
5859 :
5860 78875 : if (prevails)
5861 : {
5862 78866 : ipa_set_controlled_uses (info, k, nuses);
5863 78866 : (*info->descriptors)[k].decl_or_type = type;
5864 : }
5865 : }
5866 412123 : for (e = node->callees; e; e = e->next_callee)
5867 333991 : ipa_read_edge_info (ib, data_in, e, prevails);
5868 79559 : for (e = node->indirect_calls; e; e = e->next_callee)
5869 : {
5870 1427 : ipa_read_edge_info (ib, data_in, e, prevails);
5871 1427 : ipa_read_indirect_edge_info (ib, data_in, e, info);
5872 : }
5873 78132 : }
5874 :
5875 : /* Stream out ipa_return_summary. */
5876 : static void
5877 31694 : ipa_write_return_summaries (output_block *ob)
5878 : {
5879 31694 : if (!ipa_return_value_sum)
5880 : {
5881 14935 : streamer_write_uhwi (ob, 0);
5882 14935 : return;
5883 : }
5884 :
5885 16759 : lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
5886 16759 : unsigned int count = 0;
5887 442490 : for (int i = 0; i < lto_symtab_encoder_size (encoder); i++)
5888 : {
5889 204486 : toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i);
5890 408972 : cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode);
5891 168367 : ipa_return_value_summary *v;
5892 :
5893 168367 : if (cnode && cnode->definition && !cnode->alias
5894 123833 : && (v = ipa_return_value_sum->get (cnode))
5895 25493 : && v->vr)
5896 25493 : count++;
5897 : }
5898 16759 : streamer_write_uhwi (ob, count);
5899 :
5900 459249 : for (int i = 0; i < lto_symtab_encoder_size (encoder); i++)
5901 : {
5902 204486 : toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i);
5903 408972 : cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode);
5904 168367 : ipa_return_value_summary *v;
5905 :
5906 168367 : if (cnode && cnode->definition && !cnode->alias
5907 123833 : && (v = ipa_return_value_sum->get (cnode))
5908 25493 : && v->vr)
5909 : {
5910 25493 : streamer_write_uhwi
5911 25493 : (ob,
5912 25493 : lto_symtab_encoder_encode (encoder, cnode));
5913 25493 : v->vr->streamer_write (ob);
5914 : }
5915 : }
5916 : }
5917 :
5918 : /* Write jump functions for nodes in SET. */
5919 :
5920 : void
5921 23420 : ipa_prop_write_jump_functions (void)
5922 : {
5923 23420 : struct output_block *ob;
5924 23420 : unsigned int count = 0;
5925 23420 : lto_symtab_encoder_iterator lsei;
5926 23420 : lto_symtab_encoder_t encoder;
5927 :
5928 23420 : if (!ipa_node_params_sum || !ipa_edge_args_sum)
5929 0 : return;
5930 :
5931 23420 : ob = create_output_block (LTO_section_jump_functions);
5932 23420 : encoder = ob->decl_state->symtab_node_encoder;
5933 23420 : ob->symbol = NULL;
5934 129081 : for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
5935 105661 : lsei_next_function_in_partition (&lsei))
5936 : {
5937 105661 : cgraph_node *node = lsei_cgraph_node (lsei);
5938 105661 : if (node->has_gimple_body_p ()
5939 105661 : && ipa_node_params_sum->get (node) != NULL)
5940 93691 : count++;
5941 : }
5942 :
5943 23420 : streamer_write_uhwi (ob, count);
5944 :
5945 : /* Process all of the functions. */
5946 129081 : for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
5947 105661 : lsei_next_function_in_partition (&lsei))
5948 : {
5949 105661 : cgraph_node *node = lsei_cgraph_node (lsei);
5950 105661 : if (node->has_gimple_body_p ()
5951 105661 : && ipa_node_params_sum->get (node) != NULL)
5952 93691 : ipa_write_node_info (ob, node);
5953 : }
5954 23420 : ipa_write_return_summaries (ob);
5955 :
5956 23420 : if (noted_fnptrs_in_records)
5957 : {
5958 350 : count = 0;
5959 1081 : for (auto iter = noted_fnptrs_in_records->begin ();
5960 1081 : iter != noted_fnptrs_in_records->end();
5961 731 : ++iter)
5962 731 : if ((*iter)->fn)
5963 723 : count++;
5964 350 : streamer_write_uhwi (ob, count);
5965 :
5966 1081 : for (auto iter = noted_fnptrs_in_records->begin ();
5967 1431 : iter != noted_fnptrs_in_records->end();
5968 731 : ++iter)
5969 731 : if ((*iter)->fn)
5970 : {
5971 723 : stream_write_tree (ob, (*iter)->rec_type, true);
5972 723 : stream_write_tree (ob, (*iter)->fn, true);
5973 723 : streamer_write_uhwi (ob, (*iter)->fld_offset);
5974 : }
5975 : }
5976 : else
5977 23070 : streamer_write_uhwi (ob, 0);
5978 :
5979 23420 : produce_asm (ob);
5980 23420 : destroy_output_block (ob);
5981 : }
5982 :
5983 : /* Record that return value range of N is VAL. */
5984 :
5985 : static void
5986 773064 : ipa_record_return_value_range_1 (cgraph_node *n, value_range val)
5987 : {
5988 : // Remove local invariant from return values.
5989 773064 : if (is_a<prange> (val))
5990 : {
5991 269146 : const prange &pr = as_a <prange> (val);
5992 269146 : tree t = pr.pt_invariant ();
5993 7099 : if (t && !is_gimple_ip_invariant (t))
5994 : {
5995 358 : if (dump_file && (dump_flags & TDF_DETAILS))
5996 : {
5997 0 : fprintf (dump_file, "Could not record return range of %s:", n->dump_name ());
5998 0 : val.dump (dump_file);
5999 0 : fprintf (dump_file, "\n");
6000 0 : fprintf (dump_file, "Because uses non ipa invariant\n");
6001 : }
6002 : return;
6003 : }
6004 : }
6005 772706 : if (!ipa_return_value_sum)
6006 : {
6007 88399 : if (!ipa_vr_hash_table)
6008 77477 : ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
6009 88399 : ipa_return_value_sum = new (ggc_alloc_no_dtor <ipa_return_value_sum_t> ())
6010 88399 : ipa_return_value_sum_t (symtab, true);
6011 88399 : ipa_return_value_sum->disable_insertion_hook ();
6012 : }
6013 772706 : ipa_return_value_sum->get_create (n)->vr = ipa_get_value_range (val);
6014 772706 : if (dump_file && (dump_flags & TDF_DETAILS))
6015 : {
6016 24 : fprintf (dump_file, "Recording return range of %s:", n->dump_name ());
6017 24 : val.dump (dump_file);
6018 24 : fprintf (dump_file, "\n");
6019 : }
6020 : }
6021 :
6022 : /* Stream out ipa_return_summary. */
6023 : static void
6024 21740 : ipa_read_return_summaries (lto_input_block *ib,
6025 : struct lto_file_decl_data *file_data,
6026 : class data_in *data_in)
6027 : {
6028 21740 : unsigned int f_count = streamer_read_uhwi (ib);
6029 43672 : for (unsigned int i = 0; i < f_count; i++)
6030 : {
6031 21932 : unsigned int index = streamer_read_uhwi (ib);
6032 21932 : lto_symtab_encoder_t encoder = file_data->symtab_node_encoder;
6033 21932 : struct cgraph_node *node
6034 : = dyn_cast <cgraph_node *>
6035 21932 : (lto_symtab_encoder_deref (encoder, index));
6036 21932 : ipa_vr rvr;
6037 21932 : rvr.streamer_read (ib, data_in);
6038 21932 : if (node->prevailing_p ())
6039 : {
6040 21930 : value_range tmp;
6041 21930 : rvr.get_vrange (tmp);
6042 21930 : ipa_record_return_value_range_1 (node, tmp);
6043 21930 : }
6044 : }
6045 21740 : }
6046 :
6047 : /* Read section in file FILE_DATA of length LEN with data DATA. */
6048 :
6049 : static void
6050 13466 : ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data,
6051 : size_t len)
6052 : {
6053 13466 : const struct lto_function_header *header =
6054 : (const struct lto_function_header *) data;
6055 13466 : const int cfg_offset = sizeof (struct lto_function_header);
6056 13466 : const int main_offset = cfg_offset + header->cfg_size;
6057 13466 : const int string_offset = main_offset + header->main_size;
6058 13466 : class data_in *data_in;
6059 13466 : unsigned int i;
6060 13466 : unsigned int count;
6061 :
6062 13466 : lto_input_block ib_main ((const char *) data + main_offset,
6063 13466 : header->main_size, file_data);
6064 :
6065 13466 : data_in =
6066 26932 : lto_data_in_create (file_data, (const char *) data + string_offset,
6067 13466 : header->string_size, vNULL);
6068 13466 : count = streamer_read_uhwi (&ib_main);
6069 :
6070 91598 : for (i = 0; i < count; i++)
6071 : {
6072 78132 : unsigned int index;
6073 78132 : struct cgraph_node *node;
6074 78132 : lto_symtab_encoder_t encoder;
6075 :
6076 78132 : index = streamer_read_uhwi (&ib_main);
6077 78132 : encoder = file_data->symtab_node_encoder;
6078 78132 : node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
6079 : index));
6080 78132 : gcc_assert (node->definition);
6081 78132 : ipa_read_node_info (&ib_main, node, data_in);
6082 : }
6083 13466 : ipa_read_return_summaries (&ib_main, file_data, data_in);
6084 :
6085 13466 : count = streamer_read_uhwi (&ib_main);
6086 14132 : for (i = 0; i < count; i++)
6087 : {
6088 666 : tree rec_type = stream_read_tree (&ib_main, data_in);
6089 666 : tree fn = stream_read_tree (&ib_main, data_in);
6090 666 : unsigned fld_offset = (unsigned) streamer_read_uhwi (&ib_main);
6091 666 : note_fnptr_in_record (rec_type, fld_offset, fn);
6092 : }
6093 :
6094 13466 : lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
6095 : len);
6096 13466 : lto_data_in_delete (data_in);
6097 13466 : }
6098 :
6099 : /* Read ipcp jump functions. */
6100 :
6101 : void
6102 12380 : ipa_prop_read_jump_functions (void)
6103 : {
6104 12380 : struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
6105 12380 : struct lto_file_decl_data *file_data;
6106 12380 : unsigned int j = 0;
6107 :
6108 12380 : ipa_check_create_node_params ();
6109 12380 : ipa_check_create_edge_args ();
6110 12380 : ipa_register_cgraph_hooks ();
6111 :
6112 38226 : while ((file_data = file_data_vec[j++]))
6113 : {
6114 13466 : size_t len;
6115 13466 : const char *data
6116 13466 : = lto_get_summary_section_data (file_data, LTO_section_jump_functions,
6117 : &len);
6118 13466 : if (data)
6119 13466 : ipa_prop_read_section (file_data, data, len);
6120 : }
6121 12380 : }
6122 :
6123 : /* Return true if the IPA-CP transformation summary TS is non-NULL and contains
6124 : useful info. */
6125 : static bool
6126 167090 : useful_ipcp_transformation_info_p (ipcp_transformation *ts)
6127 : {
6128 167090 : if (!ts)
6129 : return false;
6130 24340 : if (!vec_safe_is_empty (ts->m_agg_values)
6131 23930 : || !vec_safe_is_empty (ts->m_vr))
6132 24056 : return true;
6133 : return false;
6134 : }
6135 :
6136 : /* Write into OB IPA-CP transformation summary TS describing NODE. */
6137 :
6138 : void
6139 12010 : write_ipcp_transformation_info (output_block *ob, cgraph_node *node,
6140 : ipcp_transformation *ts)
6141 : {
6142 12010 : lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
6143 12010 : int node_ref = lto_symtab_encoder_encode (encoder, node);
6144 12010 : streamer_write_uhwi (ob, node_ref);
6145 :
6146 12212 : streamer_write_uhwi (ob, vec_safe_length (ts->m_agg_values));
6147 13642 : for (const ipa_argagg_value &av : ts->m_agg_values)
6148 : {
6149 1228 : struct bitpack_d bp;
6150 :
6151 1228 : stream_write_tree (ob, av.value, true);
6152 1228 : streamer_write_uhwi (ob, av.unit_offset);
6153 1228 : streamer_write_uhwi (ob, av.index);
6154 :
6155 1228 : bp = bitpack_create (ob->main_stream);
6156 1228 : bp_pack_value (&bp, av.by_ref, 1);
6157 1228 : bp_pack_value (&bp, av.killed, 1);
6158 1228 : streamer_write_bitpack (&bp);
6159 : }
6160 :
6161 : /* If all instances of this node are inlined, ipcp info is not useful. */
6162 12010 : if (!lto_symtab_encoder_only_for_inlining_p (encoder, node))
6163 : {
6164 21756 : streamer_write_uhwi (ob, vec_safe_length (ts->m_vr));
6165 53097 : for (const ipa_vr &parm_vr : ts->m_vr)
6166 20466 : parm_vr.streamer_write (ob);
6167 : }
6168 : else
6169 1129 : streamer_write_uhwi (ob, 0);
6170 12010 : }
6171 :
6172 : /* Stream in the aggregate value replacement chain for NODE from IB. */
6173 :
6174 : static void
6175 12010 : read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node,
6176 : data_in *data_in)
6177 : {
6178 12010 : unsigned int count, i;
6179 12010 : ipcp_transformation_initialize ();
6180 12010 : ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
6181 :
6182 12010 : count = streamer_read_uhwi (ib);
6183 12010 : if (count > 0)
6184 : {
6185 202 : vec_safe_grow_cleared (ts->m_agg_values, count, true);
6186 1632 : for (i = 0; i <count; i++)
6187 : {
6188 1228 : ipa_argagg_value *av = &(*ts->m_agg_values)[i];;
6189 :
6190 1228 : av->value = stream_read_tree (ib, data_in);
6191 1228 : av->unit_offset = streamer_read_uhwi (ib);
6192 1228 : av->index = streamer_read_uhwi (ib);
6193 :
6194 1228 : bitpack_d bp = streamer_read_bitpack (ib);
6195 1228 : av->by_ref = bp_unpack_value (&bp, 1);
6196 1228 : av->killed = bp_unpack_value (&bp, 1);
6197 : }
6198 : }
6199 :
6200 12010 : count = streamer_read_uhwi (ib);
6201 12010 : if (count > 0)
6202 : {
6203 10875 : vec_safe_grow_cleared (ts->m_vr, count, true);
6204 42216 : for (i = 0; i < count; i++)
6205 : {
6206 20466 : ipa_vr *parm_vr;
6207 20466 : parm_vr = &(*ts->m_vr)[i];
6208 20466 : parm_vr->streamer_read (ib, data_in);
6209 : }
6210 : }
6211 12010 : }
6212 :
6213 :
6214 : /* Write all aggregate replacement for nodes in set. */
6215 :
6216 : void
6217 8274 : ipcp_write_transformation_summaries (void)
6218 : {
6219 8274 : struct output_block *ob;
6220 8274 : unsigned int count = 0;
6221 8274 : lto_symtab_encoder_t encoder;
6222 :
6223 8274 : ob = create_output_block (LTO_section_ipcp_transform);
6224 8274 : encoder = ob->decl_state->symtab_node_encoder;
6225 8274 : ob->symbol = NULL;
6226 :
6227 233704 : for (int i = 0; i < lto_symtab_encoder_size (encoder); i++)
6228 : {
6229 108582 : toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i);
6230 108582 : cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode);
6231 108582 : if (!cnode)
6232 25037 : continue;
6233 83545 : ipcp_transformation *ts = ipcp_get_transformation_summary (cnode);
6234 83545 : if (useful_ipcp_transformation_info_p (ts)
6235 83545 : && lto_symtab_encoder_encode_body_p (encoder, cnode))
6236 12010 : count++;
6237 : }
6238 :
6239 8274 : streamer_write_uhwi (ob, count);
6240 :
6241 241978 : for (int i = 0; i < lto_symtab_encoder_size (encoder); i++)
6242 : {
6243 108582 : toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i);
6244 108582 : cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode);
6245 108582 : if (!cnode)
6246 25037 : continue;
6247 83545 : ipcp_transformation *ts = ipcp_get_transformation_summary (cnode);
6248 83545 : if (useful_ipcp_transformation_info_p (ts)
6249 83545 : && lto_symtab_encoder_encode_body_p (encoder, cnode))
6250 12010 : write_ipcp_transformation_info (ob, cnode, ts);
6251 : }
6252 8274 : ipa_write_return_summaries (ob);
6253 8274 : produce_asm (ob);
6254 8274 : destroy_output_block (ob);
6255 8274 : }
6256 :
6257 : /* Read replacements section in file FILE_DATA of length LEN with data
6258 : DATA. */
6259 :
6260 : static void
6261 8274 : read_replacements_section (struct lto_file_decl_data *file_data,
6262 : const char *data,
6263 : size_t len)
6264 : {
6265 8274 : const struct lto_function_header *header =
6266 : (const struct lto_function_header *) data;
6267 8274 : const int cfg_offset = sizeof (struct lto_function_header);
6268 8274 : const int main_offset = cfg_offset + header->cfg_size;
6269 8274 : const int string_offset = main_offset + header->main_size;
6270 8274 : class data_in *data_in;
6271 8274 : unsigned int i;
6272 8274 : unsigned int count;
6273 :
6274 8274 : lto_input_block ib_main ((const char *) data + main_offset,
6275 8274 : header->main_size, file_data);
6276 :
6277 8274 : data_in = lto_data_in_create (file_data, (const char *) data + string_offset,
6278 8274 : header->string_size, vNULL);
6279 8274 : count = streamer_read_uhwi (&ib_main);
6280 :
6281 20284 : for (i = 0; i < count; i++)
6282 : {
6283 12010 : unsigned int index;
6284 12010 : struct cgraph_node *node;
6285 12010 : lto_symtab_encoder_t encoder;
6286 :
6287 12010 : index = streamer_read_uhwi (&ib_main);
6288 12010 : encoder = file_data->symtab_node_encoder;
6289 12010 : node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
6290 : index));
6291 12010 : read_ipcp_transformation_info (&ib_main, node, data_in);
6292 : }
6293 8274 : ipa_read_return_summaries (&ib_main, file_data, data_in);
6294 8274 : lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
6295 : len);
6296 8274 : lto_data_in_delete (data_in);
6297 8274 : }
6298 :
6299 : /* Read IPA-CP aggregate replacements. */
6300 :
6301 : void
6302 8274 : ipcp_read_transformation_summaries (void)
6303 : {
6304 8274 : struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
6305 8274 : struct lto_file_decl_data *file_data;
6306 8274 : unsigned int j = 0;
6307 :
6308 24822 : while ((file_data = file_data_vec[j++]))
6309 : {
6310 8274 : size_t len;
6311 8274 : const char *data
6312 8274 : = lto_get_summary_section_data (file_data, LTO_section_ipcp_transform,
6313 : &len);
6314 8274 : if (data)
6315 8274 : read_replacements_section (file_data, data, len);
6316 : }
6317 8274 : }
6318 :
6319 : /* Adjust the aggregate replacements in TS to reflect any parameter removals
6320 : which might have already taken place. If after adjustments there are no
6321 : aggregate replacements left, the m_agg_values will be set to NULL. In other
6322 : cases, it may be shrunk. */
6323 :
6324 : static void
6325 1833 : adjust_agg_replacement_values (cgraph_node *node, ipcp_transformation *ts)
6326 : {
6327 1833 : clone_info *cinfo = clone_info::get (node);
6328 1833 : if (!cinfo || !cinfo->param_adjustments)
6329 : return;
6330 :
6331 884 : auto_vec<int, 16> new_indices;
6332 884 : cinfo->param_adjustments->get_updated_indices (&new_indices);
6333 884 : bool removed_item = false;
6334 884 : unsigned dst_index = 0;
6335 884 : unsigned count = ts->m_agg_values->length ();
6336 4969 : for (unsigned i = 0; i < count; i++)
6337 : {
6338 4085 : ipa_argagg_value *v = &(*ts->m_agg_values)[i];
6339 4085 : gcc_checking_assert (v->index >= 0);
6340 :
6341 4085 : int new_idx = -1;
6342 4085 : if ((unsigned) v->index < new_indices.length ())
6343 2494 : new_idx = new_indices[v->index];
6344 :
6345 2494 : if (new_idx >= 0)
6346 : {
6347 1690 : v->index = new_idx;
6348 1690 : if (removed_item)
6349 11 : (*ts->m_agg_values)[dst_index] = *v;
6350 1690 : dst_index++;
6351 : }
6352 : else
6353 : removed_item = true;
6354 : }
6355 :
6356 884 : if (dst_index == 0)
6357 : {
6358 508 : ggc_free (ts->m_agg_values);
6359 508 : ts->m_agg_values = NULL;
6360 : }
6361 376 : else if (removed_item)
6362 39 : ts->m_agg_values->truncate (dst_index);
6363 :
6364 884 : return;
6365 884 : }
6366 :
6367 : /* Dominator walker driving the ipcp modification phase. */
6368 :
6369 : class ipcp_modif_dom_walker : public dom_walker
6370 : {
6371 : public:
6372 1325 : ipcp_modif_dom_walker (struct ipa_func_body_info *fbi,
6373 : vec<ipa_param_descriptor, va_gc> *descs,
6374 : ipcp_transformation *ts, bool *sc)
6375 1325 : : dom_walker (CDI_DOMINATORS), m_fbi (fbi), m_descriptors (descs),
6376 1325 : m_ts (ts), m_something_changed (sc) {}
6377 :
6378 : edge before_dom_children (basic_block) final override;
6379 1325 : bool cleanup_eh ()
6380 1325 : { return gimple_purge_all_dead_eh_edges (m_need_eh_cleanup); }
6381 :
6382 : private:
6383 : struct ipa_func_body_info *m_fbi;
6384 : vec<ipa_param_descriptor, va_gc> *m_descriptors;
6385 : ipcp_transformation *m_ts;
6386 : bool *m_something_changed;
6387 : auto_bitmap m_need_eh_cleanup;
6388 : };
6389 :
6390 : edge
6391 22860 : ipcp_modif_dom_walker::before_dom_children (basic_block bb)
6392 : {
6393 22860 : gimple_stmt_iterator gsi;
6394 126609 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6395 : {
6396 80889 : gimple *stmt = gsi_stmt (gsi);
6397 80889 : tree rhs, val, t;
6398 80889 : HOST_WIDE_INT bit_offset;
6399 80889 : poly_int64 size;
6400 80889 : int index;
6401 80889 : bool by_ref, vce;
6402 :
6403 80889 : if (!gimple_assign_load_p (stmt))
6404 79329 : continue;
6405 12238 : rhs = gimple_assign_rhs1 (stmt);
6406 12238 : if (!is_gimple_reg_type (TREE_TYPE (rhs)))
6407 629 : continue;
6408 :
6409 27572 : vce = false;
6410 : t = rhs;
6411 27572 : while (handled_component_p (t))
6412 : {
6413 : /* V_C_E can do things like convert an array of integers to one
6414 : bigger integer and similar things we do not handle below. */
6415 15963 : if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
6416 : {
6417 : vce = true;
6418 : break;
6419 : }
6420 15963 : t = TREE_OPERAND (t, 0);
6421 : }
6422 11609 : if (vce)
6423 0 : continue;
6424 :
6425 11609 : if (!ipa_load_from_parm_agg (m_fbi, m_descriptors, stmt, rhs, &index,
6426 : &bit_offset, &size, &by_ref))
6427 8600 : continue;
6428 3009 : unsigned unit_offset = bit_offset / BITS_PER_UNIT;
6429 3009 : ipa_argagg_value_list avl (m_ts);
6430 3009 : tree v = avl.get_value (index, unit_offset, by_ref);
6431 :
6432 4458 : if (!v
6433 3009 : || maybe_ne (tree_to_poly_int64 (TYPE_SIZE (TREE_TYPE (v))), size))
6434 1449 : continue;
6435 :
6436 1560 : gcc_checking_assert (is_gimple_ip_invariant (v));
6437 1560 : if (!useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (v)))
6438 : {
6439 0 : if (fold_convertible_p (TREE_TYPE (rhs), v))
6440 0 : val = fold_build1 (NOP_EXPR, TREE_TYPE (rhs), v);
6441 0 : else if (TYPE_SIZE (TREE_TYPE (rhs))
6442 0 : == TYPE_SIZE (TREE_TYPE (v)))
6443 0 : val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), v);
6444 : else
6445 : {
6446 0 : if (dump_file)
6447 : {
6448 0 : fprintf (dump_file, " const ");
6449 0 : print_generic_expr (dump_file, v);
6450 0 : fprintf (dump_file, " can't be converted to type of ");
6451 0 : print_generic_expr (dump_file, rhs);
6452 0 : fprintf (dump_file, "\n");
6453 : }
6454 0 : continue;
6455 : }
6456 : }
6457 : else
6458 : val = v;
6459 :
6460 1560 : if (dump_file && (dump_flags & TDF_DETAILS))
6461 : {
6462 41 : fprintf (dump_file, "Modifying stmt:\n ");
6463 41 : print_gimple_stmt (dump_file, stmt, 0);
6464 : }
6465 1560 : gimple_assign_set_rhs_from_tree (&gsi, val);
6466 1560 : update_stmt (stmt);
6467 :
6468 1560 : if (dump_file && (dump_flags & TDF_DETAILS))
6469 : {
6470 41 : fprintf (dump_file, "into:\n ");
6471 41 : print_gimple_stmt (dump_file, stmt, 0);
6472 41 : fprintf (dump_file, "\n");
6473 : }
6474 :
6475 1560 : *m_something_changed = true;
6476 1560 : if (maybe_clean_eh_stmt (stmt))
6477 9 : bitmap_set_bit (m_need_eh_cleanup, bb->index);
6478 : }
6479 22860 : return NULL;
6480 : }
6481 :
6482 : /* If IPA-CP discovered a constant in parameter PARM at OFFSET of a given SIZE
6483 : - whether passed by reference or not is given by BY_REF - return that
6484 : constant. Otherwise return NULL_TREE. The is supposed to be used only
6485 : after clone materialization and transformation is done (because it asserts
6486 : that killed constants have been pruned). */
6487 :
6488 : tree
6489 4422516 : ipcp_get_aggregate_const (struct function *func, tree parm, bool by_ref,
6490 : HOST_WIDE_INT bit_offset, HOST_WIDE_INT bit_size)
6491 : {
6492 4422516 : cgraph_node *node = cgraph_node::get (func->decl);
6493 4422516 : ipcp_transformation *ts = ipcp_get_transformation_summary (node);
6494 :
6495 4422516 : if (!ts || !ts->m_agg_values)
6496 : return NULL_TREE;
6497 :
6498 9788 : int index = ts->get_param_index (func->decl, parm);
6499 9788 : if (index < 0)
6500 : return NULL_TREE;
6501 :
6502 9735 : ipa_argagg_value_list avl (ts);
6503 9735 : unsigned unit_offset = bit_offset / BITS_PER_UNIT;
6504 9735 : const ipa_argagg_value *av = avl.get_elt (index, unit_offset);
6505 9735 : if (!av || av->by_ref != by_ref)
6506 : return NULL_TREE;
6507 1864 : gcc_assert (!av->killed);
6508 1864 : tree v = av->value;
6509 1864 : if (!v
6510 1864 : || maybe_ne (tree_to_poly_int64 (TYPE_SIZE (TREE_TYPE (v))), bit_size))
6511 : return NULL_TREE;
6512 :
6513 : return v;
6514 : }
6515 :
6516 : /* Return true if we have recorded VALUE and MASK about PARM.
6517 : Set VALUE and MASk accordingly. */
6518 :
6519 : bool
6520 7833873 : ipcp_get_parm_bits (tree parm, tree *value, widest_int *mask)
6521 : {
6522 7833873 : cgraph_node *cnode = cgraph_node::get (current_function_decl);
6523 7833873 : ipcp_transformation *ts = ipcp_get_transformation_summary (cnode);
6524 7833873 : if (!ts
6525 120196 : || vec_safe_length (ts->m_vr) == 0
6526 7951681 : || !ipa_vr_supported_type_p (TREE_TYPE (parm)))
6527 : return false;
6528 :
6529 115529 : int i = ts->get_param_index (current_function_decl, parm);
6530 115529 : if (i < 0)
6531 : return false;
6532 114098 : clone_info *cinfo = clone_info::get (cnode);
6533 114098 : if (cinfo && cinfo->param_adjustments)
6534 : {
6535 33690 : i = cinfo->param_adjustments->get_original_index (i);
6536 33690 : if (i < 0)
6537 : return false;
6538 : }
6539 :
6540 105071 : vec<ipa_vr, va_gc> &vr = *ts->m_vr;
6541 105071 : if (!vr[i].known_p ())
6542 : return false;
6543 83446 : value_range tmp;
6544 83446 : vr[i].get_vrange (tmp);
6545 83446 : if (tmp.undefined_p () || tmp.varying_p ())
6546 : return false;
6547 83446 : irange_bitmask bm;
6548 83446 : bm = tmp.get_bitmask ();
6549 83446 : *mask = widest_int::from (bm.mask (), TYPE_SIGN (TREE_TYPE (parm)));
6550 83446 : *value = wide_int_to_tree (TREE_TYPE (parm), bm.value ());
6551 83446 : return true;
6552 83446 : }
6553 :
6554 : /* Update value range of formal parameters of NODE as described in TS. */
6555 :
6556 : static void
6557 22900 : ipcp_update_vr (struct cgraph_node *node, ipcp_transformation *ts)
6558 : {
6559 22900 : if (vec_safe_is_empty (ts->m_vr))
6560 489 : return;
6561 22411 : const vec<ipa_vr, va_gc> &vr = *ts->m_vr;
6562 22411 : unsigned count = vr.length ();
6563 22411 : if (!count)
6564 : return;
6565 :
6566 22411 : auto_vec<int, 16> new_indices;
6567 22411 : bool need_remapping = false;
6568 22411 : clone_info *cinfo = clone_info::get (node);
6569 22411 : if (cinfo && cinfo->param_adjustments)
6570 : {
6571 7793 : cinfo->param_adjustments->get_updated_indices (&new_indices);
6572 7793 : need_remapping = true;
6573 : }
6574 22411 : auto_vec <tree, 16> parm_decls;
6575 22411 : push_function_arg_decls (&parm_decls, node->decl);
6576 :
6577 100869 : for (unsigned i = 0; i < count; ++i)
6578 : {
6579 56047 : tree parm;
6580 56047 : int remapped_idx;
6581 56047 : if (need_remapping)
6582 : {
6583 23265 : if (i >= new_indices.length ())
6584 11306 : continue;
6585 11959 : remapped_idx = new_indices[i];
6586 11959 : if (remapped_idx < 0)
6587 2476 : continue;
6588 : }
6589 : else
6590 32782 : remapped_idx = i;
6591 :
6592 42265 : parm = parm_decls[remapped_idx];
6593 :
6594 42265 : gcc_checking_assert (parm);
6595 42265 : tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl), parm);
6596 :
6597 42265 : if (!ddef || !is_gimple_reg (parm))
6598 6260 : continue;
6599 :
6600 36005 : if (vr[i].known_p ())
6601 : {
6602 27822 : value_range tmp;
6603 27822 : vr[i].get_vrange (tmp);
6604 :
6605 27822 : if (!tmp.undefined_p () && !tmp.varying_p ())
6606 : {
6607 27822 : if (dump_file)
6608 : {
6609 112 : fprintf (dump_file, "Setting value range of param %u "
6610 : "(now %i) ", i, remapped_idx);
6611 112 : tmp.dump (dump_file);
6612 112 : fprintf (dump_file, "]\n");
6613 : }
6614 27822 : set_range_info (ddef, tmp);
6615 :
6616 42909 : if (POINTER_TYPE_P (TREE_TYPE (parm))
6617 30973 : && opt_for_fn (node->decl, flag_ipa_bit_cp))
6618 : {
6619 15885 : irange_bitmask bm = tmp.get_bitmask ();
6620 15885 : unsigned tem = bm.mask ().to_uhwi ();
6621 15885 : unsigned HOST_WIDE_INT bitpos = bm.value ().to_uhwi ();
6622 15885 : unsigned align = tem & -tem;
6623 15885 : unsigned misalign = bitpos & (align - 1);
6624 :
6625 15885 : if (align > 1)
6626 : {
6627 13216 : if (dump_file)
6628 : {
6629 85 : fprintf (dump_file,
6630 : "Adjusting mask for param %u to ", i);
6631 85 : print_hex (bm.mask (), dump_file);
6632 85 : fprintf (dump_file, "\n");
6633 : }
6634 :
6635 13216 : if (dump_file)
6636 85 : fprintf (dump_file,
6637 : "Adjusting align: %u, misalign: %u\n",
6638 : align, misalign);
6639 :
6640 13216 : unsigned old_align, old_misalign;
6641 13216 : struct ptr_info_def *pi = get_ptr_info (ddef);
6642 13216 : bool old_known = get_ptr_info_alignment (pi, &old_align,
6643 : &old_misalign);
6644 :
6645 13216 : if (old_known && old_align > align)
6646 : {
6647 0 : if (dump_file)
6648 : {
6649 0 : fprintf (dump_file,
6650 : "But alignment was already %u.\n",
6651 : old_align);
6652 0 : if ((old_misalign & (align - 1)) != misalign)
6653 0 : fprintf (dump_file,
6654 : "old_misalign (%u) and misalign "
6655 : "(%u) mismatch\n",
6656 : old_misalign, misalign);
6657 : }
6658 0 : continue;
6659 : }
6660 :
6661 13216 : if (dump_file
6662 85 : && old_known
6663 0 : && ((misalign & (old_align - 1)) != old_misalign))
6664 0 : fprintf (dump_file,
6665 : "old_misalign (%u) and misalign (%u) "
6666 : "mismatch\n",
6667 : old_misalign, misalign);
6668 :
6669 13216 : set_ptr_info_alignment (pi, align, misalign);
6670 : }
6671 15885 : }
6672 11937 : else if (dump_file && INTEGRAL_TYPE_P (TREE_TYPE (parm)))
6673 : {
6674 23 : irange &r = as_a<irange> (tmp);
6675 23 : irange_bitmask bm = r.get_bitmask ();
6676 23 : unsigned prec = TYPE_PRECISION (TREE_TYPE (parm));
6677 23 : if (wi::ne_p (bm.mask (), wi::shwi (-1, prec)))
6678 : {
6679 16 : fprintf (dump_file,
6680 : "Adjusting mask for param %u to ", i);
6681 16 : print_hex (bm.mask (), dump_file);
6682 16 : fprintf (dump_file, "\n");
6683 : }
6684 23 : }
6685 : }
6686 27822 : }
6687 : }
6688 22411 : }
6689 :
6690 : /* IPCP transformation phase doing propagation of aggregate values. */
6691 :
6692 : unsigned int
6693 984236 : ipcp_transform_function (struct cgraph_node *node)
6694 : {
6695 984236 : struct ipa_func_body_info fbi;
6696 984236 : int param_count;
6697 :
6698 984236 : gcc_checking_assert (cfun);
6699 984236 : gcc_checking_assert (current_function_decl);
6700 :
6701 984236 : if (dump_file)
6702 690 : fprintf (dump_file, "Modification phase of node %s\n",
6703 : node->dump_name ());
6704 :
6705 984236 : ipcp_transformation *ts = ipcp_get_transformation_summary (node);
6706 984236 : if (!ts
6707 984236 : || (vec_safe_is_empty (ts->m_agg_values)
6708 21497 : && vec_safe_is_empty (ts->m_vr)))
6709 : return 0;
6710 :
6711 22900 : ts->maybe_create_parm_idx_map (cfun->decl);
6712 22900 : ipcp_update_vr (node, ts);
6713 22900 : if (vec_safe_is_empty (ts->m_agg_values))
6714 : return 0;
6715 2081 : param_count = count_formal_params (node->decl);
6716 2081 : if (param_count == 0)
6717 : return 0;
6718 :
6719 1833 : adjust_agg_replacement_values (node, ts);
6720 1833 : if (vec_safe_is_empty (ts->m_agg_values))
6721 : {
6722 508 : if (dump_file)
6723 4 : fprintf (dump_file, " All affected aggregate parameters were either "
6724 : "removed or converted into scalars, phase done.\n");
6725 : return 0;
6726 : }
6727 1325 : if (dump_file)
6728 : {
6729 51 : fprintf (dump_file, " Aggregate replacements:");
6730 51 : ipa_argagg_value_list avs (ts);
6731 51 : avs.dump (dump_file);
6732 : }
6733 :
6734 1325 : fbi.node = node;
6735 1325 : fbi.info = NULL;
6736 1325 : fbi.bb_infos = vNULL;
6737 1325 : fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun), true);
6738 1325 : fbi.param_count = param_count;
6739 1325 : fbi.aa_walk_budget = opt_for_fn (node->decl, param_ipa_max_aa_steps);
6740 :
6741 1325 : vec<ipa_param_descriptor, va_gc> *descriptors = NULL;
6742 1325 : vec_safe_grow_cleared (descriptors, param_count, true);
6743 1325 : ipa_populate_param_decls (node, *descriptors);
6744 1325 : bool modified_mem_access = false;
6745 1325 : calculate_dominance_info (CDI_DOMINATORS);
6746 1325 : ipcp_modif_dom_walker walker (&fbi, descriptors, ts, &modified_mem_access);
6747 1325 : walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
6748 1325 : free_dominance_info (CDI_DOMINATORS);
6749 1325 : bool cfg_changed = walker.cleanup_eh ();
6750 :
6751 1325 : int i;
6752 1325 : struct ipa_bb_info *bi;
6753 26835 : FOR_EACH_VEC_ELT (fbi.bb_infos, i, bi)
6754 48370 : free_ipa_bb_info (bi);
6755 1325 : fbi.bb_infos.release ();
6756 :
6757 1325 : ts->remove_argaggs_if ([](const ipa_argagg_value &v)
6758 : {
6759 5079 : return v.killed;
6760 : });
6761 :
6762 1325 : vec_free (descriptors);
6763 1325 : if (cfg_changed)
6764 1 : delete_unreachable_blocks_update_callgraph (node, false);
6765 :
6766 1325 : return modified_mem_access ? TODO_update_ssa_only_virtuals : 0;
6767 1325 : }
6768 :
6769 : /* Record that current function return value range is VAL. */
6770 :
6771 : void
6772 751134 : ipa_record_return_value_range (value_range val)
6773 : {
6774 751134 : ipa_record_return_value_range_1
6775 751134 : (cgraph_node::get (current_function_decl), val);
6776 751134 : }
6777 :
6778 : /* Return true if value range of DECL is known and if so initialize RANGE. */
6779 :
6780 : bool
6781 12310279 : ipa_return_value_range (value_range &range, tree decl)
6782 : {
6783 12310279 : cgraph_node *n = cgraph_node::get (decl);
6784 12310279 : if (!n || !ipa_return_value_sum)
6785 : return false;
6786 10142024 : enum availability avail;
6787 10142024 : n = n->ultimate_alias_target (&avail);
6788 10142024 : if (avail < AVAIL_AVAILABLE)
6789 : return false;
6790 2182068 : if (n->decl != decl && !useless_type_conversion_p (TREE_TYPE (decl), TREE_TYPE (n->decl)))
6791 : return false;
6792 2182068 : ipa_return_value_summary *v = ipa_return_value_sum->get (n);
6793 2182068 : if (!v)
6794 : return false;
6795 624063 : v->vr->get_vrange (range);
6796 624063 : return true;
6797 : }
6798 :
6799 : /* Reset all state within ipa-prop.cc so that we can rerun the compiler
6800 : within the same process. For use by toplev::finalize. */
6801 :
6802 : void
6803 264319 : ipa_prop_cc_finalize (void)
6804 : {
6805 264319 : if (function_insertion_hook_holder)
6806 12084 : symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder);
6807 264319 : function_insertion_hook_holder = NULL;
6808 :
6809 264319 : if (ipa_edge_args_sum)
6810 12411 : ggc_delete (ipa_edge_args_sum);
6811 264319 : ipa_edge_args_sum = NULL;
6812 :
6813 264319 : if (ipa_node_params_sum)
6814 12411 : ggc_delete (ipa_node_params_sum);
6815 264319 : ipa_node_params_sum = NULL;
6816 264319 : }
6817 :
6818 : /* Return true if the two pass_through components of two jump functions are
6819 : known to be equivalent. AGG_JF denotes whether they are part of aggregate
6820 : functions or not. The function can be used before the IPA phase of IPA-CP
6821 : or inlining because it cannot cope with refdesc changes these passes can
6822 : carry out. */
6823 :
6824 : static bool
6825 36985 : ipa_agg_pass_through_jf_equivalent_p (ipa_pass_through_data *ipt1,
6826 : ipa_pass_through_data *ipt2,
6827 : bool agg_jf)
6828 :
6829 : {
6830 36985 : gcc_assert (agg_jf ||
6831 : (!ipt1->refdesc_decremented && !ipt2->refdesc_decremented));
6832 36985 : if (ipt1->operation != ipt2->operation
6833 36985 : || ipt1->formal_id != ipt2->formal_id
6834 36985 : || (!agg_jf && (ipt1->agg_preserved != ipt2->agg_preserved)))
6835 : return false;
6836 36985 : if (ipt1->operation != NOP_EXPR
6837 36985 : && (TYPE_MAIN_VARIANT (ipt1->op_type)
6838 5556 : != TYPE_MAIN_VARIANT (ipt2->op_type)))
6839 : return false;
6840 36977 : if (((ipt1->operand != NULL_TREE) != (ipt2->operand != NULL_TREE))
6841 36977 : || (ipt1->operand
6842 5548 : && !values_equal_for_ipcp_p (ipt1->operand, ipt2->operand)))
6843 0 : return false;
6844 : return true;
6845 : }
6846 :
6847 : /* Return true if the two aggregate jump functions are known to be equivalent.
6848 : The function can be used before the IPA phase of IPA-CP or inlining because
6849 : it cannot cope with refdesc changes these passes can carry out. */
6850 :
6851 : static bool
6852 783 : ipa_agg_jump_functions_equivalent_p (ipa_agg_jf_item *ajf1,
6853 : ipa_agg_jf_item *ajf2)
6854 : {
6855 783 : if (ajf1->offset != ajf2->offset
6856 783 : || ajf1->jftype != ajf2->jftype
6857 1566 : || !types_compatible_p (ajf1->type, ajf2->type))
6858 : return false;
6859 :
6860 783 : switch (ajf1->jftype)
6861 : {
6862 297 : case IPA_JF_CONST:
6863 297 : if (!values_equal_for_ipcp_p (ajf1->value.constant,
6864 : ajf2->value.constant))
6865 : return false;
6866 : break;
6867 22 : case IPA_JF_PASS_THROUGH:
6868 22 : {
6869 22 : ipa_pass_through_data *ipt1 = &ajf1->value.pass_through;
6870 22 : ipa_pass_through_data *ipt2 = &ajf2->value.pass_through;
6871 22 : if (!ipa_agg_pass_through_jf_equivalent_p (ipt1, ipt2, true))
6872 : return false;
6873 : }
6874 : break;
6875 464 : case IPA_JF_LOAD_AGG:
6876 464 : {
6877 464 : ipa_load_agg_data *ila1 = &ajf1->value.load_agg;
6878 464 : ipa_load_agg_data *ila2 = &ajf2->value.load_agg;
6879 464 : if (!ipa_agg_pass_through_jf_equivalent_p (&ila1->pass_through,
6880 : &ila2->pass_through, true))
6881 : return false;
6882 464 : if (ila1->offset != ila2->offset
6883 464 : || ila1->by_ref != ila2->by_ref
6884 928 : || !types_compatible_p (ila1->type, ila2->type))
6885 0 : return false;
6886 : }
6887 : break;
6888 0 : default:
6889 0 : gcc_unreachable ();
6890 : }
6891 : return true;
6892 : }
6893 :
6894 : /* Return true if the two jump functions are known to be equivalent. The
6895 : function can be used before the IPA phase of IPA-CP or inlining because it
6896 : cannot cope with refdesc changes these passes can carry out. */
6897 :
6898 : bool
6899 88803 : ipa_jump_functions_equivalent_p (ipa_jump_func *jf1, ipa_jump_func *jf2)
6900 : {
6901 88803 : if (jf1->type != jf2->type)
6902 : return false;
6903 :
6904 88803 : switch (jf1->type)
6905 : {
6906 : case IPA_JF_UNKNOWN:
6907 : break;
6908 18713 : case IPA_JF_CONST:
6909 18713 : {
6910 18713 : tree cst1 = ipa_get_jf_constant (jf1);
6911 18713 : tree cst2 = ipa_get_jf_constant (jf2);
6912 18713 : if (!values_equal_for_ipcp_p (cst1, cst2))
6913 : return false;
6914 :
6915 18712 : ipa_cst_ref_desc *rd1 = jfunc_rdesc_usable (jf1);
6916 18712 : ipa_cst_ref_desc *rd2 = jfunc_rdesc_usable (jf2);
6917 18712 : if (rd1 && rd2)
6918 : {
6919 185 : gcc_assert (rd1->refcount == 1
6920 : && rd2->refcount == 1);
6921 185 : gcc_assert (!rd1->next_duplicate && !rd2->next_duplicate);
6922 : }
6923 18527 : else if (rd1)
6924 : return false;
6925 18527 : else if (rd2)
6926 : return false;
6927 : }
6928 : break;
6929 36499 : case IPA_JF_PASS_THROUGH:
6930 36499 : {
6931 36499 : ipa_pass_through_data *ipt1 = &jf1->value.pass_through;
6932 36499 : ipa_pass_through_data *ipt2 = &jf2->value.pass_through;
6933 36499 : if (!ipa_agg_pass_through_jf_equivalent_p (ipt1, ipt2, false))
6934 : return false;
6935 : }
6936 : break;
6937 11881 : case IPA_JF_ANCESTOR:
6938 11881 : {
6939 11881 : ipa_ancestor_jf_data *ia1 = &jf1->value.ancestor;
6940 11881 : ipa_ancestor_jf_data *ia2 = &jf2->value.ancestor;
6941 :
6942 11881 : if (ia1->formal_id != ia2->formal_id
6943 11881 : || ia1->agg_preserved != ia2->agg_preserved
6944 11881 : || ia1->keep_null != ia2->keep_null
6945 11881 : || ia1->offset != ia2->offset)
6946 : return false;
6947 : }
6948 : break;
6949 0 : default:
6950 0 : gcc_unreachable ();
6951 : }
6952 :
6953 88794 : if (((jf1->m_vr != nullptr) != (jf2->m_vr != nullptr))
6954 88794 : || (jf1->m_vr && !jf1->m_vr->equal_p (*jf2->m_vr)))
6955 : return false;
6956 :
6957 81484 : unsigned alen = vec_safe_length (jf1->agg.items);
6958 82117 : if (vec_safe_length (jf2->agg.items) != alen)
6959 : return false;
6960 :
6961 81483 : if (!alen)
6962 : return true;
6963 :
6964 633 : if (jf1->agg.by_ref != jf2->agg.by_ref)
6965 : return false;
6966 :
6967 1416 : for (unsigned i = 0 ; i < alen; i++)
6968 783 : if (!ipa_agg_jump_functions_equivalent_p (&(*jf1->agg.items)[i],
6969 783 : &(*jf2->agg.items)[i]))
6970 : return false;
6971 :
6972 : return true;
6973 : }
6974 :
6975 : #include "gt-ipa-prop.h"
|