gcc/cp/ChangeLog:
[official-gcc.git] / gcc / ipa-cp.c
blob3b9eab41672dd8da81f25244ec7549d2b030a1f6
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"
126 template <typename valtype> class ipcp_value;
128 /* Describes a particular source for an IPA-CP value. */
130 template <typename valtype>
131 class ipcp_value_source
133 public:
134 /* Aggregate offset of the source, negative if the source is scalar value of
135 the argument itself. */
136 HOST_WIDE_INT offset;
137 /* The incoming edge that brought the value. */
138 cgraph_edge *cs;
139 /* If the jump function that resulted into his value was a pass-through or an
140 ancestor, this is the ipcp_value of the caller from which the described
141 value has been derived. Otherwise it is NULL. */
142 ipcp_value<valtype> *val;
143 /* Next pointer in a linked list of sources of a value. */
144 ipcp_value_source *next;
145 /* If the jump function that resulted into his value was a pass-through or an
146 ancestor, this is the index of the parameter of the caller the jump
147 function references. */
148 int index;
151 /* Common ancestor for all ipcp_value instantiations. */
153 class ipcp_value_base
155 public:
156 /* Time benefit and size cost that specializing the function for this value
157 would bring about in this function alone. */
158 int local_time_benefit, local_size_cost;
159 /* Time benefit and size cost that specializing the function for this value
160 can bring about in it's callees (transitively). */
161 int prop_time_benefit, prop_size_cost;
163 ipcp_value_base ()
164 : local_time_benefit (0), local_size_cost (0),
165 prop_time_benefit (0), prop_size_cost (0) {}
168 /* Describes one particular value stored in struct ipcp_lattice. */
170 template <typename valtype>
171 class ipcp_value : public ipcp_value_base
173 public:
174 /* The actual value for the given parameter. */
175 valtype value;
176 /* The list of sources from which this value originates. */
177 ipcp_value_source <valtype> *sources;
178 /* Next pointers in a linked list of all values in a lattice. */
179 ipcp_value *next;
180 /* Next pointers in a linked list of values in a strongly connected component
181 of values. */
182 ipcp_value *scc_next;
183 /* Next pointers in a linked list of SCCs of values sorted topologically
184 according their sources. */
185 ipcp_value *topo_next;
186 /* A specialized node created for this value, NULL if none has been (so far)
187 created. */
188 cgraph_node *spec_node;
189 /* Depth first search number and low link for topological sorting of
190 values. */
191 int dfs, low_link;
192 /* True if this valye is currently on the topo-sort stack. */
193 bool on_stack;
195 ipcp_value()
196 : sources (0), next (0), scc_next (0), topo_next (0),
197 spec_node (0), dfs (0), low_link (0), on_stack (false) {}
199 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
200 HOST_WIDE_INT offset);
203 /* Lattice describing potential values of a formal parameter of a function, or
204 a part of an aggregate. TOP is represented by a lattice with zero values
205 and with contains_variable and bottom flags cleared. BOTTOM is represented
206 by a lattice with the bottom flag set. In that case, values and
207 contains_variable flag should be disregarded. */
209 template <typename valtype>
210 class ipcp_lattice
212 public:
213 /* The list of known values and types in this lattice. Note that values are
214 not deallocated if a lattice is set to bottom because there may be value
215 sources referencing them. */
216 ipcp_value<valtype> *values;
217 /* Number of known values and types in this lattice. */
218 int values_count;
219 /* The lattice contains a variable component (in addition to values). */
220 bool contains_variable;
221 /* The value of the lattice is bottom (i.e. variable and unusable for any
222 propagation). */
223 bool bottom;
225 inline bool is_single_const ();
226 inline bool set_to_bottom ();
227 inline bool set_contains_variable ();
228 bool add_value (valtype newval, cgraph_edge *cs,
229 ipcp_value<valtype> *src_val = NULL,
230 int src_idx = 0, HOST_WIDE_INT offset = -1);
231 void print (FILE * f, bool dump_sources, bool dump_benefits);
234 /* Lattice of tree values with an offset to describe a part of an
235 aggregate. */
237 class ipcp_agg_lattice : public ipcp_lattice<tree>
239 public:
240 /* Offset that is being described by this lattice. */
241 HOST_WIDE_INT offset;
242 /* Size so that we don't have to re-compute it every time we traverse the
243 list. Must correspond to TYPE_SIZE of all lat values. */
244 HOST_WIDE_INT size;
245 /* Next element of the linked list. */
246 struct ipcp_agg_lattice *next;
249 /* Lattice of known bits, only capable of holding one value.
250 Bitwise constant propagation propagates which bits of a
251 value are constant.
252 For eg:
253 int f(int x)
255 return some_op (x);
258 int f1(int y)
260 if (cond)
261 return f (y & 0xff);
262 else
263 return f (y & 0xf);
266 In the above case, the param 'x' will always have all
267 the bits (except the bits in lsb) set to 0.
268 Hence the mask of 'x' would be 0xff. The mask
269 reflects that the bits in lsb are unknown.
270 The actual propagated value is given by m_value & ~m_mask. */
272 class ipcp_bits_lattice
274 public:
275 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; }
276 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; }
277 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; }
278 bool set_to_bottom ();
279 bool set_to_constant (widest_int, widest_int);
281 widest_int get_value () { return m_value; }
282 widest_int get_mask () { return m_mask; }
284 bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
285 enum tree_code, tree);
287 bool meet_with (widest_int, widest_int, unsigned);
289 void print (FILE *);
291 private:
292 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
294 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
295 If a bit in mask is set to 0, then the corresponding bit in
296 value is known to be constant. */
297 widest_int m_value, m_mask;
299 bool meet_with_1 (widest_int, widest_int, unsigned);
300 void get_value_and_mask (tree, widest_int *, widest_int *);
303 /* Lattice of value ranges. */
305 class ipcp_vr_lattice
307 public:
308 value_range m_vr;
310 inline bool bottom_p () const;
311 inline bool top_p () const;
312 inline bool set_to_bottom ();
313 bool meet_with (const value_range *p_vr);
314 bool meet_with (const ipcp_vr_lattice &other);
315 void init () { m_vr.type = VR_UNDEFINED; }
316 void print (FILE * f);
318 private:
319 bool meet_with_1 (const value_range *other_vr);
322 /* Structure containing lattices for a parameter itself and for pieces of
323 aggregates that are passed in the parameter or by a reference in a parameter
324 plus some other useful flags. */
326 class ipcp_param_lattices
328 public:
329 /* Lattice describing the value of the parameter itself. */
330 ipcp_lattice<tree> itself;
331 /* Lattice describing the polymorphic contexts of a parameter. */
332 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
333 /* Lattices describing aggregate parts. */
334 ipcp_agg_lattice *aggs;
335 /* Lattice describing known bits. */
336 ipcp_bits_lattice bits_lattice;
337 /* Lattice describing value range. */
338 ipcp_vr_lattice m_value_range;
339 /* Number of aggregate lattices */
340 int aggs_count;
341 /* True if aggregate data were passed by reference (as opposed to by
342 value). */
343 bool aggs_by_ref;
344 /* All aggregate lattices contain a variable component (in addition to
345 values). */
346 bool aggs_contain_variable;
347 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
348 for any propagation). */
349 bool aggs_bottom;
351 /* There is a virtual call based on this parameter. */
352 bool virt_call;
355 /* Allocation pools for values and their sources in ipa-cp. */
357 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
358 ("IPA-CP constant values");
360 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
361 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
363 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
364 ("IPA-CP value sources");
366 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
367 ("IPA_CP aggregate lattices");
369 /* Maximal count found in program. */
371 static profile_count max_count;
373 /* Original overall size of the program. */
375 static long overall_size, max_new_size;
377 /* Return the param lattices structure corresponding to the Ith formal
378 parameter of the function described by INFO. */
379 static inline struct ipcp_param_lattices *
380 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
382 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
383 gcc_checking_assert (!info->ipcp_orig_node);
384 gcc_checking_assert (info->lattices);
385 return &(info->lattices[i]);
388 /* Return the lattice corresponding to the scalar value of the Ith formal
389 parameter of the function described by INFO. */
390 static inline ipcp_lattice<tree> *
391 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
393 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
394 return &plats->itself;
397 /* Return the lattice corresponding to the scalar value of the Ith formal
398 parameter of the function described by INFO. */
399 static inline ipcp_lattice<ipa_polymorphic_call_context> *
400 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
402 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
403 return &plats->ctxlat;
406 /* Return the lattice corresponding to the value range of the Ith formal
407 parameter of the function described by INFO. */
409 static inline ipcp_vr_lattice *
410 ipa_get_vr_lat (struct ipa_node_params *info, int i)
412 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
413 return &plats->m_value_range;
416 /* Return whether LAT is a lattice with a single constant and without an
417 undefined value. */
419 template <typename valtype>
420 inline bool
421 ipcp_lattice<valtype>::is_single_const ()
423 if (bottom || contains_variable || values_count != 1)
424 return false;
425 else
426 return true;
429 /* Print V which is extracted from a value in a lattice to F. */
431 static void
432 print_ipcp_constant_value (FILE * f, tree v)
434 if (TREE_CODE (v) == ADDR_EXPR
435 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
437 fprintf (f, "& ");
438 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)));
440 else
441 print_generic_expr (f, v);
444 /* Print V which is extracted from a value in a lattice to F. */
446 static void
447 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
449 v.dump(f, false);
452 /* Print a lattice LAT to F. */
454 template <typename valtype>
455 void
456 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
458 ipcp_value<valtype> *val;
459 bool prev = false;
461 if (bottom)
463 fprintf (f, "BOTTOM\n");
464 return;
467 if (!values_count && !contains_variable)
469 fprintf (f, "TOP\n");
470 return;
473 if (contains_variable)
475 fprintf (f, "VARIABLE");
476 prev = true;
477 if (dump_benefits)
478 fprintf (f, "\n");
481 for (val = values; val; val = val->next)
483 if (dump_benefits && prev)
484 fprintf (f, " ");
485 else if (!dump_benefits && prev)
486 fprintf (f, ", ");
487 else
488 prev = true;
490 print_ipcp_constant_value (f, val->value);
492 if (dump_sources)
494 ipcp_value_source<valtype> *s;
496 fprintf (f, " [from:");
497 for (s = val->sources; s; s = s->next)
498 fprintf (f, " %i(%i)", s->cs->caller->order,
499 s->cs->frequency);
500 fprintf (f, "]");
503 if (dump_benefits)
504 fprintf (f, " [loc_time: %i, loc_size: %i, "
505 "prop_time: %i, prop_size: %i]\n",
506 val->local_time_benefit, val->local_size_cost,
507 val->prop_time_benefit, val->prop_size_cost);
509 if (!dump_benefits)
510 fprintf (f, "\n");
513 void
514 ipcp_bits_lattice::print (FILE *f)
516 if (top_p ())
517 fprintf (f, " Bits unknown (TOP)\n");
518 else if (bottom_p ())
519 fprintf (f, " Bits unusable (BOTTOM)\n");
520 else
522 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
523 fprintf (f, ", mask = "); print_hex (get_mask (), f);
524 fprintf (f, "\n");
528 /* Print value range lattice to F. */
530 void
531 ipcp_vr_lattice::print (FILE * f)
533 dump_value_range (f, &m_vr);
536 /* Print all ipcp_lattices of all functions to F. */
538 static void
539 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
541 struct cgraph_node *node;
542 int i, count;
544 fprintf (f, "\nLattices:\n");
545 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
547 struct ipa_node_params *info;
549 info = IPA_NODE_REF (node);
550 fprintf (f, " Node: %s:\n", node->dump_name ());
551 count = ipa_get_param_count (info);
552 for (i = 0; i < count; i++)
554 struct ipcp_agg_lattice *aglat;
555 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
556 fprintf (f, " param [%d]: ", i);
557 plats->itself.print (f, dump_sources, dump_benefits);
558 fprintf (f, " ctxs: ");
559 plats->ctxlat.print (f, dump_sources, dump_benefits);
560 plats->bits_lattice.print (f);
561 fprintf (f, " ");
562 plats->m_value_range.print (f);
563 fprintf (f, "\n");
564 if (plats->virt_call)
565 fprintf (f, " virt_call flag set\n");
567 if (plats->aggs_bottom)
569 fprintf (f, " AGGS BOTTOM\n");
570 continue;
572 if (plats->aggs_contain_variable)
573 fprintf (f, " AGGS VARIABLE\n");
574 for (aglat = plats->aggs; aglat; aglat = aglat->next)
576 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
577 plats->aggs_by_ref ? "ref " : "", aglat->offset);
578 aglat->print (f, dump_sources, dump_benefits);
584 /* Determine whether it is at all technically possible to create clones of NODE
585 and store this information in the ipa_node_params structure associated
586 with NODE. */
588 static void
589 determine_versionability (struct cgraph_node *node,
590 struct ipa_node_params *info)
592 const char *reason = NULL;
594 /* There are a number of generic reasons functions cannot be versioned. We
595 also cannot remove parameters if there are type attributes such as fnspec
596 present. */
597 if (node->alias || node->thunk.thunk_p)
598 reason = "alias or thunk";
599 else if (!node->local.versionable)
600 reason = "not a tree_versionable_function";
601 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
602 reason = "insufficient body availability";
603 else if (!opt_for_fn (node->decl, optimize)
604 || !opt_for_fn (node->decl, flag_ipa_cp))
605 reason = "non-optimized function";
606 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
608 /* Ideally we should clone the SIMD clones themselves and create
609 vector copies of them, so IPA-cp and SIMD clones can happily
610 coexist, but that may not be worth the effort. */
611 reason = "function has SIMD clones";
613 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
615 /* Ideally we should clone the target clones themselves and create
616 copies of them, so IPA-cp and target clones can happily
617 coexist, but that may not be worth the effort. */
618 reason = "function target_clones attribute";
620 /* Don't clone decls local to a comdat group; it breaks and for C++
621 decloned constructors, inlining is always better anyway. */
622 else if (node->comdat_local_p ())
623 reason = "comdat-local function";
624 else if (node->calls_comdat_local)
626 /* TODO: call is versionable if we make sure that all
627 callers are inside of a comdat group. */
628 reason = "calls comdat-local function";
631 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
632 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
633 node->dump_name (), reason);
635 info->versionable = (reason == NULL);
638 /* Return true if it is at all technically possible to create clones of a
639 NODE. */
641 static bool
642 ipcp_versionable_function_p (struct cgraph_node *node)
644 return IPA_NODE_REF (node)->versionable;
647 /* Structure holding accumulated information about callers of a node. */
649 struct caller_statistics
651 profile_count count_sum;
652 int n_calls, n_hot_calls, freq_sum;
655 /* Initialize fields of STAT to zeroes. */
657 static inline void
658 init_caller_stats (struct caller_statistics *stats)
660 stats->count_sum = profile_count::zero ();
661 stats->n_calls = 0;
662 stats->n_hot_calls = 0;
663 stats->freq_sum = 0;
666 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
667 non-thunk incoming edges to NODE. */
669 static bool
670 gather_caller_stats (struct cgraph_node *node, void *data)
672 struct caller_statistics *stats = (struct caller_statistics *) data;
673 struct cgraph_edge *cs;
675 for (cs = node->callers; cs; cs = cs->next_caller)
676 if (!cs->caller->thunk.thunk_p)
678 if (cs->count.initialized_p ())
679 stats->count_sum += cs->count;
680 stats->freq_sum += cs->frequency;
681 stats->n_calls++;
682 if (cs->maybe_hot_p ())
683 stats->n_hot_calls ++;
685 return false;
689 /* Return true if this NODE is viable candidate for cloning. */
691 static bool
692 ipcp_cloning_candidate_p (struct cgraph_node *node)
694 struct caller_statistics stats;
696 gcc_checking_assert (node->has_gimple_body_p ());
698 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
700 if (dump_file)
701 fprintf (dump_file, "Not considering %s for cloning; "
702 "-fipa-cp-clone disabled.\n",
703 node->name ());
704 return false;
707 if (node->optimize_for_size_p ())
709 if (dump_file)
710 fprintf (dump_file, "Not considering %s for cloning; "
711 "optimizing it for size.\n",
712 node->name ());
713 return false;
716 init_caller_stats (&stats);
717 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
719 if (ipa_fn_summaries->get (node)->self_size < stats.n_calls)
721 if (dump_file)
722 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
723 node->name ());
724 return true;
727 /* When profile is available and function is hot, propagate into it even if
728 calls seems cold; constant propagation can improve function's speed
729 significantly. */
730 if (max_count > profile_count::zero ())
732 if (stats.count_sum > node->count.apply_scale (90, 100))
734 if (dump_file)
735 fprintf (dump_file, "Considering %s for cloning; "
736 "usually called directly.\n",
737 node->name ());
738 return true;
741 if (!stats.n_hot_calls)
743 if (dump_file)
744 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
745 node->name ());
746 return false;
748 if (dump_file)
749 fprintf (dump_file, "Considering %s for cloning.\n",
750 node->name ());
751 return true;
754 template <typename valtype>
755 class value_topo_info
757 public:
758 /* Head of the linked list of topologically sorted values. */
759 ipcp_value<valtype> *values_topo;
760 /* Stack for creating SCCs, represented by a linked list too. */
761 ipcp_value<valtype> *stack;
762 /* Counter driving the algorithm in add_val_to_toposort. */
763 int dfs_counter;
765 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
767 void add_val (ipcp_value<valtype> *cur_val);
768 void propagate_effects ();
771 /* Arrays representing a topological ordering of call graph nodes and a stack
772 of nodes used during constant propagation and also data required to perform
773 topological sort of values and propagation of benefits in the determined
774 order. */
776 class ipa_topo_info
778 public:
779 /* Array with obtained topological order of cgraph nodes. */
780 struct cgraph_node **order;
781 /* Stack of cgraph nodes used during propagation within SCC until all values
782 in the SCC stabilize. */
783 struct cgraph_node **stack;
784 int nnodes, stack_top;
786 value_topo_info<tree> constants;
787 value_topo_info<ipa_polymorphic_call_context> contexts;
789 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
790 constants ()
794 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
796 static void
797 build_toporder_info (struct ipa_topo_info *topo)
799 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
800 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
802 gcc_checking_assert (topo->stack_top == 0);
803 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
806 /* Free information about strongly connected components and the arrays in
807 TOPO. */
809 static void
810 free_toporder_info (struct ipa_topo_info *topo)
812 ipa_free_postorder_info ();
813 free (topo->order);
814 free (topo->stack);
817 /* Add NODE to the stack in TOPO, unless it is already there. */
819 static inline void
820 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
822 struct ipa_node_params *info = IPA_NODE_REF (node);
823 if (info->node_enqueued)
824 return;
825 info->node_enqueued = 1;
826 topo->stack[topo->stack_top++] = node;
829 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
830 is empty. */
832 static struct cgraph_node *
833 pop_node_from_stack (struct ipa_topo_info *topo)
835 if (topo->stack_top)
837 struct cgraph_node *node;
838 topo->stack_top--;
839 node = topo->stack[topo->stack_top];
840 IPA_NODE_REF (node)->node_enqueued = 0;
841 return node;
843 else
844 return NULL;
847 /* Set lattice LAT to bottom and return true if it previously was not set as
848 such. */
850 template <typename valtype>
851 inline bool
852 ipcp_lattice<valtype>::set_to_bottom ()
854 bool ret = !bottom;
855 bottom = true;
856 return ret;
859 /* Mark lattice as containing an unknown value and return true if it previously
860 was not marked as such. */
862 template <typename valtype>
863 inline bool
864 ipcp_lattice<valtype>::set_contains_variable ()
866 bool ret = !contains_variable;
867 contains_variable = true;
868 return ret;
871 /* Set all aggegate lattices in PLATS to bottom and return true if they were
872 not previously set as such. */
874 static inline bool
875 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
877 bool ret = !plats->aggs_bottom;
878 plats->aggs_bottom = true;
879 return ret;
882 /* Mark all aggegate lattices in PLATS as containing an unknown value and
883 return true if they were not previously marked as such. */
885 static inline bool
886 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
888 bool ret = !plats->aggs_contain_variable;
889 plats->aggs_contain_variable = true;
890 return ret;
893 bool
894 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
896 return meet_with_1 (&other.m_vr);
899 /* Meet the current value of the lattice with value ranfge described by VR
900 lattice. */
902 bool
903 ipcp_vr_lattice::meet_with (const value_range *p_vr)
905 return meet_with_1 (p_vr);
908 /* Meet the current value of the lattice with value ranfge described by
909 OTHER_VR lattice. */
911 bool
912 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
914 tree min = m_vr.min, max = m_vr.max;
915 value_range_type type = m_vr.type;
917 if (bottom_p ())
918 return false;
920 if (other_vr->type == VR_VARYING)
921 return set_to_bottom ();
923 vrp_meet (&m_vr, other_vr);
924 if (type != m_vr.type
925 || min != m_vr.min
926 || max != m_vr.max)
927 return true;
928 else
929 return false;
932 /* Return true if value range information in the lattice is yet unknown. */
934 bool
935 ipcp_vr_lattice::top_p () const
937 return m_vr.type == VR_UNDEFINED;
940 /* Return true if value range information in the lattice is known to be
941 unusable. */
943 bool
944 ipcp_vr_lattice::bottom_p () const
946 return m_vr.type == VR_VARYING;
949 /* Set value range information in the lattice to bottom. Return true if it
950 previously was in a different state. */
952 bool
953 ipcp_vr_lattice::set_to_bottom ()
955 if (m_vr.type == VR_VARYING)
956 return false;
957 m_vr.type = VR_VARYING;
958 return true;
961 /* Set lattice value to bottom, if it already isn't the case. */
963 bool
964 ipcp_bits_lattice::set_to_bottom ()
966 if (bottom_p ())
967 return false;
968 m_lattice_val = IPA_BITS_VARYING;
969 m_value = 0;
970 m_mask = -1;
971 return true;
974 /* Set to constant if it isn't already. Only meant to be called
975 when switching state from TOP. */
977 bool
978 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
980 gcc_assert (top_p ());
981 m_lattice_val = IPA_BITS_CONSTANT;
982 m_value = value;
983 m_mask = mask;
984 return true;
987 /* Convert operand to value, mask form. */
989 void
990 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
992 wide_int get_nonzero_bits (const_tree);
994 if (TREE_CODE (operand) == INTEGER_CST)
996 *valuep = wi::to_widest (operand);
997 *maskp = 0;
999 else
1001 *valuep = 0;
1002 *maskp = -1;
1006 /* Meet operation, similar to ccp_lattice_meet, we xor values
1007 if this->value, value have different values at same bit positions, we want
1008 to drop that bit to varying. Return true if mask is changed.
1009 This function assumes that the lattice value is in CONSTANT state */
1011 bool
1012 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
1013 unsigned precision)
1015 gcc_assert (constant_p ());
1017 widest_int old_mask = m_mask;
1018 m_mask = (m_mask | mask) | (m_value ^ value);
1020 if (wi::sext (m_mask, precision) == -1)
1021 return set_to_bottom ();
1023 return m_mask != old_mask;
1026 /* Meet the bits lattice with operand
1027 described by <value, mask, sgn, precision. */
1029 bool
1030 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1031 unsigned precision)
1033 if (bottom_p ())
1034 return false;
1036 if (top_p ())
1038 if (wi::sext (mask, precision) == -1)
1039 return set_to_bottom ();
1040 return set_to_constant (value, mask);
1043 return meet_with_1 (value, mask, precision);
1046 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1047 if code is binary operation or bit_value_unop (other) if code is unary op.
1048 In the case when code is nop_expr, no adjustment is required. */
1050 bool
1051 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1052 signop sgn, enum tree_code code, tree operand)
1054 if (other.bottom_p ())
1055 return set_to_bottom ();
1057 if (bottom_p () || other.top_p ())
1058 return false;
1060 widest_int adjusted_value, adjusted_mask;
1062 if (TREE_CODE_CLASS (code) == tcc_binary)
1064 tree type = TREE_TYPE (operand);
1065 gcc_assert (INTEGRAL_TYPE_P (type));
1066 widest_int o_value, o_mask;
1067 get_value_and_mask (operand, &o_value, &o_mask);
1069 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1070 sgn, precision, other.get_value (), other.get_mask (),
1071 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1073 if (wi::sext (adjusted_mask, precision) == -1)
1074 return set_to_bottom ();
1077 else if (TREE_CODE_CLASS (code) == tcc_unary)
1079 bit_value_unop (code, sgn, precision, &adjusted_value,
1080 &adjusted_mask, sgn, precision, other.get_value (),
1081 other.get_mask ());
1083 if (wi::sext (adjusted_mask, precision) == -1)
1084 return set_to_bottom ();
1087 else
1088 return set_to_bottom ();
1090 if (top_p ())
1092 if (wi::sext (adjusted_mask, precision) == -1)
1093 return set_to_bottom ();
1094 return set_to_constant (adjusted_value, adjusted_mask);
1096 else
1097 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1100 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1101 return true is any of them has not been marked as such so far. */
1103 static inline bool
1104 set_all_contains_variable (struct ipcp_param_lattices *plats)
1106 bool ret;
1107 ret = plats->itself.set_contains_variable ();
1108 ret |= plats->ctxlat.set_contains_variable ();
1109 ret |= set_agg_lats_contain_variable (plats);
1110 ret |= plats->bits_lattice.set_to_bottom ();
1111 ret |= plats->m_value_range.set_to_bottom ();
1112 return ret;
1115 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1116 points to by the number of callers to NODE. */
1118 static bool
1119 count_callers (cgraph_node *node, void *data)
1121 int *caller_count = (int *) data;
1123 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1124 /* Local thunks can be handled transparently, but if the thunk can not
1125 be optimized out, count it as a real use. */
1126 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
1127 ++*caller_count;
1128 return false;
1131 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1132 the one caller of some other node. Set the caller's corresponding flag. */
1134 static bool
1135 set_single_call_flag (cgraph_node *node, void *)
1137 cgraph_edge *cs = node->callers;
1138 /* Local thunks can be handled transparently, skip them. */
1139 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
1140 cs = cs->next_caller;
1141 if (cs)
1143 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1144 return true;
1146 return false;
1149 /* Initialize ipcp_lattices. */
1151 static void
1152 initialize_node_lattices (struct cgraph_node *node)
1154 struct ipa_node_params *info = IPA_NODE_REF (node);
1155 struct cgraph_edge *ie;
1156 bool disable = false, variable = false;
1157 int i;
1159 gcc_checking_assert (node->has_gimple_body_p ());
1160 if (cgraph_local_p (node))
1162 int caller_count = 0;
1163 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1164 true);
1165 gcc_checking_assert (caller_count > 0);
1166 if (caller_count == 1)
1167 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1168 NULL, true);
1170 else
1172 /* When cloning is allowed, we can assume that externally visible
1173 functions are not called. We will compensate this by cloning
1174 later. */
1175 if (ipcp_versionable_function_p (node)
1176 && ipcp_cloning_candidate_p (node))
1177 variable = true;
1178 else
1179 disable = true;
1182 for (i = 0; i < ipa_get_param_count (info); i++)
1184 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1185 plats->m_value_range.init ();
1188 if (disable || variable)
1190 for (i = 0; i < ipa_get_param_count (info); i++)
1192 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1193 if (disable)
1195 plats->itself.set_to_bottom ();
1196 plats->ctxlat.set_to_bottom ();
1197 set_agg_lats_to_bottom (plats);
1198 plats->bits_lattice.set_to_bottom ();
1199 plats->m_value_range.set_to_bottom ();
1201 else
1202 set_all_contains_variable (plats);
1204 if (dump_file && (dump_flags & TDF_DETAILS)
1205 && !node->alias && !node->thunk.thunk_p)
1206 fprintf (dump_file, "Marking all lattices of %s as %s\n",
1207 node->dump_name (), disable ? "BOTTOM" : "VARIABLE");
1210 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1211 if (ie->indirect_info->polymorphic
1212 && ie->indirect_info->param_index >= 0)
1214 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1215 ipa_get_parm_lattices (info,
1216 ie->indirect_info->param_index)->virt_call = 1;
1220 /* Return the result of a (possibly arithmetic) pass through jump function
1221 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
1222 determined or be considered an interprocedural invariant. */
1224 static tree
1225 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
1227 tree restype, res;
1229 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1230 return input;
1231 if (!is_gimple_ip_invariant (input))
1232 return NULL_TREE;
1234 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
1235 == tcc_unary)
1236 res = fold_unary (ipa_get_jf_pass_through_operation (jfunc),
1237 TREE_TYPE (input), input);
1238 else
1240 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
1241 == tcc_comparison)
1242 restype = boolean_type_node;
1243 else
1244 restype = TREE_TYPE (input);
1245 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
1246 input, ipa_get_jf_pass_through_operand (jfunc));
1248 if (res && !is_gimple_ip_invariant (res))
1249 return NULL_TREE;
1251 return res;
1254 /* Return the result of an ancestor jump function JFUNC on the constant value
1255 INPUT. Return NULL_TREE if that cannot be determined. */
1257 static tree
1258 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1260 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1261 if (TREE_CODE (input) == ADDR_EXPR)
1263 tree t = TREE_OPERAND (input, 0);
1264 t = build_ref_for_offset (EXPR_LOCATION (t), t,
1265 ipa_get_jf_ancestor_offset (jfunc), false,
1266 ptr_type_node, NULL, false);
1267 return build_fold_addr_expr (t);
1269 else
1270 return NULL_TREE;
1273 /* Determine whether JFUNC evaluates to a single known constant value and if
1274 so, return it. Otherwise return NULL. INFO describes the caller node or
1275 the one it is inlined to, so that pass-through jump functions can be
1276 evaluated. */
1278 tree
1279 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
1281 if (jfunc->type == IPA_JF_CONST)
1282 return ipa_get_jf_constant (jfunc);
1283 else if (jfunc->type == IPA_JF_PASS_THROUGH
1284 || jfunc->type == IPA_JF_ANCESTOR)
1286 tree input;
1287 int idx;
1289 if (jfunc->type == IPA_JF_PASS_THROUGH)
1290 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1291 else
1292 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1294 if (info->ipcp_orig_node)
1295 input = info->known_csts[idx];
1296 else
1298 ipcp_lattice<tree> *lat;
1300 if (!info->lattices
1301 || idx >= ipa_get_param_count (info))
1302 return NULL_TREE;
1303 lat = ipa_get_scalar_lat (info, idx);
1304 if (!lat->is_single_const ())
1305 return NULL_TREE;
1306 input = lat->values->value;
1309 if (!input)
1310 return NULL_TREE;
1312 if (jfunc->type == IPA_JF_PASS_THROUGH)
1313 return ipa_get_jf_pass_through_result (jfunc, input);
1314 else
1315 return ipa_get_jf_ancestor_result (jfunc, input);
1317 else
1318 return NULL_TREE;
1321 /* Determie whether JFUNC evaluates to single known polymorphic context, given
1322 that INFO describes the caller node or the one it is inlined to, CS is the
1323 call graph edge corresponding to JFUNC and CSIDX index of the described
1324 parameter. */
1326 ipa_polymorphic_call_context
1327 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1328 ipa_jump_func *jfunc)
1330 ipa_edge_args *args = IPA_EDGE_REF (cs);
1331 ipa_polymorphic_call_context ctx;
1332 ipa_polymorphic_call_context *edge_ctx
1333 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1335 if (edge_ctx && !edge_ctx->useless_p ())
1336 ctx = *edge_ctx;
1338 if (jfunc->type == IPA_JF_PASS_THROUGH
1339 || jfunc->type == IPA_JF_ANCESTOR)
1341 ipa_polymorphic_call_context srcctx;
1342 int srcidx;
1343 bool type_preserved = true;
1344 if (jfunc->type == IPA_JF_PASS_THROUGH)
1346 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1347 return ctx;
1348 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1349 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1351 else
1353 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1354 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1356 if (info->ipcp_orig_node)
1358 if (info->known_contexts.exists ())
1359 srcctx = info->known_contexts[srcidx];
1361 else
1363 if (!info->lattices
1364 || srcidx >= ipa_get_param_count (info))
1365 return ctx;
1366 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1367 lat = ipa_get_poly_ctx_lat (info, srcidx);
1368 if (!lat->is_single_const ())
1369 return ctx;
1370 srcctx = lat->values->value;
1372 if (srcctx.useless_p ())
1373 return ctx;
1374 if (jfunc->type == IPA_JF_ANCESTOR)
1375 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1376 if (!type_preserved)
1377 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1378 srcctx.combine_with (ctx);
1379 return srcctx;
1382 return ctx;
1385 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1386 bottom, not containing a variable component and without any known value at
1387 the same time. */
1389 DEBUG_FUNCTION void
1390 ipcp_verify_propagated_values (void)
1392 struct cgraph_node *node;
1394 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1396 struct ipa_node_params *info = IPA_NODE_REF (node);
1397 int i, count = ipa_get_param_count (info);
1399 for (i = 0; i < count; i++)
1401 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1403 if (!lat->bottom
1404 && !lat->contains_variable
1405 && lat->values_count == 0)
1407 if (dump_file)
1409 symtab->dump (dump_file);
1410 fprintf (dump_file, "\nIPA lattices after constant "
1411 "propagation, before gcc_unreachable:\n");
1412 print_all_lattices (dump_file, true, false);
1415 gcc_unreachable ();
1421 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1423 static bool
1424 values_equal_for_ipcp_p (tree x, tree y)
1426 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1428 if (x == y)
1429 return true;
1431 if (TREE_CODE (x) == ADDR_EXPR
1432 && TREE_CODE (y) == ADDR_EXPR
1433 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1434 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1435 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1436 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1437 else
1438 return operand_equal_p (x, y, 0);
1441 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1443 static bool
1444 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1445 ipa_polymorphic_call_context y)
1447 return x.equal_to (y);
1451 /* Add a new value source to the value represented by THIS, marking that a
1452 value comes from edge CS and (if the underlying jump function is a
1453 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1454 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1455 scalar value of the parameter itself or the offset within an aggregate. */
1457 template <typename valtype>
1458 void
1459 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1460 int src_idx, HOST_WIDE_INT offset)
1462 ipcp_value_source<valtype> *src;
1464 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1465 src->offset = offset;
1466 src->cs = cs;
1467 src->val = src_val;
1468 src->index = src_idx;
1470 src->next = sources;
1471 sources = src;
1474 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1475 SOURCE and clear all other fields. */
1477 static ipcp_value<tree> *
1478 allocate_and_init_ipcp_value (tree source)
1480 ipcp_value<tree> *val;
1482 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1483 val->value = source;
1484 return val;
1487 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1488 value to SOURCE and clear all other fields. */
1490 static ipcp_value<ipa_polymorphic_call_context> *
1491 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1493 ipcp_value<ipa_polymorphic_call_context> *val;
1495 // TODO
1496 val = new (ipcp_poly_ctx_values_pool.allocate ())
1497 ipcp_value<ipa_polymorphic_call_context>();
1498 val->value = source;
1499 return val;
1502 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1503 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1504 meaning. OFFSET -1 means the source is scalar and not a part of an
1505 aggregate. */
1507 template <typename valtype>
1508 bool
1509 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1510 ipcp_value<valtype> *src_val,
1511 int src_idx, HOST_WIDE_INT offset)
1513 ipcp_value<valtype> *val;
1515 if (bottom)
1516 return false;
1518 for (val = values; val; val = val->next)
1519 if (values_equal_for_ipcp_p (val->value, newval))
1521 if (ipa_edge_within_scc (cs))
1523 ipcp_value_source<valtype> *s;
1524 for (s = val->sources; s; s = s->next)
1525 if (s->cs == cs)
1526 break;
1527 if (s)
1528 return false;
1531 val->add_source (cs, src_val, src_idx, offset);
1532 return false;
1535 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1537 /* We can only free sources, not the values themselves, because sources
1538 of other values in this SCC might point to them. */
1539 for (val = values; val; val = val->next)
1541 while (val->sources)
1543 ipcp_value_source<valtype> *src = val->sources;
1544 val->sources = src->next;
1545 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1549 values = NULL;
1550 return set_to_bottom ();
1553 values_count++;
1554 val = allocate_and_init_ipcp_value (newval);
1555 val->add_source (cs, src_val, src_idx, offset);
1556 val->next = values;
1557 values = val;
1558 return true;
1561 /* Propagate values through a pass-through jump function JFUNC associated with
1562 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1563 is the index of the source parameter. */
1565 static bool
1566 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
1567 ipcp_lattice<tree> *src_lat,
1568 ipcp_lattice<tree> *dest_lat, int src_idx)
1570 ipcp_value<tree> *src_val;
1571 bool ret = false;
1573 /* Do not create new values when propagating within an SCC because if there
1574 are arithmetic functions with circular dependencies, there is infinite
1575 number of them and we would just make lattices bottom. */
1576 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1577 && ipa_edge_within_scc (cs))
1578 ret = dest_lat->set_contains_variable ();
1579 else
1580 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1582 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1584 if (cstval)
1585 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1586 else
1587 ret |= dest_lat->set_contains_variable ();
1590 return ret;
1593 /* Propagate values through an ancestor jump function JFUNC associated with
1594 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1595 is the index of the source parameter. */
1597 static bool
1598 propagate_vals_across_ancestor (struct cgraph_edge *cs,
1599 struct ipa_jump_func *jfunc,
1600 ipcp_lattice<tree> *src_lat,
1601 ipcp_lattice<tree> *dest_lat, int src_idx)
1603 ipcp_value<tree> *src_val;
1604 bool ret = false;
1606 if (ipa_edge_within_scc (cs))
1607 return dest_lat->set_contains_variable ();
1609 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1611 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1613 if (t)
1614 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1615 else
1616 ret |= dest_lat->set_contains_variable ();
1619 return ret;
1622 /* Propagate scalar values across jump function JFUNC that is associated with
1623 edge CS and put the values into DEST_LAT. */
1625 static bool
1626 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
1627 struct ipa_jump_func *jfunc,
1628 ipcp_lattice<tree> *dest_lat)
1630 if (dest_lat->bottom)
1631 return false;
1633 if (jfunc->type == IPA_JF_CONST)
1635 tree val = ipa_get_jf_constant (jfunc);
1636 return dest_lat->add_value (val, cs, NULL, 0);
1638 else if (jfunc->type == IPA_JF_PASS_THROUGH
1639 || jfunc->type == IPA_JF_ANCESTOR)
1641 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1642 ipcp_lattice<tree> *src_lat;
1643 int src_idx;
1644 bool ret;
1646 if (jfunc->type == IPA_JF_PASS_THROUGH)
1647 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1648 else
1649 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1651 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1652 if (src_lat->bottom)
1653 return dest_lat->set_contains_variable ();
1655 /* If we would need to clone the caller and cannot, do not propagate. */
1656 if (!ipcp_versionable_function_p (cs->caller)
1657 && (src_lat->contains_variable
1658 || (src_lat->values_count > 1)))
1659 return dest_lat->set_contains_variable ();
1661 if (jfunc->type == IPA_JF_PASS_THROUGH)
1662 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
1663 dest_lat, src_idx);
1664 else
1665 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
1666 src_idx);
1668 if (src_lat->contains_variable)
1669 ret |= dest_lat->set_contains_variable ();
1671 return ret;
1674 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1675 use it for indirect inlining), we should propagate them too. */
1676 return dest_lat->set_contains_variable ();
1679 /* Propagate scalar values across jump function JFUNC that is associated with
1680 edge CS and describes argument IDX and put the values into DEST_LAT. */
1682 static bool
1683 propagate_context_across_jump_function (cgraph_edge *cs,
1684 ipa_jump_func *jfunc, int idx,
1685 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1687 ipa_edge_args *args = IPA_EDGE_REF (cs);
1688 if (dest_lat->bottom)
1689 return false;
1690 bool ret = false;
1691 bool added_sth = false;
1692 bool type_preserved = true;
1694 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1695 = ipa_get_ith_polymorhic_call_context (args, idx);
1697 if (edge_ctx_ptr)
1698 edge_ctx = *edge_ctx_ptr;
1700 if (jfunc->type == IPA_JF_PASS_THROUGH
1701 || jfunc->type == IPA_JF_ANCESTOR)
1703 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1704 int src_idx;
1705 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1707 /* TODO: Once we figure out how to propagate speculations, it will
1708 probably be a good idea to switch to speculation if type_preserved is
1709 not set instead of punting. */
1710 if (jfunc->type == IPA_JF_PASS_THROUGH)
1712 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1713 goto prop_fail;
1714 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1715 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1717 else
1719 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1720 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1723 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1724 /* If we would need to clone the caller and cannot, do not propagate. */
1725 if (!ipcp_versionable_function_p (cs->caller)
1726 && (src_lat->contains_variable
1727 || (src_lat->values_count > 1)))
1728 goto prop_fail;
1730 ipcp_value<ipa_polymorphic_call_context> *src_val;
1731 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1733 ipa_polymorphic_call_context cur = src_val->value;
1735 if (!type_preserved)
1736 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1737 if (jfunc->type == IPA_JF_ANCESTOR)
1738 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1739 /* TODO: In cases we know how the context is going to be used,
1740 we can improve the result by passing proper OTR_TYPE. */
1741 cur.combine_with (edge_ctx);
1742 if (!cur.useless_p ())
1744 if (src_lat->contains_variable
1745 && !edge_ctx.equal_to (cur))
1746 ret |= dest_lat->set_contains_variable ();
1747 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1748 added_sth = true;
1754 prop_fail:
1755 if (!added_sth)
1757 if (!edge_ctx.useless_p ())
1758 ret |= dest_lat->add_value (edge_ctx, cs);
1759 else
1760 ret |= dest_lat->set_contains_variable ();
1763 return ret;
1766 /* Propagate bits across jfunc that is associated with
1767 edge cs and update dest_lattice accordingly. */
1769 bool
1770 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
1771 ipa_jump_func *jfunc,
1772 ipcp_bits_lattice *dest_lattice)
1774 if (dest_lattice->bottom_p ())
1775 return false;
1777 enum availability availability;
1778 cgraph_node *callee = cs->callee->function_symbol (&availability);
1779 struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
1780 tree parm_type = ipa_get_type (callee_info, idx);
1782 /* For K&R C programs, ipa_get_type() could return NULL_TREE.
1783 Avoid the transform for these cases. */
1784 if (!parm_type)
1786 if (dump_file && (dump_flags & TDF_DETAILS))
1787 fprintf (dump_file, "Setting dest_lattice to bottom, because"
1788 " param %i type is NULL for %s\n", idx,
1789 cs->callee->name ());
1791 return dest_lattice->set_to_bottom ();
1794 unsigned precision = TYPE_PRECISION (parm_type);
1795 signop sgn = TYPE_SIGN (parm_type);
1797 if (jfunc->type == IPA_JF_PASS_THROUGH
1798 || jfunc->type == IPA_JF_ANCESTOR)
1800 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1801 tree operand = NULL_TREE;
1802 enum tree_code code;
1803 unsigned src_idx;
1805 if (jfunc->type == IPA_JF_PASS_THROUGH)
1807 code = ipa_get_jf_pass_through_operation (jfunc);
1808 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1809 if (code != NOP_EXPR)
1810 operand = ipa_get_jf_pass_through_operand (jfunc);
1812 else
1814 code = POINTER_PLUS_EXPR;
1815 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1816 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
1817 operand = build_int_cstu (size_type_node, offset);
1820 struct ipcp_param_lattices *src_lats
1821 = ipa_get_parm_lattices (caller_info, src_idx);
1823 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1824 for eg consider:
1825 int f(int x)
1827 g (x & 0xff);
1829 Assume lattice for x is bottom, however we can still propagate
1830 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1831 and we store it in jump function during analysis stage. */
1833 if (src_lats->bits_lattice.bottom_p ()
1834 && jfunc->bits)
1835 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1836 precision);
1837 else
1838 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
1839 code, operand);
1842 else if (jfunc->type == IPA_JF_ANCESTOR)
1843 return dest_lattice->set_to_bottom ();
1844 else if (jfunc->bits)
1845 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
1846 precision);
1847 else
1848 return dest_lattice->set_to_bottom ();
1851 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1852 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1853 the result is a range or an anti-range. */
1855 static bool
1856 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr,
1857 enum tree_code operation,
1858 tree dst_type, tree src_type)
1860 memset (dst_vr, 0, sizeof (*dst_vr));
1861 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
1862 if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE)
1863 return true;
1864 else
1865 return false;
1868 /* Propagate value range across jump function JFUNC that is associated with
1869 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1870 accordingly. */
1872 static bool
1873 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
1874 struct ipcp_param_lattices *dest_plats,
1875 tree param_type)
1877 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
1879 if (dest_lat->bottom_p ())
1880 return false;
1882 if (!param_type
1883 || (!INTEGRAL_TYPE_P (param_type)
1884 && !POINTER_TYPE_P (param_type)))
1885 return dest_lat->set_to_bottom ();
1887 if (jfunc->type == IPA_JF_PASS_THROUGH)
1889 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1891 if (TREE_CODE_CLASS (operation) == tcc_unary)
1893 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1894 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1895 tree operand_type = ipa_get_type (caller_info, src_idx);
1896 struct ipcp_param_lattices *src_lats
1897 = ipa_get_parm_lattices (caller_info, src_idx);
1899 if (src_lats->m_value_range.bottom_p ())
1900 return dest_lat->set_to_bottom ();
1901 value_range vr;
1902 if (ipa_vr_operation_and_type_effects (&vr,
1903 &src_lats->m_value_range.m_vr,
1904 operation, param_type,
1905 operand_type))
1906 return dest_lat->meet_with (&vr);
1909 else if (jfunc->type == IPA_JF_CONST)
1911 tree val = ipa_get_jf_constant (jfunc);
1912 if (TREE_CODE (val) == INTEGER_CST)
1914 val = fold_convert (param_type, val);
1915 if (TREE_OVERFLOW_P (val))
1916 val = drop_tree_overflow (val);
1918 value_range tmpvr;
1919 memset (&tmpvr, 0, sizeof (tmpvr));
1920 tmpvr.type = VR_RANGE;
1921 tmpvr.min = val;
1922 tmpvr.max = val;
1923 return dest_lat->meet_with (&tmpvr);
1927 value_range vr;
1928 if (jfunc->m_vr
1929 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
1930 param_type,
1931 TREE_TYPE (jfunc->m_vr->min)))
1932 return dest_lat->meet_with (&vr);
1933 else
1934 return dest_lat->set_to_bottom ();
1937 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1938 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1939 other cases, return false). If there are no aggregate items, set
1940 aggs_by_ref to NEW_AGGS_BY_REF. */
1942 static bool
1943 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1944 bool new_aggs_by_ref)
1946 if (dest_plats->aggs)
1948 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1950 set_agg_lats_to_bottom (dest_plats);
1951 return true;
1954 else
1955 dest_plats->aggs_by_ref = new_aggs_by_ref;
1956 return false;
1959 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1960 already existing lattice for the given OFFSET and SIZE, marking all skipped
1961 lattices as containing variable and checking for overlaps. If there is no
1962 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1963 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1964 unless there are too many already. If there are two many, return false. If
1965 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1966 skipped lattices were newly marked as containing variable, set *CHANGE to
1967 true. */
1969 static bool
1970 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1971 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1972 struct ipcp_agg_lattice ***aglat,
1973 bool pre_existing, bool *change)
1975 gcc_checking_assert (offset >= 0);
1977 while (**aglat && (**aglat)->offset < offset)
1979 if ((**aglat)->offset + (**aglat)->size > offset)
1981 set_agg_lats_to_bottom (dest_plats);
1982 return false;
1984 *change |= (**aglat)->set_contains_variable ();
1985 *aglat = &(**aglat)->next;
1988 if (**aglat && (**aglat)->offset == offset)
1990 if ((**aglat)->size != val_size
1991 || ((**aglat)->next
1992 && (**aglat)->next->offset < offset + val_size))
1994 set_agg_lats_to_bottom (dest_plats);
1995 return false;
1997 gcc_checking_assert (!(**aglat)->next
1998 || (**aglat)->next->offset >= offset + val_size);
1999 return true;
2001 else
2003 struct ipcp_agg_lattice *new_al;
2005 if (**aglat && (**aglat)->offset < offset + val_size)
2007 set_agg_lats_to_bottom (dest_plats);
2008 return false;
2010 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
2011 return false;
2012 dest_plats->aggs_count++;
2013 new_al = ipcp_agg_lattice_pool.allocate ();
2014 memset (new_al, 0, sizeof (*new_al));
2016 new_al->offset = offset;
2017 new_al->size = val_size;
2018 new_al->contains_variable = pre_existing;
2020 new_al->next = **aglat;
2021 **aglat = new_al;
2022 return true;
2026 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2027 containing an unknown value. */
2029 static bool
2030 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2032 bool ret = false;
2033 while (aglat)
2035 ret |= aglat->set_contains_variable ();
2036 aglat = aglat->next;
2038 return ret;
2041 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2042 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2043 parameter used for lattice value sources. Return true if DEST_PLATS changed
2044 in any way. */
2046 static bool
2047 merge_aggregate_lattices (struct cgraph_edge *cs,
2048 struct ipcp_param_lattices *dest_plats,
2049 struct ipcp_param_lattices *src_plats,
2050 int src_idx, HOST_WIDE_INT offset_delta)
2052 bool pre_existing = dest_plats->aggs != NULL;
2053 struct ipcp_agg_lattice **dst_aglat;
2054 bool ret = false;
2056 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2057 return true;
2058 if (src_plats->aggs_bottom)
2059 return set_agg_lats_contain_variable (dest_plats);
2060 if (src_plats->aggs_contain_variable)
2061 ret |= set_agg_lats_contain_variable (dest_plats);
2062 dst_aglat = &dest_plats->aggs;
2064 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2065 src_aglat;
2066 src_aglat = src_aglat->next)
2068 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2070 if (new_offset < 0)
2071 continue;
2072 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2073 &dst_aglat, pre_existing, &ret))
2075 struct ipcp_agg_lattice *new_al = *dst_aglat;
2077 dst_aglat = &(*dst_aglat)->next;
2078 if (src_aglat->bottom)
2080 ret |= new_al->set_contains_variable ();
2081 continue;
2083 if (src_aglat->contains_variable)
2084 ret |= new_al->set_contains_variable ();
2085 for (ipcp_value<tree> *val = src_aglat->values;
2086 val;
2087 val = val->next)
2088 ret |= new_al->add_value (val->value, cs, val, src_idx,
2089 src_aglat->offset);
2091 else if (dest_plats->aggs_bottom)
2092 return true;
2094 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2095 return ret;
2098 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2099 pass-through JFUNC and if so, whether it has conform and conforms to the
2100 rules about propagating values passed by reference. */
2102 static bool
2103 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
2104 struct ipa_jump_func *jfunc)
2106 return src_plats->aggs
2107 && (!src_plats->aggs_by_ref
2108 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2111 /* Propagate scalar values across jump function JFUNC that is associated with
2112 edge CS and put the values into DEST_LAT. */
2114 static bool
2115 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2116 struct ipa_jump_func *jfunc,
2117 struct ipcp_param_lattices *dest_plats)
2119 bool ret = false;
2121 if (dest_plats->aggs_bottom)
2122 return false;
2124 if (jfunc->type == IPA_JF_PASS_THROUGH
2125 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2127 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2128 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2129 struct ipcp_param_lattices *src_plats;
2131 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2132 if (agg_pass_through_permissible_p (src_plats, jfunc))
2134 /* Currently we do not produce clobber aggregate jump
2135 functions, replace with merging when we do. */
2136 gcc_assert (!jfunc->agg.items);
2137 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2138 src_idx, 0);
2140 else
2141 ret |= set_agg_lats_contain_variable (dest_plats);
2143 else if (jfunc->type == IPA_JF_ANCESTOR
2144 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2146 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2147 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2148 struct ipcp_param_lattices *src_plats;
2150 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2151 if (src_plats->aggs && src_plats->aggs_by_ref)
2153 /* Currently we do not produce clobber aggregate jump
2154 functions, replace with merging when we do. */
2155 gcc_assert (!jfunc->agg.items);
2156 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2157 ipa_get_jf_ancestor_offset (jfunc));
2159 else if (!src_plats->aggs_by_ref)
2160 ret |= set_agg_lats_to_bottom (dest_plats);
2161 else
2162 ret |= set_agg_lats_contain_variable (dest_plats);
2164 else if (jfunc->agg.items)
2166 bool pre_existing = dest_plats->aggs != NULL;
2167 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2168 struct ipa_agg_jf_item *item;
2169 int i;
2171 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2172 return true;
2174 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2176 HOST_WIDE_INT val_size;
2178 if (item->offset < 0)
2179 continue;
2180 gcc_checking_assert (is_gimple_ip_invariant (item->value));
2181 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2183 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2184 &aglat, pre_existing, &ret))
2186 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2187 aglat = &(*aglat)->next;
2189 else if (dest_plats->aggs_bottom)
2190 return true;
2193 ret |= set_chain_of_aglats_contains_variable (*aglat);
2195 else
2196 ret |= set_agg_lats_contain_variable (dest_plats);
2198 return ret;
2201 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2202 non-thunk) destination, the call passes through a thunk. */
2204 static bool
2205 call_passes_through_thunk_p (cgraph_edge *cs)
2207 cgraph_node *alias_or_thunk = cs->callee;
2208 while (alias_or_thunk->alias)
2209 alias_or_thunk = alias_or_thunk->get_alias_target ();
2210 return alias_or_thunk->thunk.thunk_p;
2213 /* Propagate constants from the caller to the callee of CS. INFO describes the
2214 caller. */
2216 static bool
2217 propagate_constants_across_call (struct cgraph_edge *cs)
2219 struct ipa_node_params *callee_info;
2220 enum availability availability;
2221 cgraph_node *callee;
2222 struct ipa_edge_args *args;
2223 bool ret = false;
2224 int i, args_count, parms_count;
2226 callee = cs->callee->function_symbol (&availability);
2227 if (!callee->definition)
2228 return false;
2229 gcc_checking_assert (callee->has_gimple_body_p ());
2230 callee_info = IPA_NODE_REF (callee);
2232 args = IPA_EDGE_REF (cs);
2233 args_count = ipa_get_cs_argument_count (args);
2234 parms_count = ipa_get_param_count (callee_info);
2235 if (parms_count == 0)
2236 return false;
2238 /* No propagation through instrumentation thunks is available yet.
2239 It should be possible with proper mapping of call args and
2240 instrumented callee params in the propagation loop below. But
2241 this case mostly occurs when legacy code calls instrumented code
2242 and it is not a primary target for optimizations.
2243 We detect instrumentation thunks in aliases and thunks chain by
2244 checking instrumentation_clone flag for chain source and target.
2245 Going through instrumentation thunks we always have it changed
2246 from 0 to 1 and all other nodes do not change it. */
2247 if (!cs->callee->instrumentation_clone
2248 && callee->instrumentation_clone)
2250 for (i = 0; i < parms_count; i++)
2251 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2252 i));
2253 return ret;
2256 /* If this call goes through a thunk we must not propagate to the first (0th)
2257 parameter. However, we might need to uncover a thunk from below a series
2258 of aliases first. */
2259 if (call_passes_through_thunk_p (cs))
2261 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2262 0));
2263 i = 1;
2265 else
2266 i = 0;
2268 for (; (i < args_count) && (i < parms_count); i++)
2270 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2271 struct ipcp_param_lattices *dest_plats;
2272 tree param_type = ipa_get_type (callee_info, i);
2274 dest_plats = ipa_get_parm_lattices (callee_info, i);
2275 if (availability == AVAIL_INTERPOSABLE)
2276 ret |= set_all_contains_variable (dest_plats);
2277 else
2279 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2280 &dest_plats->itself);
2281 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2282 &dest_plats->ctxlat);
2284 |= propagate_bits_across_jump_function (cs, i, jump_func,
2285 &dest_plats->bits_lattice);
2286 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2287 dest_plats);
2288 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2289 ret |= propagate_vr_across_jump_function (cs, jump_func,
2290 dest_plats, param_type);
2291 else
2292 ret |= dest_plats->m_value_range.set_to_bottom ();
2295 for (; i < parms_count; i++)
2296 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2298 return ret;
2301 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2302 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2303 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2305 static tree
2306 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2307 vec<tree> known_csts,
2308 vec<ipa_polymorphic_call_context> known_contexts,
2309 vec<ipa_agg_jump_function_p> known_aggs,
2310 struct ipa_agg_replacement_value *agg_reps,
2311 bool *speculative)
2313 int param_index = ie->indirect_info->param_index;
2314 HOST_WIDE_INT anc_offset;
2315 tree t;
2316 tree target = NULL;
2318 *speculative = false;
2320 if (param_index == -1
2321 || known_csts.length () <= (unsigned int) param_index)
2322 return NULL_TREE;
2324 if (!ie->indirect_info->polymorphic)
2326 tree t;
2328 if (ie->indirect_info->agg_contents)
2330 t = NULL;
2331 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2333 while (agg_reps)
2335 if (agg_reps->index == param_index
2336 && agg_reps->offset == ie->indirect_info->offset
2337 && agg_reps->by_ref == ie->indirect_info->by_ref)
2339 t = agg_reps->value;
2340 break;
2342 agg_reps = agg_reps->next;
2345 if (!t)
2347 struct ipa_agg_jump_function *agg;
2348 if (known_aggs.length () > (unsigned int) param_index)
2349 agg = known_aggs[param_index];
2350 else
2351 agg = NULL;
2352 bool from_global_constant;
2353 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2354 ie->indirect_info->offset,
2355 ie->indirect_info->by_ref,
2356 &from_global_constant);
2357 if (t
2358 && !from_global_constant
2359 && !ie->indirect_info->guaranteed_unmodified)
2360 t = NULL_TREE;
2363 else
2364 t = known_csts[param_index];
2366 if (t
2367 && TREE_CODE (t) == ADDR_EXPR
2368 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2369 return TREE_OPERAND (t, 0);
2370 else
2371 return NULL_TREE;
2374 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2375 return NULL_TREE;
2377 gcc_assert (!ie->indirect_info->agg_contents);
2378 anc_offset = ie->indirect_info->offset;
2380 t = NULL;
2382 /* Try to work out value of virtual table pointer value in replacemnets. */
2383 if (!t && agg_reps && !ie->indirect_info->by_ref)
2385 while (agg_reps)
2387 if (agg_reps->index == param_index
2388 && agg_reps->offset == ie->indirect_info->offset
2389 && agg_reps->by_ref)
2391 t = agg_reps->value;
2392 break;
2394 agg_reps = agg_reps->next;
2398 /* Try to work out value of virtual table pointer value in known
2399 aggregate values. */
2400 if (!t && known_aggs.length () > (unsigned int) param_index
2401 && !ie->indirect_info->by_ref)
2403 struct ipa_agg_jump_function *agg;
2404 agg = known_aggs[param_index];
2405 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2406 ie->indirect_info->offset, true);
2409 /* If we found the virtual table pointer, lookup the target. */
2410 if (t)
2412 tree vtable;
2413 unsigned HOST_WIDE_INT offset;
2414 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2416 bool can_refer;
2417 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2418 vtable, offset, &can_refer);
2419 if (can_refer)
2421 if (!target
2422 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2423 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2424 || !possible_polymorphic_call_target_p
2425 (ie, cgraph_node::get (target)))
2427 /* Do not speculate builtin_unreachable, it is stupid! */
2428 if (ie->indirect_info->vptr_changed)
2429 return NULL;
2430 target = ipa_impossible_devirt_target (ie, target);
2432 *speculative = ie->indirect_info->vptr_changed;
2433 if (!*speculative)
2434 return target;
2439 /* Do we know the constant value of pointer? */
2440 if (!t)
2441 t = known_csts[param_index];
2443 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2445 ipa_polymorphic_call_context context;
2446 if (known_contexts.length () > (unsigned int) param_index)
2448 context = known_contexts[param_index];
2449 context.offset_by (anc_offset);
2450 if (ie->indirect_info->vptr_changed)
2451 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2452 ie->indirect_info->otr_type);
2453 if (t)
2455 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2456 (t, ie->indirect_info->otr_type, anc_offset);
2457 if (!ctx2.useless_p ())
2458 context.combine_with (ctx2, ie->indirect_info->otr_type);
2461 else if (t)
2463 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2464 anc_offset);
2465 if (ie->indirect_info->vptr_changed)
2466 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2467 ie->indirect_info->otr_type);
2469 else
2470 return NULL_TREE;
2472 vec <cgraph_node *>targets;
2473 bool final;
2475 targets = possible_polymorphic_call_targets
2476 (ie->indirect_info->otr_type,
2477 ie->indirect_info->otr_token,
2478 context, &final);
2479 if (!final || targets.length () > 1)
2481 struct cgraph_node *node;
2482 if (*speculative)
2483 return target;
2484 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2485 || ie->speculative || !ie->maybe_hot_p ())
2486 return NULL;
2487 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2488 ie->indirect_info->otr_token,
2489 context);
2490 if (node)
2492 *speculative = true;
2493 target = node->decl;
2495 else
2496 return NULL;
2498 else
2500 *speculative = false;
2501 if (targets.length () == 1)
2502 target = targets[0]->decl;
2503 else
2504 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2507 if (target && !possible_polymorphic_call_target_p (ie,
2508 cgraph_node::get (target)))
2510 if (*speculative)
2511 return NULL;
2512 target = ipa_impossible_devirt_target (ie, target);
2515 return target;
2519 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2520 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2521 return the destination. */
2523 tree
2524 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2525 vec<tree> known_csts,
2526 vec<ipa_polymorphic_call_context> known_contexts,
2527 vec<ipa_agg_jump_function_p> known_aggs,
2528 bool *speculative)
2530 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2531 known_aggs, NULL, speculative);
2534 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2535 and KNOWN_CONTEXTS. */
2537 static int
2538 devirtualization_time_bonus (struct cgraph_node *node,
2539 vec<tree> known_csts,
2540 vec<ipa_polymorphic_call_context> known_contexts,
2541 vec<ipa_agg_jump_function_p> known_aggs)
2543 struct cgraph_edge *ie;
2544 int res = 0;
2546 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2548 struct cgraph_node *callee;
2549 struct ipa_fn_summary *isummary;
2550 enum availability avail;
2551 tree target;
2552 bool speculative;
2554 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2555 known_aggs, &speculative);
2556 if (!target)
2557 continue;
2559 /* Only bare minimum benefit for clearly un-inlineable targets. */
2560 res += 1;
2561 callee = cgraph_node::get (target);
2562 if (!callee || !callee->definition)
2563 continue;
2564 callee = callee->function_symbol (&avail);
2565 if (avail < AVAIL_AVAILABLE)
2566 continue;
2567 isummary = ipa_fn_summaries->get (callee);
2568 if (!isummary->inlinable)
2569 continue;
2571 /* FIXME: The values below need re-considering and perhaps also
2572 integrating into the cost metrics, at lest in some very basic way. */
2573 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2574 res += 31 / ((int)speculative + 1);
2575 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2576 res += 15 / ((int)speculative + 1);
2577 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2578 || DECL_DECLARED_INLINE_P (callee->decl))
2579 res += 7 / ((int)speculative + 1);
2582 return res;
2585 /* Return time bonus incurred because of HINTS. */
2587 static int
2588 hint_time_bonus (ipa_hints hints)
2590 int result = 0;
2591 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2592 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2593 if (hints & INLINE_HINT_array_index)
2594 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2595 return result;
2598 /* If there is a reason to penalize the function described by INFO in the
2599 cloning goodness evaluation, do so. */
2601 static inline int64_t
2602 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2604 if (info->node_within_scc)
2605 evaluation = (evaluation
2606 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2608 if (info->node_calling_single_call)
2609 evaluation = (evaluation
2610 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2611 / 100;
2613 return evaluation;
2616 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2617 and SIZE_COST and with the sum of frequencies of incoming edges to the
2618 potential new clone in FREQUENCIES. */
2620 static bool
2621 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2622 int freq_sum, profile_count count_sum, int size_cost)
2624 if (time_benefit == 0
2625 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2626 || node->optimize_for_size_p ())
2627 return false;
2629 gcc_assert (size_cost > 0);
2631 struct ipa_node_params *info = IPA_NODE_REF (node);
2632 if (max_count > profile_count::zero ())
2634 int factor = RDIV (count_sum.probability_in
2635 (max_count).to_reg_br_prob_base ()
2636 * 1000, REG_BR_PROB_BASE);
2637 int64_t evaluation = (((int64_t) time_benefit * factor)
2638 / size_cost);
2639 evaluation = incorporate_penalties (info, evaluation);
2641 if (dump_file && (dump_flags & TDF_DETAILS))
2643 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2644 "size: %i, count_sum: ", time_benefit, size_cost);
2645 count_sum.dump (dump_file);
2646 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
2647 ", threshold: %i\n",
2648 info->node_within_scc ? ", scc" : "",
2649 info->node_calling_single_call ? ", single_call" : "",
2650 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2653 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2655 else
2657 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2658 / size_cost);
2659 evaluation = incorporate_penalties (info, evaluation);
2661 if (dump_file && (dump_flags & TDF_DETAILS))
2662 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2663 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2664 "%" PRId64 ", threshold: %i\n",
2665 time_benefit, size_cost, freq_sum,
2666 info->node_within_scc ? ", scc" : "",
2667 info->node_calling_single_call ? ", single_call" : "",
2668 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2670 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2674 /* Return all context independent values from aggregate lattices in PLATS in a
2675 vector. Return NULL if there are none. */
2677 static vec<ipa_agg_jf_item, va_gc> *
2678 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2680 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2682 if (plats->aggs_bottom
2683 || plats->aggs_contain_variable
2684 || plats->aggs_count == 0)
2685 return NULL;
2687 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2688 aglat;
2689 aglat = aglat->next)
2690 if (aglat->is_single_const ())
2692 struct ipa_agg_jf_item item;
2693 item.offset = aglat->offset;
2694 item.value = aglat->values->value;
2695 vec_safe_push (res, item);
2697 return res;
2700 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2701 populate them with values of parameters that are known independent of the
2702 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2703 non-NULL, the movement cost of all removable parameters will be stored in
2704 it. */
2706 static bool
2707 gather_context_independent_values (struct ipa_node_params *info,
2708 vec<tree> *known_csts,
2709 vec<ipa_polymorphic_call_context>
2710 *known_contexts,
2711 vec<ipa_agg_jump_function> *known_aggs,
2712 int *removable_params_cost)
2714 int i, count = ipa_get_param_count (info);
2715 bool ret = false;
2717 known_csts->create (0);
2718 known_contexts->create (0);
2719 known_csts->safe_grow_cleared (count);
2720 known_contexts->safe_grow_cleared (count);
2721 if (known_aggs)
2723 known_aggs->create (0);
2724 known_aggs->safe_grow_cleared (count);
2727 if (removable_params_cost)
2728 *removable_params_cost = 0;
2730 for (i = 0; i < count; i++)
2732 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2733 ipcp_lattice<tree> *lat = &plats->itself;
2735 if (lat->is_single_const ())
2737 ipcp_value<tree> *val = lat->values;
2738 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2739 (*known_csts)[i] = val->value;
2740 if (removable_params_cost)
2741 *removable_params_cost
2742 += estimate_move_cost (TREE_TYPE (val->value), false);
2743 ret = true;
2745 else if (removable_params_cost
2746 && !ipa_is_param_used (info, i))
2747 *removable_params_cost
2748 += ipa_get_param_move_cost (info, i);
2750 if (!ipa_is_param_used (info, i))
2751 continue;
2753 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2754 /* Do not account known context as reason for cloning. We can see
2755 if it permits devirtualization. */
2756 if (ctxlat->is_single_const ())
2757 (*known_contexts)[i] = ctxlat->values->value;
2759 if (known_aggs)
2761 vec<ipa_agg_jf_item, va_gc> *agg_items;
2762 struct ipa_agg_jump_function *ajf;
2764 agg_items = context_independent_aggregate_values (plats);
2765 ajf = &(*known_aggs)[i];
2766 ajf->items = agg_items;
2767 ajf->by_ref = plats->aggs_by_ref;
2768 ret |= agg_items != NULL;
2772 return ret;
2775 /* The current interface in ipa-inline-analysis requires a pointer vector.
2776 Create it.
2778 FIXME: That interface should be re-worked, this is slightly silly. Still,
2779 I'd like to discuss how to change it first and this demonstrates the
2780 issue. */
2782 static vec<ipa_agg_jump_function_p>
2783 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2785 vec<ipa_agg_jump_function_p> ret;
2786 struct ipa_agg_jump_function *ajf;
2787 int i;
2789 ret.create (known_aggs.length ());
2790 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2791 ret.quick_push (ajf);
2792 return ret;
2795 /* Perform time and size measurement of NODE with the context given in
2796 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2797 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2798 all context-independent removable parameters and EST_MOVE_COST of estimated
2799 movement of the considered parameter and store it into VAL. */
2801 static void
2802 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2803 vec<ipa_polymorphic_call_context> known_contexts,
2804 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2805 int removable_params_cost,
2806 int est_move_cost, ipcp_value_base *val)
2808 int size, time_benefit;
2809 sreal time, base_time;
2810 ipa_hints hints;
2812 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2813 known_aggs_ptrs, &size, &time,
2814 &base_time, &hints);
2815 base_time -= time;
2816 if (base_time > 65535)
2817 base_time = 65535;
2818 time_benefit = base_time.to_int ()
2819 + devirtualization_time_bonus (node, known_csts, known_contexts,
2820 known_aggs_ptrs)
2821 + hint_time_bonus (hints)
2822 + removable_params_cost + est_move_cost;
2824 gcc_checking_assert (size >=0);
2825 /* The inliner-heuristics based estimates may think that in certain
2826 contexts some functions do not have any size at all but we want
2827 all specializations to have at least a tiny cost, not least not to
2828 divide by zero. */
2829 if (size == 0)
2830 size = 1;
2832 val->local_time_benefit = time_benefit;
2833 val->local_size_cost = size;
2836 /* Iterate over known values of parameters of NODE and estimate the local
2837 effects in terms of time and size they have. */
2839 static void
2840 estimate_local_effects (struct cgraph_node *node)
2842 struct ipa_node_params *info = IPA_NODE_REF (node);
2843 int i, count = ipa_get_param_count (info);
2844 vec<tree> known_csts;
2845 vec<ipa_polymorphic_call_context> known_contexts;
2846 vec<ipa_agg_jump_function> known_aggs;
2847 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2848 bool always_const;
2849 int removable_params_cost;
2851 if (!count || !ipcp_versionable_function_p (node))
2852 return;
2854 if (dump_file && (dump_flags & TDF_DETAILS))
2855 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
2857 always_const = gather_context_independent_values (info, &known_csts,
2858 &known_contexts, &known_aggs,
2859 &removable_params_cost);
2860 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2861 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2862 known_contexts, known_aggs_ptrs);
2863 if (always_const || devirt_bonus
2864 || (removable_params_cost && node->local.can_change_signature))
2866 struct caller_statistics stats;
2867 ipa_hints hints;
2868 sreal time, base_time;
2869 int size;
2871 init_caller_stats (&stats);
2872 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2873 false);
2874 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2875 known_aggs_ptrs, &size, &time,
2876 &base_time, &hints);
2877 time -= devirt_bonus;
2878 time -= hint_time_bonus (hints);
2879 time -= removable_params_cost;
2880 size -= stats.n_calls * removable_params_cost;
2882 if (dump_file)
2883 fprintf (dump_file, " - context independent values, size: %i, "
2884 "time_benefit: %f\n", size, (base_time - time).to_double ());
2886 if (size <= 0 || node->local.local)
2888 info->do_clone_for_all_contexts = true;
2890 if (dump_file)
2891 fprintf (dump_file, " Decided to specialize for all "
2892 "known contexts, code not going to grow.\n");
2894 else if (good_cloning_opportunity_p (node,
2895 MAX ((base_time - time).to_int (),
2896 65536),
2897 stats.freq_sum, stats.count_sum,
2898 size))
2900 if (size + overall_size <= max_new_size)
2902 info->do_clone_for_all_contexts = true;
2903 overall_size += size;
2905 if (dump_file)
2906 fprintf (dump_file, " Decided to specialize for all "
2907 "known contexts, growth deemed beneficial.\n");
2909 else if (dump_file && (dump_flags & TDF_DETAILS))
2910 fprintf (dump_file, " Not cloning for all contexts because "
2911 "max_new_size would be reached with %li.\n",
2912 size + overall_size);
2914 else if (dump_file && (dump_flags & TDF_DETAILS))
2915 fprintf (dump_file, " Not cloning for all contexts because "
2916 "!good_cloning_opportunity_p.\n");
2920 for (i = 0; i < count; i++)
2922 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2923 ipcp_lattice<tree> *lat = &plats->itself;
2924 ipcp_value<tree> *val;
2926 if (lat->bottom
2927 || !lat->values
2928 || known_csts[i])
2929 continue;
2931 for (val = lat->values; val; val = val->next)
2933 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2934 known_csts[i] = val->value;
2936 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2937 perform_estimation_of_a_value (node, known_csts, known_contexts,
2938 known_aggs_ptrs,
2939 removable_params_cost, emc, val);
2941 if (dump_file && (dump_flags & TDF_DETAILS))
2943 fprintf (dump_file, " - estimates for value ");
2944 print_ipcp_constant_value (dump_file, val->value);
2945 fprintf (dump_file, " for ");
2946 ipa_dump_param (dump_file, info, i);
2947 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2948 val->local_time_benefit, val->local_size_cost);
2951 known_csts[i] = NULL_TREE;
2954 for (i = 0; i < count; i++)
2956 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2958 if (!plats->virt_call)
2959 continue;
2961 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2962 ipcp_value<ipa_polymorphic_call_context> *val;
2964 if (ctxlat->bottom
2965 || !ctxlat->values
2966 || !known_contexts[i].useless_p ())
2967 continue;
2969 for (val = ctxlat->values; val; val = val->next)
2971 known_contexts[i] = val->value;
2972 perform_estimation_of_a_value (node, known_csts, known_contexts,
2973 known_aggs_ptrs,
2974 removable_params_cost, 0, val);
2976 if (dump_file && (dump_flags & TDF_DETAILS))
2978 fprintf (dump_file, " - estimates for polymorphic context ");
2979 print_ipcp_constant_value (dump_file, val->value);
2980 fprintf (dump_file, " for ");
2981 ipa_dump_param (dump_file, info, i);
2982 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2983 val->local_time_benefit, val->local_size_cost);
2986 known_contexts[i] = ipa_polymorphic_call_context ();
2989 for (i = 0; i < count; i++)
2991 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2992 struct ipa_agg_jump_function *ajf;
2993 struct ipcp_agg_lattice *aglat;
2995 if (plats->aggs_bottom || !plats->aggs)
2996 continue;
2998 ajf = &known_aggs[i];
2999 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3001 ipcp_value<tree> *val;
3002 if (aglat->bottom || !aglat->values
3003 /* If the following is true, the one value is in known_aggs. */
3004 || (!plats->aggs_contain_variable
3005 && aglat->is_single_const ()))
3006 continue;
3008 for (val = aglat->values; val; val = val->next)
3010 struct ipa_agg_jf_item item;
3012 item.offset = aglat->offset;
3013 item.value = val->value;
3014 vec_safe_push (ajf->items, item);
3016 perform_estimation_of_a_value (node, known_csts, known_contexts,
3017 known_aggs_ptrs,
3018 removable_params_cost, 0, val);
3020 if (dump_file && (dump_flags & TDF_DETAILS))
3022 fprintf (dump_file, " - estimates for value ");
3023 print_ipcp_constant_value (dump_file, val->value);
3024 fprintf (dump_file, " for ");
3025 ipa_dump_param (dump_file, info, i);
3026 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3027 "]: time_benefit: %i, size: %i\n",
3028 plats->aggs_by_ref ? "ref " : "",
3029 aglat->offset,
3030 val->local_time_benefit, val->local_size_cost);
3033 ajf->items->pop ();
3038 for (i = 0; i < count; i++)
3039 vec_free (known_aggs[i].items);
3041 known_csts.release ();
3042 known_contexts.release ();
3043 known_aggs.release ();
3044 known_aggs_ptrs.release ();
3048 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3049 topological sort of values. */
3051 template <typename valtype>
3052 void
3053 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3055 ipcp_value_source<valtype> *src;
3057 if (cur_val->dfs)
3058 return;
3060 dfs_counter++;
3061 cur_val->dfs = dfs_counter;
3062 cur_val->low_link = dfs_counter;
3064 cur_val->topo_next = stack;
3065 stack = cur_val;
3066 cur_val->on_stack = true;
3068 for (src = cur_val->sources; src; src = src->next)
3069 if (src->val)
3071 if (src->val->dfs == 0)
3073 add_val (src->val);
3074 if (src->val->low_link < cur_val->low_link)
3075 cur_val->low_link = src->val->low_link;
3077 else if (src->val->on_stack
3078 && src->val->dfs < cur_val->low_link)
3079 cur_val->low_link = src->val->dfs;
3082 if (cur_val->dfs == cur_val->low_link)
3084 ipcp_value<valtype> *v, *scc_list = NULL;
3088 v = stack;
3089 stack = v->topo_next;
3090 v->on_stack = false;
3092 v->scc_next = scc_list;
3093 scc_list = v;
3095 while (v != cur_val);
3097 cur_val->topo_next = values_topo;
3098 values_topo = cur_val;
3102 /* Add all values in lattices associated with NODE to the topological sort if
3103 they are not there yet. */
3105 static void
3106 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3108 struct ipa_node_params *info = IPA_NODE_REF (node);
3109 int i, count = ipa_get_param_count (info);
3111 for (i = 0; i < count; i++)
3113 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3114 ipcp_lattice<tree> *lat = &plats->itself;
3115 struct ipcp_agg_lattice *aglat;
3117 if (!lat->bottom)
3119 ipcp_value<tree> *val;
3120 for (val = lat->values; val; val = val->next)
3121 topo->constants.add_val (val);
3124 if (!plats->aggs_bottom)
3125 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3126 if (!aglat->bottom)
3128 ipcp_value<tree> *val;
3129 for (val = aglat->values; val; val = val->next)
3130 topo->constants.add_val (val);
3133 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3134 if (!ctxlat->bottom)
3136 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3137 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3138 topo->contexts.add_val (ctxval);
3143 /* One pass of constants propagation along the call graph edges, from callers
3144 to callees (requires topological ordering in TOPO), iterate over strongly
3145 connected components. */
3147 static void
3148 propagate_constants_topo (struct ipa_topo_info *topo)
3150 int i;
3152 for (i = topo->nnodes - 1; i >= 0; i--)
3154 unsigned j;
3155 struct cgraph_node *v, *node = topo->order[i];
3156 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3158 /* First, iteratively propagate within the strongly connected component
3159 until all lattices stabilize. */
3160 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3161 if (v->has_gimple_body_p ())
3162 push_node_to_stack (topo, v);
3164 v = pop_node_from_stack (topo);
3165 while (v)
3167 struct cgraph_edge *cs;
3169 for (cs = v->callees; cs; cs = cs->next_callee)
3170 if (ipa_edge_within_scc (cs))
3172 IPA_NODE_REF (v)->node_within_scc = true;
3173 if (propagate_constants_across_call (cs))
3174 push_node_to_stack (topo, cs->callee->function_symbol ());
3176 v = pop_node_from_stack (topo);
3179 /* Afterwards, propagate along edges leading out of the SCC, calculates
3180 the local effects of the discovered constants and all valid values to
3181 their topological sort. */
3182 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3183 if (v->has_gimple_body_p ())
3185 struct cgraph_edge *cs;
3187 estimate_local_effects (v);
3188 add_all_node_vals_to_toposort (v, topo);
3189 for (cs = v->callees; cs; cs = cs->next_callee)
3190 if (!ipa_edge_within_scc (cs))
3191 propagate_constants_across_call (cs);
3193 cycle_nodes.release ();
3198 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3199 the bigger one if otherwise. */
3201 static int
3202 safe_add (int a, int b)
3204 if (a > INT_MAX/2 || b > INT_MAX/2)
3205 return a > b ? a : b;
3206 else
3207 return a + b;
3211 /* Propagate the estimated effects of individual values along the topological
3212 from the dependent values to those they depend on. */
3214 template <typename valtype>
3215 void
3216 value_topo_info<valtype>::propagate_effects ()
3218 ipcp_value<valtype> *base;
3220 for (base = values_topo; base; base = base->topo_next)
3222 ipcp_value_source<valtype> *src;
3223 ipcp_value<valtype> *val;
3224 int time = 0, size = 0;
3226 for (val = base; val; val = val->scc_next)
3228 time = safe_add (time,
3229 val->local_time_benefit + val->prop_time_benefit);
3230 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3233 for (val = base; val; val = val->scc_next)
3234 for (src = val->sources; src; src = src->next)
3235 if (src->val
3236 && src->cs->maybe_hot_p ())
3238 src->val->prop_time_benefit = safe_add (time,
3239 src->val->prop_time_benefit);
3240 src->val->prop_size_cost = safe_add (size,
3241 src->val->prop_size_cost);
3247 /* Propagate constants, polymorphic contexts and their effects from the
3248 summaries interprocedurally. */
3250 static void
3251 ipcp_propagate_stage (struct ipa_topo_info *topo)
3253 struct cgraph_node *node;
3255 if (dump_file)
3256 fprintf (dump_file, "\n Propagating constants:\n\n");
3258 FOR_EACH_DEFINED_FUNCTION (node)
3260 struct ipa_node_params *info = IPA_NODE_REF (node);
3262 determine_versionability (node, info);
3263 if (node->has_gimple_body_p ())
3265 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3266 ipa_get_param_count (info));
3267 initialize_node_lattices (node);
3269 if (node->definition && !node->alias)
3270 overall_size += ipa_fn_summaries->get (node)->self_size;
3271 if (node->count > max_count)
3272 max_count = node->count;
3275 max_new_size = overall_size;
3276 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3277 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3278 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3280 if (dump_file)
3281 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3282 overall_size, max_new_size);
3284 propagate_constants_topo (topo);
3285 if (flag_checking)
3286 ipcp_verify_propagated_values ();
3287 topo->constants.propagate_effects ();
3288 topo->contexts.propagate_effects ();
3290 if (dump_file)
3292 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3293 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3297 /* Discover newly direct outgoing edges from NODE which is a new clone with
3298 known KNOWN_CSTS and make them direct. */
3300 static void
3301 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3302 vec<tree> known_csts,
3303 vec<ipa_polymorphic_call_context>
3304 known_contexts,
3305 struct ipa_agg_replacement_value *aggvals)
3307 struct cgraph_edge *ie, *next_ie;
3308 bool found = false;
3310 for (ie = node->indirect_calls; ie; ie = next_ie)
3312 tree target;
3313 bool speculative;
3315 next_ie = ie->next_callee;
3316 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3317 vNULL, aggvals, &speculative);
3318 if (target)
3320 bool agg_contents = ie->indirect_info->agg_contents;
3321 bool polymorphic = ie->indirect_info->polymorphic;
3322 int param_index = ie->indirect_info->param_index;
3323 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3324 speculative);
3325 found = true;
3327 if (cs && !agg_contents && !polymorphic)
3329 struct ipa_node_params *info = IPA_NODE_REF (node);
3330 int c = ipa_get_controlled_uses (info, param_index);
3331 if (c != IPA_UNDESCRIBED_USE)
3333 struct ipa_ref *to_del;
3335 c--;
3336 ipa_set_controlled_uses (info, param_index, c);
3337 if (dump_file && (dump_flags & TDF_DETAILS))
3338 fprintf (dump_file, " controlled uses count of param "
3339 "%i bumped down to %i\n", param_index, c);
3340 if (c == 0
3341 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3343 if (dump_file && (dump_flags & TDF_DETAILS))
3344 fprintf (dump_file, " and even removing its "
3345 "cloning-created reference\n");
3346 to_del->remove_reference ();
3352 /* Turning calls to direct calls will improve overall summary. */
3353 if (found)
3354 ipa_update_overall_fn_summary (node);
3357 /* Vector of pointers which for linked lists of clones of an original crgaph
3358 edge. */
3360 static vec<cgraph_edge *> next_edge_clone;
3361 static vec<cgraph_edge *> prev_edge_clone;
3363 static inline void
3364 grow_edge_clone_vectors (void)
3366 if (next_edge_clone.length ()
3367 <= (unsigned) symtab->edges_max_uid)
3368 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3369 if (prev_edge_clone.length ()
3370 <= (unsigned) symtab->edges_max_uid)
3371 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3374 /* Edge duplication hook to grow the appropriate linked list in
3375 next_edge_clone. */
3377 static void
3378 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
3379 void *)
3381 grow_edge_clone_vectors ();
3383 struct cgraph_edge *old_next = next_edge_clone[src->uid];
3384 if (old_next)
3385 prev_edge_clone[old_next->uid] = dst;
3386 prev_edge_clone[dst->uid] = src;
3388 next_edge_clone[dst->uid] = old_next;
3389 next_edge_clone[src->uid] = dst;
3392 /* Hook that is called by cgraph.c when an edge is removed. */
3394 static void
3395 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
3397 grow_edge_clone_vectors ();
3399 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
3400 struct cgraph_edge *next = next_edge_clone[cs->uid];
3401 if (prev)
3402 next_edge_clone[prev->uid] = next;
3403 if (next)
3404 prev_edge_clone[next->uid] = prev;
3407 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3408 parameter with the given INDEX. */
3410 static tree
3411 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3412 int index)
3414 struct ipa_agg_replacement_value *aggval;
3416 aggval = ipa_get_agg_replacements_for_node (node);
3417 while (aggval)
3419 if (aggval->offset == offset
3420 && aggval->index == index)
3421 return aggval->value;
3422 aggval = aggval->next;
3424 return NULL_TREE;
3427 /* Return true is NODE is DEST or its clone for all contexts. */
3429 static bool
3430 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3432 if (node == dest)
3433 return true;
3435 struct ipa_node_params *info = IPA_NODE_REF (node);
3436 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3439 /* Return true if edge CS does bring about the value described by SRC to node
3440 DEST or its clone for all contexts. */
3442 static bool
3443 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3444 cgraph_node *dest)
3446 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3447 enum availability availability;
3448 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3450 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3451 || availability <= AVAIL_INTERPOSABLE
3452 || caller_info->node_dead)
3453 return false;
3454 if (!src->val)
3455 return true;
3457 if (caller_info->ipcp_orig_node)
3459 tree t;
3460 if (src->offset == -1)
3461 t = caller_info->known_csts[src->index];
3462 else
3463 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3464 return (t != NULL_TREE
3465 && values_equal_for_ipcp_p (src->val->value, t));
3467 else
3469 struct ipcp_agg_lattice *aglat;
3470 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3471 src->index);
3472 if (src->offset == -1)
3473 return (plats->itself.is_single_const ()
3474 && values_equal_for_ipcp_p (src->val->value,
3475 plats->itself.values->value));
3476 else
3478 if (plats->aggs_bottom || plats->aggs_contain_variable)
3479 return false;
3480 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3481 if (aglat->offset == src->offset)
3482 return (aglat->is_single_const ()
3483 && values_equal_for_ipcp_p (src->val->value,
3484 aglat->values->value));
3486 return false;
3490 /* Return true if edge CS does bring about the value described by SRC to node
3491 DEST or its clone for all contexts. */
3493 static bool
3494 cgraph_edge_brings_value_p (cgraph_edge *cs,
3495 ipcp_value_source<ipa_polymorphic_call_context> *src,
3496 cgraph_node *dest)
3498 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3499 cgraph_node *real_dest = cs->callee->function_symbol ();
3501 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3502 || caller_info->node_dead)
3503 return false;
3504 if (!src->val)
3505 return true;
3507 if (caller_info->ipcp_orig_node)
3508 return (caller_info->known_contexts.length () > (unsigned) src->index)
3509 && values_equal_for_ipcp_p (src->val->value,
3510 caller_info->known_contexts[src->index]);
3512 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3513 src->index);
3514 return plats->ctxlat.is_single_const ()
3515 && values_equal_for_ipcp_p (src->val->value,
3516 plats->ctxlat.values->value);
3519 /* Get the next clone in the linked list of clones of an edge. */
3521 static inline struct cgraph_edge *
3522 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3524 return next_edge_clone[cs->uid];
3527 /* Given VAL that is intended for DEST, iterate over all its sources and if
3528 they still hold, add their edge frequency and their number into *FREQUENCY
3529 and *CALLER_COUNT respectively. */
3531 template <typename valtype>
3532 static bool
3533 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3534 int *freq_sum,
3535 profile_count *count_sum, int *caller_count)
3537 ipcp_value_source<valtype> *src;
3538 int freq = 0, count = 0;
3539 profile_count cnt = profile_count::zero ();
3540 bool hot = false;
3542 for (src = val->sources; src; src = src->next)
3544 struct cgraph_edge *cs = src->cs;
3545 while (cs)
3547 if (cgraph_edge_brings_value_p (cs, src, dest))
3549 count++;
3550 freq += cs->frequency;
3551 if (cs->count.initialized_p ())
3552 cnt += cs->count;
3553 hot |= cs->maybe_hot_p ();
3555 cs = get_next_cgraph_edge_clone (cs);
3559 *freq_sum = freq;
3560 *count_sum = cnt;
3561 *caller_count = count;
3562 return hot;
3565 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3566 is assumed their number is known and equal to CALLER_COUNT. */
3568 template <typename valtype>
3569 static vec<cgraph_edge *>
3570 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3571 int caller_count)
3573 ipcp_value_source<valtype> *src;
3574 vec<cgraph_edge *> ret;
3576 ret.create (caller_count);
3577 for (src = val->sources; src; src = src->next)
3579 struct cgraph_edge *cs = src->cs;
3580 while (cs)
3582 if (cgraph_edge_brings_value_p (cs, src, dest))
3583 ret.quick_push (cs);
3584 cs = get_next_cgraph_edge_clone (cs);
3588 return ret;
3591 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3592 Return it or NULL if for some reason it cannot be created. */
3594 static struct ipa_replace_map *
3595 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3597 struct ipa_replace_map *replace_map;
3600 replace_map = ggc_alloc<ipa_replace_map> ();
3601 if (dump_file)
3603 fprintf (dump_file, " replacing ");
3604 ipa_dump_param (dump_file, info, parm_num);
3606 fprintf (dump_file, " with const ");
3607 print_generic_expr (dump_file, value);
3608 fprintf (dump_file, "\n");
3610 replace_map->old_tree = NULL;
3611 replace_map->parm_num = parm_num;
3612 replace_map->new_tree = value;
3613 replace_map->replace_p = true;
3614 replace_map->ref_p = false;
3616 return replace_map;
3619 /* Dump new profiling counts */
3621 static void
3622 dump_profile_updates (struct cgraph_node *orig_node,
3623 struct cgraph_node *new_node)
3625 struct cgraph_edge *cs;
3627 fprintf (dump_file, " setting count of the specialized node to ");
3628 new_node->count.dump (dump_file);
3629 fprintf (dump_file, "\n");
3630 for (cs = new_node->callees; cs; cs = cs->next_callee)
3632 fprintf (dump_file, " edge to %s has count ",
3633 cs->callee->name ());
3634 cs->count.dump (dump_file);
3635 fprintf (dump_file, "\n");
3638 fprintf (dump_file, " setting count of the original node to ");
3639 orig_node->count.dump (dump_file);
3640 fprintf (dump_file, "\n");
3641 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3643 fprintf (dump_file, " edge to %s is left with ",
3644 cs->callee->name ());
3645 cs->count.dump (dump_file);
3646 fprintf (dump_file, "\n");
3650 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3651 their profile information to reflect this. */
3653 static void
3654 update_profiling_info (struct cgraph_node *orig_node,
3655 struct cgraph_node *new_node)
3657 struct cgraph_edge *cs;
3658 struct caller_statistics stats;
3659 profile_count new_sum, orig_sum;
3660 profile_count remainder, orig_node_count = orig_node->count;
3662 if (!(orig_node_count > profile_count::zero ()))
3663 return;
3665 init_caller_stats (&stats);
3666 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3667 false);
3668 orig_sum = stats.count_sum;
3669 init_caller_stats (&stats);
3670 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3671 false);
3672 new_sum = stats.count_sum;
3674 if (orig_node_count < orig_sum + new_sum)
3676 if (dump_file)
3678 fprintf (dump_file, " Problem: node %s has too low count ",
3679 orig_node->dump_name ());
3680 orig_node_count.dump (dump_file);
3681 fprintf (dump_file, "while the sum of incoming count is ");
3682 (orig_sum + new_sum).dump (dump_file);
3683 fprintf (dump_file, "\n");
3686 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
3687 if (dump_file)
3689 fprintf (dump_file, " proceeding by pretending it was ");
3690 orig_node_count.dump (dump_file);
3691 fprintf (dump_file, "\n");
3695 new_node->count = new_sum;
3696 remainder = orig_node_count - new_sum;
3697 orig_node->count = remainder;
3699 for (cs = new_node->callees; cs; cs = cs->next_callee)
3700 /* FIXME: why we care about non-zero frequency here? */
3701 if (cs->frequency)
3702 cs->count = cs->count.apply_scale (new_sum, orig_node_count);
3703 else
3704 cs->count = profile_count::zero ();
3706 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3707 cs->count = cs->count.apply_scale (remainder, orig_node_count);
3709 if (dump_file)
3710 dump_profile_updates (orig_node, new_node);
3713 /* Update the respective profile of specialized NEW_NODE and the original
3714 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3715 have been redirected to the specialized version. */
3717 static void
3718 update_specialized_profile (struct cgraph_node *new_node,
3719 struct cgraph_node *orig_node,
3720 profile_count redirected_sum)
3722 struct cgraph_edge *cs;
3723 profile_count new_node_count, orig_node_count = orig_node->count;
3725 if (dump_file)
3727 fprintf (dump_file, " the sum of counts of redirected edges is ");
3728 redirected_sum.dump (dump_file);
3729 fprintf (dump_file, "\n");
3731 if (!(orig_node_count > profile_count::zero ()))
3732 return;
3734 gcc_assert (orig_node_count >= redirected_sum);
3736 new_node_count = new_node->count;
3737 new_node->count += redirected_sum;
3738 orig_node->count -= redirected_sum;
3740 for (cs = new_node->callees; cs; cs = cs->next_callee)
3741 if (cs->frequency)
3742 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
3743 else
3744 cs->count = profile_count::zero ();
3746 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3748 profile_count dec = cs->count.apply_scale (redirected_sum,
3749 orig_node_count);
3750 cs->count -= dec;
3753 if (dump_file)
3754 dump_profile_updates (orig_node, new_node);
3757 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3758 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3759 redirect all edges in CALLERS to it. */
3761 static struct cgraph_node *
3762 create_specialized_node (struct cgraph_node *node,
3763 vec<tree> known_csts,
3764 vec<ipa_polymorphic_call_context> known_contexts,
3765 struct ipa_agg_replacement_value *aggvals,
3766 vec<cgraph_edge *> callers)
3768 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3769 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3770 struct ipa_agg_replacement_value *av;
3771 struct cgraph_node *new_node;
3772 int i, count = ipa_get_param_count (info);
3773 bitmap args_to_skip;
3775 gcc_assert (!info->ipcp_orig_node);
3777 if (node->local.can_change_signature)
3779 args_to_skip = BITMAP_GGC_ALLOC ();
3780 for (i = 0; i < count; i++)
3782 tree t = known_csts[i];
3784 if (t || !ipa_is_param_used (info, i))
3785 bitmap_set_bit (args_to_skip, i);
3788 else
3790 args_to_skip = NULL;
3791 if (dump_file && (dump_flags & TDF_DETAILS))
3792 fprintf (dump_file, " cannot change function signature\n");
3795 for (i = 0; i < count; i++)
3797 tree t = known_csts[i];
3798 if (t)
3800 struct ipa_replace_map *replace_map;
3802 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3803 replace_map = get_replacement_map (info, t, i);
3804 if (replace_map)
3805 vec_safe_push (replace_trees, replace_map);
3809 new_node = node->create_virtual_clone (callers, replace_trees,
3810 args_to_skip, "constprop");
3811 ipa_set_node_agg_value_chain (new_node, aggvals);
3812 for (av = aggvals; av; av = av->next)
3813 new_node->maybe_create_reference (av->value, NULL);
3815 if (dump_file && (dump_flags & TDF_DETAILS))
3817 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
3818 if (known_contexts.exists ())
3820 for (i = 0; i < count; i++)
3821 if (!known_contexts[i].useless_p ())
3823 fprintf (dump_file, " known ctx %i is ", i);
3824 known_contexts[i].dump (dump_file);
3827 if (aggvals)
3828 ipa_dump_agg_replacement_values (dump_file, aggvals);
3830 ipa_check_create_node_params ();
3831 update_profiling_info (node, new_node);
3832 new_info = IPA_NODE_REF (new_node);
3833 new_info->ipcp_orig_node = node;
3834 new_info->known_csts = known_csts;
3835 new_info->known_contexts = known_contexts;
3837 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3839 callers.release ();
3840 return new_node;
3843 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3844 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3846 static void
3847 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3848 vec<tree> known_csts,
3849 vec<cgraph_edge *> callers)
3851 struct ipa_node_params *info = IPA_NODE_REF (node);
3852 int i, count = ipa_get_param_count (info);
3854 for (i = 0; i < count; i++)
3856 struct cgraph_edge *cs;
3857 tree newval = NULL_TREE;
3858 int j;
3859 bool first = true;
3861 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3862 continue;
3864 FOR_EACH_VEC_ELT (callers, j, cs)
3866 struct ipa_jump_func *jump_func;
3867 tree t;
3869 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3870 || (i == 0
3871 && call_passes_through_thunk_p (cs))
3872 || (!cs->callee->instrumentation_clone
3873 && cs->callee->function_symbol ()->instrumentation_clone))
3875 newval = NULL_TREE;
3876 break;
3878 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3879 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3880 if (!t
3881 || (newval
3882 && !values_equal_for_ipcp_p (t, newval))
3883 || (!first && !newval))
3885 newval = NULL_TREE;
3886 break;
3888 else
3889 newval = t;
3890 first = false;
3893 if (newval)
3895 if (dump_file && (dump_flags & TDF_DETAILS))
3897 fprintf (dump_file, " adding an extra known scalar value ");
3898 print_ipcp_constant_value (dump_file, newval);
3899 fprintf (dump_file, " for ");
3900 ipa_dump_param (dump_file, info, i);
3901 fprintf (dump_file, "\n");
3904 known_csts[i] = newval;
3909 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3910 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3911 CALLERS. */
3913 static void
3914 find_more_contexts_for_caller_subset (cgraph_node *node,
3915 vec<ipa_polymorphic_call_context>
3916 *known_contexts,
3917 vec<cgraph_edge *> callers)
3919 ipa_node_params *info = IPA_NODE_REF (node);
3920 int i, count = ipa_get_param_count (info);
3922 for (i = 0; i < count; i++)
3924 cgraph_edge *cs;
3926 if (ipa_get_poly_ctx_lat (info, i)->bottom
3927 || (known_contexts->exists ()
3928 && !(*known_contexts)[i].useless_p ()))
3929 continue;
3931 ipa_polymorphic_call_context newval;
3932 bool first = true;
3933 int j;
3935 FOR_EACH_VEC_ELT (callers, j, cs)
3937 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3938 return;
3939 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3941 ipa_polymorphic_call_context ctx;
3942 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3943 jfunc);
3944 if (first)
3946 newval = ctx;
3947 first = false;
3949 else
3950 newval.meet_with (ctx);
3951 if (newval.useless_p ())
3952 break;
3955 if (!newval.useless_p ())
3957 if (dump_file && (dump_flags & TDF_DETAILS))
3959 fprintf (dump_file, " adding an extra known polymorphic "
3960 "context ");
3961 print_ipcp_constant_value (dump_file, newval);
3962 fprintf (dump_file, " for ");
3963 ipa_dump_param (dump_file, info, i);
3964 fprintf (dump_file, "\n");
3967 if (!known_contexts->exists ())
3968 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3969 (*known_contexts)[i] = newval;
3975 /* Go through PLATS and create a vector of values consisting of values and
3976 offsets (minus OFFSET) of lattices that contain only a single value. */
3978 static vec<ipa_agg_jf_item>
3979 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3981 vec<ipa_agg_jf_item> res = vNULL;
3983 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3984 return vNULL;
3986 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3987 if (aglat->is_single_const ())
3989 struct ipa_agg_jf_item ti;
3990 ti.offset = aglat->offset - offset;
3991 ti.value = aglat->values->value;
3992 res.safe_push (ti);
3994 return res;
3997 /* Intersect all values in INTER with single value lattices in PLATS (while
3998 subtracting OFFSET). */
4000 static void
4001 intersect_with_plats (struct ipcp_param_lattices *plats,
4002 vec<ipa_agg_jf_item> *inter,
4003 HOST_WIDE_INT offset)
4005 struct ipcp_agg_lattice *aglat;
4006 struct ipa_agg_jf_item *item;
4007 int k;
4009 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4011 inter->release ();
4012 return;
4015 aglat = plats->aggs;
4016 FOR_EACH_VEC_ELT (*inter, k, item)
4018 bool found = false;
4019 if (!item->value)
4020 continue;
4021 while (aglat)
4023 if (aglat->offset - offset > item->offset)
4024 break;
4025 if (aglat->offset - offset == item->offset)
4027 gcc_checking_assert (item->value);
4028 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
4029 found = true;
4030 break;
4032 aglat = aglat->next;
4034 if (!found)
4035 item->value = NULL_TREE;
4039 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4040 vector result while subtracting OFFSET from the individual value offsets. */
4042 static vec<ipa_agg_jf_item>
4043 agg_replacements_to_vector (struct cgraph_node *node, int index,
4044 HOST_WIDE_INT offset)
4046 struct ipa_agg_replacement_value *av;
4047 vec<ipa_agg_jf_item> res = vNULL;
4049 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4050 if (av->index == index
4051 && (av->offset - offset) >= 0)
4053 struct ipa_agg_jf_item item;
4054 gcc_checking_assert (av->value);
4055 item.offset = av->offset - offset;
4056 item.value = av->value;
4057 res.safe_push (item);
4060 return res;
4063 /* Intersect all values in INTER with those that we have already scheduled to
4064 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4065 (while subtracting OFFSET). */
4067 static void
4068 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4069 vec<ipa_agg_jf_item> *inter,
4070 HOST_WIDE_INT offset)
4072 struct ipa_agg_replacement_value *srcvals;
4073 struct ipa_agg_jf_item *item;
4074 int i;
4076 srcvals = ipa_get_agg_replacements_for_node (node);
4077 if (!srcvals)
4079 inter->release ();
4080 return;
4083 FOR_EACH_VEC_ELT (*inter, i, item)
4085 struct ipa_agg_replacement_value *av;
4086 bool found = false;
4087 if (!item->value)
4088 continue;
4089 for (av = srcvals; av; av = av->next)
4091 gcc_checking_assert (av->value);
4092 if (av->index == index
4093 && av->offset - offset == item->offset)
4095 if (values_equal_for_ipcp_p (item->value, av->value))
4096 found = true;
4097 break;
4100 if (!found)
4101 item->value = NULL_TREE;
4105 /* Intersect values in INTER with aggregate values that come along edge CS to
4106 parameter number INDEX and return it. If INTER does not actually exist yet,
4107 copy all incoming values to it. If we determine we ended up with no values
4108 whatsoever, return a released vector. */
4110 static vec<ipa_agg_jf_item>
4111 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4112 vec<ipa_agg_jf_item> inter)
4114 struct ipa_jump_func *jfunc;
4115 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4116 if (jfunc->type == IPA_JF_PASS_THROUGH
4117 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4119 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4120 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4122 if (caller_info->ipcp_orig_node)
4124 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4125 struct ipcp_param_lattices *orig_plats;
4126 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4127 src_idx);
4128 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4130 if (!inter.exists ())
4131 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4132 else
4133 intersect_with_agg_replacements (cs->caller, src_idx,
4134 &inter, 0);
4136 else
4138 inter.release ();
4139 return vNULL;
4142 else
4144 struct ipcp_param_lattices *src_plats;
4145 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4146 if (agg_pass_through_permissible_p (src_plats, jfunc))
4148 /* Currently we do not produce clobber aggregate jump
4149 functions, adjust when we do. */
4150 gcc_checking_assert (!jfunc->agg.items);
4151 if (!inter.exists ())
4152 inter = copy_plats_to_inter (src_plats, 0);
4153 else
4154 intersect_with_plats (src_plats, &inter, 0);
4156 else
4158 inter.release ();
4159 return vNULL;
4163 else if (jfunc->type == IPA_JF_ANCESTOR
4164 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4166 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4167 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4168 struct ipcp_param_lattices *src_plats;
4169 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4171 if (caller_info->ipcp_orig_node)
4173 if (!inter.exists ())
4174 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4175 else
4176 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4177 delta);
4179 else
4181 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
4182 /* Currently we do not produce clobber aggregate jump
4183 functions, adjust when we do. */
4184 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4185 if (!inter.exists ())
4186 inter = copy_plats_to_inter (src_plats, delta);
4187 else
4188 intersect_with_plats (src_plats, &inter, delta);
4191 else if (jfunc->agg.items)
4193 struct ipa_agg_jf_item *item;
4194 int k;
4196 if (!inter.exists ())
4197 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4198 inter.safe_push ((*jfunc->agg.items)[i]);
4199 else
4200 FOR_EACH_VEC_ELT (inter, k, item)
4202 int l = 0;
4203 bool found = false;;
4205 if (!item->value)
4206 continue;
4208 while ((unsigned) l < jfunc->agg.items->length ())
4210 struct ipa_agg_jf_item *ti;
4211 ti = &(*jfunc->agg.items)[l];
4212 if (ti->offset > item->offset)
4213 break;
4214 if (ti->offset == item->offset)
4216 gcc_checking_assert (ti->value);
4217 if (values_equal_for_ipcp_p (item->value,
4218 ti->value))
4219 found = true;
4220 break;
4222 l++;
4224 if (!found)
4225 item->value = NULL;
4228 else
4230 inter.release ();
4231 return vec<ipa_agg_jf_item>();
4233 return inter;
4236 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4237 from all of them. */
4239 static struct ipa_agg_replacement_value *
4240 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4241 vec<cgraph_edge *> callers)
4243 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4244 struct ipa_agg_replacement_value *res;
4245 struct ipa_agg_replacement_value **tail = &res;
4246 struct cgraph_edge *cs;
4247 int i, j, count = ipa_get_param_count (dest_info);
4249 FOR_EACH_VEC_ELT (callers, j, cs)
4251 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4252 if (c < count)
4253 count = c;
4256 for (i = 0; i < count; i++)
4258 struct cgraph_edge *cs;
4259 vec<ipa_agg_jf_item> inter = vNULL;
4260 struct ipa_agg_jf_item *item;
4261 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4262 int j;
4264 /* Among other things, the following check should deal with all by_ref
4265 mismatches. */
4266 if (plats->aggs_bottom)
4267 continue;
4269 FOR_EACH_VEC_ELT (callers, j, cs)
4271 inter = intersect_aggregates_with_edge (cs, i, inter);
4273 if (!inter.exists ())
4274 goto next_param;
4277 FOR_EACH_VEC_ELT (inter, j, item)
4279 struct ipa_agg_replacement_value *v;
4281 if (!item->value)
4282 continue;
4284 v = ggc_alloc<ipa_agg_replacement_value> ();
4285 v->index = i;
4286 v->offset = item->offset;
4287 v->value = item->value;
4288 v->by_ref = plats->aggs_by_ref;
4289 *tail = v;
4290 tail = &v->next;
4293 next_param:
4294 if (inter.exists ())
4295 inter.release ();
4297 *tail = NULL;
4298 return res;
4301 /* Turn KNOWN_AGGS into a list of aggregate replacement values. */
4303 static struct ipa_agg_replacement_value *
4304 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
4306 struct ipa_agg_replacement_value *res;
4307 struct ipa_agg_replacement_value **tail = &res;
4308 struct ipa_agg_jump_function *aggjf;
4309 struct ipa_agg_jf_item *item;
4310 int i, j;
4312 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
4313 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
4315 struct ipa_agg_replacement_value *v;
4316 v = ggc_alloc<ipa_agg_replacement_value> ();
4317 v->index = i;
4318 v->offset = item->offset;
4319 v->value = item->value;
4320 v->by_ref = aggjf->by_ref;
4321 *tail = v;
4322 tail = &v->next;
4324 *tail = NULL;
4325 return res;
4328 /* Determine whether CS also brings all scalar values that the NODE is
4329 specialized for. */
4331 static bool
4332 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4333 struct cgraph_node *node)
4335 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4336 int count = ipa_get_param_count (dest_info);
4337 struct ipa_node_params *caller_info;
4338 struct ipa_edge_args *args;
4339 int i;
4341 caller_info = IPA_NODE_REF (cs->caller);
4342 args = IPA_EDGE_REF (cs);
4343 for (i = 0; i < count; i++)
4345 struct ipa_jump_func *jump_func;
4346 tree val, t;
4348 val = dest_info->known_csts[i];
4349 if (!val)
4350 continue;
4352 if (i >= ipa_get_cs_argument_count (args))
4353 return false;
4354 jump_func = ipa_get_ith_jump_func (args, i);
4355 t = ipa_value_from_jfunc (caller_info, jump_func);
4356 if (!t || !values_equal_for_ipcp_p (val, t))
4357 return false;
4359 return true;
4362 /* Determine whether CS also brings all aggregate values that NODE is
4363 specialized for. */
4364 static bool
4365 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4366 struct cgraph_node *node)
4368 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4369 struct ipa_node_params *orig_node_info;
4370 struct ipa_agg_replacement_value *aggval;
4371 int i, ec, count;
4373 aggval = ipa_get_agg_replacements_for_node (node);
4374 if (!aggval)
4375 return true;
4377 count = ipa_get_param_count (IPA_NODE_REF (node));
4378 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4379 if (ec < count)
4380 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4381 if (aggval->index >= ec)
4382 return false;
4384 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4385 if (orig_caller_info->ipcp_orig_node)
4386 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4388 for (i = 0; i < count; i++)
4390 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4391 struct ipcp_param_lattices *plats;
4392 bool interesting = false;
4393 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4394 if (aggval->index == i)
4396 interesting = true;
4397 break;
4399 if (!interesting)
4400 continue;
4402 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4403 if (plats->aggs_bottom)
4404 return false;
4406 values = intersect_aggregates_with_edge (cs, i, values);
4407 if (!values.exists ())
4408 return false;
4410 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4411 if (aggval->index == i)
4413 struct ipa_agg_jf_item *item;
4414 int j;
4415 bool found = false;
4416 FOR_EACH_VEC_ELT (values, j, item)
4417 if (item->value
4418 && item->offset == av->offset
4419 && values_equal_for_ipcp_p (item->value, av->value))
4421 found = true;
4422 break;
4424 if (!found)
4426 values.release ();
4427 return false;
4431 return true;
4434 /* Given an original NODE and a VAL for which we have already created a
4435 specialized clone, look whether there are incoming edges that still lead
4436 into the old node but now also bring the requested value and also conform to
4437 all other criteria such that they can be redirected the special node.
4438 This function can therefore redirect the final edge in a SCC. */
4440 template <typename valtype>
4441 static void
4442 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4444 ipcp_value_source<valtype> *src;
4445 profile_count redirected_sum = profile_count::zero ();
4447 for (src = val->sources; src; src = src->next)
4449 struct cgraph_edge *cs = src->cs;
4450 while (cs)
4452 if (cgraph_edge_brings_value_p (cs, src, node)
4453 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4454 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4456 if (dump_file)
4457 fprintf (dump_file, " - adding an extra caller %s of %s\n",
4458 cs->caller->dump_name (),
4459 val->spec_node->dump_name ());
4461 cs->redirect_callee_duplicating_thunks (val->spec_node);
4462 val->spec_node->expand_all_artificial_thunks ();
4463 if (cs->count.initialized_p ())
4464 redirected_sum = redirected_sum + cs->count;
4466 cs = get_next_cgraph_edge_clone (cs);
4470 if (redirected_sum > profile_count::zero ())
4471 update_specialized_profile (val->spec_node, node, redirected_sum);
4474 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4476 static bool
4477 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4479 ipa_polymorphic_call_context *ctx;
4480 int i;
4482 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4483 if (!ctx->useless_p ())
4484 return true;
4485 return false;
4488 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4490 static vec<ipa_polymorphic_call_context>
4491 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4493 if (known_contexts_useful_p (known_contexts))
4494 return known_contexts.copy ();
4495 else
4496 return vNULL;
4499 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4500 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4502 static void
4503 modify_known_vectors_with_val (vec<tree> *known_csts,
4504 vec<ipa_polymorphic_call_context> *known_contexts,
4505 ipcp_value<tree> *val,
4506 int index)
4508 *known_csts = known_csts->copy ();
4509 *known_contexts = copy_useful_known_contexts (*known_contexts);
4510 (*known_csts)[index] = val->value;
4513 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4514 copy according to VAL and INDEX. */
4516 static void
4517 modify_known_vectors_with_val (vec<tree> *known_csts,
4518 vec<ipa_polymorphic_call_context> *known_contexts,
4519 ipcp_value<ipa_polymorphic_call_context> *val,
4520 int index)
4522 *known_csts = known_csts->copy ();
4523 *known_contexts = known_contexts->copy ();
4524 (*known_contexts)[index] = val->value;
4527 /* Return true if OFFSET indicates this was not an aggregate value or there is
4528 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4529 AGGVALS list. */
4531 DEBUG_FUNCTION bool
4532 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4533 int index, HOST_WIDE_INT offset, tree value)
4535 if (offset == -1)
4536 return true;
4538 while (aggvals)
4540 if (aggvals->index == index
4541 && aggvals->offset == offset
4542 && values_equal_for_ipcp_p (aggvals->value, value))
4543 return true;
4544 aggvals = aggvals->next;
4546 return false;
4549 /* Return true if offset is minus one because source of a polymorphic contect
4550 cannot be an aggregate value. */
4552 DEBUG_FUNCTION bool
4553 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4554 int , HOST_WIDE_INT offset,
4555 ipa_polymorphic_call_context)
4557 return offset == -1;
4560 /* Decide wheter to create a special version of NODE for value VAL of parameter
4561 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4562 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4563 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4565 template <typename valtype>
4566 static bool
4567 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4568 ipcp_value<valtype> *val, vec<tree> known_csts,
4569 vec<ipa_polymorphic_call_context> known_contexts)
4571 struct ipa_agg_replacement_value *aggvals;
4572 int freq_sum, caller_count;
4573 profile_count count_sum;
4574 vec<cgraph_edge *> callers;
4576 if (val->spec_node)
4578 perhaps_add_new_callers (node, val);
4579 return false;
4581 else if (val->local_size_cost + overall_size > max_new_size)
4583 if (dump_file && (dump_flags & TDF_DETAILS))
4584 fprintf (dump_file, " Ignoring candidate value because "
4585 "max_new_size would be reached with %li.\n",
4586 val->local_size_cost + overall_size);
4587 return false;
4589 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4590 &caller_count))
4591 return false;
4593 if (dump_file && (dump_flags & TDF_DETAILS))
4595 fprintf (dump_file, " - considering value ");
4596 print_ipcp_constant_value (dump_file, val->value);
4597 fprintf (dump_file, " for ");
4598 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4599 if (offset != -1)
4600 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4601 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4604 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4605 freq_sum, count_sum,
4606 val->local_size_cost)
4607 && !good_cloning_opportunity_p (node,
4608 val->local_time_benefit
4609 + val->prop_time_benefit,
4610 freq_sum, count_sum,
4611 val->local_size_cost
4612 + val->prop_size_cost))
4613 return false;
4615 if (dump_file)
4616 fprintf (dump_file, " Creating a specialized node of %s.\n",
4617 node->dump_name ());
4619 callers = gather_edges_for_value (val, node, caller_count);
4620 if (offset == -1)
4621 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4622 else
4624 known_csts = known_csts.copy ();
4625 known_contexts = copy_useful_known_contexts (known_contexts);
4627 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4628 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4629 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4630 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4631 offset, val->value));
4632 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4633 aggvals, callers);
4634 overall_size += val->local_size_cost;
4636 /* TODO: If for some lattice there is only one other known value
4637 left, make a special node for it too. */
4639 return true;
4642 /* Decide whether and what specialized clones of NODE should be created. */
4644 static bool
4645 decide_whether_version_node (struct cgraph_node *node)
4647 struct ipa_node_params *info = IPA_NODE_REF (node);
4648 int i, count = ipa_get_param_count (info);
4649 vec<tree> known_csts;
4650 vec<ipa_polymorphic_call_context> known_contexts;
4651 vec<ipa_agg_jump_function> known_aggs = vNULL;
4652 bool ret = false;
4654 if (count == 0)
4655 return false;
4657 if (dump_file && (dump_flags & TDF_DETAILS))
4658 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
4659 node->dump_name ());
4661 gather_context_independent_values (info, &known_csts, &known_contexts,
4662 info->do_clone_for_all_contexts ? &known_aggs
4663 : NULL, NULL);
4665 for (i = 0; i < count;i++)
4667 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4668 ipcp_lattice<tree> *lat = &plats->itself;
4669 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4671 if (!lat->bottom
4672 && !known_csts[i])
4674 ipcp_value<tree> *val;
4675 for (val = lat->values; val; val = val->next)
4676 ret |= decide_about_value (node, i, -1, val, known_csts,
4677 known_contexts);
4680 if (!plats->aggs_bottom)
4682 struct ipcp_agg_lattice *aglat;
4683 ipcp_value<tree> *val;
4684 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4685 if (!aglat->bottom && aglat->values
4686 /* If the following is false, the one value is in
4687 known_aggs. */
4688 && (plats->aggs_contain_variable
4689 || !aglat->is_single_const ()))
4690 for (val = aglat->values; val; val = val->next)
4691 ret |= decide_about_value (node, i, aglat->offset, val,
4692 known_csts, known_contexts);
4695 if (!ctxlat->bottom
4696 && known_contexts[i].useless_p ())
4698 ipcp_value<ipa_polymorphic_call_context> *val;
4699 for (val = ctxlat->values; val; val = val->next)
4700 ret |= decide_about_value (node, i, -1, val, known_csts,
4701 known_contexts);
4704 info = IPA_NODE_REF (node);
4707 if (info->do_clone_for_all_contexts)
4709 struct cgraph_node *clone;
4710 vec<cgraph_edge *> callers;
4712 if (dump_file)
4713 fprintf (dump_file, " - Creating a specialized node of %s "
4714 "for all known contexts.\n", node->dump_name ());
4716 callers = node->collect_callers ();
4718 if (!known_contexts_useful_p (known_contexts))
4720 known_contexts.release ();
4721 known_contexts = vNULL;
4723 clone = create_specialized_node (node, known_csts, known_contexts,
4724 known_aggs_to_agg_replacement_list (known_aggs),
4725 callers);
4726 info = IPA_NODE_REF (node);
4727 info->do_clone_for_all_contexts = false;
4728 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4729 for (i = 0; i < count; i++)
4730 vec_free (known_aggs[i].items);
4731 known_aggs.release ();
4732 ret = true;
4734 else
4736 known_csts.release ();
4737 known_contexts.release ();
4740 return ret;
4743 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4745 static void
4746 spread_undeadness (struct cgraph_node *node)
4748 struct cgraph_edge *cs;
4750 for (cs = node->callees; cs; cs = cs->next_callee)
4751 if (ipa_edge_within_scc (cs))
4753 struct cgraph_node *callee;
4754 struct ipa_node_params *info;
4756 callee = cs->callee->function_symbol (NULL);
4757 info = IPA_NODE_REF (callee);
4759 if (info->node_dead)
4761 info->node_dead = 0;
4762 spread_undeadness (callee);
4767 /* Return true if NODE has a caller from outside of its SCC that is not
4768 dead. Worker callback for cgraph_for_node_and_aliases. */
4770 static bool
4771 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4772 void *data ATTRIBUTE_UNUSED)
4774 struct cgraph_edge *cs;
4776 for (cs = node->callers; cs; cs = cs->next_caller)
4777 if (cs->caller->thunk.thunk_p
4778 && cs->caller->call_for_symbol_thunks_and_aliases
4779 (has_undead_caller_from_outside_scc_p, NULL, true))
4780 return true;
4781 else if (!ipa_edge_within_scc (cs)
4782 && !IPA_NODE_REF (cs->caller)->node_dead)
4783 return true;
4784 return false;
4788 /* Identify nodes within the same SCC as NODE which are no longer needed
4789 because of new clones and will be removed as unreachable. */
4791 static void
4792 identify_dead_nodes (struct cgraph_node *node)
4794 struct cgraph_node *v;
4795 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4796 if (v->local.local
4797 && !v->call_for_symbol_thunks_and_aliases
4798 (has_undead_caller_from_outside_scc_p, NULL, true))
4799 IPA_NODE_REF (v)->node_dead = 1;
4801 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4802 if (!IPA_NODE_REF (v)->node_dead)
4803 spread_undeadness (v);
4805 if (dump_file && (dump_flags & TDF_DETAILS))
4807 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4808 if (IPA_NODE_REF (v)->node_dead)
4809 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
4813 /* The decision stage. Iterate over the topological order of call graph nodes
4814 TOPO and make specialized clones if deemed beneficial. */
4816 static void
4817 ipcp_decision_stage (struct ipa_topo_info *topo)
4819 int i;
4821 if (dump_file)
4822 fprintf (dump_file, "\nIPA decision stage:\n\n");
4824 for (i = topo->nnodes - 1; i >= 0; i--)
4826 struct cgraph_node *node = topo->order[i];
4827 bool change = false, iterate = true;
4829 while (iterate)
4831 struct cgraph_node *v;
4832 iterate = false;
4833 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4834 if (v->has_gimple_body_p ()
4835 && ipcp_versionable_function_p (v))
4836 iterate |= decide_whether_version_node (v);
4838 change |= iterate;
4840 if (change)
4841 identify_dead_nodes (node);
4845 /* Look up all the bits information that we have discovered and copy it over
4846 to the transformation summary. */
4848 static void
4849 ipcp_store_bits_results (void)
4851 cgraph_node *node;
4853 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4855 ipa_node_params *info = IPA_NODE_REF (node);
4856 bool dumped_sth = false;
4857 bool found_useful_result = false;
4859 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4861 if (dump_file)
4862 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4863 "; -fipa-bit-cp: disabled.\n",
4864 node->name ());
4865 continue;
4868 if (info->ipcp_orig_node)
4869 info = IPA_NODE_REF (info->ipcp_orig_node);
4871 unsigned count = ipa_get_param_count (info);
4872 for (unsigned i = 0; i < count; i++)
4874 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4875 if (plats->bits_lattice.constant_p ())
4877 found_useful_result = true;
4878 break;
4882 if (!found_useful_result)
4883 continue;
4885 ipcp_grow_transformations_if_necessary ();
4886 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4887 vec_safe_reserve_exact (ts->bits, count);
4889 for (unsigned i = 0; i < count; i++)
4891 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4892 ipa_bits *jfbits;
4894 if (plats->bits_lattice.constant_p ())
4895 jfbits
4896 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
4897 plats->bits_lattice.get_mask ());
4898 else
4899 jfbits = NULL;
4901 ts->bits->quick_push (jfbits);
4902 if (!dump_file || !jfbits)
4903 continue;
4904 if (!dumped_sth)
4906 fprintf (dump_file, "Propagated bits info for function %s:\n",
4907 node->dump_name ());
4908 dumped_sth = true;
4910 fprintf (dump_file, " param %i: value = ", i);
4911 print_hex (jfbits->value, dump_file);
4912 fprintf (dump_file, ", mask = ");
4913 print_hex (jfbits->mask, dump_file);
4914 fprintf (dump_file, "\n");
4919 /* Look up all VR information that we have discovered and copy it over
4920 to the transformation summary. */
4922 static void
4923 ipcp_store_vr_results (void)
4925 cgraph_node *node;
4927 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4929 ipa_node_params *info = IPA_NODE_REF (node);
4930 bool found_useful_result = false;
4932 if (!opt_for_fn (node->decl, flag_ipa_vrp))
4934 if (dump_file)
4935 fprintf (dump_file, "Not considering %s for VR discovery "
4936 "and propagate; -fipa-ipa-vrp: disabled.\n",
4937 node->name ());
4938 continue;
4941 if (info->ipcp_orig_node)
4942 info = IPA_NODE_REF (info->ipcp_orig_node);
4944 unsigned count = ipa_get_param_count (info);
4945 for (unsigned i = 0; i < count; i++)
4947 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4948 if (!plats->m_value_range.bottom_p ()
4949 && !plats->m_value_range.top_p ())
4951 found_useful_result = true;
4952 break;
4955 if (!found_useful_result)
4956 continue;
4958 ipcp_grow_transformations_if_necessary ();
4959 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4960 vec_safe_reserve_exact (ts->m_vr, count);
4962 for (unsigned i = 0; i < count; i++)
4964 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4965 ipa_vr vr;
4967 if (!plats->m_value_range.bottom_p ()
4968 && !plats->m_value_range.top_p ())
4970 vr.known = true;
4971 vr.type = plats->m_value_range.m_vr.type;
4972 vr.min = plats->m_value_range.m_vr.min;
4973 vr.max = plats->m_value_range.m_vr.max;
4975 else
4977 vr.known = false;
4978 vr.type = VR_VARYING;
4979 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
4981 ts->m_vr->quick_push (vr);
4986 /* The IPCP driver. */
4988 static unsigned int
4989 ipcp_driver (void)
4991 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4992 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4993 struct ipa_topo_info topo;
4995 ipa_check_create_node_params ();
4996 ipa_check_create_edge_args ();
4997 grow_edge_clone_vectors ();
4998 edge_duplication_hook_holder
4999 = symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
5000 edge_removal_hook_holder
5001 = symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
5003 if (dump_file)
5005 fprintf (dump_file, "\nIPA structures before propagation:\n");
5006 if (dump_flags & TDF_DETAILS)
5007 ipa_print_all_params (dump_file);
5008 ipa_print_all_jump_functions (dump_file);
5011 /* Topological sort. */
5012 build_toporder_info (&topo);
5013 /* Do the interprocedural propagation. */
5014 ipcp_propagate_stage (&topo);
5015 /* Decide what constant propagation and cloning should be performed. */
5016 ipcp_decision_stage (&topo);
5017 /* Store results of bits propagation. */
5018 ipcp_store_bits_results ();
5019 /* Store results of value range propagation. */
5020 ipcp_store_vr_results ();
5022 /* Free all IPCP structures. */
5023 free_toporder_info (&topo);
5024 next_edge_clone.release ();
5025 prev_edge_clone.release ();
5026 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
5027 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
5028 ipa_free_all_structures_after_ipa_cp ();
5029 if (dump_file)
5030 fprintf (dump_file, "\nIPA constant propagation end\n");
5031 return 0;
5034 /* Initialization and computation of IPCP data structures. This is the initial
5035 intraprocedural analysis of functions, which gathers information to be
5036 propagated later on. */
5038 static void
5039 ipcp_generate_summary (void)
5041 struct cgraph_node *node;
5043 if (dump_file)
5044 fprintf (dump_file, "\nIPA constant propagation start:\n");
5045 ipa_register_cgraph_hooks ();
5047 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5048 ipa_analyze_node (node);
5051 /* Write ipcp summary for nodes in SET. */
5053 static void
5054 ipcp_write_summary (void)
5056 ipa_prop_write_jump_functions ();
5059 /* Read ipcp summary. */
5061 static void
5062 ipcp_read_summary (void)
5064 ipa_prop_read_jump_functions ();
5067 namespace {
5069 const pass_data pass_data_ipa_cp =
5071 IPA_PASS, /* type */
5072 "cp", /* name */
5073 OPTGROUP_NONE, /* optinfo_flags */
5074 TV_IPA_CONSTANT_PROP, /* tv_id */
5075 0, /* properties_required */
5076 0, /* properties_provided */
5077 0, /* properties_destroyed */
5078 0, /* todo_flags_start */
5079 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5082 class pass_ipa_cp : public ipa_opt_pass_d
5084 public:
5085 pass_ipa_cp (gcc::context *ctxt)
5086 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5087 ipcp_generate_summary, /* generate_summary */
5088 ipcp_write_summary, /* write_summary */
5089 ipcp_read_summary, /* read_summary */
5090 ipcp_write_transformation_summaries, /*
5091 write_optimization_summary */
5092 ipcp_read_transformation_summaries, /*
5093 read_optimization_summary */
5094 NULL, /* stmt_fixup */
5095 0, /* function_transform_todo_flags_start */
5096 ipcp_transform_function, /* function_transform */
5097 NULL) /* variable_transform */
5100 /* opt_pass methods: */
5101 virtual bool gate (function *)
5103 /* FIXME: We should remove the optimize check after we ensure we never run
5104 IPA passes when not optimizing. */
5105 return (flag_ipa_cp && optimize) || in_lto_p;
5108 virtual unsigned int execute (function *) { return ipcp_driver (); }
5110 }; // class pass_ipa_cp
5112 } // anon namespace
5114 ipa_opt_pass_d *
5115 make_pass_ipa_cp (gcc::context *ctxt)
5117 return new pass_ipa_cp (ctxt);
5120 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5121 within the same process. For use by toplev::finalize. */
5123 void
5124 ipa_cp_c_finalize (void)
5126 max_count = profile_count::zero ();
5127 overall_size = 0;
5128 max_new_size = 0;