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