[testsuite] Fix FAIL: gcc.dg/lto/pr69188 on bare-metal targets
[official-gcc.git] / gcc / ipa-cp.c
blobaa3c9973a66b0f7e8266e610b5752c1302916428
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2017 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* Interprocedural constant propagation (IPA-CP).
25 The goal of this transformation is to
27 1) discover functions which are always invoked with some arguments with the
28 same known constant values and modify the functions so that the
29 subsequent optimizations can take advantage of the knowledge, and
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
48 The algorithm used is to a certain extent based on "Interprocedural Constant
49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
51 Cooper, Mary W. Hall, and Ken Kennedy.
54 First stage - intraprocedural analysis
55 =======================================
57 This phase computes jump_function and modification flags.
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
65 Constant - a constant is passed as an actual argument.
66 Unknown - neither of the above.
68 All jump function types are described in detail in ipa-prop.h, together with
69 the data structures that represent them and methods of accessing them.
71 ipcp_generate_summary() is the main function of the first stage.
73 Second stage - interprocedural analysis
74 ========================================
76 This stage is itself divided into two phases. In the first, we propagate
77 known values over the call graph, in the second, we make cloning decisions.
78 It uses a different algorithm than the original Callahan's paper.
80 First, we traverse the functions topologically from callers to callees and,
81 for each strongly connected component (SCC), we propagate constants
82 according to previously computed jump functions. We also record what known
83 values depend on other known values and estimate local effects. Finally, we
84 propagate cumulative information about these effects from dependent values
85 to those on which they depend.
87 Second, we again traverse the call graph in the same topological order and
88 make clones for functions which we know are called with the same values in
89 all contexts and decide about extra specialized clones of functions just for
90 some contexts - these decisions are based on both local estimates and
91 cumulative estimates propagated from callees.
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
96 Third phase - materialization of clones, call statement updates.
97 ============================================
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
103 #include "config.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "backend.h"
107 #include "tree.h"
108 #include "gimple-expr.h"
109 #include "predict.h"
110 #include "alloc-pool.h"
111 #include "tree-pass.h"
112 #include "cgraph.h"
113 #include "diagnostic.h"
114 #include "fold-const.h"
115 #include "gimple-fold.h"
116 #include "symbol-summary.h"
117 #include "tree-vrp.h"
118 #include "ipa-prop.h"
119 #include "tree-pretty-print.h"
120 #include "tree-inline.h"
121 #include "params.h"
122 #include "ipa-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_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
1555 ipcp_lattice<tree> *src_lat,
1556 ipcp_lattice<tree> *dest_lat, int src_idx)
1558 ipcp_value<tree> *src_val;
1559 bool ret = false;
1561 /* Do not create new values when propagating within an SCC because if there
1562 are arithmetic functions with circular dependencies, there is infinite
1563 number of them and we would just make lattices bottom. */
1564 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1565 && ipa_edge_within_scc (cs))
1566 ret = dest_lat->set_contains_variable ();
1567 else
1568 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1570 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
1572 if (cstval)
1573 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
1574 else
1575 ret |= dest_lat->set_contains_variable ();
1578 return ret;
1581 /* Propagate values through an ancestor jump function JFUNC associated with
1582 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1583 is the index of the source parameter. */
1585 static bool
1586 propagate_vals_across_ancestor (struct cgraph_edge *cs,
1587 struct ipa_jump_func *jfunc,
1588 ipcp_lattice<tree> *src_lat,
1589 ipcp_lattice<tree> *dest_lat, int src_idx)
1591 ipcp_value<tree> *src_val;
1592 bool ret = false;
1594 if (ipa_edge_within_scc (cs))
1595 return dest_lat->set_contains_variable ();
1597 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1599 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
1601 if (t)
1602 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
1603 else
1604 ret |= dest_lat->set_contains_variable ();
1607 return ret;
1610 /* Propagate scalar values across jump function JFUNC that is associated with
1611 edge CS and put the values into DEST_LAT. */
1613 static bool
1614 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
1615 struct ipa_jump_func *jfunc,
1616 ipcp_lattice<tree> *dest_lat)
1618 if (dest_lat->bottom)
1619 return false;
1621 if (jfunc->type == IPA_JF_CONST)
1623 tree val = ipa_get_jf_constant (jfunc);
1624 return dest_lat->add_value (val, cs, NULL, 0);
1626 else if (jfunc->type == IPA_JF_PASS_THROUGH
1627 || jfunc->type == IPA_JF_ANCESTOR)
1629 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1630 ipcp_lattice<tree> *src_lat;
1631 int src_idx;
1632 bool ret;
1634 if (jfunc->type == IPA_JF_PASS_THROUGH)
1635 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1636 else
1637 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1639 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
1640 if (src_lat->bottom)
1641 return dest_lat->set_contains_variable ();
1643 /* If we would need to clone the caller and cannot, do not propagate. */
1644 if (!ipcp_versionable_function_p (cs->caller)
1645 && (src_lat->contains_variable
1646 || (src_lat->values_count > 1)))
1647 return dest_lat->set_contains_variable ();
1649 if (jfunc->type == IPA_JF_PASS_THROUGH)
1650 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
1651 dest_lat, src_idx);
1652 else
1653 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
1654 src_idx);
1656 if (src_lat->contains_variable)
1657 ret |= dest_lat->set_contains_variable ();
1659 return ret;
1662 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1663 use it for indirect inlining), we should propagate them too. */
1664 return dest_lat->set_contains_variable ();
1667 /* Propagate scalar values across jump function JFUNC that is associated with
1668 edge CS and describes argument IDX and put the values into DEST_LAT. */
1670 static bool
1671 propagate_context_across_jump_function (cgraph_edge *cs,
1672 ipa_jump_func *jfunc, int idx,
1673 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1675 ipa_edge_args *args = IPA_EDGE_REF (cs);
1676 if (dest_lat->bottom)
1677 return false;
1678 bool ret = false;
1679 bool added_sth = false;
1680 bool type_preserved = true;
1682 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1683 = ipa_get_ith_polymorhic_call_context (args, idx);
1685 if (edge_ctx_ptr)
1686 edge_ctx = *edge_ctx_ptr;
1688 if (jfunc->type == IPA_JF_PASS_THROUGH
1689 || jfunc->type == IPA_JF_ANCESTOR)
1691 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1692 int src_idx;
1693 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1695 /* TODO: Once we figure out how to propagate speculations, it will
1696 probably be a good idea to switch to speculation if type_preserved is
1697 not set instead of punting. */
1698 if (jfunc->type == IPA_JF_PASS_THROUGH)
1700 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1701 goto prop_fail;
1702 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1703 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1705 else
1707 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1708 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1711 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1712 /* If we would need to clone the caller and cannot, do not propagate. */
1713 if (!ipcp_versionable_function_p (cs->caller)
1714 && (src_lat->contains_variable
1715 || (src_lat->values_count > 1)))
1716 goto prop_fail;
1718 ipcp_value<ipa_polymorphic_call_context> *src_val;
1719 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1721 ipa_polymorphic_call_context cur = src_val->value;
1723 if (!type_preserved)
1724 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1725 if (jfunc->type == IPA_JF_ANCESTOR)
1726 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1727 /* TODO: In cases we know how the context is going to be used,
1728 we can improve the result by passing proper OTR_TYPE. */
1729 cur.combine_with (edge_ctx);
1730 if (!cur.useless_p ())
1732 if (src_lat->contains_variable
1733 && !edge_ctx.equal_to (cur))
1734 ret |= dest_lat->set_contains_variable ();
1735 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1736 added_sth = true;
1742 prop_fail:
1743 if (!added_sth)
1745 if (!edge_ctx.useless_p ())
1746 ret |= dest_lat->add_value (edge_ctx, cs);
1747 else
1748 ret |= dest_lat->set_contains_variable ();
1751 return ret;
1754 /* Propagate bits across jfunc that is associated with
1755 edge cs and update dest_lattice accordingly. */
1757 bool
1758 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
1759 ipa_jump_func *jfunc,
1760 ipcp_bits_lattice *dest_lattice)
1762 if (dest_lattice->bottom_p ())
1763 return false;
1765 enum availability availability;
1766 cgraph_node *callee = cs->callee->function_symbol (&availability);
1767 struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
1768 tree parm_type = ipa_get_type (callee_info, idx);
1770 /* For K&R C programs, ipa_get_type() could return NULL_TREE.
1771 Avoid the transform for these cases. */
1772 if (!parm_type)
1774 if (dump_file && (dump_flags & TDF_DETAILS))
1775 fprintf (dump_file, "Setting dest_lattice to bottom, because"
1776 " param %i type is NULL for %s\n", idx,
1777 cs->callee->name ());
1779 return dest_lattice->set_to_bottom ();
1782 unsigned precision = TYPE_PRECISION (parm_type);
1783 signop sgn = TYPE_SIGN (parm_type);
1785 if (jfunc->type == IPA_JF_PASS_THROUGH
1786 || jfunc->type == IPA_JF_ANCESTOR)
1788 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1789 tree operand = NULL_TREE;
1790 enum tree_code code;
1791 unsigned src_idx;
1793 if (jfunc->type == IPA_JF_PASS_THROUGH)
1795 code = ipa_get_jf_pass_through_operation (jfunc);
1796 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1797 if (code != NOP_EXPR)
1798 operand = ipa_get_jf_pass_through_operand (jfunc);
1800 else
1802 code = POINTER_PLUS_EXPR;
1803 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1804 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
1805 operand = build_int_cstu (size_type_node, offset);
1808 struct ipcp_param_lattices *src_lats
1809 = ipa_get_parm_lattices (caller_info, src_idx);
1811 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1812 for eg consider:
1813 int f(int x)
1815 g (x & 0xff);
1817 Assume lattice for x is bottom, however we can still propagate
1818 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1819 and we store it in jump function during analysis stage. */
1821 if (src_lats->bits_lattice.bottom_p ()
1822 && jfunc->bits.known)
1823 return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask,
1824 precision);
1825 else
1826 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
1827 code, operand);
1830 else if (jfunc->type == IPA_JF_ANCESTOR)
1831 return dest_lattice->set_to_bottom ();
1833 else if (jfunc->bits.known)
1834 return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask, precision);
1836 else
1837 return dest_lattice->set_to_bottom ();
1840 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1841 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1842 the result is a range or an anti-range. */
1844 static bool
1845 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr,
1846 enum tree_code operation,
1847 tree dst_type, tree src_type)
1849 memset (dst_vr, 0, sizeof (*dst_vr));
1850 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
1851 if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE)
1852 return true;
1853 else
1854 return false;
1857 /* Propagate value range across jump function JFUNC that is associated with
1858 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1859 accordingly. */
1861 static bool
1862 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
1863 struct ipcp_param_lattices *dest_plats,
1864 tree param_type)
1866 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
1868 if (dest_lat->bottom_p ())
1869 return false;
1871 if (!param_type
1872 || (!INTEGRAL_TYPE_P (param_type)
1873 && !POINTER_TYPE_P (param_type)))
1874 return dest_lat->set_to_bottom ();
1876 if (jfunc->type == IPA_JF_PASS_THROUGH)
1878 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1880 if (TREE_CODE_CLASS (operation) == tcc_unary)
1882 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1883 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1884 tree operand_type = ipa_get_type (caller_info, src_idx);
1885 struct ipcp_param_lattices *src_lats
1886 = ipa_get_parm_lattices (caller_info, src_idx);
1888 if (src_lats->m_value_range.bottom_p ())
1889 return dest_lat->set_to_bottom ();
1890 value_range vr;
1891 if (ipa_vr_operation_and_type_effects (&vr,
1892 &src_lats->m_value_range.m_vr,
1893 operation, param_type,
1894 operand_type))
1895 return dest_lat->meet_with (&vr);
1898 else if (jfunc->type == IPA_JF_CONST)
1900 tree val = ipa_get_jf_constant (jfunc);
1901 if (TREE_CODE (val) == INTEGER_CST)
1903 val = fold_convert (param_type, val);
1904 if (TREE_OVERFLOW_P (val))
1905 val = drop_tree_overflow (val);
1906 jfunc->vr_known = true;
1907 jfunc->m_vr.type = VR_RANGE;
1908 jfunc->m_vr.min = val;
1909 jfunc->m_vr.max = val;
1910 return dest_lat->meet_with (&jfunc->m_vr);
1914 value_range vr;
1915 if (jfunc->vr_known
1916 && ipa_vr_operation_and_type_effects (&vr, &jfunc->m_vr, NOP_EXPR,
1917 param_type,
1918 TREE_TYPE (jfunc->m_vr.min)))
1919 return dest_lat->meet_with (&vr);
1920 else
1921 return dest_lat->set_to_bottom ();
1924 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1925 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1926 other cases, return false). If there are no aggregate items, set
1927 aggs_by_ref to NEW_AGGS_BY_REF. */
1929 static bool
1930 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1931 bool new_aggs_by_ref)
1933 if (dest_plats->aggs)
1935 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1937 set_agg_lats_to_bottom (dest_plats);
1938 return true;
1941 else
1942 dest_plats->aggs_by_ref = new_aggs_by_ref;
1943 return false;
1946 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1947 already existing lattice for the given OFFSET and SIZE, marking all skipped
1948 lattices as containing variable and checking for overlaps. If there is no
1949 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1950 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1951 unless there are too many already. If there are two many, return false. If
1952 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1953 skipped lattices were newly marked as containing variable, set *CHANGE to
1954 true. */
1956 static bool
1957 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1958 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1959 struct ipcp_agg_lattice ***aglat,
1960 bool pre_existing, bool *change)
1962 gcc_checking_assert (offset >= 0);
1964 while (**aglat && (**aglat)->offset < offset)
1966 if ((**aglat)->offset + (**aglat)->size > offset)
1968 set_agg_lats_to_bottom (dest_plats);
1969 return false;
1971 *change |= (**aglat)->set_contains_variable ();
1972 *aglat = &(**aglat)->next;
1975 if (**aglat && (**aglat)->offset == offset)
1977 if ((**aglat)->size != val_size
1978 || ((**aglat)->next
1979 && (**aglat)->next->offset < offset + val_size))
1981 set_agg_lats_to_bottom (dest_plats);
1982 return false;
1984 gcc_checking_assert (!(**aglat)->next
1985 || (**aglat)->next->offset >= offset + val_size);
1986 return true;
1988 else
1990 struct ipcp_agg_lattice *new_al;
1992 if (**aglat && (**aglat)->offset < offset + val_size)
1994 set_agg_lats_to_bottom (dest_plats);
1995 return false;
1997 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1998 return false;
1999 dest_plats->aggs_count++;
2000 new_al = ipcp_agg_lattice_pool.allocate ();
2001 memset (new_al, 0, sizeof (*new_al));
2003 new_al->offset = offset;
2004 new_al->size = val_size;
2005 new_al->contains_variable = pre_existing;
2007 new_al->next = **aglat;
2008 **aglat = new_al;
2009 return true;
2013 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2014 containing an unknown value. */
2016 static bool
2017 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2019 bool ret = false;
2020 while (aglat)
2022 ret |= aglat->set_contains_variable ();
2023 aglat = aglat->next;
2025 return ret;
2028 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2029 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2030 parameter used for lattice value sources. Return true if DEST_PLATS changed
2031 in any way. */
2033 static bool
2034 merge_aggregate_lattices (struct cgraph_edge *cs,
2035 struct ipcp_param_lattices *dest_plats,
2036 struct ipcp_param_lattices *src_plats,
2037 int src_idx, HOST_WIDE_INT offset_delta)
2039 bool pre_existing = dest_plats->aggs != NULL;
2040 struct ipcp_agg_lattice **dst_aglat;
2041 bool ret = false;
2043 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2044 return true;
2045 if (src_plats->aggs_bottom)
2046 return set_agg_lats_contain_variable (dest_plats);
2047 if (src_plats->aggs_contain_variable)
2048 ret |= set_agg_lats_contain_variable (dest_plats);
2049 dst_aglat = &dest_plats->aggs;
2051 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2052 src_aglat;
2053 src_aglat = src_aglat->next)
2055 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2057 if (new_offset < 0)
2058 continue;
2059 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2060 &dst_aglat, pre_existing, &ret))
2062 struct ipcp_agg_lattice *new_al = *dst_aglat;
2064 dst_aglat = &(*dst_aglat)->next;
2065 if (src_aglat->bottom)
2067 ret |= new_al->set_contains_variable ();
2068 continue;
2070 if (src_aglat->contains_variable)
2071 ret |= new_al->set_contains_variable ();
2072 for (ipcp_value<tree> *val = src_aglat->values;
2073 val;
2074 val = val->next)
2075 ret |= new_al->add_value (val->value, cs, val, src_idx,
2076 src_aglat->offset);
2078 else if (dest_plats->aggs_bottom)
2079 return true;
2081 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2082 return ret;
2085 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2086 pass-through JFUNC and if so, whether it has conform and conforms to the
2087 rules about propagating values passed by reference. */
2089 static bool
2090 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
2091 struct ipa_jump_func *jfunc)
2093 return src_plats->aggs
2094 && (!src_plats->aggs_by_ref
2095 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2098 /* Propagate scalar values across jump function JFUNC that is associated with
2099 edge CS and put the values into DEST_LAT. */
2101 static bool
2102 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2103 struct ipa_jump_func *jfunc,
2104 struct ipcp_param_lattices *dest_plats)
2106 bool ret = false;
2108 if (dest_plats->aggs_bottom)
2109 return false;
2111 if (jfunc->type == IPA_JF_PASS_THROUGH
2112 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2114 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2115 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2116 struct ipcp_param_lattices *src_plats;
2118 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2119 if (agg_pass_through_permissible_p (src_plats, jfunc))
2121 /* Currently we do not produce clobber aggregate jump
2122 functions, replace with merging when we do. */
2123 gcc_assert (!jfunc->agg.items);
2124 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2125 src_idx, 0);
2127 else
2128 ret |= set_agg_lats_contain_variable (dest_plats);
2130 else if (jfunc->type == IPA_JF_ANCESTOR
2131 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2133 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2134 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2135 struct ipcp_param_lattices *src_plats;
2137 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2138 if (src_plats->aggs && src_plats->aggs_by_ref)
2140 /* Currently we do not produce clobber aggregate jump
2141 functions, replace with merging when we do. */
2142 gcc_assert (!jfunc->agg.items);
2143 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2144 ipa_get_jf_ancestor_offset (jfunc));
2146 else if (!src_plats->aggs_by_ref)
2147 ret |= set_agg_lats_to_bottom (dest_plats);
2148 else
2149 ret |= set_agg_lats_contain_variable (dest_plats);
2151 else if (jfunc->agg.items)
2153 bool pre_existing = dest_plats->aggs != NULL;
2154 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2155 struct ipa_agg_jf_item *item;
2156 int i;
2158 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2159 return true;
2161 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2163 HOST_WIDE_INT val_size;
2165 if (item->offset < 0)
2166 continue;
2167 gcc_checking_assert (is_gimple_ip_invariant (item->value));
2168 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2170 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2171 &aglat, pre_existing, &ret))
2173 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2174 aglat = &(*aglat)->next;
2176 else if (dest_plats->aggs_bottom)
2177 return true;
2180 ret |= set_chain_of_aglats_contains_variable (*aglat);
2182 else
2183 ret |= set_agg_lats_contain_variable (dest_plats);
2185 return ret;
2188 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2189 non-thunk) destination, the call passes through a thunk. */
2191 static bool
2192 call_passes_through_thunk_p (cgraph_edge *cs)
2194 cgraph_node *alias_or_thunk = cs->callee;
2195 while (alias_or_thunk->alias)
2196 alias_or_thunk = alias_or_thunk->get_alias_target ();
2197 return alias_or_thunk->thunk.thunk_p;
2200 /* Propagate constants from the caller to the callee of CS. INFO describes the
2201 caller. */
2203 static bool
2204 propagate_constants_across_call (struct cgraph_edge *cs)
2206 struct ipa_node_params *callee_info;
2207 enum availability availability;
2208 cgraph_node *callee;
2209 struct ipa_edge_args *args;
2210 bool ret = false;
2211 int i, args_count, parms_count;
2213 callee = cs->callee->function_symbol (&availability);
2214 if (!callee->definition)
2215 return false;
2216 gcc_checking_assert (callee->has_gimple_body_p ());
2217 callee_info = IPA_NODE_REF (callee);
2219 args = IPA_EDGE_REF (cs);
2220 args_count = ipa_get_cs_argument_count (args);
2221 parms_count = ipa_get_param_count (callee_info);
2222 if (parms_count == 0)
2223 return false;
2225 /* No propagation through instrumentation thunks is available yet.
2226 It should be possible with proper mapping of call args and
2227 instrumented callee params in the propagation loop below. But
2228 this case mostly occurs when legacy code calls instrumented code
2229 and it is not a primary target for optimizations.
2230 We detect instrumentation thunks in aliases and thunks chain by
2231 checking instrumentation_clone flag for chain source and target.
2232 Going through instrumentation thunks we always have it changed
2233 from 0 to 1 and all other nodes do not change it. */
2234 if (!cs->callee->instrumentation_clone
2235 && callee->instrumentation_clone)
2237 for (i = 0; i < parms_count; i++)
2238 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2239 i));
2240 return ret;
2243 /* If this call goes through a thunk we must not propagate to the first (0th)
2244 parameter. However, we might need to uncover a thunk from below a series
2245 of aliases first. */
2246 if (call_passes_through_thunk_p (cs))
2248 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2249 0));
2250 i = 1;
2252 else
2253 i = 0;
2255 for (; (i < args_count) && (i < parms_count); i++)
2257 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2258 struct ipcp_param_lattices *dest_plats;
2259 tree param_type = ipa_get_type (callee_info, i);
2261 dest_plats = ipa_get_parm_lattices (callee_info, i);
2262 if (availability == AVAIL_INTERPOSABLE)
2263 ret |= set_all_contains_variable (dest_plats);
2264 else
2266 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2267 &dest_plats->itself);
2268 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2269 &dest_plats->ctxlat);
2271 |= propagate_bits_across_jump_function (cs, i, jump_func,
2272 &dest_plats->bits_lattice);
2273 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2274 dest_plats);
2275 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2276 ret |= propagate_vr_across_jump_function (cs, jump_func,
2277 dest_plats, param_type);
2278 else
2279 ret |= dest_plats->m_value_range.set_to_bottom ();
2282 for (; i < parms_count; i++)
2283 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2285 return ret;
2288 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2289 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2290 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2292 static tree
2293 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2294 vec<tree> known_csts,
2295 vec<ipa_polymorphic_call_context> known_contexts,
2296 vec<ipa_agg_jump_function_p> known_aggs,
2297 struct ipa_agg_replacement_value *agg_reps,
2298 bool *speculative)
2300 int param_index = ie->indirect_info->param_index;
2301 HOST_WIDE_INT anc_offset;
2302 tree t;
2303 tree target = NULL;
2305 *speculative = false;
2307 if (param_index == -1
2308 || known_csts.length () <= (unsigned int) param_index)
2309 return NULL_TREE;
2311 if (!ie->indirect_info->polymorphic)
2313 tree t;
2315 if (ie->indirect_info->agg_contents)
2317 t = NULL;
2318 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2320 while (agg_reps)
2322 if (agg_reps->index == param_index
2323 && agg_reps->offset == ie->indirect_info->offset
2324 && agg_reps->by_ref == ie->indirect_info->by_ref)
2326 t = agg_reps->value;
2327 break;
2329 agg_reps = agg_reps->next;
2332 if (!t)
2334 struct ipa_agg_jump_function *agg;
2335 if (known_aggs.length () > (unsigned int) param_index)
2336 agg = known_aggs[param_index];
2337 else
2338 agg = NULL;
2339 bool from_global_constant;
2340 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2341 ie->indirect_info->offset,
2342 ie->indirect_info->by_ref,
2343 &from_global_constant);
2344 if (t
2345 && !from_global_constant
2346 && !ie->indirect_info->guaranteed_unmodified)
2347 t = NULL_TREE;
2350 else
2351 t = known_csts[param_index];
2353 if (t
2354 && TREE_CODE (t) == ADDR_EXPR
2355 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2356 return TREE_OPERAND (t, 0);
2357 else
2358 return NULL_TREE;
2361 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2362 return NULL_TREE;
2364 gcc_assert (!ie->indirect_info->agg_contents);
2365 anc_offset = ie->indirect_info->offset;
2367 t = NULL;
2369 /* Try to work out value of virtual table pointer value in replacemnets. */
2370 if (!t && agg_reps && !ie->indirect_info->by_ref)
2372 while (agg_reps)
2374 if (agg_reps->index == param_index
2375 && agg_reps->offset == ie->indirect_info->offset
2376 && agg_reps->by_ref)
2378 t = agg_reps->value;
2379 break;
2381 agg_reps = agg_reps->next;
2385 /* Try to work out value of virtual table pointer value in known
2386 aggregate values. */
2387 if (!t && known_aggs.length () > (unsigned int) param_index
2388 && !ie->indirect_info->by_ref)
2390 struct ipa_agg_jump_function *agg;
2391 agg = known_aggs[param_index];
2392 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
2393 ie->indirect_info->offset, true);
2396 /* If we found the virtual table pointer, lookup the target. */
2397 if (t)
2399 tree vtable;
2400 unsigned HOST_WIDE_INT offset;
2401 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2403 bool can_refer;
2404 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2405 vtable, offset, &can_refer);
2406 if (can_refer)
2408 if (!target
2409 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2410 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2411 || !possible_polymorphic_call_target_p
2412 (ie, cgraph_node::get (target)))
2414 /* Do not speculate builtin_unreachable, it is stupid! */
2415 if (ie->indirect_info->vptr_changed)
2416 return NULL;
2417 target = ipa_impossible_devirt_target (ie, target);
2419 *speculative = ie->indirect_info->vptr_changed;
2420 if (!*speculative)
2421 return target;
2426 /* Do we know the constant value of pointer? */
2427 if (!t)
2428 t = known_csts[param_index];
2430 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2432 ipa_polymorphic_call_context context;
2433 if (known_contexts.length () > (unsigned int) param_index)
2435 context = known_contexts[param_index];
2436 context.offset_by (anc_offset);
2437 if (ie->indirect_info->vptr_changed)
2438 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2439 ie->indirect_info->otr_type);
2440 if (t)
2442 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2443 (t, ie->indirect_info->otr_type, anc_offset);
2444 if (!ctx2.useless_p ())
2445 context.combine_with (ctx2, ie->indirect_info->otr_type);
2448 else if (t)
2450 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2451 anc_offset);
2452 if (ie->indirect_info->vptr_changed)
2453 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2454 ie->indirect_info->otr_type);
2456 else
2457 return NULL_TREE;
2459 vec <cgraph_node *>targets;
2460 bool final;
2462 targets = possible_polymorphic_call_targets
2463 (ie->indirect_info->otr_type,
2464 ie->indirect_info->otr_token,
2465 context, &final);
2466 if (!final || targets.length () > 1)
2468 struct cgraph_node *node;
2469 if (*speculative)
2470 return target;
2471 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2472 || ie->speculative || !ie->maybe_hot_p ())
2473 return NULL;
2474 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2475 ie->indirect_info->otr_token,
2476 context);
2477 if (node)
2479 *speculative = true;
2480 target = node->decl;
2482 else
2483 return NULL;
2485 else
2487 *speculative = false;
2488 if (targets.length () == 1)
2489 target = targets[0]->decl;
2490 else
2491 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2494 if (target && !possible_polymorphic_call_target_p (ie,
2495 cgraph_node::get (target)))
2497 if (*speculative)
2498 return NULL;
2499 target = ipa_impossible_devirt_target (ie, target);
2502 return target;
2506 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2507 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2508 return the destination. */
2510 tree
2511 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
2512 vec<tree> known_csts,
2513 vec<ipa_polymorphic_call_context> known_contexts,
2514 vec<ipa_agg_jump_function_p> known_aggs,
2515 bool *speculative)
2517 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
2518 known_aggs, NULL, speculative);
2521 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2522 and KNOWN_CONTEXTS. */
2524 static int
2525 devirtualization_time_bonus (struct cgraph_node *node,
2526 vec<tree> known_csts,
2527 vec<ipa_polymorphic_call_context> known_contexts,
2528 vec<ipa_agg_jump_function_p> known_aggs)
2530 struct cgraph_edge *ie;
2531 int res = 0;
2533 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2535 struct cgraph_node *callee;
2536 struct inline_summary *isummary;
2537 enum availability avail;
2538 tree target;
2539 bool speculative;
2541 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
2542 known_aggs, &speculative);
2543 if (!target)
2544 continue;
2546 /* Only bare minimum benefit for clearly un-inlineable targets. */
2547 res += 1;
2548 callee = cgraph_node::get (target);
2549 if (!callee || !callee->definition)
2550 continue;
2551 callee = callee->function_symbol (&avail);
2552 if (avail < AVAIL_AVAILABLE)
2553 continue;
2554 isummary = inline_summaries->get (callee);
2555 if (!isummary->inlinable)
2556 continue;
2558 /* FIXME: The values below need re-considering and perhaps also
2559 integrating into the cost metrics, at lest in some very basic way. */
2560 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
2561 res += 31 / ((int)speculative + 1);
2562 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
2563 res += 15 / ((int)speculative + 1);
2564 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
2565 || DECL_DECLARED_INLINE_P (callee->decl))
2566 res += 7 / ((int)speculative + 1);
2569 return res;
2572 /* Return time bonus incurred because of HINTS. */
2574 static int
2575 hint_time_bonus (inline_hints hints)
2577 int result = 0;
2578 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
2579 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2580 if (hints & INLINE_HINT_array_index)
2581 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2582 return result;
2585 /* If there is a reason to penalize the function described by INFO in the
2586 cloning goodness evaluation, do so. */
2588 static inline int64_t
2589 incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2591 if (info->node_within_scc)
2592 evaluation = (evaluation
2593 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2595 if (info->node_calling_single_call)
2596 evaluation = (evaluation
2597 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2598 / 100;
2600 return evaluation;
2603 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2604 and SIZE_COST and with the sum of frequencies of incoming edges to the
2605 potential new clone in FREQUENCIES. */
2607 static bool
2608 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2609 int freq_sum, gcov_type count_sum, int size_cost)
2611 if (time_benefit == 0
2612 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
2613 || node->optimize_for_size_p ())
2614 return false;
2616 gcc_assert (size_cost > 0);
2618 struct ipa_node_params *info = IPA_NODE_REF (node);
2619 if (max_count)
2621 int factor = (count_sum * 1000) / max_count;
2622 int64_t evaluation = (((int64_t) time_benefit * factor)
2623 / size_cost);
2624 evaluation = incorporate_penalties (info, evaluation);
2626 if (dump_file && (dump_flags & TDF_DETAILS))
2627 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2628 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2629 "%s%s) -> evaluation: " "%" PRId64
2630 ", threshold: %i\n",
2631 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
2632 info->node_within_scc ? ", scc" : "",
2633 info->node_calling_single_call ? ", single_call" : "",
2634 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2636 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2638 else
2640 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
2641 / size_cost);
2642 evaluation = incorporate_penalties (info, evaluation);
2644 if (dump_file && (dump_flags & TDF_DETAILS))
2645 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2646 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2647 "%" PRId64 ", threshold: %i\n",
2648 time_benefit, size_cost, freq_sum,
2649 info->node_within_scc ? ", scc" : "",
2650 info->node_calling_single_call ? ", single_call" : "",
2651 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
2653 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2657 /* Return all context independent values from aggregate lattices in PLATS in a
2658 vector. Return NULL if there are none. */
2660 static vec<ipa_agg_jf_item, va_gc> *
2661 context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2663 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2665 if (plats->aggs_bottom
2666 || plats->aggs_contain_variable
2667 || plats->aggs_count == 0)
2668 return NULL;
2670 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2671 aglat;
2672 aglat = aglat->next)
2673 if (aglat->is_single_const ())
2675 struct ipa_agg_jf_item item;
2676 item.offset = aglat->offset;
2677 item.value = aglat->values->value;
2678 vec_safe_push (res, item);
2680 return res;
2683 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2684 populate them with values of parameters that are known independent of the
2685 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2686 non-NULL, the movement cost of all removable parameters will be stored in
2687 it. */
2689 static bool
2690 gather_context_independent_values (struct ipa_node_params *info,
2691 vec<tree> *known_csts,
2692 vec<ipa_polymorphic_call_context>
2693 *known_contexts,
2694 vec<ipa_agg_jump_function> *known_aggs,
2695 int *removable_params_cost)
2697 int i, count = ipa_get_param_count (info);
2698 bool ret = false;
2700 known_csts->create (0);
2701 known_contexts->create (0);
2702 known_csts->safe_grow_cleared (count);
2703 known_contexts->safe_grow_cleared (count);
2704 if (known_aggs)
2706 known_aggs->create (0);
2707 known_aggs->safe_grow_cleared (count);
2710 if (removable_params_cost)
2711 *removable_params_cost = 0;
2713 for (i = 0; i < count; i++)
2715 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2716 ipcp_lattice<tree> *lat = &plats->itself;
2718 if (lat->is_single_const ())
2720 ipcp_value<tree> *val = lat->values;
2721 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2722 (*known_csts)[i] = val->value;
2723 if (removable_params_cost)
2724 *removable_params_cost
2725 += estimate_move_cost (TREE_TYPE (val->value), false);
2726 ret = true;
2728 else if (removable_params_cost
2729 && !ipa_is_param_used (info, i))
2730 *removable_params_cost
2731 += ipa_get_param_move_cost (info, i);
2733 if (!ipa_is_param_used (info, i))
2734 continue;
2736 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2737 /* Do not account known context as reason for cloning. We can see
2738 if it permits devirtualization. */
2739 if (ctxlat->is_single_const ())
2740 (*known_contexts)[i] = ctxlat->values->value;
2742 if (known_aggs)
2744 vec<ipa_agg_jf_item, va_gc> *agg_items;
2745 struct ipa_agg_jump_function *ajf;
2747 agg_items = context_independent_aggregate_values (plats);
2748 ajf = &(*known_aggs)[i];
2749 ajf->items = agg_items;
2750 ajf->by_ref = plats->aggs_by_ref;
2751 ret |= agg_items != NULL;
2755 return ret;
2758 /* The current interface in ipa-inline-analysis requires a pointer vector.
2759 Create it.
2761 FIXME: That interface should be re-worked, this is slightly silly. Still,
2762 I'd like to discuss how to change it first and this demonstrates the
2763 issue. */
2765 static vec<ipa_agg_jump_function_p>
2766 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2768 vec<ipa_agg_jump_function_p> ret;
2769 struct ipa_agg_jump_function *ajf;
2770 int i;
2772 ret.create (known_aggs.length ());
2773 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2774 ret.quick_push (ajf);
2775 return ret;
2778 /* Perform time and size measurement of NODE with the context given in
2779 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2780 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2781 all context-independent removable parameters and EST_MOVE_COST of estimated
2782 movement of the considered parameter and store it into VAL. */
2784 static void
2785 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
2786 vec<ipa_polymorphic_call_context> known_contexts,
2787 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2788 int base_time, int removable_params_cost,
2789 int est_move_cost, ipcp_value_base *val)
2791 int time, size, time_benefit;
2792 inline_hints hints;
2794 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2795 known_aggs_ptrs, &size, &time,
2796 &hints);
2797 time_benefit = base_time - time
2798 + devirtualization_time_bonus (node, known_csts, known_contexts,
2799 known_aggs_ptrs)
2800 + hint_time_bonus (hints)
2801 + removable_params_cost + est_move_cost;
2803 gcc_checking_assert (size >=0);
2804 /* The inliner-heuristics based estimates may think that in certain
2805 contexts some functions do not have any size at all but we want
2806 all specializations to have at least a tiny cost, not least not to
2807 divide by zero. */
2808 if (size == 0)
2809 size = 1;
2811 val->local_time_benefit = time_benefit;
2812 val->local_size_cost = size;
2815 /* Iterate over known values of parameters of NODE and estimate the local
2816 effects in terms of time and size they have. */
2818 static void
2819 estimate_local_effects (struct cgraph_node *node)
2821 struct ipa_node_params *info = IPA_NODE_REF (node);
2822 int i, count = ipa_get_param_count (info);
2823 vec<tree> known_csts;
2824 vec<ipa_polymorphic_call_context> known_contexts;
2825 vec<ipa_agg_jump_function> known_aggs;
2826 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
2827 bool always_const;
2828 int base_time = inline_summaries->get (node)->time;
2829 int removable_params_cost;
2831 if (!count || !ipcp_versionable_function_p (node))
2832 return;
2834 if (dump_file && (dump_flags & TDF_DETAILS))
2835 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
2836 node->name (), node->order, base_time);
2838 always_const = gather_context_independent_values (info, &known_csts,
2839 &known_contexts, &known_aggs,
2840 &removable_params_cost);
2841 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
2842 int devirt_bonus = devirtualization_time_bonus (node, known_csts,
2843 known_contexts, known_aggs_ptrs);
2844 if (always_const || devirt_bonus
2845 || (removable_params_cost && node->local.can_change_signature))
2847 struct caller_statistics stats;
2848 inline_hints hints;
2849 int time, size;
2851 init_caller_stats (&stats);
2852 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2853 false);
2854 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2855 known_aggs_ptrs, &size, &time, &hints);
2856 time -= devirt_bonus;
2857 time -= hint_time_bonus (hints);
2858 time -= removable_params_cost;
2859 size -= stats.n_calls * removable_params_cost;
2861 if (dump_file)
2862 fprintf (dump_file, " - context independent values, size: %i, "
2863 "time_benefit: %i\n", size, base_time - time);
2865 if (size <= 0 || node->local.local)
2867 info->do_clone_for_all_contexts = true;
2868 base_time = time;
2870 if (dump_file)
2871 fprintf (dump_file, " Decided to specialize for all "
2872 "known contexts, code not going to grow.\n");
2874 else if (good_cloning_opportunity_p (node, base_time - time,
2875 stats.freq_sum, stats.count_sum,
2876 size))
2878 if (size + overall_size <= max_new_size)
2880 info->do_clone_for_all_contexts = true;
2881 base_time = time;
2882 overall_size += size;
2884 if (dump_file)
2885 fprintf (dump_file, " Decided to specialize for all "
2886 "known contexts, growth deemed beneficial.\n");
2888 else if (dump_file && (dump_flags & TDF_DETAILS))
2889 fprintf (dump_file, " Not cloning for all contexts because "
2890 "max_new_size would be reached with %li.\n",
2891 size + overall_size);
2893 else if (dump_file && (dump_flags & TDF_DETAILS))
2894 fprintf (dump_file, " Not cloning for all contexts because "
2895 "!good_cloning_opportunity_p.\n");
2899 for (i = 0; i < count; i++)
2901 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2902 ipcp_lattice<tree> *lat = &plats->itself;
2903 ipcp_value<tree> *val;
2905 if (lat->bottom
2906 || !lat->values
2907 || known_csts[i])
2908 continue;
2910 for (val = lat->values; val; val = val->next)
2912 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2913 known_csts[i] = val->value;
2915 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2916 perform_estimation_of_a_value (node, known_csts, known_contexts,
2917 known_aggs_ptrs, base_time,
2918 removable_params_cost, emc, val);
2920 if (dump_file && (dump_flags & TDF_DETAILS))
2922 fprintf (dump_file, " - estimates for value ");
2923 print_ipcp_constant_value (dump_file, val->value);
2924 fprintf (dump_file, " for ");
2925 ipa_dump_param (dump_file, info, i);
2926 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2927 val->local_time_benefit, val->local_size_cost);
2930 known_csts[i] = NULL_TREE;
2933 for (i = 0; i < count; i++)
2935 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2937 if (!plats->virt_call)
2938 continue;
2940 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2941 ipcp_value<ipa_polymorphic_call_context> *val;
2943 if (ctxlat->bottom
2944 || !ctxlat->values
2945 || !known_contexts[i].useless_p ())
2946 continue;
2948 for (val = ctxlat->values; val; val = val->next)
2950 known_contexts[i] = val->value;
2951 perform_estimation_of_a_value (node, known_csts, known_contexts,
2952 known_aggs_ptrs, base_time,
2953 removable_params_cost, 0, val);
2955 if (dump_file && (dump_flags & TDF_DETAILS))
2957 fprintf (dump_file, " - estimates for polymorphic context ");
2958 print_ipcp_constant_value (dump_file, val->value);
2959 fprintf (dump_file, " for ");
2960 ipa_dump_param (dump_file, info, i);
2961 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2962 val->local_time_benefit, val->local_size_cost);
2965 known_contexts[i] = ipa_polymorphic_call_context ();
2968 for (i = 0; i < count; i++)
2970 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2971 struct ipa_agg_jump_function *ajf;
2972 struct ipcp_agg_lattice *aglat;
2974 if (plats->aggs_bottom || !plats->aggs)
2975 continue;
2977 ajf = &known_aggs[i];
2978 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2980 ipcp_value<tree> *val;
2981 if (aglat->bottom || !aglat->values
2982 /* If the following is true, the one value is in known_aggs. */
2983 || (!plats->aggs_contain_variable
2984 && aglat->is_single_const ()))
2985 continue;
2987 for (val = aglat->values; val; val = val->next)
2989 struct ipa_agg_jf_item item;
2991 item.offset = aglat->offset;
2992 item.value = val->value;
2993 vec_safe_push (ajf->items, item);
2995 perform_estimation_of_a_value (node, known_csts, known_contexts,
2996 known_aggs_ptrs, base_time,
2997 removable_params_cost, 0, val);
2999 if (dump_file && (dump_flags & TDF_DETAILS))
3001 fprintf (dump_file, " - estimates for value ");
3002 print_ipcp_constant_value (dump_file, val->value);
3003 fprintf (dump_file, " for ");
3004 ipa_dump_param (dump_file, info, i);
3005 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3006 "]: time_benefit: %i, size: %i\n",
3007 plats->aggs_by_ref ? "ref " : "",
3008 aglat->offset,
3009 val->local_time_benefit, val->local_size_cost);
3012 ajf->items->pop ();
3017 for (i = 0; i < count; i++)
3018 vec_free (known_aggs[i].items);
3020 known_csts.release ();
3021 known_contexts.release ();
3022 known_aggs.release ();
3023 known_aggs_ptrs.release ();
3027 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3028 topological sort of values. */
3030 template <typename valtype>
3031 void
3032 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3034 ipcp_value_source<valtype> *src;
3036 if (cur_val->dfs)
3037 return;
3039 dfs_counter++;
3040 cur_val->dfs = dfs_counter;
3041 cur_val->low_link = dfs_counter;
3043 cur_val->topo_next = stack;
3044 stack = cur_val;
3045 cur_val->on_stack = true;
3047 for (src = cur_val->sources; src; src = src->next)
3048 if (src->val)
3050 if (src->val->dfs == 0)
3052 add_val (src->val);
3053 if (src->val->low_link < cur_val->low_link)
3054 cur_val->low_link = src->val->low_link;
3056 else if (src->val->on_stack
3057 && src->val->dfs < cur_val->low_link)
3058 cur_val->low_link = src->val->dfs;
3061 if (cur_val->dfs == cur_val->low_link)
3063 ipcp_value<valtype> *v, *scc_list = NULL;
3067 v = stack;
3068 stack = v->topo_next;
3069 v->on_stack = false;
3071 v->scc_next = scc_list;
3072 scc_list = v;
3074 while (v != cur_val);
3076 cur_val->topo_next = values_topo;
3077 values_topo = cur_val;
3081 /* Add all values in lattices associated with NODE to the topological sort if
3082 they are not there yet. */
3084 static void
3085 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3087 struct ipa_node_params *info = IPA_NODE_REF (node);
3088 int i, count = ipa_get_param_count (info);
3090 for (i = 0; i < count; i++)
3092 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3093 ipcp_lattice<tree> *lat = &plats->itself;
3094 struct ipcp_agg_lattice *aglat;
3096 if (!lat->bottom)
3098 ipcp_value<tree> *val;
3099 for (val = lat->values; val; val = val->next)
3100 topo->constants.add_val (val);
3103 if (!plats->aggs_bottom)
3104 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3105 if (!aglat->bottom)
3107 ipcp_value<tree> *val;
3108 for (val = aglat->values; val; val = val->next)
3109 topo->constants.add_val (val);
3112 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3113 if (!ctxlat->bottom)
3115 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3116 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3117 topo->contexts.add_val (ctxval);
3122 /* One pass of constants propagation along the call graph edges, from callers
3123 to callees (requires topological ordering in TOPO), iterate over strongly
3124 connected components. */
3126 static void
3127 propagate_constants_topo (struct ipa_topo_info *topo)
3129 int i;
3131 for (i = topo->nnodes - 1; i >= 0; i--)
3133 unsigned j;
3134 struct cgraph_node *v, *node = topo->order[i];
3135 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3137 /* First, iteratively propagate within the strongly connected component
3138 until all lattices stabilize. */
3139 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3140 if (v->has_gimple_body_p ())
3141 push_node_to_stack (topo, v);
3143 v = pop_node_from_stack (topo);
3144 while (v)
3146 struct cgraph_edge *cs;
3148 for (cs = v->callees; cs; cs = cs->next_callee)
3149 if (ipa_edge_within_scc (cs))
3151 IPA_NODE_REF (v)->node_within_scc = true;
3152 if (propagate_constants_across_call (cs))
3153 push_node_to_stack (topo, cs->callee->function_symbol ());
3155 v = pop_node_from_stack (topo);
3158 /* Afterwards, propagate along edges leading out of the SCC, calculates
3159 the local effects of the discovered constants and all valid values to
3160 their topological sort. */
3161 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3162 if (v->has_gimple_body_p ())
3164 struct cgraph_edge *cs;
3166 estimate_local_effects (v);
3167 add_all_node_vals_to_toposort (v, topo);
3168 for (cs = v->callees; cs; cs = cs->next_callee)
3169 if (!ipa_edge_within_scc (cs))
3170 propagate_constants_across_call (cs);
3172 cycle_nodes.release ();
3177 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3178 the bigger one if otherwise. */
3180 static int
3181 safe_add (int a, int b)
3183 if (a > INT_MAX/2 || b > INT_MAX/2)
3184 return a > b ? a : b;
3185 else
3186 return a + b;
3190 /* Propagate the estimated effects of individual values along the topological
3191 from the dependent values to those they depend on. */
3193 template <typename valtype>
3194 void
3195 value_topo_info<valtype>::propagate_effects ()
3197 ipcp_value<valtype> *base;
3199 for (base = values_topo; base; base = base->topo_next)
3201 ipcp_value_source<valtype> *src;
3202 ipcp_value<valtype> *val;
3203 int time = 0, size = 0;
3205 for (val = base; val; val = val->scc_next)
3207 time = safe_add (time,
3208 val->local_time_benefit + val->prop_time_benefit);
3209 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3212 for (val = base; val; val = val->scc_next)
3213 for (src = val->sources; src; src = src->next)
3214 if (src->val
3215 && src->cs->maybe_hot_p ())
3217 src->val->prop_time_benefit = safe_add (time,
3218 src->val->prop_time_benefit);
3219 src->val->prop_size_cost = safe_add (size,
3220 src->val->prop_size_cost);
3226 /* Propagate constants, polymorphic contexts and their effects from the
3227 summaries interprocedurally. */
3229 static void
3230 ipcp_propagate_stage (struct ipa_topo_info *topo)
3232 struct cgraph_node *node;
3234 if (dump_file)
3235 fprintf (dump_file, "\n Propagating constants:\n\n");
3237 if (in_lto_p)
3238 ipa_update_after_lto_read ();
3241 FOR_EACH_DEFINED_FUNCTION (node)
3243 struct ipa_node_params *info = IPA_NODE_REF (node);
3245 determine_versionability (node, info);
3246 if (node->has_gimple_body_p ())
3248 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
3249 ipa_get_param_count (info));
3250 initialize_node_lattices (node);
3252 if (node->definition && !node->alias)
3253 overall_size += inline_summaries->get (node)->self_size;
3254 if (node->count > max_count)
3255 max_count = node->count;
3258 max_new_size = overall_size;
3259 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
3260 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
3261 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
3263 if (dump_file)
3264 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
3265 overall_size, max_new_size);
3267 propagate_constants_topo (topo);
3268 if (flag_checking)
3269 ipcp_verify_propagated_values ();
3270 topo->constants.propagate_effects ();
3271 topo->contexts.propagate_effects ();
3273 if (dump_file)
3275 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3276 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3280 /* Discover newly direct outgoing edges from NODE which is a new clone with
3281 known KNOWN_CSTS and make them direct. */
3283 static void
3284 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3285 vec<tree> known_csts,
3286 vec<ipa_polymorphic_call_context>
3287 known_contexts,
3288 struct ipa_agg_replacement_value *aggvals)
3290 struct cgraph_edge *ie, *next_ie;
3291 bool found = false;
3293 for (ie = node->indirect_calls; ie; ie = next_ie)
3295 tree target;
3296 bool speculative;
3298 next_ie = ie->next_callee;
3299 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3300 vNULL, aggvals, &speculative);
3301 if (target)
3303 bool agg_contents = ie->indirect_info->agg_contents;
3304 bool polymorphic = ie->indirect_info->polymorphic;
3305 int param_index = ie->indirect_info->param_index;
3306 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3307 speculative);
3308 found = true;
3310 if (cs && !agg_contents && !polymorphic)
3312 struct ipa_node_params *info = IPA_NODE_REF (node);
3313 int c = ipa_get_controlled_uses (info, param_index);
3314 if (c != IPA_UNDESCRIBED_USE)
3316 struct ipa_ref *to_del;
3318 c--;
3319 ipa_set_controlled_uses (info, param_index, c);
3320 if (dump_file && (dump_flags & TDF_DETAILS))
3321 fprintf (dump_file, " controlled uses count of param "
3322 "%i bumped down to %i\n", param_index, c);
3323 if (c == 0
3324 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3326 if (dump_file && (dump_flags & TDF_DETAILS))
3327 fprintf (dump_file, " and even removing its "
3328 "cloning-created reference\n");
3329 to_del->remove_reference ();
3335 /* Turning calls to direct calls will improve overall summary. */
3336 if (found)
3337 inline_update_overall_summary (node);
3340 /* Vector of pointers which for linked lists of clones of an original crgaph
3341 edge. */
3343 static vec<cgraph_edge *> next_edge_clone;
3344 static vec<cgraph_edge *> prev_edge_clone;
3346 static inline void
3347 grow_edge_clone_vectors (void)
3349 if (next_edge_clone.length ()
3350 <= (unsigned) symtab->edges_max_uid)
3351 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3352 if (prev_edge_clone.length ()
3353 <= (unsigned) symtab->edges_max_uid)
3354 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
3357 /* Edge duplication hook to grow the appropriate linked list in
3358 next_edge_clone. */
3360 static void
3361 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
3362 void *)
3364 grow_edge_clone_vectors ();
3366 struct cgraph_edge *old_next = next_edge_clone[src->uid];
3367 if (old_next)
3368 prev_edge_clone[old_next->uid] = dst;
3369 prev_edge_clone[dst->uid] = src;
3371 next_edge_clone[dst->uid] = old_next;
3372 next_edge_clone[src->uid] = dst;
3375 /* Hook that is called by cgraph.c when an edge is removed. */
3377 static void
3378 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
3380 grow_edge_clone_vectors ();
3382 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
3383 struct cgraph_edge *next = next_edge_clone[cs->uid];
3384 if (prev)
3385 next_edge_clone[prev->uid] = next;
3386 if (next)
3387 prev_edge_clone[next->uid] = prev;
3390 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3391 parameter with the given INDEX. */
3393 static tree
3394 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
3395 int index)
3397 struct ipa_agg_replacement_value *aggval;
3399 aggval = ipa_get_agg_replacements_for_node (node);
3400 while (aggval)
3402 if (aggval->offset == offset
3403 && aggval->index == index)
3404 return aggval->value;
3405 aggval = aggval->next;
3407 return NULL_TREE;
3410 /* Return true is NODE is DEST or its clone for all contexts. */
3412 static bool
3413 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3415 if (node == dest)
3416 return true;
3418 struct ipa_node_params *info = IPA_NODE_REF (node);
3419 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3422 /* Return true if edge CS does bring about the value described by SRC to node
3423 DEST or its clone for all contexts. */
3425 static bool
3426 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3427 cgraph_node *dest)
3429 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3430 enum availability availability;
3431 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
3433 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3434 || availability <= AVAIL_INTERPOSABLE
3435 || caller_info->node_dead)
3436 return false;
3437 if (!src->val)
3438 return true;
3440 if (caller_info->ipcp_orig_node)
3442 tree t;
3443 if (src->offset == -1)
3444 t = caller_info->known_csts[src->index];
3445 else
3446 t = get_clone_agg_value (cs->caller, src->offset, src->index);
3447 return (t != NULL_TREE
3448 && values_equal_for_ipcp_p (src->val->value, t));
3450 else
3452 struct ipcp_agg_lattice *aglat;
3453 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3454 src->index);
3455 if (src->offset == -1)
3456 return (plats->itself.is_single_const ()
3457 && values_equal_for_ipcp_p (src->val->value,
3458 plats->itself.values->value));
3459 else
3461 if (plats->aggs_bottom || plats->aggs_contain_variable)
3462 return false;
3463 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3464 if (aglat->offset == src->offset)
3465 return (aglat->is_single_const ()
3466 && values_equal_for_ipcp_p (src->val->value,
3467 aglat->values->value));
3469 return false;
3473 /* Return true if edge CS does bring about the value described by SRC to node
3474 DEST or its clone for all contexts. */
3476 static bool
3477 cgraph_edge_brings_value_p (cgraph_edge *cs,
3478 ipcp_value_source<ipa_polymorphic_call_context> *src,
3479 cgraph_node *dest)
3481 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3482 cgraph_node *real_dest = cs->callee->function_symbol ();
3484 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3485 || caller_info->node_dead)
3486 return false;
3487 if (!src->val)
3488 return true;
3490 if (caller_info->ipcp_orig_node)
3491 return (caller_info->known_contexts.length () > (unsigned) src->index)
3492 && values_equal_for_ipcp_p (src->val->value,
3493 caller_info->known_contexts[src->index]);
3495 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3496 src->index);
3497 return plats->ctxlat.is_single_const ()
3498 && values_equal_for_ipcp_p (src->val->value,
3499 plats->ctxlat.values->value);
3502 /* Get the next clone in the linked list of clones of an edge. */
3504 static inline struct cgraph_edge *
3505 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3507 return next_edge_clone[cs->uid];
3510 /* Given VAL that is intended for DEST, iterate over all its sources and if
3511 they still hold, add their edge frequency and their number into *FREQUENCY
3512 and *CALLER_COUNT respectively. */
3514 template <typename valtype>
3515 static bool
3516 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3517 int *freq_sum,
3518 gcov_type *count_sum, int *caller_count)
3520 ipcp_value_source<valtype> *src;
3521 int freq = 0, count = 0;
3522 gcov_type cnt = 0;
3523 bool hot = false;
3525 for (src = val->sources; src; src = src->next)
3527 struct cgraph_edge *cs = src->cs;
3528 while (cs)
3530 if (cgraph_edge_brings_value_p (cs, src, dest))
3532 count++;
3533 freq += cs->frequency;
3534 cnt += cs->count;
3535 hot |= cs->maybe_hot_p ();
3537 cs = get_next_cgraph_edge_clone (cs);
3541 *freq_sum = freq;
3542 *count_sum = cnt;
3543 *caller_count = count;
3544 return hot;
3547 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3548 is assumed their number is known and equal to CALLER_COUNT. */
3550 template <typename valtype>
3551 static vec<cgraph_edge *>
3552 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3553 int caller_count)
3555 ipcp_value_source<valtype> *src;
3556 vec<cgraph_edge *> ret;
3558 ret.create (caller_count);
3559 for (src = val->sources; src; src = src->next)
3561 struct cgraph_edge *cs = src->cs;
3562 while (cs)
3564 if (cgraph_edge_brings_value_p (cs, src, dest))
3565 ret.quick_push (cs);
3566 cs = get_next_cgraph_edge_clone (cs);
3570 return ret;
3573 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3574 Return it or NULL if for some reason it cannot be created. */
3576 static struct ipa_replace_map *
3577 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3579 struct ipa_replace_map *replace_map;
3582 replace_map = ggc_alloc<ipa_replace_map> ();
3583 if (dump_file)
3585 fprintf (dump_file, " replacing ");
3586 ipa_dump_param (dump_file, info, parm_num);
3588 fprintf (dump_file, " with const ");
3589 print_generic_expr (dump_file, value, 0);
3590 fprintf (dump_file, "\n");
3592 replace_map->old_tree = NULL;
3593 replace_map->parm_num = parm_num;
3594 replace_map->new_tree = value;
3595 replace_map->replace_p = true;
3596 replace_map->ref_p = false;
3598 return replace_map;
3601 /* Dump new profiling counts */
3603 static void
3604 dump_profile_updates (struct cgraph_node *orig_node,
3605 struct cgraph_node *new_node)
3607 struct cgraph_edge *cs;
3609 fprintf (dump_file, " setting count of the specialized node to "
3610 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3611 for (cs = new_node->callees; cs; cs = cs->next_callee)
3612 fprintf (dump_file, " edge to %s has count "
3613 HOST_WIDE_INT_PRINT_DEC "\n",
3614 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3616 fprintf (dump_file, " setting count of the original node to "
3617 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3618 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3619 fprintf (dump_file, " edge to %s is left with "
3620 HOST_WIDE_INT_PRINT_DEC "\n",
3621 cs->callee->name (), (HOST_WIDE_INT) cs->count);
3624 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3625 their profile information to reflect this. */
3627 static void
3628 update_profiling_info (struct cgraph_node *orig_node,
3629 struct cgraph_node *new_node)
3631 struct cgraph_edge *cs;
3632 struct caller_statistics stats;
3633 gcov_type new_sum, orig_sum;
3634 gcov_type remainder, orig_node_count = orig_node->count;
3636 if (orig_node_count == 0)
3637 return;
3639 init_caller_stats (&stats);
3640 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3641 false);
3642 orig_sum = stats.count_sum;
3643 init_caller_stats (&stats);
3644 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3645 false);
3646 new_sum = stats.count_sum;
3648 if (orig_node_count < orig_sum + new_sum)
3650 if (dump_file)
3651 fprintf (dump_file, " Problem: node %s/%i has too low count "
3652 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3653 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
3654 orig_node->name (), orig_node->order,
3655 (HOST_WIDE_INT) orig_node_count,
3656 (HOST_WIDE_INT) (orig_sum + new_sum));
3658 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3659 if (dump_file)
3660 fprintf (dump_file, " proceeding by pretending it was "
3661 HOST_WIDE_INT_PRINT_DEC "\n",
3662 (HOST_WIDE_INT) orig_node_count);
3665 new_node->count = new_sum;
3666 remainder = orig_node_count - new_sum;
3667 orig_node->count = remainder;
3669 for (cs = new_node->callees; cs; cs = cs->next_callee)
3670 if (cs->frequency)
3671 cs->count = apply_probability (cs->count,
3672 GCOV_COMPUTE_SCALE (new_sum,
3673 orig_node_count));
3674 else
3675 cs->count = 0;
3677 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3678 cs->count = apply_probability (cs->count,
3679 GCOV_COMPUTE_SCALE (remainder,
3680 orig_node_count));
3682 if (dump_file)
3683 dump_profile_updates (orig_node, new_node);
3686 /* Update the respective profile of specialized NEW_NODE and the original
3687 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3688 have been redirected to the specialized version. */
3690 static void
3691 update_specialized_profile (struct cgraph_node *new_node,
3692 struct cgraph_node *orig_node,
3693 gcov_type redirected_sum)
3695 struct cgraph_edge *cs;
3696 gcov_type new_node_count, orig_node_count = orig_node->count;
3698 if (dump_file)
3699 fprintf (dump_file, " the sum of counts of redirected edges is "
3700 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3701 if (orig_node_count == 0)
3702 return;
3704 gcc_assert (orig_node_count >= redirected_sum);
3706 new_node_count = new_node->count;
3707 new_node->count += redirected_sum;
3708 orig_node->count -= redirected_sum;
3710 for (cs = new_node->callees; cs; cs = cs->next_callee)
3711 if (cs->frequency)
3712 cs->count += apply_probability (cs->count,
3713 GCOV_COMPUTE_SCALE (redirected_sum,
3714 new_node_count));
3715 else
3716 cs->count = 0;
3718 for (cs = orig_node->callees; cs; cs = cs->next_callee)
3720 gcov_type dec = apply_probability (cs->count,
3721 GCOV_COMPUTE_SCALE (redirected_sum,
3722 orig_node_count));
3723 if (dec < cs->count)
3724 cs->count -= dec;
3725 else
3726 cs->count = 0;
3729 if (dump_file)
3730 dump_profile_updates (orig_node, new_node);
3733 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3734 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3735 redirect all edges in CALLERS to it. */
3737 static struct cgraph_node *
3738 create_specialized_node (struct cgraph_node *node,
3739 vec<tree> known_csts,
3740 vec<ipa_polymorphic_call_context> known_contexts,
3741 struct ipa_agg_replacement_value *aggvals,
3742 vec<cgraph_edge *> callers)
3744 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
3745 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3746 struct ipa_agg_replacement_value *av;
3747 struct cgraph_node *new_node;
3748 int i, count = ipa_get_param_count (info);
3749 bitmap args_to_skip;
3751 gcc_assert (!info->ipcp_orig_node);
3753 if (node->local.can_change_signature)
3755 args_to_skip = BITMAP_GGC_ALLOC ();
3756 for (i = 0; i < count; i++)
3758 tree t = known_csts[i];
3760 if (t || !ipa_is_param_used (info, i))
3761 bitmap_set_bit (args_to_skip, i);
3764 else
3766 args_to_skip = NULL;
3767 if (dump_file && (dump_flags & TDF_DETAILS))
3768 fprintf (dump_file, " cannot change function signature\n");
3771 for (i = 0; i < count; i++)
3773 tree t = known_csts[i];
3774 if (t)
3776 struct ipa_replace_map *replace_map;
3778 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
3779 replace_map = get_replacement_map (info, t, i);
3780 if (replace_map)
3781 vec_safe_push (replace_trees, replace_map);
3785 new_node = node->create_virtual_clone (callers, replace_trees,
3786 args_to_skip, "constprop");
3787 ipa_set_node_agg_value_chain (new_node, aggvals);
3788 for (av = aggvals; av; av = av->next)
3789 new_node->maybe_create_reference (av->value, NULL);
3791 if (dump_file && (dump_flags & TDF_DETAILS))
3793 fprintf (dump_file, " the new node is %s/%i.\n",
3794 new_node->name (), new_node->order);
3795 if (known_contexts.exists ())
3797 for (i = 0; i < count; i++)
3798 if (!known_contexts[i].useless_p ())
3800 fprintf (dump_file, " known ctx %i is ", i);
3801 known_contexts[i].dump (dump_file);
3804 if (aggvals)
3805 ipa_dump_agg_replacement_values (dump_file, aggvals);
3807 ipa_check_create_node_params ();
3808 update_profiling_info (node, new_node);
3809 new_info = IPA_NODE_REF (new_node);
3810 new_info->ipcp_orig_node = node;
3811 new_info->known_csts = known_csts;
3812 new_info->known_contexts = known_contexts;
3814 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
3816 callers.release ();
3817 return new_node;
3820 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3821 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3823 static void
3824 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
3825 vec<tree> known_csts,
3826 vec<cgraph_edge *> callers)
3828 struct ipa_node_params *info = IPA_NODE_REF (node);
3829 int i, count = ipa_get_param_count (info);
3831 for (i = 0; i < count; i++)
3833 struct cgraph_edge *cs;
3834 tree newval = NULL_TREE;
3835 int j;
3836 bool first = true;
3838 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3839 continue;
3841 FOR_EACH_VEC_ELT (callers, j, cs)
3843 struct ipa_jump_func *jump_func;
3844 tree t;
3846 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
3847 || (i == 0
3848 && call_passes_through_thunk_p (cs))
3849 || (!cs->callee->instrumentation_clone
3850 && cs->callee->function_symbol ()->instrumentation_clone))
3852 newval = NULL_TREE;
3853 break;
3855 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
3856 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3857 if (!t
3858 || (newval
3859 && !values_equal_for_ipcp_p (t, newval))
3860 || (!first && !newval))
3862 newval = NULL_TREE;
3863 break;
3865 else
3866 newval = t;
3867 first = false;
3870 if (newval)
3872 if (dump_file && (dump_flags & TDF_DETAILS))
3874 fprintf (dump_file, " adding an extra known scalar value ");
3875 print_ipcp_constant_value (dump_file, newval);
3876 fprintf (dump_file, " for ");
3877 ipa_dump_param (dump_file, info, i);
3878 fprintf (dump_file, "\n");
3881 known_csts[i] = newval;
3886 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3887 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3888 CALLERS. */
3890 static void
3891 find_more_contexts_for_caller_subset (cgraph_node *node,
3892 vec<ipa_polymorphic_call_context>
3893 *known_contexts,
3894 vec<cgraph_edge *> callers)
3896 ipa_node_params *info = IPA_NODE_REF (node);
3897 int i, count = ipa_get_param_count (info);
3899 for (i = 0; i < count; i++)
3901 cgraph_edge *cs;
3903 if (ipa_get_poly_ctx_lat (info, i)->bottom
3904 || (known_contexts->exists ()
3905 && !(*known_contexts)[i].useless_p ()))
3906 continue;
3908 ipa_polymorphic_call_context newval;
3909 bool first = true;
3910 int j;
3912 FOR_EACH_VEC_ELT (callers, j, cs)
3914 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3915 return;
3916 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3918 ipa_polymorphic_call_context ctx;
3919 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3920 jfunc);
3921 if (first)
3923 newval = ctx;
3924 first = false;
3926 else
3927 newval.meet_with (ctx);
3928 if (newval.useless_p ())
3929 break;
3932 if (!newval.useless_p ())
3934 if (dump_file && (dump_flags & TDF_DETAILS))
3936 fprintf (dump_file, " adding an extra known polymorphic "
3937 "context ");
3938 print_ipcp_constant_value (dump_file, newval);
3939 fprintf (dump_file, " for ");
3940 ipa_dump_param (dump_file, info, i);
3941 fprintf (dump_file, "\n");
3944 if (!known_contexts->exists ())
3945 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3946 (*known_contexts)[i] = newval;
3952 /* Go through PLATS and create a vector of values consisting of values and
3953 offsets (minus OFFSET) of lattices that contain only a single value. */
3955 static vec<ipa_agg_jf_item>
3956 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3958 vec<ipa_agg_jf_item> res = vNULL;
3960 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3961 return vNULL;
3963 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3964 if (aglat->is_single_const ())
3966 struct ipa_agg_jf_item ti;
3967 ti.offset = aglat->offset - offset;
3968 ti.value = aglat->values->value;
3969 res.safe_push (ti);
3971 return res;
3974 /* Intersect all values in INTER with single value lattices in PLATS (while
3975 subtracting OFFSET). */
3977 static void
3978 intersect_with_plats (struct ipcp_param_lattices *plats,
3979 vec<ipa_agg_jf_item> *inter,
3980 HOST_WIDE_INT offset)
3982 struct ipcp_agg_lattice *aglat;
3983 struct ipa_agg_jf_item *item;
3984 int k;
3986 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3988 inter->release ();
3989 return;
3992 aglat = plats->aggs;
3993 FOR_EACH_VEC_ELT (*inter, k, item)
3995 bool found = false;
3996 if (!item->value)
3997 continue;
3998 while (aglat)
4000 if (aglat->offset - offset > item->offset)
4001 break;
4002 if (aglat->offset - offset == item->offset)
4004 gcc_checking_assert (item->value);
4005 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
4006 found = true;
4007 break;
4009 aglat = aglat->next;
4011 if (!found)
4012 item->value = NULL_TREE;
4016 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
4017 vector result while subtracting OFFSET from the individual value offsets. */
4019 static vec<ipa_agg_jf_item>
4020 agg_replacements_to_vector (struct cgraph_node *node, int index,
4021 HOST_WIDE_INT offset)
4023 struct ipa_agg_replacement_value *av;
4024 vec<ipa_agg_jf_item> res = vNULL;
4026 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4027 if (av->index == index
4028 && (av->offset - offset) >= 0)
4030 struct ipa_agg_jf_item item;
4031 gcc_checking_assert (av->value);
4032 item.offset = av->offset - offset;
4033 item.value = av->value;
4034 res.safe_push (item);
4037 return res;
4040 /* Intersect all values in INTER with those that we have already scheduled to
4041 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4042 (while subtracting OFFSET). */
4044 static void
4045 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4046 vec<ipa_agg_jf_item> *inter,
4047 HOST_WIDE_INT offset)
4049 struct ipa_agg_replacement_value *srcvals;
4050 struct ipa_agg_jf_item *item;
4051 int i;
4053 srcvals = ipa_get_agg_replacements_for_node (node);
4054 if (!srcvals)
4056 inter->release ();
4057 return;
4060 FOR_EACH_VEC_ELT (*inter, i, item)
4062 struct ipa_agg_replacement_value *av;
4063 bool found = false;
4064 if (!item->value)
4065 continue;
4066 for (av = srcvals; av; av = av->next)
4068 gcc_checking_assert (av->value);
4069 if (av->index == index
4070 && av->offset - offset == item->offset)
4072 if (values_equal_for_ipcp_p (item->value, av->value))
4073 found = true;
4074 break;
4077 if (!found)
4078 item->value = NULL_TREE;
4082 /* Intersect values in INTER with aggregate values that come along edge CS to
4083 parameter number INDEX and return it. If INTER does not actually exist yet,
4084 copy all incoming values to it. If we determine we ended up with no values
4085 whatsoever, return a released vector. */
4087 static vec<ipa_agg_jf_item>
4088 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4089 vec<ipa_agg_jf_item> inter)
4091 struct ipa_jump_func *jfunc;
4092 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4093 if (jfunc->type == IPA_JF_PASS_THROUGH
4094 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4096 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4097 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4099 if (caller_info->ipcp_orig_node)
4101 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4102 struct ipcp_param_lattices *orig_plats;
4103 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4104 src_idx);
4105 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4107 if (!inter.exists ())
4108 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4109 else
4110 intersect_with_agg_replacements (cs->caller, src_idx,
4111 &inter, 0);
4113 else
4115 inter.release ();
4116 return vNULL;
4119 else
4121 struct ipcp_param_lattices *src_plats;
4122 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
4123 if (agg_pass_through_permissible_p (src_plats, jfunc))
4125 /* Currently we do not produce clobber aggregate jump
4126 functions, adjust when we do. */
4127 gcc_checking_assert (!jfunc->agg.items);
4128 if (!inter.exists ())
4129 inter = copy_plats_to_inter (src_plats, 0);
4130 else
4131 intersect_with_plats (src_plats, &inter, 0);
4133 else
4135 inter.release ();
4136 return vNULL;
4140 else if (jfunc->type == IPA_JF_ANCESTOR
4141 && ipa_get_jf_ancestor_agg_preserved (jfunc))
4143 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4144 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
4145 struct ipcp_param_lattices *src_plats;
4146 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
4148 if (caller_info->ipcp_orig_node)
4150 if (!inter.exists ())
4151 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
4152 else
4153 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
4154 delta);
4156 else
4158 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
4159 /* Currently we do not produce clobber aggregate jump
4160 functions, adjust when we do. */
4161 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
4162 if (!inter.exists ())
4163 inter = copy_plats_to_inter (src_plats, delta);
4164 else
4165 intersect_with_plats (src_plats, &inter, delta);
4168 else if (jfunc->agg.items)
4170 struct ipa_agg_jf_item *item;
4171 int k;
4173 if (!inter.exists ())
4174 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
4175 inter.safe_push ((*jfunc->agg.items)[i]);
4176 else
4177 FOR_EACH_VEC_ELT (inter, k, item)
4179 int l = 0;
4180 bool found = false;;
4182 if (!item->value)
4183 continue;
4185 while ((unsigned) l < jfunc->agg.items->length ())
4187 struct ipa_agg_jf_item *ti;
4188 ti = &(*jfunc->agg.items)[l];
4189 if (ti->offset > item->offset)
4190 break;
4191 if (ti->offset == item->offset)
4193 gcc_checking_assert (ti->value);
4194 if (values_equal_for_ipcp_p (item->value,
4195 ti->value))
4196 found = true;
4197 break;
4199 l++;
4201 if (!found)
4202 item->value = NULL;
4205 else
4207 inter.release ();
4208 return vec<ipa_agg_jf_item>();
4210 return inter;
4213 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4214 from all of them. */
4216 static struct ipa_agg_replacement_value *
4217 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
4218 vec<cgraph_edge *> callers)
4220 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4221 struct ipa_agg_replacement_value *res;
4222 struct ipa_agg_replacement_value **tail = &res;
4223 struct cgraph_edge *cs;
4224 int i, j, count = ipa_get_param_count (dest_info);
4226 FOR_EACH_VEC_ELT (callers, j, cs)
4228 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4229 if (c < count)
4230 count = c;
4233 for (i = 0; i < count; i++)
4235 struct cgraph_edge *cs;
4236 vec<ipa_agg_jf_item> inter = vNULL;
4237 struct ipa_agg_jf_item *item;
4238 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
4239 int j;
4241 /* Among other things, the following check should deal with all by_ref
4242 mismatches. */
4243 if (plats->aggs_bottom)
4244 continue;
4246 FOR_EACH_VEC_ELT (callers, j, cs)
4248 inter = intersect_aggregates_with_edge (cs, i, inter);
4250 if (!inter.exists ())
4251 goto next_param;
4254 FOR_EACH_VEC_ELT (inter, j, item)
4256 struct ipa_agg_replacement_value *v;
4258 if (!item->value)
4259 continue;
4261 v = ggc_alloc<ipa_agg_replacement_value> ();
4262 v->index = i;
4263 v->offset = item->offset;
4264 v->value = item->value;
4265 v->by_ref = plats->aggs_by_ref;
4266 *tail = v;
4267 tail = &v->next;
4270 next_param:
4271 if (inter.exists ())
4272 inter.release ();
4274 *tail = NULL;
4275 return res;
4278 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
4280 static struct ipa_agg_replacement_value *
4281 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
4283 struct ipa_agg_replacement_value *res;
4284 struct ipa_agg_replacement_value **tail = &res;
4285 struct ipa_agg_jump_function *aggjf;
4286 struct ipa_agg_jf_item *item;
4287 int i, j;
4289 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
4290 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
4292 struct ipa_agg_replacement_value *v;
4293 v = ggc_alloc<ipa_agg_replacement_value> ();
4294 v->index = i;
4295 v->offset = item->offset;
4296 v->value = item->value;
4297 v->by_ref = aggjf->by_ref;
4298 *tail = v;
4299 tail = &v->next;
4301 *tail = NULL;
4302 return res;
4305 /* Determine whether CS also brings all scalar values that the NODE is
4306 specialized for. */
4308 static bool
4309 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
4310 struct cgraph_node *node)
4312 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
4313 int count = ipa_get_param_count (dest_info);
4314 struct ipa_node_params *caller_info;
4315 struct ipa_edge_args *args;
4316 int i;
4318 caller_info = IPA_NODE_REF (cs->caller);
4319 args = IPA_EDGE_REF (cs);
4320 for (i = 0; i < count; i++)
4322 struct ipa_jump_func *jump_func;
4323 tree val, t;
4325 val = dest_info->known_csts[i];
4326 if (!val)
4327 continue;
4329 if (i >= ipa_get_cs_argument_count (args))
4330 return false;
4331 jump_func = ipa_get_ith_jump_func (args, i);
4332 t = ipa_value_from_jfunc (caller_info, jump_func);
4333 if (!t || !values_equal_for_ipcp_p (val, t))
4334 return false;
4336 return true;
4339 /* Determine whether CS also brings all aggregate values that NODE is
4340 specialized for. */
4341 static bool
4342 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
4343 struct cgraph_node *node)
4345 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
4346 struct ipa_node_params *orig_node_info;
4347 struct ipa_agg_replacement_value *aggval;
4348 int i, ec, count;
4350 aggval = ipa_get_agg_replacements_for_node (node);
4351 if (!aggval)
4352 return true;
4354 count = ipa_get_param_count (IPA_NODE_REF (node));
4355 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4356 if (ec < count)
4357 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4358 if (aggval->index >= ec)
4359 return false;
4361 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
4362 if (orig_caller_info->ipcp_orig_node)
4363 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4365 for (i = 0; i < count; i++)
4367 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
4368 struct ipcp_param_lattices *plats;
4369 bool interesting = false;
4370 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4371 if (aggval->index == i)
4373 interesting = true;
4374 break;
4376 if (!interesting)
4377 continue;
4379 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
4380 if (plats->aggs_bottom)
4381 return false;
4383 values = intersect_aggregates_with_edge (cs, i, values);
4384 if (!values.exists ())
4385 return false;
4387 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4388 if (aggval->index == i)
4390 struct ipa_agg_jf_item *item;
4391 int j;
4392 bool found = false;
4393 FOR_EACH_VEC_ELT (values, j, item)
4394 if (item->value
4395 && item->offset == av->offset
4396 && values_equal_for_ipcp_p (item->value, av->value))
4398 found = true;
4399 break;
4401 if (!found)
4403 values.release ();
4404 return false;
4408 return true;
4411 /* Given an original NODE and a VAL for which we have already created a
4412 specialized clone, look whether there are incoming edges that still lead
4413 into the old node but now also bring the requested value and also conform to
4414 all other criteria such that they can be redirected the special node.
4415 This function can therefore redirect the final edge in a SCC. */
4417 template <typename valtype>
4418 static void
4419 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
4421 ipcp_value_source<valtype> *src;
4422 gcov_type redirected_sum = 0;
4424 for (src = val->sources; src; src = src->next)
4426 struct cgraph_edge *cs = src->cs;
4427 while (cs)
4429 if (cgraph_edge_brings_value_p (cs, src, node)
4430 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4431 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
4433 if (dump_file)
4434 fprintf (dump_file, " - adding an extra caller %s/%i"
4435 " of %s/%i\n",
4436 xstrdup_for_dump (cs->caller->name ()),
4437 cs->caller->order,
4438 xstrdup_for_dump (val->spec_node->name ()),
4439 val->spec_node->order);
4441 cs->redirect_callee_duplicating_thunks (val->spec_node);
4442 val->spec_node->expand_all_artificial_thunks ();
4443 redirected_sum += cs->count;
4445 cs = get_next_cgraph_edge_clone (cs);
4449 if (redirected_sum)
4450 update_specialized_profile (val->spec_node, node, redirected_sum);
4453 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4455 static bool
4456 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4458 ipa_polymorphic_call_context *ctx;
4459 int i;
4461 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4462 if (!ctx->useless_p ())
4463 return true;
4464 return false;
4467 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4469 static vec<ipa_polymorphic_call_context>
4470 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4472 if (known_contexts_useful_p (known_contexts))
4473 return known_contexts.copy ();
4474 else
4475 return vNULL;
4478 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4479 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4481 static void
4482 modify_known_vectors_with_val (vec<tree> *known_csts,
4483 vec<ipa_polymorphic_call_context> *known_contexts,
4484 ipcp_value<tree> *val,
4485 int index)
4487 *known_csts = known_csts->copy ();
4488 *known_contexts = copy_useful_known_contexts (*known_contexts);
4489 (*known_csts)[index] = val->value;
4492 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4493 copy according to VAL and INDEX. */
4495 static void
4496 modify_known_vectors_with_val (vec<tree> *known_csts,
4497 vec<ipa_polymorphic_call_context> *known_contexts,
4498 ipcp_value<ipa_polymorphic_call_context> *val,
4499 int index)
4501 *known_csts = known_csts->copy ();
4502 *known_contexts = known_contexts->copy ();
4503 (*known_contexts)[index] = val->value;
4506 /* Return true if OFFSET indicates this was not an aggregate value or there is
4507 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4508 AGGVALS list. */
4510 DEBUG_FUNCTION bool
4511 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4512 int index, HOST_WIDE_INT offset, tree value)
4514 if (offset == -1)
4515 return true;
4517 while (aggvals)
4519 if (aggvals->index == index
4520 && aggvals->offset == offset
4521 && values_equal_for_ipcp_p (aggvals->value, value))
4522 return true;
4523 aggvals = aggvals->next;
4525 return false;
4528 /* Return true if offset is minus one because source of a polymorphic contect
4529 cannot be an aggregate value. */
4531 DEBUG_FUNCTION bool
4532 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4533 int , HOST_WIDE_INT offset,
4534 ipa_polymorphic_call_context)
4536 return offset == -1;
4539 /* Decide wheter to create a special version of NODE for value VAL of parameter
4540 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4541 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4542 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4544 template <typename valtype>
4545 static bool
4546 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
4547 ipcp_value<valtype> *val, vec<tree> known_csts,
4548 vec<ipa_polymorphic_call_context> known_contexts)
4550 struct ipa_agg_replacement_value *aggvals;
4551 int freq_sum, caller_count;
4552 gcov_type count_sum;
4553 vec<cgraph_edge *> callers;
4555 if (val->spec_node)
4557 perhaps_add_new_callers (node, val);
4558 return false;
4560 else if (val->local_size_cost + overall_size > max_new_size)
4562 if (dump_file && (dump_flags & TDF_DETAILS))
4563 fprintf (dump_file, " Ignoring candidate value because "
4564 "max_new_size would be reached with %li.\n",
4565 val->local_size_cost + overall_size);
4566 return false;
4568 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
4569 &caller_count))
4570 return false;
4572 if (dump_file && (dump_flags & TDF_DETAILS))
4574 fprintf (dump_file, " - considering value ");
4575 print_ipcp_constant_value (dump_file, val->value);
4576 fprintf (dump_file, " for ");
4577 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
4578 if (offset != -1)
4579 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4580 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4583 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4584 freq_sum, count_sum,
4585 val->local_size_cost)
4586 && !good_cloning_opportunity_p (node,
4587 val->local_time_benefit
4588 + val->prop_time_benefit,
4589 freq_sum, count_sum,
4590 val->local_size_cost
4591 + val->prop_size_cost))
4592 return false;
4594 if (dump_file)
4595 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
4596 node->name (), node->order);
4598 callers = gather_edges_for_value (val, node, caller_count);
4599 if (offset == -1)
4600 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4601 else
4603 known_csts = known_csts.copy ();
4604 known_contexts = copy_useful_known_contexts (known_contexts);
4606 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4607 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
4608 aggvals = find_aggregate_values_for_callers_subset (node, callers);
4609 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4610 offset, val->value));
4611 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4612 aggvals, callers);
4613 overall_size += val->local_size_cost;
4615 /* TODO: If for some lattice there is only one other known value
4616 left, make a special node for it too. */
4618 return true;
4621 /* Decide whether and what specialized clones of NODE should be created. */
4623 static bool
4624 decide_whether_version_node (struct cgraph_node *node)
4626 struct ipa_node_params *info = IPA_NODE_REF (node);
4627 int i, count = ipa_get_param_count (info);
4628 vec<tree> known_csts;
4629 vec<ipa_polymorphic_call_context> known_contexts;
4630 vec<ipa_agg_jump_function> known_aggs = vNULL;
4631 bool ret = false;
4633 if (count == 0)
4634 return false;
4636 if (dump_file && (dump_flags & TDF_DETAILS))
4637 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
4638 node->name (), node->order);
4640 gather_context_independent_values (info, &known_csts, &known_contexts,
4641 info->do_clone_for_all_contexts ? &known_aggs
4642 : NULL, NULL);
4644 for (i = 0; i < count;i++)
4646 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4647 ipcp_lattice<tree> *lat = &plats->itself;
4648 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
4650 if (!lat->bottom
4651 && !known_csts[i])
4653 ipcp_value<tree> *val;
4654 for (val = lat->values; val; val = val->next)
4655 ret |= decide_about_value (node, i, -1, val, known_csts,
4656 known_contexts);
4659 if (!plats->aggs_bottom)
4661 struct ipcp_agg_lattice *aglat;
4662 ipcp_value<tree> *val;
4663 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4664 if (!aglat->bottom && aglat->values
4665 /* If the following is false, the one value is in
4666 known_aggs. */
4667 && (plats->aggs_contain_variable
4668 || !aglat->is_single_const ()))
4669 for (val = aglat->values; val; val = val->next)
4670 ret |= decide_about_value (node, i, aglat->offset, val,
4671 known_csts, known_contexts);
4674 if (!ctxlat->bottom
4675 && known_contexts[i].useless_p ())
4677 ipcp_value<ipa_polymorphic_call_context> *val;
4678 for (val = ctxlat->values; val; val = val->next)
4679 ret |= decide_about_value (node, i, -1, val, known_csts,
4680 known_contexts);
4683 info = IPA_NODE_REF (node);
4686 if (info->do_clone_for_all_contexts)
4688 struct cgraph_node *clone;
4689 vec<cgraph_edge *> callers;
4691 if (dump_file)
4692 fprintf (dump_file, " - Creating a specialized node of %s/%i "
4693 "for all known contexts.\n", node->name (),
4694 node->order);
4696 callers = node->collect_callers ();
4698 if (!known_contexts_useful_p (known_contexts))
4700 known_contexts.release ();
4701 known_contexts = vNULL;
4703 clone = create_specialized_node (node, known_csts, known_contexts,
4704 known_aggs_to_agg_replacement_list (known_aggs),
4705 callers);
4706 info = IPA_NODE_REF (node);
4707 info->do_clone_for_all_contexts = false;
4708 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
4709 for (i = 0; i < count; i++)
4710 vec_free (known_aggs[i].items);
4711 known_aggs.release ();
4712 ret = true;
4714 else
4716 known_csts.release ();
4717 known_contexts.release ();
4720 return ret;
4723 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4725 static void
4726 spread_undeadness (struct cgraph_node *node)
4728 struct cgraph_edge *cs;
4730 for (cs = node->callees; cs; cs = cs->next_callee)
4731 if (ipa_edge_within_scc (cs))
4733 struct cgraph_node *callee;
4734 struct ipa_node_params *info;
4736 callee = cs->callee->function_symbol (NULL);
4737 info = IPA_NODE_REF (callee);
4739 if (info->node_dead)
4741 info->node_dead = 0;
4742 spread_undeadness (callee);
4747 /* Return true if NODE has a caller from outside of its SCC that is not
4748 dead. Worker callback for cgraph_for_node_and_aliases. */
4750 static bool
4751 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4752 void *data ATTRIBUTE_UNUSED)
4754 struct cgraph_edge *cs;
4756 for (cs = node->callers; cs; cs = cs->next_caller)
4757 if (cs->caller->thunk.thunk_p
4758 && cs->caller->call_for_symbol_thunks_and_aliases
4759 (has_undead_caller_from_outside_scc_p, NULL, true))
4760 return true;
4761 else if (!ipa_edge_within_scc (cs)
4762 && !IPA_NODE_REF (cs->caller)->node_dead)
4763 return true;
4764 return false;
4768 /* Identify nodes within the same SCC as NODE which are no longer needed
4769 because of new clones and will be removed as unreachable. */
4771 static void
4772 identify_dead_nodes (struct cgraph_node *node)
4774 struct cgraph_node *v;
4775 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4776 if (v->local.local
4777 && !v->call_for_symbol_thunks_and_aliases
4778 (has_undead_caller_from_outside_scc_p, NULL, true))
4779 IPA_NODE_REF (v)->node_dead = 1;
4781 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4782 if (!IPA_NODE_REF (v)->node_dead)
4783 spread_undeadness (v);
4785 if (dump_file && (dump_flags & TDF_DETAILS))
4787 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4788 if (IPA_NODE_REF (v)->node_dead)
4789 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
4790 v->name (), v->order);
4794 /* The decision stage. Iterate over the topological order of call graph nodes
4795 TOPO and make specialized clones if deemed beneficial. */
4797 static void
4798 ipcp_decision_stage (struct ipa_topo_info *topo)
4800 int i;
4802 if (dump_file)
4803 fprintf (dump_file, "\nIPA decision stage:\n\n");
4805 for (i = topo->nnodes - 1; i >= 0; i--)
4807 struct cgraph_node *node = topo->order[i];
4808 bool change = false, iterate = true;
4810 while (iterate)
4812 struct cgraph_node *v;
4813 iterate = false;
4814 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
4815 if (v->has_gimple_body_p ()
4816 && ipcp_versionable_function_p (v))
4817 iterate |= decide_whether_version_node (v);
4819 change |= iterate;
4821 if (change)
4822 identify_dead_nodes (node);
4826 /* Look up all the bits information that we have discovered and copy it over
4827 to the transformation summary. */
4829 static void
4830 ipcp_store_bits_results (void)
4832 cgraph_node *node;
4834 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4836 ipa_node_params *info = IPA_NODE_REF (node);
4837 bool dumped_sth = false;
4838 bool found_useful_result = false;
4840 if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
4842 if (dump_file)
4843 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
4844 "; -fipa-bit-cp: disabled.\n",
4845 node->name ());
4846 continue;
4849 if (info->ipcp_orig_node)
4850 info = IPA_NODE_REF (info->ipcp_orig_node);
4852 unsigned count = ipa_get_param_count (info);
4853 for (unsigned i = 0; i < count; i++)
4855 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4856 if (plats->bits_lattice.constant_p ())
4858 found_useful_result = true;
4859 break;
4863 if (!found_useful_result)
4864 continue;
4866 ipcp_grow_transformations_if_necessary ();
4867 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4868 vec_safe_reserve_exact (ts->bits, count);
4870 for (unsigned i = 0; i < count; i++)
4872 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4873 ipa_bits bits_jfunc;
4875 if (plats->bits_lattice.constant_p ())
4877 bits_jfunc.known = true;
4878 bits_jfunc.value = plats->bits_lattice.get_value ();
4879 bits_jfunc.mask = plats->bits_lattice.get_mask ();
4881 else
4882 bits_jfunc.known = false;
4884 ts->bits->quick_push (bits_jfunc);
4885 if (!dump_file || !bits_jfunc.known)
4886 continue;
4887 if (!dumped_sth)
4889 fprintf (dump_file, "Propagated bits info for function %s/%i:\n",
4890 node->name (), node->order);
4891 dumped_sth = true;
4893 fprintf (dump_file, " param %i: value = ", i);
4894 print_hex (bits_jfunc.value, dump_file);
4895 fprintf (dump_file, ", mask = ");
4896 print_hex (bits_jfunc.mask, dump_file);
4897 fprintf (dump_file, "\n");
4902 /* Look up all VR information that we have discovered and copy it over
4903 to the transformation summary. */
4905 static void
4906 ipcp_store_vr_results (void)
4908 cgraph_node *node;
4910 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4912 ipa_node_params *info = IPA_NODE_REF (node);
4913 bool found_useful_result = false;
4915 if (!opt_for_fn (node->decl, flag_ipa_vrp))
4917 if (dump_file)
4918 fprintf (dump_file, "Not considering %s for VR discovery "
4919 "and propagate; -fipa-ipa-vrp: disabled.\n",
4920 node->name ());
4921 continue;
4924 if (info->ipcp_orig_node)
4925 info = IPA_NODE_REF (info->ipcp_orig_node);
4927 unsigned count = ipa_get_param_count (info);
4928 for (unsigned i = 0; i < count; i++)
4930 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4931 if (!plats->m_value_range.bottom_p ()
4932 && !plats->m_value_range.top_p ())
4934 found_useful_result = true;
4935 break;
4938 if (!found_useful_result)
4939 continue;
4941 ipcp_grow_transformations_if_necessary ();
4942 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4943 vec_safe_reserve_exact (ts->m_vr, count);
4945 for (unsigned i = 0; i < count; i++)
4947 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
4948 ipa_vr vr;
4950 if (!plats->m_value_range.bottom_p ()
4951 && !plats->m_value_range.top_p ())
4953 vr.known = true;
4954 vr.type = plats->m_value_range.m_vr.type;
4955 vr.min = plats->m_value_range.m_vr.min;
4956 vr.max = plats->m_value_range.m_vr.max;
4958 else
4960 vr.known = false;
4961 vr.type = VR_VARYING;
4962 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
4964 ts->m_vr->quick_push (vr);
4969 /* The IPCP driver. */
4971 static unsigned int
4972 ipcp_driver (void)
4974 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
4975 struct cgraph_edge_hook_list *edge_removal_hook_holder;
4976 struct ipa_topo_info topo;
4978 ipa_check_create_node_params ();
4979 ipa_check_create_edge_args ();
4980 grow_edge_clone_vectors ();
4981 edge_duplication_hook_holder
4982 = symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
4983 edge_removal_hook_holder
4984 = symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
4986 if (dump_file)
4988 fprintf (dump_file, "\nIPA structures before propagation:\n");
4989 if (dump_flags & TDF_DETAILS)
4990 ipa_print_all_params (dump_file);
4991 ipa_print_all_jump_functions (dump_file);
4994 /* Topological sort. */
4995 build_toporder_info (&topo);
4996 /* Do the interprocedural propagation. */
4997 ipcp_propagate_stage (&topo);
4998 /* Decide what constant propagation and cloning should be performed. */
4999 ipcp_decision_stage (&topo);
5000 /* Store results of bits propagation. */
5001 ipcp_store_bits_results ();
5002 /* Store results of value range propagation. */
5003 ipcp_store_vr_results ();
5005 /* Free all IPCP structures. */
5006 free_toporder_info (&topo);
5007 next_edge_clone.release ();
5008 prev_edge_clone.release ();
5009 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
5010 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
5011 ipa_free_all_structures_after_ipa_cp ();
5012 if (dump_file)
5013 fprintf (dump_file, "\nIPA constant propagation end\n");
5014 return 0;
5017 /* Initialization and computation of IPCP data structures. This is the initial
5018 intraprocedural analysis of functions, which gathers information to be
5019 propagated later on. */
5021 static void
5022 ipcp_generate_summary (void)
5024 struct cgraph_node *node;
5026 if (dump_file)
5027 fprintf (dump_file, "\nIPA constant propagation start:\n");
5028 ipa_register_cgraph_hooks ();
5030 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5031 ipa_analyze_node (node);
5034 /* Write ipcp summary for nodes in SET. */
5036 static void
5037 ipcp_write_summary (void)
5039 ipa_prop_write_jump_functions ();
5042 /* Read ipcp summary. */
5044 static void
5045 ipcp_read_summary (void)
5047 ipa_prop_read_jump_functions ();
5050 namespace {
5052 const pass_data pass_data_ipa_cp =
5054 IPA_PASS, /* type */
5055 "cp", /* name */
5056 OPTGROUP_NONE, /* optinfo_flags */
5057 TV_IPA_CONSTANT_PROP, /* tv_id */
5058 0, /* properties_required */
5059 0, /* properties_provided */
5060 0, /* properties_destroyed */
5061 0, /* todo_flags_start */
5062 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5065 class pass_ipa_cp : public ipa_opt_pass_d
5067 public:
5068 pass_ipa_cp (gcc::context *ctxt)
5069 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5070 ipcp_generate_summary, /* generate_summary */
5071 ipcp_write_summary, /* write_summary */
5072 ipcp_read_summary, /* read_summary */
5073 ipcp_write_transformation_summaries, /*
5074 write_optimization_summary */
5075 ipcp_read_transformation_summaries, /*
5076 read_optimization_summary */
5077 NULL, /* stmt_fixup */
5078 0, /* function_transform_todo_flags_start */
5079 ipcp_transform_function, /* function_transform */
5080 NULL) /* variable_transform */
5083 /* opt_pass methods: */
5084 virtual bool gate (function *)
5086 /* FIXME: We should remove the optimize check after we ensure we never run
5087 IPA passes when not optimizing. */
5088 return (flag_ipa_cp && optimize) || in_lto_p;
5091 virtual unsigned int execute (function *) { return ipcp_driver (); }
5093 }; // class pass_ipa_cp
5095 } // anon namespace
5097 ipa_opt_pass_d *
5098 make_pass_ipa_cp (gcc::context *ctxt)
5100 return new pass_ipa_cp (ctxt);
5103 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5104 within the same process. For use by toplev::finalize. */
5106 void
5107 ipa_cp_c_finalize (void)
5109 max_count = 0;
5110 overall_size = 0;
5111 max_new_size = 0;