match_asm_constraints: Use copy_rtx where needed (PR88001)
[official-gcc.git] / gcc / ipa-cp.c
blob5758915361487049ba10f1a54b66da9bf8aa9fb8
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2018 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "backend.h"
107 #include "tree.h"
108 #include "gimple-expr.h"
109 #include "predict.h"
110 #include "alloc-pool.h"
111 #include "tree-pass.h"
112 #include "cgraph.h"
113 #include "diagnostic.h"
114 #include "fold-const.h"
115 #include "gimple-fold.h"
116 #include "symbol-summary.h"
117 #include "tree-vrp.h"
118 #include "ipa-prop.h"
119 #include "tree-pretty-print.h"
120 #include "tree-inline.h"
121 #include "params.h"
122 #include "ipa-fnsummary.h"
123 #include "ipa-utils.h"
124 #include "tree-ssa-ccp.h"
125 #include "stringpool.h"
126 #include "attribs.h"
128 template <typename valtype> class ipcp_value;
130 /* Describes a particular source for an IPA-CP value. */
132 template <typename valtype>
133 class ipcp_value_source
135 public:
136 /* Aggregate offset of the source, negative if the source is scalar value of
137 the argument itself. */
138 HOST_WIDE_INT offset;
139 /* The incoming edge that brought the value. */
140 cgraph_edge *cs;
141 /* If the jump function that resulted into his value was a pass-through or an
142 ancestor, this is the ipcp_value of the caller from which the described
143 value has been derived. Otherwise it is NULL. */
144 ipcp_value<valtype> *val;
145 /* Next pointer in a linked list of sources of a value. */
146 ipcp_value_source *next;
147 /* If the jump function that resulted into his value was a pass-through or an
148 ancestor, this is the index of the parameter of the caller the jump
149 function references. */
150 int index;
153 /* Common ancestor for all ipcp_value instantiations. */
155 class ipcp_value_base
157 public:
158 /* Time benefit and size cost that specializing the function for this value
159 would bring about in this function alone. */
160 int local_time_benefit, local_size_cost;
161 /* Time benefit and size cost that specializing the function for this value
162 can bring about in it's callees (transitively). */
163 int prop_time_benefit, prop_size_cost;
165 ipcp_value_base ()
166 : local_time_benefit (0), local_size_cost (0),
167 prop_time_benefit (0), prop_size_cost (0) {}
170 /* Describes one particular value stored in struct ipcp_lattice. */
172 template <typename valtype>
173 class ipcp_value : public ipcp_value_base
175 public:
176 /* The actual value for the given parameter. */
177 valtype value;
178 /* The list of sources from which this value originates. */
179 ipcp_value_source <valtype> *sources;
180 /* Next pointers in a linked list of all values in a lattice. */
181 ipcp_value *next;
182 /* Next pointers in a linked list of values in a strongly connected component
183 of values. */
184 ipcp_value *scc_next;
185 /* Next pointers in a linked list of SCCs of values sorted topologically
186 according their sources. */
187 ipcp_value *topo_next;
188 /* A specialized node created for this value, NULL if none has been (so far)
189 created. */
190 cgraph_node *spec_node;
191 /* Depth first search number and low link for topological sorting of
192 values. */
193 int dfs, low_link;
194 /* True if this 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, 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 can not
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;
2821 time_benefit = base_time.to_int ()
2822 + devirtualization_time_bonus (node, known_csts, known_contexts,
2823 known_aggs_ptrs)
2824 + hint_time_bonus (hints)
2825 + removable_params_cost + est_move_cost;
2827 gcc_checking_assert (size >=0);
2828 /* The inliner-heuristics based estimates may think that in certain
2829 contexts some functions do not have any size at all but we want
2830 all specializations to have at least a tiny cost, not least not to
2831 divide by zero. */
2832 if (size == 0)
2833 size = 1;
2835 val->local_time_benefit = time_benefit;
2836 val->local_size_cost = size;
2839 /* Iterate over known values of parameters of NODE and estimate the local
2840 effects in terms of time and size they have. */
2842 static void
2843 estimate_local_effects (struct cgraph_node *node)
2845 struct ipa_node_params *info = IPA_NODE_REF (node);
2846 int i, count = ipa_get_param_count (info);
2847 vec<tree> known_csts;
2848 vec<ipa_polymorphic_call_context> known_contexts;
2849 vec<ipa_agg_jump_function> known_aggs;
2850 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2851 bool always_const;
2852 int removable_params_cost;
2854 if (!count || !ipcp_versionable_function_p (node))
2855 return;
2857 if (dump_file && (dump_flags & TDF_DETAILS))
2858 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
2860 always_const = gather_context_independent_values (info, &known_csts,
2861 &known_contexts, &known_aggs,
2862 &removable_params_cost);
2863 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2864 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2865 known_contexts, known_aggs_ptrs);
2866 if (always_const || devirt_bonus
2867 || (removable_params_cost && node->local.can_change_signature))
2869 struct caller_statistics stats;
2870 ipa_hints hints;
2871 sreal time, base_time;
2872 int size;
2874 init_caller_stats (&stats);
2875 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2876 false);
2877 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2878 known_aggs_ptrs, &size, &time,
2879 &base_time, &hints);
2880 time -= devirt_bonus;
2881 time -= hint_time_bonus (hints);
2882 time -= removable_params_cost;
2883 size -= stats.n_calls * removable_params_cost;
2885 if (dump_file)
2886 fprintf (dump_file, " - context independent values, size: %i, "
2887 "time_benefit: %f\n", size, (base_time - time).to_double ());
2889 if (size <= 0 || node->local.local)
2891 info->do_clone_for_all_contexts = true;
2893 if (dump_file)
2894 fprintf (dump_file, " Decided to specialize for all "
2895 "known contexts, code not going to grow.\n");
2897 else if (good_cloning_opportunity_p (node,
2898 MIN ((base_time - time).to_int (),
2899 65536),
2900 stats.freq_sum, stats.count_sum,
2901 size))
2903 if (size + overall_size <= max_new_size)
2905 info->do_clone_for_all_contexts = true;
2906 overall_size += size;
2908 if (dump_file)
2909 fprintf (dump_file, " Decided to specialize for all "
2910 "known contexts, growth deemed beneficial.\n");
2912 else if (dump_file && (dump_flags & TDF_DETAILS))
2913 fprintf (dump_file, " Not cloning for all contexts because "
2914 "max_new_size would be reached with %li.\n",
2915 size + overall_size);
2917 else if (dump_file && (dump_flags & TDF_DETAILS))
2918 fprintf (dump_file, " Not cloning for all contexts because "
2919 "!good_cloning_opportunity_p.\n");
2923 for (i = 0; i < count; i++)
2925 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2926 ipcp_lattice<tree> *lat = &plats->itself;
2927 ipcp_value<tree> *val;
2929 if (lat->bottom
2930 || !lat->values
2931 || known_csts[i])
2932 continue;
2934 for (val = lat->values; val; val = val->next)
2936 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2937 known_csts[i] = val->value;
2939 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2940 perform_estimation_of_a_value (node, known_csts, known_contexts,
2941 known_aggs_ptrs,
2942 removable_params_cost, emc, val);
2944 if (dump_file && (dump_flags & TDF_DETAILS))
2946 fprintf (dump_file, " - estimates for value ");
2947 print_ipcp_constant_value (dump_file, val->value);
2948 fprintf (dump_file, " for ");
2949 ipa_dump_param (dump_file, info, i);
2950 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2951 val->local_time_benefit, val->local_size_cost);
2954 known_csts[i] = NULL_TREE;
2957 for (i = 0; i < count; i++)
2959 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2961 if (!plats->virt_call)
2962 continue;
2964 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2965 ipcp_value<ipa_polymorphic_call_context> *val;
2967 if (ctxlat->bottom
2968 || !ctxlat->values
2969 || !known_contexts[i].useless_p ())
2970 continue;
2972 for (val = ctxlat->values; val; val = val->next)
2974 known_contexts[i] = val->value;
2975 perform_estimation_of_a_value (node, known_csts, known_contexts,
2976 known_aggs_ptrs,
2977 removable_params_cost, 0, val);
2979 if (dump_file && (dump_flags & TDF_DETAILS))
2981 fprintf (dump_file, " - estimates for polymorphic context ");
2982 print_ipcp_constant_value (dump_file, val->value);
2983 fprintf (dump_file, " for ");
2984 ipa_dump_param (dump_file, info, i);
2985 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2986 val->local_time_benefit, val->local_size_cost);
2989 known_contexts[i] = ipa_polymorphic_call_context ();
2992 for (i = 0; i < count; i++)
2994 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2995 struct ipa_agg_jump_function *ajf;
2996 struct ipcp_agg_lattice *aglat;
2998 if (plats->aggs_bottom || !plats->aggs)
2999 continue;
3001 ajf = &known_aggs[i];
3002 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3004 ipcp_value<tree> *val;
3005 if (aglat->bottom || !aglat->values
3006 /* If the following is true, the one value is in known_aggs. */
3007 || (!plats->aggs_contain_variable
3008 && aglat->is_single_const ()))
3009 continue;
3011 for (val = aglat->values; val; val = val->next)
3013 struct ipa_agg_jf_item item;
3015 item.offset = aglat->offset;
3016 item.value = val->value;
3017 vec_safe_push (ajf->items, item);
3019 perform_estimation_of_a_value (node, known_csts, known_contexts,
3020 known_aggs_ptrs,
3021 removable_params_cost, 0, val);
3023 if (dump_file && (dump_flags & TDF_DETAILS))
3025 fprintf (dump_file, " - estimates for value ");
3026 print_ipcp_constant_value (dump_file, val->value);
3027 fprintf (dump_file, " for ");
3028 ipa_dump_param (dump_file, info, i);
3029 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3030 "]: time_benefit: %i, size: %i\n",
3031 plats->aggs_by_ref ? "ref " : "",
3032 aglat->offset,
3033 val->local_time_benefit, val->local_size_cost);
3036 ajf->items->pop ();
3041 for (i = 0; i < count; i++)
3042 vec_free (known_aggs[i].items);
3044 known_csts.release ();
3045 known_contexts.release ();
3046 known_aggs.release ();
3047 known_aggs_ptrs.release ();
3051 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3052 topological sort of values. */
3054 template <typename valtype>
3055 void
3056 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3058 ipcp_value_source<valtype> *src;
3060 if (cur_val->dfs)
3061 return;
3063 dfs_counter++;
3064 cur_val->dfs = dfs_counter;
3065 cur_val->low_link = dfs_counter;
3067 cur_val->topo_next = stack;
3068 stack = cur_val;
3069 cur_val->on_stack = true;
3071 for (src = cur_val->sources; src; src = src->next)
3072 if (src->val)
3074 if (src->val->dfs == 0)
3076 add_val (src->val);
3077 if (src->val->low_link < cur_val->low_link)
3078 cur_val->low_link = src->val->low_link;
3080 else if (src->val->on_stack
3081 && src->val->dfs < cur_val->low_link)
3082 cur_val->low_link = src->val->dfs;
3085 if (cur_val->dfs == cur_val->low_link)
3087 ipcp_value<valtype> *v, *scc_list = NULL;
3091 v = stack;
3092 stack = v->topo_next;
3093 v->on_stack = false;
3095 v->scc_next = scc_list;
3096 scc_list = v;
3098 while (v != cur_val);
3100 cur_val->topo_next = values_topo;
3101 values_topo = cur_val;
3105 /* Add all values in lattices associated with NODE to the topological sort if
3106 they are not there yet. */
3108 static void
3109 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3111 struct ipa_node_params *info = IPA_NODE_REF (node);
3112 int i, count = ipa_get_param_count (info);
3114 for (i = 0; i < count; i++)
3116 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3117 ipcp_lattice<tree> *lat = &plats->itself;
3118 struct ipcp_agg_lattice *aglat;
3120 if (!lat->bottom)
3122 ipcp_value<tree> *val;
3123 for (val = lat->values; val; val = val->next)
3124 topo->constants.add_val (val);
3127 if (!plats->aggs_bottom)
3128 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3129 if (!aglat->bottom)
3131 ipcp_value<tree> *val;
3132 for (val = aglat->values; val; val = val->next)
3133 topo->constants.add_val (val);
3136 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3137 if (!ctxlat->bottom)
3139 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3140 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3141 topo->contexts.add_val (ctxval);
3146 /* One pass of constants propagation along the call graph edges, from callers
3147 to callees (requires topological ordering in TOPO), iterate over strongly
3148 connected components. */
3150 static void
3151 propagate_constants_topo (struct ipa_topo_info *topo)
3153 int i;
3155 for (i = topo->nnodes - 1; i >= 0; i--)
3157 unsigned j;
3158 struct cgraph_node *v, *node = topo->order[i];
3159 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3161 /* First, iteratively propagate within the strongly connected component
3162 until all lattices stabilize. */
3163 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3164 if (v->has_gimple_body_p ())
3165 push_node_to_stack (topo, v);
3167 v = pop_node_from_stack (topo);
3168 while (v)
3170 struct cgraph_edge *cs;
3172 for (cs = v->callees; cs; cs = cs->next_callee)
3173 if (ipa_edge_within_scc (cs))
3175 IPA_NODE_REF (v)->node_within_scc = true;
3176 if (propagate_constants_across_call (cs))
3177 push_node_to_stack (topo, cs->callee->function_symbol ());
3179 v = pop_node_from_stack (topo);
3182 /* Afterwards, propagate along edges leading out of the SCC, calculates
3183 the local effects of the discovered constants and all valid values to
3184 their topological sort. */
3185 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3186 if (v->has_gimple_body_p ())
3188 struct cgraph_edge *cs;
3190 estimate_local_effects (v);
3191 add_all_node_vals_to_toposort (v, topo);
3192 for (cs = v->callees; cs; cs = cs->next_callee)
3193 if (!ipa_edge_within_scc (cs))
3194 propagate_constants_across_call (cs);
3196 cycle_nodes.release ();
3201 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3202 the bigger one if otherwise. */
3204 static int
3205 safe_add (int a, int b)
3207 if (a > INT_MAX/2 || b > INT_MAX/2)
3208 return a > b ? a : b;
3209 else
3210 return a + b;
3214 /* Propagate the estimated effects of individual values along the topological
3215 from the dependent values to those they depend on. */
3217 template <typename valtype>
3218 void
3219 value_topo_info<valtype>::propagate_effects ()
3221 ipcp_value<valtype> *base;
3223 for (base = values_topo; base; base = base->topo_next)
3225 ipcp_value_source<valtype> *src;
3226 ipcp_value<valtype> *val;
3227 int time = 0, size = 0;
3229 for (val = base; val; val = val->scc_next)
3231 time = safe_add (time,
3232 val->local_time_benefit + val->prop_time_benefit);
3233 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3236 for (val = base; val; val = val->scc_next)
3237 for (src = val->sources; src; src = src->next)
3238 if (src->val
3239 && src->cs->maybe_hot_p ())
3241 src->val->prop_time_benefit = safe_add (time,
3242 src->val->prop_time_benefit);
3243 src->val->prop_size_cost = safe_add (size,
3244 src->val->prop_size_cost);
3250 /* Propagate constants, polymorphic contexts and their effects from the
3251 summaries interprocedurally. */
3253 static void
3254 ipcp_propagate_stage (struct ipa_topo_info *topo)
3256 struct cgraph_node *node;
3258 if (dump_file)
3259 fprintf (dump_file, "\n Propagating constants:\n\n");
3261 max_count = profile_count::uninitialized ();
3263 FOR_EACH_DEFINED_FUNCTION (node)
3265 struct ipa_node_params *info = IPA_NODE_REF (node);
3267 determine_versionability (node, info);
3268 if (node->has_gimple_body_p ())
3270 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3271 ipa_get_param_count (info));
3272 initialize_node_lattices (node);
3274 ipa_fn_summary *s = ipa_fn_summaries->get (node);
3275 if (node->definition && !node->alias && s != NULL)
3276 overall_size += s->self_size;
3277 max_count = max_count.max (node->count.ipa ());
3280 max_new_size = overall_size;
3281 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3282 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3283 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3285 if (dump_file)
3286 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3287 overall_size, max_new_size);
3289 propagate_constants_topo (topo);
3290 if (flag_checking)
3291 ipcp_verify_propagated_values ();
3292 topo->constants.propagate_effects ();
3293 topo->contexts.propagate_effects ();
3295 if (dump_file)
3297 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3298 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3302 /* Discover newly direct outgoing edges from NODE which is a new clone with
3303 known KNOWN_CSTS and make them direct. */
3305 static void
3306 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3307 vec<tree> known_csts,
3308 vec<ipa_polymorphic_call_context>
3309 known_contexts,
3310 struct ipa_agg_replacement_value *aggvals)
3312 struct cgraph_edge *ie, *next_ie;
3313 bool found = false;
3315 for (ie = node->indirect_calls; ie; ie = next_ie)
3317 tree target;
3318 bool speculative;
3320 next_ie = ie->next_callee;
3321 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3322 vNULL, aggvals, &speculative);
3323 if (target)
3325 bool agg_contents = ie->indirect_info->agg_contents;
3326 bool polymorphic = ie->indirect_info->polymorphic;
3327 int param_index = ie->indirect_info->param_index;
3328 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3329 speculative);
3330 found = true;
3332 if (cs && !agg_contents && !polymorphic)
3334 struct ipa_node_params *info = IPA_NODE_REF (node);
3335 int c = ipa_get_controlled_uses (info, param_index);
3336 if (c != IPA_UNDESCRIBED_USE)
3338 struct ipa_ref *to_del;
3340 c--;
3341 ipa_set_controlled_uses (info, param_index, c);
3342 if (dump_file && (dump_flags & TDF_DETAILS))
3343 fprintf (dump_file, " controlled uses count of param "
3344 "%i bumped down to %i\n", param_index, c);
3345 if (c == 0
3346 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3348 if (dump_file && (dump_flags & TDF_DETAILS))
3349 fprintf (dump_file, " and even removing its "
3350 "cloning-created reference\n");
3351 to_del->remove_reference ();
3357 /* Turning calls to direct calls will improve overall summary. */
3358 if (found)
3359 ipa_update_overall_fn_summary (node);
3362 class edge_clone_summary;
3363 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL;
3365 /* Edge clone summary. */
3367 struct edge_clone_summary
3369 /* Default constructor. */
3370 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
3372 /* Default destructor. */
3373 ~edge_clone_summary ()
3375 if (prev_clone)
3376 edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
3377 if (next_clone)
3378 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
3381 cgraph_edge *prev_clone;
3382 cgraph_edge *next_clone;
3385 class edge_clone_summary_t:
3386 public call_summary <edge_clone_summary *>
3388 public:
3389 edge_clone_summary_t (symbol_table *symtab):
3390 call_summary <edge_clone_summary *> (symtab)
3392 m_initialize_when_cloning = true;
3395 virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
3396 edge_clone_summary *src_data,
3397 edge_clone_summary *dst_data);
3400 /* Edge duplication hook. */
3402 void
3403 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
3404 edge_clone_summary *src_data,
3405 edge_clone_summary *dst_data)
3407 if (src_data->next_clone)
3408 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
3409 dst_data->prev_clone = src_edge;
3410 dst_data->next_clone = src_data->next_clone;
3411 src_data->next_clone = dst_edge;
3414 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3415 parameter with the given INDEX. */
3417 static tree
3418 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3419 int index)
3421 struct ipa_agg_replacement_value *aggval;
3423 aggval = ipa_get_agg_replacements_for_node (node);
3424 while (aggval)
3426 if (aggval->offset == offset
3427 && aggval->index == index)
3428 return aggval->value;
3429 aggval = aggval->next;
3431 return NULL_TREE;
3434 /* Return true is NODE is DEST or its clone for all contexts. */
3436 static bool
3437 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3439 if (node == dest)
3440 return true;
3442 struct ipa_node_params *info = IPA_NODE_REF (node);
3443 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3446 /* Return true if edge CS does bring about the value described by SRC to
3447 DEST_VAL of node DEST or its clone for all contexts. */
3449 static bool
3450 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3451 cgraph_node *dest, ipcp_value<tree> *dest_val)
3453 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3454 enum availability availability;
3455 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3457 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3458 || availability <= AVAIL_INTERPOSABLE
3459 || caller_info->node_dead)
3460 return false;
3462 if (!src->val)
3463 return true;
3465 if (caller_info->ipcp_orig_node)
3467 tree t;
3468 if (src->offset == -1)
3469 t = caller_info->known_csts[src->index];
3470 else
3471 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3472 return (t != NULL_TREE
3473 && values_equal_for_ipcp_p (src->val->value, t));
3475 else
3477 /* At the moment we do not propagate over arithmetic jump functions in
3478 SCCs, so it is safe to detect self-feeding recursive calls in this
3479 way. */
3480 if (src->val == dest_val)
3481 return true;
3483 struct ipcp_agg_lattice *aglat;
3484 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3485 src->index);
3486 if (src->offset == -1)
3487 return (plats->itself.is_single_const ()
3488 && values_equal_for_ipcp_p (src->val->value,
3489 plats->itself.values->value));
3490 else
3492 if (plats->aggs_bottom || plats->aggs_contain_variable)
3493 return false;
3494 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3495 if (aglat->offset == src->offset)
3496 return (aglat->is_single_const ()
3497 && values_equal_for_ipcp_p (src->val->value,
3498 aglat->values->value));
3500 return false;
3504 /* Return true if edge CS does bring about the value described by SRC to
3505 DST_VAL of node DEST or its clone for all contexts. */
3507 static bool
3508 cgraph_edge_brings_value_p (cgraph_edge *cs,
3509 ipcp_value_source<ipa_polymorphic_call_context> *src,
3510 cgraph_node *dest,
3511 ipcp_value<ipa_polymorphic_call_context> *)
3513 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3514 cgraph_node *real_dest = cs->callee->function_symbol ();
3516 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3517 || caller_info->node_dead)
3518 return false;
3519 if (!src->val)
3520 return true;
3522 if (caller_info->ipcp_orig_node)
3523 return (caller_info->known_contexts.length () > (unsigned) src->index)
3524 && values_equal_for_ipcp_p (src->val->value,
3525 caller_info->known_contexts[src->index]);
3527 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3528 src->index);
3529 return plats->ctxlat.is_single_const ()
3530 && values_equal_for_ipcp_p (src->val->value,
3531 plats->ctxlat.values->value);
3534 /* Get the next clone in the linked list of clones of an edge. */
3536 static inline struct cgraph_edge *
3537 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3539 edge_clone_summary *s = edge_clone_summaries->get (cs);
3540 return s != NULL ? s->next_clone : NULL;
3543 /* Given VAL that is intended for DEST, iterate over all its sources and if any
3544 of them is viable and hot, return true. In that case, for those that still
3545 hold, add their edge frequency and their number into *FREQUENCY and
3546 *CALLER_COUNT respectively. */
3548 template <typename valtype>
3549 static bool
3550 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3551 int *freq_sum,
3552 profile_count *count_sum, int *caller_count)
3554 ipcp_value_source<valtype> *src;
3555 int freq = 0, count = 0;
3556 profile_count cnt = profile_count::zero ();
3557 bool hot = false;
3558 bool non_self_recursive = false;
3560 for (src = val->sources; src; src = src->next)
3562 struct cgraph_edge *cs = src->cs;
3563 while (cs)
3565 if (cgraph_edge_brings_value_p (cs, src, dest, val))
3567 count++;
3568 freq += cs->frequency ();
3569 if (cs->count.ipa ().initialized_p ())
3570 cnt += cs->count.ipa ();
3571 hot |= cs->maybe_hot_p ();
3572 if (cs->caller != dest)
3573 non_self_recursive = true;
3575 cs = get_next_cgraph_edge_clone (cs);
3579 /* If the only edges bringing a value are self-recursive ones, do not bother
3580 evaluating it. */
3581 if (!non_self_recursive)
3582 return false;
3584 *freq_sum = freq;
3585 *count_sum = cnt;
3586 *caller_count = count;
3587 return hot;
3590 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3591 is assumed their number is known and equal to CALLER_COUNT. */
3593 template <typename valtype>
3594 static vec<cgraph_edge *>
3595 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3596 int caller_count)
3598 ipcp_value_source<valtype> *src;
3599 vec<cgraph_edge *> ret;
3601 ret.create (caller_count);
3602 for (src = val->sources; src; src = src->next)
3604 struct cgraph_edge *cs = src->cs;
3605 while (cs)
3607 if (cgraph_edge_brings_value_p (cs, src, dest, val))
3608 ret.quick_push (cs);
3609 cs = get_next_cgraph_edge_clone (cs);
3613 return ret;
3616 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3617 Return it or NULL if for some reason it cannot be created. */
3619 static struct ipa_replace_map *
3620 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3622 struct ipa_replace_map *replace_map;
3625 replace_map = ggc_alloc<ipa_replace_map> ();
3626 if (dump_file)
3628 fprintf (dump_file, " replacing ");
3629 ipa_dump_param (dump_file, info, parm_num);
3631 fprintf (dump_file, " with const ");
3632 print_generic_expr (dump_file, value);
3633 fprintf (dump_file, "\n");
3635 replace_map->old_tree = NULL;
3636 replace_map->parm_num = parm_num;
3637 replace_map->new_tree = value;
3638 replace_map->replace_p = true;
3639 replace_map->ref_p = false;
3641 return replace_map;
3644 /* Dump new profiling counts */
3646 static void
3647 dump_profile_updates (struct cgraph_node *orig_node,
3648 struct cgraph_node *new_node)
3650 struct cgraph_edge *cs;
3652 fprintf (dump_file, " setting count of the specialized node to ");
3653 new_node->count.dump (dump_file);
3654 fprintf (dump_file, "\n");
3655 for (cs = new_node->callees; cs; cs = cs->next_callee)
3657 fprintf (dump_file, " edge to %s has count ",
3658 cs->callee->name ());
3659 cs->count.dump (dump_file);
3660 fprintf (dump_file, "\n");
3663 fprintf (dump_file, " setting count of the original node to ");
3664 orig_node->count.dump (dump_file);
3665 fprintf (dump_file, "\n");
3666 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3668 fprintf (dump_file, " edge to %s is left with ",
3669 cs->callee->name ());
3670 cs->count.dump (dump_file);
3671 fprintf (dump_file, "\n");
3675 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3676 their profile information to reflect this. */
3678 static void
3679 update_profiling_info (struct cgraph_node *orig_node,
3680 struct cgraph_node *new_node)
3682 struct cgraph_edge *cs;
3683 struct caller_statistics stats;
3684 profile_count new_sum, orig_sum;
3685 profile_count remainder, orig_node_count = orig_node->count;
3687 if (!(orig_node_count.ipa () > profile_count::zero ()))
3688 return;
3690 init_caller_stats (&stats);
3691 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3692 false);
3693 orig_sum = stats.count_sum;
3694 init_caller_stats (&stats);
3695 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3696 false);
3697 new_sum = stats.count_sum;
3699 if (orig_node_count < orig_sum + new_sum)
3701 if (dump_file)
3703 fprintf (dump_file, " Problem: node %s has too low count ",
3704 orig_node->dump_name ());
3705 orig_node_count.dump (dump_file);
3706 fprintf (dump_file, "while the sum of incoming count is ");
3707 (orig_sum + new_sum).dump (dump_file);
3708 fprintf (dump_file, "\n");
3711 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
3712 if (dump_file)
3714 fprintf (dump_file, " proceeding by pretending it was ");
3715 orig_node_count.dump (dump_file);
3716 fprintf (dump_file, "\n");
3720 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
3721 - new_sum.ipa ());
3722 new_sum = orig_node_count.combine_with_ipa_count (new_sum);
3723 orig_node->count = remainder;
3725 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_node_count);
3726 for (cs = new_node->callees; cs; cs = cs->next_callee)
3727 cs->count = cs->count.apply_scale (new_sum, orig_node_count);
3729 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
3730 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3731 cs->count = cs->count.apply_scale (remainder, orig_node_count);
3733 if (dump_file)
3734 dump_profile_updates (orig_node, new_node);
3737 /* Update the respective profile of specialized NEW_NODE and the original
3738 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3739 have been redirected to the specialized version. */
3741 static void
3742 update_specialized_profile (struct cgraph_node *new_node,
3743 struct cgraph_node *orig_node,
3744 profile_count redirected_sum)
3746 struct cgraph_edge *cs;
3747 profile_count new_node_count, orig_node_count = orig_node->count;
3749 if (dump_file)
3751 fprintf (dump_file, " the sum of counts of redirected edges is ");
3752 redirected_sum.dump (dump_file);
3753 fprintf (dump_file, "\n");
3755 if (!(orig_node_count > profile_count::zero ()))
3756 return;
3758 gcc_assert (orig_node_count >= redirected_sum);
3760 new_node_count = new_node->count;
3761 new_node->count += redirected_sum;
3762 orig_node->count -= redirected_sum;
3764 for (cs = new_node->callees; cs; cs = cs->next_callee)
3765 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
3767 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3769 profile_count dec = cs->count.apply_scale (redirected_sum,
3770 orig_node_count);
3771 cs->count -= dec;
3774 if (dump_file)
3775 dump_profile_updates (orig_node, new_node);
3778 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3779 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3780 redirect all edges in CALLERS to it. */
3782 static struct cgraph_node *
3783 create_specialized_node (struct cgraph_node *node,
3784 vec<tree> known_csts,
3785 vec<ipa_polymorphic_call_context> known_contexts,
3786 struct ipa_agg_replacement_value *aggvals,
3787 vec<cgraph_edge *> callers)
3789 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3790 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3791 struct ipa_agg_replacement_value *av;
3792 struct cgraph_node *new_node;
3793 int i, count = ipa_get_param_count (info);
3794 bitmap args_to_skip;
3796 gcc_assert (!info->ipcp_orig_node);
3798 if (node->local.can_change_signature)
3800 args_to_skip = BITMAP_GGC_ALLOC ();
3801 for (i = 0; i < count; i++)
3803 tree t = known_csts[i];
3805 if (t || !ipa_is_param_used (info, i))
3806 bitmap_set_bit (args_to_skip, i);
3809 else
3811 args_to_skip = NULL;
3812 if (dump_file && (dump_flags & TDF_DETAILS))
3813 fprintf (dump_file, " cannot change function signature\n");
3816 for (i = 0; i < count; i++)
3818 tree t = known_csts[i];
3819 if (t)
3821 struct ipa_replace_map *replace_map;
3823 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3824 replace_map = get_replacement_map (info, t, i);
3825 if (replace_map)
3826 vec_safe_push (replace_trees, replace_map);
3829 auto_vec<cgraph_edge *, 2> self_recursive_calls;
3830 for (i = callers.length () - 1; i >= 0; i--)
3832 cgraph_edge *cs = callers[i];
3833 if (cs->caller == node)
3835 self_recursive_calls.safe_push (cs);
3836 callers.unordered_remove (i);
3840 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
3841 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
3842 node->decl)));
3843 new_node = node->create_virtual_clone (callers, replace_trees,
3844 args_to_skip, "constprop",
3845 suffix_counter);
3846 suffix_counter++;
3848 bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
3849 for (unsigned j = 0; j < self_recursive_calls.length (); j++)
3851 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
3852 /* Cloned edges can disappear during cloning as speculation can be
3853 resolved, check that we have one and that it comes from the last
3854 cloning. */
3855 if (cs && cs->caller == new_node)
3856 cs->redirect_callee_duplicating_thunks (new_node);
3857 /* Any future code that would make more than one clone of an outgoing
3858 edge would confuse this mechanism, so let's check that does not
3859 happen. */
3860 gcc_checking_assert (!cs
3861 || !get_next_cgraph_edge_clone (cs)
3862 || get_next_cgraph_edge_clone (cs)->caller != new_node);
3864 if (have_self_recursive_calls)
3865 new_node->expand_all_artificial_thunks ();
3867 ipa_set_node_agg_value_chain (new_node, aggvals);
3868 for (av = aggvals; av; av = av->next)
3869 new_node->maybe_create_reference (av->value, NULL);
3871 if (dump_file && (dump_flags & TDF_DETAILS))
3873 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
3874 if (known_contexts.exists ())
3876 for (i = 0; i < count; i++)
3877 if (!known_contexts[i].useless_p ())
3879 fprintf (dump_file, " known ctx %i is ", i);
3880 known_contexts[i].dump (dump_file);
3883 if (aggvals)
3884 ipa_dump_agg_replacement_values (dump_file, aggvals);
3886 ipa_check_create_node_params ();
3887 update_profiling_info (node, new_node);
3888 new_info = IPA_NODE_REF (new_node);
3889 new_info->ipcp_orig_node = node;
3890 new_info->known_csts = known_csts;
3891 new_info->known_contexts = known_contexts;
3893 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3895 callers.release ();
3896 return new_node;
3899 /* Return true, if JFUNC, which describes a i-th parameter of call CS, is a
3900 simple no-operation pass-through function to itself. */
3902 static bool
3903 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i)
3905 enum availability availability;
3906 if (cs->caller == cs->callee->function_symbol (&availability)
3907 && availability > AVAIL_INTERPOSABLE
3908 && jfunc->type == IPA_JF_PASS_THROUGH
3909 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR
3910 && ipa_get_jf_pass_through_formal_id (jfunc) == i)
3911 return true;
3912 return false;
3915 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3916 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3918 static void
3919 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3920 vec<tree> known_csts,
3921 vec<cgraph_edge *> callers)
3923 struct ipa_node_params *info = IPA_NODE_REF (node);
3924 int i, count = ipa_get_param_count (info);
3926 for (i = 0; i < count; i++)
3928 struct cgraph_edge *cs;
3929 tree newval = NULL_TREE;
3930 int j;
3931 bool first = true;
3932 tree type = ipa_get_type (info, i);
3934 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3935 continue;
3937 FOR_EACH_VEC_ELT (callers, j, cs)
3939 struct ipa_jump_func *jump_func;
3940 tree t;
3942 if (IPA_NODE_REF (cs->caller)->node_dead)
3943 continue;
3945 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3946 || (i == 0
3947 && call_passes_through_thunk_p (cs)))
3949 newval = NULL_TREE;
3950 break;
3952 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3953 if (self_recursive_pass_through_p (cs, jump_func, i))
3954 continue;
3956 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func, type);
3957 if (!t
3958 || (newval
3959 && !values_equal_for_ipcp_p (t, newval))
3960 || (!first && !newval))
3962 newval = NULL_TREE;
3963 break;
3965 else
3966 newval = t;
3967 first = false;
3970 if (newval)
3972 if (dump_file && (dump_flags & TDF_DETAILS))
3974 fprintf (dump_file, " adding an extra known scalar value ");
3975 print_ipcp_constant_value (dump_file, newval);
3976 fprintf (dump_file, " for ");
3977 ipa_dump_param (dump_file, info, i);
3978 fprintf (dump_file, "\n");
3981 known_csts[i] = newval;
3986 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3987 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3988 CALLERS. */
3990 static void
3991 find_more_contexts_for_caller_subset (cgraph_node *node,
3992 vec<ipa_polymorphic_call_context>
3993 *known_contexts,
3994 vec<cgraph_edge *> callers)
3996 ipa_node_params *info = IPA_NODE_REF (node);
3997 int i, count = ipa_get_param_count (info);
3999 for (i = 0; i < count; i++)
4001 cgraph_edge *cs;
4003 if (ipa_get_poly_ctx_lat (info, i)->bottom
4004 || (known_contexts->exists ()
4005 && !(*known_contexts)[i].useless_p ()))
4006 continue;
4008 ipa_polymorphic_call_context newval;
4009 bool first = true;
4010 int j;
4012 FOR_EACH_VEC_ELT (callers, j, cs)
4014 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
4015 return;
4016 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
4018 ipa_polymorphic_call_context ctx;
4019 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
4020 jfunc);
4021 if (first)
4023 newval = ctx;
4024 first = false;
4026 else
4027 newval.meet_with (ctx);
4028 if (newval.useless_p ())
4029 break;
4032 if (!newval.useless_p ())
4034 if (dump_file && (dump_flags & TDF_DETAILS))
4036 fprintf (dump_file, " adding an extra known polymorphic "
4037 "context ");
4038 print_ipcp_constant_value (dump_file, newval);
4039 fprintf (dump_file, " for ");
4040 ipa_dump_param (dump_file, info, i);
4041 fprintf (dump_file, "\n");
4044 if (!known_contexts->exists ())
4045 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
4046 (*known_contexts)[i] = newval;
4052 /* Go through PLATS and create a vector of values consisting of values and
4053 offsets (minus OFFSET) of lattices that contain only a single value. */
4055 static vec<ipa_agg_jf_item>
4056 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
4058 vec<ipa_agg_jf_item> res = vNULL;
4060 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4061 return vNULL;
4063 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
4064 if (aglat->is_single_const ())
4066 struct ipa_agg_jf_item ti;
4067 ti.offset = aglat->offset - offset;
4068 ti.value = aglat->values->value;
4069 res.safe_push (ti);
4071 return res;
4074 /* Intersect all values in INTER with single value lattices in PLATS (while
4075 subtracting OFFSET). */
4077 static void
4078 intersect_with_plats (struct ipcp_param_lattices *plats,
4079 vec<ipa_agg_jf_item> *inter,
4080 HOST_WIDE_INT offset)
4082 struct ipcp_agg_lattice *aglat;
4083 struct ipa_agg_jf_item *item;
4084 int k;
4086 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4088 inter->release ();
4089 return;
4092 aglat = plats->aggs;
4093 FOR_EACH_VEC_ELT (*inter, k, item)
4095 bool found = false;
4096 if (!item->value)
4097 continue;
4098 while (aglat)
4100 if (aglat->offset - offset > item->offset)
4101 break;
4102 if (aglat->offset - offset == item->offset)
4104 gcc_checking_assert (item->value);
4105 if (aglat->is_single_const ()
4106 && values_equal_for_ipcp_p (item->value,
4107 aglat->values->value))
4108 found = true;
4109 break;
4111 aglat = aglat->next;
4113 if (!found)
4114 item->value = NULL_TREE;
4118 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4119 vector result while subtracting OFFSET from the individual value offsets. */
4121 static vec<ipa_agg_jf_item>
4122 agg_replacements_to_vector (struct cgraph_node *node, int index,
4123 HOST_WIDE_INT offset)
4125 struct ipa_agg_replacement_value *av;
4126 vec<ipa_agg_jf_item> res = vNULL;
4128 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4129 if (av->index == index
4130 && (av->offset - offset) >= 0)
4132 struct ipa_agg_jf_item item;
4133 gcc_checking_assert (av->value);
4134 item.offset = av->offset - offset;
4135 item.value = av->value;
4136 res.safe_push (item);
4139 return res;
4142 /* Intersect all values in INTER with those that we have already scheduled to
4143 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4144 (while subtracting OFFSET). */
4146 static void
4147 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4148 vec<ipa_agg_jf_item> *inter,
4149 HOST_WIDE_INT offset)
4151 struct ipa_agg_replacement_value *srcvals;
4152 struct ipa_agg_jf_item *item;
4153 int i;
4155 srcvals = ipa_get_agg_replacements_for_node (node);
4156 if (!srcvals)
4158 inter->release ();
4159 return;
4162 FOR_EACH_VEC_ELT (*inter, i, item)
4164 struct ipa_agg_replacement_value *av;
4165 bool found = false;
4166 if (!item->value)
4167 continue;
4168 for (av = srcvals; av; av = av->next)
4170 gcc_checking_assert (av->value);
4171 if (av->index == index
4172 && av->offset - offset == item->offset)
4174 if (values_equal_for_ipcp_p (item->value, av->value))
4175 found = true;
4176 break;
4179 if (!found)
4180 item->value = NULL_TREE;
4184 /* Intersect values in INTER with aggregate values that come along edge CS to
4185 parameter number INDEX and return it. If INTER does not actually exist yet,
4186 copy all incoming values to it. If we determine we ended up with no values
4187 whatsoever, return a released vector. */
4189 static vec<ipa_agg_jf_item>
4190 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4191 vec<ipa_agg_jf_item> inter)
4193 struct ipa_jump_func *jfunc;
4194 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4195 if (jfunc->type == IPA_JF_PASS_THROUGH
4196 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4198 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4199 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4201 if (caller_info->ipcp_orig_node)
4203 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4204 struct ipcp_param_lattices *orig_plats;
4205 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4206 src_idx);
4207 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4209 if (!inter.exists ())
4210 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4211 else
4212 intersect_with_agg_replacements (cs->caller, src_idx,
4213 &inter, 0);
4215 else
4217 inter.release ();
4218 return vNULL;
4221 else
4223 struct ipcp_param_lattices *src_plats;
4224 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4225 if (agg_pass_through_permissible_p (src_plats, jfunc))
4227 /* Currently we do not produce clobber aggregate jump
4228 functions, adjust when we do. */
4229 gcc_checking_assert (!jfunc->agg.items);
4230 if (!inter.exists ())
4231 inter = copy_plats_to_inter (src_plats, 0);
4232 else
4233 intersect_with_plats (src_plats, &inter, 0);
4235 else
4237 inter.release ();
4238 return vNULL;
4242 else if (jfunc->type == IPA_JF_ANCESTOR
4243 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4245 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4246 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4247 struct ipcp_param_lattices *src_plats;
4248 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4250 if (caller_info->ipcp_orig_node)
4252 if (!inter.exists ())
4253 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4254 else
4255 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4256 delta);
4258 else
4260 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4261 /* Currently we do not produce clobber aggregate jump
4262 functions, adjust when we do. */
4263 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4264 if (!inter.exists ())
4265 inter = copy_plats_to_inter (src_plats, delta);
4266 else
4267 intersect_with_plats (src_plats, &inter, delta);
4270 else if (jfunc->agg.items)
4272 struct ipa_agg_jf_item *item;
4273 int k;
4275 if (!inter.exists ())
4276 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4277 inter.safe_push ((*jfunc->agg.items)[i]);
4278 else
4279 FOR_EACH_VEC_ELT (inter, k, item)
4281 int l = 0;
4282 bool found = false;
4284 if (!item->value)
4285 continue;
4287 while ((unsigned) l < jfunc->agg.items->length ())
4289 struct ipa_agg_jf_item *ti;
4290 ti = &(*jfunc->agg.items)[l];
4291 if (ti->offset > item->offset)
4292 break;
4293 if (ti->offset == item->offset)
4295 gcc_checking_assert (ti->value);
4296 if (values_equal_for_ipcp_p (item->value,
4297 ti->value))
4298 found = true;
4299 break;
4301 l++;
4303 if (!found)
4304 item->value = NULL;
4307 else
4309 inter.release ();
4310 return vec<ipa_agg_jf_item>();
4312 return inter;
4315 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4316 from all of them. */
4318 static struct ipa_agg_replacement_value *
4319 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4320 vec<cgraph_edge *> callers)
4322 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4323 struct ipa_agg_replacement_value *res;
4324 struct ipa_agg_replacement_value **tail = &res;
4325 struct cgraph_edge *cs;
4326 int i, j, count = ipa_get_param_count (dest_info);
4328 FOR_EACH_VEC_ELT (callers, j, cs)
4330 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4331 if (c < count)
4332 count = c;
4335 for (i = 0; i < count; i++)
4337 struct cgraph_edge *cs;
4338 vec<ipa_agg_jf_item> inter = vNULL;
4339 struct ipa_agg_jf_item *item;
4340 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4341 int j;
4343 /* Among other things, the following check should deal with all by_ref
4344 mismatches. */
4345 if (plats->aggs_bottom)
4346 continue;
4348 FOR_EACH_VEC_ELT (callers, j, cs)
4350 struct ipa_jump_func *jfunc
4351 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
4352 if (self_recursive_pass_through_p (cs, jfunc, i)
4353 && (!plats->aggs_by_ref
4354 || ipa_get_jf_pass_through_agg_preserved (jfunc)))
4355 continue;
4356 inter = intersect_aggregates_with_edge (cs, i, inter);
4358 if (!inter.exists ())
4359 goto next_param;
4362 FOR_EACH_VEC_ELT (inter, j, item)
4364 struct ipa_agg_replacement_value *v;
4366 if (!item->value)
4367 continue;
4369 v = ggc_alloc<ipa_agg_replacement_value> ();
4370 v->index = i;
4371 v->offset = item->offset;
4372 v->value = item->value;
4373 v->by_ref = plats->aggs_by_ref;
4374 *tail = v;
4375 tail = &v->next;
4378 next_param:
4379 if (inter.exists ())
4380 inter.release ();
4382 *tail = NULL;
4383 return res;
4386 /* Determine whether CS also brings all scalar values that the NODE is
4387 specialized for. */
4389 static bool
4390 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4391 struct cgraph_node *node)
4393 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4394 int count = ipa_get_param_count (dest_info);
4395 struct ipa_node_params *caller_info;
4396 struct ipa_edge_args *args;
4397 int i;
4399 caller_info = IPA_NODE_REF (cs->caller);
4400 args = IPA_EDGE_REF (cs);
4401 for (i = 0; i < count; i++)
4403 struct ipa_jump_func *jump_func;
4404 tree val, t;
4406 val = dest_info->known_csts[i];
4407 if (!val)
4408 continue;
4410 if (i >= ipa_get_cs_argument_count (args))
4411 return false;
4412 jump_func = ipa_get_ith_jump_func (args, i);
4413 t = ipa_value_from_jfunc (caller_info, jump_func,
4414 ipa_get_type (dest_info, i));
4415 if (!t || !values_equal_for_ipcp_p (val, t))
4416 return false;
4418 return true;
4421 /* Determine whether CS also brings all aggregate values that NODE is
4422 specialized for. */
4423 static bool
4424 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4425 struct cgraph_node *node)
4427 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4428 struct ipa_node_params *orig_node_info;
4429 struct ipa_agg_replacement_value *aggval;
4430 int i, ec, count;
4432 aggval = ipa_get_agg_replacements_for_node (node);
4433 if (!aggval)
4434 return true;
4436 count = ipa_get_param_count (IPA_NODE_REF (node));
4437 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4438 if (ec < count)
4439 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4440 if (aggval->index >= ec)
4441 return false;
4443 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4444 if (orig_caller_info->ipcp_orig_node)
4445 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4447 for (i = 0; i < count; i++)
4449 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4450 struct ipcp_param_lattices *plats;
4451 bool interesting = false;
4452 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4453 if (aggval->index == i)
4455 interesting = true;
4456 break;
4458 if (!interesting)
4459 continue;
4461 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4462 if (plats->aggs_bottom)
4463 return false;
4465 values = intersect_aggregates_with_edge (cs, i, values);
4466 if (!values.exists ())
4467 return false;
4469 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4470 if (aggval->index == i)
4472 struct ipa_agg_jf_item *item;
4473 int j;
4474 bool found = false;
4475 FOR_EACH_VEC_ELT (values, j, item)
4476 if (item->value
4477 && item->offset == av->offset
4478 && values_equal_for_ipcp_p (item->value, av->value))
4480 found = true;
4481 break;
4483 if (!found)
4485 values.release ();
4486 return false;
4490 return true;
4493 /* Given an original NODE and a VAL for which we have already created a
4494 specialized clone, look whether there are incoming edges that still lead
4495 into the old node but now also bring the requested value and also conform to
4496 all other criteria such that they can be redirected the special node.
4497 This function can therefore redirect the final edge in a SCC. */
4499 template <typename valtype>
4500 static void
4501 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4503 ipcp_value_source<valtype> *src;
4504 profile_count redirected_sum = profile_count::zero ();
4506 for (src = val->sources; src; src = src->next)
4508 struct cgraph_edge *cs = src->cs;
4509 while (cs)
4511 if (cgraph_edge_brings_value_p (cs, src, node, val)
4512 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4513 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4515 if (dump_file)
4516 fprintf (dump_file, " - adding an extra caller %s of %s\n",
4517 cs->caller->dump_name (),
4518 val->spec_node->dump_name ());
4520 cs->redirect_callee_duplicating_thunks (val->spec_node);
4521 val->spec_node->expand_all_artificial_thunks ();
4522 if (cs->count.ipa ().initialized_p ())
4523 redirected_sum = redirected_sum + cs->count.ipa ();
4525 cs = get_next_cgraph_edge_clone (cs);
4529 if (redirected_sum.nonzero_p ())
4530 update_specialized_profile (val->spec_node, node, redirected_sum);
4533 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4535 static bool
4536 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4538 ipa_polymorphic_call_context *ctx;
4539 int i;
4541 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4542 if (!ctx->useless_p ())
4543 return true;
4544 return false;
4547 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4549 static vec<ipa_polymorphic_call_context>
4550 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4552 if (known_contexts_useful_p (known_contexts))
4553 return known_contexts.copy ();
4554 else
4555 return vNULL;
4558 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4559 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4561 static void
4562 modify_known_vectors_with_val (vec<tree> *known_csts,
4563 vec<ipa_polymorphic_call_context> *known_contexts,
4564 ipcp_value<tree> *val,
4565 int index)
4567 *known_csts = known_csts->copy ();
4568 *known_contexts = copy_useful_known_contexts (*known_contexts);
4569 (*known_csts)[index] = val->value;
4572 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4573 copy according to VAL and INDEX. */
4575 static void
4576 modify_known_vectors_with_val (vec<tree> *known_csts,
4577 vec<ipa_polymorphic_call_context> *known_contexts,
4578 ipcp_value<ipa_polymorphic_call_context> *val,
4579 int index)
4581 *known_csts = known_csts->copy ();
4582 *known_contexts = known_contexts->copy ();
4583 (*known_contexts)[index] = val->value;
4586 /* Return true if OFFSET indicates this was not an aggregate value or there is
4587 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4588 AGGVALS list. */
4590 DEBUG_FUNCTION bool
4591 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4592 int index, HOST_WIDE_INT offset, tree value)
4594 if (offset == -1)
4595 return true;
4597 while (aggvals)
4599 if (aggvals->index == index
4600 && aggvals->offset == offset
4601 && values_equal_for_ipcp_p (aggvals->value, value))
4602 return true;
4603 aggvals = aggvals->next;
4605 return false;
4608 /* Return true if offset is minus one because source of a polymorphic context
4609 cannot be an aggregate value. */
4611 DEBUG_FUNCTION bool
4612 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4613 int , HOST_WIDE_INT offset,
4614 ipa_polymorphic_call_context)
4616 return offset == -1;
4619 /* Decide whether to create a special version of NODE for value VAL of parameter
4620 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4621 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4622 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4624 template <typename valtype>
4625 static bool
4626 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4627 ipcp_value<valtype> *val, vec<tree> known_csts,
4628 vec<ipa_polymorphic_call_context> known_contexts)
4630 struct ipa_agg_replacement_value *aggvals;
4631 int freq_sum, caller_count;
4632 profile_count count_sum;
4633 vec<cgraph_edge *> callers;
4635 if (val->spec_node)
4637 perhaps_add_new_callers (node, val);
4638 return false;
4640 else if (val->local_size_cost + overall_size > max_new_size)
4642 if (dump_file && (dump_flags & TDF_DETAILS))
4643 fprintf (dump_file, " Ignoring candidate value because "
4644 "max_new_size would be reached with %li.\n",
4645 val->local_size_cost + overall_size);
4646 return false;
4648 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4649 &caller_count))
4650 return false;
4652 if (dump_file && (dump_flags & TDF_DETAILS))
4654 fprintf (dump_file, " - considering value ");
4655 print_ipcp_constant_value (dump_file, val->value);
4656 fprintf (dump_file, " for ");
4657 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4658 if (offset != -1)
4659 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4660 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4663 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4664 freq_sum, count_sum,
4665 val->local_size_cost)
4666 && !good_cloning_opportunity_p (node,
4667 val->local_time_benefit
4668 + val->prop_time_benefit,
4669 freq_sum, count_sum,
4670 val->local_size_cost
4671 + val->prop_size_cost))
4672 return false;
4674 if (dump_file)
4675 fprintf (dump_file, " Creating a specialized node of %s.\n",
4676 node->dump_name ());
4678 callers = gather_edges_for_value (val, node, caller_count);
4679 if (offset == -1)
4680 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4681 else
4683 known_csts = known_csts.copy ();
4684 known_contexts = copy_useful_known_contexts (known_contexts);
4686 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4687 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4688 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4689 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4690 offset, val->value));
4691 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4692 aggvals, callers);
4693 overall_size += val->local_size_cost;
4695 /* TODO: If for some lattice there is only one other known value
4696 left, make a special node for it too. */
4698 return true;
4701 /* Decide whether and what specialized clones of NODE should be created. */
4703 static bool
4704 decide_whether_version_node (struct cgraph_node *node)
4706 struct ipa_node_params *info = IPA_NODE_REF (node);
4707 int i, count = ipa_get_param_count (info);
4708 vec<tree> known_csts;
4709 vec<ipa_polymorphic_call_context> known_contexts;
4710 vec<ipa_agg_jump_function> known_aggs = vNULL;
4711 bool ret = false;
4713 if (count == 0)
4714 return false;
4716 if (dump_file && (dump_flags & TDF_DETAILS))
4717 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
4718 node->dump_name ());
4720 gather_context_independent_values (info, &known_csts, &known_contexts,
4721 info->do_clone_for_all_contexts ? &known_aggs
4722 : NULL, NULL);
4724 for (i = 0; i < count;i++)
4726 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4727 ipcp_lattice<tree> *lat = &plats->itself;
4728 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4730 if (!lat->bottom
4731 && !known_csts[i])
4733 ipcp_value<tree> *val;
4734 for (val = lat->values; val; val = val->next)
4735 ret |= decide_about_value (node, i, -1, val, known_csts,
4736 known_contexts);
4739 if (!plats->aggs_bottom)
4741 struct ipcp_agg_lattice *aglat;
4742 ipcp_value<tree> *val;
4743 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4744 if (!aglat->bottom && aglat->values
4745 /* If the following is false, the one value is in
4746 known_aggs. */
4747 && (plats->aggs_contain_variable
4748 || !aglat->is_single_const ()))
4749 for (val = aglat->values; val; val = val->next)
4750 ret |= decide_about_value (node, i, aglat->offset, val,
4751 known_csts, known_contexts);
4754 if (!ctxlat->bottom
4755 && known_contexts[i].useless_p ())
4757 ipcp_value<ipa_polymorphic_call_context> *val;
4758 for (val = ctxlat->values; val; val = val->next)
4759 ret |= decide_about_value (node, i, -1, val, known_csts,
4760 known_contexts);
4763 info = IPA_NODE_REF (node);
4766 if (info->do_clone_for_all_contexts)
4768 struct cgraph_node *clone;
4769 vec<cgraph_edge *> callers;
4771 if (dump_file)
4772 fprintf (dump_file, " - Creating a specialized node of %s "
4773 "for all known contexts.\n", node->dump_name ());
4775 callers = node->collect_callers ();
4776 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4777 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4778 ipa_agg_replacement_value *aggvals
4779 = find_aggregate_values_for_callers_subset (node, callers);
4781 if (!known_contexts_useful_p (known_contexts))
4783 known_contexts.release ();
4784 known_contexts = vNULL;
4786 clone = create_specialized_node (node, known_csts, known_contexts,
4787 aggvals, callers);
4788 info = IPA_NODE_REF (node);
4789 info->do_clone_for_all_contexts = false;
4790 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4791 for (i = 0; i < count; i++)
4792 vec_free (known_aggs[i].items);
4793 known_aggs.release ();
4794 ret = true;
4796 else
4798 known_csts.release ();
4799 known_contexts.release ();
4802 return ret;
4805 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4807 static void
4808 spread_undeadness (struct cgraph_node *node)
4810 struct cgraph_edge *cs;
4812 for (cs = node->callees; cs; cs = cs->next_callee)
4813 if (ipa_edge_within_scc (cs))
4815 struct cgraph_node *callee;
4816 struct ipa_node_params *info;
4818 callee = cs->callee->function_symbol (NULL);
4819 info = IPA_NODE_REF (callee);
4821 if (info->node_dead)
4823 info->node_dead = 0;
4824 spread_undeadness (callee);
4829 /* Return true if NODE has a caller from outside of its SCC that is not
4830 dead. Worker callback for cgraph_for_node_and_aliases. */
4832 static bool
4833 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4834 void *data ATTRIBUTE_UNUSED)
4836 struct cgraph_edge *cs;
4838 for (cs = node->callers; cs; cs = cs->next_caller)
4839 if (cs->caller->thunk.thunk_p
4840 && cs->caller->call_for_symbol_thunks_and_aliases
4841 (has_undead_caller_from_outside_scc_p, NULL, true))
4842 return true;
4843 else if (!ipa_edge_within_scc (cs)
4844 && !IPA_NODE_REF (cs->caller)->node_dead)
4845 return true;
4846 return false;
4850 /* Identify nodes within the same SCC as NODE which are no longer needed
4851 because of new clones and will be removed as unreachable. */
4853 static void
4854 identify_dead_nodes (struct cgraph_node *node)
4856 struct cgraph_node *v;
4857 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4858 if (v->local.local
4859 && !v->call_for_symbol_thunks_and_aliases
4860 (has_undead_caller_from_outside_scc_p, NULL, true))
4861 IPA_NODE_REF (v)->node_dead = 1;
4863 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4864 if (!IPA_NODE_REF (v)->node_dead)
4865 spread_undeadness (v);
4867 if (dump_file && (dump_flags & TDF_DETAILS))
4869 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4870 if (IPA_NODE_REF (v)->node_dead)
4871 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
4875 /* The decision stage. Iterate over the topological order of call graph nodes
4876 TOPO and make specialized clones if deemed beneficial. */
4878 static void
4879 ipcp_decision_stage (struct ipa_topo_info *topo)
4881 int i;
4883 if (dump_file)
4884 fprintf (dump_file, "\nIPA decision stage:\n\n");
4886 for (i = topo->nnodes - 1; i >= 0; i--)
4888 struct cgraph_node *node = topo->order[i];
4889 bool change = false, iterate = true;
4891 while (iterate)
4893 struct cgraph_node *v;
4894 iterate = false;
4895 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4896 if (v->has_gimple_body_p ()
4897 && ipcp_versionable_function_p (v))
4898 iterate |= decide_whether_version_node (v);
4900 change |= iterate;
4902 if (change)
4903 identify_dead_nodes (node);
4907 /* Look up all the bits information that we have discovered and copy it over
4908 to the transformation summary. */
4910 static void
4911 ipcp_store_bits_results (void)
4913 cgraph_node *node;
4915 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4917 ipa_node_params *info = IPA_NODE_REF (node);
4918 bool dumped_sth = false;
4919 bool found_useful_result = false;
4921 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4923 if (dump_file)
4924 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4925 "; -fipa-bit-cp: disabled.\n",
4926 node->name ());
4927 continue;
4930 if (info->ipcp_orig_node)
4931 info = IPA_NODE_REF (info->ipcp_orig_node);
4933 unsigned count = ipa_get_param_count (info);
4934 for (unsigned i = 0; i < count; i++)
4936 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4937 if (plats->bits_lattice.constant_p ())
4939 found_useful_result = true;
4940 break;
4944 if (!found_useful_result)
4945 continue;
4947 ipcp_transformation_initialize ();
4948 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
4949 vec_safe_reserve_exact (ts->bits, count);
4951 for (unsigned i = 0; i < count; i++)
4953 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4954 ipa_bits *jfbits;
4956 if (plats->bits_lattice.constant_p ())
4957 jfbits
4958 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
4959 plats->bits_lattice.get_mask ());
4960 else
4961 jfbits = NULL;
4963 ts->bits->quick_push (jfbits);
4964 if (!dump_file || !jfbits)
4965 continue;
4966 if (!dumped_sth)
4968 fprintf (dump_file, "Propagated bits info for function %s:\n",
4969 node->dump_name ());
4970 dumped_sth = true;
4972 fprintf (dump_file, " param %i: value = ", i);
4973 print_hex (jfbits->value, dump_file);
4974 fprintf (dump_file, ", mask = ");
4975 print_hex (jfbits->mask, dump_file);
4976 fprintf (dump_file, "\n");
4981 /* Look up all VR information that we have discovered and copy it over
4982 to the transformation summary. */
4984 static void
4985 ipcp_store_vr_results (void)
4987 cgraph_node *node;
4989 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4991 ipa_node_params *info = IPA_NODE_REF (node);
4992 bool found_useful_result = false;
4994 if (!opt_for_fn (node->decl, flag_ipa_vrp))
4996 if (dump_file)
4997 fprintf (dump_file, "Not considering %s for VR discovery "
4998 "and propagate; -fipa-ipa-vrp: disabled.\n",
4999 node->name ());
5000 continue;
5003 if (info->ipcp_orig_node)
5004 info = IPA_NODE_REF (info->ipcp_orig_node);
5006 unsigned count = ipa_get_param_count (info);
5007 for (unsigned i = 0; i < count; i++)
5009 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5010 if (!plats->m_value_range.bottom_p ()
5011 && !plats->m_value_range.top_p ())
5013 found_useful_result = true;
5014 break;
5017 if (!found_useful_result)
5018 continue;
5020 ipcp_transformation_initialize ();
5021 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5022 vec_safe_reserve_exact (ts->m_vr, count);
5024 for (unsigned i = 0; i < count; i++)
5026 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5027 ipa_vr vr;
5029 if (!plats->m_value_range.bottom_p ()
5030 && !plats->m_value_range.top_p ())
5032 vr.known = true;
5033 vr.type = plats->m_value_range.m_vr.kind ();
5034 vr.min = wi::to_wide (plats->m_value_range.m_vr.min ());
5035 vr.max = wi::to_wide (plats->m_value_range.m_vr.max ());
5037 else
5039 vr.known = false;
5040 vr.type = VR_VARYING;
5041 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
5043 ts->m_vr->quick_push (vr);
5048 /* The IPCP driver. */
5050 static unsigned int
5051 ipcp_driver (void)
5053 struct ipa_topo_info topo;
5055 if (edge_clone_summaries == NULL)
5056 edge_clone_summaries = new edge_clone_summary_t (symtab);
5058 ipa_check_create_node_params ();
5059 ipa_check_create_edge_args ();
5060 clone_num_suffixes = new hash_map<const char *, unsigned>;
5062 if (dump_file)
5064 fprintf (dump_file, "\nIPA structures before propagation:\n");
5065 if (dump_flags & TDF_DETAILS)
5066 ipa_print_all_params (dump_file);
5067 ipa_print_all_jump_functions (dump_file);
5070 /* Topological sort. */
5071 build_toporder_info (&topo);
5072 /* Do the interprocedural propagation. */
5073 ipcp_propagate_stage (&topo);
5074 /* Decide what constant propagation and cloning should be performed. */
5075 ipcp_decision_stage (&topo);
5076 /* Store results of bits propagation. */
5077 ipcp_store_bits_results ();
5078 /* Store results of value range propagation. */
5079 ipcp_store_vr_results ();
5081 /* Free all IPCP structures. */
5082 delete clone_num_suffixes;
5083 free_toporder_info (&topo);
5084 delete edge_clone_summaries;
5085 edge_clone_summaries = NULL;
5086 ipa_free_all_structures_after_ipa_cp ();
5087 if (dump_file)
5088 fprintf (dump_file, "\nIPA constant propagation end\n");
5089 return 0;
5092 /* Initialization and computation of IPCP data structures. This is the initial
5093 intraprocedural analysis of functions, which gathers information to be
5094 propagated later on. */
5096 static void
5097 ipcp_generate_summary (void)
5099 struct cgraph_node *node;
5101 if (dump_file)
5102 fprintf (dump_file, "\nIPA constant propagation start:\n");
5103 ipa_register_cgraph_hooks ();
5105 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5106 ipa_analyze_node (node);
5109 /* Write ipcp summary for nodes in SET. */
5111 static void
5112 ipcp_write_summary (void)
5114 ipa_prop_write_jump_functions ();
5117 /* Read ipcp summary. */
5119 static void
5120 ipcp_read_summary (void)
5122 ipa_prop_read_jump_functions ();
5125 namespace {
5127 const pass_data pass_data_ipa_cp =
5129 IPA_PASS, /* type */
5130 "cp", /* name */
5131 OPTGROUP_NONE, /* optinfo_flags */
5132 TV_IPA_CONSTANT_PROP, /* tv_id */
5133 0, /* properties_required */
5134 0, /* properties_provided */
5135 0, /* properties_destroyed */
5136 0, /* todo_flags_start */
5137 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5140 class pass_ipa_cp : public ipa_opt_pass_d
5142 public:
5143 pass_ipa_cp (gcc::context *ctxt)
5144 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5145 ipcp_generate_summary, /* generate_summary */
5146 ipcp_write_summary, /* write_summary */
5147 ipcp_read_summary, /* read_summary */
5148 ipcp_write_transformation_summaries, /*
5149 write_optimization_summary */
5150 ipcp_read_transformation_summaries, /*
5151 read_optimization_summary */
5152 NULL, /* stmt_fixup */
5153 0, /* function_transform_todo_flags_start */
5154 ipcp_transform_function, /* function_transform */
5155 NULL) /* variable_transform */
5158 /* opt_pass methods: */
5159 virtual bool gate (function *)
5161 /* FIXME: We should remove the optimize check after we ensure we never run
5162 IPA passes when not optimizing. */
5163 return (flag_ipa_cp && optimize) || in_lto_p;
5166 virtual unsigned int execute (function *) { return ipcp_driver (); }
5168 }; // class pass_ipa_cp
5170 } // anon namespace
5172 ipa_opt_pass_d *
5173 make_pass_ipa_cp (gcc::context *ctxt)
5175 return new pass_ipa_cp (ctxt);
5178 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5179 within the same process. For use by toplev::finalize. */
5181 void
5182 ipa_cp_c_finalize (void)
5184 max_count = profile_count::uninitialized ();
5185 overall_size = 0;
5186 max_new_size = 0;