PR rtl-optimization/82913
[official-gcc.git] / gcc / ipa-cp.c
blob24d2be791038f608539c1bdb4945cc0d7e4e3e18
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2017 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "backend.h"
107 #include "tree.h"
108 #include "gimple-expr.h"
109 #include "predict.h"
110 #include "alloc-pool.h"
111 #include "tree-pass.h"
112 #include "cgraph.h"
113 #include "diagnostic.h"
114 #include "fold-const.h"
115 #include "gimple-fold.h"
116 #include "symbol-summary.h"
117 #include "tree-vrp.h"
118 #include "ipa-prop.h"
119 #include "tree-pretty-print.h"
120 #include "tree-inline.h"
121 #include "params.h"
122 #include "ipa-fnsummary.h"
123 #include "ipa-utils.h"
124 #include "tree-ssa-ccp.h"
125 #include "stringpool.h"
126 #include "attribs.h"
128 template <typename valtype> class ipcp_value;
130 /* Describes a particular source for an IPA-CP value. */
132 template <typename valtype>
133 class ipcp_value_source
135 public:
136 /* Aggregate offset of the source, negative if the source is scalar value of
137 the argument itself. */
138 HOST_WIDE_INT offset;
139 /* The incoming edge that brought the value. */
140 cgraph_edge *cs;
141 /* If the jump function that resulted into his value was a pass-through or an
142 ancestor, this is the ipcp_value of the caller from which the described
143 value has been derived. Otherwise it is NULL. */
144 ipcp_value<valtype> *val;
145 /* Next pointer in a linked list of sources of a value. */
146 ipcp_value_source *next;
147 /* If the jump function that resulted into his value was a pass-through or an
148 ancestor, this is the index of the parameter of the caller the jump
149 function references. */
150 int index;
153 /* Common ancestor for all ipcp_value instantiations. */
155 class ipcp_value_base
157 public:
158 /* Time benefit and size cost that specializing the function for this value
159 would bring about in this function alone. */
160 int local_time_benefit, local_size_cost;
161 /* Time benefit and size cost that specializing the function for this value
162 can bring about in it's callees (transitively). */
163 int prop_time_benefit, prop_size_cost;
165 ipcp_value_base ()
166 : local_time_benefit (0), local_size_cost (0),
167 prop_time_benefit (0), prop_size_cost (0) {}
170 /* Describes one particular value stored in struct ipcp_lattice. */
172 template <typename valtype>
173 class ipcp_value : public ipcp_value_base
175 public:
176 /* The actual value for the given parameter. */
177 valtype value;
178 /* The list of sources from which this value originates. */
179 ipcp_value_source <valtype> *sources;
180 /* Next pointers in a linked list of all values in a lattice. */
181 ipcp_value *next;
182 /* Next pointers in a linked list of values in a strongly connected component
183 of values. */
184 ipcp_value *scc_next;
185 /* Next pointers in a linked list of SCCs of values sorted topologically
186 according their sources. */
187 ipcp_value *topo_next;
188 /* A specialized node created for this value, NULL if none has been (so far)
189 created. */
190 cgraph_node *spec_node;
191 /* Depth first search number and low link for topological sorting of
192 values. */
193 int dfs, low_link;
194 /* True if this valye is currently on the topo-sort stack. */
195 bool on_stack;
197 ipcp_value()
198 : sources (0), next (0), scc_next (0), topo_next (0),
199 spec_node (0), dfs (0), low_link (0), on_stack (false) {}
201 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
202 HOST_WIDE_INT offset);
205 /* Lattice describing potential values of a formal parameter of a function, or
206 a part of an aggregate. TOP is represented by a lattice with zero values
207 and with contains_variable and bottom flags cleared. BOTTOM is represented
208 by a lattice with the bottom flag set. In that case, values and
209 contains_variable flag should be disregarded. */
211 template <typename valtype>
212 class ipcp_lattice
214 public:
215 /* The list of known values and types in this lattice. Note that values are
216 not deallocated if a lattice is set to bottom because there may be value
217 sources referencing them. */
218 ipcp_value<valtype> *values;
219 /* Number of known values and types in this lattice. */
220 int values_count;
221 /* The lattice contains a variable component (in addition to values). */
222 bool contains_variable;
223 /* The value of the lattice is bottom (i.e. variable and unusable for any
224 propagation). */
225 bool bottom;
227 inline bool is_single_const ();
228 inline bool set_to_bottom ();
229 inline bool set_contains_variable ();
230 bool add_value (valtype newval, cgraph_edge *cs,
231 ipcp_value<valtype> *src_val = NULL,
232 int src_idx = 0, HOST_WIDE_INT offset = -1);
233 void print (FILE * f, bool dump_sources, bool dump_benefits);
236 /* Lattice of tree values with an offset to describe a part of an
237 aggregate. */
239 class ipcp_agg_lattice : public ipcp_lattice<tree>
241 public:
242 /* Offset that is being described by this lattice. */
243 HOST_WIDE_INT offset;
244 /* Size so that we don't have to re-compute it every time we traverse the
245 list. Must correspond to TYPE_SIZE of all lat values. */
246 HOST_WIDE_INT size;
247 /* Next element of the linked list. */
248 struct ipcp_agg_lattice *next;
251 /* Lattice of known bits, only capable of holding one value.
252 Bitwise constant propagation propagates which bits of a
253 value are constant.
254 For eg:
255 int f(int x)
257 return some_op (x);
260 int f1(int y)
262 if (cond)
263 return f (y & 0xff);
264 else
265 return f (y & 0xf);
268 In the above case, the param 'x' will always have all
269 the bits (except the bits in lsb) set to 0.
270 Hence the mask of 'x' would be 0xff. The mask
271 reflects that the bits in lsb are unknown.
272 The actual propagated value is given by m_value & ~m_mask. */
274 class ipcp_bits_lattice
276 public:
277 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; }
278 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; }
279 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; }
280 bool set_to_bottom ();
281 bool set_to_constant (widest_int, widest_int);
283 widest_int get_value () { return m_value; }
284 widest_int get_mask () { return m_mask; }
286 bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
287 enum tree_code, tree);
289 bool meet_with (widest_int, widest_int, unsigned);
291 void print (FILE *);
293 private:
294 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
296 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
297 If a bit in mask is set to 0, then the corresponding bit in
298 value is known to be constant. */
299 widest_int m_value, m_mask;
301 bool meet_with_1 (widest_int, widest_int, unsigned);
302 void get_value_and_mask (tree, widest_int *, widest_int *);
305 /* Lattice of value ranges. */
307 class ipcp_vr_lattice
309 public:
310 value_range m_vr;
312 inline bool bottom_p () const;
313 inline bool top_p () const;
314 inline bool set_to_bottom ();
315 bool meet_with (const value_range *p_vr);
316 bool meet_with (const ipcp_vr_lattice &other);
317 void init () { m_vr.type = VR_UNDEFINED; }
318 void print (FILE * f);
320 private:
321 bool meet_with_1 (const value_range *other_vr);
324 /* Structure containing lattices for a parameter itself and for pieces of
325 aggregates that are passed in the parameter or by a reference in a parameter
326 plus some other useful flags. */
328 class ipcp_param_lattices
330 public:
331 /* Lattice describing the value of the parameter itself. */
332 ipcp_lattice<tree> itself;
333 /* Lattice describing the polymorphic contexts of a parameter. */
334 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
335 /* Lattices describing aggregate parts. */
336 ipcp_agg_lattice *aggs;
337 /* Lattice describing known bits. */
338 ipcp_bits_lattice bits_lattice;
339 /* Lattice describing value range. */
340 ipcp_vr_lattice m_value_range;
341 /* Number of aggregate lattices */
342 int aggs_count;
343 /* True if aggregate data were passed by reference (as opposed to by
344 value). */
345 bool aggs_by_ref;
346 /* All aggregate lattices contain a variable component (in addition to
347 values). */
348 bool aggs_contain_variable;
349 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
350 for any propagation). */
351 bool aggs_bottom;
353 /* There is a virtual call based on this parameter. */
354 bool virt_call;
357 /* Allocation pools for values and their sources in ipa-cp. */
359 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
360 ("IPA-CP constant values");
362 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
363 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
365 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
366 ("IPA-CP value sources");
368 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
369 ("IPA_CP aggregate lattices");
371 /* Maximal count found in program. */
373 static profile_count max_count;
375 /* Original overall size of the program. */
377 static long overall_size, max_new_size;
379 /* Return the param lattices structure corresponding to the Ith formal
380 parameter of the function described by INFO. */
381 static inline struct ipcp_param_lattices *
382 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
384 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
385 gcc_checking_assert (!info->ipcp_orig_node);
386 gcc_checking_assert (info->lattices);
387 return &(info->lattices[i]);
390 /* Return the lattice corresponding to the scalar value of the Ith formal
391 parameter of the function described by INFO. */
392 static inline ipcp_lattice<tree> *
393 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
395 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
396 return &plats->itself;
399 /* Return the lattice corresponding to the scalar value of the Ith formal
400 parameter of the function described by INFO. */
401 static inline ipcp_lattice<ipa_polymorphic_call_context> *
402 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
404 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
405 return &plats->ctxlat;
408 /* Return the lattice corresponding to the value range of the Ith formal
409 parameter of the function described by INFO. */
411 static inline ipcp_vr_lattice *
412 ipa_get_vr_lat (struct ipa_node_params *info, int i)
414 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
415 return &plats->m_value_range;
418 /* Return whether LAT is a lattice with a single constant and without an
419 undefined value. */
421 template <typename valtype>
422 inline bool
423 ipcp_lattice<valtype>::is_single_const ()
425 if (bottom || contains_variable || values_count != 1)
426 return false;
427 else
428 return true;
431 /* Print V which is extracted from a value in a lattice to F. */
433 static void
434 print_ipcp_constant_value (FILE * f, tree v)
436 if (TREE_CODE (v) == ADDR_EXPR
437 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
439 fprintf (f, "& ");
440 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)));
442 else
443 print_generic_expr (f, v);
446 /* Print V which is extracted from a value in a lattice to F. */
448 static void
449 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
451 v.dump(f, false);
454 /* Print a lattice LAT to F. */
456 template <typename valtype>
457 void
458 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
460 ipcp_value<valtype> *val;
461 bool prev = false;
463 if (bottom)
465 fprintf (f, "BOTTOM\n");
466 return;
469 if (!values_count && !contains_variable)
471 fprintf (f, "TOP\n");
472 return;
475 if (contains_variable)
477 fprintf (f, "VARIABLE");
478 prev = true;
479 if (dump_benefits)
480 fprintf (f, "\n");
483 for (val = values; val; val = val->next)
485 if (dump_benefits && prev)
486 fprintf (f, " ");
487 else if (!dump_benefits && prev)
488 fprintf (f, ", ");
489 else
490 prev = true;
492 print_ipcp_constant_value (f, val->value);
494 if (dump_sources)
496 ipcp_value_source<valtype> *s;
498 fprintf (f, " [from:");
499 for (s = val->sources; s; s = s->next)
500 fprintf (f, " %i(%i)", s->cs->caller->order,
501 s->cs->frequency);
502 fprintf (f, "]");
505 if (dump_benefits)
506 fprintf (f, " [loc_time: %i, loc_size: %i, "
507 "prop_time: %i, prop_size: %i]\n",
508 val->local_time_benefit, val->local_size_cost,
509 val->prop_time_benefit, val->prop_size_cost);
511 if (!dump_benefits)
512 fprintf (f, "\n");
515 void
516 ipcp_bits_lattice::print (FILE *f)
518 if (top_p ())
519 fprintf (f, " Bits unknown (TOP)\n");
520 else if (bottom_p ())
521 fprintf (f, " Bits unusable (BOTTOM)\n");
522 else
524 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
525 fprintf (f, ", mask = "); print_hex (get_mask (), f);
526 fprintf (f, "\n");
530 /* Print value range lattice to F. */
532 void
533 ipcp_vr_lattice::print (FILE * f)
535 dump_value_range (f, &m_vr);
538 /* Print all ipcp_lattices of all functions to F. */
540 static void
541 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
543 struct cgraph_node *node;
544 int i, count;
546 fprintf (f, "\nLattices:\n");
547 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
549 struct ipa_node_params *info;
551 info = IPA_NODE_REF (node);
552 fprintf (f, " Node: %s:\n", node->dump_name ());
553 count = ipa_get_param_count (info);
554 for (i = 0; i < count; i++)
556 struct ipcp_agg_lattice *aglat;
557 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
558 fprintf (f, " param [%d]: ", i);
559 plats->itself.print (f, dump_sources, dump_benefits);
560 fprintf (f, " ctxs: ");
561 plats->ctxlat.print (f, dump_sources, dump_benefits);
562 plats->bits_lattice.print (f);
563 fprintf (f, " ");
564 plats->m_value_range.print (f);
565 fprintf (f, "\n");
566 if (plats->virt_call)
567 fprintf (f, " virt_call flag set\n");
569 if (plats->aggs_bottom)
571 fprintf (f, " AGGS BOTTOM\n");
572 continue;
574 if (plats->aggs_contain_variable)
575 fprintf (f, " AGGS VARIABLE\n");
576 for (aglat = plats->aggs; aglat; aglat = aglat->next)
578 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
579 plats->aggs_by_ref ? "ref " : "", aglat->offset);
580 aglat->print (f, dump_sources, dump_benefits);
586 /* Determine whether it is at all technically possible to create clones of NODE
587 and store this information in the ipa_node_params structure associated
588 with NODE. */
590 static void
591 determine_versionability (struct cgraph_node *node,
592 struct ipa_node_params *info)
594 const char *reason = NULL;
596 /* There are a number of generic reasons functions cannot be versioned. We
597 also cannot remove parameters if there are type attributes such as fnspec
598 present. */
599 if (node->alias || node->thunk.thunk_p)
600 reason = "alias or thunk";
601 else if (!node->local.versionable)
602 reason = "not a tree_versionable_function";
603 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
604 reason = "insufficient body availability";
605 else if (!opt_for_fn (node->decl, optimize)
606 || !opt_for_fn (node->decl, flag_ipa_cp))
607 reason = "non-optimized function";
608 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
610 /* Ideally we should clone the SIMD clones themselves and create
611 vector copies of them, so IPA-cp and SIMD clones can happily
612 coexist, but that may not be worth the effort. */
613 reason = "function has SIMD clones";
615 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
617 /* Ideally we should clone the target clones themselves and create
618 copies of them, so IPA-cp and target clones can happily
619 coexist, but that may not be worth the effort. */
620 reason = "function target_clones attribute";
622 /* Don't clone decls local to a comdat group; it breaks and for C++
623 decloned constructors, inlining is always better anyway. */
624 else if (node->comdat_local_p ())
625 reason = "comdat-local function";
626 else if (node->calls_comdat_local)
628 /* TODO: call is versionable if we make sure that all
629 callers are inside of a comdat group. */
630 reason = "calls comdat-local function";
633 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
634 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
635 node->dump_name (), reason);
637 info->versionable = (reason == NULL);
640 /* Return true if it is at all technically possible to create clones of a
641 NODE. */
643 static bool
644 ipcp_versionable_function_p (struct cgraph_node *node)
646 return IPA_NODE_REF (node)->versionable;
649 /* Structure holding accumulated information about callers of a node. */
651 struct caller_statistics
653 profile_count count_sum;
654 int n_calls, n_hot_calls, freq_sum;
657 /* Initialize fields of STAT to zeroes. */
659 static inline void
660 init_caller_stats (struct caller_statistics *stats)
662 stats->count_sum = profile_count::zero ();
663 stats->n_calls = 0;
664 stats->n_hot_calls = 0;
665 stats->freq_sum = 0;
668 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
669 non-thunk incoming edges to NODE. */
671 static bool
672 gather_caller_stats (struct cgraph_node *node, void *data)
674 struct caller_statistics *stats = (struct caller_statistics *) data;
675 struct cgraph_edge *cs;
677 for (cs = node->callers; cs; cs = cs->next_caller)
678 if (!cs->caller->thunk.thunk_p)
680 if (cs->count.initialized_p ())
681 stats->count_sum += cs->count;
682 stats->freq_sum += cs->frequency;
683 stats->n_calls++;
684 if (cs->maybe_hot_p ())
685 stats->n_hot_calls ++;
687 return false;
691 /* Return true if this NODE is viable candidate for cloning. */
693 static bool
694 ipcp_cloning_candidate_p (struct cgraph_node *node)
696 struct caller_statistics stats;
698 gcc_checking_assert (node->has_gimple_body_p ());
700 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
702 if (dump_file)
703 fprintf (dump_file, "Not considering %s for cloning; "
704 "-fipa-cp-clone disabled.\n",
705 node->name ());
706 return false;
709 if (node->optimize_for_size_p ())
711 if (dump_file)
712 fprintf (dump_file, "Not considering %s for cloning; "
713 "optimizing it for size.\n",
714 node->name ());
715 return false;
718 init_caller_stats (&stats);
719 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
721 if (ipa_fn_summaries->get (node)->self_size < stats.n_calls)
723 if (dump_file)
724 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
725 node->name ());
726 return true;
729 /* When profile is available and function is hot, propagate into it even if
730 calls seems cold; constant propagation can improve function's speed
731 significantly. */
732 if (max_count > profile_count::zero ())
734 if (stats.count_sum > node->count.apply_scale (90, 100))
736 if (dump_file)
737 fprintf (dump_file, "Considering %s for cloning; "
738 "usually called directly.\n",
739 node->name ());
740 return true;
743 if (!stats.n_hot_calls)
745 if (dump_file)
746 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
747 node->name ());
748 return false;
750 if (dump_file)
751 fprintf (dump_file, "Considering %s for cloning.\n",
752 node->name ());
753 return true;
756 template <typename valtype>
757 class value_topo_info
759 public:
760 /* Head of the linked list of topologically sorted values. */
761 ipcp_value<valtype> *values_topo;
762 /* Stack for creating SCCs, represented by a linked list too. */
763 ipcp_value<valtype> *stack;
764 /* Counter driving the algorithm in add_val_to_toposort. */
765 int dfs_counter;
767 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
769 void add_val (ipcp_value<valtype> *cur_val);
770 void propagate_effects ();
773 /* Arrays representing a topological ordering of call graph nodes and a stack
774 of nodes used during constant propagation and also data required to perform
775 topological sort of values and propagation of benefits in the determined
776 order. */
778 class ipa_topo_info
780 public:
781 /* Array with obtained topological order of cgraph nodes. */
782 struct cgraph_node **order;
783 /* Stack of cgraph nodes used during propagation within SCC until all values
784 in the SCC stabilize. */
785 struct cgraph_node **stack;
786 int nnodes, stack_top;
788 value_topo_info<tree> constants;
789 value_topo_info<ipa_polymorphic_call_context> contexts;
791 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
792 constants ()
796 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
798 static void
799 build_toporder_info (struct ipa_topo_info *topo)
801 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
802 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
804 gcc_checking_assert (topo->stack_top == 0);
805 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
808 /* Free information about strongly connected components and the arrays in
809 TOPO. */
811 static void
812 free_toporder_info (struct ipa_topo_info *topo)
814 ipa_free_postorder_info ();
815 free (topo->order);
816 free (topo->stack);
819 /* Add NODE to the stack in TOPO, unless it is already there. */
821 static inline void
822 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
824 struct ipa_node_params *info = IPA_NODE_REF (node);
825 if (info->node_enqueued)
826 return;
827 info->node_enqueued = 1;
828 topo->stack[topo->stack_top++] = node;
831 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
832 is empty. */
834 static struct cgraph_node *
835 pop_node_from_stack (struct ipa_topo_info *topo)
837 if (topo->stack_top)
839 struct cgraph_node *node;
840 topo->stack_top--;
841 node = topo->stack[topo->stack_top];
842 IPA_NODE_REF (node)->node_enqueued = 0;
843 return node;
845 else
846 return NULL;
849 /* Set lattice LAT to bottom and return true if it previously was not set as
850 such. */
852 template <typename valtype>
853 inline bool
854 ipcp_lattice<valtype>::set_to_bottom ()
856 bool ret = !bottom;
857 bottom = true;
858 return ret;
861 /* Mark lattice as containing an unknown value and return true if it previously
862 was not marked as such. */
864 template <typename valtype>
865 inline bool
866 ipcp_lattice<valtype>::set_contains_variable ()
868 bool ret = !contains_variable;
869 contains_variable = true;
870 return ret;
873 /* Set all aggegate lattices in PLATS to bottom and return true if they were
874 not previously set as such. */
876 static inline bool
877 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
879 bool ret = !plats->aggs_bottom;
880 plats->aggs_bottom = true;
881 return ret;
884 /* Mark all aggegate lattices in PLATS as containing an unknown value and
885 return true if they were not previously marked as such. */
887 static inline bool
888 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
890 bool ret = !plats->aggs_contain_variable;
891 plats->aggs_contain_variable = true;
892 return ret;
895 bool
896 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
898 return meet_with_1 (&other.m_vr);
901 /* Meet the current value of the lattice with value ranfge described by VR
902 lattice. */
904 bool
905 ipcp_vr_lattice::meet_with (const value_range *p_vr)
907 return meet_with_1 (p_vr);
910 /* Meet the current value of the lattice with value ranfge described by
911 OTHER_VR lattice. */
913 bool
914 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
916 tree min = m_vr.min, max = m_vr.max;
917 value_range_type type = m_vr.type;
919 if (bottom_p ())
920 return false;
922 if (other_vr->type == VR_VARYING)
923 return set_to_bottom ();
925 vrp_meet (&m_vr, other_vr);
926 if (type != m_vr.type
927 || min != m_vr.min
928 || max != m_vr.max)
929 return true;
930 else
931 return false;
934 /* Return true if value range information in the lattice is yet unknown. */
936 bool
937 ipcp_vr_lattice::top_p () const
939 return m_vr.type == VR_UNDEFINED;
942 /* Return true if value range information in the lattice is known to be
943 unusable. */
945 bool
946 ipcp_vr_lattice::bottom_p () const
948 return m_vr.type == VR_VARYING;
951 /* Set value range information in the lattice to bottom. Return true if it
952 previously was in a different state. */
954 bool
955 ipcp_vr_lattice::set_to_bottom ()
957 if (m_vr.type == VR_VARYING)
958 return false;
959 m_vr.type = VR_VARYING;
960 return true;
963 /* Set lattice value to bottom, if it already isn't the case. */
965 bool
966 ipcp_bits_lattice::set_to_bottom ()
968 if (bottom_p ())
969 return false;
970 m_lattice_val = IPA_BITS_VARYING;
971 m_value = 0;
972 m_mask = -1;
973 return true;
976 /* Set to constant if it isn't already. Only meant to be called
977 when switching state from TOP. */
979 bool
980 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
982 gcc_assert (top_p ());
983 m_lattice_val = IPA_BITS_CONSTANT;
984 m_value = value;
985 m_mask = mask;
986 return true;
989 /* Convert operand to value, mask form. */
991 void
992 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
994 wide_int get_nonzero_bits (const_tree);
996 if (TREE_CODE (operand) == INTEGER_CST)
998 *valuep = wi::to_widest (operand);
999 *maskp = 0;
1001 else
1003 *valuep = 0;
1004 *maskp = -1;
1008 /* Meet operation, similar to ccp_lattice_meet, we xor values
1009 if this->value, value have different values at same bit positions, we want
1010 to drop that bit to varying. Return true if mask is changed.
1011 This function assumes that the lattice value is in CONSTANT state */
1013 bool
1014 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
1015 unsigned precision)
1017 gcc_assert (constant_p ());
1019 widest_int old_mask = m_mask;
1020 m_mask = (m_mask | mask) | (m_value ^ value);
1022 if (wi::sext (m_mask, precision) == -1)
1023 return set_to_bottom ();
1025 return m_mask != old_mask;
1028 /* Meet the bits lattice with operand
1029 described by <value, mask, sgn, precision. */
1031 bool
1032 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1033 unsigned precision)
1035 if (bottom_p ())
1036 return false;
1038 if (top_p ())
1040 if (wi::sext (mask, precision) == -1)
1041 return set_to_bottom ();
1042 return set_to_constant (value, mask);
1045 return meet_with_1 (value, mask, precision);
1048 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1049 if code is binary operation or bit_value_unop (other) if code is unary op.
1050 In the case when code is nop_expr, no adjustment is required. */
1052 bool
1053 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1054 signop sgn, enum tree_code code, tree operand)
1056 if (other.bottom_p ())
1057 return set_to_bottom ();
1059 if (bottom_p () || other.top_p ())
1060 return false;
1062 widest_int adjusted_value, adjusted_mask;
1064 if (TREE_CODE_CLASS (code) == tcc_binary)
1066 tree type = TREE_TYPE (operand);
1067 gcc_assert (INTEGRAL_TYPE_P (type));
1068 widest_int o_value, o_mask;
1069 get_value_and_mask (operand, &o_value, &o_mask);
1071 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1072 sgn, precision, other.get_value (), other.get_mask (),
1073 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1075 if (wi::sext (adjusted_mask, precision) == -1)
1076 return set_to_bottom ();
1079 else if (TREE_CODE_CLASS (code) == tcc_unary)
1081 bit_value_unop (code, sgn, precision, &adjusted_value,
1082 &adjusted_mask, sgn, precision, other.get_value (),
1083 other.get_mask ());
1085 if (wi::sext (adjusted_mask, precision) == -1)
1086 return set_to_bottom ();
1089 else
1090 return set_to_bottom ();
1092 if (top_p ())
1094 if (wi::sext (adjusted_mask, precision) == -1)
1095 return set_to_bottom ();
1096 return set_to_constant (adjusted_value, adjusted_mask);
1098 else
1099 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1102 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1103 return true is any of them has not been marked as such so far. */
1105 static inline bool
1106 set_all_contains_variable (struct ipcp_param_lattices *plats)
1108 bool ret;
1109 ret = plats->itself.set_contains_variable ();
1110 ret |= plats->ctxlat.set_contains_variable ();
1111 ret |= set_agg_lats_contain_variable (plats);
1112 ret |= plats->bits_lattice.set_to_bottom ();
1113 ret |= plats->m_value_range.set_to_bottom ();
1114 return ret;
1117 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1118 points to by the number of callers to NODE. */
1120 static bool
1121 count_callers (cgraph_node *node, void *data)
1123 int *caller_count = (int *) data;
1125 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1126 /* Local thunks can be handled transparently, but if the thunk can not
1127 be optimized out, count it as a real use. */
1128 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
1129 ++*caller_count;
1130 return false;
1133 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1134 the one caller of some other node. Set the caller's corresponding flag. */
1136 static bool
1137 set_single_call_flag (cgraph_node *node, void *)
1139 cgraph_edge *cs = node->callers;
1140 /* Local thunks can be handled transparently, skip them. */
1141 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
1142 cs = cs->next_caller;
1143 if (cs)
1145 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1146 return true;
1148 return false;
1151 /* Initialize ipcp_lattices. */
1153 static void
1154 initialize_node_lattices (struct cgraph_node *node)
1156 struct ipa_node_params *info = IPA_NODE_REF (node);
1157 struct cgraph_edge *ie;
1158 bool disable = false, variable = false;
1159 int i;
1161 gcc_checking_assert (node->has_gimple_body_p ());
1162 if (cgraph_local_p (node))
1164 int caller_count = 0;
1165 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1166 true);
1167 gcc_checking_assert (caller_count > 0);
1168 if (caller_count == 1)
1169 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1170 NULL, true);
1172 else
1174 /* When cloning is allowed, we can assume that externally visible
1175 functions are not called. We will compensate this by cloning
1176 later. */
1177 if (ipcp_versionable_function_p (node)
1178 && ipcp_cloning_candidate_p (node))
1179 variable = true;
1180 else
1181 disable = true;
1184 for (i = 0; i < ipa_get_param_count (info); i++)
1186 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1187 plats->m_value_range.init ();
1190 if (disable || variable)
1192 for (i = 0; i < ipa_get_param_count (info); i++)
1194 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1195 if (disable)
1197 plats->itself.set_to_bottom ();
1198 plats->ctxlat.set_to_bottom ();
1199 set_agg_lats_to_bottom (plats);
1200 plats->bits_lattice.set_to_bottom ();
1201 plats->m_value_range.set_to_bottom ();
1203 else
1204 set_all_contains_variable (plats);
1206 if (dump_file && (dump_flags & TDF_DETAILS)
1207 && !node->alias && !node->thunk.thunk_p)
1208 fprintf (dump_file, "Marking all lattices of %s as %s\n",
1209 node->dump_name (), disable ? "BOTTOM" : "VARIABLE");
1212 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1213 if (ie->indirect_info->polymorphic
1214 && ie->indirect_info->param_index >= 0)
1216 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1217 ipa_get_parm_lattices (info,
1218 ie->indirect_info->param_index)->virt_call = 1;
1222 /* Return the result of a (possibly arithmetic) pass through jump function
1223 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
1224 determined or be considered an interprocedural invariant. */
1226 static tree
1227 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
1229 tree restype, res;
1231 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1232 return input;
1233 if (!is_gimple_ip_invariant (input))
1234 return NULL_TREE;
1236 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
1237 == tcc_unary)
1238 res = fold_unary (ipa_get_jf_pass_through_operation (jfunc),
1239 TREE_TYPE (input), input);
1240 else
1242 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
1243 == tcc_comparison)
1244 restype = boolean_type_node;
1245 else
1246 restype = TREE_TYPE (input);
1247 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
1248 input, ipa_get_jf_pass_through_operand (jfunc));
1250 if (res && !is_gimple_ip_invariant (res))
1251 return NULL_TREE;
1253 return res;
1256 /* Return the result of an ancestor jump function JFUNC on the constant value
1257 INPUT. Return NULL_TREE if that cannot be determined. */
1259 static tree
1260 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1262 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1263 if (TREE_CODE (input) == ADDR_EXPR)
1265 tree t = TREE_OPERAND (input, 0);
1266 t = build_ref_for_offset (EXPR_LOCATION (t), t,
1267 ipa_get_jf_ancestor_offset (jfunc), false,
1268 ptr_type_node, NULL, false);
1269 return build_fold_addr_expr (t);
1271 else
1272 return NULL_TREE;
1275 /* Determine whether JFUNC evaluates to a single known constant value and if
1276 so, return it. Otherwise return NULL. INFO describes the caller node or
1277 the one it is inlined to, so that pass-through jump functions can be
1278 evaluated. */
1280 tree
1281 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
1283 if (jfunc->type == IPA_JF_CONST)
1284 return ipa_get_jf_constant (jfunc);
1285 else if (jfunc->type == IPA_JF_PASS_THROUGH
1286 || jfunc->type == IPA_JF_ANCESTOR)
1288 tree input;
1289 int idx;
1291 if (jfunc->type == IPA_JF_PASS_THROUGH)
1292 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1293 else
1294 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1296 if (info->ipcp_orig_node)
1297 input = info->known_csts[idx];
1298 else
1300 ipcp_lattice<tree> *lat;
1302 if (!info->lattices
1303 || idx >= ipa_get_param_count (info))
1304 return NULL_TREE;
1305 lat = ipa_get_scalar_lat (info, idx);
1306 if (!lat->is_single_const ())
1307 return NULL_TREE;
1308 input = lat->values->value;
1311 if (!input)
1312 return NULL_TREE;
1314 if (jfunc->type == IPA_JF_PASS_THROUGH)
1315 return ipa_get_jf_pass_through_result (jfunc, input);
1316 else
1317 return ipa_get_jf_ancestor_result (jfunc, input);
1319 else
1320 return NULL_TREE;
1323 /* Determie whether JFUNC evaluates to single known polymorphic context, given
1324 that INFO describes the caller node or the one it is inlined to, CS is the
1325 call graph edge corresponding to JFUNC and CSIDX index of the described
1326 parameter. */
1328 ipa_polymorphic_call_context
1329 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1330 ipa_jump_func *jfunc)
1332 ipa_edge_args *args = IPA_EDGE_REF (cs);
1333 ipa_polymorphic_call_context ctx;
1334 ipa_polymorphic_call_context *edge_ctx
1335 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1337 if (edge_ctx && !edge_ctx->useless_p ())
1338 ctx = *edge_ctx;
1340 if (jfunc->type == IPA_JF_PASS_THROUGH
1341 || jfunc->type == IPA_JF_ANCESTOR)
1343 ipa_polymorphic_call_context srcctx;
1344 int srcidx;
1345 bool type_preserved = true;
1346 if (jfunc->type == IPA_JF_PASS_THROUGH)
1348 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1349 return ctx;
1350 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1351 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1353 else
1355 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1356 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1358 if (info->ipcp_orig_node)
1360 if (info->known_contexts.exists ())
1361 srcctx = info->known_contexts[srcidx];
1363 else
1365 if (!info->lattices
1366 || srcidx >= ipa_get_param_count (info))
1367 return ctx;
1368 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1369 lat = ipa_get_poly_ctx_lat (info, srcidx);
1370 if (!lat->is_single_const ())
1371 return ctx;
1372 srcctx = lat->values->value;
1374 if (srcctx.useless_p ())
1375 return ctx;
1376 if (jfunc->type == IPA_JF_ANCESTOR)
1377 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1378 if (!type_preserved)
1379 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1380 srcctx.combine_with (ctx);
1381 return srcctx;
1384 return ctx;
1387 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1388 bottom, not containing a variable component and without any known value at
1389 the same time. */
1391 DEBUG_FUNCTION void
1392 ipcp_verify_propagated_values (void)
1394 struct cgraph_node *node;
1396 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1398 struct ipa_node_params *info = IPA_NODE_REF (node);
1399 int i, count = ipa_get_param_count (info);
1401 for (i = 0; i < count; i++)
1403 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1405 if (!lat->bottom
1406 && !lat->contains_variable
1407 && lat->values_count == 0)
1409 if (dump_file)
1411 symtab->dump (dump_file);
1412 fprintf (dump_file, "\nIPA lattices after constant "
1413 "propagation, before gcc_unreachable:\n");
1414 print_all_lattices (dump_file, true, false);
1417 gcc_unreachable ();
1423 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1425 static bool
1426 values_equal_for_ipcp_p (tree x, tree y)
1428 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1430 if (x == y)
1431 return true;
1433 if (TREE_CODE (x) == ADDR_EXPR
1434 && TREE_CODE (y) == ADDR_EXPR
1435 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1436 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1437 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1438 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1439 else
1440 return operand_equal_p (x, y, 0);
1443 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1445 static bool
1446 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1447 ipa_polymorphic_call_context y)
1449 return x.equal_to (y);
1453 /* Add a new value source to the value represented by THIS, marking that a
1454 value comes from edge CS and (if the underlying jump function is a
1455 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1456 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1457 scalar value of the parameter itself or the offset within an aggregate. */
1459 template <typename valtype>
1460 void
1461 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1462 int src_idx, HOST_WIDE_INT offset)
1464 ipcp_value_source<valtype> *src;
1466 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1467 src->offset = offset;
1468 src->cs = cs;
1469 src->val = src_val;
1470 src->index = src_idx;
1472 src->next = sources;
1473 sources = src;
1476 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1477 SOURCE and clear all other fields. */
1479 static ipcp_value<tree> *
1480 allocate_and_init_ipcp_value (tree source)
1482 ipcp_value<tree> *val;
1484 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1485 val->value = source;
1486 return val;
1489 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1490 value to SOURCE and clear all other fields. */
1492 static ipcp_value<ipa_polymorphic_call_context> *
1493 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1495 ipcp_value<ipa_polymorphic_call_context> *val;
1497 // TODO
1498 val = new (ipcp_poly_ctx_values_pool.allocate ())
1499 ipcp_value<ipa_polymorphic_call_context>();
1500 val->value = source;
1501 return val;
1504 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1505 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1506 meaning. OFFSET -1 means the source is scalar and not a part of an
1507 aggregate. */
1509 template <typename valtype>
1510 bool
1511 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1512 ipcp_value<valtype> *src_val,
1513 int src_idx, HOST_WIDE_INT offset)
1515 ipcp_value<valtype> *val;
1517 if (bottom)
1518 return false;
1520 for (val = values; val; val = val->next)
1521 if (values_equal_for_ipcp_p (val->value, newval))
1523 if (ipa_edge_within_scc (cs))
1525 ipcp_value_source<valtype> *s;
1526 for (s = val->sources; s; s = s->next)
1527 if (s->cs == cs)
1528 break;
1529 if (s)
1530 return false;
1533 val->add_source (cs, src_val, src_idx, offset);
1534 return false;
1537 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1539 /* We can only free sources, not the values themselves, because sources
1540 of other values in this SCC might point to them. */
1541 for (val = values; val; val = val->next)
1543 while (val->sources)
1545 ipcp_value_source<valtype> *src = val->sources;
1546 val->sources = src->next;
1547 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1551 values = NULL;
1552 return set_to_bottom ();
1555 values_count++;
1556 val = allocate_and_init_ipcp_value (newval);
1557 val->add_source (cs, src_val, src_idx, offset);
1558 val->next = values;
1559 values = val;
1560 return true;
1563 /* Propagate values through a pass-through jump function JFUNC associated with
1564 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1565 is the index of the source parameter. */
1567 static bool
1568 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
1569 ipcp_lattice<tree> *src_lat,
1570 ipcp_lattice<tree> *dest_lat, int src_idx)
1572 ipcp_value<tree> *src_val;
1573 bool ret = false;
1575 /* Do not create new values when propagating within an SCC because if there
1576 are arithmetic functions with circular dependencies, there is infinite
1577 number of them and we would just make lattices bottom. */
1578 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1579 && ipa_edge_within_scc (cs))
1580 ret = dest_lat->set_contains_variable ();
1581 else
1582 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1584 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1586 if (cstval)
1587 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1588 else
1589 ret |= dest_lat->set_contains_variable ();
1592 return ret;
1595 /* Propagate values through an ancestor jump function JFUNC associated with
1596 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1597 is the index of the source parameter. */
1599 static bool
1600 propagate_vals_across_ancestor (struct cgraph_edge *cs,
1601 struct ipa_jump_func *jfunc,
1602 ipcp_lattice<tree> *src_lat,
1603 ipcp_lattice<tree> *dest_lat, int src_idx)
1605 ipcp_value<tree> *src_val;
1606 bool ret = false;
1608 if (ipa_edge_within_scc (cs))
1609 return dest_lat->set_contains_variable ();
1611 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1613 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1615 if (t)
1616 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1617 else
1618 ret |= dest_lat->set_contains_variable ();
1621 return ret;
1624 /* Propagate scalar values across jump function JFUNC that is associated with
1625 edge CS and put the values into DEST_LAT. */
1627 static bool
1628 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
1629 struct ipa_jump_func *jfunc,
1630 ipcp_lattice<tree> *dest_lat)
1632 if (dest_lat->bottom)
1633 return false;
1635 if (jfunc->type == IPA_JF_CONST)
1637 tree val = ipa_get_jf_constant (jfunc);
1638 return dest_lat->add_value (val, cs, NULL, 0);
1640 else if (jfunc->type == IPA_JF_PASS_THROUGH
1641 || jfunc->type == IPA_JF_ANCESTOR)
1643 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1644 ipcp_lattice<tree> *src_lat;
1645 int src_idx;
1646 bool ret;
1648 if (jfunc->type == IPA_JF_PASS_THROUGH)
1649 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1650 else
1651 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1653 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1654 if (src_lat->bottom)
1655 return dest_lat->set_contains_variable ();
1657 /* If we would need to clone the caller and cannot, do not propagate. */
1658 if (!ipcp_versionable_function_p (cs->caller)
1659 && (src_lat->contains_variable
1660 || (src_lat->values_count > 1)))
1661 return dest_lat->set_contains_variable ();
1663 if (jfunc->type == IPA_JF_PASS_THROUGH)
1664 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
1665 dest_lat, src_idx);
1666 else
1667 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
1668 src_idx);
1670 if (src_lat->contains_variable)
1671 ret |= dest_lat->set_contains_variable ();
1673 return ret;
1676 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1677 use it for indirect inlining), we should propagate them too. */
1678 return dest_lat->set_contains_variable ();
1681 /* Propagate scalar values across jump function JFUNC that is associated with
1682 edge CS and describes argument IDX and put the values into DEST_LAT. */
1684 static bool
1685 propagate_context_across_jump_function (cgraph_edge *cs,
1686 ipa_jump_func *jfunc, int idx,
1687 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1689 ipa_edge_args *args = IPA_EDGE_REF (cs);
1690 if (dest_lat->bottom)
1691 return false;
1692 bool ret = false;
1693 bool added_sth = false;
1694 bool type_preserved = true;
1696 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1697 = ipa_get_ith_polymorhic_call_context (args, idx);
1699 if (edge_ctx_ptr)
1700 edge_ctx = *edge_ctx_ptr;
1702 if (jfunc->type == IPA_JF_PASS_THROUGH
1703 || jfunc->type == IPA_JF_ANCESTOR)
1705 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1706 int src_idx;
1707 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1709 /* TODO: Once we figure out how to propagate speculations, it will
1710 probably be a good idea to switch to speculation if type_preserved is
1711 not set instead of punting. */
1712 if (jfunc->type == IPA_JF_PASS_THROUGH)
1714 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1715 goto prop_fail;
1716 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1717 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1719 else
1721 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1722 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1725 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1726 /* If we would need to clone the caller and cannot, do not propagate. */
1727 if (!ipcp_versionable_function_p (cs->caller)
1728 && (src_lat->contains_variable
1729 || (src_lat->values_count > 1)))
1730 goto prop_fail;
1732 ipcp_value<ipa_polymorphic_call_context> *src_val;
1733 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1735 ipa_polymorphic_call_context cur = src_val->value;
1737 if (!type_preserved)
1738 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1739 if (jfunc->type == IPA_JF_ANCESTOR)
1740 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1741 /* TODO: In cases we know how the context is going to be used,
1742 we can improve the result by passing proper OTR_TYPE. */
1743 cur.combine_with (edge_ctx);
1744 if (!cur.useless_p ())
1746 if (src_lat->contains_variable
1747 && !edge_ctx.equal_to (cur))
1748 ret |= dest_lat->set_contains_variable ();
1749 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1750 added_sth = true;
1756 prop_fail:
1757 if (!added_sth)
1759 if (!edge_ctx.useless_p ())
1760 ret |= dest_lat->add_value (edge_ctx, cs);
1761 else
1762 ret |= dest_lat->set_contains_variable ();
1765 return ret;
1768 /* Propagate bits across jfunc that is associated with
1769 edge cs and update dest_lattice accordingly. */
1771 bool
1772 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
1773 ipa_jump_func *jfunc,
1774 ipcp_bits_lattice *dest_lattice)
1776 if (dest_lattice->bottom_p ())
1777 return false;
1779 enum availability availability;
1780 cgraph_node *callee = cs->callee->function_symbol (&availability);
1781 struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
1782 tree parm_type = ipa_get_type (callee_info, idx);
1784 /* For K&R C programs, ipa_get_type() could return NULL_TREE.
1785 Avoid the transform for these cases. */
1786 if (!parm_type)
1788 if (dump_file && (dump_flags & TDF_DETAILS))
1789 fprintf (dump_file, "Setting dest_lattice to bottom, because"
1790 " param %i type is NULL for %s\n", idx,
1791 cs->callee->name ());
1793 return dest_lattice->set_to_bottom ();
1796 unsigned precision = TYPE_PRECISION (parm_type);
1797 signop sgn = TYPE_SIGN (parm_type);
1799 if (jfunc->type == IPA_JF_PASS_THROUGH
1800 || jfunc->type == IPA_JF_ANCESTOR)
1802 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1803 tree operand = NULL_TREE;
1804 enum tree_code code;
1805 unsigned src_idx;
1807 if (jfunc->type == IPA_JF_PASS_THROUGH)
1809 code = ipa_get_jf_pass_through_operation (jfunc);
1810 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1811 if (code != NOP_EXPR)
1812 operand = ipa_get_jf_pass_through_operand (jfunc);
1814 else
1816 code = POINTER_PLUS_EXPR;
1817 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1818 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
1819 operand = build_int_cstu (size_type_node, offset);
1822 struct ipcp_param_lattices *src_lats
1823 = ipa_get_parm_lattices (caller_info, src_idx);
1825 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1826 for eg consider:
1827 int f(int x)
1829 g (x & 0xff);
1831 Assume lattice for x is bottom, however we can still propagate
1832 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1833 and we store it in jump function during analysis stage. */
1835 if (src_lats->bits_lattice.bottom_p ()
1836 && jfunc->bits)
1837 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1838 precision);
1839 else
1840 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
1841 code, operand);
1844 else if (jfunc->type == IPA_JF_ANCESTOR)
1845 return dest_lattice->set_to_bottom ();
1846 else if (jfunc->bits)
1847 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1848 precision);
1849 else
1850 return dest_lattice->set_to_bottom ();
1853 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1854 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1855 the result is a range or an anti-range. */
1857 static bool
1858 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr,
1859 enum tree_code operation,
1860 tree dst_type, tree src_type)
1862 memset (dst_vr, 0, sizeof (*dst_vr));
1863 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
1864 if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE)
1865 return true;
1866 else
1867 return false;
1870 /* Propagate value range across jump function JFUNC that is associated with
1871 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1872 accordingly. */
1874 static bool
1875 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
1876 struct ipcp_param_lattices *dest_plats,
1877 tree param_type)
1879 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
1881 if (dest_lat->bottom_p ())
1882 return false;
1884 if (!param_type
1885 || (!INTEGRAL_TYPE_P (param_type)
1886 && !POINTER_TYPE_P (param_type)))
1887 return dest_lat->set_to_bottom ();
1889 if (jfunc->type == IPA_JF_PASS_THROUGH)
1891 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1893 if (TREE_CODE_CLASS (operation) == tcc_unary)
1895 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1896 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1897 tree operand_type = ipa_get_type (caller_info, src_idx);
1898 struct ipcp_param_lattices *src_lats
1899 = ipa_get_parm_lattices (caller_info, src_idx);
1901 if (src_lats->m_value_range.bottom_p ())
1902 return dest_lat->set_to_bottom ();
1903 value_range vr;
1904 if (ipa_vr_operation_and_type_effects (&vr,
1905 &src_lats->m_value_range.m_vr,
1906 operation, param_type,
1907 operand_type))
1908 return dest_lat->meet_with (&vr);
1911 else if (jfunc->type == IPA_JF_CONST)
1913 tree val = ipa_get_jf_constant (jfunc);
1914 if (TREE_CODE (val) == INTEGER_CST)
1916 val = fold_convert (param_type, val);
1917 if (TREE_OVERFLOW_P (val))
1918 val = drop_tree_overflow (val);
1920 value_range tmpvr;
1921 memset (&tmpvr, 0, sizeof (tmpvr));
1922 tmpvr.type = VR_RANGE;
1923 tmpvr.min = val;
1924 tmpvr.max = val;
1925 return dest_lat->meet_with (&tmpvr);
1929 value_range vr;
1930 if (jfunc->m_vr
1931 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
1932 param_type,
1933 TREE_TYPE (jfunc->m_vr->min)))
1934 return dest_lat->meet_with (&vr);
1935 else
1936 return dest_lat->set_to_bottom ();
1939 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1940 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1941 other cases, return false). If there are no aggregate items, set
1942 aggs_by_ref to NEW_AGGS_BY_REF. */
1944 static bool
1945 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1946 bool new_aggs_by_ref)
1948 if (dest_plats->aggs)
1950 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1952 set_agg_lats_to_bottom (dest_plats);
1953 return true;
1956 else
1957 dest_plats->aggs_by_ref = new_aggs_by_ref;
1958 return false;
1961 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1962 already existing lattice for the given OFFSET and SIZE, marking all skipped
1963 lattices as containing variable and checking for overlaps. If there is no
1964 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1965 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1966 unless there are too many already. If there are two many, return false. If
1967 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1968 skipped lattices were newly marked as containing variable, set *CHANGE to
1969 true. */
1971 static bool
1972 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1973 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1974 struct ipcp_agg_lattice ***aglat,
1975 bool pre_existing, bool *change)
1977 gcc_checking_assert (offset >= 0);
1979 while (**aglat && (**aglat)->offset < offset)
1981 if ((**aglat)->offset + (**aglat)->size > offset)
1983 set_agg_lats_to_bottom (dest_plats);
1984 return false;
1986 *change |= (**aglat)->set_contains_variable ();
1987 *aglat = &(**aglat)->next;
1990 if (**aglat && (**aglat)->offset == offset)
1992 if ((**aglat)->size != val_size
1993 || ((**aglat)->next
1994 && (**aglat)->next->offset < offset + val_size))
1996 set_agg_lats_to_bottom (dest_plats);
1997 return false;
1999 gcc_checking_assert (!(**aglat)->next
2000 || (**aglat)->next->offset >= offset + val_size);
2001 return true;
2003 else
2005 struct ipcp_agg_lattice *new_al;
2007 if (**aglat && (**aglat)->offset < offset + val_size)
2009 set_agg_lats_to_bottom (dest_plats);
2010 return false;
2012 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
2013 return false;
2014 dest_plats->aggs_count++;
2015 new_al = ipcp_agg_lattice_pool.allocate ();
2016 memset (new_al, 0, sizeof (*new_al));
2018 new_al->offset = offset;
2019 new_al->size = val_size;
2020 new_al->contains_variable = pre_existing;
2022 new_al->next = **aglat;
2023 **aglat = new_al;
2024 return true;
2028 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2029 containing an unknown value. */
2031 static bool
2032 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2034 bool ret = false;
2035 while (aglat)
2037 ret |= aglat->set_contains_variable ();
2038 aglat = aglat->next;
2040 return ret;
2043 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2044 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2045 parameter used for lattice value sources. Return true if DEST_PLATS changed
2046 in any way. */
2048 static bool
2049 merge_aggregate_lattices (struct cgraph_edge *cs,
2050 struct ipcp_param_lattices *dest_plats,
2051 struct ipcp_param_lattices *src_plats,
2052 int src_idx, HOST_WIDE_INT offset_delta)
2054 bool pre_existing = dest_plats->aggs != NULL;
2055 struct ipcp_agg_lattice **dst_aglat;
2056 bool ret = false;
2058 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2059 return true;
2060 if (src_plats->aggs_bottom)
2061 return set_agg_lats_contain_variable (dest_plats);
2062 if (src_plats->aggs_contain_variable)
2063 ret |= set_agg_lats_contain_variable (dest_plats);
2064 dst_aglat = &dest_plats->aggs;
2066 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2067 src_aglat;
2068 src_aglat = src_aglat->next)
2070 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2072 if (new_offset < 0)
2073 continue;
2074 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2075 &dst_aglat, pre_existing, &ret))
2077 struct ipcp_agg_lattice *new_al = *dst_aglat;
2079 dst_aglat = &(*dst_aglat)->next;
2080 if (src_aglat->bottom)
2082 ret |= new_al->set_contains_variable ();
2083 continue;
2085 if (src_aglat->contains_variable)
2086 ret |= new_al->set_contains_variable ();
2087 for (ipcp_value<tree> *val = src_aglat->values;
2088 val;
2089 val = val->next)
2090 ret |= new_al->add_value (val->value, cs, val, src_idx,
2091 src_aglat->offset);
2093 else if (dest_plats->aggs_bottom)
2094 return true;
2096 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2097 return ret;
2100 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2101 pass-through JFUNC and if so, whether it has conform and conforms to the
2102 rules about propagating values passed by reference. */
2104 static bool
2105 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
2106 struct ipa_jump_func *jfunc)
2108 return src_plats->aggs
2109 && (!src_plats->aggs_by_ref
2110 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2113 /* Propagate scalar values across jump function JFUNC that is associated with
2114 edge CS and put the values into DEST_LAT. */
2116 static bool
2117 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2118 struct ipa_jump_func *jfunc,
2119 struct ipcp_param_lattices *dest_plats)
2121 bool ret = false;
2123 if (dest_plats->aggs_bottom)
2124 return false;
2126 if (jfunc->type == IPA_JF_PASS_THROUGH
2127 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2129 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2130 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2131 struct ipcp_param_lattices *src_plats;
2133 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2134 if (agg_pass_through_permissible_p (src_plats, jfunc))
2136 /* Currently we do not produce clobber aggregate jump
2137 functions, replace with merging when we do. */
2138 gcc_assert (!jfunc->agg.items);
2139 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2140 src_idx, 0);
2142 else
2143 ret |= set_agg_lats_contain_variable (dest_plats);
2145 else if (jfunc->type == IPA_JF_ANCESTOR
2146 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2148 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2149 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2150 struct ipcp_param_lattices *src_plats;
2152 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2153 if (src_plats->aggs && src_plats->aggs_by_ref)
2155 /* Currently we do not produce clobber aggregate jump
2156 functions, replace with merging when we do. */
2157 gcc_assert (!jfunc->agg.items);
2158 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2159 ipa_get_jf_ancestor_offset (jfunc));
2161 else if (!src_plats->aggs_by_ref)
2162 ret |= set_agg_lats_to_bottom (dest_plats);
2163 else
2164 ret |= set_agg_lats_contain_variable (dest_plats);
2166 else if (jfunc->agg.items)
2168 bool pre_existing = dest_plats->aggs != NULL;
2169 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2170 struct ipa_agg_jf_item *item;
2171 int i;
2173 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2174 return true;
2176 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2178 HOST_WIDE_INT val_size;
2180 if (item->offset < 0)
2181 continue;
2182 gcc_checking_assert (is_gimple_ip_invariant (item->value));
2183 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2185 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2186 &aglat, pre_existing, &ret))
2188 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2189 aglat = &(*aglat)->next;
2191 else if (dest_plats->aggs_bottom)
2192 return true;
2195 ret |= set_chain_of_aglats_contains_variable (*aglat);
2197 else
2198 ret |= set_agg_lats_contain_variable (dest_plats);
2200 return ret;
2203 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2204 non-thunk) destination, the call passes through a thunk. */
2206 static bool
2207 call_passes_through_thunk_p (cgraph_edge *cs)
2209 cgraph_node *alias_or_thunk = cs->callee;
2210 while (alias_or_thunk->alias)
2211 alias_or_thunk = alias_or_thunk->get_alias_target ();
2212 return alias_or_thunk->thunk.thunk_p;
2215 /* Propagate constants from the caller to the callee of CS. INFO describes the
2216 caller. */
2218 static bool
2219 propagate_constants_across_call (struct cgraph_edge *cs)
2221 struct ipa_node_params *callee_info;
2222 enum availability availability;
2223 cgraph_node *callee;
2224 struct ipa_edge_args *args;
2225 bool ret = false;
2226 int i, args_count, parms_count;
2228 callee = cs->callee->function_symbol (&availability);
2229 if (!callee->definition)
2230 return false;
2231 gcc_checking_assert (callee->has_gimple_body_p ());
2232 callee_info = IPA_NODE_REF (callee);
2234 args = IPA_EDGE_REF (cs);
2235 args_count = ipa_get_cs_argument_count (args);
2236 parms_count = ipa_get_param_count (callee_info);
2237 if (parms_count == 0)
2238 return false;
2240 /* No propagation through instrumentation thunks is available yet.
2241 It should be possible with proper mapping of call args and
2242 instrumented callee params in the propagation loop below. But
2243 this case mostly occurs when legacy code calls instrumented code
2244 and it is not a primary target for optimizations.
2245 We detect instrumentation thunks in aliases and thunks chain by
2246 checking instrumentation_clone flag for chain source and target.
2247 Going through instrumentation thunks we always have it changed
2248 from 0 to 1 and all other nodes do not change it. */
2249 if (!cs->callee->instrumentation_clone
2250 && callee->instrumentation_clone)
2252 for (i = 0; i < parms_count; i++)
2253 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2254 i));
2255 return ret;
2258 /* If this call goes through a thunk we must not propagate to the first (0th)
2259 parameter. However, we might need to uncover a thunk from below a series
2260 of aliases first. */
2261 if (call_passes_through_thunk_p (cs))
2263 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2264 0));
2265 i = 1;
2267 else
2268 i = 0;
2270 for (; (i < args_count) && (i < parms_count); i++)
2272 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2273 struct ipcp_param_lattices *dest_plats;
2274 tree param_type = ipa_get_type (callee_info, i);
2276 dest_plats = ipa_get_parm_lattices (callee_info, i);
2277 if (availability == AVAIL_INTERPOSABLE)
2278 ret |= set_all_contains_variable (dest_plats);
2279 else
2281 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2282 &dest_plats->itself);
2283 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2284 &dest_plats->ctxlat);
2286 |= propagate_bits_across_jump_function (cs, i, jump_func,
2287 &dest_plats->bits_lattice);
2288 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2289 dest_plats);
2290 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2291 ret |= propagate_vr_across_jump_function (cs, jump_func,
2292 dest_plats, param_type);
2293 else
2294 ret |= dest_plats->m_value_range.set_to_bottom ();
2297 for (; i < parms_count; i++)
2298 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2300 return ret;
2303 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2304 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2305 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2307 static tree
2308 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2309 vec<tree> known_csts,
2310 vec<ipa_polymorphic_call_context> known_contexts,
2311 vec<ipa_agg_jump_function_p> known_aggs,
2312 struct ipa_agg_replacement_value *agg_reps,
2313 bool *speculative)
2315 int param_index = ie->indirect_info->param_index;
2316 HOST_WIDE_INT anc_offset;
2317 tree t;
2318 tree target = NULL;
2320 *speculative = false;
2322 if (param_index == -1
2323 || known_csts.length () <= (unsigned int) param_index)
2324 return NULL_TREE;
2326 if (!ie->indirect_info->polymorphic)
2328 tree t;
2330 if (ie->indirect_info->agg_contents)
2332 t = NULL;
2333 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2335 while (agg_reps)
2337 if (agg_reps->index == param_index
2338 && agg_reps->offset == ie->indirect_info->offset
2339 && agg_reps->by_ref == ie->indirect_info->by_ref)
2341 t = agg_reps->value;
2342 break;
2344 agg_reps = agg_reps->next;
2347 if (!t)
2349 struct ipa_agg_jump_function *agg;
2350 if (known_aggs.length () > (unsigned int) param_index)
2351 agg = known_aggs[param_index];
2352 else
2353 agg = NULL;
2354 bool from_global_constant;
2355 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2356 ie->indirect_info->offset,
2357 ie->indirect_info->by_ref,
2358 &from_global_constant);
2359 if (t
2360 && !from_global_constant
2361 && !ie->indirect_info->guaranteed_unmodified)
2362 t = NULL_TREE;
2365 else
2366 t = known_csts[param_index];
2368 if (t
2369 && TREE_CODE (t) == ADDR_EXPR
2370 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2371 return TREE_OPERAND (t, 0);
2372 else
2373 return NULL_TREE;
2376 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2377 return NULL_TREE;
2379 gcc_assert (!ie->indirect_info->agg_contents);
2380 anc_offset = ie->indirect_info->offset;
2382 t = NULL;
2384 /* Try to work out value of virtual table pointer value in replacemnets. */
2385 if (!t && agg_reps && !ie->indirect_info->by_ref)
2387 while (agg_reps)
2389 if (agg_reps->index == param_index
2390 && agg_reps->offset == ie->indirect_info->offset
2391 && agg_reps->by_ref)
2393 t = agg_reps->value;
2394 break;
2396 agg_reps = agg_reps->next;
2400 /* Try to work out value of virtual table pointer value in known
2401 aggregate values. */
2402 if (!t && known_aggs.length () > (unsigned int) param_index
2403 && !ie->indirect_info->by_ref)
2405 struct ipa_agg_jump_function *agg;
2406 agg = known_aggs[param_index];
2407 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2408 ie->indirect_info->offset, true);
2411 /* If we found the virtual table pointer, lookup the target. */
2412 if (t)
2414 tree vtable;
2415 unsigned HOST_WIDE_INT offset;
2416 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2418 bool can_refer;
2419 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2420 vtable, offset, &can_refer);
2421 if (can_refer)
2423 if (!target
2424 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2425 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2426 || !possible_polymorphic_call_target_p
2427 (ie, cgraph_node::get (target)))
2429 /* Do not speculate builtin_unreachable, it is stupid! */
2430 if (ie->indirect_info->vptr_changed)
2431 return NULL;
2432 target = ipa_impossible_devirt_target (ie, target);
2434 *speculative = ie->indirect_info->vptr_changed;
2435 if (!*speculative)
2436 return target;
2441 /* Do we know the constant value of pointer? */
2442 if (!t)
2443 t = known_csts[param_index];
2445 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2447 ipa_polymorphic_call_context context;
2448 if (known_contexts.length () > (unsigned int) param_index)
2450 context = known_contexts[param_index];
2451 context.offset_by (anc_offset);
2452 if (ie->indirect_info->vptr_changed)
2453 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2454 ie->indirect_info->otr_type);
2455 if (t)
2457 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2458 (t, ie->indirect_info->otr_type, anc_offset);
2459 if (!ctx2.useless_p ())
2460 context.combine_with (ctx2, ie->indirect_info->otr_type);
2463 else if (t)
2465 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2466 anc_offset);
2467 if (ie->indirect_info->vptr_changed)
2468 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2469 ie->indirect_info->otr_type);
2471 else
2472 return NULL_TREE;
2474 vec <cgraph_node *>targets;
2475 bool final;
2477 targets = possible_polymorphic_call_targets
2478 (ie->indirect_info->otr_type,
2479 ie->indirect_info->otr_token,
2480 context, &final);
2481 if (!final || targets.length () > 1)
2483 struct cgraph_node *node;
2484 if (*speculative)
2485 return target;
2486 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2487 || ie->speculative || !ie->maybe_hot_p ())
2488 return NULL;
2489 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2490 ie->indirect_info->otr_token,
2491 context);
2492 if (node)
2494 *speculative = true;
2495 target = node->decl;
2497 else
2498 return NULL;
2500 else
2502 *speculative = false;
2503 if (targets.length () == 1)
2504 target = targets[0]->decl;
2505 else
2506 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2509 if (target && !possible_polymorphic_call_target_p (ie,
2510 cgraph_node::get (target)))
2512 if (*speculative)
2513 return NULL;
2514 target = ipa_impossible_devirt_target (ie, target);
2517 return target;
2521 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2522 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2523 return the destination. */
2525 tree
2526 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2527 vec<tree> known_csts,
2528 vec<ipa_polymorphic_call_context> known_contexts,
2529 vec<ipa_agg_jump_function_p> known_aggs,
2530 bool *speculative)
2532 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2533 known_aggs, NULL, speculative);
2536 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2537 and KNOWN_CONTEXTS. */
2539 static int
2540 devirtualization_time_bonus (struct cgraph_node *node,
2541 vec<tree> known_csts,
2542 vec<ipa_polymorphic_call_context> known_contexts,
2543 vec<ipa_agg_jump_function_p> known_aggs)
2545 struct cgraph_edge *ie;
2546 int res = 0;
2548 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2550 struct cgraph_node *callee;
2551 struct ipa_fn_summary *isummary;
2552 enum availability avail;
2553 tree target;
2554 bool speculative;
2556 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2557 known_aggs, &speculative);
2558 if (!target)
2559 continue;
2561 /* Only bare minimum benefit for clearly un-inlineable targets. */
2562 res += 1;
2563 callee = cgraph_node::get (target);
2564 if (!callee || !callee->definition)
2565 continue;
2566 callee = callee->function_symbol (&avail);
2567 if (avail < AVAIL_AVAILABLE)
2568 continue;
2569 isummary = ipa_fn_summaries->get (callee);
2570 if (!isummary->inlinable)
2571 continue;
2573 /* FIXME: The values below need re-considering and perhaps also
2574 integrating into the cost metrics, at lest in some very basic way. */
2575 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2576 res += 31 / ((int)speculative + 1);
2577 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2578 res += 15 / ((int)speculative + 1);
2579 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2580 || DECL_DECLARED_INLINE_P (callee->decl))
2581 res += 7 / ((int)speculative + 1);
2584 return res;
2587 /* Return time bonus incurred because of HINTS. */
2589 static int
2590 hint_time_bonus (ipa_hints hints)
2592 int result = 0;
2593 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2594 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2595 if (hints & INLINE_HINT_array_index)
2596 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2597 return result;
2600 /* If there is a reason to penalize the function described by INFO in the
2601 cloning goodness evaluation, do so. */
2603 static inline int64_t
2604 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2606 if (info->node_within_scc)
2607 evaluation = (evaluation
2608 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2610 if (info->node_calling_single_call)
2611 evaluation = (evaluation
2612 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2613 / 100;
2615 return evaluation;
2618 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2619 and SIZE_COST and with the sum of frequencies of incoming edges to the
2620 potential new clone in FREQUENCIES. */
2622 static bool
2623 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2624 int freq_sum, profile_count count_sum, int size_cost)
2626 if (time_benefit == 0
2627 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2628 || node->optimize_for_size_p ())
2629 return false;
2631 gcc_assert (size_cost > 0);
2633 struct ipa_node_params *info = IPA_NODE_REF (node);
2634 if (max_count > profile_count::zero ())
2636 int factor = RDIV (count_sum.probability_in
2637 (max_count).to_reg_br_prob_base ()
2638 * 1000, REG_BR_PROB_BASE);
2639 int64_t evaluation = (((int64_t) time_benefit * factor)
2640 / size_cost);
2641 evaluation = incorporate_penalties (info, evaluation);
2643 if (dump_file && (dump_flags & TDF_DETAILS))
2645 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2646 "size: %i, count_sum: ", time_benefit, size_cost);
2647 count_sum.dump (dump_file);
2648 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
2649 ", threshold: %i\n",
2650 info->node_within_scc ? ", scc" : "",
2651 info->node_calling_single_call ? ", single_call" : "",
2652 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2655 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2657 else
2659 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2660 / size_cost);
2661 evaluation = incorporate_penalties (info, evaluation);
2663 if (dump_file && (dump_flags & TDF_DETAILS))
2664 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2665 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2666 "%" PRId64 ", threshold: %i\n",
2667 time_benefit, size_cost, freq_sum,
2668 info->node_within_scc ? ", scc" : "",
2669 info->node_calling_single_call ? ", single_call" : "",
2670 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2672 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2676 /* Return all context independent values from aggregate lattices in PLATS in a
2677 vector. Return NULL if there are none. */
2679 static vec<ipa_agg_jf_item, va_gc> *
2680 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2682 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2684 if (plats->aggs_bottom
2685 || plats->aggs_contain_variable
2686 || plats->aggs_count == 0)
2687 return NULL;
2689 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2690 aglat;
2691 aglat = aglat->next)
2692 if (aglat->is_single_const ())
2694 struct ipa_agg_jf_item item;
2695 item.offset = aglat->offset;
2696 item.value = aglat->values->value;
2697 vec_safe_push (res, item);
2699 return res;
2702 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2703 populate them with values of parameters that are known independent of the
2704 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2705 non-NULL, the movement cost of all removable parameters will be stored in
2706 it. */
2708 static bool
2709 gather_context_independent_values (struct ipa_node_params *info,
2710 vec<tree> *known_csts,
2711 vec<ipa_polymorphic_call_context>
2712 *known_contexts,
2713 vec<ipa_agg_jump_function> *known_aggs,
2714 int *removable_params_cost)
2716 int i, count = ipa_get_param_count (info);
2717 bool ret = false;
2719 known_csts->create (0);
2720 known_contexts->create (0);
2721 known_csts->safe_grow_cleared (count);
2722 known_contexts->safe_grow_cleared (count);
2723 if (known_aggs)
2725 known_aggs->create (0);
2726 known_aggs->safe_grow_cleared (count);
2729 if (removable_params_cost)
2730 *removable_params_cost = 0;
2732 for (i = 0; i < count; i++)
2734 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2735 ipcp_lattice<tree> *lat = &plats->itself;
2737 if (lat->is_single_const ())
2739 ipcp_value<tree> *val = lat->values;
2740 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2741 (*known_csts)[i] = val->value;
2742 if (removable_params_cost)
2743 *removable_params_cost
2744 += estimate_move_cost (TREE_TYPE (val->value), false);
2745 ret = true;
2747 else if (removable_params_cost
2748 && !ipa_is_param_used (info, i))
2749 *removable_params_cost
2750 += ipa_get_param_move_cost (info, i);
2752 if (!ipa_is_param_used (info, i))
2753 continue;
2755 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2756 /* Do not account known context as reason for cloning. We can see
2757 if it permits devirtualization. */
2758 if (ctxlat->is_single_const ())
2759 (*known_contexts)[i] = ctxlat->values->value;
2761 if (known_aggs)
2763 vec<ipa_agg_jf_item, va_gc> *agg_items;
2764 struct ipa_agg_jump_function *ajf;
2766 agg_items = context_independent_aggregate_values (plats);
2767 ajf = &(*known_aggs)[i];
2768 ajf->items = agg_items;
2769 ajf->by_ref = plats->aggs_by_ref;
2770 ret |= agg_items != NULL;
2774 return ret;
2777 /* The current interface in ipa-inline-analysis requires a pointer vector.
2778 Create it.
2780 FIXME: That interface should be re-worked, this is slightly silly. Still,
2781 I'd like to discuss how to change it first and this demonstrates the
2782 issue. */
2784 static vec<ipa_agg_jump_function_p>
2785 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2787 vec<ipa_agg_jump_function_p> ret;
2788 struct ipa_agg_jump_function *ajf;
2789 int i;
2791 ret.create (known_aggs.length ());
2792 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2793 ret.quick_push (ajf);
2794 return ret;
2797 /* Perform time and size measurement of NODE with the context given in
2798 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2799 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2800 all context-independent removable parameters and EST_MOVE_COST of estimated
2801 movement of the considered parameter and store it into VAL. */
2803 static void
2804 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2805 vec<ipa_polymorphic_call_context> known_contexts,
2806 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2807 int removable_params_cost,
2808 int est_move_cost, ipcp_value_base *val)
2810 int size, time_benefit;
2811 sreal time, base_time;
2812 ipa_hints hints;
2814 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2815 known_aggs_ptrs, &size, &time,
2816 &base_time, &hints);
2817 base_time -= time;
2818 if (base_time > 65535)
2819 base_time = 65535;
2820 time_benefit = base_time.to_int ()
2821 + devirtualization_time_bonus (node, known_csts, known_contexts,
2822 known_aggs_ptrs)
2823 + hint_time_bonus (hints)
2824 + removable_params_cost + est_move_cost;
2826 gcc_checking_assert (size >=0);
2827 /* The inliner-heuristics based estimates may think that in certain
2828 contexts some functions do not have any size at all but we want
2829 all specializations to have at least a tiny cost, not least not to
2830 divide by zero. */
2831 if (size == 0)
2832 size = 1;
2834 val->local_time_benefit = time_benefit;
2835 val->local_size_cost = size;
2838 /* Iterate over known values of parameters of NODE and estimate the local
2839 effects in terms of time and size they have. */
2841 static void
2842 estimate_local_effects (struct cgraph_node *node)
2844 struct ipa_node_params *info = IPA_NODE_REF (node);
2845 int i, count = ipa_get_param_count (info);
2846 vec<tree> known_csts;
2847 vec<ipa_polymorphic_call_context> known_contexts;
2848 vec<ipa_agg_jump_function> known_aggs;
2849 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2850 bool always_const;
2851 int removable_params_cost;
2853 if (!count || !ipcp_versionable_function_p (node))
2854 return;
2856 if (dump_file && (dump_flags & TDF_DETAILS))
2857 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
2859 always_const = gather_context_independent_values (info, &known_csts,
2860 &known_contexts, &known_aggs,
2861 &removable_params_cost);
2862 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2863 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2864 known_contexts, known_aggs_ptrs);
2865 if (always_const || devirt_bonus
2866 || (removable_params_cost && node->local.can_change_signature))
2868 struct caller_statistics stats;
2869 ipa_hints hints;
2870 sreal time, base_time;
2871 int size;
2873 init_caller_stats (&stats);
2874 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2875 false);
2876 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2877 known_aggs_ptrs, &size, &time,
2878 &base_time, &hints);
2879 time -= devirt_bonus;
2880 time -= hint_time_bonus (hints);
2881 time -= removable_params_cost;
2882 size -= stats.n_calls * removable_params_cost;
2884 if (dump_file)
2885 fprintf (dump_file, " - context independent values, size: %i, "
2886 "time_benefit: %f\n", size, (base_time - time).to_double ());
2888 if (size <= 0 || node->local.local)
2890 info->do_clone_for_all_contexts = true;
2892 if (dump_file)
2893 fprintf (dump_file, " Decided to specialize for all "
2894 "known contexts, code not going to grow.\n");
2896 else if (good_cloning_opportunity_p (node,
2897 MAX ((base_time - time).to_int (),
2898 65536),
2899 stats.freq_sum, stats.count_sum,
2900 size))
2902 if (size + overall_size <= max_new_size)
2904 info->do_clone_for_all_contexts = true;
2905 overall_size += size;
2907 if (dump_file)
2908 fprintf (dump_file, " Decided to specialize for all "
2909 "known contexts, growth deemed beneficial.\n");
2911 else if (dump_file && (dump_flags & TDF_DETAILS))
2912 fprintf (dump_file, " Not cloning for all contexts because "
2913 "max_new_size would be reached with %li.\n",
2914 size + overall_size);
2916 else if (dump_file && (dump_flags & TDF_DETAILS))
2917 fprintf (dump_file, " Not cloning for all contexts because "
2918 "!good_cloning_opportunity_p.\n");
2922 for (i = 0; i < count; i++)
2924 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2925 ipcp_lattice<tree> *lat = &plats->itself;
2926 ipcp_value<tree> *val;
2928 if (lat->bottom
2929 || !lat->values
2930 || known_csts[i])
2931 continue;
2933 for (val = lat->values; val; val = val->next)
2935 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2936 known_csts[i] = val->value;
2938 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2939 perform_estimation_of_a_value (node, known_csts, known_contexts,
2940 known_aggs_ptrs,
2941 removable_params_cost, emc, val);
2943 if (dump_file && (dump_flags & TDF_DETAILS))
2945 fprintf (dump_file, " - estimates for value ");
2946 print_ipcp_constant_value (dump_file, val->value);
2947 fprintf (dump_file, " for ");
2948 ipa_dump_param (dump_file, info, i);
2949 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2950 val->local_time_benefit, val->local_size_cost);
2953 known_csts[i] = NULL_TREE;
2956 for (i = 0; i < count; i++)
2958 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2960 if (!plats->virt_call)
2961 continue;
2963 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2964 ipcp_value<ipa_polymorphic_call_context> *val;
2966 if (ctxlat->bottom
2967 || !ctxlat->values
2968 || !known_contexts[i].useless_p ())
2969 continue;
2971 for (val = ctxlat->values; val; val = val->next)
2973 known_contexts[i] = val->value;
2974 perform_estimation_of_a_value (node, known_csts, known_contexts,
2975 known_aggs_ptrs,
2976 removable_params_cost, 0, val);
2978 if (dump_file && (dump_flags & TDF_DETAILS))
2980 fprintf (dump_file, " - estimates for polymorphic context ");
2981 print_ipcp_constant_value (dump_file, val->value);
2982 fprintf (dump_file, " for ");
2983 ipa_dump_param (dump_file, info, i);
2984 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2985 val->local_time_benefit, val->local_size_cost);
2988 known_contexts[i] = ipa_polymorphic_call_context ();
2991 for (i = 0; i < count; i++)
2993 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2994 struct ipa_agg_jump_function *ajf;
2995 struct ipcp_agg_lattice *aglat;
2997 if (plats->aggs_bottom || !plats->aggs)
2998 continue;
3000 ajf = &known_aggs[i];
3001 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3003 ipcp_value<tree> *val;
3004 if (aglat->bottom || !aglat->values
3005 /* If the following is true, the one value is in known_aggs. */
3006 || (!plats->aggs_contain_variable
3007 && aglat->is_single_const ()))
3008 continue;
3010 for (val = aglat->values; val; val = val->next)
3012 struct ipa_agg_jf_item item;
3014 item.offset = aglat->offset;
3015 item.value = val->value;
3016 vec_safe_push (ajf->items, item);
3018 perform_estimation_of_a_value (node, known_csts, known_contexts,
3019 known_aggs_ptrs,
3020 removable_params_cost, 0, val);
3022 if (dump_file && (dump_flags & TDF_DETAILS))
3024 fprintf (dump_file, " - estimates for value ");
3025 print_ipcp_constant_value (dump_file, val->value);
3026 fprintf (dump_file, " for ");
3027 ipa_dump_param (dump_file, info, i);
3028 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3029 "]: time_benefit: %i, size: %i\n",
3030 plats->aggs_by_ref ? "ref " : "",
3031 aglat->offset,
3032 val->local_time_benefit, val->local_size_cost);
3035 ajf->items->pop ();
3040 for (i = 0; i < count; i++)
3041 vec_free (known_aggs[i].items);
3043 known_csts.release ();
3044 known_contexts.release ();
3045 known_aggs.release ();
3046 known_aggs_ptrs.release ();
3050 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3051 topological sort of values. */
3053 template <typename valtype>
3054 void
3055 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3057 ipcp_value_source<valtype> *src;
3059 if (cur_val->dfs)
3060 return;
3062 dfs_counter++;
3063 cur_val->dfs = dfs_counter;
3064 cur_val->low_link = dfs_counter;
3066 cur_val->topo_next = stack;
3067 stack = cur_val;
3068 cur_val->on_stack = true;
3070 for (src = cur_val->sources; src; src = src->next)
3071 if (src->val)
3073 if (src->val->dfs == 0)
3075 add_val (src->val);
3076 if (src->val->low_link < cur_val->low_link)
3077 cur_val->low_link = src->val->low_link;
3079 else if (src->val->on_stack
3080 && src->val->dfs < cur_val->low_link)
3081 cur_val->low_link = src->val->dfs;
3084 if (cur_val->dfs == cur_val->low_link)
3086 ipcp_value<valtype> *v, *scc_list = NULL;
3090 v = stack;
3091 stack = v->topo_next;
3092 v->on_stack = false;
3094 v->scc_next = scc_list;
3095 scc_list = v;
3097 while (v != cur_val);
3099 cur_val->topo_next = values_topo;
3100 values_topo = cur_val;
3104 /* Add all values in lattices associated with NODE to the topological sort if
3105 they are not there yet. */
3107 static void
3108 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3110 struct ipa_node_params *info = IPA_NODE_REF (node);
3111 int i, count = ipa_get_param_count (info);
3113 for (i = 0; i < count; i++)
3115 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3116 ipcp_lattice<tree> *lat = &plats->itself;
3117 struct ipcp_agg_lattice *aglat;
3119 if (!lat->bottom)
3121 ipcp_value<tree> *val;
3122 for (val = lat->values; val; val = val->next)
3123 topo->constants.add_val (val);
3126 if (!plats->aggs_bottom)
3127 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3128 if (!aglat->bottom)
3130 ipcp_value<tree> *val;
3131 for (val = aglat->values; val; val = val->next)
3132 topo->constants.add_val (val);
3135 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3136 if (!ctxlat->bottom)
3138 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3139 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3140 topo->contexts.add_val (ctxval);
3145 /* One pass of constants propagation along the call graph edges, from callers
3146 to callees (requires topological ordering in TOPO), iterate over strongly
3147 connected components. */
3149 static void
3150 propagate_constants_topo (struct ipa_topo_info *topo)
3152 int i;
3154 for (i = topo->nnodes - 1; i >= 0; i--)
3156 unsigned j;
3157 struct cgraph_node *v, *node = topo->order[i];
3158 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3160 /* First, iteratively propagate within the strongly connected component
3161 until all lattices stabilize. */
3162 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3163 if (v->has_gimple_body_p ())
3164 push_node_to_stack (topo, v);
3166 v = pop_node_from_stack (topo);
3167 while (v)
3169 struct cgraph_edge *cs;
3171 for (cs = v->callees; cs; cs = cs->next_callee)
3172 if (ipa_edge_within_scc (cs))
3174 IPA_NODE_REF (v)->node_within_scc = true;
3175 if (propagate_constants_across_call (cs))
3176 push_node_to_stack (topo, cs->callee->function_symbol ());
3178 v = pop_node_from_stack (topo);
3181 /* Afterwards, propagate along edges leading out of the SCC, calculates
3182 the local effects of the discovered constants and all valid values to
3183 their topological sort. */
3184 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3185 if (v->has_gimple_body_p ())
3187 struct cgraph_edge *cs;
3189 estimate_local_effects (v);
3190 add_all_node_vals_to_toposort (v, topo);
3191 for (cs = v->callees; cs; cs = cs->next_callee)
3192 if (!ipa_edge_within_scc (cs))
3193 propagate_constants_across_call (cs);
3195 cycle_nodes.release ();
3200 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3201 the bigger one if otherwise. */
3203 static int
3204 safe_add (int a, int b)
3206 if (a > INT_MAX/2 || b > INT_MAX/2)
3207 return a > b ? a : b;
3208 else
3209 return a + b;
3213 /* Propagate the estimated effects of individual values along the topological
3214 from the dependent values to those they depend on. */
3216 template <typename valtype>
3217 void
3218 value_topo_info<valtype>::propagate_effects ()
3220 ipcp_value<valtype> *base;
3222 for (base = values_topo; base; base = base->topo_next)
3224 ipcp_value_source<valtype> *src;
3225 ipcp_value<valtype> *val;
3226 int time = 0, size = 0;
3228 for (val = base; val; val = val->scc_next)
3230 time = safe_add (time,
3231 val->local_time_benefit + val->prop_time_benefit);
3232 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3235 for (val = base; val; val = val->scc_next)
3236 for (src = val->sources; src; src = src->next)
3237 if (src->val
3238 && src->cs->maybe_hot_p ())
3240 src->val->prop_time_benefit = safe_add (time,
3241 src->val->prop_time_benefit);
3242 src->val->prop_size_cost = safe_add (size,
3243 src->val->prop_size_cost);
3249 /* Propagate constants, polymorphic contexts and their effects from the
3250 summaries interprocedurally. */
3252 static void
3253 ipcp_propagate_stage (struct ipa_topo_info *topo)
3255 struct cgraph_node *node;
3257 if (dump_file)
3258 fprintf (dump_file, "\n Propagating constants:\n\n");
3260 max_count = profile_count::uninitialized ();
3262 FOR_EACH_DEFINED_FUNCTION (node)
3264 struct ipa_node_params *info = IPA_NODE_REF (node);
3266 determine_versionability (node, info);
3267 if (node->has_gimple_body_p ())
3269 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3270 ipa_get_param_count (info));
3271 initialize_node_lattices (node);
3273 if (node->definition && !node->alias)
3274 overall_size += ipa_fn_summaries->get (node)->self_size;
3275 max_count = max_count.max (node->count);
3278 max_new_size = overall_size;
3279 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3280 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3281 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3283 if (dump_file)
3284 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3285 overall_size, max_new_size);
3287 propagate_constants_topo (topo);
3288 if (flag_checking)
3289 ipcp_verify_propagated_values ();
3290 topo->constants.propagate_effects ();
3291 topo->contexts.propagate_effects ();
3293 if (dump_file)
3295 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3296 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3300 /* Discover newly direct outgoing edges from NODE which is a new clone with
3301 known KNOWN_CSTS and make them direct. */
3303 static void
3304 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3305 vec<tree> known_csts,
3306 vec<ipa_polymorphic_call_context>
3307 known_contexts,
3308 struct ipa_agg_replacement_value *aggvals)
3310 struct cgraph_edge *ie, *next_ie;
3311 bool found = false;
3313 for (ie = node->indirect_calls; ie; ie = next_ie)
3315 tree target;
3316 bool speculative;
3318 next_ie = ie->next_callee;
3319 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3320 vNULL, aggvals, &speculative);
3321 if (target)
3323 bool agg_contents = ie->indirect_info->agg_contents;
3324 bool polymorphic = ie->indirect_info->polymorphic;
3325 int param_index = ie->indirect_info->param_index;
3326 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3327 speculative);
3328 found = true;
3330 if (cs && !agg_contents && !polymorphic)
3332 struct ipa_node_params *info = IPA_NODE_REF (node);
3333 int c = ipa_get_controlled_uses (info, param_index);
3334 if (c != IPA_UNDESCRIBED_USE)
3336 struct ipa_ref *to_del;
3338 c--;
3339 ipa_set_controlled_uses (info, param_index, c);
3340 if (dump_file && (dump_flags & TDF_DETAILS))
3341 fprintf (dump_file, " controlled uses count of param "
3342 "%i bumped down to %i\n", param_index, c);
3343 if (c == 0
3344 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3346 if (dump_file && (dump_flags & TDF_DETAILS))
3347 fprintf (dump_file, " and even removing its "
3348 "cloning-created reference\n");
3349 to_del->remove_reference ();
3355 /* Turning calls to direct calls will improve overall summary. */
3356 if (found)
3357 ipa_update_overall_fn_summary (node);
3360 /* Vector of pointers which for linked lists of clones of an original crgaph
3361 edge. */
3363 static vec<cgraph_edge *> next_edge_clone;
3364 static vec<cgraph_edge *> prev_edge_clone;
3366 static inline void
3367 grow_edge_clone_vectors (void)
3369 if (next_edge_clone.length ()
3370 <= (unsigned) symtab->edges_max_uid)
3371 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3372 if (prev_edge_clone.length ()
3373 <= (unsigned) symtab->edges_max_uid)
3374 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3377 /* Edge duplication hook to grow the appropriate linked list in
3378 next_edge_clone. */
3380 static void
3381 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
3382 void *)
3384 grow_edge_clone_vectors ();
3386 struct cgraph_edge *old_next = next_edge_clone[src->uid];
3387 if (old_next)
3388 prev_edge_clone[old_next->uid] = dst;
3389 prev_edge_clone[dst->uid] = src;
3391 next_edge_clone[dst->uid] = old_next;
3392 next_edge_clone[src->uid] = dst;
3395 /* Hook that is called by cgraph.c when an edge is removed. */
3397 static void
3398 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
3400 grow_edge_clone_vectors ();
3402 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
3403 struct cgraph_edge *next = next_edge_clone[cs->uid];
3404 if (prev)
3405 next_edge_clone[prev->uid] = next;
3406 if (next)
3407 prev_edge_clone[next->uid] = prev;
3410 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3411 parameter with the given INDEX. */
3413 static tree
3414 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3415 int index)
3417 struct ipa_agg_replacement_value *aggval;
3419 aggval = ipa_get_agg_replacements_for_node (node);
3420 while (aggval)
3422 if (aggval->offset == offset
3423 && aggval->index == index)
3424 return aggval->value;
3425 aggval = aggval->next;
3427 return NULL_TREE;
3430 /* Return true is NODE is DEST or its clone for all contexts. */
3432 static bool
3433 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3435 if (node == dest)
3436 return true;
3438 struct ipa_node_params *info = IPA_NODE_REF (node);
3439 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3442 /* Return true if edge CS does bring about the value described by SRC to node
3443 DEST or its clone for all contexts. */
3445 static bool
3446 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3447 cgraph_node *dest)
3449 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3450 enum availability availability;
3451 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3453 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3454 || availability <= AVAIL_INTERPOSABLE
3455 || caller_info->node_dead)
3456 return false;
3457 if (!src->val)
3458 return true;
3460 if (caller_info->ipcp_orig_node)
3462 tree t;
3463 if (src->offset == -1)
3464 t = caller_info->known_csts[src->index];
3465 else
3466 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3467 return (t != NULL_TREE
3468 && values_equal_for_ipcp_p (src->val->value, t));
3470 else
3472 struct ipcp_agg_lattice *aglat;
3473 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3474 src->index);
3475 if (src->offset == -1)
3476 return (plats->itself.is_single_const ()
3477 && values_equal_for_ipcp_p (src->val->value,
3478 plats->itself.values->value));
3479 else
3481 if (plats->aggs_bottom || plats->aggs_contain_variable)
3482 return false;
3483 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3484 if (aglat->offset == src->offset)
3485 return (aglat->is_single_const ()
3486 && values_equal_for_ipcp_p (src->val->value,
3487 aglat->values->value));
3489 return false;
3493 /* Return true if edge CS does bring about the value described by SRC to node
3494 DEST or its clone for all contexts. */
3496 static bool
3497 cgraph_edge_brings_value_p (cgraph_edge *cs,
3498 ipcp_value_source<ipa_polymorphic_call_context> *src,
3499 cgraph_node *dest)
3501 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3502 cgraph_node *real_dest = cs->callee->function_symbol ();
3504 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3505 || caller_info->node_dead)
3506 return false;
3507 if (!src->val)
3508 return true;
3510 if (caller_info->ipcp_orig_node)
3511 return (caller_info->known_contexts.length () > (unsigned) src->index)
3512 && values_equal_for_ipcp_p (src->val->value,
3513 caller_info->known_contexts[src->index]);
3515 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3516 src->index);
3517 return plats->ctxlat.is_single_const ()
3518 && values_equal_for_ipcp_p (src->val->value,
3519 plats->ctxlat.values->value);
3522 /* Get the next clone in the linked list of clones of an edge. */
3524 static inline struct cgraph_edge *
3525 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3527 return next_edge_clone[cs->uid];
3530 /* Given VAL that is intended for DEST, iterate over all its sources and if
3531 they still hold, add their edge frequency and their number into *FREQUENCY
3532 and *CALLER_COUNT respectively. */
3534 template <typename valtype>
3535 static bool
3536 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3537 int *freq_sum,
3538 profile_count *count_sum, int *caller_count)
3540 ipcp_value_source<valtype> *src;
3541 int freq = 0, count = 0;
3542 profile_count cnt = profile_count::zero ();
3543 bool hot = false;
3545 for (src = val->sources; src; src = src->next)
3547 struct cgraph_edge *cs = src->cs;
3548 while (cs)
3550 if (cgraph_edge_brings_value_p (cs, src, dest))
3552 count++;
3553 freq += cs->frequency;
3554 if (cs->count.initialized_p ())
3555 cnt += cs->count;
3556 hot |= cs->maybe_hot_p ();
3558 cs = get_next_cgraph_edge_clone (cs);
3562 *freq_sum = freq;
3563 *count_sum = cnt;
3564 *caller_count = count;
3565 return hot;
3568 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3569 is assumed their number is known and equal to CALLER_COUNT. */
3571 template <typename valtype>
3572 static vec<cgraph_edge *>
3573 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3574 int caller_count)
3576 ipcp_value_source<valtype> *src;
3577 vec<cgraph_edge *> ret;
3579 ret.create (caller_count);
3580 for (src = val->sources; src; src = src->next)
3582 struct cgraph_edge *cs = src->cs;
3583 while (cs)
3585 if (cgraph_edge_brings_value_p (cs, src, dest))
3586 ret.quick_push (cs);
3587 cs = get_next_cgraph_edge_clone (cs);
3591 return ret;
3594 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3595 Return it or NULL if for some reason it cannot be created. */
3597 static struct ipa_replace_map *
3598 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3600 struct ipa_replace_map *replace_map;
3603 replace_map = ggc_alloc<ipa_replace_map> ();
3604 if (dump_file)
3606 fprintf (dump_file, " replacing ");
3607 ipa_dump_param (dump_file, info, parm_num);
3609 fprintf (dump_file, " with const ");
3610 print_generic_expr (dump_file, value);
3611 fprintf (dump_file, "\n");
3613 replace_map->old_tree = NULL;
3614 replace_map->parm_num = parm_num;
3615 replace_map->new_tree = value;
3616 replace_map->replace_p = true;
3617 replace_map->ref_p = false;
3619 return replace_map;
3622 /* Dump new profiling counts */
3624 static void
3625 dump_profile_updates (struct cgraph_node *orig_node,
3626 struct cgraph_node *new_node)
3628 struct cgraph_edge *cs;
3630 fprintf (dump_file, " setting count of the specialized node to ");
3631 new_node->count.dump (dump_file);
3632 fprintf (dump_file, "\n");
3633 for (cs = new_node->callees; cs; cs = cs->next_callee)
3635 fprintf (dump_file, " edge to %s has count ",
3636 cs->callee->name ());
3637 cs->count.dump (dump_file);
3638 fprintf (dump_file, "\n");
3641 fprintf (dump_file, " setting count of the original node to ");
3642 orig_node->count.dump (dump_file);
3643 fprintf (dump_file, "\n");
3644 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3646 fprintf (dump_file, " edge to %s is left with ",
3647 cs->callee->name ());
3648 cs->count.dump (dump_file);
3649 fprintf (dump_file, "\n");
3653 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3654 their profile information to reflect this. */
3656 static void
3657 update_profiling_info (struct cgraph_node *orig_node,
3658 struct cgraph_node *new_node)
3660 struct cgraph_edge *cs;
3661 struct caller_statistics stats;
3662 profile_count new_sum, orig_sum;
3663 profile_count remainder, orig_node_count = orig_node->count;
3665 if (!(orig_node_count > profile_count::zero ()))
3666 return;
3668 init_caller_stats (&stats);
3669 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3670 false);
3671 orig_sum = stats.count_sum;
3672 init_caller_stats (&stats);
3673 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3674 false);
3675 new_sum = stats.count_sum;
3677 if (orig_node_count < orig_sum + new_sum)
3679 if (dump_file)
3681 fprintf (dump_file, " Problem: node %s has too low count ",
3682 orig_node->dump_name ());
3683 orig_node_count.dump (dump_file);
3684 fprintf (dump_file, "while the sum of incoming count is ");
3685 (orig_sum + new_sum).dump (dump_file);
3686 fprintf (dump_file, "\n");
3689 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
3690 if (dump_file)
3692 fprintf (dump_file, " proceeding by pretending it was ");
3693 orig_node_count.dump (dump_file);
3694 fprintf (dump_file, "\n");
3698 new_node->count = new_sum;
3699 remainder = orig_node_count - new_sum;
3700 orig_node->count = remainder;
3702 for (cs = new_node->callees; cs; cs = cs->next_callee)
3703 /* FIXME: why we care about non-zero frequency here? */
3704 if (cs->frequency)
3705 cs->count = cs->count.apply_scale (new_sum, orig_node_count);
3706 else
3707 cs->count = profile_count::zero ();
3709 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3710 cs->count = cs->count.apply_scale (remainder, orig_node_count);
3712 if (dump_file)
3713 dump_profile_updates (orig_node, new_node);
3716 /* Update the respective profile of specialized NEW_NODE and the original
3717 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3718 have been redirected to the specialized version. */
3720 static void
3721 update_specialized_profile (struct cgraph_node *new_node,
3722 struct cgraph_node *orig_node,
3723 profile_count redirected_sum)
3725 struct cgraph_edge *cs;
3726 profile_count new_node_count, orig_node_count = orig_node->count;
3728 if (dump_file)
3730 fprintf (dump_file, " the sum of counts of redirected edges is ");
3731 redirected_sum.dump (dump_file);
3732 fprintf (dump_file, "\n");
3734 if (!(orig_node_count > profile_count::zero ()))
3735 return;
3737 gcc_assert (orig_node_count >= redirected_sum);
3739 new_node_count = new_node->count;
3740 new_node->count += redirected_sum;
3741 orig_node->count -= redirected_sum;
3743 for (cs = new_node->callees; cs; cs = cs->next_callee)
3744 if (cs->frequency)
3745 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
3746 else
3747 cs->count = profile_count::zero ();
3749 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3751 profile_count dec = cs->count.apply_scale (redirected_sum,
3752 orig_node_count);
3753 cs->count -= dec;
3756 if (dump_file)
3757 dump_profile_updates (orig_node, new_node);
3760 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3761 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3762 redirect all edges in CALLERS to it. */
3764 static struct cgraph_node *
3765 create_specialized_node (struct cgraph_node *node,
3766 vec<tree> known_csts,
3767 vec<ipa_polymorphic_call_context> known_contexts,
3768 struct ipa_agg_replacement_value *aggvals,
3769 vec<cgraph_edge *> callers)
3771 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3772 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3773 struct ipa_agg_replacement_value *av;
3774 struct cgraph_node *new_node;
3775 int i, count = ipa_get_param_count (info);
3776 bitmap args_to_skip;
3778 gcc_assert (!info->ipcp_orig_node);
3780 if (node->local.can_change_signature)
3782 args_to_skip = BITMAP_GGC_ALLOC ();
3783 for (i = 0; i < count; i++)
3785 tree t = known_csts[i];
3787 if (t || !ipa_is_param_used (info, i))
3788 bitmap_set_bit (args_to_skip, i);
3791 else
3793 args_to_skip = NULL;
3794 if (dump_file && (dump_flags & TDF_DETAILS))
3795 fprintf (dump_file, " cannot change function signature\n");
3798 for (i = 0; i < count; i++)
3800 tree t = known_csts[i];
3801 if (t)
3803 struct ipa_replace_map *replace_map;
3805 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3806 replace_map = get_replacement_map (info, t, i);
3807 if (replace_map)
3808 vec_safe_push (replace_trees, replace_map);
3812 new_node = node->create_virtual_clone (callers, replace_trees,
3813 args_to_skip, "constprop");
3814 ipa_set_node_agg_value_chain (new_node, aggvals);
3815 for (av = aggvals; av; av = av->next)
3816 new_node->maybe_create_reference (av->value, NULL);
3818 if (dump_file && (dump_flags & TDF_DETAILS))
3820 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
3821 if (known_contexts.exists ())
3823 for (i = 0; i < count; i++)
3824 if (!known_contexts[i].useless_p ())
3826 fprintf (dump_file, " known ctx %i is ", i);
3827 known_contexts[i].dump (dump_file);
3830 if (aggvals)
3831 ipa_dump_agg_replacement_values (dump_file, aggvals);
3833 ipa_check_create_node_params ();
3834 update_profiling_info (node, new_node);
3835 new_info = IPA_NODE_REF (new_node);
3836 new_info->ipcp_orig_node = node;
3837 new_info->known_csts = known_csts;
3838 new_info->known_contexts = known_contexts;
3840 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3842 callers.release ();
3843 return new_node;
3846 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3847 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3849 static void
3850 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3851 vec<tree> known_csts,
3852 vec<cgraph_edge *> callers)
3854 struct ipa_node_params *info = IPA_NODE_REF (node);
3855 int i, count = ipa_get_param_count (info);
3857 for (i = 0; i < count; i++)
3859 struct cgraph_edge *cs;
3860 tree newval = NULL_TREE;
3861 int j;
3862 bool first = true;
3864 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3865 continue;
3867 FOR_EACH_VEC_ELT (callers, j, cs)
3869 struct ipa_jump_func *jump_func;
3870 tree t;
3872 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3873 || (i == 0
3874 && call_passes_through_thunk_p (cs))
3875 || (!cs->callee->instrumentation_clone
3876 && cs->callee->function_symbol ()->instrumentation_clone))
3878 newval = NULL_TREE;
3879 break;
3881 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3882 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3883 if (!t
3884 || (newval
3885 && !values_equal_for_ipcp_p (t, newval))
3886 || (!first && !newval))
3888 newval = NULL_TREE;
3889 break;
3891 else
3892 newval = t;
3893 first = false;
3896 if (newval)
3898 if (dump_file && (dump_flags & TDF_DETAILS))
3900 fprintf (dump_file, " adding an extra known scalar value ");
3901 print_ipcp_constant_value (dump_file, newval);
3902 fprintf (dump_file, " for ");
3903 ipa_dump_param (dump_file, info, i);
3904 fprintf (dump_file, "\n");
3907 known_csts[i] = newval;
3912 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3913 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3914 CALLERS. */
3916 static void
3917 find_more_contexts_for_caller_subset (cgraph_node *node,
3918 vec<ipa_polymorphic_call_context>
3919 *known_contexts,
3920 vec<cgraph_edge *> callers)
3922 ipa_node_params *info = IPA_NODE_REF (node);
3923 int i, count = ipa_get_param_count (info);
3925 for (i = 0; i < count; i++)
3927 cgraph_edge *cs;
3929 if (ipa_get_poly_ctx_lat (info, i)->bottom
3930 || (known_contexts->exists ()
3931 && !(*known_contexts)[i].useless_p ()))
3932 continue;
3934 ipa_polymorphic_call_context newval;
3935 bool first = true;
3936 int j;
3938 FOR_EACH_VEC_ELT (callers, j, cs)
3940 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3941 return;
3942 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3944 ipa_polymorphic_call_context ctx;
3945 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3946 jfunc);
3947 if (first)
3949 newval = ctx;
3950 first = false;
3952 else
3953 newval.meet_with (ctx);
3954 if (newval.useless_p ())
3955 break;
3958 if (!newval.useless_p ())
3960 if (dump_file && (dump_flags & TDF_DETAILS))
3962 fprintf (dump_file, " adding an extra known polymorphic "
3963 "context ");
3964 print_ipcp_constant_value (dump_file, newval);
3965 fprintf (dump_file, " for ");
3966 ipa_dump_param (dump_file, info, i);
3967 fprintf (dump_file, "\n");
3970 if (!known_contexts->exists ())
3971 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3972 (*known_contexts)[i] = newval;
3978 /* Go through PLATS and create a vector of values consisting of values and
3979 offsets (minus OFFSET) of lattices that contain only a single value. */
3981 static vec<ipa_agg_jf_item>
3982 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3984 vec<ipa_agg_jf_item> res = vNULL;
3986 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3987 return vNULL;
3989 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3990 if (aglat->is_single_const ())
3992 struct ipa_agg_jf_item ti;
3993 ti.offset = aglat->offset - offset;
3994 ti.value = aglat->values->value;
3995 res.safe_push (ti);
3997 return res;
4000 /* Intersect all values in INTER with single value lattices in PLATS (while
4001 subtracting OFFSET). */
4003 static void
4004 intersect_with_plats (struct ipcp_param_lattices *plats,
4005 vec<ipa_agg_jf_item> *inter,
4006 HOST_WIDE_INT offset)
4008 struct ipcp_agg_lattice *aglat;
4009 struct ipa_agg_jf_item *item;
4010 int k;
4012 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4014 inter->release ();
4015 return;
4018 aglat = plats->aggs;
4019 FOR_EACH_VEC_ELT (*inter, k, item)
4021 bool found = false;
4022 if (!item->value)
4023 continue;
4024 while (aglat)
4026 if (aglat->offset - offset > item->offset)
4027 break;
4028 if (aglat->offset - offset == item->offset)
4030 gcc_checking_assert (item->value);
4031 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
4032 found = true;
4033 break;
4035 aglat = aglat->next;
4037 if (!found)
4038 item->value = NULL_TREE;
4042 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4043 vector result while subtracting OFFSET from the individual value offsets. */
4045 static vec<ipa_agg_jf_item>
4046 agg_replacements_to_vector (struct cgraph_node *node, int index,
4047 HOST_WIDE_INT offset)
4049 struct ipa_agg_replacement_value *av;
4050 vec<ipa_agg_jf_item> res = vNULL;
4052 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4053 if (av->index == index
4054 && (av->offset - offset) >= 0)
4056 struct ipa_agg_jf_item item;
4057 gcc_checking_assert (av->value);
4058 item.offset = av->offset - offset;
4059 item.value = av->value;
4060 res.safe_push (item);
4063 return res;
4066 /* Intersect all values in INTER with those that we have already scheduled to
4067 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4068 (while subtracting OFFSET). */
4070 static void
4071 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4072 vec<ipa_agg_jf_item> *inter,
4073 HOST_WIDE_INT offset)
4075 struct ipa_agg_replacement_value *srcvals;
4076 struct ipa_agg_jf_item *item;
4077 int i;
4079 srcvals = ipa_get_agg_replacements_for_node (node);
4080 if (!srcvals)
4082 inter->release ();
4083 return;
4086 FOR_EACH_VEC_ELT (*inter, i, item)
4088 struct ipa_agg_replacement_value *av;
4089 bool found = false;
4090 if (!item->value)
4091 continue;
4092 for (av = srcvals; av; av = av->next)
4094 gcc_checking_assert (av->value);
4095 if (av->index == index
4096 && av->offset - offset == item->offset)
4098 if (values_equal_for_ipcp_p (item->value, av->value))
4099 found = true;
4100 break;
4103 if (!found)
4104 item->value = NULL_TREE;
4108 /* Intersect values in INTER with aggregate values that come along edge CS to
4109 parameter number INDEX and return it. If INTER does not actually exist yet,
4110 copy all incoming values to it. If we determine we ended up with no values
4111 whatsoever, return a released vector. */
4113 static vec<ipa_agg_jf_item>
4114 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4115 vec<ipa_agg_jf_item> inter)
4117 struct ipa_jump_func *jfunc;
4118 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4119 if (jfunc->type == IPA_JF_PASS_THROUGH
4120 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4122 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4123 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4125 if (caller_info->ipcp_orig_node)
4127 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4128 struct ipcp_param_lattices *orig_plats;
4129 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4130 src_idx);
4131 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4133 if (!inter.exists ())
4134 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4135 else
4136 intersect_with_agg_replacements (cs->caller, src_idx,
4137 &inter, 0);
4139 else
4141 inter.release ();
4142 return vNULL;
4145 else
4147 struct ipcp_param_lattices *src_plats;
4148 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4149 if (agg_pass_through_permissible_p (src_plats, jfunc))
4151 /* Currently we do not produce clobber aggregate jump
4152 functions, adjust when we do. */
4153 gcc_checking_assert (!jfunc->agg.items);
4154 if (!inter.exists ())
4155 inter = copy_plats_to_inter (src_plats, 0);
4156 else
4157 intersect_with_plats (src_plats, &inter, 0);
4159 else
4161 inter.release ();
4162 return vNULL;
4166 else if (jfunc->type == IPA_JF_ANCESTOR
4167 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4169 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4170 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4171 struct ipcp_param_lattices *src_plats;
4172 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4174 if (caller_info->ipcp_orig_node)
4176 if (!inter.exists ())
4177 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4178 else
4179 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4180 delta);
4182 else
4184 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
4185 /* Currently we do not produce clobber aggregate jump
4186 functions, adjust when we do. */
4187 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4188 if (!inter.exists ())
4189 inter = copy_plats_to_inter (src_plats, delta);
4190 else
4191 intersect_with_plats (src_plats, &inter, delta);
4194 else if (jfunc->agg.items)
4196 struct ipa_agg_jf_item *item;
4197 int k;
4199 if (!inter.exists ())
4200 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4201 inter.safe_push ((*jfunc->agg.items)[i]);
4202 else
4203 FOR_EACH_VEC_ELT (inter, k, item)
4205 int l = 0;
4206 bool found = false;;
4208 if (!item->value)
4209 continue;
4211 while ((unsigned) l < jfunc->agg.items->length ())
4213 struct ipa_agg_jf_item *ti;
4214 ti = &(*jfunc->agg.items)[l];
4215 if (ti->offset > item->offset)
4216 break;
4217 if (ti->offset == item->offset)
4219 gcc_checking_assert (ti->value);
4220 if (values_equal_for_ipcp_p (item->value,
4221 ti->value))
4222 found = true;
4223 break;
4225 l++;
4227 if (!found)
4228 item->value = NULL;
4231 else
4233 inter.release ();
4234 return vec<ipa_agg_jf_item>();
4236 return inter;
4239 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4240 from all of them. */
4242 static struct ipa_agg_replacement_value *
4243 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4244 vec<cgraph_edge *> callers)
4246 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4247 struct ipa_agg_replacement_value *res;
4248 struct ipa_agg_replacement_value **tail = &res;
4249 struct cgraph_edge *cs;
4250 int i, j, count = ipa_get_param_count (dest_info);
4252 FOR_EACH_VEC_ELT (callers, j, cs)
4254 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4255 if (c < count)
4256 count = c;
4259 for (i = 0; i < count; i++)
4261 struct cgraph_edge *cs;
4262 vec<ipa_agg_jf_item> inter = vNULL;
4263 struct ipa_agg_jf_item *item;
4264 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4265 int j;
4267 /* Among other things, the following check should deal with all by_ref
4268 mismatches. */
4269 if (plats->aggs_bottom)
4270 continue;
4272 FOR_EACH_VEC_ELT (callers, j, cs)
4274 inter = intersect_aggregates_with_edge (cs, i, inter);
4276 if (!inter.exists ())
4277 goto next_param;
4280 FOR_EACH_VEC_ELT (inter, j, item)
4282 struct ipa_agg_replacement_value *v;
4284 if (!item->value)
4285 continue;
4287 v = ggc_alloc<ipa_agg_replacement_value> ();
4288 v->index = i;
4289 v->offset = item->offset;
4290 v->value = item->value;
4291 v->by_ref = plats->aggs_by_ref;
4292 *tail = v;
4293 tail = &v->next;
4296 next_param:
4297 if (inter.exists ())
4298 inter.release ();
4300 *tail = NULL;
4301 return res;
4304 /* Turn KNOWN_AGGS into a list of aggregate replacement values. */
4306 static struct ipa_agg_replacement_value *
4307 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
4309 struct ipa_agg_replacement_value *res;
4310 struct ipa_agg_replacement_value **tail = &res;
4311 struct ipa_agg_jump_function *aggjf;
4312 struct ipa_agg_jf_item *item;
4313 int i, j;
4315 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
4316 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
4318 struct ipa_agg_replacement_value *v;
4319 v = ggc_alloc<ipa_agg_replacement_value> ();
4320 v->index = i;
4321 v->offset = item->offset;
4322 v->value = item->value;
4323 v->by_ref = aggjf->by_ref;
4324 *tail = v;
4325 tail = &v->next;
4327 *tail = NULL;
4328 return res;
4331 /* Determine whether CS also brings all scalar values that the NODE is
4332 specialized for. */
4334 static bool
4335 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4336 struct cgraph_node *node)
4338 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4339 int count = ipa_get_param_count (dest_info);
4340 struct ipa_node_params *caller_info;
4341 struct ipa_edge_args *args;
4342 int i;
4344 caller_info = IPA_NODE_REF (cs->caller);
4345 args = IPA_EDGE_REF (cs);
4346 for (i = 0; i < count; i++)
4348 struct ipa_jump_func *jump_func;
4349 tree val, t;
4351 val = dest_info->known_csts[i];
4352 if (!val)
4353 continue;
4355 if (i >= ipa_get_cs_argument_count (args))
4356 return false;
4357 jump_func = ipa_get_ith_jump_func (args, i);
4358 t = ipa_value_from_jfunc (caller_info, jump_func);
4359 if (!t || !values_equal_for_ipcp_p (val, t))
4360 return false;
4362 return true;
4365 /* Determine whether CS also brings all aggregate values that NODE is
4366 specialized for. */
4367 static bool
4368 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4369 struct cgraph_node *node)
4371 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4372 struct ipa_node_params *orig_node_info;
4373 struct ipa_agg_replacement_value *aggval;
4374 int i, ec, count;
4376 aggval = ipa_get_agg_replacements_for_node (node);
4377 if (!aggval)
4378 return true;
4380 count = ipa_get_param_count (IPA_NODE_REF (node));
4381 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4382 if (ec < count)
4383 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4384 if (aggval->index >= ec)
4385 return false;
4387 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4388 if (orig_caller_info->ipcp_orig_node)
4389 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4391 for (i = 0; i < count; i++)
4393 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4394 struct ipcp_param_lattices *plats;
4395 bool interesting = false;
4396 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4397 if (aggval->index == i)
4399 interesting = true;
4400 break;
4402 if (!interesting)
4403 continue;
4405 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4406 if (plats->aggs_bottom)
4407 return false;
4409 values = intersect_aggregates_with_edge (cs, i, values);
4410 if (!values.exists ())
4411 return false;
4413 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4414 if (aggval->index == i)
4416 struct ipa_agg_jf_item *item;
4417 int j;
4418 bool found = false;
4419 FOR_EACH_VEC_ELT (values, j, item)
4420 if (item->value
4421 && item->offset == av->offset
4422 && values_equal_for_ipcp_p (item->value, av->value))
4424 found = true;
4425 break;
4427 if (!found)
4429 values.release ();
4430 return false;
4434 return true;
4437 /* Given an original NODE and a VAL for which we have already created a
4438 specialized clone, look whether there are incoming edges that still lead
4439 into the old node but now also bring the requested value and also conform to
4440 all other criteria such that they can be redirected the special node.
4441 This function can therefore redirect the final edge in a SCC. */
4443 template <typename valtype>
4444 static void
4445 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4447 ipcp_value_source<valtype> *src;
4448 profile_count redirected_sum = profile_count::zero ();
4450 for (src = val->sources; src; src = src->next)
4452 struct cgraph_edge *cs = src->cs;
4453 while (cs)
4455 if (cgraph_edge_brings_value_p (cs, src, node)
4456 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4457 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4459 if (dump_file)
4460 fprintf (dump_file, " - adding an extra caller %s of %s\n",
4461 cs->caller->dump_name (),
4462 val->spec_node->dump_name ());
4464 cs->redirect_callee_duplicating_thunks (val->spec_node);
4465 val->spec_node->expand_all_artificial_thunks ();
4466 if (cs->count.initialized_p ())
4467 redirected_sum = redirected_sum + cs->count;
4469 cs = get_next_cgraph_edge_clone (cs);
4473 if (redirected_sum > profile_count::zero ())
4474 update_specialized_profile (val->spec_node, node, redirected_sum);
4477 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4479 static bool
4480 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4482 ipa_polymorphic_call_context *ctx;
4483 int i;
4485 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4486 if (!ctx->useless_p ())
4487 return true;
4488 return false;
4491 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4493 static vec<ipa_polymorphic_call_context>
4494 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4496 if (known_contexts_useful_p (known_contexts))
4497 return known_contexts.copy ();
4498 else
4499 return vNULL;
4502 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4503 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4505 static void
4506 modify_known_vectors_with_val (vec<tree> *known_csts,
4507 vec<ipa_polymorphic_call_context> *known_contexts,
4508 ipcp_value<tree> *val,
4509 int index)
4511 *known_csts = known_csts->copy ();
4512 *known_contexts = copy_useful_known_contexts (*known_contexts);
4513 (*known_csts)[index] = val->value;
4516 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4517 copy according to VAL and INDEX. */
4519 static void
4520 modify_known_vectors_with_val (vec<tree> *known_csts,
4521 vec<ipa_polymorphic_call_context> *known_contexts,
4522 ipcp_value<ipa_polymorphic_call_context> *val,
4523 int index)
4525 *known_csts = known_csts->copy ();
4526 *known_contexts = known_contexts->copy ();
4527 (*known_contexts)[index] = val->value;
4530 /* Return true if OFFSET indicates this was not an aggregate value or there is
4531 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4532 AGGVALS list. */
4534 DEBUG_FUNCTION bool
4535 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4536 int index, HOST_WIDE_INT offset, tree value)
4538 if (offset == -1)
4539 return true;
4541 while (aggvals)
4543 if (aggvals->index == index
4544 && aggvals->offset == offset
4545 && values_equal_for_ipcp_p (aggvals->value, value))
4546 return true;
4547 aggvals = aggvals->next;
4549 return false;
4552 /* Return true if offset is minus one because source of a polymorphic contect
4553 cannot be an aggregate value. */
4555 DEBUG_FUNCTION bool
4556 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4557 int , HOST_WIDE_INT offset,
4558 ipa_polymorphic_call_context)
4560 return offset == -1;
4563 /* Decide wheter to create a special version of NODE for value VAL of parameter
4564 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4565 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4566 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4568 template <typename valtype>
4569 static bool
4570 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4571 ipcp_value<valtype> *val, vec<tree> known_csts,
4572 vec<ipa_polymorphic_call_context> known_contexts)
4574 struct ipa_agg_replacement_value *aggvals;
4575 int freq_sum, caller_count;
4576 profile_count count_sum;
4577 vec<cgraph_edge *> callers;
4579 if (val->spec_node)
4581 perhaps_add_new_callers (node, val);
4582 return false;
4584 else if (val->local_size_cost + overall_size > max_new_size)
4586 if (dump_file && (dump_flags & TDF_DETAILS))
4587 fprintf (dump_file, " Ignoring candidate value because "
4588 "max_new_size would be reached with %li.\n",
4589 val->local_size_cost + overall_size);
4590 return false;
4592 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4593 &caller_count))
4594 return false;
4596 if (dump_file && (dump_flags & TDF_DETAILS))
4598 fprintf (dump_file, " - considering value ");
4599 print_ipcp_constant_value (dump_file, val->value);
4600 fprintf (dump_file, " for ");
4601 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4602 if (offset != -1)
4603 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4604 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4607 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4608 freq_sum, count_sum,
4609 val->local_size_cost)
4610 && !good_cloning_opportunity_p (node,
4611 val->local_time_benefit
4612 + val->prop_time_benefit,
4613 freq_sum, count_sum,
4614 val->local_size_cost
4615 + val->prop_size_cost))
4616 return false;
4618 if (dump_file)
4619 fprintf (dump_file, " Creating a specialized node of %s.\n",
4620 node->dump_name ());
4622 callers = gather_edges_for_value (val, node, caller_count);
4623 if (offset == -1)
4624 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4625 else
4627 known_csts = known_csts.copy ();
4628 known_contexts = copy_useful_known_contexts (known_contexts);
4630 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4631 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4632 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4633 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4634 offset, val->value));
4635 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4636 aggvals, callers);
4637 overall_size += val->local_size_cost;
4639 /* TODO: If for some lattice there is only one other known value
4640 left, make a special node for it too. */
4642 return true;
4645 /* Decide whether and what specialized clones of NODE should be created. */
4647 static bool
4648 decide_whether_version_node (struct cgraph_node *node)
4650 struct ipa_node_params *info = IPA_NODE_REF (node);
4651 int i, count = ipa_get_param_count (info);
4652 vec<tree> known_csts;
4653 vec<ipa_polymorphic_call_context> known_contexts;
4654 vec<ipa_agg_jump_function> known_aggs = vNULL;
4655 bool ret = false;
4657 if (count == 0)
4658 return false;
4660 if (dump_file && (dump_flags & TDF_DETAILS))
4661 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
4662 node->dump_name ());
4664 gather_context_independent_values (info, &known_csts, &known_contexts,
4665 info->do_clone_for_all_contexts ? &known_aggs
4666 : NULL, NULL);
4668 for (i = 0; i < count;i++)
4670 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4671 ipcp_lattice<tree> *lat = &plats->itself;
4672 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4674 if (!lat->bottom
4675 && !known_csts[i])
4677 ipcp_value<tree> *val;
4678 for (val = lat->values; val; val = val->next)
4679 ret |= decide_about_value (node, i, -1, val, known_csts,
4680 known_contexts);
4683 if (!plats->aggs_bottom)
4685 struct ipcp_agg_lattice *aglat;
4686 ipcp_value<tree> *val;
4687 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4688 if (!aglat->bottom && aglat->values
4689 /* If the following is false, the one value is in
4690 known_aggs. */
4691 && (plats->aggs_contain_variable
4692 || !aglat->is_single_const ()))
4693 for (val = aglat->values; val; val = val->next)
4694 ret |= decide_about_value (node, i, aglat->offset, val,
4695 known_csts, known_contexts);
4698 if (!ctxlat->bottom
4699 && known_contexts[i].useless_p ())
4701 ipcp_value<ipa_polymorphic_call_context> *val;
4702 for (val = ctxlat->values; val; val = val->next)
4703 ret |= decide_about_value (node, i, -1, val, known_csts,
4704 known_contexts);
4707 info = IPA_NODE_REF (node);
4710 if (info->do_clone_for_all_contexts)
4712 struct cgraph_node *clone;
4713 vec<cgraph_edge *> callers;
4715 if (dump_file)
4716 fprintf (dump_file, " - Creating a specialized node of %s "
4717 "for all known contexts.\n", node->dump_name ());
4719 callers = node->collect_callers ();
4721 if (!known_contexts_useful_p (known_contexts))
4723 known_contexts.release ();
4724 known_contexts = vNULL;
4726 clone = create_specialized_node (node, known_csts, known_contexts,
4727 known_aggs_to_agg_replacement_list (known_aggs),
4728 callers);
4729 info = IPA_NODE_REF (node);
4730 info->do_clone_for_all_contexts = false;
4731 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4732 for (i = 0; i < count; i++)
4733 vec_free (known_aggs[i].items);
4734 known_aggs.release ();
4735 ret = true;
4737 else
4739 known_csts.release ();
4740 known_contexts.release ();
4743 return ret;
4746 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4748 static void
4749 spread_undeadness (struct cgraph_node *node)
4751 struct cgraph_edge *cs;
4753 for (cs = node->callees; cs; cs = cs->next_callee)
4754 if (ipa_edge_within_scc (cs))
4756 struct cgraph_node *callee;
4757 struct ipa_node_params *info;
4759 callee = cs->callee->function_symbol (NULL);
4760 info = IPA_NODE_REF (callee);
4762 if (info->node_dead)
4764 info->node_dead = 0;
4765 spread_undeadness (callee);
4770 /* Return true if NODE has a caller from outside of its SCC that is not
4771 dead. Worker callback for cgraph_for_node_and_aliases. */
4773 static bool
4774 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4775 void *data ATTRIBUTE_UNUSED)
4777 struct cgraph_edge *cs;
4779 for (cs = node->callers; cs; cs = cs->next_caller)
4780 if (cs->caller->thunk.thunk_p
4781 && cs->caller->call_for_symbol_thunks_and_aliases
4782 (has_undead_caller_from_outside_scc_p, NULL, true))
4783 return true;
4784 else if (!ipa_edge_within_scc (cs)
4785 && !IPA_NODE_REF (cs->caller)->node_dead)
4786 return true;
4787 return false;
4791 /* Identify nodes within the same SCC as NODE which are no longer needed
4792 because of new clones and will be removed as unreachable. */
4794 static void
4795 identify_dead_nodes (struct cgraph_node *node)
4797 struct cgraph_node *v;
4798 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4799 if (v->local.local
4800 && !v->call_for_symbol_thunks_and_aliases
4801 (has_undead_caller_from_outside_scc_p, NULL, true))
4802 IPA_NODE_REF (v)->node_dead = 1;
4804 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4805 if (!IPA_NODE_REF (v)->node_dead)
4806 spread_undeadness (v);
4808 if (dump_file && (dump_flags & TDF_DETAILS))
4810 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4811 if (IPA_NODE_REF (v)->node_dead)
4812 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
4816 /* The decision stage. Iterate over the topological order of call graph nodes
4817 TOPO and make specialized clones if deemed beneficial. */
4819 static void
4820 ipcp_decision_stage (struct ipa_topo_info *topo)
4822 int i;
4824 if (dump_file)
4825 fprintf (dump_file, "\nIPA decision stage:\n\n");
4827 for (i = topo->nnodes - 1; i >= 0; i--)
4829 struct cgraph_node *node = topo->order[i];
4830 bool change = false, iterate = true;
4832 while (iterate)
4834 struct cgraph_node *v;
4835 iterate = false;
4836 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4837 if (v->has_gimple_body_p ()
4838 && ipcp_versionable_function_p (v))
4839 iterate |= decide_whether_version_node (v);
4841 change |= iterate;
4843 if (change)
4844 identify_dead_nodes (node);
4848 /* Look up all the bits information that we have discovered and copy it over
4849 to the transformation summary. */
4851 static void
4852 ipcp_store_bits_results (void)
4854 cgraph_node *node;
4856 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4858 ipa_node_params *info = IPA_NODE_REF (node);
4859 bool dumped_sth = false;
4860 bool found_useful_result = false;
4862 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4864 if (dump_file)
4865 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4866 "; -fipa-bit-cp: disabled.\n",
4867 node->name ());
4868 continue;
4871 if (info->ipcp_orig_node)
4872 info = IPA_NODE_REF (info->ipcp_orig_node);
4874 unsigned count = ipa_get_param_count (info);
4875 for (unsigned i = 0; i < count; i++)
4877 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4878 if (plats->bits_lattice.constant_p ())
4880 found_useful_result = true;
4881 break;
4885 if (!found_useful_result)
4886 continue;
4888 ipcp_grow_transformations_if_necessary ();
4889 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4890 vec_safe_reserve_exact (ts->bits, count);
4892 for (unsigned i = 0; i < count; i++)
4894 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4895 ipa_bits *jfbits;
4897 if (plats->bits_lattice.constant_p ())
4898 jfbits
4899 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
4900 plats->bits_lattice.get_mask ());
4901 else
4902 jfbits = NULL;
4904 ts->bits->quick_push (jfbits);
4905 if (!dump_file || !jfbits)
4906 continue;
4907 if (!dumped_sth)
4909 fprintf (dump_file, "Propagated bits info for function %s:\n",
4910 node->dump_name ());
4911 dumped_sth = true;
4913 fprintf (dump_file, " param %i: value = ", i);
4914 print_hex (jfbits->value, dump_file);
4915 fprintf (dump_file, ", mask = ");
4916 print_hex (jfbits->mask, dump_file);
4917 fprintf (dump_file, "\n");
4922 /* Look up all VR information that we have discovered and copy it over
4923 to the transformation summary. */
4925 static void
4926 ipcp_store_vr_results (void)
4928 cgraph_node *node;
4930 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4932 ipa_node_params *info = IPA_NODE_REF (node);
4933 bool found_useful_result = false;
4935 if (!opt_for_fn (node->decl, flag_ipa_vrp))
4937 if (dump_file)
4938 fprintf (dump_file, "Not considering %s for VR discovery "
4939 "and propagate; -fipa-ipa-vrp: disabled.\n",
4940 node->name ());
4941 continue;
4944 if (info->ipcp_orig_node)
4945 info = IPA_NODE_REF (info->ipcp_orig_node);
4947 unsigned count = ipa_get_param_count (info);
4948 for (unsigned i = 0; i < count; i++)
4950 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4951 if (!plats->m_value_range.bottom_p ()
4952 && !plats->m_value_range.top_p ())
4954 found_useful_result = true;
4955 break;
4958 if (!found_useful_result)
4959 continue;
4961 ipcp_grow_transformations_if_necessary ();
4962 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4963 vec_safe_reserve_exact (ts->m_vr, count);
4965 for (unsigned i = 0; i < count; i++)
4967 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4968 ipa_vr vr;
4970 if (!plats->m_value_range.bottom_p ()
4971 && !plats->m_value_range.top_p ())
4973 vr.known = true;
4974 vr.type = plats->m_value_range.m_vr.type;
4975 vr.min = wi::to_wide (plats->m_value_range.m_vr.min);
4976 vr.max = wi::to_wide (plats->m_value_range.m_vr.max);
4978 else
4980 vr.known = false;
4981 vr.type = VR_VARYING;
4982 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
4984 ts->m_vr->quick_push (vr);
4989 /* The IPCP driver. */
4991 static unsigned int
4992 ipcp_driver (void)
4994 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4995 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4996 struct ipa_topo_info topo;
4998 ipa_check_create_node_params ();
4999 ipa_check_create_edge_args ();
5000 grow_edge_clone_vectors ();
5001 edge_duplication_hook_holder
5002 = symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
5003 edge_removal_hook_holder
5004 = symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
5006 if (dump_file)
5008 fprintf (dump_file, "\nIPA structures before propagation:\n");
5009 if (dump_flags & TDF_DETAILS)
5010 ipa_print_all_params (dump_file);
5011 ipa_print_all_jump_functions (dump_file);
5014 /* Topological sort. */
5015 build_toporder_info (&topo);
5016 /* Do the interprocedural propagation. */
5017 ipcp_propagate_stage (&topo);
5018 /* Decide what constant propagation and cloning should be performed. */
5019 ipcp_decision_stage (&topo);
5020 /* Store results of bits propagation. */
5021 ipcp_store_bits_results ();
5022 /* Store results of value range propagation. */
5023 ipcp_store_vr_results ();
5025 /* Free all IPCP structures. */
5026 free_toporder_info (&topo);
5027 next_edge_clone.release ();
5028 prev_edge_clone.release ();
5029 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
5030 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
5031 ipa_free_all_structures_after_ipa_cp ();
5032 if (dump_file)
5033 fprintf (dump_file, "\nIPA constant propagation end\n");
5034 return 0;
5037 /* Initialization and computation of IPCP data structures. This is the initial
5038 intraprocedural analysis of functions, which gathers information to be
5039 propagated later on. */
5041 static void
5042 ipcp_generate_summary (void)
5044 struct cgraph_node *node;
5046 if (dump_file)
5047 fprintf (dump_file, "\nIPA constant propagation start:\n");
5048 ipa_register_cgraph_hooks ();
5050 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5051 ipa_analyze_node (node);
5054 /* Write ipcp summary for nodes in SET. */
5056 static void
5057 ipcp_write_summary (void)
5059 ipa_prop_write_jump_functions ();
5062 /* Read ipcp summary. */
5064 static void
5065 ipcp_read_summary (void)
5067 ipa_prop_read_jump_functions ();
5070 namespace {
5072 const pass_data pass_data_ipa_cp =
5074 IPA_PASS, /* type */
5075 "cp", /* name */
5076 OPTGROUP_NONE, /* optinfo_flags */
5077 TV_IPA_CONSTANT_PROP, /* tv_id */
5078 0, /* properties_required */
5079 0, /* properties_provided */
5080 0, /* properties_destroyed */
5081 0, /* todo_flags_start */
5082 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5085 class pass_ipa_cp : public ipa_opt_pass_d
5087 public:
5088 pass_ipa_cp (gcc::context *ctxt)
5089 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5090 ipcp_generate_summary, /* generate_summary */
5091 ipcp_write_summary, /* write_summary */
5092 ipcp_read_summary, /* read_summary */
5093 ipcp_write_transformation_summaries, /*
5094 write_optimization_summary */
5095 ipcp_read_transformation_summaries, /*
5096 read_optimization_summary */
5097 NULL, /* stmt_fixup */
5098 0, /* function_transform_todo_flags_start */
5099 ipcp_transform_function, /* function_transform */
5100 NULL) /* variable_transform */
5103 /* opt_pass methods: */
5104 virtual bool gate (function *)
5106 /* FIXME: We should remove the optimize check after we ensure we never run
5107 IPA passes when not optimizing. */
5108 return (flag_ipa_cp && optimize) || in_lto_p;
5111 virtual unsigned int execute (function *) { return ipcp_driver (); }
5113 }; // class pass_ipa_cp
5115 } // anon namespace
5117 ipa_opt_pass_d *
5118 make_pass_ipa_cp (gcc::context *ctxt)
5120 return new pass_ipa_cp (ctxt);
5123 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5124 within the same process. For use by toplev::finalize. */
5126 void
5127 ipa_cp_c_finalize (void)
5129 max_count = profile_count::uninitialized ();
5130 overall_size = 0;
5131 max_new_size = 0;