Daily bump.
[official-gcc.git] / gcc / ipa-cp.c
blobd36563490160d1940ae20e419078627b74aff828
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2014 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 "tree.h"
107 #include "gimple-fold.h"
108 #include "gimple-expr.h"
109 #include "target.h"
110 #include "ipa-prop.h"
111 #include "bitmap.h"
112 #include "tree-pass.h"
113 #include "flags.h"
114 #include "diagnostic.h"
115 #include "tree-pretty-print.h"
116 #include "tree-inline.h"
117 #include "params.h"
118 #include "ipa-inline.h"
119 #include "ipa-utils.h"
121 struct ipcp_value;
123 /* Describes a particular source for an IPA-CP value. */
125 struct ipcp_value_source
127 /* Aggregate offset of the source, negative if the source is scalar value of
128 the argument itself. */
129 HOST_WIDE_INT offset;
130 /* The incoming edge that brought the value. */
131 struct cgraph_edge *cs;
132 /* If the jump function that resulted into his value was a pass-through or an
133 ancestor, this is the ipcp_value of the caller from which the described
134 value has been derived. Otherwise it is NULL. */
135 struct ipcp_value *val;
136 /* Next pointer in a linked list of sources of a value. */
137 struct ipcp_value_source *next;
138 /* If the jump function that resulted into his value was a pass-through or an
139 ancestor, this is the index of the parameter of the caller the jump
140 function references. */
141 int index;
144 /* Describes one particular value stored in struct ipcp_lattice. */
146 struct ipcp_value
148 /* The actual value for the given parameter. This is either an IPA invariant
149 or a TREE_BINFO describing a type that can be used for
150 devirtualization. */
151 tree value;
152 /* The list of sources from which this value originates. */
153 struct ipcp_value_source *sources;
154 /* Next pointers in a linked list of all values in a lattice. */
155 struct ipcp_value *next;
156 /* Next pointers in a linked list of values in a strongly connected component
157 of values. */
158 struct ipcp_value *scc_next;
159 /* Next pointers in a linked list of SCCs of values sorted topologically
160 according their sources. */
161 struct ipcp_value *topo_next;
162 /* A specialized node created for this value, NULL if none has been (so far)
163 created. */
164 struct cgraph_node *spec_node;
165 /* Depth first search number and low link for topological sorting of
166 values. */
167 int dfs, low_link;
168 /* Time benefit and size cost that specializing the function for this value
169 would bring about in this function alone. */
170 int local_time_benefit, local_size_cost;
171 /* Time benefit and size cost that specializing the function for this value
172 can bring about in it's callees (transitively). */
173 int prop_time_benefit, prop_size_cost;
174 /* True if this valye is currently on the topo-sort stack. */
175 bool on_stack;
178 /* Lattice describing potential values of a formal parameter of a function, or
179 a part of an aggreagate. TOP is represented by a lattice with zero values
180 and with contains_variable and bottom flags cleared. BOTTOM is represented
181 by a lattice with the bottom flag set. In that case, values and
182 contains_variable flag should be disregarded. */
184 struct ipcp_lattice
186 /* The list of known values and types in this lattice. Note that values are
187 not deallocated if a lattice is set to bottom because there may be value
188 sources referencing them. */
189 struct ipcp_value *values;
190 /* Number of known values and types in this lattice. */
191 int values_count;
192 /* The lattice contains a variable component (in addition to values). */
193 bool contains_variable;
194 /* The value of the lattice is bottom (i.e. variable and unusable for any
195 propagation). */
196 bool bottom;
199 /* Lattice with an offset to describe a part of an aggregate. */
201 struct ipcp_agg_lattice : public ipcp_lattice
203 /* Offset that is being described by this lattice. */
204 HOST_WIDE_INT offset;
205 /* Size so that we don't have to re-compute it every time we traverse the
206 list. Must correspond to TYPE_SIZE of all lat values. */
207 HOST_WIDE_INT size;
208 /* Next element of the linked list. */
209 struct ipcp_agg_lattice *next;
212 /* Structure containing lattices for a parameter itself and for pieces of
213 aggregates that are passed in the parameter or by a reference in a parameter
214 plus some other useful flags. */
216 struct ipcp_param_lattices
218 /* Lattice describing the value of the parameter itself. */
219 struct ipcp_lattice itself;
220 /* Lattices describing aggregate parts. */
221 struct ipcp_agg_lattice *aggs;
222 /* Number of aggregate lattices */
223 int aggs_count;
224 /* True if aggregate data were passed by reference (as opposed to by
225 value). */
226 bool aggs_by_ref;
227 /* All aggregate lattices contain a variable component (in addition to
228 values). */
229 bool aggs_contain_variable;
230 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
231 for any propagation). */
232 bool aggs_bottom;
234 /* There is a virtual call based on this parameter. */
235 bool virt_call;
238 /* Allocation pools for values and their sources in ipa-cp. */
240 alloc_pool ipcp_values_pool;
241 alloc_pool ipcp_sources_pool;
242 alloc_pool ipcp_agg_lattice_pool;
244 /* Maximal count found in program. */
246 static gcov_type max_count;
248 /* Original overall size of the program. */
250 static long overall_size, max_new_size;
252 /* Head of the linked list of topologically sorted values. */
254 static struct ipcp_value *values_topo;
256 /* Return the param lattices structure corresponding to the Ith formal
257 parameter of the function described by INFO. */
258 static inline struct ipcp_param_lattices *
259 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
261 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
262 gcc_checking_assert (!info->ipcp_orig_node);
263 gcc_checking_assert (info->lattices);
264 return &(info->lattices[i]);
267 /* Return the lattice corresponding to the scalar value of the Ith formal
268 parameter of the function described by INFO. */
269 static inline struct ipcp_lattice *
270 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
272 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
273 return &plats->itself;
276 /* Return whether LAT is a lattice with a single constant and without an
277 undefined value. */
279 static inline bool
280 ipa_lat_is_single_const (struct ipcp_lattice *lat)
282 if (lat->bottom
283 || lat->contains_variable
284 || lat->values_count != 1)
285 return false;
286 else
287 return true;
290 /* Print V which is extracted from a value in a lattice to F. */
292 static void
293 print_ipcp_constant_value (FILE * f, tree v)
295 if (TREE_CODE (v) == TREE_BINFO)
297 fprintf (f, "BINFO ");
298 print_generic_expr (f, BINFO_TYPE (v), 0);
300 else if (TREE_CODE (v) == ADDR_EXPR
301 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
303 fprintf (f, "& ");
304 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
306 else
307 print_generic_expr (f, v, 0);
310 /* Print a lattice LAT to F. */
312 static void
313 print_lattice (FILE * f, struct ipcp_lattice *lat,
314 bool dump_sources, bool dump_benefits)
316 struct ipcp_value *val;
317 bool prev = false;
319 if (lat->bottom)
321 fprintf (f, "BOTTOM\n");
322 return;
325 if (!lat->values_count && !lat->contains_variable)
327 fprintf (f, "TOP\n");
328 return;
331 if (lat->contains_variable)
333 fprintf (f, "VARIABLE");
334 prev = true;
335 if (dump_benefits)
336 fprintf (f, "\n");
339 for (val = lat->values; val; val = val->next)
341 if (dump_benefits && prev)
342 fprintf (f, " ");
343 else if (!dump_benefits && prev)
344 fprintf (f, ", ");
345 else
346 prev = true;
348 print_ipcp_constant_value (f, val->value);
350 if (dump_sources)
352 struct ipcp_value_source *s;
354 fprintf (f, " [from:");
355 for (s = val->sources; s; s = s->next)
356 fprintf (f, " %i(%i)", s->cs->caller->order,
357 s->cs->frequency);
358 fprintf (f, "]");
361 if (dump_benefits)
362 fprintf (f, " [loc_time: %i, loc_size: %i, "
363 "prop_time: %i, prop_size: %i]\n",
364 val->local_time_benefit, val->local_size_cost,
365 val->prop_time_benefit, val->prop_size_cost);
367 if (!dump_benefits)
368 fprintf (f, "\n");
371 /* Print all ipcp_lattices of all functions to F. */
373 static void
374 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
376 struct cgraph_node *node;
377 int i, count;
379 fprintf (f, "\nLattices:\n");
380 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
382 struct ipa_node_params *info;
384 info = IPA_NODE_REF (node);
385 fprintf (f, " Node: %s/%i:\n", node->name (),
386 node->order);
387 count = ipa_get_param_count (info);
388 for (i = 0; i < count; i++)
390 struct ipcp_agg_lattice *aglat;
391 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
392 fprintf (f, " param [%d]: ", i);
393 print_lattice (f, &plats->itself, dump_sources, dump_benefits);
395 if (plats->virt_call)
396 fprintf (f, " virt_call flag set\n");
398 if (plats->aggs_bottom)
400 fprintf (f, " AGGS BOTTOM\n");
401 continue;
403 if (plats->aggs_contain_variable)
404 fprintf (f, " AGGS VARIABLE\n");
405 for (aglat = plats->aggs; aglat; aglat = aglat->next)
407 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
408 plats->aggs_by_ref ? "ref " : "", aglat->offset);
409 print_lattice (f, aglat, dump_sources, dump_benefits);
415 /* Determine whether it is at all technically possible to create clones of NODE
416 and store this information in the ipa_node_params structure associated
417 with NODE. */
419 static void
420 determine_versionability (struct cgraph_node *node)
422 const char *reason = NULL;
424 /* There are a number of generic reasons functions cannot be versioned. We
425 also cannot remove parameters if there are type attributes such as fnspec
426 present. */
427 if (node->alias || node->thunk.thunk_p)
428 reason = "alias or thunk";
429 else if (!node->local.versionable)
430 reason = "not a tree_versionable_function";
431 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
432 reason = "insufficient body availability";
433 else if (!opt_for_fn (node->decl, optimize)
434 || !opt_for_fn (node->decl, flag_ipa_cp))
435 reason = "non-optimized function";
436 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
438 /* Ideally we should clone the SIMD clones themselves and create
439 vector copies of them, so IPA-cp and SIMD clones can happily
440 coexist, but that may not be worth the effort. */
441 reason = "function has SIMD clones";
443 /* Don't clone decls local to a comdat group; it breaks and for C++
444 decloned constructors, inlining is always better anyway. */
445 else if (node->comdat_local_p ())
446 reason = "comdat-local function";
448 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
449 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
450 node->name (), node->order, reason);
452 node->local.versionable = (reason == NULL);
455 /* Return true if it is at all technically possible to create clones of a
456 NODE. */
458 static bool
459 ipcp_versionable_function_p (struct cgraph_node *node)
461 return node->local.versionable;
464 /* Structure holding accumulated information about callers of a node. */
466 struct caller_statistics
468 gcov_type count_sum;
469 int n_calls, n_hot_calls, freq_sum;
472 /* Initialize fields of STAT to zeroes. */
474 static inline void
475 init_caller_stats (struct caller_statistics *stats)
477 stats->count_sum = 0;
478 stats->n_calls = 0;
479 stats->n_hot_calls = 0;
480 stats->freq_sum = 0;
483 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
484 non-thunk incoming edges to NODE. */
486 static bool
487 gather_caller_stats (struct cgraph_node *node, void *data)
489 struct caller_statistics *stats = (struct caller_statistics *) data;
490 struct cgraph_edge *cs;
492 for (cs = node->callers; cs; cs = cs->next_caller)
493 if (cs->caller->thunk.thunk_p)
494 cs->caller->call_for_symbol_thunks_and_aliases (gather_caller_stats,
495 stats, false);
496 else
498 stats->count_sum += cs->count;
499 stats->freq_sum += cs->frequency;
500 stats->n_calls++;
501 if (cs->maybe_hot_p ())
502 stats->n_hot_calls ++;
504 return false;
508 /* Return true if this NODE is viable candidate for cloning. */
510 static bool
511 ipcp_cloning_candidate_p (struct cgraph_node *node)
513 struct caller_statistics stats;
515 gcc_checking_assert (node->has_gimple_body_p ());
517 if (!flag_ipa_cp_clone)
519 if (dump_file)
520 fprintf (dump_file, "Not considering %s for cloning; "
521 "-fipa-cp-clone disabled.\n",
522 node->name ());
523 return false;
526 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
528 if (dump_file)
529 fprintf (dump_file, "Not considering %s for cloning; "
530 "optimizing it for size.\n",
531 node->name ());
532 return false;
535 init_caller_stats (&stats);
536 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
538 if (inline_summary (node)->self_size < stats.n_calls)
540 if (dump_file)
541 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
542 node->name ());
543 return true;
546 /* When profile is available and function is hot, propagate into it even if
547 calls seems cold; constant propagation can improve function's speed
548 significantly. */
549 if (max_count)
551 if (stats.count_sum > node->count * 90 / 100)
553 if (dump_file)
554 fprintf (dump_file, "Considering %s for cloning; "
555 "usually called directly.\n",
556 node->name ());
557 return true;
560 if (!stats.n_hot_calls)
562 if (dump_file)
563 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
564 node->name ());
565 return false;
567 if (dump_file)
568 fprintf (dump_file, "Considering %s for cloning.\n",
569 node->name ());
570 return true;
573 /* Arrays representing a topological ordering of call graph nodes and a stack
574 of noes used during constant propagation. */
576 struct topo_info
578 struct cgraph_node **order;
579 struct cgraph_node **stack;
580 int nnodes, stack_top;
583 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
585 static void
586 build_toporder_info (struct topo_info *topo)
588 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
589 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
591 topo->stack_top = 0;
592 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
595 /* Free information about strongly connected components and the arrays in
596 TOPO. */
598 static void
599 free_toporder_info (struct topo_info *topo)
601 ipa_free_postorder_info ();
602 free (topo->order);
603 free (topo->stack);
606 /* Add NODE to the stack in TOPO, unless it is already there. */
608 static inline void
609 push_node_to_stack (struct topo_info *topo, struct cgraph_node *node)
611 struct ipa_node_params *info = IPA_NODE_REF (node);
612 if (info->node_enqueued)
613 return;
614 info->node_enqueued = 1;
615 topo->stack[topo->stack_top++] = node;
618 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
619 is empty. */
621 static struct cgraph_node *
622 pop_node_from_stack (struct topo_info *topo)
624 if (topo->stack_top)
626 struct cgraph_node *node;
627 topo->stack_top--;
628 node = topo->stack[topo->stack_top];
629 IPA_NODE_REF (node)->node_enqueued = 0;
630 return node;
632 else
633 return NULL;
636 /* Set lattice LAT to bottom and return true if it previously was not set as
637 such. */
639 static inline bool
640 set_lattice_to_bottom (struct ipcp_lattice *lat)
642 bool ret = !lat->bottom;
643 lat->bottom = true;
644 return ret;
647 /* Mark lattice as containing an unknown value and return true if it previously
648 was not marked as such. */
650 static inline bool
651 set_lattice_contains_variable (struct ipcp_lattice *lat)
653 bool ret = !lat->contains_variable;
654 lat->contains_variable = true;
655 return ret;
658 /* Set all aggegate lattices in PLATS to bottom and return true if they were
659 not previously set as such. */
661 static inline bool
662 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
664 bool ret = !plats->aggs_bottom;
665 plats->aggs_bottom = true;
666 return ret;
669 /* Mark all aggegate lattices in PLATS as containing an unknown value and
670 return true if they were not previously marked as such. */
672 static inline bool
673 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
675 bool ret = !plats->aggs_contain_variable;
676 plats->aggs_contain_variable = true;
677 return ret;
680 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
681 return true is any of them has not been marked as such so far. */
683 static inline bool
684 set_all_contains_variable (struct ipcp_param_lattices *plats)
686 bool ret = !plats->itself.contains_variable || !plats->aggs_contain_variable;
687 plats->itself.contains_variable = true;
688 plats->aggs_contain_variable = true;
689 return ret;
692 /* Initialize ipcp_lattices. */
694 static void
695 initialize_node_lattices (struct cgraph_node *node)
697 struct ipa_node_params *info = IPA_NODE_REF (node);
698 struct cgraph_edge *ie;
699 bool disable = false, variable = false;
700 int i;
702 gcc_checking_assert (node->has_gimple_body_p ());
703 if (!node->local.local)
705 /* When cloning is allowed, we can assume that externally visible
706 functions are not called. We will compensate this by cloning
707 later. */
708 if (ipcp_versionable_function_p (node)
709 && ipcp_cloning_candidate_p (node))
710 variable = true;
711 else
712 disable = true;
715 if (disable || variable)
717 for (i = 0; i < ipa_get_param_count (info) ; i++)
719 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
720 if (disable)
722 set_lattice_to_bottom (&plats->itself);
723 set_agg_lats_to_bottom (plats);
725 else
726 set_all_contains_variable (plats);
728 if (dump_file && (dump_flags & TDF_DETAILS)
729 && !node->alias && !node->thunk.thunk_p)
730 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
731 node->name (), node->order,
732 disable ? "BOTTOM" : "VARIABLE");
735 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
736 if (ie->indirect_info->polymorphic
737 && ie->indirect_info->param_index >= 0)
739 gcc_checking_assert (ie->indirect_info->param_index >= 0);
740 ipa_get_parm_lattices (info,
741 ie->indirect_info->param_index)->virt_call = 1;
745 /* Return the result of a (possibly arithmetic) pass through jump function
746 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
747 determined or be considered an interprocedural invariant. */
749 static tree
750 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
752 tree restype, res;
754 if (TREE_CODE (input) == TREE_BINFO)
756 if (ipa_get_jf_pass_through_type_preserved (jfunc))
758 gcc_checking_assert (ipa_get_jf_pass_through_operation (jfunc)
759 == NOP_EXPR);
760 return input;
762 return NULL_TREE;
765 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
766 return input;
768 gcc_checking_assert (is_gimple_ip_invariant (input));
769 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
770 == tcc_comparison)
771 restype = boolean_type_node;
772 else
773 restype = TREE_TYPE (input);
774 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
775 input, ipa_get_jf_pass_through_operand (jfunc));
777 if (res && !is_gimple_ip_invariant (res))
778 return NULL_TREE;
780 return res;
783 /* Return the result of an ancestor jump function JFUNC on the constant value
784 INPUT. Return NULL_TREE if that cannot be determined. */
786 static tree
787 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
789 if (TREE_CODE (input) == TREE_BINFO)
791 if (!ipa_get_jf_ancestor_type_preserved (jfunc))
792 return NULL;
793 /* FIXME: At LTO we can't propagate to non-polymorphic type, because
794 we have no ODR equivalency on those. This should be fixed by
795 propagating on types rather than binfos that would make type
796 matching here unnecesary. */
797 if (in_lto_p
798 && (TREE_CODE (ipa_get_jf_ancestor_type (jfunc)) != RECORD_TYPE
799 || !TYPE_BINFO (ipa_get_jf_ancestor_type (jfunc))
800 || !BINFO_VTABLE (TYPE_BINFO (ipa_get_jf_ancestor_type (jfunc)))))
802 if (!ipa_get_jf_ancestor_offset (jfunc))
803 return input;
804 return NULL;
806 return get_binfo_at_offset (input,
807 ipa_get_jf_ancestor_offset (jfunc),
808 ipa_get_jf_ancestor_type (jfunc));
810 else if (TREE_CODE (input) == ADDR_EXPR)
812 tree t = TREE_OPERAND (input, 0);
813 t = build_ref_for_offset (EXPR_LOCATION (t), t,
814 ipa_get_jf_ancestor_offset (jfunc),
815 ipa_get_jf_ancestor_type (jfunc)
816 ? ipa_get_jf_ancestor_type (jfunc)
817 : ptr_type_node, NULL, false);
818 return build_fold_addr_expr (t);
820 else
821 return NULL_TREE;
824 /* Determine whether JFUNC evaluates to a known value (that is either a
825 constant or a binfo) and if so, return it. Otherwise return NULL. INFO
826 describes the caller node so that pass-through jump functions can be
827 evaluated. */
829 tree
830 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
832 if (jfunc->type == IPA_JF_CONST)
833 return ipa_get_jf_constant (jfunc);
834 else if (jfunc->type == IPA_JF_KNOWN_TYPE)
835 return ipa_binfo_from_known_type_jfunc (jfunc);
836 else if (jfunc->type == IPA_JF_PASS_THROUGH
837 || jfunc->type == IPA_JF_ANCESTOR)
839 tree input;
840 int idx;
842 if (jfunc->type == IPA_JF_PASS_THROUGH)
843 idx = ipa_get_jf_pass_through_formal_id (jfunc);
844 else
845 idx = ipa_get_jf_ancestor_formal_id (jfunc);
847 if (info->ipcp_orig_node)
848 input = info->known_vals[idx];
849 else
851 struct ipcp_lattice *lat;
853 if (!info->lattices)
855 gcc_checking_assert (!flag_ipa_cp);
856 return NULL_TREE;
858 lat = ipa_get_scalar_lat (info, idx);
859 if (!ipa_lat_is_single_const (lat))
860 return NULL_TREE;
861 input = lat->values->value;
864 if (!input)
865 return NULL_TREE;
867 if (jfunc->type == IPA_JF_PASS_THROUGH)
868 return ipa_get_jf_pass_through_result (jfunc, input);
869 else
870 return ipa_get_jf_ancestor_result (jfunc, input);
872 else
873 return NULL_TREE;
877 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
878 bottom, not containing a variable component and without any known value at
879 the same time. */
881 DEBUG_FUNCTION void
882 ipcp_verify_propagated_values (void)
884 struct cgraph_node *node;
886 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
888 struct ipa_node_params *info = IPA_NODE_REF (node);
889 int i, count = ipa_get_param_count (info);
891 for (i = 0; i < count; i++)
893 struct ipcp_lattice *lat = ipa_get_scalar_lat (info, i);
895 if (!lat->bottom
896 && !lat->contains_variable
897 && lat->values_count == 0)
899 if (dump_file)
901 symtab_node::dump_table (dump_file);
902 fprintf (dump_file, "\nIPA lattices after constant "
903 "propagation, before gcc_unreachable:\n");
904 print_all_lattices (dump_file, true, false);
907 gcc_unreachable ();
913 /* Return true iff X and Y should be considered equal values by IPA-CP. */
915 static bool
916 values_equal_for_ipcp_p (tree x, tree y)
918 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
920 if (x == y)
921 return true;
923 if (TREE_CODE (x) == TREE_BINFO || TREE_CODE (y) == TREE_BINFO)
924 return false;
926 if (TREE_CODE (x) == ADDR_EXPR
927 && TREE_CODE (y) == ADDR_EXPR
928 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
929 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
930 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
931 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
932 else
933 return operand_equal_p (x, y, 0);
936 /* Add a new value source to VAL, marking that a value comes from edge CS and
937 (if the underlying jump function is a pass-through or an ancestor one) from
938 a caller value SRC_VAL of a caller parameter described by SRC_INDEX. OFFSET
939 is negative if the source was the scalar value of the parameter itself or
940 the offset within an aggregate. */
942 static void
943 add_value_source (struct ipcp_value *val, struct cgraph_edge *cs,
944 struct ipcp_value *src_val, int src_idx, HOST_WIDE_INT offset)
946 struct ipcp_value_source *src;
948 src = (struct ipcp_value_source *) pool_alloc (ipcp_sources_pool);
949 src->offset = offset;
950 src->cs = cs;
951 src->val = src_val;
952 src->index = src_idx;
954 src->next = val->sources;
955 val->sources = src;
958 /* Try to add NEWVAL to LAT, potentially creating a new struct ipcp_value for
959 it. CS, SRC_VAL SRC_INDEX and OFFSET are meant for add_value_source and
960 have the same meaning. */
962 static bool
963 add_value_to_lattice (struct ipcp_lattice *lat, tree newval,
964 struct cgraph_edge *cs, struct ipcp_value *src_val,
965 int src_idx, HOST_WIDE_INT offset)
967 struct ipcp_value *val;
969 if (lat->bottom)
970 return false;
972 for (val = lat->values; val; val = val->next)
973 if (values_equal_for_ipcp_p (val->value, newval))
975 if (ipa_edge_within_scc (cs))
977 struct ipcp_value_source *s;
978 for (s = val->sources; s ; s = s->next)
979 if (s->cs == cs)
980 break;
981 if (s)
982 return false;
985 add_value_source (val, cs, src_val, src_idx, offset);
986 return false;
989 if (lat->values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
991 /* We can only free sources, not the values themselves, because sources
992 of other values in this this SCC might point to them. */
993 for (val = lat->values; val; val = val->next)
995 while (val->sources)
997 struct ipcp_value_source *src = val->sources;
998 val->sources = src->next;
999 pool_free (ipcp_sources_pool, src);
1003 lat->values = NULL;
1004 return set_lattice_to_bottom (lat);
1007 lat->values_count++;
1008 val = (struct ipcp_value *) pool_alloc (ipcp_values_pool);
1009 memset (val, 0, sizeof (*val));
1011 add_value_source (val, cs, src_val, src_idx, offset);
1012 val->value = newval;
1013 val->next = lat->values;
1014 lat->values = val;
1015 return true;
1018 /* Like above but passes a special value of offset to distinguish that the
1019 origin is the scalar value of the parameter rather than a part of an
1020 aggregate. */
1022 static inline bool
1023 add_scalar_value_to_lattice (struct ipcp_lattice *lat, tree newval,
1024 struct cgraph_edge *cs,
1025 struct ipcp_value *src_val, int src_idx)
1027 return add_value_to_lattice (lat, newval, cs, src_val, src_idx, -1);
1030 /* Propagate values through a pass-through jump function JFUNC associated with
1031 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1032 is the index of the source parameter. */
1034 static bool
1035 propagate_vals_accross_pass_through (struct cgraph_edge *cs,
1036 struct ipa_jump_func *jfunc,
1037 struct ipcp_lattice *src_lat,
1038 struct ipcp_lattice *dest_lat,
1039 int src_idx)
1041 struct ipcp_value *src_val;
1042 bool ret = false;
1044 /* Do not create new values when propagating within an SCC because if there
1045 are arithmetic functions with circular dependencies, there is infinite
1046 number of them and we would just make lattices bottom. */
1047 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1048 && ipa_edge_within_scc (cs))
1049 ret = set_lattice_contains_variable (dest_lat);
1050 else
1051 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1053 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1055 if (cstval)
1056 ret |= add_scalar_value_to_lattice (dest_lat, cstval, cs, src_val,
1057 src_idx);
1058 else
1059 ret |= set_lattice_contains_variable (dest_lat);
1062 return ret;
1065 /* Propagate values through an ancestor jump function JFUNC associated with
1066 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1067 is the index of the source parameter. */
1069 static bool
1070 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1071 struct ipa_jump_func *jfunc,
1072 struct ipcp_lattice *src_lat,
1073 struct ipcp_lattice *dest_lat,
1074 int src_idx)
1076 struct ipcp_value *src_val;
1077 bool ret = false;
1079 if (ipa_edge_within_scc (cs))
1080 return set_lattice_contains_variable (dest_lat);
1082 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1084 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1086 if (t)
1087 ret |= add_scalar_value_to_lattice (dest_lat, t, cs, src_val, src_idx);
1088 else
1089 ret |= set_lattice_contains_variable (dest_lat);
1092 return ret;
1095 /* Propagate scalar values across jump function JFUNC that is associated with
1096 edge CS and put the values into DEST_LAT. */
1098 static bool
1099 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1100 struct ipa_jump_func *jfunc,
1101 struct ipcp_lattice *dest_lat)
1103 if (dest_lat->bottom)
1104 return false;
1106 if (jfunc->type == IPA_JF_CONST
1107 || jfunc->type == IPA_JF_KNOWN_TYPE)
1109 tree val;
1111 if (jfunc->type == IPA_JF_KNOWN_TYPE)
1113 val = ipa_binfo_from_known_type_jfunc (jfunc);
1114 if (!val)
1115 return set_lattice_contains_variable (dest_lat);
1117 else
1118 val = ipa_get_jf_constant (jfunc);
1119 return add_scalar_value_to_lattice (dest_lat, val, cs, NULL, 0);
1121 else if (jfunc->type == IPA_JF_PASS_THROUGH
1122 || jfunc->type == IPA_JF_ANCESTOR)
1124 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1125 struct ipcp_lattice *src_lat;
1126 int src_idx;
1127 bool ret;
1129 if (jfunc->type == IPA_JF_PASS_THROUGH)
1130 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1131 else
1132 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1134 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1135 if (src_lat->bottom)
1136 return set_lattice_contains_variable (dest_lat);
1138 /* If we would need to clone the caller and cannot, do not propagate. */
1139 if (!ipcp_versionable_function_p (cs->caller)
1140 && (src_lat->contains_variable
1141 || (src_lat->values_count > 1)))
1142 return set_lattice_contains_variable (dest_lat);
1144 if (jfunc->type == IPA_JF_PASS_THROUGH)
1145 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1146 dest_lat, src_idx);
1147 else
1148 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1149 src_idx);
1151 if (src_lat->contains_variable)
1152 ret |= set_lattice_contains_variable (dest_lat);
1154 return ret;
1157 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1158 use it for indirect inlining), we should propagate them too. */
1159 return set_lattice_contains_variable (dest_lat);
1162 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1163 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1164 other cases, return false). If there are no aggregate items, set
1165 aggs_by_ref to NEW_AGGS_BY_REF. */
1167 static bool
1168 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1169 bool new_aggs_by_ref)
1171 if (dest_plats->aggs)
1173 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1175 set_agg_lats_to_bottom (dest_plats);
1176 return true;
1179 else
1180 dest_plats->aggs_by_ref = new_aggs_by_ref;
1181 return false;
1184 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1185 already existing lattice for the given OFFSET and SIZE, marking all skipped
1186 lattices as containing variable and checking for overlaps. If there is no
1187 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1188 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1189 unless there are too many already. If there are two many, return false. If
1190 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1191 skipped lattices were newly marked as containing variable, set *CHANGE to
1192 true. */
1194 static bool
1195 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1196 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1197 struct ipcp_agg_lattice ***aglat,
1198 bool pre_existing, bool *change)
1200 gcc_checking_assert (offset >= 0);
1202 while (**aglat && (**aglat)->offset < offset)
1204 if ((**aglat)->offset + (**aglat)->size > offset)
1206 set_agg_lats_to_bottom (dest_plats);
1207 return false;
1209 *change |= set_lattice_contains_variable (**aglat);
1210 *aglat = &(**aglat)->next;
1213 if (**aglat && (**aglat)->offset == offset)
1215 if ((**aglat)->size != val_size
1216 || ((**aglat)->next
1217 && (**aglat)->next->offset < offset + val_size))
1219 set_agg_lats_to_bottom (dest_plats);
1220 return false;
1222 gcc_checking_assert (!(**aglat)->next
1223 || (**aglat)->next->offset >= offset + val_size);
1224 return true;
1226 else
1228 struct ipcp_agg_lattice *new_al;
1230 if (**aglat && (**aglat)->offset < offset + val_size)
1232 set_agg_lats_to_bottom (dest_plats);
1233 return false;
1235 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1236 return false;
1237 dest_plats->aggs_count++;
1238 new_al = (struct ipcp_agg_lattice *) pool_alloc (ipcp_agg_lattice_pool);
1239 memset (new_al, 0, sizeof (*new_al));
1241 new_al->offset = offset;
1242 new_al->size = val_size;
1243 new_al->contains_variable = pre_existing;
1245 new_al->next = **aglat;
1246 **aglat = new_al;
1247 return true;
1251 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1252 containing an unknown value. */
1254 static bool
1255 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1257 bool ret = false;
1258 while (aglat)
1260 ret |= set_lattice_contains_variable (aglat);
1261 aglat = aglat->next;
1263 return ret;
1266 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1267 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1268 parameter used for lattice value sources. Return true if DEST_PLATS changed
1269 in any way. */
1271 static bool
1272 merge_aggregate_lattices (struct cgraph_edge *cs,
1273 struct ipcp_param_lattices *dest_plats,
1274 struct ipcp_param_lattices *src_plats,
1275 int src_idx, HOST_WIDE_INT offset_delta)
1277 bool pre_existing = dest_plats->aggs != NULL;
1278 struct ipcp_agg_lattice **dst_aglat;
1279 bool ret = false;
1281 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1282 return true;
1283 if (src_plats->aggs_bottom)
1284 return set_agg_lats_contain_variable (dest_plats);
1285 if (src_plats->aggs_contain_variable)
1286 ret |= set_agg_lats_contain_variable (dest_plats);
1287 dst_aglat = &dest_plats->aggs;
1289 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1290 src_aglat;
1291 src_aglat = src_aglat->next)
1293 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1295 if (new_offset < 0)
1296 continue;
1297 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1298 &dst_aglat, pre_existing, &ret))
1300 struct ipcp_agg_lattice *new_al = *dst_aglat;
1302 dst_aglat = &(*dst_aglat)->next;
1303 if (src_aglat->bottom)
1305 ret |= set_lattice_contains_variable (new_al);
1306 continue;
1308 if (src_aglat->contains_variable)
1309 ret |= set_lattice_contains_variable (new_al);
1310 for (struct ipcp_value *val = src_aglat->values;
1311 val;
1312 val = val->next)
1313 ret |= add_value_to_lattice (new_al, val->value, cs, val, src_idx,
1314 src_aglat->offset);
1316 else if (dest_plats->aggs_bottom)
1317 return true;
1319 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1320 return ret;
1323 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1324 pass-through JFUNC and if so, whether it has conform and conforms to the
1325 rules about propagating values passed by reference. */
1327 static bool
1328 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1329 struct ipa_jump_func *jfunc)
1331 return src_plats->aggs
1332 && (!src_plats->aggs_by_ref
1333 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1336 /* Propagate scalar values across jump function JFUNC that is associated with
1337 edge CS and put the values into DEST_LAT. */
1339 static bool
1340 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1341 struct ipa_jump_func *jfunc,
1342 struct ipcp_param_lattices *dest_plats)
1344 bool ret = false;
1346 if (dest_plats->aggs_bottom)
1347 return false;
1349 if (jfunc->type == IPA_JF_PASS_THROUGH
1350 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1352 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1353 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1354 struct ipcp_param_lattices *src_plats;
1356 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1357 if (agg_pass_through_permissible_p (src_plats, jfunc))
1359 /* Currently we do not produce clobber aggregate jump
1360 functions, replace with merging when we do. */
1361 gcc_assert (!jfunc->agg.items);
1362 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1363 src_idx, 0);
1365 else
1366 ret |= set_agg_lats_contain_variable (dest_plats);
1368 else if (jfunc->type == IPA_JF_ANCESTOR
1369 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1371 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1372 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1373 struct ipcp_param_lattices *src_plats;
1375 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1376 if (src_plats->aggs && src_plats->aggs_by_ref)
1378 /* Currently we do not produce clobber aggregate jump
1379 functions, replace with merging when we do. */
1380 gcc_assert (!jfunc->agg.items);
1381 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1382 ipa_get_jf_ancestor_offset (jfunc));
1384 else if (!src_plats->aggs_by_ref)
1385 ret |= set_agg_lats_to_bottom (dest_plats);
1386 else
1387 ret |= set_agg_lats_contain_variable (dest_plats);
1389 else if (jfunc->agg.items)
1391 bool pre_existing = dest_plats->aggs != NULL;
1392 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1393 struct ipa_agg_jf_item *item;
1394 int i;
1396 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1397 return true;
1399 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1401 HOST_WIDE_INT val_size;
1403 if (item->offset < 0)
1404 continue;
1405 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1406 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
1408 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1409 &aglat, pre_existing, &ret))
1411 ret |= add_value_to_lattice (*aglat, item->value, cs, NULL, 0, 0);
1412 aglat = &(*aglat)->next;
1414 else if (dest_plats->aggs_bottom)
1415 return true;
1418 ret |= set_chain_of_aglats_contains_variable (*aglat);
1420 else
1421 ret |= set_agg_lats_contain_variable (dest_plats);
1423 return ret;
1426 /* Propagate constants from the caller to the callee of CS. INFO describes the
1427 caller. */
1429 static bool
1430 propagate_constants_accross_call (struct cgraph_edge *cs)
1432 struct ipa_node_params *callee_info;
1433 enum availability availability;
1434 struct cgraph_node *callee, *alias_or_thunk;
1435 struct ipa_edge_args *args;
1436 bool ret = false;
1437 int i, args_count, parms_count;
1439 callee = cs->callee->function_symbol (&availability);
1440 if (!callee->definition)
1441 return false;
1442 gcc_checking_assert (callee->has_gimple_body_p ());
1443 callee_info = IPA_NODE_REF (callee);
1445 args = IPA_EDGE_REF (cs);
1446 args_count = ipa_get_cs_argument_count (args);
1447 parms_count = ipa_get_param_count (callee_info);
1448 if (parms_count == 0)
1449 return false;
1451 /* If this call goes through a thunk we must not propagate to the first (0th)
1452 parameter. However, we might need to uncover a thunk from below a series
1453 of aliases first. */
1454 alias_or_thunk = cs->callee;
1455 while (alias_or_thunk->alias)
1456 alias_or_thunk = alias_or_thunk->get_alias_target ();
1457 if (alias_or_thunk->thunk.thunk_p)
1459 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1460 0));
1461 i = 1;
1463 else
1464 i = 0;
1466 for (; (i < args_count) && (i < parms_count); i++)
1468 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1469 struct ipcp_param_lattices *dest_plats;
1471 dest_plats = ipa_get_parm_lattices (callee_info, i);
1472 if (availability == AVAIL_INTERPOSABLE)
1473 ret |= set_all_contains_variable (dest_plats);
1474 else
1476 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1477 &dest_plats->itself);
1478 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1479 dest_plats);
1482 for (; i < parms_count; i++)
1483 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1485 return ret;
1488 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1489 (which can contain both constants and binfos), KNOWN_BINFOS, KNOWN_AGGS or
1490 AGG_REPS return the destination. The latter three can be NULL. If AGG_REPS
1491 is not NULL, KNOWN_AGGS is ignored. */
1493 static tree
1494 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
1495 vec<tree> known_vals,
1496 vec<tree> known_binfos,
1497 vec<ipa_agg_jump_function_p> known_aggs,
1498 struct ipa_agg_replacement_value *agg_reps)
1500 int param_index = ie->indirect_info->param_index;
1501 HOST_WIDE_INT token, anc_offset;
1502 tree otr_type;
1503 tree t;
1504 tree target = NULL;
1506 if (param_index == -1
1507 || known_vals.length () <= (unsigned int) param_index)
1508 return NULL_TREE;
1510 if (!ie->indirect_info->polymorphic)
1512 tree t;
1514 if (ie->indirect_info->agg_contents)
1516 if (agg_reps)
1518 t = NULL;
1519 while (agg_reps)
1521 if (agg_reps->index == param_index
1522 && agg_reps->offset == ie->indirect_info->offset
1523 && agg_reps->by_ref == ie->indirect_info->by_ref)
1525 t = agg_reps->value;
1526 break;
1528 agg_reps = agg_reps->next;
1531 else if (known_aggs.length () > (unsigned int) param_index)
1533 struct ipa_agg_jump_function *agg;
1534 agg = known_aggs[param_index];
1535 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1536 ie->indirect_info->by_ref);
1538 else
1539 t = NULL;
1541 else
1542 t = known_vals[param_index];
1544 if (t &&
1545 TREE_CODE (t) == ADDR_EXPR
1546 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1547 return TREE_OPERAND (t, 0);
1548 else
1549 return NULL_TREE;
1552 if (!flag_devirtualize)
1553 return NULL_TREE;
1555 gcc_assert (!ie->indirect_info->agg_contents);
1556 token = ie->indirect_info->otr_token;
1557 anc_offset = ie->indirect_info->offset;
1558 otr_type = ie->indirect_info->otr_type;
1560 t = NULL;
1562 /* Try to work out value of virtual table pointer value in replacemnets. */
1563 if (!t && agg_reps && !ie->indirect_info->by_ref)
1565 while (agg_reps)
1567 if (agg_reps->index == param_index
1568 && agg_reps->offset == ie->indirect_info->offset
1569 && agg_reps->by_ref)
1571 t = agg_reps->value;
1572 break;
1574 agg_reps = agg_reps->next;
1578 /* Try to work out value of virtual table pointer value in known
1579 aggregate values. */
1580 if (!t && known_aggs.length () > (unsigned int) param_index
1581 && !ie->indirect_info->by_ref)
1583 struct ipa_agg_jump_function *agg;
1584 agg = known_aggs[param_index];
1585 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1586 true);
1589 /* If we found the virtual table pointer, lookup the target. */
1590 if (t)
1592 tree vtable;
1593 unsigned HOST_WIDE_INT offset;
1594 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
1596 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
1597 vtable, offset);
1598 if (target)
1600 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1601 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1602 || !possible_polymorphic_call_target_p
1603 (ie, cgraph_node::get (target)))
1604 target = ipa_impossible_devirt_target (ie, target);
1605 return target;
1610 /* Did we work out BINFO via type propagation? */
1611 if (!t && known_binfos.length () > (unsigned int) param_index)
1612 t = known_binfos[param_index];
1613 /* Or do we know the constant value of pointer? */
1614 if (!t)
1615 t = known_vals[param_index];
1616 if (!t)
1617 return NULL_TREE;
1619 if (TREE_CODE (t) != TREE_BINFO)
1621 ipa_polymorphic_call_context context;
1622 vec <cgraph_node *>targets;
1623 bool final;
1625 if (!get_polymorphic_call_info_from_invariant
1626 (&context, t, ie->indirect_info->otr_type,
1627 anc_offset))
1628 return NULL_TREE;
1629 targets = possible_polymorphic_call_targets
1630 (ie->indirect_info->otr_type,
1631 ie->indirect_info->otr_token,
1632 context, &final);
1633 if (!final || targets.length () > 1)
1634 return NULL_TREE;
1635 if (targets.length () == 1)
1636 target = targets[0]->decl;
1637 else
1638 target = ipa_impossible_devirt_target (ie, NULL_TREE);
1640 else
1642 tree binfo;
1644 binfo = get_binfo_at_offset (t, anc_offset, otr_type);
1645 if (!binfo)
1646 return NULL_TREE;
1647 target = gimple_get_virt_method_for_binfo (token, binfo);
1650 if (target && !possible_polymorphic_call_target_p (ie,
1651 cgraph_node::get (target)))
1652 target = ipa_impossible_devirt_target (ie, target);
1654 return target;
1658 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1659 (which can contain both constants and binfos), KNOWN_BINFOS (which can be
1660 NULL) or KNOWN_AGGS (which also can be NULL) return the destination. */
1662 tree
1663 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
1664 vec<tree> known_vals,
1665 vec<tree> known_binfos,
1666 vec<ipa_agg_jump_function_p> known_aggs)
1668 return ipa_get_indirect_edge_target_1 (ie, known_vals, known_binfos,
1669 known_aggs, NULL);
1672 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
1673 and KNOWN_BINFOS. */
1675 static int
1676 devirtualization_time_bonus (struct cgraph_node *node,
1677 vec<tree> known_csts,
1678 vec<tree> known_binfos,
1679 vec<ipa_agg_jump_function_p> known_aggs)
1681 struct cgraph_edge *ie;
1682 int res = 0;
1684 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1686 struct cgraph_node *callee;
1687 struct inline_summary *isummary;
1688 enum availability avail;
1689 tree target;
1691 target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos,
1692 known_aggs);
1693 if (!target)
1694 continue;
1696 /* Only bare minimum benefit for clearly un-inlineable targets. */
1697 res += 1;
1698 callee = cgraph_node::get (target);
1699 if (!callee || !callee->definition)
1700 continue;
1701 callee = callee->function_symbol (&avail);
1702 if (avail < AVAIL_AVAILABLE)
1703 continue;
1704 isummary = inline_summary (callee);
1705 if (!isummary->inlinable)
1706 continue;
1708 /* FIXME: The values below need re-considering and perhaps also
1709 integrating into the cost metrics, at lest in some very basic way. */
1710 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
1711 res += 31;
1712 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
1713 res += 15;
1714 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
1715 || DECL_DECLARED_INLINE_P (callee->decl))
1716 res += 7;
1719 return res;
1722 /* Return time bonus incurred because of HINTS. */
1724 static int
1725 hint_time_bonus (inline_hints hints)
1727 int result = 0;
1728 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
1729 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
1730 if (hints & INLINE_HINT_array_index)
1731 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
1732 return result;
1735 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
1736 and SIZE_COST and with the sum of frequencies of incoming edges to the
1737 potential new clone in FREQUENCIES. */
1739 static bool
1740 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
1741 int freq_sum, gcov_type count_sum, int size_cost)
1743 if (time_benefit == 0
1744 || !flag_ipa_cp_clone
1745 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
1746 return false;
1748 gcc_assert (size_cost > 0);
1750 if (max_count)
1752 int factor = (count_sum * 1000) / max_count;
1753 int64_t evaluation = (((int64_t) time_benefit * factor)
1754 / size_cost);
1756 if (dump_file && (dump_flags & TDF_DETAILS))
1757 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
1758 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
1759 ") -> evaluation: " "%"PRId64
1760 ", threshold: %i\n",
1761 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
1762 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
1764 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
1766 else
1768 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
1769 / size_cost);
1771 if (dump_file && (dump_flags & TDF_DETAILS))
1772 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
1773 "size: %i, freq_sum: %i) -> evaluation: "
1774 "%"PRId64 ", threshold: %i\n",
1775 time_benefit, size_cost, freq_sum, evaluation,
1776 PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
1778 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
1782 /* Return all context independent values from aggregate lattices in PLATS in a
1783 vector. Return NULL if there are none. */
1785 static vec<ipa_agg_jf_item, va_gc> *
1786 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
1788 vec<ipa_agg_jf_item, va_gc> *res = NULL;
1790 if (plats->aggs_bottom
1791 || plats->aggs_contain_variable
1792 || plats->aggs_count == 0)
1793 return NULL;
1795 for (struct ipcp_agg_lattice *aglat = plats->aggs;
1796 aglat;
1797 aglat = aglat->next)
1798 if (ipa_lat_is_single_const (aglat))
1800 struct ipa_agg_jf_item item;
1801 item.offset = aglat->offset;
1802 item.value = aglat->values->value;
1803 vec_safe_push (res, item);
1805 return res;
1808 /* Allocate KNOWN_CSTS, KNOWN_BINFOS and, if non-NULL, KNOWN_AGGS and populate
1809 them with values of parameters that are known independent of the context.
1810 INFO describes the function. If REMOVABLE_PARAMS_COST is non-NULL, the
1811 movement cost of all removable parameters will be stored in it. */
1813 static bool
1814 gather_context_independent_values (struct ipa_node_params *info,
1815 vec<tree> *known_csts,
1816 vec<tree> *known_binfos,
1817 vec<ipa_agg_jump_function> *known_aggs,
1818 int *removable_params_cost)
1820 int i, count = ipa_get_param_count (info);
1821 bool ret = false;
1823 known_csts->create (0);
1824 known_binfos->create (0);
1825 known_csts->safe_grow_cleared (count);
1826 known_binfos->safe_grow_cleared (count);
1827 if (known_aggs)
1829 known_aggs->create (0);
1830 known_aggs->safe_grow_cleared (count);
1833 if (removable_params_cost)
1834 *removable_params_cost = 0;
1836 for (i = 0; i < count ; i++)
1838 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1839 struct ipcp_lattice *lat = &plats->itself;
1841 if (ipa_lat_is_single_const (lat))
1843 struct ipcp_value *val = lat->values;
1844 if (TREE_CODE (val->value) != TREE_BINFO)
1846 (*known_csts)[i] = val->value;
1847 if (removable_params_cost)
1848 *removable_params_cost
1849 += estimate_move_cost (TREE_TYPE (val->value), false);
1850 ret = true;
1852 else if (plats->virt_call)
1854 (*known_binfos)[i] = val->value;
1855 ret = true;
1857 else if (removable_params_cost
1858 && !ipa_is_param_used (info, i))
1859 *removable_params_cost += ipa_get_param_move_cost (info, i);
1861 else if (removable_params_cost
1862 && !ipa_is_param_used (info, i))
1863 *removable_params_cost
1864 += ipa_get_param_move_cost (info, i);
1866 if (known_aggs)
1868 vec<ipa_agg_jf_item, va_gc> *agg_items;
1869 struct ipa_agg_jump_function *ajf;
1871 agg_items = context_independent_aggregate_values (plats);
1872 ajf = &(*known_aggs)[i];
1873 ajf->items = agg_items;
1874 ajf->by_ref = plats->aggs_by_ref;
1875 ret |= agg_items != NULL;
1879 return ret;
1882 /* The current interface in ipa-inline-analysis requires a pointer vector.
1883 Create it.
1885 FIXME: That interface should be re-worked, this is slightly silly. Still,
1886 I'd like to discuss how to change it first and this demonstrates the
1887 issue. */
1889 static vec<ipa_agg_jump_function_p>
1890 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
1892 vec<ipa_agg_jump_function_p> ret;
1893 struct ipa_agg_jump_function *ajf;
1894 int i;
1896 ret.create (known_aggs.length ());
1897 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
1898 ret.quick_push (ajf);
1899 return ret;
1902 /* Iterate over known values of parameters of NODE and estimate the local
1903 effects in terms of time and size they have. */
1905 static void
1906 estimate_local_effects (struct cgraph_node *node)
1908 struct ipa_node_params *info = IPA_NODE_REF (node);
1909 int i, count = ipa_get_param_count (info);
1910 vec<tree> known_csts, known_binfos;
1911 vec<ipa_agg_jump_function> known_aggs;
1912 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
1913 bool always_const;
1914 int base_time = inline_summary (node)->time;
1915 int removable_params_cost;
1917 if (!count || !ipcp_versionable_function_p (node))
1918 return;
1920 if (dump_file && (dump_flags & TDF_DETAILS))
1921 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
1922 node->name (), node->order, base_time);
1924 always_const = gather_context_independent_values (info, &known_csts,
1925 &known_binfos, &known_aggs,
1926 &removable_params_cost);
1927 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
1928 if (always_const)
1930 struct caller_statistics stats;
1931 inline_hints hints;
1932 int time, size;
1934 init_caller_stats (&stats);
1935 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
1936 false);
1937 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
1938 known_aggs_ptrs, &size, &time, &hints);
1939 time -= devirtualization_time_bonus (node, known_csts, known_binfos,
1940 known_aggs_ptrs);
1941 time -= hint_time_bonus (hints);
1942 time -= removable_params_cost;
1943 size -= stats.n_calls * removable_params_cost;
1945 if (dump_file)
1946 fprintf (dump_file, " - context independent values, size: %i, "
1947 "time_benefit: %i\n", size, base_time - time);
1949 if (size <= 0
1950 || node->will_be_removed_from_program_if_no_direct_calls_p ())
1952 info->do_clone_for_all_contexts = true;
1953 base_time = time;
1955 if (dump_file)
1956 fprintf (dump_file, " Decided to specialize for all "
1957 "known contexts, code not going to grow.\n");
1959 else if (good_cloning_opportunity_p (node, base_time - time,
1960 stats.freq_sum, stats.count_sum,
1961 size))
1963 if (size + overall_size <= max_new_size)
1965 info->do_clone_for_all_contexts = true;
1966 base_time = time;
1967 overall_size += size;
1969 if (dump_file)
1970 fprintf (dump_file, " Decided to specialize for all "
1971 "known contexts, growth deemed beneficial.\n");
1973 else if (dump_file && (dump_flags & TDF_DETAILS))
1974 fprintf (dump_file, " Not cloning for all contexts because "
1975 "max_new_size would be reached with %li.\n",
1976 size + overall_size);
1980 for (i = 0; i < count ; i++)
1982 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1983 struct ipcp_lattice *lat = &plats->itself;
1984 struct ipcp_value *val;
1985 int emc;
1987 if (lat->bottom
1988 || !lat->values
1989 || known_csts[i]
1990 || known_binfos[i])
1991 continue;
1993 for (val = lat->values; val; val = val->next)
1995 int time, size, time_benefit;
1996 inline_hints hints;
1998 if (TREE_CODE (val->value) != TREE_BINFO)
2000 known_csts[i] = val->value;
2001 known_binfos[i] = NULL_TREE;
2002 emc = estimate_move_cost (TREE_TYPE (val->value), true);
2004 else if (plats->virt_call)
2006 known_csts[i] = NULL_TREE;
2007 known_binfos[i] = val->value;
2008 emc = 0;
2010 else
2011 continue;
2013 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
2014 known_aggs_ptrs, &size, &time,
2015 &hints);
2016 time_benefit = base_time - time
2017 + devirtualization_time_bonus (node, known_csts, known_binfos,
2018 known_aggs_ptrs)
2019 + hint_time_bonus (hints)
2020 + removable_params_cost + emc;
2022 gcc_checking_assert (size >=0);
2023 /* The inliner-heuristics based estimates may think that in certain
2024 contexts some functions do not have any size at all but we want
2025 all specializations to have at least a tiny cost, not least not to
2026 divide by zero. */
2027 if (size == 0)
2028 size = 1;
2030 if (dump_file && (dump_flags & TDF_DETAILS))
2032 fprintf (dump_file, " - estimates for value ");
2033 print_ipcp_constant_value (dump_file, val->value);
2034 fprintf (dump_file, " for ");
2035 ipa_dump_param (dump_file, info, i);
2036 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2037 time_benefit, size);
2040 val->local_time_benefit = time_benefit;
2041 val->local_size_cost = size;
2043 known_binfos[i] = NULL_TREE;
2044 known_csts[i] = NULL_TREE;
2047 for (i = 0; i < count ; i++)
2049 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2050 struct ipa_agg_jump_function *ajf;
2051 struct ipcp_agg_lattice *aglat;
2053 if (plats->aggs_bottom || !plats->aggs)
2054 continue;
2056 ajf = &known_aggs[i];
2057 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2059 struct ipcp_value *val;
2060 if (aglat->bottom || !aglat->values
2061 /* If the following is true, the one value is in known_aggs. */
2062 || (!plats->aggs_contain_variable
2063 && ipa_lat_is_single_const (aglat)))
2064 continue;
2066 for (val = aglat->values; val; val = val->next)
2068 int time, size, time_benefit;
2069 struct ipa_agg_jf_item item;
2070 inline_hints hints;
2072 item.offset = aglat->offset;
2073 item.value = val->value;
2074 vec_safe_push (ajf->items, item);
2076 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
2077 known_aggs_ptrs, &size, &time,
2078 &hints);
2079 time_benefit = base_time - time
2080 + devirtualization_time_bonus (node, known_csts, known_binfos,
2081 known_aggs_ptrs)
2082 + hint_time_bonus (hints);
2083 gcc_checking_assert (size >=0);
2084 if (size == 0)
2085 size = 1;
2087 if (dump_file && (dump_flags & TDF_DETAILS))
2089 fprintf (dump_file, " - estimates for value ");
2090 print_ipcp_constant_value (dump_file, val->value);
2091 fprintf (dump_file, " for ");
2092 ipa_dump_param (dump_file, info, i);
2093 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2094 "]: time_benefit: %i, size: %i\n",
2095 plats->aggs_by_ref ? "ref " : "",
2096 aglat->offset, time_benefit, size);
2099 val->local_time_benefit = time_benefit;
2100 val->local_size_cost = size;
2101 ajf->items->pop ();
2106 for (i = 0; i < count ; i++)
2107 vec_free (known_aggs[i].items);
2109 known_csts.release ();
2110 known_binfos.release ();
2111 known_aggs.release ();
2112 known_aggs_ptrs.release ();
2116 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2117 topological sort of values. */
2119 static void
2120 add_val_to_toposort (struct ipcp_value *cur_val)
2122 static int dfs_counter = 0;
2123 static struct ipcp_value *stack;
2124 struct ipcp_value_source *src;
2126 if (cur_val->dfs)
2127 return;
2129 dfs_counter++;
2130 cur_val->dfs = dfs_counter;
2131 cur_val->low_link = dfs_counter;
2133 cur_val->topo_next = stack;
2134 stack = cur_val;
2135 cur_val->on_stack = true;
2137 for (src = cur_val->sources; src; src = src->next)
2138 if (src->val)
2140 if (src->val->dfs == 0)
2142 add_val_to_toposort (src->val);
2143 if (src->val->low_link < cur_val->low_link)
2144 cur_val->low_link = src->val->low_link;
2146 else if (src->val->on_stack
2147 && src->val->dfs < cur_val->low_link)
2148 cur_val->low_link = src->val->dfs;
2151 if (cur_val->dfs == cur_val->low_link)
2153 struct ipcp_value *v, *scc_list = NULL;
2157 v = stack;
2158 stack = v->topo_next;
2159 v->on_stack = false;
2161 v->scc_next = scc_list;
2162 scc_list = v;
2164 while (v != cur_val);
2166 cur_val->topo_next = values_topo;
2167 values_topo = cur_val;
2171 /* Add all values in lattices associated with NODE to the topological sort if
2172 they are not there yet. */
2174 static void
2175 add_all_node_vals_to_toposort (struct cgraph_node *node)
2177 struct ipa_node_params *info = IPA_NODE_REF (node);
2178 int i, count = ipa_get_param_count (info);
2180 for (i = 0; i < count ; i++)
2182 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2183 struct ipcp_lattice *lat = &plats->itself;
2184 struct ipcp_agg_lattice *aglat;
2185 struct ipcp_value *val;
2187 if (!lat->bottom)
2188 for (val = lat->values; val; val = val->next)
2189 add_val_to_toposort (val);
2191 if (!plats->aggs_bottom)
2192 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2193 if (!aglat->bottom)
2194 for (val = aglat->values; val; val = val->next)
2195 add_val_to_toposort (val);
2199 /* One pass of constants propagation along the call graph edges, from callers
2200 to callees (requires topological ordering in TOPO), iterate over strongly
2201 connected components. */
2203 static void
2204 propagate_constants_topo (struct topo_info *topo)
2206 int i;
2208 for (i = topo->nnodes - 1; i >= 0; i--)
2210 unsigned j;
2211 struct cgraph_node *v, *node = topo->order[i];
2212 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
2214 /* First, iteratively propagate within the strongly connected component
2215 until all lattices stabilize. */
2216 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2217 if (v->has_gimple_body_p ())
2218 push_node_to_stack (topo, v);
2220 v = pop_node_from_stack (topo);
2221 while (v)
2223 struct cgraph_edge *cs;
2225 for (cs = v->callees; cs; cs = cs->next_callee)
2226 if (ipa_edge_within_scc (cs)
2227 && propagate_constants_accross_call (cs))
2228 push_node_to_stack (topo, cs->callee);
2229 v = pop_node_from_stack (topo);
2232 /* Afterwards, propagate along edges leading out of the SCC, calculates
2233 the local effects of the discovered constants and all valid values to
2234 their topological sort. */
2235 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2236 if (v->has_gimple_body_p ())
2238 struct cgraph_edge *cs;
2240 estimate_local_effects (v);
2241 add_all_node_vals_to_toposort (v);
2242 for (cs = v->callees; cs; cs = cs->next_callee)
2243 if (!ipa_edge_within_scc (cs))
2244 propagate_constants_accross_call (cs);
2246 cycle_nodes.release ();
2251 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2252 the bigger one if otherwise. */
2254 static int
2255 safe_add (int a, int b)
2257 if (a > INT_MAX/2 || b > INT_MAX/2)
2258 return a > b ? a : b;
2259 else
2260 return a + b;
2264 /* Propagate the estimated effects of individual values along the topological
2265 from the dependent values to those they depend on. */
2267 static void
2268 propagate_effects (void)
2270 struct ipcp_value *base;
2272 for (base = values_topo; base; base = base->topo_next)
2274 struct ipcp_value_source *src;
2275 struct ipcp_value *val;
2276 int time = 0, size = 0;
2278 for (val = base; val; val = val->scc_next)
2280 time = safe_add (time,
2281 val->local_time_benefit + val->prop_time_benefit);
2282 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2285 for (val = base; val; val = val->scc_next)
2286 for (src = val->sources; src; src = src->next)
2287 if (src->val
2288 && src->cs->maybe_hot_p ())
2290 src->val->prop_time_benefit = safe_add (time,
2291 src->val->prop_time_benefit);
2292 src->val->prop_size_cost = safe_add (size,
2293 src->val->prop_size_cost);
2299 /* Propagate constants, binfos and their effects from the summaries
2300 interprocedurally. */
2302 static void
2303 ipcp_propagate_stage (struct topo_info *topo)
2305 struct cgraph_node *node;
2307 if (dump_file)
2308 fprintf (dump_file, "\n Propagating constants:\n\n");
2310 if (in_lto_p)
2311 ipa_update_after_lto_read ();
2314 FOR_EACH_DEFINED_FUNCTION (node)
2316 struct ipa_node_params *info = IPA_NODE_REF (node);
2318 determine_versionability (node);
2319 if (node->has_gimple_body_p ())
2321 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2322 ipa_get_param_count (info));
2323 initialize_node_lattices (node);
2325 if (node->definition && !node->alias)
2326 overall_size += inline_summary (node)->self_size;
2327 if (node->count > max_count)
2328 max_count = node->count;
2331 max_new_size = overall_size;
2332 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2333 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2334 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2336 if (dump_file)
2337 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2338 overall_size, max_new_size);
2340 propagate_constants_topo (topo);
2341 #ifdef ENABLE_CHECKING
2342 ipcp_verify_propagated_values ();
2343 #endif
2344 propagate_effects ();
2346 if (dump_file)
2348 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2349 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2353 /* Discover newly direct outgoing edges from NODE which is a new clone with
2354 known KNOWN_VALS and make them direct. */
2356 static void
2357 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2358 vec<tree> known_vals,
2359 struct ipa_agg_replacement_value *aggvals)
2361 struct cgraph_edge *ie, *next_ie;
2362 bool found = false;
2364 for (ie = node->indirect_calls; ie; ie = next_ie)
2366 tree target;
2368 next_ie = ie->next_callee;
2369 target = ipa_get_indirect_edge_target_1 (ie, known_vals, vNULL, vNULL,
2370 aggvals);
2371 if (target)
2373 bool agg_contents = ie->indirect_info->agg_contents;
2374 bool polymorphic = ie->indirect_info->polymorphic;
2375 int param_index = ie->indirect_info->param_index;
2376 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target);
2377 found = true;
2379 if (cs && !agg_contents && !polymorphic)
2381 struct ipa_node_params *info = IPA_NODE_REF (node);
2382 int c = ipa_get_controlled_uses (info, param_index);
2383 if (c != IPA_UNDESCRIBED_USE)
2385 struct ipa_ref *to_del;
2387 c--;
2388 ipa_set_controlled_uses (info, param_index, c);
2389 if (dump_file && (dump_flags & TDF_DETAILS))
2390 fprintf (dump_file, " controlled uses count of param "
2391 "%i bumped down to %i\n", param_index, c);
2392 if (c == 0
2393 && (to_del = node->find_reference (cs->callee, NULL, 0)))
2395 if (dump_file && (dump_flags & TDF_DETAILS))
2396 fprintf (dump_file, " and even removing its "
2397 "cloning-created reference\n");
2398 to_del->remove_reference ();
2404 /* Turning calls to direct calls will improve overall summary. */
2405 if (found)
2406 inline_update_overall_summary (node);
2409 /* Vector of pointers which for linked lists of clones of an original crgaph
2410 edge. */
2412 static vec<cgraph_edge *> next_edge_clone;
2413 static vec<cgraph_edge *> prev_edge_clone;
2415 static inline void
2416 grow_edge_clone_vectors (void)
2418 if (next_edge_clone.length ()
2419 <= (unsigned) symtab->edges_max_uid)
2420 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2421 if (prev_edge_clone.length ()
2422 <= (unsigned) symtab->edges_max_uid)
2423 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2426 /* Edge duplication hook to grow the appropriate linked list in
2427 next_edge_clone. */
2429 static void
2430 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2431 void *)
2433 grow_edge_clone_vectors ();
2435 struct cgraph_edge *old_next = next_edge_clone[src->uid];
2436 if (old_next)
2437 prev_edge_clone[old_next->uid] = dst;
2438 prev_edge_clone[dst->uid] = src;
2440 next_edge_clone[dst->uid] = old_next;
2441 next_edge_clone[src->uid] = dst;
2444 /* Hook that is called by cgraph.c when an edge is removed. */
2446 static void
2447 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
2449 grow_edge_clone_vectors ();
2451 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
2452 struct cgraph_edge *next = next_edge_clone[cs->uid];
2453 if (prev)
2454 next_edge_clone[prev->uid] = next;
2455 if (next)
2456 prev_edge_clone[next->uid] = prev;
2459 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2460 parameter with the given INDEX. */
2462 static tree
2463 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2464 int index)
2466 struct ipa_agg_replacement_value *aggval;
2468 aggval = ipa_get_agg_replacements_for_node (node);
2469 while (aggval)
2471 if (aggval->offset == offset
2472 && aggval->index == index)
2473 return aggval->value;
2474 aggval = aggval->next;
2476 return NULL_TREE;
2479 /* Return true if edge CS does bring about the value described by SRC. */
2481 static bool
2482 cgraph_edge_brings_value_p (struct cgraph_edge *cs,
2483 struct ipcp_value_source *src)
2485 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2486 cgraph_node *real_dest = cs->callee->function_symbol ();
2487 struct ipa_node_params *dst_info = IPA_NODE_REF (real_dest);
2489 if ((dst_info->ipcp_orig_node && !dst_info->is_all_contexts_clone)
2490 || caller_info->node_dead)
2491 return false;
2492 if (!src->val)
2493 return true;
2495 if (caller_info->ipcp_orig_node)
2497 tree t;
2498 if (src->offset == -1)
2499 t = caller_info->known_vals[src->index];
2500 else
2501 t = get_clone_agg_value (cs->caller, src->offset, src->index);
2502 return (t != NULL_TREE
2503 && values_equal_for_ipcp_p (src->val->value, t));
2505 else
2507 struct ipcp_agg_lattice *aglat;
2508 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
2509 src->index);
2510 if (src->offset == -1)
2511 return (ipa_lat_is_single_const (&plats->itself)
2512 && values_equal_for_ipcp_p (src->val->value,
2513 plats->itself.values->value));
2514 else
2516 if (plats->aggs_bottom || plats->aggs_contain_variable)
2517 return false;
2518 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2519 if (aglat->offset == src->offset)
2520 return (ipa_lat_is_single_const (aglat)
2521 && values_equal_for_ipcp_p (src->val->value,
2522 aglat->values->value));
2524 return false;
2528 /* Get the next clone in the linked list of clones of an edge. */
2530 static inline struct cgraph_edge *
2531 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
2533 return next_edge_clone[cs->uid];
2536 /* Given VAL, iterate over all its sources and if they still hold, add their
2537 edge frequency and their number into *FREQUENCY and *CALLER_COUNT
2538 respectively. */
2540 static bool
2541 get_info_about_necessary_edges (struct ipcp_value *val, int *freq_sum,
2542 gcov_type *count_sum, int *caller_count)
2544 struct ipcp_value_source *src;
2545 int freq = 0, count = 0;
2546 gcov_type cnt = 0;
2547 bool hot = false;
2549 for (src = val->sources; src; src = src->next)
2551 struct cgraph_edge *cs = src->cs;
2552 while (cs)
2554 if (cgraph_edge_brings_value_p (cs, src))
2556 count++;
2557 freq += cs->frequency;
2558 cnt += cs->count;
2559 hot |= cs->maybe_hot_p ();
2561 cs = get_next_cgraph_edge_clone (cs);
2565 *freq_sum = freq;
2566 *count_sum = cnt;
2567 *caller_count = count;
2568 return hot;
2571 /* Return a vector of incoming edges that do bring value VAL. It is assumed
2572 their number is known and equal to CALLER_COUNT. */
2574 static vec<cgraph_edge *>
2575 gather_edges_for_value (struct ipcp_value *val, int caller_count)
2577 struct ipcp_value_source *src;
2578 vec<cgraph_edge *> ret;
2580 ret.create (caller_count);
2581 for (src = val->sources; src; src = src->next)
2583 struct cgraph_edge *cs = src->cs;
2584 while (cs)
2586 if (cgraph_edge_brings_value_p (cs, src))
2587 ret.quick_push (cs);
2588 cs = get_next_cgraph_edge_clone (cs);
2592 return ret;
2595 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
2596 Return it or NULL if for some reason it cannot be created. */
2598 static struct ipa_replace_map *
2599 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
2601 struct ipa_replace_map *replace_map;
2604 replace_map = ggc_alloc<ipa_replace_map> ();
2605 if (dump_file)
2607 fprintf (dump_file, " replacing ");
2608 ipa_dump_param (dump_file, info, parm_num);
2610 fprintf (dump_file, " with const ");
2611 print_generic_expr (dump_file, value, 0);
2612 fprintf (dump_file, "\n");
2614 replace_map->old_tree = NULL;
2615 replace_map->parm_num = parm_num;
2616 replace_map->new_tree = value;
2617 replace_map->replace_p = true;
2618 replace_map->ref_p = false;
2620 return replace_map;
2623 /* Dump new profiling counts */
2625 static void
2626 dump_profile_updates (struct cgraph_node *orig_node,
2627 struct cgraph_node *new_node)
2629 struct cgraph_edge *cs;
2631 fprintf (dump_file, " setting count of the specialized node to "
2632 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
2633 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2634 fprintf (dump_file, " edge to %s has count "
2635 HOST_WIDE_INT_PRINT_DEC "\n",
2636 cs->callee->name (), (HOST_WIDE_INT) cs->count);
2638 fprintf (dump_file, " setting count of the original node to "
2639 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
2640 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2641 fprintf (dump_file, " edge to %s is left with "
2642 HOST_WIDE_INT_PRINT_DEC "\n",
2643 cs->callee->name (), (HOST_WIDE_INT) cs->count);
2646 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
2647 their profile information to reflect this. */
2649 static void
2650 update_profiling_info (struct cgraph_node *orig_node,
2651 struct cgraph_node *new_node)
2653 struct cgraph_edge *cs;
2654 struct caller_statistics stats;
2655 gcov_type new_sum, orig_sum;
2656 gcov_type remainder, orig_node_count = orig_node->count;
2658 if (orig_node_count == 0)
2659 return;
2661 init_caller_stats (&stats);
2662 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2663 false);
2664 orig_sum = stats.count_sum;
2665 init_caller_stats (&stats);
2666 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2667 false);
2668 new_sum = stats.count_sum;
2670 if (orig_node_count < orig_sum + new_sum)
2672 if (dump_file)
2673 fprintf (dump_file, " Problem: node %s/%i has too low count "
2674 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
2675 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
2676 orig_node->name (), orig_node->order,
2677 (HOST_WIDE_INT) orig_node_count,
2678 (HOST_WIDE_INT) (orig_sum + new_sum));
2680 orig_node_count = (orig_sum + new_sum) * 12 / 10;
2681 if (dump_file)
2682 fprintf (dump_file, " proceeding by pretending it was "
2683 HOST_WIDE_INT_PRINT_DEC "\n",
2684 (HOST_WIDE_INT) orig_node_count);
2687 new_node->count = new_sum;
2688 remainder = orig_node_count - new_sum;
2689 orig_node->count = remainder;
2691 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2692 if (cs->frequency)
2693 cs->count = apply_probability (cs->count,
2694 GCOV_COMPUTE_SCALE (new_sum,
2695 orig_node_count));
2696 else
2697 cs->count = 0;
2699 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2700 cs->count = apply_probability (cs->count,
2701 GCOV_COMPUTE_SCALE (remainder,
2702 orig_node_count));
2704 if (dump_file)
2705 dump_profile_updates (orig_node, new_node);
2708 /* Update the respective profile of specialized NEW_NODE and the original
2709 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
2710 have been redirected to the specialized version. */
2712 static void
2713 update_specialized_profile (struct cgraph_node *new_node,
2714 struct cgraph_node *orig_node,
2715 gcov_type redirected_sum)
2717 struct cgraph_edge *cs;
2718 gcov_type new_node_count, orig_node_count = orig_node->count;
2720 if (dump_file)
2721 fprintf (dump_file, " the sum of counts of redirected edges is "
2722 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
2723 if (orig_node_count == 0)
2724 return;
2726 gcc_assert (orig_node_count >= redirected_sum);
2728 new_node_count = new_node->count;
2729 new_node->count += redirected_sum;
2730 orig_node->count -= redirected_sum;
2732 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2733 if (cs->frequency)
2734 cs->count += apply_probability (cs->count,
2735 GCOV_COMPUTE_SCALE (redirected_sum,
2736 new_node_count));
2737 else
2738 cs->count = 0;
2740 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2742 gcov_type dec = apply_probability (cs->count,
2743 GCOV_COMPUTE_SCALE (redirected_sum,
2744 orig_node_count));
2745 if (dec < cs->count)
2746 cs->count -= dec;
2747 else
2748 cs->count = 0;
2751 if (dump_file)
2752 dump_profile_updates (orig_node, new_node);
2755 /* Create a specialized version of NODE with known constants and types of
2756 parameters in KNOWN_VALS and redirect all edges in CALLERS to it. */
2758 static struct cgraph_node *
2759 create_specialized_node (struct cgraph_node *node,
2760 vec<tree> known_vals,
2761 struct ipa_agg_replacement_value *aggvals,
2762 vec<cgraph_edge *> callers)
2764 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
2765 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
2766 struct ipa_agg_replacement_value *av;
2767 struct cgraph_node *new_node;
2768 int i, count = ipa_get_param_count (info);
2769 bitmap args_to_skip;
2771 gcc_assert (!info->ipcp_orig_node);
2773 if (node->local.can_change_signature)
2775 args_to_skip = BITMAP_GGC_ALLOC ();
2776 for (i = 0; i < count; i++)
2778 tree t = known_vals[i];
2780 if ((t && TREE_CODE (t) != TREE_BINFO)
2781 || !ipa_is_param_used (info, i))
2782 bitmap_set_bit (args_to_skip, i);
2785 else
2787 args_to_skip = NULL;
2788 if (dump_file && (dump_flags & TDF_DETAILS))
2789 fprintf (dump_file, " cannot change function signature\n");
2792 for (i = 0; i < count ; i++)
2794 tree t = known_vals[i];
2795 if (t && TREE_CODE (t) != TREE_BINFO)
2797 struct ipa_replace_map *replace_map;
2799 replace_map = get_replacement_map (info, t, i);
2800 if (replace_map)
2801 vec_safe_push (replace_trees, replace_map);
2805 new_node = node->create_virtual_clone (callers, replace_trees,
2806 args_to_skip, "constprop");
2807 ipa_set_node_agg_value_chain (new_node, aggvals);
2808 for (av = aggvals; av; av = av->next)
2809 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
2811 if (dump_file && (dump_flags & TDF_DETAILS))
2813 fprintf (dump_file, " the new node is %s/%i.\n",
2814 new_node->name (), new_node->order);
2815 if (aggvals)
2816 ipa_dump_agg_replacement_values (dump_file, aggvals);
2818 ipa_check_create_node_params ();
2819 update_profiling_info (node, new_node);
2820 new_info = IPA_NODE_REF (new_node);
2821 new_info->ipcp_orig_node = node;
2822 new_info->known_vals = known_vals;
2824 ipcp_discover_new_direct_edges (new_node, known_vals, aggvals);
2826 callers.release ();
2827 return new_node;
2830 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
2831 KNOWN_VALS with constants and types that are also known for all of the
2832 CALLERS. */
2834 static void
2835 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
2836 vec<tree> known_vals,
2837 vec<cgraph_edge *> callers)
2839 struct ipa_node_params *info = IPA_NODE_REF (node);
2840 int i, count = ipa_get_param_count (info);
2842 for (i = 0; i < count ; i++)
2844 struct cgraph_edge *cs;
2845 tree newval = NULL_TREE;
2846 int j;
2848 if (ipa_get_scalar_lat (info, i)->bottom || known_vals[i])
2849 continue;
2851 FOR_EACH_VEC_ELT (callers, j, cs)
2853 struct ipa_jump_func *jump_func;
2854 tree t;
2856 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
2858 newval = NULL_TREE;
2859 break;
2861 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
2862 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
2863 if (!t
2864 || (newval
2865 && !values_equal_for_ipcp_p (t, newval)))
2867 newval = NULL_TREE;
2868 break;
2870 else
2871 newval = t;
2874 if (newval)
2876 if (dump_file && (dump_flags & TDF_DETAILS))
2878 fprintf (dump_file, " adding an extra known scalar value ");
2879 print_ipcp_constant_value (dump_file, newval);
2880 fprintf (dump_file, " for ");
2881 ipa_dump_param (dump_file, info, i);
2882 fprintf (dump_file, "\n");
2885 known_vals[i] = newval;
2890 /* Go through PLATS and create a vector of values consisting of values and
2891 offsets (minus OFFSET) of lattices that contain only a single value. */
2893 static vec<ipa_agg_jf_item>
2894 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
2896 vec<ipa_agg_jf_item> res = vNULL;
2898 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
2899 return vNULL;
2901 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
2902 if (ipa_lat_is_single_const (aglat))
2904 struct ipa_agg_jf_item ti;
2905 ti.offset = aglat->offset - offset;
2906 ti.value = aglat->values->value;
2907 res.safe_push (ti);
2909 return res;
2912 /* Intersect all values in INTER with single value lattices in PLATS (while
2913 subtracting OFFSET). */
2915 static void
2916 intersect_with_plats (struct ipcp_param_lattices *plats,
2917 vec<ipa_agg_jf_item> *inter,
2918 HOST_WIDE_INT offset)
2920 struct ipcp_agg_lattice *aglat;
2921 struct ipa_agg_jf_item *item;
2922 int k;
2924 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
2926 inter->release ();
2927 return;
2930 aglat = plats->aggs;
2931 FOR_EACH_VEC_ELT (*inter, k, item)
2933 bool found = false;
2934 if (!item->value)
2935 continue;
2936 while (aglat)
2938 if (aglat->offset - offset > item->offset)
2939 break;
2940 if (aglat->offset - offset == item->offset)
2942 gcc_checking_assert (item->value);
2943 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
2944 found = true;
2945 break;
2947 aglat = aglat->next;
2949 if (!found)
2950 item->value = NULL_TREE;
2954 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
2955 vector result while subtracting OFFSET from the individual value offsets. */
2957 static vec<ipa_agg_jf_item>
2958 agg_replacements_to_vector (struct cgraph_node *node, int index,
2959 HOST_WIDE_INT offset)
2961 struct ipa_agg_replacement_value *av;
2962 vec<ipa_agg_jf_item> res = vNULL;
2964 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
2965 if (av->index == index
2966 && (av->offset - offset) >= 0)
2968 struct ipa_agg_jf_item item;
2969 gcc_checking_assert (av->value);
2970 item.offset = av->offset - offset;
2971 item.value = av->value;
2972 res.safe_push (item);
2975 return res;
2978 /* Intersect all values in INTER with those that we have already scheduled to
2979 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
2980 (while subtracting OFFSET). */
2982 static void
2983 intersect_with_agg_replacements (struct cgraph_node *node, int index,
2984 vec<ipa_agg_jf_item> *inter,
2985 HOST_WIDE_INT offset)
2987 struct ipa_agg_replacement_value *srcvals;
2988 struct ipa_agg_jf_item *item;
2989 int i;
2991 srcvals = ipa_get_agg_replacements_for_node (node);
2992 if (!srcvals)
2994 inter->release ();
2995 return;
2998 FOR_EACH_VEC_ELT (*inter, i, item)
3000 struct ipa_agg_replacement_value *av;
3001 bool found = false;
3002 if (!item->value)
3003 continue;
3004 for (av = srcvals; av; av = av->next)
3006 gcc_checking_assert (av->value);
3007 if (av->index == index
3008 && av->offset - offset == item->offset)
3010 if (values_equal_for_ipcp_p (item->value, av->value))
3011 found = true;
3012 break;
3015 if (!found)
3016 item->value = NULL_TREE;
3020 /* Intersect values in INTER with aggregate values that come along edge CS to
3021 parameter number INDEX and return it. If INTER does not actually exist yet,
3022 copy all incoming values to it. If we determine we ended up with no values
3023 whatsoever, return a released vector. */
3025 static vec<ipa_agg_jf_item>
3026 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
3027 vec<ipa_agg_jf_item> inter)
3029 struct ipa_jump_func *jfunc;
3030 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3031 if (jfunc->type == IPA_JF_PASS_THROUGH
3032 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3034 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3035 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3037 if (caller_info->ipcp_orig_node)
3039 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3040 struct ipcp_param_lattices *orig_plats;
3041 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3042 src_idx);
3043 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3045 if (!inter.exists ())
3046 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
3047 else
3048 intersect_with_agg_replacements (cs->caller, src_idx,
3049 &inter, 0);
3051 else
3053 inter.release ();
3054 return vNULL;
3057 else
3059 struct ipcp_param_lattices *src_plats;
3060 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3061 if (agg_pass_through_permissible_p (src_plats, jfunc))
3063 /* Currently we do not produce clobber aggregate jump
3064 functions, adjust when we do. */
3065 gcc_checking_assert (!jfunc->agg.items);
3066 if (!inter.exists ())
3067 inter = copy_plats_to_inter (src_plats, 0);
3068 else
3069 intersect_with_plats (src_plats, &inter, 0);
3071 else
3073 inter.release ();
3074 return vNULL;
3078 else if (jfunc->type == IPA_JF_ANCESTOR
3079 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3081 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3082 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3083 struct ipcp_param_lattices *src_plats;
3084 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3086 if (caller_info->ipcp_orig_node)
3088 if (!inter.exists ())
3089 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
3090 else
3091 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
3092 delta);
3094 else
3096 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3097 /* Currently we do not produce clobber aggregate jump
3098 functions, adjust when we do. */
3099 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3100 if (!inter.exists ())
3101 inter = copy_plats_to_inter (src_plats, delta);
3102 else
3103 intersect_with_plats (src_plats, &inter, delta);
3106 else if (jfunc->agg.items)
3108 struct ipa_agg_jf_item *item;
3109 int k;
3111 if (!inter.exists ())
3112 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3113 inter.safe_push ((*jfunc->agg.items)[i]);
3114 else
3115 FOR_EACH_VEC_ELT (inter, k, item)
3117 int l = 0;
3118 bool found = false;;
3120 if (!item->value)
3121 continue;
3123 while ((unsigned) l < jfunc->agg.items->length ())
3125 struct ipa_agg_jf_item *ti;
3126 ti = &(*jfunc->agg.items)[l];
3127 if (ti->offset > item->offset)
3128 break;
3129 if (ti->offset == item->offset)
3131 gcc_checking_assert (ti->value);
3132 if (values_equal_for_ipcp_p (item->value,
3133 ti->value))
3134 found = true;
3135 break;
3137 l++;
3139 if (!found)
3140 item->value = NULL;
3143 else
3145 inter.release ();
3146 return vec<ipa_agg_jf_item>();
3148 return inter;
3151 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3152 from all of them. */
3154 static struct ipa_agg_replacement_value *
3155 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3156 vec<cgraph_edge *> callers)
3158 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3159 struct ipa_agg_replacement_value *res;
3160 struct ipa_agg_replacement_value **tail = &res;
3161 struct cgraph_edge *cs;
3162 int i, j, count = ipa_get_param_count (dest_info);
3164 FOR_EACH_VEC_ELT (callers, j, cs)
3166 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3167 if (c < count)
3168 count = c;
3171 for (i = 0; i < count ; i++)
3173 struct cgraph_edge *cs;
3174 vec<ipa_agg_jf_item> inter = vNULL;
3175 struct ipa_agg_jf_item *item;
3176 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3177 int j;
3179 /* Among other things, the following check should deal with all by_ref
3180 mismatches. */
3181 if (plats->aggs_bottom)
3182 continue;
3184 FOR_EACH_VEC_ELT (callers, j, cs)
3186 inter = intersect_aggregates_with_edge (cs, i, inter);
3188 if (!inter.exists ())
3189 goto next_param;
3192 FOR_EACH_VEC_ELT (inter, j, item)
3194 struct ipa_agg_replacement_value *v;
3196 if (!item->value)
3197 continue;
3199 v = ggc_alloc<ipa_agg_replacement_value> ();
3200 v->index = i;
3201 v->offset = item->offset;
3202 v->value = item->value;
3203 v->by_ref = plats->aggs_by_ref;
3204 *tail = v;
3205 tail = &v->next;
3208 next_param:
3209 if (inter.exists ())
3210 inter.release ();
3212 *tail = NULL;
3213 return res;
3216 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3218 static struct ipa_agg_replacement_value *
3219 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
3221 struct ipa_agg_replacement_value *res;
3222 struct ipa_agg_replacement_value **tail = &res;
3223 struct ipa_agg_jump_function *aggjf;
3224 struct ipa_agg_jf_item *item;
3225 int i, j;
3227 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3228 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3230 struct ipa_agg_replacement_value *v;
3231 v = ggc_alloc<ipa_agg_replacement_value> ();
3232 v->index = i;
3233 v->offset = item->offset;
3234 v->value = item->value;
3235 v->by_ref = aggjf->by_ref;
3236 *tail = v;
3237 tail = &v->next;
3239 *tail = NULL;
3240 return res;
3243 /* Determine whether CS also brings all scalar values that the NODE is
3244 specialized for. */
3246 static bool
3247 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3248 struct cgraph_node *node)
3250 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3251 int count = ipa_get_param_count (dest_info);
3252 struct ipa_node_params *caller_info;
3253 struct ipa_edge_args *args;
3254 int i;
3256 caller_info = IPA_NODE_REF (cs->caller);
3257 args = IPA_EDGE_REF (cs);
3258 for (i = 0; i < count; i++)
3260 struct ipa_jump_func *jump_func;
3261 tree val, t;
3263 val = dest_info->known_vals[i];
3264 if (!val)
3265 continue;
3267 if (i >= ipa_get_cs_argument_count (args))
3268 return false;
3269 jump_func = ipa_get_ith_jump_func (args, i);
3270 t = ipa_value_from_jfunc (caller_info, jump_func);
3271 if (!t || !values_equal_for_ipcp_p (val, t))
3272 return false;
3274 return true;
3277 /* Determine whether CS also brings all aggregate values that NODE is
3278 specialized for. */
3279 static bool
3280 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3281 struct cgraph_node *node)
3283 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3284 struct ipa_node_params *orig_node_info;
3285 struct ipa_agg_replacement_value *aggval;
3286 int i, ec, count;
3288 aggval = ipa_get_agg_replacements_for_node (node);
3289 if (!aggval)
3290 return true;
3292 count = ipa_get_param_count (IPA_NODE_REF (node));
3293 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3294 if (ec < count)
3295 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3296 if (aggval->index >= ec)
3297 return false;
3299 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3300 if (orig_caller_info->ipcp_orig_node)
3301 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3303 for (i = 0; i < count; i++)
3305 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
3306 struct ipcp_param_lattices *plats;
3307 bool interesting = false;
3308 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3309 if (aggval->index == i)
3311 interesting = true;
3312 break;
3314 if (!interesting)
3315 continue;
3317 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3318 if (plats->aggs_bottom)
3319 return false;
3321 values = intersect_aggregates_with_edge (cs, i, values);
3322 if (!values.exists ())
3323 return false;
3325 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3326 if (aggval->index == i)
3328 struct ipa_agg_jf_item *item;
3329 int j;
3330 bool found = false;
3331 FOR_EACH_VEC_ELT (values, j, item)
3332 if (item->value
3333 && item->offset == av->offset
3334 && values_equal_for_ipcp_p (item->value, av->value))
3336 found = true;
3337 break;
3339 if (!found)
3341 values.release ();
3342 return false;
3346 return true;
3349 /* Given an original NODE and a VAL for which we have already created a
3350 specialized clone, look whether there are incoming edges that still lead
3351 into the old node but now also bring the requested value and also conform to
3352 all other criteria such that they can be redirected the the special node.
3353 This function can therefore redirect the final edge in a SCC. */
3355 static void
3356 perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val)
3358 struct ipcp_value_source *src;
3359 gcov_type redirected_sum = 0;
3361 for (src = val->sources; src; src = src->next)
3363 struct cgraph_edge *cs = src->cs;
3364 while (cs)
3366 enum availability availability;
3367 struct cgraph_node *dst = cs->callee->function_symbol (&availability);
3368 if ((dst == node || IPA_NODE_REF (dst)->is_all_contexts_clone)
3369 && availability > AVAIL_INTERPOSABLE
3370 && cgraph_edge_brings_value_p (cs, src))
3372 if (cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3373 && cgraph_edge_brings_all_agg_vals_for_node (cs,
3374 val->spec_node))
3376 if (dump_file)
3377 fprintf (dump_file, " - adding an extra caller %s/%i"
3378 " of %s/%i\n",
3379 xstrdup (cs->caller->name ()),
3380 cs->caller->order,
3381 xstrdup (val->spec_node->name ()),
3382 val->spec_node->order);
3384 cs->redirect_callee (val->spec_node);
3385 redirected_sum += cs->count;
3388 cs = get_next_cgraph_edge_clone (cs);
3392 if (redirected_sum)
3393 update_specialized_profile (val->spec_node, node, redirected_sum);
3397 /* Copy KNOWN_BINFOS to KNOWN_VALS. */
3399 static void
3400 move_binfos_to_values (vec<tree> known_vals,
3401 vec<tree> known_binfos)
3403 tree t;
3404 int i;
3406 for (i = 0; known_binfos.iterate (i, &t); i++)
3407 if (t)
3408 known_vals[i] = t;
3411 /* Return true if there is a replacement equivalent to VALUE, INDEX and OFFSET
3412 among those in the AGGVALS list. */
3414 DEBUG_FUNCTION bool
3415 ipcp_val_in_agg_replacements_p (struct ipa_agg_replacement_value *aggvals,
3416 int index, HOST_WIDE_INT offset, tree value)
3418 while (aggvals)
3420 if (aggvals->index == index
3421 && aggvals->offset == offset
3422 && values_equal_for_ipcp_p (aggvals->value, value))
3423 return true;
3424 aggvals = aggvals->next;
3426 return false;
3429 /* Decide wheter to create a special version of NODE for value VAL of parameter
3430 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
3431 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
3432 KNOWN_BINFOS and KNOWN_AGGS describe the other already known values. */
3434 static bool
3435 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
3436 struct ipcp_value *val, vec<tree> known_csts,
3437 vec<tree> known_binfos)
3439 struct ipa_agg_replacement_value *aggvals;
3440 int freq_sum, caller_count;
3441 gcov_type count_sum;
3442 vec<cgraph_edge *> callers;
3443 vec<tree> kv;
3445 if (val->spec_node)
3447 perhaps_add_new_callers (node, val);
3448 return false;
3450 else if (val->local_size_cost + overall_size > max_new_size)
3452 if (dump_file && (dump_flags & TDF_DETAILS))
3453 fprintf (dump_file, " Ignoring candidate value because "
3454 "max_new_size would be reached with %li.\n",
3455 val->local_size_cost + overall_size);
3456 return false;
3458 else if (!get_info_about_necessary_edges (val, &freq_sum, &count_sum,
3459 &caller_count))
3460 return false;
3462 if (dump_file && (dump_flags & TDF_DETAILS))
3464 fprintf (dump_file, " - considering value ");
3465 print_ipcp_constant_value (dump_file, val->value);
3466 fprintf (dump_file, " for ");
3467 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
3468 if (offset != -1)
3469 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
3470 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
3473 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
3474 freq_sum, count_sum,
3475 val->local_size_cost)
3476 && !good_cloning_opportunity_p (node,
3477 val->local_time_benefit
3478 + val->prop_time_benefit,
3479 freq_sum, count_sum,
3480 val->local_size_cost
3481 + val->prop_size_cost))
3482 return false;
3484 if (dump_file)
3485 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
3486 node->name (), node->order);
3488 callers = gather_edges_for_value (val, caller_count);
3489 kv = known_csts.copy ();
3490 move_binfos_to_values (kv, known_binfos);
3491 if (offset == -1)
3492 kv[index] = val->value;
3493 find_more_scalar_values_for_callers_subset (node, kv, callers);
3494 aggvals = find_aggregate_values_for_callers_subset (node, callers);
3495 gcc_checking_assert (offset == -1
3496 || ipcp_val_in_agg_replacements_p (aggvals, index,
3497 offset, val->value));
3498 val->spec_node = create_specialized_node (node, kv, aggvals, callers);
3499 overall_size += val->local_size_cost;
3501 /* TODO: If for some lattice there is only one other known value
3502 left, make a special node for it too. */
3504 return true;
3507 /* Decide whether and what specialized clones of NODE should be created. */
3509 static bool
3510 decide_whether_version_node (struct cgraph_node *node)
3512 struct ipa_node_params *info = IPA_NODE_REF (node);
3513 int i, count = ipa_get_param_count (info);
3514 vec<tree> known_csts, known_binfos;
3515 vec<ipa_agg_jump_function> known_aggs = vNULL;
3516 bool ret = false;
3518 if (count == 0)
3519 return false;
3521 if (dump_file && (dump_flags & TDF_DETAILS))
3522 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
3523 node->name (), node->order);
3525 gather_context_independent_values (info, &known_csts, &known_binfos,
3526 info->do_clone_for_all_contexts ? &known_aggs
3527 : NULL, NULL);
3529 for (i = 0; i < count ;i++)
3531 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3532 struct ipcp_lattice *lat = &plats->itself;
3533 struct ipcp_value *val;
3535 if (!lat->bottom
3536 && !known_csts[i]
3537 && !known_binfos[i])
3538 for (val = lat->values; val; val = val->next)
3539 ret |= decide_about_value (node, i, -1, val, known_csts,
3540 known_binfos);
3542 if (!plats->aggs_bottom)
3544 struct ipcp_agg_lattice *aglat;
3545 struct ipcp_value *val;
3546 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3547 if (!aglat->bottom && aglat->values
3548 /* If the following is false, the one value is in
3549 known_aggs. */
3550 && (plats->aggs_contain_variable
3551 || !ipa_lat_is_single_const (aglat)))
3552 for (val = aglat->values; val; val = val->next)
3553 ret |= decide_about_value (node, i, aglat->offset, val,
3554 known_csts, known_binfos);
3556 info = IPA_NODE_REF (node);
3559 if (info->do_clone_for_all_contexts)
3561 struct cgraph_node *clone;
3562 vec<cgraph_edge *> callers;
3564 if (dump_file)
3565 fprintf (dump_file, " - Creating a specialized node of %s/%i "
3566 "for all known contexts.\n", node->name (),
3567 node->order);
3569 callers = node->collect_callers ();
3570 move_binfos_to_values (known_csts, known_binfos);
3571 clone = create_specialized_node (node, known_csts,
3572 known_aggs_to_agg_replacement_list (known_aggs),
3573 callers);
3574 info = IPA_NODE_REF (node);
3575 info->do_clone_for_all_contexts = false;
3576 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
3577 for (i = 0; i < count ; i++)
3578 vec_free (known_aggs[i].items);
3579 known_aggs.release ();
3580 ret = true;
3582 else
3583 known_csts.release ();
3585 known_binfos.release ();
3586 return ret;
3589 /* Transitively mark all callees of NODE within the same SCC as not dead. */
3591 static void
3592 spread_undeadness (struct cgraph_node *node)
3594 struct cgraph_edge *cs;
3596 for (cs = node->callees; cs; cs = cs->next_callee)
3597 if (ipa_edge_within_scc (cs))
3599 struct cgraph_node *callee;
3600 struct ipa_node_params *info;
3602 callee = cs->callee->function_symbol (NULL);
3603 info = IPA_NODE_REF (callee);
3605 if (info->node_dead)
3607 info->node_dead = 0;
3608 spread_undeadness (callee);
3613 /* Return true if NODE has a caller from outside of its SCC that is not
3614 dead. Worker callback for cgraph_for_node_and_aliases. */
3616 static bool
3617 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
3618 void *data ATTRIBUTE_UNUSED)
3620 struct cgraph_edge *cs;
3622 for (cs = node->callers; cs; cs = cs->next_caller)
3623 if (cs->caller->thunk.thunk_p
3624 && cs->caller->call_for_symbol_thunks_and_aliases
3625 (has_undead_caller_from_outside_scc_p, NULL, true))
3626 return true;
3627 else if (!ipa_edge_within_scc (cs)
3628 && !IPA_NODE_REF (cs->caller)->node_dead)
3629 return true;
3630 return false;
3634 /* Identify nodes within the same SCC as NODE which are no longer needed
3635 because of new clones and will be removed as unreachable. */
3637 static void
3638 identify_dead_nodes (struct cgraph_node *node)
3640 struct cgraph_node *v;
3641 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3642 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
3643 && !v->call_for_symbol_thunks_and_aliases
3644 (has_undead_caller_from_outside_scc_p, NULL, true))
3645 IPA_NODE_REF (v)->node_dead = 1;
3647 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3648 if (!IPA_NODE_REF (v)->node_dead)
3649 spread_undeadness (v);
3651 if (dump_file && (dump_flags & TDF_DETAILS))
3653 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3654 if (IPA_NODE_REF (v)->node_dead)
3655 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
3656 v->name (), v->order);
3660 /* The decision stage. Iterate over the topological order of call graph nodes
3661 TOPO and make specialized clones if deemed beneficial. */
3663 static void
3664 ipcp_decision_stage (struct topo_info *topo)
3666 int i;
3668 if (dump_file)
3669 fprintf (dump_file, "\nIPA decision stage:\n\n");
3671 for (i = topo->nnodes - 1; i >= 0; i--)
3673 struct cgraph_node *node = topo->order[i];
3674 bool change = false, iterate = true;
3676 while (iterate)
3678 struct cgraph_node *v;
3679 iterate = false;
3680 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3681 if (v->has_gimple_body_p ()
3682 && ipcp_versionable_function_p (v))
3683 iterate |= decide_whether_version_node (v);
3685 change |= iterate;
3687 if (change)
3688 identify_dead_nodes (node);
3692 /* The IPCP driver. */
3694 static unsigned int
3695 ipcp_driver (void)
3697 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
3698 struct cgraph_edge_hook_list *edge_removal_hook_holder;
3699 struct topo_info topo;
3701 ipa_check_create_node_params ();
3702 ipa_check_create_edge_args ();
3703 grow_edge_clone_vectors ();
3704 edge_duplication_hook_holder =
3705 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
3706 edge_removal_hook_holder =
3707 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
3709 ipcp_values_pool = create_alloc_pool ("IPA-CP values",
3710 sizeof (struct ipcp_value), 32);
3711 ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources",
3712 sizeof (struct ipcp_value_source), 64);
3713 ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices",
3714 sizeof (struct ipcp_agg_lattice),
3715 32);
3716 if (dump_file)
3718 fprintf (dump_file, "\nIPA structures before propagation:\n");
3719 if (dump_flags & TDF_DETAILS)
3720 ipa_print_all_params (dump_file);
3721 ipa_print_all_jump_functions (dump_file);
3724 /* Topological sort. */
3725 build_toporder_info (&topo);
3726 /* Do the interprocedural propagation. */
3727 ipcp_propagate_stage (&topo);
3728 /* Decide what constant propagation and cloning should be performed. */
3729 ipcp_decision_stage (&topo);
3731 /* Free all IPCP structures. */
3732 free_toporder_info (&topo);
3733 next_edge_clone.release ();
3734 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
3735 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
3736 ipa_free_all_structures_after_ipa_cp ();
3737 if (dump_file)
3738 fprintf (dump_file, "\nIPA constant propagation end\n");
3739 return 0;
3742 /* Initialization and computation of IPCP data structures. This is the initial
3743 intraprocedural analysis of functions, which gathers information to be
3744 propagated later on. */
3746 static void
3747 ipcp_generate_summary (void)
3749 struct cgraph_node *node;
3751 if (dump_file)
3752 fprintf (dump_file, "\nIPA constant propagation start:\n");
3753 ipa_register_cgraph_hooks ();
3755 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3757 node->local.versionable
3758 = tree_versionable_function_p (node->decl);
3759 ipa_analyze_node (node);
3763 /* Write ipcp summary for nodes in SET. */
3765 static void
3766 ipcp_write_summary (void)
3768 ipa_prop_write_jump_functions ();
3771 /* Read ipcp summary. */
3773 static void
3774 ipcp_read_summary (void)
3776 ipa_prop_read_jump_functions ();
3779 namespace {
3781 const pass_data pass_data_ipa_cp =
3783 IPA_PASS, /* type */
3784 "cp", /* name */
3785 OPTGROUP_NONE, /* optinfo_flags */
3786 TV_IPA_CONSTANT_PROP, /* tv_id */
3787 0, /* properties_required */
3788 0, /* properties_provided */
3789 0, /* properties_destroyed */
3790 0, /* todo_flags_start */
3791 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
3794 class pass_ipa_cp : public ipa_opt_pass_d
3796 public:
3797 pass_ipa_cp (gcc::context *ctxt)
3798 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
3799 ipcp_generate_summary, /* generate_summary */
3800 ipcp_write_summary, /* write_summary */
3801 ipcp_read_summary, /* read_summary */
3802 ipa_prop_write_all_agg_replacement, /*
3803 write_optimization_summary */
3804 ipa_prop_read_all_agg_replacement, /*
3805 read_optimization_summary */
3806 NULL, /* stmt_fixup */
3807 0, /* function_transform_todo_flags_start */
3808 ipcp_transform_function, /* function_transform */
3809 NULL) /* variable_transform */
3812 /* opt_pass methods: */
3813 virtual bool gate (function *)
3815 /* FIXME: We should remove the optimize check after we ensure we never run
3816 IPA passes when not optimizing. */
3817 return flag_ipa_cp && optimize;
3820 virtual unsigned int execute (function *) { return ipcp_driver (); }
3822 }; // class pass_ipa_cp
3824 } // anon namespace
3826 ipa_opt_pass_d *
3827 make_pass_ipa_cp (gcc::context *ctxt)
3829 return new pass_ipa_cp (ctxt);