coarray_data_1.f90: Link against libatomic if target libatomic_available.
[official-gcc.git] / gcc / ipa-cp.c
blob59b15fa7362c87de3e063f5b727d1279456b6cd6
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2019 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 value 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 /* Skip constprop clones since we don't make lattices for them. */
546 if (info->ipcp_orig_node)
547 continue;
548 fprintf (f, " Node: %s:\n", node->dump_name ());
549 count = ipa_get_param_count (info);
550 for (i = 0; i < count; i++)
552 struct ipcp_agg_lattice *aglat;
553 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
554 fprintf (f, " param [%d]: ", i);
555 plats->itself.print (f, dump_sources, dump_benefits);
556 fprintf (f, " ctxs: ");
557 plats->ctxlat.print (f, dump_sources, dump_benefits);
558 plats->bits_lattice.print (f);
559 fprintf (f, " ");
560 plats->m_value_range.print (f);
561 fprintf (f, "\n");
562 if (plats->virt_call)
563 fprintf (f, " virt_call flag set\n");
565 if (plats->aggs_bottom)
567 fprintf (f, " AGGS BOTTOM\n");
568 continue;
570 if (plats->aggs_contain_variable)
571 fprintf (f, " AGGS VARIABLE\n");
572 for (aglat = plats->aggs; aglat; aglat = aglat->next)
574 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
575 plats->aggs_by_ref ? "ref " : "", aglat->offset);
576 aglat->print (f, dump_sources, dump_benefits);
582 /* Determine whether it is at all technically possible to create clones of NODE
583 and store this information in the ipa_node_params structure associated
584 with NODE. */
586 static void
587 determine_versionability (struct cgraph_node *node,
588 struct ipa_node_params *info)
590 const char *reason = NULL;
592 /* There are a number of generic reasons functions cannot be versioned. We
593 also cannot remove parameters if there are type attributes such as fnspec
594 present. */
595 if (node->alias || node->thunk.thunk_p)
596 reason = "alias or thunk";
597 else if (!node->local.versionable)
598 reason = "not a tree_versionable_function";
599 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
600 reason = "insufficient body availability";
601 else if (!opt_for_fn (node->decl, optimize)
602 || !opt_for_fn (node->decl, flag_ipa_cp))
603 reason = "non-optimized function";
604 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
606 /* Ideally we should clone the SIMD clones themselves and create
607 vector copies of them, so IPA-cp and SIMD clones can happily
608 coexist, but that may not be worth the effort. */
609 reason = "function has SIMD clones";
611 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
613 /* Ideally we should clone the target clones themselves and create
614 copies of them, so IPA-cp and target clones can happily
615 coexist, but that may not be worth the effort. */
616 reason = "function target_clones attribute";
618 /* Don't clone decls local to a comdat group; it breaks and for C++
619 decloned constructors, inlining is always better anyway. */
620 else if (node->comdat_local_p ())
621 reason = "comdat-local function";
622 else if (node->calls_comdat_local)
624 /* TODO: call is versionable if we make sure that all
625 callers are inside of a comdat group. */
626 reason = "calls comdat-local function";
629 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
630 work only when inlined. Cloning them may still lead to better code
631 because ipa-cp will not give up on cloning further. If the function is
632 external this however leads to wrong code because we may end up producing
633 offline copy of the function. */
634 if (DECL_EXTERNAL (node->decl))
635 for (cgraph_edge *edge = node->callees; !reason && edge;
636 edge = edge->next_callee)
637 if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL))
639 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
640 reason = "external function which calls va_arg_pack";
641 if (DECL_FUNCTION_CODE (edge->callee->decl)
642 == BUILT_IN_VA_ARG_PACK_LEN)
643 reason = "external function which calls va_arg_pack_len";
646 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
647 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
648 node->dump_name (), reason);
650 info->versionable = (reason == NULL);
653 /* Return true if it is at all technically possible to create clones of a
654 NODE. */
656 static bool
657 ipcp_versionable_function_p (struct cgraph_node *node)
659 return IPA_NODE_REF (node)->versionable;
662 /* Structure holding accumulated information about callers of a node. */
664 struct caller_statistics
666 profile_count count_sum;
667 int n_calls, n_hot_calls, freq_sum;
670 /* Initialize fields of STAT to zeroes. */
672 static inline void
673 init_caller_stats (struct caller_statistics *stats)
675 stats->count_sum = profile_count::zero ();
676 stats->n_calls = 0;
677 stats->n_hot_calls = 0;
678 stats->freq_sum = 0;
681 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
682 non-thunk incoming edges to NODE. */
684 static bool
685 gather_caller_stats (struct cgraph_node *node, void *data)
687 struct caller_statistics *stats = (struct caller_statistics *) data;
688 struct cgraph_edge *cs;
690 for (cs = node->callers; cs; cs = cs->next_caller)
691 if (!cs->caller->thunk.thunk_p)
693 if (cs->count.ipa ().initialized_p ())
694 stats->count_sum += cs->count.ipa ();
695 stats->freq_sum += cs->frequency ();
696 stats->n_calls++;
697 if (cs->maybe_hot_p ())
698 stats->n_hot_calls ++;
700 return false;
704 /* Return true if this NODE is viable candidate for cloning. */
706 static bool
707 ipcp_cloning_candidate_p (struct cgraph_node *node)
709 struct caller_statistics stats;
711 gcc_checking_assert (node->has_gimple_body_p ());
713 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
715 if (dump_file)
716 fprintf (dump_file, "Not considering %s for cloning; "
717 "-fipa-cp-clone disabled.\n",
718 node->name ());
719 return false;
722 if (node->optimize_for_size_p ())
724 if (dump_file)
725 fprintf (dump_file, "Not considering %s for cloning; "
726 "optimizing it for size.\n",
727 node->name ());
728 return false;
731 init_caller_stats (&stats);
732 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
734 if (ipa_fn_summaries->get (node)->self_size < stats.n_calls)
736 if (dump_file)
737 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
738 node->name ());
739 return true;
742 /* When profile is available and function is hot, propagate into it even if
743 calls seems cold; constant propagation can improve function's speed
744 significantly. */
745 if (max_count > profile_count::zero ())
747 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100))
749 if (dump_file)
750 fprintf (dump_file, "Considering %s for cloning; "
751 "usually called directly.\n",
752 node->name ());
753 return true;
756 if (!stats.n_hot_calls)
758 if (dump_file)
759 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
760 node->name ());
761 return false;
763 if (dump_file)
764 fprintf (dump_file, "Considering %s for cloning.\n",
765 node->name ());
766 return true;
769 template <typename valtype>
770 class value_topo_info
772 public:
773 /* Head of the linked list of topologically sorted values. */
774 ipcp_value<valtype> *values_topo;
775 /* Stack for creating SCCs, represented by a linked list too. */
776 ipcp_value<valtype> *stack;
777 /* Counter driving the algorithm in add_val_to_toposort. */
778 int dfs_counter;
780 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
782 void add_val (ipcp_value<valtype> *cur_val);
783 void propagate_effects ();
786 /* Arrays representing a topological ordering of call graph nodes and a stack
787 of nodes used during constant propagation and also data required to perform
788 topological sort of values and propagation of benefits in the determined
789 order. */
791 class ipa_topo_info
793 public:
794 /* Array with obtained topological order of cgraph nodes. */
795 struct cgraph_node **order;
796 /* Stack of cgraph nodes used during propagation within SCC until all values
797 in the SCC stabilize. */
798 struct cgraph_node **stack;
799 int nnodes, stack_top;
801 value_topo_info<tree> constants;
802 value_topo_info<ipa_polymorphic_call_context> contexts;
804 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
805 constants ()
809 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
811 static void
812 build_toporder_info (struct ipa_topo_info *topo)
814 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
815 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
817 gcc_checking_assert (topo->stack_top == 0);
818 topo->nnodes = ipa_reduced_postorder (topo->order, true, NULL);
821 /* Free information about strongly connected components and the arrays in
822 TOPO. */
824 static void
825 free_toporder_info (struct ipa_topo_info *topo)
827 ipa_free_postorder_info ();
828 free (topo->order);
829 free (topo->stack);
832 /* Add NODE to the stack in TOPO, unless it is already there. */
834 static inline void
835 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
837 struct ipa_node_params *info = IPA_NODE_REF (node);
838 if (info->node_enqueued)
839 return;
840 info->node_enqueued = 1;
841 topo->stack[topo->stack_top++] = node;
844 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
845 is empty. */
847 static struct cgraph_node *
848 pop_node_from_stack (struct ipa_topo_info *topo)
850 if (topo->stack_top)
852 struct cgraph_node *node;
853 topo->stack_top--;
854 node = topo->stack[topo->stack_top];
855 IPA_NODE_REF (node)->node_enqueued = 0;
856 return node;
858 else
859 return NULL;
862 /* Set lattice LAT to bottom and return true if it previously was not set as
863 such. */
865 template <typename valtype>
866 inline bool
867 ipcp_lattice<valtype>::set_to_bottom ()
869 bool ret = !bottom;
870 bottom = true;
871 return ret;
874 /* Mark lattice as containing an unknown value and return true if it previously
875 was not marked as such. */
877 template <typename valtype>
878 inline bool
879 ipcp_lattice<valtype>::set_contains_variable ()
881 bool ret = !contains_variable;
882 contains_variable = true;
883 return ret;
886 /* Set all aggregate lattices in PLATS to bottom and return true if they were
887 not previously set as such. */
889 static inline bool
890 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
892 bool ret = !plats->aggs_bottom;
893 plats->aggs_bottom = true;
894 return ret;
897 /* Mark all aggregate lattices in PLATS as containing an unknown value and
898 return true if they were not previously marked as such. */
900 static inline bool
901 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
903 bool ret = !plats->aggs_contain_variable;
904 plats->aggs_contain_variable = true;
905 return ret;
908 bool
909 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
911 return meet_with_1 (&other.m_vr);
914 /* Meet the current value of the lattice with value range described by VR
915 lattice. */
917 bool
918 ipcp_vr_lattice::meet_with (const value_range_base *p_vr)
920 return meet_with_1 (p_vr);
923 /* Meet the current value of the lattice with value range described by
924 OTHER_VR lattice. Return TRUE if anything changed. */
926 bool
927 ipcp_vr_lattice::meet_with_1 (const value_range_base *other_vr)
929 if (bottom_p ())
930 return false;
932 if (other_vr->varying_p ())
933 return set_to_bottom ();
935 value_range_base save (m_vr);
936 m_vr.union_ (other_vr);
937 return !m_vr.equal_p (save);
940 /* Return true if value range information in the lattice is yet unknown. */
942 bool
943 ipcp_vr_lattice::top_p () const
945 return m_vr.undefined_p ();
948 /* Return true if value range information in the lattice is known to be
949 unusable. */
951 bool
952 ipcp_vr_lattice::bottom_p () const
954 return m_vr.varying_p ();
957 /* Set value range information in the lattice to bottom. Return true if it
958 previously was in a different state. */
960 bool
961 ipcp_vr_lattice::set_to_bottom ()
963 if (m_vr.varying_p ())
964 return false;
965 m_vr.set_varying ();
966 return true;
969 /* Set lattice value to bottom, if it already isn't the case. */
971 bool
972 ipcp_bits_lattice::set_to_bottom ()
974 if (bottom_p ())
975 return false;
976 m_lattice_val = IPA_BITS_VARYING;
977 m_value = 0;
978 m_mask = -1;
979 return true;
982 /* Set to constant if it isn't already. Only meant to be called
983 when switching state from TOP. */
985 bool
986 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
988 gcc_assert (top_p ());
989 m_lattice_val = IPA_BITS_CONSTANT;
990 m_value = value;
991 m_mask = mask;
992 return true;
995 /* Convert operand to value, mask form. */
997 void
998 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
1000 wide_int get_nonzero_bits (const_tree);
1002 if (TREE_CODE (operand) == INTEGER_CST)
1004 *valuep = wi::to_widest (operand);
1005 *maskp = 0;
1007 else
1009 *valuep = 0;
1010 *maskp = -1;
1014 /* Meet operation, similar to ccp_lattice_meet, we xor values
1015 if this->value, value have different values at same bit positions, we want
1016 to drop that bit to varying. Return true if mask is changed.
1017 This function assumes that the lattice value is in CONSTANT state */
1019 bool
1020 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
1021 unsigned precision)
1023 gcc_assert (constant_p ());
1025 widest_int old_mask = m_mask;
1026 m_mask = (m_mask | mask) | (m_value ^ value);
1028 if (wi::sext (m_mask, precision) == -1)
1029 return set_to_bottom ();
1031 return m_mask != old_mask;
1034 /* Meet the bits lattice with operand
1035 described by <value, mask, sgn, precision. */
1037 bool
1038 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1039 unsigned precision)
1041 if (bottom_p ())
1042 return false;
1044 if (top_p ())
1046 if (wi::sext (mask, precision) == -1)
1047 return set_to_bottom ();
1048 return set_to_constant (value, mask);
1051 return meet_with_1 (value, mask, precision);
1054 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1055 if code is binary operation or bit_value_unop (other) if code is unary op.
1056 In the case when code is nop_expr, no adjustment is required. */
1058 bool
1059 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1060 signop sgn, enum tree_code code, tree operand)
1062 if (other.bottom_p ())
1063 return set_to_bottom ();
1065 if (bottom_p () || other.top_p ())
1066 return false;
1068 widest_int adjusted_value, adjusted_mask;
1070 if (TREE_CODE_CLASS (code) == tcc_binary)
1072 tree type = TREE_TYPE (operand);
1073 gcc_assert (INTEGRAL_TYPE_P (type));
1074 widest_int o_value, o_mask;
1075 get_value_and_mask (operand, &o_value, &o_mask);
1077 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1078 sgn, precision, other.get_value (), other.get_mask (),
1079 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1081 if (wi::sext (adjusted_mask, precision) == -1)
1082 return set_to_bottom ();
1085 else if (TREE_CODE_CLASS (code) == tcc_unary)
1087 bit_value_unop (code, sgn, precision, &adjusted_value,
1088 &adjusted_mask, sgn, precision, other.get_value (),
1089 other.get_mask ());
1091 if (wi::sext (adjusted_mask, precision) == -1)
1092 return set_to_bottom ();
1095 else
1096 return set_to_bottom ();
1098 if (top_p ())
1100 if (wi::sext (adjusted_mask, precision) == -1)
1101 return set_to_bottom ();
1102 return set_to_constant (adjusted_value, adjusted_mask);
1104 else
1105 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1108 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1109 return true is any of them has not been marked as such so far. */
1111 static inline bool
1112 set_all_contains_variable (struct ipcp_param_lattices *plats)
1114 bool ret;
1115 ret = plats->itself.set_contains_variable ();
1116 ret |= plats->ctxlat.set_contains_variable ();
1117 ret |= set_agg_lats_contain_variable (plats);
1118 ret |= plats->bits_lattice.set_to_bottom ();
1119 ret |= plats->m_value_range.set_to_bottom ();
1120 return ret;
1123 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1124 points to by the number of callers to NODE. */
1126 static bool
1127 count_callers (cgraph_node *node, void *data)
1129 int *caller_count = (int *) data;
1131 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1132 /* Local thunks can be handled transparently, but if the thunk cannot
1133 be optimized out, count it as a real use. */
1134 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
1135 ++*caller_count;
1136 return false;
1139 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1140 the one caller of some other node. Set the caller's corresponding flag. */
1142 static bool
1143 set_single_call_flag (cgraph_node *node, void *)
1145 cgraph_edge *cs = node->callers;
1146 /* Local thunks can be handled transparently, skip them. */
1147 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
1148 cs = cs->next_caller;
1149 if (cs)
1151 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1152 return true;
1154 return false;
1157 /* Initialize ipcp_lattices. */
1159 static void
1160 initialize_node_lattices (struct cgraph_node *node)
1162 struct ipa_node_params *info = IPA_NODE_REF (node);
1163 struct cgraph_edge *ie;
1164 bool disable = false, variable = false;
1165 int i;
1167 gcc_checking_assert (node->has_gimple_body_p ());
1168 if (node->local.local)
1170 int caller_count = 0;
1171 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1172 true);
1173 gcc_checking_assert (caller_count > 0);
1174 if (caller_count == 1)
1175 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1176 NULL, true);
1178 else
1180 /* When cloning is allowed, we can assume that externally visible
1181 functions are not called. We will compensate this by cloning
1182 later. */
1183 if (ipcp_versionable_function_p (node)
1184 && ipcp_cloning_candidate_p (node))
1185 variable = true;
1186 else
1187 disable = true;
1190 for (i = 0; i < ipa_get_param_count (info); i++)
1192 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1193 plats->m_value_range.init ();
1196 if (disable || variable)
1198 for (i = 0; i < ipa_get_param_count (info); i++)
1200 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1201 if (disable)
1203 plats->itself.set_to_bottom ();
1204 plats->ctxlat.set_to_bottom ();
1205 set_agg_lats_to_bottom (plats);
1206 plats->bits_lattice.set_to_bottom ();
1207 plats->m_value_range.set_to_bottom ();
1209 else
1210 set_all_contains_variable (plats);
1212 if (dump_file && (dump_flags & TDF_DETAILS)
1213 && !node->alias && !node->thunk.thunk_p)
1214 fprintf (dump_file, "Marking all lattices of %s as %s\n",
1215 node->dump_name (), disable ? "BOTTOM" : "VARIABLE");
1218 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1219 if (ie->indirect_info->polymorphic
1220 && ie->indirect_info->param_index >= 0)
1222 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1223 ipa_get_parm_lattices (info,
1224 ie->indirect_info->param_index)->virt_call = 1;
1228 /* Return the result of a (possibly arithmetic) pass through jump function
1229 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter
1230 to which the result is passed. Return NULL_TREE if that cannot be
1231 determined or be considered an interprocedural invariant. */
1233 static tree
1234 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input,
1235 tree res_type)
1237 tree res;
1239 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1240 return input;
1241 if (!is_gimple_ip_invariant (input))
1242 return NULL_TREE;
1244 tree_code opcode = ipa_get_jf_pass_through_operation (jfunc);
1245 if (!res_type)
1247 if (TREE_CODE_CLASS (opcode) == tcc_comparison)
1248 res_type = boolean_type_node;
1249 else if (expr_type_first_operand_type_p (opcode))
1250 res_type = TREE_TYPE (input);
1251 else
1252 return NULL_TREE;
1255 if (TREE_CODE_CLASS (opcode) == tcc_unary)
1256 res = fold_unary (opcode, res_type, input);
1257 else
1258 res = fold_binary (opcode, res_type, input,
1259 ipa_get_jf_pass_through_operand (jfunc));
1261 if (res && !is_gimple_ip_invariant (res))
1262 return NULL_TREE;
1264 return res;
1267 /* Return the result of an ancestor jump function JFUNC on the constant value
1268 INPUT. Return NULL_TREE if that cannot be determined. */
1270 static tree
1271 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1273 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1274 if (TREE_CODE (input) == ADDR_EXPR)
1276 tree t = TREE_OPERAND (input, 0);
1277 t = build_ref_for_offset (EXPR_LOCATION (t), t,
1278 ipa_get_jf_ancestor_offset (jfunc), false,
1279 ptr_type_node, NULL, false);
1280 return build_fold_addr_expr (t);
1282 else
1283 return NULL_TREE;
1286 /* Determine whether JFUNC evaluates to a single known constant value and if
1287 so, return it. Otherwise return NULL. INFO describes the caller node or
1288 the one it is inlined to, so that pass-through jump functions can be
1289 evaluated. PARM_TYPE is the type of the parameter to which the result is
1290 passed. */
1292 tree
1293 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc,
1294 tree parm_type)
1296 if (jfunc->type == IPA_JF_CONST)
1297 return ipa_get_jf_constant (jfunc);
1298 else if (jfunc->type == IPA_JF_PASS_THROUGH
1299 || jfunc->type == IPA_JF_ANCESTOR)
1301 tree input;
1302 int idx;
1304 if (jfunc->type == IPA_JF_PASS_THROUGH)
1305 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1306 else
1307 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1309 if (info->ipcp_orig_node)
1310 input = info->known_csts[idx];
1311 else
1313 ipcp_lattice<tree> *lat;
1315 if (!info->lattices
1316 || idx >= ipa_get_param_count (info))
1317 return NULL_TREE;
1318 lat = ipa_get_scalar_lat (info, idx);
1319 if (!lat->is_single_const ())
1320 return NULL_TREE;
1321 input = lat->values->value;
1324 if (!input)
1325 return NULL_TREE;
1327 if (jfunc->type == IPA_JF_PASS_THROUGH)
1328 return ipa_get_jf_pass_through_result (jfunc, input, parm_type);
1329 else
1330 return ipa_get_jf_ancestor_result (jfunc, input);
1332 else
1333 return NULL_TREE;
1336 /* Determine whether JFUNC evaluates to single known polymorphic context, given
1337 that INFO describes the caller node or the one it is inlined to, CS is the
1338 call graph edge corresponding to JFUNC and CSIDX index of the described
1339 parameter. */
1341 ipa_polymorphic_call_context
1342 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1343 ipa_jump_func *jfunc)
1345 ipa_edge_args *args = IPA_EDGE_REF (cs);
1346 ipa_polymorphic_call_context ctx;
1347 ipa_polymorphic_call_context *edge_ctx
1348 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1350 if (edge_ctx && !edge_ctx->useless_p ())
1351 ctx = *edge_ctx;
1353 if (jfunc->type == IPA_JF_PASS_THROUGH
1354 || jfunc->type == IPA_JF_ANCESTOR)
1356 ipa_polymorphic_call_context srcctx;
1357 int srcidx;
1358 bool type_preserved = true;
1359 if (jfunc->type == IPA_JF_PASS_THROUGH)
1361 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1362 return ctx;
1363 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1364 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1366 else
1368 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1369 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1371 if (info->ipcp_orig_node)
1373 if (info->known_contexts.exists ())
1374 srcctx = info->known_contexts[srcidx];
1376 else
1378 if (!info->lattices
1379 || srcidx >= ipa_get_param_count (info))
1380 return ctx;
1381 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1382 lat = ipa_get_poly_ctx_lat (info, srcidx);
1383 if (!lat->is_single_const ())
1384 return ctx;
1385 srcctx = lat->values->value;
1387 if (srcctx.useless_p ())
1388 return ctx;
1389 if (jfunc->type == IPA_JF_ANCESTOR)
1390 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1391 if (!type_preserved)
1392 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1393 srcctx.combine_with (ctx);
1394 return srcctx;
1397 return ctx;
1400 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1401 bottom, not containing a variable component and without any known value at
1402 the same time. */
1404 DEBUG_FUNCTION void
1405 ipcp_verify_propagated_values (void)
1407 struct cgraph_node *node;
1409 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1411 struct ipa_node_params *info = IPA_NODE_REF (node);
1412 int i, count = ipa_get_param_count (info);
1414 for (i = 0; i < count; i++)
1416 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1418 if (!lat->bottom
1419 && !lat->contains_variable
1420 && lat->values_count == 0)
1422 if (dump_file)
1424 symtab->dump (dump_file);
1425 fprintf (dump_file, "\nIPA lattices after constant "
1426 "propagation, before gcc_unreachable:\n");
1427 print_all_lattices (dump_file, true, false);
1430 gcc_unreachable ();
1436 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1438 static bool
1439 values_equal_for_ipcp_p (tree x, tree y)
1441 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1443 if (x == y)
1444 return true;
1446 if (TREE_CODE (x) == ADDR_EXPR
1447 && TREE_CODE (y) == ADDR_EXPR
1448 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1449 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1450 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1451 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1452 else
1453 return operand_equal_p (x, y, 0);
1456 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1458 static bool
1459 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1460 ipa_polymorphic_call_context y)
1462 return x.equal_to (y);
1466 /* Add a new value source to the value represented by THIS, marking that a
1467 value comes from edge CS and (if the underlying jump function is a
1468 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1469 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1470 scalar value of the parameter itself or the offset within an aggregate. */
1472 template <typename valtype>
1473 void
1474 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1475 int src_idx, HOST_WIDE_INT offset)
1477 ipcp_value_source<valtype> *src;
1479 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1480 src->offset = offset;
1481 src->cs = cs;
1482 src->val = src_val;
1483 src->index = src_idx;
1485 src->next = sources;
1486 sources = src;
1489 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1490 SOURCE and clear all other fields. */
1492 static ipcp_value<tree> *
1493 allocate_and_init_ipcp_value (tree source)
1495 ipcp_value<tree> *val;
1497 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1498 val->value = source;
1499 return val;
1502 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1503 value to SOURCE and clear all other fields. */
1505 static ipcp_value<ipa_polymorphic_call_context> *
1506 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1508 ipcp_value<ipa_polymorphic_call_context> *val;
1510 // TODO
1511 val = new (ipcp_poly_ctx_values_pool.allocate ())
1512 ipcp_value<ipa_polymorphic_call_context>();
1513 val->value = source;
1514 return val;
1517 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1518 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1519 meaning. OFFSET -1 means the source is scalar and not a part of an
1520 aggregate. */
1522 template <typename valtype>
1523 bool
1524 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1525 ipcp_value<valtype> *src_val,
1526 int src_idx, HOST_WIDE_INT offset)
1528 ipcp_value<valtype> *val;
1530 if (bottom)
1531 return false;
1533 for (val = values; val; val = val->next)
1534 if (values_equal_for_ipcp_p (val->value, newval))
1536 if (ipa_edge_within_scc (cs))
1538 ipcp_value_source<valtype> *s;
1539 for (s = val->sources; s; s = s->next)
1540 if (s->cs == cs)
1541 break;
1542 if (s)
1543 return false;
1546 val->add_source (cs, src_val, src_idx, offset);
1547 return false;
1550 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1552 /* We can only free sources, not the values themselves, because sources
1553 of other values in this SCC might point to them. */
1554 for (val = values; val; val = val->next)
1556 while (val->sources)
1558 ipcp_value_source<valtype> *src = val->sources;
1559 val->sources = src->next;
1560 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1564 values = NULL;
1565 return set_to_bottom ();
1568 values_count++;
1569 val = allocate_and_init_ipcp_value (newval);
1570 val->add_source (cs, src_val, src_idx, offset);
1571 val->next = values;
1572 values = val;
1573 return true;
1576 /* Propagate values through a pass-through jump function JFUNC associated with
1577 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1578 is the index of the source parameter. PARM_TYPE is the type of the
1579 parameter to which the result is passed. */
1581 static bool
1582 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
1583 ipcp_lattice<tree> *src_lat,
1584 ipcp_lattice<tree> *dest_lat, int src_idx,
1585 tree parm_type)
1587 ipcp_value<tree> *src_val;
1588 bool ret = false;
1590 /* Do not create new values when propagating within an SCC because if there
1591 are arithmetic functions with circular dependencies, there is infinite
1592 number of them and we would just make lattices bottom. If this condition
1593 is ever relaxed we have to detect self-feeding recursive calls in
1594 cgraph_edge_brings_value_p in a smarter way. */
1595 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1596 && ipa_edge_within_scc (cs))
1597 ret = dest_lat->set_contains_variable ();
1598 else
1599 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1601 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value,
1602 parm_type);
1604 if (cstval)
1605 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1606 else
1607 ret |= dest_lat->set_contains_variable ();
1610 return ret;
1613 /* Propagate values through an ancestor jump function JFUNC associated with
1614 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1615 is the index of the source parameter. */
1617 static bool
1618 propagate_vals_across_ancestor (struct cgraph_edge *cs,
1619 struct ipa_jump_func *jfunc,
1620 ipcp_lattice<tree> *src_lat,
1621 ipcp_lattice<tree> *dest_lat, int src_idx)
1623 ipcp_value<tree> *src_val;
1624 bool ret = false;
1626 if (ipa_edge_within_scc (cs))
1627 return dest_lat->set_contains_variable ();
1629 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1631 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1633 if (t)
1634 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1635 else
1636 ret |= dest_lat->set_contains_variable ();
1639 return ret;
1642 /* Propagate scalar values across jump function JFUNC that is associated with
1643 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the
1644 parameter to which the result is passed. */
1646 static bool
1647 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
1648 struct ipa_jump_func *jfunc,
1649 ipcp_lattice<tree> *dest_lat,
1650 tree param_type)
1652 if (dest_lat->bottom)
1653 return false;
1655 if (jfunc->type == IPA_JF_CONST)
1657 tree val = ipa_get_jf_constant (jfunc);
1658 return dest_lat->add_value (val, cs, NULL, 0);
1660 else if (jfunc->type == IPA_JF_PASS_THROUGH
1661 || jfunc->type == IPA_JF_ANCESTOR)
1663 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1664 ipcp_lattice<tree> *src_lat;
1665 int src_idx;
1666 bool ret;
1668 if (jfunc->type == IPA_JF_PASS_THROUGH)
1669 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1670 else
1671 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1673 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1674 if (src_lat->bottom)
1675 return dest_lat->set_contains_variable ();
1677 /* If we would need to clone the caller and cannot, do not propagate. */
1678 if (!ipcp_versionable_function_p (cs->caller)
1679 && (src_lat->contains_variable
1680 || (src_lat->values_count > 1)))
1681 return dest_lat->set_contains_variable ();
1683 if (jfunc->type == IPA_JF_PASS_THROUGH)
1684 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
1685 dest_lat, src_idx, param_type);
1686 else
1687 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
1688 src_idx);
1690 if (src_lat->contains_variable)
1691 ret |= dest_lat->set_contains_variable ();
1693 return ret;
1696 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1697 use it for indirect inlining), we should propagate them too. */
1698 return dest_lat->set_contains_variable ();
1701 /* Propagate scalar values across jump function JFUNC that is associated with
1702 edge CS and describes argument IDX and put the values into DEST_LAT. */
1704 static bool
1705 propagate_context_across_jump_function (cgraph_edge *cs,
1706 ipa_jump_func *jfunc, int idx,
1707 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1709 ipa_edge_args *args = IPA_EDGE_REF (cs);
1710 if (dest_lat->bottom)
1711 return false;
1712 bool ret = false;
1713 bool added_sth = false;
1714 bool type_preserved = true;
1716 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1717 = ipa_get_ith_polymorhic_call_context (args, idx);
1719 if (edge_ctx_ptr)
1720 edge_ctx = *edge_ctx_ptr;
1722 if (jfunc->type == IPA_JF_PASS_THROUGH
1723 || jfunc->type == IPA_JF_ANCESTOR)
1725 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1726 int src_idx;
1727 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1729 /* TODO: Once we figure out how to propagate speculations, it will
1730 probably be a good idea to switch to speculation if type_preserved is
1731 not set instead of punting. */
1732 if (jfunc->type == IPA_JF_PASS_THROUGH)
1734 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1735 goto prop_fail;
1736 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1737 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1739 else
1741 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1742 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1745 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1746 /* If we would need to clone the caller and cannot, do not propagate. */
1747 if (!ipcp_versionable_function_p (cs->caller)
1748 && (src_lat->contains_variable
1749 || (src_lat->values_count > 1)))
1750 goto prop_fail;
1752 ipcp_value<ipa_polymorphic_call_context> *src_val;
1753 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1755 ipa_polymorphic_call_context cur = src_val->value;
1757 if (!type_preserved)
1758 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1759 if (jfunc->type == IPA_JF_ANCESTOR)
1760 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1761 /* TODO: In cases we know how the context is going to be used,
1762 we can improve the result by passing proper OTR_TYPE. */
1763 cur.combine_with (edge_ctx);
1764 if (!cur.useless_p ())
1766 if (src_lat->contains_variable
1767 && !edge_ctx.equal_to (cur))
1768 ret |= dest_lat->set_contains_variable ();
1769 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1770 added_sth = true;
1776 prop_fail:
1777 if (!added_sth)
1779 if (!edge_ctx.useless_p ())
1780 ret |= dest_lat->add_value (edge_ctx, cs);
1781 else
1782 ret |= dest_lat->set_contains_variable ();
1785 return ret;
1788 /* Propagate bits across jfunc that is associated with
1789 edge cs and update dest_lattice accordingly. */
1791 bool
1792 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
1793 ipa_jump_func *jfunc,
1794 ipcp_bits_lattice *dest_lattice)
1796 if (dest_lattice->bottom_p ())
1797 return false;
1799 enum availability availability;
1800 cgraph_node *callee = cs->callee->function_symbol (&availability);
1801 struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
1802 tree parm_type = ipa_get_type (callee_info, idx);
1804 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the
1805 transform for these cases. Similarly, we can have bad type mismatches
1806 with LTO, avoid doing anything with those too. */
1807 if (!parm_type
1808 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type)))
1810 if (dump_file && (dump_flags & TDF_DETAILS))
1811 fprintf (dump_file, "Setting dest_lattice to bottom, because type of "
1812 "param %i of %s is NULL or unsuitable for bits propagation\n",
1813 idx, cs->callee->name ());
1815 return dest_lattice->set_to_bottom ();
1818 unsigned precision = TYPE_PRECISION (parm_type);
1819 signop sgn = TYPE_SIGN (parm_type);
1821 if (jfunc->type == IPA_JF_PASS_THROUGH
1822 || jfunc->type == IPA_JF_ANCESTOR)
1824 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1825 tree operand = NULL_TREE;
1826 enum tree_code code;
1827 unsigned src_idx;
1829 if (jfunc->type == IPA_JF_PASS_THROUGH)
1831 code = ipa_get_jf_pass_through_operation (jfunc);
1832 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1833 if (code != NOP_EXPR)
1834 operand = ipa_get_jf_pass_through_operand (jfunc);
1836 else
1838 code = POINTER_PLUS_EXPR;
1839 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1840 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
1841 operand = build_int_cstu (size_type_node, offset);
1844 struct ipcp_param_lattices *src_lats
1845 = ipa_get_parm_lattices (caller_info, src_idx);
1847 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1848 for eg consider:
1849 int f(int x)
1851 g (x & 0xff);
1853 Assume lattice for x is bottom, however we can still propagate
1854 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1855 and we store it in jump function during analysis stage. */
1857 if (src_lats->bits_lattice.bottom_p ()
1858 && jfunc->bits)
1859 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1860 precision);
1861 else
1862 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
1863 code, operand);
1866 else if (jfunc->type == IPA_JF_ANCESTOR)
1867 return dest_lattice->set_to_bottom ();
1868 else if (jfunc->bits)
1869 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1870 precision);
1871 else
1872 return dest_lattice->set_to_bottom ();
1875 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1876 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1877 the result is a range or an anti-range. */
1879 static bool
1880 ipa_vr_operation_and_type_effects (value_range_base *dst_vr,
1881 value_range_base *src_vr,
1882 enum tree_code operation,
1883 tree dst_type, tree src_type)
1885 extract_range_from_unary_expr (dst_vr, operation, dst_type,
1886 src_vr, src_type);
1887 if (dst_vr->varying_p () || dst_vr->undefined_p ())
1888 return false;
1889 return true;
1892 /* Propagate value range across jump function JFUNC that is associated with
1893 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1894 accordingly. */
1896 static bool
1897 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
1898 struct ipcp_param_lattices *dest_plats,
1899 tree param_type)
1901 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
1903 if (dest_lat->bottom_p ())
1904 return false;
1906 if (!param_type
1907 || (!INTEGRAL_TYPE_P (param_type)
1908 && !POINTER_TYPE_P (param_type)))
1909 return dest_lat->set_to_bottom ();
1911 if (jfunc->type == IPA_JF_PASS_THROUGH)
1913 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1915 if (TREE_CODE_CLASS (operation) == tcc_unary)
1917 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1918 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1919 tree operand_type = ipa_get_type (caller_info, src_idx);
1920 struct ipcp_param_lattices *src_lats
1921 = ipa_get_parm_lattices (caller_info, src_idx);
1923 if (src_lats->m_value_range.bottom_p ())
1924 return dest_lat->set_to_bottom ();
1925 value_range_base vr;
1926 if (ipa_vr_operation_and_type_effects (&vr,
1927 &src_lats->m_value_range.m_vr,
1928 operation, param_type,
1929 operand_type))
1930 return dest_lat->meet_with (&vr);
1933 else if (jfunc->type == IPA_JF_CONST)
1935 tree val = ipa_get_jf_constant (jfunc);
1936 if (TREE_CODE (val) == INTEGER_CST)
1938 val = fold_convert (param_type, val);
1939 if (TREE_OVERFLOW_P (val))
1940 val = drop_tree_overflow (val);
1942 value_range_base tmpvr (VR_RANGE, val, val);
1943 return dest_lat->meet_with (&tmpvr);
1947 value_range_base vr;
1948 if (jfunc->m_vr
1949 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
1950 param_type,
1951 jfunc->m_vr->type ()))
1952 return dest_lat->meet_with (&vr);
1953 else
1954 return dest_lat->set_to_bottom ();
1957 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1958 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1959 other cases, return false). If there are no aggregate items, set
1960 aggs_by_ref to NEW_AGGS_BY_REF. */
1962 static bool
1963 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1964 bool new_aggs_by_ref)
1966 if (dest_plats->aggs)
1968 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1970 set_agg_lats_to_bottom (dest_plats);
1971 return true;
1974 else
1975 dest_plats->aggs_by_ref = new_aggs_by_ref;
1976 return false;
1979 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1980 already existing lattice for the given OFFSET and SIZE, marking all skipped
1981 lattices as containing variable and checking for overlaps. If there is no
1982 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1983 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1984 unless there are too many already. If there are two many, return false. If
1985 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1986 skipped lattices were newly marked as containing variable, set *CHANGE to
1987 true. */
1989 static bool
1990 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1991 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1992 struct ipcp_agg_lattice ***aglat,
1993 bool pre_existing, bool *change)
1995 gcc_checking_assert (offset >= 0);
1997 while (**aglat && (**aglat)->offset < offset)
1999 if ((**aglat)->offset + (**aglat)->size > offset)
2001 set_agg_lats_to_bottom (dest_plats);
2002 return false;
2004 *change |= (**aglat)->set_contains_variable ();
2005 *aglat = &(**aglat)->next;
2008 if (**aglat && (**aglat)->offset == offset)
2010 if ((**aglat)->size != val_size
2011 || ((**aglat)->next
2012 && (**aglat)->next->offset < offset + val_size))
2014 set_agg_lats_to_bottom (dest_plats);
2015 return false;
2017 gcc_checking_assert (!(**aglat)->next
2018 || (**aglat)->next->offset >= offset + val_size);
2019 return true;
2021 else
2023 struct ipcp_agg_lattice *new_al;
2025 if (**aglat && (**aglat)->offset < offset + val_size)
2027 set_agg_lats_to_bottom (dest_plats);
2028 return false;
2030 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
2031 return false;
2032 dest_plats->aggs_count++;
2033 new_al = ipcp_agg_lattice_pool.allocate ();
2034 memset (new_al, 0, sizeof (*new_al));
2036 new_al->offset = offset;
2037 new_al->size = val_size;
2038 new_al->contains_variable = pre_existing;
2040 new_al->next = **aglat;
2041 **aglat = new_al;
2042 return true;
2046 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2047 containing an unknown value. */
2049 static bool
2050 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2052 bool ret = false;
2053 while (aglat)
2055 ret |= aglat->set_contains_variable ();
2056 aglat = aglat->next;
2058 return ret;
2061 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2062 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2063 parameter used for lattice value sources. Return true if DEST_PLATS changed
2064 in any way. */
2066 static bool
2067 merge_aggregate_lattices (struct cgraph_edge *cs,
2068 struct ipcp_param_lattices *dest_plats,
2069 struct ipcp_param_lattices *src_plats,
2070 int src_idx, HOST_WIDE_INT offset_delta)
2072 bool pre_existing = dest_plats->aggs != NULL;
2073 struct ipcp_agg_lattice **dst_aglat;
2074 bool ret = false;
2076 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2077 return true;
2078 if (src_plats->aggs_bottom)
2079 return set_agg_lats_contain_variable (dest_plats);
2080 if (src_plats->aggs_contain_variable)
2081 ret |= set_agg_lats_contain_variable (dest_plats);
2082 dst_aglat = &dest_plats->aggs;
2084 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2085 src_aglat;
2086 src_aglat = src_aglat->next)
2088 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2090 if (new_offset < 0)
2091 continue;
2092 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2093 &dst_aglat, pre_existing, &ret))
2095 struct ipcp_agg_lattice *new_al = *dst_aglat;
2097 dst_aglat = &(*dst_aglat)->next;
2098 if (src_aglat->bottom)
2100 ret |= new_al->set_contains_variable ();
2101 continue;
2103 if (src_aglat->contains_variable)
2104 ret |= new_al->set_contains_variable ();
2105 for (ipcp_value<tree> *val = src_aglat->values;
2106 val;
2107 val = val->next)
2108 ret |= new_al->add_value (val->value, cs, val, src_idx,
2109 src_aglat->offset);
2111 else if (dest_plats->aggs_bottom)
2112 return true;
2114 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2115 return ret;
2118 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2119 pass-through JFUNC and if so, whether it has conform and conforms to the
2120 rules about propagating values passed by reference. */
2122 static bool
2123 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
2124 struct ipa_jump_func *jfunc)
2126 return src_plats->aggs
2127 && (!src_plats->aggs_by_ref
2128 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2131 /* Propagate scalar values across jump function JFUNC that is associated with
2132 edge CS and put the values into DEST_LAT. */
2134 static bool
2135 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2136 struct ipa_jump_func *jfunc,
2137 struct ipcp_param_lattices *dest_plats)
2139 bool ret = false;
2141 if (dest_plats->aggs_bottom)
2142 return false;
2144 if (jfunc->type == IPA_JF_PASS_THROUGH
2145 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2147 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2148 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2149 struct ipcp_param_lattices *src_plats;
2151 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2152 if (agg_pass_through_permissible_p (src_plats, jfunc))
2154 /* Currently we do not produce clobber aggregate jump
2155 functions, replace with merging when we do. */
2156 gcc_assert (!jfunc->agg.items);
2157 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2158 src_idx, 0);
2160 else
2161 ret |= set_agg_lats_contain_variable (dest_plats);
2163 else if (jfunc->type == IPA_JF_ANCESTOR
2164 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2166 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2167 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2168 struct ipcp_param_lattices *src_plats;
2170 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2171 if (src_plats->aggs && src_plats->aggs_by_ref)
2173 /* Currently we do not produce clobber aggregate jump
2174 functions, replace with merging when we do. */
2175 gcc_assert (!jfunc->agg.items);
2176 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2177 ipa_get_jf_ancestor_offset (jfunc));
2179 else if (!src_plats->aggs_by_ref)
2180 ret |= set_agg_lats_to_bottom (dest_plats);
2181 else
2182 ret |= set_agg_lats_contain_variable (dest_plats);
2184 else if (jfunc->agg.items)
2186 bool pre_existing = dest_plats->aggs != NULL;
2187 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2188 struct ipa_agg_jf_item *item;
2189 int i;
2191 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2192 return true;
2194 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2196 HOST_WIDE_INT val_size;
2198 if (item->offset < 0)
2199 continue;
2200 gcc_checking_assert (is_gimple_ip_invariant (item->value));
2201 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2203 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2204 &aglat, pre_existing, &ret))
2206 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2207 aglat = &(*aglat)->next;
2209 else if (dest_plats->aggs_bottom)
2210 return true;
2213 ret |= set_chain_of_aglats_contains_variable (*aglat);
2215 else
2216 ret |= set_agg_lats_contain_variable (dest_plats);
2218 return ret;
2221 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2222 non-thunk) destination, the call passes through a thunk. */
2224 static bool
2225 call_passes_through_thunk_p (cgraph_edge *cs)
2227 cgraph_node *alias_or_thunk = cs->callee;
2228 while (alias_or_thunk->alias)
2229 alias_or_thunk = alias_or_thunk->get_alias_target ();
2230 return alias_or_thunk->thunk.thunk_p;
2233 /* Propagate constants from the caller to the callee of CS. INFO describes the
2234 caller. */
2236 static bool
2237 propagate_constants_across_call (struct cgraph_edge *cs)
2239 struct ipa_node_params *callee_info;
2240 enum availability availability;
2241 cgraph_node *callee;
2242 struct ipa_edge_args *args;
2243 bool ret = false;
2244 int i, args_count, parms_count;
2246 callee = cs->callee->function_symbol (&availability);
2247 if (!callee->definition)
2248 return false;
2249 gcc_checking_assert (callee->has_gimple_body_p ());
2250 callee_info = IPA_NODE_REF (callee);
2252 args = IPA_EDGE_REF (cs);
2253 args_count = ipa_get_cs_argument_count (args);
2254 parms_count = ipa_get_param_count (callee_info);
2255 if (parms_count == 0)
2256 return false;
2258 /* If this call goes through a thunk we must not propagate to the first (0th)
2259 parameter. However, we might need to uncover a thunk from below a series
2260 of aliases first. */
2261 if (call_passes_through_thunk_p (cs))
2263 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2264 0));
2265 i = 1;
2267 else
2268 i = 0;
2270 for (; (i < args_count) && (i < parms_count); i++)
2272 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2273 struct ipcp_param_lattices *dest_plats;
2274 tree param_type = ipa_get_type (callee_info, i);
2276 dest_plats = ipa_get_parm_lattices (callee_info, i);
2277 if (availability == AVAIL_INTERPOSABLE)
2278 ret |= set_all_contains_variable (dest_plats);
2279 else
2281 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2282 &dest_plats->itself,
2283 param_type);
2284 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2285 &dest_plats->ctxlat);
2287 |= propagate_bits_across_jump_function (cs, i, jump_func,
2288 &dest_plats->bits_lattice);
2289 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2290 dest_plats);
2291 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2292 ret |= propagate_vr_across_jump_function (cs, jump_func,
2293 dest_plats, param_type);
2294 else
2295 ret |= dest_plats->m_value_range.set_to_bottom ();
2298 for (; i < parms_count; i++)
2299 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2301 return ret;
2304 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2305 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2306 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2308 static tree
2309 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2310 vec<tree> known_csts,
2311 vec<ipa_polymorphic_call_context> known_contexts,
2312 vec<ipa_agg_jump_function_p> known_aggs,
2313 struct ipa_agg_replacement_value *agg_reps,
2314 bool *speculative)
2316 int param_index = ie->indirect_info->param_index;
2317 HOST_WIDE_INT anc_offset;
2318 tree t;
2319 tree target = NULL;
2321 *speculative = false;
2323 if (param_index == -1
2324 || known_csts.length () <= (unsigned int) param_index)
2325 return NULL_TREE;
2327 if (!ie->indirect_info->polymorphic)
2329 tree t;
2331 if (ie->indirect_info->agg_contents)
2333 t = NULL;
2334 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2336 while (agg_reps)
2338 if (agg_reps->index == param_index
2339 && agg_reps->offset == ie->indirect_info->offset
2340 && agg_reps->by_ref == ie->indirect_info->by_ref)
2342 t = agg_reps->value;
2343 break;
2345 agg_reps = agg_reps->next;
2348 if (!t)
2350 struct ipa_agg_jump_function *agg;
2351 if (known_aggs.length () > (unsigned int) param_index)
2352 agg = known_aggs[param_index];
2353 else
2354 agg = NULL;
2355 bool from_global_constant;
2356 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2357 ie->indirect_info->offset,
2358 ie->indirect_info->by_ref,
2359 &from_global_constant);
2360 if (t
2361 && !from_global_constant
2362 && !ie->indirect_info->guaranteed_unmodified)
2363 t = NULL_TREE;
2366 else
2367 t = known_csts[param_index];
2369 if (t
2370 && TREE_CODE (t) == ADDR_EXPR
2371 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2372 return TREE_OPERAND (t, 0);
2373 else
2374 return NULL_TREE;
2377 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2378 return NULL_TREE;
2380 gcc_assert (!ie->indirect_info->agg_contents);
2381 anc_offset = ie->indirect_info->offset;
2383 t = NULL;
2385 /* Try to work out value of virtual table pointer value in replacements. */
2386 if (!t && agg_reps && !ie->indirect_info->by_ref)
2388 while (agg_reps)
2390 if (agg_reps->index == param_index
2391 && agg_reps->offset == ie->indirect_info->offset
2392 && agg_reps->by_ref)
2394 t = agg_reps->value;
2395 break;
2397 agg_reps = agg_reps->next;
2401 /* Try to work out value of virtual table pointer value in known
2402 aggregate values. */
2403 if (!t && known_aggs.length () > (unsigned int) param_index
2404 && !ie->indirect_info->by_ref)
2406 struct ipa_agg_jump_function *agg;
2407 agg = known_aggs[param_index];
2408 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2409 ie->indirect_info->offset, true);
2412 /* If we found the virtual table pointer, lookup the target. */
2413 if (t)
2415 tree vtable;
2416 unsigned HOST_WIDE_INT offset;
2417 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2419 bool can_refer;
2420 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2421 vtable, offset, &can_refer);
2422 if (can_refer)
2424 if (!target
2425 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2426 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2427 || !possible_polymorphic_call_target_p
2428 (ie, cgraph_node::get (target)))
2430 /* Do not speculate builtin_unreachable, it is stupid! */
2431 if (ie->indirect_info->vptr_changed)
2432 return NULL;
2433 target = ipa_impossible_devirt_target (ie, target);
2435 *speculative = ie->indirect_info->vptr_changed;
2436 if (!*speculative)
2437 return target;
2442 /* Do we know the constant value of pointer? */
2443 if (!t)
2444 t = known_csts[param_index];
2446 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2448 ipa_polymorphic_call_context context;
2449 if (known_contexts.length () > (unsigned int) param_index)
2451 context = known_contexts[param_index];
2452 context.offset_by (anc_offset);
2453 if (ie->indirect_info->vptr_changed)
2454 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2455 ie->indirect_info->otr_type);
2456 if (t)
2458 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2459 (t, ie->indirect_info->otr_type, anc_offset);
2460 if (!ctx2.useless_p ())
2461 context.combine_with (ctx2, ie->indirect_info->otr_type);
2464 else if (t)
2466 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2467 anc_offset);
2468 if (ie->indirect_info->vptr_changed)
2469 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2470 ie->indirect_info->otr_type);
2472 else
2473 return NULL_TREE;
2475 vec <cgraph_node *>targets;
2476 bool final;
2478 targets = possible_polymorphic_call_targets
2479 (ie->indirect_info->otr_type,
2480 ie->indirect_info->otr_token,
2481 context, &final);
2482 if (!final || targets.length () > 1)
2484 struct cgraph_node *node;
2485 if (*speculative)
2486 return target;
2487 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2488 || ie->speculative || !ie->maybe_hot_p ())
2489 return NULL;
2490 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2491 ie->indirect_info->otr_token,
2492 context);
2493 if (node)
2495 *speculative = true;
2496 target = node->decl;
2498 else
2499 return NULL;
2501 else
2503 *speculative = false;
2504 if (targets.length () == 1)
2505 target = targets[0]->decl;
2506 else
2507 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2510 if (target && !possible_polymorphic_call_target_p (ie,
2511 cgraph_node::get (target)))
2513 if (*speculative)
2514 return NULL;
2515 target = ipa_impossible_devirt_target (ie, target);
2518 return target;
2522 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2523 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2524 return the destination. */
2526 tree
2527 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2528 vec<tree> known_csts,
2529 vec<ipa_polymorphic_call_context> known_contexts,
2530 vec<ipa_agg_jump_function_p> known_aggs,
2531 bool *speculative)
2533 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2534 known_aggs, NULL, speculative);
2537 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2538 and KNOWN_CONTEXTS. */
2540 static int
2541 devirtualization_time_bonus (struct cgraph_node *node,
2542 vec<tree> known_csts,
2543 vec<ipa_polymorphic_call_context> known_contexts,
2544 vec<ipa_agg_jump_function_p> known_aggs)
2546 struct cgraph_edge *ie;
2547 int res = 0;
2549 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2551 struct cgraph_node *callee;
2552 struct ipa_fn_summary *isummary;
2553 enum availability avail;
2554 tree target;
2555 bool speculative;
2557 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2558 known_aggs, &speculative);
2559 if (!target)
2560 continue;
2562 /* Only bare minimum benefit for clearly un-inlineable targets. */
2563 res += 1;
2564 callee = cgraph_node::get (target);
2565 if (!callee || !callee->definition)
2566 continue;
2567 callee = callee->function_symbol (&avail);
2568 if (avail < AVAIL_AVAILABLE)
2569 continue;
2570 isummary = ipa_fn_summaries->get (callee);
2571 if (!isummary->inlinable)
2572 continue;
2574 /* FIXME: The values below need re-considering and perhaps also
2575 integrating into the cost metrics, at lest in some very basic way. */
2576 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2577 res += 31 / ((int)speculative + 1);
2578 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2579 res += 15 / ((int)speculative + 1);
2580 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2581 || DECL_DECLARED_INLINE_P (callee->decl))
2582 res += 7 / ((int)speculative + 1);
2585 return res;
2588 /* Return time bonus incurred because of HINTS. */
2590 static int
2591 hint_time_bonus (ipa_hints hints)
2593 int result = 0;
2594 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2595 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2596 if (hints & INLINE_HINT_array_index)
2597 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2598 return result;
2601 /* If there is a reason to penalize the function described by INFO in the
2602 cloning goodness evaluation, do so. */
2604 static inline int64_t
2605 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2607 if (info->node_within_scc)
2608 evaluation = (evaluation
2609 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2611 if (info->node_calling_single_call)
2612 evaluation = (evaluation
2613 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2614 / 100;
2616 return evaluation;
2619 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2620 and SIZE_COST and with the sum of frequencies of incoming edges to the
2621 potential new clone in FREQUENCIES. */
2623 static bool
2624 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2625 int freq_sum, profile_count count_sum, int size_cost)
2627 if (time_benefit == 0
2628 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2629 || node->optimize_for_size_p ())
2630 return false;
2632 gcc_assert (size_cost > 0);
2634 struct ipa_node_params *info = IPA_NODE_REF (node);
2635 if (max_count > profile_count::zero ())
2637 int factor = RDIV (count_sum.probability_in
2638 (max_count).to_reg_br_prob_base ()
2639 * 1000, REG_BR_PROB_BASE);
2640 int64_t evaluation = (((int64_t) time_benefit * factor)
2641 / size_cost);
2642 evaluation = incorporate_penalties (info, evaluation);
2644 if (dump_file && (dump_flags & TDF_DETAILS))
2646 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2647 "size: %i, count_sum: ", time_benefit, size_cost);
2648 count_sum.dump (dump_file);
2649 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
2650 ", threshold: %i\n",
2651 info->node_within_scc ? ", scc" : "",
2652 info->node_calling_single_call ? ", single_call" : "",
2653 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2656 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2658 else
2660 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2661 / size_cost);
2662 evaluation = incorporate_penalties (info, evaluation);
2664 if (dump_file && (dump_flags & TDF_DETAILS))
2665 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2666 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2667 "%" PRId64 ", threshold: %i\n",
2668 time_benefit, size_cost, freq_sum,
2669 info->node_within_scc ? ", scc" : "",
2670 info->node_calling_single_call ? ", single_call" : "",
2671 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2673 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2677 /* Return all context independent values from aggregate lattices in PLATS in a
2678 vector. Return NULL if there are none. */
2680 static vec<ipa_agg_jf_item, va_gc> *
2681 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2683 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2685 if (plats->aggs_bottom
2686 || plats->aggs_contain_variable
2687 || plats->aggs_count == 0)
2688 return NULL;
2690 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2691 aglat;
2692 aglat = aglat->next)
2693 if (aglat->is_single_const ())
2695 struct ipa_agg_jf_item item;
2696 item.offset = aglat->offset;
2697 item.value = aglat->values->value;
2698 vec_safe_push (res, item);
2700 return res;
2703 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2704 populate them with values of parameters that are known independent of the
2705 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2706 non-NULL, the movement cost of all removable parameters will be stored in
2707 it. */
2709 static bool
2710 gather_context_independent_values (struct ipa_node_params *info,
2711 vec<tree> *known_csts,
2712 vec<ipa_polymorphic_call_context>
2713 *known_contexts,
2714 vec<ipa_agg_jump_function> *known_aggs,
2715 int *removable_params_cost)
2717 int i, count = ipa_get_param_count (info);
2718 bool ret = false;
2720 known_csts->create (0);
2721 known_contexts->create (0);
2722 known_csts->safe_grow_cleared (count);
2723 known_contexts->safe_grow_cleared (count);
2724 if (known_aggs)
2726 known_aggs->create (0);
2727 known_aggs->safe_grow_cleared (count);
2730 if (removable_params_cost)
2731 *removable_params_cost = 0;
2733 for (i = 0; i < count; i++)
2735 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2736 ipcp_lattice<tree> *lat = &plats->itself;
2738 if (lat->is_single_const ())
2740 ipcp_value<tree> *val = lat->values;
2741 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2742 (*known_csts)[i] = val->value;
2743 if (removable_params_cost)
2744 *removable_params_cost
2745 += estimate_move_cost (TREE_TYPE (val->value), false);
2746 ret = true;
2748 else if (removable_params_cost
2749 && !ipa_is_param_used (info, i))
2750 *removable_params_cost
2751 += ipa_get_param_move_cost (info, i);
2753 if (!ipa_is_param_used (info, i))
2754 continue;
2756 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2757 /* Do not account known context as reason for cloning. We can see
2758 if it permits devirtualization. */
2759 if (ctxlat->is_single_const ())
2760 (*known_contexts)[i] = ctxlat->values->value;
2762 if (known_aggs)
2764 vec<ipa_agg_jf_item, va_gc> *agg_items;
2765 struct ipa_agg_jump_function *ajf;
2767 agg_items = context_independent_aggregate_values (plats);
2768 ajf = &(*known_aggs)[i];
2769 ajf->items = agg_items;
2770 ajf->by_ref = plats->aggs_by_ref;
2771 ret |= agg_items != NULL;
2775 return ret;
2778 /* The current interface in ipa-inline-analysis requires a pointer vector.
2779 Create it.
2781 FIXME: That interface should be re-worked, this is slightly silly. Still,
2782 I'd like to discuss how to change it first and this demonstrates the
2783 issue. */
2785 static vec<ipa_agg_jump_function_p>
2786 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2788 vec<ipa_agg_jump_function_p> ret;
2789 struct ipa_agg_jump_function *ajf;
2790 int i;
2792 ret.create (known_aggs.length ());
2793 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2794 ret.quick_push (ajf);
2795 return ret;
2798 /* Perform time and size measurement of NODE with the context given in
2799 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2800 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2801 all context-independent removable parameters and EST_MOVE_COST of estimated
2802 movement of the considered parameter and store it into VAL. */
2804 static void
2805 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2806 vec<ipa_polymorphic_call_context> known_contexts,
2807 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2808 int removable_params_cost,
2809 int est_move_cost, ipcp_value_base *val)
2811 int size, time_benefit;
2812 sreal time, base_time;
2813 ipa_hints hints;
2815 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2816 known_aggs_ptrs, &size, &time,
2817 &base_time, &hints);
2818 base_time -= time;
2819 if (base_time > 65535)
2820 base_time = 65535;
2822 /* Extern inline functions have no cloning local time benefits because they
2823 will be inlined anyway. The only reason to clone them is if it enables
2824 optimization in any of the functions they call. */
2825 if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl))
2826 time_benefit = 0;
2827 else
2828 time_benefit = base_time.to_int ()
2829 + devirtualization_time_bonus (node, known_csts, known_contexts,
2830 known_aggs_ptrs)
2831 + hint_time_bonus (hints)
2832 + removable_params_cost + est_move_cost;
2834 gcc_checking_assert (size >=0);
2835 /* The inliner-heuristics based estimates may think that in certain
2836 contexts some functions do not have any size at all but we want
2837 all specializations to have at least a tiny cost, not least not to
2838 divide by zero. */
2839 if (size == 0)
2840 size = 1;
2842 val->local_time_benefit = time_benefit;
2843 val->local_size_cost = size;
2846 /* Iterate over known values of parameters of NODE and estimate the local
2847 effects in terms of time and size they have. */
2849 static void
2850 estimate_local_effects (struct cgraph_node *node)
2852 struct ipa_node_params *info = IPA_NODE_REF (node);
2853 int i, count = ipa_get_param_count (info);
2854 vec<tree> known_csts;
2855 vec<ipa_polymorphic_call_context> known_contexts;
2856 vec<ipa_agg_jump_function> known_aggs;
2857 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2858 bool always_const;
2859 int removable_params_cost;
2861 if (!count || !ipcp_versionable_function_p (node))
2862 return;
2864 if (dump_file && (dump_flags & TDF_DETAILS))
2865 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
2867 always_const = gather_context_independent_values (info, &known_csts,
2868 &known_contexts, &known_aggs,
2869 &removable_params_cost);
2870 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2871 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2872 known_contexts, known_aggs_ptrs);
2873 if (always_const || devirt_bonus
2874 || (removable_params_cost && node->local.can_change_signature))
2876 struct caller_statistics stats;
2877 ipa_hints hints;
2878 sreal time, base_time;
2879 int size;
2881 init_caller_stats (&stats);
2882 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2883 false);
2884 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2885 known_aggs_ptrs, &size, &time,
2886 &base_time, &hints);
2887 time -= devirt_bonus;
2888 time -= hint_time_bonus (hints);
2889 time -= removable_params_cost;
2890 size -= stats.n_calls * removable_params_cost;
2892 if (dump_file)
2893 fprintf (dump_file, " - context independent values, size: %i, "
2894 "time_benefit: %f\n", size, (base_time - time).to_double ());
2896 if (size <= 0 || node->local.local)
2898 info->do_clone_for_all_contexts = true;
2900 if (dump_file)
2901 fprintf (dump_file, " Decided to specialize for all "
2902 "known contexts, code not going to grow.\n");
2904 else if (good_cloning_opportunity_p (node,
2905 MIN ((base_time - time).to_int (),
2906 65536),
2907 stats.freq_sum, stats.count_sum,
2908 size))
2910 if (size + overall_size <= max_new_size)
2912 info->do_clone_for_all_contexts = true;
2913 overall_size += size;
2915 if (dump_file)
2916 fprintf (dump_file, " Decided to specialize for all "
2917 "known contexts, growth deemed beneficial.\n");
2919 else if (dump_file && (dump_flags & TDF_DETAILS))
2920 fprintf (dump_file, " Not cloning for all contexts because "
2921 "max_new_size would be reached with %li.\n",
2922 size + overall_size);
2924 else if (dump_file && (dump_flags & TDF_DETAILS))
2925 fprintf (dump_file, " Not cloning for all contexts because "
2926 "!good_cloning_opportunity_p.\n");
2930 for (i = 0; i < count; i++)
2932 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2933 ipcp_lattice<tree> *lat = &plats->itself;
2934 ipcp_value<tree> *val;
2936 if (lat->bottom
2937 || !lat->values
2938 || known_csts[i])
2939 continue;
2941 for (val = lat->values; val; val = val->next)
2943 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2944 known_csts[i] = val->value;
2946 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2947 perform_estimation_of_a_value (node, known_csts, known_contexts,
2948 known_aggs_ptrs,
2949 removable_params_cost, emc, val);
2951 if (dump_file && (dump_flags & TDF_DETAILS))
2953 fprintf (dump_file, " - estimates for value ");
2954 print_ipcp_constant_value (dump_file, val->value);
2955 fprintf (dump_file, " for ");
2956 ipa_dump_param (dump_file, info, i);
2957 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2958 val->local_time_benefit, val->local_size_cost);
2961 known_csts[i] = NULL_TREE;
2964 for (i = 0; i < count; i++)
2966 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2968 if (!plats->virt_call)
2969 continue;
2971 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2972 ipcp_value<ipa_polymorphic_call_context> *val;
2974 if (ctxlat->bottom
2975 || !ctxlat->values
2976 || !known_contexts[i].useless_p ())
2977 continue;
2979 for (val = ctxlat->values; val; val = val->next)
2981 known_contexts[i] = val->value;
2982 perform_estimation_of_a_value (node, known_csts, known_contexts,
2983 known_aggs_ptrs,
2984 removable_params_cost, 0, val);
2986 if (dump_file && (dump_flags & TDF_DETAILS))
2988 fprintf (dump_file, " - estimates for polymorphic context ");
2989 print_ipcp_constant_value (dump_file, val->value);
2990 fprintf (dump_file, " for ");
2991 ipa_dump_param (dump_file, info, i);
2992 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2993 val->local_time_benefit, val->local_size_cost);
2996 known_contexts[i] = ipa_polymorphic_call_context ();
2999 for (i = 0; i < count; i++)
3001 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3002 struct ipa_agg_jump_function *ajf;
3003 struct ipcp_agg_lattice *aglat;
3005 if (plats->aggs_bottom || !plats->aggs)
3006 continue;
3008 ajf = &known_aggs[i];
3009 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3011 ipcp_value<tree> *val;
3012 if (aglat->bottom || !aglat->values
3013 /* If the following is true, the one value is in known_aggs. */
3014 || (!plats->aggs_contain_variable
3015 && aglat->is_single_const ()))
3016 continue;
3018 for (val = aglat->values; val; val = val->next)
3020 struct ipa_agg_jf_item item;
3022 item.offset = aglat->offset;
3023 item.value = val->value;
3024 vec_safe_push (ajf->items, item);
3026 perform_estimation_of_a_value (node, known_csts, known_contexts,
3027 known_aggs_ptrs,
3028 removable_params_cost, 0, val);
3030 if (dump_file && (dump_flags & TDF_DETAILS))
3032 fprintf (dump_file, " - estimates for value ");
3033 print_ipcp_constant_value (dump_file, val->value);
3034 fprintf (dump_file, " for ");
3035 ipa_dump_param (dump_file, info, i);
3036 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3037 "]: time_benefit: %i, size: %i\n",
3038 plats->aggs_by_ref ? "ref " : "",
3039 aglat->offset,
3040 val->local_time_benefit, val->local_size_cost);
3043 ajf->items->pop ();
3048 for (i = 0; i < count; i++)
3049 vec_free (known_aggs[i].items);
3051 known_csts.release ();
3052 known_contexts.release ();
3053 known_aggs.release ();
3054 known_aggs_ptrs.release ();
3058 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3059 topological sort of values. */
3061 template <typename valtype>
3062 void
3063 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3065 ipcp_value_source<valtype> *src;
3067 if (cur_val->dfs)
3068 return;
3070 dfs_counter++;
3071 cur_val->dfs = dfs_counter;
3072 cur_val->low_link = dfs_counter;
3074 cur_val->topo_next = stack;
3075 stack = cur_val;
3076 cur_val->on_stack = true;
3078 for (src = cur_val->sources; src; src = src->next)
3079 if (src->val)
3081 if (src->val->dfs == 0)
3083 add_val (src->val);
3084 if (src->val->low_link < cur_val->low_link)
3085 cur_val->low_link = src->val->low_link;
3087 else if (src->val->on_stack
3088 && src->val->dfs < cur_val->low_link)
3089 cur_val->low_link = src->val->dfs;
3092 if (cur_val->dfs == cur_val->low_link)
3094 ipcp_value<valtype> *v, *scc_list = NULL;
3098 v = stack;
3099 stack = v->topo_next;
3100 v->on_stack = false;
3102 v->scc_next = scc_list;
3103 scc_list = v;
3105 while (v != cur_val);
3107 cur_val->topo_next = values_topo;
3108 values_topo = cur_val;
3112 /* Add all values in lattices associated with NODE to the topological sort if
3113 they are not there yet. */
3115 static void
3116 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3118 struct ipa_node_params *info = IPA_NODE_REF (node);
3119 int i, count = ipa_get_param_count (info);
3121 for (i = 0; i < count; i++)
3123 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3124 ipcp_lattice<tree> *lat = &plats->itself;
3125 struct ipcp_agg_lattice *aglat;
3127 if (!lat->bottom)
3129 ipcp_value<tree> *val;
3130 for (val = lat->values; val; val = val->next)
3131 topo->constants.add_val (val);
3134 if (!plats->aggs_bottom)
3135 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3136 if (!aglat->bottom)
3138 ipcp_value<tree> *val;
3139 for (val = aglat->values; val; val = val->next)
3140 topo->constants.add_val (val);
3143 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3144 if (!ctxlat->bottom)
3146 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3147 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3148 topo->contexts.add_val (ctxval);
3153 /* One pass of constants propagation along the call graph edges, from callers
3154 to callees (requires topological ordering in TOPO), iterate over strongly
3155 connected components. */
3157 static void
3158 propagate_constants_topo (struct ipa_topo_info *topo)
3160 int i;
3162 for (i = topo->nnodes - 1; i >= 0; i--)
3164 unsigned j;
3165 struct cgraph_node *v, *node = topo->order[i];
3166 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3168 /* First, iteratively propagate within the strongly connected component
3169 until all lattices stabilize. */
3170 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3171 if (v->has_gimple_body_p ())
3172 push_node_to_stack (topo, v);
3174 v = pop_node_from_stack (topo);
3175 while (v)
3177 struct cgraph_edge *cs;
3179 for (cs = v->callees; cs; cs = cs->next_callee)
3180 if (ipa_edge_within_scc (cs))
3182 IPA_NODE_REF (v)->node_within_scc = true;
3183 if (propagate_constants_across_call (cs))
3184 push_node_to_stack (topo, cs->callee->function_symbol ());
3186 v = pop_node_from_stack (topo);
3189 /* Afterwards, propagate along edges leading out of the SCC, calculates
3190 the local effects of the discovered constants and all valid values to
3191 their topological sort. */
3192 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3193 if (v->has_gimple_body_p ())
3195 struct cgraph_edge *cs;
3197 estimate_local_effects (v);
3198 add_all_node_vals_to_toposort (v, topo);
3199 for (cs = v->callees; cs; cs = cs->next_callee)
3200 if (!ipa_edge_within_scc (cs))
3201 propagate_constants_across_call (cs);
3203 cycle_nodes.release ();
3208 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3209 the bigger one if otherwise. */
3211 static int
3212 safe_add (int a, int b)
3214 if (a > INT_MAX/2 || b > INT_MAX/2)
3215 return a > b ? a : b;
3216 else
3217 return a + b;
3221 /* Propagate the estimated effects of individual values along the topological
3222 from the dependent values to those they depend on. */
3224 template <typename valtype>
3225 void
3226 value_topo_info<valtype>::propagate_effects ()
3228 ipcp_value<valtype> *base;
3230 for (base = values_topo; base; base = base->topo_next)
3232 ipcp_value_source<valtype> *src;
3233 ipcp_value<valtype> *val;
3234 int time = 0, size = 0;
3236 for (val = base; val; val = val->scc_next)
3238 time = safe_add (time,
3239 val->local_time_benefit + val->prop_time_benefit);
3240 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3243 for (val = base; val; val = val->scc_next)
3244 for (src = val->sources; src; src = src->next)
3245 if (src->val
3246 && src->cs->maybe_hot_p ())
3248 src->val->prop_time_benefit = safe_add (time,
3249 src->val->prop_time_benefit);
3250 src->val->prop_size_cost = safe_add (size,
3251 src->val->prop_size_cost);
3257 /* Propagate constants, polymorphic contexts and their effects from the
3258 summaries interprocedurally. */
3260 static void
3261 ipcp_propagate_stage (struct ipa_topo_info *topo)
3263 struct cgraph_node *node;
3265 if (dump_file)
3266 fprintf (dump_file, "\n Propagating constants:\n\n");
3268 max_count = profile_count::uninitialized ();
3270 FOR_EACH_DEFINED_FUNCTION (node)
3272 struct ipa_node_params *info = IPA_NODE_REF (node);
3274 determine_versionability (node, info);
3275 if (node->has_gimple_body_p ())
3277 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3278 ipa_get_param_count (info));
3279 initialize_node_lattices (node);
3281 ipa_fn_summary *s = ipa_fn_summaries->get (node);
3282 if (node->definition && !node->alias && s != NULL)
3283 overall_size += s->self_size;
3284 max_count = max_count.max (node->count.ipa ());
3287 max_new_size = overall_size;
3288 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3289 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3290 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3292 if (dump_file)
3293 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3294 overall_size, max_new_size);
3296 propagate_constants_topo (topo);
3297 if (flag_checking)
3298 ipcp_verify_propagated_values ();
3299 topo->constants.propagate_effects ();
3300 topo->contexts.propagate_effects ();
3302 if (dump_file)
3304 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3305 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3309 /* Discover newly direct outgoing edges from NODE which is a new clone with
3310 known KNOWN_CSTS and make them direct. */
3312 static void
3313 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3314 vec<tree> known_csts,
3315 vec<ipa_polymorphic_call_context>
3316 known_contexts,
3317 struct ipa_agg_replacement_value *aggvals)
3319 struct cgraph_edge *ie, *next_ie;
3320 bool found = false;
3322 for (ie = node->indirect_calls; ie; ie = next_ie)
3324 tree target;
3325 bool speculative;
3327 next_ie = ie->next_callee;
3328 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3329 vNULL, aggvals, &speculative);
3330 if (target)
3332 bool agg_contents = ie->indirect_info->agg_contents;
3333 bool polymorphic = ie->indirect_info->polymorphic;
3334 int param_index = ie->indirect_info->param_index;
3335 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3336 speculative);
3337 found = true;
3339 if (cs && !agg_contents && !polymorphic)
3341 struct ipa_node_params *info = IPA_NODE_REF (node);
3342 int c = ipa_get_controlled_uses (info, param_index);
3343 if (c != IPA_UNDESCRIBED_USE)
3345 struct ipa_ref *to_del;
3347 c--;
3348 ipa_set_controlled_uses (info, param_index, c);
3349 if (dump_file && (dump_flags & TDF_DETAILS))
3350 fprintf (dump_file, " controlled uses count of param "
3351 "%i bumped down to %i\n", param_index, c);
3352 if (c == 0
3353 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3355 if (dump_file && (dump_flags & TDF_DETAILS))
3356 fprintf (dump_file, " and even removing its "
3357 "cloning-created reference\n");
3358 to_del->remove_reference ();
3364 /* Turning calls to direct calls will improve overall summary. */
3365 if (found)
3366 ipa_update_overall_fn_summary (node);
3369 class edge_clone_summary;
3370 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL;
3372 /* Edge clone summary. */
3374 struct edge_clone_summary
3376 /* Default constructor. */
3377 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
3379 /* Default destructor. */
3380 ~edge_clone_summary ()
3382 if (prev_clone)
3383 edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
3384 if (next_clone)
3385 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
3388 cgraph_edge *prev_clone;
3389 cgraph_edge *next_clone;
3392 class edge_clone_summary_t:
3393 public call_summary <edge_clone_summary *>
3395 public:
3396 edge_clone_summary_t (symbol_table *symtab):
3397 call_summary <edge_clone_summary *> (symtab)
3399 m_initialize_when_cloning = true;
3402 virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
3403 edge_clone_summary *src_data,
3404 edge_clone_summary *dst_data);
3407 /* Edge duplication hook. */
3409 void
3410 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
3411 edge_clone_summary *src_data,
3412 edge_clone_summary *dst_data)
3414 if (src_data->next_clone)
3415 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
3416 dst_data->prev_clone = src_edge;
3417 dst_data->next_clone = src_data->next_clone;
3418 src_data->next_clone = dst_edge;
3421 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3422 parameter with the given INDEX. */
3424 static tree
3425 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3426 int index)
3428 struct ipa_agg_replacement_value *aggval;
3430 aggval = ipa_get_agg_replacements_for_node (node);
3431 while (aggval)
3433 if (aggval->offset == offset
3434 && aggval->index == index)
3435 return aggval->value;
3436 aggval = aggval->next;
3438 return NULL_TREE;
3441 /* Return true is NODE is DEST or its clone for all contexts. */
3443 static bool
3444 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3446 if (node == dest)
3447 return true;
3449 struct ipa_node_params *info = IPA_NODE_REF (node);
3450 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3453 /* Return true if edge CS does bring about the value described by SRC to
3454 DEST_VAL of node DEST or its clone for all contexts. */
3456 static bool
3457 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3458 cgraph_node *dest, ipcp_value<tree> *dest_val)
3460 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3461 enum availability availability;
3462 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3464 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3465 || availability <= AVAIL_INTERPOSABLE
3466 || caller_info->node_dead)
3467 return false;
3469 if (!src->val)
3470 return true;
3472 if (caller_info->ipcp_orig_node)
3474 tree t;
3475 if (src->offset == -1)
3476 t = caller_info->known_csts[src->index];
3477 else
3478 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3479 return (t != NULL_TREE
3480 && values_equal_for_ipcp_p (src->val->value, t));
3482 else
3484 /* At the moment we do not propagate over arithmetic jump functions in
3485 SCCs, so it is safe to detect self-feeding recursive calls in this
3486 way. */
3487 if (src->val == dest_val)
3488 return true;
3490 struct ipcp_agg_lattice *aglat;
3491 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3492 src->index);
3493 if (src->offset == -1)
3494 return (plats->itself.is_single_const ()
3495 && values_equal_for_ipcp_p (src->val->value,
3496 plats->itself.values->value));
3497 else
3499 if (plats->aggs_bottom || plats->aggs_contain_variable)
3500 return false;
3501 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3502 if (aglat->offset == src->offset)
3503 return (aglat->is_single_const ()
3504 && values_equal_for_ipcp_p (src->val->value,
3505 aglat->values->value));
3507 return false;
3511 /* Return true if edge CS does bring about the value described by SRC to
3512 DST_VAL of node DEST or its clone for all contexts. */
3514 static bool
3515 cgraph_edge_brings_value_p (cgraph_edge *cs,
3516 ipcp_value_source<ipa_polymorphic_call_context> *src,
3517 cgraph_node *dest,
3518 ipcp_value<ipa_polymorphic_call_context> *)
3520 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3521 cgraph_node *real_dest = cs->callee->function_symbol ();
3523 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3524 || caller_info->node_dead)
3525 return false;
3526 if (!src->val)
3527 return true;
3529 if (caller_info->ipcp_orig_node)
3530 return (caller_info->known_contexts.length () > (unsigned) src->index)
3531 && values_equal_for_ipcp_p (src->val->value,
3532 caller_info->known_contexts[src->index]);
3534 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3535 src->index);
3536 return plats->ctxlat.is_single_const ()
3537 && values_equal_for_ipcp_p (src->val->value,
3538 plats->ctxlat.values->value);
3541 /* Get the next clone in the linked list of clones of an edge. */
3543 static inline struct cgraph_edge *
3544 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3546 edge_clone_summary *s = edge_clone_summaries->get (cs);
3547 return s != NULL ? s->next_clone : NULL;
3550 /* Given VAL that is intended for DEST, iterate over all its sources and if any
3551 of them is viable and hot, return true. In that case, for those that still
3552 hold, add their edge frequency and their number into *FREQUENCY and
3553 *CALLER_COUNT respectively. */
3555 template <typename valtype>
3556 static bool
3557 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3558 int *freq_sum,
3559 profile_count *count_sum, int *caller_count)
3561 ipcp_value_source<valtype> *src;
3562 int freq = 0, count = 0;
3563 profile_count cnt = profile_count::zero ();
3564 bool hot = false;
3565 bool non_self_recursive = false;
3567 for (src = val->sources; src; src = src->next)
3569 struct cgraph_edge *cs = src->cs;
3570 while (cs)
3572 if (cgraph_edge_brings_value_p (cs, src, dest, val))
3574 count++;
3575 freq += cs->frequency ();
3576 if (cs->count.ipa ().initialized_p ())
3577 cnt += cs->count.ipa ();
3578 hot |= cs->maybe_hot_p ();
3579 if (cs->caller != dest)
3580 non_self_recursive = true;
3582 cs = get_next_cgraph_edge_clone (cs);
3586 /* If the only edges bringing a value are self-recursive ones, do not bother
3587 evaluating it. */
3588 if (!non_self_recursive)
3589 return false;
3591 *freq_sum = freq;
3592 *count_sum = cnt;
3593 *caller_count = count;
3594 return hot;
3597 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3598 is assumed their number is known and equal to CALLER_COUNT. */
3600 template <typename valtype>
3601 static vec<cgraph_edge *>
3602 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3603 int caller_count)
3605 ipcp_value_source<valtype> *src;
3606 vec<cgraph_edge *> ret;
3608 ret.create (caller_count);
3609 for (src = val->sources; src; src = src->next)
3611 struct cgraph_edge *cs = src->cs;
3612 while (cs)
3614 if (cgraph_edge_brings_value_p (cs, src, dest, val))
3615 ret.quick_push (cs);
3616 cs = get_next_cgraph_edge_clone (cs);
3620 return ret;
3623 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3624 Return it or NULL if for some reason it cannot be created. */
3626 static struct ipa_replace_map *
3627 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3629 struct ipa_replace_map *replace_map;
3632 replace_map = ggc_alloc<ipa_replace_map> ();
3633 if (dump_file)
3635 fprintf (dump_file, " replacing ");
3636 ipa_dump_param (dump_file, info, parm_num);
3638 fprintf (dump_file, " with const ");
3639 print_generic_expr (dump_file, value);
3640 fprintf (dump_file, "\n");
3642 replace_map->old_tree = NULL;
3643 replace_map->parm_num = parm_num;
3644 replace_map->new_tree = value;
3645 replace_map->replace_p = true;
3646 replace_map->ref_p = false;
3648 return replace_map;
3651 /* Dump new profiling counts */
3653 static void
3654 dump_profile_updates (struct cgraph_node *orig_node,
3655 struct cgraph_node *new_node)
3657 struct cgraph_edge *cs;
3659 fprintf (dump_file, " setting count of the specialized node to ");
3660 new_node->count.dump (dump_file);
3661 fprintf (dump_file, "\n");
3662 for (cs = new_node->callees; cs; cs = cs->next_callee)
3664 fprintf (dump_file, " edge to %s has count ",
3665 cs->callee->name ());
3666 cs->count.dump (dump_file);
3667 fprintf (dump_file, "\n");
3670 fprintf (dump_file, " setting count of the original node to ");
3671 orig_node->count.dump (dump_file);
3672 fprintf (dump_file, "\n");
3673 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3675 fprintf (dump_file, " edge to %s is left with ",
3676 cs->callee->name ());
3677 cs->count.dump (dump_file);
3678 fprintf (dump_file, "\n");
3682 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3683 their profile information to reflect this. */
3685 static void
3686 update_profiling_info (struct cgraph_node *orig_node,
3687 struct cgraph_node *new_node)
3689 struct cgraph_edge *cs;
3690 struct caller_statistics stats;
3691 profile_count new_sum, orig_sum;
3692 profile_count remainder, orig_node_count = orig_node->count;
3694 if (!(orig_node_count.ipa () > profile_count::zero ()))
3695 return;
3697 init_caller_stats (&stats);
3698 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3699 false);
3700 orig_sum = stats.count_sum;
3701 init_caller_stats (&stats);
3702 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3703 false);
3704 new_sum = stats.count_sum;
3706 if (orig_node_count < orig_sum + new_sum)
3708 if (dump_file)
3710 fprintf (dump_file, " Problem: node %s has too low count ",
3711 orig_node->dump_name ());
3712 orig_node_count.dump (dump_file);
3713 fprintf (dump_file, "while the sum of incoming count is ");
3714 (orig_sum + new_sum).dump (dump_file);
3715 fprintf (dump_file, "\n");
3718 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
3719 if (dump_file)
3721 fprintf (dump_file, " proceeding by pretending it was ");
3722 orig_node_count.dump (dump_file);
3723 fprintf (dump_file, "\n");
3727 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
3728 - new_sum.ipa ());
3729 new_sum = orig_node_count.combine_with_ipa_count (new_sum);
3730 orig_node->count = remainder;
3732 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_node_count);
3733 for (cs = new_node->callees; cs; cs = cs->next_callee)
3734 cs->count = cs->count.apply_scale (new_sum, orig_node_count);
3736 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
3737 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3738 cs->count = cs->count.apply_scale (remainder, orig_node_count);
3740 if (dump_file)
3741 dump_profile_updates (orig_node, new_node);
3744 /* Update the respective profile of specialized NEW_NODE and the original
3745 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3746 have been redirected to the specialized version. */
3748 static void
3749 update_specialized_profile (struct cgraph_node *new_node,
3750 struct cgraph_node *orig_node,
3751 profile_count redirected_sum)
3753 struct cgraph_edge *cs;
3754 profile_count new_node_count, orig_node_count = orig_node->count;
3756 if (dump_file)
3758 fprintf (dump_file, " the sum of counts of redirected edges is ");
3759 redirected_sum.dump (dump_file);
3760 fprintf (dump_file, "\n");
3762 if (!(orig_node_count > profile_count::zero ()))
3763 return;
3765 gcc_assert (orig_node_count >= redirected_sum);
3767 new_node_count = new_node->count;
3768 new_node->count += redirected_sum;
3769 orig_node->count -= redirected_sum;
3771 for (cs = new_node->callees; cs; cs = cs->next_callee)
3772 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
3774 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3776 profile_count dec = cs->count.apply_scale (redirected_sum,
3777 orig_node_count);
3778 cs->count -= dec;
3781 if (dump_file)
3782 dump_profile_updates (orig_node, new_node);
3785 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3786 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3787 redirect all edges in CALLERS to it. */
3789 static struct cgraph_node *
3790 create_specialized_node (struct cgraph_node *node,
3791 vec<tree> known_csts,
3792 vec<ipa_polymorphic_call_context> known_contexts,
3793 struct ipa_agg_replacement_value *aggvals,
3794 vec<cgraph_edge *> callers)
3796 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3797 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3798 struct ipa_agg_replacement_value *av;
3799 struct cgraph_node *new_node;
3800 int i, count = ipa_get_param_count (info);
3801 bitmap args_to_skip;
3803 gcc_assert (!info->ipcp_orig_node);
3805 if (node->local.can_change_signature)
3807 args_to_skip = BITMAP_GGC_ALLOC ();
3808 for (i = 0; i < count; i++)
3810 tree t = known_csts[i];
3812 if (t || !ipa_is_param_used (info, i))
3813 bitmap_set_bit (args_to_skip, i);
3816 else
3818 args_to_skip = NULL;
3819 if (dump_file && (dump_flags & TDF_DETAILS))
3820 fprintf (dump_file, " cannot change function signature\n");
3823 for (i = 0; i < count; i++)
3825 tree t = known_csts[i];
3826 if (t)
3828 struct ipa_replace_map *replace_map;
3830 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3831 replace_map = get_replacement_map (info, t, i);
3832 if (replace_map)
3833 vec_safe_push (replace_trees, replace_map);
3836 auto_vec<cgraph_edge *, 2> self_recursive_calls;
3837 for (i = callers.length () - 1; i >= 0; i--)
3839 cgraph_edge *cs = callers[i];
3840 if (cs->caller == node)
3842 self_recursive_calls.safe_push (cs);
3843 callers.unordered_remove (i);
3847 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
3848 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
3849 node->decl)));
3850 new_node = node->create_virtual_clone (callers, replace_trees,
3851 args_to_skip, "constprop",
3852 suffix_counter);
3853 suffix_counter++;
3855 bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
3856 for (unsigned j = 0; j < self_recursive_calls.length (); j++)
3858 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
3859 /* Cloned edges can disappear during cloning as speculation can be
3860 resolved, check that we have one and that it comes from the last
3861 cloning. */
3862 if (cs && cs->caller == new_node)
3863 cs->redirect_callee_duplicating_thunks (new_node);
3864 /* Any future code that would make more than one clone of an outgoing
3865 edge would confuse this mechanism, so let's check that does not
3866 happen. */
3867 gcc_checking_assert (!cs
3868 || !get_next_cgraph_edge_clone (cs)
3869 || get_next_cgraph_edge_clone (cs)->caller != new_node);
3871 if (have_self_recursive_calls)
3872 new_node->expand_all_artificial_thunks ();
3874 ipa_set_node_agg_value_chain (new_node, aggvals);
3875 for (av = aggvals; av; av = av->next)
3876 new_node->maybe_create_reference (av->value, NULL);
3878 if (dump_file && (dump_flags & TDF_DETAILS))
3880 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
3881 if (known_contexts.exists ())
3883 for (i = 0; i < count; i++)
3884 if (!known_contexts[i].useless_p ())
3886 fprintf (dump_file, " known ctx %i is ", i);
3887 known_contexts[i].dump (dump_file);
3890 if (aggvals)
3891 ipa_dump_agg_replacement_values (dump_file, aggvals);
3893 ipa_check_create_node_params ();
3894 update_profiling_info (node, new_node);
3895 new_info = IPA_NODE_REF (new_node);
3896 new_info->ipcp_orig_node = node;
3897 new_info->known_csts = known_csts;
3898 new_info->known_contexts = known_contexts;
3900 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3902 callers.release ();
3903 return new_node;
3906 /* Return true, if JFUNC, which describes a i-th parameter of call CS, is a
3907 simple no-operation pass-through function to itself. */
3909 static bool
3910 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i)
3912 enum availability availability;
3913 if (cs->caller == cs->callee->function_symbol (&availability)
3914 && availability > AVAIL_INTERPOSABLE
3915 && jfunc->type == IPA_JF_PASS_THROUGH
3916 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR
3917 && ipa_get_jf_pass_through_formal_id (jfunc) == i)
3918 return true;
3919 return false;
3922 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3923 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3925 static void
3926 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3927 vec<tree> known_csts,
3928 vec<cgraph_edge *> callers)
3930 struct ipa_node_params *info = IPA_NODE_REF (node);
3931 int i, count = ipa_get_param_count (info);
3933 for (i = 0; i < count; i++)
3935 struct cgraph_edge *cs;
3936 tree newval = NULL_TREE;
3937 int j;
3938 bool first = true;
3939 tree type = ipa_get_type (info, i);
3941 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3942 continue;
3944 FOR_EACH_VEC_ELT (callers, j, cs)
3946 struct ipa_jump_func *jump_func;
3947 tree t;
3949 if (IPA_NODE_REF (cs->caller)->node_dead)
3950 continue;
3952 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3953 || (i == 0
3954 && call_passes_through_thunk_p (cs)))
3956 newval = NULL_TREE;
3957 break;
3959 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3960 if (self_recursive_pass_through_p (cs, jump_func, i))
3961 continue;
3963 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func, type);
3964 if (!t
3965 || (newval
3966 && !values_equal_for_ipcp_p (t, newval))
3967 || (!first && !newval))
3969 newval = NULL_TREE;
3970 break;
3972 else
3973 newval = t;
3974 first = false;
3977 if (newval)
3979 if (dump_file && (dump_flags & TDF_DETAILS))
3981 fprintf (dump_file, " adding an extra known scalar value ");
3982 print_ipcp_constant_value (dump_file, newval);
3983 fprintf (dump_file, " for ");
3984 ipa_dump_param (dump_file, info, i);
3985 fprintf (dump_file, "\n");
3988 known_csts[i] = newval;
3993 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3994 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3995 CALLERS. */
3997 static void
3998 find_more_contexts_for_caller_subset (cgraph_node *node,
3999 vec<ipa_polymorphic_call_context>
4000 *known_contexts,
4001 vec<cgraph_edge *> callers)
4003 ipa_node_params *info = IPA_NODE_REF (node);
4004 int i, count = ipa_get_param_count (info);
4006 for (i = 0; i < count; i++)
4008 cgraph_edge *cs;
4010 if (ipa_get_poly_ctx_lat (info, i)->bottom
4011 || (known_contexts->exists ()
4012 && !(*known_contexts)[i].useless_p ()))
4013 continue;
4015 ipa_polymorphic_call_context newval;
4016 bool first = true;
4017 int j;
4019 FOR_EACH_VEC_ELT (callers, j, cs)
4021 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
4022 return;
4023 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
4025 ipa_polymorphic_call_context ctx;
4026 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
4027 jfunc);
4028 if (first)
4030 newval = ctx;
4031 first = false;
4033 else
4034 newval.meet_with (ctx);
4035 if (newval.useless_p ())
4036 break;
4039 if (!newval.useless_p ())
4041 if (dump_file && (dump_flags & TDF_DETAILS))
4043 fprintf (dump_file, " adding an extra known polymorphic "
4044 "context ");
4045 print_ipcp_constant_value (dump_file, newval);
4046 fprintf (dump_file, " for ");
4047 ipa_dump_param (dump_file, info, i);
4048 fprintf (dump_file, "\n");
4051 if (!known_contexts->exists ())
4052 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
4053 (*known_contexts)[i] = newval;
4059 /* Go through PLATS and create a vector of values consisting of values and
4060 offsets (minus OFFSET) of lattices that contain only a single value. */
4062 static vec<ipa_agg_jf_item>
4063 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
4065 vec<ipa_agg_jf_item> res = vNULL;
4067 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4068 return vNULL;
4070 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
4071 if (aglat->is_single_const ())
4073 struct ipa_agg_jf_item ti;
4074 ti.offset = aglat->offset - offset;
4075 ti.value = aglat->values->value;
4076 res.safe_push (ti);
4078 return res;
4081 /* Intersect all values in INTER with single value lattices in PLATS (while
4082 subtracting OFFSET). */
4084 static void
4085 intersect_with_plats (struct ipcp_param_lattices *plats,
4086 vec<ipa_agg_jf_item> *inter,
4087 HOST_WIDE_INT offset)
4089 struct ipcp_agg_lattice *aglat;
4090 struct ipa_agg_jf_item *item;
4091 int k;
4093 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4095 inter->release ();
4096 return;
4099 aglat = plats->aggs;
4100 FOR_EACH_VEC_ELT (*inter, k, item)
4102 bool found = false;
4103 if (!item->value)
4104 continue;
4105 while (aglat)
4107 if (aglat->offset - offset > item->offset)
4108 break;
4109 if (aglat->offset - offset == item->offset)
4111 gcc_checking_assert (item->value);
4112 if (aglat->is_single_const ()
4113 && values_equal_for_ipcp_p (item->value,
4114 aglat->values->value))
4115 found = true;
4116 break;
4118 aglat = aglat->next;
4120 if (!found)
4121 item->value = NULL_TREE;
4125 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4126 vector result while subtracting OFFSET from the individual value offsets. */
4128 static vec<ipa_agg_jf_item>
4129 agg_replacements_to_vector (struct cgraph_node *node, int index,
4130 HOST_WIDE_INT offset)
4132 struct ipa_agg_replacement_value *av;
4133 vec<ipa_agg_jf_item> res = vNULL;
4135 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4136 if (av->index == index
4137 && (av->offset - offset) >= 0)
4139 struct ipa_agg_jf_item item;
4140 gcc_checking_assert (av->value);
4141 item.offset = av->offset - offset;
4142 item.value = av->value;
4143 res.safe_push (item);
4146 return res;
4149 /* Intersect all values in INTER with those that we have already scheduled to
4150 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4151 (while subtracting OFFSET). */
4153 static void
4154 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4155 vec<ipa_agg_jf_item> *inter,
4156 HOST_WIDE_INT offset)
4158 struct ipa_agg_replacement_value *srcvals;
4159 struct ipa_agg_jf_item *item;
4160 int i;
4162 srcvals = ipa_get_agg_replacements_for_node (node);
4163 if (!srcvals)
4165 inter->release ();
4166 return;
4169 FOR_EACH_VEC_ELT (*inter, i, item)
4171 struct ipa_agg_replacement_value *av;
4172 bool found = false;
4173 if (!item->value)
4174 continue;
4175 for (av = srcvals; av; av = av->next)
4177 gcc_checking_assert (av->value);
4178 if (av->index == index
4179 && av->offset - offset == item->offset)
4181 if (values_equal_for_ipcp_p (item->value, av->value))
4182 found = true;
4183 break;
4186 if (!found)
4187 item->value = NULL_TREE;
4191 /* Intersect values in INTER with aggregate values that come along edge CS to
4192 parameter number INDEX and return it. If INTER does not actually exist yet,
4193 copy all incoming values to it. If we determine we ended up with no values
4194 whatsoever, return a released vector. */
4196 static vec<ipa_agg_jf_item>
4197 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4198 vec<ipa_agg_jf_item> inter)
4200 struct ipa_jump_func *jfunc;
4201 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4202 if (jfunc->type == IPA_JF_PASS_THROUGH
4203 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4205 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4206 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4208 if (caller_info->ipcp_orig_node)
4210 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4211 struct ipcp_param_lattices *orig_plats;
4212 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4213 src_idx);
4214 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4216 if (!inter.exists ())
4217 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4218 else
4219 intersect_with_agg_replacements (cs->caller, src_idx,
4220 &inter, 0);
4222 else
4224 inter.release ();
4225 return vNULL;
4228 else
4230 struct ipcp_param_lattices *src_plats;
4231 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4232 if (agg_pass_through_permissible_p (src_plats, jfunc))
4234 /* Currently we do not produce clobber aggregate jump
4235 functions, adjust when we do. */
4236 gcc_checking_assert (!jfunc->agg.items);
4237 if (!inter.exists ())
4238 inter = copy_plats_to_inter (src_plats, 0);
4239 else
4240 intersect_with_plats (src_plats, &inter, 0);
4242 else
4244 inter.release ();
4245 return vNULL;
4249 else if (jfunc->type == IPA_JF_ANCESTOR
4250 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4252 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4253 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4254 struct ipcp_param_lattices *src_plats;
4255 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4257 if (caller_info->ipcp_orig_node)
4259 if (!inter.exists ())
4260 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4261 else
4262 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4263 delta);
4265 else
4267 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4268 /* Currently we do not produce clobber aggregate jump
4269 functions, adjust when we do. */
4270 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4271 if (!inter.exists ())
4272 inter = copy_plats_to_inter (src_plats, delta);
4273 else
4274 intersect_with_plats (src_plats, &inter, delta);
4277 else if (jfunc->agg.items)
4279 struct ipa_agg_jf_item *item;
4280 int k;
4282 if (!inter.exists ())
4283 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4284 inter.safe_push ((*jfunc->agg.items)[i]);
4285 else
4286 FOR_EACH_VEC_ELT (inter, k, item)
4288 int l = 0;
4289 bool found = false;
4291 if (!item->value)
4292 continue;
4294 while ((unsigned) l < jfunc->agg.items->length ())
4296 struct ipa_agg_jf_item *ti;
4297 ti = &(*jfunc->agg.items)[l];
4298 if (ti->offset > item->offset)
4299 break;
4300 if (ti->offset == item->offset)
4302 gcc_checking_assert (ti->value);
4303 if (values_equal_for_ipcp_p (item->value,
4304 ti->value))
4305 found = true;
4306 break;
4308 l++;
4310 if (!found)
4311 item->value = NULL;
4314 else
4316 inter.release ();
4317 return vec<ipa_agg_jf_item>();
4319 return inter;
4322 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4323 from all of them. */
4325 static struct ipa_agg_replacement_value *
4326 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4327 vec<cgraph_edge *> callers)
4329 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4330 struct ipa_agg_replacement_value *res;
4331 struct ipa_agg_replacement_value **tail = &res;
4332 struct cgraph_edge *cs;
4333 int i, j, count = ipa_get_param_count (dest_info);
4335 FOR_EACH_VEC_ELT (callers, j, cs)
4337 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4338 if (c < count)
4339 count = c;
4342 for (i = 0; i < count; i++)
4344 struct cgraph_edge *cs;
4345 vec<ipa_agg_jf_item> inter = vNULL;
4346 struct ipa_agg_jf_item *item;
4347 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4348 int j;
4350 /* Among other things, the following check should deal with all by_ref
4351 mismatches. */
4352 if (plats->aggs_bottom)
4353 continue;
4355 FOR_EACH_VEC_ELT (callers, j, cs)
4357 struct ipa_jump_func *jfunc
4358 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
4359 if (self_recursive_pass_through_p (cs, jfunc, i)
4360 && (!plats->aggs_by_ref
4361 || ipa_get_jf_pass_through_agg_preserved (jfunc)))
4362 continue;
4363 inter = intersect_aggregates_with_edge (cs, i, inter);
4365 if (!inter.exists ())
4366 goto next_param;
4369 FOR_EACH_VEC_ELT (inter, j, item)
4371 struct ipa_agg_replacement_value *v;
4373 if (!item->value)
4374 continue;
4376 v = ggc_alloc<ipa_agg_replacement_value> ();
4377 v->index = i;
4378 v->offset = item->offset;
4379 v->value = item->value;
4380 v->by_ref = plats->aggs_by_ref;
4381 *tail = v;
4382 tail = &v->next;
4385 next_param:
4386 if (inter.exists ())
4387 inter.release ();
4389 *tail = NULL;
4390 return res;
4393 /* Determine whether CS also brings all scalar values that the NODE is
4394 specialized for. */
4396 static bool
4397 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4398 struct cgraph_node *node)
4400 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4401 int count = ipa_get_param_count (dest_info);
4402 struct ipa_node_params *caller_info;
4403 struct ipa_edge_args *args;
4404 int i;
4406 caller_info = IPA_NODE_REF (cs->caller);
4407 args = IPA_EDGE_REF (cs);
4408 for (i = 0; i < count; i++)
4410 struct ipa_jump_func *jump_func;
4411 tree val, t;
4413 val = dest_info->known_csts[i];
4414 if (!val)
4415 continue;
4417 if (i >= ipa_get_cs_argument_count (args))
4418 return false;
4419 jump_func = ipa_get_ith_jump_func (args, i);
4420 t = ipa_value_from_jfunc (caller_info, jump_func,
4421 ipa_get_type (dest_info, i));
4422 if (!t || !values_equal_for_ipcp_p (val, t))
4423 return false;
4425 return true;
4428 /* Determine whether CS also brings all aggregate values that NODE is
4429 specialized for. */
4430 static bool
4431 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4432 struct cgraph_node *node)
4434 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4435 struct ipa_node_params *orig_node_info;
4436 struct ipa_agg_replacement_value *aggval;
4437 int i, ec, count;
4439 aggval = ipa_get_agg_replacements_for_node (node);
4440 if (!aggval)
4441 return true;
4443 count = ipa_get_param_count (IPA_NODE_REF (node));
4444 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4445 if (ec < count)
4446 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4447 if (aggval->index >= ec)
4448 return false;
4450 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4451 if (orig_caller_info->ipcp_orig_node)
4452 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4454 for (i = 0; i < count; i++)
4456 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4457 struct ipcp_param_lattices *plats;
4458 bool interesting = false;
4459 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4460 if (aggval->index == i)
4462 interesting = true;
4463 break;
4465 if (!interesting)
4466 continue;
4468 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4469 if (plats->aggs_bottom)
4470 return false;
4472 values = intersect_aggregates_with_edge (cs, i, values);
4473 if (!values.exists ())
4474 return false;
4476 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4477 if (aggval->index == i)
4479 struct ipa_agg_jf_item *item;
4480 int j;
4481 bool found = false;
4482 FOR_EACH_VEC_ELT (values, j, item)
4483 if (item->value
4484 && item->offset == av->offset
4485 && values_equal_for_ipcp_p (item->value, av->value))
4487 found = true;
4488 break;
4490 if (!found)
4492 values.release ();
4493 return false;
4497 return true;
4500 /* Given an original NODE and a VAL for which we have already created a
4501 specialized clone, look whether there are incoming edges that still lead
4502 into the old node but now also bring the requested value and also conform to
4503 all other criteria such that they can be redirected the special node.
4504 This function can therefore redirect the final edge in a SCC. */
4506 template <typename valtype>
4507 static void
4508 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4510 ipcp_value_source<valtype> *src;
4511 profile_count redirected_sum = profile_count::zero ();
4513 for (src = val->sources; src; src = src->next)
4515 struct cgraph_edge *cs = src->cs;
4516 while (cs)
4518 if (cgraph_edge_brings_value_p (cs, src, node, val)
4519 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4520 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4522 if (dump_file)
4523 fprintf (dump_file, " - adding an extra caller %s of %s\n",
4524 cs->caller->dump_name (),
4525 val->spec_node->dump_name ());
4527 cs->redirect_callee_duplicating_thunks (val->spec_node);
4528 val->spec_node->expand_all_artificial_thunks ();
4529 if (cs->count.ipa ().initialized_p ())
4530 redirected_sum = redirected_sum + cs->count.ipa ();
4532 cs = get_next_cgraph_edge_clone (cs);
4536 if (redirected_sum.nonzero_p ())
4537 update_specialized_profile (val->spec_node, node, redirected_sum);
4540 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4542 static bool
4543 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4545 ipa_polymorphic_call_context *ctx;
4546 int i;
4548 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4549 if (!ctx->useless_p ())
4550 return true;
4551 return false;
4554 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4556 static vec<ipa_polymorphic_call_context>
4557 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4559 if (known_contexts_useful_p (known_contexts))
4560 return known_contexts.copy ();
4561 else
4562 return vNULL;
4565 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4566 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4568 static void
4569 modify_known_vectors_with_val (vec<tree> *known_csts,
4570 vec<ipa_polymorphic_call_context> *known_contexts,
4571 ipcp_value<tree> *val,
4572 int index)
4574 *known_csts = known_csts->copy ();
4575 *known_contexts = copy_useful_known_contexts (*known_contexts);
4576 (*known_csts)[index] = val->value;
4579 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4580 copy according to VAL and INDEX. */
4582 static void
4583 modify_known_vectors_with_val (vec<tree> *known_csts,
4584 vec<ipa_polymorphic_call_context> *known_contexts,
4585 ipcp_value<ipa_polymorphic_call_context> *val,
4586 int index)
4588 *known_csts = known_csts->copy ();
4589 *known_contexts = known_contexts->copy ();
4590 (*known_contexts)[index] = val->value;
4593 /* Return true if OFFSET indicates this was not an aggregate value or there is
4594 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4595 AGGVALS list. */
4597 DEBUG_FUNCTION bool
4598 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4599 int index, HOST_WIDE_INT offset, tree value)
4601 if (offset == -1)
4602 return true;
4604 while (aggvals)
4606 if (aggvals->index == index
4607 && aggvals->offset == offset
4608 && values_equal_for_ipcp_p (aggvals->value, value))
4609 return true;
4610 aggvals = aggvals->next;
4612 return false;
4615 /* Return true if offset is minus one because source of a polymorphic context
4616 cannot be an aggregate value. */
4618 DEBUG_FUNCTION bool
4619 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4620 int , HOST_WIDE_INT offset,
4621 ipa_polymorphic_call_context)
4623 return offset == -1;
4626 /* Decide whether to create a special version of NODE for value VAL of parameter
4627 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4628 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4629 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4631 template <typename valtype>
4632 static bool
4633 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4634 ipcp_value<valtype> *val, vec<tree> known_csts,
4635 vec<ipa_polymorphic_call_context> known_contexts)
4637 struct ipa_agg_replacement_value *aggvals;
4638 int freq_sum, caller_count;
4639 profile_count count_sum;
4640 vec<cgraph_edge *> callers;
4642 if (val->spec_node)
4644 perhaps_add_new_callers (node, val);
4645 return false;
4647 else if (val->local_size_cost + overall_size > max_new_size)
4649 if (dump_file && (dump_flags & TDF_DETAILS))
4650 fprintf (dump_file, " Ignoring candidate value because "
4651 "max_new_size would be reached with %li.\n",
4652 val->local_size_cost + overall_size);
4653 return false;
4655 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4656 &caller_count))
4657 return false;
4659 if (dump_file && (dump_flags & TDF_DETAILS))
4661 fprintf (dump_file, " - considering value ");
4662 print_ipcp_constant_value (dump_file, val->value);
4663 fprintf (dump_file, " for ");
4664 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4665 if (offset != -1)
4666 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4667 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4670 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4671 freq_sum, count_sum,
4672 val->local_size_cost)
4673 && !good_cloning_opportunity_p (node,
4674 val->local_time_benefit
4675 + val->prop_time_benefit,
4676 freq_sum, count_sum,
4677 val->local_size_cost
4678 + val->prop_size_cost))
4679 return false;
4681 if (dump_file)
4682 fprintf (dump_file, " Creating a specialized node of %s.\n",
4683 node->dump_name ());
4685 callers = gather_edges_for_value (val, node, caller_count);
4686 if (offset == -1)
4687 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4688 else
4690 known_csts = known_csts.copy ();
4691 known_contexts = copy_useful_known_contexts (known_contexts);
4693 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4694 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4695 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4696 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4697 offset, val->value));
4698 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4699 aggvals, callers);
4700 overall_size += val->local_size_cost;
4702 /* TODO: If for some lattice there is only one other known value
4703 left, make a special node for it too. */
4705 return true;
4708 /* Decide whether and what specialized clones of NODE should be created. */
4710 static bool
4711 decide_whether_version_node (struct cgraph_node *node)
4713 struct ipa_node_params *info = IPA_NODE_REF (node);
4714 int i, count = ipa_get_param_count (info);
4715 vec<tree> known_csts;
4716 vec<ipa_polymorphic_call_context> known_contexts;
4717 vec<ipa_agg_jump_function> known_aggs = vNULL;
4718 bool ret = false;
4720 if (count == 0)
4721 return false;
4723 if (dump_file && (dump_flags & TDF_DETAILS))
4724 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
4725 node->dump_name ());
4727 gather_context_independent_values (info, &known_csts, &known_contexts,
4728 info->do_clone_for_all_contexts ? &known_aggs
4729 : NULL, NULL);
4731 for (i = 0; i < count;i++)
4733 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4734 ipcp_lattice<tree> *lat = &plats->itself;
4735 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4737 if (!lat->bottom
4738 && !known_csts[i])
4740 ipcp_value<tree> *val;
4741 for (val = lat->values; val; val = val->next)
4742 ret |= decide_about_value (node, i, -1, val, known_csts,
4743 known_contexts);
4746 if (!plats->aggs_bottom)
4748 struct ipcp_agg_lattice *aglat;
4749 ipcp_value<tree> *val;
4750 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4751 if (!aglat->bottom && aglat->values
4752 /* If the following is false, the one value is in
4753 known_aggs. */
4754 && (plats->aggs_contain_variable
4755 || !aglat->is_single_const ()))
4756 for (val = aglat->values; val; val = val->next)
4757 ret |= decide_about_value (node, i, aglat->offset, val,
4758 known_csts, known_contexts);
4761 if (!ctxlat->bottom
4762 && known_contexts[i].useless_p ())
4764 ipcp_value<ipa_polymorphic_call_context> *val;
4765 for (val = ctxlat->values; val; val = val->next)
4766 ret |= decide_about_value (node, i, -1, val, known_csts,
4767 known_contexts);
4770 info = IPA_NODE_REF (node);
4773 if (info->do_clone_for_all_contexts)
4775 struct cgraph_node *clone;
4776 vec<cgraph_edge *> callers;
4778 if (dump_file)
4779 fprintf (dump_file, " - Creating a specialized node of %s "
4780 "for all known contexts.\n", node->dump_name ());
4782 callers = node->collect_callers ();
4783 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4784 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4785 ipa_agg_replacement_value *aggvals
4786 = find_aggregate_values_for_callers_subset (node, callers);
4788 if (!known_contexts_useful_p (known_contexts))
4790 known_contexts.release ();
4791 known_contexts = vNULL;
4793 clone = create_specialized_node (node, known_csts, known_contexts,
4794 aggvals, callers);
4795 info = IPA_NODE_REF (node);
4796 info->do_clone_for_all_contexts = false;
4797 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4798 for (i = 0; i < count; i++)
4799 vec_free (known_aggs[i].items);
4800 known_aggs.release ();
4801 ret = true;
4803 else
4805 known_csts.release ();
4806 known_contexts.release ();
4809 return ret;
4812 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4814 static void
4815 spread_undeadness (struct cgraph_node *node)
4817 struct cgraph_edge *cs;
4819 for (cs = node->callees; cs; cs = cs->next_callee)
4820 if (ipa_edge_within_scc (cs))
4822 struct cgraph_node *callee;
4823 struct ipa_node_params *info;
4825 callee = cs->callee->function_symbol (NULL);
4826 info = IPA_NODE_REF (callee);
4828 if (info->node_dead)
4830 info->node_dead = 0;
4831 spread_undeadness (callee);
4836 /* Return true if NODE has a caller from outside of its SCC that is not
4837 dead. Worker callback for cgraph_for_node_and_aliases. */
4839 static bool
4840 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4841 void *data ATTRIBUTE_UNUSED)
4843 struct cgraph_edge *cs;
4845 for (cs = node->callers; cs; cs = cs->next_caller)
4846 if (cs->caller->thunk.thunk_p
4847 && cs->caller->call_for_symbol_thunks_and_aliases
4848 (has_undead_caller_from_outside_scc_p, NULL, true))
4849 return true;
4850 else if (!ipa_edge_within_scc (cs)
4851 && !IPA_NODE_REF (cs->caller)->node_dead)
4852 return true;
4853 return false;
4857 /* Identify nodes within the same SCC as NODE which are no longer needed
4858 because of new clones and will be removed as unreachable. */
4860 static void
4861 identify_dead_nodes (struct cgraph_node *node)
4863 struct cgraph_node *v;
4864 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4865 if (v->local.local
4866 && !v->call_for_symbol_thunks_and_aliases
4867 (has_undead_caller_from_outside_scc_p, NULL, true))
4868 IPA_NODE_REF (v)->node_dead = 1;
4870 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4871 if (!IPA_NODE_REF (v)->node_dead)
4872 spread_undeadness (v);
4874 if (dump_file && (dump_flags & TDF_DETAILS))
4876 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4877 if (IPA_NODE_REF (v)->node_dead)
4878 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
4882 /* The decision stage. Iterate over the topological order of call graph nodes
4883 TOPO and make specialized clones if deemed beneficial. */
4885 static void
4886 ipcp_decision_stage (struct ipa_topo_info *topo)
4888 int i;
4890 if (dump_file)
4891 fprintf (dump_file, "\nIPA decision stage:\n\n");
4893 for (i = topo->nnodes - 1; i >= 0; i--)
4895 struct cgraph_node *node = topo->order[i];
4896 bool change = false, iterate = true;
4898 while (iterate)
4900 struct cgraph_node *v;
4901 iterate = false;
4902 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4903 if (v->has_gimple_body_p ()
4904 && ipcp_versionable_function_p (v))
4905 iterate |= decide_whether_version_node (v);
4907 change |= iterate;
4909 if (change)
4910 identify_dead_nodes (node);
4914 /* Look up all the bits information that we have discovered and copy it over
4915 to the transformation summary. */
4917 static void
4918 ipcp_store_bits_results (void)
4920 cgraph_node *node;
4922 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4924 ipa_node_params *info = IPA_NODE_REF (node);
4925 bool dumped_sth = false;
4926 bool found_useful_result = false;
4928 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4930 if (dump_file)
4931 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4932 "; -fipa-bit-cp: disabled.\n",
4933 node->name ());
4934 continue;
4937 if (info->ipcp_orig_node)
4938 info = IPA_NODE_REF (info->ipcp_orig_node);
4940 unsigned count = ipa_get_param_count (info);
4941 for (unsigned i = 0; i < count; i++)
4943 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4944 if (plats->bits_lattice.constant_p ())
4946 found_useful_result = true;
4947 break;
4951 if (!found_useful_result)
4952 continue;
4954 ipcp_transformation_initialize ();
4955 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
4956 vec_safe_reserve_exact (ts->bits, count);
4958 for (unsigned i = 0; i < count; i++)
4960 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4961 ipa_bits *jfbits;
4963 if (plats->bits_lattice.constant_p ())
4964 jfbits
4965 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
4966 plats->bits_lattice.get_mask ());
4967 else
4968 jfbits = NULL;
4970 ts->bits->quick_push (jfbits);
4971 if (!dump_file || !jfbits)
4972 continue;
4973 if (!dumped_sth)
4975 fprintf (dump_file, "Propagated bits info for function %s:\n",
4976 node->dump_name ());
4977 dumped_sth = true;
4979 fprintf (dump_file, " param %i: value = ", i);
4980 print_hex (jfbits->value, dump_file);
4981 fprintf (dump_file, ", mask = ");
4982 print_hex (jfbits->mask, dump_file);
4983 fprintf (dump_file, "\n");
4988 /* Look up all VR information that we have discovered and copy it over
4989 to the transformation summary. */
4991 static void
4992 ipcp_store_vr_results (void)
4994 cgraph_node *node;
4996 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4998 ipa_node_params *info = IPA_NODE_REF (node);
4999 bool found_useful_result = false;
5001 if (!opt_for_fn (node->decl, flag_ipa_vrp))
5003 if (dump_file)
5004 fprintf (dump_file, "Not considering %s for VR discovery "
5005 "and propagate; -fipa-ipa-vrp: disabled.\n",
5006 node->name ());
5007 continue;
5010 if (info->ipcp_orig_node)
5011 info = IPA_NODE_REF (info->ipcp_orig_node);
5013 unsigned count = ipa_get_param_count (info);
5014 for (unsigned i = 0; i < count; i++)
5016 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5017 if (!plats->m_value_range.bottom_p ()
5018 && !plats->m_value_range.top_p ())
5020 found_useful_result = true;
5021 break;
5024 if (!found_useful_result)
5025 continue;
5027 ipcp_transformation_initialize ();
5028 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5029 vec_safe_reserve_exact (ts->m_vr, count);
5031 for (unsigned i = 0; i < count; i++)
5033 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5034 ipa_vr vr;
5036 if (!plats->m_value_range.bottom_p ()
5037 && !plats->m_value_range.top_p ())
5039 vr.known = true;
5040 vr.type = plats->m_value_range.m_vr.kind ();
5041 vr.min = wi::to_wide (plats->m_value_range.m_vr.min ());
5042 vr.max = wi::to_wide (plats->m_value_range.m_vr.max ());
5044 else
5046 vr.known = false;
5047 vr.type = VR_VARYING;
5048 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
5050 ts->m_vr->quick_push (vr);
5055 /* The IPCP driver. */
5057 static unsigned int
5058 ipcp_driver (void)
5060 struct ipa_topo_info topo;
5062 if (edge_clone_summaries == NULL)
5063 edge_clone_summaries = new edge_clone_summary_t (symtab);
5065 ipa_check_create_node_params ();
5066 ipa_check_create_edge_args ();
5067 clone_num_suffixes = new hash_map<const char *, unsigned>;
5069 if (dump_file)
5071 fprintf (dump_file, "\nIPA structures before propagation:\n");
5072 if (dump_flags & TDF_DETAILS)
5073 ipa_print_all_params (dump_file);
5074 ipa_print_all_jump_functions (dump_file);
5077 /* Topological sort. */
5078 build_toporder_info (&topo);
5079 /* Do the interprocedural propagation. */
5080 ipcp_propagate_stage (&topo);
5081 /* Decide what constant propagation and cloning should be performed. */
5082 ipcp_decision_stage (&topo);
5083 /* Store results of bits propagation. */
5084 ipcp_store_bits_results ();
5085 /* Store results of value range propagation. */
5086 ipcp_store_vr_results ();
5088 /* Free all IPCP structures. */
5089 delete clone_num_suffixes;
5090 free_toporder_info (&topo);
5091 delete edge_clone_summaries;
5092 edge_clone_summaries = NULL;
5093 ipa_free_all_structures_after_ipa_cp ();
5094 if (dump_file)
5095 fprintf (dump_file, "\nIPA constant propagation end\n");
5096 return 0;
5099 /* Initialization and computation of IPCP data structures. This is the initial
5100 intraprocedural analysis of functions, which gathers information to be
5101 propagated later on. */
5103 static void
5104 ipcp_generate_summary (void)
5106 struct cgraph_node *node;
5108 if (dump_file)
5109 fprintf (dump_file, "\nIPA constant propagation start:\n");
5110 ipa_register_cgraph_hooks ();
5112 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5113 ipa_analyze_node (node);
5116 /* Write ipcp summary for nodes in SET. */
5118 static void
5119 ipcp_write_summary (void)
5121 ipa_prop_write_jump_functions ();
5124 /* Read ipcp summary. */
5126 static void
5127 ipcp_read_summary (void)
5129 ipa_prop_read_jump_functions ();
5132 namespace {
5134 const pass_data pass_data_ipa_cp =
5136 IPA_PASS, /* type */
5137 "cp", /* name */
5138 OPTGROUP_NONE, /* optinfo_flags */
5139 TV_IPA_CONSTANT_PROP, /* tv_id */
5140 0, /* properties_required */
5141 0, /* properties_provided */
5142 0, /* properties_destroyed */
5143 0, /* todo_flags_start */
5144 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5147 class pass_ipa_cp : public ipa_opt_pass_d
5149 public:
5150 pass_ipa_cp (gcc::context *ctxt)
5151 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5152 ipcp_generate_summary, /* generate_summary */
5153 ipcp_write_summary, /* write_summary */
5154 ipcp_read_summary, /* read_summary */
5155 ipcp_write_transformation_summaries, /*
5156 write_optimization_summary */
5157 ipcp_read_transformation_summaries, /*
5158 read_optimization_summary */
5159 NULL, /* stmt_fixup */
5160 0, /* function_transform_todo_flags_start */
5161 ipcp_transform_function, /* function_transform */
5162 NULL) /* variable_transform */
5165 /* opt_pass methods: */
5166 virtual bool gate (function *)
5168 /* FIXME: We should remove the optimize check after we ensure we never run
5169 IPA passes when not optimizing. */
5170 return (flag_ipa_cp && optimize) || in_lto_p;
5173 virtual unsigned int execute (function *) { return ipcp_driver (); }
5175 }; // class pass_ipa_cp
5177 } // anon namespace
5179 ipa_opt_pass_d *
5180 make_pass_ipa_cp (gcc::context *ctxt)
5182 return new pass_ipa_cp (ctxt);
5185 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5186 within the same process. For use by toplev::finalize. */
5188 void
5189 ipa_cp_c_finalize (void)
5191 max_count = profile_count::uninitialized ();
5192 overall_size = 0;
5193 max_new_size = 0;