[Patch ARM Refactor Builtins 7/8] Use qualifiers arrays when initialising builtins...
[official-gcc.git] / gcc / ipa-cp.c
blobe598241c01d91e8dae3a7f6545753a545a9cb0b6
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2014 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "tree.h"
107 #include "gimple-fold.h"
108 #include "gimple-expr.h"
109 #include "target.h"
110 #include "predict.h"
111 #include "basic-block.h"
112 #include "vec.h"
113 #include "hash-map.h"
114 #include "is-a.h"
115 #include "plugin-api.h"
116 #include "hashtab.h"
117 #include "hash-set.h"
118 #include "machmode.h"
119 #include "tm.h"
120 #include "hard-reg-set.h"
121 #include "input.h"
122 #include "function.h"
123 #include "ipa-ref.h"
124 #include "cgraph.h"
125 #include "alloc-pool.h"
126 #include "ipa-prop.h"
127 #include "bitmap.h"
128 #include "tree-pass.h"
129 #include "flags.h"
130 #include "diagnostic.h"
131 #include "tree-pretty-print.h"
132 #include "tree-inline.h"
133 #include "params.h"
134 #include "ipa-inline.h"
135 #include "ipa-utils.h"
137 template <typename valtype> class ipcp_value;
139 /* Describes a particular source for an IPA-CP value. */
141 template <typename valtype>
142 class ipcp_value_source
144 public:
145 /* Aggregate offset of the source, negative if the source is scalar value of
146 the argument itself. */
147 HOST_WIDE_INT offset;
148 /* The incoming edge that brought the value. */
149 cgraph_edge *cs;
150 /* If the jump function that resulted into his value was a pass-through or an
151 ancestor, this is the ipcp_value of the caller from which the described
152 value has been derived. Otherwise it is NULL. */
153 ipcp_value<valtype> *val;
154 /* Next pointer in a linked list of sources of a value. */
155 ipcp_value_source *next;
156 /* If the jump function that resulted into his value was a pass-through or an
157 ancestor, this is the index of the parameter of the caller the jump
158 function references. */
159 int index;
162 /* Common ancestor for all ipcp_value instantiations. */
164 class ipcp_value_base
166 public:
167 /* Time benefit and size cost that specializing the function for this value
168 would bring about in this function alone. */
169 int local_time_benefit, local_size_cost;
170 /* Time benefit and size cost that specializing the function for this value
171 can bring about in it's callees (transitively). */
172 int prop_time_benefit, prop_size_cost;
175 /* Describes one particular value stored in struct ipcp_lattice. */
177 template <typename valtype>
178 class ipcp_value : public ipcp_value_base
180 public:
181 /* The actual value for the given parameter. */
182 valtype value;
183 /* The list of sources from which this value originates. */
184 ipcp_value_source <valtype> *sources;
185 /* Next pointers in a linked list of all values in a lattice. */
186 ipcp_value *next;
187 /* Next pointers in a linked list of values in a strongly connected component
188 of values. */
189 ipcp_value *scc_next;
190 /* Next pointers in a linked list of SCCs of values sorted topologically
191 according their sources. */
192 ipcp_value *topo_next;
193 /* A specialized node created for this value, NULL if none has been (so far)
194 created. */
195 cgraph_node *spec_node;
196 /* Depth first search number and low link for topological sorting of
197 values. */
198 int dfs, low_link;
199 /* True if this valye is currently on the topo-sort stack. */
200 bool on_stack;
202 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
203 HOST_WIDE_INT offset);
206 /* Lattice describing potential values of a formal parameter of a function, or
207 a part of an aggreagate. TOP is represented by a lattice with zero values
208 and with contains_variable and bottom flags cleared. BOTTOM is represented
209 by a lattice with the bottom flag set. In that case, values and
210 contains_variable flag should be disregarded. */
212 template <typename valtype>
213 class ipcp_lattice
215 public:
216 /* The list of known values and types in this lattice. Note that values are
217 not deallocated if a lattice is set to bottom because there may be value
218 sources referencing them. */
219 ipcp_value<valtype> *values;
220 /* Number of known values and types in this lattice. */
221 int values_count;
222 /* The lattice contains a variable component (in addition to values). */
223 bool contains_variable;
224 /* The value of the lattice is bottom (i.e. variable and unusable for any
225 propagation). */
226 bool bottom;
228 inline bool is_single_const ();
229 inline bool set_to_bottom ();
230 inline bool set_contains_variable ();
231 bool add_value (valtype newval, cgraph_edge *cs,
232 ipcp_value<valtype> *src_val = NULL,
233 int src_idx = 0, HOST_WIDE_INT offset = -1);
234 void print (FILE * f, bool dump_sources, bool dump_benefits);
237 /* Lattice of tree values with an offset to describe a part of an
238 aggregate. */
240 class ipcp_agg_lattice : public ipcp_lattice<tree>
242 public:
243 /* Offset that is being described by this lattice. */
244 HOST_WIDE_INT offset;
245 /* Size so that we don't have to re-compute it every time we traverse the
246 list. Must correspond to TYPE_SIZE of all lat values. */
247 HOST_WIDE_INT size;
248 /* Next element of the linked list. */
249 struct ipcp_agg_lattice *next;
252 /* Structure containing lattices for a parameter itself and for pieces of
253 aggregates that are passed in the parameter or by a reference in a parameter
254 plus some other useful flags. */
256 class ipcp_param_lattices
258 public:
259 /* Lattice describing the value of the parameter itself. */
260 ipcp_lattice<tree> itself;
261 /* Lattice describing the the polymorphic contexts of a parameter. */
262 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
263 /* Lattices describing aggregate parts. */
264 ipcp_agg_lattice *aggs;
265 /* Number of aggregate lattices */
266 int aggs_count;
267 /* True if aggregate data were passed by reference (as opposed to by
268 value). */
269 bool aggs_by_ref;
270 /* All aggregate lattices contain a variable component (in addition to
271 values). */
272 bool aggs_contain_variable;
273 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
274 for any propagation). */
275 bool aggs_bottom;
277 /* There is a virtual call based on this parameter. */
278 bool virt_call;
281 /* Allocation pools for values and their sources in ipa-cp. */
283 alloc_pool ipcp_cst_values_pool;
284 alloc_pool ipcp_poly_ctx_values_pool;
285 alloc_pool ipcp_sources_pool;
286 alloc_pool ipcp_agg_lattice_pool;
288 /* Maximal count found in program. */
290 static gcov_type max_count;
292 /* Original overall size of the program. */
294 static long overall_size, max_new_size;
296 /* Return the param lattices structure corresponding to the Ith formal
297 parameter of the function described by INFO. */
298 static inline struct ipcp_param_lattices *
299 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
301 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
302 gcc_checking_assert (!info->ipcp_orig_node);
303 gcc_checking_assert (info->lattices);
304 return &(info->lattices[i]);
307 /* Return the lattice corresponding to the scalar value of the Ith formal
308 parameter of the function described by INFO. */
309 static inline ipcp_lattice<tree> *
310 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
312 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
313 return &plats->itself;
316 /* Return the lattice corresponding to the scalar value of the Ith formal
317 parameter of the function described by INFO. */
318 static inline ipcp_lattice<ipa_polymorphic_call_context> *
319 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
321 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
322 return &plats->ctxlat;
325 /* Return whether LAT is a lattice with a single constant and without an
326 undefined value. */
328 template <typename valtype>
329 inline bool
330 ipcp_lattice<valtype>::is_single_const ()
332 if (bottom || contains_variable || values_count != 1)
333 return false;
334 else
335 return true;
338 /* Print V which is extracted from a value in a lattice to F. */
340 static void
341 print_ipcp_constant_value (FILE * f, tree v)
343 if (TREE_CODE (v) == ADDR_EXPR
344 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
346 fprintf (f, "& ");
347 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
349 else
350 print_generic_expr (f, v, 0);
353 /* Print V which is extracted from a value in a lattice to F. */
355 static void
356 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
358 v.dump(f, false);
361 /* Print a lattice LAT to F. */
363 template <typename valtype>
364 void
365 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
367 ipcp_value<valtype> *val;
368 bool prev = false;
370 if (bottom)
372 fprintf (f, "BOTTOM\n");
373 return;
376 if (!values_count && !contains_variable)
378 fprintf (f, "TOP\n");
379 return;
382 if (contains_variable)
384 fprintf (f, "VARIABLE");
385 prev = true;
386 if (dump_benefits)
387 fprintf (f, "\n");
390 for (val = values; val; val = val->next)
392 if (dump_benefits && prev)
393 fprintf (f, " ");
394 else if (!dump_benefits && prev)
395 fprintf (f, ", ");
396 else
397 prev = true;
399 print_ipcp_constant_value (f, val->value);
401 if (dump_sources)
403 ipcp_value_source<valtype> *s;
405 fprintf (f, " [from:");
406 for (s = val->sources; s; s = s->next)
407 fprintf (f, " %i(%i)", s->cs->caller->order,
408 s->cs->frequency);
409 fprintf (f, "]");
412 if (dump_benefits)
413 fprintf (f, " [loc_time: %i, loc_size: %i, "
414 "prop_time: %i, prop_size: %i]\n",
415 val->local_time_benefit, val->local_size_cost,
416 val->prop_time_benefit, val->prop_size_cost);
418 if (!dump_benefits)
419 fprintf (f, "\n");
422 /* Print all ipcp_lattices of all functions to F. */
424 static void
425 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
427 struct cgraph_node *node;
428 int i, count;
430 fprintf (f, "\nLattices:\n");
431 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
433 struct ipa_node_params *info;
435 info = IPA_NODE_REF (node);
436 fprintf (f, " Node: %s/%i:\n", node->name (),
437 node->order);
438 count = ipa_get_param_count (info);
439 for (i = 0; i < count; i++)
441 struct ipcp_agg_lattice *aglat;
442 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
443 fprintf (f, " param [%d]: ", i);
444 plats->itself.print (f, dump_sources, dump_benefits);
445 fprintf (f, " ctxs: ");
446 plats->ctxlat.print (f, dump_sources, dump_benefits);
447 if (plats->virt_call)
448 fprintf (f, " virt_call flag set\n");
450 if (plats->aggs_bottom)
452 fprintf (f, " AGGS BOTTOM\n");
453 continue;
455 if (plats->aggs_contain_variable)
456 fprintf (f, " AGGS VARIABLE\n");
457 for (aglat = plats->aggs; aglat; aglat = aglat->next)
459 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
460 plats->aggs_by_ref ? "ref " : "", aglat->offset);
461 aglat->print (f, dump_sources, dump_benefits);
467 /* Determine whether it is at all technically possible to create clones of NODE
468 and store this information in the ipa_node_params structure associated
469 with NODE. */
471 static void
472 determine_versionability (struct cgraph_node *node)
474 const char *reason = NULL;
476 /* There are a number of generic reasons functions cannot be versioned. We
477 also cannot remove parameters if there are type attributes such as fnspec
478 present. */
479 if (node->alias || node->thunk.thunk_p)
480 reason = "alias or thunk";
481 else if (!node->local.versionable)
482 reason = "not a tree_versionable_function";
483 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
484 reason = "insufficient body availability";
485 else if (!opt_for_fn (node->decl, optimize)
486 || !opt_for_fn (node->decl, flag_ipa_cp))
487 reason = "non-optimized function";
488 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
490 /* Ideally we should clone the SIMD clones themselves and create
491 vector copies of them, so IPA-cp and SIMD clones can happily
492 coexist, but that may not be worth the effort. */
493 reason = "function has SIMD clones";
495 /* Don't clone decls local to a comdat group; it breaks and for C++
496 decloned constructors, inlining is always better anyway. */
497 else if (node->comdat_local_p ())
498 reason = "comdat-local function";
500 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
501 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
502 node->name (), node->order, reason);
504 node->local.versionable = (reason == NULL);
507 /* Return true if it is at all technically possible to create clones of a
508 NODE. */
510 static bool
511 ipcp_versionable_function_p (struct cgraph_node *node)
513 return node->local.versionable;
516 /* Structure holding accumulated information about callers of a node. */
518 struct caller_statistics
520 gcov_type count_sum;
521 int n_calls, n_hot_calls, freq_sum;
524 /* Initialize fields of STAT to zeroes. */
526 static inline void
527 init_caller_stats (struct caller_statistics *stats)
529 stats->count_sum = 0;
530 stats->n_calls = 0;
531 stats->n_hot_calls = 0;
532 stats->freq_sum = 0;
535 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
536 non-thunk incoming edges to NODE. */
538 static bool
539 gather_caller_stats (struct cgraph_node *node, void *data)
541 struct caller_statistics *stats = (struct caller_statistics *) data;
542 struct cgraph_edge *cs;
544 for (cs = node->callers; cs; cs = cs->next_caller)
545 if (cs->caller->thunk.thunk_p)
546 cs->caller->call_for_symbol_thunks_and_aliases (gather_caller_stats,
547 stats, false);
548 else
550 stats->count_sum += cs->count;
551 stats->freq_sum += cs->frequency;
552 stats->n_calls++;
553 if (cs->maybe_hot_p ())
554 stats->n_hot_calls ++;
556 return false;
560 /* Return true if this NODE is viable candidate for cloning. */
562 static bool
563 ipcp_cloning_candidate_p (struct cgraph_node *node)
565 struct caller_statistics stats;
567 gcc_checking_assert (node->has_gimple_body_p ());
569 if (!flag_ipa_cp_clone)
571 if (dump_file)
572 fprintf (dump_file, "Not considering %s for cloning; "
573 "-fipa-cp-clone disabled.\n",
574 node->name ());
575 return false;
578 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
580 if (dump_file)
581 fprintf (dump_file, "Not considering %s for cloning; "
582 "optimizing it for size.\n",
583 node->name ());
584 return false;
587 init_caller_stats (&stats);
588 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
590 if (inline_summary (node)->self_size < stats.n_calls)
592 if (dump_file)
593 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
594 node->name ());
595 return true;
598 /* When profile is available and function is hot, propagate into it even if
599 calls seems cold; constant propagation can improve function's speed
600 significantly. */
601 if (max_count)
603 if (stats.count_sum > node->count * 90 / 100)
605 if (dump_file)
606 fprintf (dump_file, "Considering %s for cloning; "
607 "usually called directly.\n",
608 node->name ());
609 return true;
612 if (!stats.n_hot_calls)
614 if (dump_file)
615 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
616 node->name ());
617 return false;
619 if (dump_file)
620 fprintf (dump_file, "Considering %s for cloning.\n",
621 node->name ());
622 return true;
625 template <typename valtype>
626 class value_topo_info
628 public:
629 /* Head of the linked list of topologically sorted values. */
630 ipcp_value<valtype> *values_topo;
631 /* Stack for creating SCCs, represented by a linked list too. */
632 ipcp_value<valtype> *stack;
633 /* Counter driving the algorithm in add_val_to_toposort. */
634 int dfs_counter;
636 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
638 void add_val (ipcp_value<valtype> *cur_val);
639 void propagate_effects ();
642 /* Arrays representing a topological ordering of call graph nodes and a stack
643 of nodes used during constant propagation and also data required to perform
644 topological sort of values and propagation of benefits in the determined
645 order. */
647 class ipa_topo_info
649 public:
650 /* Array with obtained topological order of cgraph nodes. */
651 struct cgraph_node **order;
652 /* Stack of cgraph nodes used during propagation within SCC until all values
653 in the SCC stabilize. */
654 struct cgraph_node **stack;
655 int nnodes, stack_top;
657 value_topo_info<tree> constants;
658 value_topo_info<ipa_polymorphic_call_context> contexts;
660 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
661 constants ()
665 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
667 static void
668 build_toporder_info (struct ipa_topo_info *topo)
670 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
671 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
673 gcc_checking_assert (topo->stack_top == 0);
674 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
677 /* Free information about strongly connected components and the arrays in
678 TOPO. */
680 static void
681 free_toporder_info (struct ipa_topo_info *topo)
683 ipa_free_postorder_info ();
684 free (topo->order);
685 free (topo->stack);
688 /* Add NODE to the stack in TOPO, unless it is already there. */
690 static inline void
691 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
693 struct ipa_node_params *info = IPA_NODE_REF (node);
694 if (info->node_enqueued)
695 return;
696 info->node_enqueued = 1;
697 topo->stack[topo->stack_top++] = node;
700 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
701 is empty. */
703 static struct cgraph_node *
704 pop_node_from_stack (struct ipa_topo_info *topo)
706 if (topo->stack_top)
708 struct cgraph_node *node;
709 topo->stack_top--;
710 node = topo->stack[topo->stack_top];
711 IPA_NODE_REF (node)->node_enqueued = 0;
712 return node;
714 else
715 return NULL;
718 /* Set lattice LAT to bottom and return true if it previously was not set as
719 such. */
721 template <typename valtype>
722 inline bool
723 ipcp_lattice<valtype>::set_to_bottom ()
725 bool ret = !bottom;
726 bottom = true;
727 return ret;
730 /* Mark lattice as containing an unknown value and return true if it previously
731 was not marked as such. */
733 template <typename valtype>
734 inline bool
735 ipcp_lattice<valtype>::set_contains_variable ()
737 bool ret = !contains_variable;
738 contains_variable = true;
739 return ret;
742 /* Set all aggegate lattices in PLATS to bottom and return true if they were
743 not previously set as such. */
745 static inline bool
746 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
748 bool ret = !plats->aggs_bottom;
749 plats->aggs_bottom = true;
750 return ret;
753 /* Mark all aggegate lattices in PLATS as containing an unknown value and
754 return true if they were not previously marked as such. */
756 static inline bool
757 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
759 bool ret = !plats->aggs_contain_variable;
760 plats->aggs_contain_variable = true;
761 return ret;
764 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
765 return true is any of them has not been marked as such so far. */
767 static inline bool
768 set_all_contains_variable (struct ipcp_param_lattices *plats)
770 bool ret;
771 ret = plats->itself.set_contains_variable ();
772 ret |= plats->ctxlat.set_contains_variable ();
773 ret |= set_agg_lats_contain_variable (plats);
774 return ret;
777 /* Initialize ipcp_lattices. */
779 static void
780 initialize_node_lattices (struct cgraph_node *node)
782 struct ipa_node_params *info = IPA_NODE_REF (node);
783 struct cgraph_edge *ie;
784 bool disable = false, variable = false;
785 int i;
787 gcc_checking_assert (node->has_gimple_body_p ());
788 if (!cgraph_local_p (node))
790 /* When cloning is allowed, we can assume that externally visible
791 functions are not called. We will compensate this by cloning
792 later. */
793 if (ipcp_versionable_function_p (node)
794 && ipcp_cloning_candidate_p (node))
795 variable = true;
796 else
797 disable = true;
800 if (disable || variable)
802 for (i = 0; i < ipa_get_param_count (info) ; i++)
804 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
805 if (disable)
807 plats->itself.set_to_bottom ();
808 plats->ctxlat.set_to_bottom ();
809 set_agg_lats_to_bottom (plats);
811 else
812 set_all_contains_variable (plats);
814 if (dump_file && (dump_flags & TDF_DETAILS)
815 && !node->alias && !node->thunk.thunk_p)
816 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
817 node->name (), node->order,
818 disable ? "BOTTOM" : "VARIABLE");
821 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
822 if (ie->indirect_info->polymorphic
823 && ie->indirect_info->param_index >= 0)
825 gcc_checking_assert (ie->indirect_info->param_index >= 0);
826 ipa_get_parm_lattices (info,
827 ie->indirect_info->param_index)->virt_call = 1;
831 /* Return the result of a (possibly arithmetic) pass through jump function
832 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
833 determined or be considered an interprocedural invariant. */
835 static tree
836 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
838 tree restype, res;
840 gcc_checking_assert (is_gimple_ip_invariant (input));
841 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
842 return input;
844 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
845 == tcc_comparison)
846 restype = boolean_type_node;
847 else
848 restype = TREE_TYPE (input);
849 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
850 input, ipa_get_jf_pass_through_operand (jfunc));
852 if (res && !is_gimple_ip_invariant (res))
853 return NULL_TREE;
855 return res;
858 /* Return the result of an ancestor jump function JFUNC on the constant value
859 INPUT. Return NULL_TREE if that cannot be determined. */
861 static tree
862 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
864 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
865 if (TREE_CODE (input) == ADDR_EXPR)
867 tree t = TREE_OPERAND (input, 0);
868 t = build_ref_for_offset (EXPR_LOCATION (t), t,
869 ipa_get_jf_ancestor_offset (jfunc),
870 ptr_type_node, NULL, false);
871 return build_fold_addr_expr (t);
873 else
874 return NULL_TREE;
877 /* Determine whether JFUNC evaluates to a single known constant value and if
878 so, return it. Otherwise return NULL. INFO describes the caller node or
879 the one it is inlined to, so that pass-through jump functions can be
880 evaluated. */
882 tree
883 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
885 if (jfunc->type == IPA_JF_CONST)
886 return ipa_get_jf_constant (jfunc);
887 else if (jfunc->type == IPA_JF_PASS_THROUGH
888 || jfunc->type == IPA_JF_ANCESTOR)
890 tree input;
891 int idx;
893 if (jfunc->type == IPA_JF_PASS_THROUGH)
894 idx = ipa_get_jf_pass_through_formal_id (jfunc);
895 else
896 idx = ipa_get_jf_ancestor_formal_id (jfunc);
898 if (info->ipcp_orig_node)
899 input = info->known_csts[idx];
900 else
902 ipcp_lattice<tree> *lat;
904 if (!info->lattices)
906 gcc_checking_assert (!flag_ipa_cp);
907 return NULL_TREE;
909 lat = ipa_get_scalar_lat (info, idx);
910 if (!lat->is_single_const ())
911 return NULL_TREE;
912 input = lat->values->value;
915 if (!input)
916 return NULL_TREE;
918 if (jfunc->type == IPA_JF_PASS_THROUGH)
919 return ipa_get_jf_pass_through_result (jfunc, input);
920 else
921 return ipa_get_jf_ancestor_result (jfunc, input);
923 else
924 return NULL_TREE;
927 /* Determie whether JFUNC evaluates to single known polymorphic context, given
928 that INFO describes the caller node or the one it is inlined to, CS is the
929 call graph edge corresponding to JFUNC and CSIDX index of the described
930 parameter. */
932 ipa_polymorphic_call_context
933 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
934 ipa_jump_func *jfunc)
936 ipa_edge_args *args = IPA_EDGE_REF (cs);
937 ipa_polymorphic_call_context ctx;
938 ipa_polymorphic_call_context *edge_ctx
939 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
941 if (edge_ctx && !edge_ctx->useless_p ())
942 ctx = *edge_ctx;
944 if (jfunc->type == IPA_JF_PASS_THROUGH
945 || jfunc->type == IPA_JF_ANCESTOR)
947 ipa_polymorphic_call_context srcctx;
948 int srcidx;
949 bool type_preserved = true;
950 if (jfunc->type == IPA_JF_PASS_THROUGH)
952 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
953 return ctx;
954 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
955 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
957 else
959 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
960 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
962 if (info->ipcp_orig_node)
964 if (info->known_contexts.exists ())
965 srcctx = info->known_contexts[srcidx];
967 else
969 if (!info->lattices)
971 gcc_checking_assert (!flag_ipa_cp);
972 return ctx;
974 ipcp_lattice<ipa_polymorphic_call_context> *lat;
975 lat = ipa_get_poly_ctx_lat (info, srcidx);
976 if (!lat->is_single_const ())
977 return ctx;
978 srcctx = lat->values->value;
980 if (srcctx.useless_p ())
981 return ctx;
982 if (jfunc->type == IPA_JF_ANCESTOR)
983 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
984 if (!type_preserved)
985 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
986 srcctx.combine_with (ctx);
987 return srcctx;
990 return ctx;
993 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
994 bottom, not containing a variable component and without any known value at
995 the same time. */
997 DEBUG_FUNCTION void
998 ipcp_verify_propagated_values (void)
1000 struct cgraph_node *node;
1002 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1004 struct ipa_node_params *info = IPA_NODE_REF (node);
1005 int i, count = ipa_get_param_count (info);
1007 for (i = 0; i < count; i++)
1009 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1011 if (!lat->bottom
1012 && !lat->contains_variable
1013 && lat->values_count == 0)
1015 if (dump_file)
1017 symtab_node::dump_table (dump_file);
1018 fprintf (dump_file, "\nIPA lattices after constant "
1019 "propagation, before gcc_unreachable:\n");
1020 print_all_lattices (dump_file, true, false);
1023 gcc_unreachable ();
1029 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1031 static bool
1032 values_equal_for_ipcp_p (tree x, tree y)
1034 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1036 if (x == y)
1037 return true;
1039 if (TREE_CODE (x) == ADDR_EXPR
1040 && TREE_CODE (y) == ADDR_EXPR
1041 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1042 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1043 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1044 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1045 else
1046 return operand_equal_p (x, y, 0);
1049 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1051 static bool
1052 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1053 ipa_polymorphic_call_context y)
1055 return x.equal_to (y);
1059 /* Add a new value source to the value represented by THIS, marking that a
1060 value comes from edge CS and (if the underlying jump function is a
1061 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1062 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1063 scalar value of the parameter itself or the offset within an aggregate. */
1065 template <typename valtype>
1066 void
1067 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1068 int src_idx, HOST_WIDE_INT offset)
1070 ipcp_value_source<valtype> *src;
1072 src = new (pool_alloc (ipcp_sources_pool)) ipcp_value_source<valtype>;
1073 src->offset = offset;
1074 src->cs = cs;
1075 src->val = src_val;
1076 src->index = src_idx;
1078 src->next = sources;
1079 sources = src;
1082 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1083 SOURCE and clear all other fields. */
1085 static ipcp_value<tree> *
1086 allocate_and_init_ipcp_value (tree source)
1088 ipcp_value<tree> *val;
1090 val = new (pool_alloc (ipcp_cst_values_pool)) ipcp_value<tree>;
1091 memset (val, 0, sizeof (*val));
1092 val->value = source;
1093 return val;
1096 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1097 value to SOURCE and clear all other fields. */
1099 static ipcp_value<ipa_polymorphic_call_context> *
1100 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1102 ipcp_value<ipa_polymorphic_call_context> *val;
1104 val = new (pool_alloc (ipcp_poly_ctx_values_pool))
1105 ipcp_value<ipa_polymorphic_call_context>;
1106 memset (val, 0, sizeof (*val));
1107 val->value = source;
1108 return val;
1111 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1112 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1113 meaning. OFFSET -1 means the source is scalar and not a part of an
1114 aggregate. */
1116 template <typename valtype>
1117 bool
1118 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1119 ipcp_value<valtype> *src_val,
1120 int src_idx, HOST_WIDE_INT offset)
1122 ipcp_value<valtype> *val;
1124 if (bottom)
1125 return false;
1127 for (val = values; val; val = val->next)
1128 if (values_equal_for_ipcp_p (val->value, newval))
1130 if (ipa_edge_within_scc (cs))
1132 ipcp_value_source<valtype> *s;
1133 for (s = val->sources; s ; s = s->next)
1134 if (s->cs == cs)
1135 break;
1136 if (s)
1137 return false;
1140 val->add_source (cs, src_val, src_idx, offset);
1141 return false;
1144 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1146 /* We can only free sources, not the values themselves, because sources
1147 of other values in this this SCC might point to them. */
1148 for (val = values; val; val = val->next)
1150 while (val->sources)
1152 ipcp_value_source<valtype> *src = val->sources;
1153 val->sources = src->next;
1154 pool_free (ipcp_sources_pool, src);
1158 values = NULL;
1159 return set_to_bottom ();
1162 values_count++;
1163 val = allocate_and_init_ipcp_value (newval);
1164 val->add_source (cs, src_val, src_idx, offset);
1165 val->next = values;
1166 values = val;
1167 return true;
1170 /* Propagate values through a pass-through jump function JFUNC associated with
1171 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1172 is the index of the source parameter. */
1174 static bool
1175 propagate_vals_accross_pass_through (cgraph_edge *cs,
1176 ipa_jump_func *jfunc,
1177 ipcp_lattice<tree> *src_lat,
1178 ipcp_lattice<tree> *dest_lat,
1179 int src_idx)
1181 ipcp_value<tree> *src_val;
1182 bool ret = false;
1184 /* Do not create new values when propagating within an SCC because if there
1185 are arithmetic functions with circular dependencies, there is infinite
1186 number of them and we would just make lattices bottom. */
1187 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1188 && ipa_edge_within_scc (cs))
1189 ret = dest_lat->set_contains_variable ();
1190 else
1191 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1193 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1195 if (cstval)
1196 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1197 else
1198 ret |= dest_lat->set_contains_variable ();
1201 return ret;
1204 /* Propagate values through an ancestor jump function JFUNC associated with
1205 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1206 is the index of the source parameter. */
1208 static bool
1209 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1210 struct ipa_jump_func *jfunc,
1211 ipcp_lattice<tree> *src_lat,
1212 ipcp_lattice<tree> *dest_lat,
1213 int src_idx)
1215 ipcp_value<tree> *src_val;
1216 bool ret = false;
1218 if (ipa_edge_within_scc (cs))
1219 return dest_lat->set_contains_variable ();
1221 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1223 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1225 if (t)
1226 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1227 else
1228 ret |= dest_lat->set_contains_variable ();
1231 return ret;
1234 /* Propagate scalar values across jump function JFUNC that is associated with
1235 edge CS and put the values into DEST_LAT. */
1237 static bool
1238 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1239 struct ipa_jump_func *jfunc,
1240 ipcp_lattice<tree> *dest_lat)
1242 if (dest_lat->bottom)
1243 return false;
1245 if (jfunc->type == IPA_JF_CONST)
1247 tree val = ipa_get_jf_constant (jfunc);
1248 return dest_lat->add_value (val, cs, NULL, 0);
1250 else if (jfunc->type == IPA_JF_PASS_THROUGH
1251 || jfunc->type == IPA_JF_ANCESTOR)
1253 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1254 ipcp_lattice<tree> *src_lat;
1255 int src_idx;
1256 bool ret;
1258 if (jfunc->type == IPA_JF_PASS_THROUGH)
1259 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1260 else
1261 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1263 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1264 if (src_lat->bottom)
1265 return dest_lat->set_contains_variable ();
1267 /* If we would need to clone the caller and cannot, do not propagate. */
1268 if (!ipcp_versionable_function_p (cs->caller)
1269 && (src_lat->contains_variable
1270 || (src_lat->values_count > 1)))
1271 return dest_lat->set_contains_variable ();
1273 if (jfunc->type == IPA_JF_PASS_THROUGH)
1274 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1275 dest_lat, src_idx);
1276 else
1277 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1278 src_idx);
1280 if (src_lat->contains_variable)
1281 ret |= dest_lat->set_contains_variable ();
1283 return ret;
1286 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1287 use it for indirect inlining), we should propagate them too. */
1288 return dest_lat->set_contains_variable ();
1291 /* Propagate scalar values across jump function JFUNC that is associated with
1292 edge CS and describes argument IDX and put the values into DEST_LAT. */
1294 static bool
1295 propagate_context_accross_jump_function (cgraph_edge *cs,
1296 ipa_jump_func *jfunc, int idx,
1297 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1299 ipa_edge_args *args = IPA_EDGE_REF (cs);
1300 if (dest_lat->bottom)
1301 return false;
1302 bool ret = false;
1303 bool added_sth = false;
1304 bool type_preserved = true;
1306 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1307 = ipa_get_ith_polymorhic_call_context (args, idx);
1309 if (edge_ctx_ptr)
1310 edge_ctx = *edge_ctx_ptr;
1312 if (jfunc->type == IPA_JF_PASS_THROUGH
1313 || jfunc->type == IPA_JF_ANCESTOR)
1315 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1316 int src_idx;
1317 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1319 /* TODO: Once we figure out how to propagate speculations, it will
1320 probably be a good idea to switch to speculation if type_preserved is
1321 not set instead of punting. */
1322 if (jfunc->type == IPA_JF_PASS_THROUGH)
1324 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1325 goto prop_fail;
1326 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1327 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1329 else
1331 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1332 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1335 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1336 /* If we would need to clone the caller and cannot, do not propagate. */
1337 if (!ipcp_versionable_function_p (cs->caller)
1338 && (src_lat->contains_variable
1339 || (src_lat->values_count > 1)))
1340 goto prop_fail;
1342 ipcp_value<ipa_polymorphic_call_context> *src_val;
1343 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1345 ipa_polymorphic_call_context cur = src_val->value;
1347 if (!type_preserved)
1348 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1349 if (jfunc->type == IPA_JF_ANCESTOR)
1350 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1351 /* TODO: In cases we know how the context is going to be used,
1352 we can improve the result by passing proper OTR_TYPE. */
1353 cur.combine_with (edge_ctx);
1354 if (!cur.useless_p ())
1356 if (src_lat->contains_variable
1357 && !edge_ctx.equal_to (cur))
1358 ret |= dest_lat->set_contains_variable ();
1359 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1360 added_sth = true;
1366 prop_fail:
1367 if (!added_sth)
1369 if (!edge_ctx.useless_p ())
1370 ret |= dest_lat->add_value (edge_ctx, cs);
1371 else
1372 ret |= dest_lat->set_contains_variable ();
1375 return ret;
1378 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1379 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1380 other cases, return false). If there are no aggregate items, set
1381 aggs_by_ref to NEW_AGGS_BY_REF. */
1383 static bool
1384 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1385 bool new_aggs_by_ref)
1387 if (dest_plats->aggs)
1389 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1391 set_agg_lats_to_bottom (dest_plats);
1392 return true;
1395 else
1396 dest_plats->aggs_by_ref = new_aggs_by_ref;
1397 return false;
1400 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1401 already existing lattice for the given OFFSET and SIZE, marking all skipped
1402 lattices as containing variable and checking for overlaps. If there is no
1403 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1404 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1405 unless there are too many already. If there are two many, return false. If
1406 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1407 skipped lattices were newly marked as containing variable, set *CHANGE to
1408 true. */
1410 static bool
1411 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1412 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1413 struct ipcp_agg_lattice ***aglat,
1414 bool pre_existing, bool *change)
1416 gcc_checking_assert (offset >= 0);
1418 while (**aglat && (**aglat)->offset < offset)
1420 if ((**aglat)->offset + (**aglat)->size > offset)
1422 set_agg_lats_to_bottom (dest_plats);
1423 return false;
1425 *change |= (**aglat)->set_contains_variable ();
1426 *aglat = &(**aglat)->next;
1429 if (**aglat && (**aglat)->offset == offset)
1431 if ((**aglat)->size != val_size
1432 || ((**aglat)->next
1433 && (**aglat)->next->offset < offset + val_size))
1435 set_agg_lats_to_bottom (dest_plats);
1436 return false;
1438 gcc_checking_assert (!(**aglat)->next
1439 || (**aglat)->next->offset >= offset + val_size);
1440 return true;
1442 else
1444 struct ipcp_agg_lattice *new_al;
1446 if (**aglat && (**aglat)->offset < offset + val_size)
1448 set_agg_lats_to_bottom (dest_plats);
1449 return false;
1451 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1452 return false;
1453 dest_plats->aggs_count++;
1454 new_al = (struct ipcp_agg_lattice *) pool_alloc (ipcp_agg_lattice_pool);
1455 memset (new_al, 0, sizeof (*new_al));
1457 new_al->offset = offset;
1458 new_al->size = val_size;
1459 new_al->contains_variable = pre_existing;
1461 new_al->next = **aglat;
1462 **aglat = new_al;
1463 return true;
1467 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1468 containing an unknown value. */
1470 static bool
1471 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1473 bool ret = false;
1474 while (aglat)
1476 ret |= aglat->set_contains_variable ();
1477 aglat = aglat->next;
1479 return ret;
1482 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1483 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1484 parameter used for lattice value sources. Return true if DEST_PLATS changed
1485 in any way. */
1487 static bool
1488 merge_aggregate_lattices (struct cgraph_edge *cs,
1489 struct ipcp_param_lattices *dest_plats,
1490 struct ipcp_param_lattices *src_plats,
1491 int src_idx, HOST_WIDE_INT offset_delta)
1493 bool pre_existing = dest_plats->aggs != NULL;
1494 struct ipcp_agg_lattice **dst_aglat;
1495 bool ret = false;
1497 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1498 return true;
1499 if (src_plats->aggs_bottom)
1500 return set_agg_lats_contain_variable (dest_plats);
1501 if (src_plats->aggs_contain_variable)
1502 ret |= set_agg_lats_contain_variable (dest_plats);
1503 dst_aglat = &dest_plats->aggs;
1505 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1506 src_aglat;
1507 src_aglat = src_aglat->next)
1509 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1511 if (new_offset < 0)
1512 continue;
1513 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1514 &dst_aglat, pre_existing, &ret))
1516 struct ipcp_agg_lattice *new_al = *dst_aglat;
1518 dst_aglat = &(*dst_aglat)->next;
1519 if (src_aglat->bottom)
1521 ret |= new_al->set_contains_variable ();
1522 continue;
1524 if (src_aglat->contains_variable)
1525 ret |= new_al->set_contains_variable ();
1526 for (ipcp_value<tree> *val = src_aglat->values;
1527 val;
1528 val = val->next)
1529 ret |= new_al->add_value (val->value, cs, val, src_idx,
1530 src_aglat->offset);
1532 else if (dest_plats->aggs_bottom)
1533 return true;
1535 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1536 return ret;
1539 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1540 pass-through JFUNC and if so, whether it has conform and conforms to the
1541 rules about propagating values passed by reference. */
1543 static bool
1544 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1545 struct ipa_jump_func *jfunc)
1547 return src_plats->aggs
1548 && (!src_plats->aggs_by_ref
1549 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1552 /* Propagate scalar values across jump function JFUNC that is associated with
1553 edge CS and put the values into DEST_LAT. */
1555 static bool
1556 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1557 struct ipa_jump_func *jfunc,
1558 struct ipcp_param_lattices *dest_plats)
1560 bool ret = false;
1562 if (dest_plats->aggs_bottom)
1563 return false;
1565 if (jfunc->type == IPA_JF_PASS_THROUGH
1566 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1568 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1569 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1570 struct ipcp_param_lattices *src_plats;
1572 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1573 if (agg_pass_through_permissible_p (src_plats, jfunc))
1575 /* Currently we do not produce clobber aggregate jump
1576 functions, replace with merging when we do. */
1577 gcc_assert (!jfunc->agg.items);
1578 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1579 src_idx, 0);
1581 else
1582 ret |= set_agg_lats_contain_variable (dest_plats);
1584 else if (jfunc->type == IPA_JF_ANCESTOR
1585 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1587 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1588 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1589 struct ipcp_param_lattices *src_plats;
1591 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1592 if (src_plats->aggs && src_plats->aggs_by_ref)
1594 /* Currently we do not produce clobber aggregate jump
1595 functions, replace with merging when we do. */
1596 gcc_assert (!jfunc->agg.items);
1597 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1598 ipa_get_jf_ancestor_offset (jfunc));
1600 else if (!src_plats->aggs_by_ref)
1601 ret |= set_agg_lats_to_bottom (dest_plats);
1602 else
1603 ret |= set_agg_lats_contain_variable (dest_plats);
1605 else if (jfunc->agg.items)
1607 bool pre_existing = dest_plats->aggs != NULL;
1608 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1609 struct ipa_agg_jf_item *item;
1610 int i;
1612 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1613 return true;
1615 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1617 HOST_WIDE_INT val_size;
1619 if (item->offset < 0)
1620 continue;
1621 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1622 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
1624 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1625 &aglat, pre_existing, &ret))
1627 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
1628 aglat = &(*aglat)->next;
1630 else if (dest_plats->aggs_bottom)
1631 return true;
1634 ret |= set_chain_of_aglats_contains_variable (*aglat);
1636 else
1637 ret |= set_agg_lats_contain_variable (dest_plats);
1639 return ret;
1642 /* Propagate constants from the caller to the callee of CS. INFO describes the
1643 caller. */
1645 static bool
1646 propagate_constants_accross_call (struct cgraph_edge *cs)
1648 struct ipa_node_params *callee_info;
1649 enum availability availability;
1650 struct cgraph_node *callee, *alias_or_thunk;
1651 struct ipa_edge_args *args;
1652 bool ret = false;
1653 int i, args_count, parms_count;
1655 callee = cs->callee->function_symbol (&availability);
1656 if (!callee->definition)
1657 return false;
1658 gcc_checking_assert (callee->has_gimple_body_p ());
1659 callee_info = IPA_NODE_REF (callee);
1661 args = IPA_EDGE_REF (cs);
1662 args_count = ipa_get_cs_argument_count (args);
1663 parms_count = ipa_get_param_count (callee_info);
1664 if (parms_count == 0)
1665 return false;
1667 /* No propagation through instrumentation thunks is available yet.
1668 It should be possible with proper mapping of call args and
1669 instrumented callee params in the propagation loop below. But
1670 this case mostly occurs when legacy code calls instrumented code
1671 and it is not a primary target for optimizations.
1672 We detect instrumentation thunks in aliases and thunks chain by
1673 checking instrumentation_clone flag for chain source and target.
1674 Going through instrumentation thunks we always have it changed
1675 from 0 to 1 and all other nodes do not change it. */
1676 if (!cs->callee->instrumentation_clone
1677 && callee->instrumentation_clone)
1679 for (i = 0; i < parms_count; i++)
1680 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1681 i));
1682 return ret;
1685 /* If this call goes through a thunk we must not propagate to the first (0th)
1686 parameter. However, we might need to uncover a thunk from below a series
1687 of aliases first. */
1688 alias_or_thunk = cs->callee;
1689 while (alias_or_thunk->alias)
1690 alias_or_thunk = alias_or_thunk->get_alias_target ();
1691 if (alias_or_thunk->thunk.thunk_p)
1693 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1694 0));
1695 i = 1;
1697 else
1698 i = 0;
1700 for (; (i < args_count) && (i < parms_count); i++)
1702 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1703 struct ipcp_param_lattices *dest_plats;
1705 dest_plats = ipa_get_parm_lattices (callee_info, i);
1706 if (availability == AVAIL_INTERPOSABLE)
1707 ret |= set_all_contains_variable (dest_plats);
1708 else
1710 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1711 &dest_plats->itself);
1712 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
1713 &dest_plats->ctxlat);
1714 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1715 dest_plats);
1718 for (; i < parms_count; i++)
1719 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1721 return ret;
1724 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1725 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1726 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
1728 static tree
1729 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
1730 vec<tree> known_csts,
1731 vec<ipa_polymorphic_call_context> known_contexts,
1732 vec<ipa_agg_jump_function_p> known_aggs,
1733 struct ipa_agg_replacement_value *agg_reps,
1734 bool *speculative)
1736 int param_index = ie->indirect_info->param_index;
1737 HOST_WIDE_INT anc_offset;
1738 tree t;
1739 tree target = NULL;
1741 *speculative = false;
1743 if (param_index == -1
1744 || known_csts.length () <= (unsigned int) param_index)
1745 return NULL_TREE;
1747 if (!ie->indirect_info->polymorphic)
1749 tree t;
1751 if (ie->indirect_info->agg_contents)
1753 if (agg_reps)
1755 t = NULL;
1756 while (agg_reps)
1758 if (agg_reps->index == param_index
1759 && agg_reps->offset == ie->indirect_info->offset
1760 && agg_reps->by_ref == ie->indirect_info->by_ref)
1762 t = agg_reps->value;
1763 break;
1765 agg_reps = agg_reps->next;
1768 else if (known_aggs.length () > (unsigned int) param_index)
1770 struct ipa_agg_jump_function *agg;
1771 agg = known_aggs[param_index];
1772 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1773 ie->indirect_info->by_ref);
1775 else
1776 t = NULL;
1778 else
1779 t = known_csts[param_index];
1781 if (t &&
1782 TREE_CODE (t) == ADDR_EXPR
1783 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1784 return TREE_OPERAND (t, 0);
1785 else
1786 return NULL_TREE;
1789 if (!flag_devirtualize)
1790 return NULL_TREE;
1792 gcc_assert (!ie->indirect_info->agg_contents);
1793 anc_offset = ie->indirect_info->offset;
1795 t = NULL;
1797 /* Try to work out value of virtual table pointer value in replacemnets. */
1798 if (!t && agg_reps && !ie->indirect_info->by_ref)
1800 while (agg_reps)
1802 if (agg_reps->index == param_index
1803 && agg_reps->offset == ie->indirect_info->offset
1804 && agg_reps->by_ref)
1806 t = agg_reps->value;
1807 break;
1809 agg_reps = agg_reps->next;
1813 /* Try to work out value of virtual table pointer value in known
1814 aggregate values. */
1815 if (!t && known_aggs.length () > (unsigned int) param_index
1816 && !ie->indirect_info->by_ref)
1818 struct ipa_agg_jump_function *agg;
1819 agg = known_aggs[param_index];
1820 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1821 true);
1824 /* If we found the virtual table pointer, lookup the target. */
1825 if (t)
1827 tree vtable;
1828 unsigned HOST_WIDE_INT offset;
1829 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
1831 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
1832 vtable, offset);
1833 if (target)
1835 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1836 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1837 || !possible_polymorphic_call_target_p
1838 (ie, cgraph_node::get (target)))
1839 target = ipa_impossible_devirt_target (ie, target);
1840 *speculative = ie->indirect_info->vptr_changed;
1841 if (!*speculative)
1842 return target;
1847 /* Do we know the constant value of pointer? */
1848 if (!t)
1849 t = known_csts[param_index];
1851 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
1853 ipa_polymorphic_call_context context;
1854 if (known_contexts.length () > (unsigned int) param_index)
1856 context = known_contexts[param_index];
1857 context.offset_by (anc_offset);
1858 if (ie->indirect_info->vptr_changed)
1859 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
1860 ie->indirect_info->otr_type);
1861 if (t)
1863 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
1864 (t, ie->indirect_info->otr_type, anc_offset);
1865 if (!ctx2.useless_p ())
1866 context.combine_with (ctx2, ie->indirect_info->otr_type);
1869 else if (t)
1870 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
1871 anc_offset);
1872 else
1873 return NULL_TREE;
1875 vec <cgraph_node *>targets;
1876 bool final;
1878 targets = possible_polymorphic_call_targets
1879 (ie->indirect_info->otr_type,
1880 ie->indirect_info->otr_token,
1881 context, &final);
1882 if (!final || targets.length () > 1)
1884 struct cgraph_node *node;
1885 if (*speculative)
1886 return target;
1887 if (!flag_devirtualize_speculatively || ie->speculative
1888 || !ie->maybe_hot_p ())
1889 return NULL;
1890 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
1891 ie->indirect_info->otr_token,
1892 context);
1893 if (node)
1895 *speculative = true;
1896 target = node->decl;
1898 else
1899 return NULL;
1901 else
1903 *speculative = false;
1904 if (targets.length () == 1)
1905 target = targets[0]->decl;
1906 else
1907 target = ipa_impossible_devirt_target (ie, NULL_TREE);
1910 if (target && !possible_polymorphic_call_target_p (ie,
1911 cgraph_node::get (target)))
1912 target = ipa_impossible_devirt_target (ie, target);
1914 return target;
1918 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
1919 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
1920 return the destination. */
1922 tree
1923 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
1924 vec<tree> known_csts,
1925 vec<ipa_polymorphic_call_context> known_contexts,
1926 vec<ipa_agg_jump_function_p> known_aggs,
1927 bool *speculative)
1929 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
1930 known_aggs, NULL, speculative);
1933 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
1934 and KNOWN_CONTEXTS. */
1936 static int
1937 devirtualization_time_bonus (struct cgraph_node *node,
1938 vec<tree> known_csts,
1939 vec<ipa_polymorphic_call_context> known_contexts,
1940 vec<ipa_agg_jump_function_p> known_aggs)
1942 struct cgraph_edge *ie;
1943 int res = 0;
1945 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1947 struct cgraph_node *callee;
1948 struct inline_summary *isummary;
1949 enum availability avail;
1950 tree target;
1951 bool speculative;
1953 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
1954 known_aggs, &speculative);
1955 if (!target)
1956 continue;
1958 /* Only bare minimum benefit for clearly un-inlineable targets. */
1959 res += 1;
1960 callee = cgraph_node::get (target);
1961 if (!callee || !callee->definition)
1962 continue;
1963 callee = callee->function_symbol (&avail);
1964 if (avail < AVAIL_AVAILABLE)
1965 continue;
1966 isummary = inline_summary (callee);
1967 if (!isummary->inlinable)
1968 continue;
1970 /* FIXME: The values below need re-considering and perhaps also
1971 integrating into the cost metrics, at lest in some very basic way. */
1972 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
1973 res += 31 / ((int)speculative + 1);
1974 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
1975 res += 15 / ((int)speculative + 1);
1976 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
1977 || DECL_DECLARED_INLINE_P (callee->decl))
1978 res += 7 / ((int)speculative + 1);
1981 return res;
1984 /* Return time bonus incurred because of HINTS. */
1986 static int
1987 hint_time_bonus (inline_hints hints)
1989 int result = 0;
1990 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
1991 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
1992 if (hints & INLINE_HINT_array_index)
1993 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
1994 return result;
1997 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
1998 and SIZE_COST and with the sum of frequencies of incoming edges to the
1999 potential new clone in FREQUENCIES. */
2001 static bool
2002 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2003 int freq_sum, gcov_type count_sum, int size_cost)
2005 if (time_benefit == 0
2006 || !flag_ipa_cp_clone
2007 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
2008 return false;
2010 gcc_assert (size_cost > 0);
2012 if (max_count)
2014 int factor = (count_sum * 1000) / max_count;
2015 int64_t evaluation = (((int64_t) time_benefit * factor)
2016 / size_cost);
2018 if (dump_file && (dump_flags & TDF_DETAILS))
2019 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2020 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2021 ") -> evaluation: " "%"PRId64
2022 ", threshold: %i\n",
2023 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2024 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2026 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2028 else
2030 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2031 / size_cost);
2033 if (dump_file && (dump_flags & TDF_DETAILS))
2034 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2035 "size: %i, freq_sum: %i) -> evaluation: "
2036 "%"PRId64 ", threshold: %i\n",
2037 time_benefit, size_cost, freq_sum, evaluation,
2038 PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2040 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2044 /* Return all context independent values from aggregate lattices in PLATS in a
2045 vector. Return NULL if there are none. */
2047 static vec<ipa_agg_jf_item, va_gc> *
2048 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2050 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2052 if (plats->aggs_bottom
2053 || plats->aggs_contain_variable
2054 || plats->aggs_count == 0)
2055 return NULL;
2057 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2058 aglat;
2059 aglat = aglat->next)
2060 if (aglat->is_single_const ())
2062 struct ipa_agg_jf_item item;
2063 item.offset = aglat->offset;
2064 item.value = aglat->values->value;
2065 vec_safe_push (res, item);
2067 return res;
2070 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2071 populate them with values of parameters that are known independent of the
2072 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2073 non-NULL, the movement cost of all removable parameters will be stored in
2074 it. */
2076 static bool
2077 gather_context_independent_values (struct ipa_node_params *info,
2078 vec<tree> *known_csts,
2079 vec<ipa_polymorphic_call_context>
2080 *known_contexts,
2081 vec<ipa_agg_jump_function> *known_aggs,
2082 int *removable_params_cost)
2084 int i, count = ipa_get_param_count (info);
2085 bool ret = false;
2087 known_csts->create (0);
2088 known_contexts->create (0);
2089 known_csts->safe_grow_cleared (count);
2090 known_contexts->safe_grow_cleared (count);
2091 if (known_aggs)
2093 known_aggs->create (0);
2094 known_aggs->safe_grow_cleared (count);
2097 if (removable_params_cost)
2098 *removable_params_cost = 0;
2100 for (i = 0; i < count ; i++)
2102 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2103 ipcp_lattice<tree> *lat = &plats->itself;
2105 if (lat->is_single_const ())
2107 ipcp_value<tree> *val = lat->values;
2108 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2109 (*known_csts)[i] = val->value;
2110 if (removable_params_cost)
2111 *removable_params_cost
2112 += estimate_move_cost (TREE_TYPE (val->value), false);
2113 ret = true;
2115 else if (removable_params_cost
2116 && !ipa_is_param_used (info, i))
2117 *removable_params_cost
2118 += ipa_get_param_move_cost (info, i);
2120 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2121 if (ctxlat->is_single_const ())
2123 (*known_contexts)[i] = ctxlat->values->value;
2124 ret = true;
2127 if (known_aggs)
2129 vec<ipa_agg_jf_item, va_gc> *agg_items;
2130 struct ipa_agg_jump_function *ajf;
2132 agg_items = context_independent_aggregate_values (plats);
2133 ajf = &(*known_aggs)[i];
2134 ajf->items = agg_items;
2135 ajf->by_ref = plats->aggs_by_ref;
2136 ret |= agg_items != NULL;
2140 return ret;
2143 /* The current interface in ipa-inline-analysis requires a pointer vector.
2144 Create it.
2146 FIXME: That interface should be re-worked, this is slightly silly. Still,
2147 I'd like to discuss how to change it first and this demonstrates the
2148 issue. */
2150 static vec<ipa_agg_jump_function_p>
2151 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2153 vec<ipa_agg_jump_function_p> ret;
2154 struct ipa_agg_jump_function *ajf;
2155 int i;
2157 ret.create (known_aggs.length ());
2158 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2159 ret.quick_push (ajf);
2160 return ret;
2163 /* Perform time and size measurement of NODE with the context given in
2164 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2165 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2166 all context-independent removable parameters and EST_MOVE_COST of estimated
2167 movement of the considered parameter and store it into VAL. */
2169 static void
2170 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2171 vec<ipa_polymorphic_call_context> known_contexts,
2172 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2173 int base_time, int removable_params_cost,
2174 int est_move_cost, ipcp_value_base *val)
2176 int time, size, time_benefit;
2177 inline_hints hints;
2179 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2180 known_aggs_ptrs, &size, &time,
2181 &hints);
2182 time_benefit = base_time - time
2183 + devirtualization_time_bonus (node, known_csts, known_contexts,
2184 known_aggs_ptrs)
2185 + hint_time_bonus (hints)
2186 + removable_params_cost + est_move_cost;
2188 gcc_checking_assert (size >=0);
2189 /* The inliner-heuristics based estimates may think that in certain
2190 contexts some functions do not have any size at all but we want
2191 all specializations to have at least a tiny cost, not least not to
2192 divide by zero. */
2193 if (size == 0)
2194 size = 1;
2196 val->local_time_benefit = time_benefit;
2197 val->local_size_cost = size;
2200 /* Iterate over known values of parameters of NODE and estimate the local
2201 effects in terms of time and size they have. */
2203 static void
2204 estimate_local_effects (struct cgraph_node *node)
2206 struct ipa_node_params *info = IPA_NODE_REF (node);
2207 int i, count = ipa_get_param_count (info);
2208 vec<tree> known_csts;
2209 vec<ipa_polymorphic_call_context> known_contexts;
2210 vec<ipa_agg_jump_function> known_aggs;
2211 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2212 bool always_const;
2213 int base_time = inline_summary (node)->time;
2214 int removable_params_cost;
2216 if (!count || !ipcp_versionable_function_p (node))
2217 return;
2219 if (dump_file && (dump_flags & TDF_DETAILS))
2220 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2221 node->name (), node->order, base_time);
2223 always_const = gather_context_independent_values (info, &known_csts,
2224 &known_contexts, &known_aggs,
2225 &removable_params_cost);
2226 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2227 if (always_const)
2229 struct caller_statistics stats;
2230 inline_hints hints;
2231 int time, size;
2233 init_caller_stats (&stats);
2234 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2235 false);
2236 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2237 known_aggs_ptrs, &size, &time, &hints);
2238 time -= devirtualization_time_bonus (node, known_csts, known_contexts,
2239 known_aggs_ptrs);
2240 time -= hint_time_bonus (hints);
2241 time -= removable_params_cost;
2242 size -= stats.n_calls * removable_params_cost;
2244 if (dump_file)
2245 fprintf (dump_file, " - context independent values, size: %i, "
2246 "time_benefit: %i\n", size, base_time - time);
2248 if (size <= 0
2249 || node->will_be_removed_from_program_if_no_direct_calls_p ())
2251 info->do_clone_for_all_contexts = true;
2252 base_time = time;
2254 if (dump_file)
2255 fprintf (dump_file, " Decided to specialize for all "
2256 "known contexts, code not going to grow.\n");
2258 else if (good_cloning_opportunity_p (node, base_time - time,
2259 stats.freq_sum, stats.count_sum,
2260 size))
2262 if (size + overall_size <= max_new_size)
2264 info->do_clone_for_all_contexts = true;
2265 base_time = time;
2266 overall_size += size;
2268 if (dump_file)
2269 fprintf (dump_file, " Decided to specialize for all "
2270 "known contexts, growth deemed beneficial.\n");
2272 else if (dump_file && (dump_flags & TDF_DETAILS))
2273 fprintf (dump_file, " Not cloning for all contexts because "
2274 "max_new_size would be reached with %li.\n",
2275 size + overall_size);
2279 for (i = 0; i < count ; i++)
2281 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2282 ipcp_lattice<tree> *lat = &plats->itself;
2283 ipcp_value<tree> *val;
2285 if (lat->bottom
2286 || !lat->values
2287 || known_csts[i])
2288 continue;
2290 for (val = lat->values; val; val = val->next)
2292 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2293 known_csts[i] = val->value;
2295 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2296 perform_estimation_of_a_value (node, known_csts, known_contexts,
2297 known_aggs_ptrs, base_time,
2298 removable_params_cost, emc, val);
2300 if (dump_file && (dump_flags & TDF_DETAILS))
2302 fprintf (dump_file, " - estimates for value ");
2303 print_ipcp_constant_value (dump_file, val->value);
2304 fprintf (dump_file, " for ");
2305 ipa_dump_param (dump_file, info, i);
2306 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2307 val->local_time_benefit, val->local_size_cost);
2310 known_csts[i] = NULL_TREE;
2313 for (i = 0; i < count; i++)
2315 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2317 if (!plats->virt_call)
2318 continue;
2320 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2321 ipcp_value<ipa_polymorphic_call_context> *val;
2323 if (ctxlat->bottom
2324 || !ctxlat->values
2325 || !known_contexts[i].useless_p ())
2326 continue;
2328 for (val = ctxlat->values; val; val = val->next)
2330 known_contexts[i] = val->value;
2331 perform_estimation_of_a_value (node, known_csts, known_contexts,
2332 known_aggs_ptrs, base_time,
2333 removable_params_cost, 0, val);
2335 if (dump_file && (dump_flags & TDF_DETAILS))
2337 fprintf (dump_file, " - estimates for polymorphic context ");
2338 print_ipcp_constant_value (dump_file, val->value);
2339 fprintf (dump_file, " for ");
2340 ipa_dump_param (dump_file, info, i);
2341 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2342 val->local_time_benefit, val->local_size_cost);
2345 known_contexts[i] = ipa_polymorphic_call_context ();
2348 for (i = 0; i < count ; i++)
2350 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2351 struct ipa_agg_jump_function *ajf;
2352 struct ipcp_agg_lattice *aglat;
2354 if (plats->aggs_bottom || !plats->aggs)
2355 continue;
2357 ajf = &known_aggs[i];
2358 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2360 ipcp_value<tree> *val;
2361 if (aglat->bottom || !aglat->values
2362 /* If the following is true, the one value is in known_aggs. */
2363 || (!plats->aggs_contain_variable
2364 && aglat->is_single_const ()))
2365 continue;
2367 for (val = aglat->values; val; val = val->next)
2369 struct ipa_agg_jf_item item;
2371 item.offset = aglat->offset;
2372 item.value = val->value;
2373 vec_safe_push (ajf->items, item);
2375 perform_estimation_of_a_value (node, known_csts, known_contexts,
2376 known_aggs_ptrs, base_time,
2377 removable_params_cost, 0, val);
2379 if (dump_file && (dump_flags & TDF_DETAILS))
2381 fprintf (dump_file, " - estimates for value ");
2382 print_ipcp_constant_value (dump_file, val->value);
2383 fprintf (dump_file, " for ");
2384 ipa_dump_param (dump_file, info, i);
2385 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2386 "]: time_benefit: %i, size: %i\n",
2387 plats->aggs_by_ref ? "ref " : "",
2388 aglat->offset,
2389 val->local_time_benefit, val->local_size_cost);
2392 ajf->items->pop ();
2397 for (i = 0; i < count ; i++)
2398 vec_free (known_aggs[i].items);
2400 known_csts.release ();
2401 known_contexts.release ();
2402 known_aggs.release ();
2403 known_aggs_ptrs.release ();
2407 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2408 topological sort of values. */
2410 template <typename valtype>
2411 void
2412 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
2414 ipcp_value_source<valtype> *src;
2416 if (cur_val->dfs)
2417 return;
2419 dfs_counter++;
2420 cur_val->dfs = dfs_counter;
2421 cur_val->low_link = dfs_counter;
2423 cur_val->topo_next = stack;
2424 stack = cur_val;
2425 cur_val->on_stack = true;
2427 for (src = cur_val->sources; src; src = src->next)
2428 if (src->val)
2430 if (src->val->dfs == 0)
2432 add_val (src->val);
2433 if (src->val->low_link < cur_val->low_link)
2434 cur_val->low_link = src->val->low_link;
2436 else if (src->val->on_stack
2437 && src->val->dfs < cur_val->low_link)
2438 cur_val->low_link = src->val->dfs;
2441 if (cur_val->dfs == cur_val->low_link)
2443 ipcp_value<valtype> *v, *scc_list = NULL;
2447 v = stack;
2448 stack = v->topo_next;
2449 v->on_stack = false;
2451 v->scc_next = scc_list;
2452 scc_list = v;
2454 while (v != cur_val);
2456 cur_val->topo_next = values_topo;
2457 values_topo = cur_val;
2461 /* Add all values in lattices associated with NODE to the topological sort if
2462 they are not there yet. */
2464 static void
2465 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
2467 struct ipa_node_params *info = IPA_NODE_REF (node);
2468 int i, count = ipa_get_param_count (info);
2470 for (i = 0; i < count ; i++)
2472 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2473 ipcp_lattice<tree> *lat = &plats->itself;
2474 struct ipcp_agg_lattice *aglat;
2476 if (!lat->bottom)
2478 ipcp_value<tree> *val;
2479 for (val = lat->values; val; val = val->next)
2480 topo->constants.add_val (val);
2483 if (!plats->aggs_bottom)
2484 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2485 if (!aglat->bottom)
2487 ipcp_value<tree> *val;
2488 for (val = aglat->values; val; val = val->next)
2489 topo->constants.add_val (val);
2492 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2493 if (!ctxlat->bottom)
2495 ipcp_value<ipa_polymorphic_call_context> *ctxval;
2496 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
2497 topo->contexts.add_val (ctxval);
2502 /* One pass of constants propagation along the call graph edges, from callers
2503 to callees (requires topological ordering in TOPO), iterate over strongly
2504 connected components. */
2506 static void
2507 propagate_constants_topo (struct ipa_topo_info *topo)
2509 int i;
2511 for (i = topo->nnodes - 1; i >= 0; i--)
2513 unsigned j;
2514 struct cgraph_node *v, *node = topo->order[i];
2515 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
2517 /* First, iteratively propagate within the strongly connected component
2518 until all lattices stabilize. */
2519 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2520 if (v->has_gimple_body_p ())
2521 push_node_to_stack (topo, v);
2523 v = pop_node_from_stack (topo);
2524 while (v)
2526 struct cgraph_edge *cs;
2528 for (cs = v->callees; cs; cs = cs->next_callee)
2529 if (ipa_edge_within_scc (cs)
2530 && propagate_constants_accross_call (cs))
2531 push_node_to_stack (topo, cs->callee);
2532 v = pop_node_from_stack (topo);
2535 /* Afterwards, propagate along edges leading out of the SCC, calculates
2536 the local effects of the discovered constants and all valid values to
2537 their topological sort. */
2538 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2539 if (v->has_gimple_body_p ())
2541 struct cgraph_edge *cs;
2543 estimate_local_effects (v);
2544 add_all_node_vals_to_toposort (v, topo);
2545 for (cs = v->callees; cs; cs = cs->next_callee)
2546 if (!ipa_edge_within_scc (cs))
2547 propagate_constants_accross_call (cs);
2549 cycle_nodes.release ();
2554 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2555 the bigger one if otherwise. */
2557 static int
2558 safe_add (int a, int b)
2560 if (a > INT_MAX/2 || b > INT_MAX/2)
2561 return a > b ? a : b;
2562 else
2563 return a + b;
2567 /* Propagate the estimated effects of individual values along the topological
2568 from the dependent values to those they depend on. */
2570 template <typename valtype>
2571 void
2572 value_topo_info<valtype>::propagate_effects ()
2574 ipcp_value<valtype> *base;
2576 for (base = values_topo; base; base = base->topo_next)
2578 ipcp_value_source<valtype> *src;
2579 ipcp_value<valtype> *val;
2580 int time = 0, size = 0;
2582 for (val = base; val; val = val->scc_next)
2584 time = safe_add (time,
2585 val->local_time_benefit + val->prop_time_benefit);
2586 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2589 for (val = base; val; val = val->scc_next)
2590 for (src = val->sources; src; src = src->next)
2591 if (src->val
2592 && src->cs->maybe_hot_p ())
2594 src->val->prop_time_benefit = safe_add (time,
2595 src->val->prop_time_benefit);
2596 src->val->prop_size_cost = safe_add (size,
2597 src->val->prop_size_cost);
2603 /* Propagate constants, polymorphic contexts and their effects from the
2604 summaries interprocedurally. */
2606 static void
2607 ipcp_propagate_stage (struct ipa_topo_info *topo)
2609 struct cgraph_node *node;
2611 if (dump_file)
2612 fprintf (dump_file, "\n Propagating constants:\n\n");
2614 if (in_lto_p)
2615 ipa_update_after_lto_read ();
2618 FOR_EACH_DEFINED_FUNCTION (node)
2620 struct ipa_node_params *info = IPA_NODE_REF (node);
2622 determine_versionability (node);
2623 if (node->has_gimple_body_p ())
2625 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2626 ipa_get_param_count (info));
2627 initialize_node_lattices (node);
2629 if (node->definition && !node->alias)
2630 overall_size += inline_summary (node)->self_size;
2631 if (node->count > max_count)
2632 max_count = node->count;
2635 max_new_size = overall_size;
2636 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2637 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2638 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2640 if (dump_file)
2641 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2642 overall_size, max_new_size);
2644 propagate_constants_topo (topo);
2645 #ifdef ENABLE_CHECKING
2646 ipcp_verify_propagated_values ();
2647 #endif
2648 topo->constants.propagate_effects ();
2649 topo->contexts.propagate_effects ();
2651 if (dump_file)
2653 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2654 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2658 /* Discover newly direct outgoing edges from NODE which is a new clone with
2659 known KNOWN_CSTS and make them direct. */
2661 static void
2662 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2663 vec<tree> known_csts,
2664 vec<ipa_polymorphic_call_context>
2665 known_contexts,
2666 struct ipa_agg_replacement_value *aggvals)
2668 struct cgraph_edge *ie, *next_ie;
2669 bool found = false;
2671 for (ie = node->indirect_calls; ie; ie = next_ie)
2673 tree target;
2674 bool speculative;
2676 next_ie = ie->next_callee;
2677 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2678 vNULL, aggvals, &speculative);
2679 if (target)
2681 bool agg_contents = ie->indirect_info->agg_contents;
2682 bool polymorphic = ie->indirect_info->polymorphic;
2683 int param_index = ie->indirect_info->param_index;
2684 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
2685 speculative);
2686 found = true;
2688 if (cs && !agg_contents && !polymorphic)
2690 struct ipa_node_params *info = IPA_NODE_REF (node);
2691 int c = ipa_get_controlled_uses (info, param_index);
2692 if (c != IPA_UNDESCRIBED_USE)
2694 struct ipa_ref *to_del;
2696 c--;
2697 ipa_set_controlled_uses (info, param_index, c);
2698 if (dump_file && (dump_flags & TDF_DETAILS))
2699 fprintf (dump_file, " controlled uses count of param "
2700 "%i bumped down to %i\n", param_index, c);
2701 if (c == 0
2702 && (to_del = node->find_reference (cs->callee, NULL, 0)))
2704 if (dump_file && (dump_flags & TDF_DETAILS))
2705 fprintf (dump_file, " and even removing its "
2706 "cloning-created reference\n");
2707 to_del->remove_reference ();
2713 /* Turning calls to direct calls will improve overall summary. */
2714 if (found)
2715 inline_update_overall_summary (node);
2718 /* Vector of pointers which for linked lists of clones of an original crgaph
2719 edge. */
2721 static vec<cgraph_edge *> next_edge_clone;
2722 static vec<cgraph_edge *> prev_edge_clone;
2724 static inline void
2725 grow_edge_clone_vectors (void)
2727 if (next_edge_clone.length ()
2728 <= (unsigned) symtab->edges_max_uid)
2729 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2730 if (prev_edge_clone.length ()
2731 <= (unsigned) symtab->edges_max_uid)
2732 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2735 /* Edge duplication hook to grow the appropriate linked list in
2736 next_edge_clone. */
2738 static void
2739 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2740 void *)
2742 grow_edge_clone_vectors ();
2744 struct cgraph_edge *old_next = next_edge_clone[src->uid];
2745 if (old_next)
2746 prev_edge_clone[old_next->uid] = dst;
2747 prev_edge_clone[dst->uid] = src;
2749 next_edge_clone[dst->uid] = old_next;
2750 next_edge_clone[src->uid] = dst;
2753 /* Hook that is called by cgraph.c when an edge is removed. */
2755 static void
2756 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
2758 grow_edge_clone_vectors ();
2760 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
2761 struct cgraph_edge *next = next_edge_clone[cs->uid];
2762 if (prev)
2763 next_edge_clone[prev->uid] = next;
2764 if (next)
2765 prev_edge_clone[next->uid] = prev;
2768 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2769 parameter with the given INDEX. */
2771 static tree
2772 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2773 int index)
2775 struct ipa_agg_replacement_value *aggval;
2777 aggval = ipa_get_agg_replacements_for_node (node);
2778 while (aggval)
2780 if (aggval->offset == offset
2781 && aggval->index == index)
2782 return aggval->value;
2783 aggval = aggval->next;
2785 return NULL_TREE;
2788 /* Return true if edge CS does bring about the value described by SRC. */
2790 static bool
2791 cgraph_edge_brings_value_p (struct cgraph_edge *cs,
2792 ipcp_value_source<tree> *src)
2794 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2795 cgraph_node *real_dest = cs->callee->function_symbol ();
2796 struct ipa_node_params *dst_info = IPA_NODE_REF (real_dest);
2798 if ((dst_info->ipcp_orig_node && !dst_info->is_all_contexts_clone)
2799 || caller_info->node_dead)
2800 return false;
2801 if (!src->val)
2802 return true;
2804 if (caller_info->ipcp_orig_node)
2806 tree t;
2807 if (src->offset == -1)
2808 t = caller_info->known_csts[src->index];
2809 else
2810 t = get_clone_agg_value (cs->caller, src->offset, src->index);
2811 return (t != NULL_TREE
2812 && values_equal_for_ipcp_p (src->val->value, t));
2814 else
2816 struct ipcp_agg_lattice *aglat;
2817 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
2818 src->index);
2819 if (src->offset == -1)
2820 return (plats->itself.is_single_const ()
2821 && values_equal_for_ipcp_p (src->val->value,
2822 plats->itself.values->value));
2823 else
2825 if (plats->aggs_bottom || plats->aggs_contain_variable)
2826 return false;
2827 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2828 if (aglat->offset == src->offset)
2829 return (aglat->is_single_const ()
2830 && values_equal_for_ipcp_p (src->val->value,
2831 aglat->values->value));
2833 return false;
2837 /* Return true if edge CS does bring about the value described by SRC. */
2839 static bool
2840 cgraph_edge_brings_value_p (struct cgraph_edge *cs,
2841 ipcp_value_source<ipa_polymorphic_call_context>
2842 *src)
2844 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2845 cgraph_node *real_dest = cs->callee->function_symbol ();
2846 struct ipa_node_params *dst_info = IPA_NODE_REF (real_dest);
2848 if ((dst_info->ipcp_orig_node && !dst_info->is_all_contexts_clone)
2849 || caller_info->node_dead)
2850 return false;
2851 if (!src->val)
2852 return true;
2854 if (caller_info->ipcp_orig_node)
2855 return (caller_info->known_contexts.length () > (unsigned) src->index)
2856 && values_equal_for_ipcp_p (src->val->value,
2857 caller_info->known_contexts[src->index]);
2859 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
2860 src->index);
2861 return plats->ctxlat.is_single_const ()
2862 && values_equal_for_ipcp_p (src->val->value,
2863 plats->ctxlat.values->value);
2866 /* Get the next clone in the linked list of clones of an edge. */
2868 static inline struct cgraph_edge *
2869 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
2871 return next_edge_clone[cs->uid];
2874 /* Given VAL, iterate over all its sources and if they still hold, add their
2875 edge frequency and their number into *FREQUENCY and *CALLER_COUNT
2876 respectively. */
2878 template <typename valtype>
2879 static bool
2880 get_info_about_necessary_edges (ipcp_value<valtype> *val, int *freq_sum,
2881 gcov_type *count_sum, int *caller_count)
2883 ipcp_value_source<valtype> *src;
2884 int freq = 0, count = 0;
2885 gcov_type cnt = 0;
2886 bool hot = false;
2888 for (src = val->sources; src; src = src->next)
2890 struct cgraph_edge *cs = src->cs;
2891 while (cs)
2893 if (cgraph_edge_brings_value_p (cs, src))
2895 count++;
2896 freq += cs->frequency;
2897 cnt += cs->count;
2898 hot |= cs->maybe_hot_p ();
2900 cs = get_next_cgraph_edge_clone (cs);
2904 *freq_sum = freq;
2905 *count_sum = cnt;
2906 *caller_count = count;
2907 return hot;
2910 /* Return a vector of incoming edges that do bring value VAL. It is assumed
2911 their number is known and equal to CALLER_COUNT. */
2913 template <typename valtype>
2914 static vec<cgraph_edge *>
2915 gather_edges_for_value (ipcp_value<valtype> *val, int caller_count)
2917 ipcp_value_source<valtype> *src;
2918 vec<cgraph_edge *> ret;
2920 ret.create (caller_count);
2921 for (src = val->sources; src; src = src->next)
2923 struct cgraph_edge *cs = src->cs;
2924 while (cs)
2926 if (cgraph_edge_brings_value_p (cs, src))
2927 ret.quick_push (cs);
2928 cs = get_next_cgraph_edge_clone (cs);
2932 return ret;
2935 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
2936 Return it or NULL if for some reason it cannot be created. */
2938 static struct ipa_replace_map *
2939 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
2941 struct ipa_replace_map *replace_map;
2944 replace_map = ggc_alloc<ipa_replace_map> ();
2945 if (dump_file)
2947 fprintf (dump_file, " replacing ");
2948 ipa_dump_param (dump_file, info, parm_num);
2950 fprintf (dump_file, " with const ");
2951 print_generic_expr (dump_file, value, 0);
2952 fprintf (dump_file, "\n");
2954 replace_map->old_tree = NULL;
2955 replace_map->parm_num = parm_num;
2956 replace_map->new_tree = value;
2957 replace_map->replace_p = true;
2958 replace_map->ref_p = false;
2960 return replace_map;
2963 /* Dump new profiling counts */
2965 static void
2966 dump_profile_updates (struct cgraph_node *orig_node,
2967 struct cgraph_node *new_node)
2969 struct cgraph_edge *cs;
2971 fprintf (dump_file, " setting count of the specialized node to "
2972 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
2973 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2974 fprintf (dump_file, " edge to %s has count "
2975 HOST_WIDE_INT_PRINT_DEC "\n",
2976 cs->callee->name (), (HOST_WIDE_INT) cs->count);
2978 fprintf (dump_file, " setting count of the original node to "
2979 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
2980 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2981 fprintf (dump_file, " edge to %s is left with "
2982 HOST_WIDE_INT_PRINT_DEC "\n",
2983 cs->callee->name (), (HOST_WIDE_INT) cs->count);
2986 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
2987 their profile information to reflect this. */
2989 static void
2990 update_profiling_info (struct cgraph_node *orig_node,
2991 struct cgraph_node *new_node)
2993 struct cgraph_edge *cs;
2994 struct caller_statistics stats;
2995 gcov_type new_sum, orig_sum;
2996 gcov_type remainder, orig_node_count = orig_node->count;
2998 if (orig_node_count == 0)
2999 return;
3001 init_caller_stats (&stats);
3002 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3003 false);
3004 orig_sum = stats.count_sum;
3005 init_caller_stats (&stats);
3006 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3007 false);
3008 new_sum = stats.count_sum;
3010 if (orig_node_count < orig_sum + new_sum)
3012 if (dump_file)
3013 fprintf (dump_file, " Problem: node %s/%i has too low count "
3014 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3015 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3016 orig_node->name (), orig_node->order,
3017 (HOST_WIDE_INT) orig_node_count,
3018 (HOST_WIDE_INT) (orig_sum + new_sum));
3020 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3021 if (dump_file)
3022 fprintf (dump_file, " proceeding by pretending it was "
3023 HOST_WIDE_INT_PRINT_DEC "\n",
3024 (HOST_WIDE_INT) orig_node_count);
3027 new_node->count = new_sum;
3028 remainder = orig_node_count - new_sum;
3029 orig_node->count = remainder;
3031 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3032 if (cs->frequency)
3033 cs->count = apply_probability (cs->count,
3034 GCOV_COMPUTE_SCALE (new_sum,
3035 orig_node_count));
3036 else
3037 cs->count = 0;
3039 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3040 cs->count = apply_probability (cs->count,
3041 GCOV_COMPUTE_SCALE (remainder,
3042 orig_node_count));
3044 if (dump_file)
3045 dump_profile_updates (orig_node, new_node);
3048 /* Update the respective profile of specialized NEW_NODE and the original
3049 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3050 have been redirected to the specialized version. */
3052 static void
3053 update_specialized_profile (struct cgraph_node *new_node,
3054 struct cgraph_node *orig_node,
3055 gcov_type redirected_sum)
3057 struct cgraph_edge *cs;
3058 gcov_type new_node_count, orig_node_count = orig_node->count;
3060 if (dump_file)
3061 fprintf (dump_file, " the sum of counts of redirected edges is "
3062 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3063 if (orig_node_count == 0)
3064 return;
3066 gcc_assert (orig_node_count >= redirected_sum);
3068 new_node_count = new_node->count;
3069 new_node->count += redirected_sum;
3070 orig_node->count -= redirected_sum;
3072 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3073 if (cs->frequency)
3074 cs->count += apply_probability (cs->count,
3075 GCOV_COMPUTE_SCALE (redirected_sum,
3076 new_node_count));
3077 else
3078 cs->count = 0;
3080 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3082 gcov_type dec = apply_probability (cs->count,
3083 GCOV_COMPUTE_SCALE (redirected_sum,
3084 orig_node_count));
3085 if (dec < cs->count)
3086 cs->count -= dec;
3087 else
3088 cs->count = 0;
3091 if (dump_file)
3092 dump_profile_updates (orig_node, new_node);
3095 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3096 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3097 redirect all edges in CALLERS to it. */
3099 static struct cgraph_node *
3100 create_specialized_node (struct cgraph_node *node,
3101 vec<tree> known_csts,
3102 vec<ipa_polymorphic_call_context> known_contexts,
3103 struct ipa_agg_replacement_value *aggvals,
3104 vec<cgraph_edge *> callers)
3106 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3107 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3108 struct ipa_agg_replacement_value *av;
3109 struct cgraph_node *new_node;
3110 int i, count = ipa_get_param_count (info);
3111 bitmap args_to_skip;
3113 gcc_assert (!info->ipcp_orig_node);
3115 if (node->local.can_change_signature)
3117 args_to_skip = BITMAP_GGC_ALLOC ();
3118 for (i = 0; i < count; i++)
3120 tree t = known_csts[i];
3122 if (t || !ipa_is_param_used (info, i))
3123 bitmap_set_bit (args_to_skip, i);
3126 else
3128 args_to_skip = NULL;
3129 if (dump_file && (dump_flags & TDF_DETAILS))
3130 fprintf (dump_file, " cannot change function signature\n");
3133 for (i = 0; i < count ; i++)
3135 tree t = known_csts[i];
3136 if (t)
3138 struct ipa_replace_map *replace_map;
3140 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3141 replace_map = get_replacement_map (info, t, i);
3142 if (replace_map)
3143 vec_safe_push (replace_trees, replace_map);
3147 new_node = node->create_virtual_clone (callers, replace_trees,
3148 args_to_skip, "constprop");
3149 ipa_set_node_agg_value_chain (new_node, aggvals);
3150 for (av = aggvals; av; av = av->next)
3151 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3153 if (dump_file && (dump_flags & TDF_DETAILS))
3155 fprintf (dump_file, " the new node is %s/%i.\n",
3156 new_node->name (), new_node->order);
3157 if (known_contexts.exists ())
3159 for (i = 0; i < count ; i++)
3160 if (!known_contexts[i].useless_p ())
3162 fprintf (dump_file, " known ctx %i is ", i);
3163 known_contexts[i].dump (dump_file);
3166 if (aggvals)
3167 ipa_dump_agg_replacement_values (dump_file, aggvals);
3169 ipa_check_create_node_params ();
3170 update_profiling_info (node, new_node);
3171 new_info = IPA_NODE_REF (new_node);
3172 new_info->ipcp_orig_node = node;
3173 new_info->known_csts = known_csts;
3174 new_info->known_contexts = known_contexts;
3176 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3178 callers.release ();
3179 return new_node;
3182 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3183 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3185 static void
3186 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3187 vec<tree> known_csts,
3188 vec<cgraph_edge *> callers)
3190 struct ipa_node_params *info = IPA_NODE_REF (node);
3191 int i, count = ipa_get_param_count (info);
3193 for (i = 0; i < count ; i++)
3195 struct cgraph_edge *cs;
3196 tree newval = NULL_TREE;
3197 int j;
3198 bool first = true;
3200 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3201 continue;
3203 FOR_EACH_VEC_ELT (callers, j, cs)
3205 struct ipa_jump_func *jump_func;
3206 tree t;
3208 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3210 newval = NULL_TREE;
3211 break;
3213 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3214 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3215 if (!t
3216 || (newval
3217 && !values_equal_for_ipcp_p (t, newval))
3218 || (!first && !newval))
3220 newval = NULL_TREE;
3221 break;
3223 else
3224 newval = t;
3225 first = false;
3228 if (newval)
3230 if (dump_file && (dump_flags & TDF_DETAILS))
3232 fprintf (dump_file, " adding an extra known scalar value ");
3233 print_ipcp_constant_value (dump_file, newval);
3234 fprintf (dump_file, " for ");
3235 ipa_dump_param (dump_file, info, i);
3236 fprintf (dump_file, "\n");
3239 known_csts[i] = newval;
3244 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3245 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3246 CALLERS. */
3248 static void
3249 find_more_contexts_for_caller_subset (cgraph_node *node,
3250 vec<ipa_polymorphic_call_context>
3251 *known_contexts,
3252 vec<cgraph_edge *> callers)
3254 ipa_node_params *info = IPA_NODE_REF (node);
3255 int i, count = ipa_get_param_count (info);
3257 for (i = 0; i < count ; i++)
3259 cgraph_edge *cs;
3261 if (ipa_get_poly_ctx_lat (info, i)->bottom
3262 || (known_contexts->exists ()
3263 && !(*known_contexts)[i].useless_p ()))
3264 continue;
3266 ipa_polymorphic_call_context newval;
3267 bool first = true;
3268 int j;
3270 FOR_EACH_VEC_ELT (callers, j, cs)
3272 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3273 return;
3274 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3276 ipa_polymorphic_call_context ctx;
3277 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3278 jfunc);
3279 if (first)
3281 newval = ctx;
3282 first = false;
3284 else
3285 newval.meet_with (ctx);
3286 if (newval.useless_p ())
3287 break;
3290 if (!newval.useless_p ())
3292 if (dump_file && (dump_flags & TDF_DETAILS))
3294 fprintf (dump_file, " adding an extra known polymorphic "
3295 "context ");
3296 print_ipcp_constant_value (dump_file, newval);
3297 fprintf (dump_file, " for ");
3298 ipa_dump_param (dump_file, info, i);
3299 fprintf (dump_file, "\n");
3302 if (!known_contexts->exists ())
3303 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3304 (*known_contexts)[i] = newval;
3310 /* Go through PLATS and create a vector of values consisting of values and
3311 offsets (minus OFFSET) of lattices that contain only a single value. */
3313 static vec<ipa_agg_jf_item>
3314 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3316 vec<ipa_agg_jf_item> res = vNULL;
3318 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3319 return vNULL;
3321 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3322 if (aglat->is_single_const ())
3324 struct ipa_agg_jf_item ti;
3325 ti.offset = aglat->offset - offset;
3326 ti.value = aglat->values->value;
3327 res.safe_push (ti);
3329 return res;
3332 /* Intersect all values in INTER with single value lattices in PLATS (while
3333 subtracting OFFSET). */
3335 static void
3336 intersect_with_plats (struct ipcp_param_lattices *plats,
3337 vec<ipa_agg_jf_item> *inter,
3338 HOST_WIDE_INT offset)
3340 struct ipcp_agg_lattice *aglat;
3341 struct ipa_agg_jf_item *item;
3342 int k;
3344 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3346 inter->release ();
3347 return;
3350 aglat = plats->aggs;
3351 FOR_EACH_VEC_ELT (*inter, k, item)
3353 bool found = false;
3354 if (!item->value)
3355 continue;
3356 while (aglat)
3358 if (aglat->offset - offset > item->offset)
3359 break;
3360 if (aglat->offset - offset == item->offset)
3362 gcc_checking_assert (item->value);
3363 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
3364 found = true;
3365 break;
3367 aglat = aglat->next;
3369 if (!found)
3370 item->value = NULL_TREE;
3374 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3375 vector result while subtracting OFFSET from the individual value offsets. */
3377 static vec<ipa_agg_jf_item>
3378 agg_replacements_to_vector (struct cgraph_node *node, int index,
3379 HOST_WIDE_INT offset)
3381 struct ipa_agg_replacement_value *av;
3382 vec<ipa_agg_jf_item> res = vNULL;
3384 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
3385 if (av->index == index
3386 && (av->offset - offset) >= 0)
3388 struct ipa_agg_jf_item item;
3389 gcc_checking_assert (av->value);
3390 item.offset = av->offset - offset;
3391 item.value = av->value;
3392 res.safe_push (item);
3395 return res;
3398 /* Intersect all values in INTER with those that we have already scheduled to
3399 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3400 (while subtracting OFFSET). */
3402 static void
3403 intersect_with_agg_replacements (struct cgraph_node *node, int index,
3404 vec<ipa_agg_jf_item> *inter,
3405 HOST_WIDE_INT offset)
3407 struct ipa_agg_replacement_value *srcvals;
3408 struct ipa_agg_jf_item *item;
3409 int i;
3411 srcvals = ipa_get_agg_replacements_for_node (node);
3412 if (!srcvals)
3414 inter->release ();
3415 return;
3418 FOR_EACH_VEC_ELT (*inter, i, item)
3420 struct ipa_agg_replacement_value *av;
3421 bool found = false;
3422 if (!item->value)
3423 continue;
3424 for (av = srcvals; av; av = av->next)
3426 gcc_checking_assert (av->value);
3427 if (av->index == index
3428 && av->offset - offset == item->offset)
3430 if (values_equal_for_ipcp_p (item->value, av->value))
3431 found = true;
3432 break;
3435 if (!found)
3436 item->value = NULL_TREE;
3440 /* Intersect values in INTER with aggregate values that come along edge CS to
3441 parameter number INDEX and return it. If INTER does not actually exist yet,
3442 copy all incoming values to it. If we determine we ended up with no values
3443 whatsoever, return a released vector. */
3445 static vec<ipa_agg_jf_item>
3446 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
3447 vec<ipa_agg_jf_item> inter)
3449 struct ipa_jump_func *jfunc;
3450 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3451 if (jfunc->type == IPA_JF_PASS_THROUGH
3452 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3454 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3455 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3457 if (caller_info->ipcp_orig_node)
3459 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3460 struct ipcp_param_lattices *orig_plats;
3461 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3462 src_idx);
3463 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3465 if (!inter.exists ())
3466 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
3467 else
3468 intersect_with_agg_replacements (cs->caller, src_idx,
3469 &inter, 0);
3471 else
3473 inter.release ();
3474 return vNULL;
3477 else
3479 struct ipcp_param_lattices *src_plats;
3480 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3481 if (agg_pass_through_permissible_p (src_plats, jfunc))
3483 /* Currently we do not produce clobber aggregate jump
3484 functions, adjust when we do. */
3485 gcc_checking_assert (!jfunc->agg.items);
3486 if (!inter.exists ())
3487 inter = copy_plats_to_inter (src_plats, 0);
3488 else
3489 intersect_with_plats (src_plats, &inter, 0);
3491 else
3493 inter.release ();
3494 return vNULL;
3498 else if (jfunc->type == IPA_JF_ANCESTOR
3499 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3501 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3502 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3503 struct ipcp_param_lattices *src_plats;
3504 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3506 if (caller_info->ipcp_orig_node)
3508 if (!inter.exists ())
3509 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
3510 else
3511 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
3512 delta);
3514 else
3516 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3517 /* Currently we do not produce clobber aggregate jump
3518 functions, adjust when we do. */
3519 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3520 if (!inter.exists ())
3521 inter = copy_plats_to_inter (src_plats, delta);
3522 else
3523 intersect_with_plats (src_plats, &inter, delta);
3526 else if (jfunc->agg.items)
3528 struct ipa_agg_jf_item *item;
3529 int k;
3531 if (!inter.exists ())
3532 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3533 inter.safe_push ((*jfunc->agg.items)[i]);
3534 else
3535 FOR_EACH_VEC_ELT (inter, k, item)
3537 int l = 0;
3538 bool found = false;;
3540 if (!item->value)
3541 continue;
3543 while ((unsigned) l < jfunc->agg.items->length ())
3545 struct ipa_agg_jf_item *ti;
3546 ti = &(*jfunc->agg.items)[l];
3547 if (ti->offset > item->offset)
3548 break;
3549 if (ti->offset == item->offset)
3551 gcc_checking_assert (ti->value);
3552 if (values_equal_for_ipcp_p (item->value,
3553 ti->value))
3554 found = true;
3555 break;
3557 l++;
3559 if (!found)
3560 item->value = NULL;
3563 else
3565 inter.release ();
3566 return vec<ipa_agg_jf_item>();
3568 return inter;
3571 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3572 from all of them. */
3574 static struct ipa_agg_replacement_value *
3575 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3576 vec<cgraph_edge *> callers)
3578 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3579 struct ipa_agg_replacement_value *res;
3580 struct ipa_agg_replacement_value **tail = &res;
3581 struct cgraph_edge *cs;
3582 int i, j, count = ipa_get_param_count (dest_info);
3584 FOR_EACH_VEC_ELT (callers, j, cs)
3586 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3587 if (c < count)
3588 count = c;
3591 for (i = 0; i < count ; i++)
3593 struct cgraph_edge *cs;
3594 vec<ipa_agg_jf_item> inter = vNULL;
3595 struct ipa_agg_jf_item *item;
3596 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3597 int j;
3599 /* Among other things, the following check should deal with all by_ref
3600 mismatches. */
3601 if (plats->aggs_bottom)
3602 continue;
3604 FOR_EACH_VEC_ELT (callers, j, cs)
3606 inter = intersect_aggregates_with_edge (cs, i, inter);
3608 if (!inter.exists ())
3609 goto next_param;
3612 FOR_EACH_VEC_ELT (inter, j, item)
3614 struct ipa_agg_replacement_value *v;
3616 if (!item->value)
3617 continue;
3619 v = ggc_alloc<ipa_agg_replacement_value> ();
3620 v->index = i;
3621 v->offset = item->offset;
3622 v->value = item->value;
3623 v->by_ref = plats->aggs_by_ref;
3624 *tail = v;
3625 tail = &v->next;
3628 next_param:
3629 if (inter.exists ())
3630 inter.release ();
3632 *tail = NULL;
3633 return res;
3636 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3638 static struct ipa_agg_replacement_value *
3639 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
3641 struct ipa_agg_replacement_value *res;
3642 struct ipa_agg_replacement_value **tail = &res;
3643 struct ipa_agg_jump_function *aggjf;
3644 struct ipa_agg_jf_item *item;
3645 int i, j;
3647 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3648 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3650 struct ipa_agg_replacement_value *v;
3651 v = ggc_alloc<ipa_agg_replacement_value> ();
3652 v->index = i;
3653 v->offset = item->offset;
3654 v->value = item->value;
3655 v->by_ref = aggjf->by_ref;
3656 *tail = v;
3657 tail = &v->next;
3659 *tail = NULL;
3660 return res;
3663 /* Determine whether CS also brings all scalar values that the NODE is
3664 specialized for. */
3666 static bool
3667 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3668 struct cgraph_node *node)
3670 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3671 int count = ipa_get_param_count (dest_info);
3672 struct ipa_node_params *caller_info;
3673 struct ipa_edge_args *args;
3674 int i;
3676 caller_info = IPA_NODE_REF (cs->caller);
3677 args = IPA_EDGE_REF (cs);
3678 for (i = 0; i < count; i++)
3680 struct ipa_jump_func *jump_func;
3681 tree val, t;
3683 val = dest_info->known_csts[i];
3684 if (!val)
3685 continue;
3687 if (i >= ipa_get_cs_argument_count (args))
3688 return false;
3689 jump_func = ipa_get_ith_jump_func (args, i);
3690 t = ipa_value_from_jfunc (caller_info, jump_func);
3691 if (!t || !values_equal_for_ipcp_p (val, t))
3692 return false;
3694 return true;
3697 /* Determine whether CS also brings all aggregate values that NODE is
3698 specialized for. */
3699 static bool
3700 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3701 struct cgraph_node *node)
3703 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3704 struct ipa_node_params *orig_node_info;
3705 struct ipa_agg_replacement_value *aggval;
3706 int i, ec, count;
3708 aggval = ipa_get_agg_replacements_for_node (node);
3709 if (!aggval)
3710 return true;
3712 count = ipa_get_param_count (IPA_NODE_REF (node));
3713 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3714 if (ec < count)
3715 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3716 if (aggval->index >= ec)
3717 return false;
3719 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3720 if (orig_caller_info->ipcp_orig_node)
3721 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3723 for (i = 0; i < count; i++)
3725 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
3726 struct ipcp_param_lattices *plats;
3727 bool interesting = false;
3728 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3729 if (aggval->index == i)
3731 interesting = true;
3732 break;
3734 if (!interesting)
3735 continue;
3737 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3738 if (plats->aggs_bottom)
3739 return false;
3741 values = intersect_aggregates_with_edge (cs, i, values);
3742 if (!values.exists ())
3743 return false;
3745 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3746 if (aggval->index == i)
3748 struct ipa_agg_jf_item *item;
3749 int j;
3750 bool found = false;
3751 FOR_EACH_VEC_ELT (values, j, item)
3752 if (item->value
3753 && item->offset == av->offset
3754 && values_equal_for_ipcp_p (item->value, av->value))
3756 found = true;
3757 break;
3759 if (!found)
3761 values.release ();
3762 return false;
3766 return true;
3769 /* Given an original NODE and a VAL for which we have already created a
3770 specialized clone, look whether there are incoming edges that still lead
3771 into the old node but now also bring the requested value and also conform to
3772 all other criteria such that they can be redirected the the special node.
3773 This function can therefore redirect the final edge in a SCC. */
3775 template <typename valtype>
3776 static void
3777 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
3779 ipcp_value_source<valtype> *src;
3780 gcov_type redirected_sum = 0;
3782 for (src = val->sources; src; src = src->next)
3784 struct cgraph_edge *cs = src->cs;
3785 while (cs)
3787 enum availability availability;
3788 struct cgraph_node *dst = cs->callee->function_symbol (&availability);
3789 if ((dst == node || IPA_NODE_REF (dst)->is_all_contexts_clone)
3790 && availability > AVAIL_INTERPOSABLE
3791 && cgraph_edge_brings_value_p (cs, src))
3793 if (cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3794 && cgraph_edge_brings_all_agg_vals_for_node (cs,
3795 val->spec_node))
3797 if (dump_file)
3798 fprintf (dump_file, " - adding an extra caller %s/%i"
3799 " of %s/%i\n",
3800 xstrdup (cs->caller->name ()),
3801 cs->caller->order,
3802 xstrdup (val->spec_node->name ()),
3803 val->spec_node->order);
3805 cs->redirect_callee (val->spec_node);
3806 redirected_sum += cs->count;
3809 cs = get_next_cgraph_edge_clone (cs);
3813 if (redirected_sum)
3814 update_specialized_profile (val->spec_node, node, redirected_sum);
3817 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
3819 static bool
3820 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
3822 ipa_polymorphic_call_context *ctx;
3823 int i;
3825 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
3826 if (!ctx->useless_p ())
3827 return true;
3828 return false;
3831 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
3833 static vec<ipa_polymorphic_call_context>
3834 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
3836 if (known_contexts_useful_p (known_contexts))
3837 return known_contexts.copy ();
3838 else
3839 return vNULL;
3842 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
3843 non-empty, replace KNOWN_CONTEXTS with its copy too. */
3845 static void
3846 modify_known_vectors_with_val (vec<tree> *known_csts,
3847 vec<ipa_polymorphic_call_context> *known_contexts,
3848 ipcp_value<tree> *val,
3849 int index)
3851 *known_csts = known_csts->copy ();
3852 *known_contexts = copy_useful_known_contexts (*known_contexts);
3853 (*known_csts)[index] = val->value;
3856 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
3857 copy according to VAL and INDEX. */
3859 static void
3860 modify_known_vectors_with_val (vec<tree> *known_csts,
3861 vec<ipa_polymorphic_call_context> *known_contexts,
3862 ipcp_value<ipa_polymorphic_call_context> *val,
3863 int index)
3865 *known_csts = known_csts->copy ();
3866 *known_contexts = known_contexts->copy ();
3867 (*known_contexts)[index] = val->value;
3870 /* Return true if OFFSET indicates this was not an aggregate value or there is
3871 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
3872 AGGVALS list. */
3874 DEBUG_FUNCTION bool
3875 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
3876 int index, HOST_WIDE_INT offset, tree value)
3878 if (offset == -1)
3879 return true;
3881 while (aggvals)
3883 if (aggvals->index == index
3884 && aggvals->offset == offset
3885 && values_equal_for_ipcp_p (aggvals->value, value))
3886 return true;
3887 aggvals = aggvals->next;
3889 return false;
3892 /* Return true if offset is minus one because source of a polymorphic contect
3893 cannot be an aggregate value. */
3895 DEBUG_FUNCTION bool
3896 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
3897 int , HOST_WIDE_INT offset,
3898 ipa_polymorphic_call_context)
3900 return offset == -1;
3903 /* Decide wheter to create a special version of NODE for value VAL of parameter
3904 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
3905 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
3906 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
3908 template <typename valtype>
3909 static bool
3910 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
3911 ipcp_value<valtype> *val, vec<tree> known_csts,
3912 vec<ipa_polymorphic_call_context> known_contexts)
3914 struct ipa_agg_replacement_value *aggvals;
3915 int freq_sum, caller_count;
3916 gcov_type count_sum;
3917 vec<cgraph_edge *> callers;
3919 if (val->spec_node)
3921 perhaps_add_new_callers (node, val);
3922 return false;
3924 else if (val->local_size_cost + overall_size > max_new_size)
3926 if (dump_file && (dump_flags & TDF_DETAILS))
3927 fprintf (dump_file, " Ignoring candidate value because "
3928 "max_new_size would be reached with %li.\n",
3929 val->local_size_cost + overall_size);
3930 return false;
3932 else if (!get_info_about_necessary_edges (val, &freq_sum, &count_sum,
3933 &caller_count))
3934 return false;
3936 if (dump_file && (dump_flags & TDF_DETAILS))
3938 fprintf (dump_file, " - considering value ");
3939 print_ipcp_constant_value (dump_file, val->value);
3940 fprintf (dump_file, " for ");
3941 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
3942 if (offset != -1)
3943 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
3944 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
3947 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
3948 freq_sum, count_sum,
3949 val->local_size_cost)
3950 && !good_cloning_opportunity_p (node,
3951 val->local_time_benefit
3952 + val->prop_time_benefit,
3953 freq_sum, count_sum,
3954 val->local_size_cost
3955 + val->prop_size_cost))
3956 return false;
3958 if (dump_file)
3959 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
3960 node->name (), node->order);
3962 callers = gather_edges_for_value (val, caller_count);
3963 if (offset == -1)
3964 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
3965 else
3967 known_csts = known_csts.copy ();
3968 known_contexts = copy_useful_known_contexts (known_contexts);
3970 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
3971 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
3972 aggvals = find_aggregate_values_for_callers_subset (node, callers);
3973 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
3974 offset, val->value));
3975 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
3976 aggvals, callers);
3977 overall_size += val->local_size_cost;
3979 /* TODO: If for some lattice there is only one other known value
3980 left, make a special node for it too. */
3982 return true;
3985 /* Decide whether and what specialized clones of NODE should be created. */
3987 static bool
3988 decide_whether_version_node (struct cgraph_node *node)
3990 struct ipa_node_params *info = IPA_NODE_REF (node);
3991 int i, count = ipa_get_param_count (info);
3992 vec<tree> known_csts;
3993 vec<ipa_polymorphic_call_context> known_contexts;
3994 vec<ipa_agg_jump_function> known_aggs = vNULL;
3995 bool ret = false;
3997 if (count == 0)
3998 return false;
4000 if (dump_file && (dump_flags & TDF_DETAILS))
4001 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4002 node->name (), node->order);
4004 gather_context_independent_values (info, &known_csts, &known_contexts,
4005 info->do_clone_for_all_contexts ? &known_aggs
4006 : NULL, NULL);
4008 for (i = 0; i < count ;i++)
4010 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4011 ipcp_lattice<tree> *lat = &plats->itself;
4012 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4014 if (!lat->bottom
4015 && !known_csts[i])
4017 ipcp_value<tree> *val;
4018 for (val = lat->values; val; val = val->next)
4019 ret |= decide_about_value (node, i, -1, val, known_csts,
4020 known_contexts);
4023 if (!plats->aggs_bottom)
4025 struct ipcp_agg_lattice *aglat;
4026 ipcp_value<tree> *val;
4027 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4028 if (!aglat->bottom && aglat->values
4029 /* If the following is false, the one value is in
4030 known_aggs. */
4031 && (plats->aggs_contain_variable
4032 || !aglat->is_single_const ()))
4033 for (val = aglat->values; val; val = val->next)
4034 ret |= decide_about_value (node, i, aglat->offset, val,
4035 known_csts, known_contexts);
4038 if (!ctxlat->bottom
4039 && known_contexts[i].useless_p ())
4041 ipcp_value<ipa_polymorphic_call_context> *val;
4042 for (val = ctxlat->values; val; val = val->next)
4043 ret |= decide_about_value (node, i, -1, val, known_csts,
4044 known_contexts);
4047 info = IPA_NODE_REF (node);
4050 if (info->do_clone_for_all_contexts)
4052 struct cgraph_node *clone;
4053 vec<cgraph_edge *> callers;
4055 if (dump_file)
4056 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4057 "for all known contexts.\n", node->name (),
4058 node->order);
4060 callers = node->collect_callers ();
4062 if (!known_contexts_useful_p (known_contexts))
4064 known_contexts.release ();
4065 known_contexts = vNULL;
4067 clone = create_specialized_node (node, known_csts, known_contexts,
4068 known_aggs_to_agg_replacement_list (known_aggs),
4069 callers);
4070 info = IPA_NODE_REF (node);
4071 info->do_clone_for_all_contexts = false;
4072 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4073 for (i = 0; i < count ; i++)
4074 vec_free (known_aggs[i].items);
4075 known_aggs.release ();
4076 ret = true;
4078 else
4080 known_csts.release ();
4081 known_contexts.release ();
4084 return ret;
4087 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4089 static void
4090 spread_undeadness (struct cgraph_node *node)
4092 struct cgraph_edge *cs;
4094 for (cs = node->callees; cs; cs = cs->next_callee)
4095 if (ipa_edge_within_scc (cs))
4097 struct cgraph_node *callee;
4098 struct ipa_node_params *info;
4100 callee = cs->callee->function_symbol (NULL);
4101 info = IPA_NODE_REF (callee);
4103 if (info->node_dead)
4105 info->node_dead = 0;
4106 spread_undeadness (callee);
4111 /* Return true if NODE has a caller from outside of its SCC that is not
4112 dead. Worker callback for cgraph_for_node_and_aliases. */
4114 static bool
4115 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4116 void *data ATTRIBUTE_UNUSED)
4118 struct cgraph_edge *cs;
4120 for (cs = node->callers; cs; cs = cs->next_caller)
4121 if (cs->caller->thunk.thunk_p
4122 && cs->caller->call_for_symbol_thunks_and_aliases
4123 (has_undead_caller_from_outside_scc_p, NULL, true))
4124 return true;
4125 else if (!ipa_edge_within_scc (cs)
4126 && !IPA_NODE_REF (cs->caller)->node_dead)
4127 return true;
4128 return false;
4132 /* Identify nodes within the same SCC as NODE which are no longer needed
4133 because of new clones and will be removed as unreachable. */
4135 static void
4136 identify_dead_nodes (struct cgraph_node *node)
4138 struct cgraph_node *v;
4139 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4140 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
4141 && !v->call_for_symbol_thunks_and_aliases
4142 (has_undead_caller_from_outside_scc_p, NULL, true))
4143 IPA_NODE_REF (v)->node_dead = 1;
4145 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4146 if (!IPA_NODE_REF (v)->node_dead)
4147 spread_undeadness (v);
4149 if (dump_file && (dump_flags & TDF_DETAILS))
4151 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4152 if (IPA_NODE_REF (v)->node_dead)
4153 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4154 v->name (), v->order);
4158 /* The decision stage. Iterate over the topological order of call graph nodes
4159 TOPO and make specialized clones if deemed beneficial. */
4161 static void
4162 ipcp_decision_stage (struct ipa_topo_info *topo)
4164 int i;
4166 if (dump_file)
4167 fprintf (dump_file, "\nIPA decision stage:\n\n");
4169 for (i = topo->nnodes - 1; i >= 0; i--)
4171 struct cgraph_node *node = topo->order[i];
4172 bool change = false, iterate = true;
4174 while (iterate)
4176 struct cgraph_node *v;
4177 iterate = false;
4178 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4179 if (v->has_gimple_body_p ()
4180 && ipcp_versionable_function_p (v))
4181 iterate |= decide_whether_version_node (v);
4183 change |= iterate;
4185 if (change)
4186 identify_dead_nodes (node);
4190 /* The IPCP driver. */
4192 static unsigned int
4193 ipcp_driver (void)
4195 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4196 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4197 struct ipa_topo_info topo;
4199 ipa_check_create_node_params ();
4200 ipa_check_create_edge_args ();
4201 grow_edge_clone_vectors ();
4202 edge_duplication_hook_holder =
4203 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4204 edge_removal_hook_holder =
4205 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4207 ipcp_cst_values_pool = create_alloc_pool ("IPA-CP constant values",
4208 sizeof (ipcp_value<tree>), 32);
4209 ipcp_poly_ctx_values_pool = create_alloc_pool
4210 ("IPA-CP polymorphic contexts",
4211 sizeof (ipcp_value<ipa_polymorphic_call_context>), 32);
4212 ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources",
4213 sizeof (ipcp_value_source<tree>), 64);
4214 ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices",
4215 sizeof (struct ipcp_agg_lattice),
4216 32);
4217 if (dump_file)
4219 fprintf (dump_file, "\nIPA structures before propagation:\n");
4220 if (dump_flags & TDF_DETAILS)
4221 ipa_print_all_params (dump_file);
4222 ipa_print_all_jump_functions (dump_file);
4225 /* Topological sort. */
4226 build_toporder_info (&topo);
4227 /* Do the interprocedural propagation. */
4228 ipcp_propagate_stage (&topo);
4229 /* Decide what constant propagation and cloning should be performed. */
4230 ipcp_decision_stage (&topo);
4232 /* Free all IPCP structures. */
4233 free_toporder_info (&topo);
4234 next_edge_clone.release ();
4235 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4236 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
4237 ipa_free_all_structures_after_ipa_cp ();
4238 if (dump_file)
4239 fprintf (dump_file, "\nIPA constant propagation end\n");
4240 return 0;
4243 /* Initialization and computation of IPCP data structures. This is the initial
4244 intraprocedural analysis of functions, which gathers information to be
4245 propagated later on. */
4247 static void
4248 ipcp_generate_summary (void)
4250 struct cgraph_node *node;
4252 if (dump_file)
4253 fprintf (dump_file, "\nIPA constant propagation start:\n");
4254 ipa_register_cgraph_hooks ();
4256 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4258 node->local.versionable
4259 = tree_versionable_function_p (node->decl);
4260 ipa_analyze_node (node);
4264 /* Write ipcp summary for nodes in SET. */
4266 static void
4267 ipcp_write_summary (void)
4269 ipa_prop_write_jump_functions ();
4272 /* Read ipcp summary. */
4274 static void
4275 ipcp_read_summary (void)
4277 ipa_prop_read_jump_functions ();
4280 namespace {
4282 const pass_data pass_data_ipa_cp =
4284 IPA_PASS, /* type */
4285 "cp", /* name */
4286 OPTGROUP_NONE, /* optinfo_flags */
4287 TV_IPA_CONSTANT_PROP, /* tv_id */
4288 0, /* properties_required */
4289 0, /* properties_provided */
4290 0, /* properties_destroyed */
4291 0, /* todo_flags_start */
4292 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
4295 class pass_ipa_cp : public ipa_opt_pass_d
4297 public:
4298 pass_ipa_cp (gcc::context *ctxt)
4299 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
4300 ipcp_generate_summary, /* generate_summary */
4301 ipcp_write_summary, /* write_summary */
4302 ipcp_read_summary, /* read_summary */
4303 ipa_prop_write_all_agg_replacement, /*
4304 write_optimization_summary */
4305 ipa_prop_read_all_agg_replacement, /*
4306 read_optimization_summary */
4307 NULL, /* stmt_fixup */
4308 0, /* function_transform_todo_flags_start */
4309 ipcp_transform_function, /* function_transform */
4310 NULL) /* variable_transform */
4313 /* opt_pass methods: */
4314 virtual bool gate (function *)
4316 /* FIXME: We should remove the optimize check after we ensure we never run
4317 IPA passes when not optimizing. */
4318 return flag_ipa_cp && optimize;
4321 virtual unsigned int execute (function *) { return ipcp_driver (); }
4323 }; // class pass_ipa_cp
4325 } // anon namespace
4327 ipa_opt_pass_d *
4328 make_pass_ipa_cp (gcc::context *ctxt)
4330 return new pass_ipa_cp (ctxt);
4333 /* Reset all state within ipa-cp.c so that we can rerun the compiler
4334 within the same process. For use by toplev::finalize. */
4336 void
4337 ipa_cp_c_finalize (void)
4339 max_count = 0;
4340 overall_size = 0;
4341 max_new_size = 0;