Merge branches/gcc-4_8-branch rev 210799.
[official-gcc.git] / gcc-4_8-branch / gcc / ipa-cp.c
blobd9d69b3e4aa95fa54bc8bf87a786a4b437d14a68
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2013 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 "target.h"
108 #include "gimple.h"
109 #include "cgraph.h"
110 #include "ipa-prop.h"
111 #include "tree-flow.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 /* Return true iff the CS is an edge within a strongly connected component as
291 computed by ipa_reduced_postorder. */
293 static inline bool
294 edge_within_scc (struct cgraph_edge *cs)
296 struct ipa_dfs_info *caller_dfs = (struct ipa_dfs_info *) cs->caller->symbol.aux;
297 struct ipa_dfs_info *callee_dfs;
298 struct cgraph_node *callee = cgraph_function_node (cs->callee, NULL);
300 callee_dfs = (struct ipa_dfs_info *) callee->symbol.aux;
301 return (caller_dfs
302 && callee_dfs
303 && caller_dfs->scc_no == callee_dfs->scc_no);
306 /* Print V which is extracted from a value in a lattice to F. */
308 static void
309 print_ipcp_constant_value (FILE * f, tree v)
311 if (TREE_CODE (v) == TREE_BINFO)
313 fprintf (f, "BINFO ");
314 print_generic_expr (f, BINFO_TYPE (v), 0);
316 else if (TREE_CODE (v) == ADDR_EXPR
317 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
319 fprintf (f, "& ");
320 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
322 else
323 print_generic_expr (f, v, 0);
326 /* Print a lattice LAT to F. */
328 static void
329 print_lattice (FILE * f, struct ipcp_lattice *lat,
330 bool dump_sources, bool dump_benefits)
332 struct ipcp_value *val;
333 bool prev = false;
335 if (lat->bottom)
337 fprintf (f, "BOTTOM\n");
338 return;
341 if (!lat->values_count && !lat->contains_variable)
343 fprintf (f, "TOP\n");
344 return;
347 if (lat->contains_variable)
349 fprintf (f, "VARIABLE");
350 prev = true;
351 if (dump_benefits)
352 fprintf (f, "\n");
355 for (val = lat->values; val; val = val->next)
357 if (dump_benefits && prev)
358 fprintf (f, " ");
359 else if (!dump_benefits && prev)
360 fprintf (f, ", ");
361 else
362 prev = true;
364 print_ipcp_constant_value (f, val->value);
366 if (dump_sources)
368 struct ipcp_value_source *s;
370 fprintf (f, " [from:");
371 for (s = val->sources; s; s = s->next)
372 fprintf (f, " %i(%i)", s->cs->caller->uid,s->cs->frequency);
373 fprintf (f, "]");
376 if (dump_benefits)
377 fprintf (f, " [loc_time: %i, loc_size: %i, "
378 "prop_time: %i, prop_size: %i]\n",
379 val->local_time_benefit, val->local_size_cost,
380 val->prop_time_benefit, val->prop_size_cost);
382 if (!dump_benefits)
383 fprintf (f, "\n");
386 /* Print all ipcp_lattices of all functions to F. */
388 static void
389 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
391 struct cgraph_node *node;
392 int i, count;
394 fprintf (f, "\nLattices:\n");
395 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
397 struct ipa_node_params *info;
399 info = IPA_NODE_REF (node);
400 fprintf (f, " Node: %s/%i:\n", cgraph_node_name (node), node->uid);
401 count = ipa_get_param_count (info);
402 for (i = 0; i < count; i++)
404 struct ipcp_agg_lattice *aglat;
405 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
406 fprintf (f, " param [%d]: ", i);
407 print_lattice (f, &plats->itself, dump_sources, dump_benefits);
409 if (plats->virt_call)
410 fprintf (f, " virt_call flag set\n");
412 if (plats->aggs_bottom)
414 fprintf (f, " AGGS BOTTOM\n");
415 continue;
417 if (plats->aggs_contain_variable)
418 fprintf (f, " AGGS VARIABLE\n");
419 for (aglat = plats->aggs; aglat; aglat = aglat->next)
421 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
422 plats->aggs_by_ref ? "ref " : "", aglat->offset);
423 print_lattice (f, aglat, dump_sources, dump_benefits);
429 /* Determine whether it is at all technically possible to create clones of NODE
430 and store this information in the ipa_node_params structure associated
431 with NODE. */
433 static void
434 determine_versionability (struct cgraph_node *node)
436 const char *reason = NULL;
438 /* There are a number of generic reasons functions cannot be versioned. We
439 also cannot remove parameters if there are type attributes such as fnspec
440 present. */
441 if (node->alias || node->thunk.thunk_p)
442 reason = "alias or thunk";
443 else if (!node->local.versionable)
444 reason = "not a tree_versionable_function";
445 else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
446 reason = "insufficient body availability";
447 else if (!opt_for_fn (node->symbol.decl, optimize)
448 || !opt_for_fn (node->symbol.decl, flag_ipa_cp))
449 reason = "non-optimized function";
451 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
452 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
453 cgraph_node_name (node), node->uid, reason);
455 node->local.versionable = (reason == NULL);
458 /* Return true if it is at all technically possible to create clones of a
459 NODE. */
461 static bool
462 ipcp_versionable_function_p (struct cgraph_node *node)
464 return node->local.versionable;
467 /* Structure holding accumulated information about callers of a node. */
469 struct caller_statistics
471 gcov_type count_sum;
472 int n_calls, n_hot_calls, freq_sum;
475 /* Initialize fields of STAT to zeroes. */
477 static inline void
478 init_caller_stats (struct caller_statistics *stats)
480 stats->count_sum = 0;
481 stats->n_calls = 0;
482 stats->n_hot_calls = 0;
483 stats->freq_sum = 0;
486 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
487 non-thunk incoming edges to NODE. */
489 static bool
490 gather_caller_stats (struct cgraph_node *node, void *data)
492 struct caller_statistics *stats = (struct caller_statistics *) data;
493 struct cgraph_edge *cs;
495 for (cs = node->callers; cs; cs = cs->next_caller)
496 if (cs->caller->thunk.thunk_p)
497 cgraph_for_node_and_aliases (cs->caller, gather_caller_stats,
498 stats, false);
499 else
501 stats->count_sum += cs->count;
502 stats->freq_sum += cs->frequency;
503 stats->n_calls++;
504 if (cgraph_maybe_hot_edge_p (cs))
505 stats->n_hot_calls ++;
507 return false;
511 /* Return true if this NODE is viable candidate for cloning. */
513 static bool
514 ipcp_cloning_candidate_p (struct cgraph_node *node)
516 struct caller_statistics stats;
518 gcc_checking_assert (cgraph_function_with_gimple_body_p (node));
520 if (!flag_ipa_cp_clone)
522 if (dump_file)
523 fprintf (dump_file, "Not considering %s for cloning; "
524 "-fipa-cp-clone disabled.\n",
525 cgraph_node_name (node));
526 return false;
529 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl)))
531 if (dump_file)
532 fprintf (dump_file, "Not considering %s for cloning; "
533 "optimizing it for size.\n",
534 cgraph_node_name (node));
535 return false;
538 init_caller_stats (&stats);
539 cgraph_for_node_and_aliases (node, gather_caller_stats, &stats, false);
541 if (inline_summary (node)->self_size < stats.n_calls)
543 if (dump_file)
544 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
545 cgraph_node_name (node));
546 return true;
549 /* When profile is available and function is hot, propagate into it even if
550 calls seems cold; constant propagation can improve function's speed
551 significantly. */
552 if (max_count)
554 if (stats.count_sum > node->count * 90 / 100)
556 if (dump_file)
557 fprintf (dump_file, "Considering %s for cloning; "
558 "usually called directly.\n",
559 cgraph_node_name (node));
560 return true;
563 if (!stats.n_hot_calls)
565 if (dump_file)
566 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
567 cgraph_node_name (node));
568 return false;
570 if (dump_file)
571 fprintf (dump_file, "Considering %s for cloning.\n",
572 cgraph_node_name (node));
573 return true;
576 /* Arrays representing a topological ordering of call graph nodes and a stack
577 of noes used during constant propagation. */
579 struct topo_info
581 struct cgraph_node **order;
582 struct cgraph_node **stack;
583 int nnodes, stack_top;
586 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
588 static void
589 build_toporder_info (struct topo_info *topo)
591 topo->order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
592 topo->stack = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
593 topo->stack_top = 0;
594 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
597 /* Free information about strongly connected components and the arrays in
598 TOPO. */
600 static void
601 free_toporder_info (struct topo_info *topo)
603 ipa_free_postorder_info ();
604 free (topo->order);
605 free (topo->stack);
608 /* Add NODE to the stack in TOPO, unless it is already there. */
610 static inline void
611 push_node_to_stack (struct topo_info *topo, struct cgraph_node *node)
613 struct ipa_node_params *info = IPA_NODE_REF (node);
614 if (info->node_enqueued)
615 return;
616 info->node_enqueued = 1;
617 topo->stack[topo->stack_top++] = node;
620 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
621 is empty. */
623 static struct cgraph_node *
624 pop_node_from_stack (struct topo_info *topo)
626 if (topo->stack_top)
628 struct cgraph_node *node;
629 topo->stack_top--;
630 node = topo->stack[topo->stack_top];
631 IPA_NODE_REF (node)->node_enqueued = 0;
632 return node;
634 else
635 return NULL;
638 /* Set lattice LAT to bottom and return true if it previously was not set as
639 such. */
641 static inline bool
642 set_lattice_to_bottom (struct ipcp_lattice *lat)
644 bool ret = !lat->bottom;
645 lat->bottom = true;
646 return ret;
649 /* Mark lattice as containing an unknown value and return true if it previously
650 was not marked as such. */
652 static inline bool
653 set_lattice_contains_variable (struct ipcp_lattice *lat)
655 bool ret = !lat->contains_variable;
656 lat->contains_variable = true;
657 return ret;
660 /* Set all aggegate lattices in PLATS to bottom and return true if they were
661 not previously set as such. */
663 static inline bool
664 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
666 bool ret = !plats->aggs_bottom;
667 plats->aggs_bottom = true;
668 return ret;
671 /* Mark all aggegate lattices in PLATS as containing an unknown value and
672 return true if they were not previously marked as such. */
674 static inline bool
675 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
677 bool ret = !plats->aggs_contain_variable;
678 plats->aggs_contain_variable = true;
679 return ret;
682 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
683 return true is any of them has not been marked as such so far. */
685 static inline bool
686 set_all_contains_variable (struct ipcp_param_lattices *plats)
688 bool ret = !plats->itself.contains_variable || !plats->aggs_contain_variable;
689 plats->itself.contains_variable = true;
690 plats->aggs_contain_variable = true;
691 return ret;
694 /* Initialize ipcp_lattices. */
696 static void
697 initialize_node_lattices (struct cgraph_node *node)
699 struct ipa_node_params *info = IPA_NODE_REF (node);
700 struct cgraph_edge *ie;
701 bool disable = false, variable = false;
702 int i;
704 gcc_checking_assert (cgraph_function_with_gimple_body_p (node));
705 if (!node->local.local)
707 /* When cloning is allowed, we can assume that externally visible
708 functions are not called. We will compensate this by cloning
709 later. */
710 if (ipcp_versionable_function_p (node)
711 && ipcp_cloning_candidate_p (node))
712 variable = true;
713 else
714 disable = true;
717 if (disable || variable)
719 for (i = 0; i < ipa_get_param_count (info) ; i++)
721 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
722 if (disable)
724 set_lattice_to_bottom (&plats->itself);
725 set_agg_lats_to_bottom (plats);
727 else
728 set_all_contains_variable (plats);
730 if (dump_file && (dump_flags & TDF_DETAILS)
731 && !node->alias && !node->thunk.thunk_p)
732 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
733 cgraph_node_name (node), node->uid,
734 disable ? "BOTTOM" : "VARIABLE");
736 if (!disable)
737 for (i = 0; i < ipa_get_param_count (info) ; i++)
739 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
740 tree t = TREE_TYPE (ipa_get_param(info, i));
742 if (POINTER_TYPE_P (t) && TYPE_RESTRICT (t)
743 && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
745 set_lattice_to_bottom (&plats->itself);
746 if (dump_file && (dump_flags & TDF_DETAILS)
747 && !node->alias && !node->thunk.thunk_p)
748 fprintf (dump_file, "Going to ignore param %i of of %s/%i.\n",
749 i, cgraph_node_name (node), node->uid);
753 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
754 if (ie->indirect_info->polymorphic)
756 gcc_checking_assert (ie->indirect_info->param_index >= 0);
757 ipa_get_parm_lattices (info,
758 ie->indirect_info->param_index)->virt_call = 1;
762 /* Return the result of a (possibly arithmetic) pass through jump function
763 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
764 determined or itself is considered an interprocedural invariant. */
766 static tree
767 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
769 tree restype, res;
771 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
772 return input;
773 else if (TREE_CODE (input) == TREE_BINFO)
774 return NULL_TREE;
776 gcc_checking_assert (is_gimple_ip_invariant (input));
777 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
778 == tcc_comparison)
779 restype = boolean_type_node;
780 else
781 restype = TREE_TYPE (input);
782 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
783 input, ipa_get_jf_pass_through_operand (jfunc));
785 if (res && !is_gimple_ip_invariant (res))
786 return NULL_TREE;
788 return res;
791 /* Return the result of an ancestor jump function JFUNC on the constant value
792 INPUT. Return NULL_TREE if that cannot be determined. */
794 static tree
795 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
797 if (TREE_CODE (input) == TREE_BINFO)
798 return get_binfo_at_offset (input,
799 ipa_get_jf_ancestor_offset (jfunc),
800 ipa_get_jf_ancestor_type (jfunc));
801 else if (TREE_CODE (input) == ADDR_EXPR)
803 tree t = TREE_OPERAND (input, 0);
804 t = build_ref_for_offset (EXPR_LOCATION (t), t,
805 ipa_get_jf_ancestor_offset (jfunc),
806 ipa_get_jf_ancestor_type (jfunc), NULL, false);
807 return build_fold_addr_expr (t);
809 else
810 return NULL_TREE;
813 /* Extract the acual BINFO being described by JFUNC which must be a known type
814 jump function. */
816 static tree
817 ipa_value_from_known_type_jfunc (struct ipa_jump_func *jfunc)
819 tree base_binfo = TYPE_BINFO (ipa_get_jf_known_type_base_type (jfunc));
820 if (!base_binfo)
821 return NULL_TREE;
822 return get_binfo_at_offset (base_binfo,
823 ipa_get_jf_known_type_offset (jfunc),
824 ipa_get_jf_known_type_component_type (jfunc));
827 /* Determine whether JFUNC evaluates to a known value (that is either a
828 constant or a binfo) and if so, return it. Otherwise return NULL. INFO
829 describes the caller node so that pass-through jump functions can be
830 evaluated. */
832 tree
833 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
835 if (jfunc->type == IPA_JF_CONST)
836 return ipa_get_jf_constant (jfunc);
837 else if (jfunc->type == IPA_JF_KNOWN_TYPE)
838 return ipa_value_from_known_type_jfunc (jfunc);
839 else if (jfunc->type == IPA_JF_PASS_THROUGH
840 || jfunc->type == IPA_JF_ANCESTOR)
842 tree input;
843 int idx;
845 if (jfunc->type == IPA_JF_PASS_THROUGH)
846 idx = ipa_get_jf_pass_through_formal_id (jfunc);
847 else
848 idx = ipa_get_jf_ancestor_formal_id (jfunc);
850 if (info->ipcp_orig_node)
851 input = info->known_vals[idx];
852 else
854 struct ipcp_lattice *lat;
856 if (!info->lattices)
858 gcc_checking_assert (!flag_ipa_cp);
859 return NULL_TREE;
861 lat = ipa_get_scalar_lat (info, idx);
862 if (!ipa_lat_is_single_const (lat))
863 return NULL_TREE;
864 input = lat->values->value;
867 if (!input)
868 return NULL_TREE;
870 if (jfunc->type == IPA_JF_PASS_THROUGH)
871 return ipa_get_jf_pass_through_result (jfunc, input);
872 else
873 return ipa_get_jf_ancestor_result (jfunc, input);
875 else
876 return NULL_TREE;
880 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
881 bottom, not containing a variable component and without any known value at
882 the same time. */
884 DEBUG_FUNCTION void
885 ipcp_verify_propagated_values (void)
887 struct cgraph_node *node;
889 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
891 struct ipa_node_params *info = IPA_NODE_REF (node);
892 int i, count = ipa_get_param_count (info);
894 for (i = 0; i < count; i++)
896 struct ipcp_lattice *lat = ipa_get_scalar_lat (info, i);
898 if (!lat->bottom
899 && !lat->contains_variable
900 && lat->values_count == 0)
902 if (dump_file)
904 fprintf (dump_file, "\nIPA lattices after constant "
905 "propagation:\n");
906 print_all_lattices (dump_file, true, false);
909 gcc_unreachable ();
915 /* Return true iff X and Y should be considered equal values by IPA-CP. */
917 static bool
918 values_equal_for_ipcp_p (tree x, tree y)
920 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
922 if (x == y)
923 return true;
925 if (TREE_CODE (x) == TREE_BINFO || TREE_CODE (y) == TREE_BINFO)
926 return false;
928 if (TREE_CODE (x) == ADDR_EXPR
929 && TREE_CODE (y) == ADDR_EXPR
930 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
931 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
932 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
933 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
934 else
935 return operand_equal_p (x, y, 0);
938 /* Add a new value source to VAL, marking that a value comes from edge CS and
939 (if the underlying jump function is a pass-through or an ancestor one) from
940 a caller value SRC_VAL of a caller parameter described by SRC_INDEX. OFFSET
941 is negative if the source was the scalar value of the parameter itself or
942 the offset within an aggregate. */
944 static void
945 add_value_source (struct ipcp_value *val, struct cgraph_edge *cs,
946 struct ipcp_value *src_val, int src_idx, HOST_WIDE_INT offset)
948 struct ipcp_value_source *src;
950 src = (struct ipcp_value_source *) pool_alloc (ipcp_sources_pool);
951 src->offset = offset;
952 src->cs = cs;
953 src->val = src_val;
954 src->index = src_idx;
956 src->next = val->sources;
957 val->sources = src;
960 /* Try to add NEWVAL to LAT, potentially creating a new struct ipcp_value for
961 it. CS, SRC_VAL SRC_INDEX and OFFSET are meant for add_value_source and
962 have the same meaning. */
964 static bool
965 add_value_to_lattice (struct ipcp_lattice *lat, tree newval,
966 struct cgraph_edge *cs, struct ipcp_value *src_val,
967 int src_idx, HOST_WIDE_INT offset)
969 struct ipcp_value *val;
971 if (lat->bottom)
972 return false;
974 for (val = lat->values; val; val = val->next)
975 if (values_equal_for_ipcp_p (val->value, newval))
977 if (edge_within_scc (cs))
979 struct ipcp_value_source *s;
980 for (s = val->sources; s ; s = s->next)
981 if (s->cs == cs)
982 break;
983 if (s)
984 return false;
987 add_value_source (val, cs, src_val, src_idx, offset);
988 return false;
991 if (lat->values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
993 /* We can only free sources, not the values themselves, because sources
994 of other values in this this SCC might point to them. */
995 for (val = lat->values; val; val = val->next)
997 while (val->sources)
999 struct ipcp_value_source *src = val->sources;
1000 val->sources = src->next;
1001 pool_free (ipcp_sources_pool, src);
1005 lat->values = NULL;
1006 return set_lattice_to_bottom (lat);
1009 lat->values_count++;
1010 val = (struct ipcp_value *) pool_alloc (ipcp_values_pool);
1011 memset (val, 0, sizeof (*val));
1013 add_value_source (val, cs, src_val, src_idx, offset);
1014 val->value = newval;
1015 val->next = lat->values;
1016 lat->values = val;
1017 return true;
1020 /* Like above but passes a special value of offset to distinguish that the
1021 origin is the scalar value of the parameter rather than a part of an
1022 aggregate. */
1024 static inline bool
1025 add_scalar_value_to_lattice (struct ipcp_lattice *lat, tree newval,
1026 struct cgraph_edge *cs,
1027 struct ipcp_value *src_val, int src_idx)
1029 return add_value_to_lattice (lat, newval, cs, src_val, src_idx, -1);
1032 /* Propagate values through a pass-through jump function JFUNC associated with
1033 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1034 is the index of the source parameter. */
1036 static bool
1037 propagate_vals_accross_pass_through (struct cgraph_edge *cs,
1038 struct ipa_jump_func *jfunc,
1039 struct ipcp_lattice *src_lat,
1040 struct ipcp_lattice *dest_lat,
1041 int src_idx)
1043 struct ipcp_value *src_val;
1044 bool ret = false;
1046 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1047 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1048 ret |= add_scalar_value_to_lattice (dest_lat, src_val->value, cs,
1049 src_val, src_idx);
1050 /* Do not create new values when propagating within an SCC because if there
1051 are arithmetic functions with circular dependencies, there is infinite
1052 number of them and we would just make lattices bottom. */
1053 else if (edge_within_scc (cs))
1054 ret = set_lattice_contains_variable (dest_lat);
1055 else
1056 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1058 tree cstval = src_val->value;
1060 if (TREE_CODE (cstval) == TREE_BINFO)
1062 ret |= set_lattice_contains_variable (dest_lat);
1063 continue;
1065 cstval = ipa_get_jf_pass_through_result (jfunc, cstval);
1067 if (cstval)
1068 ret |= add_scalar_value_to_lattice (dest_lat, cstval, cs, src_val,
1069 src_idx);
1070 else
1071 ret |= set_lattice_contains_variable (dest_lat);
1074 return ret;
1077 /* Propagate values through an ancestor jump function JFUNC associated with
1078 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1079 is the index of the source parameter. */
1081 static bool
1082 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1083 struct ipa_jump_func *jfunc,
1084 struct ipcp_lattice *src_lat,
1085 struct ipcp_lattice *dest_lat,
1086 int src_idx)
1088 struct ipcp_value *src_val;
1089 bool ret = false;
1091 if (edge_within_scc (cs))
1092 return set_lattice_contains_variable (dest_lat);
1094 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1096 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1098 if (t)
1099 ret |= add_scalar_value_to_lattice (dest_lat, t, cs, src_val, src_idx);
1100 else
1101 ret |= set_lattice_contains_variable (dest_lat);
1104 return ret;
1107 /* Propagate scalar values across jump function JFUNC that is associated with
1108 edge CS and put the values into DEST_LAT. */
1110 static bool
1111 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1112 struct ipa_jump_func *jfunc,
1113 struct ipcp_lattice *dest_lat)
1115 if (dest_lat->bottom)
1116 return false;
1118 if (jfunc->type == IPA_JF_CONST
1119 || jfunc->type == IPA_JF_KNOWN_TYPE)
1121 tree val;
1123 if (jfunc->type == IPA_JF_KNOWN_TYPE)
1125 val = ipa_value_from_known_type_jfunc (jfunc);
1126 if (!val)
1127 return set_lattice_contains_variable (dest_lat);
1129 else
1130 val = ipa_get_jf_constant (jfunc);
1131 return add_scalar_value_to_lattice (dest_lat, val, cs, NULL, 0);
1133 else if (jfunc->type == IPA_JF_PASS_THROUGH
1134 || jfunc->type == IPA_JF_ANCESTOR)
1136 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1137 struct ipcp_lattice *src_lat;
1138 int src_idx;
1139 bool ret;
1141 if (jfunc->type == IPA_JF_PASS_THROUGH)
1142 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1143 else
1144 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1146 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1147 if (src_lat->bottom)
1148 return set_lattice_contains_variable (dest_lat);
1150 /* If we would need to clone the caller and cannot, do not propagate. */
1151 if (!ipcp_versionable_function_p (cs->caller)
1152 && (src_lat->contains_variable
1153 || (src_lat->values_count > 1)))
1154 return set_lattice_contains_variable (dest_lat);
1156 if (jfunc->type == IPA_JF_PASS_THROUGH)
1157 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1158 dest_lat, src_idx);
1159 else
1160 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1161 src_idx);
1163 if (src_lat->contains_variable)
1164 ret |= set_lattice_contains_variable (dest_lat);
1166 return ret;
1169 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1170 use it for indirect inlining), we should propagate them too. */
1171 return set_lattice_contains_variable (dest_lat);
1174 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1175 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1176 other cases, return false). If there are no aggregate items, set
1177 aggs_by_ref to NEW_AGGS_BY_REF. */
1179 static bool
1180 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1181 bool new_aggs_by_ref)
1183 if (dest_plats->aggs)
1185 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1187 set_agg_lats_to_bottom (dest_plats);
1188 return true;
1191 else
1192 dest_plats->aggs_by_ref = new_aggs_by_ref;
1193 return false;
1196 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1197 already existing lattice for the given OFFSET and SIZE, marking all skipped
1198 lattices as containing variable and checking for overlaps. If there is no
1199 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1200 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1201 unless there are too many already. If there are two many, return false. If
1202 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1203 skipped lattices were newly marked as containing variable, set *CHANGE to
1204 true. */
1206 static bool
1207 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1208 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1209 struct ipcp_agg_lattice ***aglat,
1210 bool pre_existing, bool *change)
1212 gcc_checking_assert (offset >= 0);
1214 while (**aglat && (**aglat)->offset < offset)
1216 if ((**aglat)->offset + (**aglat)->size > offset)
1218 set_agg_lats_to_bottom (dest_plats);
1219 return false;
1221 *change |= set_lattice_contains_variable (**aglat);
1222 *aglat = &(**aglat)->next;
1225 if (**aglat && (**aglat)->offset == offset)
1227 if ((**aglat)->size != val_size
1228 || ((**aglat)->next
1229 && (**aglat)->next->offset < offset + val_size))
1231 set_agg_lats_to_bottom (dest_plats);
1232 return false;
1234 gcc_checking_assert (!(**aglat)->next
1235 || (**aglat)->next->offset >= offset + val_size);
1236 return true;
1238 else
1240 struct ipcp_agg_lattice *new_al;
1242 if (**aglat && (**aglat)->offset < offset + val_size)
1244 set_agg_lats_to_bottom (dest_plats);
1245 return false;
1247 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1248 return false;
1249 dest_plats->aggs_count++;
1250 new_al = (struct ipcp_agg_lattice *) pool_alloc (ipcp_agg_lattice_pool);
1251 memset (new_al, 0, sizeof (*new_al));
1253 new_al->offset = offset;
1254 new_al->size = val_size;
1255 new_al->contains_variable = pre_existing;
1257 new_al->next = **aglat;
1258 **aglat = new_al;
1259 return true;
1263 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1264 containing an unknown value. */
1266 static bool
1267 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1269 bool ret = false;
1270 while (aglat)
1272 ret |= set_lattice_contains_variable (aglat);
1273 aglat = aglat->next;
1275 return ret;
1278 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1279 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1280 parameter used for lattice value sources. Return true if DEST_PLATS changed
1281 in any way. */
1283 static bool
1284 merge_aggregate_lattices (struct cgraph_edge *cs,
1285 struct ipcp_param_lattices *dest_plats,
1286 struct ipcp_param_lattices *src_plats,
1287 int src_idx, HOST_WIDE_INT offset_delta)
1289 bool pre_existing = dest_plats->aggs != NULL;
1290 struct ipcp_agg_lattice **dst_aglat;
1291 bool ret = false;
1293 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1294 return true;
1295 if (src_plats->aggs_bottom)
1296 return set_agg_lats_contain_variable (dest_plats);
1297 if (src_plats->aggs_contain_variable)
1298 ret |= set_agg_lats_contain_variable (dest_plats);
1299 dst_aglat = &dest_plats->aggs;
1301 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1302 src_aglat;
1303 src_aglat = src_aglat->next)
1305 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1307 if (new_offset < 0)
1308 continue;
1309 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1310 &dst_aglat, pre_existing, &ret))
1312 struct ipcp_agg_lattice *new_al = *dst_aglat;
1314 dst_aglat = &(*dst_aglat)->next;
1315 if (src_aglat->bottom)
1317 ret |= set_lattice_contains_variable (new_al);
1318 continue;
1320 if (src_aglat->contains_variable)
1321 ret |= set_lattice_contains_variable (new_al);
1322 for (struct ipcp_value *val = src_aglat->values;
1323 val;
1324 val = val->next)
1325 ret |= add_value_to_lattice (new_al, val->value, cs, val, src_idx,
1326 src_aglat->offset);
1328 else if (dest_plats->aggs_bottom)
1329 return true;
1331 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1332 return ret;
1335 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1336 pass-through JFUNC and if so, whether it has conform and conforms to the
1337 rules about propagating values passed by reference. */
1339 static bool
1340 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1341 struct ipa_jump_func *jfunc)
1343 return src_plats->aggs
1344 && (!src_plats->aggs_by_ref
1345 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1348 /* Propagate scalar values across jump function JFUNC that is associated with
1349 edge CS and put the values into DEST_LAT. */
1351 static bool
1352 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1353 struct ipa_jump_func *jfunc,
1354 struct ipcp_param_lattices *dest_plats)
1356 bool ret = false;
1358 if (dest_plats->aggs_bottom)
1359 return false;
1361 if (jfunc->type == IPA_JF_PASS_THROUGH
1362 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1364 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1365 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1366 struct ipcp_param_lattices *src_plats;
1368 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1369 if (agg_pass_through_permissible_p (src_plats, jfunc))
1371 /* Currently we do not produce clobber aggregate jump
1372 functions, replace with merging when we do. */
1373 gcc_assert (!jfunc->agg.items);
1374 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1375 src_idx, 0);
1377 else
1378 ret |= set_agg_lats_contain_variable (dest_plats);
1380 else if (jfunc->type == IPA_JF_ANCESTOR
1381 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1383 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1384 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1385 struct ipcp_param_lattices *src_plats;
1387 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1388 if (src_plats->aggs && src_plats->aggs_by_ref)
1390 /* Currently we do not produce clobber aggregate jump
1391 functions, replace with merging when we do. */
1392 gcc_assert (!jfunc->agg.items);
1393 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1394 ipa_get_jf_ancestor_offset (jfunc));
1396 else if (!src_plats->aggs_by_ref)
1397 ret |= set_agg_lats_to_bottom (dest_plats);
1398 else
1399 ret |= set_agg_lats_contain_variable (dest_plats);
1401 else if (jfunc->agg.items)
1403 bool pre_existing = dest_plats->aggs != NULL;
1404 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1405 struct ipa_agg_jf_item *item;
1406 int i;
1408 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1409 return true;
1411 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1413 HOST_WIDE_INT val_size;
1415 if (item->offset < 0)
1416 continue;
1417 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1418 val_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (item->value)), 1);
1420 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1421 &aglat, pre_existing, &ret))
1423 ret |= add_value_to_lattice (*aglat, item->value, cs, NULL, 0, 0);
1424 aglat = &(*aglat)->next;
1426 else if (dest_plats->aggs_bottom)
1427 return true;
1430 ret |= set_chain_of_aglats_contains_variable (*aglat);
1432 else
1433 ret |= set_agg_lats_contain_variable (dest_plats);
1435 return ret;
1438 /* Propagate constants from the caller to the callee of CS. INFO describes the
1439 caller. */
1441 static bool
1442 propagate_constants_accross_call (struct cgraph_edge *cs)
1444 struct ipa_node_params *callee_info;
1445 enum availability availability;
1446 struct cgraph_node *callee, *alias_or_thunk;
1447 struct ipa_edge_args *args;
1448 bool ret = false;
1449 int i, args_count, parms_count;
1451 callee = cgraph_function_node (cs->callee, &availability);
1452 if (!callee->analyzed)
1453 return false;
1454 gcc_checking_assert (cgraph_function_with_gimple_body_p (callee));
1455 callee_info = IPA_NODE_REF (callee);
1457 args = IPA_EDGE_REF (cs);
1458 args_count = ipa_get_cs_argument_count (args);
1459 parms_count = ipa_get_param_count (callee_info);
1461 /* If this call goes through a thunk we should not propagate because we
1462 cannot redirect edges to thunks. However, we might need to uncover a
1463 thunk from below a series of aliases first. */
1464 alias_or_thunk = cs->callee;
1465 while (alias_or_thunk->alias)
1466 alias_or_thunk = cgraph_alias_aliased_node (alias_or_thunk);
1467 if (alias_or_thunk->thunk.thunk_p)
1469 for (i = 0; i < parms_count; i++)
1470 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1471 i));
1472 return ret;
1475 for (i = 0; (i < args_count) && (i < parms_count); i++)
1477 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1478 struct ipcp_param_lattices *dest_plats;
1480 dest_plats = ipa_get_parm_lattices (callee_info, i);
1481 if (availability == AVAIL_OVERWRITABLE)
1482 ret |= set_all_contains_variable (dest_plats);
1483 else
1485 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1486 &dest_plats->itself);
1487 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1488 dest_plats);
1491 for (; i < parms_count; i++)
1492 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1494 return ret;
1497 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1498 (which can contain both constants and binfos) or KNOWN_BINFOS (which can be
1499 NULL) return the destination. */
1501 tree
1502 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
1503 vec<tree> known_vals,
1504 vec<tree> known_binfos,
1505 vec<ipa_agg_jump_function_p> known_aggs)
1507 int param_index = ie->indirect_info->param_index;
1508 HOST_WIDE_INT token, anc_offset;
1509 tree otr_type;
1510 tree t;
1512 if (param_index == -1
1513 || known_vals.length () <= (unsigned int) param_index)
1514 return NULL_TREE;
1516 if (!ie->indirect_info->polymorphic)
1518 tree t;
1520 if (ie->indirect_info->agg_contents)
1522 if (known_aggs.length ()
1523 > (unsigned int) param_index)
1525 struct ipa_agg_jump_function *agg;
1526 agg = known_aggs[param_index];
1527 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1528 ie->indirect_info->by_ref);
1530 else
1531 t = NULL;
1533 else
1534 t = known_vals[param_index];
1536 if (t &&
1537 TREE_CODE (t) == ADDR_EXPR
1538 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1539 return TREE_OPERAND (t, 0);
1540 else
1541 return NULL_TREE;
1544 gcc_assert (!ie->indirect_info->agg_contents);
1545 token = ie->indirect_info->otr_token;
1546 anc_offset = ie->indirect_info->offset;
1547 otr_type = ie->indirect_info->otr_type;
1549 t = known_vals[param_index];
1550 if (!t && known_binfos.length () > (unsigned int) param_index)
1551 t = known_binfos[param_index];
1552 if (!t)
1553 return NULL_TREE;
1555 if (TREE_CODE (t) != TREE_BINFO)
1557 tree binfo;
1558 binfo = gimple_extract_devirt_binfo_from_cst (t);
1559 if (!binfo)
1560 return NULL_TREE;
1561 binfo = get_binfo_at_offset (binfo, anc_offset, otr_type);
1562 if (!binfo)
1563 return NULL_TREE;
1564 return gimple_get_virt_method_for_binfo (token, binfo);
1566 else
1568 tree binfo;
1570 binfo = get_binfo_at_offset (t, anc_offset, otr_type);
1571 if (!binfo)
1572 return NULL_TREE;
1573 return gimple_get_virt_method_for_binfo (token, binfo);
1577 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
1578 and KNOWN_BINFOS. */
1580 static int
1581 devirtualization_time_bonus (struct cgraph_node *node,
1582 vec<tree> known_csts,
1583 vec<tree> known_binfos)
1585 struct cgraph_edge *ie;
1586 int res = 0;
1588 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1590 struct cgraph_node *callee;
1591 struct inline_summary *isummary;
1592 tree target;
1594 target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos,
1595 vNULL);
1596 if (!target)
1597 continue;
1599 /* Only bare minimum benefit for clearly un-inlineable targets. */
1600 res += 1;
1601 callee = cgraph_get_node (target);
1602 if (!callee || !callee->analyzed)
1603 continue;
1604 isummary = inline_summary (callee);
1605 if (!isummary->inlinable)
1606 continue;
1608 /* FIXME: The values below need re-considering and perhaps also
1609 integrating into the cost metrics, at lest in some very basic way. */
1610 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
1611 res += 31;
1612 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
1613 res += 15;
1614 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
1615 || DECL_DECLARED_INLINE_P (callee->symbol.decl))
1616 res += 7;
1619 return res;
1622 /* Return time bonus incurred because of HINTS. */
1624 static int
1625 hint_time_bonus (inline_hints hints)
1627 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
1628 return PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
1629 return 0;
1632 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
1633 and SIZE_COST and with the sum of frequencies of incoming edges to the
1634 potential new clone in FREQUENCIES. */
1636 static bool
1637 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
1638 int freq_sum, gcov_type count_sum, int size_cost)
1640 if (time_benefit == 0
1641 || !flag_ipa_cp_clone
1642 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl)))
1643 return false;
1645 gcc_assert (size_cost > 0);
1647 if (max_count)
1649 int factor = (count_sum * 1000) / max_count;
1650 HOST_WIDEST_INT evaluation = (((HOST_WIDEST_INT) time_benefit * factor)
1651 / size_cost);
1653 if (dump_file && (dump_flags & TDF_DETAILS))
1654 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
1655 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
1656 ") -> evaluation: " HOST_WIDEST_INT_PRINT_DEC
1657 ", threshold: %i\n",
1658 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
1659 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
1661 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
1663 else
1665 HOST_WIDEST_INT evaluation = (((HOST_WIDEST_INT) time_benefit * freq_sum)
1666 / size_cost);
1668 if (dump_file && (dump_flags & TDF_DETAILS))
1669 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
1670 "size: %i, freq_sum: %i) -> evaluation: "
1671 HOST_WIDEST_INT_PRINT_DEC ", threshold: %i\n",
1672 time_benefit, size_cost, freq_sum, evaluation,
1673 PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
1675 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
1679 /* Return all context independent values from aggregate lattices in PLATS in a
1680 vector. Return NULL if there are none. */
1682 static vec<ipa_agg_jf_item_t, va_gc> *
1683 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
1685 vec<ipa_agg_jf_item_t, va_gc> *res = NULL;
1687 if (plats->aggs_bottom
1688 || plats->aggs_contain_variable
1689 || plats->aggs_count == 0)
1690 return NULL;
1692 for (struct ipcp_agg_lattice *aglat = plats->aggs;
1693 aglat;
1694 aglat = aglat->next)
1695 if (ipa_lat_is_single_const (aglat))
1697 struct ipa_agg_jf_item item;
1698 item.offset = aglat->offset;
1699 item.value = aglat->values->value;
1700 vec_safe_push (res, item);
1702 return res;
1705 /* Allocate KNOWN_CSTS, KNOWN_BINFOS and, if non-NULL, KNOWN_AGGS and populate
1706 them with values of parameters that are known independent of the context.
1707 INFO describes the function. If REMOVABLE_PARAMS_COST is non-NULL, the
1708 movement cost of all removable parameters will be stored in it. */
1710 static bool
1711 gather_context_independent_values (struct ipa_node_params *info,
1712 vec<tree> *known_csts,
1713 vec<tree> *known_binfos,
1714 vec<ipa_agg_jump_function_t> *known_aggs,
1715 int *removable_params_cost)
1717 int i, count = ipa_get_param_count (info);
1718 bool ret = false;
1720 known_csts->create (0);
1721 known_binfos->create (0);
1722 known_csts->safe_grow_cleared (count);
1723 known_binfos->safe_grow_cleared (count);
1724 if (known_aggs)
1726 known_aggs->create (0);
1727 known_aggs->safe_grow_cleared (count);
1730 if (removable_params_cost)
1731 *removable_params_cost = 0;
1733 for (i = 0; i < count ; i++)
1735 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1736 struct ipcp_lattice *lat = &plats->itself;
1738 if (ipa_lat_is_single_const (lat))
1740 struct ipcp_value *val = lat->values;
1741 if (TREE_CODE (val->value) != TREE_BINFO)
1743 (*known_csts)[i] = val->value;
1744 if (removable_params_cost)
1745 *removable_params_cost
1746 += estimate_move_cost (TREE_TYPE (val->value));
1747 ret = true;
1749 else if (plats->virt_call)
1751 (*known_binfos)[i] = val->value;
1752 ret = true;
1754 else if (removable_params_cost
1755 && !ipa_is_param_used (info, i))
1756 *removable_params_cost
1757 += estimate_move_cost (TREE_TYPE (ipa_get_param (info, i)));
1759 else if (removable_params_cost
1760 && !ipa_is_param_used (info, i))
1761 *removable_params_cost
1762 += estimate_move_cost (TREE_TYPE (ipa_get_param (info, i)));
1764 if (known_aggs)
1766 vec<ipa_agg_jf_item_t, va_gc> *agg_items;
1767 struct ipa_agg_jump_function *ajf;
1769 agg_items = context_independent_aggregate_values (plats);
1770 ajf = &(*known_aggs)[i];
1771 ajf->items = agg_items;
1772 ajf->by_ref = plats->aggs_by_ref;
1773 ret |= agg_items != NULL;
1777 return ret;
1780 /* The current interface in ipa-inline-analysis requires a pointer vector.
1781 Create it.
1783 FIXME: That interface should be re-worked, this is slightly silly. Still,
1784 I'd like to discuss how to change it first and this demonstrates the
1785 issue. */
1787 static vec<ipa_agg_jump_function_p>
1788 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function_t> known_aggs)
1790 vec<ipa_agg_jump_function_p> ret;
1791 struct ipa_agg_jump_function *ajf;
1792 int i;
1794 ret.create (known_aggs.length ());
1795 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
1796 ret.quick_push (ajf);
1797 return ret;
1800 /* Iterate over known values of parameters of NODE and estimate the local
1801 effects in terms of time and size they have. */
1803 static void
1804 estimate_local_effects (struct cgraph_node *node)
1806 struct ipa_node_params *info = IPA_NODE_REF (node);
1807 int i, count = ipa_get_param_count (info);
1808 vec<tree> known_csts, known_binfos;
1809 vec<ipa_agg_jump_function_t> known_aggs;
1810 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
1811 bool always_const;
1812 int base_time = inline_summary (node)->time;
1813 int removable_params_cost;
1815 if (!count || !ipcp_versionable_function_p (node))
1816 return;
1818 if (dump_file && (dump_flags & TDF_DETAILS))
1819 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
1820 cgraph_node_name (node), node->uid, base_time);
1822 always_const = gather_context_independent_values (info, &known_csts,
1823 &known_binfos, &known_aggs,
1824 &removable_params_cost);
1825 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
1826 if (always_const)
1828 struct caller_statistics stats;
1829 inline_hints hints;
1830 int time, size;
1832 init_caller_stats (&stats);
1833 cgraph_for_node_and_aliases (node, gather_caller_stats, &stats, false);
1834 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
1835 known_aggs_ptrs, &size, &time, &hints);
1836 time -= devirtualization_time_bonus (node, known_csts, known_binfos);
1837 time -= hint_time_bonus (hints);
1838 time -= removable_params_cost;
1839 size -= stats.n_calls * removable_params_cost;
1841 if (dump_file)
1842 fprintf (dump_file, " - context independent values, size: %i, "
1843 "time_benefit: %i\n", size, base_time - time);
1845 if (size <= 0
1846 || cgraph_will_be_removed_from_program_if_no_direct_calls (node))
1848 info->do_clone_for_all_contexts = true;
1849 base_time = time;
1851 if (dump_file)
1852 fprintf (dump_file, " Decided to specialize for all "
1853 "known contexts, code not going to grow.\n");
1855 else if (good_cloning_opportunity_p (node, base_time - time,
1856 stats.freq_sum, stats.count_sum,
1857 size))
1859 if (size + overall_size <= max_new_size)
1861 info->do_clone_for_all_contexts = true;
1862 base_time = time;
1863 overall_size += size;
1865 if (dump_file)
1866 fprintf (dump_file, " Decided to specialize for all "
1867 "known contexts, growth deemed beneficial.\n");
1869 else if (dump_file && (dump_flags & TDF_DETAILS))
1870 fprintf (dump_file, " Not cloning for all contexts because "
1871 "max_new_size would be reached with %li.\n",
1872 size + overall_size);
1876 for (i = 0; i < count ; i++)
1878 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1879 struct ipcp_lattice *lat = &plats->itself;
1880 struct ipcp_value *val;
1881 int emc;
1883 if (lat->bottom
1884 || !lat->values
1885 || known_csts[i]
1886 || known_binfos[i])
1887 continue;
1889 for (val = lat->values; val; val = val->next)
1891 int time, size, time_benefit;
1892 inline_hints hints;
1894 if (TREE_CODE (val->value) != TREE_BINFO)
1896 known_csts[i] = val->value;
1897 known_binfos[i] = NULL_TREE;
1898 emc = estimate_move_cost (TREE_TYPE (val->value));
1900 else if (plats->virt_call)
1902 known_csts[i] = NULL_TREE;
1903 known_binfos[i] = val->value;
1904 emc = 0;
1906 else
1907 continue;
1909 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
1910 known_aggs_ptrs, &size, &time,
1911 &hints);
1912 time_benefit = base_time - time
1913 + devirtualization_time_bonus (node, known_csts, known_binfos)
1914 + hint_time_bonus (hints)
1915 + removable_params_cost + emc;
1917 gcc_checking_assert (size >=0);
1918 /* The inliner-heuristics based estimates may think that in certain
1919 contexts some functions do not have any size at all but we want
1920 all specializations to have at least a tiny cost, not least not to
1921 divide by zero. */
1922 if (size == 0)
1923 size = 1;
1925 if (dump_file && (dump_flags & TDF_DETAILS))
1927 fprintf (dump_file, " - estimates for value ");
1928 print_ipcp_constant_value (dump_file, val->value);
1929 fprintf (dump_file, " for parameter ");
1930 print_generic_expr (dump_file, ipa_get_param (info, i), 0);
1931 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
1932 time_benefit, size);
1935 val->local_time_benefit = time_benefit;
1936 val->local_size_cost = size;
1938 known_binfos[i] = NULL_TREE;
1939 known_csts[i] = NULL_TREE;
1942 for (i = 0; i < count ; i++)
1944 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1945 struct ipa_agg_jump_function *ajf;
1946 struct ipcp_agg_lattice *aglat;
1948 if (plats->aggs_bottom || !plats->aggs)
1949 continue;
1951 ajf = &known_aggs[i];
1952 for (aglat = plats->aggs; aglat; aglat = aglat->next)
1954 struct ipcp_value *val;
1955 if (aglat->bottom || !aglat->values
1956 /* If the following is true, the one value is in known_aggs. */
1957 || (!plats->aggs_contain_variable
1958 && ipa_lat_is_single_const (aglat)))
1959 continue;
1961 for (val = aglat->values; val; val = val->next)
1963 int time, size, time_benefit;
1964 struct ipa_agg_jf_item item;
1965 inline_hints hints;
1967 item.offset = aglat->offset;
1968 item.value = val->value;
1969 vec_safe_push (ajf->items, item);
1971 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
1972 known_aggs_ptrs, &size, &time,
1973 &hints);
1974 time_benefit = base_time - time
1975 + devirtualization_time_bonus (node, known_csts, known_binfos)
1976 + hint_time_bonus (hints);
1977 gcc_checking_assert (size >=0);
1978 if (size == 0)
1979 size = 1;
1981 if (dump_file && (dump_flags & TDF_DETAILS))
1983 fprintf (dump_file, " - estimates for value ");
1984 print_ipcp_constant_value (dump_file, val->value);
1985 fprintf (dump_file, " for parameter ");
1986 print_generic_expr (dump_file, ipa_get_param (info, i), 0);
1987 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
1988 "]: time_benefit: %i, size: %i\n",
1989 plats->aggs_by_ref ? "ref " : "",
1990 aglat->offset, time_benefit, size);
1993 val->local_time_benefit = time_benefit;
1994 val->local_size_cost = size;
1995 ajf->items->pop ();
2000 for (i = 0; i < count ; i++)
2001 vec_free (known_aggs[i].items);
2003 known_csts.release ();
2004 known_binfos.release ();
2005 known_aggs.release ();
2006 known_aggs_ptrs.release ();
2010 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2011 topological sort of values. */
2013 static void
2014 add_val_to_toposort (struct ipcp_value *cur_val)
2016 static int dfs_counter = 0;
2017 static struct ipcp_value *stack;
2018 struct ipcp_value_source *src;
2020 if (cur_val->dfs)
2021 return;
2023 dfs_counter++;
2024 cur_val->dfs = dfs_counter;
2025 cur_val->low_link = dfs_counter;
2027 cur_val->topo_next = stack;
2028 stack = cur_val;
2029 cur_val->on_stack = true;
2031 for (src = cur_val->sources; src; src = src->next)
2032 if (src->val)
2034 if (src->val->dfs == 0)
2036 add_val_to_toposort (src->val);
2037 if (src->val->low_link < cur_val->low_link)
2038 cur_val->low_link = src->val->low_link;
2040 else if (src->val->on_stack
2041 && src->val->dfs < cur_val->low_link)
2042 cur_val->low_link = src->val->dfs;
2045 if (cur_val->dfs == cur_val->low_link)
2047 struct ipcp_value *v, *scc_list = NULL;
2051 v = stack;
2052 stack = v->topo_next;
2053 v->on_stack = false;
2055 v->scc_next = scc_list;
2056 scc_list = v;
2058 while (v != cur_val);
2060 cur_val->topo_next = values_topo;
2061 values_topo = cur_val;
2065 /* Add all values in lattices associated with NODE to the topological sort if
2066 they are not there yet. */
2068 static void
2069 add_all_node_vals_to_toposort (struct cgraph_node *node)
2071 struct ipa_node_params *info = IPA_NODE_REF (node);
2072 int i, count = ipa_get_param_count (info);
2074 for (i = 0; i < count ; i++)
2076 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2077 struct ipcp_lattice *lat = &plats->itself;
2078 struct ipcp_agg_lattice *aglat;
2079 struct ipcp_value *val;
2081 if (!lat->bottom)
2082 for (val = lat->values; val; val = val->next)
2083 add_val_to_toposort (val);
2085 if (!plats->aggs_bottom)
2086 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2087 if (!aglat->bottom)
2088 for (val = aglat->values; val; val = val->next)
2089 add_val_to_toposort (val);
2093 /* One pass of constants propagation along the call graph edges, from callers
2094 to callees (requires topological ordering in TOPO), iterate over strongly
2095 connected components. */
2097 static void
2098 propagate_constants_topo (struct topo_info *topo)
2100 int i;
2102 for (i = topo->nnodes - 1; i >= 0; i--)
2104 struct cgraph_node *v, *node = topo->order[i];
2105 struct ipa_dfs_info *node_dfs_info;
2107 if (!cgraph_function_with_gimple_body_p (node))
2108 continue;
2110 node_dfs_info = (struct ipa_dfs_info *) node->symbol.aux;
2111 /* First, iteratively propagate within the strongly connected component
2112 until all lattices stabilize. */
2113 v = node_dfs_info->next_cycle;
2114 while (v)
2116 push_node_to_stack (topo, v);
2117 v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle;
2120 v = node;
2121 while (v)
2123 struct cgraph_edge *cs;
2125 for (cs = v->callees; cs; cs = cs->next_callee)
2126 if (edge_within_scc (cs)
2127 && propagate_constants_accross_call (cs))
2128 push_node_to_stack (topo, cs->callee);
2129 v = pop_node_from_stack (topo);
2132 /* Afterwards, propagate along edges leading out of the SCC, calculates
2133 the local effects of the discovered constants and all valid values to
2134 their topological sort. */
2135 v = node;
2136 while (v)
2138 struct cgraph_edge *cs;
2140 estimate_local_effects (v);
2141 add_all_node_vals_to_toposort (v);
2142 for (cs = v->callees; cs; cs = cs->next_callee)
2143 if (!edge_within_scc (cs))
2144 propagate_constants_accross_call (cs);
2146 v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle;
2152 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2153 the bigger one if otherwise. */
2155 static int
2156 safe_add (int a, int b)
2158 if (a > INT_MAX/2 || b > INT_MAX/2)
2159 return a > b ? a : b;
2160 else
2161 return a + b;
2165 /* Propagate the estimated effects of individual values along the topological
2166 from the dependent values to those they depend on. */
2168 static void
2169 propagate_effects (void)
2171 struct ipcp_value *base;
2173 for (base = values_topo; base; base = base->topo_next)
2175 struct ipcp_value_source *src;
2176 struct ipcp_value *val;
2177 int time = 0, size = 0;
2179 for (val = base; val; val = val->scc_next)
2181 time = safe_add (time,
2182 val->local_time_benefit + val->prop_time_benefit);
2183 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2186 for (val = base; val; val = val->scc_next)
2187 for (src = val->sources; src; src = src->next)
2188 if (src->val
2189 && cgraph_maybe_hot_edge_p (src->cs))
2191 src->val->prop_time_benefit = safe_add (time,
2192 src->val->prop_time_benefit);
2193 src->val->prop_size_cost = safe_add (size,
2194 src->val->prop_size_cost);
2200 /* Propagate constants, binfos and their effects from the summaries
2201 interprocedurally. */
2203 static void
2204 ipcp_propagate_stage (struct topo_info *topo)
2206 struct cgraph_node *node;
2208 if (dump_file)
2209 fprintf (dump_file, "\n Propagating constants:\n\n");
2211 if (in_lto_p)
2212 ipa_update_after_lto_read ();
2215 FOR_EACH_DEFINED_FUNCTION (node)
2217 struct ipa_node_params *info = IPA_NODE_REF (node);
2219 determine_versionability (node);
2220 if (cgraph_function_with_gimple_body_p (node))
2222 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2223 ipa_get_param_count (info));
2224 initialize_node_lattices (node);
2226 if (node->count > max_count)
2227 max_count = node->count;
2228 overall_size += inline_summary (node)->self_size;
2231 max_new_size = overall_size;
2232 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2233 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2234 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2236 if (dump_file)
2237 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2238 overall_size, max_new_size);
2240 propagate_constants_topo (topo);
2241 #ifdef ENABLE_CHECKING
2242 ipcp_verify_propagated_values ();
2243 #endif
2244 propagate_effects ();
2246 if (dump_file)
2248 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2249 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2253 /* Discover newly direct outgoing edges from NODE which is a new clone with
2254 known KNOWN_VALS and make them direct. */
2256 static void
2257 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2258 vec<tree> known_vals)
2260 struct cgraph_edge *ie, *next_ie;
2261 bool found = false;
2263 for (ie = node->indirect_calls; ie; ie = next_ie)
2265 tree target;
2267 next_ie = ie->next_callee;
2268 target = ipa_get_indirect_edge_target (ie, known_vals, vNULL, vNULL);
2269 if (target)
2271 ipa_make_edge_direct_to_target (ie, target);
2272 found = true;
2275 /* Turning calls to direct calls will improve overall summary. */
2276 if (found)
2277 inline_update_overall_summary (node);
2280 /* Vector of pointers which for linked lists of clones of an original crgaph
2281 edge. */
2283 static vec<cgraph_edge_p> next_edge_clone;
2285 static inline void
2286 grow_next_edge_clone_vector (void)
2288 if (next_edge_clone.length ()
2289 <= (unsigned) cgraph_edge_max_uid)
2290 next_edge_clone.safe_grow_cleared (cgraph_edge_max_uid + 1);
2293 /* Edge duplication hook to grow the appropriate linked list in
2294 next_edge_clone. */
2296 static void
2297 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2298 __attribute__((unused)) void *data)
2300 grow_next_edge_clone_vector ();
2301 next_edge_clone[dst->uid] = next_edge_clone[src->uid];
2302 next_edge_clone[src->uid] = dst;
2305 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2306 parameter with the given INDEX. */
2308 static tree
2309 get_clone_agg_value (struct cgraph_node *node, HOST_WIDEST_INT offset,
2310 int index)
2312 struct ipa_agg_replacement_value *aggval;
2314 aggval = ipa_get_agg_replacements_for_node (node);
2315 while (aggval)
2317 if (aggval->offset == offset
2318 && aggval->index == index)
2319 return aggval->value;
2320 aggval = aggval->next;
2322 return NULL_TREE;
2325 /* Return true if edge CS does bring about the value described by SRC. */
2327 static bool
2328 cgraph_edge_brings_value_p (struct cgraph_edge *cs,
2329 struct ipcp_value_source *src)
2331 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2332 struct ipa_node_params *dst_info = IPA_NODE_REF (cs->callee);
2334 if ((dst_info->ipcp_orig_node && !dst_info->is_all_contexts_clone)
2335 || caller_info->node_dead)
2336 return false;
2337 if (!src->val)
2338 return true;
2340 if (caller_info->ipcp_orig_node)
2342 tree t;
2343 if (src->offset == -1)
2344 t = caller_info->known_vals[src->index];
2345 else
2346 t = get_clone_agg_value (cs->caller, src->offset, src->index);
2347 return (t != NULL_TREE
2348 && values_equal_for_ipcp_p (src->val->value, t));
2350 else
2352 struct ipcp_agg_lattice *aglat;
2353 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
2354 src->index);
2355 if (src->offset == -1)
2356 return (ipa_lat_is_single_const (&plats->itself)
2357 && values_equal_for_ipcp_p (src->val->value,
2358 plats->itself.values->value));
2359 else
2361 if (plats->aggs_bottom || plats->aggs_contain_variable)
2362 return false;
2363 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2364 if (aglat->offset == src->offset)
2365 return (ipa_lat_is_single_const (aglat)
2366 && values_equal_for_ipcp_p (src->val->value,
2367 aglat->values->value));
2369 return false;
2373 /* Get the next clone in the linked list of clones of an edge. */
2375 static inline struct cgraph_edge *
2376 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
2378 return next_edge_clone[cs->uid];
2381 /* Given VAL, iterate over all its sources and if they still hold, add their
2382 edge frequency and their number into *FREQUENCY and *CALLER_COUNT
2383 respectively. */
2385 static bool
2386 get_info_about_necessary_edges (struct ipcp_value *val, int *freq_sum,
2387 gcov_type *count_sum, int *caller_count)
2389 struct ipcp_value_source *src;
2390 int freq = 0, count = 0;
2391 gcov_type cnt = 0;
2392 bool hot = false;
2394 for (src = val->sources; src; src = src->next)
2396 struct cgraph_edge *cs = src->cs;
2397 while (cs)
2399 if (cgraph_edge_brings_value_p (cs, src))
2401 count++;
2402 freq += cs->frequency;
2403 cnt += cs->count;
2404 hot |= cgraph_maybe_hot_edge_p (cs);
2406 cs = get_next_cgraph_edge_clone (cs);
2410 *freq_sum = freq;
2411 *count_sum = cnt;
2412 *caller_count = count;
2413 return hot;
2416 /* Return a vector of incoming edges that do bring value VAL. It is assumed
2417 their number is known and equal to CALLER_COUNT. */
2419 static vec<cgraph_edge_p>
2420 gather_edges_for_value (struct ipcp_value *val, int caller_count)
2422 struct ipcp_value_source *src;
2423 vec<cgraph_edge_p> ret;
2425 ret.create (caller_count);
2426 for (src = val->sources; src; src = src->next)
2428 struct cgraph_edge *cs = src->cs;
2429 while (cs)
2431 if (cgraph_edge_brings_value_p (cs, src))
2432 ret.quick_push (cs);
2433 cs = get_next_cgraph_edge_clone (cs);
2437 return ret;
2440 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
2441 Return it or NULL if for some reason it cannot be created. */
2443 static struct ipa_replace_map *
2444 get_replacement_map (tree value, tree parm)
2446 tree req_type = TREE_TYPE (parm);
2447 struct ipa_replace_map *replace_map;
2449 if (!useless_type_conversion_p (req_type, TREE_TYPE (value)))
2451 if (fold_convertible_p (req_type, value))
2452 value = fold_build1 (NOP_EXPR, req_type, value);
2453 else if (TYPE_SIZE (req_type) == TYPE_SIZE (TREE_TYPE (value)))
2454 value = fold_build1 (VIEW_CONVERT_EXPR, req_type, value);
2455 else
2457 if (dump_file)
2459 fprintf (dump_file, " const ");
2460 print_generic_expr (dump_file, value, 0);
2461 fprintf (dump_file, " can't be converted to param ");
2462 print_generic_expr (dump_file, parm, 0);
2463 fprintf (dump_file, "\n");
2465 return NULL;
2469 replace_map = ggc_alloc_ipa_replace_map ();
2470 if (dump_file)
2472 fprintf (dump_file, " replacing param ");
2473 print_generic_expr (dump_file, parm, 0);
2474 fprintf (dump_file, " with const ");
2475 print_generic_expr (dump_file, value, 0);
2476 fprintf (dump_file, "\n");
2478 replace_map->old_tree = parm;
2479 replace_map->new_tree = value;
2480 replace_map->replace_p = true;
2481 replace_map->ref_p = false;
2483 return replace_map;
2486 /* Dump new profiling counts */
2488 static void
2489 dump_profile_updates (struct cgraph_node *orig_node,
2490 struct cgraph_node *new_node)
2492 struct cgraph_edge *cs;
2494 fprintf (dump_file, " setting count of the specialized node to "
2495 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
2496 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2497 fprintf (dump_file, " edge to %s has count "
2498 HOST_WIDE_INT_PRINT_DEC "\n",
2499 cgraph_node_name (cs->callee), (HOST_WIDE_INT) cs->count);
2501 fprintf (dump_file, " setting count of the original node to "
2502 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
2503 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2504 fprintf (dump_file, " edge to %s is left with "
2505 HOST_WIDE_INT_PRINT_DEC "\n",
2506 cgraph_node_name (cs->callee), (HOST_WIDE_INT) cs->count);
2509 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
2510 their profile information to reflect this. */
2512 static void
2513 update_profiling_info (struct cgraph_node *orig_node,
2514 struct cgraph_node *new_node)
2516 struct cgraph_edge *cs;
2517 struct caller_statistics stats;
2518 gcov_type new_sum, orig_sum;
2519 gcov_type remainder, orig_node_count = orig_node->count;
2521 if (orig_node_count == 0)
2522 return;
2524 init_caller_stats (&stats);
2525 cgraph_for_node_and_aliases (orig_node, gather_caller_stats, &stats, false);
2526 orig_sum = stats.count_sum;
2527 init_caller_stats (&stats);
2528 cgraph_for_node_and_aliases (new_node, gather_caller_stats, &stats, false);
2529 new_sum = stats.count_sum;
2531 if (orig_node_count < orig_sum + new_sum)
2533 if (dump_file)
2534 fprintf (dump_file, " Problem: node %s/%i has too low count "
2535 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
2536 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
2537 cgraph_node_name (orig_node), orig_node->uid,
2538 (HOST_WIDE_INT) orig_node_count,
2539 (HOST_WIDE_INT) (orig_sum + new_sum));
2541 orig_node_count = (orig_sum + new_sum) * 12 / 10;
2542 if (dump_file)
2543 fprintf (dump_file, " proceeding by pretending it was "
2544 HOST_WIDE_INT_PRINT_DEC "\n",
2545 (HOST_WIDE_INT) orig_node_count);
2548 new_node->count = new_sum;
2549 remainder = orig_node_count - new_sum;
2550 orig_node->count = remainder;
2552 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2553 if (cs->frequency)
2554 cs->count = cs->count * (new_sum * REG_BR_PROB_BASE
2555 / orig_node_count) / REG_BR_PROB_BASE;
2556 else
2557 cs->count = 0;
2559 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2560 cs->count = cs->count * (remainder * REG_BR_PROB_BASE
2561 / orig_node_count) / REG_BR_PROB_BASE;
2563 if (dump_file)
2564 dump_profile_updates (orig_node, new_node);
2567 /* Update the respective profile of specialized NEW_NODE and the original
2568 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
2569 have been redirected to the specialized version. */
2571 static void
2572 update_specialized_profile (struct cgraph_node *new_node,
2573 struct cgraph_node *orig_node,
2574 gcov_type redirected_sum)
2576 struct cgraph_edge *cs;
2577 gcov_type new_node_count, orig_node_count = orig_node->count;
2579 if (dump_file)
2580 fprintf (dump_file, " the sum of counts of redirected edges is "
2581 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
2582 if (orig_node_count == 0)
2583 return;
2585 gcc_assert (orig_node_count >= redirected_sum);
2587 new_node_count = new_node->count;
2588 new_node->count += redirected_sum;
2589 orig_node->count -= redirected_sum;
2591 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2592 if (cs->frequency)
2593 cs->count += cs->count * redirected_sum / new_node_count;
2594 else
2595 cs->count = 0;
2597 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2599 gcov_type dec = cs->count * (redirected_sum * REG_BR_PROB_BASE
2600 / orig_node_count) / REG_BR_PROB_BASE;
2601 if (dec < cs->count)
2602 cs->count -= dec;
2603 else
2604 cs->count = 0;
2607 if (dump_file)
2608 dump_profile_updates (orig_node, new_node);
2611 /* Create a specialized version of NODE with known constants and types of
2612 parameters in KNOWN_VALS and redirect all edges in CALLERS to it. */
2614 static struct cgraph_node *
2615 create_specialized_node (struct cgraph_node *node,
2616 vec<tree> known_vals,
2617 struct ipa_agg_replacement_value *aggvals,
2618 vec<cgraph_edge_p> callers)
2620 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
2621 vec<ipa_replace_map_p, va_gc> *replace_trees = NULL;
2622 struct cgraph_node *new_node;
2623 int i, count = ipa_get_param_count (info);
2624 bitmap args_to_skip;
2626 gcc_assert (!info->ipcp_orig_node);
2628 if (node->local.can_change_signature)
2630 args_to_skip = BITMAP_GGC_ALLOC ();
2631 for (i = 0; i < count; i++)
2633 tree t = known_vals[i];
2635 if ((t && TREE_CODE (t) != TREE_BINFO)
2636 || !ipa_is_param_used (info, i))
2637 bitmap_set_bit (args_to_skip, i);
2640 else
2642 args_to_skip = NULL;
2643 if (dump_file && (dump_flags & TDF_DETAILS))
2644 fprintf (dump_file, " cannot change function signature\n");
2647 for (i = 0; i < count ; i++)
2649 tree t = known_vals[i];
2650 if (t && TREE_CODE (t) != TREE_BINFO)
2652 struct ipa_replace_map *replace_map;
2654 replace_map = get_replacement_map (t, ipa_get_param (info, i));
2655 if (replace_map)
2656 vec_safe_push (replace_trees, replace_map);
2660 new_node = cgraph_create_virtual_clone (node, callers, replace_trees,
2661 args_to_skip, "constprop");
2662 ipa_set_node_agg_value_chain (new_node, aggvals);
2663 if (dump_file && (dump_flags & TDF_DETAILS))
2665 fprintf (dump_file, " the new node is %s/%i.\n",
2666 cgraph_node_name (new_node), new_node->uid);
2667 if (aggvals)
2668 ipa_dump_agg_replacement_values (dump_file, aggvals);
2670 gcc_checking_assert (ipa_node_params_vector.exists ()
2671 && (ipa_node_params_vector.length ()
2672 > (unsigned) cgraph_max_uid));
2673 update_profiling_info (node, new_node);
2674 new_info = IPA_NODE_REF (new_node);
2675 new_info->ipcp_orig_node = node;
2676 new_info->known_vals = known_vals;
2678 ipcp_discover_new_direct_edges (new_node, known_vals);
2680 callers.release ();
2681 return new_node;
2684 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
2685 KNOWN_VALS with constants and types that are also known for all of the
2686 CALLERS. */
2688 static void
2689 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
2690 vec<tree> known_vals,
2691 vec<cgraph_edge_p> callers)
2693 struct ipa_node_params *info = IPA_NODE_REF (node);
2694 int i, count = ipa_get_param_count (info);
2696 for (i = 0; i < count ; i++)
2698 struct cgraph_edge *cs;
2699 tree newval = NULL_TREE;
2700 int j;
2702 if (ipa_get_scalar_lat (info, i)->bottom || known_vals[i])
2703 continue;
2705 FOR_EACH_VEC_ELT (callers, j, cs)
2707 struct ipa_jump_func *jump_func;
2708 tree t;
2710 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
2712 newval = NULL_TREE;
2713 break;
2715 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
2716 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
2717 if (!t
2718 || (newval
2719 && !values_equal_for_ipcp_p (t, newval)))
2721 newval = NULL_TREE;
2722 break;
2724 else
2725 newval = t;
2728 if (newval)
2730 if (dump_file && (dump_flags & TDF_DETAILS))
2732 fprintf (dump_file, " adding an extra known scalar value ");
2733 print_ipcp_constant_value (dump_file, newval);
2734 fprintf (dump_file, " for parameter ");
2735 print_generic_expr (dump_file, ipa_get_param (info, i), 0);
2736 fprintf (dump_file, "\n");
2739 known_vals[i] = newval;
2744 /* Go through PLATS and create a vector of values consisting of values and
2745 offsets (minus OFFSET) of lattices that contain only a single value. */
2747 static vec<ipa_agg_jf_item_t>
2748 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
2750 vec<ipa_agg_jf_item_t> res = vNULL;
2752 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
2753 return vNULL;
2755 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
2756 if (ipa_lat_is_single_const (aglat))
2758 struct ipa_agg_jf_item ti;
2759 ti.offset = aglat->offset - offset;
2760 ti.value = aglat->values->value;
2761 res.safe_push (ti);
2763 return res;
2766 /* Intersect all values in INTER with single value lattices in PLATS (while
2767 subtracting OFFSET). */
2769 static void
2770 intersect_with_plats (struct ipcp_param_lattices *plats,
2771 vec<ipa_agg_jf_item_t> *inter,
2772 HOST_WIDE_INT offset)
2774 struct ipcp_agg_lattice *aglat;
2775 struct ipa_agg_jf_item *item;
2776 int k;
2778 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
2780 inter->release ();
2781 return;
2784 aglat = plats->aggs;
2785 FOR_EACH_VEC_ELT (*inter, k, item)
2787 bool found = false;
2788 if (!item->value)
2789 continue;
2790 while (aglat)
2792 if (aglat->offset - offset > item->offset)
2793 break;
2794 if (aglat->offset - offset == item->offset)
2796 gcc_checking_assert (item->value);
2797 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
2798 found = true;
2799 break;
2801 aglat = aglat->next;
2803 if (!found)
2804 item->value = NULL_TREE;
2808 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
2809 vector result while subtracting OFFSET from the individual value offsets. */
2811 static vec<ipa_agg_jf_item_t>
2812 agg_replacements_to_vector (struct cgraph_node *node, int index,
2813 HOST_WIDE_INT offset)
2815 struct ipa_agg_replacement_value *av;
2816 vec<ipa_agg_jf_item_t> res = vNULL;
2818 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
2819 if (av->index == index
2820 && (av->offset - offset) >= 0)
2822 struct ipa_agg_jf_item item;
2823 gcc_checking_assert (av->value);
2824 item.offset = av->offset - offset;
2825 item.value = av->value;
2826 res.safe_push (item);
2829 return res;
2832 /* Intersect all values in INTER with those that we have already scheduled to
2833 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
2834 (while subtracting OFFSET). */
2836 static void
2837 intersect_with_agg_replacements (struct cgraph_node *node, int index,
2838 vec<ipa_agg_jf_item_t> *inter,
2839 HOST_WIDE_INT offset)
2841 struct ipa_agg_replacement_value *srcvals;
2842 struct ipa_agg_jf_item *item;
2843 int i;
2845 srcvals = ipa_get_agg_replacements_for_node (node);
2846 if (!srcvals)
2848 inter->release ();
2849 return;
2852 FOR_EACH_VEC_ELT (*inter, i, item)
2854 struct ipa_agg_replacement_value *av;
2855 bool found = false;
2856 if (!item->value)
2857 continue;
2858 for (av = srcvals; av; av = av->next)
2860 gcc_checking_assert (av->value);
2861 if (av->index == index
2862 && av->offset - offset == item->offset)
2864 if (values_equal_for_ipcp_p (item->value, av->value))
2865 found = true;
2866 break;
2869 if (!found)
2870 item->value = NULL_TREE;
2874 /* Intersect values in INTER with aggregate values that come along edge CS to
2875 parameter number INDEX and return it. If INTER does not actually exist yet,
2876 copy all incoming values to it. If we determine we ended up with no values
2877 whatsoever, return a released vector. */
2879 static vec<ipa_agg_jf_item_t>
2880 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
2881 vec<ipa_agg_jf_item_t> inter)
2883 struct ipa_jump_func *jfunc;
2884 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
2885 if (jfunc->type == IPA_JF_PASS_THROUGH
2886 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2888 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2889 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2891 if (caller_info->ipcp_orig_node)
2893 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
2894 struct ipcp_param_lattices *orig_plats;
2895 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
2896 src_idx);
2897 if (agg_pass_through_permissible_p (orig_plats, jfunc))
2899 if (!inter.exists ())
2900 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
2901 else
2902 intersect_with_agg_replacements (cs->caller, src_idx,
2903 &inter, 0);
2906 else
2908 struct ipcp_param_lattices *src_plats;
2909 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2910 if (agg_pass_through_permissible_p (src_plats, jfunc))
2912 /* Currently we do not produce clobber aggregate jump
2913 functions, adjust when we do. */
2914 gcc_checking_assert (!jfunc->agg.items);
2915 if (!inter.exists ())
2916 inter = copy_plats_to_inter (src_plats, 0);
2917 else
2918 intersect_with_plats (src_plats, &inter, 0);
2922 else if (jfunc->type == IPA_JF_ANCESTOR
2923 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2925 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2926 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2927 struct ipcp_param_lattices *src_plats;
2928 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
2930 if (caller_info->ipcp_orig_node)
2932 if (!inter.exists ())
2933 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
2934 else
2935 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
2936 delta);
2938 else
2940 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
2941 /* Currently we do not produce clobber aggregate jump
2942 functions, adjust when we do. */
2943 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
2944 if (!inter.exists ())
2945 inter = copy_plats_to_inter (src_plats, delta);
2946 else
2947 intersect_with_plats (src_plats, &inter, delta);
2950 else if (jfunc->agg.items)
2952 struct ipa_agg_jf_item *item;
2953 int k;
2955 if (!inter.exists ())
2956 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
2957 inter.safe_push ((*jfunc->agg.items)[i]);
2958 else
2959 FOR_EACH_VEC_ELT (inter, k, item)
2961 int l = 0;
2962 bool found = false;;
2964 if (!item->value)
2965 continue;
2967 while ((unsigned) l < jfunc->agg.items->length ())
2969 struct ipa_agg_jf_item *ti;
2970 ti = &(*jfunc->agg.items)[l];
2971 if (ti->offset > item->offset)
2972 break;
2973 if (ti->offset == item->offset)
2975 gcc_checking_assert (ti->value);
2976 if (values_equal_for_ipcp_p (item->value,
2977 ti->value))
2978 found = true;
2979 break;
2981 l++;
2983 if (!found)
2984 item->value = NULL;
2987 else
2989 inter.release();
2990 return vec<ipa_agg_jf_item_t>();
2992 return inter;
2995 /* Look at edges in CALLERS and collect all known aggregate values that arrive
2996 from all of them. */
2998 static struct ipa_agg_replacement_value *
2999 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3000 vec<cgraph_edge_p> callers)
3002 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3003 struct ipa_agg_replacement_value *res = NULL;
3004 struct cgraph_edge *cs;
3005 int i, j, count = ipa_get_param_count (dest_info);
3007 FOR_EACH_VEC_ELT (callers, j, cs)
3009 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3010 if (c < count)
3011 count = c;
3014 for (i = 0; i < count ; i++)
3016 struct cgraph_edge *cs;
3017 vec<ipa_agg_jf_item_t> inter = vNULL;
3018 struct ipa_agg_jf_item *item;
3019 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3020 int j;
3022 /* Among other things, the following check should deal with all by_ref
3023 mismatches. */
3024 if (plats->aggs_bottom)
3025 continue;
3027 FOR_EACH_VEC_ELT (callers, j, cs)
3029 inter = intersect_aggregates_with_edge (cs, i, inter);
3031 if (!inter.exists ())
3032 goto next_param;
3035 FOR_EACH_VEC_ELT (inter, j, item)
3037 struct ipa_agg_replacement_value *v;
3039 if (!item->value)
3040 continue;
3042 v = ggc_alloc_ipa_agg_replacement_value ();
3043 v->index = i;
3044 v->offset = item->offset;
3045 v->value = item->value;
3046 v->by_ref = plats->aggs_by_ref;
3047 v->next = res;
3048 res = v;
3051 next_param:
3052 if (inter.exists ())
3053 inter.release ();
3055 return res;
3058 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3060 static struct ipa_agg_replacement_value *
3061 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function_t> known_aggs)
3063 struct ipa_agg_replacement_value *res = NULL;
3064 struct ipa_agg_jump_function *aggjf;
3065 struct ipa_agg_jf_item *item;
3066 int i, j;
3068 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3069 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3071 struct ipa_agg_replacement_value *v;
3072 v = ggc_alloc_ipa_agg_replacement_value ();
3073 v->index = i;
3074 v->offset = item->offset;
3075 v->value = item->value;
3076 v->by_ref = aggjf->by_ref;
3077 v->next = res;
3078 res = v;
3080 return res;
3083 /* Determine whether CS also brings all scalar values that the NODE is
3084 specialized for. */
3086 static bool
3087 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3088 struct cgraph_node *node)
3090 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3091 int count = ipa_get_param_count (dest_info);
3092 struct ipa_node_params *caller_info;
3093 struct ipa_edge_args *args;
3094 int i;
3096 caller_info = IPA_NODE_REF (cs->caller);
3097 args = IPA_EDGE_REF (cs);
3098 for (i = 0; i < count; i++)
3100 struct ipa_jump_func *jump_func;
3101 tree val, t;
3103 val = dest_info->known_vals[i];
3104 if (!val)
3105 continue;
3107 if (i >= ipa_get_cs_argument_count (args))
3108 return false;
3109 jump_func = ipa_get_ith_jump_func (args, i);
3110 t = ipa_value_from_jfunc (caller_info, jump_func);
3111 if (!t || !values_equal_for_ipcp_p (val, t))
3112 return false;
3114 return true;
3117 /* Determine whether CS also brings all aggregate values that NODE is
3118 specialized for. */
3119 static bool
3120 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3121 struct cgraph_node *node)
3123 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3124 struct ipa_node_params *orig_node_info;
3125 struct ipa_agg_replacement_value *aggval;
3126 int i, ec, count;
3128 aggval = ipa_get_agg_replacements_for_node (node);
3129 if (!aggval)
3130 return true;
3132 count = ipa_get_param_count (IPA_NODE_REF (node));
3133 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3134 if (ec < count)
3135 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3136 if (aggval->index >= ec)
3137 return false;
3139 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3140 if (orig_caller_info->ipcp_orig_node)
3141 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3143 for (i = 0; i < count; i++)
3145 static vec<ipa_agg_jf_item_t> values = vec<ipa_agg_jf_item_t>();
3146 struct ipcp_param_lattices *plats;
3147 bool interesting = false;
3148 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3149 if (aggval->index == i)
3151 interesting = true;
3152 break;
3154 if (!interesting)
3155 continue;
3157 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3158 if (plats->aggs_bottom)
3159 return false;
3161 values = intersect_aggregates_with_edge (cs, i, values);
3162 if (!values.exists())
3163 return false;
3165 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3166 if (aggval->index == i)
3168 struct ipa_agg_jf_item *item;
3169 int j;
3170 bool found = false;
3171 FOR_EACH_VEC_ELT (values, j, item)
3172 if (item->value
3173 && item->offset == av->offset
3174 && values_equal_for_ipcp_p (item->value, av->value))
3175 found = true;
3176 if (!found)
3178 values.release();
3179 return false;
3183 return true;
3186 /* Given an original NODE and a VAL for which we have already created a
3187 specialized clone, look whether there are incoming edges that still lead
3188 into the old node but now also bring the requested value and also conform to
3189 all other criteria such that they can be redirected the the special node.
3190 This function can therefore redirect the final edge in a SCC. */
3192 static void
3193 perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val)
3195 struct ipcp_value_source *src;
3196 gcov_type redirected_sum = 0;
3198 for (src = val->sources; src; src = src->next)
3200 struct cgraph_edge *cs = src->cs;
3201 while (cs)
3203 enum availability availability;
3204 struct cgraph_node *dst = cgraph_function_node (cs->callee,
3205 &availability);
3206 if ((dst == node || IPA_NODE_REF (dst)->is_all_contexts_clone)
3207 && availability > AVAIL_OVERWRITABLE
3208 && cgraph_edge_brings_value_p (cs, src))
3210 if (cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3211 && cgraph_edge_brings_all_agg_vals_for_node (cs,
3212 val->spec_node))
3214 if (dump_file)
3215 fprintf (dump_file, " - adding an extra caller %s/%i"
3216 " of %s/%i\n",
3217 xstrdup (cgraph_node_name (cs->caller)),
3218 cs->caller->uid,
3219 xstrdup (cgraph_node_name (val->spec_node)),
3220 val->spec_node->uid);
3222 cgraph_redirect_edge_callee (cs, val->spec_node);
3223 redirected_sum += cs->count;
3226 cs = get_next_cgraph_edge_clone (cs);
3230 if (redirected_sum)
3231 update_specialized_profile (val->spec_node, node, redirected_sum);
3235 /* Copy KNOWN_BINFOS to KNOWN_VALS. */
3237 static void
3238 move_binfos_to_values (vec<tree> known_vals,
3239 vec<tree> known_binfos)
3241 tree t;
3242 int i;
3244 for (i = 0; known_binfos.iterate (i, &t); i++)
3245 if (t)
3246 known_vals[i] = t;
3249 /* Return true if there is a replacement equivalent to VALUE, INDEX and OFFSET
3250 among those in the AGGVALS list. */
3252 DEBUG_FUNCTION bool
3253 ipcp_val_in_agg_replacements_p (struct ipa_agg_replacement_value *aggvals,
3254 int index, HOST_WIDE_INT offset, tree value)
3256 while (aggvals)
3258 if (aggvals->index == index
3259 && aggvals->offset == offset
3260 && values_equal_for_ipcp_p (aggvals->value, value))
3261 return true;
3262 aggvals = aggvals->next;
3264 return false;
3267 /* Decide wheter to create a special version of NODE for value VAL of parameter
3268 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
3269 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
3270 KNOWN_BINFOS and KNOWN_AGGS describe the other already known values. */
3272 static bool
3273 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
3274 struct ipcp_value *val, vec<tree> known_csts,
3275 vec<tree> known_binfos)
3277 struct ipa_agg_replacement_value *aggvals;
3278 int freq_sum, caller_count;
3279 gcov_type count_sum;
3280 vec<cgraph_edge_p> callers;
3281 vec<tree> kv;
3283 if (val->spec_node)
3285 perhaps_add_new_callers (node, val);
3286 return false;
3288 else if (val->local_size_cost + overall_size > max_new_size)
3290 if (dump_file && (dump_flags & TDF_DETAILS))
3291 fprintf (dump_file, " Ignoring candidate value because "
3292 "max_new_size would be reached with %li.\n",
3293 val->local_size_cost + overall_size);
3294 return false;
3296 else if (!get_info_about_necessary_edges (val, &freq_sum, &count_sum,
3297 &caller_count))
3298 return false;
3300 if (dump_file && (dump_flags & TDF_DETAILS))
3302 fprintf (dump_file, " - considering value ");
3303 print_ipcp_constant_value (dump_file, val->value);
3304 fprintf (dump_file, " for parameter ");
3305 print_generic_expr (dump_file, ipa_get_param (IPA_NODE_REF (node),
3306 index), 0);
3307 if (offset != -1)
3308 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
3309 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
3312 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
3313 freq_sum, count_sum,
3314 val->local_size_cost)
3315 && !good_cloning_opportunity_p (node,
3316 val->local_time_benefit
3317 + val->prop_time_benefit,
3318 freq_sum, count_sum,
3319 val->local_size_cost
3320 + val->prop_size_cost))
3321 return false;
3323 if (dump_file)
3324 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
3325 cgraph_node_name (node), node->uid);
3327 callers = gather_edges_for_value (val, caller_count);
3328 kv = known_csts.copy ();
3329 move_binfos_to_values (kv, known_binfos);
3330 if (offset == -1)
3331 kv[index] = val->value;
3332 find_more_scalar_values_for_callers_subset (node, kv, callers);
3333 aggvals = find_aggregate_values_for_callers_subset (node, callers);
3334 gcc_checking_assert (offset == -1
3335 || ipcp_val_in_agg_replacements_p (aggvals, index,
3336 offset, val->value));
3337 val->spec_node = create_specialized_node (node, kv, aggvals, callers);
3338 overall_size += val->local_size_cost;
3340 /* TODO: If for some lattice there is only one other known value
3341 left, make a special node for it too. */
3343 return true;
3346 /* Decide whether and what specialized clones of NODE should be created. */
3348 static bool
3349 decide_whether_version_node (struct cgraph_node *node)
3351 struct ipa_node_params *info = IPA_NODE_REF (node);
3352 int i, count = ipa_get_param_count (info);
3353 vec<tree> known_csts, known_binfos;
3354 vec<ipa_agg_jump_function_t> known_aggs = vNULL;
3355 bool ret = false;
3357 if (count == 0)
3358 return false;
3360 if (dump_file && (dump_flags & TDF_DETAILS))
3361 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
3362 cgraph_node_name (node), node->uid);
3364 gather_context_independent_values (info, &known_csts, &known_binfos,
3365 info->do_clone_for_all_contexts ? &known_aggs
3366 : NULL, NULL);
3368 for (i = 0; i < count ;i++)
3370 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3371 struct ipcp_lattice *lat = &plats->itself;
3372 struct ipcp_value *val;
3374 if (!lat->bottom
3375 && !known_csts[i]
3376 && !known_binfos[i])
3377 for (val = lat->values; val; val = val->next)
3378 ret |= decide_about_value (node, i, -1, val, known_csts,
3379 known_binfos);
3381 if (!plats->aggs_bottom)
3383 struct ipcp_agg_lattice *aglat;
3384 struct ipcp_value *val;
3385 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3386 if (!aglat->bottom && aglat->values
3387 /* If the following is false, the one value is in
3388 known_aggs. */
3389 && (plats->aggs_contain_variable
3390 || !ipa_lat_is_single_const (aglat)))
3391 for (val = aglat->values; val; val = val->next)
3392 ret |= decide_about_value (node, i, aglat->offset, val,
3393 known_csts, known_binfos);
3395 info = IPA_NODE_REF (node);
3398 if (info->do_clone_for_all_contexts)
3400 struct cgraph_node *clone;
3401 vec<cgraph_edge_p> callers;
3403 if (dump_file)
3404 fprintf (dump_file, " - Creating a specialized node of %s/%i "
3405 "for all known contexts.\n", cgraph_node_name (node),
3406 node->uid);
3408 callers = collect_callers_of_node (node);
3409 move_binfos_to_values (known_csts, known_binfos);
3410 clone = create_specialized_node (node, known_csts,
3411 known_aggs_to_agg_replacement_list (known_aggs),
3412 callers);
3413 info = IPA_NODE_REF (node);
3414 info->do_clone_for_all_contexts = false;
3415 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
3416 for (i = 0; i < count ; i++)
3417 vec_free (known_aggs[i].items);
3418 known_aggs.release ();
3419 ret = true;
3421 else
3422 known_csts.release ();
3424 known_binfos.release ();
3425 return ret;
3428 /* Transitively mark all callees of NODE within the same SCC as not dead. */
3430 static void
3431 spread_undeadness (struct cgraph_node *node)
3433 struct cgraph_edge *cs;
3435 for (cs = node->callees; cs; cs = cs->next_callee)
3436 if (edge_within_scc (cs))
3438 struct cgraph_node *callee;
3439 struct ipa_node_params *info;
3441 callee = cgraph_function_node (cs->callee, NULL);
3442 info = IPA_NODE_REF (callee);
3444 if (info->node_dead)
3446 info->node_dead = 0;
3447 spread_undeadness (callee);
3452 /* Return true if NODE has a caller from outside of its SCC that is not
3453 dead. Worker callback for cgraph_for_node_and_aliases. */
3455 static bool
3456 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
3457 void *data ATTRIBUTE_UNUSED)
3459 struct cgraph_edge *cs;
3461 for (cs = node->callers; cs; cs = cs->next_caller)
3462 if (cs->caller->thunk.thunk_p
3463 && cgraph_for_node_and_aliases (cs->caller,
3464 has_undead_caller_from_outside_scc_p,
3465 NULL, true))
3466 return true;
3467 else if (!edge_within_scc (cs)
3468 && !IPA_NODE_REF (cs->caller)->node_dead)
3469 return true;
3470 return false;
3474 /* Identify nodes within the same SCC as NODE which are no longer needed
3475 because of new clones and will be removed as unreachable. */
3477 static void
3478 identify_dead_nodes (struct cgraph_node *node)
3480 struct cgraph_node *v;
3481 for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
3482 if (cgraph_will_be_removed_from_program_if_no_direct_calls (v)
3483 && !cgraph_for_node_and_aliases (v,
3484 has_undead_caller_from_outside_scc_p,
3485 NULL, true))
3486 IPA_NODE_REF (v)->node_dead = 1;
3488 for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
3489 if (!IPA_NODE_REF (v)->node_dead)
3490 spread_undeadness (v);
3492 if (dump_file && (dump_flags & TDF_DETAILS))
3494 for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
3495 if (IPA_NODE_REF (v)->node_dead)
3496 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
3497 cgraph_node_name (v), v->uid);
3501 /* The decision stage. Iterate over the topological order of call graph nodes
3502 TOPO and make specialized clones if deemed beneficial. */
3504 static void
3505 ipcp_decision_stage (struct topo_info *topo)
3507 int i;
3509 if (dump_file)
3510 fprintf (dump_file, "\nIPA decision stage:\n\n");
3512 for (i = topo->nnodes - 1; i >= 0; i--)
3514 struct cgraph_node *node = topo->order[i];
3515 bool change = false, iterate = true;
3517 while (iterate)
3519 struct cgraph_node *v;
3520 iterate = false;
3521 for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
3522 if (cgraph_function_with_gimple_body_p (v)
3523 && ipcp_versionable_function_p (v))
3524 iterate |= decide_whether_version_node (v);
3526 change |= iterate;
3528 if (change)
3529 identify_dead_nodes (node);
3533 /* The IPCP driver. */
3535 static unsigned int
3536 ipcp_driver (void)
3538 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
3539 struct topo_info topo;
3541 ipa_check_create_node_params ();
3542 ipa_check_create_edge_args ();
3543 grow_next_edge_clone_vector ();
3544 edge_duplication_hook_holder =
3545 cgraph_add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
3546 ipcp_values_pool = create_alloc_pool ("IPA-CP values",
3547 sizeof (struct ipcp_value), 32);
3548 ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources",
3549 sizeof (struct ipcp_value_source), 64);
3550 ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices",
3551 sizeof (struct ipcp_agg_lattice),
3552 32);
3553 if (dump_file)
3555 fprintf (dump_file, "\nIPA structures before propagation:\n");
3556 if (dump_flags & TDF_DETAILS)
3557 ipa_print_all_params (dump_file);
3558 ipa_print_all_jump_functions (dump_file);
3561 /* Topological sort. */
3562 build_toporder_info (&topo);
3563 /* Do the interprocedural propagation. */
3564 ipcp_propagate_stage (&topo);
3565 /* Decide what constant propagation and cloning should be performed. */
3566 ipcp_decision_stage (&topo);
3568 /* Free all IPCP structures. */
3569 free_toporder_info (&topo);
3570 next_edge_clone.release ();
3571 cgraph_remove_edge_duplication_hook (edge_duplication_hook_holder);
3572 ipa_free_all_structures_after_ipa_cp ();
3573 if (dump_file)
3574 fprintf (dump_file, "\nIPA constant propagation end\n");
3575 return 0;
3578 /* Initialization and computation of IPCP data structures. This is the initial
3579 intraprocedural analysis of functions, which gathers information to be
3580 propagated later on. */
3582 static void
3583 ipcp_generate_summary (void)
3585 struct cgraph_node *node;
3587 if (dump_file)
3588 fprintf (dump_file, "\nIPA constant propagation start:\n");
3589 ipa_register_cgraph_hooks ();
3591 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3593 node->local.versionable
3594 = tree_versionable_function_p (node->symbol.decl);
3595 ipa_analyze_node (node);
3599 /* Write ipcp summary for nodes in SET. */
3601 static void
3602 ipcp_write_summary (void)
3604 ipa_prop_write_jump_functions ();
3607 /* Read ipcp summary. */
3609 static void
3610 ipcp_read_summary (void)
3612 ipa_prop_read_jump_functions ();
3615 /* Gate for IPCP optimization. */
3617 static bool
3618 cgraph_gate_cp (void)
3620 /* FIXME: We should remove the optimize check after we ensure we never run
3621 IPA passes when not optimizing. */
3622 return flag_ipa_cp && optimize;
3625 struct ipa_opt_pass_d pass_ipa_cp =
3628 IPA_PASS,
3629 "cp", /* name */
3630 OPTGROUP_NONE, /* optinfo_flags */
3631 cgraph_gate_cp, /* gate */
3632 ipcp_driver, /* execute */
3633 NULL, /* sub */
3634 NULL, /* next */
3635 0, /* static_pass_number */
3636 TV_IPA_CONSTANT_PROP, /* tv_id */
3637 0, /* properties_required */
3638 0, /* properties_provided */
3639 0, /* properties_destroyed */
3640 0, /* todo_flags_start */
3641 TODO_dump_symtab |
3642 TODO_remove_functions | TODO_ggc_collect /* todo_flags_finish */
3644 ipcp_generate_summary, /* generate_summary */
3645 ipcp_write_summary, /* write_summary */
3646 ipcp_read_summary, /* read_summary */
3647 ipa_prop_write_all_agg_replacement, /* write_optimization_summary */
3648 ipa_prop_read_all_agg_replacement, /* read_optimization_summary */
3649 NULL, /* stmt_fixup */
3650 0, /* TODOs */
3651 ipcp_transform_function, /* function_transform */
3652 NULL, /* variable_transform */