2016-11-10 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / ipa-cp.c
blob79e621a174af8271cf917eb015f107f30832800a
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2016 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-inline.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;
164 /* Describes one particular value stored in struct ipcp_lattice. */
166 template <typename valtype>
167 class ipcp_value : public ipcp_value_base
169 public:
170 /* The actual value for the given parameter. */
171 valtype value;
172 /* The list of sources from which this value originates. */
173 ipcp_value_source <valtype> *sources;
174 /* Next pointers in a linked list of all values in a lattice. */
175 ipcp_value *next;
176 /* Next pointers in a linked list of values in a strongly connected component
177 of values. */
178 ipcp_value *scc_next;
179 /* Next pointers in a linked list of SCCs of values sorted topologically
180 according their sources. */
181 ipcp_value *topo_next;
182 /* A specialized node created for this value, NULL if none has been (so far)
183 created. */
184 cgraph_node *spec_node;
185 /* Depth first search number and low link for topological sorting of
186 values. */
187 int dfs, low_link;
188 /* True if this valye is currently on the topo-sort stack. */
189 bool on_stack;
191 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
192 HOST_WIDE_INT offset);
195 /* Lattice describing potential values of a formal parameter of a function, or
196 a part of an aggreagate. TOP is represented by a lattice with zero values
197 and with contains_variable and bottom flags cleared. BOTTOM is represented
198 by a lattice with the bottom flag set. In that case, values and
199 contains_variable flag should be disregarded. */
201 template <typename valtype>
202 class ipcp_lattice
204 public:
205 /* The list of known values and types in this lattice. Note that values are
206 not deallocated if a lattice is set to bottom because there may be value
207 sources referencing them. */
208 ipcp_value<valtype> *values;
209 /* Number of known values and types in this lattice. */
210 int values_count;
211 /* The lattice contains a variable component (in addition to values). */
212 bool contains_variable;
213 /* The value of the lattice is bottom (i.e. variable and unusable for any
214 propagation). */
215 bool bottom;
217 inline bool is_single_const ();
218 inline bool set_to_bottom ();
219 inline bool set_contains_variable ();
220 bool add_value (valtype newval, cgraph_edge *cs,
221 ipcp_value<valtype> *src_val = NULL,
222 int src_idx = 0, HOST_WIDE_INT offset = -1);
223 void print (FILE * f, bool dump_sources, bool dump_benefits);
226 /* Lattice of tree values with an offset to describe a part of an
227 aggregate. */
229 class ipcp_agg_lattice : public ipcp_lattice<tree>
231 public:
232 /* Offset that is being described by this lattice. */
233 HOST_WIDE_INT offset;
234 /* Size so that we don't have to re-compute it every time we traverse the
235 list. Must correspond to TYPE_SIZE of all lat values. */
236 HOST_WIDE_INT size;
237 /* Next element of the linked list. */
238 struct ipcp_agg_lattice *next;
241 /* Lattice of known bits, only capable of holding one value.
242 Bitwise constant propagation propagates which bits of a
243 value are constant.
244 For eg:
245 int f(int x)
247 return some_op (x);
250 int f1(int y)
252 if (cond)
253 return f (y & 0xff);
254 else
255 return f (y & 0xf);
258 In the above case, the param 'x' will always have all
259 the bits (except the bits in lsb) set to 0.
260 Hence the mask of 'x' would be 0xff. The mask
261 reflects that the bits in lsb are unknown.
262 The actual propagated value is given by m_value & ~m_mask. */
264 class ipcp_bits_lattice
266 public:
267 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; }
268 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; }
269 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; }
270 bool set_to_bottom ();
271 bool set_to_constant (widest_int, widest_int);
273 widest_int get_value () { return m_value; }
274 widest_int get_mask () { return m_mask; }
276 bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
277 enum tree_code, tree);
279 bool meet_with (widest_int, widest_int, unsigned);
281 void print (FILE *);
283 private:
284 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
286 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
287 If a bit in mask is set to 0, then the corresponding bit in
288 value is known to be constant. */
289 widest_int m_value, m_mask;
291 bool meet_with_1 (widest_int, widest_int, unsigned);
292 void get_value_and_mask (tree, widest_int *, widest_int *);
295 /* Lattice of value ranges. */
297 class ipcp_vr_lattice
299 public:
300 value_range m_vr;
302 inline bool bottom_p () const;
303 inline bool top_p () const;
304 inline bool set_to_bottom ();
305 bool meet_with (const value_range *p_vr);
306 bool meet_with (const ipcp_vr_lattice &other);
307 void init () { m_vr.type = VR_UNDEFINED; }
308 void print (FILE * f);
310 private:
311 bool meet_with_1 (const value_range *other_vr);
314 /* Structure containing lattices for a parameter itself and for pieces of
315 aggregates that are passed in the parameter or by a reference in a parameter
316 plus some other useful flags. */
318 class ipcp_param_lattices
320 public:
321 /* Lattice describing the value of the parameter itself. */
322 ipcp_lattice<tree> itself;
323 /* Lattice describing the polymorphic contexts of a parameter. */
324 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
325 /* Lattices describing aggregate parts. */
326 ipcp_agg_lattice *aggs;
327 /* Lattice describing known bits. */
328 ipcp_bits_lattice bits_lattice;
329 /* Lattice describing value range. */
330 ipcp_vr_lattice m_value_range;
331 /* Number of aggregate lattices */
332 int aggs_count;
333 /* True if aggregate data were passed by reference (as opposed to by
334 value). */
335 bool aggs_by_ref;
336 /* All aggregate lattices contain a variable component (in addition to
337 values). */
338 bool aggs_contain_variable;
339 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
340 for any propagation). */
341 bool aggs_bottom;
343 /* There is a virtual call based on this parameter. */
344 bool virt_call;
347 /* Allocation pools for values and their sources in ipa-cp. */
349 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
350 ("IPA-CP constant values");
352 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
353 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
355 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
356 ("IPA-CP value sources");
358 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
359 ("IPA_CP aggregate lattices");
361 /* Maximal count found in program. */
363 static gcov_type max_count;
365 /* Original overall size of the program. */
367 static long overall_size, max_new_size;
369 /* Return the param lattices structure corresponding to the Ith formal
370 parameter of the function described by INFO. */
371 static inline struct ipcp_param_lattices *
372 ipa_get_parm_lattices (struct ipa_node_params *info, int i)
374 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
375 gcc_checking_assert (!info->ipcp_orig_node);
376 gcc_checking_assert (info->lattices);
377 return &(info->lattices[i]);
380 /* Return the lattice corresponding to the scalar value of the Ith formal
381 parameter of the function described by INFO. */
382 static inline ipcp_lattice<tree> *
383 ipa_get_scalar_lat (struct ipa_node_params *info, int i)
385 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
386 return &plats->itself;
389 /* Return the lattice corresponding to the scalar value of the Ith formal
390 parameter of the function described by INFO. */
391 static inline ipcp_lattice<ipa_polymorphic_call_context> *
392 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
394 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
395 return &plats->ctxlat;
398 /* Return the lattice corresponding to the value range of the Ith formal
399 parameter of the function described by INFO. */
401 static inline ipcp_vr_lattice *
402 ipa_get_vr_lat (struct ipa_node_params *info, int i)
404 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
405 return &plats->m_value_range;
408 /* Return whether LAT is a lattice with a single constant and without an
409 undefined value. */
411 template <typename valtype>
412 inline bool
413 ipcp_lattice<valtype>::is_single_const ()
415 if (bottom || contains_variable || values_count != 1)
416 return false;
417 else
418 return true;
421 /* Print V which is extracted from a value in a lattice to F. */
423 static void
424 print_ipcp_constant_value (FILE * f, tree v)
426 if (TREE_CODE (v) == ADDR_EXPR
427 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
429 fprintf (f, "& ");
430 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
432 else
433 print_generic_expr (f, v, 0);
436 /* Print V which is extracted from a value in a lattice to F. */
438 static void
439 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
441 v.dump(f, false);
444 /* Print a lattice LAT to F. */
446 template <typename valtype>
447 void
448 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
450 ipcp_value<valtype> *val;
451 bool prev = false;
453 if (bottom)
455 fprintf (f, "BOTTOM\n");
456 return;
459 if (!values_count && !contains_variable)
461 fprintf (f, "TOP\n");
462 return;
465 if (contains_variable)
467 fprintf (f, "VARIABLE");
468 prev = true;
469 if (dump_benefits)
470 fprintf (f, "\n");
473 for (val = values; val; val = val->next)
475 if (dump_benefits && prev)
476 fprintf (f, " ");
477 else if (!dump_benefits && prev)
478 fprintf (f, ", ");
479 else
480 prev = true;
482 print_ipcp_constant_value (f, val->value);
484 if (dump_sources)
486 ipcp_value_source<valtype> *s;
488 fprintf (f, " [from:");
489 for (s = val->sources; s; s = s->next)
490 fprintf (f, " %i(%i)", s->cs->caller->order,
491 s->cs->frequency);
492 fprintf (f, "]");
495 if (dump_benefits)
496 fprintf (f, " [loc_time: %i, loc_size: %i, "
497 "prop_time: %i, prop_size: %i]\n",
498 val->local_time_benefit, val->local_size_cost,
499 val->prop_time_benefit, val->prop_size_cost);
501 if (!dump_benefits)
502 fprintf (f, "\n");
505 void
506 ipcp_bits_lattice::print (FILE *f)
508 if (top_p ())
509 fprintf (f, " Bits unknown (TOP)\n");
510 else if (bottom_p ())
511 fprintf (f, " Bits unusable (BOTTOM)\n");
512 else
514 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
515 fprintf (f, ", mask = "); print_hex (get_mask (), f);
516 fprintf (f, "\n");
520 /* Print value range lattice to F. */
522 void
523 ipcp_vr_lattice::print (FILE * f)
525 dump_value_range (f, &m_vr);
528 /* Print all ipcp_lattices of all functions to F. */
530 static void
531 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
533 struct cgraph_node *node;
534 int i, count;
536 fprintf (f, "\nLattices:\n");
537 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
539 struct ipa_node_params *info;
541 info = IPA_NODE_REF (node);
542 fprintf (f, " Node: %s/%i:\n", node->name (),
543 node->order);
544 count = ipa_get_param_count (info);
545 for (i = 0; i < count; i++)
547 struct ipcp_agg_lattice *aglat;
548 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
549 fprintf (f, " param [%d]: ", i);
550 plats->itself.print (f, dump_sources, dump_benefits);
551 fprintf (f, " ctxs: ");
552 plats->ctxlat.print (f, dump_sources, dump_benefits);
553 plats->bits_lattice.print (f);
554 fprintf (f, " ");
555 plats->m_value_range.print (f);
556 fprintf (f, "\n");
557 if (plats->virt_call)
558 fprintf (f, " virt_call flag set\n");
560 if (plats->aggs_bottom)
562 fprintf (f, " AGGS BOTTOM\n");
563 continue;
565 if (plats->aggs_contain_variable)
566 fprintf (f, " AGGS VARIABLE\n");
567 for (aglat = plats->aggs; aglat; aglat = aglat->next)
569 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
570 plats->aggs_by_ref ? "ref " : "", aglat->offset);
571 aglat->print (f, dump_sources, dump_benefits);
577 /* Determine whether it is at all technically possible to create clones of NODE
578 and store this information in the ipa_node_params structure associated
579 with NODE. */
581 static void
582 determine_versionability (struct cgraph_node *node,
583 struct ipa_node_params *info)
585 const char *reason = NULL;
587 /* There are a number of generic reasons functions cannot be versioned. We
588 also cannot remove parameters if there are type attributes such as fnspec
589 present. */
590 if (node->alias || node->thunk.thunk_p)
591 reason = "alias or thunk";
592 else if (!node->local.versionable)
593 reason = "not a tree_versionable_function";
594 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
595 reason = "insufficient body availability";
596 else if (!opt_for_fn (node->decl, optimize)
597 || !opt_for_fn (node->decl, flag_ipa_cp))
598 reason = "non-optimized function";
599 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
601 /* Ideally we should clone the SIMD clones themselves and create
602 vector copies of them, so IPA-cp and SIMD clones can happily
603 coexist, but that may not be worth the effort. */
604 reason = "function has SIMD clones";
606 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
608 /* Ideally we should clone the target clones themselves and create
609 copies of them, so IPA-cp and target clones can happily
610 coexist, but that may not be worth the effort. */
611 reason = "function target_clones attribute";
613 /* Don't clone decls local to a comdat group; it breaks and for C++
614 decloned constructors, inlining is always better anyway. */
615 else if (node->comdat_local_p ())
616 reason = "comdat-local function";
618 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
619 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
620 node->name (), node->order, reason);
622 info->versionable = (reason == NULL);
625 /* Return true if it is at all technically possible to create clones of a
626 NODE. */
628 static bool
629 ipcp_versionable_function_p (struct cgraph_node *node)
631 return IPA_NODE_REF (node)->versionable;
634 /* Structure holding accumulated information about callers of a node. */
636 struct caller_statistics
638 gcov_type count_sum;
639 int n_calls, n_hot_calls, freq_sum;
642 /* Initialize fields of STAT to zeroes. */
644 static inline void
645 init_caller_stats (struct caller_statistics *stats)
647 stats->count_sum = 0;
648 stats->n_calls = 0;
649 stats->n_hot_calls = 0;
650 stats->freq_sum = 0;
653 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
654 non-thunk incoming edges to NODE. */
656 static bool
657 gather_caller_stats (struct cgraph_node *node, void *data)
659 struct caller_statistics *stats = (struct caller_statistics *) data;
660 struct cgraph_edge *cs;
662 for (cs = node->callers; cs; cs = cs->next_caller)
663 if (!cs->caller->thunk.thunk_p)
665 stats->count_sum += cs->count;
666 stats->freq_sum += cs->frequency;
667 stats->n_calls++;
668 if (cs->maybe_hot_p ())
669 stats->n_hot_calls ++;
671 return false;
675 /* Return true if this NODE is viable candidate for cloning. */
677 static bool
678 ipcp_cloning_candidate_p (struct cgraph_node *node)
680 struct caller_statistics stats;
682 gcc_checking_assert (node->has_gimple_body_p ());
684 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
686 if (dump_file)
687 fprintf (dump_file, "Not considering %s for cloning; "
688 "-fipa-cp-clone disabled.\n",
689 node->name ());
690 return false;
693 if (node->optimize_for_size_p ())
695 if (dump_file)
696 fprintf (dump_file, "Not considering %s for cloning; "
697 "optimizing it for size.\n",
698 node->name ());
699 return false;
702 init_caller_stats (&stats);
703 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
705 if (inline_summaries->get (node)->self_size < stats.n_calls)
707 if (dump_file)
708 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
709 node->name ());
710 return true;
713 /* When profile is available and function is hot, propagate into it even if
714 calls seems cold; constant propagation can improve function's speed
715 significantly. */
716 if (max_count)
718 if (stats.count_sum > node->count * 90 / 100)
720 if (dump_file)
721 fprintf (dump_file, "Considering %s for cloning; "
722 "usually called directly.\n",
723 node->name ());
724 return true;
727 if (!stats.n_hot_calls)
729 if (dump_file)
730 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
731 node->name ());
732 return false;
734 if (dump_file)
735 fprintf (dump_file, "Considering %s for cloning.\n",
736 node->name ());
737 return true;
740 template <typename valtype>
741 class value_topo_info
743 public:
744 /* Head of the linked list of topologically sorted values. */
745 ipcp_value<valtype> *values_topo;
746 /* Stack for creating SCCs, represented by a linked list too. */
747 ipcp_value<valtype> *stack;
748 /* Counter driving the algorithm in add_val_to_toposort. */
749 int dfs_counter;
751 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
753 void add_val (ipcp_value<valtype> *cur_val);
754 void propagate_effects ();
757 /* Arrays representing a topological ordering of call graph nodes and a stack
758 of nodes used during constant propagation and also data required to perform
759 topological sort of values and propagation of benefits in the determined
760 order. */
762 class ipa_topo_info
764 public:
765 /* Array with obtained topological order of cgraph nodes. */
766 struct cgraph_node **order;
767 /* Stack of cgraph nodes used during propagation within SCC until all values
768 in the SCC stabilize. */
769 struct cgraph_node **stack;
770 int nnodes, stack_top;
772 value_topo_info<tree> constants;
773 value_topo_info<ipa_polymorphic_call_context> contexts;
775 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
776 constants ()
780 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
782 static void
783 build_toporder_info (struct ipa_topo_info *topo)
785 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
786 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
788 gcc_checking_assert (topo->stack_top == 0);
789 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
792 /* Free information about strongly connected components and the arrays in
793 TOPO. */
795 static void
796 free_toporder_info (struct ipa_topo_info *topo)
798 ipa_free_postorder_info ();
799 free (topo->order);
800 free (topo->stack);
803 /* Add NODE to the stack in TOPO, unless it is already there. */
805 static inline void
806 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
808 struct ipa_node_params *info = IPA_NODE_REF (node);
809 if (info->node_enqueued)
810 return;
811 info->node_enqueued = 1;
812 topo->stack[topo->stack_top++] = node;
815 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
816 is empty. */
818 static struct cgraph_node *
819 pop_node_from_stack (struct ipa_topo_info *topo)
821 if (topo->stack_top)
823 struct cgraph_node *node;
824 topo->stack_top--;
825 node = topo->stack[topo->stack_top];
826 IPA_NODE_REF (node)->node_enqueued = 0;
827 return node;
829 else
830 return NULL;
833 /* Set lattice LAT to bottom and return true if it previously was not set as
834 such. */
836 template <typename valtype>
837 inline bool
838 ipcp_lattice<valtype>::set_to_bottom ()
840 bool ret = !bottom;
841 bottom = true;
842 return ret;
845 /* Mark lattice as containing an unknown value and return true if it previously
846 was not marked as such. */
848 template <typename valtype>
849 inline bool
850 ipcp_lattice<valtype>::set_contains_variable ()
852 bool ret = !contains_variable;
853 contains_variable = true;
854 return ret;
857 /* Set all aggegate lattices in PLATS to bottom and return true if they were
858 not previously set as such. */
860 static inline bool
861 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
863 bool ret = !plats->aggs_bottom;
864 plats->aggs_bottom = true;
865 return ret;
868 /* Mark all aggegate lattices in PLATS as containing an unknown value and
869 return true if they were not previously marked as such. */
871 static inline bool
872 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
874 bool ret = !plats->aggs_contain_variable;
875 plats->aggs_contain_variable = true;
876 return ret;
879 bool
880 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
882 return meet_with_1 (&other.m_vr);
885 /* Meet the current value of the lattice with value ranfge described by VR
886 lattice. */
888 bool
889 ipcp_vr_lattice::meet_with (const value_range *p_vr)
891 return meet_with_1 (p_vr);
894 /* Meet the current value of the lattice with value ranfge described by
895 OTHER_VR lattice. */
897 bool
898 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
900 tree min = m_vr.min, max = m_vr.max;
901 value_range_type type = m_vr.type;
903 if (bottom_p ())
904 return false;
906 if (other_vr->type == VR_VARYING)
907 return set_to_bottom ();
909 vrp_meet (&m_vr, other_vr);
910 if (type != m_vr.type
911 || min != m_vr.min
912 || max != m_vr.max)
913 return true;
914 else
915 return false;
918 /* Return true if value range information in the lattice is yet unknown. */
920 bool
921 ipcp_vr_lattice::top_p () const
923 return m_vr.type == VR_UNDEFINED;
926 /* Return true if value range information in the lattice is known to be
927 unusable. */
929 bool
930 ipcp_vr_lattice::bottom_p () const
932 return m_vr.type == VR_VARYING;
935 /* Set value range information in the lattice to bottom. Return true if it
936 previously was in a different state. */
938 bool
939 ipcp_vr_lattice::set_to_bottom ()
941 if (m_vr.type == VR_VARYING)
942 return false;
943 m_vr.type = VR_VARYING;
944 return true;
947 /* Set lattice value to bottom, if it already isn't the case. */
949 bool
950 ipcp_bits_lattice::set_to_bottom ()
952 if (bottom_p ())
953 return false;
954 m_lattice_val = IPA_BITS_VARYING;
955 m_value = 0;
956 m_mask = -1;
957 return true;
960 /* Set to constant if it isn't already. Only meant to be called
961 when switching state from TOP. */
963 bool
964 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
966 gcc_assert (top_p ());
967 m_lattice_val = IPA_BITS_CONSTANT;
968 m_value = value;
969 m_mask = mask;
970 return true;
973 /* Convert operand to value, mask form. */
975 void
976 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
978 wide_int get_nonzero_bits (const_tree);
980 if (TREE_CODE (operand) == INTEGER_CST)
982 *valuep = wi::to_widest (operand);
983 *maskp = 0;
985 else
987 *valuep = 0;
988 *maskp = -1;
992 /* Meet operation, similar to ccp_lattice_meet, we xor values
993 if this->value, value have different values at same bit positions, we want
994 to drop that bit to varying. Return true if mask is changed.
995 This function assumes that the lattice value is in CONSTANT state */
997 bool
998 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
999 unsigned precision)
1001 gcc_assert (constant_p ());
1003 widest_int old_mask = m_mask;
1004 m_mask = (m_mask | mask) | (m_value ^ value);
1006 if (wi::sext (m_mask, precision) == -1)
1007 return set_to_bottom ();
1009 return m_mask != old_mask;
1012 /* Meet the bits lattice with operand
1013 described by <value, mask, sgn, precision. */
1015 bool
1016 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1017 unsigned precision)
1019 if (bottom_p ())
1020 return false;
1022 if (top_p ())
1024 if (wi::sext (mask, precision) == -1)
1025 return set_to_bottom ();
1026 return set_to_constant (value, mask);
1029 return meet_with_1 (value, mask, precision);
1032 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1033 if code is binary operation or bit_value_unop (other) if code is unary op.
1034 In the case when code is nop_expr, no adjustment is required. */
1036 bool
1037 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1038 signop sgn, enum tree_code code, tree operand)
1040 if (other.bottom_p ())
1041 return set_to_bottom ();
1043 if (bottom_p () || other.top_p ())
1044 return false;
1046 widest_int adjusted_value, adjusted_mask;
1048 if (TREE_CODE_CLASS (code) == tcc_binary)
1050 tree type = TREE_TYPE (operand);
1051 gcc_assert (INTEGRAL_TYPE_P (type));
1052 widest_int o_value, o_mask;
1053 get_value_and_mask (operand, &o_value, &o_mask);
1055 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1056 sgn, precision, other.get_value (), other.get_mask (),
1057 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1059 if (wi::sext (adjusted_mask, precision) == -1)
1060 return set_to_bottom ();
1063 else if (TREE_CODE_CLASS (code) == tcc_unary)
1065 bit_value_unop (code, sgn, precision, &adjusted_value,
1066 &adjusted_mask, sgn, precision, other.get_value (),
1067 other.get_mask ());
1069 if (wi::sext (adjusted_mask, precision) == -1)
1070 return set_to_bottom ();
1073 else
1074 return set_to_bottom ();
1076 if (top_p ())
1078 if (wi::sext (adjusted_mask, precision) == -1)
1079 return set_to_bottom ();
1080 return set_to_constant (adjusted_value, adjusted_mask);
1082 else
1083 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1086 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1087 return true is any of them has not been marked as such so far. */
1089 static inline bool
1090 set_all_contains_variable (struct ipcp_param_lattices *plats)
1092 bool ret;
1093 ret = plats->itself.set_contains_variable ();
1094 ret |= plats->ctxlat.set_contains_variable ();
1095 ret |= set_agg_lats_contain_variable (plats);
1096 ret |= plats->bits_lattice.set_to_bottom ();
1097 ret |= plats->m_value_range.set_to_bottom ();
1098 return ret;
1101 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1102 points to by the number of callers to NODE. */
1104 static bool
1105 count_callers (cgraph_node *node, void *data)
1107 int *caller_count = (int *) data;
1109 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1110 /* Local thunks can be handled transparently, but if the thunk can not
1111 be optimized out, count it as a real use. */
1112 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
1113 ++*caller_count;
1114 return false;
1117 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1118 the one caller of some other node. Set the caller's corresponding flag. */
1120 static bool
1121 set_single_call_flag (cgraph_node *node, void *)
1123 cgraph_edge *cs = node->callers;
1124 /* Local thunks can be handled transparently, skip them. */
1125 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
1126 cs = cs->next_caller;
1127 if (cs)
1129 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1130 return true;
1132 return false;
1135 /* Initialize ipcp_lattices. */
1137 static void
1138 initialize_node_lattices (struct cgraph_node *node)
1140 struct ipa_node_params *info = IPA_NODE_REF (node);
1141 struct cgraph_edge *ie;
1142 bool disable = false, variable = false;
1143 int i;
1145 gcc_checking_assert (node->has_gimple_body_p ());
1146 if (cgraph_local_p (node))
1148 int caller_count = 0;
1149 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1150 true);
1151 gcc_checking_assert (caller_count > 0);
1152 if (caller_count == 1)
1153 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1154 NULL, true);
1156 else
1158 /* When cloning is allowed, we can assume that externally visible
1159 functions are not called. We will compensate this by cloning
1160 later. */
1161 if (ipcp_versionable_function_p (node)
1162 && ipcp_cloning_candidate_p (node))
1163 variable = true;
1164 else
1165 disable = true;
1168 for (i = 0; i < ipa_get_param_count (info) ; i++)
1170 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1171 plats->m_value_range.init ();
1174 if (disable || variable)
1176 for (i = 0; i < ipa_get_param_count (info) ; i++)
1178 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1179 if (disable)
1181 plats->itself.set_to_bottom ();
1182 plats->ctxlat.set_to_bottom ();
1183 set_agg_lats_to_bottom (plats);
1184 plats->bits_lattice.set_to_bottom ();
1185 plats->m_value_range.set_to_bottom ();
1187 else
1188 set_all_contains_variable (plats);
1190 if (dump_file && (dump_flags & TDF_DETAILS)
1191 && !node->alias && !node->thunk.thunk_p)
1192 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
1193 node->name (), node->order,
1194 disable ? "BOTTOM" : "VARIABLE");
1197 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1198 if (ie->indirect_info->polymorphic
1199 && ie->indirect_info->param_index >= 0)
1201 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1202 ipa_get_parm_lattices (info,
1203 ie->indirect_info->param_index)->virt_call = 1;
1207 /* Return the result of a (possibly arithmetic) pass through jump function
1208 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
1209 determined or be considered an interprocedural invariant. */
1211 static tree
1212 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
1214 tree restype, res;
1216 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1217 return input;
1218 if (!is_gimple_ip_invariant (input))
1219 return NULL_TREE;
1221 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
1222 == tcc_comparison)
1223 restype = boolean_type_node;
1224 else
1225 restype = TREE_TYPE (input);
1226 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
1227 input, ipa_get_jf_pass_through_operand (jfunc));
1229 if (res && !is_gimple_ip_invariant (res))
1230 return NULL_TREE;
1232 return res;
1235 /* Return the result of an ancestor jump function JFUNC on the constant value
1236 INPUT. Return NULL_TREE if that cannot be determined. */
1238 static tree
1239 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1241 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1242 if (TREE_CODE (input) == ADDR_EXPR)
1244 tree t = TREE_OPERAND (input, 0);
1245 t = build_ref_for_offset (EXPR_LOCATION (t), t,
1246 ipa_get_jf_ancestor_offset (jfunc), false,
1247 ptr_type_node, NULL, false);
1248 return build_fold_addr_expr (t);
1250 else
1251 return NULL_TREE;
1254 /* Determine whether JFUNC evaluates to a single known constant value and if
1255 so, return it. Otherwise return NULL. INFO describes the caller node or
1256 the one it is inlined to, so that pass-through jump functions can be
1257 evaluated. */
1259 tree
1260 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
1262 if (jfunc->type == IPA_JF_CONST)
1263 return ipa_get_jf_constant (jfunc);
1264 else if (jfunc->type == IPA_JF_PASS_THROUGH
1265 || jfunc->type == IPA_JF_ANCESTOR)
1267 tree input;
1268 int idx;
1270 if (jfunc->type == IPA_JF_PASS_THROUGH)
1271 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1272 else
1273 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1275 if (info->ipcp_orig_node)
1276 input = info->known_csts[idx];
1277 else
1279 ipcp_lattice<tree> *lat;
1281 if (!info->lattices
1282 || idx >= ipa_get_param_count (info))
1283 return NULL_TREE;
1284 lat = ipa_get_scalar_lat (info, idx);
1285 if (!lat->is_single_const ())
1286 return NULL_TREE;
1287 input = lat->values->value;
1290 if (!input)
1291 return NULL_TREE;
1293 if (jfunc->type == IPA_JF_PASS_THROUGH)
1294 return ipa_get_jf_pass_through_result (jfunc, input);
1295 else
1296 return ipa_get_jf_ancestor_result (jfunc, input);
1298 else
1299 return NULL_TREE;
1302 /* Determie whether JFUNC evaluates to single known polymorphic context, given
1303 that INFO describes the caller node or the one it is inlined to, CS is the
1304 call graph edge corresponding to JFUNC and CSIDX index of the described
1305 parameter. */
1307 ipa_polymorphic_call_context
1308 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1309 ipa_jump_func *jfunc)
1311 ipa_edge_args *args = IPA_EDGE_REF (cs);
1312 ipa_polymorphic_call_context ctx;
1313 ipa_polymorphic_call_context *edge_ctx
1314 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1316 if (edge_ctx && !edge_ctx->useless_p ())
1317 ctx = *edge_ctx;
1319 if (jfunc->type == IPA_JF_PASS_THROUGH
1320 || jfunc->type == IPA_JF_ANCESTOR)
1322 ipa_polymorphic_call_context srcctx;
1323 int srcidx;
1324 bool type_preserved = true;
1325 if (jfunc->type == IPA_JF_PASS_THROUGH)
1327 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1328 return ctx;
1329 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1330 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1332 else
1334 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1335 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1337 if (info->ipcp_orig_node)
1339 if (info->known_contexts.exists ())
1340 srcctx = info->known_contexts[srcidx];
1342 else
1344 if (!info->lattices
1345 || srcidx >= ipa_get_param_count (info))
1346 return ctx;
1347 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1348 lat = ipa_get_poly_ctx_lat (info, srcidx);
1349 if (!lat->is_single_const ())
1350 return ctx;
1351 srcctx = lat->values->value;
1353 if (srcctx.useless_p ())
1354 return ctx;
1355 if (jfunc->type == IPA_JF_ANCESTOR)
1356 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1357 if (!type_preserved)
1358 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1359 srcctx.combine_with (ctx);
1360 return srcctx;
1363 return ctx;
1366 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1367 bottom, not containing a variable component and without any known value at
1368 the same time. */
1370 DEBUG_FUNCTION void
1371 ipcp_verify_propagated_values (void)
1373 struct cgraph_node *node;
1375 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1377 struct ipa_node_params *info = IPA_NODE_REF (node);
1378 int i, count = ipa_get_param_count (info);
1380 for (i = 0; i < count; i++)
1382 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1384 if (!lat->bottom
1385 && !lat->contains_variable
1386 && lat->values_count == 0)
1388 if (dump_file)
1390 symtab_node::dump_table (dump_file);
1391 fprintf (dump_file, "\nIPA lattices after constant "
1392 "propagation, before gcc_unreachable:\n");
1393 print_all_lattices (dump_file, true, false);
1396 gcc_unreachable ();
1402 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1404 static bool
1405 values_equal_for_ipcp_p (tree x, tree y)
1407 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1409 if (x == y)
1410 return true;
1412 if (TREE_CODE (x) == ADDR_EXPR
1413 && TREE_CODE (y) == ADDR_EXPR
1414 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1415 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1416 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1417 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1418 else
1419 return operand_equal_p (x, y, 0);
1422 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1424 static bool
1425 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1426 ipa_polymorphic_call_context y)
1428 return x.equal_to (y);
1432 /* Add a new value source to the value represented by THIS, marking that a
1433 value comes from edge CS and (if the underlying jump function is a
1434 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1435 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1436 scalar value of the parameter itself or the offset within an aggregate. */
1438 template <typename valtype>
1439 void
1440 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1441 int src_idx, HOST_WIDE_INT offset)
1443 ipcp_value_source<valtype> *src;
1445 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1446 src->offset = offset;
1447 src->cs = cs;
1448 src->val = src_val;
1449 src->index = src_idx;
1451 src->next = sources;
1452 sources = src;
1455 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1456 SOURCE and clear all other fields. */
1458 static ipcp_value<tree> *
1459 allocate_and_init_ipcp_value (tree source)
1461 ipcp_value<tree> *val;
1463 val = ipcp_cst_values_pool.allocate ();
1464 memset (val, 0, sizeof (*val));
1465 val->value = source;
1466 return val;
1469 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1470 value to SOURCE and clear all other fields. */
1472 static ipcp_value<ipa_polymorphic_call_context> *
1473 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1475 ipcp_value<ipa_polymorphic_call_context> *val;
1477 // TODO
1478 val = ipcp_poly_ctx_values_pool.allocate ();
1479 memset (val, 0, sizeof (*val));
1480 val->value = source;
1481 return val;
1484 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1485 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1486 meaning. OFFSET -1 means the source is scalar and not a part of an
1487 aggregate. */
1489 template <typename valtype>
1490 bool
1491 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1492 ipcp_value<valtype> *src_val,
1493 int src_idx, HOST_WIDE_INT offset)
1495 ipcp_value<valtype> *val;
1497 if (bottom)
1498 return false;
1500 for (val = values; val; val = val->next)
1501 if (values_equal_for_ipcp_p (val->value, newval))
1503 if (ipa_edge_within_scc (cs))
1505 ipcp_value_source<valtype> *s;
1506 for (s = val->sources; s ; s = s->next)
1507 if (s->cs == cs)
1508 break;
1509 if (s)
1510 return false;
1513 val->add_source (cs, src_val, src_idx, offset);
1514 return false;
1517 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1519 /* We can only free sources, not the values themselves, because sources
1520 of other values in this SCC might point to them. */
1521 for (val = values; val; val = val->next)
1523 while (val->sources)
1525 ipcp_value_source<valtype> *src = val->sources;
1526 val->sources = src->next;
1527 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1531 values = NULL;
1532 return set_to_bottom ();
1535 values_count++;
1536 val = allocate_and_init_ipcp_value (newval);
1537 val->add_source (cs, src_val, src_idx, offset);
1538 val->next = values;
1539 values = val;
1540 return true;
1543 /* Propagate values through a pass-through jump function JFUNC associated with
1544 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1545 is the index of the source parameter. */
1547 static bool
1548 propagate_vals_accross_pass_through (cgraph_edge *cs,
1549 ipa_jump_func *jfunc,
1550 ipcp_lattice<tree> *src_lat,
1551 ipcp_lattice<tree> *dest_lat,
1552 int src_idx)
1554 ipcp_value<tree> *src_val;
1555 bool ret = false;
1557 /* Do not create new values when propagating within an SCC because if there
1558 are arithmetic functions with circular dependencies, there is infinite
1559 number of them and we would just make lattices bottom. */
1560 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1561 && ipa_edge_within_scc (cs))
1562 ret = dest_lat->set_contains_variable ();
1563 else
1564 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1566 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1568 if (cstval)
1569 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1570 else
1571 ret |= dest_lat->set_contains_variable ();
1574 return ret;
1577 /* Propagate values through an ancestor jump function JFUNC associated with
1578 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1579 is the index of the source parameter. */
1581 static bool
1582 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1583 struct ipa_jump_func *jfunc,
1584 ipcp_lattice<tree> *src_lat,
1585 ipcp_lattice<tree> *dest_lat,
1586 int src_idx)
1588 ipcp_value<tree> *src_val;
1589 bool ret = false;
1591 if (ipa_edge_within_scc (cs))
1592 return dest_lat->set_contains_variable ();
1594 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1596 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1598 if (t)
1599 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1600 else
1601 ret |= dest_lat->set_contains_variable ();
1604 return ret;
1607 /* Propagate scalar values across jump function JFUNC that is associated with
1608 edge CS and put the values into DEST_LAT. */
1610 static bool
1611 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1612 struct ipa_jump_func *jfunc,
1613 ipcp_lattice<tree> *dest_lat)
1615 if (dest_lat->bottom)
1616 return false;
1618 if (jfunc->type == IPA_JF_CONST)
1620 tree val = ipa_get_jf_constant (jfunc);
1621 return dest_lat->add_value (val, cs, NULL, 0);
1623 else if (jfunc->type == IPA_JF_PASS_THROUGH
1624 || jfunc->type == IPA_JF_ANCESTOR)
1626 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1627 ipcp_lattice<tree> *src_lat;
1628 int src_idx;
1629 bool ret;
1631 if (jfunc->type == IPA_JF_PASS_THROUGH)
1632 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1633 else
1634 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1636 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1637 if (src_lat->bottom)
1638 return dest_lat->set_contains_variable ();
1640 /* If we would need to clone the caller and cannot, do not propagate. */
1641 if (!ipcp_versionable_function_p (cs->caller)
1642 && (src_lat->contains_variable
1643 || (src_lat->values_count > 1)))
1644 return dest_lat->set_contains_variable ();
1646 if (jfunc->type == IPA_JF_PASS_THROUGH)
1647 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1648 dest_lat, src_idx);
1649 else
1650 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1651 src_idx);
1653 if (src_lat->contains_variable)
1654 ret |= dest_lat->set_contains_variable ();
1656 return ret;
1659 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1660 use it for indirect inlining), we should propagate them too. */
1661 return dest_lat->set_contains_variable ();
1664 /* Propagate scalar values across jump function JFUNC that is associated with
1665 edge CS and describes argument IDX and put the values into DEST_LAT. */
1667 static bool
1668 propagate_context_accross_jump_function (cgraph_edge *cs,
1669 ipa_jump_func *jfunc, int idx,
1670 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1672 ipa_edge_args *args = IPA_EDGE_REF (cs);
1673 if (dest_lat->bottom)
1674 return false;
1675 bool ret = false;
1676 bool added_sth = false;
1677 bool type_preserved = true;
1679 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1680 = ipa_get_ith_polymorhic_call_context (args, idx);
1682 if (edge_ctx_ptr)
1683 edge_ctx = *edge_ctx_ptr;
1685 if (jfunc->type == IPA_JF_PASS_THROUGH
1686 || jfunc->type == IPA_JF_ANCESTOR)
1688 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1689 int src_idx;
1690 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1692 /* TODO: Once we figure out how to propagate speculations, it will
1693 probably be a good idea to switch to speculation if type_preserved is
1694 not set instead of punting. */
1695 if (jfunc->type == IPA_JF_PASS_THROUGH)
1697 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1698 goto prop_fail;
1699 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1700 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1702 else
1704 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1705 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1708 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1709 /* If we would need to clone the caller and cannot, do not propagate. */
1710 if (!ipcp_versionable_function_p (cs->caller)
1711 && (src_lat->contains_variable
1712 || (src_lat->values_count > 1)))
1713 goto prop_fail;
1715 ipcp_value<ipa_polymorphic_call_context> *src_val;
1716 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1718 ipa_polymorphic_call_context cur = src_val->value;
1720 if (!type_preserved)
1721 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1722 if (jfunc->type == IPA_JF_ANCESTOR)
1723 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1724 /* TODO: In cases we know how the context is going to be used,
1725 we can improve the result by passing proper OTR_TYPE. */
1726 cur.combine_with (edge_ctx);
1727 if (!cur.useless_p ())
1729 if (src_lat->contains_variable
1730 && !edge_ctx.equal_to (cur))
1731 ret |= dest_lat->set_contains_variable ();
1732 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1733 added_sth = true;
1739 prop_fail:
1740 if (!added_sth)
1742 if (!edge_ctx.useless_p ())
1743 ret |= dest_lat->add_value (edge_ctx, cs);
1744 else
1745 ret |= dest_lat->set_contains_variable ();
1748 return ret;
1751 /* Propagate bits across jfunc that is associated with
1752 edge cs and update dest_lattice accordingly. */
1754 bool
1755 propagate_bits_accross_jump_function (cgraph_edge *cs, int idx, ipa_jump_func *jfunc,
1756 ipcp_bits_lattice *dest_lattice)
1758 if (dest_lattice->bottom_p ())
1759 return false;
1761 enum availability availability;
1762 cgraph_node *callee = cs->callee->function_symbol (&availability);
1763 struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
1764 tree parm_type = ipa_get_type (callee_info, idx);
1766 /* For K&R C programs, ipa_get_type() could return NULL_TREE.
1767 Avoid the transform for these cases. */
1768 if (!parm_type)
1770 if (dump_file && (dump_flags & TDF_DETAILS))
1771 fprintf (dump_file, "Setting dest_lattice to bottom, because"
1772 " param %i type is NULL for %s\n", idx,
1773 cs->callee->name ());
1775 return dest_lattice->set_to_bottom ();
1778 unsigned precision = TYPE_PRECISION (parm_type);
1779 signop sgn = TYPE_SIGN (parm_type);
1781 if (jfunc->type == IPA_JF_PASS_THROUGH
1782 || jfunc->type == IPA_JF_ANCESTOR)
1784 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1785 tree operand = NULL_TREE;
1786 enum tree_code code;
1787 unsigned src_idx;
1789 if (jfunc->type == IPA_JF_PASS_THROUGH)
1791 code = ipa_get_jf_pass_through_operation (jfunc);
1792 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1793 if (code != NOP_EXPR)
1794 operand = ipa_get_jf_pass_through_operand (jfunc);
1796 else
1798 code = POINTER_PLUS_EXPR;
1799 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1800 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
1801 operand = build_int_cstu (size_type_node, offset);
1804 struct ipcp_param_lattices *src_lats
1805 = ipa_get_parm_lattices (caller_info, src_idx);
1807 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1808 for eg consider:
1809 int f(int x)
1811 g (x & 0xff);
1813 Assume lattice for x is bottom, however we can still propagate
1814 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1815 and we store it in jump function during analysis stage. */
1817 if (src_lats->bits_lattice.bottom_p ()
1818 && jfunc->bits.known)
1819 return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask,
1820 precision);
1821 else
1822 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
1823 code, operand);
1826 else if (jfunc->type == IPA_JF_ANCESTOR)
1827 return dest_lattice->set_to_bottom ();
1829 else if (jfunc->bits.known)
1830 return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask, precision);
1832 else
1833 return dest_lattice->set_to_bottom ();
1836 /* Propagate value range across jump function JFUNC that is associated with
1837 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1838 accordingly. */
1840 static bool
1841 propagate_vr_accross_jump_function (cgraph_edge *cs,
1842 ipa_jump_func *jfunc,
1843 struct ipcp_param_lattices *dest_plats,
1844 tree param_type)
1846 struct ipcp_param_lattices *src_lats;
1847 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
1849 if (dest_lat->bottom_p ())
1850 return false;
1852 if (!param_type
1853 || (!INTEGRAL_TYPE_P (param_type)
1854 && !POINTER_TYPE_P (param_type)))
1855 return dest_lat->set_to_bottom ();
1857 if (jfunc->type == IPA_JF_PASS_THROUGH)
1859 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1860 if (dest_lat->bottom_p ())
1861 return false;
1862 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1863 src_lats = ipa_get_parm_lattices (caller_info, src_idx);
1865 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1866 return dest_lat->meet_with (src_lats->m_value_range);
1868 else if (jfunc->type == IPA_JF_CONST)
1870 tree val = ipa_get_jf_constant (jfunc);
1871 if (TREE_CODE (val) == INTEGER_CST)
1873 if (TREE_OVERFLOW_P (val))
1874 val = drop_tree_overflow (val);
1875 val = fold_convert (param_type, val);
1876 jfunc->vr_known = true;
1877 jfunc->m_vr.type = VR_RANGE;
1878 jfunc->m_vr.min = val;
1879 jfunc->m_vr.max = val;
1880 return dest_lat->meet_with (&jfunc->m_vr);
1884 if (jfunc->vr_known)
1885 return dest_lat->meet_with (&jfunc->m_vr);
1886 else
1887 return dest_lat->set_to_bottom ();
1890 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1891 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1892 other cases, return false). If there are no aggregate items, set
1893 aggs_by_ref to NEW_AGGS_BY_REF. */
1895 static bool
1896 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1897 bool new_aggs_by_ref)
1899 if (dest_plats->aggs)
1901 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1903 set_agg_lats_to_bottom (dest_plats);
1904 return true;
1907 else
1908 dest_plats->aggs_by_ref = new_aggs_by_ref;
1909 return false;
1912 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1913 already existing lattice for the given OFFSET and SIZE, marking all skipped
1914 lattices as containing variable and checking for overlaps. If there is no
1915 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1916 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1917 unless there are too many already. If there are two many, return false. If
1918 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1919 skipped lattices were newly marked as containing variable, set *CHANGE to
1920 true. */
1922 static bool
1923 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1924 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1925 struct ipcp_agg_lattice ***aglat,
1926 bool pre_existing, bool *change)
1928 gcc_checking_assert (offset >= 0);
1930 while (**aglat && (**aglat)->offset < offset)
1932 if ((**aglat)->offset + (**aglat)->size > offset)
1934 set_agg_lats_to_bottom (dest_plats);
1935 return false;
1937 *change |= (**aglat)->set_contains_variable ();
1938 *aglat = &(**aglat)->next;
1941 if (**aglat && (**aglat)->offset == offset)
1943 if ((**aglat)->size != val_size
1944 || ((**aglat)->next
1945 && (**aglat)->next->offset < offset + val_size))
1947 set_agg_lats_to_bottom (dest_plats);
1948 return false;
1950 gcc_checking_assert (!(**aglat)->next
1951 || (**aglat)->next->offset >= offset + val_size);
1952 return true;
1954 else
1956 struct ipcp_agg_lattice *new_al;
1958 if (**aglat && (**aglat)->offset < offset + val_size)
1960 set_agg_lats_to_bottom (dest_plats);
1961 return false;
1963 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1964 return false;
1965 dest_plats->aggs_count++;
1966 new_al = ipcp_agg_lattice_pool.allocate ();
1967 memset (new_al, 0, sizeof (*new_al));
1969 new_al->offset = offset;
1970 new_al->size = val_size;
1971 new_al->contains_variable = pre_existing;
1973 new_al->next = **aglat;
1974 **aglat = new_al;
1975 return true;
1979 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1980 containing an unknown value. */
1982 static bool
1983 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1985 bool ret = false;
1986 while (aglat)
1988 ret |= aglat->set_contains_variable ();
1989 aglat = aglat->next;
1991 return ret;
1994 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1995 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1996 parameter used for lattice value sources. Return true if DEST_PLATS changed
1997 in any way. */
1999 static bool
2000 merge_aggregate_lattices (struct cgraph_edge *cs,
2001 struct ipcp_param_lattices *dest_plats,
2002 struct ipcp_param_lattices *src_plats,
2003 int src_idx, HOST_WIDE_INT offset_delta)
2005 bool pre_existing = dest_plats->aggs != NULL;
2006 struct ipcp_agg_lattice **dst_aglat;
2007 bool ret = false;
2009 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2010 return true;
2011 if (src_plats->aggs_bottom)
2012 return set_agg_lats_contain_variable (dest_plats);
2013 if (src_plats->aggs_contain_variable)
2014 ret |= set_agg_lats_contain_variable (dest_plats);
2015 dst_aglat = &dest_plats->aggs;
2017 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2018 src_aglat;
2019 src_aglat = src_aglat->next)
2021 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2023 if (new_offset < 0)
2024 continue;
2025 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2026 &dst_aglat, pre_existing, &ret))
2028 struct ipcp_agg_lattice *new_al = *dst_aglat;
2030 dst_aglat = &(*dst_aglat)->next;
2031 if (src_aglat->bottom)
2033 ret |= new_al->set_contains_variable ();
2034 continue;
2036 if (src_aglat->contains_variable)
2037 ret |= new_al->set_contains_variable ();
2038 for (ipcp_value<tree> *val = src_aglat->values;
2039 val;
2040 val = val->next)
2041 ret |= new_al->add_value (val->value, cs, val, src_idx,
2042 src_aglat->offset);
2044 else if (dest_plats->aggs_bottom)
2045 return true;
2047 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2048 return ret;
2051 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2052 pass-through JFUNC and if so, whether it has conform and conforms to the
2053 rules about propagating values passed by reference. */
2055 static bool
2056 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
2057 struct ipa_jump_func *jfunc)
2059 return src_plats->aggs
2060 && (!src_plats->aggs_by_ref
2061 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2064 /* Propagate scalar values across jump function JFUNC that is associated with
2065 edge CS and put the values into DEST_LAT. */
2067 static bool
2068 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
2069 struct ipa_jump_func *jfunc,
2070 struct ipcp_param_lattices *dest_plats)
2072 bool ret = false;
2074 if (dest_plats->aggs_bottom)
2075 return false;
2077 if (jfunc->type == IPA_JF_PASS_THROUGH
2078 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2080 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2081 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2082 struct ipcp_param_lattices *src_plats;
2084 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2085 if (agg_pass_through_permissible_p (src_plats, jfunc))
2087 /* Currently we do not produce clobber aggregate jump
2088 functions, replace with merging when we do. */
2089 gcc_assert (!jfunc->agg.items);
2090 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2091 src_idx, 0);
2093 else
2094 ret |= set_agg_lats_contain_variable (dest_plats);
2096 else if (jfunc->type == IPA_JF_ANCESTOR
2097 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2099 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2100 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2101 struct ipcp_param_lattices *src_plats;
2103 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2104 if (src_plats->aggs && src_plats->aggs_by_ref)
2106 /* Currently we do not produce clobber aggregate jump
2107 functions, replace with merging when we do. */
2108 gcc_assert (!jfunc->agg.items);
2109 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2110 ipa_get_jf_ancestor_offset (jfunc));
2112 else if (!src_plats->aggs_by_ref)
2113 ret |= set_agg_lats_to_bottom (dest_plats);
2114 else
2115 ret |= set_agg_lats_contain_variable (dest_plats);
2117 else if (jfunc->agg.items)
2119 bool pre_existing = dest_plats->aggs != NULL;
2120 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2121 struct ipa_agg_jf_item *item;
2122 int i;
2124 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2125 return true;
2127 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2129 HOST_WIDE_INT val_size;
2131 if (item->offset < 0)
2132 continue;
2133 gcc_checking_assert (is_gimple_ip_invariant (item->value));
2134 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2136 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2137 &aglat, pre_existing, &ret))
2139 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2140 aglat = &(*aglat)->next;
2142 else if (dest_plats->aggs_bottom)
2143 return true;
2146 ret |= set_chain_of_aglats_contains_variable (*aglat);
2148 else
2149 ret |= set_agg_lats_contain_variable (dest_plats);
2151 return ret;
2154 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2155 non-thunk) destination, the call passes through a thunk. */
2157 static bool
2158 call_passes_through_thunk_p (cgraph_edge *cs)
2160 cgraph_node *alias_or_thunk = cs->callee;
2161 while (alias_or_thunk->alias)
2162 alias_or_thunk = alias_or_thunk->get_alias_target ();
2163 return alias_or_thunk->thunk.thunk_p;
2166 /* Propagate constants from the caller to the callee of CS. INFO describes the
2167 caller. */
2169 static bool
2170 propagate_constants_accross_call (struct cgraph_edge *cs)
2172 struct ipa_node_params *callee_info;
2173 enum availability availability;
2174 cgraph_node *callee;
2175 struct ipa_edge_args *args;
2176 bool ret = false;
2177 int i, args_count, parms_count;
2179 callee = cs->callee->function_symbol (&availability);
2180 if (!callee->definition)
2181 return false;
2182 gcc_checking_assert (callee->has_gimple_body_p ());
2183 callee_info = IPA_NODE_REF (callee);
2185 args = IPA_EDGE_REF (cs);
2186 args_count = ipa_get_cs_argument_count (args);
2187 parms_count = ipa_get_param_count (callee_info);
2188 if (parms_count == 0)
2189 return false;
2191 /* No propagation through instrumentation thunks is available yet.
2192 It should be possible with proper mapping of call args and
2193 instrumented callee params in the propagation loop below. But
2194 this case mostly occurs when legacy code calls instrumented code
2195 and it is not a primary target for optimizations.
2196 We detect instrumentation thunks in aliases and thunks chain by
2197 checking instrumentation_clone flag for chain source and target.
2198 Going through instrumentation thunks we always have it changed
2199 from 0 to 1 and all other nodes do not change it. */
2200 if (!cs->callee->instrumentation_clone
2201 && callee->instrumentation_clone)
2203 for (i = 0; i < parms_count; i++)
2204 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2205 i));
2206 return ret;
2209 /* If this call goes through a thunk we must not propagate to the first (0th)
2210 parameter. However, we might need to uncover a thunk from below a series
2211 of aliases first. */
2212 if (call_passes_through_thunk_p (cs))
2214 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2215 0));
2216 i = 1;
2218 else
2219 i = 0;
2221 for (; (i < args_count) && (i < parms_count); i++)
2223 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2224 struct ipcp_param_lattices *dest_plats;
2225 tree param_type = ipa_get_callee_param_type (cs, i);
2227 dest_plats = ipa_get_parm_lattices (callee_info, i);
2228 if (availability == AVAIL_INTERPOSABLE)
2229 ret |= set_all_contains_variable (dest_plats);
2230 else
2232 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
2233 &dest_plats->itself);
2234 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
2235 &dest_plats->ctxlat);
2236 ret |= propagate_bits_accross_jump_function (cs, i, jump_func,
2237 &dest_plats->bits_lattice);
2238 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
2239 dest_plats);
2240 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2241 ret |= propagate_vr_accross_jump_function (cs,
2242 jump_func, dest_plats,
2243 param_type);
2244 else
2245 ret |= dest_plats->m_value_range.set_to_bottom ();
2248 for (; i < parms_count; i++)
2249 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2251 return ret;
2254 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2255 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2256 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2258 static tree
2259 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2260 vec<tree> known_csts,
2261 vec<ipa_polymorphic_call_context> known_contexts,
2262 vec<ipa_agg_jump_function_p> known_aggs,
2263 struct ipa_agg_replacement_value *agg_reps,
2264 bool *speculative)
2266 int param_index = ie->indirect_info->param_index;
2267 HOST_WIDE_INT anc_offset;
2268 tree t;
2269 tree target = NULL;
2271 *speculative = false;
2273 if (param_index == -1
2274 || known_csts.length () <= (unsigned int) param_index)
2275 return NULL_TREE;
2277 if (!ie->indirect_info->polymorphic)
2279 tree t;
2281 if (ie->indirect_info->agg_contents)
2283 t = NULL;
2284 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2286 while (agg_reps)
2288 if (agg_reps->index == param_index
2289 && agg_reps->offset == ie->indirect_info->offset
2290 && agg_reps->by_ref == ie->indirect_info->by_ref)
2292 t = agg_reps->value;
2293 break;
2295 agg_reps = agg_reps->next;
2298 if (!t)
2300 struct ipa_agg_jump_function *agg;
2301 if (known_aggs.length () > (unsigned int) param_index)
2302 agg = known_aggs[param_index];
2303 else
2304 agg = NULL;
2305 bool from_global_constant;
2306 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2307 ie->indirect_info->offset,
2308 ie->indirect_info->by_ref,
2309 &from_global_constant);
2310 if (t
2311 && !from_global_constant
2312 && !ie->indirect_info->guaranteed_unmodified)
2313 t = NULL_TREE;
2316 else
2317 t = known_csts[param_index];
2319 if (t &&
2320 TREE_CODE (t) == ADDR_EXPR
2321 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2322 return TREE_OPERAND (t, 0);
2323 else
2324 return NULL_TREE;
2327 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2328 return NULL_TREE;
2330 gcc_assert (!ie->indirect_info->agg_contents);
2331 anc_offset = ie->indirect_info->offset;
2333 t = NULL;
2335 /* Try to work out value of virtual table pointer value in replacemnets. */
2336 if (!t && agg_reps && !ie->indirect_info->by_ref)
2338 while (agg_reps)
2340 if (agg_reps->index == param_index
2341 && agg_reps->offset == ie->indirect_info->offset
2342 && agg_reps->by_ref)
2344 t = agg_reps->value;
2345 break;
2347 agg_reps = agg_reps->next;
2351 /* Try to work out value of virtual table pointer value in known
2352 aggregate values. */
2353 if (!t && known_aggs.length () > (unsigned int) param_index
2354 && !ie->indirect_info->by_ref)
2356 struct ipa_agg_jump_function *agg;
2357 agg = known_aggs[param_index];
2358 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2359 ie->indirect_info->offset,
2360 true);
2363 /* If we found the virtual table pointer, lookup the target. */
2364 if (t)
2366 tree vtable;
2367 unsigned HOST_WIDE_INT offset;
2368 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2370 bool can_refer;
2371 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2372 vtable, offset, &can_refer);
2373 if (can_refer)
2375 if (!target
2376 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2377 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2378 || !possible_polymorphic_call_target_p
2379 (ie, cgraph_node::get (target)))
2381 /* Do not speculate builtin_unreachable, it is stupid! */
2382 if (ie->indirect_info->vptr_changed)
2383 return NULL;
2384 target = ipa_impossible_devirt_target (ie, target);
2386 *speculative = ie->indirect_info->vptr_changed;
2387 if (!*speculative)
2388 return target;
2393 /* Do we know the constant value of pointer? */
2394 if (!t)
2395 t = known_csts[param_index];
2397 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2399 ipa_polymorphic_call_context context;
2400 if (known_contexts.length () > (unsigned int) param_index)
2402 context = known_contexts[param_index];
2403 context.offset_by (anc_offset);
2404 if (ie->indirect_info->vptr_changed)
2405 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2406 ie->indirect_info->otr_type);
2407 if (t)
2409 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2410 (t, ie->indirect_info->otr_type, anc_offset);
2411 if (!ctx2.useless_p ())
2412 context.combine_with (ctx2, ie->indirect_info->otr_type);
2415 else if (t)
2417 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2418 anc_offset);
2419 if (ie->indirect_info->vptr_changed)
2420 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2421 ie->indirect_info->otr_type);
2423 else
2424 return NULL_TREE;
2426 vec <cgraph_node *>targets;
2427 bool final;
2429 targets = possible_polymorphic_call_targets
2430 (ie->indirect_info->otr_type,
2431 ie->indirect_info->otr_token,
2432 context, &final);
2433 if (!final || targets.length () > 1)
2435 struct cgraph_node *node;
2436 if (*speculative)
2437 return target;
2438 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2439 || ie->speculative || !ie->maybe_hot_p ())
2440 return NULL;
2441 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2442 ie->indirect_info->otr_token,
2443 context);
2444 if (node)
2446 *speculative = true;
2447 target = node->decl;
2449 else
2450 return NULL;
2452 else
2454 *speculative = false;
2455 if (targets.length () == 1)
2456 target = targets[0]->decl;
2457 else
2458 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2461 if (target && !possible_polymorphic_call_target_p (ie,
2462 cgraph_node::get (target)))
2464 if (*speculative)
2465 return NULL;
2466 target = ipa_impossible_devirt_target (ie, target);
2469 return target;
2473 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2474 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2475 return the destination. */
2477 tree
2478 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2479 vec<tree> known_csts,
2480 vec<ipa_polymorphic_call_context> known_contexts,
2481 vec<ipa_agg_jump_function_p> known_aggs,
2482 bool *speculative)
2484 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2485 known_aggs, NULL, speculative);
2488 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2489 and KNOWN_CONTEXTS. */
2491 static int
2492 devirtualization_time_bonus (struct cgraph_node *node,
2493 vec<tree> known_csts,
2494 vec<ipa_polymorphic_call_context> known_contexts,
2495 vec<ipa_agg_jump_function_p> known_aggs)
2497 struct cgraph_edge *ie;
2498 int res = 0;
2500 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2502 struct cgraph_node *callee;
2503 struct inline_summary *isummary;
2504 enum availability avail;
2505 tree target;
2506 bool speculative;
2508 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2509 known_aggs, &speculative);
2510 if (!target)
2511 continue;
2513 /* Only bare minimum benefit for clearly un-inlineable targets. */
2514 res += 1;
2515 callee = cgraph_node::get (target);
2516 if (!callee || !callee->definition)
2517 continue;
2518 callee = callee->function_symbol (&avail);
2519 if (avail < AVAIL_AVAILABLE)
2520 continue;
2521 isummary = inline_summaries->get (callee);
2522 if (!isummary->inlinable)
2523 continue;
2525 /* FIXME: The values below need re-considering and perhaps also
2526 integrating into the cost metrics, at lest in some very basic way. */
2527 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2528 res += 31 / ((int)speculative + 1);
2529 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2530 res += 15 / ((int)speculative + 1);
2531 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2532 || DECL_DECLARED_INLINE_P (callee->decl))
2533 res += 7 / ((int)speculative + 1);
2536 return res;
2539 /* Return time bonus incurred because of HINTS. */
2541 static int
2542 hint_time_bonus (inline_hints hints)
2544 int result = 0;
2545 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2546 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2547 if (hints & INLINE_HINT_array_index)
2548 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2549 return result;
2552 /* If there is a reason to penalize the function described by INFO in the
2553 cloning goodness evaluation, do so. */
2555 static inline int64_t
2556 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2558 if (info->node_within_scc)
2559 evaluation = (evaluation
2560 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2562 if (info->node_calling_single_call)
2563 evaluation = (evaluation
2564 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2565 / 100;
2567 return evaluation;
2570 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2571 and SIZE_COST and with the sum of frequencies of incoming edges to the
2572 potential new clone in FREQUENCIES. */
2574 static bool
2575 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2576 int freq_sum, gcov_type count_sum, int size_cost)
2578 if (time_benefit == 0
2579 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2580 || node->optimize_for_size_p ())
2581 return false;
2583 gcc_assert (size_cost > 0);
2585 struct ipa_node_params *info = IPA_NODE_REF (node);
2586 if (max_count)
2588 int factor = (count_sum * 1000) / max_count;
2589 int64_t evaluation = (((int64_t) time_benefit * factor)
2590 / size_cost);
2591 evaluation = incorporate_penalties (info, evaluation);
2593 if (dump_file && (dump_flags & TDF_DETAILS))
2594 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2595 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2596 "%s%s) -> evaluation: " "%" PRId64
2597 ", threshold: %i\n",
2598 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2599 info->node_within_scc ? ", scc" : "",
2600 info->node_calling_single_call ? ", single_call" : "",
2601 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2603 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2605 else
2607 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2608 / size_cost);
2609 evaluation = incorporate_penalties (info, evaluation);
2611 if (dump_file && (dump_flags & TDF_DETAILS))
2612 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2613 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2614 "%" PRId64 ", threshold: %i\n",
2615 time_benefit, size_cost, freq_sum,
2616 info->node_within_scc ? ", scc" : "",
2617 info->node_calling_single_call ? ", single_call" : "",
2618 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2620 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2624 /* Return all context independent values from aggregate lattices in PLATS in a
2625 vector. Return NULL if there are none. */
2627 static vec<ipa_agg_jf_item, va_gc> *
2628 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2630 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2632 if (plats->aggs_bottom
2633 || plats->aggs_contain_variable
2634 || plats->aggs_count == 0)
2635 return NULL;
2637 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2638 aglat;
2639 aglat = aglat->next)
2640 if (aglat->is_single_const ())
2642 struct ipa_agg_jf_item item;
2643 item.offset = aglat->offset;
2644 item.value = aglat->values->value;
2645 vec_safe_push (res, item);
2647 return res;
2650 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2651 populate them with values of parameters that are known independent of the
2652 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2653 non-NULL, the movement cost of all removable parameters will be stored in
2654 it. */
2656 static bool
2657 gather_context_independent_values (struct ipa_node_params *info,
2658 vec<tree> *known_csts,
2659 vec<ipa_polymorphic_call_context>
2660 *known_contexts,
2661 vec<ipa_agg_jump_function> *known_aggs,
2662 int *removable_params_cost)
2664 int i, count = ipa_get_param_count (info);
2665 bool ret = false;
2667 known_csts->create (0);
2668 known_contexts->create (0);
2669 known_csts->safe_grow_cleared (count);
2670 known_contexts->safe_grow_cleared (count);
2671 if (known_aggs)
2673 known_aggs->create (0);
2674 known_aggs->safe_grow_cleared (count);
2677 if (removable_params_cost)
2678 *removable_params_cost = 0;
2680 for (i = 0; i < count ; i++)
2682 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2683 ipcp_lattice<tree> *lat = &plats->itself;
2685 if (lat->is_single_const ())
2687 ipcp_value<tree> *val = lat->values;
2688 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2689 (*known_csts)[i] = val->value;
2690 if (removable_params_cost)
2691 *removable_params_cost
2692 += estimate_move_cost (TREE_TYPE (val->value), false);
2693 ret = true;
2695 else if (removable_params_cost
2696 && !ipa_is_param_used (info, i))
2697 *removable_params_cost
2698 += ipa_get_param_move_cost (info, i);
2700 if (!ipa_is_param_used (info, i))
2701 continue;
2703 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2704 /* Do not account known context as reason for cloning. We can see
2705 if it permits devirtualization. */
2706 if (ctxlat->is_single_const ())
2707 (*known_contexts)[i] = ctxlat->values->value;
2709 if (known_aggs)
2711 vec<ipa_agg_jf_item, va_gc> *agg_items;
2712 struct ipa_agg_jump_function *ajf;
2714 agg_items = context_independent_aggregate_values (plats);
2715 ajf = &(*known_aggs)[i];
2716 ajf->items = agg_items;
2717 ajf->by_ref = plats->aggs_by_ref;
2718 ret |= agg_items != NULL;
2722 return ret;
2725 /* The current interface in ipa-inline-analysis requires a pointer vector.
2726 Create it.
2728 FIXME: That interface should be re-worked, this is slightly silly. Still,
2729 I'd like to discuss how to change it first and this demonstrates the
2730 issue. */
2732 static vec<ipa_agg_jump_function_p>
2733 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2735 vec<ipa_agg_jump_function_p> ret;
2736 struct ipa_agg_jump_function *ajf;
2737 int i;
2739 ret.create (known_aggs.length ());
2740 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2741 ret.quick_push (ajf);
2742 return ret;
2745 /* Perform time and size measurement of NODE with the context given in
2746 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2747 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2748 all context-independent removable parameters and EST_MOVE_COST of estimated
2749 movement of the considered parameter and store it into VAL. */
2751 static void
2752 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2753 vec<ipa_polymorphic_call_context> known_contexts,
2754 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2755 int base_time, int removable_params_cost,
2756 int est_move_cost, ipcp_value_base *val)
2758 int time, size, time_benefit;
2759 inline_hints hints;
2761 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2762 known_aggs_ptrs, &size, &time,
2763 &hints);
2764 time_benefit = base_time - time
2765 + devirtualization_time_bonus (node, known_csts, known_contexts,
2766 known_aggs_ptrs)
2767 + hint_time_bonus (hints)
2768 + removable_params_cost + est_move_cost;
2770 gcc_checking_assert (size >=0);
2771 /* The inliner-heuristics based estimates may think that in certain
2772 contexts some functions do not have any size at all but we want
2773 all specializations to have at least a tiny cost, not least not to
2774 divide by zero. */
2775 if (size == 0)
2776 size = 1;
2778 val->local_time_benefit = time_benefit;
2779 val->local_size_cost = size;
2782 /* Iterate over known values of parameters of NODE and estimate the local
2783 effects in terms of time and size they have. */
2785 static void
2786 estimate_local_effects (struct cgraph_node *node)
2788 struct ipa_node_params *info = IPA_NODE_REF (node);
2789 int i, count = ipa_get_param_count (info);
2790 vec<tree> known_csts;
2791 vec<ipa_polymorphic_call_context> known_contexts;
2792 vec<ipa_agg_jump_function> known_aggs;
2793 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2794 bool always_const;
2795 int base_time = inline_summaries->get (node)->time;
2796 int removable_params_cost;
2798 if (!count || !ipcp_versionable_function_p (node))
2799 return;
2801 if (dump_file && (dump_flags & TDF_DETAILS))
2802 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2803 node->name (), node->order, base_time);
2805 always_const = gather_context_independent_values (info, &known_csts,
2806 &known_contexts, &known_aggs,
2807 &removable_params_cost);
2808 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2809 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2810 known_contexts, known_aggs_ptrs);
2811 if (always_const || devirt_bonus
2812 || (removable_params_cost && node->local.can_change_signature))
2814 struct caller_statistics stats;
2815 inline_hints hints;
2816 int time, size;
2818 init_caller_stats (&stats);
2819 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2820 false);
2821 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2822 known_aggs_ptrs, &size, &time, &hints);
2823 time -= devirt_bonus;
2824 time -= hint_time_bonus (hints);
2825 time -= removable_params_cost;
2826 size -= stats.n_calls * removable_params_cost;
2828 if (dump_file)
2829 fprintf (dump_file, " - context independent values, size: %i, "
2830 "time_benefit: %i\n", size, base_time - time);
2832 if (size <= 0 || node->local.local)
2834 info->do_clone_for_all_contexts = true;
2835 base_time = time;
2837 if (dump_file)
2838 fprintf (dump_file, " Decided to specialize for all "
2839 "known contexts, code not going to grow.\n");
2841 else if (good_cloning_opportunity_p (node, base_time - time,
2842 stats.freq_sum, stats.count_sum,
2843 size))
2845 if (size + overall_size <= max_new_size)
2847 info->do_clone_for_all_contexts = true;
2848 base_time = time;
2849 overall_size += size;
2851 if (dump_file)
2852 fprintf (dump_file, " Decided to specialize for all "
2853 "known contexts, growth deemed beneficial.\n");
2855 else if (dump_file && (dump_flags & TDF_DETAILS))
2856 fprintf (dump_file, " Not cloning for all contexts because "
2857 "max_new_size would be reached with %li.\n",
2858 size + overall_size);
2860 else if (dump_file && (dump_flags & TDF_DETAILS))
2861 fprintf (dump_file, " Not cloning for all contexts because "
2862 "!good_cloning_opportunity_p.\n");
2866 for (i = 0; i < count ; i++)
2868 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2869 ipcp_lattice<tree> *lat = &plats->itself;
2870 ipcp_value<tree> *val;
2872 if (lat->bottom
2873 || !lat->values
2874 || known_csts[i])
2875 continue;
2877 for (val = lat->values; val; val = val->next)
2879 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2880 known_csts[i] = val->value;
2882 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2883 perform_estimation_of_a_value (node, known_csts, known_contexts,
2884 known_aggs_ptrs, base_time,
2885 removable_params_cost, emc, val);
2887 if (dump_file && (dump_flags & TDF_DETAILS))
2889 fprintf (dump_file, " - estimates for value ");
2890 print_ipcp_constant_value (dump_file, val->value);
2891 fprintf (dump_file, " for ");
2892 ipa_dump_param (dump_file, info, i);
2893 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2894 val->local_time_benefit, val->local_size_cost);
2897 known_csts[i] = NULL_TREE;
2900 for (i = 0; i < count; i++)
2902 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2904 if (!plats->virt_call)
2905 continue;
2907 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2908 ipcp_value<ipa_polymorphic_call_context> *val;
2910 if (ctxlat->bottom
2911 || !ctxlat->values
2912 || !known_contexts[i].useless_p ())
2913 continue;
2915 for (val = ctxlat->values; val; val = val->next)
2917 known_contexts[i] = val->value;
2918 perform_estimation_of_a_value (node, known_csts, known_contexts,
2919 known_aggs_ptrs, base_time,
2920 removable_params_cost, 0, val);
2922 if (dump_file && (dump_flags & TDF_DETAILS))
2924 fprintf (dump_file, " - estimates for polymorphic context ");
2925 print_ipcp_constant_value (dump_file, val->value);
2926 fprintf (dump_file, " for ");
2927 ipa_dump_param (dump_file, info, i);
2928 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2929 val->local_time_benefit, val->local_size_cost);
2932 known_contexts[i] = ipa_polymorphic_call_context ();
2935 for (i = 0; i < count ; i++)
2937 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2938 struct ipa_agg_jump_function *ajf;
2939 struct ipcp_agg_lattice *aglat;
2941 if (plats->aggs_bottom || !plats->aggs)
2942 continue;
2944 ajf = &known_aggs[i];
2945 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2947 ipcp_value<tree> *val;
2948 if (aglat->bottom || !aglat->values
2949 /* If the following is true, the one value is in known_aggs. */
2950 || (!plats->aggs_contain_variable
2951 && aglat->is_single_const ()))
2952 continue;
2954 for (val = aglat->values; val; val = val->next)
2956 struct ipa_agg_jf_item item;
2958 item.offset = aglat->offset;
2959 item.value = val->value;
2960 vec_safe_push (ajf->items, item);
2962 perform_estimation_of_a_value (node, known_csts, known_contexts,
2963 known_aggs_ptrs, base_time,
2964 removable_params_cost, 0, val);
2966 if (dump_file && (dump_flags & TDF_DETAILS))
2968 fprintf (dump_file, " - estimates for value ");
2969 print_ipcp_constant_value (dump_file, val->value);
2970 fprintf (dump_file, " for ");
2971 ipa_dump_param (dump_file, info, i);
2972 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2973 "]: time_benefit: %i, size: %i\n",
2974 plats->aggs_by_ref ? "ref " : "",
2975 aglat->offset,
2976 val->local_time_benefit, val->local_size_cost);
2979 ajf->items->pop ();
2984 for (i = 0; i < count ; i++)
2985 vec_free (known_aggs[i].items);
2987 known_csts.release ();
2988 known_contexts.release ();
2989 known_aggs.release ();
2990 known_aggs_ptrs.release ();
2994 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2995 topological sort of values. */
2997 template <typename valtype>
2998 void
2999 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3001 ipcp_value_source<valtype> *src;
3003 if (cur_val->dfs)
3004 return;
3006 dfs_counter++;
3007 cur_val->dfs = dfs_counter;
3008 cur_val->low_link = dfs_counter;
3010 cur_val->topo_next = stack;
3011 stack = cur_val;
3012 cur_val->on_stack = true;
3014 for (src = cur_val->sources; src; src = src->next)
3015 if (src->val)
3017 if (src->val->dfs == 0)
3019 add_val (src->val);
3020 if (src->val->low_link < cur_val->low_link)
3021 cur_val->low_link = src->val->low_link;
3023 else if (src->val->on_stack
3024 && src->val->dfs < cur_val->low_link)
3025 cur_val->low_link = src->val->dfs;
3028 if (cur_val->dfs == cur_val->low_link)
3030 ipcp_value<valtype> *v, *scc_list = NULL;
3034 v = stack;
3035 stack = v->topo_next;
3036 v->on_stack = false;
3038 v->scc_next = scc_list;
3039 scc_list = v;
3041 while (v != cur_val);
3043 cur_val->topo_next = values_topo;
3044 values_topo = cur_val;
3048 /* Add all values in lattices associated with NODE to the topological sort if
3049 they are not there yet. */
3051 static void
3052 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3054 struct ipa_node_params *info = IPA_NODE_REF (node);
3055 int i, count = ipa_get_param_count (info);
3057 for (i = 0; i < count ; i++)
3059 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3060 ipcp_lattice<tree> *lat = &plats->itself;
3061 struct ipcp_agg_lattice *aglat;
3063 if (!lat->bottom)
3065 ipcp_value<tree> *val;
3066 for (val = lat->values; val; val = val->next)
3067 topo->constants.add_val (val);
3070 if (!plats->aggs_bottom)
3071 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3072 if (!aglat->bottom)
3074 ipcp_value<tree> *val;
3075 for (val = aglat->values; val; val = val->next)
3076 topo->constants.add_val (val);
3079 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3080 if (!ctxlat->bottom)
3082 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3083 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3084 topo->contexts.add_val (ctxval);
3089 /* One pass of constants propagation along the call graph edges, from callers
3090 to callees (requires topological ordering in TOPO), iterate over strongly
3091 connected components. */
3093 static void
3094 propagate_constants_topo (struct ipa_topo_info *topo)
3096 int i;
3098 for (i = topo->nnodes - 1; i >= 0; i--)
3100 unsigned j;
3101 struct cgraph_node *v, *node = topo->order[i];
3102 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3104 /* First, iteratively propagate within the strongly connected component
3105 until all lattices stabilize. */
3106 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3107 if (v->has_gimple_body_p ())
3108 push_node_to_stack (topo, v);
3110 v = pop_node_from_stack (topo);
3111 while (v)
3113 struct cgraph_edge *cs;
3115 for (cs = v->callees; cs; cs = cs->next_callee)
3116 if (ipa_edge_within_scc (cs))
3118 IPA_NODE_REF (v)->node_within_scc = true;
3119 if (propagate_constants_accross_call (cs))
3120 push_node_to_stack (topo, cs->callee->function_symbol ());
3122 v = pop_node_from_stack (topo);
3125 /* Afterwards, propagate along edges leading out of the SCC, calculates
3126 the local effects of the discovered constants and all valid values to
3127 their topological sort. */
3128 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3129 if (v->has_gimple_body_p ())
3131 struct cgraph_edge *cs;
3133 estimate_local_effects (v);
3134 add_all_node_vals_to_toposort (v, topo);
3135 for (cs = v->callees; cs; cs = cs->next_callee)
3136 if (!ipa_edge_within_scc (cs))
3137 propagate_constants_accross_call (cs);
3139 cycle_nodes.release ();
3144 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3145 the bigger one if otherwise. */
3147 static int
3148 safe_add (int a, int b)
3150 if (a > INT_MAX/2 || b > INT_MAX/2)
3151 return a > b ? a : b;
3152 else
3153 return a + b;
3157 /* Propagate the estimated effects of individual values along the topological
3158 from the dependent values to those they depend on. */
3160 template <typename valtype>
3161 void
3162 value_topo_info<valtype>::propagate_effects ()
3164 ipcp_value<valtype> *base;
3166 for (base = values_topo; base; base = base->topo_next)
3168 ipcp_value_source<valtype> *src;
3169 ipcp_value<valtype> *val;
3170 int time = 0, size = 0;
3172 for (val = base; val; val = val->scc_next)
3174 time = safe_add (time,
3175 val->local_time_benefit + val->prop_time_benefit);
3176 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3179 for (val = base; val; val = val->scc_next)
3180 for (src = val->sources; src; src = src->next)
3181 if (src->val
3182 && src->cs->maybe_hot_p ())
3184 src->val->prop_time_benefit = safe_add (time,
3185 src->val->prop_time_benefit);
3186 src->val->prop_size_cost = safe_add (size,
3187 src->val->prop_size_cost);
3193 /* Propagate constants, polymorphic contexts and their effects from the
3194 summaries interprocedurally. */
3196 static void
3197 ipcp_propagate_stage (struct ipa_topo_info *topo)
3199 struct cgraph_node *node;
3201 if (dump_file)
3202 fprintf (dump_file, "\n Propagating constants:\n\n");
3204 if (in_lto_p)
3205 ipa_update_after_lto_read ();
3208 FOR_EACH_DEFINED_FUNCTION (node)
3210 struct ipa_node_params *info = IPA_NODE_REF (node);
3212 /* In LTO we do not have PARM_DECLs but we would still like to be able to
3213 look at types of parameters. */
3214 if (in_lto_p)
3216 tree t = TYPE_ARG_TYPES (TREE_TYPE (node->decl));
3217 for (int k = 0; k < ipa_get_param_count (info) && t; k++)
3219 gcc_assert (t != void_list_node);
3220 info->descriptors[k].decl_or_type = TREE_VALUE (t);
3221 t = t ? TREE_CHAIN (t) : NULL;
3225 determine_versionability (node, info);
3226 if (node->has_gimple_body_p ())
3228 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3229 ipa_get_param_count (info));
3230 initialize_node_lattices (node);
3232 if (node->definition && !node->alias)
3233 overall_size += inline_summaries->get (node)->self_size;
3234 if (node->count > max_count)
3235 max_count = node->count;
3238 max_new_size = overall_size;
3239 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3240 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3241 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3243 if (dump_file)
3244 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3245 overall_size, max_new_size);
3247 propagate_constants_topo (topo);
3248 if (flag_checking)
3249 ipcp_verify_propagated_values ();
3250 topo->constants.propagate_effects ();
3251 topo->contexts.propagate_effects ();
3253 if (dump_file)
3255 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3256 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3260 /* Discover newly direct outgoing edges from NODE which is a new clone with
3261 known KNOWN_CSTS and make them direct. */
3263 static void
3264 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3265 vec<tree> known_csts,
3266 vec<ipa_polymorphic_call_context>
3267 known_contexts,
3268 struct ipa_agg_replacement_value *aggvals)
3270 struct cgraph_edge *ie, *next_ie;
3271 bool found = false;
3273 for (ie = node->indirect_calls; ie; ie = next_ie)
3275 tree target;
3276 bool speculative;
3278 next_ie = ie->next_callee;
3279 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3280 vNULL, aggvals, &speculative);
3281 if (target)
3283 bool agg_contents = ie->indirect_info->agg_contents;
3284 bool polymorphic = ie->indirect_info->polymorphic;
3285 int param_index = ie->indirect_info->param_index;
3286 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3287 speculative);
3288 found = true;
3290 if (cs && !agg_contents && !polymorphic)
3292 struct ipa_node_params *info = IPA_NODE_REF (node);
3293 int c = ipa_get_controlled_uses (info, param_index);
3294 if (c != IPA_UNDESCRIBED_USE)
3296 struct ipa_ref *to_del;
3298 c--;
3299 ipa_set_controlled_uses (info, param_index, c);
3300 if (dump_file && (dump_flags & TDF_DETAILS))
3301 fprintf (dump_file, " controlled uses count of param "
3302 "%i bumped down to %i\n", param_index, c);
3303 if (c == 0
3304 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3306 if (dump_file && (dump_flags & TDF_DETAILS))
3307 fprintf (dump_file, " and even removing its "
3308 "cloning-created reference\n");
3309 to_del->remove_reference ();
3315 /* Turning calls to direct calls will improve overall summary. */
3316 if (found)
3317 inline_update_overall_summary (node);
3320 /* Vector of pointers which for linked lists of clones of an original crgaph
3321 edge. */
3323 static vec<cgraph_edge *> next_edge_clone;
3324 static vec<cgraph_edge *> prev_edge_clone;
3326 static inline void
3327 grow_edge_clone_vectors (void)
3329 if (next_edge_clone.length ()
3330 <= (unsigned) symtab->edges_max_uid)
3331 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3332 if (prev_edge_clone.length ()
3333 <= (unsigned) symtab->edges_max_uid)
3334 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3337 /* Edge duplication hook to grow the appropriate linked list in
3338 next_edge_clone. */
3340 static void
3341 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
3342 void *)
3344 grow_edge_clone_vectors ();
3346 struct cgraph_edge *old_next = next_edge_clone[src->uid];
3347 if (old_next)
3348 prev_edge_clone[old_next->uid] = dst;
3349 prev_edge_clone[dst->uid] = src;
3351 next_edge_clone[dst->uid] = old_next;
3352 next_edge_clone[src->uid] = dst;
3355 /* Hook that is called by cgraph.c when an edge is removed. */
3357 static void
3358 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
3360 grow_edge_clone_vectors ();
3362 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
3363 struct cgraph_edge *next = next_edge_clone[cs->uid];
3364 if (prev)
3365 next_edge_clone[prev->uid] = next;
3366 if (next)
3367 prev_edge_clone[next->uid] = prev;
3370 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3371 parameter with the given INDEX. */
3373 static tree
3374 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3375 int index)
3377 struct ipa_agg_replacement_value *aggval;
3379 aggval = ipa_get_agg_replacements_for_node (node);
3380 while (aggval)
3382 if (aggval->offset == offset
3383 && aggval->index == index)
3384 return aggval->value;
3385 aggval = aggval->next;
3387 return NULL_TREE;
3390 /* Return true is NODE is DEST or its clone for all contexts. */
3392 static bool
3393 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3395 if (node == dest)
3396 return true;
3398 struct ipa_node_params *info = IPA_NODE_REF (node);
3399 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3402 /* Return true if edge CS does bring about the value described by SRC to node
3403 DEST or its clone for all contexts. */
3405 static bool
3406 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3407 cgraph_node *dest)
3409 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3410 enum availability availability;
3411 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3413 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3414 || availability <= AVAIL_INTERPOSABLE
3415 || caller_info->node_dead)
3416 return false;
3417 if (!src->val)
3418 return true;
3420 if (caller_info->ipcp_orig_node)
3422 tree t;
3423 if (src->offset == -1)
3424 t = caller_info->known_csts[src->index];
3425 else
3426 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3427 return (t != NULL_TREE
3428 && values_equal_for_ipcp_p (src->val->value, t));
3430 else
3432 struct ipcp_agg_lattice *aglat;
3433 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3434 src->index);
3435 if (src->offset == -1)
3436 return (plats->itself.is_single_const ()
3437 && values_equal_for_ipcp_p (src->val->value,
3438 plats->itself.values->value));
3439 else
3441 if (plats->aggs_bottom || plats->aggs_contain_variable)
3442 return false;
3443 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3444 if (aglat->offset == src->offset)
3445 return (aglat->is_single_const ()
3446 && values_equal_for_ipcp_p (src->val->value,
3447 aglat->values->value));
3449 return false;
3453 /* Return true if edge CS does bring about the value described by SRC to node
3454 DEST or its clone for all contexts. */
3456 static bool
3457 cgraph_edge_brings_value_p (cgraph_edge *cs,
3458 ipcp_value_source<ipa_polymorphic_call_context> *src,
3459 cgraph_node *dest)
3461 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3462 cgraph_node *real_dest = cs->callee->function_symbol ();
3464 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3465 || caller_info->node_dead)
3466 return false;
3467 if (!src->val)
3468 return true;
3470 if (caller_info->ipcp_orig_node)
3471 return (caller_info->known_contexts.length () > (unsigned) src->index)
3472 && values_equal_for_ipcp_p (src->val->value,
3473 caller_info->known_contexts[src->index]);
3475 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3476 src->index);
3477 return plats->ctxlat.is_single_const ()
3478 && values_equal_for_ipcp_p (src->val->value,
3479 plats->ctxlat.values->value);
3482 /* Get the next clone in the linked list of clones of an edge. */
3484 static inline struct cgraph_edge *
3485 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3487 return next_edge_clone[cs->uid];
3490 /* Given VAL that is intended for DEST, iterate over all its sources and if
3491 they still hold, add their edge frequency and their number into *FREQUENCY
3492 and *CALLER_COUNT respectively. */
3494 template <typename valtype>
3495 static bool
3496 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3497 int *freq_sum,
3498 gcov_type *count_sum, int *caller_count)
3500 ipcp_value_source<valtype> *src;
3501 int freq = 0, count = 0;
3502 gcov_type cnt = 0;
3503 bool hot = false;
3505 for (src = val->sources; src; src = src->next)
3507 struct cgraph_edge *cs = src->cs;
3508 while (cs)
3510 if (cgraph_edge_brings_value_p (cs, src, dest))
3512 count++;
3513 freq += cs->frequency;
3514 cnt += cs->count;
3515 hot |= cs->maybe_hot_p ();
3517 cs = get_next_cgraph_edge_clone (cs);
3521 *freq_sum = freq;
3522 *count_sum = cnt;
3523 *caller_count = count;
3524 return hot;
3527 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3528 is assumed their number is known and equal to CALLER_COUNT. */
3530 template <typename valtype>
3531 static vec<cgraph_edge *>
3532 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3533 int caller_count)
3535 ipcp_value_source<valtype> *src;
3536 vec<cgraph_edge *> ret;
3538 ret.create (caller_count);
3539 for (src = val->sources; src; src = src->next)
3541 struct cgraph_edge *cs = src->cs;
3542 while (cs)
3544 if (cgraph_edge_brings_value_p (cs, src, dest))
3545 ret.quick_push (cs);
3546 cs = get_next_cgraph_edge_clone (cs);
3550 return ret;
3553 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3554 Return it or NULL if for some reason it cannot be created. */
3556 static struct ipa_replace_map *
3557 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3559 struct ipa_replace_map *replace_map;
3562 replace_map = ggc_alloc<ipa_replace_map> ();
3563 if (dump_file)
3565 fprintf (dump_file, " replacing ");
3566 ipa_dump_param (dump_file, info, parm_num);
3568 fprintf (dump_file, " with const ");
3569 print_generic_expr (dump_file, value, 0);
3570 fprintf (dump_file, "\n");
3572 replace_map->old_tree = NULL;
3573 replace_map->parm_num = parm_num;
3574 replace_map->new_tree = value;
3575 replace_map->replace_p = true;
3576 replace_map->ref_p = false;
3578 return replace_map;
3581 /* Dump new profiling counts */
3583 static void
3584 dump_profile_updates (struct cgraph_node *orig_node,
3585 struct cgraph_node *new_node)
3587 struct cgraph_edge *cs;
3589 fprintf (dump_file, " setting count of the specialized node to "
3590 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3591 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3592 fprintf (dump_file, " edge to %s has count "
3593 HOST_WIDE_INT_PRINT_DEC "\n",
3594 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3596 fprintf (dump_file, " setting count of the original node to "
3597 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3598 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3599 fprintf (dump_file, " edge to %s is left with "
3600 HOST_WIDE_INT_PRINT_DEC "\n",
3601 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3604 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3605 their profile information to reflect this. */
3607 static void
3608 update_profiling_info (struct cgraph_node *orig_node,
3609 struct cgraph_node *new_node)
3611 struct cgraph_edge *cs;
3612 struct caller_statistics stats;
3613 gcov_type new_sum, orig_sum;
3614 gcov_type remainder, orig_node_count = orig_node->count;
3616 if (orig_node_count == 0)
3617 return;
3619 init_caller_stats (&stats);
3620 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3621 false);
3622 orig_sum = stats.count_sum;
3623 init_caller_stats (&stats);
3624 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3625 false);
3626 new_sum = stats.count_sum;
3628 if (orig_node_count < orig_sum + new_sum)
3630 if (dump_file)
3631 fprintf (dump_file, " Problem: node %s/%i has too low count "
3632 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3633 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3634 orig_node->name (), orig_node->order,
3635 (HOST_WIDE_INT) orig_node_count,
3636 (HOST_WIDE_INT) (orig_sum + new_sum));
3638 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3639 if (dump_file)
3640 fprintf (dump_file, " proceeding by pretending it was "
3641 HOST_WIDE_INT_PRINT_DEC "\n",
3642 (HOST_WIDE_INT) orig_node_count);
3645 new_node->count = new_sum;
3646 remainder = orig_node_count - new_sum;
3647 orig_node->count = remainder;
3649 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3650 if (cs->frequency)
3651 cs->count = apply_probability (cs->count,
3652 GCOV_COMPUTE_SCALE (new_sum,
3653 orig_node_count));
3654 else
3655 cs->count = 0;
3657 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3658 cs->count = apply_probability (cs->count,
3659 GCOV_COMPUTE_SCALE (remainder,
3660 orig_node_count));
3662 if (dump_file)
3663 dump_profile_updates (orig_node, new_node);
3666 /* Update the respective profile of specialized NEW_NODE and the original
3667 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3668 have been redirected to the specialized version. */
3670 static void
3671 update_specialized_profile (struct cgraph_node *new_node,
3672 struct cgraph_node *orig_node,
3673 gcov_type redirected_sum)
3675 struct cgraph_edge *cs;
3676 gcov_type new_node_count, orig_node_count = orig_node->count;
3678 if (dump_file)
3679 fprintf (dump_file, " the sum of counts of redirected edges is "
3680 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3681 if (orig_node_count == 0)
3682 return;
3684 gcc_assert (orig_node_count >= redirected_sum);
3686 new_node_count = new_node->count;
3687 new_node->count += redirected_sum;
3688 orig_node->count -= redirected_sum;
3690 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3691 if (cs->frequency)
3692 cs->count += apply_probability (cs->count,
3693 GCOV_COMPUTE_SCALE (redirected_sum,
3694 new_node_count));
3695 else
3696 cs->count = 0;
3698 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3700 gcov_type dec = apply_probability (cs->count,
3701 GCOV_COMPUTE_SCALE (redirected_sum,
3702 orig_node_count));
3703 if (dec < cs->count)
3704 cs->count -= dec;
3705 else
3706 cs->count = 0;
3709 if (dump_file)
3710 dump_profile_updates (orig_node, new_node);
3713 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3714 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3715 redirect all edges in CALLERS to it. */
3717 static struct cgraph_node *
3718 create_specialized_node (struct cgraph_node *node,
3719 vec<tree> known_csts,
3720 vec<ipa_polymorphic_call_context> known_contexts,
3721 struct ipa_agg_replacement_value *aggvals,
3722 vec<cgraph_edge *> callers)
3724 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3725 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3726 struct ipa_agg_replacement_value *av;
3727 struct cgraph_node *new_node;
3728 int i, count = ipa_get_param_count (info);
3729 bitmap args_to_skip;
3731 gcc_assert (!info->ipcp_orig_node);
3733 if (node->local.can_change_signature)
3735 args_to_skip = BITMAP_GGC_ALLOC ();
3736 for (i = 0; i < count; i++)
3738 tree t = known_csts[i];
3740 if (t || !ipa_is_param_used (info, i))
3741 bitmap_set_bit (args_to_skip, i);
3744 else
3746 args_to_skip = NULL;
3747 if (dump_file && (dump_flags & TDF_DETAILS))
3748 fprintf (dump_file, " cannot change function signature\n");
3751 for (i = 0; i < count ; i++)
3753 tree t = known_csts[i];
3754 if (t)
3756 struct ipa_replace_map *replace_map;
3758 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3759 replace_map = get_replacement_map (info, t, i);
3760 if (replace_map)
3761 vec_safe_push (replace_trees, replace_map);
3765 new_node = node->create_virtual_clone (callers, replace_trees,
3766 args_to_skip, "constprop");
3767 ipa_set_node_agg_value_chain (new_node, aggvals);
3768 for (av = aggvals; av; av = av->next)
3769 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3771 if (dump_file && (dump_flags & TDF_DETAILS))
3773 fprintf (dump_file, " the new node is %s/%i.\n",
3774 new_node->name (), new_node->order);
3775 if (known_contexts.exists ())
3777 for (i = 0; i < count ; i++)
3778 if (!known_contexts[i].useless_p ())
3780 fprintf (dump_file, " known ctx %i is ", i);
3781 known_contexts[i].dump (dump_file);
3784 if (aggvals)
3785 ipa_dump_agg_replacement_values (dump_file, aggvals);
3787 ipa_check_create_node_params ();
3788 update_profiling_info (node, new_node);
3789 new_info = IPA_NODE_REF (new_node);
3790 new_info->ipcp_orig_node = node;
3791 new_info->known_csts = known_csts;
3792 new_info->known_contexts = known_contexts;
3794 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3796 callers.release ();
3797 return new_node;
3800 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3801 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3803 static void
3804 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3805 vec<tree> known_csts,
3806 vec<cgraph_edge *> callers)
3808 struct ipa_node_params *info = IPA_NODE_REF (node);
3809 int i, count = ipa_get_param_count (info);
3811 for (i = 0; i < count ; i++)
3813 struct cgraph_edge *cs;
3814 tree newval = NULL_TREE;
3815 int j;
3816 bool first = true;
3818 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3819 continue;
3821 FOR_EACH_VEC_ELT (callers, j, cs)
3823 struct ipa_jump_func *jump_func;
3824 tree t;
3826 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3827 || (i == 0
3828 && call_passes_through_thunk_p (cs))
3829 || (!cs->callee->instrumentation_clone
3830 && cs->callee->function_symbol ()->instrumentation_clone))
3832 newval = NULL_TREE;
3833 break;
3835 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3836 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3837 if (!t
3838 || (newval
3839 && !values_equal_for_ipcp_p (t, newval))
3840 || (!first && !newval))
3842 newval = NULL_TREE;
3843 break;
3845 else
3846 newval = t;
3847 first = false;
3850 if (newval)
3852 if (dump_file && (dump_flags & TDF_DETAILS))
3854 fprintf (dump_file, " adding an extra known scalar value ");
3855 print_ipcp_constant_value (dump_file, newval);
3856 fprintf (dump_file, " for ");
3857 ipa_dump_param (dump_file, info, i);
3858 fprintf (dump_file, "\n");
3861 known_csts[i] = newval;
3866 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3867 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3868 CALLERS. */
3870 static void
3871 find_more_contexts_for_caller_subset (cgraph_node *node,
3872 vec<ipa_polymorphic_call_context>
3873 *known_contexts,
3874 vec<cgraph_edge *> callers)
3876 ipa_node_params *info = IPA_NODE_REF (node);
3877 int i, count = ipa_get_param_count (info);
3879 for (i = 0; i < count ; i++)
3881 cgraph_edge *cs;
3883 if (ipa_get_poly_ctx_lat (info, i)->bottom
3884 || (known_contexts->exists ()
3885 && !(*known_contexts)[i].useless_p ()))
3886 continue;
3888 ipa_polymorphic_call_context newval;
3889 bool first = true;
3890 int j;
3892 FOR_EACH_VEC_ELT (callers, j, cs)
3894 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3895 return;
3896 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3898 ipa_polymorphic_call_context ctx;
3899 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3900 jfunc);
3901 if (first)
3903 newval = ctx;
3904 first = false;
3906 else
3907 newval.meet_with (ctx);
3908 if (newval.useless_p ())
3909 break;
3912 if (!newval.useless_p ())
3914 if (dump_file && (dump_flags & TDF_DETAILS))
3916 fprintf (dump_file, " adding an extra known polymorphic "
3917 "context ");
3918 print_ipcp_constant_value (dump_file, newval);
3919 fprintf (dump_file, " for ");
3920 ipa_dump_param (dump_file, info, i);
3921 fprintf (dump_file, "\n");
3924 if (!known_contexts->exists ())
3925 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3926 (*known_contexts)[i] = newval;
3932 /* Go through PLATS and create a vector of values consisting of values and
3933 offsets (minus OFFSET) of lattices that contain only a single value. */
3935 static vec<ipa_agg_jf_item>
3936 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3938 vec<ipa_agg_jf_item> res = vNULL;
3940 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3941 return vNULL;
3943 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3944 if (aglat->is_single_const ())
3946 struct ipa_agg_jf_item ti;
3947 ti.offset = aglat->offset - offset;
3948 ti.value = aglat->values->value;
3949 res.safe_push (ti);
3951 return res;
3954 /* Intersect all values in INTER with single value lattices in PLATS (while
3955 subtracting OFFSET). */
3957 static void
3958 intersect_with_plats (struct ipcp_param_lattices *plats,
3959 vec<ipa_agg_jf_item> *inter,
3960 HOST_WIDE_INT offset)
3962 struct ipcp_agg_lattice *aglat;
3963 struct ipa_agg_jf_item *item;
3964 int k;
3966 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3968 inter->release ();
3969 return;
3972 aglat = plats->aggs;
3973 FOR_EACH_VEC_ELT (*inter, k, item)
3975 bool found = false;
3976 if (!item->value)
3977 continue;
3978 while (aglat)
3980 if (aglat->offset - offset > item->offset)
3981 break;
3982 if (aglat->offset - offset == item->offset)
3984 gcc_checking_assert (item->value);
3985 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
3986 found = true;
3987 break;
3989 aglat = aglat->next;
3991 if (!found)
3992 item->value = NULL_TREE;
3996 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3997 vector result while subtracting OFFSET from the individual value offsets. */
3999 static vec<ipa_agg_jf_item>
4000 agg_replacements_to_vector (struct cgraph_node *node, int index,
4001 HOST_WIDE_INT offset)
4003 struct ipa_agg_replacement_value *av;
4004 vec<ipa_agg_jf_item> res = vNULL;
4006 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4007 if (av->index == index
4008 && (av->offset - offset) >= 0)
4010 struct ipa_agg_jf_item item;
4011 gcc_checking_assert (av->value);
4012 item.offset = av->offset - offset;
4013 item.value = av->value;
4014 res.safe_push (item);
4017 return res;
4020 /* Intersect all values in INTER with those that we have already scheduled to
4021 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4022 (while subtracting OFFSET). */
4024 static void
4025 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4026 vec<ipa_agg_jf_item> *inter,
4027 HOST_WIDE_INT offset)
4029 struct ipa_agg_replacement_value *srcvals;
4030 struct ipa_agg_jf_item *item;
4031 int i;
4033 srcvals = ipa_get_agg_replacements_for_node (node);
4034 if (!srcvals)
4036 inter->release ();
4037 return;
4040 FOR_EACH_VEC_ELT (*inter, i, item)
4042 struct ipa_agg_replacement_value *av;
4043 bool found = false;
4044 if (!item->value)
4045 continue;
4046 for (av = srcvals; av; av = av->next)
4048 gcc_checking_assert (av->value);
4049 if (av->index == index
4050 && av->offset - offset == item->offset)
4052 if (values_equal_for_ipcp_p (item->value, av->value))
4053 found = true;
4054 break;
4057 if (!found)
4058 item->value = NULL_TREE;
4062 /* Intersect values in INTER with aggregate values that come along edge CS to
4063 parameter number INDEX and return it. If INTER does not actually exist yet,
4064 copy all incoming values to it. If we determine we ended up with no values
4065 whatsoever, return a released vector. */
4067 static vec<ipa_agg_jf_item>
4068 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4069 vec<ipa_agg_jf_item> inter)
4071 struct ipa_jump_func *jfunc;
4072 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4073 if (jfunc->type == IPA_JF_PASS_THROUGH
4074 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4076 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4077 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4079 if (caller_info->ipcp_orig_node)
4081 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4082 struct ipcp_param_lattices *orig_plats;
4083 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4084 src_idx);
4085 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4087 if (!inter.exists ())
4088 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4089 else
4090 intersect_with_agg_replacements (cs->caller, src_idx,
4091 &inter, 0);
4093 else
4095 inter.release ();
4096 return vNULL;
4099 else
4101 struct ipcp_param_lattices *src_plats;
4102 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4103 if (agg_pass_through_permissible_p (src_plats, jfunc))
4105 /* Currently we do not produce clobber aggregate jump
4106 functions, adjust when we do. */
4107 gcc_checking_assert (!jfunc->agg.items);
4108 if (!inter.exists ())
4109 inter = copy_plats_to_inter (src_plats, 0);
4110 else
4111 intersect_with_plats (src_plats, &inter, 0);
4113 else
4115 inter.release ();
4116 return vNULL;
4120 else if (jfunc->type == IPA_JF_ANCESTOR
4121 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4123 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4124 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4125 struct ipcp_param_lattices *src_plats;
4126 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4128 if (caller_info->ipcp_orig_node)
4130 if (!inter.exists ())
4131 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4132 else
4133 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4134 delta);
4136 else
4138 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
4139 /* Currently we do not produce clobber aggregate jump
4140 functions, adjust when we do. */
4141 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4142 if (!inter.exists ())
4143 inter = copy_plats_to_inter (src_plats, delta);
4144 else
4145 intersect_with_plats (src_plats, &inter, delta);
4148 else if (jfunc->agg.items)
4150 struct ipa_agg_jf_item *item;
4151 int k;
4153 if (!inter.exists ())
4154 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4155 inter.safe_push ((*jfunc->agg.items)[i]);
4156 else
4157 FOR_EACH_VEC_ELT (inter, k, item)
4159 int l = 0;
4160 bool found = false;;
4162 if (!item->value)
4163 continue;
4165 while ((unsigned) l < jfunc->agg.items->length ())
4167 struct ipa_agg_jf_item *ti;
4168 ti = &(*jfunc->agg.items)[l];
4169 if (ti->offset > item->offset)
4170 break;
4171 if (ti->offset == item->offset)
4173 gcc_checking_assert (ti->value);
4174 if (values_equal_for_ipcp_p (item->value,
4175 ti->value))
4176 found = true;
4177 break;
4179 l++;
4181 if (!found)
4182 item->value = NULL;
4185 else
4187 inter.release ();
4188 return vec<ipa_agg_jf_item>();
4190 return inter;
4193 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4194 from all of them. */
4196 static struct ipa_agg_replacement_value *
4197 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4198 vec<cgraph_edge *> callers)
4200 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4201 struct ipa_agg_replacement_value *res;
4202 struct ipa_agg_replacement_value **tail = &res;
4203 struct cgraph_edge *cs;
4204 int i, j, count = ipa_get_param_count (dest_info);
4206 FOR_EACH_VEC_ELT (callers, j, cs)
4208 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4209 if (c < count)
4210 count = c;
4213 for (i = 0; i < count ; i++)
4215 struct cgraph_edge *cs;
4216 vec<ipa_agg_jf_item> inter = vNULL;
4217 struct ipa_agg_jf_item *item;
4218 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4219 int j;
4221 /* Among other things, the following check should deal with all by_ref
4222 mismatches. */
4223 if (plats->aggs_bottom)
4224 continue;
4226 FOR_EACH_VEC_ELT (callers, j, cs)
4228 inter = intersect_aggregates_with_edge (cs, i, inter);
4230 if (!inter.exists ())
4231 goto next_param;
4234 FOR_EACH_VEC_ELT (inter, j, item)
4236 struct ipa_agg_replacement_value *v;
4238 if (!item->value)
4239 continue;
4241 v = ggc_alloc<ipa_agg_replacement_value> ();
4242 v->index = i;
4243 v->offset = item->offset;
4244 v->value = item->value;
4245 v->by_ref = plats->aggs_by_ref;
4246 *tail = v;
4247 tail = &v->next;
4250 next_param:
4251 if (inter.exists ())
4252 inter.release ();
4254 *tail = NULL;
4255 return res;
4258 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
4260 static struct ipa_agg_replacement_value *
4261 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
4263 struct ipa_agg_replacement_value *res;
4264 struct ipa_agg_replacement_value **tail = &res;
4265 struct ipa_agg_jump_function *aggjf;
4266 struct ipa_agg_jf_item *item;
4267 int i, j;
4269 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
4270 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
4272 struct ipa_agg_replacement_value *v;
4273 v = ggc_alloc<ipa_agg_replacement_value> ();
4274 v->index = i;
4275 v->offset = item->offset;
4276 v->value = item->value;
4277 v->by_ref = aggjf->by_ref;
4278 *tail = v;
4279 tail = &v->next;
4281 *tail = NULL;
4282 return res;
4285 /* Determine whether CS also brings all scalar values that the NODE is
4286 specialized for. */
4288 static bool
4289 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4290 struct cgraph_node *node)
4292 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4293 int count = ipa_get_param_count (dest_info);
4294 struct ipa_node_params *caller_info;
4295 struct ipa_edge_args *args;
4296 int i;
4298 caller_info = IPA_NODE_REF (cs->caller);
4299 args = IPA_EDGE_REF (cs);
4300 for (i = 0; i < count; i++)
4302 struct ipa_jump_func *jump_func;
4303 tree val, t;
4305 val = dest_info->known_csts[i];
4306 if (!val)
4307 continue;
4309 if (i >= ipa_get_cs_argument_count (args))
4310 return false;
4311 jump_func = ipa_get_ith_jump_func (args, i);
4312 t = ipa_value_from_jfunc (caller_info, jump_func);
4313 if (!t || !values_equal_for_ipcp_p (val, t))
4314 return false;
4316 return true;
4319 /* Determine whether CS also brings all aggregate values that NODE is
4320 specialized for. */
4321 static bool
4322 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4323 struct cgraph_node *node)
4325 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4326 struct ipa_node_params *orig_node_info;
4327 struct ipa_agg_replacement_value *aggval;
4328 int i, ec, count;
4330 aggval = ipa_get_agg_replacements_for_node (node);
4331 if (!aggval)
4332 return true;
4334 count = ipa_get_param_count (IPA_NODE_REF (node));
4335 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4336 if (ec < count)
4337 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4338 if (aggval->index >= ec)
4339 return false;
4341 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4342 if (orig_caller_info->ipcp_orig_node)
4343 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4345 for (i = 0; i < count; i++)
4347 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4348 struct ipcp_param_lattices *plats;
4349 bool interesting = false;
4350 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4351 if (aggval->index == i)
4353 interesting = true;
4354 break;
4356 if (!interesting)
4357 continue;
4359 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4360 if (plats->aggs_bottom)
4361 return false;
4363 values = intersect_aggregates_with_edge (cs, i, values);
4364 if (!values.exists ())
4365 return false;
4367 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4368 if (aggval->index == i)
4370 struct ipa_agg_jf_item *item;
4371 int j;
4372 bool found = false;
4373 FOR_EACH_VEC_ELT (values, j, item)
4374 if (item->value
4375 && item->offset == av->offset
4376 && values_equal_for_ipcp_p (item->value, av->value))
4378 found = true;
4379 break;
4381 if (!found)
4383 values.release ();
4384 return false;
4388 return true;
4391 /* Given an original NODE and a VAL for which we have already created a
4392 specialized clone, look whether there are incoming edges that still lead
4393 into the old node but now also bring the requested value and also conform to
4394 all other criteria such that they can be redirected the special node.
4395 This function can therefore redirect the final edge in a SCC. */
4397 template <typename valtype>
4398 static void
4399 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4401 ipcp_value_source<valtype> *src;
4402 gcov_type redirected_sum = 0;
4404 for (src = val->sources; src; src = src->next)
4406 struct cgraph_edge *cs = src->cs;
4407 while (cs)
4409 if (cgraph_edge_brings_value_p (cs, src, node)
4410 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4411 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4413 if (dump_file)
4414 fprintf (dump_file, " - adding an extra caller %s/%i"
4415 " of %s/%i\n",
4416 xstrdup_for_dump (cs->caller->name ()),
4417 cs->caller->order,
4418 xstrdup_for_dump (val->spec_node->name ()),
4419 val->spec_node->order);
4421 cs->redirect_callee_duplicating_thunks (val->spec_node);
4422 val->spec_node->expand_all_artificial_thunks ();
4423 redirected_sum += cs->count;
4425 cs = get_next_cgraph_edge_clone (cs);
4429 if (redirected_sum)
4430 update_specialized_profile (val->spec_node, node, redirected_sum);
4433 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4435 static bool
4436 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4438 ipa_polymorphic_call_context *ctx;
4439 int i;
4441 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4442 if (!ctx->useless_p ())
4443 return true;
4444 return false;
4447 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4449 static vec<ipa_polymorphic_call_context>
4450 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4452 if (known_contexts_useful_p (known_contexts))
4453 return known_contexts.copy ();
4454 else
4455 return vNULL;
4458 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4459 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4461 static void
4462 modify_known_vectors_with_val (vec<tree> *known_csts,
4463 vec<ipa_polymorphic_call_context> *known_contexts,
4464 ipcp_value<tree> *val,
4465 int index)
4467 *known_csts = known_csts->copy ();
4468 *known_contexts = copy_useful_known_contexts (*known_contexts);
4469 (*known_csts)[index] = val->value;
4472 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4473 copy according to VAL and INDEX. */
4475 static void
4476 modify_known_vectors_with_val (vec<tree> *known_csts,
4477 vec<ipa_polymorphic_call_context> *known_contexts,
4478 ipcp_value<ipa_polymorphic_call_context> *val,
4479 int index)
4481 *known_csts = known_csts->copy ();
4482 *known_contexts = known_contexts->copy ();
4483 (*known_contexts)[index] = val->value;
4486 /* Return true if OFFSET indicates this was not an aggregate value or there is
4487 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4488 AGGVALS list. */
4490 DEBUG_FUNCTION bool
4491 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4492 int index, HOST_WIDE_INT offset, tree value)
4494 if (offset == -1)
4495 return true;
4497 while (aggvals)
4499 if (aggvals->index == index
4500 && aggvals->offset == offset
4501 && values_equal_for_ipcp_p (aggvals->value, value))
4502 return true;
4503 aggvals = aggvals->next;
4505 return false;
4508 /* Return true if offset is minus one because source of a polymorphic contect
4509 cannot be an aggregate value. */
4511 DEBUG_FUNCTION bool
4512 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4513 int , HOST_WIDE_INT offset,
4514 ipa_polymorphic_call_context)
4516 return offset == -1;
4519 /* Decide wheter to create a special version of NODE for value VAL of parameter
4520 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4521 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4522 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4524 template <typename valtype>
4525 static bool
4526 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4527 ipcp_value<valtype> *val, vec<tree> known_csts,
4528 vec<ipa_polymorphic_call_context> known_contexts)
4530 struct ipa_agg_replacement_value *aggvals;
4531 int freq_sum, caller_count;
4532 gcov_type count_sum;
4533 vec<cgraph_edge *> callers;
4535 if (val->spec_node)
4537 perhaps_add_new_callers (node, val);
4538 return false;
4540 else if (val->local_size_cost + overall_size > max_new_size)
4542 if (dump_file && (dump_flags & TDF_DETAILS))
4543 fprintf (dump_file, " Ignoring candidate value because "
4544 "max_new_size would be reached with %li.\n",
4545 val->local_size_cost + overall_size);
4546 return false;
4548 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4549 &caller_count))
4550 return false;
4552 if (dump_file && (dump_flags & TDF_DETAILS))
4554 fprintf (dump_file, " - considering value ");
4555 print_ipcp_constant_value (dump_file, val->value);
4556 fprintf (dump_file, " for ");
4557 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4558 if (offset != -1)
4559 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4560 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4563 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4564 freq_sum, count_sum,
4565 val->local_size_cost)
4566 && !good_cloning_opportunity_p (node,
4567 val->local_time_benefit
4568 + val->prop_time_benefit,
4569 freq_sum, count_sum,
4570 val->local_size_cost
4571 + val->prop_size_cost))
4572 return false;
4574 if (dump_file)
4575 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
4576 node->name (), node->order);
4578 callers = gather_edges_for_value (val, node, caller_count);
4579 if (offset == -1)
4580 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4581 else
4583 known_csts = known_csts.copy ();
4584 known_contexts = copy_useful_known_contexts (known_contexts);
4586 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4587 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4588 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4589 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4590 offset, val->value));
4591 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4592 aggvals, callers);
4593 overall_size += val->local_size_cost;
4595 /* TODO: If for some lattice there is only one other known value
4596 left, make a special node for it too. */
4598 return true;
4601 /* Decide whether and what specialized clones of NODE should be created. */
4603 static bool
4604 decide_whether_version_node (struct cgraph_node *node)
4606 struct ipa_node_params *info = IPA_NODE_REF (node);
4607 int i, count = ipa_get_param_count (info);
4608 vec<tree> known_csts;
4609 vec<ipa_polymorphic_call_context> known_contexts;
4610 vec<ipa_agg_jump_function> known_aggs = vNULL;
4611 bool ret = false;
4613 if (count == 0)
4614 return false;
4616 if (dump_file && (dump_flags & TDF_DETAILS))
4617 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4618 node->name (), node->order);
4620 gather_context_independent_values (info, &known_csts, &known_contexts,
4621 info->do_clone_for_all_contexts ? &known_aggs
4622 : NULL, NULL);
4624 for (i = 0; i < count ;i++)
4626 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4627 ipcp_lattice<tree> *lat = &plats->itself;
4628 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4630 if (!lat->bottom
4631 && !known_csts[i])
4633 ipcp_value<tree> *val;
4634 for (val = lat->values; val; val = val->next)
4635 ret |= decide_about_value (node, i, -1, val, known_csts,
4636 known_contexts);
4639 if (!plats->aggs_bottom)
4641 struct ipcp_agg_lattice *aglat;
4642 ipcp_value<tree> *val;
4643 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4644 if (!aglat->bottom && aglat->values
4645 /* If the following is false, the one value is in
4646 known_aggs. */
4647 && (plats->aggs_contain_variable
4648 || !aglat->is_single_const ()))
4649 for (val = aglat->values; val; val = val->next)
4650 ret |= decide_about_value (node, i, aglat->offset, val,
4651 known_csts, known_contexts);
4654 if (!ctxlat->bottom
4655 && known_contexts[i].useless_p ())
4657 ipcp_value<ipa_polymorphic_call_context> *val;
4658 for (val = ctxlat->values; val; val = val->next)
4659 ret |= decide_about_value (node, i, -1, val, known_csts,
4660 known_contexts);
4663 info = IPA_NODE_REF (node);
4666 if (info->do_clone_for_all_contexts)
4668 struct cgraph_node *clone;
4669 vec<cgraph_edge *> callers;
4671 if (dump_file)
4672 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4673 "for all known contexts.\n", node->name (),
4674 node->order);
4676 callers = node->collect_callers ();
4678 if (!known_contexts_useful_p (known_contexts))
4680 known_contexts.release ();
4681 known_contexts = vNULL;
4683 clone = create_specialized_node (node, known_csts, known_contexts,
4684 known_aggs_to_agg_replacement_list (known_aggs),
4685 callers);
4686 info = IPA_NODE_REF (node);
4687 info->do_clone_for_all_contexts = false;
4688 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4689 for (i = 0; i < count ; i++)
4690 vec_free (known_aggs[i].items);
4691 known_aggs.release ();
4692 ret = true;
4694 else
4696 known_csts.release ();
4697 known_contexts.release ();
4700 return ret;
4703 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4705 static void
4706 spread_undeadness (struct cgraph_node *node)
4708 struct cgraph_edge *cs;
4710 for (cs = node->callees; cs; cs = cs->next_callee)
4711 if (ipa_edge_within_scc (cs))
4713 struct cgraph_node *callee;
4714 struct ipa_node_params *info;
4716 callee = cs->callee->function_symbol (NULL);
4717 info = IPA_NODE_REF (callee);
4719 if (info->node_dead)
4721 info->node_dead = 0;
4722 spread_undeadness (callee);
4727 /* Return true if NODE has a caller from outside of its SCC that is not
4728 dead. Worker callback for cgraph_for_node_and_aliases. */
4730 static bool
4731 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4732 void *data ATTRIBUTE_UNUSED)
4734 struct cgraph_edge *cs;
4736 for (cs = node->callers; cs; cs = cs->next_caller)
4737 if (cs->caller->thunk.thunk_p
4738 && cs->caller->call_for_symbol_thunks_and_aliases
4739 (has_undead_caller_from_outside_scc_p, NULL, true))
4740 return true;
4741 else if (!ipa_edge_within_scc (cs)
4742 && !IPA_NODE_REF (cs->caller)->node_dead)
4743 return true;
4744 return false;
4748 /* Identify nodes within the same SCC as NODE which are no longer needed
4749 because of new clones and will be removed as unreachable. */
4751 static void
4752 identify_dead_nodes (struct cgraph_node *node)
4754 struct cgraph_node *v;
4755 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4756 if (v->local.local
4757 && !v->call_for_symbol_thunks_and_aliases
4758 (has_undead_caller_from_outside_scc_p, NULL, true))
4759 IPA_NODE_REF (v)->node_dead = 1;
4761 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4762 if (!IPA_NODE_REF (v)->node_dead)
4763 spread_undeadness (v);
4765 if (dump_file && (dump_flags & TDF_DETAILS))
4767 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4768 if (IPA_NODE_REF (v)->node_dead)
4769 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4770 v->name (), v->order);
4774 /* The decision stage. Iterate over the topological order of call graph nodes
4775 TOPO and make specialized clones if deemed beneficial. */
4777 static void
4778 ipcp_decision_stage (struct ipa_topo_info *topo)
4780 int i;
4782 if (dump_file)
4783 fprintf (dump_file, "\nIPA decision stage:\n\n");
4785 for (i = topo->nnodes - 1; i >= 0; i--)
4787 struct cgraph_node *node = topo->order[i];
4788 bool change = false, iterate = true;
4790 while (iterate)
4792 struct cgraph_node *v;
4793 iterate = false;
4794 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4795 if (v->has_gimple_body_p ()
4796 && ipcp_versionable_function_p (v))
4797 iterate |= decide_whether_version_node (v);
4799 change |= iterate;
4801 if (change)
4802 identify_dead_nodes (node);
4806 /* Look up all the bits information that we have discovered and copy it over
4807 to the transformation summary. */
4809 static void
4810 ipcp_store_bits_results (void)
4812 cgraph_node *node;
4814 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4816 ipa_node_params *info = IPA_NODE_REF (node);
4817 bool dumped_sth = false;
4818 bool found_useful_result = false;
4820 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4822 if (dump_file)
4823 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4824 "; -fipa-bit-cp: disabled.\n",
4825 node->name ());
4826 continue;
4829 if (info->ipcp_orig_node)
4830 info = IPA_NODE_REF (info->ipcp_orig_node);
4832 unsigned count = ipa_get_param_count (info);
4833 for (unsigned i = 0; i < count; i++)
4835 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4836 if (plats->bits_lattice.constant_p ())
4838 found_useful_result = true;
4839 break;
4843 if (!found_useful_result)
4844 continue;
4846 ipcp_grow_transformations_if_necessary ();
4847 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4848 vec_safe_reserve_exact (ts->bits, count);
4850 for (unsigned i = 0; i < count; i++)
4852 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4853 ipa_bits bits_jfunc;
4855 if (plats->bits_lattice.constant_p ())
4857 bits_jfunc.known = true;
4858 bits_jfunc.value = plats->bits_lattice.get_value ();
4859 bits_jfunc.mask = plats->bits_lattice.get_mask ();
4861 else
4862 bits_jfunc.known = false;
4864 ts->bits->quick_push (bits_jfunc);
4865 if (!dump_file || !bits_jfunc.known)
4866 continue;
4867 if (!dumped_sth)
4869 fprintf (dump_file, "Propagated bits info for function %s/%i:\n",
4870 node->name (), node->order);
4871 dumped_sth = true;
4873 fprintf (dump_file, " param %i: value = ", i);
4874 print_hex (bits_jfunc.value, dump_file);
4875 fprintf (dump_file, ", mask = ");
4876 print_hex (bits_jfunc.mask, dump_file);
4877 fprintf (dump_file, "\n");
4882 /* Look up all VR information that we have discovered and copy it over
4883 to the transformation summary. */
4885 static void
4886 ipcp_store_vr_results (void)
4888 cgraph_node *node;
4890 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4892 ipa_node_params *info = IPA_NODE_REF (node);
4893 bool found_useful_result = false;
4895 if (!opt_for_fn (node->decl, flag_ipa_vrp))
4897 if (dump_file)
4898 fprintf (dump_file, "Not considering %s for VR discovery "
4899 "and propagate; -fipa-ipa-vrp: disabled.\n",
4900 node->name ());
4901 continue;
4904 if (info->ipcp_orig_node)
4905 info = IPA_NODE_REF (info->ipcp_orig_node);
4907 unsigned count = ipa_get_param_count (info);
4908 for (unsigned i = 0; i < count ; i++)
4910 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4911 if (!plats->m_value_range.bottom_p ()
4912 && !plats->m_value_range.top_p ())
4914 found_useful_result = true;
4915 break;
4918 if (!found_useful_result)
4919 continue;
4921 ipcp_grow_transformations_if_necessary ();
4922 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4923 vec_safe_reserve_exact (ts->m_vr, count);
4925 for (unsigned i = 0; i < count ; i++)
4927 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4928 ipa_vr vr;
4930 if (!plats->m_value_range.bottom_p ()
4931 && !plats->m_value_range.top_p ())
4933 vr.known = true;
4934 vr.type = plats->m_value_range.m_vr.type;
4935 vr.min = plats->m_value_range.m_vr.min;
4936 vr.max = plats->m_value_range.m_vr.max;
4938 else
4940 vr.known = false;
4941 vr.type = VR_VARYING;
4942 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
4944 ts->m_vr->quick_push (vr);
4949 /* The IPCP driver. */
4951 static unsigned int
4952 ipcp_driver (void)
4954 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4955 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4956 struct ipa_topo_info topo;
4958 ipa_check_create_node_params ();
4959 ipa_check_create_edge_args ();
4960 grow_edge_clone_vectors ();
4961 edge_duplication_hook_holder =
4962 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4963 edge_removal_hook_holder =
4964 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4966 if (dump_file)
4968 fprintf (dump_file, "\nIPA structures before propagation:\n");
4969 if (dump_flags & TDF_DETAILS)
4970 ipa_print_all_params (dump_file);
4971 ipa_print_all_jump_functions (dump_file);
4974 /* Topological sort. */
4975 build_toporder_info (&topo);
4976 /* Do the interprocedural propagation. */
4977 ipcp_propagate_stage (&topo);
4978 /* Decide what constant propagation and cloning should be performed. */
4979 ipcp_decision_stage (&topo);
4980 /* Store results of bits propagation. */
4981 ipcp_store_bits_results ();
4982 /* Store results of value range propagation. */
4983 ipcp_store_vr_results ();
4985 /* Free all IPCP structures. */
4986 free_toporder_info (&topo);
4987 next_edge_clone.release ();
4988 prev_edge_clone.release ();
4989 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4990 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
4991 ipa_free_all_structures_after_ipa_cp ();
4992 if (dump_file)
4993 fprintf (dump_file, "\nIPA constant propagation end\n");
4994 return 0;
4997 /* Initialization and computation of IPCP data structures. This is the initial
4998 intraprocedural analysis of functions, which gathers information to be
4999 propagated later on. */
5001 static void
5002 ipcp_generate_summary (void)
5004 struct cgraph_node *node;
5006 if (dump_file)
5007 fprintf (dump_file, "\nIPA constant propagation start:\n");
5008 ipa_register_cgraph_hooks ();
5010 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5011 ipa_analyze_node (node);
5014 /* Write ipcp summary for nodes in SET. */
5016 static void
5017 ipcp_write_summary (void)
5019 ipa_prop_write_jump_functions ();
5022 /* Read ipcp summary. */
5024 static void
5025 ipcp_read_summary (void)
5027 ipa_prop_read_jump_functions ();
5030 namespace {
5032 const pass_data pass_data_ipa_cp =
5034 IPA_PASS, /* type */
5035 "cp", /* name */
5036 OPTGROUP_NONE, /* optinfo_flags */
5037 TV_IPA_CONSTANT_PROP, /* tv_id */
5038 0, /* properties_required */
5039 0, /* properties_provided */
5040 0, /* properties_destroyed */
5041 0, /* todo_flags_start */
5042 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5045 class pass_ipa_cp : public ipa_opt_pass_d
5047 public:
5048 pass_ipa_cp (gcc::context *ctxt)
5049 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5050 ipcp_generate_summary, /* generate_summary */
5051 ipcp_write_summary, /* write_summary */
5052 ipcp_read_summary, /* read_summary */
5053 ipcp_write_transformation_summaries, /*
5054 write_optimization_summary */
5055 ipcp_read_transformation_summaries, /*
5056 read_optimization_summary */
5057 NULL, /* stmt_fixup */
5058 0, /* function_transform_todo_flags_start */
5059 ipcp_transform_function, /* function_transform */
5060 NULL) /* variable_transform */
5063 /* opt_pass methods: */
5064 virtual bool gate (function *)
5066 /* FIXME: We should remove the optimize check after we ensure we never run
5067 IPA passes when not optimizing. */
5068 return (flag_ipa_cp && optimize) || in_lto_p;
5071 virtual unsigned int execute (function *) { return ipcp_driver (); }
5073 }; // class pass_ipa_cp
5075 } // anon namespace
5077 ipa_opt_pass_d *
5078 make_pass_ipa_cp (gcc::context *ctxt)
5080 return new pass_ipa_cp (ctxt);
5083 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5084 within the same process. For use by toplev::finalize. */
5086 void
5087 ipa_cp_c_finalize (void)
5089 max_count = 0;
5090 overall_size = 0;
5091 max_new_size = 0;