PR rtl-optimization/88470
[official-gcc.git] / gcc / ipa-cp.c
blobd9ac7d8c35c82eaef7f1ea54805970d2aef0506f
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2018 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 "backend.h"
107 #include "tree.h"
108 #include "gimple-expr.h"
109 #include "predict.h"
110 #include "alloc-pool.h"
111 #include "tree-pass.h"
112 #include "cgraph.h"
113 #include "diagnostic.h"
114 #include "fold-const.h"
115 #include "gimple-fold.h"
116 #include "symbol-summary.h"
117 #include "tree-vrp.h"
118 #include "ipa-prop.h"
119 #include "tree-pretty-print.h"
120 #include "tree-inline.h"
121 #include "params.h"
122 #include "ipa-fnsummary.h"
123 #include "ipa-utils.h"
124 #include "tree-ssa-ccp.h"
125 #include "stringpool.h"
126 #include "attribs.h"
128 template <typename valtype> class ipcp_value;
130 /* Describes a particular source for an IPA-CP value. */
132 template <typename valtype>
133 class ipcp_value_source
135 public:
136 /* Aggregate offset of the source, negative if the source is scalar value of
137 the argument itself. */
138 HOST_WIDE_INT offset;
139 /* The incoming edge that brought the value. */
140 cgraph_edge *cs;
141 /* If the jump function that resulted into his value was a pass-through or an
142 ancestor, this is the ipcp_value of the caller from which the described
143 value has been derived. Otherwise it is NULL. */
144 ipcp_value<valtype> *val;
145 /* Next pointer in a linked list of sources of a value. */
146 ipcp_value_source *next;
147 /* If the jump function that resulted into his value was a pass-through or an
148 ancestor, this is the index of the parameter of the caller the jump
149 function references. */
150 int index;
153 /* Common ancestor for all ipcp_value instantiations. */
155 class ipcp_value_base
157 public:
158 /* Time benefit and size cost that specializing the function for this value
159 would bring about in this function alone. */
160 int local_time_benefit, local_size_cost;
161 /* Time benefit and size cost that specializing the function for this value
162 can bring about in it's callees (transitively). */
163 int prop_time_benefit, prop_size_cost;
165 ipcp_value_base ()
166 : local_time_benefit (0), local_size_cost (0),
167 prop_time_benefit (0), prop_size_cost (0) {}
170 /* Describes one particular value stored in struct ipcp_lattice. */
172 template <typename valtype>
173 class ipcp_value : public ipcp_value_base
175 public:
176 /* The actual value for the given parameter. */
177 valtype value;
178 /* The list of sources from which this value originates. */
179 ipcp_value_source <valtype> *sources;
180 /* Next pointers in a linked list of all values in a lattice. */
181 ipcp_value *next;
182 /* Next pointers in a linked list of values in a strongly connected component
183 of values. */
184 ipcp_value *scc_next;
185 /* Next pointers in a linked list of SCCs of values sorted topologically
186 according their sources. */
187 ipcp_value *topo_next;
188 /* A specialized node created for this value, NULL if none has been (so far)
189 created. */
190 cgraph_node *spec_node;
191 /* Depth first search number and low link for topological sorting of
192 values. */
193 int dfs, low_link;
194 /* True if this valye is currently on the topo-sort stack. */
195 bool on_stack;
197 ipcp_value()
198 : sources (0), next (0), scc_next (0), topo_next (0),
199 spec_node (0), dfs (0), low_link (0), on_stack (false) {}
201 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
202 HOST_WIDE_INT offset);
205 /* Lattice describing potential values of a formal parameter of a function, or
206 a part of an aggregate. TOP is represented by a lattice with zero values
207 and with contains_variable and bottom flags cleared. BOTTOM is represented
208 by a lattice with the bottom flag set. In that case, values and
209 contains_variable flag should be disregarded. */
211 template <typename valtype>
212 class ipcp_lattice
214 public:
215 /* The list of known values and types in this lattice. Note that values are
216 not deallocated if a lattice is set to bottom because there may be value
217 sources referencing them. */
218 ipcp_value<valtype> *values;
219 /* Number of known values and types in this lattice. */
220 int values_count;
221 /* The lattice contains a variable component (in addition to values). */
222 bool contains_variable;
223 /* The value of the lattice is bottom (i.e. variable and unusable for any
224 propagation). */
225 bool bottom;
227 inline bool is_single_const ();
228 inline bool set_to_bottom ();
229 inline bool set_contains_variable ();
230 bool add_value (valtype newval, cgraph_edge *cs,
231 ipcp_value<valtype> *src_val = NULL,
232 int src_idx = 0, HOST_WIDE_INT offset = -1);
233 void print (FILE * f, bool dump_sources, bool dump_benefits);
236 /* Lattice of tree values with an offset to describe a part of an
237 aggregate. */
239 class ipcp_agg_lattice : public ipcp_lattice<tree>
241 public:
242 /* Offset that is being described by this lattice. */
243 HOST_WIDE_INT offset;
244 /* Size so that we don't have to re-compute it every time we traverse the
245 list. Must correspond to TYPE_SIZE of all lat values. */
246 HOST_WIDE_INT size;
247 /* Next element of the linked list. */
248 struct ipcp_agg_lattice *next;
251 /* Lattice of known bits, only capable of holding one value.
252 Bitwise constant propagation propagates which bits of a
253 value are constant.
254 For eg:
255 int f(int x)
257 return some_op (x);
260 int f1(int y)
262 if (cond)
263 return f (y & 0xff);
264 else
265 return f (y & 0xf);
268 In the above case, the param 'x' will always have all
269 the bits (except the bits in lsb) set to 0.
270 Hence the mask of 'x' would be 0xff. The mask
271 reflects that the bits in lsb are unknown.
272 The actual propagated value is given by m_value & ~m_mask. */
274 class ipcp_bits_lattice
276 public:
277 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; }
278 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; }
279 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; }
280 bool set_to_bottom ();
281 bool set_to_constant (widest_int, widest_int);
283 widest_int get_value () { return m_value; }
284 widest_int get_mask () { return m_mask; }
286 bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
287 enum tree_code, tree);
289 bool meet_with (widest_int, widest_int, unsigned);
291 void print (FILE *);
293 private:
294 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
296 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
297 If a bit in mask is set to 0, then the corresponding bit in
298 value is known to be constant. */
299 widest_int m_value, m_mask;
301 bool meet_with_1 (widest_int, widest_int, unsigned);
302 void get_value_and_mask (tree, widest_int *, widest_int *);
305 /* Lattice of value ranges. */
307 class ipcp_vr_lattice
309 public:
310 value_range_base m_vr;
312 inline bool bottom_p () const;
313 inline bool top_p () const;
314 inline bool set_to_bottom ();
315 bool meet_with (const value_range_base *p_vr);
316 bool meet_with (const ipcp_vr_lattice &other);
317 void init () { gcc_assert (m_vr.undefined_p ()); }
318 void print (FILE * f);
320 private:
321 bool meet_with_1 (const value_range_base *other_vr);
324 /* Structure containing lattices for a parameter itself and for pieces of
325 aggregates that are passed in the parameter or by a reference in a parameter
326 plus some other useful flags. */
328 class ipcp_param_lattices
330 public:
331 /* Lattice describing the value of the parameter itself. */
332 ipcp_lattice<tree> itself;
333 /* Lattice describing the polymorphic contexts of a parameter. */
334 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
335 /* Lattices describing aggregate parts. */
336 ipcp_agg_lattice *aggs;
337 /* Lattice describing known bits. */
338 ipcp_bits_lattice bits_lattice;
339 /* Lattice describing value range. */
340 ipcp_vr_lattice m_value_range;
341 /* Number of aggregate lattices */
342 int aggs_count;
343 /* True if aggregate data were passed by reference (as opposed to by
344 value). */
345 bool aggs_by_ref;
346 /* All aggregate lattices contain a variable component (in addition to
347 values). */
348 bool aggs_contain_variable;
349 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
350 for any propagation). */
351 bool aggs_bottom;
353 /* There is a virtual call based on this parameter. */
354 bool virt_call;
357 /* Allocation pools for values and their sources in ipa-cp. */
359 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
360 ("IPA-CP constant values");
362 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
363 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
365 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
366 ("IPA-CP value sources");
368 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
369 ("IPA_CP aggregate lattices");
371 /* Maximal count found in program. */
373 static profile_count max_count;
375 /* Original overall size of the program. */
377 static long overall_size, max_new_size;
379 /* Node name to unique clone suffix number map. */
380 static hash_map<const char *, unsigned> *clone_num_suffixes;
382 /* Return the param lattices structure corresponding to the Ith formal
383 parameter of the function described by INFO. */
384 static inline struct ipcp_param_lattices *
385 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
387 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
388 gcc_checking_assert (!info->ipcp_orig_node);
389 gcc_checking_assert (info->lattices);
390 return &(info->lattices[i]);
393 /* Return the lattice corresponding to the scalar value of the Ith formal
394 parameter of the function described by INFO. */
395 static inline ipcp_lattice<tree> *
396 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
398 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
399 return &plats->itself;
402 /* Return the lattice corresponding to the scalar value of the Ith formal
403 parameter of the function described by INFO. */
404 static inline ipcp_lattice<ipa_polymorphic_call_context> *
405 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
407 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
408 return &plats->ctxlat;
411 /* Return whether LAT is a lattice with a single constant and without an
412 undefined value. */
414 template <typename valtype>
415 inline bool
416 ipcp_lattice<valtype>::is_single_const ()
418 if (bottom || contains_variable || values_count != 1)
419 return false;
420 else
421 return true;
424 /* Print V which is extracted from a value in a lattice to F. */
426 static void
427 print_ipcp_constant_value (FILE * f, tree v)
429 if (TREE_CODE (v) == ADDR_EXPR
430 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
432 fprintf (f, "& ");
433 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)));
435 else
436 print_generic_expr (f, v);
439 /* Print V which is extracted from a value in a lattice to F. */
441 static void
442 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
444 v.dump(f, false);
447 /* Print a lattice LAT to F. */
449 template <typename valtype>
450 void
451 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
453 ipcp_value<valtype> *val;
454 bool prev = false;
456 if (bottom)
458 fprintf (f, "BOTTOM\n");
459 return;
462 if (!values_count && !contains_variable)
464 fprintf (f, "TOP\n");
465 return;
468 if (contains_variable)
470 fprintf (f, "VARIABLE");
471 prev = true;
472 if (dump_benefits)
473 fprintf (f, "\n");
476 for (val = values; val; val = val->next)
478 if (dump_benefits && prev)
479 fprintf (f, " ");
480 else if (!dump_benefits && prev)
481 fprintf (f, ", ");
482 else
483 prev = true;
485 print_ipcp_constant_value (f, val->value);
487 if (dump_sources)
489 ipcp_value_source<valtype> *s;
491 fprintf (f, " [from:");
492 for (s = val->sources; s; s = s->next)
493 fprintf (f, " %i(%f)", s->cs->caller->order,
494 s->cs->sreal_frequency ().to_double ());
495 fprintf (f, "]");
498 if (dump_benefits)
499 fprintf (f, " [loc_time: %i, loc_size: %i, "
500 "prop_time: %i, prop_size: %i]\n",
501 val->local_time_benefit, val->local_size_cost,
502 val->prop_time_benefit, val->prop_size_cost);
504 if (!dump_benefits)
505 fprintf (f, "\n");
508 void
509 ipcp_bits_lattice::print (FILE *f)
511 if (top_p ())
512 fprintf (f, " Bits unknown (TOP)\n");
513 else if (bottom_p ())
514 fprintf (f, " Bits unusable (BOTTOM)\n");
515 else
517 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
518 fprintf (f, ", mask = "); print_hex (get_mask (), f);
519 fprintf (f, "\n");
523 /* Print value range lattice to F. */
525 void
526 ipcp_vr_lattice::print (FILE * f)
528 dump_value_range (f, &m_vr);
531 /* Print all ipcp_lattices of all functions to F. */
533 static void
534 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
536 struct cgraph_node *node;
537 int i, count;
539 fprintf (f, "\nLattices:\n");
540 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
542 struct ipa_node_params *info;
544 info = IPA_NODE_REF (node);
545 fprintf (f, " Node: %s:\n", node->dump_name ());
546 count = ipa_get_param_count (info);
547 for (i = 0; i < count; i++)
549 struct ipcp_agg_lattice *aglat;
550 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
551 fprintf (f, " param [%d]: ", i);
552 plats->itself.print (f, dump_sources, dump_benefits);
553 fprintf (f, " ctxs: ");
554 plats->ctxlat.print (f, dump_sources, dump_benefits);
555 plats->bits_lattice.print (f);
556 fprintf (f, " ");
557 plats->m_value_range.print (f);
558 fprintf (f, "\n");
559 if (plats->virt_call)
560 fprintf (f, " virt_call flag set\n");
562 if (plats->aggs_bottom)
564 fprintf (f, " AGGS BOTTOM\n");
565 continue;
567 if (plats->aggs_contain_variable)
568 fprintf (f, " AGGS VARIABLE\n");
569 for (aglat = plats->aggs; aglat; aglat = aglat->next)
571 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
572 plats->aggs_by_ref ? "ref " : "", aglat->offset);
573 aglat->print (f, dump_sources, dump_benefits);
579 /* Determine whether it is at all technically possible to create clones of NODE
580 and store this information in the ipa_node_params structure associated
581 with NODE. */
583 static void
584 determine_versionability (struct cgraph_node *node,
585 struct ipa_node_params *info)
587 const char *reason = NULL;
589 /* There are a number of generic reasons functions cannot be versioned. We
590 also cannot remove parameters if there are type attributes such as fnspec
591 present. */
592 if (node->alias || node->thunk.thunk_p)
593 reason = "alias or thunk";
594 else if (!node->local.versionable)
595 reason = "not a tree_versionable_function";
596 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
597 reason = "insufficient body availability";
598 else if (!opt_for_fn (node->decl, optimize)
599 || !opt_for_fn (node->decl, flag_ipa_cp))
600 reason = "non-optimized function";
601 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
603 /* Ideally we should clone the SIMD clones themselves and create
604 vector copies of them, so IPA-cp and SIMD clones can happily
605 coexist, but that may not be worth the effort. */
606 reason = "function has SIMD clones";
608 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
610 /* Ideally we should clone the target clones themselves and create
611 copies of them, so IPA-cp and target clones can happily
612 coexist, but that may not be worth the effort. */
613 reason = "function target_clones attribute";
615 /* Don't clone decls local to a comdat group; it breaks and for C++
616 decloned constructors, inlining is always better anyway. */
617 else if (node->comdat_local_p ())
618 reason = "comdat-local function";
619 else if (node->calls_comdat_local)
621 /* TODO: call is versionable if we make sure that all
622 callers are inside of a comdat group. */
623 reason = "calls comdat-local function";
626 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
627 work only when inlined. Cloning them may still lead to better code
628 because ipa-cp will not give up on cloning further. If the function is
629 external this however leads to wrong code because we may end up producing
630 offline copy of the function. */
631 if (DECL_EXTERNAL (node->decl))
632 for (cgraph_edge *edge = node->callees; !reason && edge;
633 edge = edge->next_callee)
634 if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL))
636 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
637 reason = "external function which calls va_arg_pack";
638 if (DECL_FUNCTION_CODE (edge->callee->decl)
639 == BUILT_IN_VA_ARG_PACK_LEN)
640 reason = "external function which calls va_arg_pack_len";
643 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
644 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
645 node->dump_name (), reason);
647 info->versionable = (reason == NULL);
650 /* Return true if it is at all technically possible to create clones of a
651 NODE. */
653 static bool
654 ipcp_versionable_function_p (struct cgraph_node *node)
656 return IPA_NODE_REF (node)->versionable;
659 /* Structure holding accumulated information about callers of a node. */
661 struct caller_statistics
663 profile_count count_sum;
664 int n_calls, n_hot_calls, freq_sum;
667 /* Initialize fields of STAT to zeroes. */
669 static inline void
670 init_caller_stats (struct caller_statistics *stats)
672 stats->count_sum = profile_count::zero ();
673 stats->n_calls = 0;
674 stats->n_hot_calls = 0;
675 stats->freq_sum = 0;
678 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
679 non-thunk incoming edges to NODE. */
681 static bool
682 gather_caller_stats (struct cgraph_node *node, void *data)
684 struct caller_statistics *stats = (struct caller_statistics *) data;
685 struct cgraph_edge *cs;
687 for (cs = node->callers; cs; cs = cs->next_caller)
688 if (!cs->caller->thunk.thunk_p)
690 if (cs->count.ipa ().initialized_p ())
691 stats->count_sum += cs->count.ipa ();
692 stats->freq_sum += cs->frequency ();
693 stats->n_calls++;
694 if (cs->maybe_hot_p ())
695 stats->n_hot_calls ++;
697 return false;
701 /* Return true if this NODE is viable candidate for cloning. */
703 static bool
704 ipcp_cloning_candidate_p (struct cgraph_node *node)
706 struct caller_statistics stats;
708 gcc_checking_assert (node->has_gimple_body_p ());
710 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
712 if (dump_file)
713 fprintf (dump_file, "Not considering %s for cloning; "
714 "-fipa-cp-clone disabled.\n",
715 node->name ());
716 return false;
719 if (node->optimize_for_size_p ())
721 if (dump_file)
722 fprintf (dump_file, "Not considering %s for cloning; "
723 "optimizing it for size.\n",
724 node->name ());
725 return false;
728 init_caller_stats (&stats);
729 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
731 if (ipa_fn_summaries->get (node)->self_size < stats.n_calls)
733 if (dump_file)
734 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
735 node->name ());
736 return true;
739 /* When profile is available and function is hot, propagate into it even if
740 calls seems cold; constant propagation can improve function's speed
741 significantly. */
742 if (max_count > profile_count::zero ())
744 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100))
746 if (dump_file)
747 fprintf (dump_file, "Considering %s for cloning; "
748 "usually called directly.\n",
749 node->name ());
750 return true;
753 if (!stats.n_hot_calls)
755 if (dump_file)
756 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
757 node->name ());
758 return false;
760 if (dump_file)
761 fprintf (dump_file, "Considering %s for cloning.\n",
762 node->name ());
763 return true;
766 template <typename valtype>
767 class value_topo_info
769 public:
770 /* Head of the linked list of topologically sorted values. */
771 ipcp_value<valtype> *values_topo;
772 /* Stack for creating SCCs, represented by a linked list too. */
773 ipcp_value<valtype> *stack;
774 /* Counter driving the algorithm in add_val_to_toposort. */
775 int dfs_counter;
777 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
779 void add_val (ipcp_value<valtype> *cur_val);
780 void propagate_effects ();
783 /* Arrays representing a topological ordering of call graph nodes and a stack
784 of nodes used during constant propagation and also data required to perform
785 topological sort of values and propagation of benefits in the determined
786 order. */
788 class ipa_topo_info
790 public:
791 /* Array with obtained topological order of cgraph nodes. */
792 struct cgraph_node **order;
793 /* Stack of cgraph nodes used during propagation within SCC until all values
794 in the SCC stabilize. */
795 struct cgraph_node **stack;
796 int nnodes, stack_top;
798 value_topo_info<tree> constants;
799 value_topo_info<ipa_polymorphic_call_context> contexts;
801 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
802 constants ()
806 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
808 static void
809 build_toporder_info (struct ipa_topo_info *topo)
811 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
812 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
814 gcc_checking_assert (topo->stack_top == 0);
815 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
818 /* Free information about strongly connected components and the arrays in
819 TOPO. */
821 static void
822 free_toporder_info (struct ipa_topo_info *topo)
824 ipa_free_postorder_info ();
825 free (topo->order);
826 free (topo->stack);
829 /* Add NODE to the stack in TOPO, unless it is already there. */
831 static inline void
832 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
834 struct ipa_node_params *info = IPA_NODE_REF (node);
835 if (info->node_enqueued)
836 return;
837 info->node_enqueued = 1;
838 topo->stack[topo->stack_top++] = node;
841 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
842 is empty. */
844 static struct cgraph_node *
845 pop_node_from_stack (struct ipa_topo_info *topo)
847 if (topo->stack_top)
849 struct cgraph_node *node;
850 topo->stack_top--;
851 node = topo->stack[topo->stack_top];
852 IPA_NODE_REF (node)->node_enqueued = 0;
853 return node;
855 else
856 return NULL;
859 /* Set lattice LAT to bottom and return true if it previously was not set as
860 such. */
862 template <typename valtype>
863 inline bool
864 ipcp_lattice<valtype>::set_to_bottom ()
866 bool ret = !bottom;
867 bottom = true;
868 return ret;
871 /* Mark lattice as containing an unknown value and return true if it previously
872 was not marked as such. */
874 template <typename valtype>
875 inline bool
876 ipcp_lattice<valtype>::set_contains_variable ()
878 bool ret = !contains_variable;
879 contains_variable = true;
880 return ret;
883 /* Set all aggegate lattices in PLATS to bottom and return true if they were
884 not previously set as such. */
886 static inline bool
887 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
889 bool ret = !plats->aggs_bottom;
890 plats->aggs_bottom = true;
891 return ret;
894 /* Mark all aggegate lattices in PLATS as containing an unknown value and
895 return true if they were not previously marked as such. */
897 static inline bool
898 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
900 bool ret = !plats->aggs_contain_variable;
901 plats->aggs_contain_variable = true;
902 return ret;
905 bool
906 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
908 return meet_with_1 (&other.m_vr);
911 /* Meet the current value of the lattice with value ranfge described by VR
912 lattice. */
914 bool
915 ipcp_vr_lattice::meet_with (const value_range_base *p_vr)
917 return meet_with_1 (p_vr);
920 /* Meet the current value of the lattice with value range described by
921 OTHER_VR lattice. Return TRUE if anything changed. */
923 bool
924 ipcp_vr_lattice::meet_with_1 (const value_range_base *other_vr)
926 if (bottom_p ())
927 return false;
929 if (other_vr->varying_p ())
930 return set_to_bottom ();
932 value_range_base save (m_vr);
933 m_vr.union_ (other_vr);
934 return !m_vr.equal_p (save);
937 /* Return true if value range information in the lattice is yet unknown. */
939 bool
940 ipcp_vr_lattice::top_p () const
942 return m_vr.undefined_p ();
945 /* Return true if value range information in the lattice is known to be
946 unusable. */
948 bool
949 ipcp_vr_lattice::bottom_p () const
951 return m_vr.varying_p ();
954 /* Set value range information in the lattice to bottom. Return true if it
955 previously was in a different state. */
957 bool
958 ipcp_vr_lattice::set_to_bottom ()
960 if (m_vr.varying_p ())
961 return false;
962 m_vr.set_varying ();
963 return true;
966 /* Set lattice value to bottom, if it already isn't the case. */
968 bool
969 ipcp_bits_lattice::set_to_bottom ()
971 if (bottom_p ())
972 return false;
973 m_lattice_val = IPA_BITS_VARYING;
974 m_value = 0;
975 m_mask = -1;
976 return true;
979 /* Set to constant if it isn't already. Only meant to be called
980 when switching state from TOP. */
982 bool
983 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
985 gcc_assert (top_p ());
986 m_lattice_val = IPA_BITS_CONSTANT;
987 m_value = value;
988 m_mask = mask;
989 return true;
992 /* Convert operand to value, mask form. */
994 void
995 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
997 wide_int get_nonzero_bits (const_tree);
999 if (TREE_CODE (operand) == INTEGER_CST)
1001 *valuep = wi::to_widest (operand);
1002 *maskp = 0;
1004 else
1006 *valuep = 0;
1007 *maskp = -1;
1011 /* Meet operation, similar to ccp_lattice_meet, we xor values
1012 if this->value, value have different values at same bit positions, we want
1013 to drop that bit to varying. Return true if mask is changed.
1014 This function assumes that the lattice value is in CONSTANT state */
1016 bool
1017 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
1018 unsigned precision)
1020 gcc_assert (constant_p ());
1022 widest_int old_mask = m_mask;
1023 m_mask = (m_mask | mask) | (m_value ^ value);
1025 if (wi::sext (m_mask, precision) == -1)
1026 return set_to_bottom ();
1028 return m_mask != old_mask;
1031 /* Meet the bits lattice with operand
1032 described by <value, mask, sgn, precision. */
1034 bool
1035 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1036 unsigned precision)
1038 if (bottom_p ())
1039 return false;
1041 if (top_p ())
1043 if (wi::sext (mask, precision) == -1)
1044 return set_to_bottom ();
1045 return set_to_constant (value, mask);
1048 return meet_with_1 (value, mask, precision);
1051 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1052 if code is binary operation or bit_value_unop (other) if code is unary op.
1053 In the case when code is nop_expr, no adjustment is required. */
1055 bool
1056 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1057 signop sgn, enum tree_code code, tree operand)
1059 if (other.bottom_p ())
1060 return set_to_bottom ();
1062 if (bottom_p () || other.top_p ())
1063 return false;
1065 widest_int adjusted_value, adjusted_mask;
1067 if (TREE_CODE_CLASS (code) == tcc_binary)
1069 tree type = TREE_TYPE (operand);
1070 gcc_assert (INTEGRAL_TYPE_P (type));
1071 widest_int o_value, o_mask;
1072 get_value_and_mask (operand, &o_value, &o_mask);
1074 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1075 sgn, precision, other.get_value (), other.get_mask (),
1076 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1078 if (wi::sext (adjusted_mask, precision) == -1)
1079 return set_to_bottom ();
1082 else if (TREE_CODE_CLASS (code) == tcc_unary)
1084 bit_value_unop (code, sgn, precision, &adjusted_value,
1085 &adjusted_mask, sgn, precision, other.get_value (),
1086 other.get_mask ());
1088 if (wi::sext (adjusted_mask, precision) == -1)
1089 return set_to_bottom ();
1092 else
1093 return set_to_bottom ();
1095 if (top_p ())
1097 if (wi::sext (adjusted_mask, precision) == -1)
1098 return set_to_bottom ();
1099 return set_to_constant (adjusted_value, adjusted_mask);
1101 else
1102 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1105 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1106 return true is any of them has not been marked as such so far. */
1108 static inline bool
1109 set_all_contains_variable (struct ipcp_param_lattices *plats)
1111 bool ret;
1112 ret = plats->itself.set_contains_variable ();
1113 ret |= plats->ctxlat.set_contains_variable ();
1114 ret |= set_agg_lats_contain_variable (plats);
1115 ret |= plats->bits_lattice.set_to_bottom ();
1116 ret |= plats->m_value_range.set_to_bottom ();
1117 return ret;
1120 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1121 points to by the number of callers to NODE. */
1123 static bool
1124 count_callers (cgraph_node *node, void *data)
1126 int *caller_count = (int *) data;
1128 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1129 /* Local thunks can be handled transparently, but if the thunk can not
1130 be optimized out, count it as a real use. */
1131 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
1132 ++*caller_count;
1133 return false;
1136 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1137 the one caller of some other node. Set the caller's corresponding flag. */
1139 static bool
1140 set_single_call_flag (cgraph_node *node, void *)
1142 cgraph_edge *cs = node->callers;
1143 /* Local thunks can be handled transparently, skip them. */
1144 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
1145 cs = cs->next_caller;
1146 if (cs)
1148 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1149 return true;
1151 return false;
1154 /* Initialize ipcp_lattices. */
1156 static void
1157 initialize_node_lattices (struct cgraph_node *node)
1159 struct ipa_node_params *info = IPA_NODE_REF (node);
1160 struct cgraph_edge *ie;
1161 bool disable = false, variable = false;
1162 int i;
1164 gcc_checking_assert (node->has_gimple_body_p ());
1165 if (node->local.local)
1167 int caller_count = 0;
1168 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1169 true);
1170 gcc_checking_assert (caller_count > 0);
1171 if (caller_count == 1)
1172 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1173 NULL, true);
1175 else
1177 /* When cloning is allowed, we can assume that externally visible
1178 functions are not called. We will compensate this by cloning
1179 later. */
1180 if (ipcp_versionable_function_p (node)
1181 && ipcp_cloning_candidate_p (node))
1182 variable = true;
1183 else
1184 disable = true;
1187 for (i = 0; i < ipa_get_param_count (info); i++)
1189 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1190 plats->m_value_range.init ();
1193 if (disable || variable)
1195 for (i = 0; i < ipa_get_param_count (info); i++)
1197 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1198 if (disable)
1200 plats->itself.set_to_bottom ();
1201 plats->ctxlat.set_to_bottom ();
1202 set_agg_lats_to_bottom (plats);
1203 plats->bits_lattice.set_to_bottom ();
1204 plats->m_value_range.set_to_bottom ();
1206 else
1207 set_all_contains_variable (plats);
1209 if (dump_file && (dump_flags & TDF_DETAILS)
1210 && !node->alias && !node->thunk.thunk_p)
1211 fprintf (dump_file, "Marking all lattices of %s as %s\n",
1212 node->dump_name (), disable ? "BOTTOM" : "VARIABLE");
1215 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1216 if (ie->indirect_info->polymorphic
1217 && ie->indirect_info->param_index >= 0)
1219 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1220 ipa_get_parm_lattices (info,
1221 ie->indirect_info->param_index)->virt_call = 1;
1225 /* Return the result of a (possibly arithmetic) pass through jump function
1226 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter
1227 to which the result is passed. Return NULL_TREE if that cannot be
1228 determined or be considered an interprocedural invariant. */
1230 static tree
1231 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input,
1232 tree res_type)
1234 tree res;
1236 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1237 return input;
1238 if (!is_gimple_ip_invariant (input))
1239 return NULL_TREE;
1241 tree_code opcode = ipa_get_jf_pass_through_operation (jfunc);
1242 if (!res_type)
1244 if (TREE_CODE_CLASS (opcode) == tcc_comparison)
1245 res_type = boolean_type_node;
1246 else if (expr_type_first_operand_type_p (opcode))
1247 res_type = TREE_TYPE (input);
1248 else
1249 return NULL_TREE;
1252 if (TREE_CODE_CLASS (opcode) == tcc_unary)
1253 res = fold_unary (opcode, res_type, input);
1254 else
1255 res = fold_binary (opcode, res_type, input,
1256 ipa_get_jf_pass_through_operand (jfunc));
1258 if (res && !is_gimple_ip_invariant (res))
1259 return NULL_TREE;
1261 return res;
1264 /* Return the result of an ancestor jump function JFUNC on the constant value
1265 INPUT. Return NULL_TREE if that cannot be determined. */
1267 static tree
1268 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1270 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1271 if (TREE_CODE (input) == ADDR_EXPR)
1273 tree t = TREE_OPERAND (input, 0);
1274 t = build_ref_for_offset (EXPR_LOCATION (t), t,
1275 ipa_get_jf_ancestor_offset (jfunc), false,
1276 ptr_type_node, NULL, false);
1277 return build_fold_addr_expr (t);
1279 else
1280 return NULL_TREE;
1283 /* Determine whether JFUNC evaluates to a single known constant value and if
1284 so, return it. Otherwise return NULL. INFO describes the caller node or
1285 the one it is inlined to, so that pass-through jump functions can be
1286 evaluated. PARM_TYPE is the type of the parameter to which the result is
1287 passed. */
1289 tree
1290 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc,
1291 tree parm_type)
1293 if (jfunc->type == IPA_JF_CONST)
1294 return ipa_get_jf_constant (jfunc);
1295 else if (jfunc->type == IPA_JF_PASS_THROUGH
1296 || jfunc->type == IPA_JF_ANCESTOR)
1298 tree input;
1299 int idx;
1301 if (jfunc->type == IPA_JF_PASS_THROUGH)
1302 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1303 else
1304 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1306 if (info->ipcp_orig_node)
1307 input = info->known_csts[idx];
1308 else
1310 ipcp_lattice<tree> *lat;
1312 if (!info->lattices
1313 || idx >= ipa_get_param_count (info))
1314 return NULL_TREE;
1315 lat = ipa_get_scalar_lat (info, idx);
1316 if (!lat->is_single_const ())
1317 return NULL_TREE;
1318 input = lat->values->value;
1321 if (!input)
1322 return NULL_TREE;
1324 if (jfunc->type == IPA_JF_PASS_THROUGH)
1325 return ipa_get_jf_pass_through_result (jfunc, input, parm_type);
1326 else
1327 return ipa_get_jf_ancestor_result (jfunc, input);
1329 else
1330 return NULL_TREE;
1333 /* Determie whether JFUNC evaluates to single known polymorphic context, given
1334 that INFO describes the caller node or the one it is inlined to, CS is the
1335 call graph edge corresponding to JFUNC and CSIDX index of the described
1336 parameter. */
1338 ipa_polymorphic_call_context
1339 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1340 ipa_jump_func *jfunc)
1342 ipa_edge_args *args = IPA_EDGE_REF (cs);
1343 ipa_polymorphic_call_context ctx;
1344 ipa_polymorphic_call_context *edge_ctx
1345 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1347 if (edge_ctx && !edge_ctx->useless_p ())
1348 ctx = *edge_ctx;
1350 if (jfunc->type == IPA_JF_PASS_THROUGH
1351 || jfunc->type == IPA_JF_ANCESTOR)
1353 ipa_polymorphic_call_context srcctx;
1354 int srcidx;
1355 bool type_preserved = true;
1356 if (jfunc->type == IPA_JF_PASS_THROUGH)
1358 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1359 return ctx;
1360 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1361 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1363 else
1365 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1366 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1368 if (info->ipcp_orig_node)
1370 if (info->known_contexts.exists ())
1371 srcctx = info->known_contexts[srcidx];
1373 else
1375 if (!info->lattices
1376 || srcidx >= ipa_get_param_count (info))
1377 return ctx;
1378 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1379 lat = ipa_get_poly_ctx_lat (info, srcidx);
1380 if (!lat->is_single_const ())
1381 return ctx;
1382 srcctx = lat->values->value;
1384 if (srcctx.useless_p ())
1385 return ctx;
1386 if (jfunc->type == IPA_JF_ANCESTOR)
1387 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1388 if (!type_preserved)
1389 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1390 srcctx.combine_with (ctx);
1391 return srcctx;
1394 return ctx;
1397 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1398 bottom, not containing a variable component and without any known value at
1399 the same time. */
1401 DEBUG_FUNCTION void
1402 ipcp_verify_propagated_values (void)
1404 struct cgraph_node *node;
1406 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1408 struct ipa_node_params *info = IPA_NODE_REF (node);
1409 int i, count = ipa_get_param_count (info);
1411 for (i = 0; i < count; i++)
1413 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1415 if (!lat->bottom
1416 && !lat->contains_variable
1417 && lat->values_count == 0)
1419 if (dump_file)
1421 symtab->dump (dump_file);
1422 fprintf (dump_file, "\nIPA lattices after constant "
1423 "propagation, before gcc_unreachable:\n");
1424 print_all_lattices (dump_file, true, false);
1427 gcc_unreachable ();
1433 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1435 static bool
1436 values_equal_for_ipcp_p (tree x, tree y)
1438 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1440 if (x == y)
1441 return true;
1443 if (TREE_CODE (x) == ADDR_EXPR
1444 && TREE_CODE (y) == ADDR_EXPR
1445 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1446 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1447 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1448 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1449 else
1450 return operand_equal_p (x, y, 0);
1453 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1455 static bool
1456 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1457 ipa_polymorphic_call_context y)
1459 return x.equal_to (y);
1463 /* Add a new value source to the value represented by THIS, marking that a
1464 value comes from edge CS and (if the underlying jump function is a
1465 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1466 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1467 scalar value of the parameter itself or the offset within an aggregate. */
1469 template <typename valtype>
1470 void
1471 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1472 int src_idx, HOST_WIDE_INT offset)
1474 ipcp_value_source<valtype> *src;
1476 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1477 src->offset = offset;
1478 src->cs = cs;
1479 src->val = src_val;
1480 src->index = src_idx;
1482 src->next = sources;
1483 sources = src;
1486 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1487 SOURCE and clear all other fields. */
1489 static ipcp_value<tree> *
1490 allocate_and_init_ipcp_value (tree source)
1492 ipcp_value<tree> *val;
1494 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1495 val->value = source;
1496 return val;
1499 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1500 value to SOURCE and clear all other fields. */
1502 static ipcp_value<ipa_polymorphic_call_context> *
1503 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1505 ipcp_value<ipa_polymorphic_call_context> *val;
1507 // TODO
1508 val = new (ipcp_poly_ctx_values_pool.allocate ())
1509 ipcp_value<ipa_polymorphic_call_context>();
1510 val->value = source;
1511 return val;
1514 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1515 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1516 meaning. OFFSET -1 means the source is scalar and not a part of an
1517 aggregate. */
1519 template <typename valtype>
1520 bool
1521 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1522 ipcp_value<valtype> *src_val,
1523 int src_idx, HOST_WIDE_INT offset)
1525 ipcp_value<valtype> *val;
1527 if (bottom)
1528 return false;
1530 for (val = values; val; val = val->next)
1531 if (values_equal_for_ipcp_p (val->value, newval))
1533 if (ipa_edge_within_scc (cs))
1535 ipcp_value_source<valtype> *s;
1536 for (s = val->sources; s; s = s->next)
1537 if (s->cs == cs)
1538 break;
1539 if (s)
1540 return false;
1543 val->add_source (cs, src_val, src_idx, offset);
1544 return false;
1547 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1549 /* We can only free sources, not the values themselves, because sources
1550 of other values in this SCC might point to them. */
1551 for (val = values; val; val = val->next)
1553 while (val->sources)
1555 ipcp_value_source<valtype> *src = val->sources;
1556 val->sources = src->next;
1557 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1561 values = NULL;
1562 return set_to_bottom ();
1565 values_count++;
1566 val = allocate_and_init_ipcp_value (newval);
1567 val->add_source (cs, src_val, src_idx, offset);
1568 val->next = values;
1569 values = val;
1570 return true;
1573 /* Propagate values through a pass-through jump function JFUNC associated with
1574 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1575 is the index of the source parameter. PARM_TYPE is the type of the
1576 parameter to which the result is passed. */
1578 static bool
1579 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
1580 ipcp_lattice<tree> *src_lat,
1581 ipcp_lattice<tree> *dest_lat, int src_idx,
1582 tree parm_type)
1584 ipcp_value<tree> *src_val;
1585 bool ret = false;
1587 /* Do not create new values when propagating within an SCC because if there
1588 are arithmetic functions with circular dependencies, there is infinite
1589 number of them and we would just make lattices bottom. If this condition
1590 is ever relaxed we have to detect self-feeding recursive calls in
1591 cgraph_edge_brings_value_p in a smarter way. */
1592 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1593 && ipa_edge_within_scc (cs))
1594 ret = dest_lat->set_contains_variable ();
1595 else
1596 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1598 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value,
1599 parm_type);
1601 if (cstval)
1602 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1603 else
1604 ret |= dest_lat->set_contains_variable ();
1607 return ret;
1610 /* Propagate values through an ancestor jump function JFUNC associated with
1611 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1612 is the index of the source parameter. */
1614 static bool
1615 propagate_vals_across_ancestor (struct cgraph_edge *cs,
1616 struct ipa_jump_func *jfunc,
1617 ipcp_lattice<tree> *src_lat,
1618 ipcp_lattice<tree> *dest_lat, int src_idx)
1620 ipcp_value<tree> *src_val;
1621 bool ret = false;
1623 if (ipa_edge_within_scc (cs))
1624 return dest_lat->set_contains_variable ();
1626 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1628 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1630 if (t)
1631 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1632 else
1633 ret |= dest_lat->set_contains_variable ();
1636 return ret;
1639 /* Propagate scalar values across jump function JFUNC that is associated with
1640 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the
1641 parameter to which the result is passed. */
1643 static bool
1644 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
1645 struct ipa_jump_func *jfunc,
1646 ipcp_lattice<tree> *dest_lat,
1647 tree param_type)
1649 if (dest_lat->bottom)
1650 return false;
1652 if (jfunc->type == IPA_JF_CONST)
1654 tree val = ipa_get_jf_constant (jfunc);
1655 return dest_lat->add_value (val, cs, NULL, 0);
1657 else if (jfunc->type == IPA_JF_PASS_THROUGH
1658 || jfunc->type == IPA_JF_ANCESTOR)
1660 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1661 ipcp_lattice<tree> *src_lat;
1662 int src_idx;
1663 bool ret;
1665 if (jfunc->type == IPA_JF_PASS_THROUGH)
1666 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1667 else
1668 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1670 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1671 if (src_lat->bottom)
1672 return dest_lat->set_contains_variable ();
1674 /* If we would need to clone the caller and cannot, do not propagate. */
1675 if (!ipcp_versionable_function_p (cs->caller)
1676 && (src_lat->contains_variable
1677 || (src_lat->values_count > 1)))
1678 return dest_lat->set_contains_variable ();
1680 if (jfunc->type == IPA_JF_PASS_THROUGH)
1681 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
1682 dest_lat, src_idx, param_type);
1683 else
1684 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
1685 src_idx);
1687 if (src_lat->contains_variable)
1688 ret |= dest_lat->set_contains_variable ();
1690 return ret;
1693 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1694 use it for indirect inlining), we should propagate them too. */
1695 return dest_lat->set_contains_variable ();
1698 /* Propagate scalar values across jump function JFUNC that is associated with
1699 edge CS and describes argument IDX and put the values into DEST_LAT. */
1701 static bool
1702 propagate_context_across_jump_function (cgraph_edge *cs,
1703 ipa_jump_func *jfunc, int idx,
1704 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1706 ipa_edge_args *args = IPA_EDGE_REF (cs);
1707 if (dest_lat->bottom)
1708 return false;
1709 bool ret = false;
1710 bool added_sth = false;
1711 bool type_preserved = true;
1713 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1714 = ipa_get_ith_polymorhic_call_context (args, idx);
1716 if (edge_ctx_ptr)
1717 edge_ctx = *edge_ctx_ptr;
1719 if (jfunc->type == IPA_JF_PASS_THROUGH
1720 || jfunc->type == IPA_JF_ANCESTOR)
1722 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1723 int src_idx;
1724 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1726 /* TODO: Once we figure out how to propagate speculations, it will
1727 probably be a good idea to switch to speculation if type_preserved is
1728 not set instead of punting. */
1729 if (jfunc->type == IPA_JF_PASS_THROUGH)
1731 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1732 goto prop_fail;
1733 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1734 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1736 else
1738 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1739 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1742 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1743 /* If we would need to clone the caller and cannot, do not propagate. */
1744 if (!ipcp_versionable_function_p (cs->caller)
1745 && (src_lat->contains_variable
1746 || (src_lat->values_count > 1)))
1747 goto prop_fail;
1749 ipcp_value<ipa_polymorphic_call_context> *src_val;
1750 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1752 ipa_polymorphic_call_context cur = src_val->value;
1754 if (!type_preserved)
1755 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1756 if (jfunc->type == IPA_JF_ANCESTOR)
1757 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1758 /* TODO: In cases we know how the context is going to be used,
1759 we can improve the result by passing proper OTR_TYPE. */
1760 cur.combine_with (edge_ctx);
1761 if (!cur.useless_p ())
1763 if (src_lat->contains_variable
1764 && !edge_ctx.equal_to (cur))
1765 ret |= dest_lat->set_contains_variable ();
1766 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1767 added_sth = true;
1773 prop_fail:
1774 if (!added_sth)
1776 if (!edge_ctx.useless_p ())
1777 ret |= dest_lat->add_value (edge_ctx, cs);
1778 else
1779 ret |= dest_lat->set_contains_variable ();
1782 return ret;
1785 /* Propagate bits across jfunc that is associated with
1786 edge cs and update dest_lattice accordingly. */
1788 bool
1789 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
1790 ipa_jump_func *jfunc,
1791 ipcp_bits_lattice *dest_lattice)
1793 if (dest_lattice->bottom_p ())
1794 return false;
1796 enum availability availability;
1797 cgraph_node *callee = cs->callee->function_symbol (&availability);
1798 struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
1799 tree parm_type = ipa_get_type (callee_info, idx);
1801 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the
1802 transform for these cases. Similarly, we can have bad type mismatches
1803 with LTO, avoid doing anything with those too. */
1804 if (!parm_type
1805 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type)))
1807 if (dump_file && (dump_flags & TDF_DETAILS))
1808 fprintf (dump_file, "Setting dest_lattice to bottom, because type of "
1809 "param %i of %s is NULL or unsuitable for bits propagation\n",
1810 idx, cs->callee->name ());
1812 return dest_lattice->set_to_bottom ();
1815 unsigned precision = TYPE_PRECISION (parm_type);
1816 signop sgn = TYPE_SIGN (parm_type);
1818 if (jfunc->type == IPA_JF_PASS_THROUGH
1819 || jfunc->type == IPA_JF_ANCESTOR)
1821 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1822 tree operand = NULL_TREE;
1823 enum tree_code code;
1824 unsigned src_idx;
1826 if (jfunc->type == IPA_JF_PASS_THROUGH)
1828 code = ipa_get_jf_pass_through_operation (jfunc);
1829 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1830 if (code != NOP_EXPR)
1831 operand = ipa_get_jf_pass_through_operand (jfunc);
1833 else
1835 code = POINTER_PLUS_EXPR;
1836 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1837 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
1838 operand = build_int_cstu (size_type_node, offset);
1841 struct ipcp_param_lattices *src_lats
1842 = ipa_get_parm_lattices (caller_info, src_idx);
1844 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1845 for eg consider:
1846 int f(int x)
1848 g (x & 0xff);
1850 Assume lattice for x is bottom, however we can still propagate
1851 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1852 and we store it in jump function during analysis stage. */
1854 if (src_lats->bits_lattice.bottom_p ()
1855 && jfunc->bits)
1856 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1857 precision);
1858 else
1859 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
1860 code, operand);
1863 else if (jfunc->type == IPA_JF_ANCESTOR)
1864 return dest_lattice->set_to_bottom ();
1865 else if (jfunc->bits)
1866 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1867 precision);
1868 else
1869 return dest_lattice->set_to_bottom ();
1872 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1873 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1874 the result is a range or an anti-range. */
1876 static bool
1877 ipa_vr_operation_and_type_effects (value_range_base *dst_vr,
1878 value_range_base *src_vr,
1879 enum tree_code operation,
1880 tree dst_type, tree src_type)
1882 extract_range_from_unary_expr (dst_vr, operation, dst_type,
1883 src_vr, src_type);
1884 if (dst_vr->varying_p () || dst_vr->undefined_p ())
1885 return false;
1886 return true;
1889 /* Propagate value range across jump function JFUNC that is associated with
1890 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1891 accordingly. */
1893 static bool
1894 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
1895 struct ipcp_param_lattices *dest_plats,
1896 tree param_type)
1898 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
1900 if (dest_lat->bottom_p ())
1901 return false;
1903 if (!param_type
1904 || (!INTEGRAL_TYPE_P (param_type)
1905 && !POINTER_TYPE_P (param_type)))
1906 return dest_lat->set_to_bottom ();
1908 if (jfunc->type == IPA_JF_PASS_THROUGH)
1910 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1912 if (TREE_CODE_CLASS (operation) == tcc_unary)
1914 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1915 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1916 tree operand_type = ipa_get_type (caller_info, src_idx);
1917 struct ipcp_param_lattices *src_lats
1918 = ipa_get_parm_lattices (caller_info, src_idx);
1920 if (src_lats->m_value_range.bottom_p ())
1921 return dest_lat->set_to_bottom ();
1922 value_range_base vr;
1923 if (ipa_vr_operation_and_type_effects (&vr,
1924 &src_lats->m_value_range.m_vr,
1925 operation, param_type,
1926 operand_type))
1927 return dest_lat->meet_with (&vr);
1930 else if (jfunc->type == IPA_JF_CONST)
1932 tree val = ipa_get_jf_constant (jfunc);
1933 if (TREE_CODE (val) == INTEGER_CST)
1935 val = fold_convert (param_type, val);
1936 if (TREE_OVERFLOW_P (val))
1937 val = drop_tree_overflow (val);
1939 value_range_base tmpvr (VR_RANGE, val, val);
1940 return dest_lat->meet_with (&tmpvr);
1944 value_range_base vr;
1945 if (jfunc->m_vr
1946 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
1947 param_type,
1948 jfunc->m_vr->type ()))
1949 return dest_lat->meet_with (&vr);
1950 else
1951 return dest_lat->set_to_bottom ();
1954 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1955 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1956 other cases, return false). If there are no aggregate items, set
1957 aggs_by_ref to NEW_AGGS_BY_REF. */
1959 static bool
1960 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1961 bool new_aggs_by_ref)
1963 if (dest_plats->aggs)
1965 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1967 set_agg_lats_to_bottom (dest_plats);
1968 return true;
1971 else
1972 dest_plats->aggs_by_ref = new_aggs_by_ref;
1973 return false;
1976 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1977 already existing lattice for the given OFFSET and SIZE, marking all skipped
1978 lattices as containing variable and checking for overlaps. If there is no
1979 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1980 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1981 unless there are too many already. If there are two many, return false. If
1982 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1983 skipped lattices were newly marked as containing variable, set *CHANGE to
1984 true. */
1986 static bool
1987 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1988 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1989 struct ipcp_agg_lattice ***aglat,
1990 bool pre_existing, bool *change)
1992 gcc_checking_assert (offset >= 0);
1994 while (**aglat && (**aglat)->offset < offset)
1996 if ((**aglat)->offset + (**aglat)->size > offset)
1998 set_agg_lats_to_bottom (dest_plats);
1999 return false;
2001 *change |= (**aglat)->set_contains_variable ();
2002 *aglat = &(**aglat)->next;
2005 if (**aglat && (**aglat)->offset == offset)
2007 if ((**aglat)->size != val_size
2008 || ((**aglat)->next
2009 && (**aglat)->next->offset < offset + val_size))
2011 set_agg_lats_to_bottom (dest_plats);
2012 return false;
2014 gcc_checking_assert (!(**aglat)->next
2015 || (**aglat)->next->offset >= offset + val_size);
2016 return true;
2018 else
2020 struct ipcp_agg_lattice *new_al;
2022 if (**aglat && (**aglat)->offset < offset + val_size)
2024 set_agg_lats_to_bottom (dest_plats);
2025 return false;
2027 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
2028 return false;
2029 dest_plats->aggs_count++;
2030 new_al = ipcp_agg_lattice_pool.allocate ();
2031 memset (new_al, 0, sizeof (*new_al));
2033 new_al->offset = offset;
2034 new_al->size = val_size;
2035 new_al->contains_variable = pre_existing;
2037 new_al->next = **aglat;
2038 **aglat = new_al;
2039 return true;
2043 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2044 containing an unknown value. */
2046 static bool
2047 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2049 bool ret = false;
2050 while (aglat)
2052 ret |= aglat->set_contains_variable ();
2053 aglat = aglat->next;
2055 return ret;
2058 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2059 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2060 parameter used for lattice value sources. Return true if DEST_PLATS changed
2061 in any way. */
2063 static bool
2064 merge_aggregate_lattices (struct cgraph_edge *cs,
2065 struct ipcp_param_lattices *dest_plats,
2066 struct ipcp_param_lattices *src_plats,
2067 int src_idx, HOST_WIDE_INT offset_delta)
2069 bool pre_existing = dest_plats->aggs != NULL;
2070 struct ipcp_agg_lattice **dst_aglat;
2071 bool ret = false;
2073 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2074 return true;
2075 if (src_plats->aggs_bottom)
2076 return set_agg_lats_contain_variable (dest_plats);
2077 if (src_plats->aggs_contain_variable)
2078 ret |= set_agg_lats_contain_variable (dest_plats);
2079 dst_aglat = &dest_plats->aggs;
2081 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2082 src_aglat;
2083 src_aglat = src_aglat->next)
2085 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2087 if (new_offset < 0)
2088 continue;
2089 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2090 &dst_aglat, pre_existing, &ret))
2092 struct ipcp_agg_lattice *new_al = *dst_aglat;
2094 dst_aglat = &(*dst_aglat)->next;
2095 if (src_aglat->bottom)
2097 ret |= new_al->set_contains_variable ();
2098 continue;
2100 if (src_aglat->contains_variable)
2101 ret |= new_al->set_contains_variable ();
2102 for (ipcp_value<tree> *val = src_aglat->values;
2103 val;
2104 val = val->next)
2105 ret |= new_al->add_value (val->value, cs, val, src_idx,
2106 src_aglat->offset);
2108 else if (dest_plats->aggs_bottom)
2109 return true;
2111 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2112 return ret;
2115 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2116 pass-through JFUNC and if so, whether it has conform and conforms to the
2117 rules about propagating values passed by reference. */
2119 static bool
2120 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
2121 struct ipa_jump_func *jfunc)
2123 return src_plats->aggs
2124 && (!src_plats->aggs_by_ref
2125 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2128 /* Propagate scalar values across jump function JFUNC that is associated with
2129 edge CS and put the values into DEST_LAT. */
2131 static bool
2132 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2133 struct ipa_jump_func *jfunc,
2134 struct ipcp_param_lattices *dest_plats)
2136 bool ret = false;
2138 if (dest_plats->aggs_bottom)
2139 return false;
2141 if (jfunc->type == IPA_JF_PASS_THROUGH
2142 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2144 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2145 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2146 struct ipcp_param_lattices *src_plats;
2148 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2149 if (agg_pass_through_permissible_p (src_plats, jfunc))
2151 /* Currently we do not produce clobber aggregate jump
2152 functions, replace with merging when we do. */
2153 gcc_assert (!jfunc->agg.items);
2154 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2155 src_idx, 0);
2157 else
2158 ret |= set_agg_lats_contain_variable (dest_plats);
2160 else if (jfunc->type == IPA_JF_ANCESTOR
2161 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2163 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2164 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2165 struct ipcp_param_lattices *src_plats;
2167 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2168 if (src_plats->aggs && src_plats->aggs_by_ref)
2170 /* Currently we do not produce clobber aggregate jump
2171 functions, replace with merging when we do. */
2172 gcc_assert (!jfunc->agg.items);
2173 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2174 ipa_get_jf_ancestor_offset (jfunc));
2176 else if (!src_plats->aggs_by_ref)
2177 ret |= set_agg_lats_to_bottom (dest_plats);
2178 else
2179 ret |= set_agg_lats_contain_variable (dest_plats);
2181 else if (jfunc->agg.items)
2183 bool pre_existing = dest_plats->aggs != NULL;
2184 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2185 struct ipa_agg_jf_item *item;
2186 int i;
2188 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2189 return true;
2191 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2193 HOST_WIDE_INT val_size;
2195 if (item->offset < 0)
2196 continue;
2197 gcc_checking_assert (is_gimple_ip_invariant (item->value));
2198 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2200 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2201 &aglat, pre_existing, &ret))
2203 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2204 aglat = &(*aglat)->next;
2206 else if (dest_plats->aggs_bottom)
2207 return true;
2210 ret |= set_chain_of_aglats_contains_variable (*aglat);
2212 else
2213 ret |= set_agg_lats_contain_variable (dest_plats);
2215 return ret;
2218 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2219 non-thunk) destination, the call passes through a thunk. */
2221 static bool
2222 call_passes_through_thunk_p (cgraph_edge *cs)
2224 cgraph_node *alias_or_thunk = cs->callee;
2225 while (alias_or_thunk->alias)
2226 alias_or_thunk = alias_or_thunk->get_alias_target ();
2227 return alias_or_thunk->thunk.thunk_p;
2230 /* Propagate constants from the caller to the callee of CS. INFO describes the
2231 caller. */
2233 static bool
2234 propagate_constants_across_call (struct cgraph_edge *cs)
2236 struct ipa_node_params *callee_info;
2237 enum availability availability;
2238 cgraph_node *callee;
2239 struct ipa_edge_args *args;
2240 bool ret = false;
2241 int i, args_count, parms_count;
2243 callee = cs->callee->function_symbol (&availability);
2244 if (!callee->definition)
2245 return false;
2246 gcc_checking_assert (callee->has_gimple_body_p ());
2247 callee_info = IPA_NODE_REF (callee);
2249 args = IPA_EDGE_REF (cs);
2250 args_count = ipa_get_cs_argument_count (args);
2251 parms_count = ipa_get_param_count (callee_info);
2252 if (parms_count == 0)
2253 return false;
2255 /* If this call goes through a thunk we must not propagate to the first (0th)
2256 parameter. However, we might need to uncover a thunk from below a series
2257 of aliases first. */
2258 if (call_passes_through_thunk_p (cs))
2260 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2261 0));
2262 i = 1;
2264 else
2265 i = 0;
2267 for (; (i < args_count) && (i < parms_count); i++)
2269 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2270 struct ipcp_param_lattices *dest_plats;
2271 tree param_type = ipa_get_type (callee_info, i);
2273 dest_plats = ipa_get_parm_lattices (callee_info, i);
2274 if (availability == AVAIL_INTERPOSABLE)
2275 ret |= set_all_contains_variable (dest_plats);
2276 else
2278 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2279 &dest_plats->itself,
2280 param_type);
2281 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2282 &dest_plats->ctxlat);
2284 |= propagate_bits_across_jump_function (cs, i, jump_func,
2285 &dest_plats->bits_lattice);
2286 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2287 dest_plats);
2288 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2289 ret |= propagate_vr_across_jump_function (cs, jump_func,
2290 dest_plats, param_type);
2291 else
2292 ret |= dest_plats->m_value_range.set_to_bottom ();
2295 for (; i < parms_count; i++)
2296 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2298 return ret;
2301 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2302 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2303 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2305 static tree
2306 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2307 vec<tree> known_csts,
2308 vec<ipa_polymorphic_call_context> known_contexts,
2309 vec<ipa_agg_jump_function_p> known_aggs,
2310 struct ipa_agg_replacement_value *agg_reps,
2311 bool *speculative)
2313 int param_index = ie->indirect_info->param_index;
2314 HOST_WIDE_INT anc_offset;
2315 tree t;
2316 tree target = NULL;
2318 *speculative = false;
2320 if (param_index == -1
2321 || known_csts.length () <= (unsigned int) param_index)
2322 return NULL_TREE;
2324 if (!ie->indirect_info->polymorphic)
2326 tree t;
2328 if (ie->indirect_info->agg_contents)
2330 t = NULL;
2331 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2333 while (agg_reps)
2335 if (agg_reps->index == param_index
2336 && agg_reps->offset == ie->indirect_info->offset
2337 && agg_reps->by_ref == ie->indirect_info->by_ref)
2339 t = agg_reps->value;
2340 break;
2342 agg_reps = agg_reps->next;
2345 if (!t)
2347 struct ipa_agg_jump_function *agg;
2348 if (known_aggs.length () > (unsigned int) param_index)
2349 agg = known_aggs[param_index];
2350 else
2351 agg = NULL;
2352 bool from_global_constant;
2353 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2354 ie->indirect_info->offset,
2355 ie->indirect_info->by_ref,
2356 &from_global_constant);
2357 if (t
2358 && !from_global_constant
2359 && !ie->indirect_info->guaranteed_unmodified)
2360 t = NULL_TREE;
2363 else
2364 t = known_csts[param_index];
2366 if (t
2367 && TREE_CODE (t) == ADDR_EXPR
2368 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2369 return TREE_OPERAND (t, 0);
2370 else
2371 return NULL_TREE;
2374 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2375 return NULL_TREE;
2377 gcc_assert (!ie->indirect_info->agg_contents);
2378 anc_offset = ie->indirect_info->offset;
2380 t = NULL;
2382 /* Try to work out value of virtual table pointer value in replacemnets. */
2383 if (!t && agg_reps && !ie->indirect_info->by_ref)
2385 while (agg_reps)
2387 if (agg_reps->index == param_index
2388 && agg_reps->offset == ie->indirect_info->offset
2389 && agg_reps->by_ref)
2391 t = agg_reps->value;
2392 break;
2394 agg_reps = agg_reps->next;
2398 /* Try to work out value of virtual table pointer value in known
2399 aggregate values. */
2400 if (!t && known_aggs.length () > (unsigned int) param_index
2401 && !ie->indirect_info->by_ref)
2403 struct ipa_agg_jump_function *agg;
2404 agg = known_aggs[param_index];
2405 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2406 ie->indirect_info->offset, true);
2409 /* If we found the virtual table pointer, lookup the target. */
2410 if (t)
2412 tree vtable;
2413 unsigned HOST_WIDE_INT offset;
2414 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2416 bool can_refer;
2417 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2418 vtable, offset, &can_refer);
2419 if (can_refer)
2421 if (!target
2422 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2423 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2424 || !possible_polymorphic_call_target_p
2425 (ie, cgraph_node::get (target)))
2427 /* Do not speculate builtin_unreachable, it is stupid! */
2428 if (ie->indirect_info->vptr_changed)
2429 return NULL;
2430 target = ipa_impossible_devirt_target (ie, target);
2432 *speculative = ie->indirect_info->vptr_changed;
2433 if (!*speculative)
2434 return target;
2439 /* Do we know the constant value of pointer? */
2440 if (!t)
2441 t = known_csts[param_index];
2443 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2445 ipa_polymorphic_call_context context;
2446 if (known_contexts.length () > (unsigned int) param_index)
2448 context = known_contexts[param_index];
2449 context.offset_by (anc_offset);
2450 if (ie->indirect_info->vptr_changed)
2451 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2452 ie->indirect_info->otr_type);
2453 if (t)
2455 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2456 (t, ie->indirect_info->otr_type, anc_offset);
2457 if (!ctx2.useless_p ())
2458 context.combine_with (ctx2, ie->indirect_info->otr_type);
2461 else if (t)
2463 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2464 anc_offset);
2465 if (ie->indirect_info->vptr_changed)
2466 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2467 ie->indirect_info->otr_type);
2469 else
2470 return NULL_TREE;
2472 vec <cgraph_node *>targets;
2473 bool final;
2475 targets = possible_polymorphic_call_targets
2476 (ie->indirect_info->otr_type,
2477 ie->indirect_info->otr_token,
2478 context, &final);
2479 if (!final || targets.length () > 1)
2481 struct cgraph_node *node;
2482 if (*speculative)
2483 return target;
2484 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2485 || ie->speculative || !ie->maybe_hot_p ())
2486 return NULL;
2487 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2488 ie->indirect_info->otr_token,
2489 context);
2490 if (node)
2492 *speculative = true;
2493 target = node->decl;
2495 else
2496 return NULL;
2498 else
2500 *speculative = false;
2501 if (targets.length () == 1)
2502 target = targets[0]->decl;
2503 else
2504 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2507 if (target && !possible_polymorphic_call_target_p (ie,
2508 cgraph_node::get (target)))
2510 if (*speculative)
2511 return NULL;
2512 target = ipa_impossible_devirt_target (ie, target);
2515 return target;
2519 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2520 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2521 return the destination. */
2523 tree
2524 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2525 vec<tree> known_csts,
2526 vec<ipa_polymorphic_call_context> known_contexts,
2527 vec<ipa_agg_jump_function_p> known_aggs,
2528 bool *speculative)
2530 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2531 known_aggs, NULL, speculative);
2534 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2535 and KNOWN_CONTEXTS. */
2537 static int
2538 devirtualization_time_bonus (struct cgraph_node *node,
2539 vec<tree> known_csts,
2540 vec<ipa_polymorphic_call_context> known_contexts,
2541 vec<ipa_agg_jump_function_p> known_aggs)
2543 struct cgraph_edge *ie;
2544 int res = 0;
2546 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2548 struct cgraph_node *callee;
2549 struct ipa_fn_summary *isummary;
2550 enum availability avail;
2551 tree target;
2552 bool speculative;
2554 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2555 known_aggs, &speculative);
2556 if (!target)
2557 continue;
2559 /* Only bare minimum benefit for clearly un-inlineable targets. */
2560 res += 1;
2561 callee = cgraph_node::get (target);
2562 if (!callee || !callee->definition)
2563 continue;
2564 callee = callee->function_symbol (&avail);
2565 if (avail < AVAIL_AVAILABLE)
2566 continue;
2567 isummary = ipa_fn_summaries->get (callee);
2568 if (!isummary->inlinable)
2569 continue;
2571 /* FIXME: The values below need re-considering and perhaps also
2572 integrating into the cost metrics, at lest in some very basic way. */
2573 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2574 res += 31 / ((int)speculative + 1);
2575 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2576 res += 15 / ((int)speculative + 1);
2577 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2578 || DECL_DECLARED_INLINE_P (callee->decl))
2579 res += 7 / ((int)speculative + 1);
2582 return res;
2585 /* Return time bonus incurred because of HINTS. */
2587 static int
2588 hint_time_bonus (ipa_hints hints)
2590 int result = 0;
2591 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2592 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2593 if (hints & INLINE_HINT_array_index)
2594 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2595 return result;
2598 /* If there is a reason to penalize the function described by INFO in the
2599 cloning goodness evaluation, do so. */
2601 static inline int64_t
2602 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2604 if (info->node_within_scc)
2605 evaluation = (evaluation
2606 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2608 if (info->node_calling_single_call)
2609 evaluation = (evaluation
2610 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2611 / 100;
2613 return evaluation;
2616 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2617 and SIZE_COST and with the sum of frequencies of incoming edges to the
2618 potential new clone in FREQUENCIES. */
2620 static bool
2621 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2622 int freq_sum, profile_count count_sum, int size_cost)
2624 if (time_benefit == 0
2625 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2626 || node->optimize_for_size_p ())
2627 return false;
2629 gcc_assert (size_cost > 0);
2631 struct ipa_node_params *info = IPA_NODE_REF (node);
2632 if (max_count > profile_count::zero ())
2634 int factor = RDIV (count_sum.probability_in
2635 (max_count).to_reg_br_prob_base ()
2636 * 1000, REG_BR_PROB_BASE);
2637 int64_t evaluation = (((int64_t) time_benefit * factor)
2638 / size_cost);
2639 evaluation = incorporate_penalties (info, evaluation);
2641 if (dump_file && (dump_flags & TDF_DETAILS))
2643 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2644 "size: %i, count_sum: ", time_benefit, size_cost);
2645 count_sum.dump (dump_file);
2646 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
2647 ", threshold: %i\n",
2648 info->node_within_scc ? ", scc" : "",
2649 info->node_calling_single_call ? ", single_call" : "",
2650 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2653 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2655 else
2657 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2658 / size_cost);
2659 evaluation = incorporate_penalties (info, evaluation);
2661 if (dump_file && (dump_flags & TDF_DETAILS))
2662 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2663 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2664 "%" PRId64 ", threshold: %i\n",
2665 time_benefit, size_cost, freq_sum,
2666 info->node_within_scc ? ", scc" : "",
2667 info->node_calling_single_call ? ", single_call" : "",
2668 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2670 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2674 /* Return all context independent values from aggregate lattices in PLATS in a
2675 vector. Return NULL if there are none. */
2677 static vec<ipa_agg_jf_item, va_gc> *
2678 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2680 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2682 if (plats->aggs_bottom
2683 || plats->aggs_contain_variable
2684 || plats->aggs_count == 0)
2685 return NULL;
2687 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2688 aglat;
2689 aglat = aglat->next)
2690 if (aglat->is_single_const ())
2692 struct ipa_agg_jf_item item;
2693 item.offset = aglat->offset;
2694 item.value = aglat->values->value;
2695 vec_safe_push (res, item);
2697 return res;
2700 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2701 populate them with values of parameters that are known independent of the
2702 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2703 non-NULL, the movement cost of all removable parameters will be stored in
2704 it. */
2706 static bool
2707 gather_context_independent_values (struct ipa_node_params *info,
2708 vec<tree> *known_csts,
2709 vec<ipa_polymorphic_call_context>
2710 *known_contexts,
2711 vec<ipa_agg_jump_function> *known_aggs,
2712 int *removable_params_cost)
2714 int i, count = ipa_get_param_count (info);
2715 bool ret = false;
2717 known_csts->create (0);
2718 known_contexts->create (0);
2719 known_csts->safe_grow_cleared (count);
2720 known_contexts->safe_grow_cleared (count);
2721 if (known_aggs)
2723 known_aggs->create (0);
2724 known_aggs->safe_grow_cleared (count);
2727 if (removable_params_cost)
2728 *removable_params_cost = 0;
2730 for (i = 0; i < count; i++)
2732 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2733 ipcp_lattice<tree> *lat = &plats->itself;
2735 if (lat->is_single_const ())
2737 ipcp_value<tree> *val = lat->values;
2738 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2739 (*known_csts)[i] = val->value;
2740 if (removable_params_cost)
2741 *removable_params_cost
2742 += estimate_move_cost (TREE_TYPE (val->value), false);
2743 ret = true;
2745 else if (removable_params_cost
2746 && !ipa_is_param_used (info, i))
2747 *removable_params_cost
2748 += ipa_get_param_move_cost (info, i);
2750 if (!ipa_is_param_used (info, i))
2751 continue;
2753 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2754 /* Do not account known context as reason for cloning. We can see
2755 if it permits devirtualization. */
2756 if (ctxlat->is_single_const ())
2757 (*known_contexts)[i] = ctxlat->values->value;
2759 if (known_aggs)
2761 vec<ipa_agg_jf_item, va_gc> *agg_items;
2762 struct ipa_agg_jump_function *ajf;
2764 agg_items = context_independent_aggregate_values (plats);
2765 ajf = &(*known_aggs)[i];
2766 ajf->items = agg_items;
2767 ajf->by_ref = plats->aggs_by_ref;
2768 ret |= agg_items != NULL;
2772 return ret;
2775 /* The current interface in ipa-inline-analysis requires a pointer vector.
2776 Create it.
2778 FIXME: That interface should be re-worked, this is slightly silly. Still,
2779 I'd like to discuss how to change it first and this demonstrates the
2780 issue. */
2782 static vec<ipa_agg_jump_function_p>
2783 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2785 vec<ipa_agg_jump_function_p> ret;
2786 struct ipa_agg_jump_function *ajf;
2787 int i;
2789 ret.create (known_aggs.length ());
2790 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2791 ret.quick_push (ajf);
2792 return ret;
2795 /* Perform time and size measurement of NODE with the context given in
2796 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2797 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2798 all context-independent removable parameters and EST_MOVE_COST of estimated
2799 movement of the considered parameter and store it into VAL. */
2801 static void
2802 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2803 vec<ipa_polymorphic_call_context> known_contexts,
2804 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2805 int removable_params_cost,
2806 int est_move_cost, ipcp_value_base *val)
2808 int size, time_benefit;
2809 sreal time, base_time;
2810 ipa_hints hints;
2812 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2813 known_aggs_ptrs, &size, &time,
2814 &base_time, &hints);
2815 base_time -= time;
2816 if (base_time > 65535)
2817 base_time = 65535;
2818 time_benefit = base_time.to_int ()
2819 + devirtualization_time_bonus (node, known_csts, known_contexts,
2820 known_aggs_ptrs)
2821 + hint_time_bonus (hints)
2822 + removable_params_cost + est_move_cost;
2824 gcc_checking_assert (size >=0);
2825 /* The inliner-heuristics based estimates may think that in certain
2826 contexts some functions do not have any size at all but we want
2827 all specializations to have at least a tiny cost, not least not to
2828 divide by zero. */
2829 if (size == 0)
2830 size = 1;
2832 val->local_time_benefit = time_benefit;
2833 val->local_size_cost = size;
2836 /* Iterate over known values of parameters of NODE and estimate the local
2837 effects in terms of time and size they have. */
2839 static void
2840 estimate_local_effects (struct cgraph_node *node)
2842 struct ipa_node_params *info = IPA_NODE_REF (node);
2843 int i, count = ipa_get_param_count (info);
2844 vec<tree> known_csts;
2845 vec<ipa_polymorphic_call_context> known_contexts;
2846 vec<ipa_agg_jump_function> known_aggs;
2847 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2848 bool always_const;
2849 int removable_params_cost;
2851 if (!count || !ipcp_versionable_function_p (node))
2852 return;
2854 if (dump_file && (dump_flags & TDF_DETAILS))
2855 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
2857 always_const = gather_context_independent_values (info, &known_csts,
2858 &known_contexts, &known_aggs,
2859 &removable_params_cost);
2860 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2861 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2862 known_contexts, known_aggs_ptrs);
2863 if (always_const || devirt_bonus
2864 || (removable_params_cost && node->local.can_change_signature))
2866 struct caller_statistics stats;
2867 ipa_hints hints;
2868 sreal time, base_time;
2869 int size;
2871 init_caller_stats (&stats);
2872 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2873 false);
2874 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2875 known_aggs_ptrs, &size, &time,
2876 &base_time, &hints);
2877 time -= devirt_bonus;
2878 time -= hint_time_bonus (hints);
2879 time -= removable_params_cost;
2880 size -= stats.n_calls * removable_params_cost;
2882 if (dump_file)
2883 fprintf (dump_file, " - context independent values, size: %i, "
2884 "time_benefit: %f\n", size, (base_time - time).to_double ());
2886 if (size <= 0 || node->local.local)
2888 info->do_clone_for_all_contexts = true;
2890 if (dump_file)
2891 fprintf (dump_file, " Decided to specialize for all "
2892 "known contexts, code not going to grow.\n");
2894 else if (good_cloning_opportunity_p (node,
2895 MIN ((base_time - time).to_int (),
2896 65536),
2897 stats.freq_sum, stats.count_sum,
2898 size))
2900 if (size + overall_size <= max_new_size)
2902 info->do_clone_for_all_contexts = true;
2903 overall_size += size;
2905 if (dump_file)
2906 fprintf (dump_file, " Decided to specialize for all "
2907 "known contexts, growth deemed beneficial.\n");
2909 else if (dump_file && (dump_flags & TDF_DETAILS))
2910 fprintf (dump_file, " Not cloning for all contexts because "
2911 "max_new_size would be reached with %li.\n",
2912 size + overall_size);
2914 else if (dump_file && (dump_flags & TDF_DETAILS))
2915 fprintf (dump_file, " Not cloning for all contexts because "
2916 "!good_cloning_opportunity_p.\n");
2920 for (i = 0; i < count; i++)
2922 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2923 ipcp_lattice<tree> *lat = &plats->itself;
2924 ipcp_value<tree> *val;
2926 if (lat->bottom
2927 || !lat->values
2928 || known_csts[i])
2929 continue;
2931 for (val = lat->values; val; val = val->next)
2933 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2934 known_csts[i] = val->value;
2936 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2937 perform_estimation_of_a_value (node, known_csts, known_contexts,
2938 known_aggs_ptrs,
2939 removable_params_cost, emc, val);
2941 if (dump_file && (dump_flags & TDF_DETAILS))
2943 fprintf (dump_file, " - estimates for value ");
2944 print_ipcp_constant_value (dump_file, val->value);
2945 fprintf (dump_file, " for ");
2946 ipa_dump_param (dump_file, info, i);
2947 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2948 val->local_time_benefit, val->local_size_cost);
2951 known_csts[i] = NULL_TREE;
2954 for (i = 0; i < count; i++)
2956 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2958 if (!plats->virt_call)
2959 continue;
2961 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2962 ipcp_value<ipa_polymorphic_call_context> *val;
2964 if (ctxlat->bottom
2965 || !ctxlat->values
2966 || !known_contexts[i].useless_p ())
2967 continue;
2969 for (val = ctxlat->values; val; val = val->next)
2971 known_contexts[i] = val->value;
2972 perform_estimation_of_a_value (node, known_csts, known_contexts,
2973 known_aggs_ptrs,
2974 removable_params_cost, 0, val);
2976 if (dump_file && (dump_flags & TDF_DETAILS))
2978 fprintf (dump_file, " - estimates for polymorphic context ");
2979 print_ipcp_constant_value (dump_file, val->value);
2980 fprintf (dump_file, " for ");
2981 ipa_dump_param (dump_file, info, i);
2982 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2983 val->local_time_benefit, val->local_size_cost);
2986 known_contexts[i] = ipa_polymorphic_call_context ();
2989 for (i = 0; i < count; i++)
2991 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2992 struct ipa_agg_jump_function *ajf;
2993 struct ipcp_agg_lattice *aglat;
2995 if (plats->aggs_bottom || !plats->aggs)
2996 continue;
2998 ajf = &known_aggs[i];
2999 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3001 ipcp_value<tree> *val;
3002 if (aglat->bottom || !aglat->values
3003 /* If the following is true, the one value is in known_aggs. */
3004 || (!plats->aggs_contain_variable
3005 && aglat->is_single_const ()))
3006 continue;
3008 for (val = aglat->values; val; val = val->next)
3010 struct ipa_agg_jf_item item;
3012 item.offset = aglat->offset;
3013 item.value = val->value;
3014 vec_safe_push (ajf->items, item);
3016 perform_estimation_of_a_value (node, known_csts, known_contexts,
3017 known_aggs_ptrs,
3018 removable_params_cost, 0, val);
3020 if (dump_file && (dump_flags & TDF_DETAILS))
3022 fprintf (dump_file, " - estimates for value ");
3023 print_ipcp_constant_value (dump_file, val->value);
3024 fprintf (dump_file, " for ");
3025 ipa_dump_param (dump_file, info, i);
3026 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3027 "]: time_benefit: %i, size: %i\n",
3028 plats->aggs_by_ref ? "ref " : "",
3029 aglat->offset,
3030 val->local_time_benefit, val->local_size_cost);
3033 ajf->items->pop ();
3038 for (i = 0; i < count; i++)
3039 vec_free (known_aggs[i].items);
3041 known_csts.release ();
3042 known_contexts.release ();
3043 known_aggs.release ();
3044 known_aggs_ptrs.release ();
3048 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3049 topological sort of values. */
3051 template <typename valtype>
3052 void
3053 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3055 ipcp_value_source<valtype> *src;
3057 if (cur_val->dfs)
3058 return;
3060 dfs_counter++;
3061 cur_val->dfs = dfs_counter;
3062 cur_val->low_link = dfs_counter;
3064 cur_val->topo_next = stack;
3065 stack = cur_val;
3066 cur_val->on_stack = true;
3068 for (src = cur_val->sources; src; src = src->next)
3069 if (src->val)
3071 if (src->val->dfs == 0)
3073 add_val (src->val);
3074 if (src->val->low_link < cur_val->low_link)
3075 cur_val->low_link = src->val->low_link;
3077 else if (src->val->on_stack
3078 && src->val->dfs < cur_val->low_link)
3079 cur_val->low_link = src->val->dfs;
3082 if (cur_val->dfs == cur_val->low_link)
3084 ipcp_value<valtype> *v, *scc_list = NULL;
3088 v = stack;
3089 stack = v->topo_next;
3090 v->on_stack = false;
3092 v->scc_next = scc_list;
3093 scc_list = v;
3095 while (v != cur_val);
3097 cur_val->topo_next = values_topo;
3098 values_topo = cur_val;
3102 /* Add all values in lattices associated with NODE to the topological sort if
3103 they are not there yet. */
3105 static void
3106 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3108 struct ipa_node_params *info = IPA_NODE_REF (node);
3109 int i, count = ipa_get_param_count (info);
3111 for (i = 0; i < count; i++)
3113 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3114 ipcp_lattice<tree> *lat = &plats->itself;
3115 struct ipcp_agg_lattice *aglat;
3117 if (!lat->bottom)
3119 ipcp_value<tree> *val;
3120 for (val = lat->values; val; val = val->next)
3121 topo->constants.add_val (val);
3124 if (!plats->aggs_bottom)
3125 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3126 if (!aglat->bottom)
3128 ipcp_value<tree> *val;
3129 for (val = aglat->values; val; val = val->next)
3130 topo->constants.add_val (val);
3133 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3134 if (!ctxlat->bottom)
3136 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3137 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3138 topo->contexts.add_val (ctxval);
3143 /* One pass of constants propagation along the call graph edges, from callers
3144 to callees (requires topological ordering in TOPO), iterate over strongly
3145 connected components. */
3147 static void
3148 propagate_constants_topo (struct ipa_topo_info *topo)
3150 int i;
3152 for (i = topo->nnodes - 1; i >= 0; i--)
3154 unsigned j;
3155 struct cgraph_node *v, *node = topo->order[i];
3156 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3158 /* First, iteratively propagate within the strongly connected component
3159 until all lattices stabilize. */
3160 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3161 if (v->has_gimple_body_p ())
3162 push_node_to_stack (topo, v);
3164 v = pop_node_from_stack (topo);
3165 while (v)
3167 struct cgraph_edge *cs;
3169 for (cs = v->callees; cs; cs = cs->next_callee)
3170 if (ipa_edge_within_scc (cs))
3172 IPA_NODE_REF (v)->node_within_scc = true;
3173 if (propagate_constants_across_call (cs))
3174 push_node_to_stack (topo, cs->callee->function_symbol ());
3176 v = pop_node_from_stack (topo);
3179 /* Afterwards, propagate along edges leading out of the SCC, calculates
3180 the local effects of the discovered constants and all valid values to
3181 their topological sort. */
3182 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3183 if (v->has_gimple_body_p ())
3185 struct cgraph_edge *cs;
3187 estimate_local_effects (v);
3188 add_all_node_vals_to_toposort (v, topo);
3189 for (cs = v->callees; cs; cs = cs->next_callee)
3190 if (!ipa_edge_within_scc (cs))
3191 propagate_constants_across_call (cs);
3193 cycle_nodes.release ();
3198 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3199 the bigger one if otherwise. */
3201 static int
3202 safe_add (int a, int b)
3204 if (a > INT_MAX/2 || b > INT_MAX/2)
3205 return a > b ? a : b;
3206 else
3207 return a + b;
3211 /* Propagate the estimated effects of individual values along the topological
3212 from the dependent values to those they depend on. */
3214 template <typename valtype>
3215 void
3216 value_topo_info<valtype>::propagate_effects ()
3218 ipcp_value<valtype> *base;
3220 for (base = values_topo; base; base = base->topo_next)
3222 ipcp_value_source<valtype> *src;
3223 ipcp_value<valtype> *val;
3224 int time = 0, size = 0;
3226 for (val = base; val; val = val->scc_next)
3228 time = safe_add (time,
3229 val->local_time_benefit + val->prop_time_benefit);
3230 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3233 for (val = base; val; val = val->scc_next)
3234 for (src = val->sources; src; src = src->next)
3235 if (src->val
3236 && src->cs->maybe_hot_p ())
3238 src->val->prop_time_benefit = safe_add (time,
3239 src->val->prop_time_benefit);
3240 src->val->prop_size_cost = safe_add (size,
3241 src->val->prop_size_cost);
3247 /* Propagate constants, polymorphic contexts and their effects from the
3248 summaries interprocedurally. */
3250 static void
3251 ipcp_propagate_stage (struct ipa_topo_info *topo)
3253 struct cgraph_node *node;
3255 if (dump_file)
3256 fprintf (dump_file, "\n Propagating constants:\n\n");
3258 max_count = profile_count::uninitialized ();
3260 FOR_EACH_DEFINED_FUNCTION (node)
3262 struct ipa_node_params *info = IPA_NODE_REF (node);
3264 determine_versionability (node, info);
3265 if (node->has_gimple_body_p ())
3267 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3268 ipa_get_param_count (info));
3269 initialize_node_lattices (node);
3271 ipa_fn_summary *s = ipa_fn_summaries->get (node);
3272 if (node->definition && !node->alias && s != NULL)
3273 overall_size += s->self_size;
3274 max_count = max_count.max (node->count.ipa ());
3277 max_new_size = overall_size;
3278 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3279 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3280 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3282 if (dump_file)
3283 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3284 overall_size, max_new_size);
3286 propagate_constants_topo (topo);
3287 if (flag_checking)
3288 ipcp_verify_propagated_values ();
3289 topo->constants.propagate_effects ();
3290 topo->contexts.propagate_effects ();
3292 if (dump_file)
3294 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3295 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3299 /* Discover newly direct outgoing edges from NODE which is a new clone with
3300 known KNOWN_CSTS and make them direct. */
3302 static void
3303 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3304 vec<tree> known_csts,
3305 vec<ipa_polymorphic_call_context>
3306 known_contexts,
3307 struct ipa_agg_replacement_value *aggvals)
3309 struct cgraph_edge *ie, *next_ie;
3310 bool found = false;
3312 for (ie = node->indirect_calls; ie; ie = next_ie)
3314 tree target;
3315 bool speculative;
3317 next_ie = ie->next_callee;
3318 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3319 vNULL, aggvals, &speculative);
3320 if (target)
3322 bool agg_contents = ie->indirect_info->agg_contents;
3323 bool polymorphic = ie->indirect_info->polymorphic;
3324 int param_index = ie->indirect_info->param_index;
3325 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3326 speculative);
3327 found = true;
3329 if (cs && !agg_contents && !polymorphic)
3331 struct ipa_node_params *info = IPA_NODE_REF (node);
3332 int c = ipa_get_controlled_uses (info, param_index);
3333 if (c != IPA_UNDESCRIBED_USE)
3335 struct ipa_ref *to_del;
3337 c--;
3338 ipa_set_controlled_uses (info, param_index, c);
3339 if (dump_file && (dump_flags & TDF_DETAILS))
3340 fprintf (dump_file, " controlled uses count of param "
3341 "%i bumped down to %i\n", param_index, c);
3342 if (c == 0
3343 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3345 if (dump_file && (dump_flags & TDF_DETAILS))
3346 fprintf (dump_file, " and even removing its "
3347 "cloning-created reference\n");
3348 to_del->remove_reference ();
3354 /* Turning calls to direct calls will improve overall summary. */
3355 if (found)
3356 ipa_update_overall_fn_summary (node);
3359 class edge_clone_summary;
3360 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL;
3362 /* Edge clone summary. */
3364 struct edge_clone_summary
3366 /* Default constructor. */
3367 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
3369 /* Default destructor. */
3370 ~edge_clone_summary ()
3372 if (prev_clone)
3373 edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
3374 if (next_clone)
3375 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
3378 cgraph_edge *prev_clone;
3379 cgraph_edge *next_clone;
3382 class edge_clone_summary_t:
3383 public call_summary <edge_clone_summary *>
3385 public:
3386 edge_clone_summary_t (symbol_table *symtab):
3387 call_summary <edge_clone_summary *> (symtab)
3389 m_initialize_when_cloning = true;
3392 virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
3393 edge_clone_summary *src_data,
3394 edge_clone_summary *dst_data);
3397 /* Edge duplication hook. */
3399 void
3400 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
3401 edge_clone_summary *src_data,
3402 edge_clone_summary *dst_data)
3404 if (src_data->next_clone)
3405 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
3406 dst_data->prev_clone = src_edge;
3407 dst_data->next_clone = src_data->next_clone;
3408 src_data->next_clone = dst_edge;
3411 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3412 parameter with the given INDEX. */
3414 static tree
3415 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3416 int index)
3418 struct ipa_agg_replacement_value *aggval;
3420 aggval = ipa_get_agg_replacements_for_node (node);
3421 while (aggval)
3423 if (aggval->offset == offset
3424 && aggval->index == index)
3425 return aggval->value;
3426 aggval = aggval->next;
3428 return NULL_TREE;
3431 /* Return true is NODE is DEST or its clone for all contexts. */
3433 static bool
3434 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3436 if (node == dest)
3437 return true;
3439 struct ipa_node_params *info = IPA_NODE_REF (node);
3440 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3443 /* Return true if edge CS does bring about the value described by SRC to
3444 DEST_VAL of node DEST or its clone for all contexts. */
3446 static bool
3447 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3448 cgraph_node *dest, ipcp_value<tree> *dest_val)
3450 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3451 enum availability availability;
3452 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3454 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3455 || availability <= AVAIL_INTERPOSABLE
3456 || caller_info->node_dead)
3457 return false;
3459 if (!src->val)
3460 return true;
3462 if (caller_info->ipcp_orig_node)
3464 tree t;
3465 if (src->offset == -1)
3466 t = caller_info->known_csts[src->index];
3467 else
3468 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3469 return (t != NULL_TREE
3470 && values_equal_for_ipcp_p (src->val->value, t));
3472 else
3474 /* At the moment we do not propagate over arithmetic jump functions in
3475 SCCs, so it is safe to detect self-feeding recursive calls in this
3476 way. */
3477 if (src->val == dest_val)
3478 return true;
3480 struct ipcp_agg_lattice *aglat;
3481 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3482 src->index);
3483 if (src->offset == -1)
3484 return (plats->itself.is_single_const ()
3485 && values_equal_for_ipcp_p (src->val->value,
3486 plats->itself.values->value));
3487 else
3489 if (plats->aggs_bottom || plats->aggs_contain_variable)
3490 return false;
3491 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3492 if (aglat->offset == src->offset)
3493 return (aglat->is_single_const ()
3494 && values_equal_for_ipcp_p (src->val->value,
3495 aglat->values->value));
3497 return false;
3501 /* Return true if edge CS does bring about the value described by SRC to
3502 DST_VAL of node DEST or its clone for all contexts. */
3504 static bool
3505 cgraph_edge_brings_value_p (cgraph_edge *cs,
3506 ipcp_value_source<ipa_polymorphic_call_context> *src,
3507 cgraph_node *dest,
3508 ipcp_value<ipa_polymorphic_call_context> *)
3510 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3511 cgraph_node *real_dest = cs->callee->function_symbol ();
3513 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3514 || caller_info->node_dead)
3515 return false;
3516 if (!src->val)
3517 return true;
3519 if (caller_info->ipcp_orig_node)
3520 return (caller_info->known_contexts.length () > (unsigned) src->index)
3521 && values_equal_for_ipcp_p (src->val->value,
3522 caller_info->known_contexts[src->index]);
3524 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3525 src->index);
3526 return plats->ctxlat.is_single_const ()
3527 && values_equal_for_ipcp_p (src->val->value,
3528 plats->ctxlat.values->value);
3531 /* Get the next clone in the linked list of clones of an edge. */
3533 static inline struct cgraph_edge *
3534 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3536 edge_clone_summary *s = edge_clone_summaries->get (cs);
3537 return s != NULL ? s->next_clone : NULL;
3540 /* Given VAL that is intended for DEST, iterate over all its sources and if any
3541 of them is viable and hot, return true. In that case, for those that still
3542 hold, add their edge frequency and their number into *FREQUENCY and
3543 *CALLER_COUNT respectively. */
3545 template <typename valtype>
3546 static bool
3547 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3548 int *freq_sum,
3549 profile_count *count_sum, int *caller_count)
3551 ipcp_value_source<valtype> *src;
3552 int freq = 0, count = 0;
3553 profile_count cnt = profile_count::zero ();
3554 bool hot = false;
3555 bool non_self_recursive = false;
3557 for (src = val->sources; src; src = src->next)
3559 struct cgraph_edge *cs = src->cs;
3560 while (cs)
3562 if (cgraph_edge_brings_value_p (cs, src, dest, val))
3564 count++;
3565 freq += cs->frequency ();
3566 if (cs->count.ipa ().initialized_p ())
3567 cnt += cs->count.ipa ();
3568 hot |= cs->maybe_hot_p ();
3569 if (cs->caller != dest)
3570 non_self_recursive = true;
3572 cs = get_next_cgraph_edge_clone (cs);
3576 /* If the only edges bringing a value are self-recursive ones, do not bother
3577 evaluating it. */
3578 if (!non_self_recursive)
3579 return false;
3581 *freq_sum = freq;
3582 *count_sum = cnt;
3583 *caller_count = count;
3584 return hot;
3587 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3588 is assumed their number is known and equal to CALLER_COUNT. */
3590 template <typename valtype>
3591 static vec<cgraph_edge *>
3592 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3593 int caller_count)
3595 ipcp_value_source<valtype> *src;
3596 vec<cgraph_edge *> ret;
3598 ret.create (caller_count);
3599 for (src = val->sources; src; src = src->next)
3601 struct cgraph_edge *cs = src->cs;
3602 while (cs)
3604 if (cgraph_edge_brings_value_p (cs, src, dest, val))
3605 ret.quick_push (cs);
3606 cs = get_next_cgraph_edge_clone (cs);
3610 return ret;
3613 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3614 Return it or NULL if for some reason it cannot be created. */
3616 static struct ipa_replace_map *
3617 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3619 struct ipa_replace_map *replace_map;
3622 replace_map = ggc_alloc<ipa_replace_map> ();
3623 if (dump_file)
3625 fprintf (dump_file, " replacing ");
3626 ipa_dump_param (dump_file, info, parm_num);
3628 fprintf (dump_file, " with const ");
3629 print_generic_expr (dump_file, value);
3630 fprintf (dump_file, "\n");
3632 replace_map->old_tree = NULL;
3633 replace_map->parm_num = parm_num;
3634 replace_map->new_tree = value;
3635 replace_map->replace_p = true;
3636 replace_map->ref_p = false;
3638 return replace_map;
3641 /* Dump new profiling counts */
3643 static void
3644 dump_profile_updates (struct cgraph_node *orig_node,
3645 struct cgraph_node *new_node)
3647 struct cgraph_edge *cs;
3649 fprintf (dump_file, " setting count of the specialized node to ");
3650 new_node->count.dump (dump_file);
3651 fprintf (dump_file, "\n");
3652 for (cs = new_node->callees; cs; cs = cs->next_callee)
3654 fprintf (dump_file, " edge to %s has count ",
3655 cs->callee->name ());
3656 cs->count.dump (dump_file);
3657 fprintf (dump_file, "\n");
3660 fprintf (dump_file, " setting count of the original node to ");
3661 orig_node->count.dump (dump_file);
3662 fprintf (dump_file, "\n");
3663 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3665 fprintf (dump_file, " edge to %s is left with ",
3666 cs->callee->name ());
3667 cs->count.dump (dump_file);
3668 fprintf (dump_file, "\n");
3672 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3673 their profile information to reflect this. */
3675 static void
3676 update_profiling_info (struct cgraph_node *orig_node,
3677 struct cgraph_node *new_node)
3679 struct cgraph_edge *cs;
3680 struct caller_statistics stats;
3681 profile_count new_sum, orig_sum;
3682 profile_count remainder, orig_node_count = orig_node->count;
3684 if (!(orig_node_count.ipa () > profile_count::zero ()))
3685 return;
3687 init_caller_stats (&stats);
3688 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3689 false);
3690 orig_sum = stats.count_sum;
3691 init_caller_stats (&stats);
3692 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3693 false);
3694 new_sum = stats.count_sum;
3696 if (orig_node_count < orig_sum + new_sum)
3698 if (dump_file)
3700 fprintf (dump_file, " Problem: node %s has too low count ",
3701 orig_node->dump_name ());
3702 orig_node_count.dump (dump_file);
3703 fprintf (dump_file, "while the sum of incoming count is ");
3704 (orig_sum + new_sum).dump (dump_file);
3705 fprintf (dump_file, "\n");
3708 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
3709 if (dump_file)
3711 fprintf (dump_file, " proceeding by pretending it was ");
3712 orig_node_count.dump (dump_file);
3713 fprintf (dump_file, "\n");
3717 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
3718 - new_sum.ipa ());
3719 new_sum = orig_node_count.combine_with_ipa_count (new_sum);
3720 orig_node->count = remainder;
3722 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_node_count);
3723 for (cs = new_node->callees; cs; cs = cs->next_callee)
3724 cs->count = cs->count.apply_scale (new_sum, orig_node_count);
3726 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
3727 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3728 cs->count = cs->count.apply_scale (remainder, orig_node_count);
3730 if (dump_file)
3731 dump_profile_updates (orig_node, new_node);
3734 /* Update the respective profile of specialized NEW_NODE and the original
3735 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3736 have been redirected to the specialized version. */
3738 static void
3739 update_specialized_profile (struct cgraph_node *new_node,
3740 struct cgraph_node *orig_node,
3741 profile_count redirected_sum)
3743 struct cgraph_edge *cs;
3744 profile_count new_node_count, orig_node_count = orig_node->count;
3746 if (dump_file)
3748 fprintf (dump_file, " the sum of counts of redirected edges is ");
3749 redirected_sum.dump (dump_file);
3750 fprintf (dump_file, "\n");
3752 if (!(orig_node_count > profile_count::zero ()))
3753 return;
3755 gcc_assert (orig_node_count >= redirected_sum);
3757 new_node_count = new_node->count;
3758 new_node->count += redirected_sum;
3759 orig_node->count -= redirected_sum;
3761 for (cs = new_node->callees; cs; cs = cs->next_callee)
3762 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
3764 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3766 profile_count dec = cs->count.apply_scale (redirected_sum,
3767 orig_node_count);
3768 cs->count -= dec;
3771 if (dump_file)
3772 dump_profile_updates (orig_node, new_node);
3775 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3776 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3777 redirect all edges in CALLERS to it. */
3779 static struct cgraph_node *
3780 create_specialized_node (struct cgraph_node *node,
3781 vec<tree> known_csts,
3782 vec<ipa_polymorphic_call_context> known_contexts,
3783 struct ipa_agg_replacement_value *aggvals,
3784 vec<cgraph_edge *> callers)
3786 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3787 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3788 struct ipa_agg_replacement_value *av;
3789 struct cgraph_node *new_node;
3790 int i, count = ipa_get_param_count (info);
3791 bitmap args_to_skip;
3793 gcc_assert (!info->ipcp_orig_node);
3795 if (node->local.can_change_signature)
3797 args_to_skip = BITMAP_GGC_ALLOC ();
3798 for (i = 0; i < count; i++)
3800 tree t = known_csts[i];
3802 if (t || !ipa_is_param_used (info, i))
3803 bitmap_set_bit (args_to_skip, i);
3806 else
3808 args_to_skip = NULL;
3809 if (dump_file && (dump_flags & TDF_DETAILS))
3810 fprintf (dump_file, " cannot change function signature\n");
3813 for (i = 0; i < count; i++)
3815 tree t = known_csts[i];
3816 if (t)
3818 struct ipa_replace_map *replace_map;
3820 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3821 replace_map = get_replacement_map (info, t, i);
3822 if (replace_map)
3823 vec_safe_push (replace_trees, replace_map);
3826 auto_vec<cgraph_edge *, 2> self_recursive_calls;
3827 for (i = callers.length () - 1; i >= 0; i--)
3829 cgraph_edge *cs = callers[i];
3830 if (cs->caller == node)
3832 self_recursive_calls.safe_push (cs);
3833 callers.unordered_remove (i);
3837 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
3838 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
3839 node->decl)));
3840 new_node = node->create_virtual_clone (callers, replace_trees,
3841 args_to_skip, "constprop",
3842 suffix_counter);
3843 suffix_counter++;
3845 bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
3846 for (unsigned j = 0; j < self_recursive_calls.length (); j++)
3848 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
3849 /* Cloned edges can disappear during cloning as speculation can be
3850 resolved, check that we have one and that it comes from the last
3851 cloning. */
3852 if (cs && cs->caller == new_node)
3853 cs->redirect_callee_duplicating_thunks (new_node);
3854 /* Any future code that would make more than one clone of an outgoing
3855 edge would confuse this mechanism, so let's check that does not
3856 happen. */
3857 gcc_checking_assert (!cs
3858 || !get_next_cgraph_edge_clone (cs)
3859 || get_next_cgraph_edge_clone (cs)->caller != new_node);
3861 if (have_self_recursive_calls)
3862 new_node->expand_all_artificial_thunks ();
3864 ipa_set_node_agg_value_chain (new_node, aggvals);
3865 for (av = aggvals; av; av = av->next)
3866 new_node->maybe_create_reference (av->value, NULL);
3868 if (dump_file && (dump_flags & TDF_DETAILS))
3870 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
3871 if (known_contexts.exists ())
3873 for (i = 0; i < count; i++)
3874 if (!known_contexts[i].useless_p ())
3876 fprintf (dump_file, " known ctx %i is ", i);
3877 known_contexts[i].dump (dump_file);
3880 if (aggvals)
3881 ipa_dump_agg_replacement_values (dump_file, aggvals);
3883 ipa_check_create_node_params ();
3884 update_profiling_info (node, new_node);
3885 new_info = IPA_NODE_REF (new_node);
3886 new_info->ipcp_orig_node = node;
3887 new_info->known_csts = known_csts;
3888 new_info->known_contexts = known_contexts;
3890 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3892 callers.release ();
3893 return new_node;
3896 /* Return true, if JFUNC, which describes a i-th parameter of call CS, is a
3897 simple no-operation pass-through function to itself. */
3899 static bool
3900 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i)
3902 enum availability availability;
3903 if (cs->caller == cs->callee->function_symbol (&availability)
3904 && availability > AVAIL_INTERPOSABLE
3905 && jfunc->type == IPA_JF_PASS_THROUGH
3906 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR
3907 && ipa_get_jf_pass_through_formal_id (jfunc) == i)
3908 return true;
3909 return false;
3912 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3913 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3915 static void
3916 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3917 vec<tree> known_csts,
3918 vec<cgraph_edge *> callers)
3920 struct ipa_node_params *info = IPA_NODE_REF (node);
3921 int i, count = ipa_get_param_count (info);
3923 for (i = 0; i < count; i++)
3925 struct cgraph_edge *cs;
3926 tree newval = NULL_TREE;
3927 int j;
3928 bool first = true;
3929 tree type = ipa_get_type (info, i);
3931 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3932 continue;
3934 FOR_EACH_VEC_ELT (callers, j, cs)
3936 struct ipa_jump_func *jump_func;
3937 tree t;
3939 if (IPA_NODE_REF (cs->caller)->node_dead)
3940 continue;
3942 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3943 || (i == 0
3944 && call_passes_through_thunk_p (cs)))
3946 newval = NULL_TREE;
3947 break;
3949 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3950 if (self_recursive_pass_through_p (cs, jump_func, i))
3951 continue;
3953 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func, type);
3954 if (!t
3955 || (newval
3956 && !values_equal_for_ipcp_p (t, newval))
3957 || (!first && !newval))
3959 newval = NULL_TREE;
3960 break;
3962 else
3963 newval = t;
3964 first = false;
3967 if (newval)
3969 if (dump_file && (dump_flags & TDF_DETAILS))
3971 fprintf (dump_file, " adding an extra known scalar value ");
3972 print_ipcp_constant_value (dump_file, newval);
3973 fprintf (dump_file, " for ");
3974 ipa_dump_param (dump_file, info, i);
3975 fprintf (dump_file, "\n");
3978 known_csts[i] = newval;
3983 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3984 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3985 CALLERS. */
3987 static void
3988 find_more_contexts_for_caller_subset (cgraph_node *node,
3989 vec<ipa_polymorphic_call_context>
3990 *known_contexts,
3991 vec<cgraph_edge *> callers)
3993 ipa_node_params *info = IPA_NODE_REF (node);
3994 int i, count = ipa_get_param_count (info);
3996 for (i = 0; i < count; i++)
3998 cgraph_edge *cs;
4000 if (ipa_get_poly_ctx_lat (info, i)->bottom
4001 || (known_contexts->exists ()
4002 && !(*known_contexts)[i].useless_p ()))
4003 continue;
4005 ipa_polymorphic_call_context newval;
4006 bool first = true;
4007 int j;
4009 FOR_EACH_VEC_ELT (callers, j, cs)
4011 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
4012 return;
4013 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
4015 ipa_polymorphic_call_context ctx;
4016 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
4017 jfunc);
4018 if (first)
4020 newval = ctx;
4021 first = false;
4023 else
4024 newval.meet_with (ctx);
4025 if (newval.useless_p ())
4026 break;
4029 if (!newval.useless_p ())
4031 if (dump_file && (dump_flags & TDF_DETAILS))
4033 fprintf (dump_file, " adding an extra known polymorphic "
4034 "context ");
4035 print_ipcp_constant_value (dump_file, newval);
4036 fprintf (dump_file, " for ");
4037 ipa_dump_param (dump_file, info, i);
4038 fprintf (dump_file, "\n");
4041 if (!known_contexts->exists ())
4042 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
4043 (*known_contexts)[i] = newval;
4049 /* Go through PLATS and create a vector of values consisting of values and
4050 offsets (minus OFFSET) of lattices that contain only a single value. */
4052 static vec<ipa_agg_jf_item>
4053 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
4055 vec<ipa_agg_jf_item> res = vNULL;
4057 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4058 return vNULL;
4060 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
4061 if (aglat->is_single_const ())
4063 struct ipa_agg_jf_item ti;
4064 ti.offset = aglat->offset - offset;
4065 ti.value = aglat->values->value;
4066 res.safe_push (ti);
4068 return res;
4071 /* Intersect all values in INTER with single value lattices in PLATS (while
4072 subtracting OFFSET). */
4074 static void
4075 intersect_with_plats (struct ipcp_param_lattices *plats,
4076 vec<ipa_agg_jf_item> *inter,
4077 HOST_WIDE_INT offset)
4079 struct ipcp_agg_lattice *aglat;
4080 struct ipa_agg_jf_item *item;
4081 int k;
4083 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4085 inter->release ();
4086 return;
4089 aglat = plats->aggs;
4090 FOR_EACH_VEC_ELT (*inter, k, item)
4092 bool found = false;
4093 if (!item->value)
4094 continue;
4095 while (aglat)
4097 if (aglat->offset - offset > item->offset)
4098 break;
4099 if (aglat->offset - offset == item->offset)
4101 gcc_checking_assert (item->value);
4102 if (aglat->is_single_const ()
4103 && values_equal_for_ipcp_p (item->value,
4104 aglat->values->value))
4105 found = true;
4106 break;
4108 aglat = aglat->next;
4110 if (!found)
4111 item->value = NULL_TREE;
4115 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4116 vector result while subtracting OFFSET from the individual value offsets. */
4118 static vec<ipa_agg_jf_item>
4119 agg_replacements_to_vector (struct cgraph_node *node, int index,
4120 HOST_WIDE_INT offset)
4122 struct ipa_agg_replacement_value *av;
4123 vec<ipa_agg_jf_item> res = vNULL;
4125 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4126 if (av->index == index
4127 && (av->offset - offset) >= 0)
4129 struct ipa_agg_jf_item item;
4130 gcc_checking_assert (av->value);
4131 item.offset = av->offset - offset;
4132 item.value = av->value;
4133 res.safe_push (item);
4136 return res;
4139 /* Intersect all values in INTER with those that we have already scheduled to
4140 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4141 (while subtracting OFFSET). */
4143 static void
4144 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4145 vec<ipa_agg_jf_item> *inter,
4146 HOST_WIDE_INT offset)
4148 struct ipa_agg_replacement_value *srcvals;
4149 struct ipa_agg_jf_item *item;
4150 int i;
4152 srcvals = ipa_get_agg_replacements_for_node (node);
4153 if (!srcvals)
4155 inter->release ();
4156 return;
4159 FOR_EACH_VEC_ELT (*inter, i, item)
4161 struct ipa_agg_replacement_value *av;
4162 bool found = false;
4163 if (!item->value)
4164 continue;
4165 for (av = srcvals; av; av = av->next)
4167 gcc_checking_assert (av->value);
4168 if (av->index == index
4169 && av->offset - offset == item->offset)
4171 if (values_equal_for_ipcp_p (item->value, av->value))
4172 found = true;
4173 break;
4176 if (!found)
4177 item->value = NULL_TREE;
4181 /* Intersect values in INTER with aggregate values that come along edge CS to
4182 parameter number INDEX and return it. If INTER does not actually exist yet,
4183 copy all incoming values to it. If we determine we ended up with no values
4184 whatsoever, return a released vector. */
4186 static vec<ipa_agg_jf_item>
4187 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4188 vec<ipa_agg_jf_item> inter)
4190 struct ipa_jump_func *jfunc;
4191 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4192 if (jfunc->type == IPA_JF_PASS_THROUGH
4193 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4195 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4196 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4198 if (caller_info->ipcp_orig_node)
4200 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4201 struct ipcp_param_lattices *orig_plats;
4202 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4203 src_idx);
4204 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4206 if (!inter.exists ())
4207 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4208 else
4209 intersect_with_agg_replacements (cs->caller, src_idx,
4210 &inter, 0);
4212 else
4214 inter.release ();
4215 return vNULL;
4218 else
4220 struct ipcp_param_lattices *src_plats;
4221 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4222 if (agg_pass_through_permissible_p (src_plats, jfunc))
4224 /* Currently we do not produce clobber aggregate jump
4225 functions, adjust when we do. */
4226 gcc_checking_assert (!jfunc->agg.items);
4227 if (!inter.exists ())
4228 inter = copy_plats_to_inter (src_plats, 0);
4229 else
4230 intersect_with_plats (src_plats, &inter, 0);
4232 else
4234 inter.release ();
4235 return vNULL;
4239 else if (jfunc->type == IPA_JF_ANCESTOR
4240 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4242 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4243 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4244 struct ipcp_param_lattices *src_plats;
4245 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4247 if (caller_info->ipcp_orig_node)
4249 if (!inter.exists ())
4250 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4251 else
4252 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4253 delta);
4255 else
4257 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4258 /* Currently we do not produce clobber aggregate jump
4259 functions, adjust when we do. */
4260 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4261 if (!inter.exists ())
4262 inter = copy_plats_to_inter (src_plats, delta);
4263 else
4264 intersect_with_plats (src_plats, &inter, delta);
4267 else if (jfunc->agg.items)
4269 struct ipa_agg_jf_item *item;
4270 int k;
4272 if (!inter.exists ())
4273 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4274 inter.safe_push ((*jfunc->agg.items)[i]);
4275 else
4276 FOR_EACH_VEC_ELT (inter, k, item)
4278 int l = 0;
4279 bool found = false;
4281 if (!item->value)
4282 continue;
4284 while ((unsigned) l < jfunc->agg.items->length ())
4286 struct ipa_agg_jf_item *ti;
4287 ti = &(*jfunc->agg.items)[l];
4288 if (ti->offset > item->offset)
4289 break;
4290 if (ti->offset == item->offset)
4292 gcc_checking_assert (ti->value);
4293 if (values_equal_for_ipcp_p (item->value,
4294 ti->value))
4295 found = true;
4296 break;
4298 l++;
4300 if (!found)
4301 item->value = NULL;
4304 else
4306 inter.release ();
4307 return vec<ipa_agg_jf_item>();
4309 return inter;
4312 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4313 from all of them. */
4315 static struct ipa_agg_replacement_value *
4316 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4317 vec<cgraph_edge *> callers)
4319 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4320 struct ipa_agg_replacement_value *res;
4321 struct ipa_agg_replacement_value **tail = &res;
4322 struct cgraph_edge *cs;
4323 int i, j, count = ipa_get_param_count (dest_info);
4325 FOR_EACH_VEC_ELT (callers, j, cs)
4327 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4328 if (c < count)
4329 count = c;
4332 for (i = 0; i < count; i++)
4334 struct cgraph_edge *cs;
4335 vec<ipa_agg_jf_item> inter = vNULL;
4336 struct ipa_agg_jf_item *item;
4337 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4338 int j;
4340 /* Among other things, the following check should deal with all by_ref
4341 mismatches. */
4342 if (plats->aggs_bottom)
4343 continue;
4345 FOR_EACH_VEC_ELT (callers, j, cs)
4347 struct ipa_jump_func *jfunc
4348 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
4349 if (self_recursive_pass_through_p (cs, jfunc, i)
4350 && (!plats->aggs_by_ref
4351 || ipa_get_jf_pass_through_agg_preserved (jfunc)))
4352 continue;
4353 inter = intersect_aggregates_with_edge (cs, i, inter);
4355 if (!inter.exists ())
4356 goto next_param;
4359 FOR_EACH_VEC_ELT (inter, j, item)
4361 struct ipa_agg_replacement_value *v;
4363 if (!item->value)
4364 continue;
4366 v = ggc_alloc<ipa_agg_replacement_value> ();
4367 v->index = i;
4368 v->offset = item->offset;
4369 v->value = item->value;
4370 v->by_ref = plats->aggs_by_ref;
4371 *tail = v;
4372 tail = &v->next;
4375 next_param:
4376 if (inter.exists ())
4377 inter.release ();
4379 *tail = NULL;
4380 return res;
4383 /* Determine whether CS also brings all scalar values that the NODE is
4384 specialized for. */
4386 static bool
4387 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4388 struct cgraph_node *node)
4390 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4391 int count = ipa_get_param_count (dest_info);
4392 struct ipa_node_params *caller_info;
4393 struct ipa_edge_args *args;
4394 int i;
4396 caller_info = IPA_NODE_REF (cs->caller);
4397 args = IPA_EDGE_REF (cs);
4398 for (i = 0; i < count; i++)
4400 struct ipa_jump_func *jump_func;
4401 tree val, t;
4403 val = dest_info->known_csts[i];
4404 if (!val)
4405 continue;
4407 if (i >= ipa_get_cs_argument_count (args))
4408 return false;
4409 jump_func = ipa_get_ith_jump_func (args, i);
4410 t = ipa_value_from_jfunc (caller_info, jump_func,
4411 ipa_get_type (dest_info, i));
4412 if (!t || !values_equal_for_ipcp_p (val, t))
4413 return false;
4415 return true;
4418 /* Determine whether CS also brings all aggregate values that NODE is
4419 specialized for. */
4420 static bool
4421 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4422 struct cgraph_node *node)
4424 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4425 struct ipa_node_params *orig_node_info;
4426 struct ipa_agg_replacement_value *aggval;
4427 int i, ec, count;
4429 aggval = ipa_get_agg_replacements_for_node (node);
4430 if (!aggval)
4431 return true;
4433 count = ipa_get_param_count (IPA_NODE_REF (node));
4434 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4435 if (ec < count)
4436 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4437 if (aggval->index >= ec)
4438 return false;
4440 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4441 if (orig_caller_info->ipcp_orig_node)
4442 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4444 for (i = 0; i < count; i++)
4446 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4447 struct ipcp_param_lattices *plats;
4448 bool interesting = false;
4449 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4450 if (aggval->index == i)
4452 interesting = true;
4453 break;
4455 if (!interesting)
4456 continue;
4458 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4459 if (plats->aggs_bottom)
4460 return false;
4462 values = intersect_aggregates_with_edge (cs, i, values);
4463 if (!values.exists ())
4464 return false;
4466 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4467 if (aggval->index == i)
4469 struct ipa_agg_jf_item *item;
4470 int j;
4471 bool found = false;
4472 FOR_EACH_VEC_ELT (values, j, item)
4473 if (item->value
4474 && item->offset == av->offset
4475 && values_equal_for_ipcp_p (item->value, av->value))
4477 found = true;
4478 break;
4480 if (!found)
4482 values.release ();
4483 return false;
4487 return true;
4490 /* Given an original NODE and a VAL for which we have already created a
4491 specialized clone, look whether there are incoming edges that still lead
4492 into the old node but now also bring the requested value and also conform to
4493 all other criteria such that they can be redirected the special node.
4494 This function can therefore redirect the final edge in a SCC. */
4496 template <typename valtype>
4497 static void
4498 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4500 ipcp_value_source<valtype> *src;
4501 profile_count redirected_sum = profile_count::zero ();
4503 for (src = val->sources; src; src = src->next)
4505 struct cgraph_edge *cs = src->cs;
4506 while (cs)
4508 if (cgraph_edge_brings_value_p (cs, src, node, val)
4509 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4510 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4512 if (dump_file)
4513 fprintf (dump_file, " - adding an extra caller %s of %s\n",
4514 cs->caller->dump_name (),
4515 val->spec_node->dump_name ());
4517 cs->redirect_callee_duplicating_thunks (val->spec_node);
4518 val->spec_node->expand_all_artificial_thunks ();
4519 if (cs->count.ipa ().initialized_p ())
4520 redirected_sum = redirected_sum + cs->count.ipa ();
4522 cs = get_next_cgraph_edge_clone (cs);
4526 if (redirected_sum.nonzero_p ())
4527 update_specialized_profile (val->spec_node, node, redirected_sum);
4530 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4532 static bool
4533 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4535 ipa_polymorphic_call_context *ctx;
4536 int i;
4538 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4539 if (!ctx->useless_p ())
4540 return true;
4541 return false;
4544 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4546 static vec<ipa_polymorphic_call_context>
4547 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4549 if (known_contexts_useful_p (known_contexts))
4550 return known_contexts.copy ();
4551 else
4552 return vNULL;
4555 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4556 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4558 static void
4559 modify_known_vectors_with_val (vec<tree> *known_csts,
4560 vec<ipa_polymorphic_call_context> *known_contexts,
4561 ipcp_value<tree> *val,
4562 int index)
4564 *known_csts = known_csts->copy ();
4565 *known_contexts = copy_useful_known_contexts (*known_contexts);
4566 (*known_csts)[index] = val->value;
4569 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4570 copy according to VAL and INDEX. */
4572 static void
4573 modify_known_vectors_with_val (vec<tree> *known_csts,
4574 vec<ipa_polymorphic_call_context> *known_contexts,
4575 ipcp_value<ipa_polymorphic_call_context> *val,
4576 int index)
4578 *known_csts = known_csts->copy ();
4579 *known_contexts = known_contexts->copy ();
4580 (*known_contexts)[index] = val->value;
4583 /* Return true if OFFSET indicates this was not an aggregate value or there is
4584 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4585 AGGVALS list. */
4587 DEBUG_FUNCTION bool
4588 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4589 int index, HOST_WIDE_INT offset, tree value)
4591 if (offset == -1)
4592 return true;
4594 while (aggvals)
4596 if (aggvals->index == index
4597 && aggvals->offset == offset
4598 && values_equal_for_ipcp_p (aggvals->value, value))
4599 return true;
4600 aggvals = aggvals->next;
4602 return false;
4605 /* Return true if offset is minus one because source of a polymorphic contect
4606 cannot be an aggregate value. */
4608 DEBUG_FUNCTION bool
4609 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4610 int , HOST_WIDE_INT offset,
4611 ipa_polymorphic_call_context)
4613 return offset == -1;
4616 /* Decide wheter to create a special version of NODE for value VAL of parameter
4617 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4618 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4619 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4621 template <typename valtype>
4622 static bool
4623 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4624 ipcp_value<valtype> *val, vec<tree> known_csts,
4625 vec<ipa_polymorphic_call_context> known_contexts)
4627 struct ipa_agg_replacement_value *aggvals;
4628 int freq_sum, caller_count;
4629 profile_count count_sum;
4630 vec<cgraph_edge *> callers;
4632 if (val->spec_node)
4634 perhaps_add_new_callers (node, val);
4635 return false;
4637 else if (val->local_size_cost + overall_size > max_new_size)
4639 if (dump_file && (dump_flags & TDF_DETAILS))
4640 fprintf (dump_file, " Ignoring candidate value because "
4641 "max_new_size would be reached with %li.\n",
4642 val->local_size_cost + overall_size);
4643 return false;
4645 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4646 &caller_count))
4647 return false;
4649 if (dump_file && (dump_flags & TDF_DETAILS))
4651 fprintf (dump_file, " - considering value ");
4652 print_ipcp_constant_value (dump_file, val->value);
4653 fprintf (dump_file, " for ");
4654 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4655 if (offset != -1)
4656 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4657 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4660 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4661 freq_sum, count_sum,
4662 val->local_size_cost)
4663 && !good_cloning_opportunity_p (node,
4664 val->local_time_benefit
4665 + val->prop_time_benefit,
4666 freq_sum, count_sum,
4667 val->local_size_cost
4668 + val->prop_size_cost))
4669 return false;
4671 if (dump_file)
4672 fprintf (dump_file, " Creating a specialized node of %s.\n",
4673 node->dump_name ());
4675 callers = gather_edges_for_value (val, node, caller_count);
4676 if (offset == -1)
4677 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4678 else
4680 known_csts = known_csts.copy ();
4681 known_contexts = copy_useful_known_contexts (known_contexts);
4683 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4684 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4685 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4686 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4687 offset, val->value));
4688 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4689 aggvals, callers);
4690 overall_size += val->local_size_cost;
4692 /* TODO: If for some lattice there is only one other known value
4693 left, make a special node for it too. */
4695 return true;
4698 /* Decide whether and what specialized clones of NODE should be created. */
4700 static bool
4701 decide_whether_version_node (struct cgraph_node *node)
4703 struct ipa_node_params *info = IPA_NODE_REF (node);
4704 int i, count = ipa_get_param_count (info);
4705 vec<tree> known_csts;
4706 vec<ipa_polymorphic_call_context> known_contexts;
4707 vec<ipa_agg_jump_function> known_aggs = vNULL;
4708 bool ret = false;
4710 if (count == 0)
4711 return false;
4713 if (dump_file && (dump_flags & TDF_DETAILS))
4714 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
4715 node->dump_name ());
4717 gather_context_independent_values (info, &known_csts, &known_contexts,
4718 info->do_clone_for_all_contexts ? &known_aggs
4719 : NULL, NULL);
4721 for (i = 0; i < count;i++)
4723 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4724 ipcp_lattice<tree> *lat = &plats->itself;
4725 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4727 if (!lat->bottom
4728 && !known_csts[i])
4730 ipcp_value<tree> *val;
4731 for (val = lat->values; val; val = val->next)
4732 ret |= decide_about_value (node, i, -1, val, known_csts,
4733 known_contexts);
4736 if (!plats->aggs_bottom)
4738 struct ipcp_agg_lattice *aglat;
4739 ipcp_value<tree> *val;
4740 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4741 if (!aglat->bottom && aglat->values
4742 /* If the following is false, the one value is in
4743 known_aggs. */
4744 && (plats->aggs_contain_variable
4745 || !aglat->is_single_const ()))
4746 for (val = aglat->values; val; val = val->next)
4747 ret |= decide_about_value (node, i, aglat->offset, val,
4748 known_csts, known_contexts);
4751 if (!ctxlat->bottom
4752 && known_contexts[i].useless_p ())
4754 ipcp_value<ipa_polymorphic_call_context> *val;
4755 for (val = ctxlat->values; val; val = val->next)
4756 ret |= decide_about_value (node, i, -1, val, known_csts,
4757 known_contexts);
4760 info = IPA_NODE_REF (node);
4763 if (info->do_clone_for_all_contexts)
4765 struct cgraph_node *clone;
4766 vec<cgraph_edge *> callers;
4768 if (dump_file)
4769 fprintf (dump_file, " - Creating a specialized node of %s "
4770 "for all known contexts.\n", node->dump_name ());
4772 callers = node->collect_callers ();
4773 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4774 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4775 ipa_agg_replacement_value *aggvals
4776 = find_aggregate_values_for_callers_subset (node, callers);
4778 if (!known_contexts_useful_p (known_contexts))
4780 known_contexts.release ();
4781 known_contexts = vNULL;
4783 clone = create_specialized_node (node, known_csts, known_contexts,
4784 aggvals, callers);
4785 info = IPA_NODE_REF (node);
4786 info->do_clone_for_all_contexts = false;
4787 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4788 for (i = 0; i < count; i++)
4789 vec_free (known_aggs[i].items);
4790 known_aggs.release ();
4791 ret = true;
4793 else
4795 known_csts.release ();
4796 known_contexts.release ();
4799 return ret;
4802 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4804 static void
4805 spread_undeadness (struct cgraph_node *node)
4807 struct cgraph_edge *cs;
4809 for (cs = node->callees; cs; cs = cs->next_callee)
4810 if (ipa_edge_within_scc (cs))
4812 struct cgraph_node *callee;
4813 struct ipa_node_params *info;
4815 callee = cs->callee->function_symbol (NULL);
4816 info = IPA_NODE_REF (callee);
4818 if (info->node_dead)
4820 info->node_dead = 0;
4821 spread_undeadness (callee);
4826 /* Return true if NODE has a caller from outside of its SCC that is not
4827 dead. Worker callback for cgraph_for_node_and_aliases. */
4829 static bool
4830 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4831 void *data ATTRIBUTE_UNUSED)
4833 struct cgraph_edge *cs;
4835 for (cs = node->callers; cs; cs = cs->next_caller)
4836 if (cs->caller->thunk.thunk_p
4837 && cs->caller->call_for_symbol_thunks_and_aliases
4838 (has_undead_caller_from_outside_scc_p, NULL, true))
4839 return true;
4840 else if (!ipa_edge_within_scc (cs)
4841 && !IPA_NODE_REF (cs->caller)->node_dead)
4842 return true;
4843 return false;
4847 /* Identify nodes within the same SCC as NODE which are no longer needed
4848 because of new clones and will be removed as unreachable. */
4850 static void
4851 identify_dead_nodes (struct cgraph_node *node)
4853 struct cgraph_node *v;
4854 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4855 if (v->local.local
4856 && !v->call_for_symbol_thunks_and_aliases
4857 (has_undead_caller_from_outside_scc_p, NULL, true))
4858 IPA_NODE_REF (v)->node_dead = 1;
4860 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4861 if (!IPA_NODE_REF (v)->node_dead)
4862 spread_undeadness (v);
4864 if (dump_file && (dump_flags & TDF_DETAILS))
4866 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4867 if (IPA_NODE_REF (v)->node_dead)
4868 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
4872 /* The decision stage. Iterate over the topological order of call graph nodes
4873 TOPO and make specialized clones if deemed beneficial. */
4875 static void
4876 ipcp_decision_stage (struct ipa_topo_info *topo)
4878 int i;
4880 if (dump_file)
4881 fprintf (dump_file, "\nIPA decision stage:\n\n");
4883 for (i = topo->nnodes - 1; i >= 0; i--)
4885 struct cgraph_node *node = topo->order[i];
4886 bool change = false, iterate = true;
4888 while (iterate)
4890 struct cgraph_node *v;
4891 iterate = false;
4892 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4893 if (v->has_gimple_body_p ()
4894 && ipcp_versionable_function_p (v))
4895 iterate |= decide_whether_version_node (v);
4897 change |= iterate;
4899 if (change)
4900 identify_dead_nodes (node);
4904 /* Look up all the bits information that we have discovered and copy it over
4905 to the transformation summary. */
4907 static void
4908 ipcp_store_bits_results (void)
4910 cgraph_node *node;
4912 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4914 ipa_node_params *info = IPA_NODE_REF (node);
4915 bool dumped_sth = false;
4916 bool found_useful_result = false;
4918 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4920 if (dump_file)
4921 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4922 "; -fipa-bit-cp: disabled.\n",
4923 node->name ());
4924 continue;
4927 if (info->ipcp_orig_node)
4928 info = IPA_NODE_REF (info->ipcp_orig_node);
4930 unsigned count = ipa_get_param_count (info);
4931 for (unsigned i = 0; i < count; i++)
4933 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4934 if (plats->bits_lattice.constant_p ())
4936 found_useful_result = true;
4937 break;
4941 if (!found_useful_result)
4942 continue;
4944 ipcp_transformation_initialize ();
4945 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
4946 vec_safe_reserve_exact (ts->bits, count);
4948 for (unsigned i = 0; i < count; i++)
4950 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4951 ipa_bits *jfbits;
4953 if (plats->bits_lattice.constant_p ())
4954 jfbits
4955 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
4956 plats->bits_lattice.get_mask ());
4957 else
4958 jfbits = NULL;
4960 ts->bits->quick_push (jfbits);
4961 if (!dump_file || !jfbits)
4962 continue;
4963 if (!dumped_sth)
4965 fprintf (dump_file, "Propagated bits info for function %s:\n",
4966 node->dump_name ());
4967 dumped_sth = true;
4969 fprintf (dump_file, " param %i: value = ", i);
4970 print_hex (jfbits->value, dump_file);
4971 fprintf (dump_file, ", mask = ");
4972 print_hex (jfbits->mask, dump_file);
4973 fprintf (dump_file, "\n");
4978 /* Look up all VR information that we have discovered and copy it over
4979 to the transformation summary. */
4981 static void
4982 ipcp_store_vr_results (void)
4984 cgraph_node *node;
4986 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4988 ipa_node_params *info = IPA_NODE_REF (node);
4989 bool found_useful_result = false;
4991 if (!opt_for_fn (node->decl, flag_ipa_vrp))
4993 if (dump_file)
4994 fprintf (dump_file, "Not considering %s for VR discovery "
4995 "and propagate; -fipa-ipa-vrp: disabled.\n",
4996 node->name ());
4997 continue;
5000 if (info->ipcp_orig_node)
5001 info = IPA_NODE_REF (info->ipcp_orig_node);
5003 unsigned count = ipa_get_param_count (info);
5004 for (unsigned i = 0; i < count; i++)
5006 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5007 if (!plats->m_value_range.bottom_p ()
5008 && !plats->m_value_range.top_p ())
5010 found_useful_result = true;
5011 break;
5014 if (!found_useful_result)
5015 continue;
5017 ipcp_transformation_initialize ();
5018 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5019 vec_safe_reserve_exact (ts->m_vr, count);
5021 for (unsigned i = 0; i < count; i++)
5023 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5024 ipa_vr vr;
5026 if (!plats->m_value_range.bottom_p ()
5027 && !plats->m_value_range.top_p ())
5029 vr.known = true;
5030 vr.type = plats->m_value_range.m_vr.kind ();
5031 vr.min = wi::to_wide (plats->m_value_range.m_vr.min ());
5032 vr.max = wi::to_wide (plats->m_value_range.m_vr.max ());
5034 else
5036 vr.known = false;
5037 vr.type = VR_VARYING;
5038 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
5040 ts->m_vr->quick_push (vr);
5045 /* The IPCP driver. */
5047 static unsigned int
5048 ipcp_driver (void)
5050 struct ipa_topo_info topo;
5052 if (edge_clone_summaries == NULL)
5053 edge_clone_summaries = new edge_clone_summary_t (symtab);
5055 ipa_check_create_node_params ();
5056 ipa_check_create_edge_args ();
5057 clone_num_suffixes = new hash_map<const char *, unsigned>;
5059 if (dump_file)
5061 fprintf (dump_file, "\nIPA structures before propagation:\n");
5062 if (dump_flags & TDF_DETAILS)
5063 ipa_print_all_params (dump_file);
5064 ipa_print_all_jump_functions (dump_file);
5067 /* Topological sort. */
5068 build_toporder_info (&topo);
5069 /* Do the interprocedural propagation. */
5070 ipcp_propagate_stage (&topo);
5071 /* Decide what constant propagation and cloning should be performed. */
5072 ipcp_decision_stage (&topo);
5073 /* Store results of bits propagation. */
5074 ipcp_store_bits_results ();
5075 /* Store results of value range propagation. */
5076 ipcp_store_vr_results ();
5078 /* Free all IPCP structures. */
5079 delete clone_num_suffixes;
5080 free_toporder_info (&topo);
5081 delete edge_clone_summaries;
5082 edge_clone_summaries = NULL;
5083 ipa_free_all_structures_after_ipa_cp ();
5084 if (dump_file)
5085 fprintf (dump_file, "\nIPA constant propagation end\n");
5086 return 0;
5089 /* Initialization and computation of IPCP data structures. This is the initial
5090 intraprocedural analysis of functions, which gathers information to be
5091 propagated later on. */
5093 static void
5094 ipcp_generate_summary (void)
5096 struct cgraph_node *node;
5098 if (dump_file)
5099 fprintf (dump_file, "\nIPA constant propagation start:\n");
5100 ipa_register_cgraph_hooks ();
5102 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5103 ipa_analyze_node (node);
5106 /* Write ipcp summary for nodes in SET. */
5108 static void
5109 ipcp_write_summary (void)
5111 ipa_prop_write_jump_functions ();
5114 /* Read ipcp summary. */
5116 static void
5117 ipcp_read_summary (void)
5119 ipa_prop_read_jump_functions ();
5122 namespace {
5124 const pass_data pass_data_ipa_cp =
5126 IPA_PASS, /* type */
5127 "cp", /* name */
5128 OPTGROUP_NONE, /* optinfo_flags */
5129 TV_IPA_CONSTANT_PROP, /* tv_id */
5130 0, /* properties_required */
5131 0, /* properties_provided */
5132 0, /* properties_destroyed */
5133 0, /* todo_flags_start */
5134 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5137 class pass_ipa_cp : public ipa_opt_pass_d
5139 public:
5140 pass_ipa_cp (gcc::context *ctxt)
5141 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5142 ipcp_generate_summary, /* generate_summary */
5143 ipcp_write_summary, /* write_summary */
5144 ipcp_read_summary, /* read_summary */
5145 ipcp_write_transformation_summaries, /*
5146 write_optimization_summary */
5147 ipcp_read_transformation_summaries, /*
5148 read_optimization_summary */
5149 NULL, /* stmt_fixup */
5150 0, /* function_transform_todo_flags_start */
5151 ipcp_transform_function, /* function_transform */
5152 NULL) /* variable_transform */
5155 /* opt_pass methods: */
5156 virtual bool gate (function *)
5158 /* FIXME: We should remove the optimize check after we ensure we never run
5159 IPA passes when not optimizing. */
5160 return (flag_ipa_cp && optimize) || in_lto_p;
5163 virtual unsigned int execute (function *) { return ipcp_driver (); }
5165 }; // class pass_ipa_cp
5167 } // anon namespace
5169 ipa_opt_pass_d *
5170 make_pass_ipa_cp (gcc::context *ctxt)
5172 return new pass_ipa_cp (ctxt);
5175 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5176 within the same process. For use by toplev::finalize. */
5178 void
5179 ipa_cp_c_finalize (void)
5181 max_count = profile_count::uninitialized ();
5182 overall_size = 0;
5183 max_new_size = 0;