Merge from trunk @217148.
[official-gcc.git] / gcc / ipa-cp.c
blob786a7736df1368186595268473d6d2fe5e4ec9fd
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2014 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "tree.h"
107 #include "gimple-fold.h"
108 #include "gimple-expr.h"
109 #include "target.h"
110 #include "predict.h"
111 #include "basic-block.h"
112 #include "vec.h"
113 #include "hash-map.h"
114 #include "is-a.h"
115 #include "plugin-api.h"
116 #include "hashtab.h"
117 #include "hash-set.h"
118 #include "machmode.h"
119 #include "tm.h"
120 #include "hard-reg-set.h"
121 #include "input.h"
122 #include "function.h"
123 #include "ipa-ref.h"
124 #include "cgraph.h"
125 #include "alloc-pool.h"
126 #include "ipa-prop.h"
127 #include "bitmap.h"
128 #include "tree-pass.h"
129 #include "flags.h"
130 #include "diagnostic.h"
131 #include "tree-pretty-print.h"
132 #include "tree-inline.h"
133 #include "params.h"
134 #include "ipa-inline.h"
135 #include "ipa-utils.h"
137 struct ipcp_value;
139 /* Describes a particular source for an IPA-CP value. */
141 struct ipcp_value_source
143 /* Aggregate offset of the source, negative if the source is scalar value of
144 the argument itself. */
145 HOST_WIDE_INT offset;
146 /* The incoming edge that brought the value. */
147 struct cgraph_edge *cs;
148 /* If the jump function that resulted into his value was a pass-through or an
149 ancestor, this is the ipcp_value of the caller from which the described
150 value has been derived. Otherwise it is NULL. */
151 struct ipcp_value *val;
152 /* Next pointer in a linked list of sources of a value. */
153 struct ipcp_value_source *next;
154 /* If the jump function that resulted into his value was a pass-through or an
155 ancestor, this is the index of the parameter of the caller the jump
156 function references. */
157 int index;
160 /* Describes one particular value stored in struct ipcp_lattice. */
162 struct ipcp_value
164 /* The actual value for the given parameter. This is either an IPA invariant
165 or a TREE_BINFO describing a type that can be used for
166 devirtualization. */
167 tree value;
168 /* The list of sources from which this value originates. */
169 struct ipcp_value_source *sources;
170 /* Next pointers in a linked list of all values in a lattice. */
171 struct ipcp_value *next;
172 /* Next pointers in a linked list of values in a strongly connected component
173 of values. */
174 struct ipcp_value *scc_next;
175 /* Next pointers in a linked list of SCCs of values sorted topologically
176 according their sources. */
177 struct ipcp_value *topo_next;
178 /* A specialized node created for this value, NULL if none has been (so far)
179 created. */
180 struct cgraph_node *spec_node;
181 /* Depth first search number and low link for topological sorting of
182 values. */
183 int dfs, low_link;
184 /* Time benefit and size cost that specializing the function for this value
185 would bring about in this function alone. */
186 int local_time_benefit, local_size_cost;
187 /* Time benefit and size cost that specializing the function for this value
188 can bring about in it's callees (transitively). */
189 int prop_time_benefit, prop_size_cost;
190 /* True if this valye is currently on the topo-sort stack. */
191 bool on_stack;
194 /* Lattice describing potential values of a formal parameter of a function, or
195 a part of an aggreagate. TOP is represented by a lattice with zero values
196 and with contains_variable and bottom flags cleared. BOTTOM is represented
197 by a lattice with the bottom flag set. In that case, values and
198 contains_variable flag should be disregarded. */
200 struct ipcp_lattice
202 /* The list of known values and types in this lattice. Note that values are
203 not deallocated if a lattice is set to bottom because there may be value
204 sources referencing them. */
205 struct ipcp_value *values;
206 /* Number of known values and types in this lattice. */
207 int values_count;
208 /* The lattice contains a variable component (in addition to values). */
209 bool contains_variable;
210 /* The value of the lattice is bottom (i.e. variable and unusable for any
211 propagation). */
212 bool bottom;
215 /* Lattice with an offset to describe a part of an aggregate. */
217 struct ipcp_agg_lattice : public ipcp_lattice
219 /* Offset that is being described by this lattice. */
220 HOST_WIDE_INT offset;
221 /* Size so that we don't have to re-compute it every time we traverse the
222 list. Must correspond to TYPE_SIZE of all lat values. */
223 HOST_WIDE_INT size;
224 /* Next element of the linked list. */
225 struct ipcp_agg_lattice *next;
228 /* Structure containing lattices for a parameter itself and for pieces of
229 aggregates that are passed in the parameter or by a reference in a parameter
230 plus some other useful flags. */
232 struct ipcp_param_lattices
234 /* Lattice describing the value of the parameter itself. */
235 struct ipcp_lattice itself;
236 /* Lattices describing aggregate parts. */
237 struct ipcp_agg_lattice *aggs;
238 /* Number of aggregate lattices */
239 int aggs_count;
240 /* True if aggregate data were passed by reference (as opposed to by
241 value). */
242 bool aggs_by_ref;
243 /* All aggregate lattices contain a variable component (in addition to
244 values). */
245 bool aggs_contain_variable;
246 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
247 for any propagation). */
248 bool aggs_bottom;
250 /* There is a virtual call based on this parameter. */
251 bool virt_call;
254 /* Allocation pools for values and their sources in ipa-cp. */
256 alloc_pool ipcp_values_pool;
257 alloc_pool ipcp_sources_pool;
258 alloc_pool ipcp_agg_lattice_pool;
260 /* Maximal count found in program. */
262 static gcov_type max_count;
264 /* Original overall size of the program. */
266 static long overall_size, max_new_size;
268 /* Head of the linked list of topologically sorted values. */
270 static struct ipcp_value *values_topo;
272 /* Return the param lattices structure corresponding to the Ith formal
273 parameter of the function described by INFO. */
274 static inline struct ipcp_param_lattices *
275 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
277 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
278 gcc_checking_assert (!info->ipcp_orig_node);
279 gcc_checking_assert (info->lattices);
280 return &(info->lattices[i]);
283 /* Return the lattice corresponding to the scalar value of the Ith formal
284 parameter of the function described by INFO. */
285 static inline struct ipcp_lattice *
286 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
288 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
289 return &plats->itself;
292 /* Return whether LAT is a lattice with a single constant and without an
293 undefined value. */
295 static inline bool
296 ipa_lat_is_single_const (struct ipcp_lattice *lat)
298 if (lat->bottom
299 || lat->contains_variable
300 || lat->values_count != 1)
301 return false;
302 else
303 return true;
306 /* Print V which is extracted from a value in a lattice to F. */
308 static void
309 print_ipcp_constant_value (FILE * f, tree v)
311 if (TREE_CODE (v) == TREE_BINFO)
313 fprintf (f, "BINFO ");
314 print_generic_expr (f, BINFO_TYPE (v), 0);
316 else if (TREE_CODE (v) == ADDR_EXPR
317 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
319 fprintf (f, "& ");
320 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
322 else
323 print_generic_expr (f, v, 0);
326 /* Print a lattice LAT to F. */
328 static void
329 print_lattice (FILE * f, struct ipcp_lattice *lat,
330 bool dump_sources, bool dump_benefits)
332 struct ipcp_value *val;
333 bool prev = false;
335 if (lat->bottom)
337 fprintf (f, "BOTTOM\n");
338 return;
341 if (!lat->values_count && !lat->contains_variable)
343 fprintf (f, "TOP\n");
344 return;
347 if (lat->contains_variable)
349 fprintf (f, "VARIABLE");
350 prev = true;
351 if (dump_benefits)
352 fprintf (f, "\n");
355 for (val = lat->values; val; val = val->next)
357 if (dump_benefits && prev)
358 fprintf (f, " ");
359 else if (!dump_benefits && prev)
360 fprintf (f, ", ");
361 else
362 prev = true;
364 print_ipcp_constant_value (f, val->value);
366 if (dump_sources)
368 struct ipcp_value_source *s;
370 fprintf (f, " [from:");
371 for (s = val->sources; s; s = s->next)
372 fprintf (f, " %i(%i)", s->cs->caller->order,
373 s->cs->frequency);
374 fprintf (f, "]");
377 if (dump_benefits)
378 fprintf (f, " [loc_time: %i, loc_size: %i, "
379 "prop_time: %i, prop_size: %i]\n",
380 val->local_time_benefit, val->local_size_cost,
381 val->prop_time_benefit, val->prop_size_cost);
383 if (!dump_benefits)
384 fprintf (f, "\n");
387 /* Print all ipcp_lattices of all functions to F. */
389 static void
390 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
392 struct cgraph_node *node;
393 int i, count;
395 fprintf (f, "\nLattices:\n");
396 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
398 struct ipa_node_params *info;
400 info = IPA_NODE_REF (node);
401 fprintf (f, " Node: %s/%i:\n", node->name (),
402 node->order);
403 count = ipa_get_param_count (info);
404 for (i = 0; i < count; i++)
406 struct ipcp_agg_lattice *aglat;
407 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
408 fprintf (f, " param [%d]: ", i);
409 print_lattice (f, &plats->itself, dump_sources, dump_benefits);
411 if (plats->virt_call)
412 fprintf (f, " virt_call flag set\n");
414 if (plats->aggs_bottom)
416 fprintf (f, " AGGS BOTTOM\n");
417 continue;
419 if (plats->aggs_contain_variable)
420 fprintf (f, " AGGS VARIABLE\n");
421 for (aglat = plats->aggs; aglat; aglat = aglat->next)
423 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
424 plats->aggs_by_ref ? "ref " : "", aglat->offset);
425 print_lattice (f, aglat, dump_sources, dump_benefits);
431 /* Determine whether it is at all technically possible to create clones of NODE
432 and store this information in the ipa_node_params structure associated
433 with NODE. */
435 static void
436 determine_versionability (struct cgraph_node *node)
438 const char *reason = NULL;
440 /* There are a number of generic reasons functions cannot be versioned. We
441 also cannot remove parameters if there are type attributes such as fnspec
442 present. */
443 if (node->alias || node->thunk.thunk_p)
444 reason = "alias or thunk";
445 else if (!node->local.versionable)
446 reason = "not a tree_versionable_function";
447 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
448 reason = "insufficient body availability";
449 else if (!opt_for_fn (node->decl, optimize)
450 || !opt_for_fn (node->decl, flag_ipa_cp))
451 reason = "non-optimized function";
452 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
454 /* Ideally we should clone the SIMD clones themselves and create
455 vector copies of them, so IPA-cp and SIMD clones can happily
456 coexist, but that may not be worth the effort. */
457 reason = "function has SIMD clones";
459 /* Don't clone decls local to a comdat group; it breaks and for C++
460 decloned constructors, inlining is always better anyway. */
461 else if (node->comdat_local_p ())
462 reason = "comdat-local function";
464 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
465 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
466 node->name (), node->order, reason);
468 node->local.versionable = (reason == NULL);
471 /* Return true if it is at all technically possible to create clones of a
472 NODE. */
474 static bool
475 ipcp_versionable_function_p (struct cgraph_node *node)
477 return node->local.versionable;
480 /* Structure holding accumulated information about callers of a node. */
482 struct caller_statistics
484 gcov_type count_sum;
485 int n_calls, n_hot_calls, freq_sum;
488 /* Initialize fields of STAT to zeroes. */
490 static inline void
491 init_caller_stats (struct caller_statistics *stats)
493 stats->count_sum = 0;
494 stats->n_calls = 0;
495 stats->n_hot_calls = 0;
496 stats->freq_sum = 0;
499 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
500 non-thunk incoming edges to NODE. */
502 static bool
503 gather_caller_stats (struct cgraph_node *node, void *data)
505 struct caller_statistics *stats = (struct caller_statistics *) data;
506 struct cgraph_edge *cs;
508 for (cs = node->callers; cs; cs = cs->next_caller)
509 if (cs->caller->thunk.thunk_p)
510 cs->caller->call_for_symbol_thunks_and_aliases (gather_caller_stats,
511 stats, false);
512 else
514 stats->count_sum += cs->count;
515 stats->freq_sum += cs->frequency;
516 stats->n_calls++;
517 if (cs->maybe_hot_p ())
518 stats->n_hot_calls ++;
520 return false;
524 /* Return true if this NODE is viable candidate for cloning. */
526 static bool
527 ipcp_cloning_candidate_p (struct cgraph_node *node)
529 struct caller_statistics stats;
531 gcc_checking_assert (node->has_gimple_body_p ());
533 if (!flag_ipa_cp_clone)
535 if (dump_file)
536 fprintf (dump_file, "Not considering %s for cloning; "
537 "-fipa-cp-clone disabled.\n",
538 node->name ());
539 return false;
542 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
544 if (dump_file)
545 fprintf (dump_file, "Not considering %s for cloning; "
546 "optimizing it for size.\n",
547 node->name ());
548 return false;
551 init_caller_stats (&stats);
552 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
554 if (inline_summary (node)->self_size < stats.n_calls)
556 if (dump_file)
557 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
558 node->name ());
559 return true;
562 /* When profile is available and function is hot, propagate into it even if
563 calls seems cold; constant propagation can improve function's speed
564 significantly. */
565 if (max_count)
567 if (stats.count_sum > node->count * 90 / 100)
569 if (dump_file)
570 fprintf (dump_file, "Considering %s for cloning; "
571 "usually called directly.\n",
572 node->name ());
573 return true;
576 if (!stats.n_hot_calls)
578 if (dump_file)
579 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
580 node->name ());
581 return false;
583 if (dump_file)
584 fprintf (dump_file, "Considering %s for cloning.\n",
585 node->name ());
586 return true;
589 /* Arrays representing a topological ordering of call graph nodes and a stack
590 of noes used during constant propagation. */
592 struct ipa_topo_info
594 struct cgraph_node **order;
595 struct cgraph_node **stack;
596 int nnodes, stack_top;
599 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
601 static void
602 build_toporder_info (struct ipa_topo_info *topo)
604 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
605 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
607 topo->stack_top = 0;
608 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
611 /* Free information about strongly connected components and the arrays in
612 TOPO. */
614 static void
615 free_toporder_info (struct ipa_topo_info *topo)
617 ipa_free_postorder_info ();
618 free (topo->order);
619 free (topo->stack);
622 /* Add NODE to the stack in TOPO, unless it is already there. */
624 static inline void
625 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
627 struct ipa_node_params *info = IPA_NODE_REF (node);
628 if (info->node_enqueued)
629 return;
630 info->node_enqueued = 1;
631 topo->stack[topo->stack_top++] = node;
634 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
635 is empty. */
637 static struct cgraph_node *
638 pop_node_from_stack (struct ipa_topo_info *topo)
640 if (topo->stack_top)
642 struct cgraph_node *node;
643 topo->stack_top--;
644 node = topo->stack[topo->stack_top];
645 IPA_NODE_REF (node)->node_enqueued = 0;
646 return node;
648 else
649 return NULL;
652 /* Set lattice LAT to bottom and return true if it previously was not set as
653 such. */
655 static inline bool
656 set_lattice_to_bottom (struct ipcp_lattice *lat)
658 bool ret = !lat->bottom;
659 lat->bottom = true;
660 return ret;
663 /* Mark lattice as containing an unknown value and return true if it previously
664 was not marked as such. */
666 static inline bool
667 set_lattice_contains_variable (struct ipcp_lattice *lat)
669 bool ret = !lat->contains_variable;
670 lat->contains_variable = true;
671 return ret;
674 /* Set all aggegate lattices in PLATS to bottom and return true if they were
675 not previously set as such. */
677 static inline bool
678 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
680 bool ret = !plats->aggs_bottom;
681 plats->aggs_bottom = true;
682 return ret;
685 /* Mark all aggegate lattices in PLATS as containing an unknown value and
686 return true if they were not previously marked as such. */
688 static inline bool
689 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
691 bool ret = !plats->aggs_contain_variable;
692 plats->aggs_contain_variable = true;
693 return ret;
696 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
697 return true is any of them has not been marked as such so far. */
699 static inline bool
700 set_all_contains_variable (struct ipcp_param_lattices *plats)
702 bool ret = !plats->itself.contains_variable || !plats->aggs_contain_variable;
703 plats->itself.contains_variable = true;
704 plats->aggs_contain_variable = true;
705 return ret;
708 /* Initialize ipcp_lattices. */
710 static void
711 initialize_node_lattices (struct cgraph_node *node)
713 struct ipa_node_params *info = IPA_NODE_REF (node);
714 struct cgraph_edge *ie;
715 bool disable = false, variable = false;
716 int i;
718 gcc_checking_assert (node->has_gimple_body_p ());
719 if (!cgraph_local_p (node))
721 /* When cloning is allowed, we can assume that externally visible
722 functions are not called. We will compensate this by cloning
723 later. */
724 if (ipcp_versionable_function_p (node)
725 && ipcp_cloning_candidate_p (node))
726 variable = true;
727 else
728 disable = true;
731 if (disable || variable)
733 for (i = 0; i < ipa_get_param_count (info) ; i++)
735 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
736 if (disable)
738 set_lattice_to_bottom (&plats->itself);
739 set_agg_lats_to_bottom (plats);
741 else
742 set_all_contains_variable (plats);
744 if (dump_file && (dump_flags & TDF_DETAILS)
745 && !node->alias && !node->thunk.thunk_p)
746 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
747 node->name (), node->order,
748 disable ? "BOTTOM" : "VARIABLE");
751 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
752 if (ie->indirect_info->polymorphic
753 && ie->indirect_info->param_index >= 0)
755 gcc_checking_assert (ie->indirect_info->param_index >= 0);
756 ipa_get_parm_lattices (info,
757 ie->indirect_info->param_index)->virt_call = 1;
761 /* Return the result of a (possibly arithmetic) pass through jump function
762 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
763 determined or be considered an interprocedural invariant. */
765 static tree
766 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
768 tree restype, res;
770 if (TREE_CODE (input) == TREE_BINFO)
772 if (ipa_get_jf_pass_through_type_preserved (jfunc))
774 gcc_checking_assert (ipa_get_jf_pass_through_operation (jfunc)
775 == NOP_EXPR);
776 return input;
778 return NULL_TREE;
781 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
782 return input;
784 gcc_checking_assert (is_gimple_ip_invariant (input));
785 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
786 == tcc_comparison)
787 restype = boolean_type_node;
788 else
789 restype = TREE_TYPE (input);
790 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
791 input, ipa_get_jf_pass_through_operand (jfunc));
793 if (res && !is_gimple_ip_invariant (res))
794 return NULL_TREE;
796 return res;
799 /* Return the result of an ancestor jump function JFUNC on the constant value
800 INPUT. Return NULL_TREE if that cannot be determined. */
802 static tree
803 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
805 if (TREE_CODE (input) == TREE_BINFO)
807 if (!ipa_get_jf_ancestor_type_preserved (jfunc))
808 return NULL;
809 /* FIXME: At LTO we can't propagate to non-polymorphic type, because
810 we have no ODR equivalency on those. This should be fixed by
811 propagating on types rather than binfos that would make type
812 matching here unnecesary. */
813 if (in_lto_p
814 && (TREE_CODE (ipa_get_jf_ancestor_type (jfunc)) != RECORD_TYPE
815 || !TYPE_BINFO (ipa_get_jf_ancestor_type (jfunc))
816 || !BINFO_VTABLE (TYPE_BINFO (ipa_get_jf_ancestor_type (jfunc)))))
818 if (!ipa_get_jf_ancestor_offset (jfunc))
819 return input;
820 return NULL;
822 return get_binfo_at_offset (input,
823 ipa_get_jf_ancestor_offset (jfunc),
824 ipa_get_jf_ancestor_type (jfunc));
826 else if (TREE_CODE (input) == ADDR_EXPR)
828 tree t = TREE_OPERAND (input, 0);
829 t = build_ref_for_offset (EXPR_LOCATION (t), t,
830 ipa_get_jf_ancestor_offset (jfunc), false,
831 ipa_get_jf_ancestor_type (jfunc)
832 ? ipa_get_jf_ancestor_type (jfunc)
833 : ptr_type_node, NULL, false);
834 return build_fold_addr_expr (t);
836 else
837 return NULL_TREE;
840 /* Determine whether JFUNC evaluates to a known value (that is either a
841 constant or a binfo) and if so, return it. Otherwise return NULL. INFO
842 describes the caller node so that pass-through jump functions can be
843 evaluated. */
845 tree
846 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
848 if (jfunc->type == IPA_JF_CONST)
849 return ipa_get_jf_constant (jfunc);
850 else if (jfunc->type == IPA_JF_KNOWN_TYPE)
851 return ipa_binfo_from_known_type_jfunc (jfunc);
852 else if (jfunc->type == IPA_JF_PASS_THROUGH
853 || jfunc->type == IPA_JF_ANCESTOR)
855 tree input;
856 int idx;
858 if (jfunc->type == IPA_JF_PASS_THROUGH)
859 idx = ipa_get_jf_pass_through_formal_id (jfunc);
860 else
861 idx = ipa_get_jf_ancestor_formal_id (jfunc);
863 if (info->ipcp_orig_node)
864 input = info->known_vals[idx];
865 else
867 struct ipcp_lattice *lat;
869 if (!info->lattices)
871 gcc_checking_assert (!flag_ipa_cp);
872 return NULL_TREE;
874 lat = ipa_get_scalar_lat (info, idx);
875 if (!ipa_lat_is_single_const (lat))
876 return NULL_TREE;
877 input = lat->values->value;
880 if (!input)
881 return NULL_TREE;
883 if (jfunc->type == IPA_JF_PASS_THROUGH)
884 return ipa_get_jf_pass_through_result (jfunc, input);
885 else
886 return ipa_get_jf_ancestor_result (jfunc, input);
888 else
889 return NULL_TREE;
893 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
894 bottom, not containing a variable component and without any known value at
895 the same time. */
897 DEBUG_FUNCTION void
898 ipcp_verify_propagated_values (void)
900 struct cgraph_node *node;
902 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
904 struct ipa_node_params *info = IPA_NODE_REF (node);
905 int i, count = ipa_get_param_count (info);
907 for (i = 0; i < count; i++)
909 struct ipcp_lattice *lat = ipa_get_scalar_lat (info, i);
911 if (!lat->bottom
912 && !lat->contains_variable
913 && lat->values_count == 0)
915 if (dump_file)
917 symtab_node::dump_table (dump_file);
918 fprintf (dump_file, "\nIPA lattices after constant "
919 "propagation, before gcc_unreachable:\n");
920 print_all_lattices (dump_file, true, false);
923 gcc_unreachable ();
929 /* Return true iff X and Y should be considered equal values by IPA-CP. */
931 static bool
932 values_equal_for_ipcp_p (tree x, tree y)
934 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
936 if (x == y)
937 return true;
939 if (TREE_CODE (x) == TREE_BINFO || TREE_CODE (y) == TREE_BINFO)
940 return false;
942 if (TREE_CODE (x) == ADDR_EXPR
943 && TREE_CODE (y) == ADDR_EXPR
944 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
945 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
946 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
947 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
948 else
949 return operand_equal_p (x, y, 0);
952 /* Add a new value source to VAL, marking that a value comes from edge CS and
953 (if the underlying jump function is a pass-through or an ancestor one) from
954 a caller value SRC_VAL of a caller parameter described by SRC_INDEX. OFFSET
955 is negative if the source was the scalar value of the parameter itself or
956 the offset within an aggregate. */
958 static void
959 add_value_source (struct ipcp_value *val, struct cgraph_edge *cs,
960 struct ipcp_value *src_val, int src_idx, HOST_WIDE_INT offset)
962 struct ipcp_value_source *src;
964 src = (struct ipcp_value_source *) pool_alloc (ipcp_sources_pool);
965 src->offset = offset;
966 src->cs = cs;
967 src->val = src_val;
968 src->index = src_idx;
970 src->next = val->sources;
971 val->sources = src;
974 /* Try to add NEWVAL to LAT, potentially creating a new struct ipcp_value for
975 it. CS, SRC_VAL SRC_INDEX and OFFSET are meant for add_value_source and
976 have the same meaning. */
978 static bool
979 add_value_to_lattice (struct ipcp_lattice *lat, tree newval,
980 struct cgraph_edge *cs, struct ipcp_value *src_val,
981 int src_idx, HOST_WIDE_INT offset)
983 struct ipcp_value *val;
985 if (lat->bottom)
986 return false;
988 for (val = lat->values; val; val = val->next)
989 if (values_equal_for_ipcp_p (val->value, newval))
991 if (ipa_edge_within_scc (cs))
993 struct ipcp_value_source *s;
994 for (s = val->sources; s ; s = s->next)
995 if (s->cs == cs)
996 break;
997 if (s)
998 return false;
1001 add_value_source (val, cs, src_val, src_idx, offset);
1002 return false;
1005 if (lat->values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1007 /* We can only free sources, not the values themselves, because sources
1008 of other values in this this SCC might point to them. */
1009 for (val = lat->values; val; val = val->next)
1011 while (val->sources)
1013 struct ipcp_value_source *src = val->sources;
1014 val->sources = src->next;
1015 pool_free (ipcp_sources_pool, src);
1019 lat->values = NULL;
1020 return set_lattice_to_bottom (lat);
1023 lat->values_count++;
1024 val = (struct ipcp_value *) pool_alloc (ipcp_values_pool);
1025 memset (val, 0, sizeof (*val));
1027 add_value_source (val, cs, src_val, src_idx, offset);
1028 val->value = newval;
1029 val->next = lat->values;
1030 lat->values = val;
1031 return true;
1034 /* Like above but passes a special value of offset to distinguish that the
1035 origin is the scalar value of the parameter rather than a part of an
1036 aggregate. */
1038 static inline bool
1039 add_scalar_value_to_lattice (struct ipcp_lattice *lat, tree newval,
1040 struct cgraph_edge *cs,
1041 struct ipcp_value *src_val, int src_idx)
1043 return add_value_to_lattice (lat, newval, cs, src_val, src_idx, -1);
1046 /* Propagate values through a pass-through jump function JFUNC associated with
1047 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1048 is the index of the source parameter. */
1050 static bool
1051 propagate_vals_accross_pass_through (struct cgraph_edge *cs,
1052 struct ipa_jump_func *jfunc,
1053 struct ipcp_lattice *src_lat,
1054 struct ipcp_lattice *dest_lat,
1055 int src_idx)
1057 struct ipcp_value *src_val;
1058 bool ret = false;
1060 /* Do not create new values when propagating within an SCC because if there
1061 are arithmetic functions with circular dependencies, there is infinite
1062 number of them and we would just make lattices bottom. */
1063 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1064 && ipa_edge_within_scc (cs))
1065 ret = set_lattice_contains_variable (dest_lat);
1066 else
1067 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1069 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1071 if (cstval)
1072 ret |= add_scalar_value_to_lattice (dest_lat, cstval, cs, src_val,
1073 src_idx);
1074 else
1075 ret |= set_lattice_contains_variable (dest_lat);
1078 return ret;
1081 /* Propagate values through an ancestor jump function JFUNC associated with
1082 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1083 is the index of the source parameter. */
1085 static bool
1086 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1087 struct ipa_jump_func *jfunc,
1088 struct ipcp_lattice *src_lat,
1089 struct ipcp_lattice *dest_lat,
1090 int src_idx)
1092 struct ipcp_value *src_val;
1093 bool ret = false;
1095 if (ipa_edge_within_scc (cs))
1096 return set_lattice_contains_variable (dest_lat);
1098 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1100 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1102 if (t)
1103 ret |= add_scalar_value_to_lattice (dest_lat, t, cs, src_val, src_idx);
1104 else
1105 ret |= set_lattice_contains_variable (dest_lat);
1108 return ret;
1111 /* Propagate scalar values across jump function JFUNC that is associated with
1112 edge CS and put the values into DEST_LAT. */
1114 static bool
1115 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1116 struct ipa_jump_func *jfunc,
1117 struct ipcp_lattice *dest_lat)
1119 if (dest_lat->bottom)
1120 return false;
1122 if (jfunc->type == IPA_JF_CONST
1123 || jfunc->type == IPA_JF_KNOWN_TYPE)
1125 tree val;
1127 if (jfunc->type == IPA_JF_KNOWN_TYPE)
1129 val = ipa_binfo_from_known_type_jfunc (jfunc);
1130 if (!val)
1131 return set_lattice_contains_variable (dest_lat);
1133 else
1134 val = ipa_get_jf_constant (jfunc);
1135 return add_scalar_value_to_lattice (dest_lat, val, cs, NULL, 0);
1137 else if (jfunc->type == IPA_JF_PASS_THROUGH
1138 || jfunc->type == IPA_JF_ANCESTOR)
1140 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1141 struct ipcp_lattice *src_lat;
1142 int src_idx;
1143 bool ret;
1145 if (jfunc->type == IPA_JF_PASS_THROUGH)
1146 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1147 else
1148 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1150 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1151 if (src_lat->bottom)
1152 return set_lattice_contains_variable (dest_lat);
1154 /* If we would need to clone the caller and cannot, do not propagate. */
1155 if (!ipcp_versionable_function_p (cs->caller)
1156 && (src_lat->contains_variable
1157 || (src_lat->values_count > 1)))
1158 return set_lattice_contains_variable (dest_lat);
1160 if (jfunc->type == IPA_JF_PASS_THROUGH)
1161 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1162 dest_lat, src_idx);
1163 else
1164 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1165 src_idx);
1167 if (src_lat->contains_variable)
1168 ret |= set_lattice_contains_variable (dest_lat);
1170 return ret;
1173 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1174 use it for indirect inlining), we should propagate them too. */
1175 return set_lattice_contains_variable (dest_lat);
1178 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1179 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1180 other cases, return false). If there are no aggregate items, set
1181 aggs_by_ref to NEW_AGGS_BY_REF. */
1183 static bool
1184 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1185 bool new_aggs_by_ref)
1187 if (dest_plats->aggs)
1189 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1191 set_agg_lats_to_bottom (dest_plats);
1192 return true;
1195 else
1196 dest_plats->aggs_by_ref = new_aggs_by_ref;
1197 return false;
1200 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1201 already existing lattice for the given OFFSET and SIZE, marking all skipped
1202 lattices as containing variable and checking for overlaps. If there is no
1203 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1204 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1205 unless there are too many already. If there are two many, return false. If
1206 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1207 skipped lattices were newly marked as containing variable, set *CHANGE to
1208 true. */
1210 static bool
1211 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1212 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1213 struct ipcp_agg_lattice ***aglat,
1214 bool pre_existing, bool *change)
1216 gcc_checking_assert (offset >= 0);
1218 while (**aglat && (**aglat)->offset < offset)
1220 if ((**aglat)->offset + (**aglat)->size > offset)
1222 set_agg_lats_to_bottom (dest_plats);
1223 return false;
1225 *change |= set_lattice_contains_variable (**aglat);
1226 *aglat = &(**aglat)->next;
1229 if (**aglat && (**aglat)->offset == offset)
1231 if ((**aglat)->size != val_size
1232 || ((**aglat)->next
1233 && (**aglat)->next->offset < offset + val_size))
1235 set_agg_lats_to_bottom (dest_plats);
1236 return false;
1238 gcc_checking_assert (!(**aglat)->next
1239 || (**aglat)->next->offset >= offset + val_size);
1240 return true;
1242 else
1244 struct ipcp_agg_lattice *new_al;
1246 if (**aglat && (**aglat)->offset < offset + val_size)
1248 set_agg_lats_to_bottom (dest_plats);
1249 return false;
1251 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1252 return false;
1253 dest_plats->aggs_count++;
1254 new_al = (struct ipcp_agg_lattice *) pool_alloc (ipcp_agg_lattice_pool);
1255 memset (new_al, 0, sizeof (*new_al));
1257 new_al->offset = offset;
1258 new_al->size = val_size;
1259 new_al->contains_variable = pre_existing;
1261 new_al->next = **aglat;
1262 **aglat = new_al;
1263 return true;
1267 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1268 containing an unknown value. */
1270 static bool
1271 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1273 bool ret = false;
1274 while (aglat)
1276 ret |= set_lattice_contains_variable (aglat);
1277 aglat = aglat->next;
1279 return ret;
1282 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1283 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1284 parameter used for lattice value sources. Return true if DEST_PLATS changed
1285 in any way. */
1287 static bool
1288 merge_aggregate_lattices (struct cgraph_edge *cs,
1289 struct ipcp_param_lattices *dest_plats,
1290 struct ipcp_param_lattices *src_plats,
1291 int src_idx, HOST_WIDE_INT offset_delta)
1293 bool pre_existing = dest_plats->aggs != NULL;
1294 struct ipcp_agg_lattice **dst_aglat;
1295 bool ret = false;
1297 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1298 return true;
1299 if (src_plats->aggs_bottom)
1300 return set_agg_lats_contain_variable (dest_plats);
1301 if (src_plats->aggs_contain_variable)
1302 ret |= set_agg_lats_contain_variable (dest_plats);
1303 dst_aglat = &dest_plats->aggs;
1305 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1306 src_aglat;
1307 src_aglat = src_aglat->next)
1309 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1311 if (new_offset < 0)
1312 continue;
1313 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1314 &dst_aglat, pre_existing, &ret))
1316 struct ipcp_agg_lattice *new_al = *dst_aglat;
1318 dst_aglat = &(*dst_aglat)->next;
1319 if (src_aglat->bottom)
1321 ret |= set_lattice_contains_variable (new_al);
1322 continue;
1324 if (src_aglat->contains_variable)
1325 ret |= set_lattice_contains_variable (new_al);
1326 for (struct ipcp_value *val = src_aglat->values;
1327 val;
1328 val = val->next)
1329 ret |= add_value_to_lattice (new_al, val->value, cs, val, src_idx,
1330 src_aglat->offset);
1332 else if (dest_plats->aggs_bottom)
1333 return true;
1335 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1336 return ret;
1339 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1340 pass-through JFUNC and if so, whether it has conform and conforms to the
1341 rules about propagating values passed by reference. */
1343 static bool
1344 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1345 struct ipa_jump_func *jfunc)
1347 return src_plats->aggs
1348 && (!src_plats->aggs_by_ref
1349 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1352 /* Propagate scalar values across jump function JFUNC that is associated with
1353 edge CS and put the values into DEST_LAT. */
1355 static bool
1356 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1357 struct ipa_jump_func *jfunc,
1358 struct ipcp_param_lattices *dest_plats)
1360 bool ret = false;
1362 if (dest_plats->aggs_bottom)
1363 return false;
1365 if (jfunc->type == IPA_JF_PASS_THROUGH
1366 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1368 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1369 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1370 struct ipcp_param_lattices *src_plats;
1372 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1373 if (agg_pass_through_permissible_p (src_plats, jfunc))
1375 /* Currently we do not produce clobber aggregate jump
1376 functions, replace with merging when we do. */
1377 gcc_assert (!jfunc->agg.items);
1378 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1379 src_idx, 0);
1381 else
1382 ret |= set_agg_lats_contain_variable (dest_plats);
1384 else if (jfunc->type == IPA_JF_ANCESTOR
1385 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1387 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1388 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1389 struct ipcp_param_lattices *src_plats;
1391 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1392 if (src_plats->aggs && src_plats->aggs_by_ref)
1394 /* Currently we do not produce clobber aggregate jump
1395 functions, replace with merging when we do. */
1396 gcc_assert (!jfunc->agg.items);
1397 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1398 ipa_get_jf_ancestor_offset (jfunc));
1400 else if (!src_plats->aggs_by_ref)
1401 ret |= set_agg_lats_to_bottom (dest_plats);
1402 else
1403 ret |= set_agg_lats_contain_variable (dest_plats);
1405 else if (jfunc->agg.items)
1407 bool pre_existing = dest_plats->aggs != NULL;
1408 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1409 struct ipa_agg_jf_item *item;
1410 int i;
1412 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1413 return true;
1415 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
1417 HOST_WIDE_INT val_size;
1419 if (item->offset < 0)
1420 continue;
1421 gcc_checking_assert (is_gimple_ip_invariant (item->value));
1422 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
1424 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1425 &aglat, pre_existing, &ret))
1427 ret |= add_value_to_lattice (*aglat, item->value, cs, NULL, 0, 0);
1428 aglat = &(*aglat)->next;
1430 else if (dest_plats->aggs_bottom)
1431 return true;
1434 ret |= set_chain_of_aglats_contains_variable (*aglat);
1436 else
1437 ret |= set_agg_lats_contain_variable (dest_plats);
1439 return ret;
1442 /* Propagate constants from the caller to the callee of CS. INFO describes the
1443 caller. */
1445 static bool
1446 propagate_constants_accross_call (struct cgraph_edge *cs)
1448 struct ipa_node_params *callee_info;
1449 enum availability availability;
1450 struct cgraph_node *callee, *alias_or_thunk;
1451 struct ipa_edge_args *args;
1452 bool ret = false;
1453 int i, args_count, parms_count;
1455 callee = cs->callee->function_symbol (&availability);
1456 if (!callee->definition)
1457 return false;
1458 gcc_checking_assert (callee->has_gimple_body_p ());
1459 callee_info = IPA_NODE_REF (callee);
1461 args = IPA_EDGE_REF (cs);
1462 args_count = ipa_get_cs_argument_count (args);
1463 parms_count = ipa_get_param_count (callee_info);
1464 if (parms_count == 0)
1465 return false;
1467 /* No propagation through instrumentation thunks is available yet.
1468 It should be possible with proper mapping of call args and
1469 instrumented callee params in the propagation loop below. But
1470 this case mostly occurs when legacy code calls instrumented code
1471 and it is not a primary target for optimizations.
1472 We detect instrumentation thunks in aliases and thunks chain by
1473 checking instrumentation_clone flag for chain source and target.
1474 Going through instrumentation thunks we always have it changed
1475 from 0 to 1 and all other nodes do not change it. */
1476 if (!cs->callee->instrumentation_clone
1477 && callee->instrumentation_clone)
1479 for (i = 0; i < parms_count; i++)
1480 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1481 i));
1482 return ret;
1485 /* If this call goes through a thunk we must not propagate to the first (0th)
1486 parameter. However, we might need to uncover a thunk from below a series
1487 of aliases first. */
1488 alias_or_thunk = cs->callee;
1489 while (alias_or_thunk->alias)
1490 alias_or_thunk = alias_or_thunk->get_alias_target ();
1491 if (alias_or_thunk->thunk.thunk_p)
1493 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1494 0));
1495 i = 1;
1497 else
1498 i = 0;
1500 for (; (i < args_count) && (i < parms_count); i++)
1502 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
1503 struct ipcp_param_lattices *dest_plats;
1505 dest_plats = ipa_get_parm_lattices (callee_info, i);
1506 if (availability == AVAIL_INTERPOSABLE)
1507 ret |= set_all_contains_variable (dest_plats);
1508 else
1510 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1511 &dest_plats->itself);
1512 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1513 dest_plats);
1516 for (; i < parms_count; i++)
1517 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
1519 return ret;
1522 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1523 (which can contain both constants and binfos), KNOWN_BINFOS, KNOWN_AGGS or
1524 AGG_REPS return the destination. The latter three can be NULL. If AGG_REPS
1525 is not NULL, KNOWN_AGGS is ignored. */
1527 static tree
1528 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
1529 vec<tree> known_vals,
1530 vec<tree> known_binfos,
1531 vec<ipa_agg_jump_function_p> known_aggs,
1532 struct ipa_agg_replacement_value *agg_reps)
1534 int param_index = ie->indirect_info->param_index;
1535 HOST_WIDE_INT token, anc_offset;
1536 tree otr_type;
1537 tree t;
1538 tree target = NULL;
1540 if (param_index == -1
1541 || known_vals.length () <= (unsigned int) param_index)
1542 return NULL_TREE;
1544 if (!ie->indirect_info->polymorphic)
1546 tree t;
1548 if (ie->indirect_info->agg_contents)
1550 if (agg_reps)
1552 t = NULL;
1553 while (agg_reps)
1555 if (agg_reps->index == param_index
1556 && agg_reps->offset == ie->indirect_info->offset
1557 && agg_reps->by_ref == ie->indirect_info->by_ref)
1559 t = agg_reps->value;
1560 break;
1562 agg_reps = agg_reps->next;
1565 else if (known_aggs.length () > (unsigned int) param_index)
1567 struct ipa_agg_jump_function *agg;
1568 agg = known_aggs[param_index];
1569 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1570 ie->indirect_info->by_ref);
1572 else
1573 t = NULL;
1575 else
1576 t = known_vals[param_index];
1578 if (t &&
1579 TREE_CODE (t) == ADDR_EXPR
1580 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
1581 return TREE_OPERAND (t, 0);
1582 else
1583 return NULL_TREE;
1586 if (!flag_devirtualize)
1587 return NULL_TREE;
1589 gcc_assert (!ie->indirect_info->agg_contents);
1590 token = ie->indirect_info->otr_token;
1591 anc_offset = ie->indirect_info->offset;
1592 otr_type = ie->indirect_info->otr_type;
1594 t = NULL;
1596 /* Try to work out value of virtual table pointer value in replacemnets. */
1597 if (!t && agg_reps && !ie->indirect_info->by_ref
1598 && !ie->indirect_info->vptr_changed)
1600 while (agg_reps)
1602 if (agg_reps->index == param_index
1603 && agg_reps->offset == ie->indirect_info->offset
1604 && agg_reps->by_ref)
1606 t = agg_reps->value;
1607 break;
1609 agg_reps = agg_reps->next;
1613 /* Try to work out value of virtual table pointer value in known
1614 aggregate values. */
1615 if (!t && known_aggs.length () > (unsigned int) param_index
1616 && !ie->indirect_info->by_ref
1617 && !ie->indirect_info->vptr_changed)
1619 struct ipa_agg_jump_function *agg;
1620 agg = known_aggs[param_index];
1621 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
1622 true);
1625 /* If we found the virtual table pointer, lookup the target. */
1626 if (t)
1628 tree vtable;
1629 unsigned HOST_WIDE_INT offset;
1630 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
1632 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
1633 vtable, offset);
1634 if (target)
1636 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1637 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1638 || !possible_polymorphic_call_target_p
1639 (ie, cgraph_node::get (target)))
1640 target = ipa_impossible_devirt_target (ie, target);
1641 return target;
1646 /* Did we work out BINFO via type propagation? */
1647 if (!t && known_binfos.length () > (unsigned int) param_index)
1648 t = known_binfos[param_index];
1649 /* Or do we know the constant value of pointer? */
1650 if (!t)
1651 t = known_vals[param_index];
1652 if (!t)
1653 return NULL_TREE;
1655 if (TREE_CODE (t) != TREE_BINFO)
1657 ipa_polymorphic_call_context context (t, ie->indirect_info->otr_type,
1658 anc_offset);
1659 vec <cgraph_node *>targets;
1660 bool final;
1662 targets = possible_polymorphic_call_targets
1663 (ie->indirect_info->otr_type,
1664 ie->indirect_info->otr_token,
1665 context, &final);
1666 if (!final || targets.length () > 1)
1667 return NULL_TREE;
1668 if (targets.length () == 1)
1669 target = targets[0]->decl;
1670 else
1671 target = ipa_impossible_devirt_target (ie, NULL_TREE);
1673 else
1675 tree binfo;
1677 binfo = get_binfo_at_offset (t, anc_offset, otr_type);
1678 if (!binfo)
1679 return NULL_TREE;
1680 target = gimple_get_virt_method_for_binfo (token, binfo);
1683 if (target && !possible_polymorphic_call_target_p (ie,
1684 cgraph_node::get (target)))
1685 target = ipa_impossible_devirt_target (ie, target);
1687 return target;
1691 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1692 (which can contain both constants and binfos), KNOWN_BINFOS (which can be
1693 NULL) or KNOWN_AGGS (which also can be NULL) return the destination. */
1695 tree
1696 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
1697 vec<tree> known_vals,
1698 vec<tree> known_binfos,
1699 vec<ipa_agg_jump_function_p> known_aggs)
1701 return ipa_get_indirect_edge_target_1 (ie, known_vals, known_binfos,
1702 known_aggs, NULL);
1705 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
1706 and KNOWN_BINFOS. */
1708 static int
1709 devirtualization_time_bonus (struct cgraph_node *node,
1710 vec<tree> known_csts,
1711 vec<tree> known_binfos,
1712 vec<ipa_agg_jump_function_p> known_aggs)
1714 struct cgraph_edge *ie;
1715 int res = 0;
1717 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1719 struct cgraph_node *callee;
1720 struct inline_summary *isummary;
1721 enum availability avail;
1722 tree target;
1724 target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos,
1725 known_aggs);
1726 if (!target)
1727 continue;
1729 /* Only bare minimum benefit for clearly un-inlineable targets. */
1730 res += 1;
1731 callee = cgraph_node::get (target);
1732 if (!callee || !callee->definition)
1733 continue;
1734 callee = callee->function_symbol (&avail);
1735 if (avail < AVAIL_AVAILABLE)
1736 continue;
1737 isummary = inline_summary (callee);
1738 if (!isummary->inlinable)
1739 continue;
1741 /* FIXME: The values below need re-considering and perhaps also
1742 integrating into the cost metrics, at lest in some very basic way. */
1743 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
1744 res += 31;
1745 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
1746 res += 15;
1747 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
1748 || DECL_DECLARED_INLINE_P (callee->decl))
1749 res += 7;
1752 return res;
1755 /* Return time bonus incurred because of HINTS. */
1757 static int
1758 hint_time_bonus (inline_hints hints)
1760 int result = 0;
1761 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
1762 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
1763 if (hints & INLINE_HINT_array_index)
1764 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
1765 return result;
1768 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
1769 and SIZE_COST and with the sum of frequencies of incoming edges to the
1770 potential new clone in FREQUENCIES. */
1772 static bool
1773 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
1774 int freq_sum, gcov_type count_sum, int size_cost)
1776 if (time_benefit == 0
1777 || !flag_ipa_cp_clone
1778 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
1779 return false;
1781 gcc_assert (size_cost > 0);
1783 if (max_count)
1785 int factor = (count_sum * 1000) / max_count;
1786 int64_t evaluation = (((int64_t) time_benefit * factor)
1787 / size_cost);
1789 if (dump_file && (dump_flags & TDF_DETAILS))
1790 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
1791 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
1792 ") -> evaluation: " "%"PRId64
1793 ", threshold: %i\n",
1794 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
1795 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
1797 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
1799 else
1801 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
1802 / size_cost);
1804 if (dump_file && (dump_flags & TDF_DETAILS))
1805 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
1806 "size: %i, freq_sum: %i) -> evaluation: "
1807 "%"PRId64 ", threshold: %i\n",
1808 time_benefit, size_cost, freq_sum, evaluation,
1809 PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
1811 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
1815 /* Return all context independent values from aggregate lattices in PLATS in a
1816 vector. Return NULL if there are none. */
1818 static vec<ipa_agg_jf_item, va_gc> *
1819 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
1821 vec<ipa_agg_jf_item, va_gc> *res = NULL;
1823 if (plats->aggs_bottom
1824 || plats->aggs_contain_variable
1825 || plats->aggs_count == 0)
1826 return NULL;
1828 for (struct ipcp_agg_lattice *aglat = plats->aggs;
1829 aglat;
1830 aglat = aglat->next)
1831 if (ipa_lat_is_single_const (aglat))
1833 struct ipa_agg_jf_item item;
1834 item.offset = aglat->offset;
1835 item.value = aglat->values->value;
1836 vec_safe_push (res, item);
1838 return res;
1841 /* Allocate KNOWN_CSTS, KNOWN_BINFOS and, if non-NULL, KNOWN_AGGS and populate
1842 them with values of parameters that are known independent of the context.
1843 INFO describes the function. If REMOVABLE_PARAMS_COST is non-NULL, the
1844 movement cost of all removable parameters will be stored in it. */
1846 static bool
1847 gather_context_independent_values (struct ipa_node_params *info,
1848 vec<tree> *known_csts,
1849 vec<tree> *known_binfos,
1850 vec<ipa_agg_jump_function> *known_aggs,
1851 int *removable_params_cost)
1853 int i, count = ipa_get_param_count (info);
1854 bool ret = false;
1856 known_csts->create (0);
1857 known_binfos->create (0);
1858 known_csts->safe_grow_cleared (count);
1859 known_binfos->safe_grow_cleared (count);
1860 if (known_aggs)
1862 known_aggs->create (0);
1863 known_aggs->safe_grow_cleared (count);
1866 if (removable_params_cost)
1867 *removable_params_cost = 0;
1869 for (i = 0; i < count ; i++)
1871 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1872 struct ipcp_lattice *lat = &plats->itself;
1874 if (ipa_lat_is_single_const (lat))
1876 struct ipcp_value *val = lat->values;
1877 if (TREE_CODE (val->value) != TREE_BINFO)
1879 (*known_csts)[i] = val->value;
1880 if (removable_params_cost)
1881 *removable_params_cost
1882 += estimate_move_cost (TREE_TYPE (val->value), false);
1883 ret = true;
1885 else if (plats->virt_call)
1887 (*known_binfos)[i] = val->value;
1888 ret = true;
1890 else if (removable_params_cost
1891 && !ipa_is_param_used (info, i))
1892 *removable_params_cost += ipa_get_param_move_cost (info, i);
1894 else if (removable_params_cost
1895 && !ipa_is_param_used (info, i))
1896 *removable_params_cost
1897 += ipa_get_param_move_cost (info, i);
1899 if (known_aggs)
1901 vec<ipa_agg_jf_item, va_gc> *agg_items;
1902 struct ipa_agg_jump_function *ajf;
1904 agg_items = context_independent_aggregate_values (plats);
1905 ajf = &(*known_aggs)[i];
1906 ajf->items = agg_items;
1907 ajf->by_ref = plats->aggs_by_ref;
1908 ret |= agg_items != NULL;
1912 return ret;
1915 /* The current interface in ipa-inline-analysis requires a pointer vector.
1916 Create it.
1918 FIXME: That interface should be re-worked, this is slightly silly. Still,
1919 I'd like to discuss how to change it first and this demonstrates the
1920 issue. */
1922 static vec<ipa_agg_jump_function_p>
1923 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
1925 vec<ipa_agg_jump_function_p> ret;
1926 struct ipa_agg_jump_function *ajf;
1927 int i;
1929 ret.create (known_aggs.length ());
1930 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
1931 ret.quick_push (ajf);
1932 return ret;
1935 /* Iterate over known values of parameters of NODE and estimate the local
1936 effects in terms of time and size they have. */
1938 static void
1939 estimate_local_effects (struct cgraph_node *node)
1941 struct ipa_node_params *info = IPA_NODE_REF (node);
1942 int i, count = ipa_get_param_count (info);
1943 vec<tree> known_csts, known_binfos;
1944 vec<ipa_agg_jump_function> known_aggs;
1945 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
1946 bool always_const;
1947 int base_time = inline_summary (node)->time;
1948 int removable_params_cost;
1950 if (!count || !ipcp_versionable_function_p (node))
1951 return;
1953 if (dump_file && (dump_flags & TDF_DETAILS))
1954 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
1955 node->name (), node->order, base_time);
1957 always_const = gather_context_independent_values (info, &known_csts,
1958 &known_binfos, &known_aggs,
1959 &removable_params_cost);
1960 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
1961 if (always_const)
1963 struct caller_statistics stats;
1964 inline_hints hints;
1965 int time, size;
1967 init_caller_stats (&stats);
1968 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
1969 false);
1970 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
1971 known_aggs_ptrs, &size, &time, &hints);
1972 time -= devirtualization_time_bonus (node, known_csts, known_binfos,
1973 known_aggs_ptrs);
1974 time -= hint_time_bonus (hints);
1975 time -= removable_params_cost;
1976 size -= stats.n_calls * removable_params_cost;
1978 if (dump_file)
1979 fprintf (dump_file, " - context independent values, size: %i, "
1980 "time_benefit: %i\n", size, base_time - time);
1982 if (size <= 0
1983 || node->will_be_removed_from_program_if_no_direct_calls_p ())
1985 info->do_clone_for_all_contexts = true;
1986 base_time = time;
1988 if (dump_file)
1989 fprintf (dump_file, " Decided to specialize for all "
1990 "known contexts, code not going to grow.\n");
1992 else if (good_cloning_opportunity_p (node, base_time - time,
1993 stats.freq_sum, stats.count_sum,
1994 size))
1996 if (size + overall_size <= max_new_size)
1998 info->do_clone_for_all_contexts = true;
1999 base_time = time;
2000 overall_size += size;
2002 if (dump_file)
2003 fprintf (dump_file, " Decided to specialize for all "
2004 "known contexts, growth deemed beneficial.\n");
2006 else if (dump_file && (dump_flags & TDF_DETAILS))
2007 fprintf (dump_file, " Not cloning for all contexts because "
2008 "max_new_size would be reached with %li.\n",
2009 size + overall_size);
2013 for (i = 0; i < count ; i++)
2015 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2016 struct ipcp_lattice *lat = &plats->itself;
2017 struct ipcp_value *val;
2018 int emc;
2020 if (lat->bottom
2021 || !lat->values
2022 || known_csts[i]
2023 || known_binfos[i])
2024 continue;
2026 for (val = lat->values; val; val = val->next)
2028 int time, size, time_benefit;
2029 inline_hints hints;
2031 if (TREE_CODE (val->value) != TREE_BINFO)
2033 known_csts[i] = val->value;
2034 known_binfos[i] = NULL_TREE;
2035 emc = estimate_move_cost (TREE_TYPE (val->value), true);
2037 else if (plats->virt_call)
2039 known_csts[i] = NULL_TREE;
2040 known_binfos[i] = val->value;
2041 emc = 0;
2043 else
2044 continue;
2046 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
2047 known_aggs_ptrs, &size, &time,
2048 &hints);
2049 time_benefit = base_time - time
2050 + devirtualization_time_bonus (node, known_csts, known_binfos,
2051 known_aggs_ptrs)
2052 + hint_time_bonus (hints)
2053 + removable_params_cost + emc;
2055 gcc_checking_assert (size >=0);
2056 /* The inliner-heuristics based estimates may think that in certain
2057 contexts some functions do not have any size at all but we want
2058 all specializations to have at least a tiny cost, not least not to
2059 divide by zero. */
2060 if (size == 0)
2061 size = 1;
2063 if (dump_file && (dump_flags & TDF_DETAILS))
2065 fprintf (dump_file, " - estimates for value ");
2066 print_ipcp_constant_value (dump_file, val->value);
2067 fprintf (dump_file, " for ");
2068 ipa_dump_param (dump_file, info, i);
2069 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2070 time_benefit, size);
2073 val->local_time_benefit = time_benefit;
2074 val->local_size_cost = size;
2076 known_binfos[i] = NULL_TREE;
2077 known_csts[i] = NULL_TREE;
2080 for (i = 0; i < count ; i++)
2082 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2083 struct ipa_agg_jump_function *ajf;
2084 struct ipcp_agg_lattice *aglat;
2086 if (plats->aggs_bottom || !plats->aggs)
2087 continue;
2089 ajf = &known_aggs[i];
2090 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2092 struct ipcp_value *val;
2093 if (aglat->bottom || !aglat->values
2094 /* If the following is true, the one value is in known_aggs. */
2095 || (!plats->aggs_contain_variable
2096 && ipa_lat_is_single_const (aglat)))
2097 continue;
2099 for (val = aglat->values; val; val = val->next)
2101 int time, size, time_benefit;
2102 struct ipa_agg_jf_item item;
2103 inline_hints hints;
2105 item.offset = aglat->offset;
2106 item.value = val->value;
2107 vec_safe_push (ajf->items, item);
2109 estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
2110 known_aggs_ptrs, &size, &time,
2111 &hints);
2112 time_benefit = base_time - time
2113 + devirtualization_time_bonus (node, known_csts, known_binfos,
2114 known_aggs_ptrs)
2115 + hint_time_bonus (hints);
2116 gcc_checking_assert (size >=0);
2117 if (size == 0)
2118 size = 1;
2120 if (dump_file && (dump_flags & TDF_DETAILS))
2122 fprintf (dump_file, " - estimates for value ");
2123 print_ipcp_constant_value (dump_file, val->value);
2124 fprintf (dump_file, " for ");
2125 ipa_dump_param (dump_file, info, i);
2126 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2127 "]: time_benefit: %i, size: %i\n",
2128 plats->aggs_by_ref ? "ref " : "",
2129 aglat->offset, time_benefit, size);
2132 val->local_time_benefit = time_benefit;
2133 val->local_size_cost = size;
2134 ajf->items->pop ();
2139 for (i = 0; i < count ; i++)
2140 vec_free (known_aggs[i].items);
2142 known_csts.release ();
2143 known_binfos.release ();
2144 known_aggs.release ();
2145 known_aggs_ptrs.release ();
2149 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2150 topological sort of values. */
2152 static void
2153 add_val_to_toposort (struct ipcp_value *cur_val)
2155 static int dfs_counter = 0;
2156 static struct ipcp_value *stack;
2157 struct ipcp_value_source *src;
2159 if (cur_val->dfs)
2160 return;
2162 dfs_counter++;
2163 cur_val->dfs = dfs_counter;
2164 cur_val->low_link = dfs_counter;
2166 cur_val->topo_next = stack;
2167 stack = cur_val;
2168 cur_val->on_stack = true;
2170 for (src = cur_val->sources; src; src = src->next)
2171 if (src->val)
2173 if (src->val->dfs == 0)
2175 add_val_to_toposort (src->val);
2176 if (src->val->low_link < cur_val->low_link)
2177 cur_val->low_link = src->val->low_link;
2179 else if (src->val->on_stack
2180 && src->val->dfs < cur_val->low_link)
2181 cur_val->low_link = src->val->dfs;
2184 if (cur_val->dfs == cur_val->low_link)
2186 struct ipcp_value *v, *scc_list = NULL;
2190 v = stack;
2191 stack = v->topo_next;
2192 v->on_stack = false;
2194 v->scc_next = scc_list;
2195 scc_list = v;
2197 while (v != cur_val);
2199 cur_val->topo_next = values_topo;
2200 values_topo = cur_val;
2204 /* Add all values in lattices associated with NODE to the topological sort if
2205 they are not there yet. */
2207 static void
2208 add_all_node_vals_to_toposort (struct cgraph_node *node)
2210 struct ipa_node_params *info = IPA_NODE_REF (node);
2211 int i, count = ipa_get_param_count (info);
2213 for (i = 0; i < count ; i++)
2215 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2216 struct ipcp_lattice *lat = &plats->itself;
2217 struct ipcp_agg_lattice *aglat;
2218 struct ipcp_value *val;
2220 if (!lat->bottom)
2221 for (val = lat->values; val; val = val->next)
2222 add_val_to_toposort (val);
2224 if (!plats->aggs_bottom)
2225 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2226 if (!aglat->bottom)
2227 for (val = aglat->values; val; val = val->next)
2228 add_val_to_toposort (val);
2232 /* One pass of constants propagation along the call graph edges, from callers
2233 to callees (requires topological ordering in TOPO), iterate over strongly
2234 connected components. */
2236 static void
2237 propagate_constants_topo (struct ipa_topo_info *topo)
2239 int i;
2241 for (i = topo->nnodes - 1; i >= 0; i--)
2243 unsigned j;
2244 struct cgraph_node *v, *node = topo->order[i];
2245 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
2247 /* First, iteratively propagate within the strongly connected component
2248 until all lattices stabilize. */
2249 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2250 if (v->has_gimple_body_p ())
2251 push_node_to_stack (topo, v);
2253 v = pop_node_from_stack (topo);
2254 while (v)
2256 struct cgraph_edge *cs;
2258 for (cs = v->callees; cs; cs = cs->next_callee)
2259 if (ipa_edge_within_scc (cs)
2260 && propagate_constants_accross_call (cs))
2261 push_node_to_stack (topo, cs->callee);
2262 v = pop_node_from_stack (topo);
2265 /* Afterwards, propagate along edges leading out of the SCC, calculates
2266 the local effects of the discovered constants and all valid values to
2267 their topological sort. */
2268 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
2269 if (v->has_gimple_body_p ())
2271 struct cgraph_edge *cs;
2273 estimate_local_effects (v);
2274 add_all_node_vals_to_toposort (v);
2275 for (cs = v->callees; cs; cs = cs->next_callee)
2276 if (!ipa_edge_within_scc (cs))
2277 propagate_constants_accross_call (cs);
2279 cycle_nodes.release ();
2284 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2285 the bigger one if otherwise. */
2287 static int
2288 safe_add (int a, int b)
2290 if (a > INT_MAX/2 || b > INT_MAX/2)
2291 return a > b ? a : b;
2292 else
2293 return a + b;
2297 /* Propagate the estimated effects of individual values along the topological
2298 from the dependent values to those they depend on. */
2300 static void
2301 propagate_effects (void)
2303 struct ipcp_value *base;
2305 for (base = values_topo; base; base = base->topo_next)
2307 struct ipcp_value_source *src;
2308 struct ipcp_value *val;
2309 int time = 0, size = 0;
2311 for (val = base; val; val = val->scc_next)
2313 time = safe_add (time,
2314 val->local_time_benefit + val->prop_time_benefit);
2315 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
2318 for (val = base; val; val = val->scc_next)
2319 for (src = val->sources; src; src = src->next)
2320 if (src->val
2321 && src->cs->maybe_hot_p ())
2323 src->val->prop_time_benefit = safe_add (time,
2324 src->val->prop_time_benefit);
2325 src->val->prop_size_cost = safe_add (size,
2326 src->val->prop_size_cost);
2332 /* Propagate constants, binfos and their effects from the summaries
2333 interprocedurally. */
2335 static void
2336 ipcp_propagate_stage (struct ipa_topo_info *topo)
2338 struct cgraph_node *node;
2340 if (dump_file)
2341 fprintf (dump_file, "\n Propagating constants:\n\n");
2343 if (in_lto_p)
2344 ipa_update_after_lto_read ();
2347 FOR_EACH_DEFINED_FUNCTION (node)
2349 struct ipa_node_params *info = IPA_NODE_REF (node);
2351 determine_versionability (node);
2352 if (node->has_gimple_body_p ())
2354 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
2355 ipa_get_param_count (info));
2356 initialize_node_lattices (node);
2358 if (node->definition && !node->alias)
2359 overall_size += inline_summary (node)->self_size;
2360 if (node->count > max_count)
2361 max_count = node->count;
2364 max_new_size = overall_size;
2365 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2366 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2367 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2369 if (dump_file)
2370 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2371 overall_size, max_new_size);
2373 propagate_constants_topo (topo);
2374 #ifdef ENABLE_CHECKING
2375 ipcp_verify_propagated_values ();
2376 #endif
2377 propagate_effects ();
2379 if (dump_file)
2381 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2382 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2386 /* Discover newly direct outgoing edges from NODE which is a new clone with
2387 known KNOWN_VALS and make them direct. */
2389 static void
2390 ipcp_discover_new_direct_edges (struct cgraph_node *node,
2391 vec<tree> known_vals,
2392 struct ipa_agg_replacement_value *aggvals)
2394 struct cgraph_edge *ie, *next_ie;
2395 bool found = false;
2397 for (ie = node->indirect_calls; ie; ie = next_ie)
2399 tree target;
2401 next_ie = ie->next_callee;
2402 target = ipa_get_indirect_edge_target_1 (ie, known_vals, vNULL, vNULL,
2403 aggvals);
2404 if (target)
2406 bool agg_contents = ie->indirect_info->agg_contents;
2407 bool polymorphic = ie->indirect_info->polymorphic;
2408 int param_index = ie->indirect_info->param_index;
2409 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target);
2410 found = true;
2412 if (cs && !agg_contents && !polymorphic)
2414 struct ipa_node_params *info = IPA_NODE_REF (node);
2415 int c = ipa_get_controlled_uses (info, param_index);
2416 if (c != IPA_UNDESCRIBED_USE)
2418 struct ipa_ref *to_del;
2420 c--;
2421 ipa_set_controlled_uses (info, param_index, c);
2422 if (dump_file && (dump_flags & TDF_DETAILS))
2423 fprintf (dump_file, " controlled uses count of param "
2424 "%i bumped down to %i\n", param_index, c);
2425 if (c == 0
2426 && (to_del = node->find_reference (cs->callee, NULL, 0)))
2428 if (dump_file && (dump_flags & TDF_DETAILS))
2429 fprintf (dump_file, " and even removing its "
2430 "cloning-created reference\n");
2431 to_del->remove_reference ();
2437 /* Turning calls to direct calls will improve overall summary. */
2438 if (found)
2439 inline_update_overall_summary (node);
2442 /* Vector of pointers which for linked lists of clones of an original crgaph
2443 edge. */
2445 static vec<cgraph_edge *> next_edge_clone;
2446 static vec<cgraph_edge *> prev_edge_clone;
2448 static inline void
2449 grow_edge_clone_vectors (void)
2451 if (next_edge_clone.length ()
2452 <= (unsigned) symtab->edges_max_uid)
2453 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2454 if (prev_edge_clone.length ()
2455 <= (unsigned) symtab->edges_max_uid)
2456 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
2459 /* Edge duplication hook to grow the appropriate linked list in
2460 next_edge_clone. */
2462 static void
2463 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
2464 void *)
2466 grow_edge_clone_vectors ();
2468 struct cgraph_edge *old_next = next_edge_clone[src->uid];
2469 if (old_next)
2470 prev_edge_clone[old_next->uid] = dst;
2471 prev_edge_clone[dst->uid] = src;
2473 next_edge_clone[dst->uid] = old_next;
2474 next_edge_clone[src->uid] = dst;
2477 /* Hook that is called by cgraph.c when an edge is removed. */
2479 static void
2480 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
2482 grow_edge_clone_vectors ();
2484 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
2485 struct cgraph_edge *next = next_edge_clone[cs->uid];
2486 if (prev)
2487 next_edge_clone[prev->uid] = next;
2488 if (next)
2489 prev_edge_clone[next->uid] = prev;
2492 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2493 parameter with the given INDEX. */
2495 static tree
2496 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2497 int index)
2499 struct ipa_agg_replacement_value *aggval;
2501 aggval = ipa_get_agg_replacements_for_node (node);
2502 while (aggval)
2504 if (aggval->offset == offset
2505 && aggval->index == index)
2506 return aggval->value;
2507 aggval = aggval->next;
2509 return NULL_TREE;
2512 /* Return true if edge CS does bring about the value described by SRC. */
2514 static bool
2515 cgraph_edge_brings_value_p (struct cgraph_edge *cs,
2516 struct ipcp_value_source *src)
2518 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2519 cgraph_node *real_dest = cs->callee->function_symbol ();
2520 struct ipa_node_params *dst_info = IPA_NODE_REF (real_dest);
2522 if ((dst_info->ipcp_orig_node && !dst_info->is_all_contexts_clone)
2523 || caller_info->node_dead)
2524 return false;
2525 if (!src->val)
2526 return true;
2528 if (caller_info->ipcp_orig_node)
2530 tree t;
2531 if (src->offset == -1)
2532 t = caller_info->known_vals[src->index];
2533 else
2534 t = get_clone_agg_value (cs->caller, src->offset, src->index);
2535 return (t != NULL_TREE
2536 && values_equal_for_ipcp_p (src->val->value, t));
2538 else
2540 struct ipcp_agg_lattice *aglat;
2541 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
2542 src->index);
2543 if (src->offset == -1)
2544 return (ipa_lat_is_single_const (&plats->itself)
2545 && values_equal_for_ipcp_p (src->val->value,
2546 plats->itself.values->value));
2547 else
2549 if (plats->aggs_bottom || plats->aggs_contain_variable)
2550 return false;
2551 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2552 if (aglat->offset == src->offset)
2553 return (ipa_lat_is_single_const (aglat)
2554 && values_equal_for_ipcp_p (src->val->value,
2555 aglat->values->value));
2557 return false;
2561 /* Get the next clone in the linked list of clones of an edge. */
2563 static inline struct cgraph_edge *
2564 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
2566 return next_edge_clone[cs->uid];
2569 /* Given VAL, iterate over all its sources and if they still hold, add their
2570 edge frequency and their number into *FREQUENCY and *CALLER_COUNT
2571 respectively. */
2573 static bool
2574 get_info_about_necessary_edges (struct ipcp_value *val, int *freq_sum,
2575 gcov_type *count_sum, int *caller_count)
2577 struct ipcp_value_source *src;
2578 int freq = 0, count = 0;
2579 gcov_type cnt = 0;
2580 bool hot = false;
2582 for (src = val->sources; src; src = src->next)
2584 struct cgraph_edge *cs = src->cs;
2585 while (cs)
2587 if (cgraph_edge_brings_value_p (cs, src))
2589 count++;
2590 freq += cs->frequency;
2591 cnt += cs->count;
2592 hot |= cs->maybe_hot_p ();
2594 cs = get_next_cgraph_edge_clone (cs);
2598 *freq_sum = freq;
2599 *count_sum = cnt;
2600 *caller_count = count;
2601 return hot;
2604 /* Return a vector of incoming edges that do bring value VAL. It is assumed
2605 their number is known and equal to CALLER_COUNT. */
2607 static vec<cgraph_edge *>
2608 gather_edges_for_value (struct ipcp_value *val, int caller_count)
2610 struct ipcp_value_source *src;
2611 vec<cgraph_edge *> ret;
2613 ret.create (caller_count);
2614 for (src = val->sources; src; src = src->next)
2616 struct cgraph_edge *cs = src->cs;
2617 while (cs)
2619 if (cgraph_edge_brings_value_p (cs, src))
2620 ret.quick_push (cs);
2621 cs = get_next_cgraph_edge_clone (cs);
2625 return ret;
2628 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
2629 Return it or NULL if for some reason it cannot be created. */
2631 static struct ipa_replace_map *
2632 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
2634 struct ipa_replace_map *replace_map;
2637 replace_map = ggc_alloc<ipa_replace_map> ();
2638 if (dump_file)
2640 fprintf (dump_file, " replacing ");
2641 ipa_dump_param (dump_file, info, parm_num);
2643 fprintf (dump_file, " with const ");
2644 print_generic_expr (dump_file, value, 0);
2645 fprintf (dump_file, "\n");
2647 replace_map->old_tree = NULL;
2648 replace_map->parm_num = parm_num;
2649 replace_map->new_tree = value;
2650 replace_map->replace_p = true;
2651 replace_map->ref_p = false;
2653 return replace_map;
2656 /* Dump new profiling counts */
2658 static void
2659 dump_profile_updates (struct cgraph_node *orig_node,
2660 struct cgraph_node *new_node)
2662 struct cgraph_edge *cs;
2664 fprintf (dump_file, " setting count of the specialized node to "
2665 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
2666 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2667 fprintf (dump_file, " edge to %s has count "
2668 HOST_WIDE_INT_PRINT_DEC "\n",
2669 cs->callee->name (), (HOST_WIDE_INT) cs->count);
2671 fprintf (dump_file, " setting count of the original node to "
2672 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
2673 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2674 fprintf (dump_file, " edge to %s is left with "
2675 HOST_WIDE_INT_PRINT_DEC "\n",
2676 cs->callee->name (), (HOST_WIDE_INT) cs->count);
2679 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
2680 their profile information to reflect this. */
2682 static void
2683 update_profiling_info (struct cgraph_node *orig_node,
2684 struct cgraph_node *new_node)
2686 struct cgraph_edge *cs;
2687 struct caller_statistics stats;
2688 gcov_type new_sum, orig_sum;
2689 gcov_type remainder, orig_node_count = orig_node->count;
2691 if (orig_node_count == 0)
2692 return;
2694 init_caller_stats (&stats);
2695 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2696 false);
2697 orig_sum = stats.count_sum;
2698 init_caller_stats (&stats);
2699 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2700 false);
2701 new_sum = stats.count_sum;
2703 if (orig_node_count < orig_sum + new_sum)
2705 if (dump_file)
2706 fprintf (dump_file, " Problem: node %s/%i has too low count "
2707 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
2708 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
2709 orig_node->name (), orig_node->order,
2710 (HOST_WIDE_INT) orig_node_count,
2711 (HOST_WIDE_INT) (orig_sum + new_sum));
2713 orig_node_count = (orig_sum + new_sum) * 12 / 10;
2714 if (dump_file)
2715 fprintf (dump_file, " proceeding by pretending it was "
2716 HOST_WIDE_INT_PRINT_DEC "\n",
2717 (HOST_WIDE_INT) orig_node_count);
2720 new_node->count = new_sum;
2721 remainder = orig_node_count - new_sum;
2722 orig_node->count = remainder;
2724 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2725 if (cs->frequency)
2726 cs->count = apply_probability (cs->count,
2727 GCOV_COMPUTE_SCALE (new_sum,
2728 orig_node_count));
2729 else
2730 cs->count = 0;
2732 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2733 cs->count = apply_probability (cs->count,
2734 GCOV_COMPUTE_SCALE (remainder,
2735 orig_node_count));
2737 if (dump_file)
2738 dump_profile_updates (orig_node, new_node);
2741 /* Update the respective profile of specialized NEW_NODE and the original
2742 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
2743 have been redirected to the specialized version. */
2745 static void
2746 update_specialized_profile (struct cgraph_node *new_node,
2747 struct cgraph_node *orig_node,
2748 gcov_type redirected_sum)
2750 struct cgraph_edge *cs;
2751 gcov_type new_node_count, orig_node_count = orig_node->count;
2753 if (dump_file)
2754 fprintf (dump_file, " the sum of counts of redirected edges is "
2755 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
2756 if (orig_node_count == 0)
2757 return;
2759 gcc_assert (orig_node_count >= redirected_sum);
2761 new_node_count = new_node->count;
2762 new_node->count += redirected_sum;
2763 orig_node->count -= redirected_sum;
2765 for (cs = new_node->callees; cs ; cs = cs->next_callee)
2766 if (cs->frequency)
2767 cs->count += apply_probability (cs->count,
2768 GCOV_COMPUTE_SCALE (redirected_sum,
2769 new_node_count));
2770 else
2771 cs->count = 0;
2773 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
2775 gcov_type dec = apply_probability (cs->count,
2776 GCOV_COMPUTE_SCALE (redirected_sum,
2777 orig_node_count));
2778 if (dec < cs->count)
2779 cs->count -= dec;
2780 else
2781 cs->count = 0;
2784 if (dump_file)
2785 dump_profile_updates (orig_node, new_node);
2788 /* Create a specialized version of NODE with known constants and types of
2789 parameters in KNOWN_VALS and redirect all edges in CALLERS to it. */
2791 static struct cgraph_node *
2792 create_specialized_node (struct cgraph_node *node,
2793 vec<tree> known_vals,
2794 struct ipa_agg_replacement_value *aggvals,
2795 vec<cgraph_edge *> callers)
2797 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
2798 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
2799 struct ipa_agg_replacement_value *av;
2800 struct cgraph_node *new_node;
2801 int i, count = ipa_get_param_count (info);
2802 bitmap args_to_skip;
2804 gcc_assert (!info->ipcp_orig_node);
2806 if (node->local.can_change_signature)
2808 args_to_skip = BITMAP_GGC_ALLOC ();
2809 for (i = 0; i < count; i++)
2811 tree t = known_vals[i];
2813 if ((t && TREE_CODE (t) != TREE_BINFO)
2814 || !ipa_is_param_used (info, i))
2815 bitmap_set_bit (args_to_skip, i);
2818 else
2820 args_to_skip = NULL;
2821 if (dump_file && (dump_flags & TDF_DETAILS))
2822 fprintf (dump_file, " cannot change function signature\n");
2825 for (i = 0; i < count ; i++)
2827 tree t = known_vals[i];
2828 if (t && TREE_CODE (t) != TREE_BINFO)
2830 struct ipa_replace_map *replace_map;
2832 replace_map = get_replacement_map (info, t, i);
2833 if (replace_map)
2834 vec_safe_push (replace_trees, replace_map);
2838 new_node = node->create_virtual_clone (callers, replace_trees,
2839 args_to_skip, "constprop");
2840 ipa_set_node_agg_value_chain (new_node, aggvals);
2841 for (av = aggvals; av; av = av->next)
2842 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
2844 if (dump_file && (dump_flags & TDF_DETAILS))
2846 fprintf (dump_file, " the new node is %s/%i.\n",
2847 new_node->name (), new_node->order);
2848 if (aggvals)
2849 ipa_dump_agg_replacement_values (dump_file, aggvals);
2851 ipa_check_create_node_params ();
2852 update_profiling_info (node, new_node);
2853 new_info = IPA_NODE_REF (new_node);
2854 new_info->ipcp_orig_node = node;
2855 new_info->known_vals = known_vals;
2857 ipcp_discover_new_direct_edges (new_node, known_vals, aggvals);
2859 callers.release ();
2860 return new_node;
2863 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
2864 KNOWN_VALS with constants and types that are also known for all of the
2865 CALLERS. */
2867 static void
2868 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
2869 vec<tree> known_vals,
2870 vec<cgraph_edge *> callers)
2872 struct ipa_node_params *info = IPA_NODE_REF (node);
2873 int i, count = ipa_get_param_count (info);
2875 for (i = 0; i < count ; i++)
2877 struct cgraph_edge *cs;
2878 tree newval = NULL_TREE;
2879 int j;
2881 if (ipa_get_scalar_lat (info, i)->bottom || known_vals[i])
2882 continue;
2884 FOR_EACH_VEC_ELT (callers, j, cs)
2886 struct ipa_jump_func *jump_func;
2887 tree t;
2889 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
2891 newval = NULL_TREE;
2892 break;
2894 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
2895 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
2896 if (!t
2897 || (newval
2898 && !values_equal_for_ipcp_p (t, newval)))
2900 newval = NULL_TREE;
2901 break;
2903 else
2904 newval = t;
2907 if (newval)
2909 if (dump_file && (dump_flags & TDF_DETAILS))
2911 fprintf (dump_file, " adding an extra known scalar value ");
2912 print_ipcp_constant_value (dump_file, newval);
2913 fprintf (dump_file, " for ");
2914 ipa_dump_param (dump_file, info, i);
2915 fprintf (dump_file, "\n");
2918 known_vals[i] = newval;
2923 /* Go through PLATS and create a vector of values consisting of values and
2924 offsets (minus OFFSET) of lattices that contain only a single value. */
2926 static vec<ipa_agg_jf_item>
2927 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
2929 vec<ipa_agg_jf_item> res = vNULL;
2931 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
2932 return vNULL;
2934 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
2935 if (ipa_lat_is_single_const (aglat))
2937 struct ipa_agg_jf_item ti;
2938 ti.offset = aglat->offset - offset;
2939 ti.value = aglat->values->value;
2940 res.safe_push (ti);
2942 return res;
2945 /* Intersect all values in INTER with single value lattices in PLATS (while
2946 subtracting OFFSET). */
2948 static void
2949 intersect_with_plats (struct ipcp_param_lattices *plats,
2950 vec<ipa_agg_jf_item> *inter,
2951 HOST_WIDE_INT offset)
2953 struct ipcp_agg_lattice *aglat;
2954 struct ipa_agg_jf_item *item;
2955 int k;
2957 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
2959 inter->release ();
2960 return;
2963 aglat = plats->aggs;
2964 FOR_EACH_VEC_ELT (*inter, k, item)
2966 bool found = false;
2967 if (!item->value)
2968 continue;
2969 while (aglat)
2971 if (aglat->offset - offset > item->offset)
2972 break;
2973 if (aglat->offset - offset == item->offset)
2975 gcc_checking_assert (item->value);
2976 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
2977 found = true;
2978 break;
2980 aglat = aglat->next;
2982 if (!found)
2983 item->value = NULL_TREE;
2987 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
2988 vector result while subtracting OFFSET from the individual value offsets. */
2990 static vec<ipa_agg_jf_item>
2991 agg_replacements_to_vector (struct cgraph_node *node, int index,
2992 HOST_WIDE_INT offset)
2994 struct ipa_agg_replacement_value *av;
2995 vec<ipa_agg_jf_item> res = vNULL;
2997 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
2998 if (av->index == index
2999 && (av->offset - offset) >= 0)
3001 struct ipa_agg_jf_item item;
3002 gcc_checking_assert (av->value);
3003 item.offset = av->offset - offset;
3004 item.value = av->value;
3005 res.safe_push (item);
3008 return res;
3011 /* Intersect all values in INTER with those that we have already scheduled to
3012 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3013 (while subtracting OFFSET). */
3015 static void
3016 intersect_with_agg_replacements (struct cgraph_node *node, int index,
3017 vec<ipa_agg_jf_item> *inter,
3018 HOST_WIDE_INT offset)
3020 struct ipa_agg_replacement_value *srcvals;
3021 struct ipa_agg_jf_item *item;
3022 int i;
3024 srcvals = ipa_get_agg_replacements_for_node (node);
3025 if (!srcvals)
3027 inter->release ();
3028 return;
3031 FOR_EACH_VEC_ELT (*inter, i, item)
3033 struct ipa_agg_replacement_value *av;
3034 bool found = false;
3035 if (!item->value)
3036 continue;
3037 for (av = srcvals; av; av = av->next)
3039 gcc_checking_assert (av->value);
3040 if (av->index == index
3041 && av->offset - offset == item->offset)
3043 if (values_equal_for_ipcp_p (item->value, av->value))
3044 found = true;
3045 break;
3048 if (!found)
3049 item->value = NULL_TREE;
3053 /* Intersect values in INTER with aggregate values that come along edge CS to
3054 parameter number INDEX and return it. If INTER does not actually exist yet,
3055 copy all incoming values to it. If we determine we ended up with no values
3056 whatsoever, return a released vector. */
3058 static vec<ipa_agg_jf_item>
3059 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
3060 vec<ipa_agg_jf_item> inter)
3062 struct ipa_jump_func *jfunc;
3063 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3064 if (jfunc->type == IPA_JF_PASS_THROUGH
3065 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3067 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3068 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3070 if (caller_info->ipcp_orig_node)
3072 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3073 struct ipcp_param_lattices *orig_plats;
3074 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3075 src_idx);
3076 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3078 if (!inter.exists ())
3079 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
3080 else
3081 intersect_with_agg_replacements (cs->caller, src_idx,
3082 &inter, 0);
3084 else
3086 inter.release ();
3087 return vNULL;
3090 else
3092 struct ipcp_param_lattices *src_plats;
3093 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3094 if (agg_pass_through_permissible_p (src_plats, jfunc))
3096 /* Currently we do not produce clobber aggregate jump
3097 functions, adjust when we do. */
3098 gcc_checking_assert (!jfunc->agg.items);
3099 if (!inter.exists ())
3100 inter = copy_plats_to_inter (src_plats, 0);
3101 else
3102 intersect_with_plats (src_plats, &inter, 0);
3104 else
3106 inter.release ();
3107 return vNULL;
3111 else if (jfunc->type == IPA_JF_ANCESTOR
3112 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3114 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3115 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3116 struct ipcp_param_lattices *src_plats;
3117 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3119 if (caller_info->ipcp_orig_node)
3121 if (!inter.exists ())
3122 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
3123 else
3124 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
3125 delta);
3127 else
3129 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3130 /* Currently we do not produce clobber aggregate jump
3131 functions, adjust when we do. */
3132 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3133 if (!inter.exists ())
3134 inter = copy_plats_to_inter (src_plats, delta);
3135 else
3136 intersect_with_plats (src_plats, &inter, delta);
3139 else if (jfunc->agg.items)
3141 struct ipa_agg_jf_item *item;
3142 int k;
3144 if (!inter.exists ())
3145 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3146 inter.safe_push ((*jfunc->agg.items)[i]);
3147 else
3148 FOR_EACH_VEC_ELT (inter, k, item)
3150 int l = 0;
3151 bool found = false;;
3153 if (!item->value)
3154 continue;
3156 while ((unsigned) l < jfunc->agg.items->length ())
3158 struct ipa_agg_jf_item *ti;
3159 ti = &(*jfunc->agg.items)[l];
3160 if (ti->offset > item->offset)
3161 break;
3162 if (ti->offset == item->offset)
3164 gcc_checking_assert (ti->value);
3165 if (values_equal_for_ipcp_p (item->value,
3166 ti->value))
3167 found = true;
3168 break;
3170 l++;
3172 if (!found)
3173 item->value = NULL;
3176 else
3178 inter.release ();
3179 return vec<ipa_agg_jf_item>();
3181 return inter;
3184 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3185 from all of them. */
3187 static struct ipa_agg_replacement_value *
3188 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
3189 vec<cgraph_edge *> callers)
3191 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3192 struct ipa_agg_replacement_value *res;
3193 struct ipa_agg_replacement_value **tail = &res;
3194 struct cgraph_edge *cs;
3195 int i, j, count = ipa_get_param_count (dest_info);
3197 FOR_EACH_VEC_ELT (callers, j, cs)
3199 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3200 if (c < count)
3201 count = c;
3204 for (i = 0; i < count ; i++)
3206 struct cgraph_edge *cs;
3207 vec<ipa_agg_jf_item> inter = vNULL;
3208 struct ipa_agg_jf_item *item;
3209 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
3210 int j;
3212 /* Among other things, the following check should deal with all by_ref
3213 mismatches. */
3214 if (plats->aggs_bottom)
3215 continue;
3217 FOR_EACH_VEC_ELT (callers, j, cs)
3219 inter = intersect_aggregates_with_edge (cs, i, inter);
3221 if (!inter.exists ())
3222 goto next_param;
3225 FOR_EACH_VEC_ELT (inter, j, item)
3227 struct ipa_agg_replacement_value *v;
3229 if (!item->value)
3230 continue;
3232 v = ggc_alloc<ipa_agg_replacement_value> ();
3233 v->index = i;
3234 v->offset = item->offset;
3235 v->value = item->value;
3236 v->by_ref = plats->aggs_by_ref;
3237 *tail = v;
3238 tail = &v->next;
3241 next_param:
3242 if (inter.exists ())
3243 inter.release ();
3245 *tail = NULL;
3246 return res;
3249 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3251 static struct ipa_agg_replacement_value *
3252 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
3254 struct ipa_agg_replacement_value *res;
3255 struct ipa_agg_replacement_value **tail = &res;
3256 struct ipa_agg_jump_function *aggjf;
3257 struct ipa_agg_jf_item *item;
3258 int i, j;
3260 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3261 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
3263 struct ipa_agg_replacement_value *v;
3264 v = ggc_alloc<ipa_agg_replacement_value> ();
3265 v->index = i;
3266 v->offset = item->offset;
3267 v->value = item->value;
3268 v->by_ref = aggjf->by_ref;
3269 *tail = v;
3270 tail = &v->next;
3272 *tail = NULL;
3273 return res;
3276 /* Determine whether CS also brings all scalar values that the NODE is
3277 specialized for. */
3279 static bool
3280 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3281 struct cgraph_node *node)
3283 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3284 int count = ipa_get_param_count (dest_info);
3285 struct ipa_node_params *caller_info;
3286 struct ipa_edge_args *args;
3287 int i;
3289 caller_info = IPA_NODE_REF (cs->caller);
3290 args = IPA_EDGE_REF (cs);
3291 for (i = 0; i < count; i++)
3293 struct ipa_jump_func *jump_func;
3294 tree val, t;
3296 val = dest_info->known_vals[i];
3297 if (!val)
3298 continue;
3300 if (i >= ipa_get_cs_argument_count (args))
3301 return false;
3302 jump_func = ipa_get_ith_jump_func (args, i);
3303 t = ipa_value_from_jfunc (caller_info, jump_func);
3304 if (!t || !values_equal_for_ipcp_p (val, t))
3305 return false;
3307 return true;
3310 /* Determine whether CS also brings all aggregate values that NODE is
3311 specialized for. */
3312 static bool
3313 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3314 struct cgraph_node *node)
3316 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
3317 struct ipa_node_params *orig_node_info;
3318 struct ipa_agg_replacement_value *aggval;
3319 int i, ec, count;
3321 aggval = ipa_get_agg_replacements_for_node (node);
3322 if (!aggval)
3323 return true;
3325 count = ipa_get_param_count (IPA_NODE_REF (node));
3326 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3327 if (ec < count)
3328 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3329 if (aggval->index >= ec)
3330 return false;
3332 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
3333 if (orig_caller_info->ipcp_orig_node)
3334 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
3336 for (i = 0; i < count; i++)
3338 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
3339 struct ipcp_param_lattices *plats;
3340 bool interesting = false;
3341 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3342 if (aggval->index == i)
3344 interesting = true;
3345 break;
3347 if (!interesting)
3348 continue;
3350 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
3351 if (plats->aggs_bottom)
3352 return false;
3354 values = intersect_aggregates_with_edge (cs, i, values);
3355 if (!values.exists ())
3356 return false;
3358 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
3359 if (aggval->index == i)
3361 struct ipa_agg_jf_item *item;
3362 int j;
3363 bool found = false;
3364 FOR_EACH_VEC_ELT (values, j, item)
3365 if (item->value
3366 && item->offset == av->offset
3367 && values_equal_for_ipcp_p (item->value, av->value))
3369 found = true;
3370 break;
3372 if (!found)
3374 values.release ();
3375 return false;
3379 return true;
3382 /* Given an original NODE and a VAL for which we have already created a
3383 specialized clone, look whether there are incoming edges that still lead
3384 into the old node but now also bring the requested value and also conform to
3385 all other criteria such that they can be redirected the the special node.
3386 This function can therefore redirect the final edge in a SCC. */
3388 static void
3389 perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val)
3391 struct ipcp_value_source *src;
3392 gcov_type redirected_sum = 0;
3394 for (src = val->sources; src; src = src->next)
3396 struct cgraph_edge *cs = src->cs;
3397 while (cs)
3399 enum availability availability;
3400 struct cgraph_node *dst = cs->callee->function_symbol (&availability);
3401 if ((dst == node || IPA_NODE_REF (dst)->is_all_contexts_clone)
3402 && availability > AVAIL_INTERPOSABLE
3403 && cgraph_edge_brings_value_p (cs, src))
3405 if (cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
3406 && cgraph_edge_brings_all_agg_vals_for_node (cs,
3407 val->spec_node))
3409 if (dump_file)
3410 fprintf (dump_file, " - adding an extra caller %s/%i"
3411 " of %s/%i\n",
3412 xstrdup (cs->caller->name ()),
3413 cs->caller->order,
3414 xstrdup (val->spec_node->name ()),
3415 val->spec_node->order);
3417 cs->redirect_callee (val->spec_node);
3418 redirected_sum += cs->count;
3421 cs = get_next_cgraph_edge_clone (cs);
3425 if (redirected_sum)
3426 update_specialized_profile (val->spec_node, node, redirected_sum);
3430 /* Copy KNOWN_BINFOS to KNOWN_VALS. */
3432 static void
3433 move_binfos_to_values (vec<tree> known_vals,
3434 vec<tree> known_binfos)
3436 tree t;
3437 int i;
3439 for (i = 0; known_binfos.iterate (i, &t); i++)
3440 if (t)
3441 known_vals[i] = t;
3444 /* Return true if there is a replacement equivalent to VALUE, INDEX and OFFSET
3445 among those in the AGGVALS list. */
3447 DEBUG_FUNCTION bool
3448 ipcp_val_in_agg_replacements_p (struct ipa_agg_replacement_value *aggvals,
3449 int index, HOST_WIDE_INT offset, tree value)
3451 while (aggvals)
3453 if (aggvals->index == index
3454 && aggvals->offset == offset
3455 && values_equal_for_ipcp_p (aggvals->value, value))
3456 return true;
3457 aggvals = aggvals->next;
3459 return false;
3462 /* Decide wheter to create a special version of NODE for value VAL of parameter
3463 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
3464 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
3465 KNOWN_BINFOS and KNOWN_AGGS describe the other already known values. */
3467 static bool
3468 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
3469 struct ipcp_value *val, vec<tree> known_csts,
3470 vec<tree> known_binfos)
3472 struct ipa_agg_replacement_value *aggvals;
3473 int freq_sum, caller_count;
3474 gcov_type count_sum;
3475 vec<cgraph_edge *> callers;
3476 vec<tree> kv;
3478 if (val->spec_node)
3480 perhaps_add_new_callers (node, val);
3481 return false;
3483 else if (val->local_size_cost + overall_size > max_new_size)
3485 if (dump_file && (dump_flags & TDF_DETAILS))
3486 fprintf (dump_file, " Ignoring candidate value because "
3487 "max_new_size would be reached with %li.\n",
3488 val->local_size_cost + overall_size);
3489 return false;
3491 else if (!get_info_about_necessary_edges (val, &freq_sum, &count_sum,
3492 &caller_count))
3493 return false;
3495 if (dump_file && (dump_flags & TDF_DETAILS))
3497 fprintf (dump_file, " - considering value ");
3498 print_ipcp_constant_value (dump_file, val->value);
3499 fprintf (dump_file, " for ");
3500 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
3501 if (offset != -1)
3502 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
3503 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
3506 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
3507 freq_sum, count_sum,
3508 val->local_size_cost)
3509 && !good_cloning_opportunity_p (node,
3510 val->local_time_benefit
3511 + val->prop_time_benefit,
3512 freq_sum, count_sum,
3513 val->local_size_cost
3514 + val->prop_size_cost))
3515 return false;
3517 if (dump_file)
3518 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
3519 node->name (), node->order);
3521 callers = gather_edges_for_value (val, caller_count);
3522 kv = known_csts.copy ();
3523 move_binfos_to_values (kv, known_binfos);
3524 if (offset == -1)
3525 kv[index] = val->value;
3526 find_more_scalar_values_for_callers_subset (node, kv, callers);
3527 aggvals = find_aggregate_values_for_callers_subset (node, callers);
3528 gcc_checking_assert (offset == -1
3529 || ipcp_val_in_agg_replacements_p (aggvals, index,
3530 offset, val->value));
3531 val->spec_node = create_specialized_node (node, kv, aggvals, callers);
3532 overall_size += val->local_size_cost;
3534 /* TODO: If for some lattice there is only one other known value
3535 left, make a special node for it too. */
3537 return true;
3540 /* Decide whether and what specialized clones of NODE should be created. */
3542 static bool
3543 decide_whether_version_node (struct cgraph_node *node)
3545 struct ipa_node_params *info = IPA_NODE_REF (node);
3546 int i, count = ipa_get_param_count (info);
3547 vec<tree> known_csts, known_binfos;
3548 vec<ipa_agg_jump_function> known_aggs = vNULL;
3549 bool ret = false;
3551 if (count == 0)
3552 return false;
3554 if (dump_file && (dump_flags & TDF_DETAILS))
3555 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
3556 node->name (), node->order);
3558 gather_context_independent_values (info, &known_csts, &known_binfos,
3559 info->do_clone_for_all_contexts ? &known_aggs
3560 : NULL, NULL);
3562 for (i = 0; i < count ;i++)
3564 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3565 struct ipcp_lattice *lat = &plats->itself;
3566 struct ipcp_value *val;
3568 if (!lat->bottom
3569 && !known_csts[i]
3570 && !known_binfos[i])
3571 for (val = lat->values; val; val = val->next)
3572 ret |= decide_about_value (node, i, -1, val, known_csts,
3573 known_binfos);
3575 if (!plats->aggs_bottom)
3577 struct ipcp_agg_lattice *aglat;
3578 struct ipcp_value *val;
3579 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3580 if (!aglat->bottom && aglat->values
3581 /* If the following is false, the one value is in
3582 known_aggs. */
3583 && (plats->aggs_contain_variable
3584 || !ipa_lat_is_single_const (aglat)))
3585 for (val = aglat->values; val; val = val->next)
3586 ret |= decide_about_value (node, i, aglat->offset, val,
3587 known_csts, known_binfos);
3589 info = IPA_NODE_REF (node);
3592 if (info->do_clone_for_all_contexts)
3594 struct cgraph_node *clone;
3595 vec<cgraph_edge *> callers;
3597 if (dump_file)
3598 fprintf (dump_file, " - Creating a specialized node of %s/%i "
3599 "for all known contexts.\n", node->name (),
3600 node->order);
3602 callers = node->collect_callers ();
3603 move_binfos_to_values (known_csts, known_binfos);
3604 clone = create_specialized_node (node, known_csts,
3605 known_aggs_to_agg_replacement_list (known_aggs),
3606 callers);
3607 info = IPA_NODE_REF (node);
3608 info->do_clone_for_all_contexts = false;
3609 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
3610 for (i = 0; i < count ; i++)
3611 vec_free (known_aggs[i].items);
3612 known_aggs.release ();
3613 ret = true;
3615 else
3616 known_csts.release ();
3618 known_binfos.release ();
3619 return ret;
3622 /* Transitively mark all callees of NODE within the same SCC as not dead. */
3624 static void
3625 spread_undeadness (struct cgraph_node *node)
3627 struct cgraph_edge *cs;
3629 for (cs = node->callees; cs; cs = cs->next_callee)
3630 if (ipa_edge_within_scc (cs))
3632 struct cgraph_node *callee;
3633 struct ipa_node_params *info;
3635 callee = cs->callee->function_symbol (NULL);
3636 info = IPA_NODE_REF (callee);
3638 if (info->node_dead)
3640 info->node_dead = 0;
3641 spread_undeadness (callee);
3646 /* Return true if NODE has a caller from outside of its SCC that is not
3647 dead. Worker callback for cgraph_for_node_and_aliases. */
3649 static bool
3650 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
3651 void *data ATTRIBUTE_UNUSED)
3653 struct cgraph_edge *cs;
3655 for (cs = node->callers; cs; cs = cs->next_caller)
3656 if (cs->caller->thunk.thunk_p
3657 && cs->caller->call_for_symbol_thunks_and_aliases
3658 (has_undead_caller_from_outside_scc_p, NULL, true))
3659 return true;
3660 else if (!ipa_edge_within_scc (cs)
3661 && !IPA_NODE_REF (cs->caller)->node_dead)
3662 return true;
3663 return false;
3667 /* Identify nodes within the same SCC as NODE which are no longer needed
3668 because of new clones and will be removed as unreachable. */
3670 static void
3671 identify_dead_nodes (struct cgraph_node *node)
3673 struct cgraph_node *v;
3674 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3675 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
3676 && !v->call_for_symbol_thunks_and_aliases
3677 (has_undead_caller_from_outside_scc_p, NULL, true))
3678 IPA_NODE_REF (v)->node_dead = 1;
3680 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3681 if (!IPA_NODE_REF (v)->node_dead)
3682 spread_undeadness (v);
3684 if (dump_file && (dump_flags & TDF_DETAILS))
3686 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3687 if (IPA_NODE_REF (v)->node_dead)
3688 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
3689 v->name (), v->order);
3693 /* The decision stage. Iterate over the topological order of call graph nodes
3694 TOPO and make specialized clones if deemed beneficial. */
3696 static void
3697 ipcp_decision_stage (struct ipa_topo_info *topo)
3699 int i;
3701 if (dump_file)
3702 fprintf (dump_file, "\nIPA decision stage:\n\n");
3704 for (i = topo->nnodes - 1; i >= 0; i--)
3706 struct cgraph_node *node = topo->order[i];
3707 bool change = false, iterate = true;
3709 while (iterate)
3711 struct cgraph_node *v;
3712 iterate = false;
3713 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
3714 if (v->has_gimple_body_p ()
3715 && ipcp_versionable_function_p (v))
3716 iterate |= decide_whether_version_node (v);
3718 change |= iterate;
3720 if (change)
3721 identify_dead_nodes (node);
3725 /* The IPCP driver. */
3727 static unsigned int
3728 ipcp_driver (void)
3730 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
3731 struct cgraph_edge_hook_list *edge_removal_hook_holder;
3732 struct ipa_topo_info topo;
3734 ipa_check_create_node_params ();
3735 ipa_check_create_edge_args ();
3736 grow_edge_clone_vectors ();
3737 edge_duplication_hook_holder =
3738 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
3739 edge_removal_hook_holder =
3740 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
3742 ipcp_values_pool = create_alloc_pool ("IPA-CP values",
3743 sizeof (struct ipcp_value), 32);
3744 ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources",
3745 sizeof (struct ipcp_value_source), 64);
3746 ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices",
3747 sizeof (struct ipcp_agg_lattice),
3748 32);
3749 if (dump_file)
3751 fprintf (dump_file, "\nIPA structures before propagation:\n");
3752 if (dump_flags & TDF_DETAILS)
3753 ipa_print_all_params (dump_file);
3754 ipa_print_all_jump_functions (dump_file);
3757 /* Topological sort. */
3758 build_toporder_info (&topo);
3759 /* Do the interprocedural propagation. */
3760 ipcp_propagate_stage (&topo);
3761 /* Decide what constant propagation and cloning should be performed. */
3762 ipcp_decision_stage (&topo);
3764 /* Free all IPCP structures. */
3765 free_toporder_info (&topo);
3766 next_edge_clone.release ();
3767 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
3768 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
3769 ipa_free_all_structures_after_ipa_cp ();
3770 if (dump_file)
3771 fprintf (dump_file, "\nIPA constant propagation end\n");
3772 return 0;
3775 /* Initialization and computation of IPCP data structures. This is the initial
3776 intraprocedural analysis of functions, which gathers information to be
3777 propagated later on. */
3779 static void
3780 ipcp_generate_summary (void)
3782 struct cgraph_node *node;
3784 if (dump_file)
3785 fprintf (dump_file, "\nIPA constant propagation start:\n");
3786 ipa_register_cgraph_hooks ();
3788 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3790 node->local.versionable
3791 = tree_versionable_function_p (node->decl);
3792 ipa_analyze_node (node);
3796 /* Write ipcp summary for nodes in SET. */
3798 static void
3799 ipcp_write_summary (void)
3801 ipa_prop_write_jump_functions ();
3804 /* Read ipcp summary. */
3806 static void
3807 ipcp_read_summary (void)
3809 ipa_prop_read_jump_functions ();
3812 namespace {
3814 const pass_data pass_data_ipa_cp =
3816 IPA_PASS, /* type */
3817 "cp", /* name */
3818 OPTGROUP_NONE, /* optinfo_flags */
3819 TV_IPA_CONSTANT_PROP, /* tv_id */
3820 0, /* properties_required */
3821 0, /* properties_provided */
3822 0, /* properties_destroyed */
3823 0, /* todo_flags_start */
3824 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
3827 class pass_ipa_cp : public ipa_opt_pass_d
3829 public:
3830 pass_ipa_cp (gcc::context *ctxt)
3831 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
3832 ipcp_generate_summary, /* generate_summary */
3833 ipcp_write_summary, /* write_summary */
3834 ipcp_read_summary, /* read_summary */
3835 ipa_prop_write_all_agg_replacement, /*
3836 write_optimization_summary */
3837 ipa_prop_read_all_agg_replacement, /*
3838 read_optimization_summary */
3839 NULL, /* stmt_fixup */
3840 0, /* function_transform_todo_flags_start */
3841 ipcp_transform_function, /* function_transform */
3842 NULL) /* variable_transform */
3845 /* opt_pass methods: */
3846 virtual bool gate (function *)
3848 /* FIXME: We should remove the optimize check after we ensure we never run
3849 IPA passes when not optimizing. */
3850 return flag_ipa_cp && optimize;
3853 virtual unsigned int execute (function *) { return ipcp_driver (); }
3855 }; // class pass_ipa_cp
3857 } // anon namespace
3859 ipa_opt_pass_d *
3860 make_pass_ipa_cp (gcc::context *ctxt)
3862 return new pass_ipa_cp (ctxt);
3865 /* Reset all state within ipa-cp.c so that we can rerun the compiler
3866 within the same process. For use by toplev::finalize. */
3868 void
3869 ipa_cp_c_finalize (void)
3871 max_count = 0;
3872 overall_size = 0;
3873 max_new_size = 0;
3874 values_topo = NULL;