Add -fipa-cp-alignment
[gcc.git] / gcc / ipa-cp.c
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2015 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.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
102
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "hash-set.h"
107 #include "machmode.h"
108 #include "vec.h"
109 #include "hash-map.h"
110 #include "double-int.h"
111 #include "input.h"
112 #include "alias.h"
113 #include "symtab.h"
114 #include "options.h"
115 #include "wide-int.h"
116 #include "inchash.h"
117 #include "tree.h"
118 #include "fold-const.h"
119 #include "gimple-fold.h"
120 #include "gimple-expr.h"
121 #include "target.h"
122 #include "predict.h"
123 #include "basic-block.h"
124 #include "is-a.h"
125 #include "plugin-api.h"
126 #include "tm.h"
127 #include "hard-reg-set.h"
128 #include "input.h"
129 #include "function.h"
130 #include "ipa-ref.h"
131 #include "cgraph.h"
132 #include "alloc-pool.h"
133 #include "symbol-summary.h"
134 #include "ipa-prop.h"
135 #include "bitmap.h"
136 #include "tree-pass.h"
137 #include "flags.h"
138 #include "diagnostic.h"
139 #include "tree-pretty-print.h"
140 #include "tree-inline.h"
141 #include "params.h"
142 #include "ipa-inline.h"
143 #include "ipa-utils.h"
144
145 template <typename valtype> class ipcp_value;
146
147 /* Describes a particular source for an IPA-CP value. */
148
149 template <typename valtype>
150 class ipcp_value_source
151 {
152 public:
153 /* Aggregate offset of the source, negative if the source is scalar value of
154 the argument itself. */
155 HOST_WIDE_INT offset;
156 /* The incoming edge that brought the value. */
157 cgraph_edge *cs;
158 /* If the jump function that resulted into his value was a pass-through or an
159 ancestor, this is the ipcp_value of the caller from which the described
160 value has been derived. Otherwise it is NULL. */
161 ipcp_value<valtype> *val;
162 /* Next pointer in a linked list of sources of a value. */
163 ipcp_value_source *next;
164 /* If the jump function that resulted into his value was a pass-through or an
165 ancestor, this is the index of the parameter of the caller the jump
166 function references. */
167 int index;
168 };
169
170 /* Common ancestor for all ipcp_value instantiations. */
171
172 class ipcp_value_base
173 {
174 public:
175 /* Time benefit and size cost that specializing the function for this value
176 would bring about in this function alone. */
177 int local_time_benefit, local_size_cost;
178 /* Time benefit and size cost that specializing the function for this value
179 can bring about in it's callees (transitively). */
180 int prop_time_benefit, prop_size_cost;
181 };
182
183 /* Describes one particular value stored in struct ipcp_lattice. */
184
185 template <typename valtype>
186 class ipcp_value : public ipcp_value_base
187 {
188 public:
189 /* The actual value for the given parameter. */
190 valtype value;
191 /* The list of sources from which this value originates. */
192 ipcp_value_source <valtype> *sources;
193 /* Next pointers in a linked list of all values in a lattice. */
194 ipcp_value *next;
195 /* Next pointers in a linked list of values in a strongly connected component
196 of values. */
197 ipcp_value *scc_next;
198 /* Next pointers in a linked list of SCCs of values sorted topologically
199 according their sources. */
200 ipcp_value *topo_next;
201 /* A specialized node created for this value, NULL if none has been (so far)
202 created. */
203 cgraph_node *spec_node;
204 /* Depth first search number and low link for topological sorting of
205 values. */
206 int dfs, low_link;
207 /* True if this valye is currently on the topo-sort stack. */
208 bool on_stack;
209
210 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
211 HOST_WIDE_INT offset);
212 };
213
214 /* Lattice describing potential values of a formal parameter of a function, or
215 a part of an aggreagate. TOP is represented by a lattice with zero values
216 and with contains_variable and bottom flags cleared. BOTTOM is represented
217 by a lattice with the bottom flag set. In that case, values and
218 contains_variable flag should be disregarded. */
219
220 template <typename valtype>
221 class ipcp_lattice
222 {
223 public:
224 /* The list of known values and types in this lattice. Note that values are
225 not deallocated if a lattice is set to bottom because there may be value
226 sources referencing them. */
227 ipcp_value<valtype> *values;
228 /* Number of known values and types in this lattice. */
229 int values_count;
230 /* The lattice contains a variable component (in addition to values). */
231 bool contains_variable;
232 /* The value of the lattice is bottom (i.e. variable and unusable for any
233 propagation). */
234 bool bottom;
235
236 inline bool is_single_const ();
237 inline bool set_to_bottom ();
238 inline bool set_contains_variable ();
239 bool add_value (valtype newval, cgraph_edge *cs,
240 ipcp_value<valtype> *src_val = NULL,
241 int src_idx = 0, HOST_WIDE_INT offset = -1);
242 void print (FILE * f, bool dump_sources, bool dump_benefits);
243 };
244
245 /* Lattice of tree values with an offset to describe a part of an
246 aggregate. */
247
248 class ipcp_agg_lattice : public ipcp_lattice<tree>
249 {
250 public:
251 /* Offset that is being described by this lattice. */
252 HOST_WIDE_INT offset;
253 /* Size so that we don't have to re-compute it every time we traverse the
254 list. Must correspond to TYPE_SIZE of all lat values. */
255 HOST_WIDE_INT size;
256 /* Next element of the linked list. */
257 struct ipcp_agg_lattice *next;
258 };
259
260 /* Structure containing lattices for a parameter itself and for pieces of
261 aggregates that are passed in the parameter or by a reference in a parameter
262 plus some other useful flags. */
263
264 class ipcp_param_lattices
265 {
266 public:
267 /* Lattice describing the value of the parameter itself. */
268 ipcp_lattice<tree> itself;
269 /* Lattice describing the the polymorphic contexts of a parameter. */
270 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
271 /* Lattices describing aggregate parts. */
272 ipcp_agg_lattice *aggs;
273 /* Alignment information. Very basic one value lattice where !known means
274 TOP and zero alignment bottom. */
275 ipa_alignment alignment;
276 /* Number of aggregate lattices */
277 int aggs_count;
278 /* True if aggregate data were passed by reference (as opposed to by
279 value). */
280 bool aggs_by_ref;
281 /* All aggregate lattices contain a variable component (in addition to
282 values). */
283 bool aggs_contain_variable;
284 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
285 for any propagation). */
286 bool aggs_bottom;
287
288 /* There is a virtual call based on this parameter. */
289 bool virt_call;
290 };
291
292 /* Allocation pools for values and their sources in ipa-cp. */
293
294 alloc_pool ipcp_cst_values_pool;
295 alloc_pool ipcp_poly_ctx_values_pool;
296 alloc_pool ipcp_sources_pool;
297 alloc_pool ipcp_agg_lattice_pool;
298
299 /* Maximal count found in program. */
300
301 static gcov_type max_count;
302
303 /* Original overall size of the program. */
304
305 static long overall_size, max_new_size;
306
307 /* Return the param lattices structure corresponding to the Ith formal
308 parameter of the function described by INFO. */
309 static inline struct ipcp_param_lattices *
310 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
311 {
312 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
313 gcc_checking_assert (!info->ipcp_orig_node);
314 gcc_checking_assert (info->lattices);
315 return &(info->lattices[i]);
316 }
317
318 /* Return the lattice corresponding to the scalar value of the Ith formal
319 parameter of the function described by INFO. */
320 static inline ipcp_lattice<tree> *
321 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
322 {
323 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
324 return &plats->itself;
325 }
326
327 /* Return the lattice corresponding to the scalar value of the Ith formal
328 parameter of the function described by INFO. */
329 static inline ipcp_lattice<ipa_polymorphic_call_context> *
330 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
331 {
332 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
333 return &plats->ctxlat;
334 }
335
336 /* Return whether LAT is a lattice with a single constant and without an
337 undefined value. */
338
339 template <typename valtype>
340 inline bool
341 ipcp_lattice<valtype>::is_single_const ()
342 {
343 if (bottom || contains_variable || values_count != 1)
344 return false;
345 else
346 return true;
347 }
348
349 /* Print V which is extracted from a value in a lattice to F. */
350
351 static void
352 print_ipcp_constant_value (FILE * f, tree v)
353 {
354 if (TREE_CODE (v) == ADDR_EXPR
355 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
356 {
357 fprintf (f, "& ");
358 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
359 }
360 else
361 print_generic_expr (f, v, 0);
362 }
363
364 /* Print V which is extracted from a value in a lattice to F. */
365
366 static void
367 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
368 {
369 v.dump(f, false);
370 }
371
372 /* Print a lattice LAT to F. */
373
374 template <typename valtype>
375 void
376 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
377 {
378 ipcp_value<valtype> *val;
379 bool prev = false;
380
381 if (bottom)
382 {
383 fprintf (f, "BOTTOM\n");
384 return;
385 }
386
387 if (!values_count && !contains_variable)
388 {
389 fprintf (f, "TOP\n");
390 return;
391 }
392
393 if (contains_variable)
394 {
395 fprintf (f, "VARIABLE");
396 prev = true;
397 if (dump_benefits)
398 fprintf (f, "\n");
399 }
400
401 for (val = values; val; val = val->next)
402 {
403 if (dump_benefits && prev)
404 fprintf (f, " ");
405 else if (!dump_benefits && prev)
406 fprintf (f, ", ");
407 else
408 prev = true;
409
410 print_ipcp_constant_value (f, val->value);
411
412 if (dump_sources)
413 {
414 ipcp_value_source<valtype> *s;
415
416 fprintf (f, " [from:");
417 for (s = val->sources; s; s = s->next)
418 fprintf (f, " %i(%i)", s->cs->caller->order,
419 s->cs->frequency);
420 fprintf (f, "]");
421 }
422
423 if (dump_benefits)
424 fprintf (f, " [loc_time: %i, loc_size: %i, "
425 "prop_time: %i, prop_size: %i]\n",
426 val->local_time_benefit, val->local_size_cost,
427 val->prop_time_benefit, val->prop_size_cost);
428 }
429 if (!dump_benefits)
430 fprintf (f, "\n");
431 }
432
433 /* Print all ipcp_lattices of all functions to F. */
434
435 static void
436 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
437 {
438 struct cgraph_node *node;
439 int i, count;
440
441 fprintf (f, "\nLattices:\n");
442 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
443 {
444 struct ipa_node_params *info;
445
446 info = IPA_NODE_REF (node);
447 fprintf (f, " Node: %s/%i:\n", node->name (),
448 node->order);
449 count = ipa_get_param_count (info);
450 for (i = 0; i < count; i++)
451 {
452 struct ipcp_agg_lattice *aglat;
453 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
454 fprintf (f, " param [%d]: ", i);
455 plats->itself.print (f, dump_sources, dump_benefits);
456 fprintf (f, " ctxs: ");
457 plats->ctxlat.print (f, dump_sources, dump_benefits);
458 if (plats->alignment.known && plats->alignment.align > 0)
459 fprintf (f, " Alignment %u, misalignment %u\n",
460 plats->alignment.align, plats->alignment.misalign);
461 else if (plats->alignment.known)
462 fprintf (f, " Alignment unusable\n");
463 else
464 fprintf (f, " Alignment unknown\n");
465 if (plats->virt_call)
466 fprintf (f, " virt_call flag set\n");
467
468 if (plats->aggs_bottom)
469 {
470 fprintf (f, " AGGS BOTTOM\n");
471 continue;
472 }
473 if (plats->aggs_contain_variable)
474 fprintf (f, " AGGS VARIABLE\n");
475 for (aglat = plats->aggs; aglat; aglat = aglat->next)
476 {
477 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
478 plats->aggs_by_ref ? "ref " : "", aglat->offset);
479 aglat->print (f, dump_sources, dump_benefits);
480 }
481 }
482 }
483 }
484
485 /* Determine whether it is at all technically possible to create clones of NODE
486 and store this information in the ipa_node_params structure associated
487 with NODE. */
488
489 static void
490 determine_versionability (struct cgraph_node *node)
491 {
492 const char *reason = NULL;
493
494 /* There are a number of generic reasons functions cannot be versioned. We
495 also cannot remove parameters if there are type attributes such as fnspec
496 present. */
497 if (node->alias || node->thunk.thunk_p)
498 reason = "alias or thunk";
499 else if (!node->local.versionable)
500 reason = "not a tree_versionable_function";
501 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
502 reason = "insufficient body availability";
503 else if (!opt_for_fn (node->decl, optimize)
504 || !opt_for_fn (node->decl, flag_ipa_cp))
505 reason = "non-optimized function";
506 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
507 {
508 /* Ideally we should clone the SIMD clones themselves and create
509 vector copies of them, so IPA-cp and SIMD clones can happily
510 coexist, but that may not be worth the effort. */
511 reason = "function has SIMD clones";
512 }
513 /* Don't clone decls local to a comdat group; it breaks and for C++
514 decloned constructors, inlining is always better anyway. */
515 else if (node->comdat_local_p ())
516 reason = "comdat-local function";
517
518 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
519 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
520 node->name (), node->order, reason);
521
522 node->local.versionable = (reason == NULL);
523 }
524
525 /* Return true if it is at all technically possible to create clones of a
526 NODE. */
527
528 static bool
529 ipcp_versionable_function_p (struct cgraph_node *node)
530 {
531 return node->local.versionable;
532 }
533
534 /* Structure holding accumulated information about callers of a node. */
535
536 struct caller_statistics
537 {
538 gcov_type count_sum;
539 int n_calls, n_hot_calls, freq_sum;
540 };
541
542 /* Initialize fields of STAT to zeroes. */
543
544 static inline void
545 init_caller_stats (struct caller_statistics *stats)
546 {
547 stats->count_sum = 0;
548 stats->n_calls = 0;
549 stats->n_hot_calls = 0;
550 stats->freq_sum = 0;
551 }
552
553 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
554 non-thunk incoming edges to NODE. */
555
556 static bool
557 gather_caller_stats (struct cgraph_node *node, void *data)
558 {
559 struct caller_statistics *stats = (struct caller_statistics *) data;
560 struct cgraph_edge *cs;
561
562 for (cs = node->callers; cs; cs = cs->next_caller)
563 if (!cs->caller->thunk.thunk_p)
564 {
565 stats->count_sum += cs->count;
566 stats->freq_sum += cs->frequency;
567 stats->n_calls++;
568 if (cs->maybe_hot_p ())
569 stats->n_hot_calls ++;
570 }
571 return false;
572
573 }
574
575 /* Return true if this NODE is viable candidate for cloning. */
576
577 static bool
578 ipcp_cloning_candidate_p (struct cgraph_node *node)
579 {
580 struct caller_statistics stats;
581
582 gcc_checking_assert (node->has_gimple_body_p ());
583
584 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
585 {
586 if (dump_file)
587 fprintf (dump_file, "Not considering %s for cloning; "
588 "-fipa-cp-clone disabled.\n",
589 node->name ());
590 return false;
591 }
592
593 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
594 {
595 if (dump_file)
596 fprintf (dump_file, "Not considering %s for cloning; "
597 "optimizing it for size.\n",
598 node->name ());
599 return false;
600 }
601
602 init_caller_stats (&stats);
603 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
604
605 if (inline_summaries->get (node)->self_size < stats.n_calls)
606 {
607 if (dump_file)
608 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
609 node->name ());
610 return true;
611 }
612
613 /* When profile is available and function is hot, propagate into it even if
614 calls seems cold; constant propagation can improve function's speed
615 significantly. */
616 if (max_count)
617 {
618 if (stats.count_sum > node->count * 90 / 100)
619 {
620 if (dump_file)
621 fprintf (dump_file, "Considering %s for cloning; "
622 "usually called directly.\n",
623 node->name ());
624 return true;
625 }
626 }
627 if (!stats.n_hot_calls)
628 {
629 if (dump_file)
630 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
631 node->name ());
632 return false;
633 }
634 if (dump_file)
635 fprintf (dump_file, "Considering %s for cloning.\n",
636 node->name ());
637 return true;
638 }
639
640 template <typename valtype>
641 class value_topo_info
642 {
643 public:
644 /* Head of the linked list of topologically sorted values. */
645 ipcp_value<valtype> *values_topo;
646 /* Stack for creating SCCs, represented by a linked list too. */
647 ipcp_value<valtype> *stack;
648 /* Counter driving the algorithm in add_val_to_toposort. */
649 int dfs_counter;
650
651 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
652 {}
653 void add_val (ipcp_value<valtype> *cur_val);
654 void propagate_effects ();
655 };
656
657 /* Arrays representing a topological ordering of call graph nodes and a stack
658 of nodes used during constant propagation and also data required to perform
659 topological sort of values and propagation of benefits in the determined
660 order. */
661
662 class ipa_topo_info
663 {
664 public:
665 /* Array with obtained topological order of cgraph nodes. */
666 struct cgraph_node **order;
667 /* Stack of cgraph nodes used during propagation within SCC until all values
668 in the SCC stabilize. */
669 struct cgraph_node **stack;
670 int nnodes, stack_top;
671
672 value_topo_info<tree> constants;
673 value_topo_info<ipa_polymorphic_call_context> contexts;
674
675 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
676 constants ()
677 {}
678 };
679
680 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
681
682 static void
683 build_toporder_info (struct ipa_topo_info *topo)
684 {
685 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
686 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
687
688 gcc_checking_assert (topo->stack_top == 0);
689 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
690 }
691
692 /* Free information about strongly connected components and the arrays in
693 TOPO. */
694
695 static void
696 free_toporder_info (struct ipa_topo_info *topo)
697 {
698 ipa_free_postorder_info ();
699 free (topo->order);
700 free (topo->stack);
701 }
702
703 /* Add NODE to the stack in TOPO, unless it is already there. */
704
705 static inline void
706 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
707 {
708 struct ipa_node_params *info = IPA_NODE_REF (node);
709 if (info->node_enqueued)
710 return;
711 info->node_enqueued = 1;
712 topo->stack[topo->stack_top++] = node;
713 }
714
715 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
716 is empty. */
717
718 static struct cgraph_node *
719 pop_node_from_stack (struct ipa_topo_info *topo)
720 {
721 if (topo->stack_top)
722 {
723 struct cgraph_node *node;
724 topo->stack_top--;
725 node = topo->stack[topo->stack_top];
726 IPA_NODE_REF (node)->node_enqueued = 0;
727 return node;
728 }
729 else
730 return NULL;
731 }
732
733 /* Set lattice LAT to bottom and return true if it previously was not set as
734 such. */
735
736 template <typename valtype>
737 inline bool
738 ipcp_lattice<valtype>::set_to_bottom ()
739 {
740 bool ret = !bottom;
741 bottom = true;
742 return ret;
743 }
744
745 /* Mark lattice as containing an unknown value and return true if it previously
746 was not marked as such. */
747
748 template <typename valtype>
749 inline bool
750 ipcp_lattice<valtype>::set_contains_variable ()
751 {
752 bool ret = !contains_variable;
753 contains_variable = true;
754 return ret;
755 }
756
757 /* Set all aggegate lattices in PLATS to bottom and return true if they were
758 not previously set as such. */
759
760 static inline bool
761 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
762 {
763 bool ret = !plats->aggs_bottom;
764 plats->aggs_bottom = true;
765 return ret;
766 }
767
768 /* Mark all aggegate lattices in PLATS as containing an unknown value and
769 return true if they were not previously marked as such. */
770
771 static inline bool
772 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
773 {
774 bool ret = !plats->aggs_contain_variable;
775 plats->aggs_contain_variable = true;
776 return ret;
777 }
778
779 /* Return true if alignment information in PLATS is known to be unusable. */
780
781 static inline bool
782 alignment_bottom_p (ipcp_param_lattices *plats)
783 {
784 return plats->alignment.known && (plats->alignment.align == 0);
785 }
786
787 /* Set alignment information in PLATS to unusable. Return true if it
788 previously was usable or unknown. */
789
790 static inline bool
791 set_alignment_to_bottom (ipcp_param_lattices *plats)
792 {
793 if (alignment_bottom_p (plats))
794 return false;
795 plats->alignment.known = true;
796 plats->alignment.align = 0;
797 return true;
798 }
799
800 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
801 return true is any of them has not been marked as such so far. */
802
803 static inline bool
804 set_all_contains_variable (struct ipcp_param_lattices *plats)
805 {
806 bool ret;
807 ret = plats->itself.set_contains_variable ();
808 ret |= plats->ctxlat.set_contains_variable ();
809 ret |= set_agg_lats_contain_variable (plats);
810 ret |= set_alignment_to_bottom (plats);
811 return ret;
812 }
813
814 /* Initialize ipcp_lattices. */
815
816 static void
817 initialize_node_lattices (struct cgraph_node *node)
818 {
819 struct ipa_node_params *info = IPA_NODE_REF (node);
820 struct cgraph_edge *ie;
821 bool disable = false, variable = false;
822 int i;
823
824 gcc_checking_assert (node->has_gimple_body_p ());
825 if (!cgraph_local_p (node))
826 {
827 /* When cloning is allowed, we can assume that externally visible
828 functions are not called. We will compensate this by cloning
829 later. */
830 if (ipcp_versionable_function_p (node)
831 && ipcp_cloning_candidate_p (node))
832 variable = true;
833 else
834 disable = true;
835 }
836
837 if (disable || variable)
838 {
839 for (i = 0; i < ipa_get_param_count (info) ; i++)
840 {
841 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
842 if (disable)
843 {
844 plats->itself.set_to_bottom ();
845 plats->ctxlat.set_to_bottom ();
846 set_agg_lats_to_bottom (plats);
847 set_alignment_to_bottom (plats);
848 }
849 else
850 set_all_contains_variable (plats);
851 }
852 if (dump_file && (dump_flags & TDF_DETAILS)
853 && !node->alias && !node->thunk.thunk_p)
854 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
855 node->name (), node->order,
856 disable ? "BOTTOM" : "VARIABLE");
857 }
858
859 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
860 if (ie->indirect_info->polymorphic
861 && ie->indirect_info->param_index >= 0)
862 {
863 gcc_checking_assert (ie->indirect_info->param_index >= 0);
864 ipa_get_parm_lattices (info,
865 ie->indirect_info->param_index)->virt_call = 1;
866 }
867 }
868
869 /* Return the result of a (possibly arithmetic) pass through jump function
870 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
871 determined or be considered an interprocedural invariant. */
872
873 static tree
874 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
875 {
876 tree restype, res;
877
878 gcc_checking_assert (is_gimple_ip_invariant (input));
879 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
880 return input;
881
882 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
883 == tcc_comparison)
884 restype = boolean_type_node;
885 else
886 restype = TREE_TYPE (input);
887 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
888 input, ipa_get_jf_pass_through_operand (jfunc));
889
890 if (res && !is_gimple_ip_invariant (res))
891 return NULL_TREE;
892
893 return res;
894 }
895
896 /* Return the result of an ancestor jump function JFUNC on the constant value
897 INPUT. Return NULL_TREE if that cannot be determined. */
898
899 static tree
900 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
901 {
902 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
903 if (TREE_CODE (input) == ADDR_EXPR)
904 {
905 tree t = TREE_OPERAND (input, 0);
906 t = build_ref_for_offset (EXPR_LOCATION (t), t,
907 ipa_get_jf_ancestor_offset (jfunc),
908 ptr_type_node, NULL, false);
909 return build_fold_addr_expr (t);
910 }
911 else
912 return NULL_TREE;
913 }
914
915 /* Determine whether JFUNC evaluates to a single known constant value and if
916 so, return it. Otherwise return NULL. INFO describes the caller node or
917 the one it is inlined to, so that pass-through jump functions can be
918 evaluated. */
919
920 tree
921 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
922 {
923 if (jfunc->type == IPA_JF_CONST)
924 return ipa_get_jf_constant (jfunc);
925 else if (jfunc->type == IPA_JF_PASS_THROUGH
926 || jfunc->type == IPA_JF_ANCESTOR)
927 {
928 tree input;
929 int idx;
930
931 if (jfunc->type == IPA_JF_PASS_THROUGH)
932 idx = ipa_get_jf_pass_through_formal_id (jfunc);
933 else
934 idx = ipa_get_jf_ancestor_formal_id (jfunc);
935
936 if (info->ipcp_orig_node)
937 input = info->known_csts[idx];
938 else
939 {
940 ipcp_lattice<tree> *lat;
941
942 if (!info->lattices
943 || idx >= ipa_get_param_count (info))
944 return NULL_TREE;
945 lat = ipa_get_scalar_lat (info, idx);
946 if (!lat->is_single_const ())
947 return NULL_TREE;
948 input = lat->values->value;
949 }
950
951 if (!input)
952 return NULL_TREE;
953
954 if (jfunc->type == IPA_JF_PASS_THROUGH)
955 return ipa_get_jf_pass_through_result (jfunc, input);
956 else
957 return ipa_get_jf_ancestor_result (jfunc, input);
958 }
959 else
960 return NULL_TREE;
961 }
962
963 /* Determie whether JFUNC evaluates to single known polymorphic context, given
964 that INFO describes the caller node or the one it is inlined to, CS is the
965 call graph edge corresponding to JFUNC and CSIDX index of the described
966 parameter. */
967
968 ipa_polymorphic_call_context
969 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
970 ipa_jump_func *jfunc)
971 {
972 ipa_edge_args *args = IPA_EDGE_REF (cs);
973 ipa_polymorphic_call_context ctx;
974 ipa_polymorphic_call_context *edge_ctx
975 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
976
977 if (edge_ctx && !edge_ctx->useless_p ())
978 ctx = *edge_ctx;
979
980 if (jfunc->type == IPA_JF_PASS_THROUGH
981 || jfunc->type == IPA_JF_ANCESTOR)
982 {
983 ipa_polymorphic_call_context srcctx;
984 int srcidx;
985 bool type_preserved = true;
986 if (jfunc->type == IPA_JF_PASS_THROUGH)
987 {
988 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
989 return ctx;
990 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
991 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
992 }
993 else
994 {
995 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
996 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
997 }
998 if (info->ipcp_orig_node)
999 {
1000 if (info->known_contexts.exists ())
1001 srcctx = info->known_contexts[srcidx];
1002 }
1003 else
1004 {
1005 if (!info->lattices
1006 || srcidx >= ipa_get_param_count (info))
1007 return ctx;
1008 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1009 lat = ipa_get_poly_ctx_lat (info, srcidx);
1010 if (!lat->is_single_const ())
1011 return ctx;
1012 srcctx = lat->values->value;
1013 }
1014 if (srcctx.useless_p ())
1015 return ctx;
1016 if (jfunc->type == IPA_JF_ANCESTOR)
1017 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1018 if (!type_preserved)
1019 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1020 srcctx.combine_with (ctx);
1021 return srcctx;
1022 }
1023
1024 return ctx;
1025 }
1026
1027 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1028 bottom, not containing a variable component and without any known value at
1029 the same time. */
1030
1031 DEBUG_FUNCTION void
1032 ipcp_verify_propagated_values (void)
1033 {
1034 struct cgraph_node *node;
1035
1036 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1037 {
1038 struct ipa_node_params *info = IPA_NODE_REF (node);
1039 int i, count = ipa_get_param_count (info);
1040
1041 for (i = 0; i < count; i++)
1042 {
1043 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1044
1045 if (!lat->bottom
1046 && !lat->contains_variable
1047 && lat->values_count == 0)
1048 {
1049 if (dump_file)
1050 {
1051 symtab_node::dump_table (dump_file);
1052 fprintf (dump_file, "\nIPA lattices after constant "
1053 "propagation, before gcc_unreachable:\n");
1054 print_all_lattices (dump_file, true, false);
1055 }
1056
1057 gcc_unreachable ();
1058 }
1059 }
1060 }
1061 }
1062
1063 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1064
1065 static bool
1066 values_equal_for_ipcp_p (tree x, tree y)
1067 {
1068 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1069
1070 if (x == y)
1071 return true;
1072
1073 if (TREE_CODE (x) == ADDR_EXPR
1074 && TREE_CODE (y) == ADDR_EXPR
1075 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1076 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1077 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1078 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1079 else
1080 return operand_equal_p (x, y, 0);
1081 }
1082
1083 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1084
1085 static bool
1086 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1087 ipa_polymorphic_call_context y)
1088 {
1089 return x.equal_to (y);
1090 }
1091
1092
1093 /* Add a new value source to the value represented by THIS, marking that a
1094 value comes from edge CS and (if the underlying jump function is a
1095 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1096 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1097 scalar value of the parameter itself or the offset within an aggregate. */
1098
1099 template <typename valtype>
1100 void
1101 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1102 int src_idx, HOST_WIDE_INT offset)
1103 {
1104 ipcp_value_source<valtype> *src;
1105
1106 src = new (pool_alloc (ipcp_sources_pool)) ipcp_value_source<valtype>;
1107 src->offset = offset;
1108 src->cs = cs;
1109 src->val = src_val;
1110 src->index = src_idx;
1111
1112 src->next = sources;
1113 sources = src;
1114 }
1115
1116 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1117 SOURCE and clear all other fields. */
1118
1119 static ipcp_value<tree> *
1120 allocate_and_init_ipcp_value (tree source)
1121 {
1122 ipcp_value<tree> *val;
1123
1124 val = new (pool_alloc (ipcp_cst_values_pool)) ipcp_value<tree>;
1125 memset (val, 0, sizeof (*val));
1126 val->value = source;
1127 return val;
1128 }
1129
1130 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1131 value to SOURCE and clear all other fields. */
1132
1133 static ipcp_value<ipa_polymorphic_call_context> *
1134 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1135 {
1136 ipcp_value<ipa_polymorphic_call_context> *val;
1137
1138 val = new (pool_alloc (ipcp_poly_ctx_values_pool))
1139 ipcp_value<ipa_polymorphic_call_context>;
1140 memset (val, 0, sizeof (*val));
1141 val->value = source;
1142 return val;
1143 }
1144
1145 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1146 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1147 meaning. OFFSET -1 means the source is scalar and not a part of an
1148 aggregate. */
1149
1150 template <typename valtype>
1151 bool
1152 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1153 ipcp_value<valtype> *src_val,
1154 int src_idx, HOST_WIDE_INT offset)
1155 {
1156 ipcp_value<valtype> *val;
1157
1158 if (bottom)
1159 return false;
1160
1161 for (val = values; val; val = val->next)
1162 if (values_equal_for_ipcp_p (val->value, newval))
1163 {
1164 if (ipa_edge_within_scc (cs))
1165 {
1166 ipcp_value_source<valtype> *s;
1167 for (s = val->sources; s ; s = s->next)
1168 if (s->cs == cs)
1169 break;
1170 if (s)
1171 return false;
1172 }
1173
1174 val->add_source (cs, src_val, src_idx, offset);
1175 return false;
1176 }
1177
1178 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1179 {
1180 /* We can only free sources, not the values themselves, because sources
1181 of other values in this this SCC might point to them. */
1182 for (val = values; val; val = val->next)
1183 {
1184 while (val->sources)
1185 {
1186 ipcp_value_source<valtype> *src = val->sources;
1187 val->sources = src->next;
1188 pool_free (ipcp_sources_pool, src);
1189 }
1190 }
1191
1192 values = NULL;
1193 return set_to_bottom ();
1194 }
1195
1196 values_count++;
1197 val = allocate_and_init_ipcp_value (newval);
1198 val->add_source (cs, src_val, src_idx, offset);
1199 val->next = values;
1200 values = val;
1201 return true;
1202 }
1203
1204 /* Propagate values through a pass-through jump function JFUNC associated with
1205 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1206 is the index of the source parameter. */
1207
1208 static bool
1209 propagate_vals_accross_pass_through (cgraph_edge *cs,
1210 ipa_jump_func *jfunc,
1211 ipcp_lattice<tree> *src_lat,
1212 ipcp_lattice<tree> *dest_lat,
1213 int src_idx)
1214 {
1215 ipcp_value<tree> *src_val;
1216 bool ret = false;
1217
1218 /* Do not create new values when propagating within an SCC because if there
1219 are arithmetic functions with circular dependencies, there is infinite
1220 number of them and we would just make lattices bottom. */
1221 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1222 && ipa_edge_within_scc (cs))
1223 ret = dest_lat->set_contains_variable ();
1224 else
1225 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1226 {
1227 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1228
1229 if (cstval)
1230 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1231 else
1232 ret |= dest_lat->set_contains_variable ();
1233 }
1234
1235 return ret;
1236 }
1237
1238 /* Propagate values through an ancestor jump function JFUNC associated with
1239 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1240 is the index of the source parameter. */
1241
1242 static bool
1243 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1244 struct ipa_jump_func *jfunc,
1245 ipcp_lattice<tree> *src_lat,
1246 ipcp_lattice<tree> *dest_lat,
1247 int src_idx)
1248 {
1249 ipcp_value<tree> *src_val;
1250 bool ret = false;
1251
1252 if (ipa_edge_within_scc (cs))
1253 return dest_lat->set_contains_variable ();
1254
1255 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1256 {
1257 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1258
1259 if (t)
1260 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1261 else
1262 ret |= dest_lat->set_contains_variable ();
1263 }
1264
1265 return ret;
1266 }
1267
1268 /* Propagate scalar values across jump function JFUNC that is associated with
1269 edge CS and put the values into DEST_LAT. */
1270
1271 static bool
1272 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1273 struct ipa_jump_func *jfunc,
1274 ipcp_lattice<tree> *dest_lat)
1275 {
1276 if (dest_lat->bottom)
1277 return false;
1278
1279 if (jfunc->type == IPA_JF_CONST)
1280 {
1281 tree val = ipa_get_jf_constant (jfunc);
1282 return dest_lat->add_value (val, cs, NULL, 0);
1283 }
1284 else if (jfunc->type == IPA_JF_PASS_THROUGH
1285 || jfunc->type == IPA_JF_ANCESTOR)
1286 {
1287 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1288 ipcp_lattice<tree> *src_lat;
1289 int src_idx;
1290 bool ret;
1291
1292 if (jfunc->type == IPA_JF_PASS_THROUGH)
1293 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1294 else
1295 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1296
1297 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1298 if (src_lat->bottom)
1299 return dest_lat->set_contains_variable ();
1300
1301 /* If we would need to clone the caller and cannot, do not propagate. */
1302 if (!ipcp_versionable_function_p (cs->caller)
1303 && (src_lat->contains_variable
1304 || (src_lat->values_count > 1)))
1305 return dest_lat->set_contains_variable ();
1306
1307 if (jfunc->type == IPA_JF_PASS_THROUGH)
1308 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1309 dest_lat, src_idx);
1310 else
1311 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1312 src_idx);
1313
1314 if (src_lat->contains_variable)
1315 ret |= dest_lat->set_contains_variable ();
1316
1317 return ret;
1318 }
1319
1320 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1321 use it for indirect inlining), we should propagate them too. */
1322 return dest_lat->set_contains_variable ();
1323 }
1324
1325 /* Propagate scalar values across jump function JFUNC that is associated with
1326 edge CS and describes argument IDX and put the values into DEST_LAT. */
1327
1328 static bool
1329 propagate_context_accross_jump_function (cgraph_edge *cs,
1330 ipa_jump_func *jfunc, int idx,
1331 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1332 {
1333 ipa_edge_args *args = IPA_EDGE_REF (cs);
1334 if (dest_lat->bottom)
1335 return false;
1336 bool ret = false;
1337 bool added_sth = false;
1338 bool type_preserved = true;
1339
1340 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1341 = ipa_get_ith_polymorhic_call_context (args, idx);
1342
1343 if (edge_ctx_ptr)
1344 edge_ctx = *edge_ctx_ptr;
1345
1346 if (jfunc->type == IPA_JF_PASS_THROUGH
1347 || jfunc->type == IPA_JF_ANCESTOR)
1348 {
1349 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1350 int src_idx;
1351 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1352
1353 /* TODO: Once we figure out how to propagate speculations, it will
1354 probably be a good idea to switch to speculation if type_preserved is
1355 not set instead of punting. */
1356 if (jfunc->type == IPA_JF_PASS_THROUGH)
1357 {
1358 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1359 goto prop_fail;
1360 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1361 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1362 }
1363 else
1364 {
1365 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1366 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1367 }
1368
1369 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1370 /* If we would need to clone the caller and cannot, do not propagate. */
1371 if (!ipcp_versionable_function_p (cs->caller)
1372 && (src_lat->contains_variable
1373 || (src_lat->values_count > 1)))
1374 goto prop_fail;
1375
1376 ipcp_value<ipa_polymorphic_call_context> *src_val;
1377 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1378 {
1379 ipa_polymorphic_call_context cur = src_val->value;
1380
1381 if (!type_preserved)
1382 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1383 if (jfunc->type == IPA_JF_ANCESTOR)
1384 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1385 /* TODO: In cases we know how the context is going to be used,
1386 we can improve the result by passing proper OTR_TYPE. */
1387 cur.combine_with (edge_ctx);
1388 if (!cur.useless_p ())
1389 {
1390 if (src_lat->contains_variable
1391 && !edge_ctx.equal_to (cur))
1392 ret |= dest_lat->set_contains_variable ();
1393 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1394 added_sth = true;
1395 }
1396 }
1397
1398 }
1399
1400 prop_fail:
1401 if (!added_sth)
1402 {
1403 if (!edge_ctx.useless_p ())
1404 ret |= dest_lat->add_value (edge_ctx, cs);
1405 else
1406 ret |= dest_lat->set_contains_variable ();
1407 }
1408
1409 return ret;
1410 }
1411
1412 /* Propagate alignments across jump function JFUNC that is associated with
1413 edge CS and update DEST_LAT accordingly. */
1414
1415 static bool
1416 propagate_alignment_accross_jump_function (struct cgraph_edge *cs,
1417 struct ipa_jump_func *jfunc,
1418 struct ipcp_param_lattices *dest_lat)
1419 {
1420 if (alignment_bottom_p (dest_lat))
1421 return false;
1422
1423 ipa_alignment cur;
1424 cur.known = false;
1425 if (jfunc->alignment.known)
1426 cur = jfunc->alignment;
1427 else if (jfunc->type == IPA_JF_PASS_THROUGH
1428 || jfunc->type == IPA_JF_ANCESTOR)
1429 {
1430 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1431 struct ipcp_param_lattices *src_lats;
1432 HOST_WIDE_INT offset = 0;
1433 int src_idx;
1434
1435 if (jfunc->type == IPA_JF_PASS_THROUGH)
1436 {
1437 enum tree_code op = ipa_get_jf_pass_through_operation (jfunc);
1438 if (op != NOP_EXPR)
1439 {
1440 if (op != POINTER_PLUS_EXPR
1441 && op != PLUS_EXPR
1442 && op != MINUS_EXPR)
1443 goto prop_fail;
1444 tree operand = ipa_get_jf_pass_through_operand (jfunc);
1445 if (!tree_fits_shwi_p (operand))
1446 goto prop_fail;
1447 offset = tree_to_shwi (operand);
1448 }
1449 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1450 }
1451 else
1452 {
1453 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1454 offset = ipa_get_jf_ancestor_offset (jfunc);
1455 }
1456
1457 src_lats = ipa_get_parm_lattices (caller_info, src_idx);
1458 if (!src_lats->alignment.known
1459 || alignment_bottom_p (src_lats))
1460 goto prop_fail;
1461
1462 cur = src_lats->alignment;
1463 cur.misalign = (cur.misalign + offset) % cur.align;
1464 }
1465
1466 if (cur.known)
1467 {
1468 if (!dest_lat->alignment.known)
1469 {
1470 dest_lat->alignment = cur;
1471 return true;
1472 }
1473 else if (dest_lat->alignment.align == cur.align
1474 && dest_lat->alignment.misalign == cur.misalign)
1475 return false;
1476 }
1477
1478 prop_fail:
1479 set_alignment_to_bottom (dest_lat);
1480 return true;
1481 }
1482
1483 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1484 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1485 other cases, return false). If there are no aggregate items, set
1486 aggs_by_ref to NEW_AGGS_BY_REF. */
1487
1488 static bool
1489 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1490 bool new_aggs_by_ref)
1491 {
1492 if (dest_plats->aggs)
1493 {
1494 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1495 {
1496 set_agg_lats_to_bottom (dest_plats);
1497 return true;
1498 }
1499 }
1500 else
1501 dest_plats->aggs_by_ref = new_aggs_by_ref;
1502 return false;
1503 }
1504
1505 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1506 already existing lattice for the given OFFSET and SIZE, marking all skipped
1507 lattices as containing variable and checking for overlaps. If there is no
1508 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1509 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1510 unless there are too many already. If there are two many, return false. If
1511 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1512 skipped lattices were newly marked as containing variable, set *CHANGE to
1513 true. */
1514
1515 static bool
1516 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1517 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1518 struct ipcp_agg_lattice ***aglat,
1519 bool pre_existing, bool *change)
1520 {
1521 gcc_checking_assert (offset >= 0);
1522
1523 while (**aglat && (**aglat)->offset < offset)
1524 {
1525 if ((**aglat)->offset + (**aglat)->size > offset)
1526 {
1527 set_agg_lats_to_bottom (dest_plats);
1528 return false;
1529 }
1530 *change |= (**aglat)->set_contains_variable ();
1531 *aglat = &(**aglat)->next;
1532 }
1533
1534 if (**aglat && (**aglat)->offset == offset)
1535 {
1536 if ((**aglat)->size != val_size
1537 || ((**aglat)->next
1538 && (**aglat)->next->offset < offset + val_size))
1539 {
1540 set_agg_lats_to_bottom (dest_plats);
1541 return false;
1542 }
1543 gcc_checking_assert (!(**aglat)->next
1544 || (**aglat)->next->offset >= offset + val_size);
1545 return true;
1546 }
1547 else
1548 {
1549 struct ipcp_agg_lattice *new_al;
1550
1551 if (**aglat && (**aglat)->offset < offset + val_size)
1552 {
1553 set_agg_lats_to_bottom (dest_plats);
1554 return false;
1555 }
1556 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1557 return false;
1558 dest_plats->aggs_count++;
1559 new_al = (struct ipcp_agg_lattice *) pool_alloc (ipcp_agg_lattice_pool);
1560 memset (new_al, 0, sizeof (*new_al));
1561
1562 new_al->offset = offset;
1563 new_al->size = val_size;
1564 new_al->contains_variable = pre_existing;
1565
1566 new_al->next = **aglat;
1567 **aglat = new_al;
1568 return true;
1569 }
1570 }
1571
1572 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1573 containing an unknown value. */
1574
1575 static bool
1576 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1577 {
1578 bool ret = false;
1579 while (aglat)
1580 {
1581 ret |= aglat->set_contains_variable ();
1582 aglat = aglat->next;
1583 }
1584 return ret;
1585 }
1586
1587 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1588 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1589 parameter used for lattice value sources. Return true if DEST_PLATS changed
1590 in any way. */
1591
1592 static bool
1593 merge_aggregate_lattices (struct cgraph_edge *cs,
1594 struct ipcp_param_lattices *dest_plats,
1595 struct ipcp_param_lattices *src_plats,
1596 int src_idx, HOST_WIDE_INT offset_delta)
1597 {
1598 bool pre_existing = dest_plats->aggs != NULL;
1599 struct ipcp_agg_lattice **dst_aglat;
1600 bool ret = false;
1601
1602 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1603 return true;
1604 if (src_plats->aggs_bottom)
1605 return set_agg_lats_contain_variable (dest_plats);
1606 if (src_plats->aggs_contain_variable)
1607 ret |= set_agg_lats_contain_variable (dest_plats);
1608 dst_aglat = &dest_plats->aggs;
1609
1610 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1611 src_aglat;
1612 src_aglat = src_aglat->next)
1613 {
1614 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1615
1616 if (new_offset < 0)
1617 continue;
1618 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1619 &dst_aglat, pre_existing, &ret))
1620 {
1621 struct ipcp_agg_lattice *new_al = *dst_aglat;
1622
1623 dst_aglat = &(*dst_aglat)->next;
1624 if (src_aglat->bottom)
1625 {
1626 ret |= new_al->set_contains_variable ();
1627 continue;
1628 }
1629 if (src_aglat->contains_variable)
1630 ret |= new_al->set_contains_variable ();
1631 for (ipcp_value<tree> *val = src_aglat->values;
1632 val;
1633 val = val->next)
1634 ret |= new_al->add_value (val->value, cs, val, src_idx,
1635 src_aglat->offset);
1636 }
1637 else if (dest_plats->aggs_bottom)
1638 return true;
1639 }
1640 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1641 return ret;
1642 }
1643
1644 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1645 pass-through JFUNC and if so, whether it has conform and conforms to the
1646 rules about propagating values passed by reference. */
1647
1648 static bool
1649 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1650 struct ipa_jump_func *jfunc)
1651 {
1652 return src_plats->aggs
1653 && (!src_plats->aggs_by_ref
1654 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1655 }
1656
1657 /* Propagate scalar values across jump function JFUNC that is associated with
1658 edge CS and put the values into DEST_LAT. */
1659
1660 static bool
1661 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1662 struct ipa_jump_func *jfunc,
1663 struct ipcp_param_lattices *dest_plats)
1664 {
1665 bool ret = false;
1666
1667 if (dest_plats->aggs_bottom)
1668 return false;
1669
1670 if (jfunc->type == IPA_JF_PASS_THROUGH
1671 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1672 {
1673 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1674 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1675 struct ipcp_param_lattices *src_plats;
1676
1677 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1678 if (agg_pass_through_permissible_p (src_plats, jfunc))
1679 {
1680 /* Currently we do not produce clobber aggregate jump
1681 functions, replace with merging when we do. */
1682 gcc_assert (!jfunc->agg.items);
1683 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1684 src_idx, 0);
1685 }
1686 else
1687 ret |= set_agg_lats_contain_variable (dest_plats);
1688 }
1689 else if (jfunc->type == IPA_JF_ANCESTOR
1690 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1691 {
1692 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1693 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1694 struct ipcp_param_lattices *src_plats;
1695
1696 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1697 if (src_plats->aggs && src_plats->aggs_by_ref)
1698 {
1699 /* Currently we do not produce clobber aggregate jump
1700 functions, replace with merging when we do. */
1701 gcc_assert (!jfunc->agg.items);
1702 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1703 ipa_get_jf_ancestor_offset (jfunc));
1704 }
1705 else if (!src_plats->aggs_by_ref)
1706 ret |= set_agg_lats_to_bottom (dest_plats);
1707 else
1708 ret |= set_agg_lats_contain_variable (dest_plats);
1709 }
1710 else if (jfunc->agg.items)
1711 {
1712 bool pre_existing = dest_plats->aggs != NULL;
1713 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1714 struct ipa_agg_jf_item *item;
1715 int i;
1716
1717 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1718 return true;
1719
1720 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1721 {
1722 HOST_WIDE_INT val_size;
1723
1724 if (item->offset < 0)
1725 continue;
1726 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1727 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
1728
1729 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1730 &aglat, pre_existing, &ret))
1731 {
1732 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
1733 aglat = &(*aglat)->next;
1734 }
1735 else if (dest_plats->aggs_bottom)
1736 return true;
1737 }
1738
1739 ret |= set_chain_of_aglats_contains_variable (*aglat);
1740 }
1741 else
1742 ret |= set_agg_lats_contain_variable (dest_plats);
1743
1744 return ret;
1745 }
1746
1747 /* Propagate constants from the caller to the callee of CS. INFO describes the
1748 caller. */
1749
1750 static bool
1751 propagate_constants_accross_call (struct cgraph_edge *cs)
1752 {
1753 struct ipa_node_params *callee_info;
1754 enum availability availability;
1755 struct cgraph_node *callee, *alias_or_thunk;
1756 struct ipa_edge_args *args;
1757 bool ret = false;
1758 int i, args_count, parms_count;
1759
1760 callee = cs->callee->function_symbol (&availability);
1761 if (!callee->definition)
1762 return false;
1763 gcc_checking_assert (callee->has_gimple_body_p ());
1764 callee_info = IPA_NODE_REF (callee);
1765
1766 args = IPA_EDGE_REF (cs);
1767 args_count = ipa_get_cs_argument_count (args);
1768 parms_count = ipa_get_param_count (callee_info);
1769 if (parms_count == 0)
1770 return false;
1771
1772 /* No propagation through instrumentation thunks is available yet.
1773 It should be possible with proper mapping of call args and
1774 instrumented callee params in the propagation loop below. But
1775 this case mostly occurs when legacy code calls instrumented code
1776 and it is not a primary target for optimizations.
1777 We detect instrumentation thunks in aliases and thunks chain by
1778 checking instrumentation_clone flag for chain source and target.
1779 Going through instrumentation thunks we always have it changed
1780 from 0 to 1 and all other nodes do not change it. */
1781 if (!cs->callee->instrumentation_clone
1782 && callee->instrumentation_clone)
1783 {
1784 for (i = 0; i < parms_count; i++)
1785 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1786 i));
1787 return ret;
1788 }
1789
1790 /* If this call goes through a thunk we must not propagate to the first (0th)
1791 parameter. However, we might need to uncover a thunk from below a series
1792 of aliases first. */
1793 alias_or_thunk = cs->callee;
1794 while (alias_or_thunk->alias)
1795 alias_or_thunk = alias_or_thunk->get_alias_target ();
1796 if (alias_or_thunk->thunk.thunk_p)
1797 {
1798 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1799 0));
1800 i = 1;
1801 }
1802 else
1803 i = 0;
1804
1805 for (; (i < args_count) && (i < parms_count); i++)
1806 {
1807 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1808 struct ipcp_param_lattices *dest_plats;
1809
1810 dest_plats = ipa_get_parm_lattices (callee_info, i);
1811 if (availability == AVAIL_INTERPOSABLE)
1812 ret |= set_all_contains_variable (dest_plats);
1813 else
1814 {
1815 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1816 &dest_plats->itself);
1817 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
1818 &dest_plats->ctxlat);
1819 ret |= propagate_alignment_accross_jump_function (cs, jump_func,
1820 dest_plats);
1821 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1822 dest_plats);
1823 }
1824 }
1825 for (; i < parms_count; i++)
1826 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1827
1828 return ret;
1829 }
1830
1831 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1832 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1833 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
1834
1835 static tree
1836 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
1837 vec<tree> known_csts,
1838 vec<ipa_polymorphic_call_context> known_contexts,
1839 vec<ipa_agg_jump_function_p> known_aggs,
1840 struct ipa_agg_replacement_value *agg_reps,
1841 bool *speculative)
1842 {
1843 int param_index = ie->indirect_info->param_index;
1844 HOST_WIDE_INT anc_offset;
1845 tree t;
1846 tree target = NULL;
1847
1848 *speculative = false;
1849
1850 if (param_index == -1
1851 || known_csts.length () <= (unsigned int) param_index)
1852 return NULL_TREE;
1853
1854 if (!ie->indirect_info->polymorphic)
1855 {
1856 tree t;
1857
1858 if (ie->indirect_info->agg_contents)
1859 {
1860 if (agg_reps)
1861 {
1862 t = NULL;
1863 while (agg_reps)
1864 {
1865 if (agg_reps->index == param_index
1866 && agg_reps->offset == ie->indirect_info->offset
1867 && agg_reps->by_ref == ie->indirect_info->by_ref)
1868 {
1869 t = agg_reps->value;
1870 break;
1871 }
1872 agg_reps = agg_reps->next;
1873 }
1874 }
1875 else if (known_aggs.length () > (unsigned int) param_index)
1876 {
1877 struct ipa_agg_jump_function *agg;
1878 agg = known_aggs[param_index];
1879 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1880 ie->indirect_info->by_ref);
1881 }
1882 else
1883 t = NULL;
1884 }
1885 else
1886 t = known_csts[param_index];
1887
1888 if (t &&
1889 TREE_CODE (t) == ADDR_EXPR
1890 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1891 return TREE_OPERAND (t, 0);
1892 else
1893 return NULL_TREE;
1894 }
1895
1896 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
1897 return NULL_TREE;
1898
1899 gcc_assert (!ie->indirect_info->agg_contents);
1900 anc_offset = ie->indirect_info->offset;
1901
1902 t = NULL;
1903
1904 /* Try to work out value of virtual table pointer value in replacemnets. */
1905 if (!t && agg_reps && !ie->indirect_info->by_ref)
1906 {
1907 while (agg_reps)
1908 {
1909 if (agg_reps->index == param_index
1910 && agg_reps->offset == ie->indirect_info->offset
1911 && agg_reps->by_ref)
1912 {
1913 t = agg_reps->value;
1914 break;
1915 }
1916 agg_reps = agg_reps->next;
1917 }
1918 }
1919
1920 /* Try to work out value of virtual table pointer value in known
1921 aggregate values. */
1922 if (!t && known_aggs.length () > (unsigned int) param_index
1923 && !ie->indirect_info->by_ref)
1924 {
1925 struct ipa_agg_jump_function *agg;
1926 agg = known_aggs[param_index];
1927 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1928 true);
1929 }
1930
1931 /* If we found the virtual table pointer, lookup the target. */
1932 if (t)
1933 {
1934 tree vtable;
1935 unsigned HOST_WIDE_INT offset;
1936 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
1937 {
1938 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
1939 vtable, offset);
1940 if (target)
1941 {
1942 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1943 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1944 || !possible_polymorphic_call_target_p
1945 (ie, cgraph_node::get (target)))
1946 target = ipa_impossible_devirt_target (ie, target);
1947 *speculative = ie->indirect_info->vptr_changed;
1948 if (!*speculative)
1949 return target;
1950 }
1951 }
1952 }
1953
1954 /* Do we know the constant value of pointer? */
1955 if (!t)
1956 t = known_csts[param_index];
1957
1958 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
1959
1960 ipa_polymorphic_call_context context;
1961 if (known_contexts.length () > (unsigned int) param_index)
1962 {
1963 context = known_contexts[param_index];
1964 context.offset_by (anc_offset);
1965 if (ie->indirect_info->vptr_changed)
1966 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
1967 ie->indirect_info->otr_type);
1968 if (t)
1969 {
1970 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
1971 (t, ie->indirect_info->otr_type, anc_offset);
1972 if (!ctx2.useless_p ())
1973 context.combine_with (ctx2, ie->indirect_info->otr_type);
1974 }
1975 }
1976 else if (t)
1977 {
1978 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
1979 anc_offset);
1980 if (ie->indirect_info->vptr_changed)
1981 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
1982 ie->indirect_info->otr_type);
1983 }
1984 else
1985 return NULL_TREE;
1986
1987 vec <cgraph_node *>targets;
1988 bool final;
1989
1990 targets = possible_polymorphic_call_targets
1991 (ie->indirect_info->otr_type,
1992 ie->indirect_info->otr_token,
1993 context, &final);
1994 if (!final || targets.length () > 1)
1995 {
1996 struct cgraph_node *node;
1997 if (*speculative)
1998 return target;
1999 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2000 || ie->speculative || !ie->maybe_hot_p ())
2001 return NULL;
2002 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2003 ie->indirect_info->otr_token,
2004 context);
2005 if (node)
2006 {
2007 *speculative = true;
2008 target = node->decl;
2009 }
2010 else
2011 return NULL;
2012 }
2013 else
2014 {
2015 *speculative = false;
2016 if (targets.length () == 1)
2017 target = targets[0]->decl;
2018 else
2019 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2020 }
2021
2022 if (target && !possible_polymorphic_call_target_p (ie,
2023 cgraph_node::get (target)))
2024 target = ipa_impossible_devirt_target (ie, target);
2025
2026 return target;
2027 }
2028
2029
2030 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2031 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2032 return the destination. */
2033
2034 tree
2035 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2036 vec<tree> known_csts,
2037 vec<ipa_polymorphic_call_context> known_contexts,
2038 vec<ipa_agg_jump_function_p> known_aggs,
2039 bool *speculative)
2040 {
2041 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2042 known_aggs, NULL, speculative);
2043 }
2044
2045 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2046 and KNOWN_CONTEXTS. */
2047
2048 static int
2049 devirtualization_time_bonus (struct cgraph_node *node,
2050 vec<tree> known_csts,
2051 vec<ipa_polymorphic_call_context> known_contexts,
2052 vec<ipa_agg_jump_function_p> known_aggs)
2053 {
2054 struct cgraph_edge *ie;
2055 int res = 0;
2056
2057 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2058 {
2059 struct cgraph_node *callee;
2060 struct inline_summary *isummary;
2061 enum availability avail;
2062 tree target;
2063 bool speculative;
2064
2065 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2066 known_aggs, &speculative);
2067 if (!target)
2068 continue;
2069
2070 /* Only bare minimum benefit for clearly un-inlineable targets. */
2071 res += 1;
2072 callee = cgraph_node::get (target);
2073 if (!callee || !callee->definition)
2074 continue;
2075 callee = callee->function_symbol (&avail);
2076 if (avail < AVAIL_AVAILABLE)
2077 continue;
2078 isummary = inline_summaries->get (callee);
2079 if (!isummary->inlinable)
2080 continue;
2081
2082 /* FIXME: The values below need re-considering and perhaps also
2083 integrating into the cost metrics, at lest in some very basic way. */
2084 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2085 res += 31 / ((int)speculative + 1);
2086 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2087 res += 15 / ((int)speculative + 1);
2088 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2089 || DECL_DECLARED_INLINE_P (callee->decl))
2090 res += 7 / ((int)speculative + 1);
2091 }
2092
2093 return res;
2094 }
2095
2096 /* Return time bonus incurred because of HINTS. */
2097
2098 static int
2099 hint_time_bonus (inline_hints hints)
2100 {
2101 int result = 0;
2102 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2103 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2104 if (hints & INLINE_HINT_array_index)
2105 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2106 return result;
2107 }
2108
2109 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2110 and SIZE_COST and with the sum of frequencies of incoming edges to the
2111 potential new clone in FREQUENCIES. */
2112
2113 static bool
2114 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2115 int freq_sum, gcov_type count_sum, int size_cost)
2116 {
2117 if (time_benefit == 0
2118 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2119 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
2120 return false;
2121
2122 gcc_assert (size_cost > 0);
2123
2124 if (max_count)
2125 {
2126 int factor = (count_sum * 1000) / max_count;
2127 int64_t evaluation = (((int64_t) time_benefit * factor)
2128 / size_cost);
2129
2130 if (dump_file && (dump_flags & TDF_DETAILS))
2131 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2132 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2133 ") -> evaluation: " "%"PRId64
2134 ", threshold: %i\n",
2135 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2136 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2137
2138 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2139 }
2140 else
2141 {
2142 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2143 / size_cost);
2144
2145 if (dump_file && (dump_flags & TDF_DETAILS))
2146 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2147 "size: %i, freq_sum: %i) -> evaluation: "
2148 "%"PRId64 ", threshold: %i\n",
2149 time_benefit, size_cost, freq_sum, evaluation,
2150 PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2151
2152 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2153 }
2154 }
2155
2156 /* Return all context independent values from aggregate lattices in PLATS in a
2157 vector. Return NULL if there are none. */
2158
2159 static vec<ipa_agg_jf_item, va_gc> *
2160 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2161 {
2162 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2163
2164 if (plats->aggs_bottom
2165 || plats->aggs_contain_variable
2166 || plats->aggs_count == 0)
2167 return NULL;
2168
2169 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2170 aglat;
2171 aglat = aglat->next)
2172 if (aglat->is_single_const ())
2173 {
2174 struct ipa_agg_jf_item item;
2175 item.offset = aglat->offset;
2176 item.value = aglat->values->value;
2177 vec_safe_push (res, item);
2178 }
2179 return res;
2180 }
2181
2182 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2183 populate them with values of parameters that are known independent of the
2184 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2185 non-NULL, the movement cost of all removable parameters will be stored in
2186 it. */
2187
2188 static bool
2189 gather_context_independent_values (struct ipa_node_params *info,
2190 vec<tree> *known_csts,
2191 vec<ipa_polymorphic_call_context>
2192 *known_contexts,
2193 vec<ipa_agg_jump_function> *known_aggs,
2194 int *removable_params_cost)
2195 {
2196 int i, count = ipa_get_param_count (info);
2197 bool ret = false;
2198
2199 known_csts->create (0);
2200 known_contexts->create (0);
2201 known_csts->safe_grow_cleared (count);
2202 known_contexts->safe_grow_cleared (count);
2203 if (known_aggs)
2204 {
2205 known_aggs->create (0);
2206 known_aggs->safe_grow_cleared (count);
2207 }
2208
2209 if (removable_params_cost)
2210 *removable_params_cost = 0;
2211
2212 for (i = 0; i < count ; i++)
2213 {
2214 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2215 ipcp_lattice<tree> *lat = &plats->itself;
2216
2217 if (lat->is_single_const ())
2218 {
2219 ipcp_value<tree> *val = lat->values;
2220 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2221 (*known_csts)[i] = val->value;
2222 if (removable_params_cost)
2223 *removable_params_cost
2224 += estimate_move_cost (TREE_TYPE (val->value), false);
2225 ret = true;
2226 }
2227 else if (removable_params_cost
2228 && !ipa_is_param_used (info, i))
2229 *removable_params_cost
2230 += ipa_get_param_move_cost (info, i);
2231
2232 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2233 if (ctxlat->is_single_const ())
2234 {
2235 (*known_contexts)[i] = ctxlat->values->value;
2236 ret = true;
2237 }
2238
2239 if (known_aggs)
2240 {
2241 vec<ipa_agg_jf_item, va_gc> *agg_items;
2242 struct ipa_agg_jump_function *ajf;
2243
2244 agg_items = context_independent_aggregate_values (plats);
2245 ajf = &(*known_aggs)[i];
2246 ajf->items = agg_items;
2247 ajf->by_ref = plats->aggs_by_ref;
2248 ret |= agg_items != NULL;
2249 }
2250 }
2251
2252 return ret;
2253 }
2254
2255 /* The current interface in ipa-inline-analysis requires a pointer vector.
2256 Create it.
2257
2258 FIXME: That interface should be re-worked, this is slightly silly. Still,
2259 I'd like to discuss how to change it first and this demonstrates the
2260 issue. */
2261
2262 static vec<ipa_agg_jump_function_p>
2263 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2264 {
2265 vec<ipa_agg_jump_function_p> ret;
2266 struct ipa_agg_jump_function *ajf;
2267 int i;
2268
2269 ret.create (known_aggs.length ());
2270 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2271 ret.quick_push (ajf);
2272 return ret;
2273 }
2274
2275 /* Perform time and size measurement of NODE with the context given in
2276 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2277 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2278 all context-independent removable parameters and EST_MOVE_COST of estimated
2279 movement of the considered parameter and store it into VAL. */
2280
2281 static void
2282 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2283 vec<ipa_polymorphic_call_context> known_contexts,
2284 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2285 int base_time, int removable_params_cost,
2286 int est_move_cost, ipcp_value_base *val)
2287 {
2288 int time, size, time_benefit;
2289 inline_hints hints;
2290
2291 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2292 known_aggs_ptrs, &size, &time,
2293 &hints);
2294 time_benefit = base_time - time
2295 + devirtualization_time_bonus (node, known_csts, known_contexts,
2296 known_aggs_ptrs)
2297 + hint_time_bonus (hints)
2298 + removable_params_cost + est_move_cost;
2299
2300 gcc_checking_assert (size >=0);
2301 /* The inliner-heuristics based estimates may think that in certain
2302 contexts some functions do not have any size at all but we want
2303 all specializations to have at least a tiny cost, not least not to
2304 divide by zero. */
2305 if (size == 0)
2306 size = 1;
2307
2308 val->local_time_benefit = time_benefit;
2309 val->local_size_cost = size;
2310 }
2311
2312 /* Iterate over known values of parameters of NODE and estimate the local
2313 effects in terms of time and size they have. */
2314
2315 static void
2316 estimate_local_effects (struct cgraph_node *node)
2317 {
2318 struct ipa_node_params *info = IPA_NODE_REF (node);
2319 int i, count = ipa_get_param_count (info);
2320 vec<tree> known_csts;
2321 vec<ipa_polymorphic_call_context> known_contexts;
2322 vec<ipa_agg_jump_function> known_aggs;
2323 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2324 bool always_const;
2325 int base_time = inline_summaries->get (node)->time;
2326 int removable_params_cost;
2327
2328 if (!count || !ipcp_versionable_function_p (node))
2329 return;
2330
2331 if (dump_file && (dump_flags & TDF_DETAILS))
2332 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2333 node->name (), node->order, base_time);
2334
2335 always_const = gather_context_independent_values (info, &known_csts,
2336 &known_contexts, &known_aggs,
2337 &removable_params_cost);
2338 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2339 if (always_const)
2340 {
2341 struct caller_statistics stats;
2342 inline_hints hints;
2343 int time, size;
2344
2345 init_caller_stats (&stats);
2346 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2347 false);
2348 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2349 known_aggs_ptrs, &size, &time, &hints);
2350 time -= devirtualization_time_bonus (node, known_csts, known_contexts,
2351 known_aggs_ptrs);
2352 time -= hint_time_bonus (hints);
2353 time -= removable_params_cost;
2354 size -= stats.n_calls * removable_params_cost;
2355
2356 if (dump_file)
2357 fprintf (dump_file, " - context independent values, size: %i, "
2358 "time_benefit: %i\n", size, base_time - time);
2359
2360 if (size <= 0
2361 || node->will_be_removed_from_program_if_no_direct_calls_p ())
2362 {
2363 info->do_clone_for_all_contexts = true;
2364 base_time = time;
2365
2366 if (dump_file)
2367 fprintf (dump_file, " Decided to specialize for all "
2368 "known contexts, code not going to grow.\n");
2369 }
2370 else if (good_cloning_opportunity_p (node, base_time - time,
2371 stats.freq_sum, stats.count_sum,
2372 size))
2373 {
2374 if (size + overall_size <= max_new_size)
2375 {
2376 info->do_clone_for_all_contexts = true;
2377 base_time = time;
2378 overall_size += size;
2379
2380 if (dump_file)
2381 fprintf (dump_file, " Decided to specialize for all "
2382 "known contexts, growth deemed beneficial.\n");
2383 }
2384 else if (dump_file && (dump_flags & TDF_DETAILS))
2385 fprintf (dump_file, " Not cloning for all contexts because "
2386 "max_new_size would be reached with %li.\n",
2387 size + overall_size);
2388 }
2389 }
2390
2391 for (i = 0; i < count ; i++)
2392 {
2393 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2394 ipcp_lattice<tree> *lat = &plats->itself;
2395 ipcp_value<tree> *val;
2396
2397 if (lat->bottom
2398 || !lat->values
2399 || known_csts[i])
2400 continue;
2401
2402 for (val = lat->values; val; val = val->next)
2403 {
2404 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2405 known_csts[i] = val->value;
2406
2407 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2408 perform_estimation_of_a_value (node, known_csts, known_contexts,
2409 known_aggs_ptrs, base_time,
2410 removable_params_cost, emc, val);
2411
2412 if (dump_file && (dump_flags & TDF_DETAILS))
2413 {
2414 fprintf (dump_file, " - estimates for value ");
2415 print_ipcp_constant_value (dump_file, val->value);
2416 fprintf (dump_file, " for ");
2417 ipa_dump_param (dump_file, info, i);
2418 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2419 val->local_time_benefit, val->local_size_cost);
2420 }
2421 }
2422 known_csts[i] = NULL_TREE;
2423 }
2424
2425 for (i = 0; i < count; i++)
2426 {
2427 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2428
2429 if (!plats->virt_call)
2430 continue;
2431
2432 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2433 ipcp_value<ipa_polymorphic_call_context> *val;
2434
2435 if (ctxlat->bottom
2436 || !ctxlat->values
2437 || !known_contexts[i].useless_p ())
2438 continue;
2439
2440 for (val = ctxlat->values; val; val = val->next)
2441 {
2442 known_contexts[i] = val->value;
2443 perform_estimation_of_a_value (node, known_csts, known_contexts,
2444 known_aggs_ptrs, base_time,
2445 removable_params_cost, 0, val);
2446
2447 if (dump_file && (dump_flags & TDF_DETAILS))
2448 {
2449 fprintf (dump_file, " - estimates for polymorphic context ");
2450 print_ipcp_constant_value (dump_file, val->value);
2451 fprintf (dump_file, " for ");
2452 ipa_dump_param (dump_file, info, i);
2453 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2454 val->local_time_benefit, val->local_size_cost);
2455 }
2456 }
2457 known_contexts[i] = ipa_polymorphic_call_context ();
2458 }
2459
2460 for (i = 0; i < count ; i++)
2461 {
2462 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2463 struct ipa_agg_jump_function *ajf;
2464 struct ipcp_agg_lattice *aglat;
2465
2466 if (plats->aggs_bottom || !plats->aggs)
2467 continue;
2468
2469 ajf = &known_aggs[i];
2470 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2471 {
2472 ipcp_value<tree> *val;
2473 if (aglat->bottom || !aglat->values
2474 /* If the following is true, the one value is in known_aggs. */
2475 || (!plats->aggs_contain_variable
2476 && aglat->is_single_const ()))
2477 continue;
2478
2479 for (val = aglat->values; val; val = val->next)
2480 {
2481 struct ipa_agg_jf_item item;
2482
2483 item.offset = aglat->offset;
2484 item.value = val->value;
2485 vec_safe_push (ajf->items, item);
2486
2487 perform_estimation_of_a_value (node, known_csts, known_contexts,
2488 known_aggs_ptrs, base_time,
2489 removable_params_cost, 0, val);
2490
2491 if (dump_file && (dump_flags & TDF_DETAILS))
2492 {
2493 fprintf (dump_file, " - estimates for value ");
2494 print_ipcp_constant_value (dump_file, val->value);
2495 fprintf (dump_file, " for ");
2496 ipa_dump_param (dump_file, info, i);
2497 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2498 "]: time_benefit: %i, size: %i\n",
2499 plats->aggs_by_ref ? "ref " : "",
2500 aglat->offset,
2501 val->local_time_benefit, val->local_size_cost);
2502 }
2503
2504 ajf->items->pop ();
2505 }
2506 }
2507 }
2508
2509 for (i = 0; i < count ; i++)
2510 vec_free (known_aggs[i].items);
2511
2512 known_csts.release ();
2513 known_contexts.release ();
2514 known_aggs.release ();
2515 known_aggs_ptrs.release ();
2516 }
2517
2518
2519 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2520 topological sort of values. */
2521
2522 template <typename valtype>
2523 void
2524 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
2525 {
2526 ipcp_value_source<valtype> *src;
2527
2528 if (cur_val->dfs)
2529 return;
2530
2531 dfs_counter++;
2532 cur_val->dfs = dfs_counter;
2533 cur_val->low_link = dfs_counter;
2534
2535 cur_val->topo_next = stack;
2536 stack = cur_val;
2537 cur_val->on_stack = true;
2538
2539 for (src = cur_val->sources; src; src = src->next)
2540 if (src->val)
2541 {
2542 if (src->val->dfs == 0)
2543 {
2544 add_val (src->val);
2545 if (src->val->low_link < cur_val->low_link)
2546 cur_val->low_link = src->val->low_link;
2547 }
2548 else if (src->val->on_stack
2549 && src->val->dfs < cur_val->low_link)
2550 cur_val->low_link = src->val->dfs;
2551 }
2552
2553 if (cur_val->dfs == cur_val->low_link)
2554 {
2555 ipcp_value<valtype> *v, *scc_list = NULL;
2556
2557 do
2558 {
2559 v = stack;
2560 stack = v->topo_next;
2561 v->on_stack = false;
2562
2563 v->scc_next = scc_list;
2564 scc_list = v;
2565 }
2566 while (v != cur_val);
2567
2568 cur_val->topo_next = values_topo;
2569 values_topo = cur_val;
2570 }
2571 }
2572
2573 /* Add all values in lattices associated with NODE to the topological sort if
2574 they are not there yet. */
2575
2576 static void
2577 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
2578 {
2579 struct ipa_node_params *info = IPA_NODE_REF (node);
2580 int i, count = ipa_get_param_count (info);
2581
2582 for (i = 0; i < count ; i++)
2583 {
2584 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2585 ipcp_lattice<tree> *lat = &plats->itself;
2586 struct ipcp_agg_lattice *aglat;
2587
2588 if (!lat->bottom)
2589 {
2590 ipcp_value<tree> *val;
2591 for (val = lat->values; val; val = val->next)
2592 topo->constants.add_val (val);
2593 }
2594
2595 if (!plats->aggs_bottom)
2596 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2597 if (!aglat->bottom)
2598 {
2599 ipcp_value<tree> *val;
2600 for (val = aglat->values; val; val = val->next)
2601 topo->constants.add_val (val);
2602 }
2603
2604 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2605 if (!ctxlat->bottom)
2606 {
2607 ipcp_value<ipa_polymorphic_call_context> *ctxval;
2608 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
2609 topo->contexts.add_val (ctxval);
2610 }
2611 }
2612 }
2613
2614 /* One pass of constants propagation along the call graph edges, from callers
2615 to callees (requires topological ordering in TOPO), iterate over strongly
2616 connected components. */
2617
2618 static void
2619 propagate_constants_topo (struct ipa_topo_info *topo)
2620 {
2621 int i;
2622
2623 for (i = topo->nnodes - 1; i >= 0; i--)
2624 {
2625 unsigned j;
2626 struct cgraph_node *v, *node = topo->order[i];
2627 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
2628
2629 /* First, iteratively propagate within the strongly connected component
2630 until all lattices stabilize. */
2631 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2632 if (v->has_gimple_body_p ())
2633 push_node_to_stack (topo, v);
2634
2635 v = pop_node_from_stack (topo);
2636 while (v)
2637 {
2638 struct cgraph_edge *cs;
2639
2640 for (cs = v->callees; cs; cs = cs->next_callee)
2641 if (ipa_edge_within_scc (cs)
2642 && propagate_constants_accross_call (cs))
2643 push_node_to_stack (topo, cs->callee->function_symbol ());
2644 v = pop_node_from_stack (topo);
2645 }
2646
2647 /* Afterwards, propagate along edges leading out of the SCC, calculates
2648 the local effects of the discovered constants and all valid values to
2649 their topological sort. */
2650 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2651 if (v->has_gimple_body_p ())
2652 {
2653 struct cgraph_edge *cs;
2654
2655 estimate_local_effects (v);
2656 add_all_node_vals_to_toposort (v, topo);
2657 for (cs = v->callees; cs; cs = cs->next_callee)
2658 if (!ipa_edge_within_scc (cs))
2659 propagate_constants_accross_call (cs);
2660 }
2661 cycle_nodes.release ();
2662 }
2663 }
2664
2665
2666 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2667 the bigger one if otherwise. */
2668
2669 static int
2670 safe_add (int a, int b)
2671 {
2672 if (a > INT_MAX/2 || b > INT_MAX/2)
2673 return a > b ? a : b;
2674 else
2675 return a + b;
2676 }
2677
2678
2679 /* Propagate the estimated effects of individual values along the topological
2680 from the dependent values to those they depend on. */
2681
2682 template <typename valtype>
2683 void
2684 value_topo_info<valtype>::propagate_effects ()
2685 {
2686 ipcp_value<valtype> *base;
2687
2688 for (base = values_topo; base; base = base->topo_next)
2689 {
2690 ipcp_value_source<valtype> *src;
2691 ipcp_value<valtype> *val;
2692 int time = 0, size = 0;
2693
2694 for (val = base; val; val = val->scc_next)
2695 {
2696 time = safe_add (time,
2697 val->local_time_benefit + val->prop_time_benefit);
2698 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2699 }
2700
2701 for (val = base; val; val = val->scc_next)
2702 for (src = val->sources; src; src = src->next)
2703 if (src->val
2704 && src->cs->maybe_hot_p ())
2705 {
2706 src->val->prop_time_benefit = safe_add (time,
2707 src->val->prop_time_benefit);
2708 src->val->prop_size_cost = safe_add (size,
2709 src->val->prop_size_cost);
2710 }
2711 }
2712 }
2713
2714
2715 /* Propagate constants, polymorphic contexts and their effects from the
2716 summaries interprocedurally. */
2717
2718 static void
2719 ipcp_propagate_stage (struct ipa_topo_info *topo)
2720 {
2721 struct cgraph_node *node;
2722
2723 if (dump_file)
2724 fprintf (dump_file, "\n Propagating constants:\n\n");
2725
2726 if (in_lto_p)
2727 ipa_update_after_lto_read ();
2728
2729
2730 FOR_EACH_DEFINED_FUNCTION (node)
2731 {
2732 struct ipa_node_params *info = IPA_NODE_REF (node);
2733
2734 determine_versionability (node);
2735 if (node->has_gimple_body_p ())
2736 {
2737 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2738 ipa_get_param_count (info));
2739 initialize_node_lattices (node);
2740 }
2741 if (node->definition && !node->alias)
2742 overall_size += inline_summaries->get (node)->self_size;
2743 if (node->count > max_count)
2744 max_count = node->count;
2745 }
2746
2747 max_new_size = overall_size;
2748 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2749 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2750 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2751
2752 if (dump_file)
2753 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2754 overall_size, max_new_size);
2755
2756 propagate_constants_topo (topo);
2757 #ifdef ENABLE_CHECKING
2758 ipcp_verify_propagated_values ();
2759 #endif
2760 topo->constants.propagate_effects ();
2761 topo->contexts.propagate_effects ();
2762
2763 if (dump_file)
2764 {
2765 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2766 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2767 }
2768 }
2769
2770 /* Discover newly direct outgoing edges from NODE which is a new clone with
2771 known KNOWN_CSTS and make them direct. */
2772
2773 static void
2774 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2775 vec<tree> known_csts,
2776 vec<ipa_polymorphic_call_context>
2777 known_contexts,
2778 struct ipa_agg_replacement_value *aggvals)
2779 {
2780 struct cgraph_edge *ie, *next_ie;
2781 bool found = false;
2782
2783 for (ie = node->indirect_calls; ie; ie = next_ie)
2784 {
2785 tree target;
2786 bool speculative;
2787
2788 next_ie = ie->next_callee;
2789 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2790 vNULL, aggvals, &speculative);
2791 if (target)
2792 {
2793 bool agg_contents = ie->indirect_info->agg_contents;
2794 bool polymorphic = ie->indirect_info->polymorphic;
2795 int param_index = ie->indirect_info->param_index;
2796 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
2797 speculative);
2798 found = true;
2799
2800 if (cs && !agg_contents && !polymorphic)
2801 {
2802 struct ipa_node_params *info = IPA_NODE_REF (node);
2803 int c = ipa_get_controlled_uses (info, param_index);
2804 if (c != IPA_UNDESCRIBED_USE)
2805 {
2806 struct ipa_ref *to_del;
2807
2808 c--;
2809 ipa_set_controlled_uses (info, param_index, c);
2810 if (dump_file && (dump_flags & TDF_DETAILS))
2811 fprintf (dump_file, " controlled uses count of param "
2812 "%i bumped down to %i\n", param_index, c);
2813 if (c == 0
2814 && (to_del = node->find_reference (cs->callee, NULL, 0)))
2815 {
2816 if (dump_file && (dump_flags & TDF_DETAILS))
2817 fprintf (dump_file, " and even removing its "
2818 "cloning-created reference\n");
2819 to_del->remove_reference ();
2820 }
2821 }
2822 }
2823 }
2824 }
2825 /* Turning calls to direct calls will improve overall summary. */
2826 if (found)
2827 inline_update_overall_summary (node);
2828 }
2829
2830 /* Vector of pointers which for linked lists of clones of an original crgaph
2831 edge. */
2832
2833 static vec<cgraph_edge *> next_edge_clone;
2834 static vec<cgraph_edge *> prev_edge_clone;
2835
2836 static inline void
2837 grow_edge_clone_vectors (void)
2838 {
2839 if (next_edge_clone.length ()
2840 <= (unsigned) symtab->edges_max_uid)
2841 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2842 if (prev_edge_clone.length ()
2843 <= (unsigned) symtab->edges_max_uid)
2844 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2845 }
2846
2847 /* Edge duplication hook to grow the appropriate linked list in
2848 next_edge_clone. */
2849
2850 static void
2851 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2852 void *)
2853 {
2854 grow_edge_clone_vectors ();
2855
2856 struct cgraph_edge *old_next = next_edge_clone[src->uid];
2857 if (old_next)
2858 prev_edge_clone[old_next->uid] = dst;
2859 prev_edge_clone[dst->uid] = src;
2860
2861 next_edge_clone[dst->uid] = old_next;
2862 next_edge_clone[src->uid] = dst;
2863 }
2864
2865 /* Hook that is called by cgraph.c when an edge is removed. */
2866
2867 static void
2868 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
2869 {
2870 grow_edge_clone_vectors ();
2871
2872 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
2873 struct cgraph_edge *next = next_edge_clone[cs->uid];
2874 if (prev)
2875 next_edge_clone[prev->uid] = next;
2876 if (next)
2877 prev_edge_clone[next->uid] = prev;
2878 }
2879
2880 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2881 parameter with the given INDEX. */
2882
2883 static tree
2884 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2885 int index)
2886 {
2887 struct ipa_agg_replacement_value *aggval;
2888
2889 aggval = ipa_get_agg_replacements_for_node (node);
2890 while (aggval)
2891 {
2892 if (aggval->offset == offset
2893 && aggval->index == index)
2894 return aggval->value;
2895 aggval = aggval->next;
2896 }
2897 return NULL_TREE;
2898 }
2899
2900 /* Return true is NODE is DEST or its clone for all contexts. */
2901
2902 static bool
2903 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
2904 {
2905 if (node == dest)
2906 return true;
2907
2908 struct ipa_node_params *info = IPA_NODE_REF (node);
2909 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
2910 }
2911
2912 /* Return true if edge CS does bring about the value described by SRC to node
2913 DEST or its clone for all contexts. */
2914
2915 static bool
2916 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
2917 cgraph_node *dest)
2918 {
2919 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2920 enum availability availability;
2921 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
2922
2923 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
2924 || availability <= AVAIL_INTERPOSABLE
2925 || caller_info->node_dead)
2926 return false;
2927 if (!src->val)
2928 return true;
2929
2930 if (caller_info->ipcp_orig_node)
2931 {
2932 tree t;
2933 if (src->offset == -1)
2934 t = caller_info->known_csts[src->index];
2935 else
2936 t = get_clone_agg_value (cs->caller, src->offset, src->index);
2937 return (t != NULL_TREE
2938 && values_equal_for_ipcp_p (src->val->value, t));
2939 }
2940 else
2941 {
2942 struct ipcp_agg_lattice *aglat;
2943 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
2944 src->index);
2945 if (src->offset == -1)
2946 return (plats->itself.is_single_const ()
2947 && values_equal_for_ipcp_p (src->val->value,
2948 plats->itself.values->value));
2949 else
2950 {
2951 if (plats->aggs_bottom || plats->aggs_contain_variable)
2952 return false;
2953 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2954 if (aglat->offset == src->offset)
2955 return (aglat->is_single_const ()
2956 && values_equal_for_ipcp_p (src->val->value,
2957 aglat->values->value));
2958 }
2959 return false;
2960 }
2961 }
2962
2963 /* Return true if edge CS does bring about the value described by SRC to node
2964 DEST or its clone for all contexts. */
2965
2966 static bool
2967 cgraph_edge_brings_value_p (cgraph_edge *cs,
2968 ipcp_value_source<ipa_polymorphic_call_context> *src,
2969 cgraph_node *dest)
2970 {
2971 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2972 cgraph_node *real_dest = cs->callee->function_symbol ();
2973
2974 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
2975 || caller_info->node_dead)
2976 return false;
2977 if (!src->val)
2978 return true;
2979
2980 if (caller_info->ipcp_orig_node)
2981 return (caller_info->known_contexts.length () > (unsigned) src->index)
2982 && values_equal_for_ipcp_p (src->val->value,
2983 caller_info->known_contexts[src->index]);
2984
2985 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
2986 src->index);
2987 return plats->ctxlat.is_single_const ()
2988 && values_equal_for_ipcp_p (src->val->value,
2989 plats->ctxlat.values->value);
2990 }
2991
2992 /* Get the next clone in the linked list of clones of an edge. */
2993
2994 static inline struct cgraph_edge *
2995 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
2996 {
2997 return next_edge_clone[cs->uid];
2998 }
2999
3000 /* Given VAL that is intended for DEST, iterate over all its sources and if
3001 they still hold, add their edge frequency and their number into *FREQUENCY
3002 and *CALLER_COUNT respectively. */
3003
3004 template <typename valtype>
3005 static bool
3006 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3007 int *freq_sum,
3008 gcov_type *count_sum, int *caller_count)
3009 {
3010 ipcp_value_source<valtype> *src;
3011 int freq = 0, count = 0;
3012 gcov_type cnt = 0;
3013 bool hot = false;
3014
3015 for (src = val->sources; src; src = src->next)
3016 {
3017 struct cgraph_edge *cs = src->cs;
3018 while (cs)
3019 {
3020 if (cgraph_edge_brings_value_p (cs, src, dest))
3021 {
3022 count++;
3023 freq += cs->frequency;
3024 cnt += cs->count;
3025 hot |= cs->maybe_hot_p ();
3026 }
3027 cs = get_next_cgraph_edge_clone (cs);
3028 }
3029 }
3030
3031 *freq_sum = freq;
3032 *count_sum = cnt;
3033 *caller_count = count;
3034 return hot;
3035 }
3036
3037 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3038 is assumed their number is known and equal to CALLER_COUNT. */
3039
3040 template <typename valtype>
3041 static vec<cgraph_edge *>
3042 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3043 int caller_count)
3044 {
3045 ipcp_value_source<valtype> *src;
3046 vec<cgraph_edge *> ret;
3047
3048 ret.create (caller_count);
3049 for (src = val->sources; src; src = src->next)
3050 {
3051 struct cgraph_edge *cs = src->cs;
3052 while (cs)
3053 {
3054 if (cgraph_edge_brings_value_p (cs, src, dest))
3055 ret.quick_push (cs);
3056 cs = get_next_cgraph_edge_clone (cs);
3057 }
3058 }
3059
3060 return ret;
3061 }
3062
3063 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3064 Return it or NULL if for some reason it cannot be created. */
3065
3066 static struct ipa_replace_map *
3067 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3068 {
3069 struct ipa_replace_map *replace_map;
3070
3071
3072 replace_map = ggc_alloc<ipa_replace_map> ();
3073 if (dump_file)
3074 {
3075 fprintf (dump_file, " replacing ");
3076 ipa_dump_param (dump_file, info, parm_num);
3077
3078 fprintf (dump_file, " with const ");
3079 print_generic_expr (dump_file, value, 0);
3080 fprintf (dump_file, "\n");
3081 }
3082 replace_map->old_tree = NULL;
3083 replace_map->parm_num = parm_num;
3084 replace_map->new_tree = value;
3085 replace_map->replace_p = true;
3086 replace_map->ref_p = false;
3087
3088 return replace_map;
3089 }
3090
3091 /* Dump new profiling counts */
3092
3093 static void
3094 dump_profile_updates (struct cgraph_node *orig_node,
3095 struct cgraph_node *new_node)
3096 {
3097 struct cgraph_edge *cs;
3098
3099 fprintf (dump_file, " setting count of the specialized node to "
3100 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3101 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3102 fprintf (dump_file, " edge to %s has count "
3103 HOST_WIDE_INT_PRINT_DEC "\n",
3104 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3105
3106 fprintf (dump_file, " setting count of the original node to "
3107 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3108 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3109 fprintf (dump_file, " edge to %s is left with "
3110 HOST_WIDE_INT_PRINT_DEC "\n",
3111 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3112 }
3113
3114 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3115 their profile information to reflect this. */
3116
3117 static void
3118 update_profiling_info (struct cgraph_node *orig_node,
3119 struct cgraph_node *new_node)
3120 {
3121 struct cgraph_edge *cs;
3122 struct caller_statistics stats;
3123 gcov_type new_sum, orig_sum;
3124 gcov_type remainder, orig_node_count = orig_node->count;
3125
3126 if (orig_node_count == 0)
3127 return;
3128
3129 init_caller_stats (&stats);
3130 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3131 false);
3132 orig_sum = stats.count_sum;
3133 init_caller_stats (&stats);
3134 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3135 false);
3136 new_sum = stats.count_sum;
3137
3138 if (orig_node_count < orig_sum + new_sum)
3139 {
3140 if (dump_file)
3141 fprintf (dump_file, " Problem: node %s/%i has too low count "
3142 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3143 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3144 orig_node->name (), orig_node->order,
3145 (HOST_WIDE_INT) orig_node_count,
3146 (HOST_WIDE_INT) (orig_sum + new_sum));
3147
3148 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3149 if (dump_file)
3150 fprintf (dump_file, " proceeding by pretending it was "
3151 HOST_WIDE_INT_PRINT_DEC "\n",
3152 (HOST_WIDE_INT) orig_node_count);
3153 }
3154
3155 new_node->count = new_sum;
3156 remainder = orig_node_count - new_sum;
3157 orig_node->count = remainder;
3158
3159 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3160 if (cs->frequency)
3161 cs->count = apply_probability (cs->count,
3162 GCOV_COMPUTE_SCALE (new_sum,
3163 orig_node_count));
3164 else
3165 cs->count = 0;
3166
3167 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3168 cs->count = apply_probability (cs->count,
3169 GCOV_COMPUTE_SCALE (remainder,
3170 orig_node_count));
3171
3172 if (dump_file)
3173 dump_profile_updates (orig_node, new_node);
3174 }
3175
3176 /* Update the respective profile of specialized NEW_NODE and the original
3177 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3178 have been redirected to the specialized version. */
3179
3180 static void
3181 update_specialized_profile (struct cgraph_node *new_node,
3182 struct cgraph_node *orig_node,
3183 gcov_type redirected_sum)
3184 {
3185 struct cgraph_edge *cs;
3186 gcov_type new_node_count, orig_node_count = orig_node->count;
3187
3188 if (dump_file)
3189 fprintf (dump_file, " the sum of counts of redirected edges is "
3190 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3191 if (orig_node_count == 0)
3192 return;
3193
3194 gcc_assert (orig_node_count >= redirected_sum);
3195
3196 new_node_count = new_node->count;
3197 new_node->count += redirected_sum;
3198 orig_node->count -= redirected_sum;
3199
3200 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3201 if (cs->frequency)
3202 cs->count += apply_probability (cs->count,
3203 GCOV_COMPUTE_SCALE (redirected_sum,
3204 new_node_count));
3205 else
3206 cs->count = 0;
3207
3208 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3209 {
3210 gcov_type dec = apply_probability (cs->count,
3211 GCOV_COMPUTE_SCALE (redirected_sum,
3212 orig_node_count));
3213 if (dec < cs->count)
3214 cs->count -= dec;
3215 else
3216 cs->count = 0;
3217 }
3218
3219 if (dump_file)
3220 dump_profile_updates (orig_node, new_node);
3221 }
3222
3223 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3224 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3225 redirect all edges in CALLERS to it. */
3226
3227 static struct cgraph_node *
3228 create_specialized_node (struct cgraph_node *node,
3229 vec<tree> known_csts,
3230 vec<ipa_polymorphic_call_context> known_contexts,
3231 struct ipa_agg_replacement_value *aggvals,
3232 vec<cgraph_edge *> callers)
3233 {
3234 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3235 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3236 struct ipa_agg_replacement_value *av;
3237 struct cgraph_node *new_node;
3238 int i, count = ipa_get_param_count (info);
3239 bitmap args_to_skip;
3240
3241 gcc_assert (!info->ipcp_orig_node);
3242
3243 if (node->local.can_change_signature)
3244 {
3245 args_to_skip = BITMAP_GGC_ALLOC ();
3246 for (i = 0; i < count; i++)
3247 {
3248 tree t = known_csts[i];
3249
3250 if (t || !ipa_is_param_used (info, i))
3251 bitmap_set_bit (args_to_skip, i);
3252 }
3253 }
3254 else
3255 {
3256 args_to_skip = NULL;
3257 if (dump_file && (dump_flags & TDF_DETAILS))
3258 fprintf (dump_file, " cannot change function signature\n");
3259 }
3260
3261 for (i = 0; i < count ; i++)
3262 {
3263 tree t = known_csts[i];
3264 if (t)
3265 {
3266 struct ipa_replace_map *replace_map;
3267
3268 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3269 replace_map = get_replacement_map (info, t, i);
3270 if (replace_map)
3271 vec_safe_push (replace_trees, replace_map);
3272 }
3273 }
3274
3275 new_node = node->create_virtual_clone (callers, replace_trees,
3276 args_to_skip, "constprop");
3277 ipa_set_node_agg_value_chain (new_node, aggvals);
3278 for (av = aggvals; av; av = av->next)
3279 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3280
3281 if (dump_file && (dump_flags & TDF_DETAILS))
3282 {
3283 fprintf (dump_file, " the new node is %s/%i.\n",
3284 new_node->name (), new_node->order);
3285 if (known_contexts.exists ())
3286 {
3287 for (i = 0; i < count ; i++)
3288 if (!known_contexts[i].useless_p ())
3289 {
3290 fprintf (dump_file, " known ctx %i is ", i);
3291 known_contexts[i].dump (dump_file);
3292 }
3293 }
3294 if (aggvals)
3295 ipa_dump_agg_replacement_values (dump_file, aggvals);
3296 }
3297 ipa_check_create_node_params ();
3298 update_profiling_info (node, new_node);
3299 new_info = IPA_NODE_REF (new_node);
3300 new_info->ipcp_orig_node = node;
3301 new_info->known_csts = known_csts;
3302 new_info->known_contexts = known_contexts;
3303
3304 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3305
3306 callers.release ();
3307 return new_node;
3308 }
3309
3310 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3311 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3312
3313 static void
3314 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3315 vec<tree> known_csts,
3316 vec<cgraph_edge *> callers)
3317 {
3318 struct ipa_node_params *info = IPA_NODE_REF (node);
3319 int i, count = ipa_get_param_count (info);
3320
3321 for (i = 0; i < count ; i++)
3322 {
3323 struct cgraph_edge *cs;
3324 tree newval = NULL_TREE;
3325 int j;
3326 bool first = true;
3327
3328 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3329 continue;
3330
3331 FOR_EACH_VEC_ELT (callers, j, cs)
3332 {
3333 struct ipa_jump_func *jump_func;
3334 tree t;
3335
3336 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3337 {
3338 newval = NULL_TREE;
3339 break;
3340 }
3341 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3342 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3343 if (!t
3344 || (newval
3345 && !values_equal_for_ipcp_p (t, newval))
3346 || (!first && !newval))
3347 {
3348 newval = NULL_TREE;
3349 break;
3350 }
3351 else
3352 newval = t;
3353 first = false;
3354 }
3355
3356 if (newval)
3357 {
3358 if (dump_file && (dump_flags & TDF_DETAILS))
3359 {
3360 fprintf (dump_file, " adding an extra known scalar value ");
3361 print_ipcp_constant_value (dump_file, newval);
3362 fprintf (dump_file, " for ");
3363 ipa_dump_param (dump_file, info, i);
3364 fprintf (dump_file, "\n");
3365 }
3366
3367 known_csts[i] = newval;
3368 }
3369 }
3370 }
3371
3372 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3373 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3374 CALLERS. */
3375
3376 static void
3377 find_more_contexts_for_caller_subset (cgraph_node *node,
3378 vec<ipa_polymorphic_call_context>
3379 *known_contexts,
3380 vec<cgraph_edge *> callers)
3381 {
3382 ipa_node_params *info = IPA_NODE_REF (node);
3383 int i, count = ipa_get_param_count (info);
3384
3385 for (i = 0; i < count ; i++)
3386 {
3387 cgraph_edge *cs;
3388
3389 if (ipa_get_poly_ctx_lat (info, i)->bottom
3390 || (known_contexts->exists ()
3391 && !(*known_contexts)[i].useless_p ()))
3392 continue;
3393
3394 ipa_polymorphic_call_context newval;
3395 bool first = true;
3396 int j;
3397
3398 FOR_EACH_VEC_ELT (callers, j, cs)
3399 {
3400 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3401 return;
3402 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3403 i);
3404 ipa_polymorphic_call_context ctx;
3405 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3406 jfunc);
3407 if (first)
3408 {
3409 newval = ctx;
3410 first = false;
3411 }
3412 else
3413 newval.meet_with (ctx);
3414 if (newval.useless_p ())
3415 break;
3416 }
3417
3418 if (!newval.useless_p ())
3419 {
3420 if (dump_file && (dump_flags & TDF_DETAILS))
3421 {
3422 fprintf (dump_file, " adding an extra known polymorphic "
3423 "context ");
3424 print_ipcp_constant_value (dump_file, newval);
3425 fprintf (dump_file, " for ");
3426 ipa_dump_param (dump_file, info, i);
3427 fprintf (dump_file, "\n");
3428 }
3429
3430 if (!known_contexts->exists ())
3431 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3432 (*known_contexts)[i] = newval;
3433 }
3434
3435 }
3436 }
3437
3438 /* Go through PLATS and create a vector of values consisting of values and
3439 offsets (minus OFFSET) of lattices that contain only a single value. */
3440
3441 static vec<ipa_agg_jf_item>
3442 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3443 {
3444 vec<ipa_agg_jf_item> res = vNULL;
3445
3446 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3447 return vNULL;
3448
3449 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3450 if (aglat->is_single_const ())
3451 {
3452 struct ipa_agg_jf_item ti;
3453 ti.offset = aglat->offset - offset;
3454 ti.value = aglat->values->value;
3455 res.safe_push (ti);
3456 }
3457 return res;
3458 }
3459
3460 /* Intersect all values in INTER with single value lattices in PLATS (while
3461 subtracting OFFSET). */
3462
3463 static void
3464 intersect_with_plats (struct ipcp_param_lattices *plats,
3465 vec<ipa_agg_jf_item> *inter,
3466 HOST_WIDE_INT offset)
3467 {
3468 struct ipcp_agg_lattice *aglat;
3469 struct ipa_agg_jf_item *item;
3470 int k;
3471
3472 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3473 {
3474 inter->release ();
3475 return;
3476 }
3477
3478 aglat = plats->aggs;
3479 FOR_EACH_VEC_ELT (*inter, k, item)
3480 {
3481 bool found = false;
3482 if (!item->value)
3483 continue;
3484 while (aglat)
3485 {
3486 if (aglat->offset - offset > item->offset)
3487 break;
3488 if (aglat->offset - offset == item->offset)
3489 {
3490 gcc_checking_assert (item->value);
3491 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
3492 found = true;
3493 break;
3494 }
3495 aglat = aglat->next;
3496 }
3497 if (!found)
3498 item->value = NULL_TREE;
3499 }
3500 }
3501
3502 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3503 vector result while subtracting OFFSET from the individual value offsets. */
3504
3505 static vec<ipa_agg_jf_item>
3506 agg_replacements_to_vector (struct cgraph_node *node, int index,
3507 HOST_WIDE_INT offset)
3508 {
3509 struct ipa_agg_replacement_value *av;
3510 vec<ipa_agg_jf_item> res = vNULL;
3511
3512 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
3513 if (av->index == index
3514 && (av->offset - offset) >= 0)
3515 {
3516 struct ipa_agg_jf_item item;
3517 gcc_checking_assert (av->value);
3518 item.offset = av->offset - offset;
3519 item.value = av->value;
3520 res.safe_push (item);
3521 }
3522
3523 return res;
3524 }
3525
3526 /* Intersect all values in INTER with those that we have already scheduled to
3527 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3528 (while subtracting OFFSET). */
3529
3530 static void
3531 intersect_with_agg_replacements (struct cgraph_node *node, int index,
3532 vec<ipa_agg_jf_item> *inter,
3533 HOST_WIDE_INT offset)
3534 {
3535 struct ipa_agg_replacement_value *srcvals;
3536 struct ipa_agg_jf_item *item;
3537 int i;
3538
3539 srcvals = ipa_get_agg_replacements_for_node (node);
3540 if (!srcvals)
3541 {
3542 inter->release ();
3543 return;
3544 }
3545
3546 FOR_EACH_VEC_ELT (*inter, i, item)
3547 {
3548 struct ipa_agg_replacement_value *av;
3549 bool found = false;
3550 if (!item->value)
3551 continue;
3552 for (av = srcvals; av; av = av->next)
3553 {
3554 gcc_checking_assert (av->value);
3555 if (av->index == index
3556 && av->offset - offset == item->offset)
3557 {
3558 if (values_equal_for_ipcp_p (item->value, av->value))
3559 found = true;
3560 break;
3561 }
3562 }
3563 if (!found)
3564 item->value = NULL_TREE;
3565 }
3566 }
3567
3568 /* Intersect values in INTER with aggregate values that come along edge CS to
3569 parameter number INDEX and return it. If INTER does not actually exist yet,
3570 copy all incoming values to it. If we determine we ended up with no values
3571 whatsoever, return a released vector. */
3572
3573 static vec<ipa_agg_jf_item>
3574 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
3575 vec<ipa_agg_jf_item> inter)
3576 {
3577 struct ipa_jump_func *jfunc;
3578 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3579 if (jfunc->type == IPA_JF_PASS_THROUGH
3580 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3581 {
3582 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3583 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3584
3585 if (caller_info->ipcp_orig_node)
3586 {
3587 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3588 struct ipcp_param_lattices *orig_plats;
3589 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3590 src_idx);
3591 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3592 {
3593 if (!inter.exists ())
3594 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
3595 else
3596 intersect_with_agg_replacements (cs->caller, src_idx,
3597 &inter, 0);
3598 }
3599 else
3600 {
3601 inter.release ();
3602 return vNULL;
3603 }
3604 }
3605 else
3606 {
3607 struct ipcp_param_lattices *src_plats;
3608 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3609 if (agg_pass_through_permissible_p (src_plats, jfunc))
3610 {
3611 /* Currently we do not produce clobber aggregate jump
3612 functions, adjust when we do. */
3613 gcc_checking_assert (!jfunc->agg.items);
3614 if (!inter.exists ())
3615 inter = copy_plats_to_inter (src_plats, 0);
3616 else
3617 intersect_with_plats (src_plats, &inter, 0);
3618 }
3619 else
3620 {
3621 inter.release ();
3622 return vNULL;
3623 }
3624 }
3625 }
3626 else if (jfunc->type == IPA_JF_ANCESTOR
3627 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3628 {
3629 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3630 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3631 struct ipcp_param_lattices *src_plats;
3632 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3633
3634 if (caller_info->ipcp_orig_node)
3635 {
3636 if (!inter.exists ())
3637 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
3638 else
3639 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
3640 delta);
3641 }
3642 else
3643 {
3644 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3645 /* Currently we do not produce clobber aggregate jump
3646 functions, adjust when we do. */
3647 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3648 if (!inter.exists ())
3649 inter = copy_plats_to_inter (src_plats, delta);
3650 else
3651 intersect_with_plats (src_plats, &inter, delta);
3652 }
3653 }
3654 else if (jfunc->agg.items)
3655 {
3656 struct ipa_agg_jf_item *item;
3657 int k;
3658
3659 if (!inter.exists ())
3660 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3661 inter.safe_push ((*jfunc->agg.items)[i]);
3662 else
3663 FOR_EACH_VEC_ELT (inter, k, item)
3664 {
3665 int l = 0;
3666 bool found = false;;
3667
3668 if (!item->value)
3669 continue;
3670
3671 while ((unsigned) l < jfunc->agg.items->length ())
3672 {
3673 struct ipa_agg_jf_item *ti;
3674 ti = &(*jfunc->agg.items)[l];
3675 if (ti->offset > item->offset)
3676 break;
3677 if (ti->offset == item->offset)
3678 {
3679 gcc_checking_assert (ti->value);
3680 if (values_equal_for_ipcp_p (item->value,
3681 ti->value))
3682 found = true;
3683 break;
3684 }
3685 l++;
3686 }
3687 if (!found)
3688 item->value = NULL;
3689 }
3690 }
3691 else
3692 {
3693 inter.release ();
3694 return vec<ipa_agg_jf_item>();
3695 }
3696 return inter;
3697 }
3698
3699 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3700 from all of them. */
3701
3702 static struct ipa_agg_replacement_value *
3703 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3704 vec<cgraph_edge *> callers)
3705 {
3706 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3707 struct ipa_agg_replacement_value *res;
3708 struct ipa_agg_replacement_value **tail = &res;
3709 struct cgraph_edge *cs;
3710 int i, j, count = ipa_get_param_count (dest_info);
3711
3712 FOR_EACH_VEC_ELT (callers, j, cs)
3713 {
3714 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3715 if (c < count)
3716 count = c;
3717 }
3718
3719 for (i = 0; i < count ; i++)
3720 {
3721 struct cgraph_edge *cs;
3722 vec<ipa_agg_jf_item> inter = vNULL;
3723 struct ipa_agg_jf_item *item;
3724 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3725 int j;
3726
3727 /* Among other things, the following check should deal with all by_ref
3728 mismatches. */
3729 if (plats->aggs_bottom)
3730 continue;
3731
3732 FOR_EACH_VEC_ELT (callers, j, cs)
3733 {
3734 inter = intersect_aggregates_with_edge (cs, i, inter);
3735
3736 if (!inter.exists ())
3737 goto next_param;
3738 }
3739
3740 FOR_EACH_VEC_ELT (inter, j, item)
3741 {
3742 struct ipa_agg_replacement_value *v;
3743
3744 if (!item->value)
3745 continue;
3746
3747 v = ggc_alloc<ipa_agg_replacement_value> ();
3748 v->index = i;
3749 v->offset = item->offset;
3750 v->value = item->value;
3751 v->by_ref = plats->aggs_by_ref;
3752 *tail = v;
3753 tail = &v->next;
3754 }
3755
3756 next_param:
3757 if (inter.exists ())
3758 inter.release ();
3759 }
3760 *tail = NULL;
3761 return res;
3762 }
3763
3764 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3765
3766 static struct ipa_agg_replacement_value *
3767 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
3768 {
3769 struct ipa_agg_replacement_value *res;
3770 struct ipa_agg_replacement_value **tail = &res;
3771 struct ipa_agg_jump_function *aggjf;
3772 struct ipa_agg_jf_item *item;
3773 int i, j;
3774
3775 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3776 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3777 {
3778 struct ipa_agg_replacement_value *v;
3779 v = ggc_alloc<ipa_agg_replacement_value> ();
3780 v->index = i;
3781 v->offset = item->offset;
3782 v->value = item->value;
3783 v->by_ref = aggjf->by_ref;
3784 *tail = v;
3785 tail = &v->next;
3786 }
3787 *tail = NULL;
3788 return res;
3789 }
3790
3791 /* Determine whether CS also brings all scalar values that the NODE is
3792 specialized for. */
3793
3794 static bool
3795 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3796 struct cgraph_node *node)
3797 {
3798 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3799 int count = ipa_get_param_count (dest_info);
3800 struct ipa_node_params *caller_info;
3801 struct ipa_edge_args *args;
3802 int i;
3803
3804 caller_info = IPA_NODE_REF (cs->caller);
3805 args = IPA_EDGE_REF (cs);
3806 for (i = 0; i < count; i++)
3807 {
3808 struct ipa_jump_func *jump_func;
3809 tree val, t;
3810
3811 val = dest_info->known_csts[i];
3812 if (!val)
3813 continue;
3814
3815 if (i >= ipa_get_cs_argument_count (args))
3816 return false;
3817 jump_func = ipa_get_ith_jump_func (args, i);
3818 t = ipa_value_from_jfunc (caller_info, jump_func);
3819 if (!t || !values_equal_for_ipcp_p (val, t))
3820 return false;
3821 }
3822 return true;
3823 }
3824
3825 /* Determine whether CS also brings all aggregate values that NODE is
3826 specialized for. */
3827 static bool
3828 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3829 struct cgraph_node *node)
3830 {
3831 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3832 struct ipa_node_params *orig_node_info;
3833 struct ipa_agg_replacement_value *aggval;
3834 int i, ec, count;
3835
3836 aggval = ipa_get_agg_replacements_for_node (node);
3837 if (!aggval)
3838 return true;
3839
3840 count = ipa_get_param_count (IPA_NODE_REF (node));
3841 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3842 if (ec < count)
3843 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3844 if (aggval->index >= ec)
3845 return false;
3846
3847 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3848 if (orig_caller_info->ipcp_orig_node)
3849 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3850
3851 for (i = 0; i < count; i++)
3852 {
3853 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
3854 struct ipcp_param_lattices *plats;
3855 bool interesting = false;
3856 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3857 if (aggval->index == i)
3858 {
3859 interesting = true;
3860 break;
3861 }
3862 if (!interesting)
3863 continue;
3864
3865 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3866 if (plats->aggs_bottom)
3867 return false;
3868
3869 values = intersect_aggregates_with_edge (cs, i, values);
3870 if (!values.exists ())
3871 return false;
3872
3873 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3874 if (aggval->index == i)
3875 {
3876 struct ipa_agg_jf_item *item;
3877 int j;
3878 bool found = false;
3879 FOR_EACH_VEC_ELT (values, j, item)
3880 if (item->value
3881 && item->offset == av->offset
3882 && values_equal_for_ipcp_p (item->value, av->value))
3883 {
3884 found = true;
3885 break;
3886 }
3887 if (!found)
3888 {
3889 values.release ();
3890 return false;
3891 }
3892 }
3893 }
3894 return true;
3895 }
3896
3897 /* Given an original NODE and a VAL for which we have already created a
3898 specialized clone, look whether there are incoming edges that still lead
3899 into the old node but now also bring the requested value and also conform to
3900 all other criteria such that they can be redirected the the special node.
3901 This function can therefore redirect the final edge in a SCC. */
3902
3903 template <typename valtype>
3904 static void
3905 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
3906 {
3907 ipcp_value_source<valtype> *src;
3908 gcov_type redirected_sum = 0;
3909
3910 for (src = val->sources; src; src = src->next)
3911 {
3912 struct cgraph_edge *cs = src->cs;
3913 while (cs)
3914 {
3915 if (cgraph_edge_brings_value_p (cs, src, node)
3916 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3917 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
3918 {
3919 if (dump_file)
3920 fprintf (dump_file, " - adding an extra caller %s/%i"
3921 " of %s/%i\n",
3922 xstrdup_for_dump (cs->caller->name ()),
3923 cs->caller->order,
3924 xstrdup_for_dump (val->spec_node->name ()),
3925 val->spec_node->order);
3926
3927 cs->redirect_callee_duplicating_thunks (val->spec_node);
3928 val->spec_node->expand_all_artificial_thunks ();
3929 redirected_sum += cs->count;
3930 }
3931 cs = get_next_cgraph_edge_clone (cs);
3932 }
3933 }
3934
3935 if (redirected_sum)
3936 update_specialized_profile (val->spec_node, node, redirected_sum);
3937 }
3938
3939 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
3940
3941 static bool
3942 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
3943 {
3944 ipa_polymorphic_call_context *ctx;
3945 int i;
3946
3947 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
3948 if (!ctx->useless_p ())
3949 return true;
3950 return false;
3951 }
3952
3953 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
3954
3955 static vec<ipa_polymorphic_call_context>
3956 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
3957 {
3958 if (known_contexts_useful_p (known_contexts))
3959 return known_contexts.copy ();
3960 else
3961 return vNULL;
3962 }
3963
3964 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
3965 non-empty, replace KNOWN_CONTEXTS with its copy too. */
3966
3967 static void
3968 modify_known_vectors_with_val (vec<tree> *known_csts,
3969 vec<ipa_polymorphic_call_context> *known_contexts,
3970 ipcp_value<tree> *val,
3971 int index)
3972 {
3973 *known_csts = known_csts->copy ();
3974 *known_contexts = copy_useful_known_contexts (*known_contexts);
3975 (*known_csts)[index] = val->value;
3976 }
3977
3978 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
3979 copy according to VAL and INDEX. */
3980
3981 static void
3982 modify_known_vectors_with_val (vec<tree> *known_csts,
3983 vec<ipa_polymorphic_call_context> *known_contexts,
3984 ipcp_value<ipa_polymorphic_call_context> *val,
3985 int index)
3986 {
3987 *known_csts = known_csts->copy ();
3988 *known_contexts = known_contexts->copy ();
3989 (*known_contexts)[index] = val->value;
3990 }
3991
3992 /* Return true if OFFSET indicates this was not an aggregate value or there is
3993 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
3994 AGGVALS list. */
3995
3996 DEBUG_FUNCTION bool
3997 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
3998 int index, HOST_WIDE_INT offset, tree value)
3999 {
4000 if (offset == -1)
4001 return true;
4002
4003 while (aggvals)
4004 {
4005 if (aggvals->index == index
4006 && aggvals->offset == offset
4007 && values_equal_for_ipcp_p (aggvals->value, value))
4008 return true;
4009 aggvals = aggvals->next;
4010 }
4011 return false;
4012 }
4013
4014 /* Return true if offset is minus one because source of a polymorphic contect
4015 cannot be an aggregate value. */
4016
4017 DEBUG_FUNCTION bool
4018 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4019 int , HOST_WIDE_INT offset,
4020 ipa_polymorphic_call_context)
4021 {
4022 return offset == -1;
4023 }
4024
4025 /* Decide wheter to create a special version of NODE for value VAL of parameter
4026 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4027 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4028 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4029
4030 template <typename valtype>
4031 static bool
4032 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4033 ipcp_value<valtype> *val, vec<tree> known_csts,
4034 vec<ipa_polymorphic_call_context> known_contexts)
4035 {
4036 struct ipa_agg_replacement_value *aggvals;
4037 int freq_sum, caller_count;
4038 gcov_type count_sum;
4039 vec<cgraph_edge *> callers;
4040
4041 if (val->spec_node)
4042 {
4043 perhaps_add_new_callers (node, val);
4044 return false;
4045 }
4046 else if (val->local_size_cost + overall_size > max_new_size)
4047 {
4048 if (dump_file && (dump_flags & TDF_DETAILS))
4049 fprintf (dump_file, " Ignoring candidate value because "
4050 "max_new_size would be reached with %li.\n",
4051 val->local_size_cost + overall_size);
4052 return false;
4053 }
4054 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4055 &caller_count))
4056 return false;
4057
4058 if (dump_file && (dump_flags & TDF_DETAILS))
4059 {
4060 fprintf (dump_file, " - considering value ");
4061 print_ipcp_constant_value (dump_file, val->value);
4062 fprintf (dump_file, " for ");
4063 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4064 if (offset != -1)
4065 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4066 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4067 }
4068
4069 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4070 freq_sum, count_sum,
4071 val->local_size_cost)
4072 && !good_cloning_opportunity_p (node,
4073 val->local_time_benefit
4074 + val->prop_time_benefit,
4075 freq_sum, count_sum,
4076 val->local_size_cost
4077 + val->prop_size_cost))
4078 return false;
4079
4080 if (dump_file)
4081 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
4082 node->name (), node->order);
4083
4084 callers = gather_edges_for_value (val, node, caller_count);
4085 if (offset == -1)
4086 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4087 else
4088 {
4089 known_csts = known_csts.copy ();
4090 known_contexts = copy_useful_known_contexts (known_contexts);
4091 }
4092 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4093 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4094 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4095 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4096 offset, val->value));
4097 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4098 aggvals, callers);
4099 overall_size += val->local_size_cost;
4100
4101 /* TODO: If for some lattice there is only one other known value
4102 left, make a special node for it too. */
4103
4104 return true;
4105 }
4106
4107 /* Decide whether and what specialized clones of NODE should be created. */
4108
4109 static bool
4110 decide_whether_version_node (struct cgraph_node *node)
4111 {
4112 struct ipa_node_params *info = IPA_NODE_REF (node);
4113 int i, count = ipa_get_param_count (info);
4114 vec<tree> known_csts;
4115 vec<ipa_polymorphic_call_context> known_contexts;
4116 vec<ipa_agg_jump_function> known_aggs = vNULL;
4117 bool ret = false;
4118
4119 if (count == 0)
4120 return false;
4121
4122 if (dump_file && (dump_flags & TDF_DETAILS))
4123 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4124 node->name (), node->order);
4125
4126 gather_context_independent_values (info, &known_csts, &known_contexts,
4127 info->do_clone_for_all_contexts ? &known_aggs
4128 : NULL, NULL);
4129
4130 for (i = 0; i < count ;i++)
4131 {
4132 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4133 ipcp_lattice<tree> *lat = &plats->itself;
4134 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4135
4136 if (!lat->bottom
4137 && !known_csts[i])
4138 {
4139 ipcp_value<tree> *val;
4140 for (val = lat->values; val; val = val->next)
4141 ret |= decide_about_value (node, i, -1, val, known_csts,
4142 known_contexts);
4143 }
4144
4145 if (!plats->aggs_bottom)
4146 {
4147 struct ipcp_agg_lattice *aglat;
4148 ipcp_value<tree> *val;
4149 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4150 if (!aglat->bottom && aglat->values
4151 /* If the following is false, the one value is in
4152 known_aggs. */
4153 && (plats->aggs_contain_variable
4154 || !aglat->is_single_const ()))
4155 for (val = aglat->values; val; val = val->next)
4156 ret |= decide_about_value (node, i, aglat->offset, val,
4157 known_csts, known_contexts);
4158 }
4159
4160 if (!ctxlat->bottom
4161 && known_contexts[i].useless_p ())
4162 {
4163 ipcp_value<ipa_polymorphic_call_context> *val;
4164 for (val = ctxlat->values; val; val = val->next)
4165 ret |= decide_about_value (node, i, -1, val, known_csts,
4166 known_contexts);
4167 }
4168
4169 info = IPA_NODE_REF (node);
4170 }
4171
4172 if (info->do_clone_for_all_contexts)
4173 {
4174 struct cgraph_node *clone;
4175 vec<cgraph_edge *> callers;
4176
4177 if (dump_file)
4178 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4179 "for all known contexts.\n", node->name (),
4180 node->order);
4181
4182 callers = node->collect_callers ();
4183
4184 if (!known_contexts_useful_p (known_contexts))
4185 {
4186 known_contexts.release ();
4187 known_contexts = vNULL;
4188 }
4189 clone = create_specialized_node (node, known_csts, known_contexts,
4190 known_aggs_to_agg_replacement_list (known_aggs),
4191 callers);
4192 info = IPA_NODE_REF (node);
4193 info->do_clone_for_all_contexts = false;
4194 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4195 for (i = 0; i < count ; i++)
4196 vec_free (known_aggs[i].items);
4197 known_aggs.release ();
4198 ret = true;
4199 }
4200 else
4201 {
4202 known_csts.release ();
4203 known_contexts.release ();
4204 }
4205
4206 return ret;
4207 }
4208
4209 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4210
4211 static void
4212 spread_undeadness (struct cgraph_node *node)
4213 {
4214 struct cgraph_edge *cs;
4215
4216 for (cs = node->callees; cs; cs = cs->next_callee)
4217 if (ipa_edge_within_scc (cs))
4218 {
4219 struct cgraph_node *callee;
4220 struct ipa_node_params *info;
4221
4222 callee = cs->callee->function_symbol (NULL);
4223 info = IPA_NODE_REF (callee);
4224
4225 if (info->node_dead)
4226 {
4227 info->node_dead = 0;
4228 spread_undeadness (callee);
4229 }
4230 }
4231 }
4232
4233 /* Return true if NODE has a caller from outside of its SCC that is not
4234 dead. Worker callback for cgraph_for_node_and_aliases. */
4235
4236 static bool
4237 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4238 void *data ATTRIBUTE_UNUSED)
4239 {
4240 struct cgraph_edge *cs;
4241
4242 for (cs = node->callers; cs; cs = cs->next_caller)
4243 if (cs->caller->thunk.thunk_p
4244 && cs->caller->call_for_symbol_thunks_and_aliases
4245 (has_undead_caller_from_outside_scc_p, NULL, true))
4246 return true;
4247 else if (!ipa_edge_within_scc (cs)
4248 && !IPA_NODE_REF (cs->caller)->node_dead)
4249 return true;
4250 return false;
4251 }
4252
4253
4254 /* Identify nodes within the same SCC as NODE which are no longer needed
4255 because of new clones and will be removed as unreachable. */
4256
4257 static void
4258 identify_dead_nodes (struct cgraph_node *node)
4259 {
4260 struct cgraph_node *v;
4261 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4262 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
4263 && !v->call_for_symbol_thunks_and_aliases
4264 (has_undead_caller_from_outside_scc_p, NULL, true))
4265 IPA_NODE_REF (v)->node_dead = 1;
4266
4267 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4268 if (!IPA_NODE_REF (v)->node_dead)
4269 spread_undeadness (v);
4270
4271 if (dump_file && (dump_flags & TDF_DETAILS))
4272 {
4273 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4274 if (IPA_NODE_REF (v)->node_dead)
4275 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4276 v->name (), v->order);
4277 }
4278 }
4279
4280 /* The decision stage. Iterate over the topological order of call graph nodes
4281 TOPO and make specialized clones if deemed beneficial. */
4282
4283 static void
4284 ipcp_decision_stage (struct ipa_topo_info *topo)
4285 {
4286 int i;
4287
4288 if (dump_file)
4289 fprintf (dump_file, "\nIPA decision stage:\n\n");
4290
4291 for (i = topo->nnodes - 1; i >= 0; i--)
4292 {
4293 struct cgraph_node *node = topo->order[i];
4294 bool change = false, iterate = true;
4295
4296 while (iterate)
4297 {
4298 struct cgraph_node *v;
4299 iterate = false;
4300 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4301 if (v->has_gimple_body_p ()
4302 && ipcp_versionable_function_p (v))
4303 iterate |= decide_whether_version_node (v);
4304
4305 change |= iterate;
4306 }
4307 if (change)
4308 identify_dead_nodes (node);
4309 }
4310 }
4311
4312 /* Look up all alignment information that we have discovered and copy it over
4313 to the transformation summary. */
4314
4315 static void
4316 ipcp_store_alignment_results (void)
4317 {
4318 cgraph_node *node;
4319
4320 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4321 {
4322 ipa_node_params *info = IPA_NODE_REF (node);
4323 bool dumped_sth = false;
4324 bool found_useful_result = false;
4325
4326 if (!opt_for_fn (node->decl, flag_ipa_cp_alignment))
4327 {
4328 if (dump_file)
4329 fprintf (dump_file, "Not considering %s for alignment discovery "
4330 "and propagate; -fipa-cp-alignment: disabled.\n",
4331 node->name ());
4332 continue;
4333 }
4334
4335 if (info->ipcp_orig_node)
4336 info = IPA_NODE_REF (info->ipcp_orig_node);
4337
4338 unsigned count = ipa_get_param_count (info);
4339 for (unsigned i = 0; i < count ; i++)
4340 {
4341 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4342 if (plats->alignment.known
4343 && plats->alignment.align > 0)
4344 {
4345 found_useful_result = true;
4346 break;
4347 }
4348 }
4349 if (!found_useful_result)
4350 continue;
4351
4352 ipcp_grow_transformations_if_necessary ();
4353 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4354 vec_safe_reserve_exact (ts->alignments, count);
4355
4356 for (unsigned i = 0; i < count ; i++)
4357 {
4358 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4359
4360 if (plats->alignment.align == 0)
4361 plats->alignment.known = false;
4362
4363 ts->alignments->quick_push (plats->alignment);
4364 if (!dump_file || !plats->alignment.known)
4365 continue;
4366 if (!dumped_sth)
4367 {
4368 fprintf (dump_file, "Propagated alignment info for function %s/%i:\n",
4369 node->name (), node->order);
4370 dumped_sth = true;
4371 }
4372 fprintf (dump_file, " param %i: align: %u, misalign: %u\n",
4373 i, plats->alignment.align, plats->alignment.misalign);
4374 }
4375 }
4376 }
4377
4378 /* The IPCP driver. */
4379
4380 static unsigned int
4381 ipcp_driver (void)
4382 {
4383 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4384 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4385 struct ipa_topo_info topo;
4386
4387 ipa_check_create_node_params ();
4388 ipa_check_create_edge_args ();
4389 grow_edge_clone_vectors ();
4390 edge_duplication_hook_holder =
4391 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4392 edge_removal_hook_holder =
4393 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4394
4395 ipcp_cst_values_pool = create_alloc_pool ("IPA-CP constant values",
4396 sizeof (ipcp_value<tree>), 32);
4397 ipcp_poly_ctx_values_pool = create_alloc_pool
4398 ("IPA-CP polymorphic contexts",
4399 sizeof (ipcp_value<ipa_polymorphic_call_context>), 32);
4400 ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources",
4401 sizeof (ipcp_value_source<tree>), 64);
4402 ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices",
4403 sizeof (struct ipcp_agg_lattice),
4404 32);
4405 if (dump_file)
4406 {
4407 fprintf (dump_file, "\nIPA structures before propagation:\n");
4408 if (dump_flags & TDF_DETAILS)
4409 ipa_print_all_params (dump_file);
4410 ipa_print_all_jump_functions (dump_file);
4411 }
4412
4413 /* Topological sort. */
4414 build_toporder_info (&topo);
4415 /* Do the interprocedural propagation. */
4416 ipcp_propagate_stage (&topo);
4417 /* Decide what constant propagation and cloning should be performed. */
4418 ipcp_decision_stage (&topo);
4419 /* Store results of alignment propagation. */
4420 ipcp_store_alignment_results ();
4421
4422 /* Free all IPCP structures. */
4423 free_toporder_info (&topo);
4424 next_edge_clone.release ();
4425 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4426 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
4427 ipa_free_all_structures_after_ipa_cp ();
4428 if (dump_file)
4429 fprintf (dump_file, "\nIPA constant propagation end\n");
4430 return 0;
4431 }
4432
4433 /* Initialization and computation of IPCP data structures. This is the initial
4434 intraprocedural analysis of functions, which gathers information to be
4435 propagated later on. */
4436
4437 static void
4438 ipcp_generate_summary (void)
4439 {
4440 struct cgraph_node *node;
4441
4442 if (dump_file)
4443 fprintf (dump_file, "\nIPA constant propagation start:\n");
4444 ipa_register_cgraph_hooks ();
4445
4446 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4447 {
4448 node->local.versionable
4449 = tree_versionable_function_p (node->decl);
4450 ipa_analyze_node (node);
4451 }
4452 }
4453
4454 /* Write ipcp summary for nodes in SET. */
4455
4456 static void
4457 ipcp_write_summary (void)
4458 {
4459 ipa_prop_write_jump_functions ();
4460 }
4461
4462 /* Read ipcp summary. */
4463
4464 static void
4465 ipcp_read_summary (void)
4466 {
4467 ipa_prop_read_jump_functions ();
4468 }
4469
4470 namespace {
4471
4472 const pass_data pass_data_ipa_cp =
4473 {
4474 IPA_PASS, /* type */
4475 "cp", /* name */
4476 OPTGROUP_NONE, /* optinfo_flags */
4477 TV_IPA_CONSTANT_PROP, /* tv_id */
4478 0, /* properties_required */
4479 0, /* properties_provided */
4480 0, /* properties_destroyed */
4481 0, /* todo_flags_start */
4482 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
4483 };
4484
4485 class pass_ipa_cp : public ipa_opt_pass_d
4486 {
4487 public:
4488 pass_ipa_cp (gcc::context *ctxt)
4489 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
4490 ipcp_generate_summary, /* generate_summary */
4491 ipcp_write_summary, /* write_summary */
4492 ipcp_read_summary, /* read_summary */
4493 ipcp_write_transformation_summaries, /*
4494 write_optimization_summary */
4495 ipcp_read_transformation_summaries, /*
4496 read_optimization_summary */
4497 NULL, /* stmt_fixup */
4498 0, /* function_transform_todo_flags_start */
4499 ipcp_transform_function, /* function_transform */
4500 NULL) /* variable_transform */
4501 {}
4502
4503 /* opt_pass methods: */
4504 virtual bool gate (function *)
4505 {
4506 /* FIXME: We should remove the optimize check after we ensure we never run
4507 IPA passes when not optimizing. */
4508 return (flag_ipa_cp && optimize) || in_lto_p;
4509 }
4510
4511 virtual unsigned int execute (function *) { return ipcp_driver (); }
4512
4513 }; // class pass_ipa_cp
4514
4515 } // anon namespace
4516
4517 ipa_opt_pass_d *
4518 make_pass_ipa_cp (gcc::context *ctxt)
4519 {
4520 return new pass_ipa_cp (ctxt);
4521 }
4522
4523 /* Reset all state within ipa-cp.c so that we can rerun the compiler
4524 within the same process. For use by toplev::finalize. */
4525
4526 void
4527 ipa_cp_c_finalize (void)
4528 {
4529 max_count = 0;
4530 overall_size = 0;
4531 max_new_size = 0;
4532 }