]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ipa-cp.cc
ada: Reference to nonexistent operator in reduction expression accepted
[thirdparty/gcc.git] / gcc / ipa-cp.cc
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2024 Free Software Foundation, Inc.
3
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 /* Interprocedural constant propagation (IPA-CP).
24
25 The goal of this transformation is to
26
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
30
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
35
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
38
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
47
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
52
53
54 First stage - intraprocedural analysis
55 =======================================
56
57 This phase computes jump_function and modification flags.
58
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
62
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
67
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
70
71 ipcp_generate_summary() is the main function of the first stage.
72
73 Second stage - interprocedural analysis
74 ========================================
75
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
79
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
86
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
92
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
95
96 Third phase - materialization of clones, call statement updates.
97 ============================================
98
99 This stage is currently performed by call graph code (mainly in cgraphunit.cc
100 and tree-inline.cc) according to instructions inserted to the call graph by
101 the second stage. */
102
103 #define INCLUDE_ALGORITHM
104 #include "config.h"
105 #include "system.h"
106 #include "coretypes.h"
107 #include "backend.h"
108 #include "tree.h"
109 #include "gimple-expr.h"
110 #include "gimple.h"
111 #include "predict.h"
112 #include "sreal.h"
113 #include "alloc-pool.h"
114 #include "tree-pass.h"
115 #include "cgraph.h"
116 #include "diagnostic.h"
117 #include "fold-const.h"
118 #include "gimple-iterator.h"
119 #include "gimple-fold.h"
120 #include "symbol-summary.h"
121 #include "tree-vrp.h"
122 #include "ipa-cp.h"
123 #include "ipa-prop.h"
124 #include "tree-pretty-print.h"
125 #include "tree-inline.h"
126 #include "ipa-fnsummary.h"
127 #include "ipa-utils.h"
128 #include "tree-ssa-ccp.h"
129 #include "stringpool.h"
130 #include "attribs.h"
131 #include "dbgcnt.h"
132 #include "symtab-clones.h"
133 #include "gimple-range.h"
134
135
136 /* Allocation pools for values and their sources in ipa-cp. */
137
138 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
139 ("IPA-CP constant values");
140
141 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
142 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
143
144 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
145 ("IPA-CP value sources");
146
147 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
148 ("IPA_CP aggregate lattices");
149
150 /* Base count to use in heuristics when using profile feedback. */
151
152 static profile_count base_count;
153
154 /* Original overall size of the program. */
155
156 static long overall_size, orig_overall_size;
157
158 /* Node name to unique clone suffix number map. */
159 static hash_map<const char *, unsigned> *clone_num_suffixes;
160
161 /* Return the param lattices structure corresponding to the Ith formal
162 parameter of the function described by INFO. */
163 static inline class ipcp_param_lattices *
164 ipa_get_parm_lattices (class ipa_node_params *info, int i)
165 {
166 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
167 gcc_checking_assert (!info->ipcp_orig_node);
168 return &(info->lattices[i]);
169 }
170
171 /* Return the lattice corresponding to the scalar value of the Ith formal
172 parameter of the function described by INFO. */
173 static inline ipcp_lattice<tree> *
174 ipa_get_scalar_lat (class ipa_node_params *info, int i)
175 {
176 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
177 return &plats->itself;
178 }
179
180 /* Return the lattice corresponding to the scalar value of the Ith formal
181 parameter of the function described by INFO. */
182 static inline ipcp_lattice<ipa_polymorphic_call_context> *
183 ipa_get_poly_ctx_lat (class ipa_node_params *info, int i)
184 {
185 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
186 return &plats->ctxlat;
187 }
188
189 /* Return whether LAT is a lattice with a single constant and without an
190 undefined value. */
191
192 template <typename valtype>
193 inline bool
194 ipcp_lattice<valtype>::is_single_const ()
195 {
196 if (bottom || contains_variable || values_count != 1)
197 return false;
198 else
199 return true;
200 }
201
202 /* Return true iff X and Y should be considered equal values by IPA-CP. */
203
204 bool
205 values_equal_for_ipcp_p (tree x, tree y)
206 {
207 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
208
209 if (x == y)
210 return true;
211
212 if (TREE_CODE (x) == ADDR_EXPR
213 && TREE_CODE (y) == ADDR_EXPR
214 && (TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
215 || (TREE_CODE (TREE_OPERAND (x, 0)) == VAR_DECL
216 && DECL_IN_CONSTANT_POOL (TREE_OPERAND (x, 0))))
217 && (TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL
218 || (TREE_CODE (TREE_OPERAND (y, 0)) == VAR_DECL
219 && DECL_IN_CONSTANT_POOL (TREE_OPERAND (y, 0)))))
220 return TREE_OPERAND (x, 0) == TREE_OPERAND (y, 0)
221 || operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
222 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
223 else
224 return operand_equal_p (x, y, 0);
225 }
226
227 /* Print V which is extracted from a value in a lattice to F. */
228
229 static void
230 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
231 {
232 v.dump(f, false);
233 }
234
235 /* Print a lattice LAT to F. */
236
237 template <typename valtype>
238 void
239 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
240 {
241 ipcp_value<valtype> *val;
242 bool prev = false;
243
244 if (bottom)
245 {
246 fprintf (f, "BOTTOM\n");
247 return;
248 }
249
250 if (!values_count && !contains_variable)
251 {
252 fprintf (f, "TOP\n");
253 return;
254 }
255
256 if (contains_variable)
257 {
258 fprintf (f, "VARIABLE");
259 prev = true;
260 if (dump_benefits)
261 fprintf (f, "\n");
262 }
263
264 for (val = values; val; val = val->next)
265 {
266 if (dump_benefits && prev)
267 fprintf (f, " ");
268 else if (!dump_benefits && prev)
269 fprintf (f, ", ");
270 else
271 prev = true;
272
273 print_ipcp_constant_value (f, val->value);
274
275 if (dump_sources)
276 {
277 ipcp_value_source<valtype> *s;
278
279 if (val->self_recursion_generated_p ())
280 fprintf (f, " [self_gen(%i), from:",
281 val->self_recursion_generated_level);
282 else
283 fprintf (f, " [scc: %i, from:", val->scc_no);
284 for (s = val->sources; s; s = s->next)
285 fprintf (f, " %i(%f)", s->cs->caller->order,
286 s->cs->sreal_frequency ().to_double ());
287 fprintf (f, "]");
288 }
289
290 if (dump_benefits)
291 fprintf (f, " [loc_time: %g, loc_size: %i, "
292 "prop_time: %g, prop_size: %i]\n",
293 val->local_time_benefit.to_double (), val->local_size_cost,
294 val->prop_time_benefit.to_double (), val->prop_size_cost);
295 }
296 if (!dump_benefits)
297 fprintf (f, "\n");
298 }
299
300 void
301 ipcp_bits_lattice::print (FILE *f)
302 {
303 if (top_p ())
304 fprintf (f, " Bits unknown (TOP)\n");
305 else if (bottom_p ())
306 fprintf (f, " Bits unusable (BOTTOM)\n");
307 else
308 {
309 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
310 fprintf (f, ", mask = "); print_hex (get_mask (), f);
311 fprintf (f, "\n");
312 }
313 }
314
315 /* Print value range lattice to F. */
316
317 void
318 ipcp_vr_lattice::print (FILE * f)
319 {
320 m_vr.dump (f);
321 }
322
323 /* Print all ipcp_lattices of all functions to F. */
324
325 static void
326 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
327 {
328 struct cgraph_node *node;
329 int i, count;
330
331 fprintf (f, "\nLattices:\n");
332 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
333 {
334 class ipa_node_params *info;
335
336 info = ipa_node_params_sum->get (node);
337 /* Skip unoptimized functions and constprop clones since we don't make
338 lattices for them. */
339 if (!info || info->ipcp_orig_node)
340 continue;
341 fprintf (f, " Node: %s:\n", node->dump_name ());
342 count = ipa_get_param_count (info);
343 for (i = 0; i < count; i++)
344 {
345 struct ipcp_agg_lattice *aglat;
346 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
347 fprintf (f, " param [%d]: ", i);
348 plats->itself.print (f, dump_sources, dump_benefits);
349 fprintf (f, " ctxs: ");
350 plats->ctxlat.print (f, dump_sources, dump_benefits);
351 plats->bits_lattice.print (f);
352 fprintf (f, " ");
353 plats->m_value_range.print (f);
354 fprintf (f, "\n");
355 if (plats->virt_call)
356 fprintf (f, " virt_call flag set\n");
357
358 if (plats->aggs_bottom)
359 {
360 fprintf (f, " AGGS BOTTOM\n");
361 continue;
362 }
363 if (plats->aggs_contain_variable)
364 fprintf (f, " AGGS VARIABLE\n");
365 for (aglat = plats->aggs; aglat; aglat = aglat->next)
366 {
367 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
368 plats->aggs_by_ref ? "ref " : "", aglat->offset);
369 aglat->print (f, dump_sources, dump_benefits);
370 }
371 }
372 }
373 }
374
375 /* Determine whether it is at all technically possible to create clones of NODE
376 and store this information in the ipa_node_params structure associated
377 with NODE. */
378
379 static void
380 determine_versionability (struct cgraph_node *node,
381 class ipa_node_params *info)
382 {
383 const char *reason = NULL;
384
385 /* There are a number of generic reasons functions cannot be versioned. We
386 also cannot remove parameters if there are type attributes such as fnspec
387 present. */
388 if (node->alias || node->thunk)
389 reason = "alias or thunk";
390 else if (!node->versionable)
391 reason = "not a tree_versionable_function";
392 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
393 reason = "insufficient body availability";
394 else if (!opt_for_fn (node->decl, optimize)
395 || !opt_for_fn (node->decl, flag_ipa_cp))
396 reason = "non-optimized function";
397 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
398 {
399 /* Ideally we should clone the SIMD clones themselves and create
400 vector copies of them, so IPA-cp and SIMD clones can happily
401 coexist, but that may not be worth the effort. */
402 reason = "function has SIMD clones";
403 }
404 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
405 {
406 /* Ideally we should clone the target clones themselves and create
407 copies of them, so IPA-cp and target clones can happily
408 coexist, but that may not be worth the effort. */
409 reason = "function target_clones attribute";
410 }
411 /* Don't clone decls local to a comdat group; it breaks and for C++
412 decloned constructors, inlining is always better anyway. */
413 else if (node->comdat_local_p ())
414 reason = "comdat-local function";
415 else if (node->calls_comdat_local)
416 {
417 /* TODO: call is versionable if we make sure that all
418 callers are inside of a comdat group. */
419 reason = "calls comdat-local function";
420 }
421
422 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
423 work only when inlined. Cloning them may still lead to better code
424 because ipa-cp will not give up on cloning further. If the function is
425 external this however leads to wrong code because we may end up producing
426 offline copy of the function. */
427 if (DECL_EXTERNAL (node->decl))
428 for (cgraph_edge *edge = node->callees; !reason && edge;
429 edge = edge->next_callee)
430 if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL))
431 {
432 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
433 reason = "external function which calls va_arg_pack";
434 if (DECL_FUNCTION_CODE (edge->callee->decl)
435 == BUILT_IN_VA_ARG_PACK_LEN)
436 reason = "external function which calls va_arg_pack_len";
437 }
438
439 if (reason && dump_file && !node->alias && !node->thunk)
440 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
441 node->dump_name (), reason);
442
443 info->versionable = (reason == NULL);
444 }
445
446 /* Return true if it is at all technically possible to create clones of a
447 NODE. */
448
449 static bool
450 ipcp_versionable_function_p (struct cgraph_node *node)
451 {
452 ipa_node_params *info = ipa_node_params_sum->get (node);
453 return info && info->versionable;
454 }
455
456 /* Structure holding accumulated information about callers of a node. */
457
458 struct caller_statistics
459 {
460 /* If requested (see below), self-recursive call counts are summed into this
461 field. */
462 profile_count rec_count_sum;
463 /* The sum of all ipa counts of all the other (non-recursive) calls. */
464 profile_count count_sum;
465 /* Sum of all frequencies for all calls. */
466 sreal freq_sum;
467 /* Number of calls and hot calls respectively. */
468 int n_calls, n_hot_calls;
469 /* If itself is set up, also count the number of non-self-recursive
470 calls. */
471 int n_nonrec_calls;
472 /* If non-NULL, this is the node itself and calls from it should have their
473 counts included in rec_count_sum and not count_sum. */
474 cgraph_node *itself;
475 };
476
477 /* Initialize fields of STAT to zeroes and optionally set it up so that edges
478 from IGNORED_CALLER are not counted. */
479
480 static inline void
481 init_caller_stats (caller_statistics *stats, cgraph_node *itself = NULL)
482 {
483 stats->rec_count_sum = profile_count::zero ();
484 stats->count_sum = profile_count::zero ();
485 stats->n_calls = 0;
486 stats->n_hot_calls = 0;
487 stats->n_nonrec_calls = 0;
488 stats->freq_sum = 0;
489 stats->itself = itself;
490 }
491
492 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
493 non-thunk incoming edges to NODE. */
494
495 static bool
496 gather_caller_stats (struct cgraph_node *node, void *data)
497 {
498 struct caller_statistics *stats = (struct caller_statistics *) data;
499 struct cgraph_edge *cs;
500
501 for (cs = node->callers; cs; cs = cs->next_caller)
502 if (!cs->caller->thunk)
503 {
504 ipa_node_params *info = ipa_node_params_sum->get (cs->caller);
505 if (info && info->node_dead)
506 continue;
507
508 if (cs->count.ipa ().initialized_p ())
509 {
510 if (stats->itself && stats->itself == cs->caller)
511 stats->rec_count_sum += cs->count.ipa ();
512 else
513 stats->count_sum += cs->count.ipa ();
514 }
515 stats->freq_sum += cs->sreal_frequency ();
516 stats->n_calls++;
517 if (stats->itself && stats->itself != cs->caller)
518 stats->n_nonrec_calls++;
519
520 if (cs->maybe_hot_p ())
521 stats->n_hot_calls ++;
522 }
523 return false;
524
525 }
526
527 /* Return true if this NODE is viable candidate for cloning. */
528
529 static bool
530 ipcp_cloning_candidate_p (struct cgraph_node *node)
531 {
532 struct caller_statistics stats;
533
534 gcc_checking_assert (node->has_gimple_body_p ());
535
536 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
537 {
538 if (dump_file)
539 fprintf (dump_file, "Not considering %s for cloning; "
540 "-fipa-cp-clone disabled.\n",
541 node->dump_name ());
542 return false;
543 }
544
545 if (node->optimize_for_size_p ())
546 {
547 if (dump_file)
548 fprintf (dump_file, "Not considering %s for cloning; "
549 "optimizing it for size.\n",
550 node->dump_name ());
551 return false;
552 }
553
554 init_caller_stats (&stats);
555 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
556
557 if (ipa_size_summaries->get (node)->self_size < stats.n_calls)
558 {
559 if (dump_file)
560 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
561 node->dump_name ());
562 return true;
563 }
564
565 /* When profile is available and function is hot, propagate into it even if
566 calls seems cold; constant propagation can improve function's speed
567 significantly. */
568 if (stats.count_sum > profile_count::zero ()
569 && node->count.ipa ().initialized_p ())
570 {
571 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100))
572 {
573 if (dump_file)
574 fprintf (dump_file, "Considering %s for cloning; "
575 "usually called directly.\n",
576 node->dump_name ());
577 return true;
578 }
579 }
580 if (!stats.n_hot_calls)
581 {
582 if (dump_file)
583 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
584 node->dump_name ());
585 return false;
586 }
587 if (dump_file)
588 fprintf (dump_file, "Considering %s for cloning.\n",
589 node->dump_name ());
590 return true;
591 }
592
593 template <typename valtype>
594 class value_topo_info
595 {
596 public:
597 /* Head of the linked list of topologically sorted values. */
598 ipcp_value<valtype> *values_topo;
599 /* Stack for creating SCCs, represented by a linked list too. */
600 ipcp_value<valtype> *stack;
601 /* Counter driving the algorithm in add_val_to_toposort. */
602 int dfs_counter;
603
604 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
605 {}
606 void add_val (ipcp_value<valtype> *cur_val);
607 void propagate_effects ();
608 };
609
610 /* Arrays representing a topological ordering of call graph nodes and a stack
611 of nodes used during constant propagation and also data required to perform
612 topological sort of values and propagation of benefits in the determined
613 order. */
614
615 class ipa_topo_info
616 {
617 public:
618 /* Array with obtained topological order of cgraph nodes. */
619 struct cgraph_node **order;
620 /* Stack of cgraph nodes used during propagation within SCC until all values
621 in the SCC stabilize. */
622 struct cgraph_node **stack;
623 int nnodes, stack_top;
624
625 value_topo_info<tree> constants;
626 value_topo_info<ipa_polymorphic_call_context> contexts;
627
628 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
629 constants ()
630 {}
631 };
632
633 /* Skip edges from and to nodes without ipa_cp enabled.
634 Ignore not available symbols. */
635
636 static bool
637 ignore_edge_p (cgraph_edge *e)
638 {
639 enum availability avail;
640 cgraph_node *ultimate_target
641 = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
642
643 return (avail <= AVAIL_INTERPOSABLE
644 || !opt_for_fn (ultimate_target->decl, optimize)
645 || !opt_for_fn (ultimate_target->decl, flag_ipa_cp));
646 }
647
648 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
649
650 static void
651 build_toporder_info (class ipa_topo_info *topo)
652 {
653 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
654 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
655
656 gcc_checking_assert (topo->stack_top == 0);
657 topo->nnodes = ipa_reduced_postorder (topo->order, true,
658 ignore_edge_p);
659 }
660
661 /* Free information about strongly connected components and the arrays in
662 TOPO. */
663
664 static void
665 free_toporder_info (class ipa_topo_info *topo)
666 {
667 ipa_free_postorder_info ();
668 free (topo->order);
669 free (topo->stack);
670 }
671
672 /* Add NODE to the stack in TOPO, unless it is already there. */
673
674 static inline void
675 push_node_to_stack (class ipa_topo_info *topo, struct cgraph_node *node)
676 {
677 ipa_node_params *info = ipa_node_params_sum->get (node);
678 if (info->node_enqueued)
679 return;
680 info->node_enqueued = 1;
681 topo->stack[topo->stack_top++] = node;
682 }
683
684 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
685 is empty. */
686
687 static struct cgraph_node *
688 pop_node_from_stack (class ipa_topo_info *topo)
689 {
690 if (topo->stack_top)
691 {
692 struct cgraph_node *node;
693 topo->stack_top--;
694 node = topo->stack[topo->stack_top];
695 ipa_node_params_sum->get (node)->node_enqueued = 0;
696 return node;
697 }
698 else
699 return NULL;
700 }
701
702 /* Set lattice LAT to bottom and return true if it previously was not set as
703 such. */
704
705 template <typename valtype>
706 inline bool
707 ipcp_lattice<valtype>::set_to_bottom ()
708 {
709 bool ret = !bottom;
710 bottom = true;
711 return ret;
712 }
713
714 /* Mark lattice as containing an unknown value and return true if it previously
715 was not marked as such. */
716
717 template <typename valtype>
718 inline bool
719 ipcp_lattice<valtype>::set_contains_variable ()
720 {
721 bool ret = !contains_variable;
722 contains_variable = true;
723 return ret;
724 }
725
726 /* Set all aggregate lattices in PLATS to bottom and return true if they were
727 not previously set as such. */
728
729 static inline bool
730 set_agg_lats_to_bottom (class ipcp_param_lattices *plats)
731 {
732 bool ret = !plats->aggs_bottom;
733 plats->aggs_bottom = true;
734 return ret;
735 }
736
737 /* Mark all aggregate lattices in PLATS as containing an unknown value and
738 return true if they were not previously marked as such. */
739
740 static inline bool
741 set_agg_lats_contain_variable (class ipcp_param_lattices *plats)
742 {
743 bool ret = !plats->aggs_contain_variable;
744 plats->aggs_contain_variable = true;
745 return ret;
746 }
747
748 bool
749 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
750 {
751 return meet_with_1 (other.m_vr);
752 }
753
754 /* Meet the current value of the lattice with the range described by
755 P_VR. */
756
757 bool
758 ipcp_vr_lattice::meet_with (const vrange &p_vr)
759 {
760 return meet_with_1 (p_vr);
761 }
762
763 /* Meet the current value of the lattice with the range described by
764 OTHER_VR. Return TRUE if anything changed. */
765
766 bool
767 ipcp_vr_lattice::meet_with_1 (const vrange &other_vr)
768 {
769 if (bottom_p ())
770 return false;
771
772 if (other_vr.varying_p ())
773 return set_to_bottom ();
774
775 bool res;
776 if (flag_checking)
777 {
778 Value_Range save (m_vr);
779 res = m_vr.union_ (other_vr);
780 gcc_assert (res == (m_vr != save));
781 }
782 else
783 res = m_vr.union_ (other_vr);
784 return res;
785 }
786
787 /* Return true if value range information in the lattice is yet unknown. */
788
789 bool
790 ipcp_vr_lattice::top_p () const
791 {
792 return m_vr.undefined_p ();
793 }
794
795 /* Return true if value range information in the lattice is known to be
796 unusable. */
797
798 bool
799 ipcp_vr_lattice::bottom_p () const
800 {
801 return m_vr.varying_p ();
802 }
803
804 /* Set value range information in the lattice to bottom. Return true if it
805 previously was in a different state. */
806
807 bool
808 ipcp_vr_lattice::set_to_bottom ()
809 {
810 if (m_vr.varying_p ())
811 return false;
812
813 /* Setting an unsupported type here forces the temporary to default
814 to unsupported_range, which can handle VARYING/DEFINED ranges,
815 but nothing else (union, intersect, etc). This allows us to set
816 bottoms on any ranges, and is safe as all users of the lattice
817 check for bottom first. */
818 m_vr.set_type (void_type_node);
819 m_vr.set_varying (void_type_node);
820
821 return true;
822 }
823
824 /* Set lattice value to bottom, if it already isn't the case. */
825
826 bool
827 ipcp_bits_lattice::set_to_bottom ()
828 {
829 if (bottom_p ())
830 return false;
831 m_lattice_val = IPA_BITS_VARYING;
832 m_value = 0;
833 m_mask = -1;
834 return true;
835 }
836
837 /* Set to constant if it isn't already. Only meant to be called
838 when switching state from TOP. */
839
840 bool
841 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
842 {
843 gcc_assert (top_p ());
844 m_lattice_val = IPA_BITS_CONSTANT;
845 m_value = wi::bit_and (wi::bit_not (mask), value);
846 m_mask = mask;
847 return true;
848 }
849
850 /* Return true if any of the known bits are non-zero. */
851
852 bool
853 ipcp_bits_lattice::known_nonzero_p () const
854 {
855 if (!constant_p ())
856 return false;
857 return wi::ne_p (wi::bit_and (wi::bit_not (m_mask), m_value), 0);
858 }
859
860 /* Convert operand to value, mask form. */
861
862 void
863 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
864 {
865 wide_int get_nonzero_bits (const_tree);
866
867 if (TREE_CODE (operand) == INTEGER_CST)
868 {
869 *valuep = wi::to_widest (operand);
870 *maskp = 0;
871 }
872 else
873 {
874 *valuep = 0;
875 *maskp = -1;
876 }
877 }
878
879 /* Meet operation, similar to ccp_lattice_meet, we xor values
880 if this->value, value have different values at same bit positions, we want
881 to drop that bit to varying. Return true if mask is changed.
882 This function assumes that the lattice value is in CONSTANT state. If
883 DROP_ALL_ONES, mask out any known bits with value one afterwards. */
884
885 bool
886 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
887 unsigned precision, bool drop_all_ones)
888 {
889 gcc_assert (constant_p ());
890
891 widest_int old_mask = m_mask;
892 m_mask = (m_mask | mask) | (m_value ^ value);
893 if (drop_all_ones)
894 m_mask |= m_value;
895 m_value &= ~m_mask;
896
897 if (wi::sext (m_mask, precision) == -1)
898 return set_to_bottom ();
899
900 return m_mask != old_mask;
901 }
902
903 /* Meet the bits lattice with operand
904 described by <value, mask, sgn, precision. */
905
906 bool
907 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
908 unsigned precision)
909 {
910 if (bottom_p ())
911 return false;
912
913 if (top_p ())
914 {
915 if (wi::sext (mask, precision) == -1)
916 return set_to_bottom ();
917 return set_to_constant (value, mask);
918 }
919
920 return meet_with_1 (value, mask, precision, false);
921 }
922
923 /* Meet bits lattice with the result of bit_value_binop (other, operand)
924 if code is binary operation or bit_value_unop (other) if code is unary op.
925 In the case when code is nop_expr, no adjustment is required. If
926 DROP_ALL_ONES, mask out any known bits with value one afterwards. */
927
928 bool
929 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
930 signop sgn, enum tree_code code, tree operand,
931 bool drop_all_ones)
932 {
933 if (other.bottom_p ())
934 return set_to_bottom ();
935
936 if (bottom_p () || other.top_p ())
937 return false;
938
939 widest_int adjusted_value, adjusted_mask;
940
941 if (TREE_CODE_CLASS (code) == tcc_binary)
942 {
943 tree type = TREE_TYPE (operand);
944 widest_int o_value, o_mask;
945 get_value_and_mask (operand, &o_value, &o_mask);
946
947 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
948 sgn, precision, other.get_value (), other.get_mask (),
949 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
950
951 if (wi::sext (adjusted_mask, precision) == -1)
952 return set_to_bottom ();
953 }
954
955 else if (TREE_CODE_CLASS (code) == tcc_unary)
956 {
957 bit_value_unop (code, sgn, precision, &adjusted_value,
958 &adjusted_mask, sgn, precision, other.get_value (),
959 other.get_mask ());
960
961 if (wi::sext (adjusted_mask, precision) == -1)
962 return set_to_bottom ();
963 }
964
965 else
966 return set_to_bottom ();
967
968 if (top_p ())
969 {
970 if (drop_all_ones)
971 {
972 adjusted_mask |= adjusted_value;
973 adjusted_value &= ~adjusted_mask;
974 }
975 if (wi::sext (adjusted_mask, precision) == -1)
976 return set_to_bottom ();
977 return set_to_constant (adjusted_value, adjusted_mask);
978 }
979 else
980 return meet_with_1 (adjusted_value, adjusted_mask, precision,
981 drop_all_ones);
982 }
983
984 /* Dump the contents of the list to FILE. */
985
986 void
987 ipa_argagg_value_list::dump (FILE *f)
988 {
989 bool comma = false;
990 for (const ipa_argagg_value &av : m_elts)
991 {
992 fprintf (f, "%s %i[%u]=", comma ? "," : "",
993 av.index, av.unit_offset);
994 print_generic_expr (f, av.value);
995 if (av.by_ref)
996 fprintf (f, "(by_ref)");
997 if (av.killed)
998 fprintf (f, "(killed)");
999 comma = true;
1000 }
1001 fprintf (f, "\n");
1002 }
1003
1004 /* Dump the contents of the list to stderr. */
1005
1006 void
1007 ipa_argagg_value_list::debug ()
1008 {
1009 dump (stderr);
1010 }
1011
1012 /* Return the item describing a constant stored for INDEX at UNIT_OFFSET or
1013 NULL if there is no such constant. */
1014
1015 const ipa_argagg_value *
1016 ipa_argagg_value_list::get_elt (int index, unsigned unit_offset) const
1017 {
1018 ipa_argagg_value key;
1019 key.index = index;
1020 key.unit_offset = unit_offset;
1021 const ipa_argagg_value *res
1022 = std::lower_bound (m_elts.begin (), m_elts.end (), key,
1023 [] (const ipa_argagg_value &elt,
1024 const ipa_argagg_value &val)
1025 {
1026 if (elt.index < val.index)
1027 return true;
1028 if (elt.index > val.index)
1029 return false;
1030 if (elt.unit_offset < val.unit_offset)
1031 return true;
1032 return false;
1033 });
1034
1035 if (res == m_elts.end ()
1036 || res->index != index
1037 || res->unit_offset != unit_offset)
1038 res = nullptr;
1039
1040 /* TODO: perhaps remove the check (that the underlying array is indeed
1041 sorted) if it turns out it can be too slow? */
1042 if (!flag_checking)
1043 return res;
1044
1045 const ipa_argagg_value *slow_res = NULL;
1046 int prev_index = -1;
1047 unsigned prev_unit_offset = 0;
1048 for (const ipa_argagg_value &av : m_elts)
1049 {
1050 gcc_assert (prev_index < 0
1051 || prev_index < av.index
1052 || prev_unit_offset < av.unit_offset);
1053 prev_index = av.index;
1054 prev_unit_offset = av.unit_offset;
1055 if (av.index == index
1056 && av.unit_offset == unit_offset)
1057 slow_res = &av;
1058 }
1059 gcc_assert (res == slow_res);
1060
1061 return res;
1062 }
1063
1064 /* Return the first item describing a constant stored for parameter with INDEX,
1065 regardless of offset or reference, or NULL if there is no such constant. */
1066
1067 const ipa_argagg_value *
1068 ipa_argagg_value_list::get_elt_for_index (int index) const
1069 {
1070 const ipa_argagg_value *res
1071 = std::lower_bound (m_elts.begin (), m_elts.end (), index,
1072 [] (const ipa_argagg_value &elt, unsigned idx)
1073 {
1074 return elt.index < idx;
1075 });
1076 if (res == m_elts.end ()
1077 || res->index != index)
1078 res = nullptr;
1079 return res;
1080 }
1081
1082 /* Return the aggregate constant stored for INDEX at UNIT_OFFSET, not
1083 performing any check of whether value is passed by reference, or NULL_TREE
1084 if there is no such constant. */
1085
1086 tree
1087 ipa_argagg_value_list::get_value (int index, unsigned unit_offset) const
1088 {
1089 const ipa_argagg_value *av = get_elt (index, unit_offset);
1090 return av ? av->value : NULL_TREE;
1091 }
1092
1093 /* Return the aggregate constant stored for INDEX at UNIT_OFFSET, if it is
1094 passed by reference or not according to BY_REF, or NULL_TREE if there is
1095 no such constant. */
1096
1097 tree
1098 ipa_argagg_value_list::get_value (int index, unsigned unit_offset,
1099 bool by_ref) const
1100 {
1101 const ipa_argagg_value *av = get_elt (index, unit_offset);
1102 if (av && av->by_ref == by_ref)
1103 return av->value;
1104 return NULL_TREE;
1105 }
1106
1107 /* Return true if all elements present in OTHER are also present in this
1108 list. */
1109
1110 bool
1111 ipa_argagg_value_list::superset_of_p (const ipa_argagg_value_list &other) const
1112 {
1113 unsigned j = 0;
1114 for (unsigned i = 0; i < other.m_elts.size (); i++)
1115 {
1116 unsigned other_index = other.m_elts[i].index;
1117 unsigned other_offset = other.m_elts[i].unit_offset;
1118
1119 while (j < m_elts.size ()
1120 && (m_elts[j].index < other_index
1121 || (m_elts[j].index == other_index
1122 && m_elts[j].unit_offset < other_offset)))
1123 j++;
1124
1125 if (j >= m_elts.size ()
1126 || m_elts[j].index != other_index
1127 || m_elts[j].unit_offset != other_offset
1128 || m_elts[j].by_ref != other.m_elts[i].by_ref
1129 || !m_elts[j].value
1130 || !values_equal_for_ipcp_p (m_elts[j].value, other.m_elts[i].value))
1131 return false;
1132 }
1133 return true;
1134 }
1135
1136 /* Push all items in this list that describe parameter SRC_INDEX into RES as
1137 ones describing DST_INDEX while subtracting UNIT_DELTA from their unit
1138 offsets but skip those which would end up with a negative offset. */
1139
1140 void
1141 ipa_argagg_value_list::push_adjusted_values (unsigned src_index,
1142 unsigned dest_index,
1143 unsigned unit_delta,
1144 vec<ipa_argagg_value> *res) const
1145 {
1146 const ipa_argagg_value *av = get_elt_for_index (src_index);
1147 if (!av)
1148 return;
1149 unsigned prev_unit_offset = 0;
1150 bool first = true;
1151 for (; av < m_elts.end (); ++av)
1152 {
1153 if (av->index > src_index)
1154 return;
1155 if (av->index == src_index
1156 && (av->unit_offset >= unit_delta)
1157 && av->value)
1158 {
1159 ipa_argagg_value new_av;
1160 gcc_checking_assert (av->value);
1161 new_av.value = av->value;
1162 new_av.unit_offset = av->unit_offset - unit_delta;
1163 new_av.index = dest_index;
1164 new_av.by_ref = av->by_ref;
1165 gcc_assert (!av->killed);
1166 new_av.killed = false;
1167
1168 /* Quick check that the offsets we push are indeed increasing. */
1169 gcc_assert (first
1170 || new_av.unit_offset > prev_unit_offset);
1171 prev_unit_offset = new_av.unit_offset;
1172 first = false;
1173
1174 res->safe_push (new_av);
1175 }
1176 }
1177 }
1178
1179 /* Push to RES information about single lattices describing aggregate values in
1180 PLATS as those describing parameter DEST_INDEX and the original offset minus
1181 UNIT_DELTA. Return true if any item has been pushed to RES. */
1182
1183 static bool
1184 push_agg_values_from_plats (ipcp_param_lattices *plats, int dest_index,
1185 unsigned unit_delta,
1186 vec<ipa_argagg_value> *res)
1187 {
1188 if (plats->aggs_contain_variable)
1189 return false;
1190
1191 bool pushed_sth = false;
1192 bool first = true;
1193 unsigned prev_unit_offset = 0;
1194 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
1195 if (aglat->is_single_const ()
1196 && (aglat->offset / BITS_PER_UNIT - unit_delta) >= 0)
1197 {
1198 ipa_argagg_value iav;
1199 iav.value = aglat->values->value;
1200 iav.unit_offset = aglat->offset / BITS_PER_UNIT - unit_delta;
1201 iav.index = dest_index;
1202 iav.by_ref = plats->aggs_by_ref;
1203 iav.killed = false;
1204
1205 gcc_assert (first
1206 || iav.unit_offset > prev_unit_offset);
1207 prev_unit_offset = iav.unit_offset;
1208 first = false;
1209
1210 pushed_sth = true;
1211 res->safe_push (iav);
1212 }
1213 return pushed_sth;
1214 }
1215
1216 /* Turn all values in LIST that are not present in OTHER into NULL_TREEs.
1217 Return the number of remaining valid entries. */
1218
1219 static unsigned
1220 intersect_argaggs_with (vec<ipa_argagg_value> &elts,
1221 const vec<ipa_argagg_value> &other)
1222 {
1223 unsigned valid_entries = 0;
1224 unsigned j = 0;
1225 for (unsigned i = 0; i < elts.length (); i++)
1226 {
1227 if (!elts[i].value)
1228 continue;
1229
1230 unsigned this_index = elts[i].index;
1231 unsigned this_offset = elts[i].unit_offset;
1232
1233 while (j < other.length ()
1234 && (other[j].index < this_index
1235 || (other[j].index == this_index
1236 && other[j].unit_offset < this_offset)))
1237 j++;
1238
1239 if (j >= other.length ())
1240 {
1241 elts[i].value = NULL_TREE;
1242 continue;
1243 }
1244
1245 if (other[j].index == this_index
1246 && other[j].unit_offset == this_offset
1247 && other[j].by_ref == elts[i].by_ref
1248 && other[j].value
1249 && values_equal_for_ipcp_p (other[j].value, elts[i].value))
1250 valid_entries++;
1251 else
1252 elts[i].value = NULL_TREE;
1253 }
1254 return valid_entries;
1255 }
1256
1257 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1258 return true is any of them has not been marked as such so far. */
1259
1260 static inline bool
1261 set_all_contains_variable (class ipcp_param_lattices *plats)
1262 {
1263 bool ret;
1264 ret = plats->itself.set_contains_variable ();
1265 ret |= plats->ctxlat.set_contains_variable ();
1266 ret |= set_agg_lats_contain_variable (plats);
1267 ret |= plats->bits_lattice.set_to_bottom ();
1268 ret |= plats->m_value_range.set_to_bottom ();
1269 return ret;
1270 }
1271
1272 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1273 points to by the number of callers to NODE. */
1274
1275 static bool
1276 count_callers (cgraph_node *node, void *data)
1277 {
1278 int *caller_count = (int *) data;
1279
1280 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1281 /* Local thunks can be handled transparently, but if the thunk cannot
1282 be optimized out, count it as a real use. */
1283 if (!cs->caller->thunk || !cs->caller->local)
1284 ++*caller_count;
1285 return false;
1286 }
1287
1288 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1289 the one caller of some other node. Set the caller's corresponding flag. */
1290
1291 static bool
1292 set_single_call_flag (cgraph_node *node, void *)
1293 {
1294 cgraph_edge *cs = node->callers;
1295 /* Local thunks can be handled transparently, skip them. */
1296 while (cs && cs->caller->thunk && cs->caller->local)
1297 cs = cs->next_caller;
1298 if (cs)
1299 if (ipa_node_params* info = ipa_node_params_sum->get (cs->caller))
1300 {
1301 info->node_calling_single_call = true;
1302 return true;
1303 }
1304 return false;
1305 }
1306
1307 /* Initialize ipcp_lattices. */
1308
1309 static void
1310 initialize_node_lattices (struct cgraph_node *node)
1311 {
1312 ipa_node_params *info = ipa_node_params_sum->get (node);
1313 struct cgraph_edge *ie;
1314 bool disable = false, variable = false;
1315 int i;
1316
1317 gcc_checking_assert (node->has_gimple_body_p ());
1318
1319 if (!ipa_get_param_count (info))
1320 disable = true;
1321 else if (node->local)
1322 {
1323 int caller_count = 0;
1324 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1325 true);
1326 gcc_checking_assert (caller_count > 0);
1327 if (caller_count == 1)
1328 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1329 NULL, true);
1330 }
1331 else
1332 {
1333 /* When cloning is allowed, we can assume that externally visible
1334 functions are not called. We will compensate this by cloning
1335 later. */
1336 if (ipcp_versionable_function_p (node)
1337 && ipcp_cloning_candidate_p (node))
1338 variable = true;
1339 else
1340 disable = true;
1341 }
1342
1343 if (dump_file && (dump_flags & TDF_DETAILS)
1344 && !node->alias && !node->thunk)
1345 {
1346 fprintf (dump_file, "Initializing lattices of %s\n",
1347 node->dump_name ());
1348 if (disable || variable)
1349 fprintf (dump_file, " Marking all lattices as %s\n",
1350 disable ? "BOTTOM" : "VARIABLE");
1351 }
1352
1353 auto_vec<bool, 16> surviving_params;
1354 bool pre_modified = false;
1355
1356 clone_info *cinfo = clone_info::get (node);
1357
1358 if (!disable && cinfo && cinfo->param_adjustments)
1359 {
1360 /* At the moment all IPA optimizations should use the number of
1361 parameters of the prevailing decl as the m_always_copy_start.
1362 Handling any other value would complicate the code below, so for the
1363 time bing let's only assert it is so. */
1364 gcc_assert ((cinfo->param_adjustments->m_always_copy_start
1365 == ipa_get_param_count (info))
1366 || cinfo->param_adjustments->m_always_copy_start < 0);
1367
1368 pre_modified = true;
1369 cinfo->param_adjustments->get_surviving_params (&surviving_params);
1370
1371 if (dump_file && (dump_flags & TDF_DETAILS)
1372 && !node->alias && !node->thunk)
1373 {
1374 bool first = true;
1375 for (int j = 0; j < ipa_get_param_count (info); j++)
1376 {
1377 if (j < (int) surviving_params.length ()
1378 && surviving_params[j])
1379 continue;
1380 if (first)
1381 {
1382 fprintf (dump_file,
1383 " The following parameters are dead on arrival:");
1384 first = false;
1385 }
1386 fprintf (dump_file, " %u", j);
1387 }
1388 if (!first)
1389 fprintf (dump_file, "\n");
1390 }
1391 }
1392
1393 for (i = 0; i < ipa_get_param_count (info); i++)
1394 {
1395 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1396 tree type = ipa_get_type (info, i);
1397 if (disable
1398 || !ipa_get_type (info, i)
1399 || (pre_modified && (surviving_params.length () <= (unsigned) i
1400 || !surviving_params[i])))
1401 {
1402 plats->itself.set_to_bottom ();
1403 plats->ctxlat.set_to_bottom ();
1404 set_agg_lats_to_bottom (plats);
1405 plats->bits_lattice.set_to_bottom ();
1406 plats->m_value_range.init (type);
1407 plats->m_value_range.set_to_bottom ();
1408 }
1409 else
1410 {
1411 plats->m_value_range.init (type);
1412 if (variable)
1413 set_all_contains_variable (plats);
1414 }
1415 }
1416
1417 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1418 if (ie->indirect_info->polymorphic
1419 && ie->indirect_info->param_index >= 0)
1420 {
1421 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1422 ipa_get_parm_lattices (info,
1423 ie->indirect_info->param_index)->virt_call = 1;
1424 }
1425 }
1426
1427 /* Return true if VALUE can be safely IPA-CP propagated to a parameter of type
1428 PARAM_TYPE. */
1429
1430 static bool
1431 ipacp_value_safe_for_type (tree param_type, tree value)
1432 {
1433 tree val_type = TREE_TYPE (value);
1434 if (param_type == val_type
1435 || useless_type_conversion_p (param_type, val_type)
1436 || fold_convertible_p (param_type, value))
1437 return true;
1438 else
1439 return false;
1440 }
1441
1442 /* Return the result of a (possibly arithmetic) operation on the constant
1443 value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is
1444 the type of the parameter to which the result is passed. Return
1445 NULL_TREE if that cannot be determined or be considered an
1446 interprocedural invariant. */
1447
1448 static tree
1449 ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand,
1450 tree res_type)
1451 {
1452 tree res;
1453
1454 if (opcode == NOP_EXPR)
1455 return input;
1456 if (!is_gimple_ip_invariant (input))
1457 return NULL_TREE;
1458
1459 if (opcode == ASSERT_EXPR)
1460 {
1461 if (values_equal_for_ipcp_p (input, operand))
1462 return input;
1463 else
1464 return NULL_TREE;
1465 }
1466
1467 if (!res_type)
1468 {
1469 if (TREE_CODE_CLASS (opcode) == tcc_comparison)
1470 res_type = boolean_type_node;
1471 else if (expr_type_first_operand_type_p (opcode))
1472 res_type = TREE_TYPE (input);
1473 else
1474 return NULL_TREE;
1475 }
1476
1477 if (TREE_CODE_CLASS (opcode) == tcc_unary)
1478 res = fold_unary (opcode, res_type, input);
1479 else
1480 res = fold_binary (opcode, res_type, input, operand);
1481
1482 if (res && !is_gimple_ip_invariant (res))
1483 return NULL_TREE;
1484
1485 return res;
1486 }
1487
1488 /* Return the result of a (possibly arithmetic) pass through jump function
1489 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter
1490 to which the result is passed. Return NULL_TREE if that cannot be
1491 determined or be considered an interprocedural invariant. */
1492
1493 static tree
1494 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input,
1495 tree res_type)
1496 {
1497 return ipa_get_jf_arith_result (ipa_get_jf_pass_through_operation (jfunc),
1498 input,
1499 ipa_get_jf_pass_through_operand (jfunc),
1500 res_type);
1501 }
1502
1503 /* Return the result of an ancestor jump function JFUNC on the constant value
1504 INPUT. Return NULL_TREE if that cannot be determined. */
1505
1506 static tree
1507 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1508 {
1509 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1510 if (TREE_CODE (input) == ADDR_EXPR)
1511 {
1512 gcc_checking_assert (is_gimple_ip_invariant_address (input));
1513 poly_int64 off = ipa_get_jf_ancestor_offset (jfunc);
1514 if (known_eq (off, 0))
1515 return input;
1516 poly_int64 byte_offset = exact_div (off, BITS_PER_UNIT);
1517 return build1 (ADDR_EXPR, TREE_TYPE (input),
1518 fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (input)), input,
1519 build_int_cst (ptr_type_node, byte_offset)));
1520 }
1521 else if (ipa_get_jf_ancestor_keep_null (jfunc)
1522 && zerop (input))
1523 return input;
1524 else
1525 return NULL_TREE;
1526 }
1527
1528 /* Determine whether JFUNC evaluates to a single known constant value and if
1529 so, return it. Otherwise return NULL. INFO describes the caller node or
1530 the one it is inlined to, so that pass-through jump functions can be
1531 evaluated. PARM_TYPE is the type of the parameter to which the result is
1532 passed. */
1533
1534 tree
1535 ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc,
1536 tree parm_type)
1537 {
1538 if (jfunc->type == IPA_JF_CONST)
1539 return ipa_get_jf_constant (jfunc);
1540 else if (jfunc->type == IPA_JF_PASS_THROUGH
1541 || jfunc->type == IPA_JF_ANCESTOR)
1542 {
1543 tree input;
1544 int idx;
1545
1546 if (jfunc->type == IPA_JF_PASS_THROUGH)
1547 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1548 else
1549 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1550
1551 if (info->ipcp_orig_node)
1552 input = info->known_csts[idx];
1553 else
1554 {
1555 ipcp_lattice<tree> *lat;
1556
1557 if (info->lattices.is_empty ()
1558 || idx >= ipa_get_param_count (info))
1559 return NULL_TREE;
1560 lat = ipa_get_scalar_lat (info, idx);
1561 if (!lat->is_single_const ())
1562 return NULL_TREE;
1563 input = lat->values->value;
1564 }
1565
1566 if (!input)
1567 return NULL_TREE;
1568
1569 if (jfunc->type == IPA_JF_PASS_THROUGH)
1570 return ipa_get_jf_pass_through_result (jfunc, input, parm_type);
1571 else
1572 return ipa_get_jf_ancestor_result (jfunc, input);
1573 }
1574 else
1575 return NULL_TREE;
1576 }
1577
1578 /* Determine whether JFUNC evaluates to single known polymorphic context, given
1579 that INFO describes the caller node or the one it is inlined to, CS is the
1580 call graph edge corresponding to JFUNC and CSIDX index of the described
1581 parameter. */
1582
1583 ipa_polymorphic_call_context
1584 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1585 ipa_jump_func *jfunc)
1586 {
1587 ipa_edge_args *args = ipa_edge_args_sum->get (cs);
1588 ipa_polymorphic_call_context ctx;
1589 ipa_polymorphic_call_context *edge_ctx
1590 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1591
1592 if (edge_ctx && !edge_ctx->useless_p ())
1593 ctx = *edge_ctx;
1594
1595 if (jfunc->type == IPA_JF_PASS_THROUGH
1596 || jfunc->type == IPA_JF_ANCESTOR)
1597 {
1598 ipa_polymorphic_call_context srcctx;
1599 int srcidx;
1600 bool type_preserved = true;
1601 if (jfunc->type == IPA_JF_PASS_THROUGH)
1602 {
1603 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1604 return ctx;
1605 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1606 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1607 }
1608 else
1609 {
1610 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1611 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1612 }
1613 if (info->ipcp_orig_node)
1614 {
1615 if (info->known_contexts.exists ())
1616 srcctx = info->known_contexts[srcidx];
1617 }
1618 else
1619 {
1620 if (info->lattices.is_empty ()
1621 || srcidx >= ipa_get_param_count (info))
1622 return ctx;
1623 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1624 lat = ipa_get_poly_ctx_lat (info, srcidx);
1625 if (!lat->is_single_const ())
1626 return ctx;
1627 srcctx = lat->values->value;
1628 }
1629 if (srcctx.useless_p ())
1630 return ctx;
1631 if (jfunc->type == IPA_JF_ANCESTOR)
1632 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1633 if (!type_preserved)
1634 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1635 srcctx.combine_with (ctx);
1636 return srcctx;
1637 }
1638
1639 return ctx;
1640 }
1641
1642 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1643 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1644 the result is a range that is not VARYING nor UNDEFINED. */
1645
1646 static bool
1647 ipa_vr_operation_and_type_effects (vrange &dst_vr,
1648 const vrange &src_vr,
1649 enum tree_code operation,
1650 tree dst_type, tree src_type)
1651 {
1652 if (!ipa_supports_p (dst_type) || !ipa_supports_p (src_type))
1653 return false;
1654
1655 range_op_handler handler (operation);
1656 if (!handler)
1657 return false;
1658
1659 Value_Range varying (dst_type);
1660 varying.set_varying (dst_type);
1661
1662 return (handler.operand_check_p (dst_type, src_type, dst_type)
1663 && handler.fold_range (dst_vr, dst_type, src_vr, varying)
1664 && !dst_vr.varying_p ()
1665 && !dst_vr.undefined_p ());
1666 }
1667
1668 /* Same as above, but the SRC_VR argument is an IPA_VR which must
1669 first be extracted onto a vrange. */
1670
1671 static bool
1672 ipa_vr_operation_and_type_effects (vrange &dst_vr,
1673 const ipa_vr &src_vr,
1674 enum tree_code operation,
1675 tree dst_type, tree src_type)
1676 {
1677 Value_Range tmp;
1678 src_vr.get_vrange (tmp);
1679 return ipa_vr_operation_and_type_effects (dst_vr, tmp, operation,
1680 dst_type, src_type);
1681 }
1682
1683 /* Determine range of JFUNC given that INFO describes the caller node or
1684 the one it is inlined to, CS is the call graph edge corresponding to JFUNC
1685 and PARM_TYPE of the parameter. */
1686
1687 void
1688 ipa_value_range_from_jfunc (vrange &vr,
1689 ipa_node_params *info, cgraph_edge *cs,
1690 ipa_jump_func *jfunc, tree parm_type)
1691 {
1692 vr.set_undefined ();
1693
1694 if (jfunc->m_vr)
1695 ipa_vr_operation_and_type_effects (vr,
1696 *jfunc->m_vr,
1697 NOP_EXPR, parm_type,
1698 jfunc->m_vr->type ());
1699 if (vr.singleton_p ())
1700 return;
1701 if (jfunc->type == IPA_JF_PASS_THROUGH)
1702 {
1703 int idx;
1704 ipcp_transformation *sum
1705 = ipcp_get_transformation_summary (cs->caller->inlined_to
1706 ? cs->caller->inlined_to
1707 : cs->caller);
1708 if (!sum || !sum->m_vr)
1709 return;
1710
1711 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1712
1713 if (!(*sum->m_vr)[idx].known_p ())
1714 return;
1715 tree vr_type = ipa_get_type (info, idx);
1716 Value_Range srcvr;
1717 (*sum->m_vr)[idx].get_vrange (srcvr);
1718
1719 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1720
1721 if (TREE_CODE_CLASS (operation) == tcc_unary)
1722 {
1723 Value_Range res (parm_type);
1724
1725 if (ipa_vr_operation_and_type_effects (res,
1726 srcvr,
1727 operation, parm_type,
1728 vr_type))
1729 vr.intersect (res);
1730 }
1731 else
1732 {
1733 Value_Range op_res (vr_type);
1734 Value_Range res (vr_type);
1735 tree op = ipa_get_jf_pass_through_operand (jfunc);
1736 Value_Range op_vr (TREE_TYPE (op));
1737 range_op_handler handler (operation);
1738
1739 ipa_range_set_and_normalize (op_vr, op);
1740
1741 if (!handler
1742 || !op_res.supports_type_p (vr_type)
1743 /* Sometimes we try to fold comparison operators using a
1744 pointer type to hold the result instead of a boolean
1745 type. Avoid trapping in the sanity check in
1746 fold_range until this is fixed. */
1747 || srcvr.undefined_p ()
1748 || op_vr.undefined_p ()
1749 || !handler.operand_check_p (vr_type, srcvr.type (), op_vr.type ())
1750 || !handler.fold_range (op_res, vr_type, srcvr, op_vr))
1751 op_res.set_varying (vr_type);
1752
1753 if (ipa_vr_operation_and_type_effects (res,
1754 op_res,
1755 NOP_EXPR, parm_type,
1756 vr_type))
1757 vr.intersect (res);
1758 }
1759 }
1760 }
1761
1762 /* Determine whether ITEM, jump function for an aggregate part, evaluates to a
1763 single known constant value and if so, return it. Otherwise return NULL.
1764 NODE and INFO describes the caller node or the one it is inlined to, and
1765 its related info. */
1766
1767 tree
1768 ipa_agg_value_from_jfunc (ipa_node_params *info, cgraph_node *node,
1769 const ipa_agg_jf_item *item)
1770 {
1771 tree value = NULL_TREE;
1772 int src_idx;
1773
1774 if (item->offset < 0
1775 || item->jftype == IPA_JF_UNKNOWN
1776 || item->offset >= (HOST_WIDE_INT) UINT_MAX * BITS_PER_UNIT)
1777 return NULL_TREE;
1778
1779 if (item->jftype == IPA_JF_CONST)
1780 return item->value.constant;
1781
1782 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
1783 || item->jftype == IPA_JF_LOAD_AGG);
1784
1785 src_idx = item->value.pass_through.formal_id;
1786
1787 if (info->ipcp_orig_node)
1788 {
1789 if (item->jftype == IPA_JF_PASS_THROUGH)
1790 value = info->known_csts[src_idx];
1791 else if (ipcp_transformation *ts = ipcp_get_transformation_summary (node))
1792 {
1793 ipa_argagg_value_list avl (ts);
1794 value = avl.get_value (src_idx,
1795 item->value.load_agg.offset / BITS_PER_UNIT,
1796 item->value.load_agg.by_ref);
1797 }
1798 }
1799 else if (!info->lattices.is_empty ())
1800 {
1801 class ipcp_param_lattices *src_plats
1802 = ipa_get_parm_lattices (info, src_idx);
1803
1804 if (item->jftype == IPA_JF_PASS_THROUGH)
1805 {
1806 struct ipcp_lattice<tree> *lat = &src_plats->itself;
1807
1808 if (!lat->is_single_const ())
1809 return NULL_TREE;
1810
1811 value = lat->values->value;
1812 }
1813 else if (src_plats->aggs
1814 && !src_plats->aggs_bottom
1815 && !src_plats->aggs_contain_variable
1816 && src_plats->aggs_by_ref == item->value.load_agg.by_ref)
1817 {
1818 struct ipcp_agg_lattice *aglat;
1819
1820 for (aglat = src_plats->aggs; aglat; aglat = aglat->next)
1821 {
1822 if (aglat->offset > item->value.load_agg.offset)
1823 break;
1824
1825 if (aglat->offset == item->value.load_agg.offset)
1826 {
1827 if (aglat->is_single_const ())
1828 value = aglat->values->value;
1829 break;
1830 }
1831 }
1832 }
1833 }
1834
1835 if (!value)
1836 return NULL_TREE;
1837
1838 if (item->jftype == IPA_JF_LOAD_AGG)
1839 {
1840 tree load_type = item->value.load_agg.type;
1841 tree value_type = TREE_TYPE (value);
1842
1843 /* Ensure value type is compatible with load type. */
1844 if (!useless_type_conversion_p (load_type, value_type))
1845 return NULL_TREE;
1846 }
1847
1848 return ipa_get_jf_arith_result (item->value.pass_through.operation,
1849 value,
1850 item->value.pass_through.operand,
1851 item->type);
1852 }
1853
1854 /* Process all items in AGG_JFUNC relative to caller (or the node the original
1855 caller is inlined to) NODE which described by INFO and push the results to
1856 RES as describing values passed in parameter DST_INDEX. */
1857
1858 void
1859 ipa_push_agg_values_from_jfunc (ipa_node_params *info, cgraph_node *node,
1860 ipa_agg_jump_function *agg_jfunc,
1861 unsigned dst_index,
1862 vec<ipa_argagg_value> *res)
1863 {
1864 unsigned prev_unit_offset = 0;
1865 bool first = true;
1866
1867 for (const ipa_agg_jf_item &item : agg_jfunc->items)
1868 {
1869 tree value = ipa_agg_value_from_jfunc (info, node, &item);
1870 if (!value)
1871 continue;
1872
1873 ipa_argagg_value iav;
1874 iav.value = value;
1875 iav.unit_offset = item.offset / BITS_PER_UNIT;
1876 iav.index = dst_index;
1877 iav.by_ref = agg_jfunc->by_ref;
1878 iav.killed = 0;
1879
1880 gcc_assert (first
1881 || iav.unit_offset > prev_unit_offset);
1882 prev_unit_offset = iav.unit_offset;
1883 first = false;
1884
1885 res->safe_push (iav);
1886 }
1887 }
1888
1889 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1890 bottom, not containing a variable component and without any known value at
1891 the same time. */
1892
1893 DEBUG_FUNCTION void
1894 ipcp_verify_propagated_values (void)
1895 {
1896 struct cgraph_node *node;
1897
1898 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1899 {
1900 ipa_node_params *info = ipa_node_params_sum->get (node);
1901 if (!opt_for_fn (node->decl, flag_ipa_cp)
1902 || !opt_for_fn (node->decl, optimize))
1903 continue;
1904 int i, count = ipa_get_param_count (info);
1905
1906 for (i = 0; i < count; i++)
1907 {
1908 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1909
1910 if (!lat->bottom
1911 && !lat->contains_variable
1912 && lat->values_count == 0)
1913 {
1914 if (dump_file)
1915 {
1916 symtab->dump (dump_file);
1917 fprintf (dump_file, "\nIPA lattices after constant "
1918 "propagation, before gcc_unreachable:\n");
1919 print_all_lattices (dump_file, true, false);
1920 }
1921
1922 gcc_unreachable ();
1923 }
1924 }
1925 }
1926 }
1927
1928 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1929
1930 static bool
1931 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1932 ipa_polymorphic_call_context y)
1933 {
1934 return x.equal_to (y);
1935 }
1936
1937
1938 /* Add a new value source to the value represented by THIS, marking that a
1939 value comes from edge CS and (if the underlying jump function is a
1940 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1941 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1942 scalar value of the parameter itself or the offset within an aggregate. */
1943
1944 template <typename valtype>
1945 void
1946 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1947 int src_idx, HOST_WIDE_INT offset)
1948 {
1949 ipcp_value_source<valtype> *src;
1950
1951 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1952 src->offset = offset;
1953 src->cs = cs;
1954 src->val = src_val;
1955 src->index = src_idx;
1956
1957 src->next = sources;
1958 sources = src;
1959 }
1960
1961 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1962 SOURCE and clear all other fields. */
1963
1964 static ipcp_value<tree> *
1965 allocate_and_init_ipcp_value (tree cst, unsigned same_lat_gen_level)
1966 {
1967 ipcp_value<tree> *val;
1968
1969 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1970 val->value = cst;
1971 val->self_recursion_generated_level = same_lat_gen_level;
1972 return val;
1973 }
1974
1975 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1976 value to SOURCE and clear all other fields. */
1977
1978 static ipcp_value<ipa_polymorphic_call_context> *
1979 allocate_and_init_ipcp_value (ipa_polymorphic_call_context ctx,
1980 unsigned same_lat_gen_level)
1981 {
1982 ipcp_value<ipa_polymorphic_call_context> *val;
1983
1984 val = new (ipcp_poly_ctx_values_pool.allocate ())
1985 ipcp_value<ipa_polymorphic_call_context>();
1986 val->value = ctx;
1987 val->self_recursion_generated_level = same_lat_gen_level;
1988 return val;
1989 }
1990
1991 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1992 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1993 meaning. OFFSET -1 means the source is scalar and not a part of an
1994 aggregate. If non-NULL, VAL_P records address of existing or newly added
1995 ipcp_value.
1996
1997 If the value is generated for a self-recursive call as a result of an
1998 arithmetic pass-through jump-function acting on a value in the same lattice,
1999 SAME_LAT_GEN_LEVEL must be the length of such chain, otherwise it must be
2000 zero. If it is non-zero, PARAM_IPA_CP_VALUE_LIST_SIZE limit is ignored. */
2001
2002 template <typename valtype>
2003 bool
2004 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
2005 ipcp_value<valtype> *src_val,
2006 int src_idx, HOST_WIDE_INT offset,
2007 ipcp_value<valtype> **val_p,
2008 unsigned same_lat_gen_level)
2009 {
2010 ipcp_value<valtype> *val, *last_val = NULL;
2011
2012 if (val_p)
2013 *val_p = NULL;
2014
2015 if (bottom)
2016 return false;
2017
2018 for (val = values; val; last_val = val, val = val->next)
2019 if (values_equal_for_ipcp_p (val->value, newval))
2020 {
2021 if (val_p)
2022 *val_p = val;
2023
2024 if (val->self_recursion_generated_level < same_lat_gen_level)
2025 val->self_recursion_generated_level = same_lat_gen_level;
2026
2027 if (ipa_edge_within_scc (cs))
2028 {
2029 ipcp_value_source<valtype> *s;
2030 for (s = val->sources; s; s = s->next)
2031 if (s->cs == cs && s->val == src_val)
2032 break;
2033 if (s)
2034 return false;
2035 }
2036
2037 val->add_source (cs, src_val, src_idx, offset);
2038 return false;
2039 }
2040
2041 if (!same_lat_gen_level && values_count >= opt_for_fn (cs->callee->decl,
2042 param_ipa_cp_value_list_size))
2043 {
2044 /* We can only free sources, not the values themselves, because sources
2045 of other values in this SCC might point to them. */
2046 for (val = values; val; val = val->next)
2047 {
2048 while (val->sources)
2049 {
2050 ipcp_value_source<valtype> *src = val->sources;
2051 val->sources = src->next;
2052 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
2053 }
2054 }
2055 values = NULL;
2056 return set_to_bottom ();
2057 }
2058
2059 values_count++;
2060 val = allocate_and_init_ipcp_value (newval, same_lat_gen_level);
2061 val->add_source (cs, src_val, src_idx, offset);
2062 val->next = NULL;
2063
2064 /* Add the new value to end of value list, which can reduce iterations
2065 of propagation stage for recursive function. */
2066 if (last_val)
2067 last_val->next = val;
2068 else
2069 values = val;
2070
2071 if (val_p)
2072 *val_p = val;
2073
2074 return true;
2075 }
2076
2077 /* A helper function that returns result of operation specified by OPCODE on
2078 the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the
2079 value of SRC_VAL. If the operation is binary, OPND2 is a constant value
2080 acting as its second operand. If non-NULL, RES_TYPE is expected type of
2081 the result. */
2082
2083 static tree
2084 get_val_across_arith_op (enum tree_code opcode,
2085 tree opnd1_type,
2086 tree opnd2,
2087 ipcp_value<tree> *src_val,
2088 tree res_type)
2089 {
2090 tree opnd1 = src_val->value;
2091
2092 /* Skip source values that is incompatible with specified type. */
2093 if (opnd1_type
2094 && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1)))
2095 return NULL_TREE;
2096
2097 return ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type);
2098 }
2099
2100 /* Propagate values through an arithmetic transformation described by a jump
2101 function associated with edge CS, taking values from SRC_LAT and putting
2102 them into DEST_LAT. OPND1_TYPE is expected type for the values in SRC_LAT.
2103 OPND2 is a constant value if transformation is a binary operation.
2104 SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice of
2105 a part of the aggregate. SRC_IDX is the index of the source parameter.
2106 RES_TYPE is the value type of result being propagated into. Return true if
2107 DEST_LAT changed. */
2108
2109 static bool
2110 propagate_vals_across_arith_jfunc (cgraph_edge *cs,
2111 enum tree_code opcode,
2112 tree opnd1_type,
2113 tree opnd2,
2114 ipcp_lattice<tree> *src_lat,
2115 ipcp_lattice<tree> *dest_lat,
2116 HOST_WIDE_INT src_offset,
2117 int src_idx,
2118 tree res_type)
2119 {
2120 ipcp_value<tree> *src_val;
2121 bool ret = false;
2122
2123 /* Due to circular dependencies, propagating within an SCC through arithmetic
2124 transformation would create infinite number of values. But for
2125 self-feeding recursive function, we could allow propagation in a limited
2126 count, and this can enable a simple kind of recursive function versioning.
2127 For other scenario, we would just make lattices bottom. */
2128 if (opcode != NOP_EXPR && ipa_edge_within_scc (cs))
2129 {
2130 int i;
2131
2132 int max_recursive_depth = opt_for_fn(cs->caller->decl,
2133 param_ipa_cp_max_recursive_depth);
2134 if (src_lat != dest_lat || max_recursive_depth < 1)
2135 return dest_lat->set_contains_variable ();
2136
2137 /* No benefit if recursive execution is in low probability. */
2138 if (cs->sreal_frequency () * 100
2139 <= ((sreal) 1) * opt_for_fn (cs->caller->decl,
2140 param_ipa_cp_min_recursive_probability))
2141 return dest_lat->set_contains_variable ();
2142
2143 auto_vec<ipcp_value<tree> *, 8> val_seeds;
2144
2145 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2146 {
2147 /* Now we do not use self-recursively generated value as propagation
2148 source, this is absolutely conservative, but could avoid explosion
2149 of lattice's value space, especially when one recursive function
2150 calls another recursive. */
2151 if (src_val->self_recursion_generated_p ())
2152 {
2153 ipcp_value_source<tree> *s;
2154
2155 /* If the lattice has already been propagated for the call site,
2156 no need to do that again. */
2157 for (s = src_val->sources; s; s = s->next)
2158 if (s->cs == cs)
2159 return dest_lat->set_contains_variable ();
2160 }
2161 else
2162 val_seeds.safe_push (src_val);
2163 }
2164
2165 gcc_assert ((int) val_seeds.length () <= param_ipa_cp_value_list_size);
2166
2167 /* Recursively generate lattice values with a limited count. */
2168 FOR_EACH_VEC_ELT (val_seeds, i, src_val)
2169 {
2170 for (int j = 1; j < max_recursive_depth; j++)
2171 {
2172 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2173 src_val, res_type);
2174 if (!cstval
2175 || !ipacp_value_safe_for_type (res_type, cstval))
2176 break;
2177
2178 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2179 src_offset, &src_val, j);
2180 gcc_checking_assert (src_val);
2181 }
2182 }
2183 ret |= dest_lat->set_contains_variable ();
2184 }
2185 else
2186 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2187 {
2188 /* Now we do not use self-recursively generated value as propagation
2189 source, otherwise it is easy to make value space of normal lattice
2190 overflow. */
2191 if (src_val->self_recursion_generated_p ())
2192 {
2193 ret |= dest_lat->set_contains_variable ();
2194 continue;
2195 }
2196
2197 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2198 src_val, res_type);
2199 if (cstval
2200 && ipacp_value_safe_for_type (res_type, cstval))
2201 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2202 src_offset);
2203 else
2204 ret |= dest_lat->set_contains_variable ();
2205 }
2206
2207 return ret;
2208 }
2209
2210 /* Propagate values through a pass-through jump function JFUNC associated with
2211 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2212 is the index of the source parameter. PARM_TYPE is the type of the
2213 parameter to which the result is passed. */
2214
2215 static bool
2216 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
2217 ipcp_lattice<tree> *src_lat,
2218 ipcp_lattice<tree> *dest_lat, int src_idx,
2219 tree parm_type)
2220 {
2221 return propagate_vals_across_arith_jfunc (cs,
2222 ipa_get_jf_pass_through_operation (jfunc),
2223 NULL_TREE,
2224 ipa_get_jf_pass_through_operand (jfunc),
2225 src_lat, dest_lat, -1, src_idx, parm_type);
2226 }
2227
2228 /* Propagate values through an ancestor jump function JFUNC associated with
2229 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2230 is the index of the source parameter. */
2231
2232 static bool
2233 propagate_vals_across_ancestor (struct cgraph_edge *cs,
2234 struct ipa_jump_func *jfunc,
2235 ipcp_lattice<tree> *src_lat,
2236 ipcp_lattice<tree> *dest_lat, int src_idx,
2237 tree param_type)
2238 {
2239 ipcp_value<tree> *src_val;
2240 bool ret = false;
2241
2242 if (ipa_edge_within_scc (cs))
2243 return dest_lat->set_contains_variable ();
2244
2245 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2246 {
2247 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
2248
2249 if (t && ipacp_value_safe_for_type (param_type, t))
2250 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
2251 else
2252 ret |= dest_lat->set_contains_variable ();
2253 }
2254
2255 return ret;
2256 }
2257
2258 /* Propagate scalar values across jump function JFUNC that is associated with
2259 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the
2260 parameter to which the result is passed. */
2261
2262 static bool
2263 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
2264 struct ipa_jump_func *jfunc,
2265 ipcp_lattice<tree> *dest_lat,
2266 tree param_type)
2267 {
2268 if (dest_lat->bottom)
2269 return false;
2270
2271 if (jfunc->type == IPA_JF_CONST)
2272 {
2273 tree val = ipa_get_jf_constant (jfunc);
2274 if (ipacp_value_safe_for_type (param_type, val))
2275 return dest_lat->add_value (val, cs, NULL, 0);
2276 else
2277 return dest_lat->set_contains_variable ();
2278 }
2279 else if (jfunc->type == IPA_JF_PASS_THROUGH
2280 || jfunc->type == IPA_JF_ANCESTOR)
2281 {
2282 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
2283 ipcp_lattice<tree> *src_lat;
2284 int src_idx;
2285 bool ret;
2286
2287 if (jfunc->type == IPA_JF_PASS_THROUGH)
2288 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2289 else
2290 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2291
2292 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
2293 if (src_lat->bottom)
2294 return dest_lat->set_contains_variable ();
2295
2296 /* If we would need to clone the caller and cannot, do not propagate. */
2297 if (!ipcp_versionable_function_p (cs->caller)
2298 && (src_lat->contains_variable
2299 || (src_lat->values_count > 1)))
2300 return dest_lat->set_contains_variable ();
2301
2302 if (jfunc->type == IPA_JF_PASS_THROUGH)
2303 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
2304 dest_lat, src_idx,
2305 param_type);
2306 else
2307 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
2308 src_idx, param_type);
2309
2310 if (src_lat->contains_variable)
2311 ret |= dest_lat->set_contains_variable ();
2312
2313 return ret;
2314 }
2315
2316 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
2317 use it for indirect inlining), we should propagate them too. */
2318 return dest_lat->set_contains_variable ();
2319 }
2320
2321 /* Propagate scalar values across jump function JFUNC that is associated with
2322 edge CS and describes argument IDX and put the values into DEST_LAT. */
2323
2324 static bool
2325 propagate_context_across_jump_function (cgraph_edge *cs,
2326 ipa_jump_func *jfunc, int idx,
2327 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
2328 {
2329 if (dest_lat->bottom)
2330 return false;
2331 ipa_edge_args *args = ipa_edge_args_sum->get (cs);
2332 bool ret = false;
2333 bool added_sth = false;
2334 bool type_preserved = true;
2335
2336 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
2337 = ipa_get_ith_polymorhic_call_context (args, idx);
2338
2339 if (edge_ctx_ptr)
2340 edge_ctx = *edge_ctx_ptr;
2341
2342 if (jfunc->type == IPA_JF_PASS_THROUGH
2343 || jfunc->type == IPA_JF_ANCESTOR)
2344 {
2345 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
2346 int src_idx;
2347 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
2348
2349 /* TODO: Once we figure out how to propagate speculations, it will
2350 probably be a good idea to switch to speculation if type_preserved is
2351 not set instead of punting. */
2352 if (jfunc->type == IPA_JF_PASS_THROUGH)
2353 {
2354 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
2355 goto prop_fail;
2356 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
2357 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2358 }
2359 else
2360 {
2361 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
2362 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2363 }
2364
2365 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
2366 /* If we would need to clone the caller and cannot, do not propagate. */
2367 if (!ipcp_versionable_function_p (cs->caller)
2368 && (src_lat->contains_variable
2369 || (src_lat->values_count > 1)))
2370 goto prop_fail;
2371
2372 ipcp_value<ipa_polymorphic_call_context> *src_val;
2373 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2374 {
2375 ipa_polymorphic_call_context cur = src_val->value;
2376
2377 if (!type_preserved)
2378 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
2379 if (jfunc->type == IPA_JF_ANCESTOR)
2380 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
2381 /* TODO: In cases we know how the context is going to be used,
2382 we can improve the result by passing proper OTR_TYPE. */
2383 cur.combine_with (edge_ctx);
2384 if (!cur.useless_p ())
2385 {
2386 if (src_lat->contains_variable
2387 && !edge_ctx.equal_to (cur))
2388 ret |= dest_lat->set_contains_variable ();
2389 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
2390 added_sth = true;
2391 }
2392 }
2393 }
2394
2395 prop_fail:
2396 if (!added_sth)
2397 {
2398 if (!edge_ctx.useless_p ())
2399 ret |= dest_lat->add_value (edge_ctx, cs);
2400 else
2401 ret |= dest_lat->set_contains_variable ();
2402 }
2403
2404 return ret;
2405 }
2406
2407 /* Propagate bits across jfunc that is associated with
2408 edge cs and update dest_lattice accordingly. */
2409
2410 bool
2411 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
2412 ipa_jump_func *jfunc,
2413 ipcp_bits_lattice *dest_lattice)
2414 {
2415 if (dest_lattice->bottom_p ())
2416 return false;
2417
2418 enum availability availability;
2419 cgraph_node *callee = cs->callee->function_symbol (&availability);
2420 ipa_node_params *callee_info = ipa_node_params_sum->get (callee);
2421 tree parm_type = ipa_get_type (callee_info, idx);
2422
2423 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the
2424 transform for these cases. Similarly, we can have bad type mismatches
2425 with LTO, avoid doing anything with those too. */
2426 if (!parm_type
2427 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type)))
2428 {
2429 if (dump_file && (dump_flags & TDF_DETAILS))
2430 fprintf (dump_file, "Setting dest_lattice to bottom, because type of "
2431 "param %i of %s is NULL or unsuitable for bits propagation\n",
2432 idx, cs->callee->dump_name ());
2433
2434 return dest_lattice->set_to_bottom ();
2435 }
2436
2437 unsigned precision = TYPE_PRECISION (parm_type);
2438 signop sgn = TYPE_SIGN (parm_type);
2439
2440 if (jfunc->type == IPA_JF_PASS_THROUGH
2441 || jfunc->type == IPA_JF_ANCESTOR)
2442 {
2443 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
2444 tree operand = NULL_TREE;
2445 enum tree_code code;
2446 unsigned src_idx;
2447 bool keep_null = false;
2448
2449 if (jfunc->type == IPA_JF_PASS_THROUGH)
2450 {
2451 code = ipa_get_jf_pass_through_operation (jfunc);
2452 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2453 if (code != NOP_EXPR)
2454 operand = ipa_get_jf_pass_through_operand (jfunc);
2455 }
2456 else
2457 {
2458 code = POINTER_PLUS_EXPR;
2459 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2460 unsigned HOST_WIDE_INT offset
2461 = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
2462 keep_null = (ipa_get_jf_ancestor_keep_null (jfunc) || !offset);
2463 operand = build_int_cstu (size_type_node, offset);
2464 }
2465
2466 class ipcp_param_lattices *src_lats
2467 = ipa_get_parm_lattices (caller_info, src_idx);
2468
2469 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
2470 for eg consider:
2471 int f(int x)
2472 {
2473 g (x & 0xff);
2474 }
2475 Assume lattice for x is bottom, however we can still propagate
2476 result of x & 0xff == 0xff, which gets computed during ccp1 pass
2477 and we store it in jump function during analysis stage. */
2478
2479 if (!src_lats->bits_lattice.bottom_p ())
2480 {
2481 bool drop_all_ones
2482 = keep_null && !src_lats->bits_lattice.known_nonzero_p ();
2483
2484 return dest_lattice->meet_with (src_lats->bits_lattice, precision,
2485 sgn, code, operand, drop_all_ones);
2486 }
2487 }
2488
2489 Value_Range vr (parm_type);
2490 if (jfunc->m_vr)
2491 {
2492 jfunc->m_vr->get_vrange (vr);
2493 if (!vr.undefined_p () && !vr.varying_p ())
2494 {
2495 irange_bitmask bm = vr.get_bitmask ();
2496 widest_int mask
2497 = widest_int::from (bm.mask (), TYPE_SIGN (parm_type));
2498 widest_int value
2499 = widest_int::from (bm.value (), TYPE_SIGN (parm_type));
2500 return dest_lattice->meet_with (value, mask, precision);
2501 }
2502 }
2503 return dest_lattice->set_to_bottom ();
2504 }
2505
2506 /* Propagate value range across jump function JFUNC that is associated with
2507 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
2508 accordingly. */
2509
2510 static bool
2511 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
2512 class ipcp_param_lattices *dest_plats,
2513 tree param_type)
2514 {
2515 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
2516
2517 if (dest_lat->bottom_p ())
2518 return false;
2519
2520 if (!param_type
2521 || (!INTEGRAL_TYPE_P (param_type)
2522 && !POINTER_TYPE_P (param_type)))
2523 return dest_lat->set_to_bottom ();
2524
2525 if (jfunc->type == IPA_JF_PASS_THROUGH)
2526 {
2527 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
2528 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
2529 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2530 class ipcp_param_lattices *src_lats
2531 = ipa_get_parm_lattices (caller_info, src_idx);
2532 tree operand_type = ipa_get_type (caller_info, src_idx);
2533
2534 if (src_lats->m_value_range.bottom_p ())
2535 return dest_lat->set_to_bottom ();
2536
2537 Value_Range vr (param_type);
2538 if (TREE_CODE_CLASS (operation) == tcc_unary)
2539 ipa_vr_operation_and_type_effects (vr,
2540 src_lats->m_value_range.m_vr,
2541 operation, param_type,
2542 operand_type);
2543 /* A crude way to prevent unbounded number of value range updates
2544 in SCC components. We should allow limited number of updates within
2545 SCC, too. */
2546 else if (!ipa_edge_within_scc (cs))
2547 {
2548 tree op = ipa_get_jf_pass_through_operand (jfunc);
2549 Value_Range op_vr (TREE_TYPE (op));
2550 Value_Range op_res (param_type);
2551 range_op_handler handler (operation);
2552
2553 ipa_range_set_and_normalize (op_vr, op);
2554
2555 if (!handler
2556 || !ipa_supports_p (operand_type)
2557 /* Sometimes we try to fold comparison operators using a
2558 pointer type to hold the result instead of a boolean
2559 type. Avoid trapping in the sanity check in
2560 fold_range until this is fixed. */
2561 || src_lats->m_value_range.m_vr.undefined_p ()
2562 || op_vr.undefined_p ()
2563 || !handler.operand_check_p (operand_type,
2564 src_lats->m_value_range.m_vr.type (),
2565 op_vr.type ())
2566 || !handler.fold_range (op_res, operand_type,
2567 src_lats->m_value_range.m_vr, op_vr))
2568 op_res.set_varying (param_type);
2569
2570 ipa_vr_operation_and_type_effects (vr,
2571 op_res,
2572 NOP_EXPR, param_type,
2573 operand_type);
2574 }
2575 if (!vr.undefined_p () && !vr.varying_p ())
2576 {
2577 if (jfunc->m_vr)
2578 {
2579 Value_Range jvr (param_type);
2580 if (ipa_vr_operation_and_type_effects (jvr, *jfunc->m_vr,
2581 NOP_EXPR,
2582 param_type,
2583 jfunc->m_vr->type ()))
2584 vr.intersect (jvr);
2585 }
2586 return dest_lat->meet_with (vr);
2587 }
2588 }
2589 else if (jfunc->type == IPA_JF_CONST)
2590 {
2591 tree val = ipa_get_jf_constant (jfunc);
2592 if (TREE_CODE (val) == INTEGER_CST)
2593 {
2594 val = fold_convert (param_type, val);
2595 if (TREE_OVERFLOW_P (val))
2596 val = drop_tree_overflow (val);
2597
2598 Value_Range tmpvr (val, val);
2599 return dest_lat->meet_with (tmpvr);
2600 }
2601 }
2602
2603 Value_Range vr (param_type);
2604 if (jfunc->m_vr
2605 && ipa_vr_operation_and_type_effects (vr, *jfunc->m_vr, NOP_EXPR,
2606 param_type,
2607 jfunc->m_vr->type ()))
2608 return dest_lat->meet_with (vr);
2609 else
2610 return dest_lat->set_to_bottom ();
2611 }
2612
2613 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
2614 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
2615 other cases, return false). If there are no aggregate items, set
2616 aggs_by_ref to NEW_AGGS_BY_REF. */
2617
2618 static bool
2619 set_check_aggs_by_ref (class ipcp_param_lattices *dest_plats,
2620 bool new_aggs_by_ref)
2621 {
2622 if (dest_plats->aggs)
2623 {
2624 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
2625 {
2626 set_agg_lats_to_bottom (dest_plats);
2627 return true;
2628 }
2629 }
2630 else
2631 dest_plats->aggs_by_ref = new_aggs_by_ref;
2632 return false;
2633 }
2634
2635 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
2636 already existing lattice for the given OFFSET and SIZE, marking all skipped
2637 lattices as containing variable and checking for overlaps. If there is no
2638 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
2639 it with offset, size and contains_variable to PRE_EXISTING, and return true,
2640 unless there are too many already. If there are two many, return false. If
2641 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
2642 skipped lattices were newly marked as containing variable, set *CHANGE to
2643 true. MAX_AGG_ITEMS is the maximum number of lattices. */
2644
2645 static bool
2646 merge_agg_lats_step (class ipcp_param_lattices *dest_plats,
2647 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
2648 struct ipcp_agg_lattice ***aglat,
2649 bool pre_existing, bool *change, int max_agg_items)
2650 {
2651 gcc_checking_assert (offset >= 0);
2652
2653 while (**aglat && (**aglat)->offset < offset)
2654 {
2655 if ((**aglat)->offset + (**aglat)->size > offset)
2656 {
2657 set_agg_lats_to_bottom (dest_plats);
2658 return false;
2659 }
2660 *change |= (**aglat)->set_contains_variable ();
2661 *aglat = &(**aglat)->next;
2662 }
2663
2664 if (**aglat && (**aglat)->offset == offset)
2665 {
2666 if ((**aglat)->size != val_size)
2667 {
2668 set_agg_lats_to_bottom (dest_plats);
2669 return false;
2670 }
2671 gcc_assert (!(**aglat)->next
2672 || (**aglat)->next->offset >= offset + val_size);
2673 return true;
2674 }
2675 else
2676 {
2677 struct ipcp_agg_lattice *new_al;
2678
2679 if (**aglat && (**aglat)->offset < offset + val_size)
2680 {
2681 set_agg_lats_to_bottom (dest_plats);
2682 return false;
2683 }
2684 if (dest_plats->aggs_count == max_agg_items)
2685 return false;
2686 dest_plats->aggs_count++;
2687 new_al = ipcp_agg_lattice_pool.allocate ();
2688
2689 new_al->offset = offset;
2690 new_al->size = val_size;
2691 new_al->contains_variable = pre_existing;
2692
2693 new_al->next = **aglat;
2694 **aglat = new_al;
2695 return true;
2696 }
2697 }
2698
2699 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2700 containing an unknown value. */
2701
2702 static bool
2703 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2704 {
2705 bool ret = false;
2706 while (aglat)
2707 {
2708 ret |= aglat->set_contains_variable ();
2709 aglat = aglat->next;
2710 }
2711 return ret;
2712 }
2713
2714 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2715 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2716 parameter used for lattice value sources. Return true if DEST_PLATS changed
2717 in any way. */
2718
2719 static bool
2720 merge_aggregate_lattices (struct cgraph_edge *cs,
2721 class ipcp_param_lattices *dest_plats,
2722 class ipcp_param_lattices *src_plats,
2723 int src_idx, HOST_WIDE_INT offset_delta)
2724 {
2725 bool pre_existing = dest_plats->aggs != NULL;
2726 struct ipcp_agg_lattice **dst_aglat;
2727 bool ret = false;
2728
2729 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2730 return true;
2731 if (src_plats->aggs_bottom)
2732 return set_agg_lats_contain_variable (dest_plats);
2733 if (src_plats->aggs_contain_variable)
2734 ret |= set_agg_lats_contain_variable (dest_plats);
2735 dst_aglat = &dest_plats->aggs;
2736
2737 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2738 param_ipa_max_agg_items);
2739 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2740 src_aglat;
2741 src_aglat = src_aglat->next)
2742 {
2743 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2744
2745 if (new_offset < 0)
2746 continue;
2747 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2748 &dst_aglat, pre_existing, &ret, max_agg_items))
2749 {
2750 struct ipcp_agg_lattice *new_al = *dst_aglat;
2751
2752 dst_aglat = &(*dst_aglat)->next;
2753 if (src_aglat->bottom)
2754 {
2755 ret |= new_al->set_contains_variable ();
2756 continue;
2757 }
2758 if (src_aglat->contains_variable)
2759 ret |= new_al->set_contains_variable ();
2760 for (ipcp_value<tree> *val = src_aglat->values;
2761 val;
2762 val = val->next)
2763 ret |= new_al->add_value (val->value, cs, val, src_idx,
2764 src_aglat->offset);
2765 }
2766 else if (dest_plats->aggs_bottom)
2767 return true;
2768 }
2769 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2770 return ret;
2771 }
2772
2773 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2774 pass-through JFUNC and if so, whether it has conform and conforms to the
2775 rules about propagating values passed by reference. */
2776
2777 static bool
2778 agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats,
2779 struct ipa_jump_func *jfunc)
2780 {
2781 return src_plats->aggs
2782 && (!src_plats->aggs_by_ref
2783 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2784 }
2785
2786 /* Propagate values through ITEM, jump function for a part of an aggregate,
2787 into corresponding aggregate lattice AGLAT. CS is the call graph edge
2788 associated with the jump function. Return true if AGLAT changed in any
2789 way. */
2790
2791 static bool
2792 propagate_aggregate_lattice (struct cgraph_edge *cs,
2793 struct ipa_agg_jf_item *item,
2794 struct ipcp_agg_lattice *aglat)
2795 {
2796 class ipa_node_params *caller_info;
2797 class ipcp_param_lattices *src_plats;
2798 struct ipcp_lattice<tree> *src_lat;
2799 HOST_WIDE_INT src_offset;
2800 int src_idx;
2801 tree load_type;
2802 bool ret;
2803
2804 if (item->jftype == IPA_JF_CONST)
2805 {
2806 tree value = item->value.constant;
2807
2808 gcc_checking_assert (is_gimple_ip_invariant (value));
2809 return aglat->add_value (value, cs, NULL, 0);
2810 }
2811
2812 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
2813 || item->jftype == IPA_JF_LOAD_AGG);
2814
2815 caller_info = ipa_node_params_sum->get (cs->caller);
2816 src_idx = item->value.pass_through.formal_id;
2817 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2818
2819 if (item->jftype == IPA_JF_PASS_THROUGH)
2820 {
2821 load_type = NULL_TREE;
2822 src_lat = &src_plats->itself;
2823 src_offset = -1;
2824 }
2825 else
2826 {
2827 HOST_WIDE_INT load_offset = item->value.load_agg.offset;
2828 struct ipcp_agg_lattice *src_aglat;
2829
2830 for (src_aglat = src_plats->aggs; src_aglat; src_aglat = src_aglat->next)
2831 if (src_aglat->offset >= load_offset)
2832 break;
2833
2834 load_type = item->value.load_agg.type;
2835 if (!src_aglat
2836 || src_aglat->offset > load_offset
2837 || src_aglat->size != tree_to_shwi (TYPE_SIZE (load_type))
2838 || src_plats->aggs_by_ref != item->value.load_agg.by_ref)
2839 return aglat->set_contains_variable ();
2840
2841 src_lat = src_aglat;
2842 src_offset = load_offset;
2843 }
2844
2845 if (src_lat->bottom
2846 || (!ipcp_versionable_function_p (cs->caller)
2847 && !src_lat->is_single_const ()))
2848 return aglat->set_contains_variable ();
2849
2850 ret = propagate_vals_across_arith_jfunc (cs,
2851 item->value.pass_through.operation,
2852 load_type,
2853 item->value.pass_through.operand,
2854 src_lat, aglat,
2855 src_offset,
2856 src_idx,
2857 item->type);
2858
2859 if (src_lat->contains_variable)
2860 ret |= aglat->set_contains_variable ();
2861
2862 return ret;
2863 }
2864
2865 /* Propagate scalar values across jump function JFUNC that is associated with
2866 edge CS and put the values into DEST_LAT. */
2867
2868 static bool
2869 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2870 struct ipa_jump_func *jfunc,
2871 class ipcp_param_lattices *dest_plats)
2872 {
2873 bool ret = false;
2874
2875 if (dest_plats->aggs_bottom)
2876 return false;
2877
2878 if (jfunc->type == IPA_JF_PASS_THROUGH
2879 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2880 {
2881 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
2882 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2883 class ipcp_param_lattices *src_plats;
2884
2885 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2886 if (agg_pass_through_permissible_p (src_plats, jfunc))
2887 {
2888 /* Currently we do not produce clobber aggregate jump
2889 functions, replace with merging when we do. */
2890 gcc_assert (!jfunc->agg.items);
2891 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2892 src_idx, 0);
2893 return ret;
2894 }
2895 }
2896 else if (jfunc->type == IPA_JF_ANCESTOR
2897 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2898 {
2899 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
2900 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2901 class ipcp_param_lattices *src_plats;
2902
2903 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2904 if (src_plats->aggs && src_plats->aggs_by_ref)
2905 {
2906 /* Currently we do not produce clobber aggregate jump
2907 functions, replace with merging when we do. */
2908 gcc_assert (!jfunc->agg.items);
2909 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2910 ipa_get_jf_ancestor_offset (jfunc));
2911 }
2912 else if (!src_plats->aggs_by_ref)
2913 ret |= set_agg_lats_to_bottom (dest_plats);
2914 else
2915 ret |= set_agg_lats_contain_variable (dest_plats);
2916 return ret;
2917 }
2918
2919 if (jfunc->agg.items)
2920 {
2921 bool pre_existing = dest_plats->aggs != NULL;
2922 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2923 struct ipa_agg_jf_item *item;
2924 int i;
2925
2926 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2927 return true;
2928
2929 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2930 param_ipa_max_agg_items);
2931 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2932 {
2933 HOST_WIDE_INT val_size;
2934
2935 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN)
2936 continue;
2937 val_size = tree_to_shwi (TYPE_SIZE (item->type));
2938
2939 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2940 &aglat, pre_existing, &ret, max_agg_items))
2941 {
2942 ret |= propagate_aggregate_lattice (cs, item, *aglat);
2943 aglat = &(*aglat)->next;
2944 }
2945 else if (dest_plats->aggs_bottom)
2946 return true;
2947 }
2948
2949 ret |= set_chain_of_aglats_contains_variable (*aglat);
2950 }
2951 else
2952 ret |= set_agg_lats_contain_variable (dest_plats);
2953
2954 return ret;
2955 }
2956
2957 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2958 non-thunk) destination, the call passes through a thunk. */
2959
2960 static bool
2961 call_passes_through_thunk (cgraph_edge *cs)
2962 {
2963 cgraph_node *alias_or_thunk = cs->callee;
2964 while (alias_or_thunk->alias)
2965 alias_or_thunk = alias_or_thunk->get_alias_target ();
2966 return alias_or_thunk->thunk;
2967 }
2968
2969 /* Propagate constants from the caller to the callee of CS. INFO describes the
2970 caller. */
2971
2972 static bool
2973 propagate_constants_across_call (struct cgraph_edge *cs)
2974 {
2975 class ipa_node_params *callee_info;
2976 enum availability availability;
2977 cgraph_node *callee;
2978 class ipa_edge_args *args;
2979 bool ret = false;
2980 int i, args_count, parms_count;
2981
2982 callee = cs->callee->function_symbol (&availability);
2983 if (!callee->definition)
2984 return false;
2985 gcc_checking_assert (callee->has_gimple_body_p ());
2986 callee_info = ipa_node_params_sum->get (callee);
2987 if (!callee_info)
2988 return false;
2989
2990 args = ipa_edge_args_sum->get (cs);
2991 parms_count = ipa_get_param_count (callee_info);
2992 if (parms_count == 0)
2993 return false;
2994 if (!args
2995 || !opt_for_fn (cs->caller->decl, flag_ipa_cp)
2996 || !opt_for_fn (cs->caller->decl, optimize))
2997 {
2998 for (i = 0; i < parms_count; i++)
2999 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
3000 i));
3001 return ret;
3002 }
3003 args_count = ipa_get_cs_argument_count (args);
3004
3005 /* If this call goes through a thunk we must not propagate to the first (0th)
3006 parameter. However, we might need to uncover a thunk from below a series
3007 of aliases first. */
3008 if (call_passes_through_thunk (cs))
3009 {
3010 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
3011 0));
3012 i = 1;
3013 }
3014 else
3015 i = 0;
3016
3017 for (; (i < args_count) && (i < parms_count); i++)
3018 {
3019 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
3020 class ipcp_param_lattices *dest_plats;
3021 tree param_type = ipa_get_type (callee_info, i);
3022
3023 dest_plats = ipa_get_parm_lattices (callee_info, i);
3024 if (availability == AVAIL_INTERPOSABLE)
3025 ret |= set_all_contains_variable (dest_plats);
3026 else
3027 {
3028 ret |= propagate_scalar_across_jump_function (cs, jump_func,
3029 &dest_plats->itself,
3030 param_type);
3031 ret |= propagate_context_across_jump_function (cs, jump_func, i,
3032 &dest_plats->ctxlat);
3033 ret
3034 |= propagate_bits_across_jump_function (cs, i, jump_func,
3035 &dest_plats->bits_lattice);
3036 ret |= propagate_aggs_across_jump_function (cs, jump_func,
3037 dest_plats);
3038 if (opt_for_fn (callee->decl, flag_ipa_vrp))
3039 ret |= propagate_vr_across_jump_function (cs, jump_func,
3040 dest_plats, param_type);
3041 else
3042 ret |= dest_plats->m_value_range.set_to_bottom ();
3043 }
3044 }
3045 for (; i < parms_count; i++)
3046 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
3047
3048 return ret;
3049 }
3050
3051 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
3052 KNOWN_CONTEXTS, and known aggregates either in AVS or KNOWN_AGGS return
3053 the destination. The latter three can be NULL. If AGG_REPS is not NULL,
3054 KNOWN_AGGS is ignored. */
3055
3056 static tree
3057 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
3058 const vec<tree> &known_csts,
3059 const vec<ipa_polymorphic_call_context> &known_contexts,
3060 const ipa_argagg_value_list &avs,
3061 bool *speculative)
3062 {
3063 int param_index = ie->indirect_info->param_index;
3064 HOST_WIDE_INT anc_offset;
3065 tree t = NULL;
3066 tree target = NULL;
3067
3068 *speculative = false;
3069
3070 if (param_index == -1)
3071 return NULL_TREE;
3072
3073 if (!ie->indirect_info->polymorphic)
3074 {
3075 tree t = NULL;
3076
3077 if (ie->indirect_info->agg_contents)
3078 {
3079 t = NULL;
3080 if ((unsigned) param_index < known_csts.length ()
3081 && known_csts[param_index])
3082 t = ipa_find_agg_cst_from_init (known_csts[param_index],
3083 ie->indirect_info->offset,
3084 ie->indirect_info->by_ref);
3085
3086 if (!t && ie->indirect_info->guaranteed_unmodified)
3087 t = avs.get_value (param_index,
3088 ie->indirect_info->offset / BITS_PER_UNIT,
3089 ie->indirect_info->by_ref);
3090 }
3091 else if ((unsigned) param_index < known_csts.length ())
3092 t = known_csts[param_index];
3093
3094 if (t
3095 && TREE_CODE (t) == ADDR_EXPR
3096 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
3097 return TREE_OPERAND (t, 0);
3098 else
3099 return NULL_TREE;
3100 }
3101
3102 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
3103 return NULL_TREE;
3104
3105 gcc_assert (!ie->indirect_info->agg_contents);
3106 gcc_assert (!ie->indirect_info->by_ref);
3107 anc_offset = ie->indirect_info->offset;
3108
3109 t = NULL;
3110
3111 if ((unsigned) param_index < known_csts.length ()
3112 && known_csts[param_index])
3113 t = ipa_find_agg_cst_from_init (known_csts[param_index],
3114 ie->indirect_info->offset, true);
3115
3116 /* Try to work out value of virtual table pointer value in replacements. */
3117 /* or known aggregate values. */
3118 if (!t)
3119 t = avs.get_value (param_index,
3120 ie->indirect_info->offset / BITS_PER_UNIT,
3121 true);
3122
3123 /* If we found the virtual table pointer, lookup the target. */
3124 if (t)
3125 {
3126 tree vtable;
3127 unsigned HOST_WIDE_INT offset;
3128 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
3129 {
3130 bool can_refer;
3131 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
3132 vtable, offset, &can_refer);
3133 if (can_refer)
3134 {
3135 if (!target
3136 || fndecl_built_in_p (target, BUILT_IN_UNREACHABLE)
3137 || !possible_polymorphic_call_target_p
3138 (ie, cgraph_node::get (target)))
3139 {
3140 /* Do not speculate builtin_unreachable, it is stupid! */
3141 if (ie->indirect_info->vptr_changed)
3142 return NULL;
3143 target = ipa_impossible_devirt_target (ie, target);
3144 }
3145 *speculative = ie->indirect_info->vptr_changed;
3146 if (!*speculative)
3147 return target;
3148 }
3149 }
3150 }
3151
3152 /* Do we know the constant value of pointer? */
3153 if (!t && (unsigned) param_index < known_csts.length ())
3154 t = known_csts[param_index];
3155
3156 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
3157
3158 ipa_polymorphic_call_context context;
3159 if (known_contexts.length () > (unsigned int) param_index)
3160 {
3161 context = known_contexts[param_index];
3162 context.offset_by (anc_offset);
3163 if (ie->indirect_info->vptr_changed)
3164 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
3165 ie->indirect_info->otr_type);
3166 if (t)
3167 {
3168 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
3169 (t, ie->indirect_info->otr_type, anc_offset);
3170 if (!ctx2.useless_p ())
3171 context.combine_with (ctx2, ie->indirect_info->otr_type);
3172 }
3173 }
3174 else if (t)
3175 {
3176 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
3177 anc_offset);
3178 if (ie->indirect_info->vptr_changed)
3179 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
3180 ie->indirect_info->otr_type);
3181 }
3182 else
3183 return NULL_TREE;
3184
3185 vec <cgraph_node *>targets;
3186 bool final;
3187
3188 targets = possible_polymorphic_call_targets
3189 (ie->indirect_info->otr_type,
3190 ie->indirect_info->otr_token,
3191 context, &final);
3192 if (!final || targets.length () > 1)
3193 {
3194 struct cgraph_node *node;
3195 if (*speculative)
3196 return target;
3197 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
3198 || ie->speculative || !ie->maybe_hot_p ())
3199 return NULL;
3200 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
3201 ie->indirect_info->otr_token,
3202 context);
3203 if (node)
3204 {
3205 *speculative = true;
3206 target = node->decl;
3207 }
3208 else
3209 return NULL;
3210 }
3211 else
3212 {
3213 *speculative = false;
3214 if (targets.length () == 1)
3215 target = targets[0]->decl;
3216 else
3217 target = ipa_impossible_devirt_target (ie, NULL_TREE);
3218 }
3219
3220 if (target && !possible_polymorphic_call_target_p (ie,
3221 cgraph_node::get (target)))
3222 {
3223 if (*speculative)
3224 return NULL;
3225 target = ipa_impossible_devirt_target (ie, target);
3226 }
3227
3228 return target;
3229 }
3230
3231 /* If an indirect edge IE can be turned into a direct one based on data in
3232 AVALS, return the destination. Store into *SPECULATIVE a boolean determinig
3233 whether the discovered target is only speculative guess. */
3234
3235 tree
3236 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
3237 ipa_call_arg_values *avals,
3238 bool *speculative)
3239 {
3240 ipa_argagg_value_list avl (avals);
3241 return ipa_get_indirect_edge_target_1 (ie, avals->m_known_vals,
3242 avals->m_known_contexts,
3243 avl, speculative);
3244 }
3245
3246 /* Calculate devirtualization time bonus for NODE, assuming we know information
3247 about arguments stored in AVALS. */
3248
3249 static int
3250 devirtualization_time_bonus (struct cgraph_node *node,
3251 ipa_auto_call_arg_values *avals)
3252 {
3253 struct cgraph_edge *ie;
3254 int res = 0;
3255
3256 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
3257 {
3258 struct cgraph_node *callee;
3259 class ipa_fn_summary *isummary;
3260 enum availability avail;
3261 tree target;
3262 bool speculative;
3263
3264 ipa_argagg_value_list avl (avals);
3265 target = ipa_get_indirect_edge_target_1 (ie, avals->m_known_vals,
3266 avals->m_known_contexts,
3267 avl, &speculative);
3268 if (!target)
3269 continue;
3270
3271 /* Only bare minimum benefit for clearly un-inlineable targets. */
3272 res += 1;
3273 callee = cgraph_node::get (target);
3274 if (!callee || !callee->definition)
3275 continue;
3276 callee = callee->function_symbol (&avail);
3277 if (avail < AVAIL_AVAILABLE)
3278 continue;
3279 isummary = ipa_fn_summaries->get (callee);
3280 if (!isummary || !isummary->inlinable)
3281 continue;
3282
3283 int size = ipa_size_summaries->get (callee)->size;
3284 /* FIXME: The values below need re-considering and perhaps also
3285 integrating into the cost metrics, at lest in some very basic way. */
3286 int max_inline_insns_auto
3287 = opt_for_fn (callee->decl, param_max_inline_insns_auto);
3288 if (size <= max_inline_insns_auto / 4)
3289 res += 31 / ((int)speculative + 1);
3290 else if (size <= max_inline_insns_auto / 2)
3291 res += 15 / ((int)speculative + 1);
3292 else if (size <= max_inline_insns_auto
3293 || DECL_DECLARED_INLINE_P (callee->decl))
3294 res += 7 / ((int)speculative + 1);
3295 }
3296
3297 return res;
3298 }
3299
3300 /* Return time bonus incurred because of hints stored in ESTIMATES. */
3301
3302 static int
3303 hint_time_bonus (cgraph_node *node, const ipa_call_estimates &estimates)
3304 {
3305 int result = 0;
3306 ipa_hints hints = estimates.hints;
3307 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
3308 result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
3309
3310 sreal bonus_for_one = opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
3311
3312 if (hints & INLINE_HINT_loop_iterations)
3313 result += (estimates.loops_with_known_iterations * bonus_for_one).to_int ();
3314
3315 if (hints & INLINE_HINT_loop_stride)
3316 result += (estimates.loops_with_known_strides * bonus_for_one).to_int ();
3317
3318 return result;
3319 }
3320
3321 /* If there is a reason to penalize the function described by INFO in the
3322 cloning goodness evaluation, do so. */
3323
3324 static inline sreal
3325 incorporate_penalties (cgraph_node *node, ipa_node_params *info,
3326 sreal evaluation)
3327 {
3328 if (info->node_within_scc && !info->node_is_self_scc)
3329 evaluation = (evaluation
3330 * (100 - opt_for_fn (node->decl,
3331 param_ipa_cp_recursion_penalty))) / 100;
3332
3333 if (info->node_calling_single_call)
3334 evaluation = (evaluation
3335 * (100 - opt_for_fn (node->decl,
3336 param_ipa_cp_single_call_penalty)))
3337 / 100;
3338
3339 return evaluation;
3340 }
3341
3342 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
3343 and SIZE_COST and with the sum of frequencies of incoming edges to the
3344 potential new clone in FREQUENCIES. */
3345
3346 static bool
3347 good_cloning_opportunity_p (struct cgraph_node *node, sreal time_benefit,
3348 sreal freq_sum, profile_count count_sum,
3349 int size_cost)
3350 {
3351 if (time_benefit == 0
3352 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
3353 || node->optimize_for_size_p ())
3354 return false;
3355
3356 gcc_assert (size_cost > 0);
3357
3358 ipa_node_params *info = ipa_node_params_sum->get (node);
3359 int eval_threshold = opt_for_fn (node->decl, param_ipa_cp_eval_threshold);
3360 if (count_sum.nonzero_p ())
3361 {
3362 gcc_assert (base_count.nonzero_p ());
3363 sreal factor = count_sum.probability_in (base_count).to_sreal ();
3364 sreal evaluation = (time_benefit * factor) / size_cost;
3365 evaluation = incorporate_penalties (node, info, evaluation);
3366 evaluation *= 1000;
3367
3368 if (dump_file && (dump_flags & TDF_DETAILS))
3369 {
3370 fprintf (dump_file, " good_cloning_opportunity_p (time: %g, "
3371 "size: %i, count_sum: ", time_benefit.to_double (),
3372 size_cost);
3373 count_sum.dump (dump_file);
3374 fprintf (dump_file, "%s%s) -> evaluation: %.2f, threshold: %i\n",
3375 info->node_within_scc
3376 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3377 info->node_calling_single_call ? ", single_call" : "",
3378 evaluation.to_double (), eval_threshold);
3379 }
3380
3381 return evaluation.to_int () >= eval_threshold;
3382 }
3383 else
3384 {
3385 sreal evaluation = (time_benefit * freq_sum) / size_cost;
3386 evaluation = incorporate_penalties (node, info, evaluation);
3387 evaluation *= 1000;
3388
3389 if (dump_file && (dump_flags & TDF_DETAILS))
3390 fprintf (dump_file, " good_cloning_opportunity_p (time: %g, "
3391 "size: %i, freq_sum: %g%s%s) -> evaluation: %.2f, "
3392 "threshold: %i\n",
3393 time_benefit.to_double (), size_cost, freq_sum.to_double (),
3394 info->node_within_scc
3395 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3396 info->node_calling_single_call ? ", single_call" : "",
3397 evaluation.to_double (), eval_threshold);
3398
3399 return evaluation.to_int () >= eval_threshold;
3400 }
3401 }
3402
3403 /* Grow vectors in AVALS and fill them with information about values of
3404 parameters that are known to be independent of the context. Only calculate
3405 m_known_aggs if CALCULATE_AGGS is true. INFO describes the function. If
3406 REMOVABLE_PARAMS_COST is non-NULL, the movement cost of all removable
3407 parameters will be stored in it.
3408
3409 TODO: Also grow context independent value range vectors. */
3410
3411 static bool
3412 gather_context_independent_values (class ipa_node_params *info,
3413 ipa_auto_call_arg_values *avals,
3414 bool calculate_aggs,
3415 int *removable_params_cost)
3416 {
3417 int i, count = ipa_get_param_count (info);
3418 bool ret = false;
3419
3420 avals->m_known_vals.safe_grow_cleared (count, true);
3421 avals->m_known_contexts.safe_grow_cleared (count, true);
3422
3423 if (removable_params_cost)
3424 *removable_params_cost = 0;
3425
3426 for (i = 0; i < count; i++)
3427 {
3428 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3429 ipcp_lattice<tree> *lat = &plats->itself;
3430
3431 if (lat->is_single_const ())
3432 {
3433 ipcp_value<tree> *val = lat->values;
3434 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3435 avals->m_known_vals[i] = val->value;
3436 if (removable_params_cost)
3437 *removable_params_cost
3438 += estimate_move_cost (TREE_TYPE (val->value), false);
3439 ret = true;
3440 }
3441 else if (removable_params_cost
3442 && !ipa_is_param_used (info, i))
3443 *removable_params_cost
3444 += ipa_get_param_move_cost (info, i);
3445
3446 if (!ipa_is_param_used (info, i))
3447 continue;
3448
3449 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3450 /* Do not account known context as reason for cloning. We can see
3451 if it permits devirtualization. */
3452 if (ctxlat->is_single_const ())
3453 avals->m_known_contexts[i] = ctxlat->values->value;
3454
3455 if (calculate_aggs)
3456 ret |= push_agg_values_from_plats (plats, i, 0, &avals->m_known_aggs);
3457 }
3458
3459 return ret;
3460 }
3461
3462 /* Perform time and size measurement of NODE with the context given in AVALS,
3463 calculate the benefit compared to the node without specialization and store
3464 it into VAL. Take into account REMOVABLE_PARAMS_COST of all
3465 context-independent or unused removable parameters and EST_MOVE_COST, the
3466 estimated movement of the considered parameter. */
3467
3468 static void
3469 perform_estimation_of_a_value (cgraph_node *node,
3470 ipa_auto_call_arg_values *avals,
3471 int removable_params_cost, int est_move_cost,
3472 ipcp_value_base *val)
3473 {
3474 sreal time_benefit;
3475 ipa_call_estimates estimates;
3476
3477 estimate_ipcp_clone_size_and_time (node, avals, &estimates);
3478
3479 /* Extern inline functions have no cloning local time benefits because they
3480 will be inlined anyway. The only reason to clone them is if it enables
3481 optimization in any of the functions they call. */
3482 if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl))
3483 time_benefit = 0;
3484 else
3485 time_benefit = (estimates.nonspecialized_time - estimates.time)
3486 + (devirtualization_time_bonus (node, avals)
3487 + hint_time_bonus (node, estimates)
3488 + removable_params_cost + est_move_cost);
3489
3490 int size = estimates.size;
3491 gcc_checking_assert (size >=0);
3492 /* The inliner-heuristics based estimates may think that in certain
3493 contexts some functions do not have any size at all but we want
3494 all specializations to have at least a tiny cost, not least not to
3495 divide by zero. */
3496 if (size == 0)
3497 size = 1;
3498
3499 val->local_time_benefit = time_benefit;
3500 val->local_size_cost = size;
3501 }
3502
3503 /* Get the overall limit oof growth based on parameters extracted from growth.
3504 it does not really make sense to mix functions with different overall growth
3505 limits but it is possible and if it happens, we do not want to select one
3506 limit at random. */
3507
3508 static long
3509 get_max_overall_size (cgraph_node *node)
3510 {
3511 long max_new_size = orig_overall_size;
3512 long large_unit = opt_for_fn (node->decl, param_ipa_cp_large_unit_insns);
3513 if (max_new_size < large_unit)
3514 max_new_size = large_unit;
3515 int unit_growth = opt_for_fn (node->decl, param_ipa_cp_unit_growth);
3516 max_new_size += max_new_size * unit_growth / 100 + 1;
3517 return max_new_size;
3518 }
3519
3520 /* Return true if NODE should be cloned just for a parameter removal, possibly
3521 dumping a reason if not. */
3522
3523 static bool
3524 clone_for_param_removal_p (cgraph_node *node)
3525 {
3526 if (!node->can_change_signature)
3527 {
3528 if (dump_file && (dump_flags & TDF_DETAILS))
3529 fprintf (dump_file, " Not considering cloning to remove parameters, "
3530 "function cannot change signature.\n");
3531 return false;
3532 }
3533 if (node->can_be_local_p ())
3534 {
3535 if (dump_file && (dump_flags & TDF_DETAILS))
3536 fprintf (dump_file, " Not considering cloning to remove parameters, "
3537 "IPA-SRA can do it potentially better.\n");
3538 return false;
3539 }
3540 return true;
3541 }
3542
3543 /* Iterate over known values of parameters of NODE and estimate the local
3544 effects in terms of time and size they have. */
3545
3546 static void
3547 estimate_local_effects (struct cgraph_node *node)
3548 {
3549 ipa_node_params *info = ipa_node_params_sum->get (node);
3550 int count = ipa_get_param_count (info);
3551 bool always_const;
3552 int removable_params_cost;
3553
3554 if (!count || !ipcp_versionable_function_p (node))
3555 return;
3556
3557 if (dump_file && (dump_flags & TDF_DETAILS))
3558 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
3559
3560 ipa_auto_call_arg_values avals;
3561 always_const = gather_context_independent_values (info, &avals, true,
3562 &removable_params_cost);
3563 int devirt_bonus = devirtualization_time_bonus (node, &avals);
3564 if (always_const || devirt_bonus
3565 || (removable_params_cost && clone_for_param_removal_p (node)))
3566 {
3567 struct caller_statistics stats;
3568 ipa_call_estimates estimates;
3569
3570 init_caller_stats (&stats);
3571 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3572 false);
3573 estimate_ipcp_clone_size_and_time (node, &avals, &estimates);
3574 sreal time = estimates.nonspecialized_time - estimates.time;
3575 time += devirt_bonus;
3576 time += hint_time_bonus (node, estimates);
3577 time += removable_params_cost;
3578 int size = estimates.size - stats.n_calls * removable_params_cost;
3579
3580 if (dump_file)
3581 fprintf (dump_file, " - context independent values, size: %i, "
3582 "time_benefit: %f\n", size, (time).to_double ());
3583
3584 if (size <= 0 || node->local)
3585 {
3586 info->do_clone_for_all_contexts = true;
3587
3588 if (dump_file)
3589 fprintf (dump_file, " Decided to specialize for all "
3590 "known contexts, code not going to grow.\n");
3591 }
3592 else if (good_cloning_opportunity_p (node, time, stats.freq_sum,
3593 stats.count_sum, size))
3594 {
3595 if (size + overall_size <= get_max_overall_size (node))
3596 {
3597 info->do_clone_for_all_contexts = true;
3598 overall_size += size;
3599
3600 if (dump_file)
3601 fprintf (dump_file, " Decided to specialize for all "
3602 "known contexts, growth (to %li) deemed "
3603 "beneficial.\n", overall_size);
3604 }
3605 else if (dump_file && (dump_flags & TDF_DETAILS))
3606 fprintf (dump_file, " Not cloning for all contexts because "
3607 "maximum unit size would be reached with %li.\n",
3608 size + overall_size);
3609 }
3610 else if (dump_file && (dump_flags & TDF_DETAILS))
3611 fprintf (dump_file, " Not cloning for all contexts because "
3612 "!good_cloning_opportunity_p.\n");
3613
3614 }
3615
3616 for (int i = 0; i < count; i++)
3617 {
3618 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3619 ipcp_lattice<tree> *lat = &plats->itself;
3620 ipcp_value<tree> *val;
3621
3622 if (lat->bottom
3623 || !lat->values
3624 || avals.m_known_vals[i])
3625 continue;
3626
3627 for (val = lat->values; val; val = val->next)
3628 {
3629 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3630 avals.m_known_vals[i] = val->value;
3631
3632 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
3633 perform_estimation_of_a_value (node, &avals, removable_params_cost,
3634 emc, val);
3635
3636 if (dump_file && (dump_flags & TDF_DETAILS))
3637 {
3638 fprintf (dump_file, " - estimates for value ");
3639 print_ipcp_constant_value (dump_file, val->value);
3640 fprintf (dump_file, " for ");
3641 ipa_dump_param (dump_file, info, i);
3642 fprintf (dump_file, ": time_benefit: %g, size: %i\n",
3643 val->local_time_benefit.to_double (),
3644 val->local_size_cost);
3645 }
3646 }
3647 avals.m_known_vals[i] = NULL_TREE;
3648 }
3649
3650 for (int i = 0; i < count; i++)
3651 {
3652 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3653
3654 if (!plats->virt_call)
3655 continue;
3656
3657 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3658 ipcp_value<ipa_polymorphic_call_context> *val;
3659
3660 if (ctxlat->bottom
3661 || !ctxlat->values
3662 || !avals.m_known_contexts[i].useless_p ())
3663 continue;
3664
3665 for (val = ctxlat->values; val; val = val->next)
3666 {
3667 avals.m_known_contexts[i] = val->value;
3668 perform_estimation_of_a_value (node, &avals, removable_params_cost,
3669 0, val);
3670
3671 if (dump_file && (dump_flags & TDF_DETAILS))
3672 {
3673 fprintf (dump_file, " - estimates for polymorphic context ");
3674 print_ipcp_constant_value (dump_file, val->value);
3675 fprintf (dump_file, " for ");
3676 ipa_dump_param (dump_file, info, i);
3677 fprintf (dump_file, ": time_benefit: %g, size: %i\n",
3678 val->local_time_benefit.to_double (),
3679 val->local_size_cost);
3680 }
3681 }
3682 avals.m_known_contexts[i] = ipa_polymorphic_call_context ();
3683 }
3684
3685 unsigned all_ctx_len = avals.m_known_aggs.length ();
3686 auto_vec<ipa_argagg_value, 32> all_ctx;
3687 all_ctx.reserve_exact (all_ctx_len);
3688 all_ctx.splice (avals.m_known_aggs);
3689 avals.m_known_aggs.safe_grow_cleared (all_ctx_len + 1);
3690
3691 unsigned j = 0;
3692 for (int index = 0; index < count; index++)
3693 {
3694 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, index);
3695
3696 if (plats->aggs_bottom || !plats->aggs)
3697 continue;
3698
3699 for (ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3700 {
3701 ipcp_value<tree> *val;
3702 if (aglat->bottom || !aglat->values
3703 /* If the following is true, the one value is already part of all
3704 context estimations. */
3705 || (!plats->aggs_contain_variable
3706 && aglat->is_single_const ()))
3707 continue;
3708
3709 unsigned unit_offset = aglat->offset / BITS_PER_UNIT;
3710 while (j < all_ctx_len
3711 && (all_ctx[j].index < index
3712 || (all_ctx[j].index == index
3713 && all_ctx[j].unit_offset < unit_offset)))
3714 {
3715 avals.m_known_aggs[j] = all_ctx[j];
3716 j++;
3717 }
3718
3719 for (unsigned k = j; k < all_ctx_len; k++)
3720 avals.m_known_aggs[k+1] = all_ctx[k];
3721
3722 for (val = aglat->values; val; val = val->next)
3723 {
3724 avals.m_known_aggs[j].value = val->value;
3725 avals.m_known_aggs[j].unit_offset = unit_offset;
3726 avals.m_known_aggs[j].index = index;
3727 avals.m_known_aggs[j].by_ref = plats->aggs_by_ref;
3728 avals.m_known_aggs[j].killed = false;
3729
3730 perform_estimation_of_a_value (node, &avals,
3731 removable_params_cost, 0, val);
3732
3733 if (dump_file && (dump_flags & TDF_DETAILS))
3734 {
3735 fprintf (dump_file, " - estimates for value ");
3736 print_ipcp_constant_value (dump_file, val->value);
3737 fprintf (dump_file, " for ");
3738 ipa_dump_param (dump_file, info, index);
3739 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3740 "]: time_benefit: %g, size: %i\n",
3741 plats->aggs_by_ref ? "ref " : "",
3742 aglat->offset,
3743 val->local_time_benefit.to_double (),
3744 val->local_size_cost);
3745 }
3746 }
3747 }
3748 }
3749 }
3750
3751
3752 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3753 topological sort of values. */
3754
3755 template <typename valtype>
3756 void
3757 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3758 {
3759 ipcp_value_source<valtype> *src;
3760
3761 if (cur_val->dfs)
3762 return;
3763
3764 dfs_counter++;
3765 cur_val->dfs = dfs_counter;
3766 cur_val->low_link = dfs_counter;
3767
3768 cur_val->topo_next = stack;
3769 stack = cur_val;
3770 cur_val->on_stack = true;
3771
3772 for (src = cur_val->sources; src; src = src->next)
3773 if (src->val)
3774 {
3775 if (src->val->dfs == 0)
3776 {
3777 add_val (src->val);
3778 if (src->val->low_link < cur_val->low_link)
3779 cur_val->low_link = src->val->low_link;
3780 }
3781 else if (src->val->on_stack
3782 && src->val->dfs < cur_val->low_link)
3783 cur_val->low_link = src->val->dfs;
3784 }
3785
3786 if (cur_val->dfs == cur_val->low_link)
3787 {
3788 ipcp_value<valtype> *v, *scc_list = NULL;
3789
3790 do
3791 {
3792 v = stack;
3793 stack = v->topo_next;
3794 v->on_stack = false;
3795 v->scc_no = cur_val->dfs;
3796
3797 v->scc_next = scc_list;
3798 scc_list = v;
3799 }
3800 while (v != cur_val);
3801
3802 cur_val->topo_next = values_topo;
3803 values_topo = cur_val;
3804 }
3805 }
3806
3807 /* Add all values in lattices associated with NODE to the topological sort if
3808 they are not there yet. */
3809
3810 static void
3811 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3812 {
3813 ipa_node_params *info = ipa_node_params_sum->get (node);
3814 int i, count = ipa_get_param_count (info);
3815
3816 for (i = 0; i < count; i++)
3817 {
3818 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3819 ipcp_lattice<tree> *lat = &plats->itself;
3820 struct ipcp_agg_lattice *aglat;
3821
3822 if (!lat->bottom)
3823 {
3824 ipcp_value<tree> *val;
3825 for (val = lat->values; val; val = val->next)
3826 topo->constants.add_val (val);
3827 }
3828
3829 if (!plats->aggs_bottom)
3830 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3831 if (!aglat->bottom)
3832 {
3833 ipcp_value<tree> *val;
3834 for (val = aglat->values; val; val = val->next)
3835 topo->constants.add_val (val);
3836 }
3837
3838 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3839 if (!ctxlat->bottom)
3840 {
3841 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3842 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3843 topo->contexts.add_val (ctxval);
3844 }
3845 }
3846 }
3847
3848 /* One pass of constants propagation along the call graph edges, from callers
3849 to callees (requires topological ordering in TOPO), iterate over strongly
3850 connected components. */
3851
3852 static void
3853 propagate_constants_topo (class ipa_topo_info *topo)
3854 {
3855 int i;
3856
3857 for (i = topo->nnodes - 1; i >= 0; i--)
3858 {
3859 unsigned j;
3860 struct cgraph_node *v, *node = topo->order[i];
3861 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3862
3863 /* First, iteratively propagate within the strongly connected component
3864 until all lattices stabilize. */
3865 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3866 if (v->has_gimple_body_p ())
3867 {
3868 if (opt_for_fn (v->decl, flag_ipa_cp)
3869 && opt_for_fn (v->decl, optimize))
3870 push_node_to_stack (topo, v);
3871 /* When V is not optimized, we can not push it to stack, but
3872 still we need to set all its callees lattices to bottom. */
3873 else
3874 {
3875 for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
3876 propagate_constants_across_call (cs);
3877 }
3878 }
3879
3880 v = pop_node_from_stack (topo);
3881 while (v)
3882 {
3883 struct cgraph_edge *cs;
3884 class ipa_node_params *info = NULL;
3885 bool self_scc = true;
3886
3887 for (cs = v->callees; cs; cs = cs->next_callee)
3888 if (ipa_edge_within_scc (cs))
3889 {
3890 cgraph_node *callee = cs->callee->function_symbol ();
3891
3892 if (v != callee)
3893 self_scc = false;
3894
3895 if (!info)
3896 {
3897 info = ipa_node_params_sum->get (v);
3898 info->node_within_scc = true;
3899 }
3900
3901 if (propagate_constants_across_call (cs))
3902 push_node_to_stack (topo, callee);
3903 }
3904
3905 if (info)
3906 info->node_is_self_scc = self_scc;
3907
3908 v = pop_node_from_stack (topo);
3909 }
3910
3911 /* Afterwards, propagate along edges leading out of the SCC, calculates
3912 the local effects of the discovered constants and all valid values to
3913 their topological sort. */
3914 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3915 if (v->has_gimple_body_p ()
3916 && opt_for_fn (v->decl, flag_ipa_cp)
3917 && opt_for_fn (v->decl, optimize))
3918 {
3919 struct cgraph_edge *cs;
3920
3921 estimate_local_effects (v);
3922 add_all_node_vals_to_toposort (v, topo);
3923 for (cs = v->callees; cs; cs = cs->next_callee)
3924 if (!ipa_edge_within_scc (cs))
3925 propagate_constants_across_call (cs);
3926 }
3927 cycle_nodes.release ();
3928 }
3929 }
3930
3931 /* Propagate the estimated effects of individual values along the topological
3932 from the dependent values to those they depend on. */
3933
3934 template <typename valtype>
3935 void
3936 value_topo_info<valtype>::propagate_effects ()
3937 {
3938 ipcp_value<valtype> *base;
3939 hash_set<ipcp_value<valtype> *> processed_srcvals;
3940
3941 for (base = values_topo; base; base = base->topo_next)
3942 {
3943 ipcp_value_source<valtype> *src;
3944 ipcp_value<valtype> *val;
3945 sreal time = 0;
3946 HOST_WIDE_INT size = 0;
3947
3948 for (val = base; val; val = val->scc_next)
3949 {
3950 time = time + val->local_time_benefit + val->prop_time_benefit;
3951 size = size + val->local_size_cost + val->prop_size_cost;
3952 }
3953
3954 for (val = base; val; val = val->scc_next)
3955 {
3956 processed_srcvals.empty ();
3957 for (src = val->sources; src; src = src->next)
3958 if (src->val
3959 && src->cs->maybe_hot_p ())
3960 {
3961 if (!processed_srcvals.add (src->val))
3962 {
3963 HOST_WIDE_INT prop_size = size + src->val->prop_size_cost;
3964 if (prop_size < INT_MAX)
3965 src->val->prop_size_cost = prop_size;
3966 else
3967 continue;
3968 }
3969
3970 int special_factor = 1;
3971 if (val->same_scc (src->val))
3972 special_factor
3973 = opt_for_fn(src->cs->caller->decl,
3974 param_ipa_cp_recursive_freq_factor);
3975 else if (val->self_recursion_generated_p ()
3976 && (src->cs->callee->function_symbol ()
3977 == src->cs->caller))
3978 {
3979 int max_recur_gen_depth
3980 = opt_for_fn(src->cs->caller->decl,
3981 param_ipa_cp_max_recursive_depth);
3982 special_factor = max_recur_gen_depth
3983 - val->self_recursion_generated_level + 1;
3984 }
3985
3986 src->val->prop_time_benefit
3987 += time * special_factor * src->cs->sreal_frequency ();
3988 }
3989
3990 if (size < INT_MAX)
3991 {
3992 val->prop_time_benefit = time;
3993 val->prop_size_cost = size;
3994 }
3995 else
3996 {
3997 val->prop_time_benefit = 0;
3998 val->prop_size_cost = 0;
3999 }
4000 }
4001 }
4002 }
4003
4004 /* Callback for qsort to sort counts of all edges. */
4005
4006 static int
4007 compare_edge_profile_counts (const void *a, const void *b)
4008 {
4009 const profile_count *cnt1 = (const profile_count *) a;
4010 const profile_count *cnt2 = (const profile_count *) b;
4011
4012 if (*cnt1 < *cnt2)
4013 return 1;
4014 if (*cnt1 > *cnt2)
4015 return -1;
4016 return 0;
4017 }
4018
4019
4020 /* Propagate constants, polymorphic contexts and their effects from the
4021 summaries interprocedurally. */
4022
4023 static void
4024 ipcp_propagate_stage (class ipa_topo_info *topo)
4025 {
4026 struct cgraph_node *node;
4027
4028 if (dump_file)
4029 fprintf (dump_file, "\n Propagating constants:\n\n");
4030
4031 base_count = profile_count::uninitialized ();
4032
4033 bool compute_count_base = false;
4034 unsigned base_count_pos_percent = 0;
4035 FOR_EACH_DEFINED_FUNCTION (node)
4036 {
4037 if (node->has_gimple_body_p ()
4038 && opt_for_fn (node->decl, flag_ipa_cp)
4039 && opt_for_fn (node->decl, optimize))
4040 {
4041 ipa_node_params *info = ipa_node_params_sum->get (node);
4042 determine_versionability (node, info);
4043
4044 unsigned nlattices = ipa_get_param_count (info);
4045 info->lattices.safe_grow_cleared (nlattices, true);
4046 initialize_node_lattices (node);
4047 }
4048 ipa_size_summary *s = ipa_size_summaries->get (node);
4049 if (node->definition && !node->alias && s != NULL)
4050 overall_size += s->self_size;
4051 if (node->count.ipa ().initialized_p ())
4052 {
4053 compute_count_base = true;
4054 unsigned pos_percent = opt_for_fn (node->decl,
4055 param_ipa_cp_profile_count_base);
4056 base_count_pos_percent = MAX (base_count_pos_percent, pos_percent);
4057 }
4058 }
4059
4060 if (compute_count_base)
4061 {
4062 auto_vec<profile_count> all_edge_counts;
4063 all_edge_counts.reserve_exact (symtab->edges_count);
4064 FOR_EACH_DEFINED_FUNCTION (node)
4065 for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
4066 {
4067 profile_count count = cs->count.ipa ();
4068 if (!count.nonzero_p ())
4069 continue;
4070
4071 enum availability avail;
4072 cgraph_node *tgt
4073 = cs->callee->function_or_virtual_thunk_symbol (&avail);
4074 ipa_node_params *info = ipa_node_params_sum->get (tgt);
4075 if (info && info->versionable)
4076 all_edge_counts.quick_push (count);
4077 }
4078
4079 if (!all_edge_counts.is_empty ())
4080 {
4081 gcc_assert (base_count_pos_percent <= 100);
4082 all_edge_counts.qsort (compare_edge_profile_counts);
4083
4084 unsigned base_count_pos
4085 = ((all_edge_counts.length () * (base_count_pos_percent)) / 100);
4086 base_count = all_edge_counts[base_count_pos];
4087
4088 if (dump_file)
4089 {
4090 fprintf (dump_file, "\nSelected base_count from %u edges at "
4091 "position %u, arriving at: ", all_edge_counts.length (),
4092 base_count_pos);
4093 base_count.dump (dump_file);
4094 fprintf (dump_file, "\n");
4095 }
4096 }
4097 else if (dump_file)
4098 fprintf (dump_file, "\nNo candidates with non-zero call count found, "
4099 "continuing as if without profile feedback.\n");
4100 }
4101
4102 orig_overall_size = overall_size;
4103
4104 if (dump_file)
4105 fprintf (dump_file, "\noverall_size: %li\n", overall_size);
4106
4107 propagate_constants_topo (topo);
4108 if (flag_checking)
4109 ipcp_verify_propagated_values ();
4110 topo->constants.propagate_effects ();
4111 topo->contexts.propagate_effects ();
4112
4113 if (dump_file)
4114 {
4115 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
4116 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
4117 }
4118 }
4119
4120 /* Discover newly direct outgoing edges from NODE which is a new clone with
4121 known KNOWN_CSTS and make them direct. */
4122
4123 static void
4124 ipcp_discover_new_direct_edges (struct cgraph_node *node,
4125 vec<tree> known_csts,
4126 vec<ipa_polymorphic_call_context>
4127 known_contexts,
4128 vec<ipa_argagg_value, va_gc> *aggvals)
4129 {
4130 struct cgraph_edge *ie, *next_ie;
4131 bool found = false;
4132
4133 for (ie = node->indirect_calls; ie; ie = next_ie)
4134 {
4135 tree target;
4136 bool speculative;
4137
4138 next_ie = ie->next_callee;
4139 ipa_argagg_value_list avs (aggvals);
4140 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
4141 avs, &speculative);
4142 if (target)
4143 {
4144 bool agg_contents = ie->indirect_info->agg_contents;
4145 bool polymorphic = ie->indirect_info->polymorphic;
4146 int param_index = ie->indirect_info->param_index;
4147 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
4148 speculative);
4149 found = true;
4150
4151 if (cs && !agg_contents && !polymorphic)
4152 {
4153 ipa_node_params *info = ipa_node_params_sum->get (node);
4154 int c = ipa_get_controlled_uses (info, param_index);
4155 if (c != IPA_UNDESCRIBED_USE
4156 && !ipa_get_param_load_dereferenced (info, param_index))
4157 {
4158 struct ipa_ref *to_del;
4159
4160 c--;
4161 ipa_set_controlled_uses (info, param_index, c);
4162 if (dump_file && (dump_flags & TDF_DETAILS))
4163 fprintf (dump_file, " controlled uses count of param "
4164 "%i bumped down to %i\n", param_index, c);
4165 if (c == 0
4166 && (to_del = node->find_reference (cs->callee, NULL, 0,
4167 IPA_REF_ADDR)))
4168 {
4169 if (dump_file && (dump_flags & TDF_DETAILS))
4170 fprintf (dump_file, " and even removing its "
4171 "cloning-created reference\n");
4172 to_del->remove_reference ();
4173 }
4174 }
4175 }
4176 }
4177 }
4178 /* Turning calls to direct calls will improve overall summary. */
4179 if (found)
4180 ipa_update_overall_fn_summary (node);
4181 }
4182
4183 class edge_clone_summary;
4184 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL;
4185
4186 /* Edge clone summary. */
4187
4188 class edge_clone_summary
4189 {
4190 public:
4191 /* Default constructor. */
4192 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
4193
4194 /* Default destructor. */
4195 ~edge_clone_summary ()
4196 {
4197 if (prev_clone)
4198 edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
4199 if (next_clone)
4200 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
4201 }
4202
4203 cgraph_edge *prev_clone;
4204 cgraph_edge *next_clone;
4205 };
4206
4207 class edge_clone_summary_t:
4208 public call_summary <edge_clone_summary *>
4209 {
4210 public:
4211 edge_clone_summary_t (symbol_table *symtab):
4212 call_summary <edge_clone_summary *> (symtab)
4213 {
4214 m_initialize_when_cloning = true;
4215 }
4216
4217 void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4218 edge_clone_summary *src_data,
4219 edge_clone_summary *dst_data) final override;
4220 };
4221
4222 /* Edge duplication hook. */
4223
4224 void
4225 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4226 edge_clone_summary *src_data,
4227 edge_clone_summary *dst_data)
4228 {
4229 if (src_data->next_clone)
4230 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
4231 dst_data->prev_clone = src_edge;
4232 dst_data->next_clone = src_data->next_clone;
4233 src_data->next_clone = dst_edge;
4234 }
4235
4236 /* Return true is CS calls DEST or its clone for all contexts. When
4237 ALLOW_RECURSION_TO_CLONE is false, also return false for self-recursive
4238 edges from/to an all-context clone. */
4239
4240 static bool
4241 calls_same_node_or_its_all_contexts_clone_p (cgraph_edge *cs, cgraph_node *dest,
4242 bool allow_recursion_to_clone)
4243 {
4244 enum availability availability;
4245 cgraph_node *callee = cs->callee->function_symbol (&availability);
4246
4247 if (availability <= AVAIL_INTERPOSABLE)
4248 return false;
4249 if (callee == dest)
4250 return true;
4251 if (!allow_recursion_to_clone && cs->caller == callee)
4252 return false;
4253
4254 ipa_node_params *info = ipa_node_params_sum->get (callee);
4255 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
4256 }
4257
4258 /* Return true if edge CS does bring about the value described by SRC to
4259 DEST_VAL of node DEST or its clone for all contexts. */
4260
4261 static bool
4262 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
4263 cgraph_node *dest, ipcp_value<tree> *dest_val)
4264 {
4265 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
4266
4267 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, !src->val)
4268 || caller_info->node_dead)
4269 return false;
4270
4271 if (!src->val)
4272 return true;
4273
4274 if (caller_info->ipcp_orig_node)
4275 {
4276 tree t = NULL_TREE;
4277 if (src->offset == -1)
4278 t = caller_info->known_csts[src->index];
4279 else if (ipcp_transformation *ts
4280 = ipcp_get_transformation_summary (cs->caller))
4281 {
4282 ipa_argagg_value_list avl (ts);
4283 t = avl.get_value (src->index, src->offset / BITS_PER_UNIT);
4284 }
4285 return (t != NULL_TREE
4286 && values_equal_for_ipcp_p (src->val->value, t));
4287 }
4288 else
4289 {
4290 if (src->val == dest_val)
4291 return true;
4292
4293 struct ipcp_agg_lattice *aglat;
4294 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4295 src->index);
4296 if (src->offset == -1)
4297 return (plats->itself.is_single_const ()
4298 && values_equal_for_ipcp_p (src->val->value,
4299 plats->itself.values->value));
4300 else
4301 {
4302 if (plats->aggs_bottom || plats->aggs_contain_variable)
4303 return false;
4304 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4305 if (aglat->offset == src->offset)
4306 return (aglat->is_single_const ()
4307 && values_equal_for_ipcp_p (src->val->value,
4308 aglat->values->value));
4309 }
4310 return false;
4311 }
4312 }
4313
4314 /* Return true if edge CS does bring about the value described by SRC to
4315 DST_VAL of node DEST or its clone for all contexts. */
4316
4317 static bool
4318 cgraph_edge_brings_value_p (cgraph_edge *cs,
4319 ipcp_value_source<ipa_polymorphic_call_context> *src,
4320 cgraph_node *dest,
4321 ipcp_value<ipa_polymorphic_call_context> *)
4322 {
4323 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
4324
4325 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, true)
4326 || caller_info->node_dead)
4327 return false;
4328 if (!src->val)
4329 return true;
4330
4331 if (caller_info->ipcp_orig_node)
4332 return (caller_info->known_contexts.length () > (unsigned) src->index)
4333 && values_equal_for_ipcp_p (src->val->value,
4334 caller_info->known_contexts[src->index]);
4335
4336 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4337 src->index);
4338 return plats->ctxlat.is_single_const ()
4339 && values_equal_for_ipcp_p (src->val->value,
4340 plats->ctxlat.values->value);
4341 }
4342
4343 /* Get the next clone in the linked list of clones of an edge. */
4344
4345 static inline struct cgraph_edge *
4346 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
4347 {
4348 edge_clone_summary *s = edge_clone_summaries->get (cs);
4349 return s != NULL ? s->next_clone : NULL;
4350 }
4351
4352 /* Given VAL that is intended for DEST, iterate over all its sources and if any
4353 of them is viable and hot, return true. In that case, for those that still
4354 hold, add their edge frequency and their number and cumulative profile
4355 counts of self-ecursive and other edges into *FREQUENCY, *CALLER_COUNT,
4356 REC_COUNT_SUM and NONREC_COUNT_SUM respectively. */
4357
4358 template <typename valtype>
4359 static bool
4360 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
4361 sreal *freq_sum, int *caller_count,
4362 profile_count *rec_count_sum,
4363 profile_count *nonrec_count_sum)
4364 {
4365 ipcp_value_source<valtype> *src;
4366 sreal freq = 0;
4367 int count = 0;
4368 profile_count rec_cnt = profile_count::zero ();
4369 profile_count nonrec_cnt = profile_count::zero ();
4370 bool hot = false;
4371 bool non_self_recursive = false;
4372
4373 for (src = val->sources; src; src = src->next)
4374 {
4375 struct cgraph_edge *cs = src->cs;
4376 while (cs)
4377 {
4378 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4379 {
4380 count++;
4381 freq += cs->sreal_frequency ();
4382 hot |= cs->maybe_hot_p ();
4383 if (cs->caller != dest)
4384 {
4385 non_self_recursive = true;
4386 if (cs->count.ipa ().initialized_p ())
4387 rec_cnt += cs->count.ipa ();
4388 }
4389 else if (cs->count.ipa ().initialized_p ())
4390 nonrec_cnt += cs->count.ipa ();
4391 }
4392 cs = get_next_cgraph_edge_clone (cs);
4393 }
4394 }
4395
4396 /* If the only edges bringing a value are self-recursive ones, do not bother
4397 evaluating it. */
4398 if (!non_self_recursive)
4399 return false;
4400
4401 *freq_sum = freq;
4402 *caller_count = count;
4403 *rec_count_sum = rec_cnt;
4404 *nonrec_count_sum = nonrec_cnt;
4405
4406 if (!hot && ipa_node_params_sum->get (dest)->node_within_scc)
4407 {
4408 struct cgraph_edge *cs;
4409
4410 /* Cold non-SCC source edge could trigger hot recursive execution of
4411 function. Consider the case as hot and rely on following cost model
4412 computation to further select right one. */
4413 for (cs = dest->callers; cs; cs = cs->next_caller)
4414 if (cs->caller == dest && cs->maybe_hot_p ())
4415 return true;
4416 }
4417
4418 return hot;
4419 }
4420
4421 /* Given a NODE, and a set of its CALLERS, try to adjust order of the callers
4422 to let a non-self-recursive caller be the first element. Thus, we can
4423 simplify intersecting operations on values that arrive from all of these
4424 callers, especially when there exists self-recursive call. Return true if
4425 this kind of adjustment is possible. */
4426
4427 static bool
4428 adjust_callers_for_value_intersection (vec<cgraph_edge *> &callers,
4429 cgraph_node *node)
4430 {
4431 for (unsigned i = 0; i < callers.length (); i++)
4432 {
4433 cgraph_edge *cs = callers[i];
4434
4435 if (cs->caller != node)
4436 {
4437 if (i > 0)
4438 {
4439 callers[i] = callers[0];
4440 callers[0] = cs;
4441 }
4442 return true;
4443 }
4444 }
4445 return false;
4446 }
4447
4448 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
4449 is assumed their number is known and equal to CALLER_COUNT. */
4450
4451 template <typename valtype>
4452 static vec<cgraph_edge *>
4453 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
4454 int caller_count)
4455 {
4456 ipcp_value_source<valtype> *src;
4457 vec<cgraph_edge *> ret;
4458
4459 ret.create (caller_count);
4460 for (src = val->sources; src; src = src->next)
4461 {
4462 struct cgraph_edge *cs = src->cs;
4463 while (cs)
4464 {
4465 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4466 ret.quick_push (cs);
4467 cs = get_next_cgraph_edge_clone (cs);
4468 }
4469 }
4470
4471 if (caller_count > 1)
4472 adjust_callers_for_value_intersection (ret, dest);
4473
4474 return ret;
4475 }
4476
4477 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
4478 Return it or NULL if for some reason it cannot be created. FORCE_LOAD_REF
4479 should be set to true when the reference created for the constant should be
4480 a load one and not an address one because the corresponding parameter p is
4481 only used as *p. */
4482
4483 static struct ipa_replace_map *
4484 get_replacement_map (class ipa_node_params *info, tree value, int parm_num,
4485 bool force_load_ref)
4486 {
4487 struct ipa_replace_map *replace_map;
4488
4489 replace_map = ggc_alloc<ipa_replace_map> ();
4490 if (dump_file)
4491 {
4492 fprintf (dump_file, " replacing ");
4493 ipa_dump_param (dump_file, info, parm_num);
4494
4495 fprintf (dump_file, " with const ");
4496 print_generic_expr (dump_file, value);
4497
4498 if (force_load_ref)
4499 fprintf (dump_file, " - forcing load reference\n");
4500 else
4501 fprintf (dump_file, "\n");
4502 }
4503 replace_map->parm_num = parm_num;
4504 replace_map->new_tree = value;
4505 replace_map->force_load_ref = force_load_ref;
4506 return replace_map;
4507 }
4508
4509 /* Dump new profiling counts of NODE. SPEC is true when NODE is a specialzied
4510 one, otherwise it will be referred to as the original node. */
4511
4512 static void
4513 dump_profile_updates (cgraph_node *node, bool spec)
4514 {
4515 if (spec)
4516 fprintf (dump_file, " setting count of the specialized node %s to ",
4517 node->dump_name ());
4518 else
4519 fprintf (dump_file, " setting count of the original node %s to ",
4520 node->dump_name ());
4521
4522 node->count.dump (dump_file);
4523 fprintf (dump_file, "\n");
4524 for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
4525 {
4526 fprintf (dump_file, " edge to %s has count ",
4527 cs->callee->dump_name ());
4528 cs->count.dump (dump_file);
4529 fprintf (dump_file, "\n");
4530 }
4531 }
4532
4533 /* With partial train run we do not want to assume that original's count is
4534 zero whenever we redurect all executed edges to clone. Simply drop profile
4535 to local one in this case. In eany case, return the new value. ORIG_NODE
4536 is the original node and its count has not been updaed yet. */
4537
4538 profile_count
4539 lenient_count_portion_handling (profile_count remainder, cgraph_node *orig_node)
4540 {
4541 if (remainder.ipa_p () && !remainder.ipa ().nonzero_p ()
4542 && orig_node->count.ipa_p () && orig_node->count.ipa ().nonzero_p ()
4543 && opt_for_fn (orig_node->decl, flag_profile_partial_training))
4544 remainder = remainder.guessed_local ();
4545
4546 return remainder;
4547 }
4548
4549 /* Structure to sum counts coming from nodes other than the original node and
4550 its clones. */
4551
4552 struct gather_other_count_struct
4553 {
4554 cgraph_node *orig;
4555 profile_count other_count;
4556 };
4557
4558 /* Worker callback of call_for_symbol_thunks_and_aliases summing the number of
4559 counts that come from non-self-recursive calls.. */
4560
4561 static bool
4562 gather_count_of_non_rec_edges (cgraph_node *node, void *data)
4563 {
4564 gather_other_count_struct *desc = (gather_other_count_struct *) data;
4565 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
4566 if (cs->caller != desc->orig && cs->caller->clone_of != desc->orig)
4567 desc->other_count += cs->count.ipa ();
4568 return false;
4569 }
4570
4571 /* Structure to help analyze if we need to boost counts of some clones of some
4572 non-recursive edges to match the new callee count. */
4573
4574 struct desc_incoming_count_struct
4575 {
4576 cgraph_node *orig;
4577 hash_set <cgraph_edge *> *processed_edges;
4578 profile_count count;
4579 unsigned unproc_orig_rec_edges;
4580 };
4581
4582 /* Go over edges calling NODE and its thunks and gather information about
4583 incoming counts so that we know if we need to make any adjustments. */
4584
4585 static void
4586 analyze_clone_icoming_counts (cgraph_node *node,
4587 desc_incoming_count_struct *desc)
4588 {
4589 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
4590 if (cs->caller->thunk)
4591 {
4592 analyze_clone_icoming_counts (cs->caller, desc);
4593 continue;
4594 }
4595 else
4596 {
4597 if (cs->count.initialized_p ())
4598 desc->count += cs->count.ipa ();
4599 if (!desc->processed_edges->contains (cs)
4600 && cs->caller->clone_of == desc->orig)
4601 desc->unproc_orig_rec_edges++;
4602 }
4603 }
4604
4605 /* If caller edge counts of a clone created for a self-recursive arithmetic
4606 jump function must be adjusted because it is coming from a the "seed" clone
4607 for the first value and so has been excessively scaled back as if it was not
4608 a recursive call, adjust it so that the incoming counts of NODE match its
4609 count. NODE is the node or its thunk. */
4610
4611 static void
4612 adjust_clone_incoming_counts (cgraph_node *node,
4613 desc_incoming_count_struct *desc)
4614 {
4615 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
4616 if (cs->caller->thunk)
4617 {
4618 adjust_clone_incoming_counts (cs->caller, desc);
4619 profile_count sum = profile_count::zero ();
4620 for (cgraph_edge *e = cs->caller->callers; e; e = e->next_caller)
4621 if (e->count.initialized_p ())
4622 sum += e->count.ipa ();
4623 cs->count = cs->count.combine_with_ipa_count (sum);
4624 }
4625 else if (!desc->processed_edges->contains (cs)
4626 && cs->caller->clone_of == desc->orig)
4627 {
4628 cs->count += desc->count;
4629 if (dump_file)
4630 {
4631 fprintf (dump_file, " Adjusted count of an incoming edge of "
4632 "a clone %s -> %s to ", cs->caller->dump_name (),
4633 cs->callee->dump_name ());
4634 cs->count.dump (dump_file);
4635 fprintf (dump_file, "\n");
4636 }
4637 }
4638 }
4639
4640 /* When ORIG_NODE has been cloned for values which have been generated fora
4641 self-recursive call as a result of an arithmetic pass-through
4642 jump-functions, adjust its count together with counts of all such clones in
4643 SELF_GEN_CLONES which also at this point contains ORIG_NODE itself.
4644
4645 The function sums the counts of the original node and all its clones that
4646 cannot be attributed to a specific clone because it comes from a
4647 non-recursive edge. This sum is then evenly divided between the clones and
4648 on top of that each one gets all the counts which can be attributed directly
4649 to it. */
4650
4651 static void
4652 update_counts_for_self_gen_clones (cgraph_node *orig_node,
4653 const vec<cgraph_node *> &self_gen_clones)
4654 {
4655 profile_count redist_sum = orig_node->count.ipa ();
4656 if (!(redist_sum > profile_count::zero ()))
4657 return;
4658
4659 if (dump_file)
4660 fprintf (dump_file, " Updating profile of self recursive clone "
4661 "series\n");
4662
4663 gather_other_count_struct gocs;
4664 gocs.orig = orig_node;
4665 gocs.other_count = profile_count::zero ();
4666
4667 auto_vec <profile_count, 8> other_edges_count;
4668 for (cgraph_node *n : self_gen_clones)
4669 {
4670 gocs.other_count = profile_count::zero ();
4671 n->call_for_symbol_thunks_and_aliases (gather_count_of_non_rec_edges,
4672 &gocs, false);
4673 other_edges_count.safe_push (gocs.other_count);
4674 redist_sum -= gocs.other_count;
4675 }
4676
4677 hash_set<cgraph_edge *> processed_edges;
4678 unsigned i = 0;
4679 for (cgraph_node *n : self_gen_clones)
4680 {
4681 profile_count orig_count = n->count;
4682 profile_count new_count
4683 = (redist_sum / self_gen_clones.length () + other_edges_count[i]);
4684 new_count = lenient_count_portion_handling (new_count, orig_node);
4685 n->count = new_count;
4686 profile_count::adjust_for_ipa_scaling (&new_count, &orig_count);
4687 for (cgraph_edge *cs = n->callees; cs; cs = cs->next_callee)
4688 {
4689 cs->count = cs->count.apply_scale (new_count, orig_count);
4690 processed_edges.add (cs);
4691 }
4692 for (cgraph_edge *cs = n->indirect_calls; cs; cs = cs->next_callee)
4693 cs->count = cs->count.apply_scale (new_count, orig_count);
4694
4695 i++;
4696 }
4697
4698 /* There are still going to be edges to ORIG_NODE that have one or more
4699 clones coming from another node clone in SELF_GEN_CLONES and which we
4700 scaled by the same amount, which means that the total incoming sum of
4701 counts to ORIG_NODE will be too high, scale such edges back. */
4702 for (cgraph_edge *cs = orig_node->callees; cs; cs = cs->next_callee)
4703 {
4704 if (cs->callee->ultimate_alias_target () == orig_node)
4705 {
4706 unsigned den = 0;
4707 for (cgraph_edge *e = cs; e; e = get_next_cgraph_edge_clone (e))
4708 if (e->callee->ultimate_alias_target () == orig_node
4709 && processed_edges.contains (e))
4710 den++;
4711 if (den > 0)
4712 for (cgraph_edge *e = cs; e; e = get_next_cgraph_edge_clone (e))
4713 if (e->callee->ultimate_alias_target () == orig_node
4714 && processed_edges.contains (e))
4715 e->count /= den;
4716 }
4717 }
4718
4719 /* Edges from the seeds of the valus generated for arithmetic jump-functions
4720 along self-recursive edges are likely to have fairly low count and so
4721 edges from them to nodes in the self_gen_clones do not correspond to the
4722 artificially distributed count of the nodes, the total sum of incoming
4723 edges to some clones might be too low. Detect this situation and correct
4724 it. */
4725 for (cgraph_node *n : self_gen_clones)
4726 {
4727 if (!(n->count.ipa () > profile_count::zero ()))
4728 continue;
4729
4730 desc_incoming_count_struct desc;
4731 desc.orig = orig_node;
4732 desc.processed_edges = &processed_edges;
4733 desc.count = profile_count::zero ();
4734 desc.unproc_orig_rec_edges = 0;
4735 analyze_clone_icoming_counts (n, &desc);
4736
4737 if (n->count.differs_from_p (desc.count))
4738 {
4739 if (n->count > desc.count
4740 && desc.unproc_orig_rec_edges > 0)
4741 {
4742 desc.count = n->count - desc.count;
4743 desc.count = desc.count /= desc.unproc_orig_rec_edges;
4744 adjust_clone_incoming_counts (n, &desc);
4745 }
4746 else if (dump_file)
4747 fprintf (dump_file,
4748 " Unable to fix up incoming counts for %s.\n",
4749 n->dump_name ());
4750 }
4751 }
4752
4753 if (dump_file)
4754 for (cgraph_node *n : self_gen_clones)
4755 dump_profile_updates (n, n != orig_node);
4756 return;
4757 }
4758
4759 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
4760 their profile information to reflect this. This function should not be used
4761 for clones generated for arithmetic pass-through jump functions on a
4762 self-recursive call graph edge, that situation is handled by
4763 update_counts_for_self_gen_clones. */
4764
4765 static void
4766 update_profiling_info (struct cgraph_node *orig_node,
4767 struct cgraph_node *new_node)
4768 {
4769 struct caller_statistics stats;
4770 profile_count new_sum;
4771 profile_count remainder, orig_node_count = orig_node->count.ipa ();
4772
4773 if (!(orig_node_count > profile_count::zero ()))
4774 return;
4775
4776 if (dump_file)
4777 {
4778 fprintf (dump_file, " Updating profile from original count: ");
4779 orig_node_count.dump (dump_file);
4780 fprintf (dump_file, "\n");
4781 }
4782
4783 init_caller_stats (&stats, new_node);
4784 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
4785 false);
4786 new_sum = stats.count_sum;
4787
4788 bool orig_edges_processed = false;
4789 if (new_sum > orig_node_count)
4790 {
4791 /* TODO: Profile has alreay gone astray, keep what we have but lower it
4792 to global0 category. */
4793 remainder = orig_node->count.global0 ();
4794
4795 for (cgraph_edge *cs = orig_node->callees; cs; cs = cs->next_callee)
4796 cs->count = cs->count.global0 ();
4797 for (cgraph_edge *cs = orig_node->indirect_calls;
4798 cs;
4799 cs = cs->next_callee)
4800 cs->count = cs->count.global0 ();
4801 orig_edges_processed = true;
4802 }
4803 else if (stats.rec_count_sum.nonzero_p ())
4804 {
4805 int new_nonrec_calls = stats.n_nonrec_calls;
4806 /* There are self-recursive edges which are likely to bring in the
4807 majority of calls but which we must divide in between the original and
4808 new node. */
4809 init_caller_stats (&stats, orig_node);
4810 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats,
4811 &stats, false);
4812 int orig_nonrec_calls = stats.n_nonrec_calls;
4813 profile_count orig_nonrec_call_count = stats.count_sum;
4814
4815 if (orig_node->local)
4816 {
4817 if (!orig_nonrec_call_count.nonzero_p ())
4818 {
4819 if (dump_file)
4820 fprintf (dump_file, " The original is local and the only "
4821 "incoming edges from non-dead callers with nonzero "
4822 "counts are self-recursive, assuming it is cold.\n");
4823 /* The NEW_NODE count and counts of all its outgoing edges
4824 are still unmodified copies of ORIG_NODE's. Just clear
4825 the latter and bail out. */
4826 profile_count zero;
4827 if (opt_for_fn (orig_node->decl, flag_profile_partial_training))
4828 zero = profile_count::zero ().guessed_local ();
4829 else
4830 zero = profile_count::adjusted_zero ();
4831 orig_node->count = zero;
4832 for (cgraph_edge *cs = orig_node->callees;
4833 cs;
4834 cs = cs->next_callee)
4835 cs->count = zero;
4836 for (cgraph_edge *cs = orig_node->indirect_calls;
4837 cs;
4838 cs = cs->next_callee)
4839 cs->count = zero;
4840 return;
4841 }
4842 }
4843 else
4844 {
4845 /* Let's behave as if there was another caller that accounts for all
4846 the calls that were either indirect or from other compilation
4847 units. */
4848 orig_nonrec_calls++;
4849 profile_count pretend_caller_count
4850 = (orig_node_count - new_sum - orig_nonrec_call_count
4851 - stats.rec_count_sum);
4852 orig_nonrec_call_count += pretend_caller_count;
4853 }
4854
4855 /* Divide all "unexplained" counts roughly proportionally to sums of
4856 counts of non-recursive calls.
4857
4858 We put rather arbitrary limits on how many counts we claim because the
4859 number of non-self-recursive incoming count is only a rough guideline
4860 and there are cases (such as mcf) where using it blindly just takes
4861 too many. And if lattices are considered in the opposite order we
4862 could also take too few. */
4863 profile_count unexp = orig_node_count - new_sum - orig_nonrec_call_count;
4864
4865 int limit_den = 2 * (orig_nonrec_calls + new_nonrec_calls);
4866 profile_count new_part
4867 = MAX(MIN (unexp.apply_scale (new_sum,
4868 new_sum + orig_nonrec_call_count),
4869 unexp.apply_scale (limit_den - 1, limit_den)),
4870 unexp.apply_scale (new_nonrec_calls, limit_den));
4871 if (dump_file)
4872 {
4873 fprintf (dump_file, " Claiming ");
4874 new_part.dump (dump_file);
4875 fprintf (dump_file, " of unexplained ");
4876 unexp.dump (dump_file);
4877 fprintf (dump_file, " counts because of self-recursive "
4878 "calls\n");
4879 }
4880 new_sum += new_part;
4881 remainder = lenient_count_portion_handling (orig_node_count - new_sum,
4882 orig_node);
4883 }
4884 else
4885 remainder = lenient_count_portion_handling (orig_node_count - new_sum,
4886 orig_node);
4887
4888 new_sum = orig_node_count.combine_with_ipa_count (new_sum);
4889 new_node->count = new_sum;
4890 orig_node->count = remainder;
4891
4892 profile_count orig_new_node_count = orig_node_count;
4893 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_new_node_count);
4894 for (cgraph_edge *cs = new_node->callees; cs; cs = cs->next_callee)
4895 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4896 for (cgraph_edge *cs = new_node->indirect_calls; cs; cs = cs->next_callee)
4897 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4898
4899 if (!orig_edges_processed)
4900 {
4901 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
4902 for (cgraph_edge *cs = orig_node->callees; cs; cs = cs->next_callee)
4903 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4904 for (cgraph_edge *cs = orig_node->indirect_calls;
4905 cs;
4906 cs = cs->next_callee)
4907 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4908 }
4909
4910 if (dump_file)
4911 {
4912 dump_profile_updates (new_node, true);
4913 dump_profile_updates (orig_node, false);
4914 }
4915 }
4916
4917 /* Update the respective profile of specialized NEW_NODE and the original
4918 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
4919 have been redirected to the specialized version. */
4920
4921 static void
4922 update_specialized_profile (struct cgraph_node *new_node,
4923 struct cgraph_node *orig_node,
4924 profile_count redirected_sum)
4925 {
4926 struct cgraph_edge *cs;
4927 profile_count new_node_count, orig_node_count = orig_node->count.ipa ();
4928
4929 if (dump_file)
4930 {
4931 fprintf (dump_file, " the sum of counts of redirected edges is ");
4932 redirected_sum.dump (dump_file);
4933 fprintf (dump_file, "\n old ipa count of the original node is ");
4934 orig_node_count.dump (dump_file);
4935 fprintf (dump_file, "\n");
4936 }
4937 if (!(orig_node_count > profile_count::zero ()))
4938 return;
4939
4940 new_node_count = new_node->count;
4941 new_node->count += redirected_sum;
4942 orig_node->count
4943 = lenient_count_portion_handling (orig_node->count - redirected_sum,
4944 orig_node);
4945
4946 for (cs = new_node->callees; cs; cs = cs->next_callee)
4947 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
4948
4949 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4950 {
4951 profile_count dec = cs->count.apply_scale (redirected_sum,
4952 orig_node_count);
4953 cs->count -= dec;
4954 }
4955
4956 if (dump_file)
4957 {
4958 dump_profile_updates (new_node, true);
4959 dump_profile_updates (orig_node, false);
4960 }
4961 }
4962
4963 static void adjust_references_in_caller (cgraph_edge *cs,
4964 symtab_node *symbol, int index);
4965
4966 /* Simple structure to pass a symbol and index (with same meaning as parameters
4967 of adjust_references_in_caller) through a void* parameter of a
4968 call_for_symbol_thunks_and_aliases callback. */
4969 struct symbol_and_index_together
4970 {
4971 symtab_node *symbol;
4972 int index;
4973 };
4974
4975 /* Worker callback of call_for_symbol_thunks_and_aliases to recursively call
4976 adjust_references_in_caller on edges up in the call-graph, if necessary. */
4977 static bool
4978 adjust_refs_in_act_callers (struct cgraph_node *node, void *data)
4979 {
4980 symbol_and_index_together *pack = (symbol_and_index_together *) data;
4981 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
4982 if (!cs->caller->thunk)
4983 adjust_references_in_caller (cs, pack->symbol, pack->index);
4984 return false;
4985 }
4986
4987 /* At INDEX of a function being called by CS there is an ADDR_EXPR of a
4988 variable which is only dereferenced and which is represented by SYMBOL. See
4989 if we can remove ADDR reference in callers assosiated witht the call. */
4990
4991 static void
4992 adjust_references_in_caller (cgraph_edge *cs, symtab_node *symbol, int index)
4993 {
4994 ipa_edge_args *args = ipa_edge_args_sum->get (cs);
4995 ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, index);
4996 if (jfunc->type == IPA_JF_CONST)
4997 {
4998 ipa_ref *to_del = cs->caller->find_reference (symbol, cs->call_stmt,
4999 cs->lto_stmt_uid,
5000 IPA_REF_ADDR);
5001 if (!to_del)
5002 return;
5003 to_del->remove_reference ();
5004 ipa_zap_jf_refdesc (jfunc);
5005 if (dump_file)
5006 fprintf (dump_file, " Removed a reference from %s to %s.\n",
5007 cs->caller->dump_name (), symbol->dump_name ());
5008 return;
5009 }
5010
5011 if (jfunc->type != IPA_JF_PASS_THROUGH
5012 || ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR
5013 || ipa_get_jf_pass_through_refdesc_decremented (jfunc))
5014 return;
5015
5016 int fidx = ipa_get_jf_pass_through_formal_id (jfunc);
5017 cgraph_node *caller = cs->caller;
5018 ipa_node_params *caller_info = ipa_node_params_sum->get (caller);
5019 /* TODO: This consistency check may be too big and not really
5020 that useful. Consider removing it. */
5021 tree cst;
5022 if (caller_info->ipcp_orig_node)
5023 cst = caller_info->known_csts[fidx];
5024 else
5025 {
5026 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (caller_info, fidx);
5027 gcc_assert (lat->is_single_const ());
5028 cst = lat->values->value;
5029 }
5030 gcc_assert (TREE_CODE (cst) == ADDR_EXPR
5031 && (symtab_node::get (get_base_address (TREE_OPERAND (cst, 0)))
5032 == symbol));
5033
5034 int cuses = ipa_get_controlled_uses (caller_info, fidx);
5035 if (cuses == IPA_UNDESCRIBED_USE)
5036 return;
5037 gcc_assert (cuses > 0);
5038 cuses--;
5039 ipa_set_controlled_uses (caller_info, fidx, cuses);
5040 ipa_set_jf_pass_through_refdesc_decremented (jfunc, true);
5041 if (dump_file && (dump_flags & TDF_DETAILS))
5042 fprintf (dump_file, " Controlled uses of parameter %i of %s dropped "
5043 "to %i.\n", fidx, caller->dump_name (), cuses);
5044 if (cuses)
5045 return;
5046
5047 if (caller_info->ipcp_orig_node)
5048 {
5049 /* Cloning machinery has created a reference here, we need to either
5050 remove it or change it to a read one. */
5051 ipa_ref *to_del = caller->find_reference (symbol, NULL, 0, IPA_REF_ADDR);
5052 if (to_del)
5053 {
5054 to_del->remove_reference ();
5055 if (dump_file)
5056 fprintf (dump_file, " Removed a reference from %s to %s.\n",
5057 cs->caller->dump_name (), symbol->dump_name ());
5058 if (ipa_get_param_load_dereferenced (caller_info, fidx))
5059 {
5060 caller->create_reference (symbol, IPA_REF_LOAD, NULL);
5061 if (dump_file)
5062 fprintf (dump_file,
5063 " ...and replaced it with LOAD one.\n");
5064 }
5065 }
5066 }
5067
5068 symbol_and_index_together pack;
5069 pack.symbol = symbol;
5070 pack.index = fidx;
5071 if (caller->can_change_signature)
5072 caller->call_for_symbol_thunks_and_aliases (adjust_refs_in_act_callers,
5073 &pack, true);
5074 }
5075
5076
5077 /* Return true if we would like to remove a parameter from NODE when cloning it
5078 with KNOWN_CSTS scalar constants. */
5079
5080 static bool
5081 want_remove_some_param_p (cgraph_node *node, vec<tree> known_csts)
5082 {
5083 auto_vec<bool, 16> surviving;
5084 bool filled_vec = false;
5085 ipa_node_params *info = ipa_node_params_sum->get (node);
5086 int i, count = ipa_get_param_count (info);
5087
5088 for (i = 0; i < count; i++)
5089 {
5090 if (!known_csts[i] && ipa_is_param_used (info, i))
5091 continue;
5092
5093 if (!filled_vec)
5094 {
5095 clone_info *info = clone_info::get (node);
5096 if (!info || !info->param_adjustments)
5097 return true;
5098 info->param_adjustments->get_surviving_params (&surviving);
5099 filled_vec = true;
5100 }
5101 if (surviving.length() < (unsigned) i && surviving[i])
5102 return true;
5103 }
5104 return false;
5105 }
5106
5107 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
5108 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
5109 redirect all edges in CALLERS to it. */
5110
5111 static struct cgraph_node *
5112 create_specialized_node (struct cgraph_node *node,
5113 vec<tree> known_csts,
5114 vec<ipa_polymorphic_call_context> known_contexts,
5115 vec<ipa_argagg_value, va_gc> *aggvals,
5116 vec<cgraph_edge *> &callers)
5117 {
5118 ipa_node_params *new_info, *info = ipa_node_params_sum->get (node);
5119 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
5120 vec<ipa_adjusted_param, va_gc> *new_params = NULL;
5121 struct cgraph_node *new_node;
5122 int i, count = ipa_get_param_count (info);
5123 clone_info *cinfo = clone_info::get (node);
5124 ipa_param_adjustments *old_adjustments = cinfo
5125 ? cinfo->param_adjustments : NULL;
5126 ipa_param_adjustments *new_adjustments;
5127 gcc_assert (!info->ipcp_orig_node);
5128 gcc_assert (node->can_change_signature
5129 || !old_adjustments);
5130
5131 if (old_adjustments)
5132 {
5133 /* At the moment all IPA optimizations should use the number of
5134 parameters of the prevailing decl as the m_always_copy_start.
5135 Handling any other value would complicate the code below, so for the
5136 time bing let's only assert it is so. */
5137 gcc_assert (old_adjustments->m_always_copy_start == count
5138 || old_adjustments->m_always_copy_start < 0);
5139 int old_adj_count = vec_safe_length (old_adjustments->m_adj_params);
5140 for (i = 0; i < old_adj_count; i++)
5141 {
5142 ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
5143 if (!node->can_change_signature
5144 || old_adj->op != IPA_PARAM_OP_COPY
5145 || (!known_csts[old_adj->base_index]
5146 && ipa_is_param_used (info, old_adj->base_index)))
5147 {
5148 ipa_adjusted_param new_adj = *old_adj;
5149
5150 new_adj.prev_clone_adjustment = true;
5151 new_adj.prev_clone_index = i;
5152 vec_safe_push (new_params, new_adj);
5153 }
5154 }
5155 bool skip_return = old_adjustments->m_skip_return;
5156 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
5157 ipa_param_adjustments (new_params, count,
5158 skip_return));
5159 }
5160 else if (node->can_change_signature
5161 && want_remove_some_param_p (node, known_csts))
5162 {
5163 ipa_adjusted_param adj;
5164 memset (&adj, 0, sizeof (adj));
5165 adj.op = IPA_PARAM_OP_COPY;
5166 for (i = 0; i < count; i++)
5167 if (!known_csts[i] && ipa_is_param_used (info, i))
5168 {
5169 adj.base_index = i;
5170 adj.prev_clone_index = i;
5171 vec_safe_push (new_params, adj);
5172 }
5173 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
5174 ipa_param_adjustments (new_params, count, false));
5175 }
5176 else
5177 new_adjustments = NULL;
5178
5179 auto_vec<cgraph_edge *, 2> self_recursive_calls;
5180 for (i = callers.length () - 1; i >= 0; i--)
5181 {
5182 cgraph_edge *cs = callers[i];
5183 if (cs->caller == node)
5184 {
5185 self_recursive_calls.safe_push (cs);
5186 callers.unordered_remove (i);
5187 }
5188 }
5189 replace_trees = cinfo ? vec_safe_copy (cinfo->tree_map) : NULL;
5190 for (i = 0; i < count; i++)
5191 {
5192 tree t = known_csts[i];
5193 if (!t)
5194 continue;
5195
5196 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
5197
5198 bool load_ref = false;
5199 symtab_node *ref_symbol;
5200 if (TREE_CODE (t) == ADDR_EXPR)
5201 {
5202 tree base = get_base_address (TREE_OPERAND (t, 0));
5203 if (TREE_CODE (base) == VAR_DECL
5204 && ipa_get_controlled_uses (info, i) == 0
5205 && ipa_get_param_load_dereferenced (info, i)
5206 && (ref_symbol = symtab_node::get (base)))
5207 {
5208 load_ref = true;
5209 if (node->can_change_signature)
5210 for (cgraph_edge *caller : callers)
5211 adjust_references_in_caller (caller, ref_symbol, i);
5212 }
5213 }
5214
5215 ipa_replace_map *replace_map = get_replacement_map (info, t, i, load_ref);
5216 if (replace_map)
5217 vec_safe_push (replace_trees, replace_map);
5218 }
5219
5220 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
5221 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
5222 node->decl)));
5223 new_node = node->create_virtual_clone (callers, replace_trees,
5224 new_adjustments, "constprop",
5225 suffix_counter);
5226 suffix_counter++;
5227
5228 bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
5229 for (unsigned j = 0; j < self_recursive_calls.length (); j++)
5230 {
5231 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
5232 /* Cloned edges can disappear during cloning as speculation can be
5233 resolved, check that we have one and that it comes from the last
5234 cloning. */
5235 if (cs && cs->caller == new_node)
5236 cs->redirect_callee_duplicating_thunks (new_node);
5237 /* Any future code that would make more than one clone of an outgoing
5238 edge would confuse this mechanism, so let's check that does not
5239 happen. */
5240 gcc_checking_assert (!cs
5241 || !get_next_cgraph_edge_clone (cs)
5242 || get_next_cgraph_edge_clone (cs)->caller != new_node);
5243 }
5244 if (have_self_recursive_calls)
5245 new_node->expand_all_artificial_thunks ();
5246
5247 ipa_set_node_agg_value_chain (new_node, aggvals);
5248 for (const ipa_argagg_value &av : aggvals)
5249 new_node->maybe_create_reference (av.value, NULL);
5250
5251 if (dump_file && (dump_flags & TDF_DETAILS))
5252 {
5253 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
5254 if (known_contexts.exists ())
5255 {
5256 for (i = 0; i < count; i++)
5257 if (!known_contexts[i].useless_p ())
5258 {
5259 fprintf (dump_file, " known ctx %i is ", i);
5260 known_contexts[i].dump (dump_file);
5261 }
5262 }
5263 if (aggvals)
5264 {
5265 fprintf (dump_file, " Aggregate replacements:");
5266 ipa_argagg_value_list avs (aggvals);
5267 avs.dump (dump_file);
5268 }
5269 }
5270
5271 new_info = ipa_node_params_sum->get (new_node);
5272 new_info->ipcp_orig_node = node;
5273 new_node->ipcp_clone = true;
5274 new_info->known_csts = known_csts;
5275 new_info->known_contexts = known_contexts;
5276
5277 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts,
5278 aggvals);
5279
5280 return new_node;
5281 }
5282
5283 /* Return true if JFUNC, which describes a i-th parameter of call CS, is a
5284 pass-through function to itself when the cgraph_node involved is not an
5285 IPA-CP clone. When SIMPLE is true, further check if JFUNC is a simple
5286 no-operation pass-through. */
5287
5288 static bool
5289 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i,
5290 bool simple = true)
5291 {
5292 enum availability availability;
5293 if (cs->caller == cs->callee->function_symbol (&availability)
5294 && availability > AVAIL_INTERPOSABLE
5295 && jfunc->type == IPA_JF_PASS_THROUGH
5296 && (!simple || ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
5297 && ipa_get_jf_pass_through_formal_id (jfunc) == i
5298 && ipa_node_params_sum->get (cs->caller)
5299 && !ipa_node_params_sum->get (cs->caller)->ipcp_orig_node)
5300 return true;
5301 return false;
5302 }
5303
5304 /* Return true if JFUNC, which describes a part of an aggregate represented or
5305 pointed to by the i-th parameter of call CS, is a pass-through function to
5306 itself when the cgraph_node involved is not an IPA-CP clone.. When
5307 SIMPLE is true, further check if JFUNC is a simple no-operation
5308 pass-through. */
5309
5310 static bool
5311 self_recursive_agg_pass_through_p (const cgraph_edge *cs,
5312 const ipa_agg_jf_item *jfunc,
5313 int i, bool simple = true)
5314 {
5315 enum availability availability;
5316 if (cs->caller == cs->callee->function_symbol (&availability)
5317 && availability > AVAIL_INTERPOSABLE
5318 && jfunc->jftype == IPA_JF_LOAD_AGG
5319 && jfunc->offset == jfunc->value.load_agg.offset
5320 && (!simple || jfunc->value.pass_through.operation == NOP_EXPR)
5321 && jfunc->value.pass_through.formal_id == i
5322 && useless_type_conversion_p (jfunc->value.load_agg.type, jfunc->type)
5323 && ipa_node_params_sum->get (cs->caller)
5324 && !ipa_node_params_sum->get (cs->caller)->ipcp_orig_node)
5325 return true;
5326 return false;
5327 }
5328
5329 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
5330 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
5331
5332 static void
5333 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
5334 vec<tree> &known_csts,
5335 const vec<cgraph_edge *> &callers)
5336 {
5337 ipa_node_params *info = ipa_node_params_sum->get (node);
5338 int i, count = ipa_get_param_count (info);
5339
5340 for (i = 0; i < count; i++)
5341 {
5342 struct cgraph_edge *cs;
5343 tree newval = NULL_TREE;
5344 int j;
5345 bool first = true;
5346 tree type = ipa_get_type (info, i);
5347
5348 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
5349 continue;
5350
5351 FOR_EACH_VEC_ELT (callers, j, cs)
5352 {
5353 struct ipa_jump_func *jump_func;
5354 tree t;
5355
5356 ipa_edge_args *args = ipa_edge_args_sum->get (cs);
5357 if (!args
5358 || i >= ipa_get_cs_argument_count (args)
5359 || (i == 0
5360 && call_passes_through_thunk (cs)))
5361 {
5362 newval = NULL_TREE;
5363 break;
5364 }
5365 jump_func = ipa_get_ith_jump_func (args, i);
5366
5367 /* Besides simple pass-through jump function, arithmetic jump
5368 function could also introduce argument-direct-pass-through for
5369 self-feeding recursive call. For example,
5370
5371 fn (int i)
5372 {
5373 fn (i & 1);
5374 }
5375
5376 Given that i is 0, recursive propagation via (i & 1) also gets
5377 0. */
5378 if (self_recursive_pass_through_p (cs, jump_func, i, false))
5379 {
5380 gcc_assert (newval);
5381 t = ipa_get_jf_arith_result (
5382 ipa_get_jf_pass_through_operation (jump_func),
5383 newval,
5384 ipa_get_jf_pass_through_operand (jump_func),
5385 type);
5386 }
5387 else
5388 t = ipa_value_from_jfunc (ipa_node_params_sum->get (cs->caller),
5389 jump_func, type);
5390 if (!t
5391 || (newval
5392 && !values_equal_for_ipcp_p (t, newval))
5393 || (!first && !newval))
5394 {
5395 newval = NULL_TREE;
5396 break;
5397 }
5398 else
5399 newval = t;
5400 first = false;
5401 }
5402
5403 if (newval)
5404 {
5405 if (dump_file && (dump_flags & TDF_DETAILS))
5406 {
5407 fprintf (dump_file, " adding an extra known scalar value ");
5408 print_ipcp_constant_value (dump_file, newval);
5409 fprintf (dump_file, " for ");
5410 ipa_dump_param (dump_file, info, i);
5411 fprintf (dump_file, "\n");
5412 }
5413
5414 known_csts[i] = newval;
5415 }
5416 }
5417 }
5418
5419 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
5420 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
5421 CALLERS. */
5422
5423 static void
5424 find_more_contexts_for_caller_subset (cgraph_node *node,
5425 vec<ipa_polymorphic_call_context>
5426 *known_contexts,
5427 const vec<cgraph_edge *> &callers)
5428 {
5429 ipa_node_params *info = ipa_node_params_sum->get (node);
5430 int i, count = ipa_get_param_count (info);
5431
5432 for (i = 0; i < count; i++)
5433 {
5434 cgraph_edge *cs;
5435
5436 if (ipa_get_poly_ctx_lat (info, i)->bottom
5437 || (known_contexts->exists ()
5438 && !(*known_contexts)[i].useless_p ()))
5439 continue;
5440
5441 ipa_polymorphic_call_context newval;
5442 bool first = true;
5443 int j;
5444
5445 FOR_EACH_VEC_ELT (callers, j, cs)
5446 {
5447 ipa_edge_args *args = ipa_edge_args_sum->get (cs);
5448 if (!args
5449 || i >= ipa_get_cs_argument_count (args))
5450 return;
5451 ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, i);
5452 ipa_polymorphic_call_context ctx;
5453 ctx = ipa_context_from_jfunc (ipa_node_params_sum->get (cs->caller),
5454 cs, i, jfunc);
5455 if (first)
5456 {
5457 newval = ctx;
5458 first = false;
5459 }
5460 else
5461 newval.meet_with (ctx);
5462 if (newval.useless_p ())
5463 break;
5464 }
5465
5466 if (!newval.useless_p ())
5467 {
5468 if (dump_file && (dump_flags & TDF_DETAILS))
5469 {
5470 fprintf (dump_file, " adding an extra known polymorphic "
5471 "context ");
5472 print_ipcp_constant_value (dump_file, newval);
5473 fprintf (dump_file, " for ");
5474 ipa_dump_param (dump_file, info, i);
5475 fprintf (dump_file, "\n");
5476 }
5477
5478 if (!known_contexts->exists ())
5479 known_contexts->safe_grow_cleared (ipa_get_param_count (info),
5480 true);
5481 (*known_contexts)[i] = newval;
5482 }
5483
5484 }
5485 }
5486
5487 /* Push all aggregate values coming along edge CS for parameter number INDEX to
5488 RES. If INTERIM is non-NULL, it contains the current interim state of
5489 collected aggregate values which can be used to compute values passed over
5490 self-recursive edges.
5491
5492 This basically one iteration of push_agg_values_from_edge over one
5493 parameter, which allows for simpler early returns. */
5494
5495 static void
5496 push_agg_values_for_index_from_edge (struct cgraph_edge *cs, int index,
5497 vec<ipa_argagg_value> *res,
5498 const ipa_argagg_value_list *interim)
5499 {
5500 bool agg_values_from_caller = false;
5501 bool agg_jf_preserved = false;
5502 unsigned unit_delta = UINT_MAX;
5503 int src_idx = -1;
5504 ipa_jump_func *jfunc = ipa_get_ith_jump_func (ipa_edge_args_sum->get (cs),
5505 index);
5506
5507 if (jfunc->type == IPA_JF_PASS_THROUGH
5508 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
5509 {
5510 agg_values_from_caller = true;
5511 agg_jf_preserved = ipa_get_jf_pass_through_agg_preserved (jfunc);
5512 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
5513 unit_delta = 0;
5514 }
5515 else if (jfunc->type == IPA_JF_ANCESTOR
5516 && ipa_get_jf_ancestor_agg_preserved (jfunc))
5517 {
5518 agg_values_from_caller = true;
5519 agg_jf_preserved = true;
5520 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
5521 unit_delta = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
5522 }
5523
5524 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
5525 if (agg_values_from_caller)
5526 {
5527 if (caller_info->ipcp_orig_node)
5528 {
5529 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
5530 ipcp_transformation *ts
5531 = ipcp_get_transformation_summary (cs->caller);
5532 ipa_node_params *orig_info = ipa_node_params_sum->get (orig_node);
5533 ipcp_param_lattices *orig_plats
5534 = ipa_get_parm_lattices (orig_info, src_idx);
5535 if (ts
5536 && orig_plats->aggs
5537 && (agg_jf_preserved || !orig_plats->aggs_by_ref))
5538 {
5539 ipa_argagg_value_list src (ts);
5540 src.push_adjusted_values (src_idx, index, unit_delta, res);
5541 return;
5542 }
5543 }
5544 else
5545 {
5546 ipcp_param_lattices *src_plats
5547 = ipa_get_parm_lattices (caller_info, src_idx);
5548 if (src_plats->aggs
5549 && !src_plats->aggs_bottom
5550 && (agg_jf_preserved || !src_plats->aggs_by_ref))
5551 {
5552 if (interim && self_recursive_pass_through_p (cs, jfunc, index))
5553 {
5554 interim->push_adjusted_values (src_idx, index, unit_delta,
5555 res);
5556 return;
5557 }
5558 if (!src_plats->aggs_contain_variable)
5559 {
5560 push_agg_values_from_plats (src_plats, index, unit_delta,
5561 res);
5562 return;
5563 }
5564 }
5565 }
5566 }
5567
5568 if (!jfunc->agg.items)
5569 return;
5570 bool first = true;
5571 unsigned prev_unit_offset = 0;
5572 for (const ipa_agg_jf_item &agg_jf : *jfunc->agg.items)
5573 {
5574 tree value, srcvalue;
5575 /* Besides simple pass-through aggregate jump function, arithmetic
5576 aggregate jump function could also bring same aggregate value as
5577 parameter passed-in for self-feeding recursive call. For example,
5578
5579 fn (int *i)
5580 {
5581 int j = *i & 1;
5582 fn (&j);
5583 }
5584
5585 Given that *i is 0, recursive propagation via (*i & 1) also gets 0. */
5586 if (interim
5587 && self_recursive_agg_pass_through_p (cs, &agg_jf, index, false)
5588 && (srcvalue = interim->get_value(index,
5589 agg_jf.offset / BITS_PER_UNIT)))
5590 value = ipa_get_jf_arith_result (agg_jf.value.pass_through.operation,
5591 srcvalue,
5592 agg_jf.value.pass_through.operand,
5593 agg_jf.type);
5594 else
5595 value = ipa_agg_value_from_jfunc (caller_info, cs->caller,
5596 &agg_jf);
5597 if (value)
5598 {
5599 struct ipa_argagg_value iav;
5600 iav.value = value;
5601 iav.unit_offset = agg_jf.offset / BITS_PER_UNIT;
5602 iav.index = index;
5603 iav.by_ref = jfunc->agg.by_ref;
5604 iav.killed = false;
5605
5606 gcc_assert (first
5607 || iav.unit_offset > prev_unit_offset);
5608 prev_unit_offset = iav.unit_offset;
5609 first = false;
5610
5611 res->safe_push (iav);
5612 }
5613 }
5614 return;
5615 }
5616
5617 /* Push all aggregate values coming along edge CS to RES. DEST_INFO is the
5618 description of ultimate callee of CS or the one it was cloned from (the
5619 summary where lattices are). If INTERIM is non-NULL, it contains the
5620 current interim state of collected aggregate values which can be used to
5621 compute values passed over self-recursive edges (if OPTIMIZE_SELF_RECURSION
5622 is true) and to skip values which clearly will not be part of intersection
5623 with INTERIM. */
5624
5625 static void
5626 push_agg_values_from_edge (struct cgraph_edge *cs,
5627 ipa_node_params *dest_info,
5628 vec<ipa_argagg_value> *res,
5629 const ipa_argagg_value_list *interim,
5630 bool optimize_self_recursion)
5631 {
5632 ipa_edge_args *args = ipa_edge_args_sum->get (cs);
5633 if (!args)
5634 return;
5635
5636 int count = MIN (ipa_get_param_count (dest_info),
5637 ipa_get_cs_argument_count (args));
5638
5639 unsigned interim_index = 0;
5640 for (int index = 0; index < count; index++)
5641 {
5642 if (interim)
5643 {
5644 while (interim_index < interim->m_elts.size ()
5645 && interim->m_elts[interim_index].value
5646 && interim->m_elts[interim_index].index < index)
5647 interim_index++;
5648 if (interim_index >= interim->m_elts.size ()
5649 || interim->m_elts[interim_index].index > index)
5650 continue;
5651 }
5652
5653 ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, index);
5654 if (!ipa_is_param_used (dest_info, index)
5655 || plats->aggs_bottom)
5656 continue;
5657 push_agg_values_for_index_from_edge (cs, index, res,
5658 optimize_self_recursion ? interim
5659 : NULL);
5660 }
5661 }
5662
5663
5664 /* Look at edges in CALLERS and collect all known aggregate values that arrive
5665 from all of them. Return nullptr if there are none. */
5666
5667 static struct vec<ipa_argagg_value, va_gc> *
5668 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
5669 const vec<cgraph_edge *> &callers)
5670 {
5671 ipa_node_params *dest_info = ipa_node_params_sum->get (node);
5672 if (dest_info->ipcp_orig_node)
5673 dest_info = ipa_node_params_sum->get (dest_info->ipcp_orig_node);
5674
5675 /* gather_edges_for_value puts a non-recursive call into the first element of
5676 callers if it can. */
5677 auto_vec<ipa_argagg_value, 32> interim;
5678 push_agg_values_from_edge (callers[0], dest_info, &interim, NULL, true);
5679
5680 unsigned valid_entries = interim.length ();
5681 if (!valid_entries)
5682 return nullptr;
5683
5684 unsigned caller_count = callers.length();
5685 for (unsigned i = 1; i < caller_count; i++)
5686 {
5687 auto_vec<ipa_argagg_value, 32> last;
5688 ipa_argagg_value_list avs (&interim);
5689 push_agg_values_from_edge (callers[i], dest_info, &last, &avs, true);
5690
5691 valid_entries = intersect_argaggs_with (interim, last);
5692 if (!valid_entries)
5693 return nullptr;
5694 }
5695
5696 vec<ipa_argagg_value, va_gc> *res = NULL;
5697 vec_safe_reserve_exact (res, valid_entries);
5698 for (const ipa_argagg_value &av : interim)
5699 if (av.value)
5700 res->quick_push(av);
5701 gcc_checking_assert (res->length () == valid_entries);
5702 return res;
5703 }
5704
5705 /* Determine whether CS also brings all scalar values that the NODE is
5706 specialized for. */
5707
5708 static bool
5709 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
5710 struct cgraph_node *node)
5711 {
5712 ipa_node_params *dest_info = ipa_node_params_sum->get (node);
5713 int count = ipa_get_param_count (dest_info);
5714 class ipa_node_params *caller_info;
5715 class ipa_edge_args *args;
5716 int i;
5717
5718 caller_info = ipa_node_params_sum->get (cs->caller);
5719 args = ipa_edge_args_sum->get (cs);
5720 for (i = 0; i < count; i++)
5721 {
5722 struct ipa_jump_func *jump_func;
5723 tree val, t;
5724
5725 val = dest_info->known_csts[i];
5726 if (!val)
5727 continue;
5728
5729 if (i >= ipa_get_cs_argument_count (args))
5730 return false;
5731 jump_func = ipa_get_ith_jump_func (args, i);
5732 t = ipa_value_from_jfunc (caller_info, jump_func,
5733 ipa_get_type (dest_info, i));
5734 if (!t || !values_equal_for_ipcp_p (val, t))
5735 return false;
5736 }
5737 return true;
5738 }
5739
5740 /* Determine whether CS also brings all aggregate values that NODE is
5741 specialized for. */
5742
5743 static bool
5744 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
5745 struct cgraph_node *node)
5746 {
5747 ipcp_transformation *ts = ipcp_get_transformation_summary (node);
5748 if (!ts || vec_safe_is_empty (ts->m_agg_values))
5749 return true;
5750
5751 const ipa_argagg_value_list existing (ts->m_agg_values);
5752 auto_vec<ipa_argagg_value, 32> edge_values;
5753 ipa_node_params *dest_info = ipa_node_params_sum->get (node);
5754 gcc_checking_assert (dest_info->ipcp_orig_node);
5755 dest_info = ipa_node_params_sum->get (dest_info->ipcp_orig_node);
5756 push_agg_values_from_edge (cs, dest_info, &edge_values, &existing, false);
5757 const ipa_argagg_value_list avl (&edge_values);
5758 return avl.superset_of_p (existing);
5759 }
5760
5761 /* Given an original NODE and a VAL for which we have already created a
5762 specialized clone, look whether there are incoming edges that still lead
5763 into the old node but now also bring the requested value and also conform to
5764 all other criteria such that they can be redirected the special node.
5765 This function can therefore redirect the final edge in a SCC. */
5766
5767 template <typename valtype>
5768 static void
5769 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
5770 {
5771 ipcp_value_source<valtype> *src;
5772 profile_count redirected_sum = profile_count::zero ();
5773
5774 for (src = val->sources; src; src = src->next)
5775 {
5776 struct cgraph_edge *cs = src->cs;
5777 while (cs)
5778 {
5779 if (cgraph_edge_brings_value_p (cs, src, node, val)
5780 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
5781 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
5782 {
5783 if (dump_file)
5784 fprintf (dump_file, " - adding an extra caller %s of %s\n",
5785 cs->caller->dump_name (),
5786 val->spec_node->dump_name ());
5787
5788 cs->redirect_callee_duplicating_thunks (val->spec_node);
5789 val->spec_node->expand_all_artificial_thunks ();
5790 if (cs->count.ipa ().initialized_p ())
5791 redirected_sum = redirected_sum + cs->count.ipa ();
5792 }
5793 cs = get_next_cgraph_edge_clone (cs);
5794 }
5795 }
5796
5797 if (redirected_sum.nonzero_p ())
5798 update_specialized_profile (val->spec_node, node, redirected_sum);
5799 }
5800
5801 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
5802
5803 static bool
5804 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
5805 {
5806 ipa_polymorphic_call_context *ctx;
5807 int i;
5808
5809 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
5810 if (!ctx->useless_p ())
5811 return true;
5812 return false;
5813 }
5814
5815 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
5816
5817 static vec<ipa_polymorphic_call_context>
5818 copy_useful_known_contexts (const vec<ipa_polymorphic_call_context> &known_contexts)
5819 {
5820 if (known_contexts_useful_p (known_contexts))
5821 return known_contexts.copy ();
5822 else
5823 return vNULL;
5824 }
5825
5826 /* Copy known scalar values from AVALS into KNOWN_CSTS and modify the copy
5827 according to VAL and INDEX. If non-empty, replace KNOWN_CONTEXTS with its
5828 copy too. */
5829
5830 static void
5831 copy_known_vectors_add_val (ipa_auto_call_arg_values *avals,
5832 vec<tree> *known_csts,
5833 vec<ipa_polymorphic_call_context> *known_contexts,
5834 ipcp_value<tree> *val, int index)
5835 {
5836 *known_csts = avals->m_known_vals.copy ();
5837 *known_contexts = copy_useful_known_contexts (avals->m_known_contexts);
5838 (*known_csts)[index] = val->value;
5839 }
5840
5841 /* Copy known scalar values from AVALS into KNOWN_CSTS. Similarly, copy
5842 contexts to KNOWN_CONTEXTS and modify the copy according to VAL and
5843 INDEX. */
5844
5845 static void
5846 copy_known_vectors_add_val (ipa_auto_call_arg_values *avals,
5847 vec<tree> *known_csts,
5848 vec<ipa_polymorphic_call_context> *known_contexts,
5849 ipcp_value<ipa_polymorphic_call_context> *val,
5850 int index)
5851 {
5852 *known_csts = avals->m_known_vals.copy ();
5853 *known_contexts = avals->m_known_contexts.copy ();
5854 (*known_contexts)[index] = val->value;
5855 }
5856
5857 /* Return true if OFFSET indicates this was not an aggregate value or there is
5858 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
5859 AGGVALS list. */
5860
5861 DEBUG_FUNCTION bool
5862 ipcp_val_agg_replacement_ok_p (vec<ipa_argagg_value, va_gc> *aggvals,
5863 int index, HOST_WIDE_INT offset, tree value)
5864 {
5865 if (offset == -1)
5866 return true;
5867
5868 const ipa_argagg_value_list avl (aggvals);
5869 tree v = avl.get_value (index, offset / BITS_PER_UNIT);
5870 return v && values_equal_for_ipcp_p (v, value);
5871 }
5872
5873 /* Return true if offset is minus one because source of a polymorphic context
5874 cannot be an aggregate value. */
5875
5876 DEBUG_FUNCTION bool
5877 ipcp_val_agg_replacement_ok_p (vec<ipa_argagg_value, va_gc> *,
5878 int , HOST_WIDE_INT offset,
5879 ipa_polymorphic_call_context)
5880 {
5881 return offset == -1;
5882 }
5883
5884 /* Decide whether to create a special version of NODE for value VAL of
5885 parameter at the given INDEX. If OFFSET is -1, the value is for the
5886 parameter itself, otherwise it is stored at the given OFFSET of the
5887 parameter. AVALS describes the other already known values. SELF_GEN_CLONES
5888 is a vector which contains clones created for self-recursive calls with an
5889 arithmetic pass-through jump function. */
5890
5891 template <typename valtype>
5892 static bool
5893 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
5894 ipcp_value<valtype> *val, ipa_auto_call_arg_values *avals,
5895 vec<cgraph_node *> *self_gen_clones)
5896 {
5897 int caller_count;
5898 sreal freq_sum;
5899 profile_count count_sum, rec_count_sum;
5900 vec<cgraph_edge *> callers;
5901
5902 if (val->spec_node)
5903 {
5904 perhaps_add_new_callers (node, val);
5905 return false;
5906 }
5907 else if (val->local_size_cost + overall_size > get_max_overall_size (node))
5908 {
5909 if (dump_file && (dump_flags & TDF_DETAILS))
5910 fprintf (dump_file, " Ignoring candidate value because "
5911 "maximum unit size would be reached with %li.\n",
5912 val->local_size_cost + overall_size);
5913 return false;
5914 }
5915 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &caller_count,
5916 &rec_count_sum, &count_sum))
5917 return false;
5918
5919 if (!dbg_cnt (ipa_cp_values))
5920 return false;
5921
5922 if (val->self_recursion_generated_p ())
5923 {
5924 /* The edge counts in this case might not have been adjusted yet.
5925 Nevertleless, even if they were it would be only a guesswork which we
5926 can do now. The recursive part of the counts can be derived from the
5927 count of the original node anyway. */
5928 if (node->count.ipa ().nonzero_p ())
5929 {
5930 unsigned dem = self_gen_clones->length () + 1;
5931 rec_count_sum = node->count.ipa () / dem;
5932 }
5933 else
5934 rec_count_sum = profile_count::zero ();
5935 }
5936
5937 /* get_info_about_necessary_edges only sums up ipa counts. */
5938 count_sum += rec_count_sum;
5939
5940 if (dump_file && (dump_flags & TDF_DETAILS))
5941 {
5942 fprintf (dump_file, " - considering value ");
5943 print_ipcp_constant_value (dump_file, val->value);
5944 fprintf (dump_file, " for ");
5945 ipa_dump_param (dump_file, ipa_node_params_sum->get (node), index);
5946 if (offset != -1)
5947 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
5948 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
5949 }
5950
5951 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
5952 freq_sum, count_sum,
5953 val->local_size_cost)
5954 && !good_cloning_opportunity_p (node, val->prop_time_benefit,
5955 freq_sum, count_sum, val->prop_size_cost))
5956 return false;
5957
5958 if (dump_file)
5959 fprintf (dump_file, " Creating a specialized node of %s.\n",
5960 node->dump_name ());
5961
5962 vec<tree> known_csts;
5963 vec<ipa_polymorphic_call_context> known_contexts;
5964
5965 callers = gather_edges_for_value (val, node, caller_count);
5966 if (offset == -1)
5967 copy_known_vectors_add_val (avals, &known_csts, &known_contexts, val, index);
5968 else
5969 {
5970 known_csts = avals->m_known_vals.copy ();
5971 known_contexts = copy_useful_known_contexts (avals->m_known_contexts);
5972 }
5973 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
5974 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
5975 vec<ipa_argagg_value, va_gc> *aggvals
5976 = find_aggregate_values_for_callers_subset (node, callers);
5977 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
5978 offset, val->value));
5979 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
5980 aggvals, callers);
5981
5982 if (val->self_recursion_generated_p ())
5983 self_gen_clones->safe_push (val->spec_node);
5984 else
5985 update_profiling_info (node, val->spec_node);
5986
5987 callers.release ();
5988 overall_size += val->local_size_cost;
5989 if (dump_file && (dump_flags & TDF_DETAILS))
5990 fprintf (dump_file, " overall size reached %li\n",
5991 overall_size);
5992
5993 /* TODO: If for some lattice there is only one other known value
5994 left, make a special node for it too. */
5995
5996 return true;
5997 }
5998
5999 /* Like irange::contains_p(), but convert VAL to the range of R if
6000 necessary. */
6001
6002 static inline bool
6003 ipa_range_contains_p (const vrange &r, tree val)
6004 {
6005 if (r.undefined_p ())
6006 return false;
6007
6008 tree type = r.type ();
6009 if (!wi::fits_to_tree_p (wi::to_wide (val), type))
6010 return false;
6011
6012 val = fold_convert (type, val);
6013 return r.contains_p (val);
6014 }
6015
6016 /* Decide whether and what specialized clones of NODE should be created. */
6017
6018 static bool
6019 decide_whether_version_node (struct cgraph_node *node)
6020 {
6021 ipa_node_params *info = ipa_node_params_sum->get (node);
6022 int i, count = ipa_get_param_count (info);
6023 bool ret = false;
6024
6025 if (count == 0)
6026 return false;
6027
6028 if (dump_file && (dump_flags & TDF_DETAILS))
6029 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
6030 node->dump_name ());
6031
6032 auto_vec <cgraph_node *, 9> self_gen_clones;
6033 ipa_auto_call_arg_values avals;
6034 gather_context_independent_values (info, &avals, false, NULL);
6035
6036 for (i = 0; i < count;i++)
6037 {
6038 if (!ipa_is_param_used (info, i))
6039 continue;
6040
6041 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
6042 ipcp_lattice<tree> *lat = &plats->itself;
6043 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
6044
6045 if (!lat->bottom
6046 && !avals.m_known_vals[i])
6047 {
6048 ipcp_value<tree> *val;
6049 for (val = lat->values; val; val = val->next)
6050 {
6051 /* If some values generated for self-recursive calls with
6052 arithmetic jump functions fall outside of the known
6053 range for the parameter, we can skip them. */
6054 if (TREE_CODE (val->value) == INTEGER_CST
6055 && !plats->m_value_range.bottom_p ()
6056 && !ipa_range_contains_p (plats->m_value_range.m_vr,
6057 val->value))
6058 {
6059 /* This can happen also if a constant present in the source
6060 code falls outside of the range of parameter's type, so we
6061 cannot assert. */
6062 if (dump_file && (dump_flags & TDF_DETAILS))
6063 {
6064 fprintf (dump_file, " - skipping%s value ",
6065 val->self_recursion_generated_p ()
6066 ? " self_recursion_generated" : "");
6067 print_ipcp_constant_value (dump_file, val->value);
6068 fprintf (dump_file, " because it is outside known "
6069 "value range.\n");
6070 }
6071 continue;
6072 }
6073 ret |= decide_about_value (node, i, -1, val, &avals,
6074 &self_gen_clones);
6075 }
6076 }
6077
6078 if (!plats->aggs_bottom)
6079 {
6080 struct ipcp_agg_lattice *aglat;
6081 ipcp_value<tree> *val;
6082 for (aglat = plats->aggs; aglat; aglat = aglat->next)
6083 if (!aglat->bottom && aglat->values
6084 /* If the following is false, the one value has been considered
6085 for cloning for all contexts. */
6086 && (plats->aggs_contain_variable
6087 || !aglat->is_single_const ()))
6088 for (val = aglat->values; val; val = val->next)
6089 ret |= decide_about_value (node, i, aglat->offset, val, &avals,
6090 &self_gen_clones);
6091 }
6092
6093 if (!ctxlat->bottom
6094 && avals.m_known_contexts[i].useless_p ())
6095 {
6096 ipcp_value<ipa_polymorphic_call_context> *val;
6097 for (val = ctxlat->values; val; val = val->next)
6098 ret |= decide_about_value (node, i, -1, val, &avals,
6099 &self_gen_clones);
6100 }
6101 }
6102
6103 if (!self_gen_clones.is_empty ())
6104 {
6105 self_gen_clones.safe_push (node);
6106 update_counts_for_self_gen_clones (node, self_gen_clones);
6107 }
6108
6109 if (info->do_clone_for_all_contexts)
6110 {
6111 if (!dbg_cnt (ipa_cp_values))
6112 {
6113 info->do_clone_for_all_contexts = false;
6114 return ret;
6115 }
6116
6117 struct cgraph_node *clone;
6118 auto_vec<cgraph_edge *> callers = node->collect_callers ();
6119
6120 for (int i = callers.length () - 1; i >= 0; i--)
6121 {
6122 cgraph_edge *cs = callers[i];
6123 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
6124
6125 if (caller_info && caller_info->node_dead)
6126 callers.unordered_remove (i);
6127 }
6128
6129 if (!adjust_callers_for_value_intersection (callers, node))
6130 {
6131 /* If node is not called by anyone, or all its caller edges are
6132 self-recursive, the node is not really in use, no need to do
6133 cloning. */
6134 info->do_clone_for_all_contexts = false;
6135 return ret;
6136 }
6137
6138 if (dump_file)
6139 fprintf (dump_file, " - Creating a specialized node of %s "
6140 "for all known contexts.\n", node->dump_name ());
6141
6142 vec<tree> known_csts = avals.m_known_vals.copy ();
6143 vec<ipa_polymorphic_call_context> known_contexts
6144 = copy_useful_known_contexts (avals.m_known_contexts);
6145 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
6146 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
6147 vec<ipa_argagg_value, va_gc> *aggvals
6148 = find_aggregate_values_for_callers_subset (node, callers);
6149
6150 if (!known_contexts_useful_p (known_contexts))
6151 {
6152 known_contexts.release ();
6153 known_contexts = vNULL;
6154 }
6155 clone = create_specialized_node (node, known_csts, known_contexts,
6156 aggvals, callers);
6157 info->do_clone_for_all_contexts = false;
6158 ipa_node_params_sum->get (clone)->is_all_contexts_clone = true;
6159 ret = true;
6160 }
6161
6162 return ret;
6163 }
6164
6165 /* Transitively mark all callees of NODE within the same SCC as not dead. */
6166
6167 static void
6168 spread_undeadness (struct cgraph_node *node)
6169 {
6170 struct cgraph_edge *cs;
6171
6172 for (cs = node->callees; cs; cs = cs->next_callee)
6173 if (ipa_edge_within_scc (cs))
6174 {
6175 struct cgraph_node *callee;
6176 class ipa_node_params *info;
6177
6178 callee = cs->callee->function_symbol (NULL);
6179 info = ipa_node_params_sum->get (callee);
6180
6181 if (info && info->node_dead)
6182 {
6183 info->node_dead = 0;
6184 spread_undeadness (callee);
6185 }
6186 }
6187 }
6188
6189 /* Return true if NODE has a caller from outside of its SCC that is not
6190 dead. Worker callback for cgraph_for_node_and_aliases. */
6191
6192 static bool
6193 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
6194 void *data ATTRIBUTE_UNUSED)
6195 {
6196 struct cgraph_edge *cs;
6197
6198 for (cs = node->callers; cs; cs = cs->next_caller)
6199 if (cs->caller->thunk
6200 && cs->caller->call_for_symbol_thunks_and_aliases
6201 (has_undead_caller_from_outside_scc_p, NULL, true))
6202 return true;
6203 else if (!ipa_edge_within_scc (cs))
6204 {
6205 ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
6206 if (!caller_info /* Unoptimized caller are like dead ones. */
6207 || !caller_info->node_dead)
6208 return true;
6209 }
6210 return false;
6211 }
6212
6213
6214 /* Identify nodes within the same SCC as NODE which are no longer needed
6215 because of new clones and will be removed as unreachable. */
6216
6217 static void
6218 identify_dead_nodes (struct cgraph_node *node)
6219 {
6220 struct cgraph_node *v;
6221 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
6222 if (v->local)
6223 {
6224 ipa_node_params *info = ipa_node_params_sum->get (v);
6225 if (info
6226 && !v->call_for_symbol_thunks_and_aliases
6227 (has_undead_caller_from_outside_scc_p, NULL, true))
6228 info->node_dead = 1;
6229 }
6230
6231 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
6232 {
6233 ipa_node_params *info = ipa_node_params_sum->get (v);
6234 if (info && !info->node_dead)
6235 spread_undeadness (v);
6236 }
6237
6238 if (dump_file && (dump_flags & TDF_DETAILS))
6239 {
6240 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
6241 if (ipa_node_params_sum->get (v)
6242 && ipa_node_params_sum->get (v)->node_dead)
6243 fprintf (dump_file, " Marking node as dead: %s.\n",
6244 v->dump_name ());
6245 }
6246 }
6247
6248 /* The decision stage. Iterate over the topological order of call graph nodes
6249 TOPO and make specialized clones if deemed beneficial. */
6250
6251 static void
6252 ipcp_decision_stage (class ipa_topo_info *topo)
6253 {
6254 int i;
6255
6256 if (dump_file)
6257 fprintf (dump_file, "\nIPA decision stage:\n\n");
6258
6259 for (i = topo->nnodes - 1; i >= 0; i--)
6260 {
6261 struct cgraph_node *node = topo->order[i];
6262 bool change = false, iterate = true;
6263
6264 while (iterate)
6265 {
6266 struct cgraph_node *v;
6267 iterate = false;
6268 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
6269 if (v->has_gimple_body_p ()
6270 && ipcp_versionable_function_p (v))
6271 iterate |= decide_whether_version_node (v);
6272
6273 change |= iterate;
6274 }
6275 if (change)
6276 identify_dead_nodes (node);
6277 }
6278 }
6279
6280 /* Look up all VR and bits information that we have discovered and copy it
6281 over to the transformation summary. */
6282
6283 static void
6284 ipcp_store_vr_results (void)
6285 {
6286 cgraph_node *node;
6287
6288 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
6289 {
6290 ipa_node_params *info = ipa_node_params_sum->get (node);
6291 bool dumped_sth = false;
6292 bool found_useful_result = false;
6293 bool do_vr = true;
6294 bool do_bits = true;
6295
6296 if (!info || !opt_for_fn (node->decl, flag_ipa_vrp))
6297 {
6298 if (dump_file)
6299 fprintf (dump_file, "Not considering %s for VR discovery "
6300 "and propagate; -fipa-ipa-vrp: disabled.\n",
6301 node->dump_name ());
6302 do_vr = false;
6303 }
6304 if (!info || !opt_for_fn (node->decl, flag_ipa_bit_cp))
6305 {
6306 if (dump_file)
6307 fprintf (dump_file, "Not considering %s for ipa bitwise "
6308 "propagation ; -fipa-bit-cp: disabled.\n",
6309 node->dump_name ());
6310 do_bits = false;
6311 }
6312 if (!do_bits && !do_vr)
6313 continue;
6314
6315 if (info->ipcp_orig_node)
6316 info = ipa_node_params_sum->get (info->ipcp_orig_node);
6317 if (info->lattices.is_empty ())
6318 /* Newly expanded artificial thunks do not have lattices. */
6319 continue;
6320
6321 unsigned count = ipa_get_param_count (info);
6322 for (unsigned i = 0; i < count; i++)
6323 {
6324 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
6325 if (do_vr
6326 && !plats->m_value_range.bottom_p ()
6327 && !plats->m_value_range.top_p ())
6328 {
6329 found_useful_result = true;
6330 break;
6331 }
6332 if (do_bits && plats->bits_lattice.constant_p ())
6333 {
6334 found_useful_result = true;
6335 break;
6336 }
6337 }
6338 if (!found_useful_result)
6339 continue;
6340
6341 ipcp_transformation_initialize ();
6342 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
6343 vec_safe_reserve_exact (ts->m_vr, count);
6344
6345 for (unsigned i = 0; i < count; i++)
6346 {
6347 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
6348 ipcp_bits_lattice *bits = NULL;
6349
6350 if (do_bits
6351 && plats->bits_lattice.constant_p ()
6352 && dbg_cnt (ipa_cp_bits))
6353 bits = &plats->bits_lattice;
6354
6355 if (do_vr
6356 && !plats->m_value_range.bottom_p ()
6357 && !plats->m_value_range.top_p ()
6358 && dbg_cnt (ipa_cp_vr))
6359 {
6360 if (bits)
6361 {
6362 Value_Range tmp = plats->m_value_range.m_vr;
6363 tree type = ipa_get_type (info, i);
6364 irange_bitmask bm (wide_int::from (bits->get_value (),
6365 TYPE_PRECISION (type),
6366 TYPE_SIGN (type)),
6367 wide_int::from (bits->get_mask (),
6368 TYPE_PRECISION (type),
6369 TYPE_SIGN (type)));
6370 tmp.update_bitmask (bm);
6371 ipa_vr vr (tmp);
6372 ts->m_vr->quick_push (vr);
6373 }
6374 else
6375 {
6376 ipa_vr vr (plats->m_value_range.m_vr);
6377 ts->m_vr->quick_push (vr);
6378 }
6379 }
6380 else if (bits)
6381 {
6382 tree type = ipa_get_type (info, i);
6383 Value_Range tmp;
6384 tmp.set_varying (type);
6385 irange_bitmask bm (wide_int::from (bits->get_value (),
6386 TYPE_PRECISION (type),
6387 TYPE_SIGN (type)),
6388 wide_int::from (bits->get_mask (),
6389 TYPE_PRECISION (type),
6390 TYPE_SIGN (type)));
6391 tmp.update_bitmask (bm);
6392 ipa_vr vr (tmp);
6393 ts->m_vr->quick_push (vr);
6394 }
6395 else
6396 {
6397 ipa_vr vr;
6398 ts->m_vr->quick_push (vr);
6399 }
6400
6401 if (!dump_file || !bits)
6402 continue;
6403
6404 if (!dumped_sth)
6405 {
6406 fprintf (dump_file, "Propagated bits info for function %s:\n",
6407 node->dump_name ());
6408 dumped_sth = true;
6409 }
6410 fprintf (dump_file, " param %i: value = ", i);
6411 print_hex (bits->get_value (), dump_file);
6412 fprintf (dump_file, ", mask = ");
6413 print_hex (bits->get_mask (), dump_file);
6414 fprintf (dump_file, "\n");
6415 }
6416 }
6417 }
6418
6419 /* The IPCP driver. */
6420
6421 static unsigned int
6422 ipcp_driver (void)
6423 {
6424 class ipa_topo_info topo;
6425
6426 if (edge_clone_summaries == NULL)
6427 edge_clone_summaries = new edge_clone_summary_t (symtab);
6428
6429 ipa_check_create_node_params ();
6430 ipa_check_create_edge_args ();
6431 clone_num_suffixes = new hash_map<const char *, unsigned>;
6432
6433 if (dump_file)
6434 {
6435 fprintf (dump_file, "\nIPA structures before propagation:\n");
6436 if (dump_flags & TDF_DETAILS)
6437 ipa_print_all_params (dump_file);
6438 ipa_print_all_jump_functions (dump_file);
6439 }
6440
6441 /* Topological sort. */
6442 build_toporder_info (&topo);
6443 /* Do the interprocedural propagation. */
6444 ipcp_propagate_stage (&topo);
6445 /* Decide what constant propagation and cloning should be performed. */
6446 ipcp_decision_stage (&topo);
6447 /* Store results of value range and bits propagation. */
6448 ipcp_store_vr_results ();
6449
6450 /* Free all IPCP structures. */
6451 delete clone_num_suffixes;
6452 free_toporder_info (&topo);
6453 delete edge_clone_summaries;
6454 edge_clone_summaries = NULL;
6455 ipa_free_all_structures_after_ipa_cp ();
6456 if (dump_file)
6457 fprintf (dump_file, "\nIPA constant propagation end\n");
6458 return 0;
6459 }
6460
6461 /* Initialization and computation of IPCP data structures. This is the initial
6462 intraprocedural analysis of functions, which gathers information to be
6463 propagated later on. */
6464
6465 static void
6466 ipcp_generate_summary (void)
6467 {
6468 struct cgraph_node *node;
6469
6470 if (dump_file)
6471 fprintf (dump_file, "\nIPA constant propagation start:\n");
6472 ipa_register_cgraph_hooks ();
6473
6474 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
6475 ipa_analyze_node (node);
6476 }
6477
6478 namespace {
6479
6480 const pass_data pass_data_ipa_cp =
6481 {
6482 IPA_PASS, /* type */
6483 "cp", /* name */
6484 OPTGROUP_NONE, /* optinfo_flags */
6485 TV_IPA_CONSTANT_PROP, /* tv_id */
6486 0, /* properties_required */
6487 0, /* properties_provided */
6488 0, /* properties_destroyed */
6489 0, /* todo_flags_start */
6490 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
6491 };
6492
6493 class pass_ipa_cp : public ipa_opt_pass_d
6494 {
6495 public:
6496 pass_ipa_cp (gcc::context *ctxt)
6497 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
6498 ipcp_generate_summary, /* generate_summary */
6499 NULL, /* write_summary */
6500 NULL, /* read_summary */
6501 ipcp_write_transformation_summaries, /*
6502 write_optimization_summary */
6503 ipcp_read_transformation_summaries, /*
6504 read_optimization_summary */
6505 NULL, /* stmt_fixup */
6506 0, /* function_transform_todo_flags_start */
6507 ipcp_transform_function, /* function_transform */
6508 NULL) /* variable_transform */
6509 {}
6510
6511 /* opt_pass methods: */
6512 bool gate (function *) final override
6513 {
6514 /* FIXME: We should remove the optimize check after we ensure we never run
6515 IPA passes when not optimizing. */
6516 return (flag_ipa_cp && optimize) || in_lto_p;
6517 }
6518
6519 unsigned int execute (function *) final override { return ipcp_driver (); }
6520
6521 }; // class pass_ipa_cp
6522
6523 } // anon namespace
6524
6525 ipa_opt_pass_d *
6526 make_pass_ipa_cp (gcc::context *ctxt)
6527 {
6528 return new pass_ipa_cp (ctxt);
6529 }
6530
6531 /* Reset all state within ipa-cp.cc so that we can rerun the compiler
6532 within the same process. For use by toplev::finalize. */
6533
6534 void
6535 ipa_cp_cc_finalize (void)
6536 {
6537 base_count = profile_count::uninitialized ();
6538 overall_size = 0;
6539 orig_overall_size = 0;
6540 ipcp_free_transformation_sum ();
6541 }
6542
6543 /* Given PARAM which must be a parameter of function FNDECL described by THIS,
6544 return its index in the DECL_ARGUMENTS chain, using a pre-computed
6545 DECL_UID-sorted vector if available (which is pre-computed only if there are
6546 many parameters). Can return -1 if param is static chain not represented
6547 among DECL_ARGUMENTS. */
6548
6549 int
6550 ipcp_transformation::get_param_index (const_tree fndecl, const_tree param) const
6551 {
6552 gcc_assert (TREE_CODE (param) == PARM_DECL);
6553 if (m_uid_to_idx)
6554 {
6555 unsigned puid = DECL_UID (param);
6556 const ipa_uid_to_idx_map_elt *res
6557 = std::lower_bound (m_uid_to_idx->begin(), m_uid_to_idx->end (), puid,
6558 [] (const ipa_uid_to_idx_map_elt &elt, unsigned uid)
6559 {
6560 return elt.uid < uid;
6561 });
6562 if (res == m_uid_to_idx->end ()
6563 || res->uid != puid)
6564 {
6565 gcc_assert (DECL_STATIC_CHAIN (fndecl));
6566 return -1;
6567 }
6568 return res->index;
6569 }
6570
6571 unsigned index = 0;
6572 for (tree p = DECL_ARGUMENTS (fndecl); p; p = DECL_CHAIN (p), index++)
6573 if (p == param)
6574 return (int) index;
6575
6576 gcc_assert (DECL_STATIC_CHAIN (fndecl));
6577 return -1;
6578 }
6579
6580 /* Helper function to qsort a vector of ipa_uid_to_idx_map_elt elements
6581 according to the uid. */
6582
6583 static int
6584 compare_uids (const void *a, const void *b)
6585 {
6586 const ipa_uid_to_idx_map_elt *e1 = (const ipa_uid_to_idx_map_elt *) a;
6587 const ipa_uid_to_idx_map_elt *e2 = (const ipa_uid_to_idx_map_elt *) b;
6588 if (e1->uid < e2->uid)
6589 return -1;
6590 if (e1->uid > e2->uid)
6591 return 1;
6592 gcc_unreachable ();
6593 }
6594
6595 /* Assuming THIS describes FNDECL and it has sufficiently many parameters to
6596 justify the overhead, create a DECL_UID-sorted vector to speed up mapping
6597 from parameters to their indices in DECL_ARGUMENTS chain. */
6598
6599 void
6600 ipcp_transformation::maybe_create_parm_idx_map (tree fndecl)
6601 {
6602 int c = count_formal_params (fndecl);
6603 if (c < 32)
6604 return;
6605
6606 m_uid_to_idx = NULL;
6607 vec_safe_reserve (m_uid_to_idx, c, true);
6608 unsigned index = 0;
6609 for (tree p = DECL_ARGUMENTS (fndecl); p; p = DECL_CHAIN (p), index++)
6610 {
6611 ipa_uid_to_idx_map_elt elt;
6612 elt.uid = DECL_UID (p);
6613 elt.index = index;
6614 m_uid_to_idx->quick_push (elt);
6615 }
6616 m_uid_to_idx->qsort (compare_uids);
6617 }