2015-08-31 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / ipa-cp.c
blob8de7e56847ef441a996a22ac0616aed5ab5d6022
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
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.
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.
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/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
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
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.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
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.
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.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
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:
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.
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.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
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.
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.
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.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
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. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "alias.h"
107 #include "tree.h"
108 #include "options.h"
109 #include "fold-const.h"
110 #include "gimple-fold.h"
111 #include "gimple-expr.h"
112 #include "target.h"
113 #include "backend.h"
114 #include "predict.h"
115 #include "hard-reg-set.h"
116 #include "cgraph.h"
117 #include "alloc-pool.h"
118 #include "symbol-summary.h"
119 #include "ipa-prop.h"
120 #include "tree-pass.h"
121 #include "flags.h"
122 #include "diagnostic.h"
123 #include "tree-pretty-print.h"
124 #include "tree-inline.h"
125 #include "params.h"
126 #include "ipa-inline.h"
127 #include "ipa-utils.h"
129 template <typename valtype> class ipcp_value;
131 /* Describes a particular source for an IPA-CP value. */
133 template <typename valtype>
134 class ipcp_value_source
136 public:
137 /* Aggregate offset of the source, negative if the source is scalar value of
138 the argument itself. */
139 HOST_WIDE_INT offset;
140 /* The incoming edge that brought the value. */
141 cgraph_edge *cs;
142 /* If the jump function that resulted into his value was a pass-through or an
143 ancestor, this is the ipcp_value of the caller from which the described
144 value has been derived. Otherwise it is NULL. */
145 ipcp_value<valtype> *val;
146 /* Next pointer in a linked list of sources of a value. */
147 ipcp_value_source *next;
148 /* If the jump function that resulted into his value was a pass-through or an
149 ancestor, this is the index of the parameter of the caller the jump
150 function references. */
151 int index;
154 /* Common ancestor for all ipcp_value instantiations. */
156 class ipcp_value_base
158 public:
159 /* Time benefit and size cost that specializing the function for this value
160 would bring about in this function alone. */
161 int local_time_benefit, local_size_cost;
162 /* Time benefit and size cost that specializing the function for this value
163 can bring about in it's callees (transitively). */
164 int prop_time_benefit, prop_size_cost;
167 /* Describes one particular value stored in struct ipcp_lattice. */
169 template <typename valtype>
170 class ipcp_value : public ipcp_value_base
172 public:
173 /* The actual value for the given parameter. */
174 valtype value;
175 /* The list of sources from which this value originates. */
176 ipcp_value_source <valtype> *sources;
177 /* Next pointers in a linked list of all values in a lattice. */
178 ipcp_value *next;
179 /* Next pointers in a linked list of values in a strongly connected component
180 of values. */
181 ipcp_value *scc_next;
182 /* Next pointers in a linked list of SCCs of values sorted topologically
183 according their sources. */
184 ipcp_value *topo_next;
185 /* A specialized node created for this value, NULL if none has been (so far)
186 created. */
187 cgraph_node *spec_node;
188 /* Depth first search number and low link for topological sorting of
189 values. */
190 int dfs, low_link;
191 /* True if this valye is currently on the topo-sort stack. */
192 bool on_stack;
194 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
195 HOST_WIDE_INT offset);
198 /* Lattice describing potential values of a formal parameter of a function, or
199 a part of an aggreagate. TOP is represented by a lattice with zero values
200 and with contains_variable and bottom flags cleared. BOTTOM is represented
201 by a lattice with the bottom flag set. In that case, values and
202 contains_variable flag should be disregarded. */
204 template <typename valtype>
205 class ipcp_lattice
207 public:
208 /* The list of known values and types in this lattice. Note that values are
209 not deallocated if a lattice is set to bottom because there may be value
210 sources referencing them. */
211 ipcp_value<valtype> *values;
212 /* Number of known values and types in this lattice. */
213 int values_count;
214 /* The lattice contains a variable component (in addition to values). */
215 bool contains_variable;
216 /* The value of the lattice is bottom (i.e. variable and unusable for any
217 propagation). */
218 bool bottom;
220 inline bool is_single_const ();
221 inline bool set_to_bottom ();
222 inline bool set_contains_variable ();
223 bool add_value (valtype newval, cgraph_edge *cs,
224 ipcp_value<valtype> *src_val = NULL,
225 int src_idx = 0, HOST_WIDE_INT offset = -1);
226 void print (FILE * f, bool dump_sources, bool dump_benefits);
229 /* Lattice of tree values with an offset to describe a part of an
230 aggregate. */
232 class ipcp_agg_lattice : public ipcp_lattice<tree>
234 public:
235 /* Offset that is being described by this lattice. */
236 HOST_WIDE_INT offset;
237 /* Size so that we don't have to re-compute it every time we traverse the
238 list. Must correspond to TYPE_SIZE of all lat values. */
239 HOST_WIDE_INT size;
240 /* Next element of the linked list. */
241 struct ipcp_agg_lattice *next;
244 /* Structure containing lattices for a parameter itself and for pieces of
245 aggregates that are passed in the parameter or by a reference in a parameter
246 plus some other useful flags. */
248 class ipcp_param_lattices
250 public:
251 /* Lattice describing the value of the parameter itself. */
252 ipcp_lattice<tree> itself;
253 /* Lattice describing the polymorphic contexts of a parameter. */
254 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
255 /* Lattices describing aggregate parts. */
256 ipcp_agg_lattice *aggs;
257 /* Alignment information. Very basic one value lattice where !known means
258 TOP and zero alignment bottom. */
259 ipa_alignment alignment;
260 /* Number of aggregate lattices */
261 int aggs_count;
262 /* True if aggregate data were passed by reference (as opposed to by
263 value). */
264 bool aggs_by_ref;
265 /* All aggregate lattices contain a variable component (in addition to
266 values). */
267 bool aggs_contain_variable;
268 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
269 for any propagation). */
270 bool aggs_bottom;
272 /* There is a virtual call based on this parameter. */
273 bool virt_call;
276 /* Allocation pools for values and their sources in ipa-cp. */
278 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
279 ("IPA-CP constant values", 32);
281 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
282 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts", 32);
284 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
285 ("IPA-CP value sources", 64);
287 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
288 ("IPA_CP aggregate lattices", 32);
290 /* Maximal count found in program. */
292 static gcov_type max_count;
294 /* Original overall size of the program. */
296 static long overall_size, max_new_size;
298 /* Return the param lattices structure corresponding to the Ith formal
299 parameter of the function described by INFO. */
300 static inline struct ipcp_param_lattices *
301 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
303 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
304 gcc_checking_assert (!info->ipcp_orig_node);
305 gcc_checking_assert (info->lattices);
306 return &(info->lattices[i]);
309 /* Return the lattice corresponding to the scalar value of the Ith formal
310 parameter of the function described by INFO. */
311 static inline ipcp_lattice<tree> *
312 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
314 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
315 return &plats->itself;
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<ipa_polymorphic_call_context> *
321 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
323 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
324 return &plats->ctxlat;
327 /* Return whether LAT is a lattice with a single constant and without an
328 undefined value. */
330 template <typename valtype>
331 inline bool
332 ipcp_lattice<valtype>::is_single_const ()
334 if (bottom || contains_variable || values_count != 1)
335 return false;
336 else
337 return true;
340 /* Print V which is extracted from a value in a lattice to F. */
342 static void
343 print_ipcp_constant_value (FILE * f, tree v)
345 if (TREE_CODE (v) == ADDR_EXPR
346 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
348 fprintf (f, "& ");
349 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
351 else
352 print_generic_expr (f, v, 0);
355 /* Print V which is extracted from a value in a lattice to F. */
357 static void
358 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
360 v.dump(f, false);
363 /* Print a lattice LAT to F. */
365 template <typename valtype>
366 void
367 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
369 ipcp_value<valtype> *val;
370 bool prev = false;
372 if (bottom)
374 fprintf (f, "BOTTOM\n");
375 return;
378 if (!values_count && !contains_variable)
380 fprintf (f, "TOP\n");
381 return;
384 if (contains_variable)
386 fprintf (f, "VARIABLE");
387 prev = true;
388 if (dump_benefits)
389 fprintf (f, "\n");
392 for (val = values; val; val = val->next)
394 if (dump_benefits && prev)
395 fprintf (f, " ");
396 else if (!dump_benefits && prev)
397 fprintf (f, ", ");
398 else
399 prev = true;
401 print_ipcp_constant_value (f, val->value);
403 if (dump_sources)
405 ipcp_value_source<valtype> *s;
407 fprintf (f, " [from:");
408 for (s = val->sources; s; s = s->next)
409 fprintf (f, " %i(%i)", s->cs->caller->order,
410 s->cs->frequency);
411 fprintf (f, "]");
414 if (dump_benefits)
415 fprintf (f, " [loc_time: %i, loc_size: %i, "
416 "prop_time: %i, prop_size: %i]\n",
417 val->local_time_benefit, val->local_size_cost,
418 val->prop_time_benefit, val->prop_size_cost);
420 if (!dump_benefits)
421 fprintf (f, "\n");
424 /* Print all ipcp_lattices of all functions to F. */
426 static void
427 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
429 struct cgraph_node *node;
430 int i, count;
432 fprintf (f, "\nLattices:\n");
433 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
435 struct ipa_node_params *info;
437 info = IPA_NODE_REF (node);
438 fprintf (f, " Node: %s/%i:\n", node->name (),
439 node->order);
440 count = ipa_get_param_count (info);
441 for (i = 0; i < count; i++)
443 struct ipcp_agg_lattice *aglat;
444 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
445 fprintf (f, " param [%d]: ", i);
446 plats->itself.print (f, dump_sources, dump_benefits);
447 fprintf (f, " ctxs: ");
448 plats->ctxlat.print (f, dump_sources, dump_benefits);
449 if (plats->alignment.known && plats->alignment.align > 0)
450 fprintf (f, " Alignment %u, misalignment %u\n",
451 plats->alignment.align, plats->alignment.misalign);
452 else if (plats->alignment.known)
453 fprintf (f, " Alignment unusable\n");
454 else
455 fprintf (f, " Alignment unknown\n");
456 if (plats->virt_call)
457 fprintf (f, " virt_call flag set\n");
459 if (plats->aggs_bottom)
461 fprintf (f, " AGGS BOTTOM\n");
462 continue;
464 if (plats->aggs_contain_variable)
465 fprintf (f, " AGGS VARIABLE\n");
466 for (aglat = plats->aggs; aglat; aglat = aglat->next)
468 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
469 plats->aggs_by_ref ? "ref " : "", aglat->offset);
470 aglat->print (f, dump_sources, dump_benefits);
476 /* Determine whether it is at all technically possible to create clones of NODE
477 and store this information in the ipa_node_params structure associated
478 with NODE. */
480 static void
481 determine_versionability (struct cgraph_node *node)
483 const char *reason = NULL;
485 /* There are a number of generic reasons functions cannot be versioned. We
486 also cannot remove parameters if there are type attributes such as fnspec
487 present. */
488 if (node->alias || node->thunk.thunk_p)
489 reason = "alias or thunk";
490 else if (!node->local.versionable)
491 reason = "not a tree_versionable_function";
492 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
493 reason = "insufficient body availability";
494 else if (!opt_for_fn (node->decl, optimize)
495 || !opt_for_fn (node->decl, flag_ipa_cp))
496 reason = "non-optimized function";
497 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
499 /* Ideally we should clone the SIMD clones themselves and create
500 vector copies of them, so IPA-cp and SIMD clones can happily
501 coexist, but that may not be worth the effort. */
502 reason = "function has SIMD clones";
504 /* Don't clone decls local to a comdat group; it breaks and for C++
505 decloned constructors, inlining is always better anyway. */
506 else if (node->comdat_local_p ())
507 reason = "comdat-local function";
509 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
510 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
511 node->name (), node->order, reason);
513 node->local.versionable = (reason == NULL);
516 /* Return true if it is at all technically possible to create clones of a
517 NODE. */
519 static bool
520 ipcp_versionable_function_p (struct cgraph_node *node)
522 return node->local.versionable;
525 /* Structure holding accumulated information about callers of a node. */
527 struct caller_statistics
529 gcov_type count_sum;
530 int n_calls, n_hot_calls, freq_sum;
533 /* Initialize fields of STAT to zeroes. */
535 static inline void
536 init_caller_stats (struct caller_statistics *stats)
538 stats->count_sum = 0;
539 stats->n_calls = 0;
540 stats->n_hot_calls = 0;
541 stats->freq_sum = 0;
544 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
545 non-thunk incoming edges to NODE. */
547 static bool
548 gather_caller_stats (struct cgraph_node *node, void *data)
550 struct caller_statistics *stats = (struct caller_statistics *) data;
551 struct cgraph_edge *cs;
553 for (cs = node->callers; cs; cs = cs->next_caller)
554 if (!cs->caller->thunk.thunk_p)
556 stats->count_sum += cs->count;
557 stats->freq_sum += cs->frequency;
558 stats->n_calls++;
559 if (cs->maybe_hot_p ())
560 stats->n_hot_calls ++;
562 return false;
566 /* Return true if this NODE is viable candidate for cloning. */
568 static bool
569 ipcp_cloning_candidate_p (struct cgraph_node *node)
571 struct caller_statistics stats;
573 gcc_checking_assert (node->has_gimple_body_p ());
575 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
577 if (dump_file)
578 fprintf (dump_file, "Not considering %s for cloning; "
579 "-fipa-cp-clone disabled.\n",
580 node->name ());
581 return false;
584 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
586 if (dump_file)
587 fprintf (dump_file, "Not considering %s for cloning; "
588 "optimizing it for size.\n",
589 node->name ());
590 return false;
593 init_caller_stats (&stats);
594 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
596 if (inline_summaries->get (node)->self_size < stats.n_calls)
598 if (dump_file)
599 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
600 node->name ());
601 return true;
604 /* When profile is available and function is hot, propagate into it even if
605 calls seems cold; constant propagation can improve function's speed
606 significantly. */
607 if (max_count)
609 if (stats.count_sum > node->count * 90 / 100)
611 if (dump_file)
612 fprintf (dump_file, "Considering %s for cloning; "
613 "usually called directly.\n",
614 node->name ());
615 return true;
618 if (!stats.n_hot_calls)
620 if (dump_file)
621 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
622 node->name ());
623 return false;
625 if (dump_file)
626 fprintf (dump_file, "Considering %s for cloning.\n",
627 node->name ());
628 return true;
631 template <typename valtype>
632 class value_topo_info
634 public:
635 /* Head of the linked list of topologically sorted values. */
636 ipcp_value<valtype> *values_topo;
637 /* Stack for creating SCCs, represented by a linked list too. */
638 ipcp_value<valtype> *stack;
639 /* Counter driving the algorithm in add_val_to_toposort. */
640 int dfs_counter;
642 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
644 void add_val (ipcp_value<valtype> *cur_val);
645 void propagate_effects ();
648 /* Arrays representing a topological ordering of call graph nodes and a stack
649 of nodes used during constant propagation and also data required to perform
650 topological sort of values and propagation of benefits in the determined
651 order. */
653 class ipa_topo_info
655 public:
656 /* Array with obtained topological order of cgraph nodes. */
657 struct cgraph_node **order;
658 /* Stack of cgraph nodes used during propagation within SCC until all values
659 in the SCC stabilize. */
660 struct cgraph_node **stack;
661 int nnodes, stack_top;
663 value_topo_info<tree> constants;
664 value_topo_info<ipa_polymorphic_call_context> contexts;
666 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
667 constants ()
671 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
673 static void
674 build_toporder_info (struct ipa_topo_info *topo)
676 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
677 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
679 gcc_checking_assert (topo->stack_top == 0);
680 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
683 /* Free information about strongly connected components and the arrays in
684 TOPO. */
686 static void
687 free_toporder_info (struct ipa_topo_info *topo)
689 ipa_free_postorder_info ();
690 free (topo->order);
691 free (topo->stack);
694 /* Add NODE to the stack in TOPO, unless it is already there. */
696 static inline void
697 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
699 struct ipa_node_params *info = IPA_NODE_REF (node);
700 if (info->node_enqueued)
701 return;
702 info->node_enqueued = 1;
703 topo->stack[topo->stack_top++] = node;
706 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
707 is empty. */
709 static struct cgraph_node *
710 pop_node_from_stack (struct ipa_topo_info *topo)
712 if (topo->stack_top)
714 struct cgraph_node *node;
715 topo->stack_top--;
716 node = topo->stack[topo->stack_top];
717 IPA_NODE_REF (node)->node_enqueued = 0;
718 return node;
720 else
721 return NULL;
724 /* Set lattice LAT to bottom and return true if it previously was not set as
725 such. */
727 template <typename valtype>
728 inline bool
729 ipcp_lattice<valtype>::set_to_bottom ()
731 bool ret = !bottom;
732 bottom = true;
733 return ret;
736 /* Mark lattice as containing an unknown value and return true if it previously
737 was not marked as such. */
739 template <typename valtype>
740 inline bool
741 ipcp_lattice<valtype>::set_contains_variable ()
743 bool ret = !contains_variable;
744 contains_variable = true;
745 return ret;
748 /* Set all aggegate lattices in PLATS to bottom and return true if they were
749 not previously set as such. */
751 static inline bool
752 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
754 bool ret = !plats->aggs_bottom;
755 plats->aggs_bottom = true;
756 return ret;
759 /* Mark all aggegate lattices in PLATS as containing an unknown value and
760 return true if they were not previously marked as such. */
762 static inline bool
763 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
765 bool ret = !plats->aggs_contain_variable;
766 plats->aggs_contain_variable = true;
767 return ret;
770 /* Return true if alignment information in PLATS is known to be unusable. */
772 static inline bool
773 alignment_bottom_p (ipcp_param_lattices *plats)
775 return plats->alignment.known && (plats->alignment.align == 0);
778 /* Set alignment information in PLATS to unusable. Return true if it
779 previously was usable or unknown. */
781 static inline bool
782 set_alignment_to_bottom (ipcp_param_lattices *plats)
784 if (alignment_bottom_p (plats))
785 return false;
786 plats->alignment.known = true;
787 plats->alignment.align = 0;
788 return true;
791 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
792 return true is any of them has not been marked as such so far. */
794 static inline bool
795 set_all_contains_variable (struct ipcp_param_lattices *plats)
797 bool ret;
798 ret = plats->itself.set_contains_variable ();
799 ret |= plats->ctxlat.set_contains_variable ();
800 ret |= set_agg_lats_contain_variable (plats);
801 ret |= set_alignment_to_bottom (plats);
802 return ret;
805 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
806 points to by the number of callers to NODE. */
808 static bool
809 count_callers (cgraph_node *node, void *data)
811 int *caller_count = (int *) data;
813 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
814 /* Local thunks can be handled transparently, but if the thunk can not
815 be optimized out, count it as a real use. */
816 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
817 ++*caller_count;
818 return false;
821 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
822 the one caller of some other node. Set the caller's corresponding flag. */
824 static bool
825 set_single_call_flag (cgraph_node *node, void *)
827 cgraph_edge *cs = node->callers;
828 /* Local thunks can be handled transparently, skip them. */
829 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
830 cs = cs->next_caller;
831 if (cs)
833 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
834 return true;
836 return false;
839 /* Initialize ipcp_lattices. */
841 static void
842 initialize_node_lattices (struct cgraph_node *node)
844 struct ipa_node_params *info = IPA_NODE_REF (node);
845 struct cgraph_edge *ie;
846 bool disable = false, variable = false;
847 int i;
849 gcc_checking_assert (node->has_gimple_body_p ());
850 if (cgraph_local_p (node))
852 int caller_count = 0;
853 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
854 true);
855 gcc_checking_assert (caller_count > 0);
856 if (caller_count == 1)
857 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
858 NULL, true);
860 else
862 /* When cloning is allowed, we can assume that externally visible
863 functions are not called. We will compensate this by cloning
864 later. */
865 if (ipcp_versionable_function_p (node)
866 && ipcp_cloning_candidate_p (node))
867 variable = true;
868 else
869 disable = true;
872 if (disable || variable)
874 for (i = 0; i < ipa_get_param_count (info) ; i++)
876 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
877 if (disable)
879 plats->itself.set_to_bottom ();
880 plats->ctxlat.set_to_bottom ();
881 set_agg_lats_to_bottom (plats);
882 set_alignment_to_bottom (plats);
884 else
885 set_all_contains_variable (plats);
887 if (dump_file && (dump_flags & TDF_DETAILS)
888 && !node->alias && !node->thunk.thunk_p)
889 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
890 node->name (), node->order,
891 disable ? "BOTTOM" : "VARIABLE");
894 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
895 if (ie->indirect_info->polymorphic
896 && ie->indirect_info->param_index >= 0)
898 gcc_checking_assert (ie->indirect_info->param_index >= 0);
899 ipa_get_parm_lattices (info,
900 ie->indirect_info->param_index)->virt_call = 1;
904 /* Return the result of a (possibly arithmetic) pass through jump function
905 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
906 determined or be considered an interprocedural invariant. */
908 static tree
909 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
911 tree restype, res;
913 gcc_checking_assert (is_gimple_ip_invariant (input));
914 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
915 return input;
917 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
918 == tcc_comparison)
919 restype = boolean_type_node;
920 else
921 restype = TREE_TYPE (input);
922 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
923 input, ipa_get_jf_pass_through_operand (jfunc));
925 if (res && !is_gimple_ip_invariant (res))
926 return NULL_TREE;
928 return res;
931 /* Return the result of an ancestor jump function JFUNC on the constant value
932 INPUT. Return NULL_TREE if that cannot be determined. */
934 static tree
935 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
937 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
938 if (TREE_CODE (input) == ADDR_EXPR)
940 tree t = TREE_OPERAND (input, 0);
941 t = build_ref_for_offset (EXPR_LOCATION (t), t,
942 ipa_get_jf_ancestor_offset (jfunc),
943 ptr_type_node, NULL, false);
944 return build_fold_addr_expr (t);
946 else
947 return NULL_TREE;
950 /* Determine whether JFUNC evaluates to a single known constant value and if
951 so, return it. Otherwise return NULL. INFO describes the caller node or
952 the one it is inlined to, so that pass-through jump functions can be
953 evaluated. */
955 tree
956 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
958 if (jfunc->type == IPA_JF_CONST)
959 return ipa_get_jf_constant (jfunc);
960 else if (jfunc->type == IPA_JF_PASS_THROUGH
961 || jfunc->type == IPA_JF_ANCESTOR)
963 tree input;
964 int idx;
966 if (jfunc->type == IPA_JF_PASS_THROUGH)
967 idx = ipa_get_jf_pass_through_formal_id (jfunc);
968 else
969 idx = ipa_get_jf_ancestor_formal_id (jfunc);
971 if (info->ipcp_orig_node)
972 input = info->known_csts[idx];
973 else
975 ipcp_lattice<tree> *lat;
977 if (!info->lattices
978 || idx >= ipa_get_param_count (info))
979 return NULL_TREE;
980 lat = ipa_get_scalar_lat (info, idx);
981 if (!lat->is_single_const ())
982 return NULL_TREE;
983 input = lat->values->value;
986 if (!input)
987 return NULL_TREE;
989 if (jfunc->type == IPA_JF_PASS_THROUGH)
990 return ipa_get_jf_pass_through_result (jfunc, input);
991 else
992 return ipa_get_jf_ancestor_result (jfunc, input);
994 else
995 return NULL_TREE;
998 /* Determie whether JFUNC evaluates to single known polymorphic context, given
999 that INFO describes the caller node or the one it is inlined to, CS is the
1000 call graph edge corresponding to JFUNC and CSIDX index of the described
1001 parameter. */
1003 ipa_polymorphic_call_context
1004 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1005 ipa_jump_func *jfunc)
1007 ipa_edge_args *args = IPA_EDGE_REF (cs);
1008 ipa_polymorphic_call_context ctx;
1009 ipa_polymorphic_call_context *edge_ctx
1010 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1012 if (edge_ctx && !edge_ctx->useless_p ())
1013 ctx = *edge_ctx;
1015 if (jfunc->type == IPA_JF_PASS_THROUGH
1016 || jfunc->type == IPA_JF_ANCESTOR)
1018 ipa_polymorphic_call_context srcctx;
1019 int srcidx;
1020 bool type_preserved = true;
1021 if (jfunc->type == IPA_JF_PASS_THROUGH)
1023 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1024 return ctx;
1025 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1026 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1028 else
1030 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1031 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1033 if (info->ipcp_orig_node)
1035 if (info->known_contexts.exists ())
1036 srcctx = info->known_contexts[srcidx];
1038 else
1040 if (!info->lattices
1041 || srcidx >= ipa_get_param_count (info))
1042 return ctx;
1043 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1044 lat = ipa_get_poly_ctx_lat (info, srcidx);
1045 if (!lat->is_single_const ())
1046 return ctx;
1047 srcctx = lat->values->value;
1049 if (srcctx.useless_p ())
1050 return ctx;
1051 if (jfunc->type == IPA_JF_ANCESTOR)
1052 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1053 if (!type_preserved)
1054 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1055 srcctx.combine_with (ctx);
1056 return srcctx;
1059 return ctx;
1062 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1063 bottom, not containing a variable component and without any known value at
1064 the same time. */
1066 DEBUG_FUNCTION void
1067 ipcp_verify_propagated_values (void)
1069 struct cgraph_node *node;
1071 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1073 struct ipa_node_params *info = IPA_NODE_REF (node);
1074 int i, count = ipa_get_param_count (info);
1076 for (i = 0; i < count; i++)
1078 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1080 if (!lat->bottom
1081 && !lat->contains_variable
1082 && lat->values_count == 0)
1084 if (dump_file)
1086 symtab_node::dump_table (dump_file);
1087 fprintf (dump_file, "\nIPA lattices after constant "
1088 "propagation, before gcc_unreachable:\n");
1089 print_all_lattices (dump_file, true, false);
1092 gcc_unreachable ();
1098 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1100 static bool
1101 values_equal_for_ipcp_p (tree x, tree y)
1103 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1105 if (x == y)
1106 return true;
1108 if (TREE_CODE (x) == ADDR_EXPR
1109 && TREE_CODE (y) == ADDR_EXPR
1110 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1111 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1112 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1113 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1114 else
1115 return operand_equal_p (x, y, 0);
1118 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1120 static bool
1121 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1122 ipa_polymorphic_call_context y)
1124 return x.equal_to (y);
1128 /* Add a new value source to the value represented by THIS, marking that a
1129 value comes from edge CS and (if the underlying jump function is a
1130 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1131 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1132 scalar value of the parameter itself or the offset within an aggregate. */
1134 template <typename valtype>
1135 void
1136 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1137 int src_idx, HOST_WIDE_INT offset)
1139 ipcp_value_source<valtype> *src;
1141 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1142 src->offset = offset;
1143 src->cs = cs;
1144 src->val = src_val;
1145 src->index = src_idx;
1147 src->next = sources;
1148 sources = src;
1151 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1152 SOURCE and clear all other fields. */
1154 static ipcp_value<tree> *
1155 allocate_and_init_ipcp_value (tree source)
1157 ipcp_value<tree> *val;
1159 val = ipcp_cst_values_pool.allocate ();
1160 memset (val, 0, sizeof (*val));
1161 val->value = source;
1162 return val;
1165 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1166 value to SOURCE and clear all other fields. */
1168 static ipcp_value<ipa_polymorphic_call_context> *
1169 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1171 ipcp_value<ipa_polymorphic_call_context> *val;
1173 // TODO
1174 val = ipcp_poly_ctx_values_pool.allocate ();
1175 memset (val, 0, sizeof (*val));
1176 val->value = source;
1177 return val;
1180 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1181 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1182 meaning. OFFSET -1 means the source is scalar and not a part of an
1183 aggregate. */
1185 template <typename valtype>
1186 bool
1187 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1188 ipcp_value<valtype> *src_val,
1189 int src_idx, HOST_WIDE_INT offset)
1191 ipcp_value<valtype> *val;
1193 if (bottom)
1194 return false;
1196 for (val = values; val; val = val->next)
1197 if (values_equal_for_ipcp_p (val->value, newval))
1199 if (ipa_edge_within_scc (cs))
1201 ipcp_value_source<valtype> *s;
1202 for (s = val->sources; s ; s = s->next)
1203 if (s->cs == cs)
1204 break;
1205 if (s)
1206 return false;
1209 val->add_source (cs, src_val, src_idx, offset);
1210 return false;
1213 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1215 /* We can only free sources, not the values themselves, because sources
1216 of other values in this SCC might point to them. */
1217 for (val = values; val; val = val->next)
1219 while (val->sources)
1221 ipcp_value_source<valtype> *src = val->sources;
1222 val->sources = src->next;
1223 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1227 values = NULL;
1228 return set_to_bottom ();
1231 values_count++;
1232 val = allocate_and_init_ipcp_value (newval);
1233 val->add_source (cs, src_val, src_idx, offset);
1234 val->next = values;
1235 values = val;
1236 return true;
1239 /* Propagate values through a pass-through jump function JFUNC associated with
1240 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1241 is the index of the source parameter. */
1243 static bool
1244 propagate_vals_accross_pass_through (cgraph_edge *cs,
1245 ipa_jump_func *jfunc,
1246 ipcp_lattice<tree> *src_lat,
1247 ipcp_lattice<tree> *dest_lat,
1248 int src_idx)
1250 ipcp_value<tree> *src_val;
1251 bool ret = false;
1253 /* Do not create new values when propagating within an SCC because if there
1254 are arithmetic functions with circular dependencies, there is infinite
1255 number of them and we would just make lattices bottom. */
1256 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1257 && ipa_edge_within_scc (cs))
1258 ret = dest_lat->set_contains_variable ();
1259 else
1260 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1262 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1264 if (cstval)
1265 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1266 else
1267 ret |= dest_lat->set_contains_variable ();
1270 return ret;
1273 /* Propagate values through an ancestor jump function JFUNC associated with
1274 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1275 is the index of the source parameter. */
1277 static bool
1278 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1279 struct ipa_jump_func *jfunc,
1280 ipcp_lattice<tree> *src_lat,
1281 ipcp_lattice<tree> *dest_lat,
1282 int src_idx)
1284 ipcp_value<tree> *src_val;
1285 bool ret = false;
1287 if (ipa_edge_within_scc (cs))
1288 return dest_lat->set_contains_variable ();
1290 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1292 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1294 if (t)
1295 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1296 else
1297 ret |= dest_lat->set_contains_variable ();
1300 return ret;
1303 /* Propagate scalar values across jump function JFUNC that is associated with
1304 edge CS and put the values into DEST_LAT. */
1306 static bool
1307 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1308 struct ipa_jump_func *jfunc,
1309 ipcp_lattice<tree> *dest_lat)
1311 if (dest_lat->bottom)
1312 return false;
1314 if (jfunc->type == IPA_JF_CONST)
1316 tree val = ipa_get_jf_constant (jfunc);
1317 return dest_lat->add_value (val, cs, NULL, 0);
1319 else if (jfunc->type == IPA_JF_PASS_THROUGH
1320 || jfunc->type == IPA_JF_ANCESTOR)
1322 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1323 ipcp_lattice<tree> *src_lat;
1324 int src_idx;
1325 bool ret;
1327 if (jfunc->type == IPA_JF_PASS_THROUGH)
1328 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1329 else
1330 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1332 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1333 if (src_lat->bottom)
1334 return dest_lat->set_contains_variable ();
1336 /* If we would need to clone the caller and cannot, do not propagate. */
1337 if (!ipcp_versionable_function_p (cs->caller)
1338 && (src_lat->contains_variable
1339 || (src_lat->values_count > 1)))
1340 return dest_lat->set_contains_variable ();
1342 if (jfunc->type == IPA_JF_PASS_THROUGH)
1343 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1344 dest_lat, src_idx);
1345 else
1346 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1347 src_idx);
1349 if (src_lat->contains_variable)
1350 ret |= dest_lat->set_contains_variable ();
1352 return ret;
1355 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1356 use it for indirect inlining), we should propagate them too. */
1357 return dest_lat->set_contains_variable ();
1360 /* Propagate scalar values across jump function JFUNC that is associated with
1361 edge CS and describes argument IDX and put the values into DEST_LAT. */
1363 static bool
1364 propagate_context_accross_jump_function (cgraph_edge *cs,
1365 ipa_jump_func *jfunc, int idx,
1366 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1368 ipa_edge_args *args = IPA_EDGE_REF (cs);
1369 if (dest_lat->bottom)
1370 return false;
1371 bool ret = false;
1372 bool added_sth = false;
1373 bool type_preserved = true;
1375 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1376 = ipa_get_ith_polymorhic_call_context (args, idx);
1378 if (edge_ctx_ptr)
1379 edge_ctx = *edge_ctx_ptr;
1381 if (jfunc->type == IPA_JF_PASS_THROUGH
1382 || jfunc->type == IPA_JF_ANCESTOR)
1384 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1385 int src_idx;
1386 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1388 /* TODO: Once we figure out how to propagate speculations, it will
1389 probably be a good idea to switch to speculation if type_preserved is
1390 not set instead of punting. */
1391 if (jfunc->type == IPA_JF_PASS_THROUGH)
1393 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1394 goto prop_fail;
1395 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1396 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1398 else
1400 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1401 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1404 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1405 /* If we would need to clone the caller and cannot, do not propagate. */
1406 if (!ipcp_versionable_function_p (cs->caller)
1407 && (src_lat->contains_variable
1408 || (src_lat->values_count > 1)))
1409 goto prop_fail;
1411 ipcp_value<ipa_polymorphic_call_context> *src_val;
1412 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1414 ipa_polymorphic_call_context cur = src_val->value;
1416 if (!type_preserved)
1417 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1418 if (jfunc->type == IPA_JF_ANCESTOR)
1419 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1420 /* TODO: In cases we know how the context is going to be used,
1421 we can improve the result by passing proper OTR_TYPE. */
1422 cur.combine_with (edge_ctx);
1423 if (!cur.useless_p ())
1425 if (src_lat->contains_variable
1426 && !edge_ctx.equal_to (cur))
1427 ret |= dest_lat->set_contains_variable ();
1428 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1429 added_sth = true;
1435 prop_fail:
1436 if (!added_sth)
1438 if (!edge_ctx.useless_p ())
1439 ret |= dest_lat->add_value (edge_ctx, cs);
1440 else
1441 ret |= dest_lat->set_contains_variable ();
1444 return ret;
1447 /* Propagate alignments across jump function JFUNC that is associated with
1448 edge CS and update DEST_LAT accordingly. */
1450 static bool
1451 propagate_alignment_accross_jump_function (struct cgraph_edge *cs,
1452 struct ipa_jump_func *jfunc,
1453 struct ipcp_param_lattices *dest_lat)
1455 if (alignment_bottom_p (dest_lat))
1456 return false;
1458 ipa_alignment cur;
1459 cur.known = false;
1460 if (jfunc->alignment.known)
1461 cur = jfunc->alignment;
1462 else if (jfunc->type == IPA_JF_PASS_THROUGH
1463 || jfunc->type == IPA_JF_ANCESTOR)
1465 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1466 struct ipcp_param_lattices *src_lats;
1467 HOST_WIDE_INT offset = 0;
1468 int src_idx;
1470 if (jfunc->type == IPA_JF_PASS_THROUGH)
1472 enum tree_code op = ipa_get_jf_pass_through_operation (jfunc);
1473 if (op != NOP_EXPR)
1475 if (op != POINTER_PLUS_EXPR
1476 && op != PLUS_EXPR)
1477 goto prop_fail;
1478 tree operand = ipa_get_jf_pass_through_operand (jfunc);
1479 if (!tree_fits_shwi_p (operand))
1480 goto prop_fail;
1481 offset = tree_to_shwi (operand);
1483 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1485 else
1487 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1488 offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;;
1491 src_lats = ipa_get_parm_lattices (caller_info, src_idx);
1492 if (!src_lats->alignment.known
1493 || alignment_bottom_p (src_lats))
1494 goto prop_fail;
1496 cur = src_lats->alignment;
1497 cur.misalign = (cur.misalign + offset) % cur.align;
1500 if (cur.known)
1502 if (!dest_lat->alignment.known)
1504 dest_lat->alignment = cur;
1505 return true;
1507 else if (dest_lat->alignment.align == cur.align
1508 && dest_lat->alignment.misalign == cur.misalign)
1509 return false;
1512 prop_fail:
1513 set_alignment_to_bottom (dest_lat);
1514 return true;
1517 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1518 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1519 other cases, return false). If there are no aggregate items, set
1520 aggs_by_ref to NEW_AGGS_BY_REF. */
1522 static bool
1523 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1524 bool new_aggs_by_ref)
1526 if (dest_plats->aggs)
1528 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1530 set_agg_lats_to_bottom (dest_plats);
1531 return true;
1534 else
1535 dest_plats->aggs_by_ref = new_aggs_by_ref;
1536 return false;
1539 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1540 already existing lattice for the given OFFSET and SIZE, marking all skipped
1541 lattices as containing variable and checking for overlaps. If there is no
1542 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1543 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1544 unless there are too many already. If there are two many, return false. If
1545 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1546 skipped lattices were newly marked as containing variable, set *CHANGE to
1547 true. */
1549 static bool
1550 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1551 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1552 struct ipcp_agg_lattice ***aglat,
1553 bool pre_existing, bool *change)
1555 gcc_checking_assert (offset >= 0);
1557 while (**aglat && (**aglat)->offset < offset)
1559 if ((**aglat)->offset + (**aglat)->size > offset)
1561 set_agg_lats_to_bottom (dest_plats);
1562 return false;
1564 *change |= (**aglat)->set_contains_variable ();
1565 *aglat = &(**aglat)->next;
1568 if (**aglat && (**aglat)->offset == offset)
1570 if ((**aglat)->size != val_size
1571 || ((**aglat)->next
1572 && (**aglat)->next->offset < offset + val_size))
1574 set_agg_lats_to_bottom (dest_plats);
1575 return false;
1577 gcc_checking_assert (!(**aglat)->next
1578 || (**aglat)->next->offset >= offset + val_size);
1579 return true;
1581 else
1583 struct ipcp_agg_lattice *new_al;
1585 if (**aglat && (**aglat)->offset < offset + val_size)
1587 set_agg_lats_to_bottom (dest_plats);
1588 return false;
1590 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1591 return false;
1592 dest_plats->aggs_count++;
1593 new_al = ipcp_agg_lattice_pool.allocate ();
1594 memset (new_al, 0, sizeof (*new_al));
1596 new_al->offset = offset;
1597 new_al->size = val_size;
1598 new_al->contains_variable = pre_existing;
1600 new_al->next = **aglat;
1601 **aglat = new_al;
1602 return true;
1606 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1607 containing an unknown value. */
1609 static bool
1610 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1612 bool ret = false;
1613 while (aglat)
1615 ret |= aglat->set_contains_variable ();
1616 aglat = aglat->next;
1618 return ret;
1621 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1622 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1623 parameter used for lattice value sources. Return true if DEST_PLATS changed
1624 in any way. */
1626 static bool
1627 merge_aggregate_lattices (struct cgraph_edge *cs,
1628 struct ipcp_param_lattices *dest_plats,
1629 struct ipcp_param_lattices *src_plats,
1630 int src_idx, HOST_WIDE_INT offset_delta)
1632 bool pre_existing = dest_plats->aggs != NULL;
1633 struct ipcp_agg_lattice **dst_aglat;
1634 bool ret = false;
1636 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1637 return true;
1638 if (src_plats->aggs_bottom)
1639 return set_agg_lats_contain_variable (dest_plats);
1640 if (src_plats->aggs_contain_variable)
1641 ret |= set_agg_lats_contain_variable (dest_plats);
1642 dst_aglat = &dest_plats->aggs;
1644 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1645 src_aglat;
1646 src_aglat = src_aglat->next)
1648 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1650 if (new_offset < 0)
1651 continue;
1652 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1653 &dst_aglat, pre_existing, &ret))
1655 struct ipcp_agg_lattice *new_al = *dst_aglat;
1657 dst_aglat = &(*dst_aglat)->next;
1658 if (src_aglat->bottom)
1660 ret |= new_al->set_contains_variable ();
1661 continue;
1663 if (src_aglat->contains_variable)
1664 ret |= new_al->set_contains_variable ();
1665 for (ipcp_value<tree> *val = src_aglat->values;
1666 val;
1667 val = val->next)
1668 ret |= new_al->add_value (val->value, cs, val, src_idx,
1669 src_aglat->offset);
1671 else if (dest_plats->aggs_bottom)
1672 return true;
1674 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1675 return ret;
1678 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1679 pass-through JFUNC and if so, whether it has conform and conforms to the
1680 rules about propagating values passed by reference. */
1682 static bool
1683 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1684 struct ipa_jump_func *jfunc)
1686 return src_plats->aggs
1687 && (!src_plats->aggs_by_ref
1688 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1691 /* Propagate scalar values across jump function JFUNC that is associated with
1692 edge CS and put the values into DEST_LAT. */
1694 static bool
1695 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1696 struct ipa_jump_func *jfunc,
1697 struct ipcp_param_lattices *dest_plats)
1699 bool ret = false;
1701 if (dest_plats->aggs_bottom)
1702 return false;
1704 if (jfunc->type == IPA_JF_PASS_THROUGH
1705 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1707 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1708 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1709 struct ipcp_param_lattices *src_plats;
1711 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1712 if (agg_pass_through_permissible_p (src_plats, jfunc))
1714 /* Currently we do not produce clobber aggregate jump
1715 functions, replace with merging when we do. */
1716 gcc_assert (!jfunc->agg.items);
1717 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1718 src_idx, 0);
1720 else
1721 ret |= set_agg_lats_contain_variable (dest_plats);
1723 else if (jfunc->type == IPA_JF_ANCESTOR
1724 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1726 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1727 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1728 struct ipcp_param_lattices *src_plats;
1730 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1731 if (src_plats->aggs && src_plats->aggs_by_ref)
1733 /* Currently we do not produce clobber aggregate jump
1734 functions, replace with merging when we do. */
1735 gcc_assert (!jfunc->agg.items);
1736 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1737 ipa_get_jf_ancestor_offset (jfunc));
1739 else if (!src_plats->aggs_by_ref)
1740 ret |= set_agg_lats_to_bottom (dest_plats);
1741 else
1742 ret |= set_agg_lats_contain_variable (dest_plats);
1744 else if (jfunc->agg.items)
1746 bool pre_existing = dest_plats->aggs != NULL;
1747 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1748 struct ipa_agg_jf_item *item;
1749 int i;
1751 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1752 return true;
1754 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1756 HOST_WIDE_INT val_size;
1758 if (item->offset < 0)
1759 continue;
1760 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1761 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
1763 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1764 &aglat, pre_existing, &ret))
1766 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
1767 aglat = &(*aglat)->next;
1769 else if (dest_plats->aggs_bottom)
1770 return true;
1773 ret |= set_chain_of_aglats_contains_variable (*aglat);
1775 else
1776 ret |= set_agg_lats_contain_variable (dest_plats);
1778 return ret;
1781 /* Propagate constants from the caller to the callee of CS. INFO describes the
1782 caller. */
1784 static bool
1785 propagate_constants_accross_call (struct cgraph_edge *cs)
1787 struct ipa_node_params *callee_info;
1788 enum availability availability;
1789 struct cgraph_node *callee, *alias_or_thunk;
1790 struct ipa_edge_args *args;
1791 bool ret = false;
1792 int i, args_count, parms_count;
1794 callee = cs->callee->function_symbol (&availability);
1795 if (!callee->definition)
1796 return false;
1797 gcc_checking_assert (callee->has_gimple_body_p ());
1798 callee_info = IPA_NODE_REF (callee);
1800 args = IPA_EDGE_REF (cs);
1801 args_count = ipa_get_cs_argument_count (args);
1802 parms_count = ipa_get_param_count (callee_info);
1803 if (parms_count == 0)
1804 return false;
1806 /* No propagation through instrumentation thunks is available yet.
1807 It should be possible with proper mapping of call args and
1808 instrumented callee params in the propagation loop below. But
1809 this case mostly occurs when legacy code calls instrumented code
1810 and it is not a primary target for optimizations.
1811 We detect instrumentation thunks in aliases and thunks chain by
1812 checking instrumentation_clone flag for chain source and target.
1813 Going through instrumentation thunks we always have it changed
1814 from 0 to 1 and all other nodes do not change it. */
1815 if (!cs->callee->instrumentation_clone
1816 && callee->instrumentation_clone)
1818 for (i = 0; i < parms_count; i++)
1819 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1820 i));
1821 return ret;
1824 /* If this call goes through a thunk we must not propagate to the first (0th)
1825 parameter. However, we might need to uncover a thunk from below a series
1826 of aliases first. */
1827 alias_or_thunk = cs->callee;
1828 while (alias_or_thunk->alias)
1829 alias_or_thunk = alias_or_thunk->get_alias_target ();
1830 if (alias_or_thunk->thunk.thunk_p)
1832 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1833 0));
1834 i = 1;
1836 else
1837 i = 0;
1839 for (; (i < args_count) && (i < parms_count); i++)
1841 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1842 struct ipcp_param_lattices *dest_plats;
1844 dest_plats = ipa_get_parm_lattices (callee_info, i);
1845 if (availability == AVAIL_INTERPOSABLE)
1846 ret |= set_all_contains_variable (dest_plats);
1847 else
1849 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1850 &dest_plats->itself);
1851 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
1852 &dest_plats->ctxlat);
1853 ret |= propagate_alignment_accross_jump_function (cs, jump_func,
1854 dest_plats);
1855 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1856 dest_plats);
1859 for (; i < parms_count; i++)
1860 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1862 return ret;
1865 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1866 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1867 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
1869 static tree
1870 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
1871 vec<tree> known_csts,
1872 vec<ipa_polymorphic_call_context> known_contexts,
1873 vec<ipa_agg_jump_function_p> known_aggs,
1874 struct ipa_agg_replacement_value *agg_reps,
1875 bool *speculative)
1877 int param_index = ie->indirect_info->param_index;
1878 HOST_WIDE_INT anc_offset;
1879 tree t;
1880 tree target = NULL;
1882 *speculative = false;
1884 if (param_index == -1
1885 || known_csts.length () <= (unsigned int) param_index)
1886 return NULL_TREE;
1888 if (!ie->indirect_info->polymorphic)
1890 tree t;
1892 if (ie->indirect_info->agg_contents)
1894 if (agg_reps)
1896 t = NULL;
1897 while (agg_reps)
1899 if (agg_reps->index == param_index
1900 && agg_reps->offset == ie->indirect_info->offset
1901 && agg_reps->by_ref == ie->indirect_info->by_ref)
1903 t = agg_reps->value;
1904 break;
1906 agg_reps = agg_reps->next;
1909 else if (known_aggs.length () > (unsigned int) param_index)
1911 struct ipa_agg_jump_function *agg;
1912 agg = known_aggs[param_index];
1913 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1914 ie->indirect_info->by_ref);
1916 else
1917 t = NULL;
1919 else
1920 t = known_csts[param_index];
1922 if (t &&
1923 TREE_CODE (t) == ADDR_EXPR
1924 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1925 return TREE_OPERAND (t, 0);
1926 else
1927 return NULL_TREE;
1930 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
1931 return NULL_TREE;
1933 gcc_assert (!ie->indirect_info->agg_contents);
1934 anc_offset = ie->indirect_info->offset;
1936 t = NULL;
1938 /* Try to work out value of virtual table pointer value in replacemnets. */
1939 if (!t && agg_reps && !ie->indirect_info->by_ref)
1941 while (agg_reps)
1943 if (agg_reps->index == param_index
1944 && agg_reps->offset == ie->indirect_info->offset
1945 && agg_reps->by_ref)
1947 t = agg_reps->value;
1948 break;
1950 agg_reps = agg_reps->next;
1954 /* Try to work out value of virtual table pointer value in known
1955 aggregate values. */
1956 if (!t && known_aggs.length () > (unsigned int) param_index
1957 && !ie->indirect_info->by_ref)
1959 struct ipa_agg_jump_function *agg;
1960 agg = known_aggs[param_index];
1961 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1962 true);
1965 /* If we found the virtual table pointer, lookup the target. */
1966 if (t)
1968 tree vtable;
1969 unsigned HOST_WIDE_INT offset;
1970 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
1972 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
1973 vtable, offset);
1974 if (target)
1976 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1977 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1978 || !possible_polymorphic_call_target_p
1979 (ie, cgraph_node::get (target)))
1980 target = ipa_impossible_devirt_target (ie, target);
1981 *speculative = ie->indirect_info->vptr_changed;
1982 if (!*speculative)
1983 return target;
1988 /* Do we know the constant value of pointer? */
1989 if (!t)
1990 t = known_csts[param_index];
1992 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
1994 ipa_polymorphic_call_context context;
1995 if (known_contexts.length () > (unsigned int) param_index)
1997 context = known_contexts[param_index];
1998 context.offset_by (anc_offset);
1999 if (ie->indirect_info->vptr_changed)
2000 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2001 ie->indirect_info->otr_type);
2002 if (t)
2004 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2005 (t, ie->indirect_info->otr_type, anc_offset);
2006 if (!ctx2.useless_p ())
2007 context.combine_with (ctx2, ie->indirect_info->otr_type);
2010 else if (t)
2012 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2013 anc_offset);
2014 if (ie->indirect_info->vptr_changed)
2015 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2016 ie->indirect_info->otr_type);
2018 else
2019 return NULL_TREE;
2021 vec <cgraph_node *>targets;
2022 bool final;
2024 targets = possible_polymorphic_call_targets
2025 (ie->indirect_info->otr_type,
2026 ie->indirect_info->otr_token,
2027 context, &final);
2028 if (!final || targets.length () > 1)
2030 struct cgraph_node *node;
2031 if (*speculative)
2032 return target;
2033 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2034 || ie->speculative || !ie->maybe_hot_p ())
2035 return NULL;
2036 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2037 ie->indirect_info->otr_token,
2038 context);
2039 if (node)
2041 *speculative = true;
2042 target = node->decl;
2044 else
2045 return NULL;
2047 else
2049 *speculative = false;
2050 if (targets.length () == 1)
2051 target = targets[0]->decl;
2052 else
2053 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2056 if (target && !possible_polymorphic_call_target_p (ie,
2057 cgraph_node::get (target)))
2058 target = ipa_impossible_devirt_target (ie, target);
2060 return target;
2064 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2065 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2066 return the destination. */
2068 tree
2069 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2070 vec<tree> known_csts,
2071 vec<ipa_polymorphic_call_context> known_contexts,
2072 vec<ipa_agg_jump_function_p> known_aggs,
2073 bool *speculative)
2075 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2076 known_aggs, NULL, speculative);
2079 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2080 and KNOWN_CONTEXTS. */
2082 static int
2083 devirtualization_time_bonus (struct cgraph_node *node,
2084 vec<tree> known_csts,
2085 vec<ipa_polymorphic_call_context> known_contexts,
2086 vec<ipa_agg_jump_function_p> known_aggs)
2088 struct cgraph_edge *ie;
2089 int res = 0;
2091 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2093 struct cgraph_node *callee;
2094 struct inline_summary *isummary;
2095 enum availability avail;
2096 tree target;
2097 bool speculative;
2099 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2100 known_aggs, &speculative);
2101 if (!target)
2102 continue;
2104 /* Only bare minimum benefit for clearly un-inlineable targets. */
2105 res += 1;
2106 callee = cgraph_node::get (target);
2107 if (!callee || !callee->definition)
2108 continue;
2109 callee = callee->function_symbol (&avail);
2110 if (avail < AVAIL_AVAILABLE)
2111 continue;
2112 isummary = inline_summaries->get (callee);
2113 if (!isummary->inlinable)
2114 continue;
2116 /* FIXME: The values below need re-considering and perhaps also
2117 integrating into the cost metrics, at lest in some very basic way. */
2118 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2119 res += 31 / ((int)speculative + 1);
2120 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2121 res += 15 / ((int)speculative + 1);
2122 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2123 || DECL_DECLARED_INLINE_P (callee->decl))
2124 res += 7 / ((int)speculative + 1);
2127 return res;
2130 /* Return time bonus incurred because of HINTS. */
2132 static int
2133 hint_time_bonus (inline_hints hints)
2135 int result = 0;
2136 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2137 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2138 if (hints & INLINE_HINT_array_index)
2139 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2140 return result;
2143 /* If there is a reason to penalize the function described by INFO in the
2144 cloning goodness evaluation, do so. */
2146 static inline int64_t
2147 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2149 if (info->node_within_scc)
2150 evaluation = (evaluation
2151 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2153 if (info->node_calling_single_call)
2154 evaluation = (evaluation
2155 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2156 / 100;
2158 return evaluation;
2161 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2162 and SIZE_COST and with the sum of frequencies of incoming edges to the
2163 potential new clone in FREQUENCIES. */
2165 static bool
2166 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2167 int freq_sum, gcov_type count_sum, int size_cost)
2169 if (time_benefit == 0
2170 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2171 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
2172 return false;
2174 gcc_assert (size_cost > 0);
2176 struct ipa_node_params *info = IPA_NODE_REF (node);
2177 if (max_count)
2179 int factor = (count_sum * 1000) / max_count;
2180 int64_t evaluation = (((int64_t) time_benefit * factor)
2181 / size_cost);
2182 evaluation = incorporate_penalties (info, evaluation);
2184 if (dump_file && (dump_flags & TDF_DETAILS))
2185 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2186 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2187 "%s%s) -> evaluation: " "%" PRId64
2188 ", threshold: %i\n",
2189 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2190 info->node_within_scc ? ", scc" : "",
2191 info->node_calling_single_call ? ", single_call" : "",
2192 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2194 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2196 else
2198 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2199 / size_cost);
2200 evaluation = incorporate_penalties (info, evaluation);
2202 if (dump_file && (dump_flags & TDF_DETAILS))
2203 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2204 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2205 "%" PRId64 ", threshold: %i\n",
2206 time_benefit, size_cost, freq_sum,
2207 info->node_within_scc ? ", scc" : "",
2208 info->node_calling_single_call ? ", single_call" : "",
2209 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2211 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2215 /* Return all context independent values from aggregate lattices in PLATS in a
2216 vector. Return NULL if there are none. */
2218 static vec<ipa_agg_jf_item, va_gc> *
2219 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2221 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2223 if (plats->aggs_bottom
2224 || plats->aggs_contain_variable
2225 || plats->aggs_count == 0)
2226 return NULL;
2228 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2229 aglat;
2230 aglat = aglat->next)
2231 if (aglat->is_single_const ())
2233 struct ipa_agg_jf_item item;
2234 item.offset = aglat->offset;
2235 item.value = aglat->values->value;
2236 vec_safe_push (res, item);
2238 return res;
2241 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2242 populate them with values of parameters that are known independent of the
2243 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2244 non-NULL, the movement cost of all removable parameters will be stored in
2245 it. */
2247 static bool
2248 gather_context_independent_values (struct ipa_node_params *info,
2249 vec<tree> *known_csts,
2250 vec<ipa_polymorphic_call_context>
2251 *known_contexts,
2252 vec<ipa_agg_jump_function> *known_aggs,
2253 int *removable_params_cost)
2255 int i, count = ipa_get_param_count (info);
2256 bool ret = false;
2258 known_csts->create (0);
2259 known_contexts->create (0);
2260 known_csts->safe_grow_cleared (count);
2261 known_contexts->safe_grow_cleared (count);
2262 if (known_aggs)
2264 known_aggs->create (0);
2265 known_aggs->safe_grow_cleared (count);
2268 if (removable_params_cost)
2269 *removable_params_cost = 0;
2271 for (i = 0; i < count ; i++)
2273 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2274 ipcp_lattice<tree> *lat = &plats->itself;
2276 if (lat->is_single_const ())
2278 ipcp_value<tree> *val = lat->values;
2279 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2280 (*known_csts)[i] = val->value;
2281 if (removable_params_cost)
2282 *removable_params_cost
2283 += estimate_move_cost (TREE_TYPE (val->value), false);
2284 ret = true;
2286 else if (removable_params_cost
2287 && !ipa_is_param_used (info, i))
2288 *removable_params_cost
2289 += ipa_get_param_move_cost (info, i);
2291 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2292 if (ctxlat->is_single_const ())
2294 (*known_contexts)[i] = ctxlat->values->value;
2295 ret = true;
2298 if (known_aggs)
2300 vec<ipa_agg_jf_item, va_gc> *agg_items;
2301 struct ipa_agg_jump_function *ajf;
2303 agg_items = context_independent_aggregate_values (plats);
2304 ajf = &(*known_aggs)[i];
2305 ajf->items = agg_items;
2306 ajf->by_ref = plats->aggs_by_ref;
2307 ret |= agg_items != NULL;
2311 return ret;
2314 /* The current interface in ipa-inline-analysis requires a pointer vector.
2315 Create it.
2317 FIXME: That interface should be re-worked, this is slightly silly. Still,
2318 I'd like to discuss how to change it first and this demonstrates the
2319 issue. */
2321 static vec<ipa_agg_jump_function_p>
2322 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2324 vec<ipa_agg_jump_function_p> ret;
2325 struct ipa_agg_jump_function *ajf;
2326 int i;
2328 ret.create (known_aggs.length ());
2329 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2330 ret.quick_push (ajf);
2331 return ret;
2334 /* Perform time and size measurement of NODE with the context given in
2335 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2336 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2337 all context-independent removable parameters and EST_MOVE_COST of estimated
2338 movement of the considered parameter and store it into VAL. */
2340 static void
2341 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2342 vec<ipa_polymorphic_call_context> known_contexts,
2343 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2344 int base_time, int removable_params_cost,
2345 int est_move_cost, ipcp_value_base *val)
2347 int time, size, time_benefit;
2348 inline_hints hints;
2350 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2351 known_aggs_ptrs, &size, &time,
2352 &hints);
2353 time_benefit = base_time - time
2354 + devirtualization_time_bonus (node, known_csts, known_contexts,
2355 known_aggs_ptrs)
2356 + hint_time_bonus (hints)
2357 + removable_params_cost + est_move_cost;
2359 gcc_checking_assert (size >=0);
2360 /* The inliner-heuristics based estimates may think that in certain
2361 contexts some functions do not have any size at all but we want
2362 all specializations to have at least a tiny cost, not least not to
2363 divide by zero. */
2364 if (size == 0)
2365 size = 1;
2367 val->local_time_benefit = time_benefit;
2368 val->local_size_cost = size;
2371 /* Iterate over known values of parameters of NODE and estimate the local
2372 effects in terms of time and size they have. */
2374 static void
2375 estimate_local_effects (struct cgraph_node *node)
2377 struct ipa_node_params *info = IPA_NODE_REF (node);
2378 int i, count = ipa_get_param_count (info);
2379 vec<tree> known_csts;
2380 vec<ipa_polymorphic_call_context> known_contexts;
2381 vec<ipa_agg_jump_function> known_aggs;
2382 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2383 bool always_const;
2384 int base_time = inline_summaries->get (node)->time;
2385 int removable_params_cost;
2387 if (!count || !ipcp_versionable_function_p (node))
2388 return;
2390 if (dump_file && (dump_flags & TDF_DETAILS))
2391 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2392 node->name (), node->order, base_time);
2394 always_const = gather_context_independent_values (info, &known_csts,
2395 &known_contexts, &known_aggs,
2396 &removable_params_cost);
2397 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2398 if (always_const)
2400 struct caller_statistics stats;
2401 inline_hints hints;
2402 int time, size;
2404 init_caller_stats (&stats);
2405 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2406 false);
2407 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2408 known_aggs_ptrs, &size, &time, &hints);
2409 time -= devirtualization_time_bonus (node, known_csts, known_contexts,
2410 known_aggs_ptrs);
2411 time -= hint_time_bonus (hints);
2412 time -= removable_params_cost;
2413 size -= stats.n_calls * removable_params_cost;
2415 if (dump_file)
2416 fprintf (dump_file, " - context independent values, size: %i, "
2417 "time_benefit: %i\n", size, base_time - time);
2419 if (size <= 0
2420 || node->will_be_removed_from_program_if_no_direct_calls_p ())
2422 info->do_clone_for_all_contexts = true;
2423 base_time = time;
2425 if (dump_file)
2426 fprintf (dump_file, " Decided to specialize for all "
2427 "known contexts, code not going to grow.\n");
2429 else if (good_cloning_opportunity_p (node, base_time - time,
2430 stats.freq_sum, stats.count_sum,
2431 size))
2433 if (size + overall_size <= max_new_size)
2435 info->do_clone_for_all_contexts = true;
2436 base_time = time;
2437 overall_size += size;
2439 if (dump_file)
2440 fprintf (dump_file, " Decided to specialize for all "
2441 "known contexts, growth deemed beneficial.\n");
2443 else if (dump_file && (dump_flags & TDF_DETAILS))
2444 fprintf (dump_file, " Not cloning for all contexts because "
2445 "max_new_size would be reached with %li.\n",
2446 size + overall_size);
2450 for (i = 0; i < count ; i++)
2452 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2453 ipcp_lattice<tree> *lat = &plats->itself;
2454 ipcp_value<tree> *val;
2456 if (lat->bottom
2457 || !lat->values
2458 || known_csts[i])
2459 continue;
2461 for (val = lat->values; val; val = val->next)
2463 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2464 known_csts[i] = val->value;
2466 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2467 perform_estimation_of_a_value (node, known_csts, known_contexts,
2468 known_aggs_ptrs, base_time,
2469 removable_params_cost, emc, val);
2471 if (dump_file && (dump_flags & TDF_DETAILS))
2473 fprintf (dump_file, " - estimates for value ");
2474 print_ipcp_constant_value (dump_file, val->value);
2475 fprintf (dump_file, " for ");
2476 ipa_dump_param (dump_file, info, i);
2477 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2478 val->local_time_benefit, val->local_size_cost);
2481 known_csts[i] = NULL_TREE;
2484 for (i = 0; i < count; i++)
2486 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2488 if (!plats->virt_call)
2489 continue;
2491 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2492 ipcp_value<ipa_polymorphic_call_context> *val;
2494 if (ctxlat->bottom
2495 || !ctxlat->values
2496 || !known_contexts[i].useless_p ())
2497 continue;
2499 for (val = ctxlat->values; val; val = val->next)
2501 known_contexts[i] = val->value;
2502 perform_estimation_of_a_value (node, known_csts, known_contexts,
2503 known_aggs_ptrs, base_time,
2504 removable_params_cost, 0, val);
2506 if (dump_file && (dump_flags & TDF_DETAILS))
2508 fprintf (dump_file, " - estimates for polymorphic context ");
2509 print_ipcp_constant_value (dump_file, val->value);
2510 fprintf (dump_file, " for ");
2511 ipa_dump_param (dump_file, info, i);
2512 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2513 val->local_time_benefit, val->local_size_cost);
2516 known_contexts[i] = ipa_polymorphic_call_context ();
2519 for (i = 0; i < count ; i++)
2521 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2522 struct ipa_agg_jump_function *ajf;
2523 struct ipcp_agg_lattice *aglat;
2525 if (plats->aggs_bottom || !plats->aggs)
2526 continue;
2528 ajf = &known_aggs[i];
2529 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2531 ipcp_value<tree> *val;
2532 if (aglat->bottom || !aglat->values
2533 /* If the following is true, the one value is in known_aggs. */
2534 || (!plats->aggs_contain_variable
2535 && aglat->is_single_const ()))
2536 continue;
2538 for (val = aglat->values; val; val = val->next)
2540 struct ipa_agg_jf_item item;
2542 item.offset = aglat->offset;
2543 item.value = val->value;
2544 vec_safe_push (ajf->items, item);
2546 perform_estimation_of_a_value (node, known_csts, known_contexts,
2547 known_aggs_ptrs, base_time,
2548 removable_params_cost, 0, val);
2550 if (dump_file && (dump_flags & TDF_DETAILS))
2552 fprintf (dump_file, " - estimates for value ");
2553 print_ipcp_constant_value (dump_file, val->value);
2554 fprintf (dump_file, " for ");
2555 ipa_dump_param (dump_file, info, i);
2556 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2557 "]: time_benefit: %i, size: %i\n",
2558 plats->aggs_by_ref ? "ref " : "",
2559 aglat->offset,
2560 val->local_time_benefit, val->local_size_cost);
2563 ajf->items->pop ();
2568 for (i = 0; i < count ; i++)
2569 vec_free (known_aggs[i].items);
2571 known_csts.release ();
2572 known_contexts.release ();
2573 known_aggs.release ();
2574 known_aggs_ptrs.release ();
2578 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2579 topological sort of values. */
2581 template <typename valtype>
2582 void
2583 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
2585 ipcp_value_source<valtype> *src;
2587 if (cur_val->dfs)
2588 return;
2590 dfs_counter++;
2591 cur_val->dfs = dfs_counter;
2592 cur_val->low_link = dfs_counter;
2594 cur_val->topo_next = stack;
2595 stack = cur_val;
2596 cur_val->on_stack = true;
2598 for (src = cur_val->sources; src; src = src->next)
2599 if (src->val)
2601 if (src->val->dfs == 0)
2603 add_val (src->val);
2604 if (src->val->low_link < cur_val->low_link)
2605 cur_val->low_link = src->val->low_link;
2607 else if (src->val->on_stack
2608 && src->val->dfs < cur_val->low_link)
2609 cur_val->low_link = src->val->dfs;
2612 if (cur_val->dfs == cur_val->low_link)
2614 ipcp_value<valtype> *v, *scc_list = NULL;
2618 v = stack;
2619 stack = v->topo_next;
2620 v->on_stack = false;
2622 v->scc_next = scc_list;
2623 scc_list = v;
2625 while (v != cur_val);
2627 cur_val->topo_next = values_topo;
2628 values_topo = cur_val;
2632 /* Add all values in lattices associated with NODE to the topological sort if
2633 they are not there yet. */
2635 static void
2636 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
2638 struct ipa_node_params *info = IPA_NODE_REF (node);
2639 int i, count = ipa_get_param_count (info);
2641 for (i = 0; i < count ; i++)
2643 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2644 ipcp_lattice<tree> *lat = &plats->itself;
2645 struct ipcp_agg_lattice *aglat;
2647 if (!lat->bottom)
2649 ipcp_value<tree> *val;
2650 for (val = lat->values; val; val = val->next)
2651 topo->constants.add_val (val);
2654 if (!plats->aggs_bottom)
2655 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2656 if (!aglat->bottom)
2658 ipcp_value<tree> *val;
2659 for (val = aglat->values; val; val = val->next)
2660 topo->constants.add_val (val);
2663 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2664 if (!ctxlat->bottom)
2666 ipcp_value<ipa_polymorphic_call_context> *ctxval;
2667 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
2668 topo->contexts.add_val (ctxval);
2673 /* One pass of constants propagation along the call graph edges, from callers
2674 to callees (requires topological ordering in TOPO), iterate over strongly
2675 connected components. */
2677 static void
2678 propagate_constants_topo (struct ipa_topo_info *topo)
2680 int i;
2682 for (i = topo->nnodes - 1; i >= 0; i--)
2684 unsigned j;
2685 struct cgraph_node *v, *node = topo->order[i];
2686 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
2688 /* First, iteratively propagate within the strongly connected component
2689 until all lattices stabilize. */
2690 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2691 if (v->has_gimple_body_p ())
2692 push_node_to_stack (topo, v);
2694 v = pop_node_from_stack (topo);
2695 while (v)
2697 struct cgraph_edge *cs;
2699 for (cs = v->callees; cs; cs = cs->next_callee)
2700 if (ipa_edge_within_scc (cs))
2702 IPA_NODE_REF (v)->node_within_scc = true;
2703 if (propagate_constants_accross_call (cs))
2704 push_node_to_stack (topo, cs->callee->function_symbol ());
2706 v = pop_node_from_stack (topo);
2709 /* Afterwards, propagate along edges leading out of the SCC, calculates
2710 the local effects of the discovered constants and all valid values to
2711 their topological sort. */
2712 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2713 if (v->has_gimple_body_p ())
2715 struct cgraph_edge *cs;
2717 estimate_local_effects (v);
2718 add_all_node_vals_to_toposort (v, topo);
2719 for (cs = v->callees; cs; cs = cs->next_callee)
2720 if (!ipa_edge_within_scc (cs))
2721 propagate_constants_accross_call (cs);
2723 cycle_nodes.release ();
2728 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2729 the bigger one if otherwise. */
2731 static int
2732 safe_add (int a, int b)
2734 if (a > INT_MAX/2 || b > INT_MAX/2)
2735 return a > b ? a : b;
2736 else
2737 return a + b;
2741 /* Propagate the estimated effects of individual values along the topological
2742 from the dependent values to those they depend on. */
2744 template <typename valtype>
2745 void
2746 value_topo_info<valtype>::propagate_effects ()
2748 ipcp_value<valtype> *base;
2750 for (base = values_topo; base; base = base->topo_next)
2752 ipcp_value_source<valtype> *src;
2753 ipcp_value<valtype> *val;
2754 int time = 0, size = 0;
2756 for (val = base; val; val = val->scc_next)
2758 time = safe_add (time,
2759 val->local_time_benefit + val->prop_time_benefit);
2760 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2763 for (val = base; val; val = val->scc_next)
2764 for (src = val->sources; src; src = src->next)
2765 if (src->val
2766 && src->cs->maybe_hot_p ())
2768 src->val->prop_time_benefit = safe_add (time,
2769 src->val->prop_time_benefit);
2770 src->val->prop_size_cost = safe_add (size,
2771 src->val->prop_size_cost);
2777 /* Propagate constants, polymorphic contexts and their effects from the
2778 summaries interprocedurally. */
2780 static void
2781 ipcp_propagate_stage (struct ipa_topo_info *topo)
2783 struct cgraph_node *node;
2785 if (dump_file)
2786 fprintf (dump_file, "\n Propagating constants:\n\n");
2788 if (in_lto_p)
2789 ipa_update_after_lto_read ();
2792 FOR_EACH_DEFINED_FUNCTION (node)
2794 struct ipa_node_params *info = IPA_NODE_REF (node);
2796 determine_versionability (node);
2797 if (node->has_gimple_body_p ())
2799 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2800 ipa_get_param_count (info));
2801 initialize_node_lattices (node);
2803 if (node->definition && !node->alias)
2804 overall_size += inline_summaries->get (node)->self_size;
2805 if (node->count > max_count)
2806 max_count = node->count;
2809 max_new_size = overall_size;
2810 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2811 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2812 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2814 if (dump_file)
2815 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2816 overall_size, max_new_size);
2818 propagate_constants_topo (topo);
2819 #ifdef ENABLE_CHECKING
2820 ipcp_verify_propagated_values ();
2821 #endif
2822 topo->constants.propagate_effects ();
2823 topo->contexts.propagate_effects ();
2825 if (dump_file)
2827 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2828 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2832 /* Discover newly direct outgoing edges from NODE which is a new clone with
2833 known KNOWN_CSTS and make them direct. */
2835 static void
2836 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2837 vec<tree> known_csts,
2838 vec<ipa_polymorphic_call_context>
2839 known_contexts,
2840 struct ipa_agg_replacement_value *aggvals)
2842 struct cgraph_edge *ie, *next_ie;
2843 bool found = false;
2845 for (ie = node->indirect_calls; ie; ie = next_ie)
2847 tree target;
2848 bool speculative;
2850 next_ie = ie->next_callee;
2851 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2852 vNULL, aggvals, &speculative);
2853 if (target)
2855 bool agg_contents = ie->indirect_info->agg_contents;
2856 bool polymorphic = ie->indirect_info->polymorphic;
2857 int param_index = ie->indirect_info->param_index;
2858 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
2859 speculative);
2860 found = true;
2862 if (cs && !agg_contents && !polymorphic)
2864 struct ipa_node_params *info = IPA_NODE_REF (node);
2865 int c = ipa_get_controlled_uses (info, param_index);
2866 if (c != IPA_UNDESCRIBED_USE)
2868 struct ipa_ref *to_del;
2870 c--;
2871 ipa_set_controlled_uses (info, param_index, c);
2872 if (dump_file && (dump_flags & TDF_DETAILS))
2873 fprintf (dump_file, " controlled uses count of param "
2874 "%i bumped down to %i\n", param_index, c);
2875 if (c == 0
2876 && (to_del = node->find_reference (cs->callee, NULL, 0)))
2878 if (dump_file && (dump_flags & TDF_DETAILS))
2879 fprintf (dump_file, " and even removing its "
2880 "cloning-created reference\n");
2881 to_del->remove_reference ();
2887 /* Turning calls to direct calls will improve overall summary. */
2888 if (found)
2889 inline_update_overall_summary (node);
2892 /* Vector of pointers which for linked lists of clones of an original crgaph
2893 edge. */
2895 static vec<cgraph_edge *> next_edge_clone;
2896 static vec<cgraph_edge *> prev_edge_clone;
2898 static inline void
2899 grow_edge_clone_vectors (void)
2901 if (next_edge_clone.length ()
2902 <= (unsigned) symtab->edges_max_uid)
2903 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2904 if (prev_edge_clone.length ()
2905 <= (unsigned) symtab->edges_max_uid)
2906 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2909 /* Edge duplication hook to grow the appropriate linked list in
2910 next_edge_clone. */
2912 static void
2913 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2914 void *)
2916 grow_edge_clone_vectors ();
2918 struct cgraph_edge *old_next = next_edge_clone[src->uid];
2919 if (old_next)
2920 prev_edge_clone[old_next->uid] = dst;
2921 prev_edge_clone[dst->uid] = src;
2923 next_edge_clone[dst->uid] = old_next;
2924 next_edge_clone[src->uid] = dst;
2927 /* Hook that is called by cgraph.c when an edge is removed. */
2929 static void
2930 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
2932 grow_edge_clone_vectors ();
2934 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
2935 struct cgraph_edge *next = next_edge_clone[cs->uid];
2936 if (prev)
2937 next_edge_clone[prev->uid] = next;
2938 if (next)
2939 prev_edge_clone[next->uid] = prev;
2942 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2943 parameter with the given INDEX. */
2945 static tree
2946 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2947 int index)
2949 struct ipa_agg_replacement_value *aggval;
2951 aggval = ipa_get_agg_replacements_for_node (node);
2952 while (aggval)
2954 if (aggval->offset == offset
2955 && aggval->index == index)
2956 return aggval->value;
2957 aggval = aggval->next;
2959 return NULL_TREE;
2962 /* Return true is NODE is DEST or its clone for all contexts. */
2964 static bool
2965 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
2967 if (node == dest)
2968 return true;
2970 struct ipa_node_params *info = IPA_NODE_REF (node);
2971 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
2974 /* Return true if edge CS does bring about the value described by SRC to node
2975 DEST or its clone for all contexts. */
2977 static bool
2978 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
2979 cgraph_node *dest)
2981 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2982 enum availability availability;
2983 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
2985 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
2986 || availability <= AVAIL_INTERPOSABLE
2987 || caller_info->node_dead)
2988 return false;
2989 if (!src->val)
2990 return true;
2992 if (caller_info->ipcp_orig_node)
2994 tree t;
2995 if (src->offset == -1)
2996 t = caller_info->known_csts[src->index];
2997 else
2998 t = get_clone_agg_value (cs->caller, src->offset, src->index);
2999 return (t != NULL_TREE
3000 && values_equal_for_ipcp_p (src->val->value, t));
3002 else
3004 struct ipcp_agg_lattice *aglat;
3005 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3006 src->index);
3007 if (src->offset == -1)
3008 return (plats->itself.is_single_const ()
3009 && values_equal_for_ipcp_p (src->val->value,
3010 plats->itself.values->value));
3011 else
3013 if (plats->aggs_bottom || plats->aggs_contain_variable)
3014 return false;
3015 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3016 if (aglat->offset == src->offset)
3017 return (aglat->is_single_const ()
3018 && values_equal_for_ipcp_p (src->val->value,
3019 aglat->values->value));
3021 return false;
3025 /* Return true if edge CS does bring about the value described by SRC to node
3026 DEST or its clone for all contexts. */
3028 static bool
3029 cgraph_edge_brings_value_p (cgraph_edge *cs,
3030 ipcp_value_source<ipa_polymorphic_call_context> *src,
3031 cgraph_node *dest)
3033 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3034 cgraph_node *real_dest = cs->callee->function_symbol ();
3036 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3037 || caller_info->node_dead)
3038 return false;
3039 if (!src->val)
3040 return true;
3042 if (caller_info->ipcp_orig_node)
3043 return (caller_info->known_contexts.length () > (unsigned) src->index)
3044 && values_equal_for_ipcp_p (src->val->value,
3045 caller_info->known_contexts[src->index]);
3047 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3048 src->index);
3049 return plats->ctxlat.is_single_const ()
3050 && values_equal_for_ipcp_p (src->val->value,
3051 plats->ctxlat.values->value);
3054 /* Get the next clone in the linked list of clones of an edge. */
3056 static inline struct cgraph_edge *
3057 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3059 return next_edge_clone[cs->uid];
3062 /* Given VAL that is intended for DEST, iterate over all its sources and if
3063 they still hold, add their edge frequency and their number into *FREQUENCY
3064 and *CALLER_COUNT respectively. */
3066 template <typename valtype>
3067 static bool
3068 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3069 int *freq_sum,
3070 gcov_type *count_sum, int *caller_count)
3072 ipcp_value_source<valtype> *src;
3073 int freq = 0, count = 0;
3074 gcov_type cnt = 0;
3075 bool hot = false;
3077 for (src = val->sources; src; src = src->next)
3079 struct cgraph_edge *cs = src->cs;
3080 while (cs)
3082 if (cgraph_edge_brings_value_p (cs, src, dest))
3084 count++;
3085 freq += cs->frequency;
3086 cnt += cs->count;
3087 hot |= cs->maybe_hot_p ();
3089 cs = get_next_cgraph_edge_clone (cs);
3093 *freq_sum = freq;
3094 *count_sum = cnt;
3095 *caller_count = count;
3096 return hot;
3099 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3100 is assumed their number is known and equal to CALLER_COUNT. */
3102 template <typename valtype>
3103 static vec<cgraph_edge *>
3104 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3105 int caller_count)
3107 ipcp_value_source<valtype> *src;
3108 vec<cgraph_edge *> ret;
3110 ret.create (caller_count);
3111 for (src = val->sources; src; src = src->next)
3113 struct cgraph_edge *cs = src->cs;
3114 while (cs)
3116 if (cgraph_edge_brings_value_p (cs, src, dest))
3117 ret.quick_push (cs);
3118 cs = get_next_cgraph_edge_clone (cs);
3122 return ret;
3125 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3126 Return it or NULL if for some reason it cannot be created. */
3128 static struct ipa_replace_map *
3129 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3131 struct ipa_replace_map *replace_map;
3134 replace_map = ggc_alloc<ipa_replace_map> ();
3135 if (dump_file)
3137 fprintf (dump_file, " replacing ");
3138 ipa_dump_param (dump_file, info, parm_num);
3140 fprintf (dump_file, " with const ");
3141 print_generic_expr (dump_file, value, 0);
3142 fprintf (dump_file, "\n");
3144 replace_map->old_tree = NULL;
3145 replace_map->parm_num = parm_num;
3146 replace_map->new_tree = value;
3147 replace_map->replace_p = true;
3148 replace_map->ref_p = false;
3150 return replace_map;
3153 /* Dump new profiling counts */
3155 static void
3156 dump_profile_updates (struct cgraph_node *orig_node,
3157 struct cgraph_node *new_node)
3159 struct cgraph_edge *cs;
3161 fprintf (dump_file, " setting count of the specialized node to "
3162 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3163 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3164 fprintf (dump_file, " edge to %s has count "
3165 HOST_WIDE_INT_PRINT_DEC "\n",
3166 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3168 fprintf (dump_file, " setting count of the original node to "
3169 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3170 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3171 fprintf (dump_file, " edge to %s is left with "
3172 HOST_WIDE_INT_PRINT_DEC "\n",
3173 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3176 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3177 their profile information to reflect this. */
3179 static void
3180 update_profiling_info (struct cgraph_node *orig_node,
3181 struct cgraph_node *new_node)
3183 struct cgraph_edge *cs;
3184 struct caller_statistics stats;
3185 gcov_type new_sum, orig_sum;
3186 gcov_type remainder, orig_node_count = orig_node->count;
3188 if (orig_node_count == 0)
3189 return;
3191 init_caller_stats (&stats);
3192 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3193 false);
3194 orig_sum = stats.count_sum;
3195 init_caller_stats (&stats);
3196 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3197 false);
3198 new_sum = stats.count_sum;
3200 if (orig_node_count < orig_sum + new_sum)
3202 if (dump_file)
3203 fprintf (dump_file, " Problem: node %s/%i has too low count "
3204 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3205 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3206 orig_node->name (), orig_node->order,
3207 (HOST_WIDE_INT) orig_node_count,
3208 (HOST_WIDE_INT) (orig_sum + new_sum));
3210 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3211 if (dump_file)
3212 fprintf (dump_file, " proceeding by pretending it was "
3213 HOST_WIDE_INT_PRINT_DEC "\n",
3214 (HOST_WIDE_INT) orig_node_count);
3217 new_node->count = new_sum;
3218 remainder = orig_node_count - new_sum;
3219 orig_node->count = remainder;
3221 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3222 if (cs->frequency)
3223 cs->count = apply_probability (cs->count,
3224 GCOV_COMPUTE_SCALE (new_sum,
3225 orig_node_count));
3226 else
3227 cs->count = 0;
3229 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3230 cs->count = apply_probability (cs->count,
3231 GCOV_COMPUTE_SCALE (remainder,
3232 orig_node_count));
3234 if (dump_file)
3235 dump_profile_updates (orig_node, new_node);
3238 /* Update the respective profile of specialized NEW_NODE and the original
3239 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3240 have been redirected to the specialized version. */
3242 static void
3243 update_specialized_profile (struct cgraph_node *new_node,
3244 struct cgraph_node *orig_node,
3245 gcov_type redirected_sum)
3247 struct cgraph_edge *cs;
3248 gcov_type new_node_count, orig_node_count = orig_node->count;
3250 if (dump_file)
3251 fprintf (dump_file, " the sum of counts of redirected edges is "
3252 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3253 if (orig_node_count == 0)
3254 return;
3256 gcc_assert (orig_node_count >= redirected_sum);
3258 new_node_count = new_node->count;
3259 new_node->count += redirected_sum;
3260 orig_node->count -= redirected_sum;
3262 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3263 if (cs->frequency)
3264 cs->count += apply_probability (cs->count,
3265 GCOV_COMPUTE_SCALE (redirected_sum,
3266 new_node_count));
3267 else
3268 cs->count = 0;
3270 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3272 gcov_type dec = apply_probability (cs->count,
3273 GCOV_COMPUTE_SCALE (redirected_sum,
3274 orig_node_count));
3275 if (dec < cs->count)
3276 cs->count -= dec;
3277 else
3278 cs->count = 0;
3281 if (dump_file)
3282 dump_profile_updates (orig_node, new_node);
3285 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3286 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3287 redirect all edges in CALLERS to it. */
3289 static struct cgraph_node *
3290 create_specialized_node (struct cgraph_node *node,
3291 vec<tree> known_csts,
3292 vec<ipa_polymorphic_call_context> known_contexts,
3293 struct ipa_agg_replacement_value *aggvals,
3294 vec<cgraph_edge *> callers)
3296 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3297 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3298 struct ipa_agg_replacement_value *av;
3299 struct cgraph_node *new_node;
3300 int i, count = ipa_get_param_count (info);
3301 bitmap args_to_skip;
3303 gcc_assert (!info->ipcp_orig_node);
3305 if (node->local.can_change_signature)
3307 args_to_skip = BITMAP_GGC_ALLOC ();
3308 for (i = 0; i < count; i++)
3310 tree t = known_csts[i];
3312 if (t || !ipa_is_param_used (info, i))
3313 bitmap_set_bit (args_to_skip, i);
3316 else
3318 args_to_skip = NULL;
3319 if (dump_file && (dump_flags & TDF_DETAILS))
3320 fprintf (dump_file, " cannot change function signature\n");
3323 for (i = 0; i < count ; i++)
3325 tree t = known_csts[i];
3326 if (t)
3328 struct ipa_replace_map *replace_map;
3330 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3331 replace_map = get_replacement_map (info, t, i);
3332 if (replace_map)
3333 vec_safe_push (replace_trees, replace_map);
3337 new_node = node->create_virtual_clone (callers, replace_trees,
3338 args_to_skip, "constprop");
3339 ipa_set_node_agg_value_chain (new_node, aggvals);
3340 for (av = aggvals; av; av = av->next)
3341 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3343 if (dump_file && (dump_flags & TDF_DETAILS))
3345 fprintf (dump_file, " the new node is %s/%i.\n",
3346 new_node->name (), new_node->order);
3347 if (known_contexts.exists ())
3349 for (i = 0; i < count ; i++)
3350 if (!known_contexts[i].useless_p ())
3352 fprintf (dump_file, " known ctx %i is ", i);
3353 known_contexts[i].dump (dump_file);
3356 if (aggvals)
3357 ipa_dump_agg_replacement_values (dump_file, aggvals);
3359 ipa_check_create_node_params ();
3360 update_profiling_info (node, new_node);
3361 new_info = IPA_NODE_REF (new_node);
3362 new_info->ipcp_orig_node = node;
3363 new_info->known_csts = known_csts;
3364 new_info->known_contexts = known_contexts;
3366 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3368 callers.release ();
3369 return new_node;
3372 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3373 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3375 static void
3376 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3377 vec<tree> known_csts,
3378 vec<cgraph_edge *> callers)
3380 struct ipa_node_params *info = IPA_NODE_REF (node);
3381 int i, count = ipa_get_param_count (info);
3383 for (i = 0; i < count ; i++)
3385 struct cgraph_edge *cs;
3386 tree newval = NULL_TREE;
3387 int j;
3388 bool first = true;
3390 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3391 continue;
3393 FOR_EACH_VEC_ELT (callers, j, cs)
3395 struct ipa_jump_func *jump_func;
3396 tree t;
3398 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3400 newval = NULL_TREE;
3401 break;
3403 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3404 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3405 if (!t
3406 || (newval
3407 && !values_equal_for_ipcp_p (t, newval))
3408 || (!first && !newval))
3410 newval = NULL_TREE;
3411 break;
3413 else
3414 newval = t;
3415 first = false;
3418 if (newval)
3420 if (dump_file && (dump_flags & TDF_DETAILS))
3422 fprintf (dump_file, " adding an extra known scalar value ");
3423 print_ipcp_constant_value (dump_file, newval);
3424 fprintf (dump_file, " for ");
3425 ipa_dump_param (dump_file, info, i);
3426 fprintf (dump_file, "\n");
3429 known_csts[i] = newval;
3434 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3435 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3436 CALLERS. */
3438 static void
3439 find_more_contexts_for_caller_subset (cgraph_node *node,
3440 vec<ipa_polymorphic_call_context>
3441 *known_contexts,
3442 vec<cgraph_edge *> callers)
3444 ipa_node_params *info = IPA_NODE_REF (node);
3445 int i, count = ipa_get_param_count (info);
3447 for (i = 0; i < count ; i++)
3449 cgraph_edge *cs;
3451 if (ipa_get_poly_ctx_lat (info, i)->bottom
3452 || (known_contexts->exists ()
3453 && !(*known_contexts)[i].useless_p ()))
3454 continue;
3456 ipa_polymorphic_call_context newval;
3457 bool first = true;
3458 int j;
3460 FOR_EACH_VEC_ELT (callers, j, cs)
3462 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3463 return;
3464 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3466 ipa_polymorphic_call_context ctx;
3467 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3468 jfunc);
3469 if (first)
3471 newval = ctx;
3472 first = false;
3474 else
3475 newval.meet_with (ctx);
3476 if (newval.useless_p ())
3477 break;
3480 if (!newval.useless_p ())
3482 if (dump_file && (dump_flags & TDF_DETAILS))
3484 fprintf (dump_file, " adding an extra known polymorphic "
3485 "context ");
3486 print_ipcp_constant_value (dump_file, newval);
3487 fprintf (dump_file, " for ");
3488 ipa_dump_param (dump_file, info, i);
3489 fprintf (dump_file, "\n");
3492 if (!known_contexts->exists ())
3493 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3494 (*known_contexts)[i] = newval;
3500 /* Go through PLATS and create a vector of values consisting of values and
3501 offsets (minus OFFSET) of lattices that contain only a single value. */
3503 static vec<ipa_agg_jf_item>
3504 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3506 vec<ipa_agg_jf_item> res = vNULL;
3508 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3509 return vNULL;
3511 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3512 if (aglat->is_single_const ())
3514 struct ipa_agg_jf_item ti;
3515 ti.offset = aglat->offset - offset;
3516 ti.value = aglat->values->value;
3517 res.safe_push (ti);
3519 return res;
3522 /* Intersect all values in INTER with single value lattices in PLATS (while
3523 subtracting OFFSET). */
3525 static void
3526 intersect_with_plats (struct ipcp_param_lattices *plats,
3527 vec<ipa_agg_jf_item> *inter,
3528 HOST_WIDE_INT offset)
3530 struct ipcp_agg_lattice *aglat;
3531 struct ipa_agg_jf_item *item;
3532 int k;
3534 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3536 inter->release ();
3537 return;
3540 aglat = plats->aggs;
3541 FOR_EACH_VEC_ELT (*inter, k, item)
3543 bool found = false;
3544 if (!item->value)
3545 continue;
3546 while (aglat)
3548 if (aglat->offset - offset > item->offset)
3549 break;
3550 if (aglat->offset - offset == item->offset)
3552 gcc_checking_assert (item->value);
3553 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
3554 found = true;
3555 break;
3557 aglat = aglat->next;
3559 if (!found)
3560 item->value = NULL_TREE;
3564 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3565 vector result while subtracting OFFSET from the individual value offsets. */
3567 static vec<ipa_agg_jf_item>
3568 agg_replacements_to_vector (struct cgraph_node *node, int index,
3569 HOST_WIDE_INT offset)
3571 struct ipa_agg_replacement_value *av;
3572 vec<ipa_agg_jf_item> res = vNULL;
3574 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
3575 if (av->index == index
3576 && (av->offset - offset) >= 0)
3578 struct ipa_agg_jf_item item;
3579 gcc_checking_assert (av->value);
3580 item.offset = av->offset - offset;
3581 item.value = av->value;
3582 res.safe_push (item);
3585 return res;
3588 /* Intersect all values in INTER with those that we have already scheduled to
3589 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3590 (while subtracting OFFSET). */
3592 static void
3593 intersect_with_agg_replacements (struct cgraph_node *node, int index,
3594 vec<ipa_agg_jf_item> *inter,
3595 HOST_WIDE_INT offset)
3597 struct ipa_agg_replacement_value *srcvals;
3598 struct ipa_agg_jf_item *item;
3599 int i;
3601 srcvals = ipa_get_agg_replacements_for_node (node);
3602 if (!srcvals)
3604 inter->release ();
3605 return;
3608 FOR_EACH_VEC_ELT (*inter, i, item)
3610 struct ipa_agg_replacement_value *av;
3611 bool found = false;
3612 if (!item->value)
3613 continue;
3614 for (av = srcvals; av; av = av->next)
3616 gcc_checking_assert (av->value);
3617 if (av->index == index
3618 && av->offset - offset == item->offset)
3620 if (values_equal_for_ipcp_p (item->value, av->value))
3621 found = true;
3622 break;
3625 if (!found)
3626 item->value = NULL_TREE;
3630 /* Intersect values in INTER with aggregate values that come along edge CS to
3631 parameter number INDEX and return it. If INTER does not actually exist yet,
3632 copy all incoming values to it. If we determine we ended up with no values
3633 whatsoever, return a released vector. */
3635 static vec<ipa_agg_jf_item>
3636 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
3637 vec<ipa_agg_jf_item> inter)
3639 struct ipa_jump_func *jfunc;
3640 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3641 if (jfunc->type == IPA_JF_PASS_THROUGH
3642 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3644 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3645 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3647 if (caller_info->ipcp_orig_node)
3649 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3650 struct ipcp_param_lattices *orig_plats;
3651 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3652 src_idx);
3653 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3655 if (!inter.exists ())
3656 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
3657 else
3658 intersect_with_agg_replacements (cs->caller, src_idx,
3659 &inter, 0);
3661 else
3663 inter.release ();
3664 return vNULL;
3667 else
3669 struct ipcp_param_lattices *src_plats;
3670 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3671 if (agg_pass_through_permissible_p (src_plats, jfunc))
3673 /* Currently we do not produce clobber aggregate jump
3674 functions, adjust when we do. */
3675 gcc_checking_assert (!jfunc->agg.items);
3676 if (!inter.exists ())
3677 inter = copy_plats_to_inter (src_plats, 0);
3678 else
3679 intersect_with_plats (src_plats, &inter, 0);
3681 else
3683 inter.release ();
3684 return vNULL;
3688 else if (jfunc->type == IPA_JF_ANCESTOR
3689 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3691 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3692 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3693 struct ipcp_param_lattices *src_plats;
3694 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3696 if (caller_info->ipcp_orig_node)
3698 if (!inter.exists ())
3699 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
3700 else
3701 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
3702 delta);
3704 else
3706 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3707 /* Currently we do not produce clobber aggregate jump
3708 functions, adjust when we do. */
3709 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3710 if (!inter.exists ())
3711 inter = copy_plats_to_inter (src_plats, delta);
3712 else
3713 intersect_with_plats (src_plats, &inter, delta);
3716 else if (jfunc->agg.items)
3718 struct ipa_agg_jf_item *item;
3719 int k;
3721 if (!inter.exists ())
3722 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3723 inter.safe_push ((*jfunc->agg.items)[i]);
3724 else
3725 FOR_EACH_VEC_ELT (inter, k, item)
3727 int l = 0;
3728 bool found = false;;
3730 if (!item->value)
3731 continue;
3733 while ((unsigned) l < jfunc->agg.items->length ())
3735 struct ipa_agg_jf_item *ti;
3736 ti = &(*jfunc->agg.items)[l];
3737 if (ti->offset > item->offset)
3738 break;
3739 if (ti->offset == item->offset)
3741 gcc_checking_assert (ti->value);
3742 if (values_equal_for_ipcp_p (item->value,
3743 ti->value))
3744 found = true;
3745 break;
3747 l++;
3749 if (!found)
3750 item->value = NULL;
3753 else
3755 inter.release ();
3756 return vec<ipa_agg_jf_item>();
3758 return inter;
3761 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3762 from all of them. */
3764 static struct ipa_agg_replacement_value *
3765 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3766 vec<cgraph_edge *> callers)
3768 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3769 struct ipa_agg_replacement_value *res;
3770 struct ipa_agg_replacement_value **tail = &res;
3771 struct cgraph_edge *cs;
3772 int i, j, count = ipa_get_param_count (dest_info);
3774 FOR_EACH_VEC_ELT (callers, j, cs)
3776 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3777 if (c < count)
3778 count = c;
3781 for (i = 0; i < count ; i++)
3783 struct cgraph_edge *cs;
3784 vec<ipa_agg_jf_item> inter = vNULL;
3785 struct ipa_agg_jf_item *item;
3786 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3787 int j;
3789 /* Among other things, the following check should deal with all by_ref
3790 mismatches. */
3791 if (plats->aggs_bottom)
3792 continue;
3794 FOR_EACH_VEC_ELT (callers, j, cs)
3796 inter = intersect_aggregates_with_edge (cs, i, inter);
3798 if (!inter.exists ())
3799 goto next_param;
3802 FOR_EACH_VEC_ELT (inter, j, item)
3804 struct ipa_agg_replacement_value *v;
3806 if (!item->value)
3807 continue;
3809 v = ggc_alloc<ipa_agg_replacement_value> ();
3810 v->index = i;
3811 v->offset = item->offset;
3812 v->value = item->value;
3813 v->by_ref = plats->aggs_by_ref;
3814 *tail = v;
3815 tail = &v->next;
3818 next_param:
3819 if (inter.exists ())
3820 inter.release ();
3822 *tail = NULL;
3823 return res;
3826 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3828 static struct ipa_agg_replacement_value *
3829 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
3831 struct ipa_agg_replacement_value *res;
3832 struct ipa_agg_replacement_value **tail = &res;
3833 struct ipa_agg_jump_function *aggjf;
3834 struct ipa_agg_jf_item *item;
3835 int i, j;
3837 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3838 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3840 struct ipa_agg_replacement_value *v;
3841 v = ggc_alloc<ipa_agg_replacement_value> ();
3842 v->index = i;
3843 v->offset = item->offset;
3844 v->value = item->value;
3845 v->by_ref = aggjf->by_ref;
3846 *tail = v;
3847 tail = &v->next;
3849 *tail = NULL;
3850 return res;
3853 /* Determine whether CS also brings all scalar values that the NODE is
3854 specialized for. */
3856 static bool
3857 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3858 struct cgraph_node *node)
3860 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3861 int count = ipa_get_param_count (dest_info);
3862 struct ipa_node_params *caller_info;
3863 struct ipa_edge_args *args;
3864 int i;
3866 caller_info = IPA_NODE_REF (cs->caller);
3867 args = IPA_EDGE_REF (cs);
3868 for (i = 0; i < count; i++)
3870 struct ipa_jump_func *jump_func;
3871 tree val, t;
3873 val = dest_info->known_csts[i];
3874 if (!val)
3875 continue;
3877 if (i >= ipa_get_cs_argument_count (args))
3878 return false;
3879 jump_func = ipa_get_ith_jump_func (args, i);
3880 t = ipa_value_from_jfunc (caller_info, jump_func);
3881 if (!t || !values_equal_for_ipcp_p (val, t))
3882 return false;
3884 return true;
3887 /* Determine whether CS also brings all aggregate values that NODE is
3888 specialized for. */
3889 static bool
3890 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3891 struct cgraph_node *node)
3893 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3894 struct ipa_node_params *orig_node_info;
3895 struct ipa_agg_replacement_value *aggval;
3896 int i, ec, count;
3898 aggval = ipa_get_agg_replacements_for_node (node);
3899 if (!aggval)
3900 return true;
3902 count = ipa_get_param_count (IPA_NODE_REF (node));
3903 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3904 if (ec < count)
3905 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3906 if (aggval->index >= ec)
3907 return false;
3909 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3910 if (orig_caller_info->ipcp_orig_node)
3911 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3913 for (i = 0; i < count; i++)
3915 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
3916 struct ipcp_param_lattices *plats;
3917 bool interesting = false;
3918 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3919 if (aggval->index == i)
3921 interesting = true;
3922 break;
3924 if (!interesting)
3925 continue;
3927 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3928 if (plats->aggs_bottom)
3929 return false;
3931 values = intersect_aggregates_with_edge (cs, i, values);
3932 if (!values.exists ())
3933 return false;
3935 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3936 if (aggval->index == i)
3938 struct ipa_agg_jf_item *item;
3939 int j;
3940 bool found = false;
3941 FOR_EACH_VEC_ELT (values, j, item)
3942 if (item->value
3943 && item->offset == av->offset
3944 && values_equal_for_ipcp_p (item->value, av->value))
3946 found = true;
3947 break;
3949 if (!found)
3951 values.release ();
3952 return false;
3956 return true;
3959 /* Given an original NODE and a VAL for which we have already created a
3960 specialized clone, look whether there are incoming edges that still lead
3961 into the old node but now also bring the requested value and also conform to
3962 all other criteria such that they can be redirected the special node.
3963 This function can therefore redirect the final edge in a SCC. */
3965 template <typename valtype>
3966 static void
3967 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
3969 ipcp_value_source<valtype> *src;
3970 gcov_type redirected_sum = 0;
3972 for (src = val->sources; src; src = src->next)
3974 struct cgraph_edge *cs = src->cs;
3975 while (cs)
3977 if (cgraph_edge_brings_value_p (cs, src, node)
3978 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3979 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
3981 if (dump_file)
3982 fprintf (dump_file, " - adding an extra caller %s/%i"
3983 " of %s/%i\n",
3984 xstrdup_for_dump (cs->caller->name ()),
3985 cs->caller->order,
3986 xstrdup_for_dump (val->spec_node->name ()),
3987 val->spec_node->order);
3989 cs->redirect_callee_duplicating_thunks (val->spec_node);
3990 val->spec_node->expand_all_artificial_thunks ();
3991 redirected_sum += cs->count;
3993 cs = get_next_cgraph_edge_clone (cs);
3997 if (redirected_sum)
3998 update_specialized_profile (val->spec_node, node, redirected_sum);
4001 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4003 static bool
4004 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4006 ipa_polymorphic_call_context *ctx;
4007 int i;
4009 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4010 if (!ctx->useless_p ())
4011 return true;
4012 return false;
4015 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4017 static vec<ipa_polymorphic_call_context>
4018 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4020 if (known_contexts_useful_p (known_contexts))
4021 return known_contexts.copy ();
4022 else
4023 return vNULL;
4026 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4027 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4029 static void
4030 modify_known_vectors_with_val (vec<tree> *known_csts,
4031 vec<ipa_polymorphic_call_context> *known_contexts,
4032 ipcp_value<tree> *val,
4033 int index)
4035 *known_csts = known_csts->copy ();
4036 *known_contexts = copy_useful_known_contexts (*known_contexts);
4037 (*known_csts)[index] = val->value;
4040 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4041 copy according to VAL and INDEX. */
4043 static void
4044 modify_known_vectors_with_val (vec<tree> *known_csts,
4045 vec<ipa_polymorphic_call_context> *known_contexts,
4046 ipcp_value<ipa_polymorphic_call_context> *val,
4047 int index)
4049 *known_csts = known_csts->copy ();
4050 *known_contexts = known_contexts->copy ();
4051 (*known_contexts)[index] = val->value;
4054 /* Return true if OFFSET indicates this was not an aggregate value or there is
4055 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4056 AGGVALS list. */
4058 DEBUG_FUNCTION bool
4059 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4060 int index, HOST_WIDE_INT offset, tree value)
4062 if (offset == -1)
4063 return true;
4065 while (aggvals)
4067 if (aggvals->index == index
4068 && aggvals->offset == offset
4069 && values_equal_for_ipcp_p (aggvals->value, value))
4070 return true;
4071 aggvals = aggvals->next;
4073 return false;
4076 /* Return true if offset is minus one because source of a polymorphic contect
4077 cannot be an aggregate value. */
4079 DEBUG_FUNCTION bool
4080 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4081 int , HOST_WIDE_INT offset,
4082 ipa_polymorphic_call_context)
4084 return offset == -1;
4087 /* Decide wheter to create a special version of NODE for value VAL of parameter
4088 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4089 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4090 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4092 template <typename valtype>
4093 static bool
4094 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4095 ipcp_value<valtype> *val, vec<tree> known_csts,
4096 vec<ipa_polymorphic_call_context> known_contexts)
4098 struct ipa_agg_replacement_value *aggvals;
4099 int freq_sum, caller_count;
4100 gcov_type count_sum;
4101 vec<cgraph_edge *> callers;
4103 if (val->spec_node)
4105 perhaps_add_new_callers (node, val);
4106 return false;
4108 else if (val->local_size_cost + overall_size > max_new_size)
4110 if (dump_file && (dump_flags & TDF_DETAILS))
4111 fprintf (dump_file, " Ignoring candidate value because "
4112 "max_new_size would be reached with %li.\n",
4113 val->local_size_cost + overall_size);
4114 return false;
4116 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4117 &caller_count))
4118 return false;
4120 if (dump_file && (dump_flags & TDF_DETAILS))
4122 fprintf (dump_file, " - considering value ");
4123 print_ipcp_constant_value (dump_file, val->value);
4124 fprintf (dump_file, " for ");
4125 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4126 if (offset != -1)
4127 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4128 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4131 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4132 freq_sum, count_sum,
4133 val->local_size_cost)
4134 && !good_cloning_opportunity_p (node,
4135 val->local_time_benefit
4136 + val->prop_time_benefit,
4137 freq_sum, count_sum,
4138 val->local_size_cost
4139 + val->prop_size_cost))
4140 return false;
4142 if (dump_file)
4143 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
4144 node->name (), node->order);
4146 callers = gather_edges_for_value (val, node, caller_count);
4147 if (offset == -1)
4148 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4149 else
4151 known_csts = known_csts.copy ();
4152 known_contexts = copy_useful_known_contexts (known_contexts);
4154 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4155 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4156 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4157 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4158 offset, val->value));
4159 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4160 aggvals, callers);
4161 overall_size += val->local_size_cost;
4163 /* TODO: If for some lattice there is only one other known value
4164 left, make a special node for it too. */
4166 return true;
4169 /* Decide whether and what specialized clones of NODE should be created. */
4171 static bool
4172 decide_whether_version_node (struct cgraph_node *node)
4174 struct ipa_node_params *info = IPA_NODE_REF (node);
4175 int i, count = ipa_get_param_count (info);
4176 vec<tree> known_csts;
4177 vec<ipa_polymorphic_call_context> known_contexts;
4178 vec<ipa_agg_jump_function> known_aggs = vNULL;
4179 bool ret = false;
4181 if (count == 0)
4182 return false;
4184 if (dump_file && (dump_flags & TDF_DETAILS))
4185 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4186 node->name (), node->order);
4188 gather_context_independent_values (info, &known_csts, &known_contexts,
4189 info->do_clone_for_all_contexts ? &known_aggs
4190 : NULL, NULL);
4192 for (i = 0; i < count ;i++)
4194 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4195 ipcp_lattice<tree> *lat = &plats->itself;
4196 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4198 if (!lat->bottom
4199 && !known_csts[i])
4201 ipcp_value<tree> *val;
4202 for (val = lat->values; val; val = val->next)
4203 ret |= decide_about_value (node, i, -1, val, known_csts,
4204 known_contexts);
4207 if (!plats->aggs_bottom)
4209 struct ipcp_agg_lattice *aglat;
4210 ipcp_value<tree> *val;
4211 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4212 if (!aglat->bottom && aglat->values
4213 /* If the following is false, the one value is in
4214 known_aggs. */
4215 && (plats->aggs_contain_variable
4216 || !aglat->is_single_const ()))
4217 for (val = aglat->values; val; val = val->next)
4218 ret |= decide_about_value (node, i, aglat->offset, val,
4219 known_csts, known_contexts);
4222 if (!ctxlat->bottom
4223 && known_contexts[i].useless_p ())
4225 ipcp_value<ipa_polymorphic_call_context> *val;
4226 for (val = ctxlat->values; val; val = val->next)
4227 ret |= decide_about_value (node, i, -1, val, known_csts,
4228 known_contexts);
4231 info = IPA_NODE_REF (node);
4234 if (info->do_clone_for_all_contexts)
4236 struct cgraph_node *clone;
4237 vec<cgraph_edge *> callers;
4239 if (dump_file)
4240 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4241 "for all known contexts.\n", node->name (),
4242 node->order);
4244 callers = node->collect_callers ();
4246 if (!known_contexts_useful_p (known_contexts))
4248 known_contexts.release ();
4249 known_contexts = vNULL;
4251 clone = create_specialized_node (node, known_csts, known_contexts,
4252 known_aggs_to_agg_replacement_list (known_aggs),
4253 callers);
4254 info = IPA_NODE_REF (node);
4255 info->do_clone_for_all_contexts = false;
4256 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4257 for (i = 0; i < count ; i++)
4258 vec_free (known_aggs[i].items);
4259 known_aggs.release ();
4260 ret = true;
4262 else
4264 known_csts.release ();
4265 known_contexts.release ();
4268 return ret;
4271 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4273 static void
4274 spread_undeadness (struct cgraph_node *node)
4276 struct cgraph_edge *cs;
4278 for (cs = node->callees; cs; cs = cs->next_callee)
4279 if (ipa_edge_within_scc (cs))
4281 struct cgraph_node *callee;
4282 struct ipa_node_params *info;
4284 callee = cs->callee->function_symbol (NULL);
4285 info = IPA_NODE_REF (callee);
4287 if (info->node_dead)
4289 info->node_dead = 0;
4290 spread_undeadness (callee);
4295 /* Return true if NODE has a caller from outside of its SCC that is not
4296 dead. Worker callback for cgraph_for_node_and_aliases. */
4298 static bool
4299 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4300 void *data ATTRIBUTE_UNUSED)
4302 struct cgraph_edge *cs;
4304 for (cs = node->callers; cs; cs = cs->next_caller)
4305 if (cs->caller->thunk.thunk_p
4306 && cs->caller->call_for_symbol_thunks_and_aliases
4307 (has_undead_caller_from_outside_scc_p, NULL, true))
4308 return true;
4309 else if (!ipa_edge_within_scc (cs)
4310 && !IPA_NODE_REF (cs->caller)->node_dead)
4311 return true;
4312 return false;
4316 /* Identify nodes within the same SCC as NODE which are no longer needed
4317 because of new clones and will be removed as unreachable. */
4319 static void
4320 identify_dead_nodes (struct cgraph_node *node)
4322 struct cgraph_node *v;
4323 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4324 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
4325 && !v->call_for_symbol_thunks_and_aliases
4326 (has_undead_caller_from_outside_scc_p, NULL, true))
4327 IPA_NODE_REF (v)->node_dead = 1;
4329 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4330 if (!IPA_NODE_REF (v)->node_dead)
4331 spread_undeadness (v);
4333 if (dump_file && (dump_flags & TDF_DETAILS))
4335 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4336 if (IPA_NODE_REF (v)->node_dead)
4337 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4338 v->name (), v->order);
4342 /* The decision stage. Iterate over the topological order of call graph nodes
4343 TOPO and make specialized clones if deemed beneficial. */
4345 static void
4346 ipcp_decision_stage (struct ipa_topo_info *topo)
4348 int i;
4350 if (dump_file)
4351 fprintf (dump_file, "\nIPA decision stage:\n\n");
4353 for (i = topo->nnodes - 1; i >= 0; i--)
4355 struct cgraph_node *node = topo->order[i];
4356 bool change = false, iterate = true;
4358 while (iterate)
4360 struct cgraph_node *v;
4361 iterate = false;
4362 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4363 if (v->has_gimple_body_p ()
4364 && ipcp_versionable_function_p (v))
4365 iterate |= decide_whether_version_node (v);
4367 change |= iterate;
4369 if (change)
4370 identify_dead_nodes (node);
4374 /* Look up all alignment information that we have discovered and copy it over
4375 to the transformation summary. */
4377 static void
4378 ipcp_store_alignment_results (void)
4380 cgraph_node *node;
4382 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4384 ipa_node_params *info = IPA_NODE_REF (node);
4385 bool dumped_sth = false;
4386 bool found_useful_result = false;
4388 if (!opt_for_fn (node->decl, flag_ipa_cp_alignment))
4390 if (dump_file)
4391 fprintf (dump_file, "Not considering %s for alignment discovery "
4392 "and propagate; -fipa-cp-alignment: disabled.\n",
4393 node->name ());
4394 continue;
4397 if (info->ipcp_orig_node)
4398 info = IPA_NODE_REF (info->ipcp_orig_node);
4400 unsigned count = ipa_get_param_count (info);
4401 for (unsigned i = 0; i < count ; i++)
4403 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4404 if (plats->alignment.known
4405 && plats->alignment.align > 0)
4407 found_useful_result = true;
4408 break;
4411 if (!found_useful_result)
4412 continue;
4414 ipcp_grow_transformations_if_necessary ();
4415 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4416 vec_safe_reserve_exact (ts->alignments, count);
4418 for (unsigned i = 0; i < count ; i++)
4420 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4422 if (plats->alignment.align == 0)
4423 plats->alignment.known = false;
4425 ts->alignments->quick_push (plats->alignment);
4426 if (!dump_file || !plats->alignment.known)
4427 continue;
4428 if (!dumped_sth)
4430 fprintf (dump_file, "Propagated alignment info for function %s/%i:\n",
4431 node->name (), node->order);
4432 dumped_sth = true;
4434 fprintf (dump_file, " param %i: align: %u, misalign: %u\n",
4435 i, plats->alignment.align, plats->alignment.misalign);
4440 /* The IPCP driver. */
4442 static unsigned int
4443 ipcp_driver (void)
4445 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4446 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4447 struct ipa_topo_info topo;
4449 ipa_check_create_node_params ();
4450 ipa_check_create_edge_args ();
4451 grow_edge_clone_vectors ();
4452 edge_duplication_hook_holder =
4453 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4454 edge_removal_hook_holder =
4455 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4457 if (dump_file)
4459 fprintf (dump_file, "\nIPA structures before propagation:\n");
4460 if (dump_flags & TDF_DETAILS)
4461 ipa_print_all_params (dump_file);
4462 ipa_print_all_jump_functions (dump_file);
4465 /* Topological sort. */
4466 build_toporder_info (&topo);
4467 /* Do the interprocedural propagation. */
4468 ipcp_propagate_stage (&topo);
4469 /* Decide what constant propagation and cloning should be performed. */
4470 ipcp_decision_stage (&topo);
4471 /* Store results of alignment propagation. */
4472 ipcp_store_alignment_results ();
4474 /* Free all IPCP structures. */
4475 free_toporder_info (&topo);
4476 next_edge_clone.release ();
4477 prev_edge_clone.release ();
4478 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4479 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
4480 ipa_free_all_structures_after_ipa_cp ();
4481 if (dump_file)
4482 fprintf (dump_file, "\nIPA constant propagation end\n");
4483 return 0;
4486 /* Initialization and computation of IPCP data structures. This is the initial
4487 intraprocedural analysis of functions, which gathers information to be
4488 propagated later on. */
4490 static void
4491 ipcp_generate_summary (void)
4493 struct cgraph_node *node;
4495 if (dump_file)
4496 fprintf (dump_file, "\nIPA constant propagation start:\n");
4497 ipa_register_cgraph_hooks ();
4499 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4501 node->local.versionable
4502 = tree_versionable_function_p (node->decl);
4503 ipa_analyze_node (node);
4507 /* Write ipcp summary for nodes in SET. */
4509 static void
4510 ipcp_write_summary (void)
4512 ipa_prop_write_jump_functions ();
4515 /* Read ipcp summary. */
4517 static void
4518 ipcp_read_summary (void)
4520 ipa_prop_read_jump_functions ();
4523 namespace {
4525 const pass_data pass_data_ipa_cp =
4527 IPA_PASS, /* type */
4528 "cp", /* name */
4529 OPTGROUP_NONE, /* optinfo_flags */
4530 TV_IPA_CONSTANT_PROP, /* tv_id */
4531 0, /* properties_required */
4532 0, /* properties_provided */
4533 0, /* properties_destroyed */
4534 0, /* todo_flags_start */
4535 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
4538 class pass_ipa_cp : public ipa_opt_pass_d
4540 public:
4541 pass_ipa_cp (gcc::context *ctxt)
4542 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
4543 ipcp_generate_summary, /* generate_summary */
4544 ipcp_write_summary, /* write_summary */
4545 ipcp_read_summary, /* read_summary */
4546 ipcp_write_transformation_summaries, /*
4547 write_optimization_summary */
4548 ipcp_read_transformation_summaries, /*
4549 read_optimization_summary */
4550 NULL, /* stmt_fixup */
4551 0, /* function_transform_todo_flags_start */
4552 ipcp_transform_function, /* function_transform */
4553 NULL) /* variable_transform */
4556 /* opt_pass methods: */
4557 virtual bool gate (function *)
4559 /* FIXME: We should remove the optimize check after we ensure we never run
4560 IPA passes when not optimizing. */
4561 return (flag_ipa_cp && optimize) || in_lto_p;
4564 virtual unsigned int execute (function *) { return ipcp_driver (); }
4566 }; // class pass_ipa_cp
4568 } // anon namespace
4570 ipa_opt_pass_d *
4571 make_pass_ipa_cp (gcc::context *ctxt)
4573 return new pass_ipa_cp (ctxt);
4576 /* Reset all state within ipa-cp.c so that we can rerun the compiler
4577 within the same process. For use by toplev::finalize. */
4579 void
4580 ipa_cp_c_finalize (void)
4582 max_count = 0;
4583 overall_size = 0;
4584 max_new_size = 0;