Daily bump.
[official-gcc.git] / gcc / ipa-cp.c
blob02b027d0c52796934d8b6caffaa3e9d2b25aad54
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "alias.h"
107 #include "symtab.h"
108 #include "options.h"
109 #include "tree.h"
110 #include "fold-const.h"
111 #include "gimple-fold.h"
112 #include "gimple-expr.h"
113 #include "target.h"
114 #include "predict.h"
115 #include "basic-block.h"
116 #include "tm.h"
117 #include "hard-reg-set.h"
118 #include "function.h"
119 #include "cgraph.h"
120 #include "alloc-pool.h"
121 #include "symbol-summary.h"
122 #include "ipa-prop.h"
123 #include "bitmap.h"
124 #include "tree-pass.h"
125 #include "flags.h"
126 #include "diagnostic.h"
127 #include "tree-pretty-print.h"
128 #include "tree-inline.h"
129 #include "params.h"
130 #include "ipa-inline.h"
131 #include "ipa-utils.h"
133 template <typename valtype> class ipcp_value;
135 /* Describes a particular source for an IPA-CP value. */
137 template <typename valtype>
138 class ipcp_value_source
140 public:
141 /* Aggregate offset of the source, negative if the source is scalar value of
142 the argument itself. */
143 HOST_WIDE_INT offset;
144 /* The incoming edge that brought the value. */
145 cgraph_edge *cs;
146 /* If the jump function that resulted into his value was a pass-through or an
147 ancestor, this is the ipcp_value of the caller from which the described
148 value has been derived. Otherwise it is NULL. */
149 ipcp_value<valtype> *val;
150 /* Next pointer in a linked list of sources of a value. */
151 ipcp_value_source *next;
152 /* If the jump function that resulted into his value was a pass-through or an
153 ancestor, this is the index of the parameter of the caller the jump
154 function references. */
155 int index;
158 /* Common ancestor for all ipcp_value instantiations. */
160 class ipcp_value_base
162 public:
163 /* Time benefit and size cost that specializing the function for this value
164 would bring about in this function alone. */
165 int local_time_benefit, local_size_cost;
166 /* Time benefit and size cost that specializing the function for this value
167 can bring about in it's callees (transitively). */
168 int prop_time_benefit, prop_size_cost;
171 /* Describes one particular value stored in struct ipcp_lattice. */
173 template <typename valtype>
174 class ipcp_value : public ipcp_value_base
176 public:
177 /* The actual value for the given parameter. */
178 valtype value;
179 /* The list of sources from which this value originates. */
180 ipcp_value_source <valtype> *sources;
181 /* Next pointers in a linked list of all values in a lattice. */
182 ipcp_value *next;
183 /* Next pointers in a linked list of values in a strongly connected component
184 of values. */
185 ipcp_value *scc_next;
186 /* Next pointers in a linked list of SCCs of values sorted topologically
187 according their sources. */
188 ipcp_value *topo_next;
189 /* A specialized node created for this value, NULL if none has been (so far)
190 created. */
191 cgraph_node *spec_node;
192 /* Depth first search number and low link for topological sorting of
193 values. */
194 int dfs, low_link;
195 /* True if this valye is currently on the topo-sort stack. */
196 bool on_stack;
198 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
199 HOST_WIDE_INT offset);
202 /* Lattice describing potential values of a formal parameter of a function, or
203 a part of an aggreagate. TOP is represented by a lattice with zero values
204 and with contains_variable and bottom flags cleared. BOTTOM is represented
205 by a lattice with the bottom flag set. In that case, values and
206 contains_variable flag should be disregarded. */
208 template <typename valtype>
209 class ipcp_lattice
211 public:
212 /* The list of known values and types in this lattice. Note that values are
213 not deallocated if a lattice is set to bottom because there may be value
214 sources referencing them. */
215 ipcp_value<valtype> *values;
216 /* Number of known values and types in this lattice. */
217 int values_count;
218 /* The lattice contains a variable component (in addition to values). */
219 bool contains_variable;
220 /* The value of the lattice is bottom (i.e. variable and unusable for any
221 propagation). */
222 bool bottom;
224 inline bool is_single_const ();
225 inline bool set_to_bottom ();
226 inline bool set_contains_variable ();
227 bool add_value (valtype newval, cgraph_edge *cs,
228 ipcp_value<valtype> *src_val = NULL,
229 int src_idx = 0, HOST_WIDE_INT offset = -1);
230 void print (FILE * f, bool dump_sources, bool dump_benefits);
233 /* Lattice of tree values with an offset to describe a part of an
234 aggregate. */
236 class ipcp_agg_lattice : public ipcp_lattice<tree>
238 public:
239 /* Offset that is being described by this lattice. */
240 HOST_WIDE_INT offset;
241 /* Size so that we don't have to re-compute it every time we traverse the
242 list. Must correspond to TYPE_SIZE of all lat values. */
243 HOST_WIDE_INT size;
244 /* Next element of the linked list. */
245 struct ipcp_agg_lattice *next;
248 /* Structure containing lattices for a parameter itself and for pieces of
249 aggregates that are passed in the parameter or by a reference in a parameter
250 plus some other useful flags. */
252 class ipcp_param_lattices
254 public:
255 /* Lattice describing the value of the parameter itself. */
256 ipcp_lattice<tree> itself;
257 /* Lattice describing the the polymorphic contexts of a parameter. */
258 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
259 /* Lattices describing aggregate parts. */
260 ipcp_agg_lattice *aggs;
261 /* Alignment information. Very basic one value lattice where !known means
262 TOP and zero alignment bottom. */
263 ipa_alignment alignment;
264 /* Number of aggregate lattices */
265 int aggs_count;
266 /* True if aggregate data were passed by reference (as opposed to by
267 value). */
268 bool aggs_by_ref;
269 /* All aggregate lattices contain a variable component (in addition to
270 values). */
271 bool aggs_contain_variable;
272 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
273 for any propagation). */
274 bool aggs_bottom;
276 /* There is a virtual call based on this parameter. */
277 bool virt_call;
280 /* Allocation pools for values and their sources in ipa-cp. */
282 pool_allocator<ipcp_value<tree> > ipcp_cst_values_pool
283 ("IPA-CP constant values", 32);
285 pool_allocator<ipcp_value<ipa_polymorphic_call_context> >
286 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts", 32);
288 pool_allocator<ipcp_value_source<tree> > ipcp_sources_pool
289 ("IPA-CP value sources", 64);
291 pool_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
292 ("IPA_CP aggregate lattices", 32);
294 /* Maximal count found in program. */
296 static gcov_type max_count;
298 /* Original overall size of the program. */
300 static long overall_size, max_new_size;
302 /* Return the param lattices structure corresponding to the Ith formal
303 parameter of the function described by INFO. */
304 static inline struct ipcp_param_lattices *
305 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
307 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
308 gcc_checking_assert (!info->ipcp_orig_node);
309 gcc_checking_assert (info->lattices);
310 return &(info->lattices[i]);
313 /* Return the lattice corresponding to the scalar value of the Ith formal
314 parameter of the function described by INFO. */
315 static inline ipcp_lattice<tree> *
316 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
318 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
319 return &plats->itself;
322 /* Return the lattice corresponding to the scalar value of the Ith formal
323 parameter of the function described by INFO. */
324 static inline ipcp_lattice<ipa_polymorphic_call_context> *
325 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
327 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
328 return &plats->ctxlat;
331 /* Return whether LAT is a lattice with a single constant and without an
332 undefined value. */
334 template <typename valtype>
335 inline bool
336 ipcp_lattice<valtype>::is_single_const ()
338 if (bottom || contains_variable || values_count != 1)
339 return false;
340 else
341 return true;
344 /* Print V which is extracted from a value in a lattice to F. */
346 static void
347 print_ipcp_constant_value (FILE * f, tree v)
349 if (TREE_CODE (v) == ADDR_EXPR
350 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
352 fprintf (f, "& ");
353 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
355 else
356 print_generic_expr (f, v, 0);
359 /* Print V which is extracted from a value in a lattice to F. */
361 static void
362 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
364 v.dump(f, false);
367 /* Print a lattice LAT to F. */
369 template <typename valtype>
370 void
371 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
373 ipcp_value<valtype> *val;
374 bool prev = false;
376 if (bottom)
378 fprintf (f, "BOTTOM\n");
379 return;
382 if (!values_count && !contains_variable)
384 fprintf (f, "TOP\n");
385 return;
388 if (contains_variable)
390 fprintf (f, "VARIABLE");
391 prev = true;
392 if (dump_benefits)
393 fprintf (f, "\n");
396 for (val = values; val; val = val->next)
398 if (dump_benefits && prev)
399 fprintf (f, " ");
400 else if (!dump_benefits && prev)
401 fprintf (f, ", ");
402 else
403 prev = true;
405 print_ipcp_constant_value (f, val->value);
407 if (dump_sources)
409 ipcp_value_source<valtype> *s;
411 fprintf (f, " [from:");
412 for (s = val->sources; s; s = s->next)
413 fprintf (f, " %i(%i)", s->cs->caller->order,
414 s->cs->frequency);
415 fprintf (f, "]");
418 if (dump_benefits)
419 fprintf (f, " [loc_time: %i, loc_size: %i, "
420 "prop_time: %i, prop_size: %i]\n",
421 val->local_time_benefit, val->local_size_cost,
422 val->prop_time_benefit, val->prop_size_cost);
424 if (!dump_benefits)
425 fprintf (f, "\n");
428 /* Print all ipcp_lattices of all functions to F. */
430 static void
431 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
433 struct cgraph_node *node;
434 int i, count;
436 fprintf (f, "\nLattices:\n");
437 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
439 struct ipa_node_params *info;
441 info = IPA_NODE_REF (node);
442 fprintf (f, " Node: %s/%i:\n", node->name (),
443 node->order);
444 count = ipa_get_param_count (info);
445 for (i = 0; i < count; i++)
447 struct ipcp_agg_lattice *aglat;
448 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
449 fprintf (f, " param [%d]: ", i);
450 plats->itself.print (f, dump_sources, dump_benefits);
451 fprintf (f, " ctxs: ");
452 plats->ctxlat.print (f, dump_sources, dump_benefits);
453 if (plats->alignment.known && plats->alignment.align > 0)
454 fprintf (f, " Alignment %u, misalignment %u\n",
455 plats->alignment.align, plats->alignment.misalign);
456 else if (plats->alignment.known)
457 fprintf (f, " Alignment unusable\n");
458 else
459 fprintf (f, " Alignment unknown\n");
460 if (plats->virt_call)
461 fprintf (f, " virt_call flag set\n");
463 if (plats->aggs_bottom)
465 fprintf (f, " AGGS BOTTOM\n");
466 continue;
468 if (plats->aggs_contain_variable)
469 fprintf (f, " AGGS VARIABLE\n");
470 for (aglat = plats->aggs; aglat; aglat = aglat->next)
472 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
473 plats->aggs_by_ref ? "ref " : "", aglat->offset);
474 aglat->print (f, dump_sources, dump_benefits);
480 /* Determine whether it is at all technically possible to create clones of NODE
481 and store this information in the ipa_node_params structure associated
482 with NODE. */
484 static void
485 determine_versionability (struct cgraph_node *node)
487 const char *reason = NULL;
489 /* There are a number of generic reasons functions cannot be versioned. We
490 also cannot remove parameters if there are type attributes such as fnspec
491 present. */
492 if (node->alias || node->thunk.thunk_p)
493 reason = "alias or thunk";
494 else if (!node->local.versionable)
495 reason = "not a tree_versionable_function";
496 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
497 reason = "insufficient body availability";
498 else if (!opt_for_fn (node->decl, optimize)
499 || !opt_for_fn (node->decl, flag_ipa_cp))
500 reason = "non-optimized function";
501 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
503 /* Ideally we should clone the SIMD clones themselves and create
504 vector copies of them, so IPA-cp and SIMD clones can happily
505 coexist, but that may not be worth the effort. */
506 reason = "function has SIMD clones";
508 /* Don't clone decls local to a comdat group; it breaks and for C++
509 decloned constructors, inlining is always better anyway. */
510 else if (node->comdat_local_p ())
511 reason = "comdat-local function";
513 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
514 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
515 node->name (), node->order, reason);
517 node->local.versionable = (reason == NULL);
520 /* Return true if it is at all technically possible to create clones of a
521 NODE. */
523 static bool
524 ipcp_versionable_function_p (struct cgraph_node *node)
526 return node->local.versionable;
529 /* Structure holding accumulated information about callers of a node. */
531 struct caller_statistics
533 gcov_type count_sum;
534 int n_calls, n_hot_calls, freq_sum;
537 /* Initialize fields of STAT to zeroes. */
539 static inline void
540 init_caller_stats (struct caller_statistics *stats)
542 stats->count_sum = 0;
543 stats->n_calls = 0;
544 stats->n_hot_calls = 0;
545 stats->freq_sum = 0;
548 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
549 non-thunk incoming edges to NODE. */
551 static bool
552 gather_caller_stats (struct cgraph_node *node, void *data)
554 struct caller_statistics *stats = (struct caller_statistics *) data;
555 struct cgraph_edge *cs;
557 for (cs = node->callers; cs; cs = cs->next_caller)
558 if (!cs->caller->thunk.thunk_p)
560 stats->count_sum += cs->count;
561 stats->freq_sum += cs->frequency;
562 stats->n_calls++;
563 if (cs->maybe_hot_p ())
564 stats->n_hot_calls ++;
566 return false;
570 /* Return true if this NODE is viable candidate for cloning. */
572 static bool
573 ipcp_cloning_candidate_p (struct cgraph_node *node)
575 struct caller_statistics stats;
577 gcc_checking_assert (node->has_gimple_body_p ());
579 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
581 if (dump_file)
582 fprintf (dump_file, "Not considering %s for cloning; "
583 "-fipa-cp-clone disabled.\n",
584 node->name ());
585 return false;
588 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
590 if (dump_file)
591 fprintf (dump_file, "Not considering %s for cloning; "
592 "optimizing it for size.\n",
593 node->name ());
594 return false;
597 init_caller_stats (&stats);
598 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
600 if (inline_summaries->get (node)->self_size < stats.n_calls)
602 if (dump_file)
603 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
604 node->name ());
605 return true;
608 /* When profile is available and function is hot, propagate into it even if
609 calls seems cold; constant propagation can improve function's speed
610 significantly. */
611 if (max_count)
613 if (stats.count_sum > node->count * 90 / 100)
615 if (dump_file)
616 fprintf (dump_file, "Considering %s for cloning; "
617 "usually called directly.\n",
618 node->name ());
619 return true;
622 if (!stats.n_hot_calls)
624 if (dump_file)
625 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
626 node->name ());
627 return false;
629 if (dump_file)
630 fprintf (dump_file, "Considering %s for cloning.\n",
631 node->name ());
632 return true;
635 template <typename valtype>
636 class value_topo_info
638 public:
639 /* Head of the linked list of topologically sorted values. */
640 ipcp_value<valtype> *values_topo;
641 /* Stack for creating SCCs, represented by a linked list too. */
642 ipcp_value<valtype> *stack;
643 /* Counter driving the algorithm in add_val_to_toposort. */
644 int dfs_counter;
646 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
648 void add_val (ipcp_value<valtype> *cur_val);
649 void propagate_effects ();
652 /* Arrays representing a topological ordering of call graph nodes and a stack
653 of nodes used during constant propagation and also data required to perform
654 topological sort of values and propagation of benefits in the determined
655 order. */
657 class ipa_topo_info
659 public:
660 /* Array with obtained topological order of cgraph nodes. */
661 struct cgraph_node **order;
662 /* Stack of cgraph nodes used during propagation within SCC until all values
663 in the SCC stabilize. */
664 struct cgraph_node **stack;
665 int nnodes, stack_top;
667 value_topo_info<tree> constants;
668 value_topo_info<ipa_polymorphic_call_context> contexts;
670 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
671 constants ()
675 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
677 static void
678 build_toporder_info (struct ipa_topo_info *topo)
680 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
681 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
683 gcc_checking_assert (topo->stack_top == 0);
684 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
687 /* Free information about strongly connected components and the arrays in
688 TOPO. */
690 static void
691 free_toporder_info (struct ipa_topo_info *topo)
693 ipa_free_postorder_info ();
694 free (topo->order);
695 free (topo->stack);
698 /* Add NODE to the stack in TOPO, unless it is already there. */
700 static inline void
701 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
703 struct ipa_node_params *info = IPA_NODE_REF (node);
704 if (info->node_enqueued)
705 return;
706 info->node_enqueued = 1;
707 topo->stack[topo->stack_top++] = node;
710 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
711 is empty. */
713 static struct cgraph_node *
714 pop_node_from_stack (struct ipa_topo_info *topo)
716 if (topo->stack_top)
718 struct cgraph_node *node;
719 topo->stack_top--;
720 node = topo->stack[topo->stack_top];
721 IPA_NODE_REF (node)->node_enqueued = 0;
722 return node;
724 else
725 return NULL;
728 /* Set lattice LAT to bottom and return true if it previously was not set as
729 such. */
731 template <typename valtype>
732 inline bool
733 ipcp_lattice<valtype>::set_to_bottom ()
735 bool ret = !bottom;
736 bottom = true;
737 return ret;
740 /* Mark lattice as containing an unknown value and return true if it previously
741 was not marked as such. */
743 template <typename valtype>
744 inline bool
745 ipcp_lattice<valtype>::set_contains_variable ()
747 bool ret = !contains_variable;
748 contains_variable = true;
749 return ret;
752 /* Set all aggegate lattices in PLATS to bottom and return true if they were
753 not previously set as such. */
755 static inline bool
756 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
758 bool ret = !plats->aggs_bottom;
759 plats->aggs_bottom = true;
760 return ret;
763 /* Mark all aggegate lattices in PLATS as containing an unknown value and
764 return true if they were not previously marked as such. */
766 static inline bool
767 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
769 bool ret = !plats->aggs_contain_variable;
770 plats->aggs_contain_variable = true;
771 return ret;
774 /* Return true if alignment information in PLATS is known to be unusable. */
776 static inline bool
777 alignment_bottom_p (ipcp_param_lattices *plats)
779 return plats->alignment.known && (plats->alignment.align == 0);
782 /* Set alignment information in PLATS to unusable. Return true if it
783 previously was usable or unknown. */
785 static inline bool
786 set_alignment_to_bottom (ipcp_param_lattices *plats)
788 if (alignment_bottom_p (plats))
789 return false;
790 plats->alignment.known = true;
791 plats->alignment.align = 0;
792 return true;
795 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
796 return true is any of them has not been marked as such so far. */
798 static inline bool
799 set_all_contains_variable (struct ipcp_param_lattices *plats)
801 bool ret;
802 ret = plats->itself.set_contains_variable ();
803 ret |= plats->ctxlat.set_contains_variable ();
804 ret |= set_agg_lats_contain_variable (plats);
805 ret |= set_alignment_to_bottom (plats);
806 return ret;
809 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
810 points to by the number of callers to NODE. */
812 static bool
813 count_callers (cgraph_node *node, void *data)
815 int *caller_count = (int *) data;
817 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
818 /* Local thunks can be handled transparently, but if the thunk can not
819 be optimized out, count it as a real use. */
820 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
821 ++*caller_count;
822 return false;
825 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
826 the one caller of some other node. Set the caller's corresponding flag. */
828 static bool
829 set_single_call_flag (cgraph_node *node, void *)
831 cgraph_edge *cs = node->callers;
832 /* Local thunks can be handled transparently, skip them. */
833 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
834 cs = cs->next_caller;
835 if (cs)
837 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
838 return true;
840 return false;
843 /* Initialize ipcp_lattices. */
845 static void
846 initialize_node_lattices (struct cgraph_node *node)
848 struct ipa_node_params *info = IPA_NODE_REF (node);
849 struct cgraph_edge *ie;
850 bool disable = false, variable = false;
851 int i;
853 gcc_checking_assert (node->has_gimple_body_p ());
854 if (cgraph_local_p (node))
856 int caller_count = 0;
857 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
858 true);
859 gcc_checking_assert (caller_count > 0);
860 if (caller_count == 1)
861 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
862 NULL, true);
864 else
866 /* When cloning is allowed, we can assume that externally visible
867 functions are not called. We will compensate this by cloning
868 later. */
869 if (ipcp_versionable_function_p (node)
870 && ipcp_cloning_candidate_p (node))
871 variable = true;
872 else
873 disable = true;
876 if (disable || variable)
878 for (i = 0; i < ipa_get_param_count (info) ; i++)
880 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
881 if (disable)
883 plats->itself.set_to_bottom ();
884 plats->ctxlat.set_to_bottom ();
885 set_agg_lats_to_bottom (plats);
886 set_alignment_to_bottom (plats);
888 else
889 set_all_contains_variable (plats);
891 if (dump_file && (dump_flags & TDF_DETAILS)
892 && !node->alias && !node->thunk.thunk_p)
893 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
894 node->name (), node->order,
895 disable ? "BOTTOM" : "VARIABLE");
898 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
899 if (ie->indirect_info->polymorphic
900 && ie->indirect_info->param_index >= 0)
902 gcc_checking_assert (ie->indirect_info->param_index >= 0);
903 ipa_get_parm_lattices (info,
904 ie->indirect_info->param_index)->virt_call = 1;
908 /* Return the result of a (possibly arithmetic) pass through jump function
909 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
910 determined or be considered an interprocedural invariant. */
912 static tree
913 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
915 tree restype, res;
917 gcc_checking_assert (is_gimple_ip_invariant (input));
918 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
919 return input;
921 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
922 == tcc_comparison)
923 restype = boolean_type_node;
924 else
925 restype = TREE_TYPE (input);
926 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
927 input, ipa_get_jf_pass_through_operand (jfunc));
929 if (res && !is_gimple_ip_invariant (res))
930 return NULL_TREE;
932 return res;
935 /* Return the result of an ancestor jump function JFUNC on the constant value
936 INPUT. Return NULL_TREE if that cannot be determined. */
938 static tree
939 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
941 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
942 if (TREE_CODE (input) == ADDR_EXPR)
944 tree t = TREE_OPERAND (input, 0);
945 t = build_ref_for_offset (EXPR_LOCATION (t), t,
946 ipa_get_jf_ancestor_offset (jfunc),
947 ptr_type_node, NULL, false);
948 return build_fold_addr_expr (t);
950 else
951 return NULL_TREE;
954 /* Determine whether JFUNC evaluates to a single known constant value and if
955 so, return it. Otherwise return NULL. INFO describes the caller node or
956 the one it is inlined to, so that pass-through jump functions can be
957 evaluated. */
959 tree
960 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
962 if (jfunc->type == IPA_JF_CONST)
963 return ipa_get_jf_constant (jfunc);
964 else if (jfunc->type == IPA_JF_PASS_THROUGH
965 || jfunc->type == IPA_JF_ANCESTOR)
967 tree input;
968 int idx;
970 if (jfunc->type == IPA_JF_PASS_THROUGH)
971 idx = ipa_get_jf_pass_through_formal_id (jfunc);
972 else
973 idx = ipa_get_jf_ancestor_formal_id (jfunc);
975 if (info->ipcp_orig_node)
976 input = info->known_csts[idx];
977 else
979 ipcp_lattice<tree> *lat;
981 if (!info->lattices
982 || idx >= ipa_get_param_count (info))
983 return NULL_TREE;
984 lat = ipa_get_scalar_lat (info, idx);
985 if (!lat->is_single_const ())
986 return NULL_TREE;
987 input = lat->values->value;
990 if (!input)
991 return NULL_TREE;
993 if (jfunc->type == IPA_JF_PASS_THROUGH)
994 return ipa_get_jf_pass_through_result (jfunc, input);
995 else
996 return ipa_get_jf_ancestor_result (jfunc, input);
998 else
999 return NULL_TREE;
1002 /* Determie whether JFUNC evaluates to single known polymorphic context, given
1003 that INFO describes the caller node or the one it is inlined to, CS is the
1004 call graph edge corresponding to JFUNC and CSIDX index of the described
1005 parameter. */
1007 ipa_polymorphic_call_context
1008 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1009 ipa_jump_func *jfunc)
1011 ipa_edge_args *args = IPA_EDGE_REF (cs);
1012 ipa_polymorphic_call_context ctx;
1013 ipa_polymorphic_call_context *edge_ctx
1014 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1016 if (edge_ctx && !edge_ctx->useless_p ())
1017 ctx = *edge_ctx;
1019 if (jfunc->type == IPA_JF_PASS_THROUGH
1020 || jfunc->type == IPA_JF_ANCESTOR)
1022 ipa_polymorphic_call_context srcctx;
1023 int srcidx;
1024 bool type_preserved = true;
1025 if (jfunc->type == IPA_JF_PASS_THROUGH)
1027 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1028 return ctx;
1029 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1030 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1032 else
1034 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1035 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1037 if (info->ipcp_orig_node)
1039 if (info->known_contexts.exists ())
1040 srcctx = info->known_contexts[srcidx];
1042 else
1044 if (!info->lattices
1045 || srcidx >= ipa_get_param_count (info))
1046 return ctx;
1047 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1048 lat = ipa_get_poly_ctx_lat (info, srcidx);
1049 if (!lat->is_single_const ())
1050 return ctx;
1051 srcctx = lat->values->value;
1053 if (srcctx.useless_p ())
1054 return ctx;
1055 if (jfunc->type == IPA_JF_ANCESTOR)
1056 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1057 if (!type_preserved)
1058 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1059 srcctx.combine_with (ctx);
1060 return srcctx;
1063 return ctx;
1066 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1067 bottom, not containing a variable component and without any known value at
1068 the same time. */
1070 DEBUG_FUNCTION void
1071 ipcp_verify_propagated_values (void)
1073 struct cgraph_node *node;
1075 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1077 struct ipa_node_params *info = IPA_NODE_REF (node);
1078 int i, count = ipa_get_param_count (info);
1080 for (i = 0; i < count; i++)
1082 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1084 if (!lat->bottom
1085 && !lat->contains_variable
1086 && lat->values_count == 0)
1088 if (dump_file)
1090 symtab_node::dump_table (dump_file);
1091 fprintf (dump_file, "\nIPA lattices after constant "
1092 "propagation, before gcc_unreachable:\n");
1093 print_all_lattices (dump_file, true, false);
1096 gcc_unreachable ();
1102 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1104 static bool
1105 values_equal_for_ipcp_p (tree x, tree y)
1107 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1109 if (x == y)
1110 return true;
1112 if (TREE_CODE (x) == ADDR_EXPR
1113 && TREE_CODE (y) == ADDR_EXPR
1114 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1115 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1116 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1117 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1118 else
1119 return operand_equal_p (x, y, 0);
1122 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1124 static bool
1125 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1126 ipa_polymorphic_call_context y)
1128 return x.equal_to (y);
1132 /* Add a new value source to the value represented by THIS, marking that a
1133 value comes from edge CS and (if the underlying jump function is a
1134 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1135 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1136 scalar value of the parameter itself or the offset within an aggregate. */
1138 template <typename valtype>
1139 void
1140 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1141 int src_idx, HOST_WIDE_INT offset)
1143 ipcp_value_source<valtype> *src;
1145 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1146 src->offset = offset;
1147 src->cs = cs;
1148 src->val = src_val;
1149 src->index = src_idx;
1151 src->next = sources;
1152 sources = src;
1155 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1156 SOURCE and clear all other fields. */
1158 static ipcp_value<tree> *
1159 allocate_and_init_ipcp_value (tree source)
1161 ipcp_value<tree> *val;
1163 val = ipcp_cst_values_pool.allocate ();
1164 memset (val, 0, sizeof (*val));
1165 val->value = source;
1166 return val;
1169 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1170 value to SOURCE and clear all other fields. */
1172 static ipcp_value<ipa_polymorphic_call_context> *
1173 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1175 ipcp_value<ipa_polymorphic_call_context> *val;
1177 // TODO
1178 val = ipcp_poly_ctx_values_pool.allocate ();
1179 memset (val, 0, sizeof (*val));
1180 val->value = source;
1181 return val;
1184 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1185 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1186 meaning. OFFSET -1 means the source is scalar and not a part of an
1187 aggregate. */
1189 template <typename valtype>
1190 bool
1191 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1192 ipcp_value<valtype> *src_val,
1193 int src_idx, HOST_WIDE_INT offset)
1195 ipcp_value<valtype> *val;
1197 if (bottom)
1198 return false;
1200 for (val = values; val; val = val->next)
1201 if (values_equal_for_ipcp_p (val->value, newval))
1203 if (ipa_edge_within_scc (cs))
1205 ipcp_value_source<valtype> *s;
1206 for (s = val->sources; s ; s = s->next)
1207 if (s->cs == cs)
1208 break;
1209 if (s)
1210 return false;
1213 val->add_source (cs, src_val, src_idx, offset);
1214 return false;
1217 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1219 /* We can only free sources, not the values themselves, because sources
1220 of other values in this this SCC might point to them. */
1221 for (val = values; val; val = val->next)
1223 while (val->sources)
1225 ipcp_value_source<valtype> *src = val->sources;
1226 val->sources = src->next;
1227 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1231 values = NULL;
1232 return set_to_bottom ();
1235 values_count++;
1236 val = allocate_and_init_ipcp_value (newval);
1237 val->add_source (cs, src_val, src_idx, offset);
1238 val->next = values;
1239 values = val;
1240 return true;
1243 /* Propagate values through a pass-through jump function JFUNC associated with
1244 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1245 is the index of the source parameter. */
1247 static bool
1248 propagate_vals_accross_pass_through (cgraph_edge *cs,
1249 ipa_jump_func *jfunc,
1250 ipcp_lattice<tree> *src_lat,
1251 ipcp_lattice<tree> *dest_lat,
1252 int src_idx)
1254 ipcp_value<tree> *src_val;
1255 bool ret = false;
1257 /* Do not create new values when propagating within an SCC because if there
1258 are arithmetic functions with circular dependencies, there is infinite
1259 number of them and we would just make lattices bottom. */
1260 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1261 && ipa_edge_within_scc (cs))
1262 ret = dest_lat->set_contains_variable ();
1263 else
1264 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1266 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1268 if (cstval)
1269 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1270 else
1271 ret |= dest_lat->set_contains_variable ();
1274 return ret;
1277 /* Propagate values through an ancestor jump function JFUNC associated with
1278 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1279 is the index of the source parameter. */
1281 static bool
1282 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1283 struct ipa_jump_func *jfunc,
1284 ipcp_lattice<tree> *src_lat,
1285 ipcp_lattice<tree> *dest_lat,
1286 int src_idx)
1288 ipcp_value<tree> *src_val;
1289 bool ret = false;
1291 if (ipa_edge_within_scc (cs))
1292 return dest_lat->set_contains_variable ();
1294 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1296 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1298 if (t)
1299 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1300 else
1301 ret |= dest_lat->set_contains_variable ();
1304 return ret;
1307 /* Propagate scalar values across jump function JFUNC that is associated with
1308 edge CS and put the values into DEST_LAT. */
1310 static bool
1311 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1312 struct ipa_jump_func *jfunc,
1313 ipcp_lattice<tree> *dest_lat)
1315 if (dest_lat->bottom)
1316 return false;
1318 if (jfunc->type == IPA_JF_CONST)
1320 tree val = ipa_get_jf_constant (jfunc);
1321 return dest_lat->add_value (val, cs, NULL, 0);
1323 else if (jfunc->type == IPA_JF_PASS_THROUGH
1324 || jfunc->type == IPA_JF_ANCESTOR)
1326 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1327 ipcp_lattice<tree> *src_lat;
1328 int src_idx;
1329 bool ret;
1331 if (jfunc->type == IPA_JF_PASS_THROUGH)
1332 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1333 else
1334 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1336 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1337 if (src_lat->bottom)
1338 return dest_lat->set_contains_variable ();
1340 /* If we would need to clone the caller and cannot, do not propagate. */
1341 if (!ipcp_versionable_function_p (cs->caller)
1342 && (src_lat->contains_variable
1343 || (src_lat->values_count > 1)))
1344 return dest_lat->set_contains_variable ();
1346 if (jfunc->type == IPA_JF_PASS_THROUGH)
1347 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1348 dest_lat, src_idx);
1349 else
1350 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1351 src_idx);
1353 if (src_lat->contains_variable)
1354 ret |= dest_lat->set_contains_variable ();
1356 return ret;
1359 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1360 use it for indirect inlining), we should propagate them too. */
1361 return dest_lat->set_contains_variable ();
1364 /* Propagate scalar values across jump function JFUNC that is associated with
1365 edge CS and describes argument IDX and put the values into DEST_LAT. */
1367 static bool
1368 propagate_context_accross_jump_function (cgraph_edge *cs,
1369 ipa_jump_func *jfunc, int idx,
1370 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1372 ipa_edge_args *args = IPA_EDGE_REF (cs);
1373 if (dest_lat->bottom)
1374 return false;
1375 bool ret = false;
1376 bool added_sth = false;
1377 bool type_preserved = true;
1379 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1380 = ipa_get_ith_polymorhic_call_context (args, idx);
1382 if (edge_ctx_ptr)
1383 edge_ctx = *edge_ctx_ptr;
1385 if (jfunc->type == IPA_JF_PASS_THROUGH
1386 || jfunc->type == IPA_JF_ANCESTOR)
1388 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1389 int src_idx;
1390 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1392 /* TODO: Once we figure out how to propagate speculations, it will
1393 probably be a good idea to switch to speculation if type_preserved is
1394 not set instead of punting. */
1395 if (jfunc->type == IPA_JF_PASS_THROUGH)
1397 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1398 goto prop_fail;
1399 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1400 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1402 else
1404 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1405 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1408 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1409 /* If we would need to clone the caller and cannot, do not propagate. */
1410 if (!ipcp_versionable_function_p (cs->caller)
1411 && (src_lat->contains_variable
1412 || (src_lat->values_count > 1)))
1413 goto prop_fail;
1415 ipcp_value<ipa_polymorphic_call_context> *src_val;
1416 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1418 ipa_polymorphic_call_context cur = src_val->value;
1420 if (!type_preserved)
1421 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1422 if (jfunc->type == IPA_JF_ANCESTOR)
1423 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1424 /* TODO: In cases we know how the context is going to be used,
1425 we can improve the result by passing proper OTR_TYPE. */
1426 cur.combine_with (edge_ctx);
1427 if (!cur.useless_p ())
1429 if (src_lat->contains_variable
1430 && !edge_ctx.equal_to (cur))
1431 ret |= dest_lat->set_contains_variable ();
1432 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1433 added_sth = true;
1439 prop_fail:
1440 if (!added_sth)
1442 if (!edge_ctx.useless_p ())
1443 ret |= dest_lat->add_value (edge_ctx, cs);
1444 else
1445 ret |= dest_lat->set_contains_variable ();
1448 return ret;
1451 /* Propagate alignments across jump function JFUNC that is associated with
1452 edge CS and update DEST_LAT accordingly. */
1454 static bool
1455 propagate_alignment_accross_jump_function (struct cgraph_edge *cs,
1456 struct ipa_jump_func *jfunc,
1457 struct ipcp_param_lattices *dest_lat)
1459 if (alignment_bottom_p (dest_lat))
1460 return false;
1462 ipa_alignment cur;
1463 cur.known = false;
1464 if (jfunc->alignment.known)
1465 cur = jfunc->alignment;
1466 else if (jfunc->type == IPA_JF_PASS_THROUGH
1467 || jfunc->type == IPA_JF_ANCESTOR)
1469 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1470 struct ipcp_param_lattices *src_lats;
1471 HOST_WIDE_INT offset = 0;
1472 int src_idx;
1474 if (jfunc->type == IPA_JF_PASS_THROUGH)
1476 enum tree_code op = ipa_get_jf_pass_through_operation (jfunc);
1477 if (op != NOP_EXPR)
1479 if (op != POINTER_PLUS_EXPR
1480 && op != PLUS_EXPR)
1481 goto prop_fail;
1482 tree operand = ipa_get_jf_pass_through_operand (jfunc);
1483 if (!tree_fits_shwi_p (operand))
1484 goto prop_fail;
1485 offset = tree_to_shwi (operand);
1487 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1489 else
1491 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1492 offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;;
1495 src_lats = ipa_get_parm_lattices (caller_info, src_idx);
1496 if (!src_lats->alignment.known
1497 || alignment_bottom_p (src_lats))
1498 goto prop_fail;
1500 cur = src_lats->alignment;
1501 cur.misalign = (cur.misalign + offset) % cur.align;
1504 if (cur.known)
1506 if (!dest_lat->alignment.known)
1508 dest_lat->alignment = cur;
1509 return true;
1511 else if (dest_lat->alignment.align == cur.align
1512 && dest_lat->alignment.misalign == cur.misalign)
1513 return false;
1516 prop_fail:
1517 set_alignment_to_bottom (dest_lat);
1518 return true;
1521 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1522 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1523 other cases, return false). If there are no aggregate items, set
1524 aggs_by_ref to NEW_AGGS_BY_REF. */
1526 static bool
1527 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1528 bool new_aggs_by_ref)
1530 if (dest_plats->aggs)
1532 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1534 set_agg_lats_to_bottom (dest_plats);
1535 return true;
1538 else
1539 dest_plats->aggs_by_ref = new_aggs_by_ref;
1540 return false;
1543 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1544 already existing lattice for the given OFFSET and SIZE, marking all skipped
1545 lattices as containing variable and checking for overlaps. If there is no
1546 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1547 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1548 unless there are too many already. If there are two many, return false. If
1549 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1550 skipped lattices were newly marked as containing variable, set *CHANGE to
1551 true. */
1553 static bool
1554 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1555 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1556 struct ipcp_agg_lattice ***aglat,
1557 bool pre_existing, bool *change)
1559 gcc_checking_assert (offset >= 0);
1561 while (**aglat && (**aglat)->offset < offset)
1563 if ((**aglat)->offset + (**aglat)->size > offset)
1565 set_agg_lats_to_bottom (dest_plats);
1566 return false;
1568 *change |= (**aglat)->set_contains_variable ();
1569 *aglat = &(**aglat)->next;
1572 if (**aglat && (**aglat)->offset == offset)
1574 if ((**aglat)->size != val_size
1575 || ((**aglat)->next
1576 && (**aglat)->next->offset < offset + val_size))
1578 set_agg_lats_to_bottom (dest_plats);
1579 return false;
1581 gcc_checking_assert (!(**aglat)->next
1582 || (**aglat)->next->offset >= offset + val_size);
1583 return true;
1585 else
1587 struct ipcp_agg_lattice *new_al;
1589 if (**aglat && (**aglat)->offset < offset + val_size)
1591 set_agg_lats_to_bottom (dest_plats);
1592 return false;
1594 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1595 return false;
1596 dest_plats->aggs_count++;
1597 new_al = ipcp_agg_lattice_pool.allocate ();
1598 memset (new_al, 0, sizeof (*new_al));
1600 new_al->offset = offset;
1601 new_al->size = val_size;
1602 new_al->contains_variable = pre_existing;
1604 new_al->next = **aglat;
1605 **aglat = new_al;
1606 return true;
1610 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1611 containing an unknown value. */
1613 static bool
1614 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1616 bool ret = false;
1617 while (aglat)
1619 ret |= aglat->set_contains_variable ();
1620 aglat = aglat->next;
1622 return ret;
1625 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1626 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1627 parameter used for lattice value sources. Return true if DEST_PLATS changed
1628 in any way. */
1630 static bool
1631 merge_aggregate_lattices (struct cgraph_edge *cs,
1632 struct ipcp_param_lattices *dest_plats,
1633 struct ipcp_param_lattices *src_plats,
1634 int src_idx, HOST_WIDE_INT offset_delta)
1636 bool pre_existing = dest_plats->aggs != NULL;
1637 struct ipcp_agg_lattice **dst_aglat;
1638 bool ret = false;
1640 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1641 return true;
1642 if (src_plats->aggs_bottom)
1643 return set_agg_lats_contain_variable (dest_plats);
1644 if (src_plats->aggs_contain_variable)
1645 ret |= set_agg_lats_contain_variable (dest_plats);
1646 dst_aglat = &dest_plats->aggs;
1648 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1649 src_aglat;
1650 src_aglat = src_aglat->next)
1652 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1654 if (new_offset < 0)
1655 continue;
1656 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1657 &dst_aglat, pre_existing, &ret))
1659 struct ipcp_agg_lattice *new_al = *dst_aglat;
1661 dst_aglat = &(*dst_aglat)->next;
1662 if (src_aglat->bottom)
1664 ret |= new_al->set_contains_variable ();
1665 continue;
1667 if (src_aglat->contains_variable)
1668 ret |= new_al->set_contains_variable ();
1669 for (ipcp_value<tree> *val = src_aglat->values;
1670 val;
1671 val = val->next)
1672 ret |= new_al->add_value (val->value, cs, val, src_idx,
1673 src_aglat->offset);
1675 else if (dest_plats->aggs_bottom)
1676 return true;
1678 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1679 return ret;
1682 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1683 pass-through JFUNC and if so, whether it has conform and conforms to the
1684 rules about propagating values passed by reference. */
1686 static bool
1687 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1688 struct ipa_jump_func *jfunc)
1690 return src_plats->aggs
1691 && (!src_plats->aggs_by_ref
1692 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1695 /* Propagate scalar values across jump function JFUNC that is associated with
1696 edge CS and put the values into DEST_LAT. */
1698 static bool
1699 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1700 struct ipa_jump_func *jfunc,
1701 struct ipcp_param_lattices *dest_plats)
1703 bool ret = false;
1705 if (dest_plats->aggs_bottom)
1706 return false;
1708 if (jfunc->type == IPA_JF_PASS_THROUGH
1709 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1711 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1712 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1713 struct ipcp_param_lattices *src_plats;
1715 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1716 if (agg_pass_through_permissible_p (src_plats, jfunc))
1718 /* Currently we do not produce clobber aggregate jump
1719 functions, replace with merging when we do. */
1720 gcc_assert (!jfunc->agg.items);
1721 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1722 src_idx, 0);
1724 else
1725 ret |= set_agg_lats_contain_variable (dest_plats);
1727 else if (jfunc->type == IPA_JF_ANCESTOR
1728 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1730 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1731 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1732 struct ipcp_param_lattices *src_plats;
1734 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1735 if (src_plats->aggs && src_plats->aggs_by_ref)
1737 /* Currently we do not produce clobber aggregate jump
1738 functions, replace with merging when we do. */
1739 gcc_assert (!jfunc->agg.items);
1740 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1741 ipa_get_jf_ancestor_offset (jfunc));
1743 else if (!src_plats->aggs_by_ref)
1744 ret |= set_agg_lats_to_bottom (dest_plats);
1745 else
1746 ret |= set_agg_lats_contain_variable (dest_plats);
1748 else if (jfunc->agg.items)
1750 bool pre_existing = dest_plats->aggs != NULL;
1751 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1752 struct ipa_agg_jf_item *item;
1753 int i;
1755 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1756 return true;
1758 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1760 HOST_WIDE_INT val_size;
1762 if (item->offset < 0)
1763 continue;
1764 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1765 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
1767 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1768 &aglat, pre_existing, &ret))
1770 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
1771 aglat = &(*aglat)->next;
1773 else if (dest_plats->aggs_bottom)
1774 return true;
1777 ret |= set_chain_of_aglats_contains_variable (*aglat);
1779 else
1780 ret |= set_agg_lats_contain_variable (dest_plats);
1782 return ret;
1785 /* Propagate constants from the caller to the callee of CS. INFO describes the
1786 caller. */
1788 static bool
1789 propagate_constants_accross_call (struct cgraph_edge *cs)
1791 struct ipa_node_params *callee_info;
1792 enum availability availability;
1793 struct cgraph_node *callee, *alias_or_thunk;
1794 struct ipa_edge_args *args;
1795 bool ret = false;
1796 int i, args_count, parms_count;
1798 callee = cs->callee->function_symbol (&availability);
1799 if (!callee->definition)
1800 return false;
1801 gcc_checking_assert (callee->has_gimple_body_p ());
1802 callee_info = IPA_NODE_REF (callee);
1804 args = IPA_EDGE_REF (cs);
1805 args_count = ipa_get_cs_argument_count (args);
1806 parms_count = ipa_get_param_count (callee_info);
1807 if (parms_count == 0)
1808 return false;
1810 /* No propagation through instrumentation thunks is available yet.
1811 It should be possible with proper mapping of call args and
1812 instrumented callee params in the propagation loop below. But
1813 this case mostly occurs when legacy code calls instrumented code
1814 and it is not a primary target for optimizations.
1815 We detect instrumentation thunks in aliases and thunks chain by
1816 checking instrumentation_clone flag for chain source and target.
1817 Going through instrumentation thunks we always have it changed
1818 from 0 to 1 and all other nodes do not change it. */
1819 if (!cs->callee->instrumentation_clone
1820 && callee->instrumentation_clone)
1822 for (i = 0; i < parms_count; i++)
1823 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1824 i));
1825 return ret;
1828 /* If this call goes through a thunk we must not propagate to the first (0th)
1829 parameter. However, we might need to uncover a thunk from below a series
1830 of aliases first. */
1831 alias_or_thunk = cs->callee;
1832 while (alias_or_thunk->alias)
1833 alias_or_thunk = alias_or_thunk->get_alias_target ();
1834 if (alias_or_thunk->thunk.thunk_p)
1836 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1837 0));
1838 i = 1;
1840 else
1841 i = 0;
1843 for (; (i < args_count) && (i < parms_count); i++)
1845 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1846 struct ipcp_param_lattices *dest_plats;
1848 dest_plats = ipa_get_parm_lattices (callee_info, i);
1849 if (availability == AVAIL_INTERPOSABLE)
1850 ret |= set_all_contains_variable (dest_plats);
1851 else
1853 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1854 &dest_plats->itself);
1855 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
1856 &dest_plats->ctxlat);
1857 ret |= propagate_alignment_accross_jump_function (cs, jump_func,
1858 dest_plats);
1859 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1860 dest_plats);
1863 for (; i < parms_count; i++)
1864 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1866 return ret;
1869 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1870 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1871 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
1873 static tree
1874 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
1875 vec<tree> known_csts,
1876 vec<ipa_polymorphic_call_context> known_contexts,
1877 vec<ipa_agg_jump_function_p> known_aggs,
1878 struct ipa_agg_replacement_value *agg_reps,
1879 bool *speculative)
1881 int param_index = ie->indirect_info->param_index;
1882 HOST_WIDE_INT anc_offset;
1883 tree t;
1884 tree target = NULL;
1886 *speculative = false;
1888 if (param_index == -1
1889 || known_csts.length () <= (unsigned int) param_index)
1890 return NULL_TREE;
1892 if (!ie->indirect_info->polymorphic)
1894 tree t;
1896 if (ie->indirect_info->agg_contents)
1898 if (agg_reps)
1900 t = NULL;
1901 while (agg_reps)
1903 if (agg_reps->index == param_index
1904 && agg_reps->offset == ie->indirect_info->offset
1905 && agg_reps->by_ref == ie->indirect_info->by_ref)
1907 t = agg_reps->value;
1908 break;
1910 agg_reps = agg_reps->next;
1913 else if (known_aggs.length () > (unsigned int) param_index)
1915 struct ipa_agg_jump_function *agg;
1916 agg = known_aggs[param_index];
1917 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1918 ie->indirect_info->by_ref);
1920 else
1921 t = NULL;
1923 else
1924 t = known_csts[param_index];
1926 if (t &&
1927 TREE_CODE (t) == ADDR_EXPR
1928 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1929 return TREE_OPERAND (t, 0);
1930 else
1931 return NULL_TREE;
1934 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
1935 return NULL_TREE;
1937 gcc_assert (!ie->indirect_info->agg_contents);
1938 anc_offset = ie->indirect_info->offset;
1940 t = NULL;
1942 /* Try to work out value of virtual table pointer value in replacemnets. */
1943 if (!t && agg_reps && !ie->indirect_info->by_ref)
1945 while (agg_reps)
1947 if (agg_reps->index == param_index
1948 && agg_reps->offset == ie->indirect_info->offset
1949 && agg_reps->by_ref)
1951 t = agg_reps->value;
1952 break;
1954 agg_reps = agg_reps->next;
1958 /* Try to work out value of virtual table pointer value in known
1959 aggregate values. */
1960 if (!t && known_aggs.length () > (unsigned int) param_index
1961 && !ie->indirect_info->by_ref)
1963 struct ipa_agg_jump_function *agg;
1964 agg = known_aggs[param_index];
1965 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1966 true);
1969 /* If we found the virtual table pointer, lookup the target. */
1970 if (t)
1972 tree vtable;
1973 unsigned HOST_WIDE_INT offset;
1974 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
1976 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
1977 vtable, offset);
1978 if (target)
1980 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1981 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1982 || !possible_polymorphic_call_target_p
1983 (ie, cgraph_node::get (target)))
1984 target = ipa_impossible_devirt_target (ie, target);
1985 *speculative = ie->indirect_info->vptr_changed;
1986 if (!*speculative)
1987 return target;
1992 /* Do we know the constant value of pointer? */
1993 if (!t)
1994 t = known_csts[param_index];
1996 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
1998 ipa_polymorphic_call_context context;
1999 if (known_contexts.length () > (unsigned int) param_index)
2001 context = known_contexts[param_index];
2002 context.offset_by (anc_offset);
2003 if (ie->indirect_info->vptr_changed)
2004 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2005 ie->indirect_info->otr_type);
2006 if (t)
2008 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2009 (t, ie->indirect_info->otr_type, anc_offset);
2010 if (!ctx2.useless_p ())
2011 context.combine_with (ctx2, ie->indirect_info->otr_type);
2014 else if (t)
2016 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2017 anc_offset);
2018 if (ie->indirect_info->vptr_changed)
2019 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2020 ie->indirect_info->otr_type);
2022 else
2023 return NULL_TREE;
2025 vec <cgraph_node *>targets;
2026 bool final;
2028 targets = possible_polymorphic_call_targets
2029 (ie->indirect_info->otr_type,
2030 ie->indirect_info->otr_token,
2031 context, &final);
2032 if (!final || targets.length () > 1)
2034 struct cgraph_node *node;
2035 if (*speculative)
2036 return target;
2037 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2038 || ie->speculative || !ie->maybe_hot_p ())
2039 return NULL;
2040 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2041 ie->indirect_info->otr_token,
2042 context);
2043 if (node)
2045 *speculative = true;
2046 target = node->decl;
2048 else
2049 return NULL;
2051 else
2053 *speculative = false;
2054 if (targets.length () == 1)
2055 target = targets[0]->decl;
2056 else
2057 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2060 if (target && !possible_polymorphic_call_target_p (ie,
2061 cgraph_node::get (target)))
2062 target = ipa_impossible_devirt_target (ie, target);
2064 return target;
2068 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2069 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2070 return the destination. */
2072 tree
2073 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2074 vec<tree> known_csts,
2075 vec<ipa_polymorphic_call_context> known_contexts,
2076 vec<ipa_agg_jump_function_p> known_aggs,
2077 bool *speculative)
2079 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2080 known_aggs, NULL, speculative);
2083 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2084 and KNOWN_CONTEXTS. */
2086 static int
2087 devirtualization_time_bonus (struct cgraph_node *node,
2088 vec<tree> known_csts,
2089 vec<ipa_polymorphic_call_context> known_contexts,
2090 vec<ipa_agg_jump_function_p> known_aggs)
2092 struct cgraph_edge *ie;
2093 int res = 0;
2095 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2097 struct cgraph_node *callee;
2098 struct inline_summary *isummary;
2099 enum availability avail;
2100 tree target;
2101 bool speculative;
2103 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2104 known_aggs, &speculative);
2105 if (!target)
2106 continue;
2108 /* Only bare minimum benefit for clearly un-inlineable targets. */
2109 res += 1;
2110 callee = cgraph_node::get (target);
2111 if (!callee || !callee->definition)
2112 continue;
2113 callee = callee->function_symbol (&avail);
2114 if (avail < AVAIL_AVAILABLE)
2115 continue;
2116 isummary = inline_summaries->get (callee);
2117 if (!isummary->inlinable)
2118 continue;
2120 /* FIXME: The values below need re-considering and perhaps also
2121 integrating into the cost metrics, at lest in some very basic way. */
2122 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2123 res += 31 / ((int)speculative + 1);
2124 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2125 res += 15 / ((int)speculative + 1);
2126 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2127 || DECL_DECLARED_INLINE_P (callee->decl))
2128 res += 7 / ((int)speculative + 1);
2131 return res;
2134 /* Return time bonus incurred because of HINTS. */
2136 static int
2137 hint_time_bonus (inline_hints hints)
2139 int result = 0;
2140 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2141 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2142 if (hints & INLINE_HINT_array_index)
2143 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2144 return result;
2147 /* If there is a reason to penalize the function described by INFO in the
2148 cloning goodness evaluation, do so. */
2150 static inline int64_t
2151 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2153 if (info->node_within_scc)
2154 evaluation = (evaluation
2155 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2157 if (info->node_calling_single_call)
2158 evaluation = (evaluation
2159 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2160 / 100;
2162 return evaluation;
2165 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2166 and SIZE_COST and with the sum of frequencies of incoming edges to the
2167 potential new clone in FREQUENCIES. */
2169 static bool
2170 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2171 int freq_sum, gcov_type count_sum, int size_cost)
2173 if (time_benefit == 0
2174 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2175 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
2176 return false;
2178 gcc_assert (size_cost > 0);
2180 struct ipa_node_params *info = IPA_NODE_REF (node);
2181 if (max_count)
2183 int factor = (count_sum * 1000) / max_count;
2184 int64_t evaluation = (((int64_t) time_benefit * factor)
2185 / size_cost);
2186 evaluation = incorporate_penalties (info, evaluation);
2188 if (dump_file && (dump_flags & TDF_DETAILS))
2189 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2190 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2191 "%s%s) -> evaluation: " "%" PRId64
2192 ", threshold: %i\n",
2193 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2194 info->node_within_scc ? ", scc" : "",
2195 info->node_calling_single_call ? ", single_call" : "",
2196 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2198 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2200 else
2202 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2203 / size_cost);
2204 evaluation = incorporate_penalties (info, evaluation);
2206 if (dump_file && (dump_flags & TDF_DETAILS))
2207 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2208 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2209 "%" PRId64 ", threshold: %i\n",
2210 time_benefit, size_cost, freq_sum,
2211 info->node_within_scc ? ", scc" : "",
2212 info->node_calling_single_call ? ", single_call" : "",
2213 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2215 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2219 /* Return all context independent values from aggregate lattices in PLATS in a
2220 vector. Return NULL if there are none. */
2222 static vec<ipa_agg_jf_item, va_gc> *
2223 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2225 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2227 if (plats->aggs_bottom
2228 || plats->aggs_contain_variable
2229 || plats->aggs_count == 0)
2230 return NULL;
2232 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2233 aglat;
2234 aglat = aglat->next)
2235 if (aglat->is_single_const ())
2237 struct ipa_agg_jf_item item;
2238 item.offset = aglat->offset;
2239 item.value = aglat->values->value;
2240 vec_safe_push (res, item);
2242 return res;
2245 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2246 populate them with values of parameters that are known independent of the
2247 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2248 non-NULL, the movement cost of all removable parameters will be stored in
2249 it. */
2251 static bool
2252 gather_context_independent_values (struct ipa_node_params *info,
2253 vec<tree> *known_csts,
2254 vec<ipa_polymorphic_call_context>
2255 *known_contexts,
2256 vec<ipa_agg_jump_function> *known_aggs,
2257 int *removable_params_cost)
2259 int i, count = ipa_get_param_count (info);
2260 bool ret = false;
2262 known_csts->create (0);
2263 known_contexts->create (0);
2264 known_csts->safe_grow_cleared (count);
2265 known_contexts->safe_grow_cleared (count);
2266 if (known_aggs)
2268 known_aggs->create (0);
2269 known_aggs->safe_grow_cleared (count);
2272 if (removable_params_cost)
2273 *removable_params_cost = 0;
2275 for (i = 0; i < count ; i++)
2277 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2278 ipcp_lattice<tree> *lat = &plats->itself;
2280 if (lat->is_single_const ())
2282 ipcp_value<tree> *val = lat->values;
2283 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2284 (*known_csts)[i] = val->value;
2285 if (removable_params_cost)
2286 *removable_params_cost
2287 += estimate_move_cost (TREE_TYPE (val->value), false);
2288 ret = true;
2290 else if (removable_params_cost
2291 && !ipa_is_param_used (info, i))
2292 *removable_params_cost
2293 += ipa_get_param_move_cost (info, i);
2295 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2296 if (ctxlat->is_single_const ())
2298 (*known_contexts)[i] = ctxlat->values->value;
2299 ret = true;
2302 if (known_aggs)
2304 vec<ipa_agg_jf_item, va_gc> *agg_items;
2305 struct ipa_agg_jump_function *ajf;
2307 agg_items = context_independent_aggregate_values (plats);
2308 ajf = &(*known_aggs)[i];
2309 ajf->items = agg_items;
2310 ajf->by_ref = plats->aggs_by_ref;
2311 ret |= agg_items != NULL;
2315 return ret;
2318 /* The current interface in ipa-inline-analysis requires a pointer vector.
2319 Create it.
2321 FIXME: That interface should be re-worked, this is slightly silly. Still,
2322 I'd like to discuss how to change it first and this demonstrates the
2323 issue. */
2325 static vec<ipa_agg_jump_function_p>
2326 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2328 vec<ipa_agg_jump_function_p> ret;
2329 struct ipa_agg_jump_function *ajf;
2330 int i;
2332 ret.create (known_aggs.length ());
2333 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2334 ret.quick_push (ajf);
2335 return ret;
2338 /* Perform time and size measurement of NODE with the context given in
2339 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2340 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2341 all context-independent removable parameters and EST_MOVE_COST of estimated
2342 movement of the considered parameter and store it into VAL. */
2344 static void
2345 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2346 vec<ipa_polymorphic_call_context> known_contexts,
2347 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2348 int base_time, int removable_params_cost,
2349 int est_move_cost, ipcp_value_base *val)
2351 int time, size, time_benefit;
2352 inline_hints hints;
2354 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2355 known_aggs_ptrs, &size, &time,
2356 &hints);
2357 time_benefit = base_time - time
2358 + devirtualization_time_bonus (node, known_csts, known_contexts,
2359 known_aggs_ptrs)
2360 + hint_time_bonus (hints)
2361 + removable_params_cost + est_move_cost;
2363 gcc_checking_assert (size >=0);
2364 /* The inliner-heuristics based estimates may think that in certain
2365 contexts some functions do not have any size at all but we want
2366 all specializations to have at least a tiny cost, not least not to
2367 divide by zero. */
2368 if (size == 0)
2369 size = 1;
2371 val->local_time_benefit = time_benefit;
2372 val->local_size_cost = size;
2375 /* Iterate over known values of parameters of NODE and estimate the local
2376 effects in terms of time and size they have. */
2378 static void
2379 estimate_local_effects (struct cgraph_node *node)
2381 struct ipa_node_params *info = IPA_NODE_REF (node);
2382 int i, count = ipa_get_param_count (info);
2383 vec<tree> known_csts;
2384 vec<ipa_polymorphic_call_context> known_contexts;
2385 vec<ipa_agg_jump_function> known_aggs;
2386 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2387 bool always_const;
2388 int base_time = inline_summaries->get (node)->time;
2389 int removable_params_cost;
2391 if (!count || !ipcp_versionable_function_p (node))
2392 return;
2394 if (dump_file && (dump_flags & TDF_DETAILS))
2395 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2396 node->name (), node->order, base_time);
2398 always_const = gather_context_independent_values (info, &known_csts,
2399 &known_contexts, &known_aggs,
2400 &removable_params_cost);
2401 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2402 if (always_const)
2404 struct caller_statistics stats;
2405 inline_hints hints;
2406 int time, size;
2408 init_caller_stats (&stats);
2409 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2410 false);
2411 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2412 known_aggs_ptrs, &size, &time, &hints);
2413 time -= devirtualization_time_bonus (node, known_csts, known_contexts,
2414 known_aggs_ptrs);
2415 time -= hint_time_bonus (hints);
2416 time -= removable_params_cost;
2417 size -= stats.n_calls * removable_params_cost;
2419 if (dump_file)
2420 fprintf (dump_file, " - context independent values, size: %i, "
2421 "time_benefit: %i\n", size, base_time - time);
2423 if (size <= 0
2424 || node->will_be_removed_from_program_if_no_direct_calls_p ())
2426 info->do_clone_for_all_contexts = true;
2427 base_time = time;
2429 if (dump_file)
2430 fprintf (dump_file, " Decided to specialize for all "
2431 "known contexts, code not going to grow.\n");
2433 else if (good_cloning_opportunity_p (node, base_time - time,
2434 stats.freq_sum, stats.count_sum,
2435 size))
2437 if (size + overall_size <= max_new_size)
2439 info->do_clone_for_all_contexts = true;
2440 base_time = time;
2441 overall_size += size;
2443 if (dump_file)
2444 fprintf (dump_file, " Decided to specialize for all "
2445 "known contexts, growth deemed beneficial.\n");
2447 else if (dump_file && (dump_flags & TDF_DETAILS))
2448 fprintf (dump_file, " Not cloning for all contexts because "
2449 "max_new_size would be reached with %li.\n",
2450 size + overall_size);
2454 for (i = 0; i < count ; i++)
2456 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2457 ipcp_lattice<tree> *lat = &plats->itself;
2458 ipcp_value<tree> *val;
2460 if (lat->bottom
2461 || !lat->values
2462 || known_csts[i])
2463 continue;
2465 for (val = lat->values; val; val = val->next)
2467 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2468 known_csts[i] = val->value;
2470 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2471 perform_estimation_of_a_value (node, known_csts, known_contexts,
2472 known_aggs_ptrs, base_time,
2473 removable_params_cost, emc, val);
2475 if (dump_file && (dump_flags & TDF_DETAILS))
2477 fprintf (dump_file, " - estimates for value ");
2478 print_ipcp_constant_value (dump_file, val->value);
2479 fprintf (dump_file, " for ");
2480 ipa_dump_param (dump_file, info, i);
2481 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2482 val->local_time_benefit, val->local_size_cost);
2485 known_csts[i] = NULL_TREE;
2488 for (i = 0; i < count; i++)
2490 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2492 if (!plats->virt_call)
2493 continue;
2495 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2496 ipcp_value<ipa_polymorphic_call_context> *val;
2498 if (ctxlat->bottom
2499 || !ctxlat->values
2500 || !known_contexts[i].useless_p ())
2501 continue;
2503 for (val = ctxlat->values; val; val = val->next)
2505 known_contexts[i] = val->value;
2506 perform_estimation_of_a_value (node, known_csts, known_contexts,
2507 known_aggs_ptrs, base_time,
2508 removable_params_cost, 0, val);
2510 if (dump_file && (dump_flags & TDF_DETAILS))
2512 fprintf (dump_file, " - estimates for polymorphic context ");
2513 print_ipcp_constant_value (dump_file, val->value);
2514 fprintf (dump_file, " for ");
2515 ipa_dump_param (dump_file, info, i);
2516 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2517 val->local_time_benefit, val->local_size_cost);
2520 known_contexts[i] = ipa_polymorphic_call_context ();
2523 for (i = 0; i < count ; i++)
2525 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2526 struct ipa_agg_jump_function *ajf;
2527 struct ipcp_agg_lattice *aglat;
2529 if (plats->aggs_bottom || !plats->aggs)
2530 continue;
2532 ajf = &known_aggs[i];
2533 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2535 ipcp_value<tree> *val;
2536 if (aglat->bottom || !aglat->values
2537 /* If the following is true, the one value is in known_aggs. */
2538 || (!plats->aggs_contain_variable
2539 && aglat->is_single_const ()))
2540 continue;
2542 for (val = aglat->values; val; val = val->next)
2544 struct ipa_agg_jf_item item;
2546 item.offset = aglat->offset;
2547 item.value = val->value;
2548 vec_safe_push (ajf->items, item);
2550 perform_estimation_of_a_value (node, known_csts, known_contexts,
2551 known_aggs_ptrs, base_time,
2552 removable_params_cost, 0, val);
2554 if (dump_file && (dump_flags & TDF_DETAILS))
2556 fprintf (dump_file, " - estimates for value ");
2557 print_ipcp_constant_value (dump_file, val->value);
2558 fprintf (dump_file, " for ");
2559 ipa_dump_param (dump_file, info, i);
2560 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2561 "]: time_benefit: %i, size: %i\n",
2562 plats->aggs_by_ref ? "ref " : "",
2563 aglat->offset,
2564 val->local_time_benefit, val->local_size_cost);
2567 ajf->items->pop ();
2572 for (i = 0; i < count ; i++)
2573 vec_free (known_aggs[i].items);
2575 known_csts.release ();
2576 known_contexts.release ();
2577 known_aggs.release ();
2578 known_aggs_ptrs.release ();
2582 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2583 topological sort of values. */
2585 template <typename valtype>
2586 void
2587 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
2589 ipcp_value_source<valtype> *src;
2591 if (cur_val->dfs)
2592 return;
2594 dfs_counter++;
2595 cur_val->dfs = dfs_counter;
2596 cur_val->low_link = dfs_counter;
2598 cur_val->topo_next = stack;
2599 stack = cur_val;
2600 cur_val->on_stack = true;
2602 for (src = cur_val->sources; src; src = src->next)
2603 if (src->val)
2605 if (src->val->dfs == 0)
2607 add_val (src->val);
2608 if (src->val->low_link < cur_val->low_link)
2609 cur_val->low_link = src->val->low_link;
2611 else if (src->val->on_stack
2612 && src->val->dfs < cur_val->low_link)
2613 cur_val->low_link = src->val->dfs;
2616 if (cur_val->dfs == cur_val->low_link)
2618 ipcp_value<valtype> *v, *scc_list = NULL;
2622 v = stack;
2623 stack = v->topo_next;
2624 v->on_stack = false;
2626 v->scc_next = scc_list;
2627 scc_list = v;
2629 while (v != cur_val);
2631 cur_val->topo_next = values_topo;
2632 values_topo = cur_val;
2636 /* Add all values in lattices associated with NODE to the topological sort if
2637 they are not there yet. */
2639 static void
2640 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
2642 struct ipa_node_params *info = IPA_NODE_REF (node);
2643 int i, count = ipa_get_param_count (info);
2645 for (i = 0; i < count ; i++)
2647 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2648 ipcp_lattice<tree> *lat = &plats->itself;
2649 struct ipcp_agg_lattice *aglat;
2651 if (!lat->bottom)
2653 ipcp_value<tree> *val;
2654 for (val = lat->values; val; val = val->next)
2655 topo->constants.add_val (val);
2658 if (!plats->aggs_bottom)
2659 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2660 if (!aglat->bottom)
2662 ipcp_value<tree> *val;
2663 for (val = aglat->values; val; val = val->next)
2664 topo->constants.add_val (val);
2667 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2668 if (!ctxlat->bottom)
2670 ipcp_value<ipa_polymorphic_call_context> *ctxval;
2671 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
2672 topo->contexts.add_val (ctxval);
2677 /* One pass of constants propagation along the call graph edges, from callers
2678 to callees (requires topological ordering in TOPO), iterate over strongly
2679 connected components. */
2681 static void
2682 propagate_constants_topo (struct ipa_topo_info *topo)
2684 int i;
2686 for (i = topo->nnodes - 1; i >= 0; i--)
2688 unsigned j;
2689 struct cgraph_node *v, *node = topo->order[i];
2690 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
2692 /* First, iteratively propagate within the strongly connected component
2693 until all lattices stabilize. */
2694 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2695 if (v->has_gimple_body_p ())
2696 push_node_to_stack (topo, v);
2698 v = pop_node_from_stack (topo);
2699 while (v)
2701 struct cgraph_edge *cs;
2703 for (cs = v->callees; cs; cs = cs->next_callee)
2704 if (ipa_edge_within_scc (cs))
2706 IPA_NODE_REF (v)->node_within_scc = true;
2707 if (propagate_constants_accross_call (cs))
2708 push_node_to_stack (topo, cs->callee->function_symbol ());
2710 v = pop_node_from_stack (topo);
2713 /* Afterwards, propagate along edges leading out of the SCC, calculates
2714 the local effects of the discovered constants and all valid values to
2715 their topological sort. */
2716 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2717 if (v->has_gimple_body_p ())
2719 struct cgraph_edge *cs;
2721 estimate_local_effects (v);
2722 add_all_node_vals_to_toposort (v, topo);
2723 for (cs = v->callees; cs; cs = cs->next_callee)
2724 if (!ipa_edge_within_scc (cs))
2725 propagate_constants_accross_call (cs);
2727 cycle_nodes.release ();
2732 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2733 the bigger one if otherwise. */
2735 static int
2736 safe_add (int a, int b)
2738 if (a > INT_MAX/2 || b > INT_MAX/2)
2739 return a > b ? a : b;
2740 else
2741 return a + b;
2745 /* Propagate the estimated effects of individual values along the topological
2746 from the dependent values to those they depend on. */
2748 template <typename valtype>
2749 void
2750 value_topo_info<valtype>::propagate_effects ()
2752 ipcp_value<valtype> *base;
2754 for (base = values_topo; base; base = base->topo_next)
2756 ipcp_value_source<valtype> *src;
2757 ipcp_value<valtype> *val;
2758 int time = 0, size = 0;
2760 for (val = base; val; val = val->scc_next)
2762 time = safe_add (time,
2763 val->local_time_benefit + val->prop_time_benefit);
2764 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2767 for (val = base; val; val = val->scc_next)
2768 for (src = val->sources; src; src = src->next)
2769 if (src->val
2770 && src->cs->maybe_hot_p ())
2772 src->val->prop_time_benefit = safe_add (time,
2773 src->val->prop_time_benefit);
2774 src->val->prop_size_cost = safe_add (size,
2775 src->val->prop_size_cost);
2781 /* Propagate constants, polymorphic contexts and their effects from the
2782 summaries interprocedurally. */
2784 static void
2785 ipcp_propagate_stage (struct ipa_topo_info *topo)
2787 struct cgraph_node *node;
2789 if (dump_file)
2790 fprintf (dump_file, "\n Propagating constants:\n\n");
2792 if (in_lto_p)
2793 ipa_update_after_lto_read ();
2796 FOR_EACH_DEFINED_FUNCTION (node)
2798 struct ipa_node_params *info = IPA_NODE_REF (node);
2800 determine_versionability (node);
2801 if (node->has_gimple_body_p ())
2803 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2804 ipa_get_param_count (info));
2805 initialize_node_lattices (node);
2807 if (node->definition && !node->alias)
2808 overall_size += inline_summaries->get (node)->self_size;
2809 if (node->count > max_count)
2810 max_count = node->count;
2813 max_new_size = overall_size;
2814 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2815 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2816 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2818 if (dump_file)
2819 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2820 overall_size, max_new_size);
2822 propagate_constants_topo (topo);
2823 #ifdef ENABLE_CHECKING
2824 ipcp_verify_propagated_values ();
2825 #endif
2826 topo->constants.propagate_effects ();
2827 topo->contexts.propagate_effects ();
2829 if (dump_file)
2831 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2832 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2836 /* Discover newly direct outgoing edges from NODE which is a new clone with
2837 known KNOWN_CSTS and make them direct. */
2839 static void
2840 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2841 vec<tree> known_csts,
2842 vec<ipa_polymorphic_call_context>
2843 known_contexts,
2844 struct ipa_agg_replacement_value *aggvals)
2846 struct cgraph_edge *ie, *next_ie;
2847 bool found = false;
2849 for (ie = node->indirect_calls; ie; ie = next_ie)
2851 tree target;
2852 bool speculative;
2854 next_ie = ie->next_callee;
2855 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2856 vNULL, aggvals, &speculative);
2857 if (target)
2859 bool agg_contents = ie->indirect_info->agg_contents;
2860 bool polymorphic = ie->indirect_info->polymorphic;
2861 int param_index = ie->indirect_info->param_index;
2862 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
2863 speculative);
2864 found = true;
2866 if (cs && !agg_contents && !polymorphic)
2868 struct ipa_node_params *info = IPA_NODE_REF (node);
2869 int c = ipa_get_controlled_uses (info, param_index);
2870 if (c != IPA_UNDESCRIBED_USE)
2872 struct ipa_ref *to_del;
2874 c--;
2875 ipa_set_controlled_uses (info, param_index, c);
2876 if (dump_file && (dump_flags & TDF_DETAILS))
2877 fprintf (dump_file, " controlled uses count of param "
2878 "%i bumped down to %i\n", param_index, c);
2879 if (c == 0
2880 && (to_del = node->find_reference (cs->callee, NULL, 0)))
2882 if (dump_file && (dump_flags & TDF_DETAILS))
2883 fprintf (dump_file, " and even removing its "
2884 "cloning-created reference\n");
2885 to_del->remove_reference ();
2891 /* Turning calls to direct calls will improve overall summary. */
2892 if (found)
2893 inline_update_overall_summary (node);
2896 /* Vector of pointers which for linked lists of clones of an original crgaph
2897 edge. */
2899 static vec<cgraph_edge *> next_edge_clone;
2900 static vec<cgraph_edge *> prev_edge_clone;
2902 static inline void
2903 grow_edge_clone_vectors (void)
2905 if (next_edge_clone.length ()
2906 <= (unsigned) symtab->edges_max_uid)
2907 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2908 if (prev_edge_clone.length ()
2909 <= (unsigned) symtab->edges_max_uid)
2910 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2913 /* Edge duplication hook to grow the appropriate linked list in
2914 next_edge_clone. */
2916 static void
2917 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2918 void *)
2920 grow_edge_clone_vectors ();
2922 struct cgraph_edge *old_next = next_edge_clone[src->uid];
2923 if (old_next)
2924 prev_edge_clone[old_next->uid] = dst;
2925 prev_edge_clone[dst->uid] = src;
2927 next_edge_clone[dst->uid] = old_next;
2928 next_edge_clone[src->uid] = dst;
2931 /* Hook that is called by cgraph.c when an edge is removed. */
2933 static void
2934 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
2936 grow_edge_clone_vectors ();
2938 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
2939 struct cgraph_edge *next = next_edge_clone[cs->uid];
2940 if (prev)
2941 next_edge_clone[prev->uid] = next;
2942 if (next)
2943 prev_edge_clone[next->uid] = prev;
2946 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2947 parameter with the given INDEX. */
2949 static tree
2950 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2951 int index)
2953 struct ipa_agg_replacement_value *aggval;
2955 aggval = ipa_get_agg_replacements_for_node (node);
2956 while (aggval)
2958 if (aggval->offset == offset
2959 && aggval->index == index)
2960 return aggval->value;
2961 aggval = aggval->next;
2963 return NULL_TREE;
2966 /* Return true is NODE is DEST or its clone for all contexts. */
2968 static bool
2969 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
2971 if (node == dest)
2972 return true;
2974 struct ipa_node_params *info = IPA_NODE_REF (node);
2975 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
2978 /* Return true if edge CS does bring about the value described by SRC to node
2979 DEST or its clone for all contexts. */
2981 static bool
2982 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
2983 cgraph_node *dest)
2985 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2986 enum availability availability;
2987 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
2989 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
2990 || availability <= AVAIL_INTERPOSABLE
2991 || caller_info->node_dead)
2992 return false;
2993 if (!src->val)
2994 return true;
2996 if (caller_info->ipcp_orig_node)
2998 tree t;
2999 if (src->offset == -1)
3000 t = caller_info->known_csts[src->index];
3001 else
3002 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3003 return (t != NULL_TREE
3004 && values_equal_for_ipcp_p (src->val->value, t));
3006 else
3008 struct ipcp_agg_lattice *aglat;
3009 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3010 src->index);
3011 if (src->offset == -1)
3012 return (plats->itself.is_single_const ()
3013 && values_equal_for_ipcp_p (src->val->value,
3014 plats->itself.values->value));
3015 else
3017 if (plats->aggs_bottom || plats->aggs_contain_variable)
3018 return false;
3019 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3020 if (aglat->offset == src->offset)
3021 return (aglat->is_single_const ()
3022 && values_equal_for_ipcp_p (src->val->value,
3023 aglat->values->value));
3025 return false;
3029 /* Return true if edge CS does bring about the value described by SRC to node
3030 DEST or its clone for all contexts. */
3032 static bool
3033 cgraph_edge_brings_value_p (cgraph_edge *cs,
3034 ipcp_value_source<ipa_polymorphic_call_context> *src,
3035 cgraph_node *dest)
3037 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3038 cgraph_node *real_dest = cs->callee->function_symbol ();
3040 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3041 || caller_info->node_dead)
3042 return false;
3043 if (!src->val)
3044 return true;
3046 if (caller_info->ipcp_orig_node)
3047 return (caller_info->known_contexts.length () > (unsigned) src->index)
3048 && values_equal_for_ipcp_p (src->val->value,
3049 caller_info->known_contexts[src->index]);
3051 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3052 src->index);
3053 return plats->ctxlat.is_single_const ()
3054 && values_equal_for_ipcp_p (src->val->value,
3055 plats->ctxlat.values->value);
3058 /* Get the next clone in the linked list of clones of an edge. */
3060 static inline struct cgraph_edge *
3061 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3063 return next_edge_clone[cs->uid];
3066 /* Given VAL that is intended for DEST, iterate over all its sources and if
3067 they still hold, add their edge frequency and their number into *FREQUENCY
3068 and *CALLER_COUNT respectively. */
3070 template <typename valtype>
3071 static bool
3072 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3073 int *freq_sum,
3074 gcov_type *count_sum, int *caller_count)
3076 ipcp_value_source<valtype> *src;
3077 int freq = 0, count = 0;
3078 gcov_type cnt = 0;
3079 bool hot = false;
3081 for (src = val->sources; src; src = src->next)
3083 struct cgraph_edge *cs = src->cs;
3084 while (cs)
3086 if (cgraph_edge_brings_value_p (cs, src, dest))
3088 count++;
3089 freq += cs->frequency;
3090 cnt += cs->count;
3091 hot |= cs->maybe_hot_p ();
3093 cs = get_next_cgraph_edge_clone (cs);
3097 *freq_sum = freq;
3098 *count_sum = cnt;
3099 *caller_count = count;
3100 return hot;
3103 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3104 is assumed their number is known and equal to CALLER_COUNT. */
3106 template <typename valtype>
3107 static vec<cgraph_edge *>
3108 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3109 int caller_count)
3111 ipcp_value_source<valtype> *src;
3112 vec<cgraph_edge *> ret;
3114 ret.create (caller_count);
3115 for (src = val->sources; src; src = src->next)
3117 struct cgraph_edge *cs = src->cs;
3118 while (cs)
3120 if (cgraph_edge_brings_value_p (cs, src, dest))
3121 ret.quick_push (cs);
3122 cs = get_next_cgraph_edge_clone (cs);
3126 return ret;
3129 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3130 Return it or NULL if for some reason it cannot be created. */
3132 static struct ipa_replace_map *
3133 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3135 struct ipa_replace_map *replace_map;
3138 replace_map = ggc_alloc<ipa_replace_map> ();
3139 if (dump_file)
3141 fprintf (dump_file, " replacing ");
3142 ipa_dump_param (dump_file, info, parm_num);
3144 fprintf (dump_file, " with const ");
3145 print_generic_expr (dump_file, value, 0);
3146 fprintf (dump_file, "\n");
3148 replace_map->old_tree = NULL;
3149 replace_map->parm_num = parm_num;
3150 replace_map->new_tree = value;
3151 replace_map->replace_p = true;
3152 replace_map->ref_p = false;
3154 return replace_map;
3157 /* Dump new profiling counts */
3159 static void
3160 dump_profile_updates (struct cgraph_node *orig_node,
3161 struct cgraph_node *new_node)
3163 struct cgraph_edge *cs;
3165 fprintf (dump_file, " setting count of the specialized node to "
3166 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3167 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3168 fprintf (dump_file, " edge to %s has count "
3169 HOST_WIDE_INT_PRINT_DEC "\n",
3170 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3172 fprintf (dump_file, " setting count of the original node to "
3173 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3174 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3175 fprintf (dump_file, " edge to %s is left with "
3176 HOST_WIDE_INT_PRINT_DEC "\n",
3177 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3180 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3181 their profile information to reflect this. */
3183 static void
3184 update_profiling_info (struct cgraph_node *orig_node,
3185 struct cgraph_node *new_node)
3187 struct cgraph_edge *cs;
3188 struct caller_statistics stats;
3189 gcov_type new_sum, orig_sum;
3190 gcov_type remainder, orig_node_count = orig_node->count;
3192 if (orig_node_count == 0)
3193 return;
3195 init_caller_stats (&stats);
3196 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3197 false);
3198 orig_sum = stats.count_sum;
3199 init_caller_stats (&stats);
3200 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3201 false);
3202 new_sum = stats.count_sum;
3204 if (orig_node_count < orig_sum + new_sum)
3206 if (dump_file)
3207 fprintf (dump_file, " Problem: node %s/%i has too low count "
3208 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3209 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3210 orig_node->name (), orig_node->order,
3211 (HOST_WIDE_INT) orig_node_count,
3212 (HOST_WIDE_INT) (orig_sum + new_sum));
3214 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3215 if (dump_file)
3216 fprintf (dump_file, " proceeding by pretending it was "
3217 HOST_WIDE_INT_PRINT_DEC "\n",
3218 (HOST_WIDE_INT) orig_node_count);
3221 new_node->count = new_sum;
3222 remainder = orig_node_count - new_sum;
3223 orig_node->count = remainder;
3225 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3226 if (cs->frequency)
3227 cs->count = apply_probability (cs->count,
3228 GCOV_COMPUTE_SCALE (new_sum,
3229 orig_node_count));
3230 else
3231 cs->count = 0;
3233 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3234 cs->count = apply_probability (cs->count,
3235 GCOV_COMPUTE_SCALE (remainder,
3236 orig_node_count));
3238 if (dump_file)
3239 dump_profile_updates (orig_node, new_node);
3242 /* Update the respective profile of specialized NEW_NODE and the original
3243 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3244 have been redirected to the specialized version. */
3246 static void
3247 update_specialized_profile (struct cgraph_node *new_node,
3248 struct cgraph_node *orig_node,
3249 gcov_type redirected_sum)
3251 struct cgraph_edge *cs;
3252 gcov_type new_node_count, orig_node_count = orig_node->count;
3254 if (dump_file)
3255 fprintf (dump_file, " the sum of counts of redirected edges is "
3256 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3257 if (orig_node_count == 0)
3258 return;
3260 gcc_assert (orig_node_count >= redirected_sum);
3262 new_node_count = new_node->count;
3263 new_node->count += redirected_sum;
3264 orig_node->count -= redirected_sum;
3266 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3267 if (cs->frequency)
3268 cs->count += apply_probability (cs->count,
3269 GCOV_COMPUTE_SCALE (redirected_sum,
3270 new_node_count));
3271 else
3272 cs->count = 0;
3274 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3276 gcov_type dec = apply_probability (cs->count,
3277 GCOV_COMPUTE_SCALE (redirected_sum,
3278 orig_node_count));
3279 if (dec < cs->count)
3280 cs->count -= dec;
3281 else
3282 cs->count = 0;
3285 if (dump_file)
3286 dump_profile_updates (orig_node, new_node);
3289 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3290 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3291 redirect all edges in CALLERS to it. */
3293 static struct cgraph_node *
3294 create_specialized_node (struct cgraph_node *node,
3295 vec<tree> known_csts,
3296 vec<ipa_polymorphic_call_context> known_contexts,
3297 struct ipa_agg_replacement_value *aggvals,
3298 vec<cgraph_edge *> callers)
3300 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3301 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3302 struct ipa_agg_replacement_value *av;
3303 struct cgraph_node *new_node;
3304 int i, count = ipa_get_param_count (info);
3305 bitmap args_to_skip;
3307 gcc_assert (!info->ipcp_orig_node);
3309 if (node->local.can_change_signature)
3311 args_to_skip = BITMAP_GGC_ALLOC ();
3312 for (i = 0; i < count; i++)
3314 tree t = known_csts[i];
3316 if (t || !ipa_is_param_used (info, i))
3317 bitmap_set_bit (args_to_skip, i);
3320 else
3322 args_to_skip = NULL;
3323 if (dump_file && (dump_flags & TDF_DETAILS))
3324 fprintf (dump_file, " cannot change function signature\n");
3327 for (i = 0; i < count ; i++)
3329 tree t = known_csts[i];
3330 if (t)
3332 struct ipa_replace_map *replace_map;
3334 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3335 replace_map = get_replacement_map (info, t, i);
3336 if (replace_map)
3337 vec_safe_push (replace_trees, replace_map);
3341 new_node = node->create_virtual_clone (callers, replace_trees,
3342 args_to_skip, "constprop");
3343 ipa_set_node_agg_value_chain (new_node, aggvals);
3344 for (av = aggvals; av; av = av->next)
3345 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3347 if (dump_file && (dump_flags & TDF_DETAILS))
3349 fprintf (dump_file, " the new node is %s/%i.\n",
3350 new_node->name (), new_node->order);
3351 if (known_contexts.exists ())
3353 for (i = 0; i < count ; i++)
3354 if (!known_contexts[i].useless_p ())
3356 fprintf (dump_file, " known ctx %i is ", i);
3357 known_contexts[i].dump (dump_file);
3360 if (aggvals)
3361 ipa_dump_agg_replacement_values (dump_file, aggvals);
3363 ipa_check_create_node_params ();
3364 update_profiling_info (node, new_node);
3365 new_info = IPA_NODE_REF (new_node);
3366 new_info->ipcp_orig_node = node;
3367 new_info->known_csts = known_csts;
3368 new_info->known_contexts = known_contexts;
3370 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3372 callers.release ();
3373 return new_node;
3376 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3377 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3379 static void
3380 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3381 vec<tree> known_csts,
3382 vec<cgraph_edge *> callers)
3384 struct ipa_node_params *info = IPA_NODE_REF (node);
3385 int i, count = ipa_get_param_count (info);
3387 for (i = 0; i < count ; i++)
3389 struct cgraph_edge *cs;
3390 tree newval = NULL_TREE;
3391 int j;
3392 bool first = true;
3394 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3395 continue;
3397 FOR_EACH_VEC_ELT (callers, j, cs)
3399 struct ipa_jump_func *jump_func;
3400 tree t;
3402 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3404 newval = NULL_TREE;
3405 break;
3407 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3408 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3409 if (!t
3410 || (newval
3411 && !values_equal_for_ipcp_p (t, newval))
3412 || (!first && !newval))
3414 newval = NULL_TREE;
3415 break;
3417 else
3418 newval = t;
3419 first = false;
3422 if (newval)
3424 if (dump_file && (dump_flags & TDF_DETAILS))
3426 fprintf (dump_file, " adding an extra known scalar value ");
3427 print_ipcp_constant_value (dump_file, newval);
3428 fprintf (dump_file, " for ");
3429 ipa_dump_param (dump_file, info, i);
3430 fprintf (dump_file, "\n");
3433 known_csts[i] = newval;
3438 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3439 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3440 CALLERS. */
3442 static void
3443 find_more_contexts_for_caller_subset (cgraph_node *node,
3444 vec<ipa_polymorphic_call_context>
3445 *known_contexts,
3446 vec<cgraph_edge *> callers)
3448 ipa_node_params *info = IPA_NODE_REF (node);
3449 int i, count = ipa_get_param_count (info);
3451 for (i = 0; i < count ; i++)
3453 cgraph_edge *cs;
3455 if (ipa_get_poly_ctx_lat (info, i)->bottom
3456 || (known_contexts->exists ()
3457 && !(*known_contexts)[i].useless_p ()))
3458 continue;
3460 ipa_polymorphic_call_context newval;
3461 bool first = true;
3462 int j;
3464 FOR_EACH_VEC_ELT (callers, j, cs)
3466 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3467 return;
3468 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3470 ipa_polymorphic_call_context ctx;
3471 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3472 jfunc);
3473 if (first)
3475 newval = ctx;
3476 first = false;
3478 else
3479 newval.meet_with (ctx);
3480 if (newval.useless_p ())
3481 break;
3484 if (!newval.useless_p ())
3486 if (dump_file && (dump_flags & TDF_DETAILS))
3488 fprintf (dump_file, " adding an extra known polymorphic "
3489 "context ");
3490 print_ipcp_constant_value (dump_file, newval);
3491 fprintf (dump_file, " for ");
3492 ipa_dump_param (dump_file, info, i);
3493 fprintf (dump_file, "\n");
3496 if (!known_contexts->exists ())
3497 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3498 (*known_contexts)[i] = newval;
3504 /* Go through PLATS and create a vector of values consisting of values and
3505 offsets (minus OFFSET) of lattices that contain only a single value. */
3507 static vec<ipa_agg_jf_item>
3508 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3510 vec<ipa_agg_jf_item> res = vNULL;
3512 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3513 return vNULL;
3515 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3516 if (aglat->is_single_const ())
3518 struct ipa_agg_jf_item ti;
3519 ti.offset = aglat->offset - offset;
3520 ti.value = aglat->values->value;
3521 res.safe_push (ti);
3523 return res;
3526 /* Intersect all values in INTER with single value lattices in PLATS (while
3527 subtracting OFFSET). */
3529 static void
3530 intersect_with_plats (struct ipcp_param_lattices *plats,
3531 vec<ipa_agg_jf_item> *inter,
3532 HOST_WIDE_INT offset)
3534 struct ipcp_agg_lattice *aglat;
3535 struct ipa_agg_jf_item *item;
3536 int k;
3538 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3540 inter->release ();
3541 return;
3544 aglat = plats->aggs;
3545 FOR_EACH_VEC_ELT (*inter, k, item)
3547 bool found = false;
3548 if (!item->value)
3549 continue;
3550 while (aglat)
3552 if (aglat->offset - offset > item->offset)
3553 break;
3554 if (aglat->offset - offset == item->offset)
3556 gcc_checking_assert (item->value);
3557 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
3558 found = true;
3559 break;
3561 aglat = aglat->next;
3563 if (!found)
3564 item->value = NULL_TREE;
3568 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3569 vector result while subtracting OFFSET from the individual value offsets. */
3571 static vec<ipa_agg_jf_item>
3572 agg_replacements_to_vector (struct cgraph_node *node, int index,
3573 HOST_WIDE_INT offset)
3575 struct ipa_agg_replacement_value *av;
3576 vec<ipa_agg_jf_item> res = vNULL;
3578 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
3579 if (av->index == index
3580 && (av->offset - offset) >= 0)
3582 struct ipa_agg_jf_item item;
3583 gcc_checking_assert (av->value);
3584 item.offset = av->offset - offset;
3585 item.value = av->value;
3586 res.safe_push (item);
3589 return res;
3592 /* Intersect all values in INTER with those that we have already scheduled to
3593 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3594 (while subtracting OFFSET). */
3596 static void
3597 intersect_with_agg_replacements (struct cgraph_node *node, int index,
3598 vec<ipa_agg_jf_item> *inter,
3599 HOST_WIDE_INT offset)
3601 struct ipa_agg_replacement_value *srcvals;
3602 struct ipa_agg_jf_item *item;
3603 int i;
3605 srcvals = ipa_get_agg_replacements_for_node (node);
3606 if (!srcvals)
3608 inter->release ();
3609 return;
3612 FOR_EACH_VEC_ELT (*inter, i, item)
3614 struct ipa_agg_replacement_value *av;
3615 bool found = false;
3616 if (!item->value)
3617 continue;
3618 for (av = srcvals; av; av = av->next)
3620 gcc_checking_assert (av->value);
3621 if (av->index == index
3622 && av->offset - offset == item->offset)
3624 if (values_equal_for_ipcp_p (item->value, av->value))
3625 found = true;
3626 break;
3629 if (!found)
3630 item->value = NULL_TREE;
3634 /* Intersect values in INTER with aggregate values that come along edge CS to
3635 parameter number INDEX and return it. If INTER does not actually exist yet,
3636 copy all incoming values to it. If we determine we ended up with no values
3637 whatsoever, return a released vector. */
3639 static vec<ipa_agg_jf_item>
3640 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
3641 vec<ipa_agg_jf_item> inter)
3643 struct ipa_jump_func *jfunc;
3644 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3645 if (jfunc->type == IPA_JF_PASS_THROUGH
3646 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3648 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3649 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3651 if (caller_info->ipcp_orig_node)
3653 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3654 struct ipcp_param_lattices *orig_plats;
3655 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3656 src_idx);
3657 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3659 if (!inter.exists ())
3660 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
3661 else
3662 intersect_with_agg_replacements (cs->caller, src_idx,
3663 &inter, 0);
3665 else
3667 inter.release ();
3668 return vNULL;
3671 else
3673 struct ipcp_param_lattices *src_plats;
3674 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3675 if (agg_pass_through_permissible_p (src_plats, jfunc))
3677 /* Currently we do not produce clobber aggregate jump
3678 functions, adjust when we do. */
3679 gcc_checking_assert (!jfunc->agg.items);
3680 if (!inter.exists ())
3681 inter = copy_plats_to_inter (src_plats, 0);
3682 else
3683 intersect_with_plats (src_plats, &inter, 0);
3685 else
3687 inter.release ();
3688 return vNULL;
3692 else if (jfunc->type == IPA_JF_ANCESTOR
3693 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3695 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3696 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3697 struct ipcp_param_lattices *src_plats;
3698 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3700 if (caller_info->ipcp_orig_node)
3702 if (!inter.exists ())
3703 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
3704 else
3705 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
3706 delta);
3708 else
3710 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3711 /* Currently we do not produce clobber aggregate jump
3712 functions, adjust when we do. */
3713 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3714 if (!inter.exists ())
3715 inter = copy_plats_to_inter (src_plats, delta);
3716 else
3717 intersect_with_plats (src_plats, &inter, delta);
3720 else if (jfunc->agg.items)
3722 struct ipa_agg_jf_item *item;
3723 int k;
3725 if (!inter.exists ())
3726 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3727 inter.safe_push ((*jfunc->agg.items)[i]);
3728 else
3729 FOR_EACH_VEC_ELT (inter, k, item)
3731 int l = 0;
3732 bool found = false;;
3734 if (!item->value)
3735 continue;
3737 while ((unsigned) l < jfunc->agg.items->length ())
3739 struct ipa_agg_jf_item *ti;
3740 ti = &(*jfunc->agg.items)[l];
3741 if (ti->offset > item->offset)
3742 break;
3743 if (ti->offset == item->offset)
3745 gcc_checking_assert (ti->value);
3746 if (values_equal_for_ipcp_p (item->value,
3747 ti->value))
3748 found = true;
3749 break;
3751 l++;
3753 if (!found)
3754 item->value = NULL;
3757 else
3759 inter.release ();
3760 return vec<ipa_agg_jf_item>();
3762 return inter;
3765 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3766 from all of them. */
3768 static struct ipa_agg_replacement_value *
3769 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3770 vec<cgraph_edge *> callers)
3772 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3773 struct ipa_agg_replacement_value *res;
3774 struct ipa_agg_replacement_value **tail = &res;
3775 struct cgraph_edge *cs;
3776 int i, j, count = ipa_get_param_count (dest_info);
3778 FOR_EACH_VEC_ELT (callers, j, cs)
3780 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3781 if (c < count)
3782 count = c;
3785 for (i = 0; i < count ; i++)
3787 struct cgraph_edge *cs;
3788 vec<ipa_agg_jf_item> inter = vNULL;
3789 struct ipa_agg_jf_item *item;
3790 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3791 int j;
3793 /* Among other things, the following check should deal with all by_ref
3794 mismatches. */
3795 if (plats->aggs_bottom)
3796 continue;
3798 FOR_EACH_VEC_ELT (callers, j, cs)
3800 inter = intersect_aggregates_with_edge (cs, i, inter);
3802 if (!inter.exists ())
3803 goto next_param;
3806 FOR_EACH_VEC_ELT (inter, j, item)
3808 struct ipa_agg_replacement_value *v;
3810 if (!item->value)
3811 continue;
3813 v = ggc_alloc<ipa_agg_replacement_value> ();
3814 v->index = i;
3815 v->offset = item->offset;
3816 v->value = item->value;
3817 v->by_ref = plats->aggs_by_ref;
3818 *tail = v;
3819 tail = &v->next;
3822 next_param:
3823 if (inter.exists ())
3824 inter.release ();
3826 *tail = NULL;
3827 return res;
3830 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3832 static struct ipa_agg_replacement_value *
3833 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
3835 struct ipa_agg_replacement_value *res;
3836 struct ipa_agg_replacement_value **tail = &res;
3837 struct ipa_agg_jump_function *aggjf;
3838 struct ipa_agg_jf_item *item;
3839 int i, j;
3841 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3842 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3844 struct ipa_agg_replacement_value *v;
3845 v = ggc_alloc<ipa_agg_replacement_value> ();
3846 v->index = i;
3847 v->offset = item->offset;
3848 v->value = item->value;
3849 v->by_ref = aggjf->by_ref;
3850 *tail = v;
3851 tail = &v->next;
3853 *tail = NULL;
3854 return res;
3857 /* Determine whether CS also brings all scalar values that the NODE is
3858 specialized for. */
3860 static bool
3861 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3862 struct cgraph_node *node)
3864 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3865 int count = ipa_get_param_count (dest_info);
3866 struct ipa_node_params *caller_info;
3867 struct ipa_edge_args *args;
3868 int i;
3870 caller_info = IPA_NODE_REF (cs->caller);
3871 args = IPA_EDGE_REF (cs);
3872 for (i = 0; i < count; i++)
3874 struct ipa_jump_func *jump_func;
3875 tree val, t;
3877 val = dest_info->known_csts[i];
3878 if (!val)
3879 continue;
3881 if (i >= ipa_get_cs_argument_count (args))
3882 return false;
3883 jump_func = ipa_get_ith_jump_func (args, i);
3884 t = ipa_value_from_jfunc (caller_info, jump_func);
3885 if (!t || !values_equal_for_ipcp_p (val, t))
3886 return false;
3888 return true;
3891 /* Determine whether CS also brings all aggregate values that NODE is
3892 specialized for. */
3893 static bool
3894 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3895 struct cgraph_node *node)
3897 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3898 struct ipa_node_params *orig_node_info;
3899 struct ipa_agg_replacement_value *aggval;
3900 int i, ec, count;
3902 aggval = ipa_get_agg_replacements_for_node (node);
3903 if (!aggval)
3904 return true;
3906 count = ipa_get_param_count (IPA_NODE_REF (node));
3907 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3908 if (ec < count)
3909 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3910 if (aggval->index >= ec)
3911 return false;
3913 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3914 if (orig_caller_info->ipcp_orig_node)
3915 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3917 for (i = 0; i < count; i++)
3919 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
3920 struct ipcp_param_lattices *plats;
3921 bool interesting = false;
3922 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3923 if (aggval->index == i)
3925 interesting = true;
3926 break;
3928 if (!interesting)
3929 continue;
3931 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3932 if (plats->aggs_bottom)
3933 return false;
3935 values = intersect_aggregates_with_edge (cs, i, values);
3936 if (!values.exists ())
3937 return false;
3939 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3940 if (aggval->index == i)
3942 struct ipa_agg_jf_item *item;
3943 int j;
3944 bool found = false;
3945 FOR_EACH_VEC_ELT (values, j, item)
3946 if (item->value
3947 && item->offset == av->offset
3948 && values_equal_for_ipcp_p (item->value, av->value))
3950 found = true;
3951 break;
3953 if (!found)
3955 values.release ();
3956 return false;
3960 return true;
3963 /* Given an original NODE and a VAL for which we have already created a
3964 specialized clone, look whether there are incoming edges that still lead
3965 into the old node but now also bring the requested value and also conform to
3966 all other criteria such that they can be redirected the the special node.
3967 This function can therefore redirect the final edge in a SCC. */
3969 template <typename valtype>
3970 static void
3971 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
3973 ipcp_value_source<valtype> *src;
3974 gcov_type redirected_sum = 0;
3976 for (src = val->sources; src; src = src->next)
3978 struct cgraph_edge *cs = src->cs;
3979 while (cs)
3981 if (cgraph_edge_brings_value_p (cs, src, node)
3982 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3983 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
3985 if (dump_file)
3986 fprintf (dump_file, " - adding an extra caller %s/%i"
3987 " of %s/%i\n",
3988 xstrdup_for_dump (cs->caller->name ()),
3989 cs->caller->order,
3990 xstrdup_for_dump (val->spec_node->name ()),
3991 val->spec_node->order);
3993 cs->redirect_callee_duplicating_thunks (val->spec_node);
3994 val->spec_node->expand_all_artificial_thunks ();
3995 redirected_sum += cs->count;
3997 cs = get_next_cgraph_edge_clone (cs);
4001 if (redirected_sum)
4002 update_specialized_profile (val->spec_node, node, redirected_sum);
4005 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4007 static bool
4008 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4010 ipa_polymorphic_call_context *ctx;
4011 int i;
4013 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4014 if (!ctx->useless_p ())
4015 return true;
4016 return false;
4019 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4021 static vec<ipa_polymorphic_call_context>
4022 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4024 if (known_contexts_useful_p (known_contexts))
4025 return known_contexts.copy ();
4026 else
4027 return vNULL;
4030 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4031 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4033 static void
4034 modify_known_vectors_with_val (vec<tree> *known_csts,
4035 vec<ipa_polymorphic_call_context> *known_contexts,
4036 ipcp_value<tree> *val,
4037 int index)
4039 *known_csts = known_csts->copy ();
4040 *known_contexts = copy_useful_known_contexts (*known_contexts);
4041 (*known_csts)[index] = val->value;
4044 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4045 copy according to VAL and INDEX. */
4047 static void
4048 modify_known_vectors_with_val (vec<tree> *known_csts,
4049 vec<ipa_polymorphic_call_context> *known_contexts,
4050 ipcp_value<ipa_polymorphic_call_context> *val,
4051 int index)
4053 *known_csts = known_csts->copy ();
4054 *known_contexts = known_contexts->copy ();
4055 (*known_contexts)[index] = val->value;
4058 /* Return true if OFFSET indicates this was not an aggregate value or there is
4059 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4060 AGGVALS list. */
4062 DEBUG_FUNCTION bool
4063 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4064 int index, HOST_WIDE_INT offset, tree value)
4066 if (offset == -1)
4067 return true;
4069 while (aggvals)
4071 if (aggvals->index == index
4072 && aggvals->offset == offset
4073 && values_equal_for_ipcp_p (aggvals->value, value))
4074 return true;
4075 aggvals = aggvals->next;
4077 return false;
4080 /* Return true if offset is minus one because source of a polymorphic contect
4081 cannot be an aggregate value. */
4083 DEBUG_FUNCTION bool
4084 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4085 int , HOST_WIDE_INT offset,
4086 ipa_polymorphic_call_context)
4088 return offset == -1;
4091 /* Decide wheter to create a special version of NODE for value VAL of parameter
4092 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4093 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4094 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4096 template <typename valtype>
4097 static bool
4098 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4099 ipcp_value<valtype> *val, vec<tree> known_csts,
4100 vec<ipa_polymorphic_call_context> known_contexts)
4102 struct ipa_agg_replacement_value *aggvals;
4103 int freq_sum, caller_count;
4104 gcov_type count_sum;
4105 vec<cgraph_edge *> callers;
4107 if (val->spec_node)
4109 perhaps_add_new_callers (node, val);
4110 return false;
4112 else if (val->local_size_cost + overall_size > max_new_size)
4114 if (dump_file && (dump_flags & TDF_DETAILS))
4115 fprintf (dump_file, " Ignoring candidate value because "
4116 "max_new_size would be reached with %li.\n",
4117 val->local_size_cost + overall_size);
4118 return false;
4120 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4121 &caller_count))
4122 return false;
4124 if (dump_file && (dump_flags & TDF_DETAILS))
4126 fprintf (dump_file, " - considering value ");
4127 print_ipcp_constant_value (dump_file, val->value);
4128 fprintf (dump_file, " for ");
4129 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4130 if (offset != -1)
4131 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4132 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4135 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4136 freq_sum, count_sum,
4137 val->local_size_cost)
4138 && !good_cloning_opportunity_p (node,
4139 val->local_time_benefit
4140 + val->prop_time_benefit,
4141 freq_sum, count_sum,
4142 val->local_size_cost
4143 + val->prop_size_cost))
4144 return false;
4146 if (dump_file)
4147 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
4148 node->name (), node->order);
4150 callers = gather_edges_for_value (val, node, caller_count);
4151 if (offset == -1)
4152 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4153 else
4155 known_csts = known_csts.copy ();
4156 known_contexts = copy_useful_known_contexts (known_contexts);
4158 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4159 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4160 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4161 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4162 offset, val->value));
4163 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4164 aggvals, callers);
4165 overall_size += val->local_size_cost;
4167 /* TODO: If for some lattice there is only one other known value
4168 left, make a special node for it too. */
4170 return true;
4173 /* Decide whether and what specialized clones of NODE should be created. */
4175 static bool
4176 decide_whether_version_node (struct cgraph_node *node)
4178 struct ipa_node_params *info = IPA_NODE_REF (node);
4179 int i, count = ipa_get_param_count (info);
4180 vec<tree> known_csts;
4181 vec<ipa_polymorphic_call_context> known_contexts;
4182 vec<ipa_agg_jump_function> known_aggs = vNULL;
4183 bool ret = false;
4185 if (count == 0)
4186 return false;
4188 if (dump_file && (dump_flags & TDF_DETAILS))
4189 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4190 node->name (), node->order);
4192 gather_context_independent_values (info, &known_csts, &known_contexts,
4193 info->do_clone_for_all_contexts ? &known_aggs
4194 : NULL, NULL);
4196 for (i = 0; i < count ;i++)
4198 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4199 ipcp_lattice<tree> *lat = &plats->itself;
4200 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4202 if (!lat->bottom
4203 && !known_csts[i])
4205 ipcp_value<tree> *val;
4206 for (val = lat->values; val; val = val->next)
4207 ret |= decide_about_value (node, i, -1, val, known_csts,
4208 known_contexts);
4211 if (!plats->aggs_bottom)
4213 struct ipcp_agg_lattice *aglat;
4214 ipcp_value<tree> *val;
4215 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4216 if (!aglat->bottom && aglat->values
4217 /* If the following is false, the one value is in
4218 known_aggs. */
4219 && (plats->aggs_contain_variable
4220 || !aglat->is_single_const ()))
4221 for (val = aglat->values; val; val = val->next)
4222 ret |= decide_about_value (node, i, aglat->offset, val,
4223 known_csts, known_contexts);
4226 if (!ctxlat->bottom
4227 && known_contexts[i].useless_p ())
4229 ipcp_value<ipa_polymorphic_call_context> *val;
4230 for (val = ctxlat->values; val; val = val->next)
4231 ret |= decide_about_value (node, i, -1, val, known_csts,
4232 known_contexts);
4235 info = IPA_NODE_REF (node);
4238 if (info->do_clone_for_all_contexts)
4240 struct cgraph_node *clone;
4241 vec<cgraph_edge *> callers;
4243 if (dump_file)
4244 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4245 "for all known contexts.\n", node->name (),
4246 node->order);
4248 callers = node->collect_callers ();
4250 if (!known_contexts_useful_p (known_contexts))
4252 known_contexts.release ();
4253 known_contexts = vNULL;
4255 clone = create_specialized_node (node, known_csts, known_contexts,
4256 known_aggs_to_agg_replacement_list (known_aggs),
4257 callers);
4258 info = IPA_NODE_REF (node);
4259 info->do_clone_for_all_contexts = false;
4260 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4261 for (i = 0; i < count ; i++)
4262 vec_free (known_aggs[i].items);
4263 known_aggs.release ();
4264 ret = true;
4266 else
4268 known_csts.release ();
4269 known_contexts.release ();
4272 return ret;
4275 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4277 static void
4278 spread_undeadness (struct cgraph_node *node)
4280 struct cgraph_edge *cs;
4282 for (cs = node->callees; cs; cs = cs->next_callee)
4283 if (ipa_edge_within_scc (cs))
4285 struct cgraph_node *callee;
4286 struct ipa_node_params *info;
4288 callee = cs->callee->function_symbol (NULL);
4289 info = IPA_NODE_REF (callee);
4291 if (info->node_dead)
4293 info->node_dead = 0;
4294 spread_undeadness (callee);
4299 /* Return true if NODE has a caller from outside of its SCC that is not
4300 dead. Worker callback for cgraph_for_node_and_aliases. */
4302 static bool
4303 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4304 void *data ATTRIBUTE_UNUSED)
4306 struct cgraph_edge *cs;
4308 for (cs = node->callers; cs; cs = cs->next_caller)
4309 if (cs->caller->thunk.thunk_p
4310 && cs->caller->call_for_symbol_thunks_and_aliases
4311 (has_undead_caller_from_outside_scc_p, NULL, true))
4312 return true;
4313 else if (!ipa_edge_within_scc (cs)
4314 && !IPA_NODE_REF (cs->caller)->node_dead)
4315 return true;
4316 return false;
4320 /* Identify nodes within the same SCC as NODE which are no longer needed
4321 because of new clones and will be removed as unreachable. */
4323 static void
4324 identify_dead_nodes (struct cgraph_node *node)
4326 struct cgraph_node *v;
4327 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4328 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
4329 && !v->call_for_symbol_thunks_and_aliases
4330 (has_undead_caller_from_outside_scc_p, NULL, true))
4331 IPA_NODE_REF (v)->node_dead = 1;
4333 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4334 if (!IPA_NODE_REF (v)->node_dead)
4335 spread_undeadness (v);
4337 if (dump_file && (dump_flags & TDF_DETAILS))
4339 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4340 if (IPA_NODE_REF (v)->node_dead)
4341 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4342 v->name (), v->order);
4346 /* The decision stage. Iterate over the topological order of call graph nodes
4347 TOPO and make specialized clones if deemed beneficial. */
4349 static void
4350 ipcp_decision_stage (struct ipa_topo_info *topo)
4352 int i;
4354 if (dump_file)
4355 fprintf (dump_file, "\nIPA decision stage:\n\n");
4357 for (i = topo->nnodes - 1; i >= 0; i--)
4359 struct cgraph_node *node = topo->order[i];
4360 bool change = false, iterate = true;
4362 while (iterate)
4364 struct cgraph_node *v;
4365 iterate = false;
4366 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4367 if (v->has_gimple_body_p ()
4368 && ipcp_versionable_function_p (v))
4369 iterate |= decide_whether_version_node (v);
4371 change |= iterate;
4373 if (change)
4374 identify_dead_nodes (node);
4378 /* Look up all alignment information that we have discovered and copy it over
4379 to the transformation summary. */
4381 static void
4382 ipcp_store_alignment_results (void)
4384 cgraph_node *node;
4386 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4388 ipa_node_params *info = IPA_NODE_REF (node);
4389 bool dumped_sth = false;
4390 bool found_useful_result = false;
4392 if (!opt_for_fn (node->decl, flag_ipa_cp_alignment))
4394 if (dump_file)
4395 fprintf (dump_file, "Not considering %s for alignment discovery "
4396 "and propagate; -fipa-cp-alignment: disabled.\n",
4397 node->name ());
4398 continue;
4401 if (info->ipcp_orig_node)
4402 info = IPA_NODE_REF (info->ipcp_orig_node);
4404 unsigned count = ipa_get_param_count (info);
4405 for (unsigned i = 0; i < count ; i++)
4407 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4408 if (plats->alignment.known
4409 && plats->alignment.align > 0)
4411 found_useful_result = true;
4412 break;
4415 if (!found_useful_result)
4416 continue;
4418 ipcp_grow_transformations_if_necessary ();
4419 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4420 vec_safe_reserve_exact (ts->alignments, count);
4422 for (unsigned i = 0; i < count ; i++)
4424 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4426 if (plats->alignment.align == 0)
4427 plats->alignment.known = false;
4429 ts->alignments->quick_push (plats->alignment);
4430 if (!dump_file || !plats->alignment.known)
4431 continue;
4432 if (!dumped_sth)
4434 fprintf (dump_file, "Propagated alignment info for function %s/%i:\n",
4435 node->name (), node->order);
4436 dumped_sth = true;
4438 fprintf (dump_file, " param %i: align: %u, misalign: %u\n",
4439 i, plats->alignment.align, plats->alignment.misalign);
4444 /* The IPCP driver. */
4446 static unsigned int
4447 ipcp_driver (void)
4449 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4450 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4451 struct ipa_topo_info topo;
4453 ipa_check_create_node_params ();
4454 ipa_check_create_edge_args ();
4455 grow_edge_clone_vectors ();
4456 edge_duplication_hook_holder =
4457 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4458 edge_removal_hook_holder =
4459 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4461 if (dump_file)
4463 fprintf (dump_file, "\nIPA structures before propagation:\n");
4464 if (dump_flags & TDF_DETAILS)
4465 ipa_print_all_params (dump_file);
4466 ipa_print_all_jump_functions (dump_file);
4469 /* Topological sort. */
4470 build_toporder_info (&topo);
4471 /* Do the interprocedural propagation. */
4472 ipcp_propagate_stage (&topo);
4473 /* Decide what constant propagation and cloning should be performed. */
4474 ipcp_decision_stage (&topo);
4475 /* Store results of alignment propagation. */
4476 ipcp_store_alignment_results ();
4478 /* Free all IPCP structures. */
4479 free_toporder_info (&topo);
4480 next_edge_clone.release ();
4481 prev_edge_clone.release ();
4482 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4483 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
4484 ipa_free_all_structures_after_ipa_cp ();
4485 if (dump_file)
4486 fprintf (dump_file, "\nIPA constant propagation end\n");
4487 return 0;
4490 /* Initialization and computation of IPCP data structures. This is the initial
4491 intraprocedural analysis of functions, which gathers information to be
4492 propagated later on. */
4494 static void
4495 ipcp_generate_summary (void)
4497 struct cgraph_node *node;
4499 if (dump_file)
4500 fprintf (dump_file, "\nIPA constant propagation start:\n");
4501 ipa_register_cgraph_hooks ();
4503 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4505 node->local.versionable
4506 = tree_versionable_function_p (node->decl);
4507 ipa_analyze_node (node);
4511 /* Write ipcp summary for nodes in SET. */
4513 static void
4514 ipcp_write_summary (void)
4516 ipa_prop_write_jump_functions ();
4519 /* Read ipcp summary. */
4521 static void
4522 ipcp_read_summary (void)
4524 ipa_prop_read_jump_functions ();
4527 namespace {
4529 const pass_data pass_data_ipa_cp =
4531 IPA_PASS, /* type */
4532 "cp", /* name */
4533 OPTGROUP_NONE, /* optinfo_flags */
4534 TV_IPA_CONSTANT_PROP, /* tv_id */
4535 0, /* properties_required */
4536 0, /* properties_provided */
4537 0, /* properties_destroyed */
4538 0, /* todo_flags_start */
4539 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
4542 class pass_ipa_cp : public ipa_opt_pass_d
4544 public:
4545 pass_ipa_cp (gcc::context *ctxt)
4546 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
4547 ipcp_generate_summary, /* generate_summary */
4548 ipcp_write_summary, /* write_summary */
4549 ipcp_read_summary, /* read_summary */
4550 ipcp_write_transformation_summaries, /*
4551 write_optimization_summary */
4552 ipcp_read_transformation_summaries, /*
4553 read_optimization_summary */
4554 NULL, /* stmt_fixup */
4555 0, /* function_transform_todo_flags_start */
4556 ipcp_transform_function, /* function_transform */
4557 NULL) /* variable_transform */
4560 /* opt_pass methods: */
4561 virtual bool gate (function *)
4563 /* FIXME: We should remove the optimize check after we ensure we never run
4564 IPA passes when not optimizing. */
4565 return (flag_ipa_cp && optimize) || in_lto_p;
4568 virtual unsigned int execute (function *) { return ipcp_driver (); }
4570 }; // class pass_ipa_cp
4572 } // anon namespace
4574 ipa_opt_pass_d *
4575 make_pass_ipa_cp (gcc::context *ctxt)
4577 return new pass_ipa_cp (ctxt);
4580 /* Reset all state within ipa-cp.c so that we can rerun the compiler
4581 within the same process. For use by toplev::finalize. */
4583 void
4584 ipa_cp_c_finalize (void)
4586 max_count = 0;
4587 overall_size = 0;
4588 max_new_size = 0;