aix: Support libsupc++ as a FAT library
[official-gcc.git] / gcc / ipa-cp.c
blobe4910a04ffaa03776cbaed17dd7dcbb34ba4b2e1
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2020 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 "ipa-fnsummary.h"
122 #include "ipa-utils.h"
123 #include "tree-ssa-ccp.h"
124 #include "stringpool.h"
125 #include "attribs.h"
126 #include "dbgcnt.h"
128 template <typename valtype> class ipcp_value;
130 /* Describes a particular source for an IPA-CP value. */
132 template <typename valtype>
133 struct 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 struct 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 ipcp_value<valtype> **val_p = NULL,
234 bool unlimited = false);
235 void print (FILE * f, bool dump_sources, bool dump_benefits);
238 /* Lattice of tree values with an offset to describe a part of an
239 aggregate. */
241 struct ipcp_agg_lattice : public ipcp_lattice<tree>
243 public:
244 /* Offset that is being described by this lattice. */
245 HOST_WIDE_INT offset;
246 /* Size so that we don't have to re-compute it every time we traverse the
247 list. Must correspond to TYPE_SIZE of all lat values. */
248 HOST_WIDE_INT size;
249 /* Next element of the linked list. */
250 struct ipcp_agg_lattice *next;
253 /* Lattice of known bits, only capable of holding one value.
254 Bitwise constant propagation propagates which bits of a
255 value are constant.
256 For eg:
257 int f(int x)
259 return some_op (x);
262 int f1(int y)
264 if (cond)
265 return f (y & 0xff);
266 else
267 return f (y & 0xf);
270 In the above case, the param 'x' will always have all
271 the bits (except the bits in lsb) set to 0.
272 Hence the mask of 'x' would be 0xff. The mask
273 reflects that the bits in lsb are unknown.
274 The actual propagated value is given by m_value & ~m_mask. */
276 class ipcp_bits_lattice
278 public:
279 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; }
280 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; }
281 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; }
282 bool set_to_bottom ();
283 bool set_to_constant (widest_int, widest_int);
285 widest_int get_value () { return m_value; }
286 widest_int get_mask () { return m_mask; }
288 bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
289 enum tree_code, tree);
291 bool meet_with (widest_int, widest_int, unsigned);
293 void print (FILE *);
295 private:
296 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
298 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
299 If a bit in mask is set to 0, then the corresponding bit in
300 value is known to be constant. */
301 widest_int m_value, m_mask;
303 bool meet_with_1 (widest_int, widest_int, unsigned);
304 void get_value_and_mask (tree, widest_int *, widest_int *);
307 /* Lattice of value ranges. */
309 class ipcp_vr_lattice
311 public:
312 value_range m_vr;
314 inline bool bottom_p () const;
315 inline bool top_p () const;
316 inline bool set_to_bottom ();
317 bool meet_with (const value_range *p_vr);
318 bool meet_with (const ipcp_vr_lattice &other);
319 void init () { gcc_assert (m_vr.undefined_p ()); }
320 void print (FILE * f);
322 private:
323 bool meet_with_1 (const value_range *other_vr);
326 /* Structure containing lattices for a parameter itself and for pieces of
327 aggregates that are passed in the parameter or by a reference in a parameter
328 plus some other useful flags. */
330 class ipcp_param_lattices
332 public:
333 /* Lattice describing the value of the parameter itself. */
334 ipcp_lattice<tree> itself;
335 /* Lattice describing the polymorphic contexts of a parameter. */
336 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
337 /* Lattices describing aggregate parts. */
338 ipcp_agg_lattice *aggs;
339 /* Lattice describing known bits. */
340 ipcp_bits_lattice bits_lattice;
341 /* Lattice describing value range. */
342 ipcp_vr_lattice m_value_range;
343 /* Number of aggregate lattices */
344 int aggs_count;
345 /* True if aggregate data were passed by reference (as opposed to by
346 value). */
347 bool aggs_by_ref;
348 /* All aggregate lattices contain a variable component (in addition to
349 values). */
350 bool aggs_contain_variable;
351 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
352 for any propagation). */
353 bool aggs_bottom;
355 /* There is a virtual call based on this parameter. */
356 bool virt_call;
359 /* Allocation pools for values and their sources in ipa-cp. */
361 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
362 ("IPA-CP constant values");
364 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
365 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
367 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
368 ("IPA-CP value sources");
370 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
371 ("IPA_CP aggregate lattices");
373 /* Maximal count found in program. */
375 static profile_count max_count;
377 /* Original overall size of the program. */
379 static long overall_size, orig_overall_size;
381 /* Node name to unique clone suffix number map. */
382 static hash_map<const char *, unsigned> *clone_num_suffixes;
384 /* Return the param lattices structure corresponding to the Ith formal
385 parameter of the function described by INFO. */
386 static inline class ipcp_param_lattices *
387 ipa_get_parm_lattices (class ipa_node_params *info, int i)
389 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
390 gcc_checking_assert (!info->ipcp_orig_node);
391 gcc_checking_assert (info->lattices);
392 return &(info->lattices[i]);
395 /* Return the lattice corresponding to the scalar value of the Ith formal
396 parameter of the function described by INFO. */
397 static inline ipcp_lattice<tree> *
398 ipa_get_scalar_lat (class ipa_node_params *info, int i)
400 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
401 return &plats->itself;
404 /* Return the lattice corresponding to the scalar value of the Ith formal
405 parameter of the function described by INFO. */
406 static inline ipcp_lattice<ipa_polymorphic_call_context> *
407 ipa_get_poly_ctx_lat (class ipa_node_params *info, int i)
409 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
410 return &plats->ctxlat;
413 /* Return whether LAT is a lattice with a single constant and without an
414 undefined value. */
416 template <typename valtype>
417 inline bool
418 ipcp_lattice<valtype>::is_single_const ()
420 if (bottom || contains_variable || values_count != 1)
421 return false;
422 else
423 return true;
426 /* Print V which is extracted from a value in a lattice to F. */
428 static void
429 print_ipcp_constant_value (FILE * f, tree v)
431 if (TREE_CODE (v) == ADDR_EXPR
432 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
434 fprintf (f, "& ");
435 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)));
437 else
438 print_generic_expr (f, v);
441 /* Print V which is extracted from a value in a lattice to F. */
443 static void
444 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
446 v.dump(f, false);
449 /* Print a lattice LAT to F. */
451 template <typename valtype>
452 void
453 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
455 ipcp_value<valtype> *val;
456 bool prev = false;
458 if (bottom)
460 fprintf (f, "BOTTOM\n");
461 return;
464 if (!values_count && !contains_variable)
466 fprintf (f, "TOP\n");
467 return;
470 if (contains_variable)
472 fprintf (f, "VARIABLE");
473 prev = true;
474 if (dump_benefits)
475 fprintf (f, "\n");
478 for (val = values; val; val = val->next)
480 if (dump_benefits && prev)
481 fprintf (f, " ");
482 else if (!dump_benefits && prev)
483 fprintf (f, ", ");
484 else
485 prev = true;
487 print_ipcp_constant_value (f, val->value);
489 if (dump_sources)
491 ipcp_value_source<valtype> *s;
493 fprintf (f, " [from:");
494 for (s = val->sources; s; s = s->next)
495 fprintf (f, " %i(%f)", s->cs->caller->order,
496 s->cs->sreal_frequency ().to_double ());
497 fprintf (f, "]");
500 if (dump_benefits)
501 fprintf (f, " [loc_time: %i, loc_size: %i, "
502 "prop_time: %i, prop_size: %i]\n",
503 val->local_time_benefit, val->local_size_cost,
504 val->prop_time_benefit, val->prop_size_cost);
506 if (!dump_benefits)
507 fprintf (f, "\n");
510 void
511 ipcp_bits_lattice::print (FILE *f)
513 if (top_p ())
514 fprintf (f, " Bits unknown (TOP)\n");
515 else if (bottom_p ())
516 fprintf (f, " Bits unusable (BOTTOM)\n");
517 else
519 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
520 fprintf (f, ", mask = "); print_hex (get_mask (), f);
521 fprintf (f, "\n");
525 /* Print value range lattice to F. */
527 void
528 ipcp_vr_lattice::print (FILE * f)
530 dump_value_range (f, &m_vr);
533 /* Print all ipcp_lattices of all functions to F. */
535 static void
536 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
538 struct cgraph_node *node;
539 int i, count;
541 fprintf (f, "\nLattices:\n");
542 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
544 class ipa_node_params *info;
546 info = IPA_NODE_REF (node);
547 /* Skip unoptimized functions and constprop clones since we don't make
548 lattices for them. */
549 if (!info || info->ipcp_orig_node)
550 continue;
551 fprintf (f, " Node: %s:\n", node->dump_name ());
552 count = ipa_get_param_count (info);
553 for (i = 0; i < count; i++)
555 struct ipcp_agg_lattice *aglat;
556 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
557 fprintf (f, " param [%d]: ", i);
558 plats->itself.print (f, dump_sources, dump_benefits);
559 fprintf (f, " ctxs: ");
560 plats->ctxlat.print (f, dump_sources, dump_benefits);
561 plats->bits_lattice.print (f);
562 fprintf (f, " ");
563 plats->m_value_range.print (f);
564 fprintf (f, "\n");
565 if (plats->virt_call)
566 fprintf (f, " virt_call flag set\n");
568 if (plats->aggs_bottom)
570 fprintf (f, " AGGS BOTTOM\n");
571 continue;
573 if (plats->aggs_contain_variable)
574 fprintf (f, " AGGS VARIABLE\n");
575 for (aglat = plats->aggs; aglat; aglat = aglat->next)
577 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
578 plats->aggs_by_ref ? "ref " : "", aglat->offset);
579 aglat->print (f, dump_sources, dump_benefits);
585 /* Determine whether it is at all technically possible to create clones of NODE
586 and store this information in the ipa_node_params structure associated
587 with NODE. */
589 static void
590 determine_versionability (struct cgraph_node *node,
591 class ipa_node_params *info)
593 const char *reason = NULL;
595 /* There are a number of generic reasons functions cannot be versioned. We
596 also cannot remove parameters if there are type attributes such as fnspec
597 present. */
598 if (node->alias || node->thunk.thunk_p)
599 reason = "alias or thunk";
600 else if (!node->versionable)
601 reason = "not a tree_versionable_function";
602 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
603 reason = "insufficient body availability";
604 else if (!opt_for_fn (node->decl, optimize)
605 || !opt_for_fn (node->decl, flag_ipa_cp))
606 reason = "non-optimized function";
607 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
609 /* Ideally we should clone the SIMD clones themselves and create
610 vector copies of them, so IPA-cp and SIMD clones can happily
611 coexist, but that may not be worth the effort. */
612 reason = "function has SIMD clones";
614 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
616 /* Ideally we should clone the target clones themselves and create
617 copies of them, so IPA-cp and target clones can happily
618 coexist, but that may not be worth the effort. */
619 reason = "function target_clones attribute";
621 /* Don't clone decls local to a comdat group; it breaks and for C++
622 decloned constructors, inlining is always better anyway. */
623 else if (node->comdat_local_p ())
624 reason = "comdat-local function";
625 else if (node->calls_comdat_local)
627 /* TODO: call is versionable if we make sure that all
628 callers are inside of a comdat group. */
629 reason = "calls comdat-local function";
632 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
633 work only when inlined. Cloning them may still lead to better code
634 because ipa-cp will not give up on cloning further. If the function is
635 external this however leads to wrong code because we may end up producing
636 offline copy of the function. */
637 if (DECL_EXTERNAL (node->decl))
638 for (cgraph_edge *edge = node->callees; !reason && edge;
639 edge = edge->next_callee)
640 if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL))
642 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
643 reason = "external function which calls va_arg_pack";
644 if (DECL_FUNCTION_CODE (edge->callee->decl)
645 == BUILT_IN_VA_ARG_PACK_LEN)
646 reason = "external function which calls va_arg_pack_len";
649 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
650 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
651 node->dump_name (), reason);
653 info->versionable = (reason == NULL);
656 /* Return true if it is at all technically possible to create clones of a
657 NODE. */
659 static bool
660 ipcp_versionable_function_p (struct cgraph_node *node)
662 return IPA_NODE_REF (node) && IPA_NODE_REF (node)->versionable;
665 /* Structure holding accumulated information about callers of a node. */
667 struct caller_statistics
669 profile_count count_sum;
670 int n_calls, n_hot_calls, freq_sum;
673 /* Initialize fields of STAT to zeroes. */
675 static inline void
676 init_caller_stats (struct caller_statistics *stats)
678 stats->count_sum = profile_count::zero ();
679 stats->n_calls = 0;
680 stats->n_hot_calls = 0;
681 stats->freq_sum = 0;
684 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
685 non-thunk incoming edges to NODE. */
687 static bool
688 gather_caller_stats (struct cgraph_node *node, void *data)
690 struct caller_statistics *stats = (struct caller_statistics *) data;
691 struct cgraph_edge *cs;
693 for (cs = node->callers; cs; cs = cs->next_caller)
694 if (!cs->caller->thunk.thunk_p)
696 if (cs->count.ipa ().initialized_p ())
697 stats->count_sum += cs->count.ipa ();
698 stats->freq_sum += cs->frequency ();
699 stats->n_calls++;
700 if (cs->maybe_hot_p ())
701 stats->n_hot_calls ++;
703 return false;
707 /* Return true if this NODE is viable candidate for cloning. */
709 static bool
710 ipcp_cloning_candidate_p (struct cgraph_node *node)
712 struct caller_statistics stats;
714 gcc_checking_assert (node->has_gimple_body_p ());
716 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
718 if (dump_file)
719 fprintf (dump_file, "Not considering %s for cloning; "
720 "-fipa-cp-clone disabled.\n",
721 node->dump_name ());
722 return false;
725 if (node->optimize_for_size_p ())
727 if (dump_file)
728 fprintf (dump_file, "Not considering %s for cloning; "
729 "optimizing it for size.\n",
730 node->dump_name ());
731 return false;
734 init_caller_stats (&stats);
735 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
737 if (ipa_size_summaries->get (node)->self_size < stats.n_calls)
739 if (dump_file)
740 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
741 node->dump_name ());
742 return true;
745 /* When profile is available and function is hot, propagate into it even if
746 calls seems cold; constant propagation can improve function's speed
747 significantly. */
748 if (max_count > profile_count::zero ())
750 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100))
752 if (dump_file)
753 fprintf (dump_file, "Considering %s for cloning; "
754 "usually called directly.\n",
755 node->dump_name ());
756 return true;
759 if (!stats.n_hot_calls)
761 if (dump_file)
762 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
763 node->dump_name ());
764 return false;
766 if (dump_file)
767 fprintf (dump_file, "Considering %s for cloning.\n",
768 node->dump_name ());
769 return true;
772 template <typename valtype>
773 class value_topo_info
775 public:
776 /* Head of the linked list of topologically sorted values. */
777 ipcp_value<valtype> *values_topo;
778 /* Stack for creating SCCs, represented by a linked list too. */
779 ipcp_value<valtype> *stack;
780 /* Counter driving the algorithm in add_val_to_toposort. */
781 int dfs_counter;
783 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
785 void add_val (ipcp_value<valtype> *cur_val);
786 void propagate_effects ();
789 /* Arrays representing a topological ordering of call graph nodes and a stack
790 of nodes used during constant propagation and also data required to perform
791 topological sort of values and propagation of benefits in the determined
792 order. */
794 class ipa_topo_info
796 public:
797 /* Array with obtained topological order of cgraph nodes. */
798 struct cgraph_node **order;
799 /* Stack of cgraph nodes used during propagation within SCC until all values
800 in the SCC stabilize. */
801 struct cgraph_node **stack;
802 int nnodes, stack_top;
804 value_topo_info<tree> constants;
805 value_topo_info<ipa_polymorphic_call_context> contexts;
807 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
808 constants ()
812 /* Skip edges from and to nodes without ipa_cp enabled.
813 Ignore not available symbols. */
815 static bool
816 ignore_edge_p (cgraph_edge *e)
818 enum availability avail;
819 cgraph_node *ultimate_target
820 = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
822 return (avail <= AVAIL_INTERPOSABLE
823 || !opt_for_fn (ultimate_target->decl, optimize)
824 || !opt_for_fn (ultimate_target->decl, flag_ipa_cp));
827 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
829 static void
830 build_toporder_info (class ipa_topo_info *topo)
832 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
833 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
835 gcc_checking_assert (topo->stack_top == 0);
836 topo->nnodes = ipa_reduced_postorder (topo->order, true,
837 ignore_edge_p);
840 /* Free information about strongly connected components and the arrays in
841 TOPO. */
843 static void
844 free_toporder_info (class ipa_topo_info *topo)
846 ipa_free_postorder_info ();
847 free (topo->order);
848 free (topo->stack);
851 /* Add NODE to the stack in TOPO, unless it is already there. */
853 static inline void
854 push_node_to_stack (class ipa_topo_info *topo, struct cgraph_node *node)
856 class ipa_node_params *info = IPA_NODE_REF (node);
857 if (info->node_enqueued)
858 return;
859 info->node_enqueued = 1;
860 topo->stack[topo->stack_top++] = node;
863 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
864 is empty. */
866 static struct cgraph_node *
867 pop_node_from_stack (class ipa_topo_info *topo)
869 if (topo->stack_top)
871 struct cgraph_node *node;
872 topo->stack_top--;
873 node = topo->stack[topo->stack_top];
874 IPA_NODE_REF (node)->node_enqueued = 0;
875 return node;
877 else
878 return NULL;
881 /* Set lattice LAT to bottom and return true if it previously was not set as
882 such. */
884 template <typename valtype>
885 inline bool
886 ipcp_lattice<valtype>::set_to_bottom ()
888 bool ret = !bottom;
889 bottom = true;
890 return ret;
893 /* Mark lattice as containing an unknown value and return true if it previously
894 was not marked as such. */
896 template <typename valtype>
897 inline bool
898 ipcp_lattice<valtype>::set_contains_variable ()
900 bool ret = !contains_variable;
901 contains_variable = true;
902 return ret;
905 /* Set all aggregate lattices in PLATS to bottom and return true if they were
906 not previously set as such. */
908 static inline bool
909 set_agg_lats_to_bottom (class ipcp_param_lattices *plats)
911 bool ret = !plats->aggs_bottom;
912 plats->aggs_bottom = true;
913 return ret;
916 /* Mark all aggregate lattices in PLATS as containing an unknown value and
917 return true if they were not previously marked as such. */
919 static inline bool
920 set_agg_lats_contain_variable (class ipcp_param_lattices *plats)
922 bool ret = !plats->aggs_contain_variable;
923 plats->aggs_contain_variable = true;
924 return ret;
927 bool
928 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
930 return meet_with_1 (&other.m_vr);
933 /* Meet the current value of the lattice with value range described by VR
934 lattice. */
936 bool
937 ipcp_vr_lattice::meet_with (const value_range *p_vr)
939 return meet_with_1 (p_vr);
942 /* Meet the current value of the lattice with value range described by
943 OTHER_VR lattice. Return TRUE if anything changed. */
945 bool
946 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
948 if (bottom_p ())
949 return false;
951 if (other_vr->varying_p ())
952 return set_to_bottom ();
954 value_range save (m_vr);
955 m_vr.union_ (other_vr);
956 return !m_vr.equal_p (save);
959 /* Return true if value range information in the lattice is yet unknown. */
961 bool
962 ipcp_vr_lattice::top_p () const
964 return m_vr.undefined_p ();
967 /* Return true if value range information in the lattice is known to be
968 unusable. */
970 bool
971 ipcp_vr_lattice::bottom_p () const
973 return m_vr.varying_p ();
976 /* Set value range information in the lattice to bottom. Return true if it
977 previously was in a different state. */
979 bool
980 ipcp_vr_lattice::set_to_bottom ()
982 if (m_vr.varying_p ())
983 return false;
984 /* ?? We create all sorts of VARYING ranges for floats, structures,
985 and other types which we cannot handle as ranges. We should
986 probably avoid handling them throughout the pass, but it's easier
987 to create a sensible VARYING here and let the lattice
988 propagate. */
989 m_vr.set_varying (integer_type_node);
990 return true;
993 /* Set lattice value to bottom, if it already isn't the case. */
995 bool
996 ipcp_bits_lattice::set_to_bottom ()
998 if (bottom_p ())
999 return false;
1000 m_lattice_val = IPA_BITS_VARYING;
1001 m_value = 0;
1002 m_mask = -1;
1003 return true;
1006 /* Set to constant if it isn't already. Only meant to be called
1007 when switching state from TOP. */
1009 bool
1010 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
1012 gcc_assert (top_p ());
1013 m_lattice_val = IPA_BITS_CONSTANT;
1014 m_value = wi::bit_and (wi::bit_not (mask), value);
1015 m_mask = mask;
1016 return true;
1019 /* Convert operand to value, mask form. */
1021 void
1022 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
1024 wide_int get_nonzero_bits (const_tree);
1026 if (TREE_CODE (operand) == INTEGER_CST)
1028 *valuep = wi::to_widest (operand);
1029 *maskp = 0;
1031 else
1033 *valuep = 0;
1034 *maskp = -1;
1038 /* Meet operation, similar to ccp_lattice_meet, we xor values
1039 if this->value, value have different values at same bit positions, we want
1040 to drop that bit to varying. Return true if mask is changed.
1041 This function assumes that the lattice value is in CONSTANT state */
1043 bool
1044 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
1045 unsigned precision)
1047 gcc_assert (constant_p ());
1049 widest_int old_mask = m_mask;
1050 m_mask = (m_mask | mask) | (m_value ^ value);
1051 m_value &= ~m_mask;
1053 if (wi::sext (m_mask, precision) == -1)
1054 return set_to_bottom ();
1056 return m_mask != old_mask;
1059 /* Meet the bits lattice with operand
1060 described by <value, mask, sgn, precision. */
1062 bool
1063 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1064 unsigned precision)
1066 if (bottom_p ())
1067 return false;
1069 if (top_p ())
1071 if (wi::sext (mask, precision) == -1)
1072 return set_to_bottom ();
1073 return set_to_constant (value, mask);
1076 return meet_with_1 (value, mask, precision);
1079 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1080 if code is binary operation or bit_value_unop (other) if code is unary op.
1081 In the case when code is nop_expr, no adjustment is required. */
1083 bool
1084 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1085 signop sgn, enum tree_code code, tree operand)
1087 if (other.bottom_p ())
1088 return set_to_bottom ();
1090 if (bottom_p () || other.top_p ())
1091 return false;
1093 widest_int adjusted_value, adjusted_mask;
1095 if (TREE_CODE_CLASS (code) == tcc_binary)
1097 tree type = TREE_TYPE (operand);
1098 widest_int o_value, o_mask;
1099 get_value_and_mask (operand, &o_value, &o_mask);
1101 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1102 sgn, precision, other.get_value (), other.get_mask (),
1103 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1105 if (wi::sext (adjusted_mask, precision) == -1)
1106 return set_to_bottom ();
1109 else if (TREE_CODE_CLASS (code) == tcc_unary)
1111 bit_value_unop (code, sgn, precision, &adjusted_value,
1112 &adjusted_mask, sgn, precision, other.get_value (),
1113 other.get_mask ());
1115 if (wi::sext (adjusted_mask, precision) == -1)
1116 return set_to_bottom ();
1119 else
1120 return set_to_bottom ();
1122 if (top_p ())
1124 if (wi::sext (adjusted_mask, precision) == -1)
1125 return set_to_bottom ();
1126 return set_to_constant (adjusted_value, adjusted_mask);
1128 else
1129 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1132 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1133 return true is any of them has not been marked as such so far. */
1135 static inline bool
1136 set_all_contains_variable (class ipcp_param_lattices *plats)
1138 bool ret;
1139 ret = plats->itself.set_contains_variable ();
1140 ret |= plats->ctxlat.set_contains_variable ();
1141 ret |= set_agg_lats_contain_variable (plats);
1142 ret |= plats->bits_lattice.set_to_bottom ();
1143 ret |= plats->m_value_range.set_to_bottom ();
1144 return ret;
1147 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1148 points to by the number of callers to NODE. */
1150 static bool
1151 count_callers (cgraph_node *node, void *data)
1153 int *caller_count = (int *) data;
1155 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1156 /* Local thunks can be handled transparently, but if the thunk cannot
1157 be optimized out, count it as a real use. */
1158 if (!cs->caller->thunk.thunk_p || !cs->caller->local)
1159 ++*caller_count;
1160 return false;
1163 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1164 the one caller of some other node. Set the caller's corresponding flag. */
1166 static bool
1167 set_single_call_flag (cgraph_node *node, void *)
1169 cgraph_edge *cs = node->callers;
1170 /* Local thunks can be handled transparently, skip them. */
1171 while (cs && cs->caller->thunk.thunk_p && cs->caller->local)
1172 cs = cs->next_caller;
1173 if (cs && IPA_NODE_REF (cs->caller))
1175 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1176 return true;
1178 return false;
1181 /* Initialize ipcp_lattices. */
1183 static void
1184 initialize_node_lattices (struct cgraph_node *node)
1186 class ipa_node_params *info = IPA_NODE_REF (node);
1187 struct cgraph_edge *ie;
1188 bool disable = false, variable = false;
1189 int i;
1191 gcc_checking_assert (node->has_gimple_body_p ());
1193 if (!ipa_get_param_count (info))
1194 disable = true;
1195 else if (node->local)
1197 int caller_count = 0;
1198 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1199 true);
1200 gcc_checking_assert (caller_count > 0);
1201 if (caller_count == 1)
1202 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1203 NULL, true);
1205 else
1207 /* When cloning is allowed, we can assume that externally visible
1208 functions are not called. We will compensate this by cloning
1209 later. */
1210 if (ipcp_versionable_function_p (node)
1211 && ipcp_cloning_candidate_p (node))
1212 variable = true;
1213 else
1214 disable = true;
1217 if (dump_file && (dump_flags & TDF_DETAILS)
1218 && !node->alias && !node->thunk.thunk_p)
1220 fprintf (dump_file, "Initializing lattices of %s\n",
1221 node->dump_name ());
1222 if (disable || variable)
1223 fprintf (dump_file, " Marking all lattices as %s\n",
1224 disable ? "BOTTOM" : "VARIABLE");
1227 auto_vec<bool, 16> surviving_params;
1228 bool pre_modified = false;
1229 if (!disable && node->clone.param_adjustments)
1231 /* At the moment all IPA optimizations should use the number of
1232 parameters of the prevailing decl as the m_always_copy_start.
1233 Handling any other value would complicate the code below, so for the
1234 time bing let's only assert it is so. */
1235 gcc_assert ((node->clone.param_adjustments->m_always_copy_start
1236 == ipa_get_param_count (info))
1237 || node->clone.param_adjustments->m_always_copy_start < 0);
1239 pre_modified = true;
1240 node->clone.param_adjustments->get_surviving_params (&surviving_params);
1242 if (dump_file && (dump_flags & TDF_DETAILS)
1243 && !node->alias && !node->thunk.thunk_p)
1245 bool first = true;
1246 for (int j = 0; j < ipa_get_param_count (info); j++)
1248 if (j < (int) surviving_params.length ()
1249 && surviving_params[j])
1250 continue;
1251 if (first)
1253 fprintf (dump_file,
1254 " The following parameters are dead on arrival:");
1255 first = false;
1257 fprintf (dump_file, " %u", j);
1259 if (!first)
1260 fprintf (dump_file, "\n");
1264 for (i = 0; i < ipa_get_param_count (info); i++)
1266 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1267 if (disable
1268 || (pre_modified && (surviving_params.length () <= (unsigned) i
1269 || !surviving_params[i])))
1271 plats->itself.set_to_bottom ();
1272 plats->ctxlat.set_to_bottom ();
1273 set_agg_lats_to_bottom (plats);
1274 plats->bits_lattice.set_to_bottom ();
1275 plats->m_value_range.m_vr = value_range ();
1276 plats->m_value_range.set_to_bottom ();
1278 else
1280 plats->m_value_range.init ();
1281 if (variable)
1282 set_all_contains_variable (plats);
1286 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1287 if (ie->indirect_info->polymorphic
1288 && ie->indirect_info->param_index >= 0)
1290 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1291 ipa_get_parm_lattices (info,
1292 ie->indirect_info->param_index)->virt_call = 1;
1296 /* Return the result of a (possibly arithmetic) operation on the constant
1297 value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is
1298 the type of the parameter to which the result is passed. Return
1299 NULL_TREE if that cannot be determined or be considered an
1300 interprocedural invariant. */
1302 static tree
1303 ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand,
1304 tree res_type)
1306 tree res;
1308 if (opcode == NOP_EXPR)
1309 return input;
1310 if (!is_gimple_ip_invariant (input))
1311 return NULL_TREE;
1313 if (!res_type)
1315 if (TREE_CODE_CLASS (opcode) == tcc_comparison)
1316 res_type = boolean_type_node;
1317 else if (expr_type_first_operand_type_p (opcode))
1318 res_type = TREE_TYPE (input);
1319 else
1320 return NULL_TREE;
1323 if (TREE_CODE_CLASS (opcode) == tcc_unary)
1324 res = fold_unary (opcode, res_type, input);
1325 else
1326 res = fold_binary (opcode, res_type, input, operand);
1328 if (res && !is_gimple_ip_invariant (res))
1329 return NULL_TREE;
1331 return res;
1334 /* Return the result of a (possibly arithmetic) pass through jump function
1335 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter
1336 to which the result is passed. Return NULL_TREE if that cannot be
1337 determined or be considered an interprocedural invariant. */
1339 static tree
1340 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input,
1341 tree res_type)
1343 return ipa_get_jf_arith_result (ipa_get_jf_pass_through_operation (jfunc),
1344 input,
1345 ipa_get_jf_pass_through_operand (jfunc),
1346 res_type);
1349 /* Return the result of an ancestor jump function JFUNC on the constant value
1350 INPUT. Return NULL_TREE if that cannot be determined. */
1352 static tree
1353 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1355 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1356 if (TREE_CODE (input) == ADDR_EXPR)
1358 gcc_checking_assert (is_gimple_ip_invariant_address (input));
1359 poly_int64 off = ipa_get_jf_ancestor_offset (jfunc);
1360 if (known_eq (off, 0))
1361 return input;
1362 poly_int64 byte_offset = exact_div (off, BITS_PER_UNIT);
1363 return build1 (ADDR_EXPR, TREE_TYPE (input),
1364 fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (input)), input,
1365 build_int_cst (ptr_type_node, byte_offset)));
1367 else
1368 return NULL_TREE;
1371 /* Determine whether JFUNC evaluates to a single known constant value and if
1372 so, return it. Otherwise return NULL. INFO describes the caller node or
1373 the one it is inlined to, so that pass-through jump functions can be
1374 evaluated. PARM_TYPE is the type of the parameter to which the result is
1375 passed. */
1377 tree
1378 ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc,
1379 tree parm_type)
1381 if (jfunc->type == IPA_JF_CONST)
1382 return ipa_get_jf_constant (jfunc);
1383 else if (jfunc->type == IPA_JF_PASS_THROUGH
1384 || jfunc->type == IPA_JF_ANCESTOR)
1386 tree input;
1387 int idx;
1389 if (jfunc->type == IPA_JF_PASS_THROUGH)
1390 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1391 else
1392 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1394 if (info->ipcp_orig_node)
1395 input = info->known_csts[idx];
1396 else
1398 ipcp_lattice<tree> *lat;
1400 if (!info->lattices
1401 || idx >= ipa_get_param_count (info))
1402 return NULL_TREE;
1403 lat = ipa_get_scalar_lat (info, idx);
1404 if (!lat->is_single_const ())
1405 return NULL_TREE;
1406 input = lat->values->value;
1409 if (!input)
1410 return NULL_TREE;
1412 if (jfunc->type == IPA_JF_PASS_THROUGH)
1413 return ipa_get_jf_pass_through_result (jfunc, input, parm_type);
1414 else
1415 return ipa_get_jf_ancestor_result (jfunc, input);
1417 else
1418 return NULL_TREE;
1421 /* Determine whether JFUNC evaluates to single known polymorphic context, given
1422 that INFO describes the caller node or the one it is inlined to, CS is the
1423 call graph edge corresponding to JFUNC and CSIDX index of the described
1424 parameter. */
1426 ipa_polymorphic_call_context
1427 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1428 ipa_jump_func *jfunc)
1430 ipa_edge_args *args = IPA_EDGE_REF (cs);
1431 ipa_polymorphic_call_context ctx;
1432 ipa_polymorphic_call_context *edge_ctx
1433 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1435 if (edge_ctx && !edge_ctx->useless_p ())
1436 ctx = *edge_ctx;
1438 if (jfunc->type == IPA_JF_PASS_THROUGH
1439 || jfunc->type == IPA_JF_ANCESTOR)
1441 ipa_polymorphic_call_context srcctx;
1442 int srcidx;
1443 bool type_preserved = true;
1444 if (jfunc->type == IPA_JF_PASS_THROUGH)
1446 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1447 return ctx;
1448 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1449 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1451 else
1453 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1454 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1456 if (info->ipcp_orig_node)
1458 if (info->known_contexts.exists ())
1459 srcctx = info->known_contexts[srcidx];
1461 else
1463 if (!info->lattices
1464 || srcidx >= ipa_get_param_count (info))
1465 return ctx;
1466 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1467 lat = ipa_get_poly_ctx_lat (info, srcidx);
1468 if (!lat->is_single_const ())
1469 return ctx;
1470 srcctx = lat->values->value;
1472 if (srcctx.useless_p ())
1473 return ctx;
1474 if (jfunc->type == IPA_JF_ANCESTOR)
1475 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1476 if (!type_preserved)
1477 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1478 srcctx.combine_with (ctx);
1479 return srcctx;
1482 return ctx;
1485 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1486 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1487 the result is a range or an anti-range. */
1489 static bool
1490 ipa_vr_operation_and_type_effects (value_range *dst_vr,
1491 value_range *src_vr,
1492 enum tree_code operation,
1493 tree dst_type, tree src_type)
1495 range_fold_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
1496 if (dst_vr->varying_p () || dst_vr->undefined_p ())
1497 return false;
1498 return true;
1501 /* Determine value_range of JFUNC given that INFO describes the caller node or
1502 the one it is inlined to, CS is the call graph edge corresponding to JFUNC
1503 and PARM_TYPE of the parameter. */
1505 value_range
1506 ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs,
1507 ipa_jump_func *jfunc, tree parm_type)
1509 value_range vr;
1510 return vr;
1511 if (jfunc->m_vr)
1512 ipa_vr_operation_and_type_effects (&vr,
1513 jfunc->m_vr,
1514 NOP_EXPR, parm_type,
1515 jfunc->m_vr->type ());
1516 if (vr.singleton_p ())
1517 return vr;
1518 if (jfunc->type == IPA_JF_PASS_THROUGH)
1520 int idx;
1521 ipcp_transformation *sum
1522 = ipcp_get_transformation_summary (cs->caller->inlined_to
1523 ? cs->caller->inlined_to
1524 : cs->caller);
1525 if (!sum || !sum->m_vr)
1526 return vr;
1528 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1530 if (!(*sum->m_vr)[idx].known)
1531 return vr;
1532 tree vr_type = ipa_get_type (info, idx);
1533 value_range srcvr (wide_int_to_tree (vr_type, (*sum->m_vr)[idx].min),
1534 wide_int_to_tree (vr_type, (*sum->m_vr)[idx].max),
1535 (*sum->m_vr)[idx].type);
1537 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1539 if (TREE_CODE_CLASS (operation) == tcc_unary)
1541 value_range res;
1543 if (ipa_vr_operation_and_type_effects (&res,
1544 &srcvr,
1545 operation, parm_type,
1546 vr_type))
1547 vr.intersect (res);
1549 else
1551 value_range op_res, res;
1552 tree op = ipa_get_jf_pass_through_operand (jfunc);
1553 value_range op_vr (op, op);
1555 range_fold_binary_expr (&op_res, operation, vr_type, &srcvr, &op_vr);
1556 if (ipa_vr_operation_and_type_effects (&res,
1557 &op_res,
1558 NOP_EXPR, parm_type,
1559 vr_type))
1560 vr.intersect (res);
1563 return vr;
1566 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
1567 parameter with the given INDEX. */
1569 static tree
1570 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
1571 int index)
1573 struct ipa_agg_replacement_value *aggval;
1575 aggval = ipa_get_agg_replacements_for_node (node);
1576 while (aggval)
1578 if (aggval->offset == offset
1579 && aggval->index == index)
1580 return aggval->value;
1581 aggval = aggval->next;
1583 return NULL_TREE;
1586 /* Determine whether ITEM, jump function for an aggregate part, evaluates to a
1587 single known constant value and if so, return it. Otherwise return NULL.
1588 NODE and INFO describes the caller node or the one it is inlined to, and
1589 its related info. */
1591 static tree
1592 ipa_agg_value_from_node (class ipa_node_params *info,
1593 struct cgraph_node *node,
1594 struct ipa_agg_jf_item *item)
1596 tree value = NULL_TREE;
1597 int src_idx;
1599 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN)
1600 return NULL_TREE;
1602 if (item->jftype == IPA_JF_CONST)
1603 return item->value.constant;
1605 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
1606 || item->jftype == IPA_JF_LOAD_AGG);
1608 src_idx = item->value.pass_through.formal_id;
1610 if (info->ipcp_orig_node)
1612 if (item->jftype == IPA_JF_PASS_THROUGH)
1613 value = info->known_csts[src_idx];
1614 else
1615 value = get_clone_agg_value (node, item->value.load_agg.offset,
1616 src_idx);
1618 else if (info->lattices)
1620 class ipcp_param_lattices *src_plats
1621 = ipa_get_parm_lattices (info, src_idx);
1623 if (item->jftype == IPA_JF_PASS_THROUGH)
1625 struct ipcp_lattice<tree> *lat = &src_plats->itself;
1627 if (!lat->is_single_const ())
1628 return NULL_TREE;
1630 value = lat->values->value;
1632 else if (src_plats->aggs
1633 && !src_plats->aggs_bottom
1634 && !src_plats->aggs_contain_variable
1635 && src_plats->aggs_by_ref == item->value.load_agg.by_ref)
1637 struct ipcp_agg_lattice *aglat;
1639 for (aglat = src_plats->aggs; aglat; aglat = aglat->next)
1641 if (aglat->offset > item->value.load_agg.offset)
1642 break;
1644 if (aglat->offset == item->value.load_agg.offset)
1646 if (aglat->is_single_const ())
1647 value = aglat->values->value;
1648 break;
1654 if (!value)
1655 return NULL_TREE;
1657 if (item->jftype == IPA_JF_LOAD_AGG)
1659 tree load_type = item->value.load_agg.type;
1660 tree value_type = TREE_TYPE (value);
1662 /* Ensure value type is compatible with load type. */
1663 if (!useless_type_conversion_p (load_type, value_type))
1664 return NULL_TREE;
1667 return ipa_get_jf_arith_result (item->value.pass_through.operation,
1668 value,
1669 item->value.pass_through.operand,
1670 item->type);
1673 /* Determine whether AGG_JFUNC evaluates to a set of known constant value for
1674 an aggregate and if so, return it. Otherwise return an empty set. NODE
1675 and INFO describes the caller node or the one it is inlined to, and its
1676 related info. */
1678 struct ipa_agg_value_set
1679 ipa_agg_value_set_from_jfunc (class ipa_node_params *info, cgraph_node *node,
1680 struct ipa_agg_jump_function *agg_jfunc)
1682 struct ipa_agg_value_set agg;
1683 struct ipa_agg_jf_item *item;
1684 int i;
1686 agg.items = vNULL;
1687 agg.by_ref = agg_jfunc->by_ref;
1689 FOR_EACH_VEC_SAFE_ELT (agg_jfunc->items, i, item)
1691 tree value = ipa_agg_value_from_node (info, node, item);
1693 if (value)
1695 struct ipa_agg_value value_item;
1697 value_item.offset = item->offset;
1698 value_item.value = value;
1700 agg.items.safe_push (value_item);
1703 return agg;
1706 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1707 bottom, not containing a variable component and without any known value at
1708 the same time. */
1710 DEBUG_FUNCTION void
1711 ipcp_verify_propagated_values (void)
1713 struct cgraph_node *node;
1715 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1717 class ipa_node_params *info = IPA_NODE_REF (node);
1718 if (!opt_for_fn (node->decl, flag_ipa_cp)
1719 || !opt_for_fn (node->decl, optimize))
1720 continue;
1721 int i, count = ipa_get_param_count (info);
1723 for (i = 0; i < count; i++)
1725 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1727 if (!lat->bottom
1728 && !lat->contains_variable
1729 && lat->values_count == 0)
1731 if (dump_file)
1733 symtab->dump (dump_file);
1734 fprintf (dump_file, "\nIPA lattices after constant "
1735 "propagation, before gcc_unreachable:\n");
1736 print_all_lattices (dump_file, true, false);
1739 gcc_unreachable ();
1745 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1747 static bool
1748 values_equal_for_ipcp_p (tree x, tree y)
1750 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1752 if (x == y)
1753 return true;
1755 if (TREE_CODE (x) == ADDR_EXPR
1756 && TREE_CODE (y) == ADDR_EXPR
1757 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1758 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1759 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1760 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1761 else
1762 return operand_equal_p (x, y, 0);
1765 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1767 static bool
1768 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1769 ipa_polymorphic_call_context y)
1771 return x.equal_to (y);
1775 /* Add a new value source to the value represented by THIS, marking that a
1776 value comes from edge CS and (if the underlying jump function is a
1777 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1778 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1779 scalar value of the parameter itself or the offset within an aggregate. */
1781 template <typename valtype>
1782 void
1783 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1784 int src_idx, HOST_WIDE_INT offset)
1786 ipcp_value_source<valtype> *src;
1788 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1789 src->offset = offset;
1790 src->cs = cs;
1791 src->val = src_val;
1792 src->index = src_idx;
1794 src->next = sources;
1795 sources = src;
1798 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1799 SOURCE and clear all other fields. */
1801 static ipcp_value<tree> *
1802 allocate_and_init_ipcp_value (tree source)
1804 ipcp_value<tree> *val;
1806 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1807 val->value = source;
1808 return val;
1811 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1812 value to SOURCE and clear all other fields. */
1814 static ipcp_value<ipa_polymorphic_call_context> *
1815 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1817 ipcp_value<ipa_polymorphic_call_context> *val;
1819 // TODO
1820 val = new (ipcp_poly_ctx_values_pool.allocate ())
1821 ipcp_value<ipa_polymorphic_call_context>();
1822 val->value = source;
1823 return val;
1826 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1827 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1828 meaning. OFFSET -1 means the source is scalar and not a part of an
1829 aggregate. If non-NULL, VAL_P records address of existing or newly added
1830 ipcp_value. UNLIMITED means whether value count should not exceed the limit
1831 given by PARAM_IPA_CP_VALUE_LIST_SIZE. */
1833 template <typename valtype>
1834 bool
1835 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1836 ipcp_value<valtype> *src_val,
1837 int src_idx, HOST_WIDE_INT offset,
1838 ipcp_value<valtype> **val_p,
1839 bool unlimited)
1841 ipcp_value<valtype> *val, *last_val = NULL;
1843 if (val_p)
1844 *val_p = NULL;
1846 if (bottom)
1847 return false;
1849 for (val = values; val; last_val = val, val = val->next)
1850 if (values_equal_for_ipcp_p (val->value, newval))
1852 if (val_p)
1853 *val_p = val;
1855 if (ipa_edge_within_scc (cs))
1857 ipcp_value_source<valtype> *s;
1858 for (s = val->sources; s; s = s->next)
1859 if (s->cs == cs && s->val == src_val)
1860 break;
1861 if (s)
1862 return false;
1865 val->add_source (cs, src_val, src_idx, offset);
1866 return false;
1869 if (!unlimited && values_count == opt_for_fn (cs->caller->decl,
1870 param_ipa_cp_value_list_size))
1872 /* We can only free sources, not the values themselves, because sources
1873 of other values in this SCC might point to them. */
1874 for (val = values; val; val = val->next)
1876 while (val->sources)
1878 ipcp_value_source<valtype> *src = val->sources;
1879 val->sources = src->next;
1880 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1883 values = NULL;
1884 return set_to_bottom ();
1887 values_count++;
1888 val = allocate_and_init_ipcp_value (newval);
1889 val->add_source (cs, src_val, src_idx, offset);
1890 val->next = NULL;
1892 /* Add the new value to end of value list, which can reduce iterations
1893 of propagation stage for recursive function. */
1894 if (last_val)
1895 last_val->next = val;
1896 else
1897 values = val;
1899 if (val_p)
1900 *val_p = val;
1902 return true;
1905 /* Return true, if a ipcp_value VAL is orginated from parameter value of
1906 self-feeding recursive function via some kind of pass-through jump
1907 function. */
1909 static bool
1910 self_recursively_generated_p (ipcp_value<tree> *val)
1912 class ipa_node_params *info = NULL;
1914 for (ipcp_value_source<tree> *src = val->sources; src; src = src->next)
1916 cgraph_edge *cs = src->cs;
1918 if (!src->val || cs->caller != cs->callee->function_symbol ())
1919 return false;
1921 if (src->val == val)
1922 continue;
1924 if (!info)
1925 info = IPA_NODE_REF (cs->caller);
1927 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info,
1928 src->index);
1929 ipcp_lattice<tree> *src_lat;
1930 ipcp_value<tree> *src_val;
1932 if (src->offset == -1)
1933 src_lat = &plats->itself;
1934 else
1936 struct ipcp_agg_lattice *src_aglat;
1938 for (src_aglat = plats->aggs; src_aglat; src_aglat = src_aglat->next)
1939 if (src_aglat->offset == src->offset)
1940 break;
1942 if (!src_aglat)
1943 return false;
1945 src_lat = src_aglat;
1948 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1949 if (src_val == val)
1950 break;
1952 if (!src_val)
1953 return false;
1956 return true;
1959 /* A helper function that returns result of operation specified by OPCODE on
1960 the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the
1961 value of SRC_VAL. If the operation is binary, OPND2 is a constant value
1962 acting as its second operand. If non-NULL, RES_TYPE is expected type of
1963 the result. */
1965 static tree
1966 get_val_across_arith_op (enum tree_code opcode,
1967 tree opnd1_type,
1968 tree opnd2,
1969 ipcp_value<tree> *src_val,
1970 tree res_type)
1972 tree opnd1 = src_val->value;
1974 /* Skip source values that is incompatible with specified type. */
1975 if (opnd1_type
1976 && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1)))
1977 return NULL_TREE;
1979 return ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type);
1982 /* Propagate values through an arithmetic transformation described by a jump
1983 function associated with edge CS, taking values from SRC_LAT and putting
1984 them into DEST_LAT. OPND1_TYPE is expected type for the values in SRC_LAT.
1985 OPND2 is a constant value if transformation is a binary operation.
1986 SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice of
1987 a part of the aggregate. SRC_IDX is the index of the source parameter.
1988 RES_TYPE is the value type of result being propagated into. Return true if
1989 DEST_LAT changed. */
1991 static bool
1992 propagate_vals_across_arith_jfunc (cgraph_edge *cs,
1993 enum tree_code opcode,
1994 tree opnd1_type,
1995 tree opnd2,
1996 ipcp_lattice<tree> *src_lat,
1997 ipcp_lattice<tree> *dest_lat,
1998 HOST_WIDE_INT src_offset,
1999 int src_idx,
2000 tree res_type)
2002 ipcp_value<tree> *src_val;
2003 bool ret = false;
2005 /* Due to circular dependencies, propagating within an SCC through arithmetic
2006 transformation would create infinite number of values. But for
2007 self-feeding recursive function, we could allow propagation in a limited
2008 count, and this can enable a simple kind of recursive function versioning.
2009 For other scenario, we would just make lattices bottom. */
2010 if (opcode != NOP_EXPR && ipa_edge_within_scc (cs))
2012 int i;
2014 int max_recursive_depth = opt_for_fn(cs->caller->decl,
2015 param_ipa_cp_max_recursive_depth);
2016 if (src_lat != dest_lat || max_recursive_depth < 1)
2017 return dest_lat->set_contains_variable ();
2019 /* No benefit if recursive execution is in low probability. */
2020 if (cs->sreal_frequency () * 100
2021 <= ((sreal) 1) * opt_for_fn (cs->caller->decl,
2022 param_ipa_cp_min_recursive_probability))
2023 return dest_lat->set_contains_variable ();
2025 auto_vec<ipcp_value<tree> *, 8> val_seeds;
2027 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2029 /* Now we do not use self-recursively generated value as propagation
2030 source, this is absolutely conservative, but could avoid explosion
2031 of lattice's value space, especially when one recursive function
2032 calls another recursive. */
2033 if (self_recursively_generated_p (src_val))
2035 ipcp_value_source<tree> *s;
2037 /* If the lattice has already been propagated for the call site,
2038 no need to do that again. */
2039 for (s = src_val->sources; s; s = s->next)
2040 if (s->cs == cs)
2041 return dest_lat->set_contains_variable ();
2043 else
2044 val_seeds.safe_push (src_val);
2047 gcc_assert ((int) val_seeds.length () <= param_ipa_cp_value_list_size);
2049 /* Recursively generate lattice values with a limited count. */
2050 FOR_EACH_VEC_ELT (val_seeds, i, src_val)
2052 for (int j = 1; j < max_recursive_depth; j++)
2054 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2055 src_val, res_type);
2056 if (!cstval)
2057 break;
2059 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2060 src_offset, &src_val, true);
2061 gcc_checking_assert (src_val);
2064 ret |= dest_lat->set_contains_variable ();
2066 else
2067 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2069 /* Now we do not use self-recursively generated value as propagation
2070 source, otherwise it is easy to make value space of normal lattice
2071 overflow. */
2072 if (self_recursively_generated_p (src_val))
2074 ret |= dest_lat->set_contains_variable ();
2075 continue;
2078 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2079 src_val, res_type);
2080 if (cstval)
2081 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2082 src_offset);
2083 else
2084 ret |= dest_lat->set_contains_variable ();
2087 return ret;
2090 /* Propagate values through a pass-through jump function JFUNC associated with
2091 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2092 is the index of the source parameter. PARM_TYPE is the type of the
2093 parameter to which the result is passed. */
2095 static bool
2096 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
2097 ipcp_lattice<tree> *src_lat,
2098 ipcp_lattice<tree> *dest_lat, int src_idx,
2099 tree parm_type)
2101 return propagate_vals_across_arith_jfunc (cs,
2102 ipa_get_jf_pass_through_operation (jfunc),
2103 NULL_TREE,
2104 ipa_get_jf_pass_through_operand (jfunc),
2105 src_lat, dest_lat, -1, src_idx, parm_type);
2108 /* Propagate values through an ancestor jump function JFUNC associated with
2109 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2110 is the index of the source parameter. */
2112 static bool
2113 propagate_vals_across_ancestor (struct cgraph_edge *cs,
2114 struct ipa_jump_func *jfunc,
2115 ipcp_lattice<tree> *src_lat,
2116 ipcp_lattice<tree> *dest_lat, int src_idx)
2118 ipcp_value<tree> *src_val;
2119 bool ret = false;
2121 if (ipa_edge_within_scc (cs))
2122 return dest_lat->set_contains_variable ();
2124 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2126 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
2128 if (t)
2129 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
2130 else
2131 ret |= dest_lat->set_contains_variable ();
2134 return ret;
2137 /* Propagate scalar values across jump function JFUNC that is associated with
2138 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the
2139 parameter to which the result is passed. */
2141 static bool
2142 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
2143 struct ipa_jump_func *jfunc,
2144 ipcp_lattice<tree> *dest_lat,
2145 tree param_type)
2147 if (dest_lat->bottom)
2148 return false;
2150 if (jfunc->type == IPA_JF_CONST)
2152 tree val = ipa_get_jf_constant (jfunc);
2153 return dest_lat->add_value (val, cs, NULL, 0);
2155 else if (jfunc->type == IPA_JF_PASS_THROUGH
2156 || jfunc->type == IPA_JF_ANCESTOR)
2158 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2159 ipcp_lattice<tree> *src_lat;
2160 int src_idx;
2161 bool ret;
2163 if (jfunc->type == IPA_JF_PASS_THROUGH)
2164 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2165 else
2166 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2168 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
2169 if (src_lat->bottom)
2170 return dest_lat->set_contains_variable ();
2172 /* If we would need to clone the caller and cannot, do not propagate. */
2173 if (!ipcp_versionable_function_p (cs->caller)
2174 && (src_lat->contains_variable
2175 || (src_lat->values_count > 1)))
2176 return dest_lat->set_contains_variable ();
2178 if (jfunc->type == IPA_JF_PASS_THROUGH)
2179 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
2180 dest_lat, src_idx, param_type);
2181 else
2182 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
2183 src_idx);
2185 if (src_lat->contains_variable)
2186 ret |= dest_lat->set_contains_variable ();
2188 return ret;
2191 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
2192 use it for indirect inlining), we should propagate them too. */
2193 return dest_lat->set_contains_variable ();
2196 /* Propagate scalar values across jump function JFUNC that is associated with
2197 edge CS and describes argument IDX and put the values into DEST_LAT. */
2199 static bool
2200 propagate_context_across_jump_function (cgraph_edge *cs,
2201 ipa_jump_func *jfunc, int idx,
2202 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
2204 ipa_edge_args *args = IPA_EDGE_REF (cs);
2205 if (dest_lat->bottom)
2206 return false;
2207 bool ret = false;
2208 bool added_sth = false;
2209 bool type_preserved = true;
2211 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
2212 = ipa_get_ith_polymorhic_call_context (args, idx);
2214 if (edge_ctx_ptr)
2215 edge_ctx = *edge_ctx_ptr;
2217 if (jfunc->type == IPA_JF_PASS_THROUGH
2218 || jfunc->type == IPA_JF_ANCESTOR)
2220 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2221 int src_idx;
2222 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
2224 /* TODO: Once we figure out how to propagate speculations, it will
2225 probably be a good idea to switch to speculation if type_preserved is
2226 not set instead of punting. */
2227 if (jfunc->type == IPA_JF_PASS_THROUGH)
2229 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
2230 goto prop_fail;
2231 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
2232 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2234 else
2236 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
2237 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2240 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
2241 /* If we would need to clone the caller and cannot, do not propagate. */
2242 if (!ipcp_versionable_function_p (cs->caller)
2243 && (src_lat->contains_variable
2244 || (src_lat->values_count > 1)))
2245 goto prop_fail;
2247 ipcp_value<ipa_polymorphic_call_context> *src_val;
2248 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2250 ipa_polymorphic_call_context cur = src_val->value;
2252 if (!type_preserved)
2253 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
2254 if (jfunc->type == IPA_JF_ANCESTOR)
2255 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
2256 /* TODO: In cases we know how the context is going to be used,
2257 we can improve the result by passing proper OTR_TYPE. */
2258 cur.combine_with (edge_ctx);
2259 if (!cur.useless_p ())
2261 if (src_lat->contains_variable
2262 && !edge_ctx.equal_to (cur))
2263 ret |= dest_lat->set_contains_variable ();
2264 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
2265 added_sth = true;
2270 prop_fail:
2271 if (!added_sth)
2273 if (!edge_ctx.useless_p ())
2274 ret |= dest_lat->add_value (edge_ctx, cs);
2275 else
2276 ret |= dest_lat->set_contains_variable ();
2279 return ret;
2282 /* Propagate bits across jfunc that is associated with
2283 edge cs and update dest_lattice accordingly. */
2285 bool
2286 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
2287 ipa_jump_func *jfunc,
2288 ipcp_bits_lattice *dest_lattice)
2290 if (dest_lattice->bottom_p ())
2291 return false;
2293 enum availability availability;
2294 cgraph_node *callee = cs->callee->function_symbol (&availability);
2295 class ipa_node_params *callee_info = IPA_NODE_REF (callee);
2296 tree parm_type = ipa_get_type (callee_info, idx);
2298 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the
2299 transform for these cases. Similarly, we can have bad type mismatches
2300 with LTO, avoid doing anything with those too. */
2301 if (!parm_type
2302 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type)))
2304 if (dump_file && (dump_flags & TDF_DETAILS))
2305 fprintf (dump_file, "Setting dest_lattice to bottom, because type of "
2306 "param %i of %s is NULL or unsuitable for bits propagation\n",
2307 idx, cs->callee->dump_name ());
2309 return dest_lattice->set_to_bottom ();
2312 unsigned precision = TYPE_PRECISION (parm_type);
2313 signop sgn = TYPE_SIGN (parm_type);
2315 if (jfunc->type == IPA_JF_PASS_THROUGH
2316 || jfunc->type == IPA_JF_ANCESTOR)
2318 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2319 tree operand = NULL_TREE;
2320 enum tree_code code;
2321 unsigned src_idx;
2323 if (jfunc->type == IPA_JF_PASS_THROUGH)
2325 code = ipa_get_jf_pass_through_operation (jfunc);
2326 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2327 if (code != NOP_EXPR)
2328 operand = ipa_get_jf_pass_through_operand (jfunc);
2330 else
2332 code = POINTER_PLUS_EXPR;
2333 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2334 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
2335 operand = build_int_cstu (size_type_node, offset);
2338 class ipcp_param_lattices *src_lats
2339 = ipa_get_parm_lattices (caller_info, src_idx);
2341 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
2342 for eg consider:
2343 int f(int x)
2345 g (x & 0xff);
2347 Assume lattice for x is bottom, however we can still propagate
2348 result of x & 0xff == 0xff, which gets computed during ccp1 pass
2349 and we store it in jump function during analysis stage. */
2351 if (src_lats->bits_lattice.bottom_p ()
2352 && jfunc->bits)
2353 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
2354 precision);
2355 else
2356 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
2357 code, operand);
2360 else if (jfunc->type == IPA_JF_ANCESTOR)
2361 return dest_lattice->set_to_bottom ();
2362 else if (jfunc->bits)
2363 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
2364 precision);
2365 else
2366 return dest_lattice->set_to_bottom ();
2369 /* Propagate value range across jump function JFUNC that is associated with
2370 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
2371 accordingly. */
2373 static bool
2374 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
2375 class ipcp_param_lattices *dest_plats,
2376 tree param_type)
2378 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
2380 if (dest_lat->bottom_p ())
2381 return false;
2383 if (!param_type
2384 || (!INTEGRAL_TYPE_P (param_type)
2385 && !POINTER_TYPE_P (param_type)))
2386 return dest_lat->set_to_bottom ();
2388 if (jfunc->type == IPA_JF_PASS_THROUGH)
2390 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
2391 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2392 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2393 class ipcp_param_lattices *src_lats
2394 = ipa_get_parm_lattices (caller_info, src_idx);
2395 tree operand_type = ipa_get_type (caller_info, src_idx);
2397 if (src_lats->m_value_range.bottom_p ())
2398 return dest_lat->set_to_bottom ();
2400 value_range vr;
2401 if (TREE_CODE_CLASS (operation) == tcc_unary)
2402 ipa_vr_operation_and_type_effects (&vr,
2403 &src_lats->m_value_range.m_vr,
2404 operation, param_type,
2405 operand_type);
2406 /* A crude way to prevent unbounded number of value range updates
2407 in SCC components. We should allow limited number of updates within
2408 SCC, too. */
2409 else if (!ipa_edge_within_scc (cs))
2411 tree op = ipa_get_jf_pass_through_operand (jfunc);
2412 value_range op_vr (op, op);
2413 value_range op_res,res;
2415 range_fold_binary_expr (&op_res, operation, operand_type,
2416 &src_lats->m_value_range.m_vr, &op_vr);
2417 ipa_vr_operation_and_type_effects (&vr,
2418 &op_res,
2419 NOP_EXPR, param_type,
2420 operand_type);
2422 if (!vr.undefined_p () && !vr.varying_p ())
2424 if (jfunc->m_vr)
2426 value_range jvr;
2427 if (ipa_vr_operation_and_type_effects (&jvr, jfunc->m_vr,
2428 NOP_EXPR,
2429 param_type,
2430 jfunc->m_vr->type ()))
2431 vr.intersect (jvr);
2433 return dest_lat->meet_with (&vr);
2436 else if (jfunc->type == IPA_JF_CONST)
2438 tree val = ipa_get_jf_constant (jfunc);
2439 if (TREE_CODE (val) == INTEGER_CST)
2441 val = fold_convert (param_type, val);
2442 if (TREE_OVERFLOW_P (val))
2443 val = drop_tree_overflow (val);
2445 value_range tmpvr (val, val);
2446 return dest_lat->meet_with (&tmpvr);
2450 value_range vr;
2451 if (jfunc->m_vr
2452 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
2453 param_type,
2454 jfunc->m_vr->type ()))
2455 return dest_lat->meet_with (&vr);
2456 else
2457 return dest_lat->set_to_bottom ();
2460 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
2461 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
2462 other cases, return false). If there are no aggregate items, set
2463 aggs_by_ref to NEW_AGGS_BY_REF. */
2465 static bool
2466 set_check_aggs_by_ref (class ipcp_param_lattices *dest_plats,
2467 bool new_aggs_by_ref)
2469 if (dest_plats->aggs)
2471 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
2473 set_agg_lats_to_bottom (dest_plats);
2474 return true;
2477 else
2478 dest_plats->aggs_by_ref = new_aggs_by_ref;
2479 return false;
2482 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
2483 already existing lattice for the given OFFSET and SIZE, marking all skipped
2484 lattices as containing variable and checking for overlaps. If there is no
2485 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
2486 it with offset, size and contains_variable to PRE_EXISTING, and return true,
2487 unless there are too many already. If there are two many, return false. If
2488 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
2489 skipped lattices were newly marked as containing variable, set *CHANGE to
2490 true. MAX_AGG_ITEMS is the maximum number of lattices. */
2492 static bool
2493 merge_agg_lats_step (class ipcp_param_lattices *dest_plats,
2494 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
2495 struct ipcp_agg_lattice ***aglat,
2496 bool pre_existing, bool *change, int max_agg_items)
2498 gcc_checking_assert (offset >= 0);
2500 while (**aglat && (**aglat)->offset < offset)
2502 if ((**aglat)->offset + (**aglat)->size > offset)
2504 set_agg_lats_to_bottom (dest_plats);
2505 return false;
2507 *change |= (**aglat)->set_contains_variable ();
2508 *aglat = &(**aglat)->next;
2511 if (**aglat && (**aglat)->offset == offset)
2513 if ((**aglat)->size != val_size)
2515 set_agg_lats_to_bottom (dest_plats);
2516 return false;
2518 gcc_assert (!(**aglat)->next
2519 || (**aglat)->next->offset >= offset + val_size);
2520 return true;
2522 else
2524 struct ipcp_agg_lattice *new_al;
2526 if (**aglat && (**aglat)->offset < offset + val_size)
2528 set_agg_lats_to_bottom (dest_plats);
2529 return false;
2531 if (dest_plats->aggs_count == max_agg_items)
2532 return false;
2533 dest_plats->aggs_count++;
2534 new_al = ipcp_agg_lattice_pool.allocate ();
2535 memset (new_al, 0, sizeof (*new_al));
2537 new_al->offset = offset;
2538 new_al->size = val_size;
2539 new_al->contains_variable = pre_existing;
2541 new_al->next = **aglat;
2542 **aglat = new_al;
2543 return true;
2547 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2548 containing an unknown value. */
2550 static bool
2551 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2553 bool ret = false;
2554 while (aglat)
2556 ret |= aglat->set_contains_variable ();
2557 aglat = aglat->next;
2559 return ret;
2562 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2563 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2564 parameter used for lattice value sources. Return true if DEST_PLATS changed
2565 in any way. */
2567 static bool
2568 merge_aggregate_lattices (struct cgraph_edge *cs,
2569 class ipcp_param_lattices *dest_plats,
2570 class ipcp_param_lattices *src_plats,
2571 int src_idx, HOST_WIDE_INT offset_delta)
2573 bool pre_existing = dest_plats->aggs != NULL;
2574 struct ipcp_agg_lattice **dst_aglat;
2575 bool ret = false;
2577 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2578 return true;
2579 if (src_plats->aggs_bottom)
2580 return set_agg_lats_contain_variable (dest_plats);
2581 if (src_plats->aggs_contain_variable)
2582 ret |= set_agg_lats_contain_variable (dest_plats);
2583 dst_aglat = &dest_plats->aggs;
2585 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2586 param_ipa_max_agg_items);
2587 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2588 src_aglat;
2589 src_aglat = src_aglat->next)
2591 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2593 if (new_offset < 0)
2594 continue;
2595 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2596 &dst_aglat, pre_existing, &ret, max_agg_items))
2598 struct ipcp_agg_lattice *new_al = *dst_aglat;
2600 dst_aglat = &(*dst_aglat)->next;
2601 if (src_aglat->bottom)
2603 ret |= new_al->set_contains_variable ();
2604 continue;
2606 if (src_aglat->contains_variable)
2607 ret |= new_al->set_contains_variable ();
2608 for (ipcp_value<tree> *val = src_aglat->values;
2609 val;
2610 val = val->next)
2611 ret |= new_al->add_value (val->value, cs, val, src_idx,
2612 src_aglat->offset);
2614 else if (dest_plats->aggs_bottom)
2615 return true;
2617 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2618 return ret;
2621 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2622 pass-through JFUNC and if so, whether it has conform and conforms to the
2623 rules about propagating values passed by reference. */
2625 static bool
2626 agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats,
2627 struct ipa_jump_func *jfunc)
2629 return src_plats->aggs
2630 && (!src_plats->aggs_by_ref
2631 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2634 /* Propagate values through ITEM, jump function for a part of an aggregate,
2635 into corresponding aggregate lattice AGLAT. CS is the call graph edge
2636 associated with the jump function. Return true if AGLAT changed in any
2637 way. */
2639 static bool
2640 propagate_aggregate_lattice (struct cgraph_edge *cs,
2641 struct ipa_agg_jf_item *item,
2642 struct ipcp_agg_lattice *aglat)
2644 class ipa_node_params *caller_info;
2645 class ipcp_param_lattices *src_plats;
2646 struct ipcp_lattice<tree> *src_lat;
2647 HOST_WIDE_INT src_offset;
2648 int src_idx;
2649 tree load_type;
2650 bool ret;
2652 if (item->jftype == IPA_JF_CONST)
2654 tree value = item->value.constant;
2656 gcc_checking_assert (is_gimple_ip_invariant (value));
2657 return aglat->add_value (value, cs, NULL, 0);
2660 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
2661 || item->jftype == IPA_JF_LOAD_AGG);
2663 caller_info = IPA_NODE_REF (cs->caller);
2664 src_idx = item->value.pass_through.formal_id;
2665 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2667 if (item->jftype == IPA_JF_PASS_THROUGH)
2669 load_type = NULL_TREE;
2670 src_lat = &src_plats->itself;
2671 src_offset = -1;
2673 else
2675 HOST_WIDE_INT load_offset = item->value.load_agg.offset;
2676 struct ipcp_agg_lattice *src_aglat;
2678 for (src_aglat = src_plats->aggs; src_aglat; src_aglat = src_aglat->next)
2679 if (src_aglat->offset >= load_offset)
2680 break;
2682 load_type = item->value.load_agg.type;
2683 if (!src_aglat
2684 || src_aglat->offset > load_offset
2685 || src_aglat->size != tree_to_shwi (TYPE_SIZE (load_type))
2686 || src_plats->aggs_by_ref != item->value.load_agg.by_ref)
2687 return aglat->set_contains_variable ();
2689 src_lat = src_aglat;
2690 src_offset = load_offset;
2693 if (src_lat->bottom
2694 || (!ipcp_versionable_function_p (cs->caller)
2695 && !src_lat->is_single_const ()))
2696 return aglat->set_contains_variable ();
2698 ret = propagate_vals_across_arith_jfunc (cs,
2699 item->value.pass_through.operation,
2700 load_type,
2701 item->value.pass_through.operand,
2702 src_lat, aglat,
2703 src_offset,
2704 src_idx,
2705 item->type);
2707 if (src_lat->contains_variable)
2708 ret |= aglat->set_contains_variable ();
2710 return ret;
2713 /* Propagate scalar values across jump function JFUNC that is associated with
2714 edge CS and put the values into DEST_LAT. */
2716 static bool
2717 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2718 struct ipa_jump_func *jfunc,
2719 class ipcp_param_lattices *dest_plats)
2721 bool ret = false;
2723 if (dest_plats->aggs_bottom)
2724 return false;
2726 if (jfunc->type == IPA_JF_PASS_THROUGH
2727 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2729 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2730 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2731 class ipcp_param_lattices *src_plats;
2733 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2734 if (agg_pass_through_permissible_p (src_plats, jfunc))
2736 /* Currently we do not produce clobber aggregate jump
2737 functions, replace with merging when we do. */
2738 gcc_assert (!jfunc->agg.items);
2739 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2740 src_idx, 0);
2741 return ret;
2744 else if (jfunc->type == IPA_JF_ANCESTOR
2745 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2747 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2748 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2749 class ipcp_param_lattices *src_plats;
2751 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2752 if (src_plats->aggs && src_plats->aggs_by_ref)
2754 /* Currently we do not produce clobber aggregate jump
2755 functions, replace with merging when we do. */
2756 gcc_assert (!jfunc->agg.items);
2757 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2758 ipa_get_jf_ancestor_offset (jfunc));
2760 else if (!src_plats->aggs_by_ref)
2761 ret |= set_agg_lats_to_bottom (dest_plats);
2762 else
2763 ret |= set_agg_lats_contain_variable (dest_plats);
2764 return ret;
2767 if (jfunc->agg.items)
2769 bool pre_existing = dest_plats->aggs != NULL;
2770 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2771 struct ipa_agg_jf_item *item;
2772 int i;
2774 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2775 return true;
2777 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2778 param_ipa_max_agg_items);
2779 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2781 HOST_WIDE_INT val_size;
2783 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN)
2784 continue;
2785 val_size = tree_to_shwi (TYPE_SIZE (item->type));
2787 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2788 &aglat, pre_existing, &ret, max_agg_items))
2790 ret |= propagate_aggregate_lattice (cs, item, *aglat);
2791 aglat = &(*aglat)->next;
2793 else if (dest_plats->aggs_bottom)
2794 return true;
2797 ret |= set_chain_of_aglats_contains_variable (*aglat);
2799 else
2800 ret |= set_agg_lats_contain_variable (dest_plats);
2802 return ret;
2805 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2806 non-thunk) destination, the call passes through a thunk. */
2808 static bool
2809 call_passes_through_thunk_p (cgraph_edge *cs)
2811 cgraph_node *alias_or_thunk = cs->callee;
2812 while (alias_or_thunk->alias)
2813 alias_or_thunk = alias_or_thunk->get_alias_target ();
2814 return alias_or_thunk->thunk.thunk_p;
2817 /* Propagate constants from the caller to the callee of CS. INFO describes the
2818 caller. */
2820 static bool
2821 propagate_constants_across_call (struct cgraph_edge *cs)
2823 class ipa_node_params *callee_info;
2824 enum availability availability;
2825 cgraph_node *callee;
2826 class ipa_edge_args *args;
2827 bool ret = false;
2828 int i, args_count, parms_count;
2830 callee = cs->callee->function_symbol (&availability);
2831 if (!callee->definition)
2832 return false;
2833 gcc_checking_assert (callee->has_gimple_body_p ());
2834 callee_info = IPA_NODE_REF (callee);
2835 if (!callee_info)
2836 return false;
2838 args = IPA_EDGE_REF (cs);
2839 parms_count = ipa_get_param_count (callee_info);
2840 if (parms_count == 0)
2841 return false;
2842 if (!args
2843 || !opt_for_fn (cs->caller->decl, flag_ipa_cp)
2844 || !opt_for_fn (cs->caller->decl, optimize))
2846 for (i = 0; i < parms_count; i++)
2847 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2848 i));
2849 return ret;
2851 args_count = ipa_get_cs_argument_count (args);
2853 /* If this call goes through a thunk we must not propagate to the first (0th)
2854 parameter. However, we might need to uncover a thunk from below a series
2855 of aliases first. */
2856 if (call_passes_through_thunk_p (cs))
2858 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2859 0));
2860 i = 1;
2862 else
2863 i = 0;
2865 for (; (i < args_count) && (i < parms_count); i++)
2867 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2868 class ipcp_param_lattices *dest_plats;
2869 tree param_type = ipa_get_type (callee_info, i);
2871 dest_plats = ipa_get_parm_lattices (callee_info, i);
2872 if (availability == AVAIL_INTERPOSABLE)
2873 ret |= set_all_contains_variable (dest_plats);
2874 else
2876 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2877 &dest_plats->itself,
2878 param_type);
2879 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2880 &dest_plats->ctxlat);
2882 |= propagate_bits_across_jump_function (cs, i, jump_func,
2883 &dest_plats->bits_lattice);
2884 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2885 dest_plats);
2886 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2887 ret |= propagate_vr_across_jump_function (cs, jump_func,
2888 dest_plats, param_type);
2889 else
2890 ret |= dest_plats->m_value_range.set_to_bottom ();
2893 for (; i < parms_count; i++)
2894 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2896 return ret;
2899 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2900 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2901 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2903 static tree
2904 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2905 vec<tree> known_csts,
2906 vec<ipa_polymorphic_call_context> known_contexts,
2907 vec<ipa_agg_value_set> known_aggs,
2908 struct ipa_agg_replacement_value *agg_reps,
2909 bool *speculative)
2911 int param_index = ie->indirect_info->param_index;
2912 HOST_WIDE_INT anc_offset;
2913 tree t = NULL;
2914 tree target = NULL;
2916 *speculative = false;
2918 if (param_index == -1)
2919 return NULL_TREE;
2921 if (!ie->indirect_info->polymorphic)
2923 tree t = NULL;
2925 if (ie->indirect_info->agg_contents)
2927 t = NULL;
2928 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2930 while (agg_reps)
2932 if (agg_reps->index == param_index
2933 && agg_reps->offset == ie->indirect_info->offset
2934 && agg_reps->by_ref == ie->indirect_info->by_ref)
2936 t = agg_reps->value;
2937 break;
2939 agg_reps = agg_reps->next;
2942 if (!t)
2944 struct ipa_agg_value_set *agg;
2945 if (known_aggs.length () > (unsigned int) param_index)
2946 agg = &known_aggs[param_index];
2947 else
2948 agg = NULL;
2949 bool from_global_constant;
2950 t = ipa_find_agg_cst_for_param (agg,
2951 (unsigned) param_index
2952 < known_csts.length ()
2953 ? known_csts[param_index]
2954 : NULL,
2955 ie->indirect_info->offset,
2956 ie->indirect_info->by_ref,
2957 &from_global_constant);
2958 if (t
2959 && !from_global_constant
2960 && !ie->indirect_info->guaranteed_unmodified)
2961 t = NULL_TREE;
2964 else if ((unsigned) param_index < known_csts.length ())
2965 t = known_csts[param_index];
2967 if (t
2968 && TREE_CODE (t) == ADDR_EXPR
2969 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2970 return TREE_OPERAND (t, 0);
2971 else
2972 return NULL_TREE;
2975 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2976 return NULL_TREE;
2978 gcc_assert (!ie->indirect_info->agg_contents);
2979 anc_offset = ie->indirect_info->offset;
2981 t = NULL;
2983 /* Try to work out value of virtual table pointer value in replacements. */
2984 if (!t && agg_reps && !ie->indirect_info->by_ref)
2986 while (agg_reps)
2988 if (agg_reps->index == param_index
2989 && agg_reps->offset == ie->indirect_info->offset
2990 && agg_reps->by_ref)
2992 t = agg_reps->value;
2993 break;
2995 agg_reps = agg_reps->next;
2999 /* Try to work out value of virtual table pointer value in known
3000 aggregate values. */
3001 if (!t && known_aggs.length () > (unsigned int) param_index
3002 && !ie->indirect_info->by_ref)
3004 struct ipa_agg_value_set *agg = &known_aggs[param_index];
3005 t = ipa_find_agg_cst_for_param (agg,
3006 (unsigned) param_index
3007 < known_csts.length ()
3008 ? known_csts[param_index] : NULL,
3009 ie->indirect_info->offset, true);
3012 /* If we found the virtual table pointer, lookup the target. */
3013 if (t)
3015 tree vtable;
3016 unsigned HOST_WIDE_INT offset;
3017 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
3019 bool can_refer;
3020 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
3021 vtable, offset, &can_refer);
3022 if (can_refer)
3024 if (!target
3025 || fndecl_built_in_p (target, BUILT_IN_UNREACHABLE)
3026 || !possible_polymorphic_call_target_p
3027 (ie, cgraph_node::get (target)))
3029 /* Do not speculate builtin_unreachable, it is stupid! */
3030 if (ie->indirect_info->vptr_changed)
3031 return NULL;
3032 target = ipa_impossible_devirt_target (ie, target);
3034 *speculative = ie->indirect_info->vptr_changed;
3035 if (!*speculative)
3036 return target;
3041 /* Do we know the constant value of pointer? */
3042 if (!t && (unsigned) param_index < known_csts.length ())
3043 t = known_csts[param_index];
3045 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
3047 ipa_polymorphic_call_context context;
3048 if (known_contexts.length () > (unsigned int) param_index)
3050 context = known_contexts[param_index];
3051 context.offset_by (anc_offset);
3052 if (ie->indirect_info->vptr_changed)
3053 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
3054 ie->indirect_info->otr_type);
3055 if (t)
3057 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
3058 (t, ie->indirect_info->otr_type, anc_offset);
3059 if (!ctx2.useless_p ())
3060 context.combine_with (ctx2, ie->indirect_info->otr_type);
3063 else if (t)
3065 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
3066 anc_offset);
3067 if (ie->indirect_info->vptr_changed)
3068 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
3069 ie->indirect_info->otr_type);
3071 else
3072 return NULL_TREE;
3074 vec <cgraph_node *>targets;
3075 bool final;
3077 targets = possible_polymorphic_call_targets
3078 (ie->indirect_info->otr_type,
3079 ie->indirect_info->otr_token,
3080 context, &final);
3081 if (!final || targets.length () > 1)
3083 struct cgraph_node *node;
3084 if (*speculative)
3085 return target;
3086 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
3087 || ie->speculative || !ie->maybe_hot_p ())
3088 return NULL;
3089 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
3090 ie->indirect_info->otr_token,
3091 context);
3092 if (node)
3094 *speculative = true;
3095 target = node->decl;
3097 else
3098 return NULL;
3100 else
3102 *speculative = false;
3103 if (targets.length () == 1)
3104 target = targets[0]->decl;
3105 else
3106 target = ipa_impossible_devirt_target (ie, NULL_TREE);
3109 if (target && !possible_polymorphic_call_target_p (ie,
3110 cgraph_node::get (target)))
3112 if (*speculative)
3113 return NULL;
3114 target = ipa_impossible_devirt_target (ie, target);
3117 return target;
3121 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
3122 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
3123 return the destination. */
3125 tree
3126 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
3127 vec<tree> known_csts,
3128 vec<ipa_polymorphic_call_context> known_contexts,
3129 vec<ipa_agg_value_set> known_aggs,
3130 bool *speculative)
3132 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3133 known_aggs, NULL, speculative);
3136 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
3137 and KNOWN_CONTEXTS. */
3139 static int
3140 devirtualization_time_bonus (struct cgraph_node *node,
3141 vec<tree> known_csts,
3142 vec<ipa_polymorphic_call_context> known_contexts,
3143 vec<ipa_agg_value_set> known_aggs)
3145 struct cgraph_edge *ie;
3146 int res = 0;
3148 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
3150 struct cgraph_node *callee;
3151 class ipa_fn_summary *isummary;
3152 enum availability avail;
3153 tree target;
3154 bool speculative;
3156 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
3157 known_aggs, &speculative);
3158 if (!target)
3159 continue;
3161 /* Only bare minimum benefit for clearly un-inlineable targets. */
3162 res += 1;
3163 callee = cgraph_node::get (target);
3164 if (!callee || !callee->definition)
3165 continue;
3166 callee = callee->function_symbol (&avail);
3167 if (avail < AVAIL_AVAILABLE)
3168 continue;
3169 isummary = ipa_fn_summaries->get (callee);
3170 if (!isummary || !isummary->inlinable)
3171 continue;
3173 int size = ipa_size_summaries->get (callee)->size;
3174 /* FIXME: The values below need re-considering and perhaps also
3175 integrating into the cost metrics, at lest in some very basic way. */
3176 int max_inline_insns_auto
3177 = opt_for_fn (callee->decl, param_max_inline_insns_auto);
3178 if (size <= max_inline_insns_auto / 4)
3179 res += 31 / ((int)speculative + 1);
3180 else if (size <= max_inline_insns_auto / 2)
3181 res += 15 / ((int)speculative + 1);
3182 else if (size <= max_inline_insns_auto
3183 || DECL_DECLARED_INLINE_P (callee->decl))
3184 res += 7 / ((int)speculative + 1);
3187 return res;
3190 /* Return time bonus incurred because of HINTS. */
3192 static int
3193 hint_time_bonus (cgraph_node *node, ipa_hints hints)
3195 int result = 0;
3196 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
3197 result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
3198 return result;
3201 /* If there is a reason to penalize the function described by INFO in the
3202 cloning goodness evaluation, do so. */
3204 static inline int64_t
3205 incorporate_penalties (cgraph_node *node, ipa_node_params *info,
3206 int64_t evaluation)
3208 if (info->node_within_scc && !info->node_is_self_scc)
3209 evaluation = (evaluation
3210 * (100 - opt_for_fn (node->decl,
3211 param_ipa_cp_recursion_penalty))) / 100;
3213 if (info->node_calling_single_call)
3214 evaluation = (evaluation
3215 * (100 - opt_for_fn (node->decl,
3216 param_ipa_cp_single_call_penalty)))
3217 / 100;
3219 return evaluation;
3222 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
3223 and SIZE_COST and with the sum of frequencies of incoming edges to the
3224 potential new clone in FREQUENCIES. */
3226 static bool
3227 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
3228 int freq_sum, profile_count count_sum, int size_cost)
3230 if (time_benefit == 0
3231 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
3232 || node->optimize_for_size_p ())
3233 return false;
3235 gcc_assert (size_cost > 0);
3237 class ipa_node_params *info = IPA_NODE_REF (node);
3238 int eval_threshold = opt_for_fn (node->decl, param_ipa_cp_eval_threshold);
3239 if (max_count > profile_count::zero ())
3241 int factor = RDIV (count_sum.probability_in
3242 (max_count).to_reg_br_prob_base ()
3243 * 1000, REG_BR_PROB_BASE);
3244 int64_t evaluation = (((int64_t) time_benefit * factor)
3245 / size_cost);
3246 evaluation = incorporate_penalties (node, info, evaluation);
3248 if (dump_file && (dump_flags & TDF_DETAILS))
3250 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
3251 "size: %i, count_sum: ", time_benefit, size_cost);
3252 count_sum.dump (dump_file);
3253 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
3254 ", threshold: %i\n",
3255 info->node_within_scc
3256 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3257 info->node_calling_single_call ? ", single_call" : "",
3258 evaluation, eval_threshold);
3261 return evaluation >= eval_threshold;
3263 else
3265 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
3266 / size_cost);
3267 evaluation = incorporate_penalties (node, info, evaluation);
3269 if (dump_file && (dump_flags & TDF_DETAILS))
3270 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
3271 "size: %i, freq_sum: %i%s%s) -> evaluation: "
3272 "%" PRId64 ", threshold: %i\n",
3273 time_benefit, size_cost, freq_sum,
3274 info->node_within_scc
3275 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3276 info->node_calling_single_call ? ", single_call" : "",
3277 evaluation, eval_threshold);
3279 return evaluation >= eval_threshold;
3283 /* Return all context independent values from aggregate lattices in PLATS in a
3284 vector. Return NULL if there are none. */
3286 static vec<ipa_agg_value>
3287 context_independent_aggregate_values (class ipcp_param_lattices *plats)
3289 vec<ipa_agg_value> res = vNULL;
3291 if (plats->aggs_bottom
3292 || plats->aggs_contain_variable
3293 || plats->aggs_count == 0)
3294 return vNULL;
3296 for (struct ipcp_agg_lattice *aglat = plats->aggs;
3297 aglat;
3298 aglat = aglat->next)
3299 if (aglat->is_single_const ())
3301 struct ipa_agg_value item;
3302 item.offset = aglat->offset;
3303 item.value = aglat->values->value;
3304 res.safe_push (item);
3306 return res;
3309 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
3310 populate them with values of parameters that are known independent of the
3311 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
3312 non-NULL, the movement cost of all removable parameters will be stored in
3313 it. */
3315 static bool
3316 gather_context_independent_values (class ipa_node_params *info,
3317 vec<tree> *known_csts,
3318 vec<ipa_polymorphic_call_context>
3319 *known_contexts,
3320 vec<ipa_agg_value_set> *known_aggs,
3321 int *removable_params_cost)
3323 int i, count = ipa_get_param_count (info);
3324 bool ret = false;
3326 known_csts->create (0);
3327 known_contexts->create (0);
3328 known_csts->safe_grow_cleared (count);
3329 known_contexts->safe_grow_cleared (count);
3330 if (known_aggs)
3332 known_aggs->create (0);
3333 known_aggs->safe_grow_cleared (count);
3336 if (removable_params_cost)
3337 *removable_params_cost = 0;
3339 for (i = 0; i < count; i++)
3341 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3342 ipcp_lattice<tree> *lat = &plats->itself;
3344 if (lat->is_single_const ())
3346 ipcp_value<tree> *val = lat->values;
3347 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3348 (*known_csts)[i] = val->value;
3349 if (removable_params_cost)
3350 *removable_params_cost
3351 += estimate_move_cost (TREE_TYPE (val->value), false);
3352 ret = true;
3354 else if (removable_params_cost
3355 && !ipa_is_param_used (info, i))
3356 *removable_params_cost
3357 += ipa_get_param_move_cost (info, i);
3359 if (!ipa_is_param_used (info, i))
3360 continue;
3362 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3363 /* Do not account known context as reason for cloning. We can see
3364 if it permits devirtualization. */
3365 if (ctxlat->is_single_const ())
3366 (*known_contexts)[i] = ctxlat->values->value;
3368 if (known_aggs)
3370 vec<ipa_agg_value> agg_items;
3371 struct ipa_agg_value_set *agg;
3373 agg_items = context_independent_aggregate_values (plats);
3374 agg = &(*known_aggs)[i];
3375 agg->items = agg_items;
3376 agg->by_ref = plats->aggs_by_ref;
3377 ret |= !agg_items.is_empty ();
3381 return ret;
3384 /* Perform time and size measurement of NODE with the context given in
3385 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
3386 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
3387 all context-independent removable parameters and EST_MOVE_COST of estimated
3388 movement of the considered parameter and store it into VAL. */
3390 static void
3391 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
3392 vec<ipa_polymorphic_call_context> known_contexts,
3393 vec<ipa_agg_value_set> known_aggs,
3394 int removable_params_cost,
3395 int est_move_cost, ipcp_value_base *val)
3397 int size, time_benefit;
3398 sreal time, base_time;
3399 ipa_hints hints;
3401 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
3402 known_aggs, &size, &time,
3403 &base_time, &hints);
3404 base_time -= time;
3405 if (base_time > 65535)
3406 base_time = 65535;
3408 /* Extern inline functions have no cloning local time benefits because they
3409 will be inlined anyway. The only reason to clone them is if it enables
3410 optimization in any of the functions they call. */
3411 if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl))
3412 time_benefit = 0;
3413 else
3414 time_benefit = base_time.to_int ()
3415 + devirtualization_time_bonus (node, known_csts, known_contexts,
3416 known_aggs)
3417 + hint_time_bonus (node, hints)
3418 + removable_params_cost + est_move_cost;
3420 gcc_checking_assert (size >=0);
3421 /* The inliner-heuristics based estimates may think that in certain
3422 contexts some functions do not have any size at all but we want
3423 all specializations to have at least a tiny cost, not least not to
3424 divide by zero. */
3425 if (size == 0)
3426 size = 1;
3428 val->local_time_benefit = time_benefit;
3429 val->local_size_cost = size;
3432 /* Get the overall limit oof growth based on parameters extracted from growth.
3433 it does not really make sense to mix functions with different overall growth
3434 limits but it is possible and if it happens, we do not want to select one
3435 limit at random. */
3437 static long
3438 get_max_overall_size (cgraph_node *node)
3440 long max_new_size = orig_overall_size;
3441 long large_unit = opt_for_fn (node->decl, param_large_unit_insns);
3442 if (max_new_size < large_unit)
3443 max_new_size = large_unit;
3444 int unit_growth = opt_for_fn (node->decl, param_ipa_cp_unit_growth);
3445 max_new_size += max_new_size * unit_growth / 100 + 1;
3446 return max_new_size;
3449 /* Iterate over known values of parameters of NODE and estimate the local
3450 effects in terms of time and size they have. */
3452 static void
3453 estimate_local_effects (struct cgraph_node *node)
3455 class ipa_node_params *info = IPA_NODE_REF (node);
3456 int i, count = ipa_get_param_count (info);
3457 vec<tree> known_csts;
3458 vec<ipa_polymorphic_call_context> known_contexts;
3459 vec<ipa_agg_value_set> known_aggs;
3460 bool always_const;
3461 int removable_params_cost;
3463 if (!count || !ipcp_versionable_function_p (node))
3464 return;
3466 if (dump_file && (dump_flags & TDF_DETAILS))
3467 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
3469 always_const = gather_context_independent_values (info, &known_csts,
3470 &known_contexts, &known_aggs,
3471 &removable_params_cost);
3472 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
3473 known_contexts, known_aggs);
3474 if (always_const || devirt_bonus
3475 || (removable_params_cost && node->can_change_signature))
3477 struct caller_statistics stats;
3478 ipa_hints hints;
3479 sreal time, base_time;
3480 int size;
3482 init_caller_stats (&stats);
3483 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3484 false);
3485 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
3486 known_aggs, &size, &time,
3487 &base_time, &hints);
3488 time -= devirt_bonus;
3489 time -= hint_time_bonus (node, hints);
3490 time -= removable_params_cost;
3491 size -= stats.n_calls * removable_params_cost;
3493 if (dump_file)
3494 fprintf (dump_file, " - context independent values, size: %i, "
3495 "time_benefit: %f\n", size, (base_time - time).to_double ());
3497 if (size <= 0 || node->local)
3499 info->do_clone_for_all_contexts = true;
3501 if (dump_file)
3502 fprintf (dump_file, " Decided to specialize for all "
3503 "known contexts, code not going to grow.\n");
3505 else if (good_cloning_opportunity_p (node,
3506 MIN ((base_time - time).to_int (),
3507 65536),
3508 stats.freq_sum, stats.count_sum,
3509 size))
3511 if (size + overall_size <= get_max_overall_size (node))
3513 info->do_clone_for_all_contexts = true;
3514 overall_size += size;
3516 if (dump_file)
3517 fprintf (dump_file, " Decided to specialize for all "
3518 "known contexts, growth deemed beneficial.\n");
3520 else if (dump_file && (dump_flags & TDF_DETAILS))
3521 fprintf (dump_file, " Not cloning for all contexts because "
3522 "maximum unit size would be reached with %li.\n",
3523 size + overall_size);
3525 else if (dump_file && (dump_flags & TDF_DETAILS))
3526 fprintf (dump_file, " Not cloning for all contexts because "
3527 "!good_cloning_opportunity_p.\n");
3531 for (i = 0; i < count; i++)
3533 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3534 ipcp_lattice<tree> *lat = &plats->itself;
3535 ipcp_value<tree> *val;
3537 if (lat->bottom
3538 || !lat->values
3539 || known_csts[i])
3540 continue;
3542 for (val = lat->values; val; val = val->next)
3544 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3545 known_csts[i] = val->value;
3547 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
3548 perform_estimation_of_a_value (node, known_csts, known_contexts,
3549 known_aggs,
3550 removable_params_cost, emc, val);
3552 if (dump_file && (dump_flags & TDF_DETAILS))
3554 fprintf (dump_file, " - estimates for value ");
3555 print_ipcp_constant_value (dump_file, val->value);
3556 fprintf (dump_file, " for ");
3557 ipa_dump_param (dump_file, info, i);
3558 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
3559 val->local_time_benefit, val->local_size_cost);
3562 known_csts[i] = NULL_TREE;
3565 for (i = 0; i < count; i++)
3567 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3569 if (!plats->virt_call)
3570 continue;
3572 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3573 ipcp_value<ipa_polymorphic_call_context> *val;
3575 if (ctxlat->bottom
3576 || !ctxlat->values
3577 || !known_contexts[i].useless_p ())
3578 continue;
3580 for (val = ctxlat->values; val; val = val->next)
3582 known_contexts[i] = val->value;
3583 perform_estimation_of_a_value (node, known_csts, known_contexts,
3584 known_aggs,
3585 removable_params_cost, 0, val);
3587 if (dump_file && (dump_flags & TDF_DETAILS))
3589 fprintf (dump_file, " - estimates for polymorphic context ");
3590 print_ipcp_constant_value (dump_file, val->value);
3591 fprintf (dump_file, " for ");
3592 ipa_dump_param (dump_file, info, i);
3593 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
3594 val->local_time_benefit, val->local_size_cost);
3597 known_contexts[i] = ipa_polymorphic_call_context ();
3600 for (i = 0; i < count; i++)
3602 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3603 struct ipa_agg_value_set *agg;
3604 struct ipcp_agg_lattice *aglat;
3606 if (plats->aggs_bottom || !plats->aggs)
3607 continue;
3609 agg = &known_aggs[i];
3610 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3612 ipcp_value<tree> *val;
3613 if (aglat->bottom || !aglat->values
3614 /* If the following is true, the one value is in known_aggs. */
3615 || (!plats->aggs_contain_variable
3616 && aglat->is_single_const ()))
3617 continue;
3619 for (val = aglat->values; val; val = val->next)
3621 struct ipa_agg_value item;
3623 item.offset = aglat->offset;
3624 item.value = val->value;
3625 agg->items.safe_push (item);
3627 perform_estimation_of_a_value (node, known_csts, known_contexts,
3628 known_aggs,
3629 removable_params_cost, 0, val);
3631 if (dump_file && (dump_flags & TDF_DETAILS))
3633 fprintf (dump_file, " - estimates for value ");
3634 print_ipcp_constant_value (dump_file, val->value);
3635 fprintf (dump_file, " for ");
3636 ipa_dump_param (dump_file, info, i);
3637 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3638 "]: time_benefit: %i, size: %i\n",
3639 plats->aggs_by_ref ? "ref " : "",
3640 aglat->offset,
3641 val->local_time_benefit, val->local_size_cost);
3644 agg->items.pop ();
3649 known_csts.release ();
3650 known_contexts.release ();
3651 ipa_release_agg_values (known_aggs);
3655 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3656 topological sort of values. */
3658 template <typename valtype>
3659 void
3660 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3662 ipcp_value_source<valtype> *src;
3664 if (cur_val->dfs)
3665 return;
3667 dfs_counter++;
3668 cur_val->dfs = dfs_counter;
3669 cur_val->low_link = dfs_counter;
3671 cur_val->topo_next = stack;
3672 stack = cur_val;
3673 cur_val->on_stack = true;
3675 for (src = cur_val->sources; src; src = src->next)
3676 if (src->val)
3678 if (src->val->dfs == 0)
3680 add_val (src->val);
3681 if (src->val->low_link < cur_val->low_link)
3682 cur_val->low_link = src->val->low_link;
3684 else if (src->val->on_stack
3685 && src->val->dfs < cur_val->low_link)
3686 cur_val->low_link = src->val->dfs;
3689 if (cur_val->dfs == cur_val->low_link)
3691 ipcp_value<valtype> *v, *scc_list = NULL;
3695 v = stack;
3696 stack = v->topo_next;
3697 v->on_stack = false;
3699 v->scc_next = scc_list;
3700 scc_list = v;
3702 while (v != cur_val);
3704 cur_val->topo_next = values_topo;
3705 values_topo = cur_val;
3709 /* Add all values in lattices associated with NODE to the topological sort if
3710 they are not there yet. */
3712 static void
3713 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3715 class ipa_node_params *info = IPA_NODE_REF (node);
3716 int i, count = ipa_get_param_count (info);
3718 for (i = 0; i < count; i++)
3720 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3721 ipcp_lattice<tree> *lat = &plats->itself;
3722 struct ipcp_agg_lattice *aglat;
3724 if (!lat->bottom)
3726 ipcp_value<tree> *val;
3727 for (val = lat->values; val; val = val->next)
3728 topo->constants.add_val (val);
3731 if (!plats->aggs_bottom)
3732 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3733 if (!aglat->bottom)
3735 ipcp_value<tree> *val;
3736 for (val = aglat->values; val; val = val->next)
3737 topo->constants.add_val (val);
3740 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3741 if (!ctxlat->bottom)
3743 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3744 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3745 topo->contexts.add_val (ctxval);
3750 /* One pass of constants propagation along the call graph edges, from callers
3751 to callees (requires topological ordering in TOPO), iterate over strongly
3752 connected components. */
3754 static void
3755 propagate_constants_topo (class ipa_topo_info *topo)
3757 int i;
3759 for (i = topo->nnodes - 1; i >= 0; i--)
3761 unsigned j;
3762 struct cgraph_node *v, *node = topo->order[i];
3763 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3765 /* First, iteratively propagate within the strongly connected component
3766 until all lattices stabilize. */
3767 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3768 if (v->has_gimple_body_p ())
3770 if (opt_for_fn (v->decl, flag_ipa_cp)
3771 && opt_for_fn (v->decl, optimize))
3772 push_node_to_stack (topo, v);
3773 /* When V is not optimized, we can not push it to stack, but
3774 still we need to set all its callees lattices to bottom. */
3775 else
3777 for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
3778 propagate_constants_across_call (cs);
3782 v = pop_node_from_stack (topo);
3783 while (v)
3785 struct cgraph_edge *cs;
3786 class ipa_node_params *info = NULL;
3787 bool self_scc = true;
3789 for (cs = v->callees; cs; cs = cs->next_callee)
3790 if (ipa_edge_within_scc (cs))
3792 cgraph_node *callee = cs->callee->function_symbol ();
3794 if (v != callee)
3795 self_scc = false;
3797 if (!info)
3799 info = IPA_NODE_REF (v);
3800 info->node_within_scc = true;
3803 if (propagate_constants_across_call (cs))
3804 push_node_to_stack (topo, callee);
3807 if (info)
3808 info->node_is_self_scc = self_scc;
3810 v = pop_node_from_stack (topo);
3813 /* Afterwards, propagate along edges leading out of the SCC, calculates
3814 the local effects of the discovered constants and all valid values to
3815 their topological sort. */
3816 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3817 if (v->has_gimple_body_p ()
3818 && opt_for_fn (v->decl, flag_ipa_cp)
3819 && opt_for_fn (v->decl, optimize))
3821 struct cgraph_edge *cs;
3823 estimate_local_effects (v);
3824 add_all_node_vals_to_toposort (v, topo);
3825 for (cs = v->callees; cs; cs = cs->next_callee)
3826 if (!ipa_edge_within_scc (cs))
3827 propagate_constants_across_call (cs);
3829 cycle_nodes.release ();
3834 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3835 the bigger one if otherwise. */
3837 static int
3838 safe_add (int a, int b)
3840 if (a > INT_MAX/2 || b > INT_MAX/2)
3841 return a > b ? a : b;
3842 else
3843 return a + b;
3847 /* Propagate the estimated effects of individual values along the topological
3848 from the dependent values to those they depend on. */
3850 template <typename valtype>
3851 void
3852 value_topo_info<valtype>::propagate_effects ()
3854 ipcp_value<valtype> *base;
3856 for (base = values_topo; base; base = base->topo_next)
3858 ipcp_value_source<valtype> *src;
3859 ipcp_value<valtype> *val;
3860 int time = 0, size = 0;
3862 for (val = base; val; val = val->scc_next)
3864 time = safe_add (time,
3865 val->local_time_benefit + val->prop_time_benefit);
3866 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3869 for (val = base; val; val = val->scc_next)
3870 for (src = val->sources; src; src = src->next)
3871 if (src->val
3872 && src->cs->maybe_hot_p ())
3874 src->val->prop_time_benefit = safe_add (time,
3875 src->val->prop_time_benefit);
3876 src->val->prop_size_cost = safe_add (size,
3877 src->val->prop_size_cost);
3883 /* Propagate constants, polymorphic contexts and their effects from the
3884 summaries interprocedurally. */
3886 static void
3887 ipcp_propagate_stage (class ipa_topo_info *topo)
3889 struct cgraph_node *node;
3891 if (dump_file)
3892 fprintf (dump_file, "\n Propagating constants:\n\n");
3894 max_count = profile_count::uninitialized ();
3896 FOR_EACH_DEFINED_FUNCTION (node)
3898 if (node->has_gimple_body_p ()
3899 && opt_for_fn (node->decl, flag_ipa_cp)
3900 && opt_for_fn (node->decl, optimize))
3902 class ipa_node_params *info = IPA_NODE_REF (node);
3903 determine_versionability (node, info);
3905 unsigned nlattices = ipa_get_param_count (info);
3906 void *chunk = XCNEWVEC (class ipcp_param_lattices, nlattices);
3907 info->lattices = new (chunk) ipcp_param_lattices[nlattices];
3908 initialize_node_lattices (node);
3910 ipa_size_summary *s = ipa_size_summaries->get (node);
3911 if (node->definition && !node->alias && s != NULL)
3912 overall_size += s->self_size;
3913 max_count = max_count.max (node->count.ipa ());
3916 orig_overall_size = overall_size;
3918 if (dump_file)
3919 fprintf (dump_file, "\noverall_size: %li\n", overall_size);
3921 propagate_constants_topo (topo);
3922 if (flag_checking)
3923 ipcp_verify_propagated_values ();
3924 topo->constants.propagate_effects ();
3925 topo->contexts.propagate_effects ();
3927 if (dump_file)
3929 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3930 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3934 /* Discover newly direct outgoing edges from NODE which is a new clone with
3935 known KNOWN_CSTS and make them direct. */
3937 static void
3938 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3939 vec<tree> known_csts,
3940 vec<ipa_polymorphic_call_context>
3941 known_contexts,
3942 struct ipa_agg_replacement_value *aggvals)
3944 struct cgraph_edge *ie, *next_ie;
3945 bool found = false;
3947 for (ie = node->indirect_calls; ie; ie = next_ie)
3949 tree target;
3950 bool speculative;
3952 next_ie = ie->next_callee;
3953 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3954 vNULL, aggvals, &speculative);
3955 if (target)
3957 bool agg_contents = ie->indirect_info->agg_contents;
3958 bool polymorphic = ie->indirect_info->polymorphic;
3959 int param_index = ie->indirect_info->param_index;
3960 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3961 speculative);
3962 found = true;
3964 if (cs && !agg_contents && !polymorphic)
3966 class ipa_node_params *info = IPA_NODE_REF (node);
3967 int c = ipa_get_controlled_uses (info, param_index);
3968 if (c != IPA_UNDESCRIBED_USE)
3970 struct ipa_ref *to_del;
3972 c--;
3973 ipa_set_controlled_uses (info, param_index, c);
3974 if (dump_file && (dump_flags & TDF_DETAILS))
3975 fprintf (dump_file, " controlled uses count of param "
3976 "%i bumped down to %i\n", param_index, c);
3977 if (c == 0
3978 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3980 if (dump_file && (dump_flags & TDF_DETAILS))
3981 fprintf (dump_file, " and even removing its "
3982 "cloning-created reference\n");
3983 to_del->remove_reference ();
3989 /* Turning calls to direct calls will improve overall summary. */
3990 if (found)
3991 ipa_update_overall_fn_summary (node);
3994 class edge_clone_summary;
3995 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL;
3997 /* Edge clone summary. */
3999 class edge_clone_summary
4001 public:
4002 /* Default constructor. */
4003 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
4005 /* Default destructor. */
4006 ~edge_clone_summary ()
4008 if (prev_clone)
4009 edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
4010 if (next_clone)
4011 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
4014 cgraph_edge *prev_clone;
4015 cgraph_edge *next_clone;
4018 class edge_clone_summary_t:
4019 public call_summary <edge_clone_summary *>
4021 public:
4022 edge_clone_summary_t (symbol_table *symtab):
4023 call_summary <edge_clone_summary *> (symtab)
4025 m_initialize_when_cloning = true;
4028 virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4029 edge_clone_summary *src_data,
4030 edge_clone_summary *dst_data);
4033 /* Edge duplication hook. */
4035 void
4036 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4037 edge_clone_summary *src_data,
4038 edge_clone_summary *dst_data)
4040 if (src_data->next_clone)
4041 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
4042 dst_data->prev_clone = src_edge;
4043 dst_data->next_clone = src_data->next_clone;
4044 src_data->next_clone = dst_edge;
4047 /* Return true is CS calls DEST or its clone for all contexts. When
4048 ALLOW_RECURSION_TO_CLONE is false, also return false for self-recursive
4049 edges from/to an all-context clone. */
4051 static bool
4052 calls_same_node_or_its_all_contexts_clone_p (cgraph_edge *cs, cgraph_node *dest,
4053 bool allow_recursion_to_clone)
4055 enum availability availability;
4056 cgraph_node *callee = cs->callee->function_symbol (&availability);
4058 if (availability <= AVAIL_INTERPOSABLE)
4059 return false;
4060 if (callee == dest)
4061 return true;
4062 if (!allow_recursion_to_clone && cs->caller == callee)
4063 return false;
4065 class ipa_node_params *info = IPA_NODE_REF (callee);
4066 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
4069 /* Return true if edge CS does bring about the value described by SRC to
4070 DEST_VAL of node DEST or its clone for all contexts. */
4072 static bool
4073 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
4074 cgraph_node *dest, ipcp_value<tree> *dest_val)
4076 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4078 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, !src->val)
4079 || caller_info->node_dead)
4080 return false;
4082 if (!src->val)
4083 return true;
4085 if (caller_info->ipcp_orig_node)
4087 tree t;
4088 if (src->offset == -1)
4089 t = caller_info->known_csts[src->index];
4090 else
4091 t = get_clone_agg_value (cs->caller, src->offset, src->index);
4092 return (t != NULL_TREE
4093 && values_equal_for_ipcp_p (src->val->value, t));
4095 else
4097 if (src->val == dest_val)
4098 return true;
4100 struct ipcp_agg_lattice *aglat;
4101 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4102 src->index);
4103 if (src->offset == -1)
4104 return (plats->itself.is_single_const ()
4105 && values_equal_for_ipcp_p (src->val->value,
4106 plats->itself.values->value));
4107 else
4109 if (plats->aggs_bottom || plats->aggs_contain_variable)
4110 return false;
4111 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4112 if (aglat->offset == src->offset)
4113 return (aglat->is_single_const ()
4114 && values_equal_for_ipcp_p (src->val->value,
4115 aglat->values->value));
4117 return false;
4121 /* Return true if edge CS does bring about the value described by SRC to
4122 DST_VAL of node DEST or its clone for all contexts. */
4124 static bool
4125 cgraph_edge_brings_value_p (cgraph_edge *cs,
4126 ipcp_value_source<ipa_polymorphic_call_context> *src,
4127 cgraph_node *dest,
4128 ipcp_value<ipa_polymorphic_call_context> *)
4130 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4132 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, true)
4133 || caller_info->node_dead)
4134 return false;
4135 if (!src->val)
4136 return true;
4138 if (caller_info->ipcp_orig_node)
4139 return (caller_info->known_contexts.length () > (unsigned) src->index)
4140 && values_equal_for_ipcp_p (src->val->value,
4141 caller_info->known_contexts[src->index]);
4143 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4144 src->index);
4145 return plats->ctxlat.is_single_const ()
4146 && values_equal_for_ipcp_p (src->val->value,
4147 plats->ctxlat.values->value);
4150 /* Get the next clone in the linked list of clones of an edge. */
4152 static inline struct cgraph_edge *
4153 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
4155 edge_clone_summary *s = edge_clone_summaries->get (cs);
4156 return s != NULL ? s->next_clone : NULL;
4159 /* Given VAL that is intended for DEST, iterate over all its sources and if any
4160 of them is viable and hot, return true. In that case, for those that still
4161 hold, add their edge frequency and their number into *FREQUENCY and
4162 *CALLER_COUNT respectively. */
4164 template <typename valtype>
4165 static bool
4166 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
4167 int *freq_sum,
4168 profile_count *count_sum, int *caller_count)
4170 ipcp_value_source<valtype> *src;
4171 int freq = 0, count = 0;
4172 profile_count cnt = profile_count::zero ();
4173 bool hot = false;
4174 bool non_self_recursive = false;
4176 for (src = val->sources; src; src = src->next)
4178 struct cgraph_edge *cs = src->cs;
4179 while (cs)
4181 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4183 count++;
4184 freq += cs->frequency ();
4185 if (cs->count.ipa ().initialized_p ())
4186 cnt += cs->count.ipa ();
4187 hot |= cs->maybe_hot_p ();
4188 if (cs->caller != dest)
4189 non_self_recursive = true;
4191 cs = get_next_cgraph_edge_clone (cs);
4195 /* If the only edges bringing a value are self-recursive ones, do not bother
4196 evaluating it. */
4197 if (!non_self_recursive)
4198 return false;
4200 *freq_sum = freq;
4201 *count_sum = cnt;
4202 *caller_count = count;
4204 if (!hot && IPA_NODE_REF (dest)->node_within_scc)
4206 struct cgraph_edge *cs;
4208 /* Cold non-SCC source edge could trigger hot recursive execution of
4209 function. Consider the case as hot and rely on following cost model
4210 computation to further select right one. */
4211 for (cs = dest->callers; cs; cs = cs->next_caller)
4212 if (cs->caller == dest && cs->maybe_hot_p ())
4213 return true;
4216 return hot;
4219 /* Given a NODE, and a set of its CALLERS, try to adjust order of the callers
4220 to let a non-self-recursive caller be the first element. Thus, we can
4221 simplify intersecting operations on values that arrive from all of these
4222 callers, especially when there exists self-recursive call. Return true if
4223 this kind of adjustment is possible. */
4225 static bool
4226 adjust_callers_for_value_intersection (vec<cgraph_edge *> callers,
4227 cgraph_node *node)
4229 for (unsigned i = 0; i < callers.length (); i++)
4231 cgraph_edge *cs = callers[i];
4233 if (cs->caller != node)
4235 if (i > 0)
4237 callers[i] = callers[0];
4238 callers[0] = cs;
4240 return true;
4243 return false;
4246 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
4247 is assumed their number is known and equal to CALLER_COUNT. */
4249 template <typename valtype>
4250 static vec<cgraph_edge *>
4251 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
4252 int caller_count)
4254 ipcp_value_source<valtype> *src;
4255 vec<cgraph_edge *> ret;
4257 ret.create (caller_count);
4258 for (src = val->sources; src; src = src->next)
4260 struct cgraph_edge *cs = src->cs;
4261 while (cs)
4263 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4264 ret.quick_push (cs);
4265 cs = get_next_cgraph_edge_clone (cs);
4269 if (caller_count > 1)
4270 adjust_callers_for_value_intersection (ret, dest);
4272 return ret;
4275 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
4276 Return it or NULL if for some reason it cannot be created. */
4278 static struct ipa_replace_map *
4279 get_replacement_map (class ipa_node_params *info, tree value, int parm_num)
4281 struct ipa_replace_map *replace_map;
4283 replace_map = ggc_alloc<ipa_replace_map> ();
4284 if (dump_file)
4286 fprintf (dump_file, " replacing ");
4287 ipa_dump_param (dump_file, info, parm_num);
4289 fprintf (dump_file, " with const ");
4290 print_generic_expr (dump_file, value);
4291 fprintf (dump_file, "\n");
4293 replace_map->parm_num = parm_num;
4294 replace_map->new_tree = value;
4295 return replace_map;
4298 /* Dump new profiling counts */
4300 static void
4301 dump_profile_updates (struct cgraph_node *orig_node,
4302 struct cgraph_node *new_node)
4304 struct cgraph_edge *cs;
4306 fprintf (dump_file, " setting count of the specialized node to ");
4307 new_node->count.dump (dump_file);
4308 fprintf (dump_file, "\n");
4309 for (cs = new_node->callees; cs; cs = cs->next_callee)
4311 fprintf (dump_file, " edge to %s has count ",
4312 cs->callee->dump_name ());
4313 cs->count.dump (dump_file);
4314 fprintf (dump_file, "\n");
4317 fprintf (dump_file, " setting count of the original node to ");
4318 orig_node->count.dump (dump_file);
4319 fprintf (dump_file, "\n");
4320 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4322 fprintf (dump_file, " edge to %s is left with ",
4323 cs->callee->dump_name ());
4324 cs->count.dump (dump_file);
4325 fprintf (dump_file, "\n");
4329 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
4330 their profile information to reflect this. */
4332 static void
4333 update_profiling_info (struct cgraph_node *orig_node,
4334 struct cgraph_node *new_node)
4336 struct cgraph_edge *cs;
4337 struct caller_statistics stats;
4338 profile_count new_sum, orig_sum;
4339 profile_count remainder, orig_node_count = orig_node->count;
4340 profile_count orig_new_node_count = new_node->count;
4342 if (!(orig_node_count.ipa () > profile_count::zero ()))
4343 return;
4345 init_caller_stats (&stats);
4346 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
4347 false);
4348 orig_sum = stats.count_sum;
4349 init_caller_stats (&stats);
4350 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
4351 false);
4352 new_sum = stats.count_sum;
4354 if (orig_node_count < orig_sum + new_sum)
4356 if (dump_file)
4358 fprintf (dump_file, " Problem: node %s has too low count ",
4359 orig_node->dump_name ());
4360 orig_node_count.dump (dump_file);
4361 fprintf (dump_file, "while the sum of incoming count is ");
4362 (orig_sum + new_sum).dump (dump_file);
4363 fprintf (dump_file, "\n");
4366 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
4367 if (dump_file)
4369 fprintf (dump_file, " proceeding by pretending it was ");
4370 orig_node_count.dump (dump_file);
4371 fprintf (dump_file, "\n");
4375 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
4376 - new_sum.ipa ());
4378 /* With partial train run we do not want to assume that original's
4379 count is zero whenever we redurect all executed edges to clone.
4380 Simply drop profile to local one in this case. */
4381 if (remainder.ipa_p () && !remainder.ipa ().nonzero_p ()
4382 && orig_node->count.ipa_p () && orig_node->count.ipa ().nonzero_p ()
4383 && flag_profile_partial_training)
4384 remainder = remainder.guessed_local ();
4386 new_sum = orig_node_count.combine_with_ipa_count (new_sum);
4387 new_node->count = new_sum;
4388 orig_node->count = remainder;
4390 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_new_node_count);
4391 for (cs = new_node->callees; cs; cs = cs->next_callee)
4392 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4393 for (cs = new_node->indirect_calls; cs; cs = cs->next_callee)
4394 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4396 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
4397 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4398 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4399 for (cs = orig_node->indirect_calls; cs; cs = cs->next_callee)
4400 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4402 if (dump_file)
4403 dump_profile_updates (orig_node, new_node);
4406 /* Update the respective profile of specialized NEW_NODE and the original
4407 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
4408 have been redirected to the specialized version. */
4410 static void
4411 update_specialized_profile (struct cgraph_node *new_node,
4412 struct cgraph_node *orig_node,
4413 profile_count redirected_sum)
4415 struct cgraph_edge *cs;
4416 profile_count new_node_count, orig_node_count = orig_node->count;
4418 if (dump_file)
4420 fprintf (dump_file, " the sum of counts of redirected edges is ");
4421 redirected_sum.dump (dump_file);
4422 fprintf (dump_file, "\n");
4424 if (!(orig_node_count > profile_count::zero ()))
4425 return;
4427 gcc_assert (orig_node_count >= redirected_sum);
4429 new_node_count = new_node->count;
4430 new_node->count += redirected_sum;
4431 orig_node->count -= redirected_sum;
4433 for (cs = new_node->callees; cs; cs = cs->next_callee)
4434 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
4436 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4438 profile_count dec = cs->count.apply_scale (redirected_sum,
4439 orig_node_count);
4440 cs->count -= dec;
4443 if (dump_file)
4444 dump_profile_updates (orig_node, new_node);
4447 /* Return true if we would like to remove a parameter from NODE when cloning it
4448 with KNOWN_CSTS scalar constants. */
4450 static bool
4451 want_remove_some_param_p (cgraph_node *node, vec<tree> known_csts)
4453 auto_vec<bool, 16> surviving;
4454 bool filled_vec = false;
4455 ipa_node_params *info = IPA_NODE_REF (node);
4456 int i, count = ipa_get_param_count (info);
4458 for (i = 0; i < count; i++)
4460 if (!known_csts[i] && ipa_is_param_used (info, i))
4461 continue;
4463 if (!filled_vec)
4465 if (!node->clone.param_adjustments)
4466 return true;
4467 node->clone.param_adjustments->get_surviving_params (&surviving);
4468 filled_vec = true;
4470 if (surviving.length() < (unsigned) i && surviving[i])
4471 return true;
4473 return false;
4476 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
4477 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
4478 redirect all edges in CALLERS to it. */
4480 static struct cgraph_node *
4481 create_specialized_node (struct cgraph_node *node,
4482 vec<tree> known_csts,
4483 vec<ipa_polymorphic_call_context> known_contexts,
4484 struct ipa_agg_replacement_value *aggvals,
4485 vec<cgraph_edge *> callers)
4487 class ipa_node_params *new_info, *info = IPA_NODE_REF (node);
4488 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
4489 vec<ipa_adjusted_param, va_gc> *new_params = NULL;
4490 struct ipa_agg_replacement_value *av;
4491 struct cgraph_node *new_node;
4492 int i, count = ipa_get_param_count (info);
4493 ipa_param_adjustments *old_adjustments = node->clone.param_adjustments;
4494 ipa_param_adjustments *new_adjustments;
4495 gcc_assert (!info->ipcp_orig_node);
4496 gcc_assert (node->can_change_signature
4497 || !old_adjustments);
4499 if (old_adjustments)
4501 /* At the moment all IPA optimizations should use the number of
4502 parameters of the prevailing decl as the m_always_copy_start.
4503 Handling any other value would complicate the code below, so for the
4504 time bing let's only assert it is so. */
4505 gcc_assert (old_adjustments->m_always_copy_start == count
4506 || old_adjustments->m_always_copy_start < 0);
4507 int old_adj_count = vec_safe_length (old_adjustments->m_adj_params);
4508 for (i = 0; i < old_adj_count; i++)
4510 ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
4511 if (!node->can_change_signature
4512 || old_adj->op != IPA_PARAM_OP_COPY
4513 || (!known_csts[old_adj->base_index]
4514 && ipa_is_param_used (info, old_adj->base_index)))
4516 ipa_adjusted_param new_adj = *old_adj;
4518 new_adj.prev_clone_adjustment = true;
4519 new_adj.prev_clone_index = i;
4520 vec_safe_push (new_params, new_adj);
4523 bool skip_return = old_adjustments->m_skip_return;
4524 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
4525 ipa_param_adjustments (new_params, count,
4526 skip_return));
4528 else if (node->can_change_signature
4529 && want_remove_some_param_p (node, known_csts))
4531 ipa_adjusted_param adj;
4532 memset (&adj, 0, sizeof (adj));
4533 adj.op = IPA_PARAM_OP_COPY;
4534 for (i = 0; i < count; i++)
4535 if (!known_csts[i] && ipa_is_param_used (info, i))
4537 adj.base_index = i;
4538 adj.prev_clone_index = i;
4539 vec_safe_push (new_params, adj);
4541 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
4542 ipa_param_adjustments (new_params, count, false));
4544 else
4545 new_adjustments = NULL;
4547 replace_trees = vec_safe_copy (node->clone.tree_map);
4548 for (i = 0; i < count; i++)
4550 tree t = known_csts[i];
4551 if (t)
4553 struct ipa_replace_map *replace_map;
4555 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
4556 replace_map = get_replacement_map (info, t, i);
4557 if (replace_map)
4558 vec_safe_push (replace_trees, replace_map);
4561 auto_vec<cgraph_edge *, 2> self_recursive_calls;
4562 for (i = callers.length () - 1; i >= 0; i--)
4564 cgraph_edge *cs = callers[i];
4565 if (cs->caller == node)
4567 self_recursive_calls.safe_push (cs);
4568 callers.unordered_remove (i);
4572 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
4573 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
4574 node->decl)));
4575 new_node = node->create_virtual_clone (callers, replace_trees,
4576 new_adjustments, "constprop",
4577 suffix_counter);
4578 suffix_counter++;
4580 bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
4581 for (unsigned j = 0; j < self_recursive_calls.length (); j++)
4583 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
4584 /* Cloned edges can disappear during cloning as speculation can be
4585 resolved, check that we have one and that it comes from the last
4586 cloning. */
4587 if (cs && cs->caller == new_node)
4588 cs->redirect_callee_duplicating_thunks (new_node);
4589 /* Any future code that would make more than one clone of an outgoing
4590 edge would confuse this mechanism, so let's check that does not
4591 happen. */
4592 gcc_checking_assert (!cs
4593 || !get_next_cgraph_edge_clone (cs)
4594 || get_next_cgraph_edge_clone (cs)->caller != new_node);
4596 if (have_self_recursive_calls)
4597 new_node->expand_all_artificial_thunks ();
4599 ipa_set_node_agg_value_chain (new_node, aggvals);
4600 for (av = aggvals; av; av = av->next)
4601 new_node->maybe_create_reference (av->value, NULL);
4603 if (dump_file && (dump_flags & TDF_DETAILS))
4605 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
4606 if (known_contexts.exists ())
4608 for (i = 0; i < count; i++)
4609 if (!known_contexts[i].useless_p ())
4611 fprintf (dump_file, " known ctx %i is ", i);
4612 known_contexts[i].dump (dump_file);
4615 if (aggvals)
4616 ipa_dump_agg_replacement_values (dump_file, aggvals);
4618 ipa_check_create_node_params ();
4619 update_profiling_info (node, new_node);
4620 new_info = IPA_NODE_REF (new_node);
4621 new_info->ipcp_orig_node = node;
4622 new_node->ipcp_clone = true;
4623 new_info->known_csts = known_csts;
4624 new_info->known_contexts = known_contexts;
4626 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
4628 callers.release ();
4629 return new_node;
4632 /* Return true if JFUNC, which describes a i-th parameter of call CS, is a
4633 pass-through function to itself when the cgraph_node involved is not an
4634 IPA-CP clone. When SIMPLE is true, further check if JFUNC is a simple
4635 no-operation pass-through. */
4637 static bool
4638 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i,
4639 bool simple = true)
4641 enum availability availability;
4642 if (cs->caller == cs->callee->function_symbol (&availability)
4643 && availability > AVAIL_INTERPOSABLE
4644 && jfunc->type == IPA_JF_PASS_THROUGH
4645 && (!simple || ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4646 && ipa_get_jf_pass_through_formal_id (jfunc) == i
4647 && IPA_NODE_REF (cs->caller)
4648 && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
4649 return true;
4650 return false;
4653 /* Return true if JFUNC, which describes a part of an aggregate represented or
4654 pointed to by the i-th parameter of call CS, is a pass-through function to
4655 itself when the cgraph_node involved is not an IPA-CP clone.. When
4656 SIMPLE is true, further check if JFUNC is a simple no-operation
4657 pass-through. */
4659 static bool
4660 self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
4661 int i, bool simple = true)
4663 enum availability availability;
4664 if (cs->caller == cs->callee->function_symbol (&availability)
4665 && availability > AVAIL_INTERPOSABLE
4666 && jfunc->jftype == IPA_JF_LOAD_AGG
4667 && jfunc->offset == jfunc->value.load_agg.offset
4668 && (!simple || jfunc->value.pass_through.operation == NOP_EXPR)
4669 && jfunc->value.pass_through.formal_id == i
4670 && useless_type_conversion_p (jfunc->value.load_agg.type, jfunc->type)
4671 && IPA_NODE_REF (cs->caller)
4672 && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
4673 return true;
4674 return false;
4677 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
4678 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
4680 static void
4681 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
4682 vec<tree> known_csts,
4683 vec<cgraph_edge *> callers)
4685 class ipa_node_params *info = IPA_NODE_REF (node);
4686 int i, count = ipa_get_param_count (info);
4688 for (i = 0; i < count; i++)
4690 struct cgraph_edge *cs;
4691 tree newval = NULL_TREE;
4692 int j;
4693 bool first = true;
4694 tree type = ipa_get_type (info, i);
4696 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
4697 continue;
4699 FOR_EACH_VEC_ELT (callers, j, cs)
4701 struct ipa_jump_func *jump_func;
4702 tree t;
4704 if (!IPA_EDGE_REF (cs)
4705 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
4706 || (i == 0
4707 && call_passes_through_thunk_p (cs)))
4709 newval = NULL_TREE;
4710 break;
4712 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
4714 /* Besides simple pass-through jump function, arithmetic jump
4715 function could also introduce argument-direct-pass-through for
4716 self-feeding recursive call. For example,
4718 fn (int i)
4720 fn (i & 1);
4723 Given that i is 0, recursive propagation via (i & 1) also gets
4724 0. */
4725 if (self_recursive_pass_through_p (cs, jump_func, i, false))
4727 gcc_assert (newval);
4728 t = ipa_get_jf_arith_result (
4729 ipa_get_jf_pass_through_operation (jump_func),
4730 newval,
4731 ipa_get_jf_pass_through_operand (jump_func),
4732 type);
4734 else
4735 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func,
4736 type);
4737 if (!t
4738 || (newval
4739 && !values_equal_for_ipcp_p (t, newval))
4740 || (!first && !newval))
4742 newval = NULL_TREE;
4743 break;
4745 else
4746 newval = t;
4747 first = false;
4750 if (newval)
4752 if (dump_file && (dump_flags & TDF_DETAILS))
4754 fprintf (dump_file, " adding an extra known scalar value ");
4755 print_ipcp_constant_value (dump_file, newval);
4756 fprintf (dump_file, " for ");
4757 ipa_dump_param (dump_file, info, i);
4758 fprintf (dump_file, "\n");
4761 known_csts[i] = newval;
4766 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
4767 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
4768 CALLERS. */
4770 static void
4771 find_more_contexts_for_caller_subset (cgraph_node *node,
4772 vec<ipa_polymorphic_call_context>
4773 *known_contexts,
4774 vec<cgraph_edge *> callers)
4776 ipa_node_params *info = IPA_NODE_REF (node);
4777 int i, count = ipa_get_param_count (info);
4779 for (i = 0; i < count; i++)
4781 cgraph_edge *cs;
4783 if (ipa_get_poly_ctx_lat (info, i)->bottom
4784 || (known_contexts->exists ()
4785 && !(*known_contexts)[i].useless_p ()))
4786 continue;
4788 ipa_polymorphic_call_context newval;
4789 bool first = true;
4790 int j;
4792 FOR_EACH_VEC_ELT (callers, j, cs)
4794 if (!IPA_EDGE_REF (cs)
4795 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
4796 return;
4797 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
4799 ipa_polymorphic_call_context ctx;
4800 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
4801 jfunc);
4802 if (first)
4804 newval = ctx;
4805 first = false;
4807 else
4808 newval.meet_with (ctx);
4809 if (newval.useless_p ())
4810 break;
4813 if (!newval.useless_p ())
4815 if (dump_file && (dump_flags & TDF_DETAILS))
4817 fprintf (dump_file, " adding an extra known polymorphic "
4818 "context ");
4819 print_ipcp_constant_value (dump_file, newval);
4820 fprintf (dump_file, " for ");
4821 ipa_dump_param (dump_file, info, i);
4822 fprintf (dump_file, "\n");
4825 if (!known_contexts->exists ())
4826 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
4827 (*known_contexts)[i] = newval;
4833 /* Go through PLATS and create a vector of values consisting of values and
4834 offsets (minus OFFSET) of lattices that contain only a single value. */
4836 static vec<ipa_agg_value>
4837 copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset)
4839 vec<ipa_agg_value> res = vNULL;
4841 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4842 return vNULL;
4844 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
4845 if (aglat->is_single_const ())
4847 struct ipa_agg_value ti;
4848 ti.offset = aglat->offset - offset;
4849 ti.value = aglat->values->value;
4850 res.safe_push (ti);
4852 return res;
4855 /* Intersect all values in INTER with single value lattices in PLATS (while
4856 subtracting OFFSET). */
4858 static void
4859 intersect_with_plats (class ipcp_param_lattices *plats,
4860 vec<ipa_agg_value> *inter,
4861 HOST_WIDE_INT offset)
4863 struct ipcp_agg_lattice *aglat;
4864 struct ipa_agg_value *item;
4865 int k;
4867 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4869 inter->release ();
4870 return;
4873 aglat = plats->aggs;
4874 FOR_EACH_VEC_ELT (*inter, k, item)
4876 bool found = false;
4877 if (!item->value)
4878 continue;
4879 while (aglat)
4881 if (aglat->offset - offset > item->offset)
4882 break;
4883 if (aglat->offset - offset == item->offset)
4885 if (aglat->is_single_const ())
4887 tree value = aglat->values->value;
4889 if (values_equal_for_ipcp_p (item->value, value))
4890 found = true;
4892 break;
4894 aglat = aglat->next;
4896 if (!found)
4897 item->value = NULL_TREE;
4901 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4902 vector result while subtracting OFFSET from the individual value offsets. */
4904 static vec<ipa_agg_value>
4905 agg_replacements_to_vector (struct cgraph_node *node, int index,
4906 HOST_WIDE_INT offset)
4908 struct ipa_agg_replacement_value *av;
4909 vec<ipa_agg_value> res = vNULL;
4911 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4912 if (av->index == index
4913 && (av->offset - offset) >= 0)
4915 struct ipa_agg_value item;
4916 gcc_checking_assert (av->value);
4917 item.offset = av->offset - offset;
4918 item.value = av->value;
4919 res.safe_push (item);
4922 return res;
4925 /* Intersect all values in INTER with those that we have already scheduled to
4926 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4927 (while subtracting OFFSET). */
4929 static void
4930 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4931 vec<ipa_agg_value> *inter,
4932 HOST_WIDE_INT offset)
4934 struct ipa_agg_replacement_value *srcvals;
4935 struct ipa_agg_value *item;
4936 int i;
4938 srcvals = ipa_get_agg_replacements_for_node (node);
4939 if (!srcvals)
4941 inter->release ();
4942 return;
4945 FOR_EACH_VEC_ELT (*inter, i, item)
4947 struct ipa_agg_replacement_value *av;
4948 bool found = false;
4949 if (!item->value)
4950 continue;
4951 for (av = srcvals; av; av = av->next)
4953 gcc_checking_assert (av->value);
4954 if (av->index == index
4955 && av->offset - offset == item->offset)
4957 if (values_equal_for_ipcp_p (item->value, av->value))
4958 found = true;
4959 break;
4962 if (!found)
4963 item->value = NULL_TREE;
4967 /* Intersect values in INTER with aggregate values that come along edge CS to
4968 parameter number INDEX and return it. If INTER does not actually exist yet,
4969 copy all incoming values to it. If we determine we ended up with no values
4970 whatsoever, return a released vector. */
4972 static vec<ipa_agg_value>
4973 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4974 vec<ipa_agg_value> inter)
4976 struct ipa_jump_func *jfunc;
4977 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4978 if (jfunc->type == IPA_JF_PASS_THROUGH
4979 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4981 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4982 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4984 if (caller_info->ipcp_orig_node)
4986 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4987 class ipcp_param_lattices *orig_plats;
4988 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4989 src_idx);
4990 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4992 if (!inter.exists ())
4993 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4994 else
4995 intersect_with_agg_replacements (cs->caller, src_idx,
4996 &inter, 0);
4997 return inter;
5000 else
5002 class ipcp_param_lattices *src_plats;
5003 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
5004 if (agg_pass_through_permissible_p (src_plats, jfunc))
5006 /* Currently we do not produce clobber aggregate jump
5007 functions, adjust when we do. */
5008 gcc_checking_assert (!jfunc->agg.items);
5009 if (!inter.exists ())
5010 inter = copy_plats_to_inter (src_plats, 0);
5011 else
5012 intersect_with_plats (src_plats, &inter, 0);
5013 return inter;
5017 else if (jfunc->type == IPA_JF_ANCESTOR
5018 && ipa_get_jf_ancestor_agg_preserved (jfunc))
5020 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5021 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
5022 class ipcp_param_lattices *src_plats;
5023 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
5025 if (caller_info->ipcp_orig_node)
5027 if (!inter.exists ())
5028 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
5029 else
5030 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
5031 delta);
5033 else
5035 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
5036 /* Currently we do not produce clobber aggregate jump
5037 functions, adjust when we do. */
5038 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
5039 if (!inter.exists ())
5040 inter = copy_plats_to_inter (src_plats, delta);
5041 else
5042 intersect_with_plats (src_plats, &inter, delta);
5044 return inter;
5047 if (jfunc->agg.items)
5049 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5050 struct ipa_agg_value *item;
5051 int k;
5053 if (!inter.exists ())
5054 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
5056 struct ipa_agg_jf_item *agg_item = &(*jfunc->agg.items)[i];
5057 tree value = ipa_agg_value_from_node (caller_info, cs->caller,
5058 agg_item);
5059 if (value)
5061 struct ipa_agg_value agg_value;
5063 agg_value.value = value;
5064 agg_value.offset = agg_item->offset;
5065 inter.safe_push (agg_value);
5068 else
5069 FOR_EACH_VEC_ELT (inter, k, item)
5071 int l = 0;
5072 bool found = false;
5074 if (!item->value)
5075 continue;
5077 while ((unsigned) l < jfunc->agg.items->length ())
5079 struct ipa_agg_jf_item *ti;
5080 ti = &(*jfunc->agg.items)[l];
5081 if (ti->offset > item->offset)
5082 break;
5083 if (ti->offset == item->offset)
5085 tree value;
5087 /* Besides simple pass-through aggregate jump function,
5088 arithmetic aggregate jump function could also bring
5089 same aggregate value as parameter passed-in for
5090 self-feeding recursive call. For example,
5092 fn (int *i)
5094 int j = *i & 1;
5095 fn (&j);
5098 Given that *i is 0, recursive propagation via (*i & 1)
5099 also gets 0. */
5100 if (self_recursive_agg_pass_through_p (cs, ti, index,
5101 false))
5102 value = ipa_get_jf_arith_result (
5103 ti->value.pass_through.operation,
5104 item->value,
5105 ti->value.pass_through.operand,
5106 ti->type);
5107 else
5108 value = ipa_agg_value_from_node (caller_info,
5109 cs->caller, ti);
5111 if (value && values_equal_for_ipcp_p (item->value, value))
5112 found = true;
5113 break;
5115 l++;
5117 if (!found)
5118 item->value = NULL;
5121 else
5123 inter.release ();
5124 return vNULL;
5126 return inter;
5129 /* Look at edges in CALLERS and collect all known aggregate values that arrive
5130 from all of them. */
5132 static struct ipa_agg_replacement_value *
5133 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
5134 vec<cgraph_edge *> callers)
5136 class ipa_node_params *dest_info = IPA_NODE_REF (node);
5137 struct ipa_agg_replacement_value *res;
5138 struct ipa_agg_replacement_value **tail = &res;
5139 struct cgraph_edge *cs;
5140 int i, j, count = ipa_get_param_count (dest_info);
5142 FOR_EACH_VEC_ELT (callers, j, cs)
5144 if (!IPA_EDGE_REF (cs))
5146 count = 0;
5147 break;
5149 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
5150 if (c < count)
5151 count = c;
5154 for (i = 0; i < count; i++)
5156 struct cgraph_edge *cs;
5157 vec<ipa_agg_value> inter = vNULL;
5158 struct ipa_agg_value *item;
5159 class ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
5160 int j;
5162 /* Among other things, the following check should deal with all by_ref
5163 mismatches. */
5164 if (plats->aggs_bottom)
5165 continue;
5167 FOR_EACH_VEC_ELT (callers, j, cs)
5169 struct ipa_jump_func *jfunc
5170 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
5171 if (self_recursive_pass_through_p (cs, jfunc, i)
5172 && (!plats->aggs_by_ref
5173 || ipa_get_jf_pass_through_agg_preserved (jfunc)))
5174 continue;
5175 inter = intersect_aggregates_with_edge (cs, i, inter);
5177 if (!inter.exists ())
5178 goto next_param;
5181 FOR_EACH_VEC_ELT (inter, j, item)
5183 struct ipa_agg_replacement_value *v;
5185 if (!item->value)
5186 continue;
5188 v = ggc_alloc<ipa_agg_replacement_value> ();
5189 v->index = i;
5190 v->offset = item->offset;
5191 v->value = item->value;
5192 v->by_ref = plats->aggs_by_ref;
5193 *tail = v;
5194 tail = &v->next;
5197 next_param:
5198 if (inter.exists ())
5199 inter.release ();
5201 *tail = NULL;
5202 return res;
5205 /* Determine whether CS also brings all scalar values that the NODE is
5206 specialized for. */
5208 static bool
5209 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
5210 struct cgraph_node *node)
5212 class ipa_node_params *dest_info = IPA_NODE_REF (node);
5213 int count = ipa_get_param_count (dest_info);
5214 class ipa_node_params *caller_info;
5215 class ipa_edge_args *args;
5216 int i;
5218 caller_info = IPA_NODE_REF (cs->caller);
5219 args = IPA_EDGE_REF (cs);
5220 for (i = 0; i < count; i++)
5222 struct ipa_jump_func *jump_func;
5223 tree val, t;
5225 val = dest_info->known_csts[i];
5226 if (!val)
5227 continue;
5229 if (i >= ipa_get_cs_argument_count (args))
5230 return false;
5231 jump_func = ipa_get_ith_jump_func (args, i);
5232 t = ipa_value_from_jfunc (caller_info, jump_func,
5233 ipa_get_type (dest_info, i));
5234 if (!t || !values_equal_for_ipcp_p (val, t))
5235 return false;
5237 return true;
5240 /* Determine whether CS also brings all aggregate values that NODE is
5241 specialized for. */
5242 static bool
5243 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
5244 struct cgraph_node *node)
5246 class ipa_node_params *orig_node_info;
5247 struct ipa_agg_replacement_value *aggval;
5248 int i, ec, count;
5250 aggval = ipa_get_agg_replacements_for_node (node);
5251 if (!aggval)
5252 return true;
5254 count = ipa_get_param_count (IPA_NODE_REF (node));
5255 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
5256 if (ec < count)
5257 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5258 if (aggval->index >= ec)
5259 return false;
5261 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
5263 for (i = 0; i < count; i++)
5265 class ipcp_param_lattices *plats;
5266 bool interesting = false;
5267 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5268 if (aggval->index == i)
5270 interesting = true;
5271 break;
5273 if (!interesting)
5274 continue;
5276 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
5277 if (plats->aggs_bottom)
5278 return false;
5280 vec<ipa_agg_value> values = intersect_aggregates_with_edge (cs, i, vNULL);
5281 if (!values.exists ())
5282 return false;
5284 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5285 if (aggval->index == i)
5287 struct ipa_agg_value *item;
5288 int j;
5289 bool found = false;
5290 FOR_EACH_VEC_ELT (values, j, item)
5291 if (item->value
5292 && item->offset == av->offset
5293 && values_equal_for_ipcp_p (item->value, av->value))
5295 found = true;
5296 break;
5298 if (!found)
5300 values.release ();
5301 return false;
5304 values.release ();
5306 return true;
5309 /* Given an original NODE and a VAL for which we have already created a
5310 specialized clone, look whether there are incoming edges that still lead
5311 into the old node but now also bring the requested value and also conform to
5312 all other criteria such that they can be redirected the special node.
5313 This function can therefore redirect the final edge in a SCC. */
5315 template <typename valtype>
5316 static void
5317 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
5319 ipcp_value_source<valtype> *src;
5320 profile_count redirected_sum = profile_count::zero ();
5322 for (src = val->sources; src; src = src->next)
5324 struct cgraph_edge *cs = src->cs;
5325 while (cs)
5327 if (cgraph_edge_brings_value_p (cs, src, node, val)
5328 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
5329 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
5331 if (dump_file)
5332 fprintf (dump_file, " - adding an extra caller %s of %s\n",
5333 cs->caller->dump_name (),
5334 val->spec_node->dump_name ());
5336 cs->redirect_callee_duplicating_thunks (val->spec_node);
5337 val->spec_node->expand_all_artificial_thunks ();
5338 if (cs->count.ipa ().initialized_p ())
5339 redirected_sum = redirected_sum + cs->count.ipa ();
5341 cs = get_next_cgraph_edge_clone (cs);
5345 if (redirected_sum.nonzero_p ())
5346 update_specialized_profile (val->spec_node, node, redirected_sum);
5349 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
5351 static bool
5352 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
5354 ipa_polymorphic_call_context *ctx;
5355 int i;
5357 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
5358 if (!ctx->useless_p ())
5359 return true;
5360 return false;
5363 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
5365 static vec<ipa_polymorphic_call_context>
5366 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
5368 if (known_contexts_useful_p (known_contexts))
5369 return known_contexts.copy ();
5370 else
5371 return vNULL;
5374 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
5375 non-empty, replace KNOWN_CONTEXTS with its copy too. */
5377 static void
5378 modify_known_vectors_with_val (vec<tree> *known_csts,
5379 vec<ipa_polymorphic_call_context> *known_contexts,
5380 ipcp_value<tree> *val,
5381 int index)
5383 *known_csts = known_csts->copy ();
5384 *known_contexts = copy_useful_known_contexts (*known_contexts);
5385 (*known_csts)[index] = val->value;
5388 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
5389 copy according to VAL and INDEX. */
5391 static void
5392 modify_known_vectors_with_val (vec<tree> *known_csts,
5393 vec<ipa_polymorphic_call_context> *known_contexts,
5394 ipcp_value<ipa_polymorphic_call_context> *val,
5395 int index)
5397 *known_csts = known_csts->copy ();
5398 *known_contexts = known_contexts->copy ();
5399 (*known_contexts)[index] = val->value;
5402 /* Return true if OFFSET indicates this was not an aggregate value or there is
5403 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
5404 AGGVALS list. */
5406 DEBUG_FUNCTION bool
5407 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
5408 int index, HOST_WIDE_INT offset, tree value)
5410 if (offset == -1)
5411 return true;
5413 while (aggvals)
5415 if (aggvals->index == index
5416 && aggvals->offset == offset
5417 && values_equal_for_ipcp_p (aggvals->value, value))
5418 return true;
5419 aggvals = aggvals->next;
5421 return false;
5424 /* Return true if offset is minus one because source of a polymorphic context
5425 cannot be an aggregate value. */
5427 DEBUG_FUNCTION bool
5428 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
5429 int , HOST_WIDE_INT offset,
5430 ipa_polymorphic_call_context)
5432 return offset == -1;
5435 /* Decide whether to create a special version of NODE for value VAL of parameter
5436 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
5437 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
5438 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
5440 template <typename valtype>
5441 static bool
5442 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
5443 ipcp_value<valtype> *val, vec<tree> known_csts,
5444 vec<ipa_polymorphic_call_context> known_contexts)
5446 struct ipa_agg_replacement_value *aggvals;
5447 int freq_sum, caller_count;
5448 profile_count count_sum;
5449 vec<cgraph_edge *> callers;
5451 if (val->spec_node)
5453 perhaps_add_new_callers (node, val);
5454 return false;
5456 else if (val->local_size_cost + overall_size > get_max_overall_size (node))
5458 if (dump_file && (dump_flags & TDF_DETAILS))
5459 fprintf (dump_file, " Ignoring candidate value because "
5460 "maximum unit size would be reached with %li.\n",
5461 val->local_size_cost + overall_size);
5462 return false;
5464 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
5465 &caller_count))
5466 return false;
5468 if (dump_file && (dump_flags & TDF_DETAILS))
5470 fprintf (dump_file, " - considering value ");
5471 print_ipcp_constant_value (dump_file, val->value);
5472 fprintf (dump_file, " for ");
5473 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
5474 if (offset != -1)
5475 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
5476 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
5479 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
5480 freq_sum, count_sum,
5481 val->local_size_cost)
5482 && !good_cloning_opportunity_p (node,
5483 val->local_time_benefit
5484 + val->prop_time_benefit,
5485 freq_sum, count_sum,
5486 val->local_size_cost
5487 + val->prop_size_cost))
5488 return false;
5490 if (dump_file)
5491 fprintf (dump_file, " Creating a specialized node of %s.\n",
5492 node->dump_name ());
5494 callers = gather_edges_for_value (val, node, caller_count);
5495 if (offset == -1)
5496 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
5497 else
5499 known_csts = known_csts.copy ();
5500 known_contexts = copy_useful_known_contexts (known_contexts);
5502 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
5503 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
5504 aggvals = find_aggregate_values_for_callers_subset (node, callers);
5505 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
5506 offset, val->value));
5507 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
5508 aggvals, callers);
5509 overall_size += val->local_size_cost;
5511 /* TODO: If for some lattice there is only one other known value
5512 left, make a special node for it too. */
5514 return true;
5517 /* Decide whether and what specialized clones of NODE should be created. */
5519 static bool
5520 decide_whether_version_node (struct cgraph_node *node)
5522 class ipa_node_params *info = IPA_NODE_REF (node);
5523 int i, count = ipa_get_param_count (info);
5524 vec<tree> known_csts;
5525 vec<ipa_polymorphic_call_context> known_contexts;
5526 bool ret = false;
5528 if (count == 0)
5529 return false;
5531 if (dump_file && (dump_flags & TDF_DETAILS))
5532 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
5533 node->dump_name ());
5535 gather_context_independent_values (info, &known_csts, &known_contexts,
5536 NULL, NULL);
5538 for (i = 0; i < count;i++)
5540 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5541 ipcp_lattice<tree> *lat = &plats->itself;
5542 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
5544 if (!lat->bottom
5545 && !known_csts[i])
5547 ipcp_value<tree> *val;
5548 for (val = lat->values; val; val = val->next)
5549 ret |= decide_about_value (node, i, -1, val, known_csts,
5550 known_contexts);
5553 if (!plats->aggs_bottom)
5555 struct ipcp_agg_lattice *aglat;
5556 ipcp_value<tree> *val;
5557 for (aglat = plats->aggs; aglat; aglat = aglat->next)
5558 if (!aglat->bottom && aglat->values
5559 /* If the following is false, the one value is in
5560 known_aggs. */
5561 && (plats->aggs_contain_variable
5562 || !aglat->is_single_const ()))
5563 for (val = aglat->values; val; val = val->next)
5564 ret |= decide_about_value (node, i, aglat->offset, val,
5565 known_csts, known_contexts);
5568 if (!ctxlat->bottom
5569 && known_contexts[i].useless_p ())
5571 ipcp_value<ipa_polymorphic_call_context> *val;
5572 for (val = ctxlat->values; val; val = val->next)
5573 ret |= decide_about_value (node, i, -1, val, known_csts,
5574 known_contexts);
5577 info = IPA_NODE_REF (node);
5580 if (info->do_clone_for_all_contexts)
5582 struct cgraph_node *clone;
5583 vec<cgraph_edge *> callers = node->collect_callers ();
5585 for (int i = callers.length () - 1; i >= 0; i--)
5587 cgraph_edge *cs = callers[i];
5588 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5590 if (caller_info && caller_info->node_dead)
5591 callers.unordered_remove (i);
5594 if (!adjust_callers_for_value_intersection (callers, node))
5596 /* If node is not called by anyone, or all its caller edges are
5597 self-recursive, the node is not really be in use, no need to
5598 do cloning. */
5599 callers.release ();
5600 known_csts.release ();
5601 known_contexts.release ();
5602 info->do_clone_for_all_contexts = false;
5603 return ret;
5606 if (dump_file)
5607 fprintf (dump_file, " - Creating a specialized node of %s "
5608 "for all known contexts.\n", node->dump_name ());
5610 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
5611 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
5612 ipa_agg_replacement_value *aggvals
5613 = find_aggregate_values_for_callers_subset (node, callers);
5615 if (!known_contexts_useful_p (known_contexts))
5617 known_contexts.release ();
5618 known_contexts = vNULL;
5620 clone = create_specialized_node (node, known_csts, known_contexts,
5621 aggvals, callers);
5622 info = IPA_NODE_REF (node);
5623 info->do_clone_for_all_contexts = false;
5624 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
5625 ret = true;
5627 else
5629 known_csts.release ();
5630 known_contexts.release ();
5633 return ret;
5636 /* Transitively mark all callees of NODE within the same SCC as not dead. */
5638 static void
5639 spread_undeadness (struct cgraph_node *node)
5641 struct cgraph_edge *cs;
5643 for (cs = node->callees; cs; cs = cs->next_callee)
5644 if (ipa_edge_within_scc (cs))
5646 struct cgraph_node *callee;
5647 class ipa_node_params *info;
5649 callee = cs->callee->function_symbol (NULL);
5650 info = IPA_NODE_REF (callee);
5652 if (info && info->node_dead)
5654 info->node_dead = 0;
5655 spread_undeadness (callee);
5660 /* Return true if NODE has a caller from outside of its SCC that is not
5661 dead. Worker callback for cgraph_for_node_and_aliases. */
5663 static bool
5664 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
5665 void *data ATTRIBUTE_UNUSED)
5667 struct cgraph_edge *cs;
5669 for (cs = node->callers; cs; cs = cs->next_caller)
5670 if (cs->caller->thunk.thunk_p
5671 && cs->caller->call_for_symbol_thunks_and_aliases
5672 (has_undead_caller_from_outside_scc_p, NULL, true))
5673 return true;
5674 else if (!ipa_edge_within_scc (cs)
5675 && (!IPA_NODE_REF (cs->caller) /* Unoptimized caller. */
5676 || !IPA_NODE_REF (cs->caller)->node_dead))
5677 return true;
5678 return false;
5682 /* Identify nodes within the same SCC as NODE which are no longer needed
5683 because of new clones and will be removed as unreachable. */
5685 static void
5686 identify_dead_nodes (struct cgraph_node *node)
5688 struct cgraph_node *v;
5689 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5690 if (v->local
5691 && IPA_NODE_REF (v)
5692 && !v->call_for_symbol_thunks_and_aliases
5693 (has_undead_caller_from_outside_scc_p, NULL, true))
5694 IPA_NODE_REF (v)->node_dead = 1;
5696 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5697 if (IPA_NODE_REF (v) && !IPA_NODE_REF (v)->node_dead)
5698 spread_undeadness (v);
5700 if (dump_file && (dump_flags & TDF_DETAILS))
5702 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5703 if (IPA_NODE_REF (v) && IPA_NODE_REF (v)->node_dead)
5704 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
5708 /* The decision stage. Iterate over the topological order of call graph nodes
5709 TOPO and make specialized clones if deemed beneficial. */
5711 static void
5712 ipcp_decision_stage (class ipa_topo_info *topo)
5714 int i;
5716 if (dump_file)
5717 fprintf (dump_file, "\nIPA decision stage:\n\n");
5719 for (i = topo->nnodes - 1; i >= 0; i--)
5721 struct cgraph_node *node = topo->order[i];
5722 bool change = false, iterate = true;
5724 while (iterate)
5726 struct cgraph_node *v;
5727 iterate = false;
5728 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5729 if (v->has_gimple_body_p ()
5730 && ipcp_versionable_function_p (v))
5731 iterate |= decide_whether_version_node (v);
5733 change |= iterate;
5735 if (change)
5736 identify_dead_nodes (node);
5740 /* Look up all the bits information that we have discovered and copy it over
5741 to the transformation summary. */
5743 static void
5744 ipcp_store_bits_results (void)
5746 cgraph_node *node;
5748 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5750 ipa_node_params *info = IPA_NODE_REF (node);
5751 bool dumped_sth = false;
5752 bool found_useful_result = false;
5754 if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
5756 if (dump_file)
5757 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
5758 "; -fipa-bit-cp: disabled.\n",
5759 node->dump_name ());
5760 continue;
5763 if (info->ipcp_orig_node)
5764 info = IPA_NODE_REF (info->ipcp_orig_node);
5765 if (!info->lattices)
5766 /* Newly expanded artificial thunks do not have lattices. */
5767 continue;
5769 unsigned count = ipa_get_param_count (info);
5770 for (unsigned i = 0; i < count; i++)
5772 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5773 if (plats->bits_lattice.constant_p ())
5775 found_useful_result = true;
5776 break;
5780 if (!found_useful_result)
5781 continue;
5783 ipcp_transformation_initialize ();
5784 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5785 vec_safe_reserve_exact (ts->bits, count);
5787 for (unsigned i = 0; i < count; i++)
5789 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5790 ipa_bits *jfbits;
5792 if (plats->bits_lattice.constant_p ())
5794 jfbits
5795 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
5796 plats->bits_lattice.get_mask ());
5797 if (!dbg_cnt (ipa_cp_bits))
5798 jfbits = NULL;
5800 else
5801 jfbits = NULL;
5803 ts->bits->quick_push (jfbits);
5804 if (!dump_file || !jfbits)
5805 continue;
5806 if (!dumped_sth)
5808 fprintf (dump_file, "Propagated bits info for function %s:\n",
5809 node->dump_name ());
5810 dumped_sth = true;
5812 fprintf (dump_file, " param %i: value = ", i);
5813 print_hex (jfbits->value, dump_file);
5814 fprintf (dump_file, ", mask = ");
5815 print_hex (jfbits->mask, dump_file);
5816 fprintf (dump_file, "\n");
5821 /* Look up all VR information that we have discovered and copy it over
5822 to the transformation summary. */
5824 static void
5825 ipcp_store_vr_results (void)
5827 cgraph_node *node;
5829 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5831 ipa_node_params *info = IPA_NODE_REF (node);
5832 bool found_useful_result = false;
5834 if (!info || !opt_for_fn (node->decl, flag_ipa_vrp))
5836 if (dump_file)
5837 fprintf (dump_file, "Not considering %s for VR discovery "
5838 "and propagate; -fipa-ipa-vrp: disabled.\n",
5839 node->dump_name ());
5840 continue;
5843 if (info->ipcp_orig_node)
5844 info = IPA_NODE_REF (info->ipcp_orig_node);
5845 if (!info->lattices)
5846 /* Newly expanded artificial thunks do not have lattices. */
5847 continue;
5849 unsigned count = ipa_get_param_count (info);
5850 for (unsigned i = 0; i < count; i++)
5852 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5853 if (!plats->m_value_range.bottom_p ()
5854 && !plats->m_value_range.top_p ())
5856 found_useful_result = true;
5857 break;
5860 if (!found_useful_result)
5861 continue;
5863 ipcp_transformation_initialize ();
5864 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5865 vec_safe_reserve_exact (ts->m_vr, count);
5867 for (unsigned i = 0; i < count; i++)
5869 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5870 ipa_vr vr;
5872 if (!plats->m_value_range.bottom_p ()
5873 && !plats->m_value_range.top_p ())
5875 vr.known = true;
5876 vr.type = plats->m_value_range.m_vr.kind ();
5877 vr.min = wi::to_wide (plats->m_value_range.m_vr.min ());
5878 vr.max = wi::to_wide (plats->m_value_range.m_vr.max ());
5880 else
5882 vr.known = false;
5883 vr.type = VR_VARYING;
5884 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
5886 ts->m_vr->quick_push (vr);
5891 /* The IPCP driver. */
5893 static unsigned int
5894 ipcp_driver (void)
5896 class ipa_topo_info topo;
5898 if (edge_clone_summaries == NULL)
5899 edge_clone_summaries = new edge_clone_summary_t (symtab);
5901 ipa_check_create_node_params ();
5902 ipa_check_create_edge_args ();
5903 clone_num_suffixes = new hash_map<const char *, unsigned>;
5905 if (dump_file)
5907 fprintf (dump_file, "\nIPA structures before propagation:\n");
5908 if (dump_flags & TDF_DETAILS)
5909 ipa_print_all_params (dump_file);
5910 ipa_print_all_jump_functions (dump_file);
5913 /* Topological sort. */
5914 build_toporder_info (&topo);
5915 /* Do the interprocedural propagation. */
5916 ipcp_propagate_stage (&topo);
5917 /* Decide what constant propagation and cloning should be performed. */
5918 ipcp_decision_stage (&topo);
5919 /* Store results of bits propagation. */
5920 ipcp_store_bits_results ();
5921 /* Store results of value range propagation. */
5922 ipcp_store_vr_results ();
5924 /* Free all IPCP structures. */
5925 delete clone_num_suffixes;
5926 free_toporder_info (&topo);
5927 delete edge_clone_summaries;
5928 edge_clone_summaries = NULL;
5929 ipa_free_all_structures_after_ipa_cp ();
5930 if (dump_file)
5931 fprintf (dump_file, "\nIPA constant propagation end\n");
5932 return 0;
5935 /* Initialization and computation of IPCP data structures. This is the initial
5936 intraprocedural analysis of functions, which gathers information to be
5937 propagated later on. */
5939 static void
5940 ipcp_generate_summary (void)
5942 struct cgraph_node *node;
5944 if (dump_file)
5945 fprintf (dump_file, "\nIPA constant propagation start:\n");
5946 ipa_register_cgraph_hooks ();
5948 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5949 ipa_analyze_node (node);
5952 /* Write ipcp summary for nodes in SET. */
5954 static void
5955 ipcp_write_summary (void)
5957 ipa_prop_write_jump_functions ();
5960 /* Read ipcp summary. */
5962 static void
5963 ipcp_read_summary (void)
5965 ipa_prop_read_jump_functions ();
5968 namespace {
5970 const pass_data pass_data_ipa_cp =
5972 IPA_PASS, /* type */
5973 "cp", /* name */
5974 OPTGROUP_NONE, /* optinfo_flags */
5975 TV_IPA_CONSTANT_PROP, /* tv_id */
5976 0, /* properties_required */
5977 0, /* properties_provided */
5978 0, /* properties_destroyed */
5979 0, /* todo_flags_start */
5980 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5983 class pass_ipa_cp : public ipa_opt_pass_d
5985 public:
5986 pass_ipa_cp (gcc::context *ctxt)
5987 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5988 ipcp_generate_summary, /* generate_summary */
5989 ipcp_write_summary, /* write_summary */
5990 ipcp_read_summary, /* read_summary */
5991 ipcp_write_transformation_summaries, /*
5992 write_optimization_summary */
5993 ipcp_read_transformation_summaries, /*
5994 read_optimization_summary */
5995 NULL, /* stmt_fixup */
5996 0, /* function_transform_todo_flags_start */
5997 ipcp_transform_function, /* function_transform */
5998 NULL) /* variable_transform */
6001 /* opt_pass methods: */
6002 virtual bool gate (function *)
6004 /* FIXME: We should remove the optimize check after we ensure we never run
6005 IPA passes when not optimizing. */
6006 return (flag_ipa_cp && optimize) || in_lto_p;
6009 virtual unsigned int execute (function *) { return ipcp_driver (); }
6011 }; // class pass_ipa_cp
6013 } // anon namespace
6015 ipa_opt_pass_d *
6016 make_pass_ipa_cp (gcc::context *ctxt)
6018 return new pass_ipa_cp (ctxt);
6021 /* Reset all state within ipa-cp.c so that we can rerun the compiler
6022 within the same process. For use by toplev::finalize. */
6024 void
6025 ipa_cp_c_finalize (void)
6027 max_count = profile_count::uninitialized ();
6028 overall_size = 0;
6029 orig_overall_size = 0;
6030 ipcp_free_transformation_sum ();