Define arm_arch_core_flags in a single file
[official-gcc.git] / gcc / ipa-cp.c
blob4ec7cc5dfeb45addf084209942e44db9ae4ddd6e
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_unary)
1223 res = fold_unary (ipa_get_jf_pass_through_operation (jfunc),
1224 TREE_TYPE (input), input);
1225 else
1227 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
1228 == tcc_comparison)
1229 restype = boolean_type_node;
1230 else
1231 restype = TREE_TYPE (input);
1232 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
1233 input, ipa_get_jf_pass_through_operand (jfunc));
1235 if (res && !is_gimple_ip_invariant (res))
1236 return NULL_TREE;
1238 return res;
1241 /* Return the result of an ancestor jump function JFUNC on the constant value
1242 INPUT. Return NULL_TREE if that cannot be determined. */
1244 static tree
1245 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1247 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1248 if (TREE_CODE (input) == ADDR_EXPR)
1250 tree t = TREE_OPERAND (input, 0);
1251 t = build_ref_for_offset (EXPR_LOCATION (t), t,
1252 ipa_get_jf_ancestor_offset (jfunc), false,
1253 ptr_type_node, NULL, false);
1254 return build_fold_addr_expr (t);
1256 else
1257 return NULL_TREE;
1260 /* Determine whether JFUNC evaluates to a single known constant value and if
1261 so, return it. Otherwise return NULL. INFO describes the caller node or
1262 the one it is inlined to, so that pass-through jump functions can be
1263 evaluated. */
1265 tree
1266 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
1268 if (jfunc->type == IPA_JF_CONST)
1269 return ipa_get_jf_constant (jfunc);
1270 else if (jfunc->type == IPA_JF_PASS_THROUGH
1271 || jfunc->type == IPA_JF_ANCESTOR)
1273 tree input;
1274 int idx;
1276 if (jfunc->type == IPA_JF_PASS_THROUGH)
1277 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1278 else
1279 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1281 if (info->ipcp_orig_node)
1282 input = info->known_csts[idx];
1283 else
1285 ipcp_lattice<tree> *lat;
1287 if (!info->lattices
1288 || idx >= ipa_get_param_count (info))
1289 return NULL_TREE;
1290 lat = ipa_get_scalar_lat (info, idx);
1291 if (!lat->is_single_const ())
1292 return NULL_TREE;
1293 input = lat->values->value;
1296 if (!input)
1297 return NULL_TREE;
1299 if (jfunc->type == IPA_JF_PASS_THROUGH)
1300 return ipa_get_jf_pass_through_result (jfunc, input);
1301 else
1302 return ipa_get_jf_ancestor_result (jfunc, input);
1304 else
1305 return NULL_TREE;
1308 /* Determie whether JFUNC evaluates to single known polymorphic context, given
1309 that INFO describes the caller node or the one it is inlined to, CS is the
1310 call graph edge corresponding to JFUNC and CSIDX index of the described
1311 parameter. */
1313 ipa_polymorphic_call_context
1314 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1315 ipa_jump_func *jfunc)
1317 ipa_edge_args *args = IPA_EDGE_REF (cs);
1318 ipa_polymorphic_call_context ctx;
1319 ipa_polymorphic_call_context *edge_ctx
1320 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1322 if (edge_ctx && !edge_ctx->useless_p ())
1323 ctx = *edge_ctx;
1325 if (jfunc->type == IPA_JF_PASS_THROUGH
1326 || jfunc->type == IPA_JF_ANCESTOR)
1328 ipa_polymorphic_call_context srcctx;
1329 int srcidx;
1330 bool type_preserved = true;
1331 if (jfunc->type == IPA_JF_PASS_THROUGH)
1333 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1334 return ctx;
1335 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1336 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1338 else
1340 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1341 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1343 if (info->ipcp_orig_node)
1345 if (info->known_contexts.exists ())
1346 srcctx = info->known_contexts[srcidx];
1348 else
1350 if (!info->lattices
1351 || srcidx >= ipa_get_param_count (info))
1352 return ctx;
1353 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1354 lat = ipa_get_poly_ctx_lat (info, srcidx);
1355 if (!lat->is_single_const ())
1356 return ctx;
1357 srcctx = lat->values->value;
1359 if (srcctx.useless_p ())
1360 return ctx;
1361 if (jfunc->type == IPA_JF_ANCESTOR)
1362 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1363 if (!type_preserved)
1364 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1365 srcctx.combine_with (ctx);
1366 return srcctx;
1369 return ctx;
1372 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1373 bottom, not containing a variable component and without any known value at
1374 the same time. */
1376 DEBUG_FUNCTION void
1377 ipcp_verify_propagated_values (void)
1379 struct cgraph_node *node;
1381 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1383 struct ipa_node_params *info = IPA_NODE_REF (node);
1384 int i, count = ipa_get_param_count (info);
1386 for (i = 0; i < count; i++)
1388 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1390 if (!lat->bottom
1391 && !lat->contains_variable
1392 && lat->values_count == 0)
1394 if (dump_file)
1396 symtab_node::dump_table (dump_file);
1397 fprintf (dump_file, "\nIPA lattices after constant "
1398 "propagation, before gcc_unreachable:\n");
1399 print_all_lattices (dump_file, true, false);
1402 gcc_unreachable ();
1408 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1410 static bool
1411 values_equal_for_ipcp_p (tree x, tree y)
1413 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1415 if (x == y)
1416 return true;
1418 if (TREE_CODE (x) == ADDR_EXPR
1419 && TREE_CODE (y) == ADDR_EXPR
1420 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1421 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1422 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1423 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1424 else
1425 return operand_equal_p (x, y, 0);
1428 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1430 static bool
1431 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1432 ipa_polymorphic_call_context y)
1434 return x.equal_to (y);
1438 /* Add a new value source to the value represented by THIS, marking that a
1439 value comes from edge CS and (if the underlying jump function is a
1440 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1441 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1442 scalar value of the parameter itself or the offset within an aggregate. */
1444 template <typename valtype>
1445 void
1446 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1447 int src_idx, HOST_WIDE_INT offset)
1449 ipcp_value_source<valtype> *src;
1451 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1452 src->offset = offset;
1453 src->cs = cs;
1454 src->val = src_val;
1455 src->index = src_idx;
1457 src->next = sources;
1458 sources = src;
1461 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1462 SOURCE and clear all other fields. */
1464 static ipcp_value<tree> *
1465 allocate_and_init_ipcp_value (tree source)
1467 ipcp_value<tree> *val;
1469 val = ipcp_cst_values_pool.allocate ();
1470 memset (val, 0, sizeof (*val));
1471 val->value = source;
1472 return val;
1475 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1476 value to SOURCE and clear all other fields. */
1478 static ipcp_value<ipa_polymorphic_call_context> *
1479 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1481 ipcp_value<ipa_polymorphic_call_context> *val;
1483 // TODO
1484 val = ipcp_poly_ctx_values_pool.allocate ();
1485 memset (val, 0, sizeof (*val));
1486 val->value = source;
1487 return val;
1490 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1491 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1492 meaning. OFFSET -1 means the source is scalar and not a part of an
1493 aggregate. */
1495 template <typename valtype>
1496 bool
1497 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1498 ipcp_value<valtype> *src_val,
1499 int src_idx, HOST_WIDE_INT offset)
1501 ipcp_value<valtype> *val;
1503 if (bottom)
1504 return false;
1506 for (val = values; val; val = val->next)
1507 if (values_equal_for_ipcp_p (val->value, newval))
1509 if (ipa_edge_within_scc (cs))
1511 ipcp_value_source<valtype> *s;
1512 for (s = val->sources; s ; s = s->next)
1513 if (s->cs == cs)
1514 break;
1515 if (s)
1516 return false;
1519 val->add_source (cs, src_val, src_idx, offset);
1520 return false;
1523 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
1525 /* We can only free sources, not the values themselves, because sources
1526 of other values in this SCC might point to them. */
1527 for (val = values; val; val = val->next)
1529 while (val->sources)
1531 ipcp_value_source<valtype> *src = val->sources;
1532 val->sources = src->next;
1533 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1537 values = NULL;
1538 return set_to_bottom ();
1541 values_count++;
1542 val = allocate_and_init_ipcp_value (newval);
1543 val->add_source (cs, src_val, src_idx, offset);
1544 val->next = values;
1545 values = val;
1546 return true;
1549 /* Propagate values through a pass-through jump function JFUNC associated with
1550 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1551 is the index of the source parameter. */
1553 static bool
1554 propagate_vals_accross_pass_through (cgraph_edge *cs,
1555 ipa_jump_func *jfunc,
1556 ipcp_lattice<tree> *src_lat,
1557 ipcp_lattice<tree> *dest_lat,
1558 int src_idx)
1560 ipcp_value<tree> *src_val;
1561 bool ret = false;
1563 /* Do not create new values when propagating within an SCC because if there
1564 are arithmetic functions with circular dependencies, there is infinite
1565 number of them and we would just make lattices bottom. */
1566 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1567 && ipa_edge_within_scc (cs))
1568 ret = dest_lat->set_contains_variable ();
1569 else
1570 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1572 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1574 if (cstval)
1575 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1576 else
1577 ret |= dest_lat->set_contains_variable ();
1580 return ret;
1583 /* Propagate values through an ancestor jump function JFUNC associated with
1584 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1585 is the index of the source parameter. */
1587 static bool
1588 propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1589 struct ipa_jump_func *jfunc,
1590 ipcp_lattice<tree> *src_lat,
1591 ipcp_lattice<tree> *dest_lat,
1592 int src_idx)
1594 ipcp_value<tree> *src_val;
1595 bool ret = false;
1597 if (ipa_edge_within_scc (cs))
1598 return dest_lat->set_contains_variable ();
1600 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1602 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1604 if (t)
1605 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1606 else
1607 ret |= dest_lat->set_contains_variable ();
1610 return ret;
1613 /* Propagate scalar values across jump function JFUNC that is associated with
1614 edge CS and put the values into DEST_LAT. */
1616 static bool
1617 propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1618 struct ipa_jump_func *jfunc,
1619 ipcp_lattice<tree> *dest_lat)
1621 if (dest_lat->bottom)
1622 return false;
1624 if (jfunc->type == IPA_JF_CONST)
1626 tree val = ipa_get_jf_constant (jfunc);
1627 return dest_lat->add_value (val, cs, NULL, 0);
1629 else if (jfunc->type == IPA_JF_PASS_THROUGH
1630 || jfunc->type == IPA_JF_ANCESTOR)
1632 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1633 ipcp_lattice<tree> *src_lat;
1634 int src_idx;
1635 bool ret;
1637 if (jfunc->type == IPA_JF_PASS_THROUGH)
1638 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1639 else
1640 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1642 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1643 if (src_lat->bottom)
1644 return dest_lat->set_contains_variable ();
1646 /* If we would need to clone the caller and cannot, do not propagate. */
1647 if (!ipcp_versionable_function_p (cs->caller)
1648 && (src_lat->contains_variable
1649 || (src_lat->values_count > 1)))
1650 return dest_lat->set_contains_variable ();
1652 if (jfunc->type == IPA_JF_PASS_THROUGH)
1653 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1654 dest_lat, src_idx);
1655 else
1656 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1657 src_idx);
1659 if (src_lat->contains_variable)
1660 ret |= dest_lat->set_contains_variable ();
1662 return ret;
1665 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1666 use it for indirect inlining), we should propagate them too. */
1667 return dest_lat->set_contains_variable ();
1670 /* Propagate scalar values across jump function JFUNC that is associated with
1671 edge CS and describes argument IDX and put the values into DEST_LAT. */
1673 static bool
1674 propagate_context_accross_jump_function (cgraph_edge *cs,
1675 ipa_jump_func *jfunc, int idx,
1676 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1678 ipa_edge_args *args = IPA_EDGE_REF (cs);
1679 if (dest_lat->bottom)
1680 return false;
1681 bool ret = false;
1682 bool added_sth = false;
1683 bool type_preserved = true;
1685 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1686 = ipa_get_ith_polymorhic_call_context (args, idx);
1688 if (edge_ctx_ptr)
1689 edge_ctx = *edge_ctx_ptr;
1691 if (jfunc->type == IPA_JF_PASS_THROUGH
1692 || jfunc->type == IPA_JF_ANCESTOR)
1694 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1695 int src_idx;
1696 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1698 /* TODO: Once we figure out how to propagate speculations, it will
1699 probably be a good idea to switch to speculation if type_preserved is
1700 not set instead of punting. */
1701 if (jfunc->type == IPA_JF_PASS_THROUGH)
1703 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1704 goto prop_fail;
1705 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1706 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1708 else
1710 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1711 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1714 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1715 /* If we would need to clone the caller and cannot, do not propagate. */
1716 if (!ipcp_versionable_function_p (cs->caller)
1717 && (src_lat->contains_variable
1718 || (src_lat->values_count > 1)))
1719 goto prop_fail;
1721 ipcp_value<ipa_polymorphic_call_context> *src_val;
1722 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1724 ipa_polymorphic_call_context cur = src_val->value;
1726 if (!type_preserved)
1727 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1728 if (jfunc->type == IPA_JF_ANCESTOR)
1729 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1730 /* TODO: In cases we know how the context is going to be used,
1731 we can improve the result by passing proper OTR_TYPE. */
1732 cur.combine_with (edge_ctx);
1733 if (!cur.useless_p ())
1735 if (src_lat->contains_variable
1736 && !edge_ctx.equal_to (cur))
1737 ret |= dest_lat->set_contains_variable ();
1738 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1739 added_sth = true;
1745 prop_fail:
1746 if (!added_sth)
1748 if (!edge_ctx.useless_p ())
1749 ret |= dest_lat->add_value (edge_ctx, cs);
1750 else
1751 ret |= dest_lat->set_contains_variable ();
1754 return ret;
1757 /* Propagate bits across jfunc that is associated with
1758 edge cs and update dest_lattice accordingly. */
1760 bool
1761 propagate_bits_accross_jump_function (cgraph_edge *cs, int idx, ipa_jump_func *jfunc,
1762 ipcp_bits_lattice *dest_lattice)
1764 if (dest_lattice->bottom_p ())
1765 return false;
1767 enum availability availability;
1768 cgraph_node *callee = cs->callee->function_symbol (&availability);
1769 struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
1770 tree parm_type = ipa_get_type (callee_info, idx);
1772 /* For K&R C programs, ipa_get_type() could return NULL_TREE.
1773 Avoid the transform for these cases. */
1774 if (!parm_type)
1776 if (dump_file && (dump_flags & TDF_DETAILS))
1777 fprintf (dump_file, "Setting dest_lattice to bottom, because"
1778 " param %i type is NULL for %s\n", idx,
1779 cs->callee->name ());
1781 return dest_lattice->set_to_bottom ();
1784 unsigned precision = TYPE_PRECISION (parm_type);
1785 signop sgn = TYPE_SIGN (parm_type);
1787 if (jfunc->type == IPA_JF_PASS_THROUGH
1788 || jfunc->type == IPA_JF_ANCESTOR)
1790 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1791 tree operand = NULL_TREE;
1792 enum tree_code code;
1793 unsigned src_idx;
1795 if (jfunc->type == IPA_JF_PASS_THROUGH)
1797 code = ipa_get_jf_pass_through_operation (jfunc);
1798 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1799 if (code != NOP_EXPR)
1800 operand = ipa_get_jf_pass_through_operand (jfunc);
1802 else
1804 code = POINTER_PLUS_EXPR;
1805 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1806 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
1807 operand = build_int_cstu (size_type_node, offset);
1810 struct ipcp_param_lattices *src_lats
1811 = ipa_get_parm_lattices (caller_info, src_idx);
1813 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1814 for eg consider:
1815 int f(int x)
1817 g (x & 0xff);
1819 Assume lattice for x is bottom, however we can still propagate
1820 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1821 and we store it in jump function during analysis stage. */
1823 if (src_lats->bits_lattice.bottom_p ()
1824 && jfunc->bits.known)
1825 return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask,
1826 precision);
1827 else
1828 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
1829 code, operand);
1832 else if (jfunc->type == IPA_JF_ANCESTOR)
1833 return dest_lattice->set_to_bottom ();
1835 else if (jfunc->bits.known)
1836 return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask, precision);
1838 else
1839 return dest_lattice->set_to_bottom ();
1842 /* Propagate value range across jump function JFUNC that is associated with
1843 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1844 accordingly. */
1846 static bool
1847 propagate_vr_accross_jump_function (cgraph_edge *cs,
1848 ipa_jump_func *jfunc,
1849 struct ipcp_param_lattices *dest_plats,
1850 tree param_type)
1852 struct ipcp_param_lattices *src_lats;
1853 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
1855 if (dest_lat->bottom_p ())
1856 return false;
1858 if (!param_type
1859 || (!INTEGRAL_TYPE_P (param_type)
1860 && !POINTER_TYPE_P (param_type)))
1861 return dest_lat->set_to_bottom ();
1863 if (jfunc->type == IPA_JF_PASS_THROUGH)
1865 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1866 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1867 src_lats = ipa_get_parm_lattices (caller_info, src_idx);
1869 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1870 return dest_lat->meet_with (src_lats->m_value_range);
1871 else if (param_type
1872 && (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
1873 == tcc_unary))
1875 value_range vr;
1876 memset (&vr, 0, sizeof (vr));
1877 tree operand_type = ipa_get_type (caller_info, src_idx);
1878 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1880 if (src_lats->m_value_range.bottom_p ())
1881 return dest_lat->set_to_bottom ();
1883 extract_range_from_unary_expr (&vr,
1884 operation,
1885 param_type,
1886 &src_lats->m_value_range.m_vr,
1887 operand_type);
1888 if (vr.type == VR_RANGE
1889 || vr.type == VR_ANTI_RANGE)
1890 return dest_lat->meet_with (&vr);
1893 else if (jfunc->type == IPA_JF_CONST)
1895 tree val = ipa_get_jf_constant (jfunc);
1896 if (TREE_CODE (val) == INTEGER_CST)
1898 val = fold_convert (param_type, val);
1899 if (TREE_OVERFLOW_P (val))
1900 val = drop_tree_overflow (val);
1901 jfunc->vr_known = true;
1902 jfunc->m_vr.type = VR_RANGE;
1903 jfunc->m_vr.min = val;
1904 jfunc->m_vr.max = val;
1905 return dest_lat->meet_with (&jfunc->m_vr);
1909 if (jfunc->vr_known)
1910 return dest_lat->meet_with (&jfunc->m_vr);
1911 else
1912 return dest_lat->set_to_bottom ();
1915 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1916 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1917 other cases, return false). If there are no aggregate items, set
1918 aggs_by_ref to NEW_AGGS_BY_REF. */
1920 static bool
1921 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1922 bool new_aggs_by_ref)
1924 if (dest_plats->aggs)
1926 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1928 set_agg_lats_to_bottom (dest_plats);
1929 return true;
1932 else
1933 dest_plats->aggs_by_ref = new_aggs_by_ref;
1934 return false;
1937 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1938 already existing lattice for the given OFFSET and SIZE, marking all skipped
1939 lattices as containing variable and checking for overlaps. If there is no
1940 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1941 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1942 unless there are too many already. If there are two many, return false. If
1943 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1944 skipped lattices were newly marked as containing variable, set *CHANGE to
1945 true. */
1947 static bool
1948 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1949 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1950 struct ipcp_agg_lattice ***aglat,
1951 bool pre_existing, bool *change)
1953 gcc_checking_assert (offset >= 0);
1955 while (**aglat && (**aglat)->offset < offset)
1957 if ((**aglat)->offset + (**aglat)->size > offset)
1959 set_agg_lats_to_bottom (dest_plats);
1960 return false;
1962 *change |= (**aglat)->set_contains_variable ();
1963 *aglat = &(**aglat)->next;
1966 if (**aglat && (**aglat)->offset == offset)
1968 if ((**aglat)->size != val_size
1969 || ((**aglat)->next
1970 && (**aglat)->next->offset < offset + val_size))
1972 set_agg_lats_to_bottom (dest_plats);
1973 return false;
1975 gcc_checking_assert (!(**aglat)->next
1976 || (**aglat)->next->offset >= offset + val_size);
1977 return true;
1979 else
1981 struct ipcp_agg_lattice *new_al;
1983 if (**aglat && (**aglat)->offset < offset + val_size)
1985 set_agg_lats_to_bottom (dest_plats);
1986 return false;
1988 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1989 return false;
1990 dest_plats->aggs_count++;
1991 new_al = ipcp_agg_lattice_pool.allocate ();
1992 memset (new_al, 0, sizeof (*new_al));
1994 new_al->offset = offset;
1995 new_al->size = val_size;
1996 new_al->contains_variable = pre_existing;
1998 new_al->next = **aglat;
1999 **aglat = new_al;
2000 return true;
2004 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2005 containing an unknown value. */
2007 static bool
2008 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2010 bool ret = false;
2011 while (aglat)
2013 ret |= aglat->set_contains_variable ();
2014 aglat = aglat->next;
2016 return ret;
2019 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2020 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2021 parameter used for lattice value sources. Return true if DEST_PLATS changed
2022 in any way. */
2024 static bool
2025 merge_aggregate_lattices (struct cgraph_edge *cs,
2026 struct ipcp_param_lattices *dest_plats,
2027 struct ipcp_param_lattices *src_plats,
2028 int src_idx, HOST_WIDE_INT offset_delta)
2030 bool pre_existing = dest_plats->aggs != NULL;
2031 struct ipcp_agg_lattice **dst_aglat;
2032 bool ret = false;
2034 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2035 return true;
2036 if (src_plats->aggs_bottom)
2037 return set_agg_lats_contain_variable (dest_plats);
2038 if (src_plats->aggs_contain_variable)
2039 ret |= set_agg_lats_contain_variable (dest_plats);
2040 dst_aglat = &dest_plats->aggs;
2042 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2043 src_aglat;
2044 src_aglat = src_aglat->next)
2046 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2048 if (new_offset < 0)
2049 continue;
2050 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2051 &dst_aglat, pre_existing, &ret))
2053 struct ipcp_agg_lattice *new_al = *dst_aglat;
2055 dst_aglat = &(*dst_aglat)->next;
2056 if (src_aglat->bottom)
2058 ret |= new_al->set_contains_variable ();
2059 continue;
2061 if (src_aglat->contains_variable)
2062 ret |= new_al->set_contains_variable ();
2063 for (ipcp_value<tree> *val = src_aglat->values;
2064 val;
2065 val = val->next)
2066 ret |= new_al->add_value (val->value, cs, val, src_idx,
2067 src_aglat->offset);
2069 else if (dest_plats->aggs_bottom)
2070 return true;
2072 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2073 return ret;
2076 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2077 pass-through JFUNC and if so, whether it has conform and conforms to the
2078 rules about propagating values passed by reference. */
2080 static bool
2081 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
2082 struct ipa_jump_func *jfunc)
2084 return src_plats->aggs
2085 && (!src_plats->aggs_by_ref
2086 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2089 /* Propagate scalar values across jump function JFUNC that is associated with
2090 edge CS and put the values into DEST_LAT. */
2092 static bool
2093 propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
2094 struct ipa_jump_func *jfunc,
2095 struct ipcp_param_lattices *dest_plats)
2097 bool ret = false;
2099 if (dest_plats->aggs_bottom)
2100 return false;
2102 if (jfunc->type == IPA_JF_PASS_THROUGH
2103 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2105 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2106 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2107 struct ipcp_param_lattices *src_plats;
2109 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2110 if (agg_pass_through_permissible_p (src_plats, jfunc))
2112 /* Currently we do not produce clobber aggregate jump
2113 functions, replace with merging when we do. */
2114 gcc_assert (!jfunc->agg.items);
2115 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2116 src_idx, 0);
2118 else
2119 ret |= set_agg_lats_contain_variable (dest_plats);
2121 else if (jfunc->type == IPA_JF_ANCESTOR
2122 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2124 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2125 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2126 struct ipcp_param_lattices *src_plats;
2128 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2129 if (src_plats->aggs && src_plats->aggs_by_ref)
2131 /* Currently we do not produce clobber aggregate jump
2132 functions, replace with merging when we do. */
2133 gcc_assert (!jfunc->agg.items);
2134 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2135 ipa_get_jf_ancestor_offset (jfunc));
2137 else if (!src_plats->aggs_by_ref)
2138 ret |= set_agg_lats_to_bottom (dest_plats);
2139 else
2140 ret |= set_agg_lats_contain_variable (dest_plats);
2142 else if (jfunc->agg.items)
2144 bool pre_existing = dest_plats->aggs != NULL;
2145 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2146 struct ipa_agg_jf_item *item;
2147 int i;
2149 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2150 return true;
2152 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2154 HOST_WIDE_INT val_size;
2156 if (item->offset < 0)
2157 continue;
2158 gcc_checking_assert (is_gimple_ip_invariant (item->value));
2159 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2161 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2162 &aglat, pre_existing, &ret))
2164 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2165 aglat = &(*aglat)->next;
2167 else if (dest_plats->aggs_bottom)
2168 return true;
2171 ret |= set_chain_of_aglats_contains_variable (*aglat);
2173 else
2174 ret |= set_agg_lats_contain_variable (dest_plats);
2176 return ret;
2179 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2180 non-thunk) destination, the call passes through a thunk. */
2182 static bool
2183 call_passes_through_thunk_p (cgraph_edge *cs)
2185 cgraph_node *alias_or_thunk = cs->callee;
2186 while (alias_or_thunk->alias)
2187 alias_or_thunk = alias_or_thunk->get_alias_target ();
2188 return alias_or_thunk->thunk.thunk_p;
2191 /* Propagate constants from the caller to the callee of CS. INFO describes the
2192 caller. */
2194 static bool
2195 propagate_constants_accross_call (struct cgraph_edge *cs)
2197 struct ipa_node_params *callee_info;
2198 enum availability availability;
2199 cgraph_node *callee;
2200 struct ipa_edge_args *args;
2201 bool ret = false;
2202 int i, args_count, parms_count;
2204 callee = cs->callee->function_symbol (&availability);
2205 if (!callee->definition)
2206 return false;
2207 gcc_checking_assert (callee->has_gimple_body_p ());
2208 callee_info = IPA_NODE_REF (callee);
2210 args = IPA_EDGE_REF (cs);
2211 args_count = ipa_get_cs_argument_count (args);
2212 parms_count = ipa_get_param_count (callee_info);
2213 if (parms_count == 0)
2214 return false;
2216 /* No propagation through instrumentation thunks is available yet.
2217 It should be possible with proper mapping of call args and
2218 instrumented callee params in the propagation loop below. But
2219 this case mostly occurs when legacy code calls instrumented code
2220 and it is not a primary target for optimizations.
2221 We detect instrumentation thunks in aliases and thunks chain by
2222 checking instrumentation_clone flag for chain source and target.
2223 Going through instrumentation thunks we always have it changed
2224 from 0 to 1 and all other nodes do not change it. */
2225 if (!cs->callee->instrumentation_clone
2226 && callee->instrumentation_clone)
2228 for (i = 0; i < parms_count; i++)
2229 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2230 i));
2231 return ret;
2234 /* If this call goes through a thunk we must not propagate to the first (0th)
2235 parameter. However, we might need to uncover a thunk from below a series
2236 of aliases first. */
2237 if (call_passes_through_thunk_p (cs))
2239 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2240 0));
2241 i = 1;
2243 else
2244 i = 0;
2246 for (; (i < args_count) && (i < parms_count); i++)
2248 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2249 struct ipcp_param_lattices *dest_plats;
2250 tree param_type = ipa_get_callee_param_type (cs, i);
2252 dest_plats = ipa_get_parm_lattices (callee_info, i);
2253 if (availability == AVAIL_INTERPOSABLE)
2254 ret |= set_all_contains_variable (dest_plats);
2255 else
2257 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
2258 &dest_plats->itself);
2259 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
2260 &dest_plats->ctxlat);
2261 ret |= propagate_bits_accross_jump_function (cs, i, jump_func,
2262 &dest_plats->bits_lattice);
2263 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
2264 dest_plats);
2265 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2266 ret |= propagate_vr_accross_jump_function (cs,
2267 jump_func, dest_plats,
2268 param_type);
2269 else
2270 ret |= dest_plats->m_value_range.set_to_bottom ();
2273 for (; i < parms_count; i++)
2274 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2276 return ret;
2279 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2280 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2281 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2283 static tree
2284 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2285 vec<tree> known_csts,
2286 vec<ipa_polymorphic_call_context> known_contexts,
2287 vec<ipa_agg_jump_function_p> known_aggs,
2288 struct ipa_agg_replacement_value *agg_reps,
2289 bool *speculative)
2291 int param_index = ie->indirect_info->param_index;
2292 HOST_WIDE_INT anc_offset;
2293 tree t;
2294 tree target = NULL;
2296 *speculative = false;
2298 if (param_index == -1
2299 || known_csts.length () <= (unsigned int) param_index)
2300 return NULL_TREE;
2302 if (!ie->indirect_info->polymorphic)
2304 tree t;
2306 if (ie->indirect_info->agg_contents)
2308 t = NULL;
2309 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2311 while (agg_reps)
2313 if (agg_reps->index == param_index
2314 && agg_reps->offset == ie->indirect_info->offset
2315 && agg_reps->by_ref == ie->indirect_info->by_ref)
2317 t = agg_reps->value;
2318 break;
2320 agg_reps = agg_reps->next;
2323 if (!t)
2325 struct ipa_agg_jump_function *agg;
2326 if (known_aggs.length () > (unsigned int) param_index)
2327 agg = known_aggs[param_index];
2328 else
2329 agg = NULL;
2330 bool from_global_constant;
2331 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2332 ie->indirect_info->offset,
2333 ie->indirect_info->by_ref,
2334 &from_global_constant);
2335 if (t
2336 && !from_global_constant
2337 && !ie->indirect_info->guaranteed_unmodified)
2338 t = NULL_TREE;
2341 else
2342 t = known_csts[param_index];
2344 if (t &&
2345 TREE_CODE (t) == ADDR_EXPR
2346 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2347 return TREE_OPERAND (t, 0);
2348 else
2349 return NULL_TREE;
2352 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2353 return NULL_TREE;
2355 gcc_assert (!ie->indirect_info->agg_contents);
2356 anc_offset = ie->indirect_info->offset;
2358 t = NULL;
2360 /* Try to work out value of virtual table pointer value in replacemnets. */
2361 if (!t && agg_reps && !ie->indirect_info->by_ref)
2363 while (agg_reps)
2365 if (agg_reps->index == param_index
2366 && agg_reps->offset == ie->indirect_info->offset
2367 && agg_reps->by_ref)
2369 t = agg_reps->value;
2370 break;
2372 agg_reps = agg_reps->next;
2376 /* Try to work out value of virtual table pointer value in known
2377 aggregate values. */
2378 if (!t && known_aggs.length () > (unsigned int) param_index
2379 && !ie->indirect_info->by_ref)
2381 struct ipa_agg_jump_function *agg;
2382 agg = known_aggs[param_index];
2383 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2384 ie->indirect_info->offset,
2385 true);
2388 /* If we found the virtual table pointer, lookup the target. */
2389 if (t)
2391 tree vtable;
2392 unsigned HOST_WIDE_INT offset;
2393 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2395 bool can_refer;
2396 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2397 vtable, offset, &can_refer);
2398 if (can_refer)
2400 if (!target
2401 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2402 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2403 || !possible_polymorphic_call_target_p
2404 (ie, cgraph_node::get (target)))
2406 /* Do not speculate builtin_unreachable, it is stupid! */
2407 if (ie->indirect_info->vptr_changed)
2408 return NULL;
2409 target = ipa_impossible_devirt_target (ie, target);
2411 *speculative = ie->indirect_info->vptr_changed;
2412 if (!*speculative)
2413 return target;
2418 /* Do we know the constant value of pointer? */
2419 if (!t)
2420 t = known_csts[param_index];
2422 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2424 ipa_polymorphic_call_context context;
2425 if (known_contexts.length () > (unsigned int) param_index)
2427 context = known_contexts[param_index];
2428 context.offset_by (anc_offset);
2429 if (ie->indirect_info->vptr_changed)
2430 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2431 ie->indirect_info->otr_type);
2432 if (t)
2434 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2435 (t, ie->indirect_info->otr_type, anc_offset);
2436 if (!ctx2.useless_p ())
2437 context.combine_with (ctx2, ie->indirect_info->otr_type);
2440 else if (t)
2442 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2443 anc_offset);
2444 if (ie->indirect_info->vptr_changed)
2445 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2446 ie->indirect_info->otr_type);
2448 else
2449 return NULL_TREE;
2451 vec <cgraph_node *>targets;
2452 bool final;
2454 targets = possible_polymorphic_call_targets
2455 (ie->indirect_info->otr_type,
2456 ie->indirect_info->otr_token,
2457 context, &final);
2458 if (!final || targets.length () > 1)
2460 struct cgraph_node *node;
2461 if (*speculative)
2462 return target;
2463 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2464 || ie->speculative || !ie->maybe_hot_p ())
2465 return NULL;
2466 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2467 ie->indirect_info->otr_token,
2468 context);
2469 if (node)
2471 *speculative = true;
2472 target = node->decl;
2474 else
2475 return NULL;
2477 else
2479 *speculative = false;
2480 if (targets.length () == 1)
2481 target = targets[0]->decl;
2482 else
2483 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2486 if (target && !possible_polymorphic_call_target_p (ie,
2487 cgraph_node::get (target)))
2489 if (*speculative)
2490 return NULL;
2491 target = ipa_impossible_devirt_target (ie, target);
2494 return target;
2498 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2499 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2500 return the destination. */
2502 tree
2503 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2504 vec<tree> known_csts,
2505 vec<ipa_polymorphic_call_context> known_contexts,
2506 vec<ipa_agg_jump_function_p> known_aggs,
2507 bool *speculative)
2509 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2510 known_aggs, NULL, speculative);
2513 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2514 and KNOWN_CONTEXTS. */
2516 static int
2517 devirtualization_time_bonus (struct cgraph_node *node,
2518 vec<tree> known_csts,
2519 vec<ipa_polymorphic_call_context> known_contexts,
2520 vec<ipa_agg_jump_function_p> known_aggs)
2522 struct cgraph_edge *ie;
2523 int res = 0;
2525 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2527 struct cgraph_node *callee;
2528 struct inline_summary *isummary;
2529 enum availability avail;
2530 tree target;
2531 bool speculative;
2533 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2534 known_aggs, &speculative);
2535 if (!target)
2536 continue;
2538 /* Only bare minimum benefit for clearly un-inlineable targets. */
2539 res += 1;
2540 callee = cgraph_node::get (target);
2541 if (!callee || !callee->definition)
2542 continue;
2543 callee = callee->function_symbol (&avail);
2544 if (avail < AVAIL_AVAILABLE)
2545 continue;
2546 isummary = inline_summaries->get (callee);
2547 if (!isummary->inlinable)
2548 continue;
2550 /* FIXME: The values below need re-considering and perhaps also
2551 integrating into the cost metrics, at lest in some very basic way. */
2552 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2553 res += 31 / ((int)speculative + 1);
2554 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2555 res += 15 / ((int)speculative + 1);
2556 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2557 || DECL_DECLARED_INLINE_P (callee->decl))
2558 res += 7 / ((int)speculative + 1);
2561 return res;
2564 /* Return time bonus incurred because of HINTS. */
2566 static int
2567 hint_time_bonus (inline_hints hints)
2569 int result = 0;
2570 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2571 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2572 if (hints & INLINE_HINT_array_index)
2573 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2574 return result;
2577 /* If there is a reason to penalize the function described by INFO in the
2578 cloning goodness evaluation, do so. */
2580 static inline int64_t
2581 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2583 if (info->node_within_scc)
2584 evaluation = (evaluation
2585 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2587 if (info->node_calling_single_call)
2588 evaluation = (evaluation
2589 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2590 / 100;
2592 return evaluation;
2595 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2596 and SIZE_COST and with the sum of frequencies of incoming edges to the
2597 potential new clone in FREQUENCIES. */
2599 static bool
2600 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2601 int freq_sum, gcov_type count_sum, int size_cost)
2603 if (time_benefit == 0
2604 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2605 || node->optimize_for_size_p ())
2606 return false;
2608 gcc_assert (size_cost > 0);
2610 struct ipa_node_params *info = IPA_NODE_REF (node);
2611 if (max_count)
2613 int factor = (count_sum * 1000) / max_count;
2614 int64_t evaluation = (((int64_t) time_benefit * factor)
2615 / size_cost);
2616 evaluation = incorporate_penalties (info, evaluation);
2618 if (dump_file && (dump_flags & TDF_DETAILS))
2619 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2620 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2621 "%s%s) -> evaluation: " "%" PRId64
2622 ", threshold: %i\n",
2623 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2624 info->node_within_scc ? ", scc" : "",
2625 info->node_calling_single_call ? ", single_call" : "",
2626 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2628 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2630 else
2632 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2633 / size_cost);
2634 evaluation = incorporate_penalties (info, evaluation);
2636 if (dump_file && (dump_flags & TDF_DETAILS))
2637 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2638 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2639 "%" PRId64 ", threshold: %i\n",
2640 time_benefit, size_cost, freq_sum,
2641 info->node_within_scc ? ", scc" : "",
2642 info->node_calling_single_call ? ", single_call" : "",
2643 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2645 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2649 /* Return all context independent values from aggregate lattices in PLATS in a
2650 vector. Return NULL if there are none. */
2652 static vec<ipa_agg_jf_item, va_gc> *
2653 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2655 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2657 if (plats->aggs_bottom
2658 || plats->aggs_contain_variable
2659 || plats->aggs_count == 0)
2660 return NULL;
2662 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2663 aglat;
2664 aglat = aglat->next)
2665 if (aglat->is_single_const ())
2667 struct ipa_agg_jf_item item;
2668 item.offset = aglat->offset;
2669 item.value = aglat->values->value;
2670 vec_safe_push (res, item);
2672 return res;
2675 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2676 populate them with values of parameters that are known independent of the
2677 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2678 non-NULL, the movement cost of all removable parameters will be stored in
2679 it. */
2681 static bool
2682 gather_context_independent_values (struct ipa_node_params *info,
2683 vec<tree> *known_csts,
2684 vec<ipa_polymorphic_call_context>
2685 *known_contexts,
2686 vec<ipa_agg_jump_function> *known_aggs,
2687 int *removable_params_cost)
2689 int i, count = ipa_get_param_count (info);
2690 bool ret = false;
2692 known_csts->create (0);
2693 known_contexts->create (0);
2694 known_csts->safe_grow_cleared (count);
2695 known_contexts->safe_grow_cleared (count);
2696 if (known_aggs)
2698 known_aggs->create (0);
2699 known_aggs->safe_grow_cleared (count);
2702 if (removable_params_cost)
2703 *removable_params_cost = 0;
2705 for (i = 0; i < count ; i++)
2707 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2708 ipcp_lattice<tree> *lat = &plats->itself;
2710 if (lat->is_single_const ())
2712 ipcp_value<tree> *val = lat->values;
2713 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2714 (*known_csts)[i] = val->value;
2715 if (removable_params_cost)
2716 *removable_params_cost
2717 += estimate_move_cost (TREE_TYPE (val->value), false);
2718 ret = true;
2720 else if (removable_params_cost
2721 && !ipa_is_param_used (info, i))
2722 *removable_params_cost
2723 += ipa_get_param_move_cost (info, i);
2725 if (!ipa_is_param_used (info, i))
2726 continue;
2728 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2729 /* Do not account known context as reason for cloning. We can see
2730 if it permits devirtualization. */
2731 if (ctxlat->is_single_const ())
2732 (*known_contexts)[i] = ctxlat->values->value;
2734 if (known_aggs)
2736 vec<ipa_agg_jf_item, va_gc> *agg_items;
2737 struct ipa_agg_jump_function *ajf;
2739 agg_items = context_independent_aggregate_values (plats);
2740 ajf = &(*known_aggs)[i];
2741 ajf->items = agg_items;
2742 ajf->by_ref = plats->aggs_by_ref;
2743 ret |= agg_items != NULL;
2747 return ret;
2750 /* The current interface in ipa-inline-analysis requires a pointer vector.
2751 Create it.
2753 FIXME: That interface should be re-worked, this is slightly silly. Still,
2754 I'd like to discuss how to change it first and this demonstrates the
2755 issue. */
2757 static vec<ipa_agg_jump_function_p>
2758 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2760 vec<ipa_agg_jump_function_p> ret;
2761 struct ipa_agg_jump_function *ajf;
2762 int i;
2764 ret.create (known_aggs.length ());
2765 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2766 ret.quick_push (ajf);
2767 return ret;
2770 /* Perform time and size measurement of NODE with the context given in
2771 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2772 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2773 all context-independent removable parameters and EST_MOVE_COST of estimated
2774 movement of the considered parameter and store it into VAL. */
2776 static void
2777 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2778 vec<ipa_polymorphic_call_context> known_contexts,
2779 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2780 int base_time, int removable_params_cost,
2781 int est_move_cost, ipcp_value_base *val)
2783 int time, size, time_benefit;
2784 inline_hints hints;
2786 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2787 known_aggs_ptrs, &size, &time,
2788 &hints);
2789 time_benefit = base_time - time
2790 + devirtualization_time_bonus (node, known_csts, known_contexts,
2791 known_aggs_ptrs)
2792 + hint_time_bonus (hints)
2793 + removable_params_cost + est_move_cost;
2795 gcc_checking_assert (size >=0);
2796 /* The inliner-heuristics based estimates may think that in certain
2797 contexts some functions do not have any size at all but we want
2798 all specializations to have at least a tiny cost, not least not to
2799 divide by zero. */
2800 if (size == 0)
2801 size = 1;
2803 val->local_time_benefit = time_benefit;
2804 val->local_size_cost = size;
2807 /* Iterate over known values of parameters of NODE and estimate the local
2808 effects in terms of time and size they have. */
2810 static void
2811 estimate_local_effects (struct cgraph_node *node)
2813 struct ipa_node_params *info = IPA_NODE_REF (node);
2814 int i, count = ipa_get_param_count (info);
2815 vec<tree> known_csts;
2816 vec<ipa_polymorphic_call_context> known_contexts;
2817 vec<ipa_agg_jump_function> known_aggs;
2818 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2819 bool always_const;
2820 int base_time = inline_summaries->get (node)->time;
2821 int removable_params_cost;
2823 if (!count || !ipcp_versionable_function_p (node))
2824 return;
2826 if (dump_file && (dump_flags & TDF_DETAILS))
2827 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2828 node->name (), node->order, base_time);
2830 always_const = gather_context_independent_values (info, &known_csts,
2831 &known_contexts, &known_aggs,
2832 &removable_params_cost);
2833 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2834 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2835 known_contexts, known_aggs_ptrs);
2836 if (always_const || devirt_bonus
2837 || (removable_params_cost && node->local.can_change_signature))
2839 struct caller_statistics stats;
2840 inline_hints hints;
2841 int time, size;
2843 init_caller_stats (&stats);
2844 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2845 false);
2846 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2847 known_aggs_ptrs, &size, &time, &hints);
2848 time -= devirt_bonus;
2849 time -= hint_time_bonus (hints);
2850 time -= removable_params_cost;
2851 size -= stats.n_calls * removable_params_cost;
2853 if (dump_file)
2854 fprintf (dump_file, " - context independent values, size: %i, "
2855 "time_benefit: %i\n", size, base_time - time);
2857 if (size <= 0 || node->local.local)
2859 info->do_clone_for_all_contexts = true;
2860 base_time = time;
2862 if (dump_file)
2863 fprintf (dump_file, " Decided to specialize for all "
2864 "known contexts, code not going to grow.\n");
2866 else if (good_cloning_opportunity_p (node, base_time - time,
2867 stats.freq_sum, stats.count_sum,
2868 size))
2870 if (size + overall_size <= max_new_size)
2872 info->do_clone_for_all_contexts = true;
2873 base_time = time;
2874 overall_size += size;
2876 if (dump_file)
2877 fprintf (dump_file, " Decided to specialize for all "
2878 "known contexts, growth deemed beneficial.\n");
2880 else if (dump_file && (dump_flags & TDF_DETAILS))
2881 fprintf (dump_file, " Not cloning for all contexts because "
2882 "max_new_size would be reached with %li.\n",
2883 size + overall_size);
2885 else if (dump_file && (dump_flags & TDF_DETAILS))
2886 fprintf (dump_file, " Not cloning for all contexts because "
2887 "!good_cloning_opportunity_p.\n");
2891 for (i = 0; i < count ; i++)
2893 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2894 ipcp_lattice<tree> *lat = &plats->itself;
2895 ipcp_value<tree> *val;
2897 if (lat->bottom
2898 || !lat->values
2899 || known_csts[i])
2900 continue;
2902 for (val = lat->values; val; val = val->next)
2904 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2905 known_csts[i] = val->value;
2907 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2908 perform_estimation_of_a_value (node, known_csts, known_contexts,
2909 known_aggs_ptrs, base_time,
2910 removable_params_cost, emc, val);
2912 if (dump_file && (dump_flags & TDF_DETAILS))
2914 fprintf (dump_file, " - estimates for value ");
2915 print_ipcp_constant_value (dump_file, val->value);
2916 fprintf (dump_file, " for ");
2917 ipa_dump_param (dump_file, info, i);
2918 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2919 val->local_time_benefit, val->local_size_cost);
2922 known_csts[i] = NULL_TREE;
2925 for (i = 0; i < count; i++)
2927 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2929 if (!plats->virt_call)
2930 continue;
2932 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2933 ipcp_value<ipa_polymorphic_call_context> *val;
2935 if (ctxlat->bottom
2936 || !ctxlat->values
2937 || !known_contexts[i].useless_p ())
2938 continue;
2940 for (val = ctxlat->values; val; val = val->next)
2942 known_contexts[i] = val->value;
2943 perform_estimation_of_a_value (node, known_csts, known_contexts,
2944 known_aggs_ptrs, base_time,
2945 removable_params_cost, 0, val);
2947 if (dump_file && (dump_flags & TDF_DETAILS))
2949 fprintf (dump_file, " - estimates for polymorphic context ");
2950 print_ipcp_constant_value (dump_file, val->value);
2951 fprintf (dump_file, " for ");
2952 ipa_dump_param (dump_file, info, i);
2953 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2954 val->local_time_benefit, val->local_size_cost);
2957 known_contexts[i] = ipa_polymorphic_call_context ();
2960 for (i = 0; i < count ; i++)
2962 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2963 struct ipa_agg_jump_function *ajf;
2964 struct ipcp_agg_lattice *aglat;
2966 if (plats->aggs_bottom || !plats->aggs)
2967 continue;
2969 ajf = &known_aggs[i];
2970 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2972 ipcp_value<tree> *val;
2973 if (aglat->bottom || !aglat->values
2974 /* If the following is true, the one value is in known_aggs. */
2975 || (!plats->aggs_contain_variable
2976 && aglat->is_single_const ()))
2977 continue;
2979 for (val = aglat->values; val; val = val->next)
2981 struct ipa_agg_jf_item item;
2983 item.offset = aglat->offset;
2984 item.value = val->value;
2985 vec_safe_push (ajf->items, item);
2987 perform_estimation_of_a_value (node, known_csts, known_contexts,
2988 known_aggs_ptrs, base_time,
2989 removable_params_cost, 0, val);
2991 if (dump_file && (dump_flags & TDF_DETAILS))
2993 fprintf (dump_file, " - estimates for value ");
2994 print_ipcp_constant_value (dump_file, val->value);
2995 fprintf (dump_file, " for ");
2996 ipa_dump_param (dump_file, info, i);
2997 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2998 "]: time_benefit: %i, size: %i\n",
2999 plats->aggs_by_ref ? "ref " : "",
3000 aglat->offset,
3001 val->local_time_benefit, val->local_size_cost);
3004 ajf->items->pop ();
3009 for (i = 0; i < count ; i++)
3010 vec_free (known_aggs[i].items);
3012 known_csts.release ();
3013 known_contexts.release ();
3014 known_aggs.release ();
3015 known_aggs_ptrs.release ();
3019 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3020 topological sort of values. */
3022 template <typename valtype>
3023 void
3024 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3026 ipcp_value_source<valtype> *src;
3028 if (cur_val->dfs)
3029 return;
3031 dfs_counter++;
3032 cur_val->dfs = dfs_counter;
3033 cur_val->low_link = dfs_counter;
3035 cur_val->topo_next = stack;
3036 stack = cur_val;
3037 cur_val->on_stack = true;
3039 for (src = cur_val->sources; src; src = src->next)
3040 if (src->val)
3042 if (src->val->dfs == 0)
3044 add_val (src->val);
3045 if (src->val->low_link < cur_val->low_link)
3046 cur_val->low_link = src->val->low_link;
3048 else if (src->val->on_stack
3049 && src->val->dfs < cur_val->low_link)
3050 cur_val->low_link = src->val->dfs;
3053 if (cur_val->dfs == cur_val->low_link)
3055 ipcp_value<valtype> *v, *scc_list = NULL;
3059 v = stack;
3060 stack = v->topo_next;
3061 v->on_stack = false;
3063 v->scc_next = scc_list;
3064 scc_list = v;
3066 while (v != cur_val);
3068 cur_val->topo_next = values_topo;
3069 values_topo = cur_val;
3073 /* Add all values in lattices associated with NODE to the topological sort if
3074 they are not there yet. */
3076 static void
3077 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3079 struct ipa_node_params *info = IPA_NODE_REF (node);
3080 int i, count = ipa_get_param_count (info);
3082 for (i = 0; i < count ; i++)
3084 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3085 ipcp_lattice<tree> *lat = &plats->itself;
3086 struct ipcp_agg_lattice *aglat;
3088 if (!lat->bottom)
3090 ipcp_value<tree> *val;
3091 for (val = lat->values; val; val = val->next)
3092 topo->constants.add_val (val);
3095 if (!plats->aggs_bottom)
3096 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3097 if (!aglat->bottom)
3099 ipcp_value<tree> *val;
3100 for (val = aglat->values; val; val = val->next)
3101 topo->constants.add_val (val);
3104 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3105 if (!ctxlat->bottom)
3107 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3108 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3109 topo->contexts.add_val (ctxval);
3114 /* One pass of constants propagation along the call graph edges, from callers
3115 to callees (requires topological ordering in TOPO), iterate over strongly
3116 connected components. */
3118 static void
3119 propagate_constants_topo (struct ipa_topo_info *topo)
3121 int i;
3123 for (i = topo->nnodes - 1; i >= 0; i--)
3125 unsigned j;
3126 struct cgraph_node *v, *node = topo->order[i];
3127 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3129 /* First, iteratively propagate within the strongly connected component
3130 until all lattices stabilize. */
3131 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3132 if (v->has_gimple_body_p ())
3133 push_node_to_stack (topo, v);
3135 v = pop_node_from_stack (topo);
3136 while (v)
3138 struct cgraph_edge *cs;
3140 for (cs = v->callees; cs; cs = cs->next_callee)
3141 if (ipa_edge_within_scc (cs))
3143 IPA_NODE_REF (v)->node_within_scc = true;
3144 if (propagate_constants_accross_call (cs))
3145 push_node_to_stack (topo, cs->callee->function_symbol ());
3147 v = pop_node_from_stack (topo);
3150 /* Afterwards, propagate along edges leading out of the SCC, calculates
3151 the local effects of the discovered constants and all valid values to
3152 their topological sort. */
3153 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3154 if (v->has_gimple_body_p ())
3156 struct cgraph_edge *cs;
3158 estimate_local_effects (v);
3159 add_all_node_vals_to_toposort (v, topo);
3160 for (cs = v->callees; cs; cs = cs->next_callee)
3161 if (!ipa_edge_within_scc (cs))
3162 propagate_constants_accross_call (cs);
3164 cycle_nodes.release ();
3169 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3170 the bigger one if otherwise. */
3172 static int
3173 safe_add (int a, int b)
3175 if (a > INT_MAX/2 || b > INT_MAX/2)
3176 return a > b ? a : b;
3177 else
3178 return a + b;
3182 /* Propagate the estimated effects of individual values along the topological
3183 from the dependent values to those they depend on. */
3185 template <typename valtype>
3186 void
3187 value_topo_info<valtype>::propagate_effects ()
3189 ipcp_value<valtype> *base;
3191 for (base = values_topo; base; base = base->topo_next)
3193 ipcp_value_source<valtype> *src;
3194 ipcp_value<valtype> *val;
3195 int time = 0, size = 0;
3197 for (val = base; val; val = val->scc_next)
3199 time = safe_add (time,
3200 val->local_time_benefit + val->prop_time_benefit);
3201 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3204 for (val = base; val; val = val->scc_next)
3205 for (src = val->sources; src; src = src->next)
3206 if (src->val
3207 && src->cs->maybe_hot_p ())
3209 src->val->prop_time_benefit = safe_add (time,
3210 src->val->prop_time_benefit);
3211 src->val->prop_size_cost = safe_add (size,
3212 src->val->prop_size_cost);
3218 /* Propagate constants, polymorphic contexts and their effects from the
3219 summaries interprocedurally. */
3221 static void
3222 ipcp_propagate_stage (struct ipa_topo_info *topo)
3224 struct cgraph_node *node;
3226 if (dump_file)
3227 fprintf (dump_file, "\n Propagating constants:\n\n");
3229 if (in_lto_p)
3230 ipa_update_after_lto_read ();
3233 FOR_EACH_DEFINED_FUNCTION (node)
3235 struct ipa_node_params *info = IPA_NODE_REF (node);
3237 /* In LTO we do not have PARM_DECLs but we would still like to be able to
3238 look at types of parameters. */
3239 if (in_lto_p)
3241 tree t = TYPE_ARG_TYPES (TREE_TYPE (node->decl));
3242 for (int k = 0; k < ipa_get_param_count (info) && t; k++)
3244 gcc_assert (t != void_list_node);
3245 info->descriptors[k].decl_or_type = TREE_VALUE (t);
3246 t = t ? TREE_CHAIN (t) : NULL;
3250 determine_versionability (node, info);
3251 if (node->has_gimple_body_p ())
3253 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3254 ipa_get_param_count (info));
3255 initialize_node_lattices (node);
3257 if (node->definition && !node->alias)
3258 overall_size += inline_summaries->get (node)->self_size;
3259 if (node->count > max_count)
3260 max_count = node->count;
3263 max_new_size = overall_size;
3264 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3265 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3266 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3268 if (dump_file)
3269 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3270 overall_size, max_new_size);
3272 propagate_constants_topo (topo);
3273 if (flag_checking)
3274 ipcp_verify_propagated_values ();
3275 topo->constants.propagate_effects ();
3276 topo->contexts.propagate_effects ();
3278 if (dump_file)
3280 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3281 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3285 /* Discover newly direct outgoing edges from NODE which is a new clone with
3286 known KNOWN_CSTS and make them direct. */
3288 static void
3289 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3290 vec<tree> known_csts,
3291 vec<ipa_polymorphic_call_context>
3292 known_contexts,
3293 struct ipa_agg_replacement_value *aggvals)
3295 struct cgraph_edge *ie, *next_ie;
3296 bool found = false;
3298 for (ie = node->indirect_calls; ie; ie = next_ie)
3300 tree target;
3301 bool speculative;
3303 next_ie = ie->next_callee;
3304 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3305 vNULL, aggvals, &speculative);
3306 if (target)
3308 bool agg_contents = ie->indirect_info->agg_contents;
3309 bool polymorphic = ie->indirect_info->polymorphic;
3310 int param_index = ie->indirect_info->param_index;
3311 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3312 speculative);
3313 found = true;
3315 if (cs && !agg_contents && !polymorphic)
3317 struct ipa_node_params *info = IPA_NODE_REF (node);
3318 int c = ipa_get_controlled_uses (info, param_index);
3319 if (c != IPA_UNDESCRIBED_USE)
3321 struct ipa_ref *to_del;
3323 c--;
3324 ipa_set_controlled_uses (info, param_index, c);
3325 if (dump_file && (dump_flags & TDF_DETAILS))
3326 fprintf (dump_file, " controlled uses count of param "
3327 "%i bumped down to %i\n", param_index, c);
3328 if (c == 0
3329 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3331 if (dump_file && (dump_flags & TDF_DETAILS))
3332 fprintf (dump_file, " and even removing its "
3333 "cloning-created reference\n");
3334 to_del->remove_reference ();
3340 /* Turning calls to direct calls will improve overall summary. */
3341 if (found)
3342 inline_update_overall_summary (node);
3345 /* Vector of pointers which for linked lists of clones of an original crgaph
3346 edge. */
3348 static vec<cgraph_edge *> next_edge_clone;
3349 static vec<cgraph_edge *> prev_edge_clone;
3351 static inline void
3352 grow_edge_clone_vectors (void)
3354 if (next_edge_clone.length ()
3355 <= (unsigned) symtab->edges_max_uid)
3356 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3357 if (prev_edge_clone.length ()
3358 <= (unsigned) symtab->edges_max_uid)
3359 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3362 /* Edge duplication hook to grow the appropriate linked list in
3363 next_edge_clone. */
3365 static void
3366 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
3367 void *)
3369 grow_edge_clone_vectors ();
3371 struct cgraph_edge *old_next = next_edge_clone[src->uid];
3372 if (old_next)
3373 prev_edge_clone[old_next->uid] = dst;
3374 prev_edge_clone[dst->uid] = src;
3376 next_edge_clone[dst->uid] = old_next;
3377 next_edge_clone[src->uid] = dst;
3380 /* Hook that is called by cgraph.c when an edge is removed. */
3382 static void
3383 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
3385 grow_edge_clone_vectors ();
3387 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
3388 struct cgraph_edge *next = next_edge_clone[cs->uid];
3389 if (prev)
3390 next_edge_clone[prev->uid] = next;
3391 if (next)
3392 prev_edge_clone[next->uid] = prev;
3395 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3396 parameter with the given INDEX. */
3398 static tree
3399 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3400 int index)
3402 struct ipa_agg_replacement_value *aggval;
3404 aggval = ipa_get_agg_replacements_for_node (node);
3405 while (aggval)
3407 if (aggval->offset == offset
3408 && aggval->index == index)
3409 return aggval->value;
3410 aggval = aggval->next;
3412 return NULL_TREE;
3415 /* Return true is NODE is DEST or its clone for all contexts. */
3417 static bool
3418 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3420 if (node == dest)
3421 return true;
3423 struct ipa_node_params *info = IPA_NODE_REF (node);
3424 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3427 /* Return true if edge CS does bring about the value described by SRC to node
3428 DEST or its clone for all contexts. */
3430 static bool
3431 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3432 cgraph_node *dest)
3434 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3435 enum availability availability;
3436 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3438 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3439 || availability <= AVAIL_INTERPOSABLE
3440 || caller_info->node_dead)
3441 return false;
3442 if (!src->val)
3443 return true;
3445 if (caller_info->ipcp_orig_node)
3447 tree t;
3448 if (src->offset == -1)
3449 t = caller_info->known_csts[src->index];
3450 else
3451 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3452 return (t != NULL_TREE
3453 && values_equal_for_ipcp_p (src->val->value, t));
3455 else
3457 struct ipcp_agg_lattice *aglat;
3458 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3459 src->index);
3460 if (src->offset == -1)
3461 return (plats->itself.is_single_const ()
3462 && values_equal_for_ipcp_p (src->val->value,
3463 plats->itself.values->value));
3464 else
3466 if (plats->aggs_bottom || plats->aggs_contain_variable)
3467 return false;
3468 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3469 if (aglat->offset == src->offset)
3470 return (aglat->is_single_const ()
3471 && values_equal_for_ipcp_p (src->val->value,
3472 aglat->values->value));
3474 return false;
3478 /* Return true if edge CS does bring about the value described by SRC to node
3479 DEST or its clone for all contexts. */
3481 static bool
3482 cgraph_edge_brings_value_p (cgraph_edge *cs,
3483 ipcp_value_source<ipa_polymorphic_call_context> *src,
3484 cgraph_node *dest)
3486 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3487 cgraph_node *real_dest = cs->callee->function_symbol ();
3489 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3490 || caller_info->node_dead)
3491 return false;
3492 if (!src->val)
3493 return true;
3495 if (caller_info->ipcp_orig_node)
3496 return (caller_info->known_contexts.length () > (unsigned) src->index)
3497 && values_equal_for_ipcp_p (src->val->value,
3498 caller_info->known_contexts[src->index]);
3500 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3501 src->index);
3502 return plats->ctxlat.is_single_const ()
3503 && values_equal_for_ipcp_p (src->val->value,
3504 plats->ctxlat.values->value);
3507 /* Get the next clone in the linked list of clones of an edge. */
3509 static inline struct cgraph_edge *
3510 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3512 return next_edge_clone[cs->uid];
3515 /* Given VAL that is intended for DEST, iterate over all its sources and if
3516 they still hold, add their edge frequency and their number into *FREQUENCY
3517 and *CALLER_COUNT respectively. */
3519 template <typename valtype>
3520 static bool
3521 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3522 int *freq_sum,
3523 gcov_type *count_sum, int *caller_count)
3525 ipcp_value_source<valtype> *src;
3526 int freq = 0, count = 0;
3527 gcov_type cnt = 0;
3528 bool hot = false;
3530 for (src = val->sources; src; src = src->next)
3532 struct cgraph_edge *cs = src->cs;
3533 while (cs)
3535 if (cgraph_edge_brings_value_p (cs, src, dest))
3537 count++;
3538 freq += cs->frequency;
3539 cnt += cs->count;
3540 hot |= cs->maybe_hot_p ();
3542 cs = get_next_cgraph_edge_clone (cs);
3546 *freq_sum = freq;
3547 *count_sum = cnt;
3548 *caller_count = count;
3549 return hot;
3552 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3553 is assumed their number is known and equal to CALLER_COUNT. */
3555 template <typename valtype>
3556 static vec<cgraph_edge *>
3557 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3558 int caller_count)
3560 ipcp_value_source<valtype> *src;
3561 vec<cgraph_edge *> ret;
3563 ret.create (caller_count);
3564 for (src = val->sources; src; src = src->next)
3566 struct cgraph_edge *cs = src->cs;
3567 while (cs)
3569 if (cgraph_edge_brings_value_p (cs, src, dest))
3570 ret.quick_push (cs);
3571 cs = get_next_cgraph_edge_clone (cs);
3575 return ret;
3578 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3579 Return it or NULL if for some reason it cannot be created. */
3581 static struct ipa_replace_map *
3582 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3584 struct ipa_replace_map *replace_map;
3587 replace_map = ggc_alloc<ipa_replace_map> ();
3588 if (dump_file)
3590 fprintf (dump_file, " replacing ");
3591 ipa_dump_param (dump_file, info, parm_num);
3593 fprintf (dump_file, " with const ");
3594 print_generic_expr (dump_file, value, 0);
3595 fprintf (dump_file, "\n");
3597 replace_map->old_tree = NULL;
3598 replace_map->parm_num = parm_num;
3599 replace_map->new_tree = value;
3600 replace_map->replace_p = true;
3601 replace_map->ref_p = false;
3603 return replace_map;
3606 /* Dump new profiling counts */
3608 static void
3609 dump_profile_updates (struct cgraph_node *orig_node,
3610 struct cgraph_node *new_node)
3612 struct cgraph_edge *cs;
3614 fprintf (dump_file, " setting count of the specialized node to "
3615 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3616 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3617 fprintf (dump_file, " edge to %s has count "
3618 HOST_WIDE_INT_PRINT_DEC "\n",
3619 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3621 fprintf (dump_file, " setting count of the original node to "
3622 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3623 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3624 fprintf (dump_file, " edge to %s is left with "
3625 HOST_WIDE_INT_PRINT_DEC "\n",
3626 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3629 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3630 their profile information to reflect this. */
3632 static void
3633 update_profiling_info (struct cgraph_node *orig_node,
3634 struct cgraph_node *new_node)
3636 struct cgraph_edge *cs;
3637 struct caller_statistics stats;
3638 gcov_type new_sum, orig_sum;
3639 gcov_type remainder, orig_node_count = orig_node->count;
3641 if (orig_node_count == 0)
3642 return;
3644 init_caller_stats (&stats);
3645 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3646 false);
3647 orig_sum = stats.count_sum;
3648 init_caller_stats (&stats);
3649 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3650 false);
3651 new_sum = stats.count_sum;
3653 if (orig_node_count < orig_sum + new_sum)
3655 if (dump_file)
3656 fprintf (dump_file, " Problem: node %s/%i has too low count "
3657 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3658 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3659 orig_node->name (), orig_node->order,
3660 (HOST_WIDE_INT) orig_node_count,
3661 (HOST_WIDE_INT) (orig_sum + new_sum));
3663 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3664 if (dump_file)
3665 fprintf (dump_file, " proceeding by pretending it was "
3666 HOST_WIDE_INT_PRINT_DEC "\n",
3667 (HOST_WIDE_INT) orig_node_count);
3670 new_node->count = new_sum;
3671 remainder = orig_node_count - new_sum;
3672 orig_node->count = remainder;
3674 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3675 if (cs->frequency)
3676 cs->count = apply_probability (cs->count,
3677 GCOV_COMPUTE_SCALE (new_sum,
3678 orig_node_count));
3679 else
3680 cs->count = 0;
3682 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3683 cs->count = apply_probability (cs->count,
3684 GCOV_COMPUTE_SCALE (remainder,
3685 orig_node_count));
3687 if (dump_file)
3688 dump_profile_updates (orig_node, new_node);
3691 /* Update the respective profile of specialized NEW_NODE and the original
3692 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3693 have been redirected to the specialized version. */
3695 static void
3696 update_specialized_profile (struct cgraph_node *new_node,
3697 struct cgraph_node *orig_node,
3698 gcov_type redirected_sum)
3700 struct cgraph_edge *cs;
3701 gcov_type new_node_count, orig_node_count = orig_node->count;
3703 if (dump_file)
3704 fprintf (dump_file, " the sum of counts of redirected edges is "
3705 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3706 if (orig_node_count == 0)
3707 return;
3709 gcc_assert (orig_node_count >= redirected_sum);
3711 new_node_count = new_node->count;
3712 new_node->count += redirected_sum;
3713 orig_node->count -= redirected_sum;
3715 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3716 if (cs->frequency)
3717 cs->count += apply_probability (cs->count,
3718 GCOV_COMPUTE_SCALE (redirected_sum,
3719 new_node_count));
3720 else
3721 cs->count = 0;
3723 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3725 gcov_type dec = apply_probability (cs->count,
3726 GCOV_COMPUTE_SCALE (redirected_sum,
3727 orig_node_count));
3728 if (dec < cs->count)
3729 cs->count -= dec;
3730 else
3731 cs->count = 0;
3734 if (dump_file)
3735 dump_profile_updates (orig_node, new_node);
3738 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3739 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3740 redirect all edges in CALLERS to it. */
3742 static struct cgraph_node *
3743 create_specialized_node (struct cgraph_node *node,
3744 vec<tree> known_csts,
3745 vec<ipa_polymorphic_call_context> known_contexts,
3746 struct ipa_agg_replacement_value *aggvals,
3747 vec<cgraph_edge *> callers)
3749 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3750 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3751 struct ipa_agg_replacement_value *av;
3752 struct cgraph_node *new_node;
3753 int i, count = ipa_get_param_count (info);
3754 bitmap args_to_skip;
3756 gcc_assert (!info->ipcp_orig_node);
3758 if (node->local.can_change_signature)
3760 args_to_skip = BITMAP_GGC_ALLOC ();
3761 for (i = 0; i < count; i++)
3763 tree t = known_csts[i];
3765 if (t || !ipa_is_param_used (info, i))
3766 bitmap_set_bit (args_to_skip, i);
3769 else
3771 args_to_skip = NULL;
3772 if (dump_file && (dump_flags & TDF_DETAILS))
3773 fprintf (dump_file, " cannot change function signature\n");
3776 for (i = 0; i < count ; i++)
3778 tree t = known_csts[i];
3779 if (t)
3781 struct ipa_replace_map *replace_map;
3783 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3784 replace_map = get_replacement_map (info, t, i);
3785 if (replace_map)
3786 vec_safe_push (replace_trees, replace_map);
3790 new_node = node->create_virtual_clone (callers, replace_trees,
3791 args_to_skip, "constprop");
3792 ipa_set_node_agg_value_chain (new_node, aggvals);
3793 for (av = aggvals; av; av = av->next)
3794 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3796 if (dump_file && (dump_flags & TDF_DETAILS))
3798 fprintf (dump_file, " the new node is %s/%i.\n",
3799 new_node->name (), new_node->order);
3800 if (known_contexts.exists ())
3802 for (i = 0; i < count ; i++)
3803 if (!known_contexts[i].useless_p ())
3805 fprintf (dump_file, " known ctx %i is ", i);
3806 known_contexts[i].dump (dump_file);
3809 if (aggvals)
3810 ipa_dump_agg_replacement_values (dump_file, aggvals);
3812 ipa_check_create_node_params ();
3813 update_profiling_info (node, new_node);
3814 new_info = IPA_NODE_REF (new_node);
3815 new_info->ipcp_orig_node = node;
3816 new_info->known_csts = known_csts;
3817 new_info->known_contexts = known_contexts;
3819 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3821 callers.release ();
3822 return new_node;
3825 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3826 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3828 static void
3829 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3830 vec<tree> known_csts,
3831 vec<cgraph_edge *> callers)
3833 struct ipa_node_params *info = IPA_NODE_REF (node);
3834 int i, count = ipa_get_param_count (info);
3836 for (i = 0; i < count ; i++)
3838 struct cgraph_edge *cs;
3839 tree newval = NULL_TREE;
3840 int j;
3841 bool first = true;
3843 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3844 continue;
3846 FOR_EACH_VEC_ELT (callers, j, cs)
3848 struct ipa_jump_func *jump_func;
3849 tree t;
3851 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3852 || (i == 0
3853 && call_passes_through_thunk_p (cs))
3854 || (!cs->callee->instrumentation_clone
3855 && cs->callee->function_symbol ()->instrumentation_clone))
3857 newval = NULL_TREE;
3858 break;
3860 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3861 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3862 if (!t
3863 || (newval
3864 && !values_equal_for_ipcp_p (t, newval))
3865 || (!first && !newval))
3867 newval = NULL_TREE;
3868 break;
3870 else
3871 newval = t;
3872 first = false;
3875 if (newval)
3877 if (dump_file && (dump_flags & TDF_DETAILS))
3879 fprintf (dump_file, " adding an extra known scalar value ");
3880 print_ipcp_constant_value (dump_file, newval);
3881 fprintf (dump_file, " for ");
3882 ipa_dump_param (dump_file, info, i);
3883 fprintf (dump_file, "\n");
3886 known_csts[i] = newval;
3891 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3892 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3893 CALLERS. */
3895 static void
3896 find_more_contexts_for_caller_subset (cgraph_node *node,
3897 vec<ipa_polymorphic_call_context>
3898 *known_contexts,
3899 vec<cgraph_edge *> callers)
3901 ipa_node_params *info = IPA_NODE_REF (node);
3902 int i, count = ipa_get_param_count (info);
3904 for (i = 0; i < count ; i++)
3906 cgraph_edge *cs;
3908 if (ipa_get_poly_ctx_lat (info, i)->bottom
3909 || (known_contexts->exists ()
3910 && !(*known_contexts)[i].useless_p ()))
3911 continue;
3913 ipa_polymorphic_call_context newval;
3914 bool first = true;
3915 int j;
3917 FOR_EACH_VEC_ELT (callers, j, cs)
3919 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3920 return;
3921 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3923 ipa_polymorphic_call_context ctx;
3924 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3925 jfunc);
3926 if (first)
3928 newval = ctx;
3929 first = false;
3931 else
3932 newval.meet_with (ctx);
3933 if (newval.useless_p ())
3934 break;
3937 if (!newval.useless_p ())
3939 if (dump_file && (dump_flags & TDF_DETAILS))
3941 fprintf (dump_file, " adding an extra known polymorphic "
3942 "context ");
3943 print_ipcp_constant_value (dump_file, newval);
3944 fprintf (dump_file, " for ");
3945 ipa_dump_param (dump_file, info, i);
3946 fprintf (dump_file, "\n");
3949 if (!known_contexts->exists ())
3950 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3951 (*known_contexts)[i] = newval;
3957 /* Go through PLATS and create a vector of values consisting of values and
3958 offsets (minus OFFSET) of lattices that contain only a single value. */
3960 static vec<ipa_agg_jf_item>
3961 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3963 vec<ipa_agg_jf_item> res = vNULL;
3965 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3966 return vNULL;
3968 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3969 if (aglat->is_single_const ())
3971 struct ipa_agg_jf_item ti;
3972 ti.offset = aglat->offset - offset;
3973 ti.value = aglat->values->value;
3974 res.safe_push (ti);
3976 return res;
3979 /* Intersect all values in INTER with single value lattices in PLATS (while
3980 subtracting OFFSET). */
3982 static void
3983 intersect_with_plats (struct ipcp_param_lattices *plats,
3984 vec<ipa_agg_jf_item> *inter,
3985 HOST_WIDE_INT offset)
3987 struct ipcp_agg_lattice *aglat;
3988 struct ipa_agg_jf_item *item;
3989 int k;
3991 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3993 inter->release ();
3994 return;
3997 aglat = plats->aggs;
3998 FOR_EACH_VEC_ELT (*inter, k, item)
4000 bool found = false;
4001 if (!item->value)
4002 continue;
4003 while (aglat)
4005 if (aglat->offset - offset > item->offset)
4006 break;
4007 if (aglat->offset - offset == item->offset)
4009 gcc_checking_assert (item->value);
4010 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
4011 found = true;
4012 break;
4014 aglat = aglat->next;
4016 if (!found)
4017 item->value = NULL_TREE;
4021 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
4022 vector result while subtracting OFFSET from the individual value offsets. */
4024 static vec<ipa_agg_jf_item>
4025 agg_replacements_to_vector (struct cgraph_node *node, int index,
4026 HOST_WIDE_INT offset)
4028 struct ipa_agg_replacement_value *av;
4029 vec<ipa_agg_jf_item> res = vNULL;
4031 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4032 if (av->index == index
4033 && (av->offset - offset) >= 0)
4035 struct ipa_agg_jf_item item;
4036 gcc_checking_assert (av->value);
4037 item.offset = av->offset - offset;
4038 item.value = av->value;
4039 res.safe_push (item);
4042 return res;
4045 /* Intersect all values in INTER with those that we have already scheduled to
4046 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4047 (while subtracting OFFSET). */
4049 static void
4050 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4051 vec<ipa_agg_jf_item> *inter,
4052 HOST_WIDE_INT offset)
4054 struct ipa_agg_replacement_value *srcvals;
4055 struct ipa_agg_jf_item *item;
4056 int i;
4058 srcvals = ipa_get_agg_replacements_for_node (node);
4059 if (!srcvals)
4061 inter->release ();
4062 return;
4065 FOR_EACH_VEC_ELT (*inter, i, item)
4067 struct ipa_agg_replacement_value *av;
4068 bool found = false;
4069 if (!item->value)
4070 continue;
4071 for (av = srcvals; av; av = av->next)
4073 gcc_checking_assert (av->value);
4074 if (av->index == index
4075 && av->offset - offset == item->offset)
4077 if (values_equal_for_ipcp_p (item->value, av->value))
4078 found = true;
4079 break;
4082 if (!found)
4083 item->value = NULL_TREE;
4087 /* Intersect values in INTER with aggregate values that come along edge CS to
4088 parameter number INDEX and return it. If INTER does not actually exist yet,
4089 copy all incoming values to it. If we determine we ended up with no values
4090 whatsoever, return a released vector. */
4092 static vec<ipa_agg_jf_item>
4093 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4094 vec<ipa_agg_jf_item> inter)
4096 struct ipa_jump_func *jfunc;
4097 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4098 if (jfunc->type == IPA_JF_PASS_THROUGH
4099 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4101 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4102 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4104 if (caller_info->ipcp_orig_node)
4106 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4107 struct ipcp_param_lattices *orig_plats;
4108 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4109 src_idx);
4110 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4112 if (!inter.exists ())
4113 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4114 else
4115 intersect_with_agg_replacements (cs->caller, src_idx,
4116 &inter, 0);
4118 else
4120 inter.release ();
4121 return vNULL;
4124 else
4126 struct ipcp_param_lattices *src_plats;
4127 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4128 if (agg_pass_through_permissible_p (src_plats, jfunc))
4130 /* Currently we do not produce clobber aggregate jump
4131 functions, adjust when we do. */
4132 gcc_checking_assert (!jfunc->agg.items);
4133 if (!inter.exists ())
4134 inter = copy_plats_to_inter (src_plats, 0);
4135 else
4136 intersect_with_plats (src_plats, &inter, 0);
4138 else
4140 inter.release ();
4141 return vNULL;
4145 else if (jfunc->type == IPA_JF_ANCESTOR
4146 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4148 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4149 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4150 struct ipcp_param_lattices *src_plats;
4151 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4153 if (caller_info->ipcp_orig_node)
4155 if (!inter.exists ())
4156 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4157 else
4158 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4159 delta);
4161 else
4163 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
4164 /* Currently we do not produce clobber aggregate jump
4165 functions, adjust when we do. */
4166 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4167 if (!inter.exists ())
4168 inter = copy_plats_to_inter (src_plats, delta);
4169 else
4170 intersect_with_plats (src_plats, &inter, delta);
4173 else if (jfunc->agg.items)
4175 struct ipa_agg_jf_item *item;
4176 int k;
4178 if (!inter.exists ())
4179 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4180 inter.safe_push ((*jfunc->agg.items)[i]);
4181 else
4182 FOR_EACH_VEC_ELT (inter, k, item)
4184 int l = 0;
4185 bool found = false;;
4187 if (!item->value)
4188 continue;
4190 while ((unsigned) l < jfunc->agg.items->length ())
4192 struct ipa_agg_jf_item *ti;
4193 ti = &(*jfunc->agg.items)[l];
4194 if (ti->offset > item->offset)
4195 break;
4196 if (ti->offset == item->offset)
4198 gcc_checking_assert (ti->value);
4199 if (values_equal_for_ipcp_p (item->value,
4200 ti->value))
4201 found = true;
4202 break;
4204 l++;
4206 if (!found)
4207 item->value = NULL;
4210 else
4212 inter.release ();
4213 return vec<ipa_agg_jf_item>();
4215 return inter;
4218 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4219 from all of them. */
4221 static struct ipa_agg_replacement_value *
4222 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4223 vec<cgraph_edge *> callers)
4225 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4226 struct ipa_agg_replacement_value *res;
4227 struct ipa_agg_replacement_value **tail = &res;
4228 struct cgraph_edge *cs;
4229 int i, j, count = ipa_get_param_count (dest_info);
4231 FOR_EACH_VEC_ELT (callers, j, cs)
4233 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4234 if (c < count)
4235 count = c;
4238 for (i = 0; i < count ; i++)
4240 struct cgraph_edge *cs;
4241 vec<ipa_agg_jf_item> inter = vNULL;
4242 struct ipa_agg_jf_item *item;
4243 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4244 int j;
4246 /* Among other things, the following check should deal with all by_ref
4247 mismatches. */
4248 if (plats->aggs_bottom)
4249 continue;
4251 FOR_EACH_VEC_ELT (callers, j, cs)
4253 inter = intersect_aggregates_with_edge (cs, i, inter);
4255 if (!inter.exists ())
4256 goto next_param;
4259 FOR_EACH_VEC_ELT (inter, j, item)
4261 struct ipa_agg_replacement_value *v;
4263 if (!item->value)
4264 continue;
4266 v = ggc_alloc<ipa_agg_replacement_value> ();
4267 v->index = i;
4268 v->offset = item->offset;
4269 v->value = item->value;
4270 v->by_ref = plats->aggs_by_ref;
4271 *tail = v;
4272 tail = &v->next;
4275 next_param:
4276 if (inter.exists ())
4277 inter.release ();
4279 *tail = NULL;
4280 return res;
4283 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
4285 static struct ipa_agg_replacement_value *
4286 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
4288 struct ipa_agg_replacement_value *res;
4289 struct ipa_agg_replacement_value **tail = &res;
4290 struct ipa_agg_jump_function *aggjf;
4291 struct ipa_agg_jf_item *item;
4292 int i, j;
4294 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
4295 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
4297 struct ipa_agg_replacement_value *v;
4298 v = ggc_alloc<ipa_agg_replacement_value> ();
4299 v->index = i;
4300 v->offset = item->offset;
4301 v->value = item->value;
4302 v->by_ref = aggjf->by_ref;
4303 *tail = v;
4304 tail = &v->next;
4306 *tail = NULL;
4307 return res;
4310 /* Determine whether CS also brings all scalar values that the NODE is
4311 specialized for. */
4313 static bool
4314 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4315 struct cgraph_node *node)
4317 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4318 int count = ipa_get_param_count (dest_info);
4319 struct ipa_node_params *caller_info;
4320 struct ipa_edge_args *args;
4321 int i;
4323 caller_info = IPA_NODE_REF (cs->caller);
4324 args = IPA_EDGE_REF (cs);
4325 for (i = 0; i < count; i++)
4327 struct ipa_jump_func *jump_func;
4328 tree val, t;
4330 val = dest_info->known_csts[i];
4331 if (!val)
4332 continue;
4334 if (i >= ipa_get_cs_argument_count (args))
4335 return false;
4336 jump_func = ipa_get_ith_jump_func (args, i);
4337 t = ipa_value_from_jfunc (caller_info, jump_func);
4338 if (!t || !values_equal_for_ipcp_p (val, t))
4339 return false;
4341 return true;
4344 /* Determine whether CS also brings all aggregate values that NODE is
4345 specialized for. */
4346 static bool
4347 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4348 struct cgraph_node *node)
4350 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4351 struct ipa_node_params *orig_node_info;
4352 struct ipa_agg_replacement_value *aggval;
4353 int i, ec, count;
4355 aggval = ipa_get_agg_replacements_for_node (node);
4356 if (!aggval)
4357 return true;
4359 count = ipa_get_param_count (IPA_NODE_REF (node));
4360 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4361 if (ec < count)
4362 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4363 if (aggval->index >= ec)
4364 return false;
4366 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4367 if (orig_caller_info->ipcp_orig_node)
4368 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4370 for (i = 0; i < count; i++)
4372 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4373 struct ipcp_param_lattices *plats;
4374 bool interesting = false;
4375 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4376 if (aggval->index == i)
4378 interesting = true;
4379 break;
4381 if (!interesting)
4382 continue;
4384 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4385 if (plats->aggs_bottom)
4386 return false;
4388 values = intersect_aggregates_with_edge (cs, i, values);
4389 if (!values.exists ())
4390 return false;
4392 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4393 if (aggval->index == i)
4395 struct ipa_agg_jf_item *item;
4396 int j;
4397 bool found = false;
4398 FOR_EACH_VEC_ELT (values, j, item)
4399 if (item->value
4400 && item->offset == av->offset
4401 && values_equal_for_ipcp_p (item->value, av->value))
4403 found = true;
4404 break;
4406 if (!found)
4408 values.release ();
4409 return false;
4413 return true;
4416 /* Given an original NODE and a VAL for which we have already created a
4417 specialized clone, look whether there are incoming edges that still lead
4418 into the old node but now also bring the requested value and also conform to
4419 all other criteria such that they can be redirected the special node.
4420 This function can therefore redirect the final edge in a SCC. */
4422 template <typename valtype>
4423 static void
4424 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4426 ipcp_value_source<valtype> *src;
4427 gcov_type redirected_sum = 0;
4429 for (src = val->sources; src; src = src->next)
4431 struct cgraph_edge *cs = src->cs;
4432 while (cs)
4434 if (cgraph_edge_brings_value_p (cs, src, node)
4435 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4436 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4438 if (dump_file)
4439 fprintf (dump_file, " - adding an extra caller %s/%i"
4440 " of %s/%i\n",
4441 xstrdup_for_dump (cs->caller->name ()),
4442 cs->caller->order,
4443 xstrdup_for_dump (val->spec_node->name ()),
4444 val->spec_node->order);
4446 cs->redirect_callee_duplicating_thunks (val->spec_node);
4447 val->spec_node->expand_all_artificial_thunks ();
4448 redirected_sum += cs->count;
4450 cs = get_next_cgraph_edge_clone (cs);
4454 if (redirected_sum)
4455 update_specialized_profile (val->spec_node, node, redirected_sum);
4458 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4460 static bool
4461 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4463 ipa_polymorphic_call_context *ctx;
4464 int i;
4466 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4467 if (!ctx->useless_p ())
4468 return true;
4469 return false;
4472 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4474 static vec<ipa_polymorphic_call_context>
4475 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4477 if (known_contexts_useful_p (known_contexts))
4478 return known_contexts.copy ();
4479 else
4480 return vNULL;
4483 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4484 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4486 static void
4487 modify_known_vectors_with_val (vec<tree> *known_csts,
4488 vec<ipa_polymorphic_call_context> *known_contexts,
4489 ipcp_value<tree> *val,
4490 int index)
4492 *known_csts = known_csts->copy ();
4493 *known_contexts = copy_useful_known_contexts (*known_contexts);
4494 (*known_csts)[index] = val->value;
4497 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4498 copy according to VAL and INDEX. */
4500 static void
4501 modify_known_vectors_with_val (vec<tree> *known_csts,
4502 vec<ipa_polymorphic_call_context> *known_contexts,
4503 ipcp_value<ipa_polymorphic_call_context> *val,
4504 int index)
4506 *known_csts = known_csts->copy ();
4507 *known_contexts = known_contexts->copy ();
4508 (*known_contexts)[index] = val->value;
4511 /* Return true if OFFSET indicates this was not an aggregate value or there is
4512 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4513 AGGVALS list. */
4515 DEBUG_FUNCTION bool
4516 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4517 int index, HOST_WIDE_INT offset, tree value)
4519 if (offset == -1)
4520 return true;
4522 while (aggvals)
4524 if (aggvals->index == index
4525 && aggvals->offset == offset
4526 && values_equal_for_ipcp_p (aggvals->value, value))
4527 return true;
4528 aggvals = aggvals->next;
4530 return false;
4533 /* Return true if offset is minus one because source of a polymorphic contect
4534 cannot be an aggregate value. */
4536 DEBUG_FUNCTION bool
4537 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4538 int , HOST_WIDE_INT offset,
4539 ipa_polymorphic_call_context)
4541 return offset == -1;
4544 /* Decide wheter to create a special version of NODE for value VAL of parameter
4545 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4546 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4547 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4549 template <typename valtype>
4550 static bool
4551 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4552 ipcp_value<valtype> *val, vec<tree> known_csts,
4553 vec<ipa_polymorphic_call_context> known_contexts)
4555 struct ipa_agg_replacement_value *aggvals;
4556 int freq_sum, caller_count;
4557 gcov_type count_sum;
4558 vec<cgraph_edge *> callers;
4560 if (val->spec_node)
4562 perhaps_add_new_callers (node, val);
4563 return false;
4565 else if (val->local_size_cost + overall_size > max_new_size)
4567 if (dump_file && (dump_flags & TDF_DETAILS))
4568 fprintf (dump_file, " Ignoring candidate value because "
4569 "max_new_size would be reached with %li.\n",
4570 val->local_size_cost + overall_size);
4571 return false;
4573 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4574 &caller_count))
4575 return false;
4577 if (dump_file && (dump_flags & TDF_DETAILS))
4579 fprintf (dump_file, " - considering value ");
4580 print_ipcp_constant_value (dump_file, val->value);
4581 fprintf (dump_file, " for ");
4582 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4583 if (offset != -1)
4584 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4585 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4588 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4589 freq_sum, count_sum,
4590 val->local_size_cost)
4591 && !good_cloning_opportunity_p (node,
4592 val->local_time_benefit
4593 + val->prop_time_benefit,
4594 freq_sum, count_sum,
4595 val->local_size_cost
4596 + val->prop_size_cost))
4597 return false;
4599 if (dump_file)
4600 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
4601 node->name (), node->order);
4603 callers = gather_edges_for_value (val, node, caller_count);
4604 if (offset == -1)
4605 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4606 else
4608 known_csts = known_csts.copy ();
4609 known_contexts = copy_useful_known_contexts (known_contexts);
4611 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4612 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4613 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4614 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4615 offset, val->value));
4616 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4617 aggvals, callers);
4618 overall_size += val->local_size_cost;
4620 /* TODO: If for some lattice there is only one other known value
4621 left, make a special node for it too. */
4623 return true;
4626 /* Decide whether and what specialized clones of NODE should be created. */
4628 static bool
4629 decide_whether_version_node (struct cgraph_node *node)
4631 struct ipa_node_params *info = IPA_NODE_REF (node);
4632 int i, count = ipa_get_param_count (info);
4633 vec<tree> known_csts;
4634 vec<ipa_polymorphic_call_context> known_contexts;
4635 vec<ipa_agg_jump_function> known_aggs = vNULL;
4636 bool ret = false;
4638 if (count == 0)
4639 return false;
4641 if (dump_file && (dump_flags & TDF_DETAILS))
4642 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4643 node->name (), node->order);
4645 gather_context_independent_values (info, &known_csts, &known_contexts,
4646 info->do_clone_for_all_contexts ? &known_aggs
4647 : NULL, NULL);
4649 for (i = 0; i < count ;i++)
4651 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4652 ipcp_lattice<tree> *lat = &plats->itself;
4653 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4655 if (!lat->bottom
4656 && !known_csts[i])
4658 ipcp_value<tree> *val;
4659 for (val = lat->values; val; val = val->next)
4660 ret |= decide_about_value (node, i, -1, val, known_csts,
4661 known_contexts);
4664 if (!plats->aggs_bottom)
4666 struct ipcp_agg_lattice *aglat;
4667 ipcp_value<tree> *val;
4668 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4669 if (!aglat->bottom && aglat->values
4670 /* If the following is false, the one value is in
4671 known_aggs. */
4672 && (plats->aggs_contain_variable
4673 || !aglat->is_single_const ()))
4674 for (val = aglat->values; val; val = val->next)
4675 ret |= decide_about_value (node, i, aglat->offset, val,
4676 known_csts, known_contexts);
4679 if (!ctxlat->bottom
4680 && known_contexts[i].useless_p ())
4682 ipcp_value<ipa_polymorphic_call_context> *val;
4683 for (val = ctxlat->values; val; val = val->next)
4684 ret |= decide_about_value (node, i, -1, val, known_csts,
4685 known_contexts);
4688 info = IPA_NODE_REF (node);
4691 if (info->do_clone_for_all_contexts)
4693 struct cgraph_node *clone;
4694 vec<cgraph_edge *> callers;
4696 if (dump_file)
4697 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4698 "for all known contexts.\n", node->name (),
4699 node->order);
4701 callers = node->collect_callers ();
4703 if (!known_contexts_useful_p (known_contexts))
4705 known_contexts.release ();
4706 known_contexts = vNULL;
4708 clone = create_specialized_node (node, known_csts, known_contexts,
4709 known_aggs_to_agg_replacement_list (known_aggs),
4710 callers);
4711 info = IPA_NODE_REF (node);
4712 info->do_clone_for_all_contexts = false;
4713 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4714 for (i = 0; i < count ; i++)
4715 vec_free (known_aggs[i].items);
4716 known_aggs.release ();
4717 ret = true;
4719 else
4721 known_csts.release ();
4722 known_contexts.release ();
4725 return ret;
4728 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4730 static void
4731 spread_undeadness (struct cgraph_node *node)
4733 struct cgraph_edge *cs;
4735 for (cs = node->callees; cs; cs = cs->next_callee)
4736 if (ipa_edge_within_scc (cs))
4738 struct cgraph_node *callee;
4739 struct ipa_node_params *info;
4741 callee = cs->callee->function_symbol (NULL);
4742 info = IPA_NODE_REF (callee);
4744 if (info->node_dead)
4746 info->node_dead = 0;
4747 spread_undeadness (callee);
4752 /* Return true if NODE has a caller from outside of its SCC that is not
4753 dead. Worker callback for cgraph_for_node_and_aliases. */
4755 static bool
4756 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4757 void *data ATTRIBUTE_UNUSED)
4759 struct cgraph_edge *cs;
4761 for (cs = node->callers; cs; cs = cs->next_caller)
4762 if (cs->caller->thunk.thunk_p
4763 && cs->caller->call_for_symbol_thunks_and_aliases
4764 (has_undead_caller_from_outside_scc_p, NULL, true))
4765 return true;
4766 else if (!ipa_edge_within_scc (cs)
4767 && !IPA_NODE_REF (cs->caller)->node_dead)
4768 return true;
4769 return false;
4773 /* Identify nodes within the same SCC as NODE which are no longer needed
4774 because of new clones and will be removed as unreachable. */
4776 static void
4777 identify_dead_nodes (struct cgraph_node *node)
4779 struct cgraph_node *v;
4780 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4781 if (v->local.local
4782 && !v->call_for_symbol_thunks_and_aliases
4783 (has_undead_caller_from_outside_scc_p, NULL, true))
4784 IPA_NODE_REF (v)->node_dead = 1;
4786 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4787 if (!IPA_NODE_REF (v)->node_dead)
4788 spread_undeadness (v);
4790 if (dump_file && (dump_flags & TDF_DETAILS))
4792 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4793 if (IPA_NODE_REF (v)->node_dead)
4794 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4795 v->name (), v->order);
4799 /* The decision stage. Iterate over the topological order of call graph nodes
4800 TOPO and make specialized clones if deemed beneficial. */
4802 static void
4803 ipcp_decision_stage (struct ipa_topo_info *topo)
4805 int i;
4807 if (dump_file)
4808 fprintf (dump_file, "\nIPA decision stage:\n\n");
4810 for (i = topo->nnodes - 1; i >= 0; i--)
4812 struct cgraph_node *node = topo->order[i];
4813 bool change = false, iterate = true;
4815 while (iterate)
4817 struct cgraph_node *v;
4818 iterate = false;
4819 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4820 if (v->has_gimple_body_p ()
4821 && ipcp_versionable_function_p (v))
4822 iterate |= decide_whether_version_node (v);
4824 change |= iterate;
4826 if (change)
4827 identify_dead_nodes (node);
4831 /* Look up all the bits information that we have discovered and copy it over
4832 to the transformation summary. */
4834 static void
4835 ipcp_store_bits_results (void)
4837 cgraph_node *node;
4839 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4841 ipa_node_params *info = IPA_NODE_REF (node);
4842 bool dumped_sth = false;
4843 bool found_useful_result = false;
4845 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4847 if (dump_file)
4848 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4849 "; -fipa-bit-cp: disabled.\n",
4850 node->name ());
4851 continue;
4854 if (info->ipcp_orig_node)
4855 info = IPA_NODE_REF (info->ipcp_orig_node);
4857 unsigned count = ipa_get_param_count (info);
4858 for (unsigned i = 0; i < count; i++)
4860 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4861 if (plats->bits_lattice.constant_p ())
4863 found_useful_result = true;
4864 break;
4868 if (!found_useful_result)
4869 continue;
4871 ipcp_grow_transformations_if_necessary ();
4872 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4873 vec_safe_reserve_exact (ts->bits, count);
4875 for (unsigned i = 0; i < count; i++)
4877 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4878 ipa_bits bits_jfunc;
4880 if (plats->bits_lattice.constant_p ())
4882 bits_jfunc.known = true;
4883 bits_jfunc.value = plats->bits_lattice.get_value ();
4884 bits_jfunc.mask = plats->bits_lattice.get_mask ();
4886 else
4887 bits_jfunc.known = false;
4889 ts->bits->quick_push (bits_jfunc);
4890 if (!dump_file || !bits_jfunc.known)
4891 continue;
4892 if (!dumped_sth)
4894 fprintf (dump_file, "Propagated bits info for function %s/%i:\n",
4895 node->name (), node->order);
4896 dumped_sth = true;
4898 fprintf (dump_file, " param %i: value = ", i);
4899 print_hex (bits_jfunc.value, dump_file);
4900 fprintf (dump_file, ", mask = ");
4901 print_hex (bits_jfunc.mask, dump_file);
4902 fprintf (dump_file, "\n");
4907 /* Look up all VR information that we have discovered and copy it over
4908 to the transformation summary. */
4910 static void
4911 ipcp_store_vr_results (void)
4913 cgraph_node *node;
4915 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4917 ipa_node_params *info = IPA_NODE_REF (node);
4918 bool found_useful_result = false;
4920 if (!opt_for_fn (node->decl, flag_ipa_vrp))
4922 if (dump_file)
4923 fprintf (dump_file, "Not considering %s for VR discovery "
4924 "and propagate; -fipa-ipa-vrp: disabled.\n",
4925 node->name ());
4926 continue;
4929 if (info->ipcp_orig_node)
4930 info = IPA_NODE_REF (info->ipcp_orig_node);
4932 unsigned count = ipa_get_param_count (info);
4933 for (unsigned i = 0; i < count ; i++)
4935 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4936 if (!plats->m_value_range.bottom_p ()
4937 && !plats->m_value_range.top_p ())
4939 found_useful_result = true;
4940 break;
4943 if (!found_useful_result)
4944 continue;
4946 ipcp_grow_transformations_if_necessary ();
4947 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4948 vec_safe_reserve_exact (ts->m_vr, count);
4950 for (unsigned i = 0; i < count ; i++)
4952 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4953 ipa_vr vr;
4955 if (!plats->m_value_range.bottom_p ()
4956 && !plats->m_value_range.top_p ())
4958 vr.known = true;
4959 vr.type = plats->m_value_range.m_vr.type;
4960 vr.min = plats->m_value_range.m_vr.min;
4961 vr.max = plats->m_value_range.m_vr.max;
4963 else
4965 vr.known = false;
4966 vr.type = VR_VARYING;
4967 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
4969 ts->m_vr->quick_push (vr);
4974 /* The IPCP driver. */
4976 static unsigned int
4977 ipcp_driver (void)
4979 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4980 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4981 struct ipa_topo_info topo;
4983 ipa_check_create_node_params ();
4984 ipa_check_create_edge_args ();
4985 grow_edge_clone_vectors ();
4986 edge_duplication_hook_holder =
4987 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4988 edge_removal_hook_holder =
4989 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4991 if (dump_file)
4993 fprintf (dump_file, "\nIPA structures before propagation:\n");
4994 if (dump_flags & TDF_DETAILS)
4995 ipa_print_all_params (dump_file);
4996 ipa_print_all_jump_functions (dump_file);
4999 /* Topological sort. */
5000 build_toporder_info (&topo);
5001 /* Do the interprocedural propagation. */
5002 ipcp_propagate_stage (&topo);
5003 /* Decide what constant propagation and cloning should be performed. */
5004 ipcp_decision_stage (&topo);
5005 /* Store results of bits propagation. */
5006 ipcp_store_bits_results ();
5007 /* Store results of value range propagation. */
5008 ipcp_store_vr_results ();
5010 /* Free all IPCP structures. */
5011 free_toporder_info (&topo);
5012 next_edge_clone.release ();
5013 prev_edge_clone.release ();
5014 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
5015 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
5016 ipa_free_all_structures_after_ipa_cp ();
5017 if (dump_file)
5018 fprintf (dump_file, "\nIPA constant propagation end\n");
5019 return 0;
5022 /* Initialization and computation of IPCP data structures. This is the initial
5023 intraprocedural analysis of functions, which gathers information to be
5024 propagated later on. */
5026 static void
5027 ipcp_generate_summary (void)
5029 struct cgraph_node *node;
5031 if (dump_file)
5032 fprintf (dump_file, "\nIPA constant propagation start:\n");
5033 ipa_register_cgraph_hooks ();
5035 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5036 ipa_analyze_node (node);
5039 /* Write ipcp summary for nodes in SET. */
5041 static void
5042 ipcp_write_summary (void)
5044 ipa_prop_write_jump_functions ();
5047 /* Read ipcp summary. */
5049 static void
5050 ipcp_read_summary (void)
5052 ipa_prop_read_jump_functions ();
5055 namespace {
5057 const pass_data pass_data_ipa_cp =
5059 IPA_PASS, /* type */
5060 "cp", /* name */
5061 OPTGROUP_NONE, /* optinfo_flags */
5062 TV_IPA_CONSTANT_PROP, /* tv_id */
5063 0, /* properties_required */
5064 0, /* properties_provided */
5065 0, /* properties_destroyed */
5066 0, /* todo_flags_start */
5067 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5070 class pass_ipa_cp : public ipa_opt_pass_d
5072 public:
5073 pass_ipa_cp (gcc::context *ctxt)
5074 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5075 ipcp_generate_summary, /* generate_summary */
5076 ipcp_write_summary, /* write_summary */
5077 ipcp_read_summary, /* read_summary */
5078 ipcp_write_transformation_summaries, /*
5079 write_optimization_summary */
5080 ipcp_read_transformation_summaries, /*
5081 read_optimization_summary */
5082 NULL, /* stmt_fixup */
5083 0, /* function_transform_todo_flags_start */
5084 ipcp_transform_function, /* function_transform */
5085 NULL) /* variable_transform */
5088 /* opt_pass methods: */
5089 virtual bool gate (function *)
5091 /* FIXME: We should remove the optimize check after we ensure we never run
5092 IPA passes when not optimizing. */
5093 return (flag_ipa_cp && optimize) || in_lto_p;
5096 virtual unsigned int execute (function *) { return ipcp_driver (); }
5098 }; // class pass_ipa_cp
5100 } // anon namespace
5102 ipa_opt_pass_d *
5103 make_pass_ipa_cp (gcc::context *ctxt)
5105 return new pass_ipa_cp (ctxt);
5108 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5109 within the same process. For use by toplev::finalize. */
5111 void
5112 ipa_cp_c_finalize (void)
5114 max_count = 0;
5115 overall_size = 0;
5116 max_new_size = 0;