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