tree-core.h: Include symtab.h.
[official-gcc.git] / gcc / ipa-cp.c
blob16b9cde43b9670d1c293f321eb73be82ab402405
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "alias.h"
107 #include "tree.h"
108 #include "options.h"
109 #include "fold-const.h"
110 #include "gimple-fold.h"
111 #include "gimple-expr.h"
112 #include "target.h"
113 #include "backend.h"
114 #include "hard-reg-set.h"
115 #include "cgraph.h"
116 #include "alloc-pool.h"
117 #include "symbol-summary.h"
118 #include "ipa-prop.h"
119 #include "tree-pass.h"
120 #include "flags.h"
121 #include "diagnostic.h"
122 #include "tree-pretty-print.h"
123 #include "tree-inline.h"
124 #include "params.h"
125 #include "ipa-inline.h"
126 #include "ipa-utils.h"
128 template <typename valtype> class ipcp_value;
130 /* Describes a particular source for an IPA-CP value. */
132 template <typename valtype>
133 class ipcp_value_source
135 public:
136 /* Aggregate offset of the source, negative if the source is scalar value of
137 the argument itself. */
138 HOST_WIDE_INT offset;
139 /* The incoming edge that brought the value. */
140 cgraph_edge *cs;
141 /* If the jump function that resulted into his value was a pass-through or an
142 ancestor, this is the ipcp_value of the caller from which the described
143 value has been derived. Otherwise it is NULL. */
144 ipcp_value<valtype> *val;
145 /* Next pointer in a linked list of sources of a value. */
146 ipcp_value_source *next;
147 /* If the jump function that resulted into his value was a pass-through or an
148 ancestor, this is the index of the parameter of the caller the jump
149 function references. */
150 int index;
153 /* Common ancestor for all ipcp_value instantiations. */
155 class ipcp_value_base
157 public:
158 /* Time benefit and size cost that specializing the function for this value
159 would bring about in this function alone. */
160 int local_time_benefit, local_size_cost;
161 /* Time benefit and size cost that specializing the function for this value
162 can bring about in it's callees (transitively). */
163 int prop_time_benefit, prop_size_cost;
166 /* Describes one particular value stored in struct ipcp_lattice. */
168 template <typename valtype>
169 class ipcp_value : public ipcp_value_base
171 public:
172 /* The actual value for the given parameter. */
173 valtype value;
174 /* The list of sources from which this value originates. */
175 ipcp_value_source <valtype> *sources;
176 /* Next pointers in a linked list of all values in a lattice. */
177 ipcp_value *next;
178 /* Next pointers in a linked list of values in a strongly connected component
179 of values. */
180 ipcp_value *scc_next;
181 /* Next pointers in a linked list of SCCs of values sorted topologically
182 according their sources. */
183 ipcp_value *topo_next;
184 /* A specialized node created for this value, NULL if none has been (so far)
185 created. */
186 cgraph_node *spec_node;
187 /* Depth first search number and low link for topological sorting of
188 values. */
189 int dfs, low_link;
190 /* True if this valye is currently on the topo-sort stack. */
191 bool on_stack;
193 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
194 HOST_WIDE_INT offset);
197 /* Lattice describing potential values of a formal parameter of a function, or
198 a part of an aggreagate. TOP is represented by a lattice with zero values
199 and with contains_variable and bottom flags cleared. BOTTOM is represented
200 by a lattice with the bottom flag set. In that case, values and
201 contains_variable flag should be disregarded. */
203 template <typename valtype>
204 class ipcp_lattice
206 public:
207 /* The list of known values and types in this lattice. Note that values are
208 not deallocated if a lattice is set to bottom because there may be value
209 sources referencing them. */
210 ipcp_value<valtype> *values;
211 /* Number of known values and types in this lattice. */
212 int values_count;
213 /* The lattice contains a variable component (in addition to values). */
214 bool contains_variable;
215 /* The value of the lattice is bottom (i.e. variable and unusable for any
216 propagation). */
217 bool bottom;
219 inline bool is_single_const ();
220 inline bool set_to_bottom ();
221 inline bool set_contains_variable ();
222 bool add_value (valtype newval, cgraph_edge *cs,
223 ipcp_value<valtype> *src_val = NULL,
224 int src_idx = 0, HOST_WIDE_INT offset = -1);
225 void print (FILE * f, bool dump_sources, bool dump_benefits);
228 /* Lattice of tree values with an offset to describe a part of an
229 aggregate. */
231 class ipcp_agg_lattice : public ipcp_lattice<tree>
233 public:
234 /* Offset that is being described by this lattice. */
235 HOST_WIDE_INT offset;
236 /* Size so that we don't have to re-compute it every time we traverse the
237 list. Must correspond to TYPE_SIZE of all lat values. */
238 HOST_WIDE_INT size;
239 /* Next element of the linked list. */
240 struct ipcp_agg_lattice *next;
243 /* Structure containing lattices for a parameter itself and for pieces of
244 aggregates that are passed in the parameter or by a reference in a parameter
245 plus some other useful flags. */
247 class ipcp_param_lattices
249 public:
250 /* Lattice describing the value of the parameter itself. */
251 ipcp_lattice<tree> itself;
252 /* Lattice describing the the polymorphic contexts of a parameter. */
253 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
254 /* Lattices describing aggregate parts. */
255 ipcp_agg_lattice *aggs;
256 /* Alignment information. Very basic one value lattice where !known means
257 TOP and zero alignment bottom. */
258 ipa_alignment alignment;
259 /* Number of aggregate lattices */
260 int aggs_count;
261 /* True if aggregate data were passed by reference (as opposed to by
262 value). */
263 bool aggs_by_ref;
264 /* All aggregate lattices contain a variable component (in addition to
265 values). */
266 bool aggs_contain_variable;
267 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
268 for any propagation). */
269 bool aggs_bottom;
271 /* There is a virtual call based on this parameter. */
272 bool virt_call;
275 /* Allocation pools for values and their sources in ipa-cp. */
277 pool_allocator<ipcp_value<tree> > ipcp_cst_values_pool
278 ("IPA-CP constant values", 32);
280 pool_allocator<ipcp_value<ipa_polymorphic_call_context> >
281 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts", 32);
283 pool_allocator<ipcp_value_source<tree> > ipcp_sources_pool
284 ("IPA-CP value sources", 64);
286 pool_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
287 ("IPA_CP aggregate lattices", 32);
289 /* Maximal count found in program. */
291 static gcov_type max_count;
293 /* Original overall size of the program. */
295 static long overall_size, max_new_size;
297 /* Return the param lattices structure corresponding to the Ith formal
298 parameter of the function described by INFO. */
299 static inline struct ipcp_param_lattices *
300 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
302 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
303 gcc_checking_assert (!info->ipcp_orig_node);
304 gcc_checking_assert (info->lattices);
305 return &(info->lattices[i]);
308 /* Return the lattice corresponding to the scalar value of the Ith formal
309 parameter of the function described by INFO. */
310 static inline ipcp_lattice<tree> *
311 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
313 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
314 return &plats->itself;
317 /* Return the lattice corresponding to the scalar value of the Ith formal
318 parameter of the function described by INFO. */
319 static inline ipcp_lattice<ipa_polymorphic_call_context> *
320 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
322 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
323 return &plats->ctxlat;
326 /* Return whether LAT is a lattice with a single constant and without an
327 undefined value. */
329 template <typename valtype>
330 inline bool
331 ipcp_lattice<valtype>::is_single_const ()
333 if (bottom || contains_variable || values_count != 1)
334 return false;
335 else
336 return true;
339 /* Print V which is extracted from a value in a lattice to F. */
341 static void
342 print_ipcp_constant_value (FILE * f, tree v)
344 if (TREE_CODE (v) == ADDR_EXPR
345 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
347 fprintf (f, "& ");
348 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
350 else
351 print_generic_expr (f, v, 0);
354 /* Print V which is extracted from a value in a lattice to F. */
356 static void
357 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
359 v.dump(f, false);
362 /* Print a lattice LAT to F. */
364 template <typename valtype>
365 void
366 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
368 ipcp_value<valtype> *val;
369 bool prev = false;
371 if (bottom)
373 fprintf (f, "BOTTOM\n");
374 return;
377 if (!values_count && !contains_variable)
379 fprintf (f, "TOP\n");
380 return;
383 if (contains_variable)
385 fprintf (f, "VARIABLE");
386 prev = true;
387 if (dump_benefits)
388 fprintf (f, "\n");
391 for (val = values; val; val = val->next)
393 if (dump_benefits && prev)
394 fprintf (f, " ");
395 else if (!dump_benefits && prev)
396 fprintf (f, ", ");
397 else
398 prev = true;
400 print_ipcp_constant_value (f, val->value);
402 if (dump_sources)
404 ipcp_value_source<valtype> *s;
406 fprintf (f, " [from:");
407 for (s = val->sources; s; s = s->next)
408 fprintf (f, " %i(%i)", s->cs->caller->order,
409 s->cs->frequency);
410 fprintf (f, "]");
413 if (dump_benefits)
414 fprintf (f, " [loc_time: %i, loc_size: %i, "
415 "prop_time: %i, prop_size: %i]\n",
416 val->local_time_benefit, val->local_size_cost,
417 val->prop_time_benefit, val->prop_size_cost);
419 if (!dump_benefits)
420 fprintf (f, "\n");
423 /* Print all ipcp_lattices of all functions to F. */
425 static void
426 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
428 struct cgraph_node *node;
429 int i, count;
431 fprintf (f, "\nLattices:\n");
432 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
434 struct ipa_node_params *info;
436 info = IPA_NODE_REF (node);
437 fprintf (f, " Node: %s/%i:\n", node->name (),
438 node->order);
439 count = ipa_get_param_count (info);
440 for (i = 0; i < count; i++)
442 struct ipcp_agg_lattice *aglat;
443 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
444 fprintf (f, " param [%d]: ", i);
445 plats->itself.print (f, dump_sources, dump_benefits);
446 fprintf (f, " ctxs: ");
447 plats->ctxlat.print (f, dump_sources, dump_benefits);
448 if (plats->alignment.known && plats->alignment.align > 0)
449 fprintf (f, " Alignment %u, misalignment %u\n",
450 plats->alignment.align, plats->alignment.misalign);
451 else if (plats->alignment.known)
452 fprintf (f, " Alignment unusable\n");
453 else
454 fprintf (f, " Alignment unknown\n");
455 if (plats->virt_call)
456 fprintf (f, " virt_call flag set\n");
458 if (plats->aggs_bottom)
460 fprintf (f, " AGGS BOTTOM\n");
461 continue;
463 if (plats->aggs_contain_variable)
464 fprintf (f, " AGGS VARIABLE\n");
465 for (aglat = plats->aggs; aglat; aglat = aglat->next)
467 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
468 plats->aggs_by_ref ? "ref " : "", aglat->offset);
469 aglat->print (f, dump_sources, dump_benefits);
475 /* Determine whether it is at all technically possible to create clones of NODE
476 and store this information in the ipa_node_params structure associated
477 with NODE. */
479 static void
480 determine_versionability (struct cgraph_node *node)
482 const char *reason = NULL;
484 /* There are a number of generic reasons functions cannot be versioned. We
485 also cannot remove parameters if there are type attributes such as fnspec
486 present. */
487 if (node->alias || node->thunk.thunk_p)
488 reason = "alias or thunk";
489 else if (!node->local.versionable)
490 reason = "not a tree_versionable_function";
491 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
492 reason = "insufficient body availability";
493 else if (!opt_for_fn (node->decl, optimize)
494 || !opt_for_fn (node->decl, flag_ipa_cp))
495 reason = "non-optimized function";
496 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
498 /* Ideally we should clone the SIMD clones themselves and create
499 vector copies of them, so IPA-cp and SIMD clones can happily
500 coexist, but that may not be worth the effort. */
501 reason = "function has SIMD clones";
503 /* Don't clone decls local to a comdat group; it breaks and for C++
504 decloned constructors, inlining is always better anyway. */
505 else if (node->comdat_local_p ())
506 reason = "comdat-local function";
508 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
509 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
510 node->name (), node->order, reason);
512 node->local.versionable = (reason == NULL);
515 /* Return true if it is at all technically possible to create clones of a
516 NODE. */
518 static bool
519 ipcp_versionable_function_p (struct cgraph_node *node)
521 return node->local.versionable;
524 /* Structure holding accumulated information about callers of a node. */
526 struct caller_statistics
528 gcov_type count_sum;
529 int n_calls, n_hot_calls, freq_sum;
532 /* Initialize fields of STAT to zeroes. */
534 static inline void
535 init_caller_stats (struct caller_statistics *stats)
537 stats->count_sum = 0;
538 stats->n_calls = 0;
539 stats->n_hot_calls = 0;
540 stats->freq_sum = 0;
543 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
544 non-thunk incoming edges to NODE. */
546 static bool
547 gather_caller_stats (struct cgraph_node *node, void *data)
549 struct caller_statistics *stats = (struct caller_statistics *) data;
550 struct cgraph_edge *cs;
552 for (cs = node->callers; cs; cs = cs->next_caller)
553 if (!cs->caller->thunk.thunk_p)
555 stats->count_sum += cs->count;
556 stats->freq_sum += cs->frequency;
557 stats->n_calls++;
558 if (cs->maybe_hot_p ())
559 stats->n_hot_calls ++;
561 return false;
565 /* Return true if this NODE is viable candidate for cloning. */
567 static bool
568 ipcp_cloning_candidate_p (struct cgraph_node *node)
570 struct caller_statistics stats;
572 gcc_checking_assert (node->has_gimple_body_p ());
574 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
576 if (dump_file)
577 fprintf (dump_file, "Not considering %s for cloning; "
578 "-fipa-cp-clone disabled.\n",
579 node->name ());
580 return false;
583 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
585 if (dump_file)
586 fprintf (dump_file, "Not considering %s for cloning; "
587 "optimizing it for size.\n",
588 node->name ());
589 return false;
592 init_caller_stats (&stats);
593 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
595 if (inline_summaries->get (node)->self_size < stats.n_calls)
597 if (dump_file)
598 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
599 node->name ());
600 return true;
603 /* When profile is available and function is hot, propagate into it even if
604 calls seems cold; constant propagation can improve function's speed
605 significantly. */
606 if (max_count)
608 if (stats.count_sum > node->count * 90 / 100)
610 if (dump_file)
611 fprintf (dump_file, "Considering %s for cloning; "
612 "usually called directly.\n",
613 node->name ());
614 return true;
617 if (!stats.n_hot_calls)
619 if (dump_file)
620 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
621 node->name ());
622 return false;
624 if (dump_file)
625 fprintf (dump_file, "Considering %s for cloning.\n",
626 node->name ());
627 return true;
630 template <typename valtype>
631 class value_topo_info
633 public:
634 /* Head of the linked list of topologically sorted values. */
635 ipcp_value<valtype> *values_topo;
636 /* Stack for creating SCCs, represented by a linked list too. */
637 ipcp_value<valtype> *stack;
638 /* Counter driving the algorithm in add_val_to_toposort. */
639 int dfs_counter;
641 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
643 void add_val (ipcp_value<valtype> *cur_val);
644 void propagate_effects ();
647 /* Arrays representing a topological ordering of call graph nodes and a stack
648 of nodes used during constant propagation and also data required to perform
649 topological sort of values and propagation of benefits in the determined
650 order. */
652 class ipa_topo_info
654 public:
655 /* Array with obtained topological order of cgraph nodes. */
656 struct cgraph_node **order;
657 /* Stack of cgraph nodes used during propagation within SCC until all values
658 in the SCC stabilize. */
659 struct cgraph_node **stack;
660 int nnodes, stack_top;
662 value_topo_info<tree> constants;
663 value_topo_info<ipa_polymorphic_call_context> contexts;
665 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
666 constants ()
670 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
672 static void
673 build_toporder_info (struct ipa_topo_info *topo)
675 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
676 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
678 gcc_checking_assert (topo->stack_top == 0);
679 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
682 /* Free information about strongly connected components and the arrays in
683 TOPO. */
685 static void
686 free_toporder_info (struct ipa_topo_info *topo)
688 ipa_free_postorder_info ();
689 free (topo->order);
690 free (topo->stack);
693 /* Add NODE to the stack in TOPO, unless it is already there. */
695 static inline void
696 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
698 struct ipa_node_params *info = IPA_NODE_REF (node);
699 if (info->node_enqueued)
700 return;
701 info->node_enqueued = 1;
702 topo->stack[topo->stack_top++] = node;
705 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
706 is empty. */
708 static struct cgraph_node *
709 pop_node_from_stack (struct ipa_topo_info *topo)
711 if (topo->stack_top)
713 struct cgraph_node *node;
714 topo->stack_top--;
715 node = topo->stack[topo->stack_top];
716 IPA_NODE_REF (node)->node_enqueued = 0;
717 return node;
719 else
720 return NULL;
723 /* Set lattice LAT to bottom and return true if it previously was not set as
724 such. */
726 template <typename valtype>
727 inline bool
728 ipcp_lattice<valtype>::set_to_bottom ()
730 bool ret = !bottom;
731 bottom = true;
732 return ret;
735 /* Mark lattice as containing an unknown value and return true if it previously
736 was not marked as such. */
738 template <typename valtype>
739 inline bool
740 ipcp_lattice<valtype>::set_contains_variable ()
742 bool ret = !contains_variable;
743 contains_variable = true;
744 return ret;
747 /* Set all aggegate lattices in PLATS to bottom and return true if they were
748 not previously set as such. */
750 static inline bool
751 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
753 bool ret = !plats->aggs_bottom;
754 plats->aggs_bottom = true;
755 return ret;
758 /* Mark all aggegate lattices in PLATS as containing an unknown value and
759 return true if they were not previously marked as such. */
761 static inline bool
762 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
764 bool ret = !plats->aggs_contain_variable;
765 plats->aggs_contain_variable = true;
766 return ret;
769 /* Return true if alignment information in PLATS is known to be unusable. */
771 static inline bool
772 alignment_bottom_p (ipcp_param_lattices *plats)
774 return plats->alignment.known && (plats->alignment.align == 0);
777 /* Set alignment information in PLATS to unusable. Return true if it
778 previously was usable or unknown. */
780 static inline bool
781 set_alignment_to_bottom (ipcp_param_lattices *plats)
783 if (alignment_bottom_p (plats))
784 return false;
785 plats->alignment.known = true;
786 plats->alignment.align = 0;
787 return true;
790 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
791 return true is any of them has not been marked as such so far. */
793 static inline bool
794 set_all_contains_variable (struct ipcp_param_lattices *plats)
796 bool ret;
797 ret = plats->itself.set_contains_variable ();
798 ret |= plats->ctxlat.set_contains_variable ();
799 ret |= set_agg_lats_contain_variable (plats);
800 ret |= set_alignment_to_bottom (plats);
801 return ret;
804 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
805 points to by the number of callers to NODE. */
807 static bool
808 count_callers (cgraph_node *node, void *data)
810 int *caller_count = (int *) data;
812 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
813 /* Local thunks can be handled transparently, but if the thunk can not
814 be optimized out, count it as a real use. */
815 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
816 ++*caller_count;
817 return false;
820 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
821 the one caller of some other node. Set the caller's corresponding flag. */
823 static bool
824 set_single_call_flag (cgraph_node *node, void *)
826 cgraph_edge *cs = node->callers;
827 /* Local thunks can be handled transparently, skip them. */
828 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
829 cs = cs->next_caller;
830 if (cs)
832 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
833 return true;
835 return false;
838 /* Initialize ipcp_lattices. */
840 static void
841 initialize_node_lattices (struct cgraph_node *node)
843 struct ipa_node_params *info = IPA_NODE_REF (node);
844 struct cgraph_edge *ie;
845 bool disable = false, variable = false;
846 int i;
848 gcc_checking_assert (node->has_gimple_body_p ());
849 if (cgraph_local_p (node))
851 int caller_count = 0;
852 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
853 true);
854 gcc_checking_assert (caller_count > 0);
855 if (caller_count == 1)
856 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
857 NULL, true);
859 else
861 /* When cloning is allowed, we can assume that externally visible
862 functions are not called. We will compensate this by cloning
863 later. */
864 if (ipcp_versionable_function_p (node)
865 && ipcp_cloning_candidate_p (node))
866 variable = true;
867 else
868 disable = true;
871 if (disable || variable)
873 for (i = 0; i < ipa_get_param_count (info) ; i++)
875 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
876 if (disable)
878 plats->itself.set_to_bottom ();
879 plats->ctxlat.set_to_bottom ();
880 set_agg_lats_to_bottom (plats);
881 set_alignment_to_bottom (plats);
883 else
884 set_all_contains_variable (plats);
886 if (dump_file && (dump_flags & TDF_DETAILS)
887 && !node->alias && !node->thunk.thunk_p)
888 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
889 node->name (), node->order,
890 disable ? "BOTTOM" : "VARIABLE");
893 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
894 if (ie->indirect_info->polymorphic
895 && ie->indirect_info->param_index >= 0)
897 gcc_checking_assert (ie->indirect_info->param_index >= 0);
898 ipa_get_parm_lattices (info,
899 ie->indirect_info->param_index)->virt_call = 1;
903 /* Return the result of a (possibly arithmetic) pass through jump function
904 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
905 determined or be considered an interprocedural invariant. */
907 static tree
908 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
910 tree restype, res;
912 gcc_checking_assert (is_gimple_ip_invariant (input));
913 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
914 return input;
916 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
917 == tcc_comparison)
918 restype = boolean_type_node;
919 else
920 restype = TREE_TYPE (input);
921 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
922 input, ipa_get_jf_pass_through_operand (jfunc));
924 if (res && !is_gimple_ip_invariant (res))
925 return NULL_TREE;
927 return res;
930 /* Return the result of an ancestor jump function JFUNC on the constant value
931 INPUT. Return NULL_TREE if that cannot be determined. */
933 static tree
934 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
936 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
937 if (TREE_CODE (input) == ADDR_EXPR)
939 tree t = TREE_OPERAND (input, 0);
940 t = build_ref_for_offset (EXPR_LOCATION (t), t,
941 ipa_get_jf_ancestor_offset (jfunc),
942 ptr_type_node, NULL, false);
943 return build_fold_addr_expr (t);
945 else
946 return NULL_TREE;
949 /* Determine whether JFUNC evaluates to a single known constant value and if
950 so, return it. Otherwise return NULL. INFO describes the caller node or
951 the one it is inlined to, so that pass-through jump functions can be
952 evaluated. */
954 tree
955 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
957 if (jfunc->type == IPA_JF_CONST)
958 return ipa_get_jf_constant (jfunc);
959 else if (jfunc->type == IPA_JF_PASS_THROUGH
960 || jfunc->type == IPA_JF_ANCESTOR)
962 tree input;
963 int idx;
965 if (jfunc->type == IPA_JF_PASS_THROUGH)
966 idx = ipa_get_jf_pass_through_formal_id (jfunc);
967 else
968 idx = ipa_get_jf_ancestor_formal_id (jfunc);
970 if (info->ipcp_orig_node)
971 input = info->known_csts[idx];
972 else
974 ipcp_lattice<tree> *lat;
976 if (!info->lattices
977 || idx >= ipa_get_param_count (info))
978 return NULL_TREE;
979 lat = ipa_get_scalar_lat (info, idx);
980 if (!lat->is_single_const ())
981 return NULL_TREE;
982 input = lat->values->value;
985 if (!input)
986 return NULL_TREE;
988 if (jfunc->type == IPA_JF_PASS_THROUGH)
989 return ipa_get_jf_pass_through_result (jfunc, input);
990 else
991 return ipa_get_jf_ancestor_result (jfunc, input);
993 else
994 return NULL_TREE;
997 /* Determie whether JFUNC evaluates to single known polymorphic context, given
998 that INFO describes the caller node or the one it is inlined to, CS is the
999 call graph edge corresponding to JFUNC and CSIDX index of the described
1000 parameter. */
1002 ipa_polymorphic_call_context
1003 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1004 ipa_jump_func *jfunc)
1006 ipa_edge_args *args = IPA_EDGE_REF (cs);
1007 ipa_polymorphic_call_context ctx;
1008 ipa_polymorphic_call_context *edge_ctx
1009 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1011 if (edge_ctx && !edge_ctx->useless_p ())
1012 ctx = *edge_ctx;
1014 if (jfunc->type == IPA_JF_PASS_THROUGH
1015 || jfunc->type == IPA_JF_ANCESTOR)
1017 ipa_polymorphic_call_context srcctx;
1018 int srcidx;
1019 bool type_preserved = true;
1020 if (jfunc->type == IPA_JF_PASS_THROUGH)
1022 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1023 return ctx;
1024 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1025 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1027 else
1029 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1030 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1032 if (info->ipcp_orig_node)
1034 if (info->known_contexts.exists ())
1035 srcctx = info->known_contexts[srcidx];
1037 else
1039 if (!info->lattices
1040 || srcidx >= ipa_get_param_count (info))
1041 return ctx;
1042 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1043 lat = ipa_get_poly_ctx_lat (info, srcidx);
1044 if (!lat->is_single_const ())
1045 return ctx;
1046 srcctx = lat->values->value;
1048 if (srcctx.useless_p ())
1049 return ctx;
1050 if (jfunc->type == IPA_JF_ANCESTOR)
1051 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1052 if (!type_preserved)
1053 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1054 srcctx.combine_with (ctx);
1055 return srcctx;
1058 return ctx;
1061 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1062 bottom, not containing a variable component and without any known value at
1063 the same time. */
1065 DEBUG_FUNCTION void
1066 ipcp_verify_propagated_values (void)
1068 struct cgraph_node *node;
1070 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1072 struct ipa_node_params *info = IPA_NODE_REF (node);
1073 int i, count = ipa_get_param_count (info);
1075 for (i = 0; i < count; i++)
1077 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1079 if (!lat->bottom
1080 && !lat->contains_variable
1081 && lat->values_count == 0)
1083 if (dump_file)
1085 symtab_node::dump_table (dump_file);
1086 fprintf (dump_file, "\nIPA lattices after constant "
1087 "propagation, before gcc_unreachable:\n");
1088 print_all_lattices (dump_file, true, false);
1091 gcc_unreachable ();
1097 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1099 static bool
1100 values_equal_for_ipcp_p (tree x, tree y)
1102 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1104 if (x == y)
1105 return true;
1107 if (TREE_CODE (x) == ADDR_EXPR
1108 && TREE_CODE (y) == ADDR_EXPR
1109 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1110 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1111 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1112 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1113 else
1114 return operand_equal_p (x, y, 0);
1117 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1119 static bool
1120 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1121 ipa_polymorphic_call_context y)
1123 return x.equal_to (y);
1127 /* Add a new value source to the value represented by THIS, marking that a
1128 value comes from edge CS and (if the underlying jump function is a
1129 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1130 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1131 scalar value of the parameter itself or the offset within an aggregate. */
1133 template <typename valtype>
1134 void
1135 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1136 int src_idx, HOST_WIDE_INT offset)
1138 ipcp_value_source<valtype> *src;
1140 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1141 src->offset = offset;
1142 src->cs = cs;
1143 src->val = src_val;
1144 src->index = src_idx;
1146 src->next = sources;
1147 sources = src;
1150 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1151 SOURCE and clear all other fields. */
1153 static ipcp_value<tree> *
1154 allocate_and_init_ipcp_value (tree source)
1156 ipcp_value<tree> *val;
1158 val = ipcp_cst_values_pool.allocate ();
1159 memset (val, 0, sizeof (*val));
1160 val->value = source;
1161 return val;
1164 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1165 value to SOURCE and clear all other fields. */
1167 static ipcp_value<ipa_polymorphic_call_context> *
1168 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1170 ipcp_value<ipa_polymorphic_call_context> *val;
1172 // TODO
1173 val = ipcp_poly_ctx_values_pool.allocate ();
1174 memset (val, 0, sizeof (*val));
1175 val->value = source;
1176 return val;
1179 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1180 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1181 meaning. OFFSET -1 means the source is scalar and not a part of an
1182 aggregate. */
1184 template <typename valtype>
1185 bool
1186 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1187 ipcp_value<valtype> *src_val,
1188 int src_idx, HOST_WIDE_INT offset)
1190 ipcp_value<valtype> *val;
1192 if (bottom)
1193 return false;
1195 for (val = values; val; val = val->next)
1196 if (values_equal_for_ipcp_p (val->value, newval))
1198 if (ipa_edge_within_scc (cs))
1200 ipcp_value_source<valtype> *s;
1201 for (s = val->sources; s ; s = s->next)
1202 if (s->cs == cs)
1203 break;
1204 if (s)
1205 return false;
1208 val->add_source (cs, src_val, src_idx, offset);
1209 return false;
1212 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1214 /* We can only free sources, not the values themselves, because sources
1215 of other values in this this SCC might point to them. */
1216 for (val = values; val; val = val->next)
1218 while (val->sources)
1220 ipcp_value_source<valtype> *src = val->sources;
1221 val->sources = src->next;
1222 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1226 values = NULL;
1227 return set_to_bottom ();
1230 values_count++;
1231 val = allocate_and_init_ipcp_value (newval);
1232 val->add_source (cs, src_val, src_idx, offset);
1233 val->next = values;
1234 values = val;
1235 return true;
1238 /* Propagate values through a pass-through jump function JFUNC associated with
1239 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1240 is the index of the source parameter. */
1242 static bool
1243 propagate_vals_accross_pass_through (cgraph_edge *cs,
1244 ipa_jump_func *jfunc,
1245 ipcp_lattice<tree> *src_lat,
1246 ipcp_lattice<tree> *dest_lat,
1247 int src_idx)
1249 ipcp_value<tree> *src_val;
1250 bool ret = false;
1252 /* Do not create new values when propagating within an SCC because if there
1253 are arithmetic functions with circular dependencies, there is infinite
1254 number of them and we would just make lattices bottom. */
1255 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1256 && ipa_edge_within_scc (cs))
1257 ret = dest_lat->set_contains_variable ();
1258 else
1259 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1261 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1263 if (cstval)
1264 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1265 else
1266 ret |= dest_lat->set_contains_variable ();
1269 return ret;
1272 /* Propagate values through an ancestor jump function JFUNC associated with
1273 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1274 is the index of the source parameter. */
1276 static bool
1277 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1278 struct ipa_jump_func *jfunc,
1279 ipcp_lattice<tree> *src_lat,
1280 ipcp_lattice<tree> *dest_lat,
1281 int src_idx)
1283 ipcp_value<tree> *src_val;
1284 bool ret = false;
1286 if (ipa_edge_within_scc (cs))
1287 return dest_lat->set_contains_variable ();
1289 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1291 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1293 if (t)
1294 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1295 else
1296 ret |= dest_lat->set_contains_variable ();
1299 return ret;
1302 /* Propagate scalar values across jump function JFUNC that is associated with
1303 edge CS and put the values into DEST_LAT. */
1305 static bool
1306 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1307 struct ipa_jump_func *jfunc,
1308 ipcp_lattice<tree> *dest_lat)
1310 if (dest_lat->bottom)
1311 return false;
1313 if (jfunc->type == IPA_JF_CONST)
1315 tree val = ipa_get_jf_constant (jfunc);
1316 return dest_lat->add_value (val, cs, NULL, 0);
1318 else if (jfunc->type == IPA_JF_PASS_THROUGH
1319 || jfunc->type == IPA_JF_ANCESTOR)
1321 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1322 ipcp_lattice<tree> *src_lat;
1323 int src_idx;
1324 bool ret;
1326 if (jfunc->type == IPA_JF_PASS_THROUGH)
1327 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1328 else
1329 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1331 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1332 if (src_lat->bottom)
1333 return dest_lat->set_contains_variable ();
1335 /* If we would need to clone the caller and cannot, do not propagate. */
1336 if (!ipcp_versionable_function_p (cs->caller)
1337 && (src_lat->contains_variable
1338 || (src_lat->values_count > 1)))
1339 return dest_lat->set_contains_variable ();
1341 if (jfunc->type == IPA_JF_PASS_THROUGH)
1342 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1343 dest_lat, src_idx);
1344 else
1345 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1346 src_idx);
1348 if (src_lat->contains_variable)
1349 ret |= dest_lat->set_contains_variable ();
1351 return ret;
1354 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1355 use it for indirect inlining), we should propagate them too. */
1356 return dest_lat->set_contains_variable ();
1359 /* Propagate scalar values across jump function JFUNC that is associated with
1360 edge CS and describes argument IDX and put the values into DEST_LAT. */
1362 static bool
1363 propagate_context_accross_jump_function (cgraph_edge *cs,
1364 ipa_jump_func *jfunc, int idx,
1365 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1367 ipa_edge_args *args = IPA_EDGE_REF (cs);
1368 if (dest_lat->bottom)
1369 return false;
1370 bool ret = false;
1371 bool added_sth = false;
1372 bool type_preserved = true;
1374 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1375 = ipa_get_ith_polymorhic_call_context (args, idx);
1377 if (edge_ctx_ptr)
1378 edge_ctx = *edge_ctx_ptr;
1380 if (jfunc->type == IPA_JF_PASS_THROUGH
1381 || jfunc->type == IPA_JF_ANCESTOR)
1383 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1384 int src_idx;
1385 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1387 /* TODO: Once we figure out how to propagate speculations, it will
1388 probably be a good idea to switch to speculation if type_preserved is
1389 not set instead of punting. */
1390 if (jfunc->type == IPA_JF_PASS_THROUGH)
1392 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1393 goto prop_fail;
1394 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1395 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1397 else
1399 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1400 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1403 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1404 /* If we would need to clone the caller and cannot, do not propagate. */
1405 if (!ipcp_versionable_function_p (cs->caller)
1406 && (src_lat->contains_variable
1407 || (src_lat->values_count > 1)))
1408 goto prop_fail;
1410 ipcp_value<ipa_polymorphic_call_context> *src_val;
1411 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1413 ipa_polymorphic_call_context cur = src_val->value;
1415 if (!type_preserved)
1416 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1417 if (jfunc->type == IPA_JF_ANCESTOR)
1418 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1419 /* TODO: In cases we know how the context is going to be used,
1420 we can improve the result by passing proper OTR_TYPE. */
1421 cur.combine_with (edge_ctx);
1422 if (!cur.useless_p ())
1424 if (src_lat->contains_variable
1425 && !edge_ctx.equal_to (cur))
1426 ret |= dest_lat->set_contains_variable ();
1427 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1428 added_sth = true;
1434 prop_fail:
1435 if (!added_sth)
1437 if (!edge_ctx.useless_p ())
1438 ret |= dest_lat->add_value (edge_ctx, cs);
1439 else
1440 ret |= dest_lat->set_contains_variable ();
1443 return ret;
1446 /* Propagate alignments across jump function JFUNC that is associated with
1447 edge CS and update DEST_LAT accordingly. */
1449 static bool
1450 propagate_alignment_accross_jump_function (struct cgraph_edge *cs,
1451 struct ipa_jump_func *jfunc,
1452 struct ipcp_param_lattices *dest_lat)
1454 if (alignment_bottom_p (dest_lat))
1455 return false;
1457 ipa_alignment cur;
1458 cur.known = false;
1459 if (jfunc->alignment.known)
1460 cur = jfunc->alignment;
1461 else if (jfunc->type == IPA_JF_PASS_THROUGH
1462 || jfunc->type == IPA_JF_ANCESTOR)
1464 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1465 struct ipcp_param_lattices *src_lats;
1466 HOST_WIDE_INT offset = 0;
1467 int src_idx;
1469 if (jfunc->type == IPA_JF_PASS_THROUGH)
1471 enum tree_code op = ipa_get_jf_pass_through_operation (jfunc);
1472 if (op != NOP_EXPR)
1474 if (op != POINTER_PLUS_EXPR
1475 && op != PLUS_EXPR)
1476 goto prop_fail;
1477 tree operand = ipa_get_jf_pass_through_operand (jfunc);
1478 if (!tree_fits_shwi_p (operand))
1479 goto prop_fail;
1480 offset = tree_to_shwi (operand);
1482 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1484 else
1486 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1487 offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;;
1490 src_lats = ipa_get_parm_lattices (caller_info, src_idx);
1491 if (!src_lats->alignment.known
1492 || alignment_bottom_p (src_lats))
1493 goto prop_fail;
1495 cur = src_lats->alignment;
1496 cur.misalign = (cur.misalign + offset) % cur.align;
1499 if (cur.known)
1501 if (!dest_lat->alignment.known)
1503 dest_lat->alignment = cur;
1504 return true;
1506 else if (dest_lat->alignment.align == cur.align
1507 && dest_lat->alignment.misalign == cur.misalign)
1508 return false;
1511 prop_fail:
1512 set_alignment_to_bottom (dest_lat);
1513 return true;
1516 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1517 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1518 other cases, return false). If there are no aggregate items, set
1519 aggs_by_ref to NEW_AGGS_BY_REF. */
1521 static bool
1522 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1523 bool new_aggs_by_ref)
1525 if (dest_plats->aggs)
1527 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1529 set_agg_lats_to_bottom (dest_plats);
1530 return true;
1533 else
1534 dest_plats->aggs_by_ref = new_aggs_by_ref;
1535 return false;
1538 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1539 already existing lattice for the given OFFSET and SIZE, marking all skipped
1540 lattices as containing variable and checking for overlaps. If there is no
1541 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1542 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1543 unless there are too many already. If there are two many, return false. If
1544 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1545 skipped lattices were newly marked as containing variable, set *CHANGE to
1546 true. */
1548 static bool
1549 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1550 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1551 struct ipcp_agg_lattice ***aglat,
1552 bool pre_existing, bool *change)
1554 gcc_checking_assert (offset >= 0);
1556 while (**aglat && (**aglat)->offset < offset)
1558 if ((**aglat)->offset + (**aglat)->size > offset)
1560 set_agg_lats_to_bottom (dest_plats);
1561 return false;
1563 *change |= (**aglat)->set_contains_variable ();
1564 *aglat = &(**aglat)->next;
1567 if (**aglat && (**aglat)->offset == offset)
1569 if ((**aglat)->size != val_size
1570 || ((**aglat)->next
1571 && (**aglat)->next->offset < offset + val_size))
1573 set_agg_lats_to_bottom (dest_plats);
1574 return false;
1576 gcc_checking_assert (!(**aglat)->next
1577 || (**aglat)->next->offset >= offset + val_size);
1578 return true;
1580 else
1582 struct ipcp_agg_lattice *new_al;
1584 if (**aglat && (**aglat)->offset < offset + val_size)
1586 set_agg_lats_to_bottom (dest_plats);
1587 return false;
1589 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1590 return false;
1591 dest_plats->aggs_count++;
1592 new_al = ipcp_agg_lattice_pool.allocate ();
1593 memset (new_al, 0, sizeof (*new_al));
1595 new_al->offset = offset;
1596 new_al->size = val_size;
1597 new_al->contains_variable = pre_existing;
1599 new_al->next = **aglat;
1600 **aglat = new_al;
1601 return true;
1605 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1606 containing an unknown value. */
1608 static bool
1609 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1611 bool ret = false;
1612 while (aglat)
1614 ret |= aglat->set_contains_variable ();
1615 aglat = aglat->next;
1617 return ret;
1620 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1621 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1622 parameter used for lattice value sources. Return true if DEST_PLATS changed
1623 in any way. */
1625 static bool
1626 merge_aggregate_lattices (struct cgraph_edge *cs,
1627 struct ipcp_param_lattices *dest_plats,
1628 struct ipcp_param_lattices *src_plats,
1629 int src_idx, HOST_WIDE_INT offset_delta)
1631 bool pre_existing = dest_plats->aggs != NULL;
1632 struct ipcp_agg_lattice **dst_aglat;
1633 bool ret = false;
1635 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1636 return true;
1637 if (src_plats->aggs_bottom)
1638 return set_agg_lats_contain_variable (dest_plats);
1639 if (src_plats->aggs_contain_variable)
1640 ret |= set_agg_lats_contain_variable (dest_plats);
1641 dst_aglat = &dest_plats->aggs;
1643 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1644 src_aglat;
1645 src_aglat = src_aglat->next)
1647 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1649 if (new_offset < 0)
1650 continue;
1651 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1652 &dst_aglat, pre_existing, &ret))
1654 struct ipcp_agg_lattice *new_al = *dst_aglat;
1656 dst_aglat = &(*dst_aglat)->next;
1657 if (src_aglat->bottom)
1659 ret |= new_al->set_contains_variable ();
1660 continue;
1662 if (src_aglat->contains_variable)
1663 ret |= new_al->set_contains_variable ();
1664 for (ipcp_value<tree> *val = src_aglat->values;
1665 val;
1666 val = val->next)
1667 ret |= new_al->add_value (val->value, cs, val, src_idx,
1668 src_aglat->offset);
1670 else if (dest_plats->aggs_bottom)
1671 return true;
1673 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1674 return ret;
1677 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1678 pass-through JFUNC and if so, whether it has conform and conforms to the
1679 rules about propagating values passed by reference. */
1681 static bool
1682 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1683 struct ipa_jump_func *jfunc)
1685 return src_plats->aggs
1686 && (!src_plats->aggs_by_ref
1687 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1690 /* Propagate scalar values across jump function JFUNC that is associated with
1691 edge CS and put the values into DEST_LAT. */
1693 static bool
1694 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1695 struct ipa_jump_func *jfunc,
1696 struct ipcp_param_lattices *dest_plats)
1698 bool ret = false;
1700 if (dest_plats->aggs_bottom)
1701 return false;
1703 if (jfunc->type == IPA_JF_PASS_THROUGH
1704 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1706 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1707 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1708 struct ipcp_param_lattices *src_plats;
1710 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1711 if (agg_pass_through_permissible_p (src_plats, jfunc))
1713 /* Currently we do not produce clobber aggregate jump
1714 functions, replace with merging when we do. */
1715 gcc_assert (!jfunc->agg.items);
1716 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1717 src_idx, 0);
1719 else
1720 ret |= set_agg_lats_contain_variable (dest_plats);
1722 else if (jfunc->type == IPA_JF_ANCESTOR
1723 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1725 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1726 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1727 struct ipcp_param_lattices *src_plats;
1729 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1730 if (src_plats->aggs && src_plats->aggs_by_ref)
1732 /* Currently we do not produce clobber aggregate jump
1733 functions, replace with merging when we do. */
1734 gcc_assert (!jfunc->agg.items);
1735 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1736 ipa_get_jf_ancestor_offset (jfunc));
1738 else if (!src_plats->aggs_by_ref)
1739 ret |= set_agg_lats_to_bottom (dest_plats);
1740 else
1741 ret |= set_agg_lats_contain_variable (dest_plats);
1743 else if (jfunc->agg.items)
1745 bool pre_existing = dest_plats->aggs != NULL;
1746 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1747 struct ipa_agg_jf_item *item;
1748 int i;
1750 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1751 return true;
1753 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1755 HOST_WIDE_INT val_size;
1757 if (item->offset < 0)
1758 continue;
1759 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1760 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
1762 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1763 &aglat, pre_existing, &ret))
1765 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
1766 aglat = &(*aglat)->next;
1768 else if (dest_plats->aggs_bottom)
1769 return true;
1772 ret |= set_chain_of_aglats_contains_variable (*aglat);
1774 else
1775 ret |= set_agg_lats_contain_variable (dest_plats);
1777 return ret;
1780 /* Propagate constants from the caller to the callee of CS. INFO describes the
1781 caller. */
1783 static bool
1784 propagate_constants_accross_call (struct cgraph_edge *cs)
1786 struct ipa_node_params *callee_info;
1787 enum availability availability;
1788 struct cgraph_node *callee, *alias_or_thunk;
1789 struct ipa_edge_args *args;
1790 bool ret = false;
1791 int i, args_count, parms_count;
1793 callee = cs->callee->function_symbol (&availability);
1794 if (!callee->definition)
1795 return false;
1796 gcc_checking_assert (callee->has_gimple_body_p ());
1797 callee_info = IPA_NODE_REF (callee);
1799 args = IPA_EDGE_REF (cs);
1800 args_count = ipa_get_cs_argument_count (args);
1801 parms_count = ipa_get_param_count (callee_info);
1802 if (parms_count == 0)
1803 return false;
1805 /* No propagation through instrumentation thunks is available yet.
1806 It should be possible with proper mapping of call args and
1807 instrumented callee params in the propagation loop below. But
1808 this case mostly occurs when legacy code calls instrumented code
1809 and it is not a primary target for optimizations.
1810 We detect instrumentation thunks in aliases and thunks chain by
1811 checking instrumentation_clone flag for chain source and target.
1812 Going through instrumentation thunks we always have it changed
1813 from 0 to 1 and all other nodes do not change it. */
1814 if (!cs->callee->instrumentation_clone
1815 && callee->instrumentation_clone)
1817 for (i = 0; i < parms_count; i++)
1818 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1819 i));
1820 return ret;
1823 /* If this call goes through a thunk we must not propagate to the first (0th)
1824 parameter. However, we might need to uncover a thunk from below a series
1825 of aliases first. */
1826 alias_or_thunk = cs->callee;
1827 while (alias_or_thunk->alias)
1828 alias_or_thunk = alias_or_thunk->get_alias_target ();
1829 if (alias_or_thunk->thunk.thunk_p)
1831 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1832 0));
1833 i = 1;
1835 else
1836 i = 0;
1838 for (; (i < args_count) && (i < parms_count); i++)
1840 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1841 struct ipcp_param_lattices *dest_plats;
1843 dest_plats = ipa_get_parm_lattices (callee_info, i);
1844 if (availability == AVAIL_INTERPOSABLE)
1845 ret |= set_all_contains_variable (dest_plats);
1846 else
1848 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1849 &dest_plats->itself);
1850 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
1851 &dest_plats->ctxlat);
1852 ret |= propagate_alignment_accross_jump_function (cs, jump_func,
1853 dest_plats);
1854 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1855 dest_plats);
1858 for (; i < parms_count; i++)
1859 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1861 return ret;
1864 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1865 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1866 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
1868 static tree
1869 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
1870 vec<tree> known_csts,
1871 vec<ipa_polymorphic_call_context> known_contexts,
1872 vec<ipa_agg_jump_function_p> known_aggs,
1873 struct ipa_agg_replacement_value *agg_reps,
1874 bool *speculative)
1876 int param_index = ie->indirect_info->param_index;
1877 HOST_WIDE_INT anc_offset;
1878 tree t;
1879 tree target = NULL;
1881 *speculative = false;
1883 if (param_index == -1
1884 || known_csts.length () <= (unsigned int) param_index)
1885 return NULL_TREE;
1887 if (!ie->indirect_info->polymorphic)
1889 tree t;
1891 if (ie->indirect_info->agg_contents)
1893 if (agg_reps)
1895 t = NULL;
1896 while (agg_reps)
1898 if (agg_reps->index == param_index
1899 && agg_reps->offset == ie->indirect_info->offset
1900 && agg_reps->by_ref == ie->indirect_info->by_ref)
1902 t = agg_reps->value;
1903 break;
1905 agg_reps = agg_reps->next;
1908 else if (known_aggs.length () > (unsigned int) param_index)
1910 struct ipa_agg_jump_function *agg;
1911 agg = known_aggs[param_index];
1912 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1913 ie->indirect_info->by_ref);
1915 else
1916 t = NULL;
1918 else
1919 t = known_csts[param_index];
1921 if (t &&
1922 TREE_CODE (t) == ADDR_EXPR
1923 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1924 return TREE_OPERAND (t, 0);
1925 else
1926 return NULL_TREE;
1929 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
1930 return NULL_TREE;
1932 gcc_assert (!ie->indirect_info->agg_contents);
1933 anc_offset = ie->indirect_info->offset;
1935 t = NULL;
1937 /* Try to work out value of virtual table pointer value in replacemnets. */
1938 if (!t && agg_reps && !ie->indirect_info->by_ref)
1940 while (agg_reps)
1942 if (agg_reps->index == param_index
1943 && agg_reps->offset == ie->indirect_info->offset
1944 && agg_reps->by_ref)
1946 t = agg_reps->value;
1947 break;
1949 agg_reps = agg_reps->next;
1953 /* Try to work out value of virtual table pointer value in known
1954 aggregate values. */
1955 if (!t && known_aggs.length () > (unsigned int) param_index
1956 && !ie->indirect_info->by_ref)
1958 struct ipa_agg_jump_function *agg;
1959 agg = known_aggs[param_index];
1960 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1961 true);
1964 /* If we found the virtual table pointer, lookup the target. */
1965 if (t)
1967 tree vtable;
1968 unsigned HOST_WIDE_INT offset;
1969 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
1971 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
1972 vtable, offset);
1973 if (target)
1975 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1976 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1977 || !possible_polymorphic_call_target_p
1978 (ie, cgraph_node::get (target)))
1979 target = ipa_impossible_devirt_target (ie, target);
1980 *speculative = ie->indirect_info->vptr_changed;
1981 if (!*speculative)
1982 return target;
1987 /* Do we know the constant value of pointer? */
1988 if (!t)
1989 t = known_csts[param_index];
1991 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
1993 ipa_polymorphic_call_context context;
1994 if (known_contexts.length () > (unsigned int) param_index)
1996 context = known_contexts[param_index];
1997 context.offset_by (anc_offset);
1998 if (ie->indirect_info->vptr_changed)
1999 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2000 ie->indirect_info->otr_type);
2001 if (t)
2003 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2004 (t, ie->indirect_info->otr_type, anc_offset);
2005 if (!ctx2.useless_p ())
2006 context.combine_with (ctx2, ie->indirect_info->otr_type);
2009 else if (t)
2011 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2012 anc_offset);
2013 if (ie->indirect_info->vptr_changed)
2014 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2015 ie->indirect_info->otr_type);
2017 else
2018 return NULL_TREE;
2020 vec <cgraph_node *>targets;
2021 bool final;
2023 targets = possible_polymorphic_call_targets
2024 (ie->indirect_info->otr_type,
2025 ie->indirect_info->otr_token,
2026 context, &final);
2027 if (!final || targets.length () > 1)
2029 struct cgraph_node *node;
2030 if (*speculative)
2031 return target;
2032 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2033 || ie->speculative || !ie->maybe_hot_p ())
2034 return NULL;
2035 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2036 ie->indirect_info->otr_token,
2037 context);
2038 if (node)
2040 *speculative = true;
2041 target = node->decl;
2043 else
2044 return NULL;
2046 else
2048 *speculative = false;
2049 if (targets.length () == 1)
2050 target = targets[0]->decl;
2051 else
2052 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2055 if (target && !possible_polymorphic_call_target_p (ie,
2056 cgraph_node::get (target)))
2057 target = ipa_impossible_devirt_target (ie, target);
2059 return target;
2063 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2064 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2065 return the destination. */
2067 tree
2068 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2069 vec<tree> known_csts,
2070 vec<ipa_polymorphic_call_context> known_contexts,
2071 vec<ipa_agg_jump_function_p> known_aggs,
2072 bool *speculative)
2074 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2075 known_aggs, NULL, speculative);
2078 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2079 and KNOWN_CONTEXTS. */
2081 static int
2082 devirtualization_time_bonus (struct cgraph_node *node,
2083 vec<tree> known_csts,
2084 vec<ipa_polymorphic_call_context> known_contexts,
2085 vec<ipa_agg_jump_function_p> known_aggs)
2087 struct cgraph_edge *ie;
2088 int res = 0;
2090 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2092 struct cgraph_node *callee;
2093 struct inline_summary *isummary;
2094 enum availability avail;
2095 tree target;
2096 bool speculative;
2098 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2099 known_aggs, &speculative);
2100 if (!target)
2101 continue;
2103 /* Only bare minimum benefit for clearly un-inlineable targets. */
2104 res += 1;
2105 callee = cgraph_node::get (target);
2106 if (!callee || !callee->definition)
2107 continue;
2108 callee = callee->function_symbol (&avail);
2109 if (avail < AVAIL_AVAILABLE)
2110 continue;
2111 isummary = inline_summaries->get (callee);
2112 if (!isummary->inlinable)
2113 continue;
2115 /* FIXME: The values below need re-considering and perhaps also
2116 integrating into the cost metrics, at lest in some very basic way. */
2117 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2118 res += 31 / ((int)speculative + 1);
2119 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2120 res += 15 / ((int)speculative + 1);
2121 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2122 || DECL_DECLARED_INLINE_P (callee->decl))
2123 res += 7 / ((int)speculative + 1);
2126 return res;
2129 /* Return time bonus incurred because of HINTS. */
2131 static int
2132 hint_time_bonus (inline_hints hints)
2134 int result = 0;
2135 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2136 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2137 if (hints & INLINE_HINT_array_index)
2138 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2139 return result;
2142 /* If there is a reason to penalize the function described by INFO in the
2143 cloning goodness evaluation, do so. */
2145 static inline int64_t
2146 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2148 if (info->node_within_scc)
2149 evaluation = (evaluation
2150 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2152 if (info->node_calling_single_call)
2153 evaluation = (evaluation
2154 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2155 / 100;
2157 return evaluation;
2160 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2161 and SIZE_COST and with the sum of frequencies of incoming edges to the
2162 potential new clone in FREQUENCIES. */
2164 static bool
2165 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2166 int freq_sum, gcov_type count_sum, int size_cost)
2168 if (time_benefit == 0
2169 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2170 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
2171 return false;
2173 gcc_assert (size_cost > 0);
2175 struct ipa_node_params *info = IPA_NODE_REF (node);
2176 if (max_count)
2178 int factor = (count_sum * 1000) / max_count;
2179 int64_t evaluation = (((int64_t) time_benefit * factor)
2180 / size_cost);
2181 evaluation = incorporate_penalties (info, evaluation);
2183 if (dump_file && (dump_flags & TDF_DETAILS))
2184 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2185 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2186 "%s%s) -> evaluation: " "%" PRId64
2187 ", threshold: %i\n",
2188 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2189 info->node_within_scc ? ", scc" : "",
2190 info->node_calling_single_call ? ", single_call" : "",
2191 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2193 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2195 else
2197 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2198 / size_cost);
2199 evaluation = incorporate_penalties (info, evaluation);
2201 if (dump_file && (dump_flags & TDF_DETAILS))
2202 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2203 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2204 "%" PRId64 ", threshold: %i\n",
2205 time_benefit, size_cost, freq_sum,
2206 info->node_within_scc ? ", scc" : "",
2207 info->node_calling_single_call ? ", single_call" : "",
2208 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2210 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2214 /* Return all context independent values from aggregate lattices in PLATS in a
2215 vector. Return NULL if there are none. */
2217 static vec<ipa_agg_jf_item, va_gc> *
2218 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2220 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2222 if (plats->aggs_bottom
2223 || plats->aggs_contain_variable
2224 || plats->aggs_count == 0)
2225 return NULL;
2227 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2228 aglat;
2229 aglat = aglat->next)
2230 if (aglat->is_single_const ())
2232 struct ipa_agg_jf_item item;
2233 item.offset = aglat->offset;
2234 item.value = aglat->values->value;
2235 vec_safe_push (res, item);
2237 return res;
2240 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2241 populate them with values of parameters that are known independent of the
2242 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2243 non-NULL, the movement cost of all removable parameters will be stored in
2244 it. */
2246 static bool
2247 gather_context_independent_values (struct ipa_node_params *info,
2248 vec<tree> *known_csts,
2249 vec<ipa_polymorphic_call_context>
2250 *known_contexts,
2251 vec<ipa_agg_jump_function> *known_aggs,
2252 int *removable_params_cost)
2254 int i, count = ipa_get_param_count (info);
2255 bool ret = false;
2257 known_csts->create (0);
2258 known_contexts->create (0);
2259 known_csts->safe_grow_cleared (count);
2260 known_contexts->safe_grow_cleared (count);
2261 if (known_aggs)
2263 known_aggs->create (0);
2264 known_aggs->safe_grow_cleared (count);
2267 if (removable_params_cost)
2268 *removable_params_cost = 0;
2270 for (i = 0; i < count ; i++)
2272 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2273 ipcp_lattice<tree> *lat = &plats->itself;
2275 if (lat->is_single_const ())
2277 ipcp_value<tree> *val = lat->values;
2278 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2279 (*known_csts)[i] = val->value;
2280 if (removable_params_cost)
2281 *removable_params_cost
2282 += estimate_move_cost (TREE_TYPE (val->value), false);
2283 ret = true;
2285 else if (removable_params_cost
2286 && !ipa_is_param_used (info, i))
2287 *removable_params_cost
2288 += ipa_get_param_move_cost (info, i);
2290 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2291 if (ctxlat->is_single_const ())
2293 (*known_contexts)[i] = ctxlat->values->value;
2294 ret = true;
2297 if (known_aggs)
2299 vec<ipa_agg_jf_item, va_gc> *agg_items;
2300 struct ipa_agg_jump_function *ajf;
2302 agg_items = context_independent_aggregate_values (plats);
2303 ajf = &(*known_aggs)[i];
2304 ajf->items = agg_items;
2305 ajf->by_ref = plats->aggs_by_ref;
2306 ret |= agg_items != NULL;
2310 return ret;
2313 /* The current interface in ipa-inline-analysis requires a pointer vector.
2314 Create it.
2316 FIXME: That interface should be re-worked, this is slightly silly. Still,
2317 I'd like to discuss how to change it first and this demonstrates the
2318 issue. */
2320 static vec<ipa_agg_jump_function_p>
2321 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2323 vec<ipa_agg_jump_function_p> ret;
2324 struct ipa_agg_jump_function *ajf;
2325 int i;
2327 ret.create (known_aggs.length ());
2328 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2329 ret.quick_push (ajf);
2330 return ret;
2333 /* Perform time and size measurement of NODE with the context given in
2334 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2335 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2336 all context-independent removable parameters and EST_MOVE_COST of estimated
2337 movement of the considered parameter and store it into VAL. */
2339 static void
2340 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2341 vec<ipa_polymorphic_call_context> known_contexts,
2342 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2343 int base_time, int removable_params_cost,
2344 int est_move_cost, ipcp_value_base *val)
2346 int time, size, time_benefit;
2347 inline_hints hints;
2349 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2350 known_aggs_ptrs, &size, &time,
2351 &hints);
2352 time_benefit = base_time - time
2353 + devirtualization_time_bonus (node, known_csts, known_contexts,
2354 known_aggs_ptrs)
2355 + hint_time_bonus (hints)
2356 + removable_params_cost + est_move_cost;
2358 gcc_checking_assert (size >=0);
2359 /* The inliner-heuristics based estimates may think that in certain
2360 contexts some functions do not have any size at all but we want
2361 all specializations to have at least a tiny cost, not least not to
2362 divide by zero. */
2363 if (size == 0)
2364 size = 1;
2366 val->local_time_benefit = time_benefit;
2367 val->local_size_cost = size;
2370 /* Iterate over known values of parameters of NODE and estimate the local
2371 effects in terms of time and size they have. */
2373 static void
2374 estimate_local_effects (struct cgraph_node *node)
2376 struct ipa_node_params *info = IPA_NODE_REF (node);
2377 int i, count = ipa_get_param_count (info);
2378 vec<tree> known_csts;
2379 vec<ipa_polymorphic_call_context> known_contexts;
2380 vec<ipa_agg_jump_function> known_aggs;
2381 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2382 bool always_const;
2383 int base_time = inline_summaries->get (node)->time;
2384 int removable_params_cost;
2386 if (!count || !ipcp_versionable_function_p (node))
2387 return;
2389 if (dump_file && (dump_flags & TDF_DETAILS))
2390 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2391 node->name (), node->order, base_time);
2393 always_const = gather_context_independent_values (info, &known_csts,
2394 &known_contexts, &known_aggs,
2395 &removable_params_cost);
2396 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2397 if (always_const)
2399 struct caller_statistics stats;
2400 inline_hints hints;
2401 int time, size;
2403 init_caller_stats (&stats);
2404 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2405 false);
2406 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2407 known_aggs_ptrs, &size, &time, &hints);
2408 time -= devirtualization_time_bonus (node, known_csts, known_contexts,
2409 known_aggs_ptrs);
2410 time -= hint_time_bonus (hints);
2411 time -= removable_params_cost;
2412 size -= stats.n_calls * removable_params_cost;
2414 if (dump_file)
2415 fprintf (dump_file, " - context independent values, size: %i, "
2416 "time_benefit: %i\n", size, base_time - time);
2418 if (size <= 0
2419 || node->will_be_removed_from_program_if_no_direct_calls_p ())
2421 info->do_clone_for_all_contexts = true;
2422 base_time = time;
2424 if (dump_file)
2425 fprintf (dump_file, " Decided to specialize for all "
2426 "known contexts, code not going to grow.\n");
2428 else if (good_cloning_opportunity_p (node, base_time - time,
2429 stats.freq_sum, stats.count_sum,
2430 size))
2432 if (size + overall_size <= max_new_size)
2434 info->do_clone_for_all_contexts = true;
2435 base_time = time;
2436 overall_size += size;
2438 if (dump_file)
2439 fprintf (dump_file, " Decided to specialize for all "
2440 "known contexts, growth deemed beneficial.\n");
2442 else if (dump_file && (dump_flags & TDF_DETAILS))
2443 fprintf (dump_file, " Not cloning for all contexts because "
2444 "max_new_size would be reached with %li.\n",
2445 size + overall_size);
2449 for (i = 0; i < count ; i++)
2451 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2452 ipcp_lattice<tree> *lat = &plats->itself;
2453 ipcp_value<tree> *val;
2455 if (lat->bottom
2456 || !lat->values
2457 || known_csts[i])
2458 continue;
2460 for (val = lat->values; val; val = val->next)
2462 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2463 known_csts[i] = val->value;
2465 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2466 perform_estimation_of_a_value (node, known_csts, known_contexts,
2467 known_aggs_ptrs, base_time,
2468 removable_params_cost, emc, val);
2470 if (dump_file && (dump_flags & TDF_DETAILS))
2472 fprintf (dump_file, " - estimates for value ");
2473 print_ipcp_constant_value (dump_file, val->value);
2474 fprintf (dump_file, " for ");
2475 ipa_dump_param (dump_file, info, i);
2476 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2477 val->local_time_benefit, val->local_size_cost);
2480 known_csts[i] = NULL_TREE;
2483 for (i = 0; i < count; i++)
2485 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2487 if (!plats->virt_call)
2488 continue;
2490 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2491 ipcp_value<ipa_polymorphic_call_context> *val;
2493 if (ctxlat->bottom
2494 || !ctxlat->values
2495 || !known_contexts[i].useless_p ())
2496 continue;
2498 for (val = ctxlat->values; val; val = val->next)
2500 known_contexts[i] = val->value;
2501 perform_estimation_of_a_value (node, known_csts, known_contexts,
2502 known_aggs_ptrs, base_time,
2503 removable_params_cost, 0, val);
2505 if (dump_file && (dump_flags & TDF_DETAILS))
2507 fprintf (dump_file, " - estimates for polymorphic context ");
2508 print_ipcp_constant_value (dump_file, val->value);
2509 fprintf (dump_file, " for ");
2510 ipa_dump_param (dump_file, info, i);
2511 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2512 val->local_time_benefit, val->local_size_cost);
2515 known_contexts[i] = ipa_polymorphic_call_context ();
2518 for (i = 0; i < count ; i++)
2520 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2521 struct ipa_agg_jump_function *ajf;
2522 struct ipcp_agg_lattice *aglat;
2524 if (plats->aggs_bottom || !plats->aggs)
2525 continue;
2527 ajf = &known_aggs[i];
2528 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2530 ipcp_value<tree> *val;
2531 if (aglat->bottom || !aglat->values
2532 /* If the following is true, the one value is in known_aggs. */
2533 || (!plats->aggs_contain_variable
2534 && aglat->is_single_const ()))
2535 continue;
2537 for (val = aglat->values; val; val = val->next)
2539 struct ipa_agg_jf_item item;
2541 item.offset = aglat->offset;
2542 item.value = val->value;
2543 vec_safe_push (ajf->items, item);
2545 perform_estimation_of_a_value (node, known_csts, known_contexts,
2546 known_aggs_ptrs, base_time,
2547 removable_params_cost, 0, val);
2549 if (dump_file && (dump_flags & TDF_DETAILS))
2551 fprintf (dump_file, " - estimates for value ");
2552 print_ipcp_constant_value (dump_file, val->value);
2553 fprintf (dump_file, " for ");
2554 ipa_dump_param (dump_file, info, i);
2555 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2556 "]: time_benefit: %i, size: %i\n",
2557 plats->aggs_by_ref ? "ref " : "",
2558 aglat->offset,
2559 val->local_time_benefit, val->local_size_cost);
2562 ajf->items->pop ();
2567 for (i = 0; i < count ; i++)
2568 vec_free (known_aggs[i].items);
2570 known_csts.release ();
2571 known_contexts.release ();
2572 known_aggs.release ();
2573 known_aggs_ptrs.release ();
2577 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2578 topological sort of values. */
2580 template <typename valtype>
2581 void
2582 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
2584 ipcp_value_source<valtype> *src;
2586 if (cur_val->dfs)
2587 return;
2589 dfs_counter++;
2590 cur_val->dfs = dfs_counter;
2591 cur_val->low_link = dfs_counter;
2593 cur_val->topo_next = stack;
2594 stack = cur_val;
2595 cur_val->on_stack = true;
2597 for (src = cur_val->sources; src; src = src->next)
2598 if (src->val)
2600 if (src->val->dfs == 0)
2602 add_val (src->val);
2603 if (src->val->low_link < cur_val->low_link)
2604 cur_val->low_link = src->val->low_link;
2606 else if (src->val->on_stack
2607 && src->val->dfs < cur_val->low_link)
2608 cur_val->low_link = src->val->dfs;
2611 if (cur_val->dfs == cur_val->low_link)
2613 ipcp_value<valtype> *v, *scc_list = NULL;
2617 v = stack;
2618 stack = v->topo_next;
2619 v->on_stack = false;
2621 v->scc_next = scc_list;
2622 scc_list = v;
2624 while (v != cur_val);
2626 cur_val->topo_next = values_topo;
2627 values_topo = cur_val;
2631 /* Add all values in lattices associated with NODE to the topological sort if
2632 they are not there yet. */
2634 static void
2635 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
2637 struct ipa_node_params *info = IPA_NODE_REF (node);
2638 int i, count = ipa_get_param_count (info);
2640 for (i = 0; i < count ; i++)
2642 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2643 ipcp_lattice<tree> *lat = &plats->itself;
2644 struct ipcp_agg_lattice *aglat;
2646 if (!lat->bottom)
2648 ipcp_value<tree> *val;
2649 for (val = lat->values; val; val = val->next)
2650 topo->constants.add_val (val);
2653 if (!plats->aggs_bottom)
2654 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2655 if (!aglat->bottom)
2657 ipcp_value<tree> *val;
2658 for (val = aglat->values; val; val = val->next)
2659 topo->constants.add_val (val);
2662 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2663 if (!ctxlat->bottom)
2665 ipcp_value<ipa_polymorphic_call_context> *ctxval;
2666 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
2667 topo->contexts.add_val (ctxval);
2672 /* One pass of constants propagation along the call graph edges, from callers
2673 to callees (requires topological ordering in TOPO), iterate over strongly
2674 connected components. */
2676 static void
2677 propagate_constants_topo (struct ipa_topo_info *topo)
2679 int i;
2681 for (i = topo->nnodes - 1; i >= 0; i--)
2683 unsigned j;
2684 struct cgraph_node *v, *node = topo->order[i];
2685 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
2687 /* First, iteratively propagate within the strongly connected component
2688 until all lattices stabilize. */
2689 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2690 if (v->has_gimple_body_p ())
2691 push_node_to_stack (topo, v);
2693 v = pop_node_from_stack (topo);
2694 while (v)
2696 struct cgraph_edge *cs;
2698 for (cs = v->callees; cs; cs = cs->next_callee)
2699 if (ipa_edge_within_scc (cs))
2701 IPA_NODE_REF (v)->node_within_scc = true;
2702 if (propagate_constants_accross_call (cs))
2703 push_node_to_stack (topo, cs->callee->function_symbol ());
2705 v = pop_node_from_stack (topo);
2708 /* Afterwards, propagate along edges leading out of the SCC, calculates
2709 the local effects of the discovered constants and all valid values to
2710 their topological sort. */
2711 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2712 if (v->has_gimple_body_p ())
2714 struct cgraph_edge *cs;
2716 estimate_local_effects (v);
2717 add_all_node_vals_to_toposort (v, topo);
2718 for (cs = v->callees; cs; cs = cs->next_callee)
2719 if (!ipa_edge_within_scc (cs))
2720 propagate_constants_accross_call (cs);
2722 cycle_nodes.release ();
2727 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2728 the bigger one if otherwise. */
2730 static int
2731 safe_add (int a, int b)
2733 if (a > INT_MAX/2 || b > INT_MAX/2)
2734 return a > b ? a : b;
2735 else
2736 return a + b;
2740 /* Propagate the estimated effects of individual values along the topological
2741 from the dependent values to those they depend on. */
2743 template <typename valtype>
2744 void
2745 value_topo_info<valtype>::propagate_effects ()
2747 ipcp_value<valtype> *base;
2749 for (base = values_topo; base; base = base->topo_next)
2751 ipcp_value_source<valtype> *src;
2752 ipcp_value<valtype> *val;
2753 int time = 0, size = 0;
2755 for (val = base; val; val = val->scc_next)
2757 time = safe_add (time,
2758 val->local_time_benefit + val->prop_time_benefit);
2759 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2762 for (val = base; val; val = val->scc_next)
2763 for (src = val->sources; src; src = src->next)
2764 if (src->val
2765 && src->cs->maybe_hot_p ())
2767 src->val->prop_time_benefit = safe_add (time,
2768 src->val->prop_time_benefit);
2769 src->val->prop_size_cost = safe_add (size,
2770 src->val->prop_size_cost);
2776 /* Propagate constants, polymorphic contexts and their effects from the
2777 summaries interprocedurally. */
2779 static void
2780 ipcp_propagate_stage (struct ipa_topo_info *topo)
2782 struct cgraph_node *node;
2784 if (dump_file)
2785 fprintf (dump_file, "\n Propagating constants:\n\n");
2787 if (in_lto_p)
2788 ipa_update_after_lto_read ();
2791 FOR_EACH_DEFINED_FUNCTION (node)
2793 struct ipa_node_params *info = IPA_NODE_REF (node);
2795 determine_versionability (node);
2796 if (node->has_gimple_body_p ())
2798 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2799 ipa_get_param_count (info));
2800 initialize_node_lattices (node);
2802 if (node->definition && !node->alias)
2803 overall_size += inline_summaries->get (node)->self_size;
2804 if (node->count > max_count)
2805 max_count = node->count;
2808 max_new_size = overall_size;
2809 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2810 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2811 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2813 if (dump_file)
2814 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2815 overall_size, max_new_size);
2817 propagate_constants_topo (topo);
2818 #ifdef ENABLE_CHECKING
2819 ipcp_verify_propagated_values ();
2820 #endif
2821 topo->constants.propagate_effects ();
2822 topo->contexts.propagate_effects ();
2824 if (dump_file)
2826 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2827 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2831 /* Discover newly direct outgoing edges from NODE which is a new clone with
2832 known KNOWN_CSTS and make them direct. */
2834 static void
2835 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2836 vec<tree> known_csts,
2837 vec<ipa_polymorphic_call_context>
2838 known_contexts,
2839 struct ipa_agg_replacement_value *aggvals)
2841 struct cgraph_edge *ie, *next_ie;
2842 bool found = false;
2844 for (ie = node->indirect_calls; ie; ie = next_ie)
2846 tree target;
2847 bool speculative;
2849 next_ie = ie->next_callee;
2850 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2851 vNULL, aggvals, &speculative);
2852 if (target)
2854 bool agg_contents = ie->indirect_info->agg_contents;
2855 bool polymorphic = ie->indirect_info->polymorphic;
2856 int param_index = ie->indirect_info->param_index;
2857 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
2858 speculative);
2859 found = true;
2861 if (cs && !agg_contents && !polymorphic)
2863 struct ipa_node_params *info = IPA_NODE_REF (node);
2864 int c = ipa_get_controlled_uses (info, param_index);
2865 if (c != IPA_UNDESCRIBED_USE)
2867 struct ipa_ref *to_del;
2869 c--;
2870 ipa_set_controlled_uses (info, param_index, c);
2871 if (dump_file && (dump_flags & TDF_DETAILS))
2872 fprintf (dump_file, " controlled uses count of param "
2873 "%i bumped down to %i\n", param_index, c);
2874 if (c == 0
2875 && (to_del = node->find_reference (cs->callee, NULL, 0)))
2877 if (dump_file && (dump_flags & TDF_DETAILS))
2878 fprintf (dump_file, " and even removing its "
2879 "cloning-created reference\n");
2880 to_del->remove_reference ();
2886 /* Turning calls to direct calls will improve overall summary. */
2887 if (found)
2888 inline_update_overall_summary (node);
2891 /* Vector of pointers which for linked lists of clones of an original crgaph
2892 edge. */
2894 static vec<cgraph_edge *> next_edge_clone;
2895 static vec<cgraph_edge *> prev_edge_clone;
2897 static inline void
2898 grow_edge_clone_vectors (void)
2900 if (next_edge_clone.length ()
2901 <= (unsigned) symtab->edges_max_uid)
2902 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2903 if (prev_edge_clone.length ()
2904 <= (unsigned) symtab->edges_max_uid)
2905 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2908 /* Edge duplication hook to grow the appropriate linked list in
2909 next_edge_clone. */
2911 static void
2912 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2913 void *)
2915 grow_edge_clone_vectors ();
2917 struct cgraph_edge *old_next = next_edge_clone[src->uid];
2918 if (old_next)
2919 prev_edge_clone[old_next->uid] = dst;
2920 prev_edge_clone[dst->uid] = src;
2922 next_edge_clone[dst->uid] = old_next;
2923 next_edge_clone[src->uid] = dst;
2926 /* Hook that is called by cgraph.c when an edge is removed. */
2928 static void
2929 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
2931 grow_edge_clone_vectors ();
2933 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
2934 struct cgraph_edge *next = next_edge_clone[cs->uid];
2935 if (prev)
2936 next_edge_clone[prev->uid] = next;
2937 if (next)
2938 prev_edge_clone[next->uid] = prev;
2941 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2942 parameter with the given INDEX. */
2944 static tree
2945 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2946 int index)
2948 struct ipa_agg_replacement_value *aggval;
2950 aggval = ipa_get_agg_replacements_for_node (node);
2951 while (aggval)
2953 if (aggval->offset == offset
2954 && aggval->index == index)
2955 return aggval->value;
2956 aggval = aggval->next;
2958 return NULL_TREE;
2961 /* Return true is NODE is DEST or its clone for all contexts. */
2963 static bool
2964 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
2966 if (node == dest)
2967 return true;
2969 struct ipa_node_params *info = IPA_NODE_REF (node);
2970 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
2973 /* Return true if edge CS does bring about the value described by SRC to node
2974 DEST or its clone for all contexts. */
2976 static bool
2977 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
2978 cgraph_node *dest)
2980 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2981 enum availability availability;
2982 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
2984 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
2985 || availability <= AVAIL_INTERPOSABLE
2986 || caller_info->node_dead)
2987 return false;
2988 if (!src->val)
2989 return true;
2991 if (caller_info->ipcp_orig_node)
2993 tree t;
2994 if (src->offset == -1)
2995 t = caller_info->known_csts[src->index];
2996 else
2997 t = get_clone_agg_value (cs->caller, src->offset, src->index);
2998 return (t != NULL_TREE
2999 && values_equal_for_ipcp_p (src->val->value, t));
3001 else
3003 struct ipcp_agg_lattice *aglat;
3004 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3005 src->index);
3006 if (src->offset == -1)
3007 return (plats->itself.is_single_const ()
3008 && values_equal_for_ipcp_p (src->val->value,
3009 plats->itself.values->value));
3010 else
3012 if (plats->aggs_bottom || plats->aggs_contain_variable)
3013 return false;
3014 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3015 if (aglat->offset == src->offset)
3016 return (aglat->is_single_const ()
3017 && values_equal_for_ipcp_p (src->val->value,
3018 aglat->values->value));
3020 return false;
3024 /* Return true if edge CS does bring about the value described by SRC to node
3025 DEST or its clone for all contexts. */
3027 static bool
3028 cgraph_edge_brings_value_p (cgraph_edge *cs,
3029 ipcp_value_source<ipa_polymorphic_call_context> *src,
3030 cgraph_node *dest)
3032 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3033 cgraph_node *real_dest = cs->callee->function_symbol ();
3035 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3036 || caller_info->node_dead)
3037 return false;
3038 if (!src->val)
3039 return true;
3041 if (caller_info->ipcp_orig_node)
3042 return (caller_info->known_contexts.length () > (unsigned) src->index)
3043 && values_equal_for_ipcp_p (src->val->value,
3044 caller_info->known_contexts[src->index]);
3046 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3047 src->index);
3048 return plats->ctxlat.is_single_const ()
3049 && values_equal_for_ipcp_p (src->val->value,
3050 plats->ctxlat.values->value);
3053 /* Get the next clone in the linked list of clones of an edge. */
3055 static inline struct cgraph_edge *
3056 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3058 return next_edge_clone[cs->uid];
3061 /* Given VAL that is intended for DEST, iterate over all its sources and if
3062 they still hold, add their edge frequency and their number into *FREQUENCY
3063 and *CALLER_COUNT respectively. */
3065 template <typename valtype>
3066 static bool
3067 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3068 int *freq_sum,
3069 gcov_type *count_sum, int *caller_count)
3071 ipcp_value_source<valtype> *src;
3072 int freq = 0, count = 0;
3073 gcov_type cnt = 0;
3074 bool hot = false;
3076 for (src = val->sources; src; src = src->next)
3078 struct cgraph_edge *cs = src->cs;
3079 while (cs)
3081 if (cgraph_edge_brings_value_p (cs, src, dest))
3083 count++;
3084 freq += cs->frequency;
3085 cnt += cs->count;
3086 hot |= cs->maybe_hot_p ();
3088 cs = get_next_cgraph_edge_clone (cs);
3092 *freq_sum = freq;
3093 *count_sum = cnt;
3094 *caller_count = count;
3095 return hot;
3098 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3099 is assumed their number is known and equal to CALLER_COUNT. */
3101 template <typename valtype>
3102 static vec<cgraph_edge *>
3103 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3104 int caller_count)
3106 ipcp_value_source<valtype> *src;
3107 vec<cgraph_edge *> ret;
3109 ret.create (caller_count);
3110 for (src = val->sources; src; src = src->next)
3112 struct cgraph_edge *cs = src->cs;
3113 while (cs)
3115 if (cgraph_edge_brings_value_p (cs, src, dest))
3116 ret.quick_push (cs);
3117 cs = get_next_cgraph_edge_clone (cs);
3121 return ret;
3124 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3125 Return it or NULL if for some reason it cannot be created. */
3127 static struct ipa_replace_map *
3128 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3130 struct ipa_replace_map *replace_map;
3133 replace_map = ggc_alloc<ipa_replace_map> ();
3134 if (dump_file)
3136 fprintf (dump_file, " replacing ");
3137 ipa_dump_param (dump_file, info, parm_num);
3139 fprintf (dump_file, " with const ");
3140 print_generic_expr (dump_file, value, 0);
3141 fprintf (dump_file, "\n");
3143 replace_map->old_tree = NULL;
3144 replace_map->parm_num = parm_num;
3145 replace_map->new_tree = value;
3146 replace_map->replace_p = true;
3147 replace_map->ref_p = false;
3149 return replace_map;
3152 /* Dump new profiling counts */
3154 static void
3155 dump_profile_updates (struct cgraph_node *orig_node,
3156 struct cgraph_node *new_node)
3158 struct cgraph_edge *cs;
3160 fprintf (dump_file, " setting count of the specialized node to "
3161 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3162 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3163 fprintf (dump_file, " edge to %s has count "
3164 HOST_WIDE_INT_PRINT_DEC "\n",
3165 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3167 fprintf (dump_file, " setting count of the original node to "
3168 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3169 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3170 fprintf (dump_file, " edge to %s is left with "
3171 HOST_WIDE_INT_PRINT_DEC "\n",
3172 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3175 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3176 their profile information to reflect this. */
3178 static void
3179 update_profiling_info (struct cgraph_node *orig_node,
3180 struct cgraph_node *new_node)
3182 struct cgraph_edge *cs;
3183 struct caller_statistics stats;
3184 gcov_type new_sum, orig_sum;
3185 gcov_type remainder, orig_node_count = orig_node->count;
3187 if (orig_node_count == 0)
3188 return;
3190 init_caller_stats (&stats);
3191 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3192 false);
3193 orig_sum = stats.count_sum;
3194 init_caller_stats (&stats);
3195 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3196 false);
3197 new_sum = stats.count_sum;
3199 if (orig_node_count < orig_sum + new_sum)
3201 if (dump_file)
3202 fprintf (dump_file, " Problem: node %s/%i has too low count "
3203 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3204 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3205 orig_node->name (), orig_node->order,
3206 (HOST_WIDE_INT) orig_node_count,
3207 (HOST_WIDE_INT) (orig_sum + new_sum));
3209 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3210 if (dump_file)
3211 fprintf (dump_file, " proceeding by pretending it was "
3212 HOST_WIDE_INT_PRINT_DEC "\n",
3213 (HOST_WIDE_INT) orig_node_count);
3216 new_node->count = new_sum;
3217 remainder = orig_node_count - new_sum;
3218 orig_node->count = remainder;
3220 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3221 if (cs->frequency)
3222 cs->count = apply_probability (cs->count,
3223 GCOV_COMPUTE_SCALE (new_sum,
3224 orig_node_count));
3225 else
3226 cs->count = 0;
3228 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3229 cs->count = apply_probability (cs->count,
3230 GCOV_COMPUTE_SCALE (remainder,
3231 orig_node_count));
3233 if (dump_file)
3234 dump_profile_updates (orig_node, new_node);
3237 /* Update the respective profile of specialized NEW_NODE and the original
3238 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3239 have been redirected to the specialized version. */
3241 static void
3242 update_specialized_profile (struct cgraph_node *new_node,
3243 struct cgraph_node *orig_node,
3244 gcov_type redirected_sum)
3246 struct cgraph_edge *cs;
3247 gcov_type new_node_count, orig_node_count = orig_node->count;
3249 if (dump_file)
3250 fprintf (dump_file, " the sum of counts of redirected edges is "
3251 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3252 if (orig_node_count == 0)
3253 return;
3255 gcc_assert (orig_node_count >= redirected_sum);
3257 new_node_count = new_node->count;
3258 new_node->count += redirected_sum;
3259 orig_node->count -= redirected_sum;
3261 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3262 if (cs->frequency)
3263 cs->count += apply_probability (cs->count,
3264 GCOV_COMPUTE_SCALE (redirected_sum,
3265 new_node_count));
3266 else
3267 cs->count = 0;
3269 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3271 gcov_type dec = apply_probability (cs->count,
3272 GCOV_COMPUTE_SCALE (redirected_sum,
3273 orig_node_count));
3274 if (dec < cs->count)
3275 cs->count -= dec;
3276 else
3277 cs->count = 0;
3280 if (dump_file)
3281 dump_profile_updates (orig_node, new_node);
3284 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3285 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3286 redirect all edges in CALLERS to it. */
3288 static struct cgraph_node *
3289 create_specialized_node (struct cgraph_node *node,
3290 vec<tree> known_csts,
3291 vec<ipa_polymorphic_call_context> known_contexts,
3292 struct ipa_agg_replacement_value *aggvals,
3293 vec<cgraph_edge *> callers)
3295 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3296 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3297 struct ipa_agg_replacement_value *av;
3298 struct cgraph_node *new_node;
3299 int i, count = ipa_get_param_count (info);
3300 bitmap args_to_skip;
3302 gcc_assert (!info->ipcp_orig_node);
3304 if (node->local.can_change_signature)
3306 args_to_skip = BITMAP_GGC_ALLOC ();
3307 for (i = 0; i < count; i++)
3309 tree t = known_csts[i];
3311 if (t || !ipa_is_param_used (info, i))
3312 bitmap_set_bit (args_to_skip, i);
3315 else
3317 args_to_skip = NULL;
3318 if (dump_file && (dump_flags & TDF_DETAILS))
3319 fprintf (dump_file, " cannot change function signature\n");
3322 for (i = 0; i < count ; i++)
3324 tree t = known_csts[i];
3325 if (t)
3327 struct ipa_replace_map *replace_map;
3329 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3330 replace_map = get_replacement_map (info, t, i);
3331 if (replace_map)
3332 vec_safe_push (replace_trees, replace_map);
3336 new_node = node->create_virtual_clone (callers, replace_trees,
3337 args_to_skip, "constprop");
3338 ipa_set_node_agg_value_chain (new_node, aggvals);
3339 for (av = aggvals; av; av = av->next)
3340 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3342 if (dump_file && (dump_flags & TDF_DETAILS))
3344 fprintf (dump_file, " the new node is %s/%i.\n",
3345 new_node->name (), new_node->order);
3346 if (known_contexts.exists ())
3348 for (i = 0; i < count ; i++)
3349 if (!known_contexts[i].useless_p ())
3351 fprintf (dump_file, " known ctx %i is ", i);
3352 known_contexts[i].dump (dump_file);
3355 if (aggvals)
3356 ipa_dump_agg_replacement_values (dump_file, aggvals);
3358 ipa_check_create_node_params ();
3359 update_profiling_info (node, new_node);
3360 new_info = IPA_NODE_REF (new_node);
3361 new_info->ipcp_orig_node = node;
3362 new_info->known_csts = known_csts;
3363 new_info->known_contexts = known_contexts;
3365 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3367 callers.release ();
3368 return new_node;
3371 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3372 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3374 static void
3375 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3376 vec<tree> known_csts,
3377 vec<cgraph_edge *> callers)
3379 struct ipa_node_params *info = IPA_NODE_REF (node);
3380 int i, count = ipa_get_param_count (info);
3382 for (i = 0; i < count ; i++)
3384 struct cgraph_edge *cs;
3385 tree newval = NULL_TREE;
3386 int j;
3387 bool first = true;
3389 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3390 continue;
3392 FOR_EACH_VEC_ELT (callers, j, cs)
3394 struct ipa_jump_func *jump_func;
3395 tree t;
3397 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3399 newval = NULL_TREE;
3400 break;
3402 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3403 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3404 if (!t
3405 || (newval
3406 && !values_equal_for_ipcp_p (t, newval))
3407 || (!first && !newval))
3409 newval = NULL_TREE;
3410 break;
3412 else
3413 newval = t;
3414 first = false;
3417 if (newval)
3419 if (dump_file && (dump_flags & TDF_DETAILS))
3421 fprintf (dump_file, " adding an extra known scalar value ");
3422 print_ipcp_constant_value (dump_file, newval);
3423 fprintf (dump_file, " for ");
3424 ipa_dump_param (dump_file, info, i);
3425 fprintf (dump_file, "\n");
3428 known_csts[i] = newval;
3433 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3434 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3435 CALLERS. */
3437 static void
3438 find_more_contexts_for_caller_subset (cgraph_node *node,
3439 vec<ipa_polymorphic_call_context>
3440 *known_contexts,
3441 vec<cgraph_edge *> callers)
3443 ipa_node_params *info = IPA_NODE_REF (node);
3444 int i, count = ipa_get_param_count (info);
3446 for (i = 0; i < count ; i++)
3448 cgraph_edge *cs;
3450 if (ipa_get_poly_ctx_lat (info, i)->bottom
3451 || (known_contexts->exists ()
3452 && !(*known_contexts)[i].useless_p ()))
3453 continue;
3455 ipa_polymorphic_call_context newval;
3456 bool first = true;
3457 int j;
3459 FOR_EACH_VEC_ELT (callers, j, cs)
3461 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3462 return;
3463 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3465 ipa_polymorphic_call_context ctx;
3466 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3467 jfunc);
3468 if (first)
3470 newval = ctx;
3471 first = false;
3473 else
3474 newval.meet_with (ctx);
3475 if (newval.useless_p ())
3476 break;
3479 if (!newval.useless_p ())
3481 if (dump_file && (dump_flags & TDF_DETAILS))
3483 fprintf (dump_file, " adding an extra known polymorphic "
3484 "context ");
3485 print_ipcp_constant_value (dump_file, newval);
3486 fprintf (dump_file, " for ");
3487 ipa_dump_param (dump_file, info, i);
3488 fprintf (dump_file, "\n");
3491 if (!known_contexts->exists ())
3492 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3493 (*known_contexts)[i] = newval;
3499 /* Go through PLATS and create a vector of values consisting of values and
3500 offsets (minus OFFSET) of lattices that contain only a single value. */
3502 static vec<ipa_agg_jf_item>
3503 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3505 vec<ipa_agg_jf_item> res = vNULL;
3507 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3508 return vNULL;
3510 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3511 if (aglat->is_single_const ())
3513 struct ipa_agg_jf_item ti;
3514 ti.offset = aglat->offset - offset;
3515 ti.value = aglat->values->value;
3516 res.safe_push (ti);
3518 return res;
3521 /* Intersect all values in INTER with single value lattices in PLATS (while
3522 subtracting OFFSET). */
3524 static void
3525 intersect_with_plats (struct ipcp_param_lattices *plats,
3526 vec<ipa_agg_jf_item> *inter,
3527 HOST_WIDE_INT offset)
3529 struct ipcp_agg_lattice *aglat;
3530 struct ipa_agg_jf_item *item;
3531 int k;
3533 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3535 inter->release ();
3536 return;
3539 aglat = plats->aggs;
3540 FOR_EACH_VEC_ELT (*inter, k, item)
3542 bool found = false;
3543 if (!item->value)
3544 continue;
3545 while (aglat)
3547 if (aglat->offset - offset > item->offset)
3548 break;
3549 if (aglat->offset - offset == item->offset)
3551 gcc_checking_assert (item->value);
3552 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
3553 found = true;
3554 break;
3556 aglat = aglat->next;
3558 if (!found)
3559 item->value = NULL_TREE;
3563 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3564 vector result while subtracting OFFSET from the individual value offsets. */
3566 static vec<ipa_agg_jf_item>
3567 agg_replacements_to_vector (struct cgraph_node *node, int index,
3568 HOST_WIDE_INT offset)
3570 struct ipa_agg_replacement_value *av;
3571 vec<ipa_agg_jf_item> res = vNULL;
3573 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
3574 if (av->index == index
3575 && (av->offset - offset) >= 0)
3577 struct ipa_agg_jf_item item;
3578 gcc_checking_assert (av->value);
3579 item.offset = av->offset - offset;
3580 item.value = av->value;
3581 res.safe_push (item);
3584 return res;
3587 /* Intersect all values in INTER with those that we have already scheduled to
3588 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3589 (while subtracting OFFSET). */
3591 static void
3592 intersect_with_agg_replacements (struct cgraph_node *node, int index,
3593 vec<ipa_agg_jf_item> *inter,
3594 HOST_WIDE_INT offset)
3596 struct ipa_agg_replacement_value *srcvals;
3597 struct ipa_agg_jf_item *item;
3598 int i;
3600 srcvals = ipa_get_agg_replacements_for_node (node);
3601 if (!srcvals)
3603 inter->release ();
3604 return;
3607 FOR_EACH_VEC_ELT (*inter, i, item)
3609 struct ipa_agg_replacement_value *av;
3610 bool found = false;
3611 if (!item->value)
3612 continue;
3613 for (av = srcvals; av; av = av->next)
3615 gcc_checking_assert (av->value);
3616 if (av->index == index
3617 && av->offset - offset == item->offset)
3619 if (values_equal_for_ipcp_p (item->value, av->value))
3620 found = true;
3621 break;
3624 if (!found)
3625 item->value = NULL_TREE;
3629 /* Intersect values in INTER with aggregate values that come along edge CS to
3630 parameter number INDEX and return it. If INTER does not actually exist yet,
3631 copy all incoming values to it. If we determine we ended up with no values
3632 whatsoever, return a released vector. */
3634 static vec<ipa_agg_jf_item>
3635 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
3636 vec<ipa_agg_jf_item> inter)
3638 struct ipa_jump_func *jfunc;
3639 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3640 if (jfunc->type == IPA_JF_PASS_THROUGH
3641 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3643 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3644 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3646 if (caller_info->ipcp_orig_node)
3648 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3649 struct ipcp_param_lattices *orig_plats;
3650 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3651 src_idx);
3652 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3654 if (!inter.exists ())
3655 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
3656 else
3657 intersect_with_agg_replacements (cs->caller, src_idx,
3658 &inter, 0);
3660 else
3662 inter.release ();
3663 return vNULL;
3666 else
3668 struct ipcp_param_lattices *src_plats;
3669 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3670 if (agg_pass_through_permissible_p (src_plats, jfunc))
3672 /* Currently we do not produce clobber aggregate jump
3673 functions, adjust when we do. */
3674 gcc_checking_assert (!jfunc->agg.items);
3675 if (!inter.exists ())
3676 inter = copy_plats_to_inter (src_plats, 0);
3677 else
3678 intersect_with_plats (src_plats, &inter, 0);
3680 else
3682 inter.release ();
3683 return vNULL;
3687 else if (jfunc->type == IPA_JF_ANCESTOR
3688 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3690 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3691 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3692 struct ipcp_param_lattices *src_plats;
3693 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3695 if (caller_info->ipcp_orig_node)
3697 if (!inter.exists ())
3698 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
3699 else
3700 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
3701 delta);
3703 else
3705 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3706 /* Currently we do not produce clobber aggregate jump
3707 functions, adjust when we do. */
3708 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3709 if (!inter.exists ())
3710 inter = copy_plats_to_inter (src_plats, delta);
3711 else
3712 intersect_with_plats (src_plats, &inter, delta);
3715 else if (jfunc->agg.items)
3717 struct ipa_agg_jf_item *item;
3718 int k;
3720 if (!inter.exists ())
3721 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3722 inter.safe_push ((*jfunc->agg.items)[i]);
3723 else
3724 FOR_EACH_VEC_ELT (inter, k, item)
3726 int l = 0;
3727 bool found = false;;
3729 if (!item->value)
3730 continue;
3732 while ((unsigned) l < jfunc->agg.items->length ())
3734 struct ipa_agg_jf_item *ti;
3735 ti = &(*jfunc->agg.items)[l];
3736 if (ti->offset > item->offset)
3737 break;
3738 if (ti->offset == item->offset)
3740 gcc_checking_assert (ti->value);
3741 if (values_equal_for_ipcp_p (item->value,
3742 ti->value))
3743 found = true;
3744 break;
3746 l++;
3748 if (!found)
3749 item->value = NULL;
3752 else
3754 inter.release ();
3755 return vec<ipa_agg_jf_item>();
3757 return inter;
3760 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3761 from all of them. */
3763 static struct ipa_agg_replacement_value *
3764 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3765 vec<cgraph_edge *> callers)
3767 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3768 struct ipa_agg_replacement_value *res;
3769 struct ipa_agg_replacement_value **tail = &res;
3770 struct cgraph_edge *cs;
3771 int i, j, count = ipa_get_param_count (dest_info);
3773 FOR_EACH_VEC_ELT (callers, j, cs)
3775 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3776 if (c < count)
3777 count = c;
3780 for (i = 0; i < count ; i++)
3782 struct cgraph_edge *cs;
3783 vec<ipa_agg_jf_item> inter = vNULL;
3784 struct ipa_agg_jf_item *item;
3785 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3786 int j;
3788 /* Among other things, the following check should deal with all by_ref
3789 mismatches. */
3790 if (plats->aggs_bottom)
3791 continue;
3793 FOR_EACH_VEC_ELT (callers, j, cs)
3795 inter = intersect_aggregates_with_edge (cs, i, inter);
3797 if (!inter.exists ())
3798 goto next_param;
3801 FOR_EACH_VEC_ELT (inter, j, item)
3803 struct ipa_agg_replacement_value *v;
3805 if (!item->value)
3806 continue;
3808 v = ggc_alloc<ipa_agg_replacement_value> ();
3809 v->index = i;
3810 v->offset = item->offset;
3811 v->value = item->value;
3812 v->by_ref = plats->aggs_by_ref;
3813 *tail = v;
3814 tail = &v->next;
3817 next_param:
3818 if (inter.exists ())
3819 inter.release ();
3821 *tail = NULL;
3822 return res;
3825 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3827 static struct ipa_agg_replacement_value *
3828 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
3830 struct ipa_agg_replacement_value *res;
3831 struct ipa_agg_replacement_value **tail = &res;
3832 struct ipa_agg_jump_function *aggjf;
3833 struct ipa_agg_jf_item *item;
3834 int i, j;
3836 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3837 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3839 struct ipa_agg_replacement_value *v;
3840 v = ggc_alloc<ipa_agg_replacement_value> ();
3841 v->index = i;
3842 v->offset = item->offset;
3843 v->value = item->value;
3844 v->by_ref = aggjf->by_ref;
3845 *tail = v;
3846 tail = &v->next;
3848 *tail = NULL;
3849 return res;
3852 /* Determine whether CS also brings all scalar values that the NODE is
3853 specialized for. */
3855 static bool
3856 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3857 struct cgraph_node *node)
3859 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3860 int count = ipa_get_param_count (dest_info);
3861 struct ipa_node_params *caller_info;
3862 struct ipa_edge_args *args;
3863 int i;
3865 caller_info = IPA_NODE_REF (cs->caller);
3866 args = IPA_EDGE_REF (cs);
3867 for (i = 0; i < count; i++)
3869 struct ipa_jump_func *jump_func;
3870 tree val, t;
3872 val = dest_info->known_csts[i];
3873 if (!val)
3874 continue;
3876 if (i >= ipa_get_cs_argument_count (args))
3877 return false;
3878 jump_func = ipa_get_ith_jump_func (args, i);
3879 t = ipa_value_from_jfunc (caller_info, jump_func);
3880 if (!t || !values_equal_for_ipcp_p (val, t))
3881 return false;
3883 return true;
3886 /* Determine whether CS also brings all aggregate values that NODE is
3887 specialized for. */
3888 static bool
3889 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3890 struct cgraph_node *node)
3892 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3893 struct ipa_node_params *orig_node_info;
3894 struct ipa_agg_replacement_value *aggval;
3895 int i, ec, count;
3897 aggval = ipa_get_agg_replacements_for_node (node);
3898 if (!aggval)
3899 return true;
3901 count = ipa_get_param_count (IPA_NODE_REF (node));
3902 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3903 if (ec < count)
3904 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3905 if (aggval->index >= ec)
3906 return false;
3908 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3909 if (orig_caller_info->ipcp_orig_node)
3910 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3912 for (i = 0; i < count; i++)
3914 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
3915 struct ipcp_param_lattices *plats;
3916 bool interesting = false;
3917 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3918 if (aggval->index == i)
3920 interesting = true;
3921 break;
3923 if (!interesting)
3924 continue;
3926 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3927 if (plats->aggs_bottom)
3928 return false;
3930 values = intersect_aggregates_with_edge (cs, i, values);
3931 if (!values.exists ())
3932 return false;
3934 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3935 if (aggval->index == i)
3937 struct ipa_agg_jf_item *item;
3938 int j;
3939 bool found = false;
3940 FOR_EACH_VEC_ELT (values, j, item)
3941 if (item->value
3942 && item->offset == av->offset
3943 && values_equal_for_ipcp_p (item->value, av->value))
3945 found = true;
3946 break;
3948 if (!found)
3950 values.release ();
3951 return false;
3955 return true;
3958 /* Given an original NODE and a VAL for which we have already created a
3959 specialized clone, look whether there are incoming edges that still lead
3960 into the old node but now also bring the requested value and also conform to
3961 all other criteria such that they can be redirected the the special node.
3962 This function can therefore redirect the final edge in a SCC. */
3964 template <typename valtype>
3965 static void
3966 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
3968 ipcp_value_source<valtype> *src;
3969 gcov_type redirected_sum = 0;
3971 for (src = val->sources; src; src = src->next)
3973 struct cgraph_edge *cs = src->cs;
3974 while (cs)
3976 if (cgraph_edge_brings_value_p (cs, src, node)
3977 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3978 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
3980 if (dump_file)
3981 fprintf (dump_file, " - adding an extra caller %s/%i"
3982 " of %s/%i\n",
3983 xstrdup_for_dump (cs->caller->name ()),
3984 cs->caller->order,
3985 xstrdup_for_dump (val->spec_node->name ()),
3986 val->spec_node->order);
3988 cs->redirect_callee_duplicating_thunks (val->spec_node);
3989 val->spec_node->expand_all_artificial_thunks ();
3990 redirected_sum += cs->count;
3992 cs = get_next_cgraph_edge_clone (cs);
3996 if (redirected_sum)
3997 update_specialized_profile (val->spec_node, node, redirected_sum);
4000 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4002 static bool
4003 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4005 ipa_polymorphic_call_context *ctx;
4006 int i;
4008 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4009 if (!ctx->useless_p ())
4010 return true;
4011 return false;
4014 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4016 static vec<ipa_polymorphic_call_context>
4017 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4019 if (known_contexts_useful_p (known_contexts))
4020 return known_contexts.copy ();
4021 else
4022 return vNULL;
4025 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4026 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4028 static void
4029 modify_known_vectors_with_val (vec<tree> *known_csts,
4030 vec<ipa_polymorphic_call_context> *known_contexts,
4031 ipcp_value<tree> *val,
4032 int index)
4034 *known_csts = known_csts->copy ();
4035 *known_contexts = copy_useful_known_contexts (*known_contexts);
4036 (*known_csts)[index] = val->value;
4039 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4040 copy according to VAL and INDEX. */
4042 static void
4043 modify_known_vectors_with_val (vec<tree> *known_csts,
4044 vec<ipa_polymorphic_call_context> *known_contexts,
4045 ipcp_value<ipa_polymorphic_call_context> *val,
4046 int index)
4048 *known_csts = known_csts->copy ();
4049 *known_contexts = known_contexts->copy ();
4050 (*known_contexts)[index] = val->value;
4053 /* Return true if OFFSET indicates this was not an aggregate value or there is
4054 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4055 AGGVALS list. */
4057 DEBUG_FUNCTION bool
4058 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4059 int index, HOST_WIDE_INT offset, tree value)
4061 if (offset == -1)
4062 return true;
4064 while (aggvals)
4066 if (aggvals->index == index
4067 && aggvals->offset == offset
4068 && values_equal_for_ipcp_p (aggvals->value, value))
4069 return true;
4070 aggvals = aggvals->next;
4072 return false;
4075 /* Return true if offset is minus one because source of a polymorphic contect
4076 cannot be an aggregate value. */
4078 DEBUG_FUNCTION bool
4079 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4080 int , HOST_WIDE_INT offset,
4081 ipa_polymorphic_call_context)
4083 return offset == -1;
4086 /* Decide wheter to create a special version of NODE for value VAL of parameter
4087 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4088 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4089 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4091 template <typename valtype>
4092 static bool
4093 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4094 ipcp_value<valtype> *val, vec<tree> known_csts,
4095 vec<ipa_polymorphic_call_context> known_contexts)
4097 struct ipa_agg_replacement_value *aggvals;
4098 int freq_sum, caller_count;
4099 gcov_type count_sum;
4100 vec<cgraph_edge *> callers;
4102 if (val->spec_node)
4104 perhaps_add_new_callers (node, val);
4105 return false;
4107 else if (val->local_size_cost + overall_size > max_new_size)
4109 if (dump_file && (dump_flags & TDF_DETAILS))
4110 fprintf (dump_file, " Ignoring candidate value because "
4111 "max_new_size would be reached with %li.\n",
4112 val->local_size_cost + overall_size);
4113 return false;
4115 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4116 &caller_count))
4117 return false;
4119 if (dump_file && (dump_flags & TDF_DETAILS))
4121 fprintf (dump_file, " - considering value ");
4122 print_ipcp_constant_value (dump_file, val->value);
4123 fprintf (dump_file, " for ");
4124 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4125 if (offset != -1)
4126 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4127 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4130 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4131 freq_sum, count_sum,
4132 val->local_size_cost)
4133 && !good_cloning_opportunity_p (node,
4134 val->local_time_benefit
4135 + val->prop_time_benefit,
4136 freq_sum, count_sum,
4137 val->local_size_cost
4138 + val->prop_size_cost))
4139 return false;
4141 if (dump_file)
4142 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
4143 node->name (), node->order);
4145 callers = gather_edges_for_value (val, node, caller_count);
4146 if (offset == -1)
4147 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4148 else
4150 known_csts = known_csts.copy ();
4151 known_contexts = copy_useful_known_contexts (known_contexts);
4153 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4154 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4155 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4156 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4157 offset, val->value));
4158 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4159 aggvals, callers);
4160 overall_size += val->local_size_cost;
4162 /* TODO: If for some lattice there is only one other known value
4163 left, make a special node for it too. */
4165 return true;
4168 /* Decide whether and what specialized clones of NODE should be created. */
4170 static bool
4171 decide_whether_version_node (struct cgraph_node *node)
4173 struct ipa_node_params *info = IPA_NODE_REF (node);
4174 int i, count = ipa_get_param_count (info);
4175 vec<tree> known_csts;
4176 vec<ipa_polymorphic_call_context> known_contexts;
4177 vec<ipa_agg_jump_function> known_aggs = vNULL;
4178 bool ret = false;
4180 if (count == 0)
4181 return false;
4183 if (dump_file && (dump_flags & TDF_DETAILS))
4184 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4185 node->name (), node->order);
4187 gather_context_independent_values (info, &known_csts, &known_contexts,
4188 info->do_clone_for_all_contexts ? &known_aggs
4189 : NULL, NULL);
4191 for (i = 0; i < count ;i++)
4193 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4194 ipcp_lattice<tree> *lat = &plats->itself;
4195 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4197 if (!lat->bottom
4198 && !known_csts[i])
4200 ipcp_value<tree> *val;
4201 for (val = lat->values; val; val = val->next)
4202 ret |= decide_about_value (node, i, -1, val, known_csts,
4203 known_contexts);
4206 if (!plats->aggs_bottom)
4208 struct ipcp_agg_lattice *aglat;
4209 ipcp_value<tree> *val;
4210 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4211 if (!aglat->bottom && aglat->values
4212 /* If the following is false, the one value is in
4213 known_aggs. */
4214 && (plats->aggs_contain_variable
4215 || !aglat->is_single_const ()))
4216 for (val = aglat->values; val; val = val->next)
4217 ret |= decide_about_value (node, i, aglat->offset, val,
4218 known_csts, known_contexts);
4221 if (!ctxlat->bottom
4222 && known_contexts[i].useless_p ())
4224 ipcp_value<ipa_polymorphic_call_context> *val;
4225 for (val = ctxlat->values; val; val = val->next)
4226 ret |= decide_about_value (node, i, -1, val, known_csts,
4227 known_contexts);
4230 info = IPA_NODE_REF (node);
4233 if (info->do_clone_for_all_contexts)
4235 struct cgraph_node *clone;
4236 vec<cgraph_edge *> callers;
4238 if (dump_file)
4239 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4240 "for all known contexts.\n", node->name (),
4241 node->order);
4243 callers = node->collect_callers ();
4245 if (!known_contexts_useful_p (known_contexts))
4247 known_contexts.release ();
4248 known_contexts = vNULL;
4250 clone = create_specialized_node (node, known_csts, known_contexts,
4251 known_aggs_to_agg_replacement_list (known_aggs),
4252 callers);
4253 info = IPA_NODE_REF (node);
4254 info->do_clone_for_all_contexts = false;
4255 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4256 for (i = 0; i < count ; i++)
4257 vec_free (known_aggs[i].items);
4258 known_aggs.release ();
4259 ret = true;
4261 else
4263 known_csts.release ();
4264 known_contexts.release ();
4267 return ret;
4270 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4272 static void
4273 spread_undeadness (struct cgraph_node *node)
4275 struct cgraph_edge *cs;
4277 for (cs = node->callees; cs; cs = cs->next_callee)
4278 if (ipa_edge_within_scc (cs))
4280 struct cgraph_node *callee;
4281 struct ipa_node_params *info;
4283 callee = cs->callee->function_symbol (NULL);
4284 info = IPA_NODE_REF (callee);
4286 if (info->node_dead)
4288 info->node_dead = 0;
4289 spread_undeadness (callee);
4294 /* Return true if NODE has a caller from outside of its SCC that is not
4295 dead. Worker callback for cgraph_for_node_and_aliases. */
4297 static bool
4298 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4299 void *data ATTRIBUTE_UNUSED)
4301 struct cgraph_edge *cs;
4303 for (cs = node->callers; cs; cs = cs->next_caller)
4304 if (cs->caller->thunk.thunk_p
4305 && cs->caller->call_for_symbol_thunks_and_aliases
4306 (has_undead_caller_from_outside_scc_p, NULL, true))
4307 return true;
4308 else if (!ipa_edge_within_scc (cs)
4309 && !IPA_NODE_REF (cs->caller)->node_dead)
4310 return true;
4311 return false;
4315 /* Identify nodes within the same SCC as NODE which are no longer needed
4316 because of new clones and will be removed as unreachable. */
4318 static void
4319 identify_dead_nodes (struct cgraph_node *node)
4321 struct cgraph_node *v;
4322 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4323 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
4324 && !v->call_for_symbol_thunks_and_aliases
4325 (has_undead_caller_from_outside_scc_p, NULL, true))
4326 IPA_NODE_REF (v)->node_dead = 1;
4328 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4329 if (!IPA_NODE_REF (v)->node_dead)
4330 spread_undeadness (v);
4332 if (dump_file && (dump_flags & TDF_DETAILS))
4334 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4335 if (IPA_NODE_REF (v)->node_dead)
4336 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4337 v->name (), v->order);
4341 /* The decision stage. Iterate over the topological order of call graph nodes
4342 TOPO and make specialized clones if deemed beneficial. */
4344 static void
4345 ipcp_decision_stage (struct ipa_topo_info *topo)
4347 int i;
4349 if (dump_file)
4350 fprintf (dump_file, "\nIPA decision stage:\n\n");
4352 for (i = topo->nnodes - 1; i >= 0; i--)
4354 struct cgraph_node *node = topo->order[i];
4355 bool change = false, iterate = true;
4357 while (iterate)
4359 struct cgraph_node *v;
4360 iterate = false;
4361 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4362 if (v->has_gimple_body_p ()
4363 && ipcp_versionable_function_p (v))
4364 iterate |= decide_whether_version_node (v);
4366 change |= iterate;
4368 if (change)
4369 identify_dead_nodes (node);
4373 /* Look up all alignment information that we have discovered and copy it over
4374 to the transformation summary. */
4376 static void
4377 ipcp_store_alignment_results (void)
4379 cgraph_node *node;
4381 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4383 ipa_node_params *info = IPA_NODE_REF (node);
4384 bool dumped_sth = false;
4385 bool found_useful_result = false;
4387 if (!opt_for_fn (node->decl, flag_ipa_cp_alignment))
4389 if (dump_file)
4390 fprintf (dump_file, "Not considering %s for alignment discovery "
4391 "and propagate; -fipa-cp-alignment: disabled.\n",
4392 node->name ());
4393 continue;
4396 if (info->ipcp_orig_node)
4397 info = IPA_NODE_REF (info->ipcp_orig_node);
4399 unsigned count = ipa_get_param_count (info);
4400 for (unsigned i = 0; i < count ; i++)
4402 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4403 if (plats->alignment.known
4404 && plats->alignment.align > 0)
4406 found_useful_result = true;
4407 break;
4410 if (!found_useful_result)
4411 continue;
4413 ipcp_grow_transformations_if_necessary ();
4414 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4415 vec_safe_reserve_exact (ts->alignments, count);
4417 for (unsigned i = 0; i < count ; i++)
4419 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4421 if (plats->alignment.align == 0)
4422 plats->alignment.known = false;
4424 ts->alignments->quick_push (plats->alignment);
4425 if (!dump_file || !plats->alignment.known)
4426 continue;
4427 if (!dumped_sth)
4429 fprintf (dump_file, "Propagated alignment info for function %s/%i:\n",
4430 node->name (), node->order);
4431 dumped_sth = true;
4433 fprintf (dump_file, " param %i: align: %u, misalign: %u\n",
4434 i, plats->alignment.align, plats->alignment.misalign);
4439 /* The IPCP driver. */
4441 static unsigned int
4442 ipcp_driver (void)
4444 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4445 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4446 struct ipa_topo_info topo;
4448 ipa_check_create_node_params ();
4449 ipa_check_create_edge_args ();
4450 grow_edge_clone_vectors ();
4451 edge_duplication_hook_holder =
4452 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4453 edge_removal_hook_holder =
4454 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4456 if (dump_file)
4458 fprintf (dump_file, "\nIPA structures before propagation:\n");
4459 if (dump_flags & TDF_DETAILS)
4460 ipa_print_all_params (dump_file);
4461 ipa_print_all_jump_functions (dump_file);
4464 /* Topological sort. */
4465 build_toporder_info (&topo);
4466 /* Do the interprocedural propagation. */
4467 ipcp_propagate_stage (&topo);
4468 /* Decide what constant propagation and cloning should be performed. */
4469 ipcp_decision_stage (&topo);
4470 /* Store results of alignment propagation. */
4471 ipcp_store_alignment_results ();
4473 /* Free all IPCP structures. */
4474 free_toporder_info (&topo);
4475 next_edge_clone.release ();
4476 prev_edge_clone.release ();
4477 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4478 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
4479 ipa_free_all_structures_after_ipa_cp ();
4480 if (dump_file)
4481 fprintf (dump_file, "\nIPA constant propagation end\n");
4482 return 0;
4485 /* Initialization and computation of IPCP data structures. This is the initial
4486 intraprocedural analysis of functions, which gathers information to be
4487 propagated later on. */
4489 static void
4490 ipcp_generate_summary (void)
4492 struct cgraph_node *node;
4494 if (dump_file)
4495 fprintf (dump_file, "\nIPA constant propagation start:\n");
4496 ipa_register_cgraph_hooks ();
4498 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4500 node->local.versionable
4501 = tree_versionable_function_p (node->decl);
4502 ipa_analyze_node (node);
4506 /* Write ipcp summary for nodes in SET. */
4508 static void
4509 ipcp_write_summary (void)
4511 ipa_prop_write_jump_functions ();
4514 /* Read ipcp summary. */
4516 static void
4517 ipcp_read_summary (void)
4519 ipa_prop_read_jump_functions ();
4522 namespace {
4524 const pass_data pass_data_ipa_cp =
4526 IPA_PASS, /* type */
4527 "cp", /* name */
4528 OPTGROUP_NONE, /* optinfo_flags */
4529 TV_IPA_CONSTANT_PROP, /* tv_id */
4530 0, /* properties_required */
4531 0, /* properties_provided */
4532 0, /* properties_destroyed */
4533 0, /* todo_flags_start */
4534 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
4537 class pass_ipa_cp : public ipa_opt_pass_d
4539 public:
4540 pass_ipa_cp (gcc::context *ctxt)
4541 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
4542 ipcp_generate_summary, /* generate_summary */
4543 ipcp_write_summary, /* write_summary */
4544 ipcp_read_summary, /* read_summary */
4545 ipcp_write_transformation_summaries, /*
4546 write_optimization_summary */
4547 ipcp_read_transformation_summaries, /*
4548 read_optimization_summary */
4549 NULL, /* stmt_fixup */
4550 0, /* function_transform_todo_flags_start */
4551 ipcp_transform_function, /* function_transform */
4552 NULL) /* variable_transform */
4555 /* opt_pass methods: */
4556 virtual bool gate (function *)
4558 /* FIXME: We should remove the optimize check after we ensure we never run
4559 IPA passes when not optimizing. */
4560 return (flag_ipa_cp && optimize) || in_lto_p;
4563 virtual unsigned int execute (function *) { return ipcp_driver (); }
4565 }; // class pass_ipa_cp
4567 } // anon namespace
4569 ipa_opt_pass_d *
4570 make_pass_ipa_cp (gcc::context *ctxt)
4572 return new pass_ipa_cp (ctxt);
4575 /* Reset all state within ipa-cp.c so that we can rerun the compiler
4576 within the same process. For use by toplev::finalize. */
4578 void
4579 ipa_cp_c_finalize (void)
4581 max_count = 0;
4582 overall_size = 0;
4583 max_new_size = 0;