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