testsuite: skip zero-scratch-regs on powerpc.
[official-gcc.git] / gcc / ipa-cp.c
blob465b072d88da29a03e607c312012d3dddb149e66
1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2020 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 "ipa-fnsummary.h"
122 #include "ipa-utils.h"
123 #include "tree-ssa-ccp.h"
124 #include "stringpool.h"
125 #include "attribs.h"
126 #include "dbgcnt.h"
127 #include "symtab-clones.h"
129 template <typename valtype> class ipcp_value;
131 /* Describes a particular source for an IPA-CP value. */
133 template <typename valtype>
134 struct ipcp_value_source
136 public:
137 /* Aggregate offset of the source, negative if the source is scalar value of
138 the argument itself. */
139 HOST_WIDE_INT offset;
140 /* The incoming edge that brought the value. */
141 cgraph_edge *cs;
142 /* If the jump function that resulted into his value was a pass-through or an
143 ancestor, this is the ipcp_value of the caller from which the described
144 value has been derived. Otherwise it is NULL. */
145 ipcp_value<valtype> *val;
146 /* Next pointer in a linked list of sources of a value. */
147 ipcp_value_source *next;
148 /* If the jump function that resulted into his value was a pass-through or an
149 ancestor, this is the index of the parameter of the caller the jump
150 function references. */
151 int index;
154 /* Common ancestor for all ipcp_value instantiations. */
156 class ipcp_value_base
158 public:
159 /* Time benefit and size cost that specializing the function for this value
160 would bring about in this function alone. */
161 int local_time_benefit, local_size_cost;
162 /* Time benefit and size cost that specializing the function for this value
163 can bring about in it's callees (transitively). */
164 int prop_time_benefit, prop_size_cost;
166 ipcp_value_base ()
167 : local_time_benefit (0), local_size_cost (0),
168 prop_time_benefit (0), prop_size_cost (0) {}
171 /* Describes one particular value stored in struct ipcp_lattice. */
173 template <typename valtype>
174 class ipcp_value : public ipcp_value_base
176 public:
177 /* The actual value for the given parameter. */
178 valtype value;
179 /* The list of sources from which this value originates. */
180 ipcp_value_source <valtype> *sources;
181 /* Next pointers in a linked list of all values in a lattice. */
182 ipcp_value *next;
183 /* Next pointers in a linked list of values in a strongly connected component
184 of values. */
185 ipcp_value *scc_next;
186 /* Next pointers in a linked list of SCCs of values sorted topologically
187 according their sources. */
188 ipcp_value *topo_next;
189 /* A specialized node created for this value, NULL if none has been (so far)
190 created. */
191 cgraph_node *spec_node;
192 /* Depth first search number and low link for topological sorting of
193 values. */
194 int dfs, low_link;
195 /* True if this value is currently on the topo-sort stack. */
196 bool on_stack;
198 ipcp_value()
199 : sources (0), next (0), scc_next (0), topo_next (0),
200 spec_node (0), dfs (0), low_link (0), on_stack (false) {}
202 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
203 HOST_WIDE_INT offset);
206 /* Lattice describing potential values of a formal parameter of a function, or
207 a part of an aggregate. TOP is represented by a lattice with zero values
208 and with contains_variable and bottom flags cleared. BOTTOM is represented
209 by a lattice with the bottom flag set. In that case, values and
210 contains_variable flag should be disregarded. */
212 template <typename valtype>
213 struct ipcp_lattice
215 public:
216 /* The list of known values and types in this lattice. Note that values are
217 not deallocated if a lattice is set to bottom because there may be value
218 sources referencing them. */
219 ipcp_value<valtype> *values;
220 /* Number of known values and types in this lattice. */
221 int values_count;
222 /* The lattice contains a variable component (in addition to values). */
223 bool contains_variable;
224 /* The value of the lattice is bottom (i.e. variable and unusable for any
225 propagation). */
226 bool bottom;
228 inline bool is_single_const ();
229 inline bool set_to_bottom ();
230 inline bool set_contains_variable ();
231 bool add_value (valtype newval, cgraph_edge *cs,
232 ipcp_value<valtype> *src_val = NULL,
233 int src_idx = 0, HOST_WIDE_INT offset = -1,
234 ipcp_value<valtype> **val_p = NULL,
235 bool unlimited = false);
236 void print (FILE * f, bool dump_sources, bool dump_benefits);
239 /* Lattice of tree values with an offset to describe a part of an
240 aggregate. */
242 struct ipcp_agg_lattice : public ipcp_lattice<tree>
244 public:
245 /* Offset that is being described by this lattice. */
246 HOST_WIDE_INT offset;
247 /* Size so that we don't have to re-compute it every time we traverse the
248 list. Must correspond to TYPE_SIZE of all lat values. */
249 HOST_WIDE_INT size;
250 /* Next element of the linked list. */
251 struct ipcp_agg_lattice *next;
254 /* Lattice of known bits, only capable of holding one value.
255 Bitwise constant propagation propagates which bits of a
256 value are constant.
257 For eg:
258 int f(int x)
260 return some_op (x);
263 int f1(int y)
265 if (cond)
266 return f (y & 0xff);
267 else
268 return f (y & 0xf);
271 In the above case, the param 'x' will always have all
272 the bits (except the bits in lsb) set to 0.
273 Hence the mask of 'x' would be 0xff. The mask
274 reflects that the bits in lsb are unknown.
275 The actual propagated value is given by m_value & ~m_mask. */
277 class ipcp_bits_lattice
279 public:
280 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; }
281 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; }
282 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; }
283 bool set_to_bottom ();
284 bool set_to_constant (widest_int, widest_int);
286 widest_int get_value () { return m_value; }
287 widest_int get_mask () { return m_mask; }
289 bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
290 enum tree_code, tree);
292 bool meet_with (widest_int, widest_int, unsigned);
294 void print (FILE *);
296 private:
297 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
299 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
300 If a bit in mask is set to 0, then the corresponding bit in
301 value is known to be constant. */
302 widest_int m_value, m_mask;
304 bool meet_with_1 (widest_int, widest_int, unsigned);
305 void get_value_and_mask (tree, widest_int *, widest_int *);
308 /* Lattice of value ranges. */
310 class ipcp_vr_lattice
312 public:
313 value_range m_vr;
315 inline bool bottom_p () const;
316 inline bool top_p () const;
317 inline bool set_to_bottom ();
318 bool meet_with (const value_range *p_vr);
319 bool meet_with (const ipcp_vr_lattice &other);
320 void init () { gcc_assert (m_vr.undefined_p ()); }
321 void print (FILE * f);
323 private:
324 bool meet_with_1 (const value_range *other_vr);
327 /* Structure containing lattices for a parameter itself and for pieces of
328 aggregates that are passed in the parameter or by a reference in a parameter
329 plus some other useful flags. */
331 class ipcp_param_lattices
333 public:
334 /* Lattice describing the value of the parameter itself. */
335 ipcp_lattice<tree> itself;
336 /* Lattice describing the polymorphic contexts of a parameter. */
337 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
338 /* Lattices describing aggregate parts. */
339 ipcp_agg_lattice *aggs;
340 /* Lattice describing known bits. */
341 ipcp_bits_lattice bits_lattice;
342 /* Lattice describing value range. */
343 ipcp_vr_lattice m_value_range;
344 /* Number of aggregate lattices */
345 int aggs_count;
346 /* True if aggregate data were passed by reference (as opposed to by
347 value). */
348 bool aggs_by_ref;
349 /* All aggregate lattices contain a variable component (in addition to
350 values). */
351 bool aggs_contain_variable;
352 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
353 for any propagation). */
354 bool aggs_bottom;
356 /* There is a virtual call based on this parameter. */
357 bool virt_call;
360 /* Allocation pools for values and their sources in ipa-cp. */
362 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
363 ("IPA-CP constant values");
365 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
366 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
368 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
369 ("IPA-CP value sources");
371 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
372 ("IPA_CP aggregate lattices");
374 /* Maximal count found in program. */
376 static profile_count max_count;
378 /* Original overall size of the program. */
380 static long overall_size, orig_overall_size;
382 /* Node name to unique clone suffix number map. */
383 static hash_map<const char *, unsigned> *clone_num_suffixes;
385 /* Return the param lattices structure corresponding to the Ith formal
386 parameter of the function described by INFO. */
387 static inline class ipcp_param_lattices *
388 ipa_get_parm_lattices (class ipa_node_params *info, int i)
390 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
391 gcc_checking_assert (!info->ipcp_orig_node);
392 gcc_checking_assert (info->lattices);
393 return &(info->lattices[i]);
396 /* Return the lattice corresponding to the scalar value of the Ith formal
397 parameter of the function described by INFO. */
398 static inline ipcp_lattice<tree> *
399 ipa_get_scalar_lat (class ipa_node_params *info, int i)
401 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
402 return &plats->itself;
405 /* Return the lattice corresponding to the scalar value of the Ith formal
406 parameter of the function described by INFO. */
407 static inline ipcp_lattice<ipa_polymorphic_call_context> *
408 ipa_get_poly_ctx_lat (class ipa_node_params *info, int i)
410 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
411 return &plats->ctxlat;
414 /* Return whether LAT is a lattice with a single constant and without an
415 undefined value. */
417 template <typename valtype>
418 inline bool
419 ipcp_lattice<valtype>::is_single_const ()
421 if (bottom || contains_variable || values_count != 1)
422 return false;
423 else
424 return true;
427 /* Print V which is extracted from a value in a lattice to F. */
429 static void
430 print_ipcp_constant_value (FILE * f, tree v)
432 if (TREE_CODE (v) == ADDR_EXPR
433 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
435 fprintf (f, "& ");
436 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)));
438 else
439 print_generic_expr (f, v);
442 /* Print V which is extracted from a value in a lattice to F. */
444 static void
445 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
447 v.dump(f, false);
450 /* Print a lattice LAT to F. */
452 template <typename valtype>
453 void
454 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
456 ipcp_value<valtype> *val;
457 bool prev = false;
459 if (bottom)
461 fprintf (f, "BOTTOM\n");
462 return;
465 if (!values_count && !contains_variable)
467 fprintf (f, "TOP\n");
468 return;
471 if (contains_variable)
473 fprintf (f, "VARIABLE");
474 prev = true;
475 if (dump_benefits)
476 fprintf (f, "\n");
479 for (val = values; val; val = val->next)
481 if (dump_benefits && prev)
482 fprintf (f, " ");
483 else if (!dump_benefits && prev)
484 fprintf (f, ", ");
485 else
486 prev = true;
488 print_ipcp_constant_value (f, val->value);
490 if (dump_sources)
492 ipcp_value_source<valtype> *s;
494 fprintf (f, " [from:");
495 for (s = val->sources; s; s = s->next)
496 fprintf (f, " %i(%f)", s->cs->caller->order,
497 s->cs->sreal_frequency ().to_double ());
498 fprintf (f, "]");
501 if (dump_benefits)
502 fprintf (f, " [loc_time: %i, loc_size: %i, "
503 "prop_time: %i, prop_size: %i]\n",
504 val->local_time_benefit, val->local_size_cost,
505 val->prop_time_benefit, val->prop_size_cost);
507 if (!dump_benefits)
508 fprintf (f, "\n");
511 void
512 ipcp_bits_lattice::print (FILE *f)
514 if (top_p ())
515 fprintf (f, " Bits unknown (TOP)\n");
516 else if (bottom_p ())
517 fprintf (f, " Bits unusable (BOTTOM)\n");
518 else
520 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
521 fprintf (f, ", mask = "); print_hex (get_mask (), f);
522 fprintf (f, "\n");
526 /* Print value range lattice to F. */
528 void
529 ipcp_vr_lattice::print (FILE * f)
531 dump_value_range (f, &m_vr);
534 /* Print all ipcp_lattices of all functions to F. */
536 static void
537 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
539 struct cgraph_node *node;
540 int i, count;
542 fprintf (f, "\nLattices:\n");
543 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
545 class ipa_node_params *info;
547 info = IPA_NODE_REF (node);
548 /* Skip unoptimized functions and constprop clones since we don't make
549 lattices for them. */
550 if (!info || info->ipcp_orig_node)
551 continue;
552 fprintf (f, " Node: %s:\n", node->dump_name ());
553 count = ipa_get_param_count (info);
554 for (i = 0; i < count; i++)
556 struct ipcp_agg_lattice *aglat;
557 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
558 fprintf (f, " param [%d]: ", i);
559 plats->itself.print (f, dump_sources, dump_benefits);
560 fprintf (f, " ctxs: ");
561 plats->ctxlat.print (f, dump_sources, dump_benefits);
562 plats->bits_lattice.print (f);
563 fprintf (f, " ");
564 plats->m_value_range.print (f);
565 fprintf (f, "\n");
566 if (plats->virt_call)
567 fprintf (f, " virt_call flag set\n");
569 if (plats->aggs_bottom)
571 fprintf (f, " AGGS BOTTOM\n");
572 continue;
574 if (plats->aggs_contain_variable)
575 fprintf (f, " AGGS VARIABLE\n");
576 for (aglat = plats->aggs; aglat; aglat = aglat->next)
578 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
579 plats->aggs_by_ref ? "ref " : "", aglat->offset);
580 aglat->print (f, dump_sources, dump_benefits);
586 /* Determine whether it is at all technically possible to create clones of NODE
587 and store this information in the ipa_node_params structure associated
588 with NODE. */
590 static void
591 determine_versionability (struct cgraph_node *node,
592 class ipa_node_params *info)
594 const char *reason = NULL;
596 /* There are a number of generic reasons functions cannot be versioned. We
597 also cannot remove parameters if there are type attributes such as fnspec
598 present. */
599 if (node->alias || node->thunk)
600 reason = "alias or thunk";
601 else if (!node->versionable)
602 reason = "not a tree_versionable_function";
603 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
604 reason = "insufficient body availability";
605 else if (!opt_for_fn (node->decl, optimize)
606 || !opt_for_fn (node->decl, flag_ipa_cp))
607 reason = "non-optimized function";
608 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
610 /* Ideally we should clone the SIMD clones themselves and create
611 vector copies of them, so IPA-cp and SIMD clones can happily
612 coexist, but that may not be worth the effort. */
613 reason = "function has SIMD clones";
615 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
617 /* Ideally we should clone the target clones themselves and create
618 copies of them, so IPA-cp and target clones can happily
619 coexist, but that may not be worth the effort. */
620 reason = "function target_clones attribute";
622 /* Don't clone decls local to a comdat group; it breaks and for C++
623 decloned constructors, inlining is always better anyway. */
624 else if (node->comdat_local_p ())
625 reason = "comdat-local function";
626 else if (node->calls_comdat_local)
628 /* TODO: call is versionable if we make sure that all
629 callers are inside of a comdat group. */
630 reason = "calls comdat-local function";
633 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
634 work only when inlined. Cloning them may still lead to better code
635 because ipa-cp will not give up on cloning further. If the function is
636 external this however leads to wrong code because we may end up producing
637 offline copy of the function. */
638 if (DECL_EXTERNAL (node->decl))
639 for (cgraph_edge *edge = node->callees; !reason && edge;
640 edge = edge->next_callee)
641 if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL))
643 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
644 reason = "external function which calls va_arg_pack";
645 if (DECL_FUNCTION_CODE (edge->callee->decl)
646 == BUILT_IN_VA_ARG_PACK_LEN)
647 reason = "external function which calls va_arg_pack_len";
650 if (reason && dump_file && !node->alias && !node->thunk)
651 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
652 node->dump_name (), reason);
654 info->versionable = (reason == NULL);
657 /* Return true if it is at all technically possible to create clones of a
658 NODE. */
660 static bool
661 ipcp_versionable_function_p (struct cgraph_node *node)
663 return IPA_NODE_REF (node) && IPA_NODE_REF (node)->versionable;
666 /* Structure holding accumulated information about callers of a node. */
668 struct caller_statistics
670 profile_count count_sum;
671 int n_calls, n_hot_calls, freq_sum;
674 /* Initialize fields of STAT to zeroes. */
676 static inline void
677 init_caller_stats (struct caller_statistics *stats)
679 stats->count_sum = profile_count::zero ();
680 stats->n_calls = 0;
681 stats->n_hot_calls = 0;
682 stats->freq_sum = 0;
685 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
686 non-thunk incoming edges to NODE. */
688 static bool
689 gather_caller_stats (struct cgraph_node *node, void *data)
691 struct caller_statistics *stats = (struct caller_statistics *) data;
692 struct cgraph_edge *cs;
694 for (cs = node->callers; cs; cs = cs->next_caller)
695 if (!cs->caller->thunk)
697 if (cs->count.ipa ().initialized_p ())
698 stats->count_sum += cs->count.ipa ();
699 stats->freq_sum += cs->frequency ();
700 stats->n_calls++;
701 if (cs->maybe_hot_p ())
702 stats->n_hot_calls ++;
704 return false;
708 /* Return true if this NODE is viable candidate for cloning. */
710 static bool
711 ipcp_cloning_candidate_p (struct cgraph_node *node)
713 struct caller_statistics stats;
715 gcc_checking_assert (node->has_gimple_body_p ());
717 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
719 if (dump_file)
720 fprintf (dump_file, "Not considering %s for cloning; "
721 "-fipa-cp-clone disabled.\n",
722 node->dump_name ());
723 return false;
726 if (node->optimize_for_size_p ())
728 if (dump_file)
729 fprintf (dump_file, "Not considering %s for cloning; "
730 "optimizing it for size.\n",
731 node->dump_name ());
732 return false;
735 init_caller_stats (&stats);
736 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
738 if (ipa_size_summaries->get (node)->self_size < stats.n_calls)
740 if (dump_file)
741 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
742 node->dump_name ());
743 return true;
746 /* When profile is available and function is hot, propagate into it even if
747 calls seems cold; constant propagation can improve function's speed
748 significantly. */
749 if (max_count > profile_count::zero ())
751 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100))
753 if (dump_file)
754 fprintf (dump_file, "Considering %s for cloning; "
755 "usually called directly.\n",
756 node->dump_name ());
757 return true;
760 if (!stats.n_hot_calls)
762 if (dump_file)
763 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
764 node->dump_name ());
765 return false;
767 if (dump_file)
768 fprintf (dump_file, "Considering %s for cloning.\n",
769 node->dump_name ());
770 return true;
773 template <typename valtype>
774 class value_topo_info
776 public:
777 /* Head of the linked list of topologically sorted values. */
778 ipcp_value<valtype> *values_topo;
779 /* Stack for creating SCCs, represented by a linked list too. */
780 ipcp_value<valtype> *stack;
781 /* Counter driving the algorithm in add_val_to_toposort. */
782 int dfs_counter;
784 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
786 void add_val (ipcp_value<valtype> *cur_val);
787 void propagate_effects ();
790 /* Arrays representing a topological ordering of call graph nodes and a stack
791 of nodes used during constant propagation and also data required to perform
792 topological sort of values and propagation of benefits in the determined
793 order. */
795 class ipa_topo_info
797 public:
798 /* Array with obtained topological order of cgraph nodes. */
799 struct cgraph_node **order;
800 /* Stack of cgraph nodes used during propagation within SCC until all values
801 in the SCC stabilize. */
802 struct cgraph_node **stack;
803 int nnodes, stack_top;
805 value_topo_info<tree> constants;
806 value_topo_info<ipa_polymorphic_call_context> contexts;
808 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
809 constants ()
813 /* Skip edges from and to nodes without ipa_cp enabled.
814 Ignore not available symbols. */
816 static bool
817 ignore_edge_p (cgraph_edge *e)
819 enum availability avail;
820 cgraph_node *ultimate_target
821 = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
823 return (avail <= AVAIL_INTERPOSABLE
824 || !opt_for_fn (ultimate_target->decl, optimize)
825 || !opt_for_fn (ultimate_target->decl, flag_ipa_cp));
828 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
830 static void
831 build_toporder_info (class ipa_topo_info *topo)
833 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
834 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
836 gcc_checking_assert (topo->stack_top == 0);
837 topo->nnodes = ipa_reduced_postorder (topo->order, true,
838 ignore_edge_p);
841 /* Free information about strongly connected components and the arrays in
842 TOPO. */
844 static void
845 free_toporder_info (class ipa_topo_info *topo)
847 ipa_free_postorder_info ();
848 free (topo->order);
849 free (topo->stack);
852 /* Add NODE to the stack in TOPO, unless it is already there. */
854 static inline void
855 push_node_to_stack (class ipa_topo_info *topo, struct cgraph_node *node)
857 class ipa_node_params *info = IPA_NODE_REF (node);
858 if (info->node_enqueued)
859 return;
860 info->node_enqueued = 1;
861 topo->stack[topo->stack_top++] = node;
864 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
865 is empty. */
867 static struct cgraph_node *
868 pop_node_from_stack (class ipa_topo_info *topo)
870 if (topo->stack_top)
872 struct cgraph_node *node;
873 topo->stack_top--;
874 node = topo->stack[topo->stack_top];
875 IPA_NODE_REF (node)->node_enqueued = 0;
876 return node;
878 else
879 return NULL;
882 /* Set lattice LAT to bottom and return true if it previously was not set as
883 such. */
885 template <typename valtype>
886 inline bool
887 ipcp_lattice<valtype>::set_to_bottom ()
889 bool ret = !bottom;
890 bottom = true;
891 return ret;
894 /* Mark lattice as containing an unknown value and return true if it previously
895 was not marked as such. */
897 template <typename valtype>
898 inline bool
899 ipcp_lattice<valtype>::set_contains_variable ()
901 bool ret = !contains_variable;
902 contains_variable = true;
903 return ret;
906 /* Set all aggregate lattices in PLATS to bottom and return true if they were
907 not previously set as such. */
909 static inline bool
910 set_agg_lats_to_bottom (class ipcp_param_lattices *plats)
912 bool ret = !plats->aggs_bottom;
913 plats->aggs_bottom = true;
914 return ret;
917 /* Mark all aggregate lattices in PLATS as containing an unknown value and
918 return true if they were not previously marked as such. */
920 static inline bool
921 set_agg_lats_contain_variable (class ipcp_param_lattices *plats)
923 bool ret = !plats->aggs_contain_variable;
924 plats->aggs_contain_variable = true;
925 return ret;
928 bool
929 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
931 return meet_with_1 (&other.m_vr);
934 /* Meet the current value of the lattice with value range described by VR
935 lattice. */
937 bool
938 ipcp_vr_lattice::meet_with (const value_range *p_vr)
940 return meet_with_1 (p_vr);
943 /* Meet the current value of the lattice with value range described by
944 OTHER_VR lattice. Return TRUE if anything changed. */
946 bool
947 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
949 if (bottom_p ())
950 return false;
952 if (other_vr->varying_p ())
953 return set_to_bottom ();
955 value_range save (m_vr);
956 m_vr.union_ (other_vr);
957 return !m_vr.equal_p (save);
960 /* Return true if value range information in the lattice is yet unknown. */
962 bool
963 ipcp_vr_lattice::top_p () const
965 return m_vr.undefined_p ();
968 /* Return true if value range information in the lattice is known to be
969 unusable. */
971 bool
972 ipcp_vr_lattice::bottom_p () const
974 return m_vr.varying_p ();
977 /* Set value range information in the lattice to bottom. Return true if it
978 previously was in a different state. */
980 bool
981 ipcp_vr_lattice::set_to_bottom ()
983 if (m_vr.varying_p ())
984 return false;
985 /* ?? We create all sorts of VARYING ranges for floats, structures,
986 and other types which we cannot handle as ranges. We should
987 probably avoid handling them throughout the pass, but it's easier
988 to create a sensible VARYING here and let the lattice
989 propagate. */
990 m_vr.set_varying (integer_type_node);
991 return true;
994 /* Set lattice value to bottom, if it already isn't the case. */
996 bool
997 ipcp_bits_lattice::set_to_bottom ()
999 if (bottom_p ())
1000 return false;
1001 m_lattice_val = IPA_BITS_VARYING;
1002 m_value = 0;
1003 m_mask = -1;
1004 return true;
1007 /* Set to constant if it isn't already. Only meant to be called
1008 when switching state from TOP. */
1010 bool
1011 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
1013 gcc_assert (top_p ());
1014 m_lattice_val = IPA_BITS_CONSTANT;
1015 m_value = wi::bit_and (wi::bit_not (mask), value);
1016 m_mask = mask;
1017 return true;
1020 /* Convert operand to value, mask form. */
1022 void
1023 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
1025 wide_int get_nonzero_bits (const_tree);
1027 if (TREE_CODE (operand) == INTEGER_CST)
1029 *valuep = wi::to_widest (operand);
1030 *maskp = 0;
1032 else
1034 *valuep = 0;
1035 *maskp = -1;
1039 /* Meet operation, similar to ccp_lattice_meet, we xor values
1040 if this->value, value have different values at same bit positions, we want
1041 to drop that bit to varying. Return true if mask is changed.
1042 This function assumes that the lattice value is in CONSTANT state */
1044 bool
1045 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
1046 unsigned precision)
1048 gcc_assert (constant_p ());
1050 widest_int old_mask = m_mask;
1051 m_mask = (m_mask | mask) | (m_value ^ value);
1052 m_value &= ~m_mask;
1054 if (wi::sext (m_mask, precision) == -1)
1055 return set_to_bottom ();
1057 return m_mask != old_mask;
1060 /* Meet the bits lattice with operand
1061 described by <value, mask, sgn, precision. */
1063 bool
1064 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1065 unsigned precision)
1067 if (bottom_p ())
1068 return false;
1070 if (top_p ())
1072 if (wi::sext (mask, precision) == -1)
1073 return set_to_bottom ();
1074 return set_to_constant (value, mask);
1077 return meet_with_1 (value, mask, precision);
1080 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1081 if code is binary operation or bit_value_unop (other) if code is unary op.
1082 In the case when code is nop_expr, no adjustment is required. */
1084 bool
1085 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1086 signop sgn, enum tree_code code, tree operand)
1088 if (other.bottom_p ())
1089 return set_to_bottom ();
1091 if (bottom_p () || other.top_p ())
1092 return false;
1094 widest_int adjusted_value, adjusted_mask;
1096 if (TREE_CODE_CLASS (code) == tcc_binary)
1098 tree type = TREE_TYPE (operand);
1099 widest_int o_value, o_mask;
1100 get_value_and_mask (operand, &o_value, &o_mask);
1102 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1103 sgn, precision, other.get_value (), other.get_mask (),
1104 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1106 if (wi::sext (adjusted_mask, precision) == -1)
1107 return set_to_bottom ();
1110 else if (TREE_CODE_CLASS (code) == tcc_unary)
1112 bit_value_unop (code, sgn, precision, &adjusted_value,
1113 &adjusted_mask, sgn, precision, other.get_value (),
1114 other.get_mask ());
1116 if (wi::sext (adjusted_mask, precision) == -1)
1117 return set_to_bottom ();
1120 else
1121 return set_to_bottom ();
1123 if (top_p ())
1125 if (wi::sext (adjusted_mask, precision) == -1)
1126 return set_to_bottom ();
1127 return set_to_constant (adjusted_value, adjusted_mask);
1129 else
1130 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1133 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1134 return true is any of them has not been marked as such so far. */
1136 static inline bool
1137 set_all_contains_variable (class ipcp_param_lattices *plats)
1139 bool ret;
1140 ret = plats->itself.set_contains_variable ();
1141 ret |= plats->ctxlat.set_contains_variable ();
1142 ret |= set_agg_lats_contain_variable (plats);
1143 ret |= plats->bits_lattice.set_to_bottom ();
1144 ret |= plats->m_value_range.set_to_bottom ();
1145 return ret;
1148 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1149 points to by the number of callers to NODE. */
1151 static bool
1152 count_callers (cgraph_node *node, void *data)
1154 int *caller_count = (int *) data;
1156 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1157 /* Local thunks can be handled transparently, but if the thunk cannot
1158 be optimized out, count it as a real use. */
1159 if (!cs->caller->thunk || !cs->caller->local)
1160 ++*caller_count;
1161 return false;
1164 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1165 the one caller of some other node. Set the caller's corresponding flag. */
1167 static bool
1168 set_single_call_flag (cgraph_node *node, void *)
1170 cgraph_edge *cs = node->callers;
1171 /* Local thunks can be handled transparently, skip them. */
1172 while (cs && cs->caller->thunk && cs->caller->local)
1173 cs = cs->next_caller;
1174 if (cs && IPA_NODE_REF (cs->caller))
1176 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1177 return true;
1179 return false;
1182 /* Initialize ipcp_lattices. */
1184 static void
1185 initialize_node_lattices (struct cgraph_node *node)
1187 class ipa_node_params *info = IPA_NODE_REF (node);
1188 struct cgraph_edge *ie;
1189 bool disable = false, variable = false;
1190 int i;
1192 gcc_checking_assert (node->has_gimple_body_p ());
1194 if (!ipa_get_param_count (info))
1195 disable = true;
1196 else if (node->local)
1198 int caller_count = 0;
1199 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1200 true);
1201 gcc_checking_assert (caller_count > 0);
1202 if (caller_count == 1)
1203 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1204 NULL, true);
1206 else
1208 /* When cloning is allowed, we can assume that externally visible
1209 functions are not called. We will compensate this by cloning
1210 later. */
1211 if (ipcp_versionable_function_p (node)
1212 && ipcp_cloning_candidate_p (node))
1213 variable = true;
1214 else
1215 disable = true;
1218 if (dump_file && (dump_flags & TDF_DETAILS)
1219 && !node->alias && !node->thunk)
1221 fprintf (dump_file, "Initializing lattices of %s\n",
1222 node->dump_name ());
1223 if (disable || variable)
1224 fprintf (dump_file, " Marking all lattices as %s\n",
1225 disable ? "BOTTOM" : "VARIABLE");
1228 auto_vec<bool, 16> surviving_params;
1229 bool pre_modified = false;
1231 clone_info *cinfo = clone_info::get (node);
1233 if (!disable && cinfo && cinfo->param_adjustments)
1235 /* At the moment all IPA optimizations should use the number of
1236 parameters of the prevailing decl as the m_always_copy_start.
1237 Handling any other value would complicate the code below, so for the
1238 time bing let's only assert it is so. */
1239 gcc_assert ((cinfo->param_adjustments->m_always_copy_start
1240 == ipa_get_param_count (info))
1241 || cinfo->param_adjustments->m_always_copy_start < 0);
1243 pre_modified = true;
1244 cinfo->param_adjustments->get_surviving_params (&surviving_params);
1246 if (dump_file && (dump_flags & TDF_DETAILS)
1247 && !node->alias && !node->thunk)
1249 bool first = true;
1250 for (int j = 0; j < ipa_get_param_count (info); j++)
1252 if (j < (int) surviving_params.length ()
1253 && surviving_params[j])
1254 continue;
1255 if (first)
1257 fprintf (dump_file,
1258 " The following parameters are dead on arrival:");
1259 first = false;
1261 fprintf (dump_file, " %u", j);
1263 if (!first)
1264 fprintf (dump_file, "\n");
1268 for (i = 0; i < ipa_get_param_count (info); i++)
1270 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1271 if (disable
1272 || (pre_modified && (surviving_params.length () <= (unsigned) i
1273 || !surviving_params[i])))
1275 plats->itself.set_to_bottom ();
1276 plats->ctxlat.set_to_bottom ();
1277 set_agg_lats_to_bottom (plats);
1278 plats->bits_lattice.set_to_bottom ();
1279 plats->m_value_range.m_vr = value_range ();
1280 plats->m_value_range.set_to_bottom ();
1282 else
1284 plats->m_value_range.init ();
1285 if (variable)
1286 set_all_contains_variable (plats);
1290 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1291 if (ie->indirect_info->polymorphic
1292 && ie->indirect_info->param_index >= 0)
1294 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1295 ipa_get_parm_lattices (info,
1296 ie->indirect_info->param_index)->virt_call = 1;
1300 /* Return the result of a (possibly arithmetic) operation on the constant
1301 value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is
1302 the type of the parameter to which the result is passed. Return
1303 NULL_TREE if that cannot be determined or be considered an
1304 interprocedural invariant. */
1306 static tree
1307 ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand,
1308 tree res_type)
1310 tree res;
1312 if (opcode == NOP_EXPR)
1313 return input;
1314 if (!is_gimple_ip_invariant (input))
1315 return NULL_TREE;
1317 if (!res_type)
1319 if (TREE_CODE_CLASS (opcode) == tcc_comparison)
1320 res_type = boolean_type_node;
1321 else if (expr_type_first_operand_type_p (opcode))
1322 res_type = TREE_TYPE (input);
1323 else
1324 return NULL_TREE;
1327 if (TREE_CODE_CLASS (opcode) == tcc_unary)
1328 res = fold_unary (opcode, res_type, input);
1329 else
1330 res = fold_binary (opcode, res_type, input, operand);
1332 if (res && !is_gimple_ip_invariant (res))
1333 return NULL_TREE;
1335 return res;
1338 /* Return the result of a (possibly arithmetic) pass through jump function
1339 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter
1340 to which the result is passed. Return NULL_TREE if that cannot be
1341 determined or be considered an interprocedural invariant. */
1343 static tree
1344 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input,
1345 tree res_type)
1347 return ipa_get_jf_arith_result (ipa_get_jf_pass_through_operation (jfunc),
1348 input,
1349 ipa_get_jf_pass_through_operand (jfunc),
1350 res_type);
1353 /* Return the result of an ancestor jump function JFUNC on the constant value
1354 INPUT. Return NULL_TREE if that cannot be determined. */
1356 static tree
1357 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1359 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1360 if (TREE_CODE (input) == ADDR_EXPR)
1362 gcc_checking_assert (is_gimple_ip_invariant_address (input));
1363 poly_int64 off = ipa_get_jf_ancestor_offset (jfunc);
1364 if (known_eq (off, 0))
1365 return input;
1366 poly_int64 byte_offset = exact_div (off, BITS_PER_UNIT);
1367 return build1 (ADDR_EXPR, TREE_TYPE (input),
1368 fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (input)), input,
1369 build_int_cst (ptr_type_node, byte_offset)));
1371 else
1372 return NULL_TREE;
1375 /* Determine whether JFUNC evaluates to a single known constant value and if
1376 so, return it. Otherwise return NULL. INFO describes the caller node or
1377 the one it is inlined to, so that pass-through jump functions can be
1378 evaluated. PARM_TYPE is the type of the parameter to which the result is
1379 passed. */
1381 tree
1382 ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc,
1383 tree parm_type)
1385 if (jfunc->type == IPA_JF_CONST)
1386 return ipa_get_jf_constant (jfunc);
1387 else if (jfunc->type == IPA_JF_PASS_THROUGH
1388 || jfunc->type == IPA_JF_ANCESTOR)
1390 tree input;
1391 int idx;
1393 if (jfunc->type == IPA_JF_PASS_THROUGH)
1394 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1395 else
1396 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1398 if (info->ipcp_orig_node)
1399 input = info->known_csts[idx];
1400 else
1402 ipcp_lattice<tree> *lat;
1404 if (!info->lattices
1405 || idx >= ipa_get_param_count (info))
1406 return NULL_TREE;
1407 lat = ipa_get_scalar_lat (info, idx);
1408 if (!lat->is_single_const ())
1409 return NULL_TREE;
1410 input = lat->values->value;
1413 if (!input)
1414 return NULL_TREE;
1416 if (jfunc->type == IPA_JF_PASS_THROUGH)
1417 return ipa_get_jf_pass_through_result (jfunc, input, parm_type);
1418 else
1419 return ipa_get_jf_ancestor_result (jfunc, input);
1421 else
1422 return NULL_TREE;
1425 /* Determine whether JFUNC evaluates to single known polymorphic context, given
1426 that INFO describes the caller node or the one it is inlined to, CS is the
1427 call graph edge corresponding to JFUNC and CSIDX index of the described
1428 parameter. */
1430 ipa_polymorphic_call_context
1431 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1432 ipa_jump_func *jfunc)
1434 ipa_edge_args *args = IPA_EDGE_REF (cs);
1435 ipa_polymorphic_call_context ctx;
1436 ipa_polymorphic_call_context *edge_ctx
1437 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1439 if (edge_ctx && !edge_ctx->useless_p ())
1440 ctx = *edge_ctx;
1442 if (jfunc->type == IPA_JF_PASS_THROUGH
1443 || jfunc->type == IPA_JF_ANCESTOR)
1445 ipa_polymorphic_call_context srcctx;
1446 int srcidx;
1447 bool type_preserved = true;
1448 if (jfunc->type == IPA_JF_PASS_THROUGH)
1450 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1451 return ctx;
1452 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1453 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1455 else
1457 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1458 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1460 if (info->ipcp_orig_node)
1462 if (info->known_contexts.exists ())
1463 srcctx = info->known_contexts[srcidx];
1465 else
1467 if (!info->lattices
1468 || srcidx >= ipa_get_param_count (info))
1469 return ctx;
1470 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1471 lat = ipa_get_poly_ctx_lat (info, srcidx);
1472 if (!lat->is_single_const ())
1473 return ctx;
1474 srcctx = lat->values->value;
1476 if (srcctx.useless_p ())
1477 return ctx;
1478 if (jfunc->type == IPA_JF_ANCESTOR)
1479 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1480 if (!type_preserved)
1481 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1482 srcctx.combine_with (ctx);
1483 return srcctx;
1486 return ctx;
1489 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1490 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1491 the result is a range or an anti-range. */
1493 static bool
1494 ipa_vr_operation_and_type_effects (value_range *dst_vr,
1495 value_range *src_vr,
1496 enum tree_code operation,
1497 tree dst_type, tree src_type)
1499 range_fold_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
1500 if (dst_vr->varying_p () || dst_vr->undefined_p ())
1501 return false;
1502 return true;
1505 /* Determine value_range of JFUNC given that INFO describes the caller node or
1506 the one it is inlined to, CS is the call graph edge corresponding to JFUNC
1507 and PARM_TYPE of the parameter. */
1509 value_range
1510 ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs,
1511 ipa_jump_func *jfunc, tree parm_type)
1513 value_range vr;
1514 return vr;
1515 if (jfunc->m_vr)
1516 ipa_vr_operation_and_type_effects (&vr,
1517 jfunc->m_vr,
1518 NOP_EXPR, parm_type,
1519 jfunc->m_vr->type ());
1520 if (vr.singleton_p ())
1521 return vr;
1522 if (jfunc->type == IPA_JF_PASS_THROUGH)
1524 int idx;
1525 ipcp_transformation *sum
1526 = ipcp_get_transformation_summary (cs->caller->inlined_to
1527 ? cs->caller->inlined_to
1528 : cs->caller);
1529 if (!sum || !sum->m_vr)
1530 return vr;
1532 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1534 if (!(*sum->m_vr)[idx].known)
1535 return vr;
1536 tree vr_type = ipa_get_type (info, idx);
1537 value_range srcvr (wide_int_to_tree (vr_type, (*sum->m_vr)[idx].min),
1538 wide_int_to_tree (vr_type, (*sum->m_vr)[idx].max),
1539 (*sum->m_vr)[idx].type);
1541 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1543 if (TREE_CODE_CLASS (operation) == tcc_unary)
1545 value_range res;
1547 if (ipa_vr_operation_and_type_effects (&res,
1548 &srcvr,
1549 operation, parm_type,
1550 vr_type))
1551 vr.intersect (res);
1553 else
1555 value_range op_res, res;
1556 tree op = ipa_get_jf_pass_through_operand (jfunc);
1557 value_range op_vr (op, op);
1559 range_fold_binary_expr (&op_res, operation, vr_type, &srcvr, &op_vr);
1560 if (ipa_vr_operation_and_type_effects (&res,
1561 &op_res,
1562 NOP_EXPR, parm_type,
1563 vr_type))
1564 vr.intersect (res);
1567 return vr;
1570 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
1571 parameter with the given INDEX. */
1573 static tree
1574 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
1575 int index)
1577 struct ipa_agg_replacement_value *aggval;
1579 aggval = ipa_get_agg_replacements_for_node (node);
1580 while (aggval)
1582 if (aggval->offset == offset
1583 && aggval->index == index)
1584 return aggval->value;
1585 aggval = aggval->next;
1587 return NULL_TREE;
1590 /* Determine whether ITEM, jump function for an aggregate part, evaluates to a
1591 single known constant value and if so, return it. Otherwise return NULL.
1592 NODE and INFO describes the caller node or the one it is inlined to, and
1593 its related info. */
1595 static tree
1596 ipa_agg_value_from_node (class ipa_node_params *info,
1597 struct cgraph_node *node,
1598 struct ipa_agg_jf_item *item)
1600 tree value = NULL_TREE;
1601 int src_idx;
1603 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN)
1604 return NULL_TREE;
1606 if (item->jftype == IPA_JF_CONST)
1607 return item->value.constant;
1609 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
1610 || item->jftype == IPA_JF_LOAD_AGG);
1612 src_idx = item->value.pass_through.formal_id;
1614 if (info->ipcp_orig_node)
1616 if (item->jftype == IPA_JF_PASS_THROUGH)
1617 value = info->known_csts[src_idx];
1618 else
1619 value = get_clone_agg_value (node, item->value.load_agg.offset,
1620 src_idx);
1622 else if (info->lattices)
1624 class ipcp_param_lattices *src_plats
1625 = ipa_get_parm_lattices (info, src_idx);
1627 if (item->jftype == IPA_JF_PASS_THROUGH)
1629 struct ipcp_lattice<tree> *lat = &src_plats->itself;
1631 if (!lat->is_single_const ())
1632 return NULL_TREE;
1634 value = lat->values->value;
1636 else if (src_plats->aggs
1637 && !src_plats->aggs_bottom
1638 && !src_plats->aggs_contain_variable
1639 && src_plats->aggs_by_ref == item->value.load_agg.by_ref)
1641 struct ipcp_agg_lattice *aglat;
1643 for (aglat = src_plats->aggs; aglat; aglat = aglat->next)
1645 if (aglat->offset > item->value.load_agg.offset)
1646 break;
1648 if (aglat->offset == item->value.load_agg.offset)
1650 if (aglat->is_single_const ())
1651 value = aglat->values->value;
1652 break;
1658 if (!value)
1659 return NULL_TREE;
1661 if (item->jftype == IPA_JF_LOAD_AGG)
1663 tree load_type = item->value.load_agg.type;
1664 tree value_type = TREE_TYPE (value);
1666 /* Ensure value type is compatible with load type. */
1667 if (!useless_type_conversion_p (load_type, value_type))
1668 return NULL_TREE;
1671 return ipa_get_jf_arith_result (item->value.pass_through.operation,
1672 value,
1673 item->value.pass_through.operand,
1674 item->type);
1677 /* Determine whether AGG_JFUNC evaluates to a set of known constant value for
1678 an aggregate and if so, return it. Otherwise return an empty set. NODE
1679 and INFO describes the caller node or the one it is inlined to, and its
1680 related info. */
1682 struct ipa_agg_value_set
1683 ipa_agg_value_set_from_jfunc (class ipa_node_params *info, cgraph_node *node,
1684 struct ipa_agg_jump_function *agg_jfunc)
1686 struct ipa_agg_value_set agg;
1687 struct ipa_agg_jf_item *item;
1688 int i;
1690 agg.items = vNULL;
1691 agg.by_ref = agg_jfunc->by_ref;
1693 FOR_EACH_VEC_SAFE_ELT (agg_jfunc->items, i, item)
1695 tree value = ipa_agg_value_from_node (info, node, item);
1697 if (value)
1699 struct ipa_agg_value value_item;
1701 value_item.offset = item->offset;
1702 value_item.value = value;
1704 agg.items.safe_push (value_item);
1707 return agg;
1710 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1711 bottom, not containing a variable component and without any known value at
1712 the same time. */
1714 DEBUG_FUNCTION void
1715 ipcp_verify_propagated_values (void)
1717 struct cgraph_node *node;
1719 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1721 class ipa_node_params *info = IPA_NODE_REF (node);
1722 if (!opt_for_fn (node->decl, flag_ipa_cp)
1723 || !opt_for_fn (node->decl, optimize))
1724 continue;
1725 int i, count = ipa_get_param_count (info);
1727 for (i = 0; i < count; i++)
1729 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1731 if (!lat->bottom
1732 && !lat->contains_variable
1733 && lat->values_count == 0)
1735 if (dump_file)
1737 symtab->dump (dump_file);
1738 fprintf (dump_file, "\nIPA lattices after constant "
1739 "propagation, before gcc_unreachable:\n");
1740 print_all_lattices (dump_file, true, false);
1743 gcc_unreachable ();
1749 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1751 static bool
1752 values_equal_for_ipcp_p (tree x, tree y)
1754 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1756 if (x == y)
1757 return true;
1759 if (TREE_CODE (x) == ADDR_EXPR
1760 && TREE_CODE (y) == ADDR_EXPR
1761 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1762 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1763 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1764 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1765 else
1766 return operand_equal_p (x, y, 0);
1769 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1771 static bool
1772 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1773 ipa_polymorphic_call_context y)
1775 return x.equal_to (y);
1779 /* Add a new value source to the value represented by THIS, marking that a
1780 value comes from edge CS and (if the underlying jump function is a
1781 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1782 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1783 scalar value of the parameter itself or the offset within an aggregate. */
1785 template <typename valtype>
1786 void
1787 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1788 int src_idx, HOST_WIDE_INT offset)
1790 ipcp_value_source<valtype> *src;
1792 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1793 src->offset = offset;
1794 src->cs = cs;
1795 src->val = src_val;
1796 src->index = src_idx;
1798 src->next = sources;
1799 sources = src;
1802 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1803 SOURCE and clear all other fields. */
1805 static ipcp_value<tree> *
1806 allocate_and_init_ipcp_value (tree source)
1808 ipcp_value<tree> *val;
1810 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1811 val->value = source;
1812 return val;
1815 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1816 value to SOURCE and clear all other fields. */
1818 static ipcp_value<ipa_polymorphic_call_context> *
1819 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1821 ipcp_value<ipa_polymorphic_call_context> *val;
1823 // TODO
1824 val = new (ipcp_poly_ctx_values_pool.allocate ())
1825 ipcp_value<ipa_polymorphic_call_context>();
1826 val->value = source;
1827 return val;
1830 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1831 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1832 meaning. OFFSET -1 means the source is scalar and not a part of an
1833 aggregate. If non-NULL, VAL_P records address of existing or newly added
1834 ipcp_value. UNLIMITED means whether value count should not exceed the limit
1835 given by PARAM_IPA_CP_VALUE_LIST_SIZE. */
1837 template <typename valtype>
1838 bool
1839 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1840 ipcp_value<valtype> *src_val,
1841 int src_idx, HOST_WIDE_INT offset,
1842 ipcp_value<valtype> **val_p,
1843 bool unlimited)
1845 ipcp_value<valtype> *val, *last_val = NULL;
1847 if (val_p)
1848 *val_p = NULL;
1850 if (bottom)
1851 return false;
1853 for (val = values; val; last_val = val, val = val->next)
1854 if (values_equal_for_ipcp_p (val->value, newval))
1856 if (val_p)
1857 *val_p = val;
1859 if (ipa_edge_within_scc (cs))
1861 ipcp_value_source<valtype> *s;
1862 for (s = val->sources; s; s = s->next)
1863 if (s->cs == cs && s->val == src_val)
1864 break;
1865 if (s)
1866 return false;
1869 val->add_source (cs, src_val, src_idx, offset);
1870 return false;
1873 if (!unlimited && values_count == opt_for_fn (cs->caller->decl,
1874 param_ipa_cp_value_list_size))
1876 /* We can only free sources, not the values themselves, because sources
1877 of other values in this SCC might point to them. */
1878 for (val = values; val; val = val->next)
1880 while (val->sources)
1882 ipcp_value_source<valtype> *src = val->sources;
1883 val->sources = src->next;
1884 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1887 values = NULL;
1888 return set_to_bottom ();
1891 values_count++;
1892 val = allocate_and_init_ipcp_value (newval);
1893 val->add_source (cs, src_val, src_idx, offset);
1894 val->next = NULL;
1896 /* Add the new value to end of value list, which can reduce iterations
1897 of propagation stage for recursive function. */
1898 if (last_val)
1899 last_val->next = val;
1900 else
1901 values = val;
1903 if (val_p)
1904 *val_p = val;
1906 return true;
1909 /* Return true, if a ipcp_value VAL is orginated from parameter value of
1910 self-feeding recursive function via some kind of pass-through jump
1911 function. */
1913 static bool
1914 self_recursively_generated_p (ipcp_value<tree> *val)
1916 class ipa_node_params *info = NULL;
1918 for (ipcp_value_source<tree> *src = val->sources; src; src = src->next)
1920 cgraph_edge *cs = src->cs;
1922 if (!src->val || cs->caller != cs->callee->function_symbol ())
1923 return false;
1925 if (src->val == val)
1926 continue;
1928 if (!info)
1929 info = IPA_NODE_REF (cs->caller);
1931 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info,
1932 src->index);
1933 ipcp_lattice<tree> *src_lat;
1934 ipcp_value<tree> *src_val;
1936 if (src->offset == -1)
1937 src_lat = &plats->itself;
1938 else
1940 struct ipcp_agg_lattice *src_aglat;
1942 for (src_aglat = plats->aggs; src_aglat; src_aglat = src_aglat->next)
1943 if (src_aglat->offset == src->offset)
1944 break;
1946 if (!src_aglat)
1947 return false;
1949 src_lat = src_aglat;
1952 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1953 if (src_val == val)
1954 break;
1956 if (!src_val)
1957 return false;
1960 return true;
1963 /* A helper function that returns result of operation specified by OPCODE on
1964 the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the
1965 value of SRC_VAL. If the operation is binary, OPND2 is a constant value
1966 acting as its second operand. If non-NULL, RES_TYPE is expected type of
1967 the result. */
1969 static tree
1970 get_val_across_arith_op (enum tree_code opcode,
1971 tree opnd1_type,
1972 tree opnd2,
1973 ipcp_value<tree> *src_val,
1974 tree res_type)
1976 tree opnd1 = src_val->value;
1978 /* Skip source values that is incompatible with specified type. */
1979 if (opnd1_type
1980 && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1)))
1981 return NULL_TREE;
1983 return ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type);
1986 /* Propagate values through an arithmetic transformation described by a jump
1987 function associated with edge CS, taking values from SRC_LAT and putting
1988 them into DEST_LAT. OPND1_TYPE is expected type for the values in SRC_LAT.
1989 OPND2 is a constant value if transformation is a binary operation.
1990 SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice of
1991 a part of the aggregate. SRC_IDX is the index of the source parameter.
1992 RES_TYPE is the value type of result being propagated into. Return true if
1993 DEST_LAT changed. */
1995 static bool
1996 propagate_vals_across_arith_jfunc (cgraph_edge *cs,
1997 enum tree_code opcode,
1998 tree opnd1_type,
1999 tree opnd2,
2000 ipcp_lattice<tree> *src_lat,
2001 ipcp_lattice<tree> *dest_lat,
2002 HOST_WIDE_INT src_offset,
2003 int src_idx,
2004 tree res_type)
2006 ipcp_value<tree> *src_val;
2007 bool ret = false;
2009 /* Due to circular dependencies, propagating within an SCC through arithmetic
2010 transformation would create infinite number of values. But for
2011 self-feeding recursive function, we could allow propagation in a limited
2012 count, and this can enable a simple kind of recursive function versioning.
2013 For other scenario, we would just make lattices bottom. */
2014 if (opcode != NOP_EXPR && ipa_edge_within_scc (cs))
2016 int i;
2018 int max_recursive_depth = opt_for_fn(cs->caller->decl,
2019 param_ipa_cp_max_recursive_depth);
2020 if (src_lat != dest_lat || max_recursive_depth < 1)
2021 return dest_lat->set_contains_variable ();
2023 /* No benefit if recursive execution is in low probability. */
2024 if (cs->sreal_frequency () * 100
2025 <= ((sreal) 1) * opt_for_fn (cs->caller->decl,
2026 param_ipa_cp_min_recursive_probability))
2027 return dest_lat->set_contains_variable ();
2029 auto_vec<ipcp_value<tree> *, 8> val_seeds;
2031 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2033 /* Now we do not use self-recursively generated value as propagation
2034 source, this is absolutely conservative, but could avoid explosion
2035 of lattice's value space, especially when one recursive function
2036 calls another recursive. */
2037 if (self_recursively_generated_p (src_val))
2039 ipcp_value_source<tree> *s;
2041 /* If the lattice has already been propagated for the call site,
2042 no need to do that again. */
2043 for (s = src_val->sources; s; s = s->next)
2044 if (s->cs == cs)
2045 return dest_lat->set_contains_variable ();
2047 else
2048 val_seeds.safe_push (src_val);
2051 gcc_assert ((int) val_seeds.length () <= param_ipa_cp_value_list_size);
2053 /* Recursively generate lattice values with a limited count. */
2054 FOR_EACH_VEC_ELT (val_seeds, i, src_val)
2056 for (int j = 1; j < max_recursive_depth; j++)
2058 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2059 src_val, res_type);
2060 if (!cstval)
2061 break;
2063 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2064 src_offset, &src_val, true);
2065 gcc_checking_assert (src_val);
2068 ret |= dest_lat->set_contains_variable ();
2070 else
2071 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2073 /* Now we do not use self-recursively generated value as propagation
2074 source, otherwise it is easy to make value space of normal lattice
2075 overflow. */
2076 if (self_recursively_generated_p (src_val))
2078 ret |= dest_lat->set_contains_variable ();
2079 continue;
2082 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2083 src_val, res_type);
2084 if (cstval)
2085 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2086 src_offset);
2087 else
2088 ret |= dest_lat->set_contains_variable ();
2091 return ret;
2094 /* Propagate values through a pass-through jump function JFUNC associated with
2095 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2096 is the index of the source parameter. PARM_TYPE is the type of the
2097 parameter to which the result is passed. */
2099 static bool
2100 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
2101 ipcp_lattice<tree> *src_lat,
2102 ipcp_lattice<tree> *dest_lat, int src_idx,
2103 tree parm_type)
2105 return propagate_vals_across_arith_jfunc (cs,
2106 ipa_get_jf_pass_through_operation (jfunc),
2107 NULL_TREE,
2108 ipa_get_jf_pass_through_operand (jfunc),
2109 src_lat, dest_lat, -1, src_idx, parm_type);
2112 /* Propagate values through an ancestor jump function JFUNC associated with
2113 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2114 is the index of the source parameter. */
2116 static bool
2117 propagate_vals_across_ancestor (struct cgraph_edge *cs,
2118 struct ipa_jump_func *jfunc,
2119 ipcp_lattice<tree> *src_lat,
2120 ipcp_lattice<tree> *dest_lat, int src_idx)
2122 ipcp_value<tree> *src_val;
2123 bool ret = false;
2125 if (ipa_edge_within_scc (cs))
2126 return dest_lat->set_contains_variable ();
2128 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2130 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
2132 if (t)
2133 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
2134 else
2135 ret |= dest_lat->set_contains_variable ();
2138 return ret;
2141 /* Propagate scalar values across jump function JFUNC that is associated with
2142 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the
2143 parameter to which the result is passed. */
2145 static bool
2146 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
2147 struct ipa_jump_func *jfunc,
2148 ipcp_lattice<tree> *dest_lat,
2149 tree param_type)
2151 if (dest_lat->bottom)
2152 return false;
2154 if (jfunc->type == IPA_JF_CONST)
2156 tree val = ipa_get_jf_constant (jfunc);
2157 return dest_lat->add_value (val, cs, NULL, 0);
2159 else if (jfunc->type == IPA_JF_PASS_THROUGH
2160 || jfunc->type == IPA_JF_ANCESTOR)
2162 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2163 ipcp_lattice<tree> *src_lat;
2164 int src_idx;
2165 bool ret;
2167 if (jfunc->type == IPA_JF_PASS_THROUGH)
2168 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2169 else
2170 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2172 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
2173 if (src_lat->bottom)
2174 return dest_lat->set_contains_variable ();
2176 /* If we would need to clone the caller and cannot, do not propagate. */
2177 if (!ipcp_versionable_function_p (cs->caller)
2178 && (src_lat->contains_variable
2179 || (src_lat->values_count > 1)))
2180 return dest_lat->set_contains_variable ();
2182 if (jfunc->type == IPA_JF_PASS_THROUGH)
2183 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
2184 dest_lat, src_idx, param_type);
2185 else
2186 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
2187 src_idx);
2189 if (src_lat->contains_variable)
2190 ret |= dest_lat->set_contains_variable ();
2192 return ret;
2195 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
2196 use it for indirect inlining), we should propagate them too. */
2197 return dest_lat->set_contains_variable ();
2200 /* Propagate scalar values across jump function JFUNC that is associated with
2201 edge CS and describes argument IDX and put the values into DEST_LAT. */
2203 static bool
2204 propagate_context_across_jump_function (cgraph_edge *cs,
2205 ipa_jump_func *jfunc, int idx,
2206 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
2208 ipa_edge_args *args = IPA_EDGE_REF (cs);
2209 if (dest_lat->bottom)
2210 return false;
2211 bool ret = false;
2212 bool added_sth = false;
2213 bool type_preserved = true;
2215 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
2216 = ipa_get_ith_polymorhic_call_context (args, idx);
2218 if (edge_ctx_ptr)
2219 edge_ctx = *edge_ctx_ptr;
2221 if (jfunc->type == IPA_JF_PASS_THROUGH
2222 || jfunc->type == IPA_JF_ANCESTOR)
2224 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2225 int src_idx;
2226 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
2228 /* TODO: Once we figure out how to propagate speculations, it will
2229 probably be a good idea to switch to speculation if type_preserved is
2230 not set instead of punting. */
2231 if (jfunc->type == IPA_JF_PASS_THROUGH)
2233 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
2234 goto prop_fail;
2235 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
2236 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2238 else
2240 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
2241 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2244 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
2245 /* If we would need to clone the caller and cannot, do not propagate. */
2246 if (!ipcp_versionable_function_p (cs->caller)
2247 && (src_lat->contains_variable
2248 || (src_lat->values_count > 1)))
2249 goto prop_fail;
2251 ipcp_value<ipa_polymorphic_call_context> *src_val;
2252 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2254 ipa_polymorphic_call_context cur = src_val->value;
2256 if (!type_preserved)
2257 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
2258 if (jfunc->type == IPA_JF_ANCESTOR)
2259 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
2260 /* TODO: In cases we know how the context is going to be used,
2261 we can improve the result by passing proper OTR_TYPE. */
2262 cur.combine_with (edge_ctx);
2263 if (!cur.useless_p ())
2265 if (src_lat->contains_variable
2266 && !edge_ctx.equal_to (cur))
2267 ret |= dest_lat->set_contains_variable ();
2268 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
2269 added_sth = true;
2274 prop_fail:
2275 if (!added_sth)
2277 if (!edge_ctx.useless_p ())
2278 ret |= dest_lat->add_value (edge_ctx, cs);
2279 else
2280 ret |= dest_lat->set_contains_variable ();
2283 return ret;
2286 /* Propagate bits across jfunc that is associated with
2287 edge cs and update dest_lattice accordingly. */
2289 bool
2290 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
2291 ipa_jump_func *jfunc,
2292 ipcp_bits_lattice *dest_lattice)
2294 if (dest_lattice->bottom_p ())
2295 return false;
2297 enum availability availability;
2298 cgraph_node *callee = cs->callee->function_symbol (&availability);
2299 class ipa_node_params *callee_info = IPA_NODE_REF (callee);
2300 tree parm_type = ipa_get_type (callee_info, idx);
2302 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the
2303 transform for these cases. Similarly, we can have bad type mismatches
2304 with LTO, avoid doing anything with those too. */
2305 if (!parm_type
2306 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type)))
2308 if (dump_file && (dump_flags & TDF_DETAILS))
2309 fprintf (dump_file, "Setting dest_lattice to bottom, because type of "
2310 "param %i of %s is NULL or unsuitable for bits propagation\n",
2311 idx, cs->callee->dump_name ());
2313 return dest_lattice->set_to_bottom ();
2316 unsigned precision = TYPE_PRECISION (parm_type);
2317 signop sgn = TYPE_SIGN (parm_type);
2319 if (jfunc->type == IPA_JF_PASS_THROUGH
2320 || jfunc->type == IPA_JF_ANCESTOR)
2322 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2323 tree operand = NULL_TREE;
2324 enum tree_code code;
2325 unsigned src_idx;
2327 if (jfunc->type == IPA_JF_PASS_THROUGH)
2329 code = ipa_get_jf_pass_through_operation (jfunc);
2330 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2331 if (code != NOP_EXPR)
2332 operand = ipa_get_jf_pass_through_operand (jfunc);
2334 else
2336 code = POINTER_PLUS_EXPR;
2337 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2338 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
2339 operand = build_int_cstu (size_type_node, offset);
2342 class ipcp_param_lattices *src_lats
2343 = ipa_get_parm_lattices (caller_info, src_idx);
2345 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
2346 for eg consider:
2347 int f(int x)
2349 g (x & 0xff);
2351 Assume lattice for x is bottom, however we can still propagate
2352 result of x & 0xff == 0xff, which gets computed during ccp1 pass
2353 and we store it in jump function during analysis stage. */
2355 if (src_lats->bits_lattice.bottom_p ()
2356 && jfunc->bits)
2357 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
2358 precision);
2359 else
2360 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
2361 code, operand);
2364 else if (jfunc->type == IPA_JF_ANCESTOR)
2365 return dest_lattice->set_to_bottom ();
2366 else if (jfunc->bits)
2367 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
2368 precision);
2369 else
2370 return dest_lattice->set_to_bottom ();
2373 /* Propagate value range across jump function JFUNC that is associated with
2374 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
2375 accordingly. */
2377 static bool
2378 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
2379 class ipcp_param_lattices *dest_plats,
2380 tree param_type)
2382 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
2384 if (dest_lat->bottom_p ())
2385 return false;
2387 if (!param_type
2388 || (!INTEGRAL_TYPE_P (param_type)
2389 && !POINTER_TYPE_P (param_type)))
2390 return dest_lat->set_to_bottom ();
2392 if (jfunc->type == IPA_JF_PASS_THROUGH)
2394 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
2395 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2396 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2397 class ipcp_param_lattices *src_lats
2398 = ipa_get_parm_lattices (caller_info, src_idx);
2399 tree operand_type = ipa_get_type (caller_info, src_idx);
2401 if (src_lats->m_value_range.bottom_p ())
2402 return dest_lat->set_to_bottom ();
2404 value_range vr;
2405 if (TREE_CODE_CLASS (operation) == tcc_unary)
2406 ipa_vr_operation_and_type_effects (&vr,
2407 &src_lats->m_value_range.m_vr,
2408 operation, param_type,
2409 operand_type);
2410 /* A crude way to prevent unbounded number of value range updates
2411 in SCC components. We should allow limited number of updates within
2412 SCC, too. */
2413 else if (!ipa_edge_within_scc (cs))
2415 tree op = ipa_get_jf_pass_through_operand (jfunc);
2416 value_range op_vr (op, op);
2417 value_range op_res,res;
2419 range_fold_binary_expr (&op_res, operation, operand_type,
2420 &src_lats->m_value_range.m_vr, &op_vr);
2421 ipa_vr_operation_and_type_effects (&vr,
2422 &op_res,
2423 NOP_EXPR, param_type,
2424 operand_type);
2426 if (!vr.undefined_p () && !vr.varying_p ())
2428 if (jfunc->m_vr)
2430 value_range jvr;
2431 if (ipa_vr_operation_and_type_effects (&jvr, jfunc->m_vr,
2432 NOP_EXPR,
2433 param_type,
2434 jfunc->m_vr->type ()))
2435 vr.intersect (jvr);
2437 return dest_lat->meet_with (&vr);
2440 else if (jfunc->type == IPA_JF_CONST)
2442 tree val = ipa_get_jf_constant (jfunc);
2443 if (TREE_CODE (val) == INTEGER_CST)
2445 val = fold_convert (param_type, val);
2446 if (TREE_OVERFLOW_P (val))
2447 val = drop_tree_overflow (val);
2449 value_range tmpvr (val, val);
2450 return dest_lat->meet_with (&tmpvr);
2454 value_range vr;
2455 if (jfunc->m_vr
2456 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
2457 param_type,
2458 jfunc->m_vr->type ()))
2459 return dest_lat->meet_with (&vr);
2460 else
2461 return dest_lat->set_to_bottom ();
2464 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
2465 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
2466 other cases, return false). If there are no aggregate items, set
2467 aggs_by_ref to NEW_AGGS_BY_REF. */
2469 static bool
2470 set_check_aggs_by_ref (class ipcp_param_lattices *dest_plats,
2471 bool new_aggs_by_ref)
2473 if (dest_plats->aggs)
2475 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
2477 set_agg_lats_to_bottom (dest_plats);
2478 return true;
2481 else
2482 dest_plats->aggs_by_ref = new_aggs_by_ref;
2483 return false;
2486 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
2487 already existing lattice for the given OFFSET and SIZE, marking all skipped
2488 lattices as containing variable and checking for overlaps. If there is no
2489 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
2490 it with offset, size and contains_variable to PRE_EXISTING, and return true,
2491 unless there are too many already. If there are two many, return false. If
2492 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
2493 skipped lattices were newly marked as containing variable, set *CHANGE to
2494 true. MAX_AGG_ITEMS is the maximum number of lattices. */
2496 static bool
2497 merge_agg_lats_step (class ipcp_param_lattices *dest_plats,
2498 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
2499 struct ipcp_agg_lattice ***aglat,
2500 bool pre_existing, bool *change, int max_agg_items)
2502 gcc_checking_assert (offset >= 0);
2504 while (**aglat && (**aglat)->offset < offset)
2506 if ((**aglat)->offset + (**aglat)->size > offset)
2508 set_agg_lats_to_bottom (dest_plats);
2509 return false;
2511 *change |= (**aglat)->set_contains_variable ();
2512 *aglat = &(**aglat)->next;
2515 if (**aglat && (**aglat)->offset == offset)
2517 if ((**aglat)->size != val_size)
2519 set_agg_lats_to_bottom (dest_plats);
2520 return false;
2522 gcc_assert (!(**aglat)->next
2523 || (**aglat)->next->offset >= offset + val_size);
2524 return true;
2526 else
2528 struct ipcp_agg_lattice *new_al;
2530 if (**aglat && (**aglat)->offset < offset + val_size)
2532 set_agg_lats_to_bottom (dest_plats);
2533 return false;
2535 if (dest_plats->aggs_count == max_agg_items)
2536 return false;
2537 dest_plats->aggs_count++;
2538 new_al = ipcp_agg_lattice_pool.allocate ();
2539 memset (new_al, 0, sizeof (*new_al));
2541 new_al->offset = offset;
2542 new_al->size = val_size;
2543 new_al->contains_variable = pre_existing;
2545 new_al->next = **aglat;
2546 **aglat = new_al;
2547 return true;
2551 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2552 containing an unknown value. */
2554 static bool
2555 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2557 bool ret = false;
2558 while (aglat)
2560 ret |= aglat->set_contains_variable ();
2561 aglat = aglat->next;
2563 return ret;
2566 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2567 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2568 parameter used for lattice value sources. Return true if DEST_PLATS changed
2569 in any way. */
2571 static bool
2572 merge_aggregate_lattices (struct cgraph_edge *cs,
2573 class ipcp_param_lattices *dest_plats,
2574 class ipcp_param_lattices *src_plats,
2575 int src_idx, HOST_WIDE_INT offset_delta)
2577 bool pre_existing = dest_plats->aggs != NULL;
2578 struct ipcp_agg_lattice **dst_aglat;
2579 bool ret = false;
2581 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2582 return true;
2583 if (src_plats->aggs_bottom)
2584 return set_agg_lats_contain_variable (dest_plats);
2585 if (src_plats->aggs_contain_variable)
2586 ret |= set_agg_lats_contain_variable (dest_plats);
2587 dst_aglat = &dest_plats->aggs;
2589 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2590 param_ipa_max_agg_items);
2591 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2592 src_aglat;
2593 src_aglat = src_aglat->next)
2595 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2597 if (new_offset < 0)
2598 continue;
2599 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2600 &dst_aglat, pre_existing, &ret, max_agg_items))
2602 struct ipcp_agg_lattice *new_al = *dst_aglat;
2604 dst_aglat = &(*dst_aglat)->next;
2605 if (src_aglat->bottom)
2607 ret |= new_al->set_contains_variable ();
2608 continue;
2610 if (src_aglat->contains_variable)
2611 ret |= new_al->set_contains_variable ();
2612 for (ipcp_value<tree> *val = src_aglat->values;
2613 val;
2614 val = val->next)
2615 ret |= new_al->add_value (val->value, cs, val, src_idx,
2616 src_aglat->offset);
2618 else if (dest_plats->aggs_bottom)
2619 return true;
2621 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2622 return ret;
2625 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2626 pass-through JFUNC and if so, whether it has conform and conforms to the
2627 rules about propagating values passed by reference. */
2629 static bool
2630 agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats,
2631 struct ipa_jump_func *jfunc)
2633 return src_plats->aggs
2634 && (!src_plats->aggs_by_ref
2635 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2638 /* Propagate values through ITEM, jump function for a part of an aggregate,
2639 into corresponding aggregate lattice AGLAT. CS is the call graph edge
2640 associated with the jump function. Return true if AGLAT changed in any
2641 way. */
2643 static bool
2644 propagate_aggregate_lattice (struct cgraph_edge *cs,
2645 struct ipa_agg_jf_item *item,
2646 struct ipcp_agg_lattice *aglat)
2648 class ipa_node_params *caller_info;
2649 class ipcp_param_lattices *src_plats;
2650 struct ipcp_lattice<tree> *src_lat;
2651 HOST_WIDE_INT src_offset;
2652 int src_idx;
2653 tree load_type;
2654 bool ret;
2656 if (item->jftype == IPA_JF_CONST)
2658 tree value = item->value.constant;
2660 gcc_checking_assert (is_gimple_ip_invariant (value));
2661 return aglat->add_value (value, cs, NULL, 0);
2664 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
2665 || item->jftype == IPA_JF_LOAD_AGG);
2667 caller_info = IPA_NODE_REF (cs->caller);
2668 src_idx = item->value.pass_through.formal_id;
2669 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2671 if (item->jftype == IPA_JF_PASS_THROUGH)
2673 load_type = NULL_TREE;
2674 src_lat = &src_plats->itself;
2675 src_offset = -1;
2677 else
2679 HOST_WIDE_INT load_offset = item->value.load_agg.offset;
2680 struct ipcp_agg_lattice *src_aglat;
2682 for (src_aglat = src_plats->aggs; src_aglat; src_aglat = src_aglat->next)
2683 if (src_aglat->offset >= load_offset)
2684 break;
2686 load_type = item->value.load_agg.type;
2687 if (!src_aglat
2688 || src_aglat->offset > load_offset
2689 || src_aglat->size != tree_to_shwi (TYPE_SIZE (load_type))
2690 || src_plats->aggs_by_ref != item->value.load_agg.by_ref)
2691 return aglat->set_contains_variable ();
2693 src_lat = src_aglat;
2694 src_offset = load_offset;
2697 if (src_lat->bottom
2698 || (!ipcp_versionable_function_p (cs->caller)
2699 && !src_lat->is_single_const ()))
2700 return aglat->set_contains_variable ();
2702 ret = propagate_vals_across_arith_jfunc (cs,
2703 item->value.pass_through.operation,
2704 load_type,
2705 item->value.pass_through.operand,
2706 src_lat, aglat,
2707 src_offset,
2708 src_idx,
2709 item->type);
2711 if (src_lat->contains_variable)
2712 ret |= aglat->set_contains_variable ();
2714 return ret;
2717 /* Propagate scalar values across jump function JFUNC that is associated with
2718 edge CS and put the values into DEST_LAT. */
2720 static bool
2721 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2722 struct ipa_jump_func *jfunc,
2723 class ipcp_param_lattices *dest_plats)
2725 bool ret = false;
2727 if (dest_plats->aggs_bottom)
2728 return false;
2730 if (jfunc->type == IPA_JF_PASS_THROUGH
2731 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2733 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2734 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2735 class ipcp_param_lattices *src_plats;
2737 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2738 if (agg_pass_through_permissible_p (src_plats, jfunc))
2740 /* Currently we do not produce clobber aggregate jump
2741 functions, replace with merging when we do. */
2742 gcc_assert (!jfunc->agg.items);
2743 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2744 src_idx, 0);
2745 return ret;
2748 else if (jfunc->type == IPA_JF_ANCESTOR
2749 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2751 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2752 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2753 class ipcp_param_lattices *src_plats;
2755 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2756 if (src_plats->aggs && src_plats->aggs_by_ref)
2758 /* Currently we do not produce clobber aggregate jump
2759 functions, replace with merging when we do. */
2760 gcc_assert (!jfunc->agg.items);
2761 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2762 ipa_get_jf_ancestor_offset (jfunc));
2764 else if (!src_plats->aggs_by_ref)
2765 ret |= set_agg_lats_to_bottom (dest_plats);
2766 else
2767 ret |= set_agg_lats_contain_variable (dest_plats);
2768 return ret;
2771 if (jfunc->agg.items)
2773 bool pre_existing = dest_plats->aggs != NULL;
2774 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2775 struct ipa_agg_jf_item *item;
2776 int i;
2778 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2779 return true;
2781 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2782 param_ipa_max_agg_items);
2783 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2785 HOST_WIDE_INT val_size;
2787 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN)
2788 continue;
2789 val_size = tree_to_shwi (TYPE_SIZE (item->type));
2791 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2792 &aglat, pre_existing, &ret, max_agg_items))
2794 ret |= propagate_aggregate_lattice (cs, item, *aglat);
2795 aglat = &(*aglat)->next;
2797 else if (dest_plats->aggs_bottom)
2798 return true;
2801 ret |= set_chain_of_aglats_contains_variable (*aglat);
2803 else
2804 ret |= set_agg_lats_contain_variable (dest_plats);
2806 return ret;
2809 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2810 non-thunk) destination, the call passes through a thunk. */
2812 static bool
2813 call_passes_through_thunk (cgraph_edge *cs)
2815 cgraph_node *alias_or_thunk = cs->callee;
2816 while (alias_or_thunk->alias)
2817 alias_or_thunk = alias_or_thunk->get_alias_target ();
2818 return alias_or_thunk->thunk;
2821 /* Propagate constants from the caller to the callee of CS. INFO describes the
2822 caller. */
2824 static bool
2825 propagate_constants_across_call (struct cgraph_edge *cs)
2827 class ipa_node_params *callee_info;
2828 enum availability availability;
2829 cgraph_node *callee;
2830 class ipa_edge_args *args;
2831 bool ret = false;
2832 int i, args_count, parms_count;
2834 callee = cs->callee->function_symbol (&availability);
2835 if (!callee->definition)
2836 return false;
2837 gcc_checking_assert (callee->has_gimple_body_p ());
2838 callee_info = IPA_NODE_REF (callee);
2839 if (!callee_info)
2840 return false;
2842 args = IPA_EDGE_REF (cs);
2843 parms_count = ipa_get_param_count (callee_info);
2844 if (parms_count == 0)
2845 return false;
2846 if (!args
2847 || !opt_for_fn (cs->caller->decl, flag_ipa_cp)
2848 || !opt_for_fn (cs->caller->decl, optimize))
2850 for (i = 0; i < parms_count; i++)
2851 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2852 i));
2853 return ret;
2855 args_count = ipa_get_cs_argument_count (args);
2857 /* If this call goes through a thunk we must not propagate to the first (0th)
2858 parameter. However, we might need to uncover a thunk from below a series
2859 of aliases first. */
2860 if (call_passes_through_thunk (cs))
2862 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2863 0));
2864 i = 1;
2866 else
2867 i = 0;
2869 for (; (i < args_count) && (i < parms_count); i++)
2871 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2872 class ipcp_param_lattices *dest_plats;
2873 tree param_type = ipa_get_type (callee_info, i);
2875 dest_plats = ipa_get_parm_lattices (callee_info, i);
2876 if (availability == AVAIL_INTERPOSABLE)
2877 ret |= set_all_contains_variable (dest_plats);
2878 else
2880 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2881 &dest_plats->itself,
2882 param_type);
2883 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2884 &dest_plats->ctxlat);
2886 |= propagate_bits_across_jump_function (cs, i, jump_func,
2887 &dest_plats->bits_lattice);
2888 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2889 dest_plats);
2890 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2891 ret |= propagate_vr_across_jump_function (cs, jump_func,
2892 dest_plats, param_type);
2893 else
2894 ret |= dest_plats->m_value_range.set_to_bottom ();
2897 for (; i < parms_count; i++)
2898 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2900 return ret;
2903 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2904 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2905 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2907 static tree
2908 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2909 vec<tree> known_csts,
2910 vec<ipa_polymorphic_call_context> known_contexts,
2911 vec<ipa_agg_value_set> known_aggs,
2912 struct ipa_agg_replacement_value *agg_reps,
2913 bool *speculative)
2915 int param_index = ie->indirect_info->param_index;
2916 HOST_WIDE_INT anc_offset;
2917 tree t = NULL;
2918 tree target = NULL;
2920 *speculative = false;
2922 if (param_index == -1)
2923 return NULL_TREE;
2925 if (!ie->indirect_info->polymorphic)
2927 tree t = NULL;
2929 if (ie->indirect_info->agg_contents)
2931 t = NULL;
2932 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2934 while (agg_reps)
2936 if (agg_reps->index == param_index
2937 && agg_reps->offset == ie->indirect_info->offset
2938 && agg_reps->by_ref == ie->indirect_info->by_ref)
2940 t = agg_reps->value;
2941 break;
2943 agg_reps = agg_reps->next;
2946 if (!t)
2948 struct ipa_agg_value_set *agg;
2949 if (known_aggs.length () > (unsigned int) param_index)
2950 agg = &known_aggs[param_index];
2951 else
2952 agg = NULL;
2953 bool from_global_constant;
2954 t = ipa_find_agg_cst_for_param (agg,
2955 (unsigned) param_index
2956 < known_csts.length ()
2957 ? known_csts[param_index]
2958 : NULL,
2959 ie->indirect_info->offset,
2960 ie->indirect_info->by_ref,
2961 &from_global_constant);
2962 if (t
2963 && !from_global_constant
2964 && !ie->indirect_info->guaranteed_unmodified)
2965 t = NULL_TREE;
2968 else if ((unsigned) param_index < known_csts.length ())
2969 t = known_csts[param_index];
2971 if (t
2972 && TREE_CODE (t) == ADDR_EXPR
2973 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2974 return TREE_OPERAND (t, 0);
2975 else
2976 return NULL_TREE;
2979 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2980 return NULL_TREE;
2982 gcc_assert (!ie->indirect_info->agg_contents);
2983 anc_offset = ie->indirect_info->offset;
2985 t = NULL;
2987 /* Try to work out value of virtual table pointer value in replacements. */
2988 if (!t && agg_reps && !ie->indirect_info->by_ref)
2990 while (agg_reps)
2992 if (agg_reps->index == param_index
2993 && agg_reps->offset == ie->indirect_info->offset
2994 && agg_reps->by_ref)
2996 t = agg_reps->value;
2997 break;
2999 agg_reps = agg_reps->next;
3003 /* Try to work out value of virtual table pointer value in known
3004 aggregate values. */
3005 if (!t && known_aggs.length () > (unsigned int) param_index
3006 && !ie->indirect_info->by_ref)
3008 struct ipa_agg_value_set *agg = &known_aggs[param_index];
3009 t = ipa_find_agg_cst_for_param (agg,
3010 (unsigned) param_index
3011 < known_csts.length ()
3012 ? known_csts[param_index] : NULL,
3013 ie->indirect_info->offset, true);
3016 /* If we found the virtual table pointer, lookup the target. */
3017 if (t)
3019 tree vtable;
3020 unsigned HOST_WIDE_INT offset;
3021 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
3023 bool can_refer;
3024 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
3025 vtable, offset, &can_refer);
3026 if (can_refer)
3028 if (!target
3029 || fndecl_built_in_p (target, BUILT_IN_UNREACHABLE)
3030 || !possible_polymorphic_call_target_p
3031 (ie, cgraph_node::get (target)))
3033 /* Do not speculate builtin_unreachable, it is stupid! */
3034 if (ie->indirect_info->vptr_changed)
3035 return NULL;
3036 target = ipa_impossible_devirt_target (ie, target);
3038 *speculative = ie->indirect_info->vptr_changed;
3039 if (!*speculative)
3040 return target;
3045 /* Do we know the constant value of pointer? */
3046 if (!t && (unsigned) param_index < known_csts.length ())
3047 t = known_csts[param_index];
3049 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
3051 ipa_polymorphic_call_context context;
3052 if (known_contexts.length () > (unsigned int) param_index)
3054 context = known_contexts[param_index];
3055 context.offset_by (anc_offset);
3056 if (ie->indirect_info->vptr_changed)
3057 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
3058 ie->indirect_info->otr_type);
3059 if (t)
3061 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
3062 (t, ie->indirect_info->otr_type, anc_offset);
3063 if (!ctx2.useless_p ())
3064 context.combine_with (ctx2, ie->indirect_info->otr_type);
3067 else if (t)
3069 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
3070 anc_offset);
3071 if (ie->indirect_info->vptr_changed)
3072 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
3073 ie->indirect_info->otr_type);
3075 else
3076 return NULL_TREE;
3078 vec <cgraph_node *>targets;
3079 bool final;
3081 targets = possible_polymorphic_call_targets
3082 (ie->indirect_info->otr_type,
3083 ie->indirect_info->otr_token,
3084 context, &final);
3085 if (!final || targets.length () > 1)
3087 struct cgraph_node *node;
3088 if (*speculative)
3089 return target;
3090 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
3091 || ie->speculative || !ie->maybe_hot_p ())
3092 return NULL;
3093 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
3094 ie->indirect_info->otr_token,
3095 context);
3096 if (node)
3098 *speculative = true;
3099 target = node->decl;
3101 else
3102 return NULL;
3104 else
3106 *speculative = false;
3107 if (targets.length () == 1)
3108 target = targets[0]->decl;
3109 else
3110 target = ipa_impossible_devirt_target (ie, NULL_TREE);
3113 if (target && !possible_polymorphic_call_target_p (ie,
3114 cgraph_node::get (target)))
3116 if (*speculative)
3117 return NULL;
3118 target = ipa_impossible_devirt_target (ie, target);
3121 return target;
3124 /* If an indirect edge IE can be turned into a direct one based on data in
3125 AVALS, return the destination. Store into *SPECULATIVE a boolean determinig
3126 whether the discovered target is only speculative guess. */
3128 tree
3129 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
3130 ipa_call_arg_values *avals,
3131 bool *speculative)
3133 return ipa_get_indirect_edge_target_1 (ie, avals->m_known_vals,
3134 avals->m_known_contexts,
3135 avals->m_known_aggs,
3136 NULL, speculative);
3139 /* The same functionality as above overloaded for ipa_auto_call_arg_values. */
3141 tree
3142 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
3143 ipa_auto_call_arg_values *avals,
3144 bool *speculative)
3146 return ipa_get_indirect_edge_target_1 (ie, avals->m_known_vals,
3147 avals->m_known_contexts,
3148 avals->m_known_aggs,
3149 NULL, speculative);
3152 /* Calculate devirtualization time bonus for NODE, assuming we know information
3153 about arguments stored in AVALS. */
3155 static int
3156 devirtualization_time_bonus (struct cgraph_node *node,
3157 ipa_auto_call_arg_values *avals)
3159 struct cgraph_edge *ie;
3160 int res = 0;
3162 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
3164 struct cgraph_node *callee;
3165 class ipa_fn_summary *isummary;
3166 enum availability avail;
3167 tree target;
3168 bool speculative;
3170 target = ipa_get_indirect_edge_target (ie, avals, &speculative);
3171 if (!target)
3172 continue;
3174 /* Only bare minimum benefit for clearly un-inlineable targets. */
3175 res += 1;
3176 callee = cgraph_node::get (target);
3177 if (!callee || !callee->definition)
3178 continue;
3179 callee = callee->function_symbol (&avail);
3180 if (avail < AVAIL_AVAILABLE)
3181 continue;
3182 isummary = ipa_fn_summaries->get (callee);
3183 if (!isummary || !isummary->inlinable)
3184 continue;
3186 int size = ipa_size_summaries->get (callee)->size;
3187 /* FIXME: The values below need re-considering and perhaps also
3188 integrating into the cost metrics, at lest in some very basic way. */
3189 int max_inline_insns_auto
3190 = opt_for_fn (callee->decl, param_max_inline_insns_auto);
3191 if (size <= max_inline_insns_auto / 4)
3192 res += 31 / ((int)speculative + 1);
3193 else if (size <= max_inline_insns_auto / 2)
3194 res += 15 / ((int)speculative + 1);
3195 else if (size <= max_inline_insns_auto
3196 || DECL_DECLARED_INLINE_P (callee->decl))
3197 res += 7 / ((int)speculative + 1);
3200 return res;
3203 /* Return time bonus incurred because of hints stored in ESTIMATES. */
3205 static int
3206 hint_time_bonus (cgraph_node *node, const ipa_call_estimates &estimates)
3208 int result = 0;
3209 ipa_hints hints = estimates.hints;
3210 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
3211 result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
3213 sreal bonus_for_one = opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
3215 if (hints & INLINE_HINT_loop_iterations)
3216 result += (estimates.loops_with_known_iterations * bonus_for_one).to_int ();
3218 if (hints & INLINE_HINT_loop_stride)
3219 result += (estimates.loops_with_known_strides * bonus_for_one).to_int ();
3221 return result;
3224 /* If there is a reason to penalize the function described by INFO in the
3225 cloning goodness evaluation, do so. */
3227 static inline int64_t
3228 incorporate_penalties (cgraph_node *node, ipa_node_params *info,
3229 int64_t evaluation)
3231 if (info->node_within_scc && !info->node_is_self_scc)
3232 evaluation = (evaluation
3233 * (100 - opt_for_fn (node->decl,
3234 param_ipa_cp_recursion_penalty))) / 100;
3236 if (info->node_calling_single_call)
3237 evaluation = (evaluation
3238 * (100 - opt_for_fn (node->decl,
3239 param_ipa_cp_single_call_penalty)))
3240 / 100;
3242 return evaluation;
3245 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
3246 and SIZE_COST and with the sum of frequencies of incoming edges to the
3247 potential new clone in FREQUENCIES. */
3249 static bool
3250 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
3251 int freq_sum, profile_count count_sum, int size_cost)
3253 if (time_benefit == 0
3254 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
3255 || node->optimize_for_size_p ())
3256 return false;
3258 gcc_assert (size_cost > 0);
3260 class ipa_node_params *info = IPA_NODE_REF (node);
3261 int eval_threshold = opt_for_fn (node->decl, param_ipa_cp_eval_threshold);
3262 if (max_count > profile_count::zero ())
3264 int factor = RDIV (count_sum.probability_in
3265 (max_count).to_reg_br_prob_base ()
3266 * 1000, REG_BR_PROB_BASE);
3267 int64_t evaluation = (((int64_t) time_benefit * factor)
3268 / size_cost);
3269 evaluation = incorporate_penalties (node, info, evaluation);
3271 if (dump_file && (dump_flags & TDF_DETAILS))
3273 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
3274 "size: %i, count_sum: ", time_benefit, size_cost);
3275 count_sum.dump (dump_file);
3276 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
3277 ", threshold: %i\n",
3278 info->node_within_scc
3279 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3280 info->node_calling_single_call ? ", single_call" : "",
3281 evaluation, eval_threshold);
3284 return evaluation >= eval_threshold;
3286 else
3288 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
3289 / size_cost);
3290 evaluation = incorporate_penalties (node, info, evaluation);
3292 if (dump_file && (dump_flags & TDF_DETAILS))
3293 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
3294 "size: %i, freq_sum: %i%s%s) -> evaluation: "
3295 "%" PRId64 ", threshold: %i\n",
3296 time_benefit, size_cost, freq_sum,
3297 info->node_within_scc
3298 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3299 info->node_calling_single_call ? ", single_call" : "",
3300 evaluation, eval_threshold);
3302 return evaluation >= eval_threshold;
3306 /* Return all context independent values from aggregate lattices in PLATS in a
3307 vector. Return NULL if there are none. */
3309 static vec<ipa_agg_value>
3310 context_independent_aggregate_values (class ipcp_param_lattices *plats)
3312 vec<ipa_agg_value> res = vNULL;
3314 if (plats->aggs_bottom
3315 || plats->aggs_contain_variable
3316 || plats->aggs_count == 0)
3317 return vNULL;
3319 for (struct ipcp_agg_lattice *aglat = plats->aggs;
3320 aglat;
3321 aglat = aglat->next)
3322 if (aglat->is_single_const ())
3324 struct ipa_agg_value item;
3325 item.offset = aglat->offset;
3326 item.value = aglat->values->value;
3327 res.safe_push (item);
3329 return res;
3332 /* Grow vectors in AVALS and fill them with information about values of
3333 parameters that are known to be independent of the context. Only calculate
3334 m_known_aggs if CALCULATE_AGGS is true. INFO describes the function. If
3335 REMOVABLE_PARAMS_COST is non-NULL, the movement cost of all removable
3336 parameters will be stored in it.
3338 TODO: Also grow context independent value range vectors. */
3340 static bool
3341 gather_context_independent_values (class ipa_node_params *info,
3342 ipa_auto_call_arg_values *avals,
3343 bool calculate_aggs,
3344 int *removable_params_cost)
3346 int i, count = ipa_get_param_count (info);
3347 bool ret = false;
3349 avals->m_known_vals.safe_grow_cleared (count, true);
3350 avals->m_known_contexts.safe_grow_cleared (count, true);
3351 if (calculate_aggs)
3352 avals->m_known_aggs.safe_grow_cleared (count, true);
3354 if (removable_params_cost)
3355 *removable_params_cost = 0;
3357 for (i = 0; i < count; i++)
3359 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3360 ipcp_lattice<tree> *lat = &plats->itself;
3362 if (lat->is_single_const ())
3364 ipcp_value<tree> *val = lat->values;
3365 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3366 avals->m_known_vals[i] = val->value;
3367 if (removable_params_cost)
3368 *removable_params_cost
3369 += estimate_move_cost (TREE_TYPE (val->value), false);
3370 ret = true;
3372 else if (removable_params_cost
3373 && !ipa_is_param_used (info, i))
3374 *removable_params_cost
3375 += ipa_get_param_move_cost (info, i);
3377 if (!ipa_is_param_used (info, i))
3378 continue;
3380 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3381 /* Do not account known context as reason for cloning. We can see
3382 if it permits devirtualization. */
3383 if (ctxlat->is_single_const ())
3384 avals->m_known_contexts[i] = ctxlat->values->value;
3386 if (calculate_aggs)
3388 vec<ipa_agg_value> agg_items;
3389 struct ipa_agg_value_set *agg;
3391 agg_items = context_independent_aggregate_values (plats);
3392 agg = &avals->m_known_aggs[i];
3393 agg->items = agg_items;
3394 agg->by_ref = plats->aggs_by_ref;
3395 ret |= !agg_items.is_empty ();
3399 return ret;
3402 /* Perform time and size measurement of NODE with the context given in AVALS,
3403 calculate the benefit compared to the node without specialization and store
3404 it into VAL. Take into account REMOVABLE_PARAMS_COST of all
3405 context-independent or unused removable parameters and EST_MOVE_COST, the
3406 estimated movement of the considered parameter. */
3408 static void
3409 perform_estimation_of_a_value (cgraph_node *node,
3410 ipa_auto_call_arg_values *avals,
3411 int removable_params_cost, int est_move_cost,
3412 ipcp_value_base *val)
3414 int time_benefit;
3415 ipa_call_estimates estimates;
3417 estimate_ipcp_clone_size_and_time (node, avals, &estimates);
3418 sreal time_delta = estimates.nonspecialized_time - estimates.time;
3419 if (time_delta > 65535)
3420 time_delta = 65535;
3422 /* Extern inline functions have no cloning local time benefits because they
3423 will be inlined anyway. The only reason to clone them is if it enables
3424 optimization in any of the functions they call. */
3425 if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl))
3426 time_benefit = 0;
3427 else
3428 time_benefit = time_delta.to_int ()
3429 + devirtualization_time_bonus (node, avals)
3430 + hint_time_bonus (node, estimates)
3431 + removable_params_cost + est_move_cost;
3433 int size = estimates.size;
3434 gcc_checking_assert (size >=0);
3435 /* The inliner-heuristics based estimates may think that in certain
3436 contexts some functions do not have any size at all but we want
3437 all specializations to have at least a tiny cost, not least not to
3438 divide by zero. */
3439 if (size == 0)
3440 size = 1;
3442 val->local_time_benefit = time_benefit;
3443 val->local_size_cost = size;
3446 /* Get the overall limit oof growth based on parameters extracted from growth.
3447 it does not really make sense to mix functions with different overall growth
3448 limits but it is possible and if it happens, we do not want to select one
3449 limit at random. */
3451 static long
3452 get_max_overall_size (cgraph_node *node)
3454 long max_new_size = orig_overall_size;
3455 long large_unit = opt_for_fn (node->decl, param_ipa_cp_large_unit_insns);
3456 if (max_new_size < large_unit)
3457 max_new_size = large_unit;
3458 int unit_growth = opt_for_fn (node->decl, param_ipa_cp_unit_growth);
3459 max_new_size += max_new_size * unit_growth / 100 + 1;
3460 return max_new_size;
3463 /* Iterate over known values of parameters of NODE and estimate the local
3464 effects in terms of time and size they have. */
3466 static void
3467 estimate_local_effects (struct cgraph_node *node)
3469 class ipa_node_params *info = IPA_NODE_REF (node);
3470 int i, count = ipa_get_param_count (info);
3471 bool always_const;
3472 int removable_params_cost;
3474 if (!count || !ipcp_versionable_function_p (node))
3475 return;
3477 if (dump_file && (dump_flags & TDF_DETAILS))
3478 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
3480 ipa_auto_call_arg_values avals;
3481 always_const = gather_context_independent_values (info, &avals, true,
3482 &removable_params_cost);
3483 int devirt_bonus = devirtualization_time_bonus (node, &avals);
3484 if (always_const || devirt_bonus
3485 || (removable_params_cost && node->can_change_signature))
3487 struct caller_statistics stats;
3488 ipa_call_estimates estimates;
3490 init_caller_stats (&stats);
3491 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3492 false);
3493 estimate_ipcp_clone_size_and_time (node, &avals, &estimates);
3494 sreal time = estimates.nonspecialized_time - estimates.time;
3495 time += devirt_bonus;
3496 time += hint_time_bonus (node, estimates);
3497 time += removable_params_cost;
3498 int size = estimates.size - stats.n_calls * removable_params_cost;
3500 if (dump_file)
3501 fprintf (dump_file, " - context independent values, size: %i, "
3502 "time_benefit: %f\n", size, (time).to_double ());
3504 if (size <= 0 || node->local)
3506 info->do_clone_for_all_contexts = true;
3508 if (dump_file)
3509 fprintf (dump_file, " Decided to specialize for all "
3510 "known contexts, code not going to grow.\n");
3512 else if (good_cloning_opportunity_p (node,
3513 MIN ((time).to_int (), 65536),
3514 stats.freq_sum, stats.count_sum,
3515 size))
3517 if (size + overall_size <= get_max_overall_size (node))
3519 info->do_clone_for_all_contexts = true;
3520 overall_size += size;
3522 if (dump_file)
3523 fprintf (dump_file, " Decided to specialize for all "
3524 "known contexts, growth (to %li) deemed "
3525 "beneficial.\n", overall_size);
3527 else if (dump_file && (dump_flags & TDF_DETAILS))
3528 fprintf (dump_file, " Not cloning for all contexts because "
3529 "maximum unit size would be reached with %li.\n",
3530 size + overall_size);
3532 else if (dump_file && (dump_flags & TDF_DETAILS))
3533 fprintf (dump_file, " Not cloning for all contexts because "
3534 "!good_cloning_opportunity_p.\n");
3538 for (i = 0; i < count; i++)
3540 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3541 ipcp_lattice<tree> *lat = &plats->itself;
3542 ipcp_value<tree> *val;
3544 if (lat->bottom
3545 || !lat->values
3546 || avals.m_known_vals[i])
3547 continue;
3549 for (val = lat->values; val; val = val->next)
3551 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3552 avals.m_known_vals[i] = val->value;
3554 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
3555 perform_estimation_of_a_value (node, &avals, removable_params_cost,
3556 emc, val);
3558 if (dump_file && (dump_flags & TDF_DETAILS))
3560 fprintf (dump_file, " - estimates for value ");
3561 print_ipcp_constant_value (dump_file, val->value);
3562 fprintf (dump_file, " for ");
3563 ipa_dump_param (dump_file, info, i);
3564 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
3565 val->local_time_benefit, val->local_size_cost);
3568 avals.m_known_vals[i] = NULL_TREE;
3571 for (i = 0; i < count; i++)
3573 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3575 if (!plats->virt_call)
3576 continue;
3578 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3579 ipcp_value<ipa_polymorphic_call_context> *val;
3581 if (ctxlat->bottom
3582 || !ctxlat->values
3583 || !avals.m_known_contexts[i].useless_p ())
3584 continue;
3586 for (val = ctxlat->values; val; val = val->next)
3588 avals.m_known_contexts[i] = val->value;
3589 perform_estimation_of_a_value (node, &avals, removable_params_cost,
3590 0, val);
3592 if (dump_file && (dump_flags & TDF_DETAILS))
3594 fprintf (dump_file, " - estimates for polymorphic context ");
3595 print_ipcp_constant_value (dump_file, val->value);
3596 fprintf (dump_file, " for ");
3597 ipa_dump_param (dump_file, info, i);
3598 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
3599 val->local_time_benefit, val->local_size_cost);
3602 avals.m_known_contexts[i] = ipa_polymorphic_call_context ();
3605 for (i = 0; i < count; i++)
3607 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3609 if (plats->aggs_bottom || !plats->aggs)
3610 continue;
3612 ipa_agg_value_set *agg = &avals.m_known_aggs[i];
3613 for (ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3615 ipcp_value<tree> *val;
3616 if (aglat->bottom || !aglat->values
3617 /* If the following is true, the one value is in known_aggs. */
3618 || (!plats->aggs_contain_variable
3619 && aglat->is_single_const ()))
3620 continue;
3622 for (val = aglat->values; val; val = val->next)
3624 struct ipa_agg_value item;
3626 item.offset = aglat->offset;
3627 item.value = val->value;
3628 agg->items.safe_push (item);
3630 perform_estimation_of_a_value (node, &avals,
3631 removable_params_cost, 0, val);
3633 if (dump_file && (dump_flags & TDF_DETAILS))
3635 fprintf (dump_file, " - estimates for value ");
3636 print_ipcp_constant_value (dump_file, val->value);
3637 fprintf (dump_file, " for ");
3638 ipa_dump_param (dump_file, info, i);
3639 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3640 "]: time_benefit: %i, size: %i\n",
3641 plats->aggs_by_ref ? "ref " : "",
3642 aglat->offset,
3643 val->local_time_benefit, val->local_size_cost);
3646 agg->items.pop ();
3653 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3654 topological sort of values. */
3656 template <typename valtype>
3657 void
3658 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3660 ipcp_value_source<valtype> *src;
3662 if (cur_val->dfs)
3663 return;
3665 dfs_counter++;
3666 cur_val->dfs = dfs_counter;
3667 cur_val->low_link = dfs_counter;
3669 cur_val->topo_next = stack;
3670 stack = cur_val;
3671 cur_val->on_stack = true;
3673 for (src = cur_val->sources; src; src = src->next)
3674 if (src->val)
3676 if (src->val->dfs == 0)
3678 add_val (src->val);
3679 if (src->val->low_link < cur_val->low_link)
3680 cur_val->low_link = src->val->low_link;
3682 else if (src->val->on_stack
3683 && src->val->dfs < cur_val->low_link)
3684 cur_val->low_link = src->val->dfs;
3687 if (cur_val->dfs == cur_val->low_link)
3689 ipcp_value<valtype> *v, *scc_list = NULL;
3693 v = stack;
3694 stack = v->topo_next;
3695 v->on_stack = false;
3697 v->scc_next = scc_list;
3698 scc_list = v;
3700 while (v != cur_val);
3702 cur_val->topo_next = values_topo;
3703 values_topo = cur_val;
3707 /* Add all values in lattices associated with NODE to the topological sort if
3708 they are not there yet. */
3710 static void
3711 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3713 class ipa_node_params *info = IPA_NODE_REF (node);
3714 int i, count = ipa_get_param_count (info);
3716 for (i = 0; i < count; i++)
3718 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3719 ipcp_lattice<tree> *lat = &plats->itself;
3720 struct ipcp_agg_lattice *aglat;
3722 if (!lat->bottom)
3724 ipcp_value<tree> *val;
3725 for (val = lat->values; val; val = val->next)
3726 topo->constants.add_val (val);
3729 if (!plats->aggs_bottom)
3730 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3731 if (!aglat->bottom)
3733 ipcp_value<tree> *val;
3734 for (val = aglat->values; val; val = val->next)
3735 topo->constants.add_val (val);
3738 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3739 if (!ctxlat->bottom)
3741 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3742 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3743 topo->contexts.add_val (ctxval);
3748 /* One pass of constants propagation along the call graph edges, from callers
3749 to callees (requires topological ordering in TOPO), iterate over strongly
3750 connected components. */
3752 static void
3753 propagate_constants_topo (class ipa_topo_info *topo)
3755 int i;
3757 for (i = topo->nnodes - 1; i >= 0; i--)
3759 unsigned j;
3760 struct cgraph_node *v, *node = topo->order[i];
3761 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3763 /* First, iteratively propagate within the strongly connected component
3764 until all lattices stabilize. */
3765 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3766 if (v->has_gimple_body_p ())
3768 if (opt_for_fn (v->decl, flag_ipa_cp)
3769 && opt_for_fn (v->decl, optimize))
3770 push_node_to_stack (topo, v);
3771 /* When V is not optimized, we can not push it to stack, but
3772 still we need to set all its callees lattices to bottom. */
3773 else
3775 for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
3776 propagate_constants_across_call (cs);
3780 v = pop_node_from_stack (topo);
3781 while (v)
3783 struct cgraph_edge *cs;
3784 class ipa_node_params *info = NULL;
3785 bool self_scc = true;
3787 for (cs = v->callees; cs; cs = cs->next_callee)
3788 if (ipa_edge_within_scc (cs))
3790 cgraph_node *callee = cs->callee->function_symbol ();
3792 if (v != callee)
3793 self_scc = false;
3795 if (!info)
3797 info = IPA_NODE_REF (v);
3798 info->node_within_scc = true;
3801 if (propagate_constants_across_call (cs))
3802 push_node_to_stack (topo, callee);
3805 if (info)
3806 info->node_is_self_scc = self_scc;
3808 v = pop_node_from_stack (topo);
3811 /* Afterwards, propagate along edges leading out of the SCC, calculates
3812 the local effects of the discovered constants and all valid values to
3813 their topological sort. */
3814 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3815 if (v->has_gimple_body_p ()
3816 && opt_for_fn (v->decl, flag_ipa_cp)
3817 && opt_for_fn (v->decl, optimize))
3819 struct cgraph_edge *cs;
3821 estimate_local_effects (v);
3822 add_all_node_vals_to_toposort (v, topo);
3823 for (cs = v->callees; cs; cs = cs->next_callee)
3824 if (!ipa_edge_within_scc (cs))
3825 propagate_constants_across_call (cs);
3827 cycle_nodes.release ();
3832 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3833 the bigger one if otherwise. */
3835 static int
3836 safe_add (int a, int b)
3838 if (a > INT_MAX/2 || b > INT_MAX/2)
3839 return a > b ? a : b;
3840 else
3841 return a + b;
3845 /* Propagate the estimated effects of individual values along the topological
3846 from the dependent values to those they depend on. */
3848 template <typename valtype>
3849 void
3850 value_topo_info<valtype>::propagate_effects ()
3852 ipcp_value<valtype> *base;
3854 for (base = values_topo; base; base = base->topo_next)
3856 ipcp_value_source<valtype> *src;
3857 ipcp_value<valtype> *val;
3858 int time = 0, size = 0;
3860 for (val = base; val; val = val->scc_next)
3862 time = safe_add (time,
3863 val->local_time_benefit + val->prop_time_benefit);
3864 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
3867 for (val = base; val; val = val->scc_next)
3868 for (src = val->sources; src; src = src->next)
3869 if (src->val
3870 && src->cs->maybe_hot_p ())
3872 src->val->prop_time_benefit = safe_add (time,
3873 src->val->prop_time_benefit);
3874 src->val->prop_size_cost = safe_add (size,
3875 src->val->prop_size_cost);
3881 /* Propagate constants, polymorphic contexts and their effects from the
3882 summaries interprocedurally. */
3884 static void
3885 ipcp_propagate_stage (class ipa_topo_info *topo)
3887 struct cgraph_node *node;
3889 if (dump_file)
3890 fprintf (dump_file, "\n Propagating constants:\n\n");
3892 max_count = profile_count::uninitialized ();
3894 FOR_EACH_DEFINED_FUNCTION (node)
3896 if (node->has_gimple_body_p ()
3897 && opt_for_fn (node->decl, flag_ipa_cp)
3898 && opt_for_fn (node->decl, optimize))
3900 class ipa_node_params *info = IPA_NODE_REF (node);
3901 determine_versionability (node, info);
3903 unsigned nlattices = ipa_get_param_count (info);
3904 void *chunk = XCNEWVEC (class ipcp_param_lattices, nlattices);
3905 info->lattices = new (chunk) ipcp_param_lattices[nlattices];
3906 initialize_node_lattices (node);
3908 ipa_size_summary *s = ipa_size_summaries->get (node);
3909 if (node->definition && !node->alias && s != NULL)
3910 overall_size += s->self_size;
3911 max_count = max_count.max (node->count.ipa ());
3914 orig_overall_size = overall_size;
3916 if (dump_file)
3917 fprintf (dump_file, "\noverall_size: %li\n", overall_size);
3919 propagate_constants_topo (topo);
3920 if (flag_checking)
3921 ipcp_verify_propagated_values ();
3922 topo->constants.propagate_effects ();
3923 topo->contexts.propagate_effects ();
3925 if (dump_file)
3927 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3928 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3932 /* Discover newly direct outgoing edges from NODE which is a new clone with
3933 known KNOWN_CSTS and make them direct. */
3935 static void
3936 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3937 vec<tree> known_csts,
3938 vec<ipa_polymorphic_call_context>
3939 known_contexts,
3940 struct ipa_agg_replacement_value *aggvals)
3942 struct cgraph_edge *ie, *next_ie;
3943 bool found = false;
3945 for (ie = node->indirect_calls; ie; ie = next_ie)
3947 tree target;
3948 bool speculative;
3950 next_ie = ie->next_callee;
3951 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3952 vNULL, aggvals, &speculative);
3953 if (target)
3955 bool agg_contents = ie->indirect_info->agg_contents;
3956 bool polymorphic = ie->indirect_info->polymorphic;
3957 int param_index = ie->indirect_info->param_index;
3958 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3959 speculative);
3960 found = true;
3962 if (cs && !agg_contents && !polymorphic)
3964 class ipa_node_params *info = IPA_NODE_REF (node);
3965 int c = ipa_get_controlled_uses (info, param_index);
3966 if (c != IPA_UNDESCRIBED_USE)
3968 struct ipa_ref *to_del;
3970 c--;
3971 ipa_set_controlled_uses (info, param_index, c);
3972 if (dump_file && (dump_flags & TDF_DETAILS))
3973 fprintf (dump_file, " controlled uses count of param "
3974 "%i bumped down to %i\n", param_index, c);
3975 if (c == 0
3976 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3978 if (dump_file && (dump_flags & TDF_DETAILS))
3979 fprintf (dump_file, " and even removing its "
3980 "cloning-created reference\n");
3981 to_del->remove_reference ();
3987 /* Turning calls to direct calls will improve overall summary. */
3988 if (found)
3989 ipa_update_overall_fn_summary (node);
3992 class edge_clone_summary;
3993 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL;
3995 /* Edge clone summary. */
3997 class edge_clone_summary
3999 public:
4000 /* Default constructor. */
4001 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
4003 /* Default destructor. */
4004 ~edge_clone_summary ()
4006 if (prev_clone)
4007 edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
4008 if (next_clone)
4009 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
4012 cgraph_edge *prev_clone;
4013 cgraph_edge *next_clone;
4016 class edge_clone_summary_t:
4017 public call_summary <edge_clone_summary *>
4019 public:
4020 edge_clone_summary_t (symbol_table *symtab):
4021 call_summary <edge_clone_summary *> (symtab)
4023 m_initialize_when_cloning = true;
4026 virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4027 edge_clone_summary *src_data,
4028 edge_clone_summary *dst_data);
4031 /* Edge duplication hook. */
4033 void
4034 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4035 edge_clone_summary *src_data,
4036 edge_clone_summary *dst_data)
4038 if (src_data->next_clone)
4039 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
4040 dst_data->prev_clone = src_edge;
4041 dst_data->next_clone = src_data->next_clone;
4042 src_data->next_clone = dst_edge;
4045 /* Return true is CS calls DEST or its clone for all contexts. When
4046 ALLOW_RECURSION_TO_CLONE is false, also return false for self-recursive
4047 edges from/to an all-context clone. */
4049 static bool
4050 calls_same_node_or_its_all_contexts_clone_p (cgraph_edge *cs, cgraph_node *dest,
4051 bool allow_recursion_to_clone)
4053 enum availability availability;
4054 cgraph_node *callee = cs->callee->function_symbol (&availability);
4056 if (availability <= AVAIL_INTERPOSABLE)
4057 return false;
4058 if (callee == dest)
4059 return true;
4060 if (!allow_recursion_to_clone && cs->caller == callee)
4061 return false;
4063 class ipa_node_params *info = IPA_NODE_REF (callee);
4064 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
4067 /* Return true if edge CS does bring about the value described by SRC to
4068 DEST_VAL of node DEST or its clone for all contexts. */
4070 static bool
4071 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
4072 cgraph_node *dest, ipcp_value<tree> *dest_val)
4074 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4076 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, !src->val)
4077 || caller_info->node_dead)
4078 return false;
4080 if (!src->val)
4081 return true;
4083 if (caller_info->ipcp_orig_node)
4085 tree t;
4086 if (src->offset == -1)
4087 t = caller_info->known_csts[src->index];
4088 else
4089 t = get_clone_agg_value (cs->caller, src->offset, src->index);
4090 return (t != NULL_TREE
4091 && values_equal_for_ipcp_p (src->val->value, t));
4093 else
4095 if (src->val == dest_val)
4096 return true;
4098 struct ipcp_agg_lattice *aglat;
4099 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4100 src->index);
4101 if (src->offset == -1)
4102 return (plats->itself.is_single_const ()
4103 && values_equal_for_ipcp_p (src->val->value,
4104 plats->itself.values->value));
4105 else
4107 if (plats->aggs_bottom || plats->aggs_contain_variable)
4108 return false;
4109 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4110 if (aglat->offset == src->offset)
4111 return (aglat->is_single_const ()
4112 && values_equal_for_ipcp_p (src->val->value,
4113 aglat->values->value));
4115 return false;
4119 /* Return true if edge CS does bring about the value described by SRC to
4120 DST_VAL of node DEST or its clone for all contexts. */
4122 static bool
4123 cgraph_edge_brings_value_p (cgraph_edge *cs,
4124 ipcp_value_source<ipa_polymorphic_call_context> *src,
4125 cgraph_node *dest,
4126 ipcp_value<ipa_polymorphic_call_context> *)
4128 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4130 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, true)
4131 || caller_info->node_dead)
4132 return false;
4133 if (!src->val)
4134 return true;
4136 if (caller_info->ipcp_orig_node)
4137 return (caller_info->known_contexts.length () > (unsigned) src->index)
4138 && values_equal_for_ipcp_p (src->val->value,
4139 caller_info->known_contexts[src->index]);
4141 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4142 src->index);
4143 return plats->ctxlat.is_single_const ()
4144 && values_equal_for_ipcp_p (src->val->value,
4145 plats->ctxlat.values->value);
4148 /* Get the next clone in the linked list of clones of an edge. */
4150 static inline struct cgraph_edge *
4151 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
4153 edge_clone_summary *s = edge_clone_summaries->get (cs);
4154 return s != NULL ? s->next_clone : NULL;
4157 /* Given VAL that is intended for DEST, iterate over all its sources and if any
4158 of them is viable and hot, return true. In that case, for those that still
4159 hold, add their edge frequency and their number into *FREQUENCY and
4160 *CALLER_COUNT respectively. */
4162 template <typename valtype>
4163 static bool
4164 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
4165 int *freq_sum,
4166 profile_count *count_sum, int *caller_count)
4168 ipcp_value_source<valtype> *src;
4169 int freq = 0, count = 0;
4170 profile_count cnt = profile_count::zero ();
4171 bool hot = false;
4172 bool non_self_recursive = false;
4174 for (src = val->sources; src; src = src->next)
4176 struct cgraph_edge *cs = src->cs;
4177 while (cs)
4179 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4181 count++;
4182 freq += cs->frequency ();
4183 if (cs->count.ipa ().initialized_p ())
4184 cnt += cs->count.ipa ();
4185 hot |= cs->maybe_hot_p ();
4186 if (cs->caller != dest)
4187 non_self_recursive = true;
4189 cs = get_next_cgraph_edge_clone (cs);
4193 /* If the only edges bringing a value are self-recursive ones, do not bother
4194 evaluating it. */
4195 if (!non_self_recursive)
4196 return false;
4198 *freq_sum = freq;
4199 *count_sum = cnt;
4200 *caller_count = count;
4202 if (!hot && IPA_NODE_REF (dest)->node_within_scc)
4204 struct cgraph_edge *cs;
4206 /* Cold non-SCC source edge could trigger hot recursive execution of
4207 function. Consider the case as hot and rely on following cost model
4208 computation to further select right one. */
4209 for (cs = dest->callers; cs; cs = cs->next_caller)
4210 if (cs->caller == dest && cs->maybe_hot_p ())
4211 return true;
4214 return hot;
4217 /* Given a NODE, and a set of its CALLERS, try to adjust order of the callers
4218 to let a non-self-recursive caller be the first element. Thus, we can
4219 simplify intersecting operations on values that arrive from all of these
4220 callers, especially when there exists self-recursive call. Return true if
4221 this kind of adjustment is possible. */
4223 static bool
4224 adjust_callers_for_value_intersection (vec<cgraph_edge *> callers,
4225 cgraph_node *node)
4227 for (unsigned i = 0; i < callers.length (); i++)
4229 cgraph_edge *cs = callers[i];
4231 if (cs->caller != node)
4233 if (i > 0)
4235 callers[i] = callers[0];
4236 callers[0] = cs;
4238 return true;
4241 return false;
4244 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
4245 is assumed their number is known and equal to CALLER_COUNT. */
4247 template <typename valtype>
4248 static vec<cgraph_edge *>
4249 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
4250 int caller_count)
4252 ipcp_value_source<valtype> *src;
4253 vec<cgraph_edge *> ret;
4255 ret.create (caller_count);
4256 for (src = val->sources; src; src = src->next)
4258 struct cgraph_edge *cs = src->cs;
4259 while (cs)
4261 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4262 ret.quick_push (cs);
4263 cs = get_next_cgraph_edge_clone (cs);
4267 if (caller_count > 1)
4268 adjust_callers_for_value_intersection (ret, dest);
4270 return ret;
4273 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
4274 Return it or NULL if for some reason it cannot be created. */
4276 static struct ipa_replace_map *
4277 get_replacement_map (class ipa_node_params *info, tree value, int parm_num)
4279 struct ipa_replace_map *replace_map;
4281 replace_map = ggc_alloc<ipa_replace_map> ();
4282 if (dump_file)
4284 fprintf (dump_file, " replacing ");
4285 ipa_dump_param (dump_file, info, parm_num);
4287 fprintf (dump_file, " with const ");
4288 print_generic_expr (dump_file, value);
4289 fprintf (dump_file, "\n");
4291 replace_map->parm_num = parm_num;
4292 replace_map->new_tree = value;
4293 return replace_map;
4296 /* Dump new profiling counts */
4298 static void
4299 dump_profile_updates (struct cgraph_node *orig_node,
4300 struct cgraph_node *new_node)
4302 struct cgraph_edge *cs;
4304 fprintf (dump_file, " setting count of the specialized node to ");
4305 new_node->count.dump (dump_file);
4306 fprintf (dump_file, "\n");
4307 for (cs = new_node->callees; cs; cs = cs->next_callee)
4309 fprintf (dump_file, " edge to %s has count ",
4310 cs->callee->dump_name ());
4311 cs->count.dump (dump_file);
4312 fprintf (dump_file, "\n");
4315 fprintf (dump_file, " setting count of the original node to ");
4316 orig_node->count.dump (dump_file);
4317 fprintf (dump_file, "\n");
4318 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4320 fprintf (dump_file, " edge to %s is left with ",
4321 cs->callee->dump_name ());
4322 cs->count.dump (dump_file);
4323 fprintf (dump_file, "\n");
4327 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
4328 their profile information to reflect this. */
4330 static void
4331 update_profiling_info (struct cgraph_node *orig_node,
4332 struct cgraph_node *new_node)
4334 struct cgraph_edge *cs;
4335 struct caller_statistics stats;
4336 profile_count new_sum, orig_sum;
4337 profile_count remainder, orig_node_count = orig_node->count;
4338 profile_count orig_new_node_count = new_node->count;
4340 if (!(orig_node_count.ipa () > profile_count::zero ()))
4341 return;
4343 init_caller_stats (&stats);
4344 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
4345 false);
4346 orig_sum = stats.count_sum;
4347 init_caller_stats (&stats);
4348 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
4349 false);
4350 new_sum = stats.count_sum;
4352 if (orig_node_count < orig_sum + new_sum)
4354 if (dump_file)
4356 fprintf (dump_file, " Problem: node %s has too low count ",
4357 orig_node->dump_name ());
4358 orig_node_count.dump (dump_file);
4359 fprintf (dump_file, "while the sum of incoming count is ");
4360 (orig_sum + new_sum).dump (dump_file);
4361 fprintf (dump_file, "\n");
4364 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
4365 if (dump_file)
4367 fprintf (dump_file, " proceeding by pretending it was ");
4368 orig_node_count.dump (dump_file);
4369 fprintf (dump_file, "\n");
4373 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
4374 - new_sum.ipa ());
4376 /* With partial train run we do not want to assume that original's
4377 count is zero whenever we redurect all executed edges to clone.
4378 Simply drop profile to local one in this case. */
4379 if (remainder.ipa_p () && !remainder.ipa ().nonzero_p ()
4380 && orig_node->count.ipa_p () && orig_node->count.ipa ().nonzero_p ()
4381 && flag_profile_partial_training)
4382 remainder = remainder.guessed_local ();
4384 new_sum = orig_node_count.combine_with_ipa_count (new_sum);
4385 new_node->count = new_sum;
4386 orig_node->count = remainder;
4388 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_new_node_count);
4389 for (cs = new_node->callees; cs; cs = cs->next_callee)
4390 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4391 for (cs = new_node->indirect_calls; cs; cs = cs->next_callee)
4392 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4394 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
4395 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4396 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4397 for (cs = orig_node->indirect_calls; cs; cs = cs->next_callee)
4398 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4400 if (dump_file)
4401 dump_profile_updates (orig_node, new_node);
4404 /* Update the respective profile of specialized NEW_NODE and the original
4405 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
4406 have been redirected to the specialized version. */
4408 static void
4409 update_specialized_profile (struct cgraph_node *new_node,
4410 struct cgraph_node *orig_node,
4411 profile_count redirected_sum)
4413 struct cgraph_edge *cs;
4414 profile_count new_node_count, orig_node_count = orig_node->count;
4416 if (dump_file)
4418 fprintf (dump_file, " the sum of counts of redirected edges is ");
4419 redirected_sum.dump (dump_file);
4420 fprintf (dump_file, "\n");
4422 if (!(orig_node_count > profile_count::zero ()))
4423 return;
4425 gcc_assert (orig_node_count >= redirected_sum);
4427 new_node_count = new_node->count;
4428 new_node->count += redirected_sum;
4429 orig_node->count -= redirected_sum;
4431 for (cs = new_node->callees; cs; cs = cs->next_callee)
4432 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
4434 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4436 profile_count dec = cs->count.apply_scale (redirected_sum,
4437 orig_node_count);
4438 cs->count -= dec;
4441 if (dump_file)
4442 dump_profile_updates (orig_node, new_node);
4445 /* Return true if we would like to remove a parameter from NODE when cloning it
4446 with KNOWN_CSTS scalar constants. */
4448 static bool
4449 want_remove_some_param_p (cgraph_node *node, vec<tree> known_csts)
4451 auto_vec<bool, 16> surviving;
4452 bool filled_vec = false;
4453 ipa_node_params *info = IPA_NODE_REF (node);
4454 int i, count = ipa_get_param_count (info);
4456 for (i = 0; i < count; i++)
4458 if (!known_csts[i] && ipa_is_param_used (info, i))
4459 continue;
4461 if (!filled_vec)
4463 clone_info *info = clone_info::get (node);
4464 if (!info || !info->param_adjustments)
4465 return true;
4466 info->param_adjustments->get_surviving_params (&surviving);
4467 filled_vec = true;
4469 if (surviving.length() < (unsigned) i && surviving[i])
4470 return true;
4472 return false;
4475 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
4476 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
4477 redirect all edges in CALLERS to it. */
4479 static struct cgraph_node *
4480 create_specialized_node (struct cgraph_node *node,
4481 vec<tree> known_csts,
4482 vec<ipa_polymorphic_call_context> known_contexts,
4483 struct ipa_agg_replacement_value *aggvals,
4484 vec<cgraph_edge *> callers)
4486 class ipa_node_params *new_info, *info = IPA_NODE_REF (node);
4487 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
4488 vec<ipa_adjusted_param, va_gc> *new_params = NULL;
4489 struct ipa_agg_replacement_value *av;
4490 struct cgraph_node *new_node;
4491 int i, count = ipa_get_param_count (info);
4492 clone_info *cinfo = clone_info::get (node);
4493 ipa_param_adjustments *old_adjustments = cinfo
4494 ? cinfo->param_adjustments : NULL;
4495 ipa_param_adjustments *new_adjustments;
4496 gcc_assert (!info->ipcp_orig_node);
4497 gcc_assert (node->can_change_signature
4498 || !old_adjustments);
4500 if (old_adjustments)
4502 /* At the moment all IPA optimizations should use the number of
4503 parameters of the prevailing decl as the m_always_copy_start.
4504 Handling any other value would complicate the code below, so for the
4505 time bing let's only assert it is so. */
4506 gcc_assert (old_adjustments->m_always_copy_start == count
4507 || old_adjustments->m_always_copy_start < 0);
4508 int old_adj_count = vec_safe_length (old_adjustments->m_adj_params);
4509 for (i = 0; i < old_adj_count; i++)
4511 ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
4512 if (!node->can_change_signature
4513 || old_adj->op != IPA_PARAM_OP_COPY
4514 || (!known_csts[old_adj->base_index]
4515 && ipa_is_param_used (info, old_adj->base_index)))
4517 ipa_adjusted_param new_adj = *old_adj;
4519 new_adj.prev_clone_adjustment = true;
4520 new_adj.prev_clone_index = i;
4521 vec_safe_push (new_params, new_adj);
4524 bool skip_return = old_adjustments->m_skip_return;
4525 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
4526 ipa_param_adjustments (new_params, count,
4527 skip_return));
4529 else if (node->can_change_signature
4530 && want_remove_some_param_p (node, known_csts))
4532 ipa_adjusted_param adj;
4533 memset (&adj, 0, sizeof (adj));
4534 adj.op = IPA_PARAM_OP_COPY;
4535 for (i = 0; i < count; i++)
4536 if (!known_csts[i] && ipa_is_param_used (info, i))
4538 adj.base_index = i;
4539 adj.prev_clone_index = i;
4540 vec_safe_push (new_params, adj);
4542 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
4543 ipa_param_adjustments (new_params, count, false));
4545 else
4546 new_adjustments = NULL;
4548 replace_trees = cinfo ? vec_safe_copy (cinfo->tree_map) : NULL;
4549 for (i = 0; i < count; i++)
4551 tree t = known_csts[i];
4552 if (t)
4554 struct ipa_replace_map *replace_map;
4556 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
4557 replace_map = get_replacement_map (info, t, i);
4558 if (replace_map)
4559 vec_safe_push (replace_trees, replace_map);
4562 auto_vec<cgraph_edge *, 2> self_recursive_calls;
4563 for (i = callers.length () - 1; i >= 0; i--)
4565 cgraph_edge *cs = callers[i];
4566 if (cs->caller == node)
4568 self_recursive_calls.safe_push (cs);
4569 callers.unordered_remove (i);
4573 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
4574 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
4575 node->decl)));
4576 new_node = node->create_virtual_clone (callers, replace_trees,
4577 new_adjustments, "constprop",
4578 suffix_counter);
4579 suffix_counter++;
4581 bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
4582 for (unsigned j = 0; j < self_recursive_calls.length (); j++)
4584 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
4585 /* Cloned edges can disappear during cloning as speculation can be
4586 resolved, check that we have one and that it comes from the last
4587 cloning. */
4588 if (cs && cs->caller == new_node)
4589 cs->redirect_callee_duplicating_thunks (new_node);
4590 /* Any future code that would make more than one clone of an outgoing
4591 edge would confuse this mechanism, so let's check that does not
4592 happen. */
4593 gcc_checking_assert (!cs
4594 || !get_next_cgraph_edge_clone (cs)
4595 || get_next_cgraph_edge_clone (cs)->caller != new_node);
4597 if (have_self_recursive_calls)
4598 new_node->expand_all_artificial_thunks ();
4600 ipa_set_node_agg_value_chain (new_node, aggvals);
4601 for (av = aggvals; av; av = av->next)
4602 new_node->maybe_create_reference (av->value, NULL);
4604 if (dump_file && (dump_flags & TDF_DETAILS))
4606 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
4607 if (known_contexts.exists ())
4609 for (i = 0; i < count; i++)
4610 if (!known_contexts[i].useless_p ())
4612 fprintf (dump_file, " known ctx %i is ", i);
4613 known_contexts[i].dump (dump_file);
4616 if (aggvals)
4617 ipa_dump_agg_replacement_values (dump_file, aggvals);
4619 ipa_check_create_node_params ();
4620 update_profiling_info (node, new_node);
4621 new_info = IPA_NODE_REF (new_node);
4622 new_info->ipcp_orig_node = node;
4623 new_node->ipcp_clone = true;
4624 new_info->known_csts = known_csts;
4625 new_info->known_contexts = known_contexts;
4627 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
4629 callers.release ();
4630 return new_node;
4633 /* Return true if JFUNC, which describes a i-th parameter of call CS, is a
4634 pass-through function to itself when the cgraph_node involved is not an
4635 IPA-CP clone. When SIMPLE is true, further check if JFUNC is a simple
4636 no-operation pass-through. */
4638 static bool
4639 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i,
4640 bool simple = true)
4642 enum availability availability;
4643 if (cs->caller == cs->callee->function_symbol (&availability)
4644 && availability > AVAIL_INTERPOSABLE
4645 && jfunc->type == IPA_JF_PASS_THROUGH
4646 && (!simple || ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4647 && ipa_get_jf_pass_through_formal_id (jfunc) == i
4648 && IPA_NODE_REF (cs->caller)
4649 && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
4650 return true;
4651 return false;
4654 /* Return true if JFUNC, which describes a part of an aggregate represented or
4655 pointed to by the i-th parameter of call CS, is a pass-through function to
4656 itself when the cgraph_node involved is not an IPA-CP clone.. When
4657 SIMPLE is true, further check if JFUNC is a simple no-operation
4658 pass-through. */
4660 static bool
4661 self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
4662 int i, bool simple = true)
4664 enum availability availability;
4665 if (cs->caller == cs->callee->function_symbol (&availability)
4666 && availability > AVAIL_INTERPOSABLE
4667 && jfunc->jftype == IPA_JF_LOAD_AGG
4668 && jfunc->offset == jfunc->value.load_agg.offset
4669 && (!simple || jfunc->value.pass_through.operation == NOP_EXPR)
4670 && jfunc->value.pass_through.formal_id == i
4671 && useless_type_conversion_p (jfunc->value.load_agg.type, jfunc->type)
4672 && IPA_NODE_REF (cs->caller)
4673 && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
4674 return true;
4675 return false;
4678 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
4679 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
4681 static void
4682 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
4683 vec<tree> known_csts,
4684 vec<cgraph_edge *> callers)
4686 class ipa_node_params *info = IPA_NODE_REF (node);
4687 int i, count = ipa_get_param_count (info);
4689 for (i = 0; i < count; i++)
4691 struct cgraph_edge *cs;
4692 tree newval = NULL_TREE;
4693 int j;
4694 bool first = true;
4695 tree type = ipa_get_type (info, i);
4697 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
4698 continue;
4700 FOR_EACH_VEC_ELT (callers, j, cs)
4702 struct ipa_jump_func *jump_func;
4703 tree t;
4705 if (!IPA_EDGE_REF (cs)
4706 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
4707 || (i == 0
4708 && call_passes_through_thunk (cs)))
4710 newval = NULL_TREE;
4711 break;
4713 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
4715 /* Besides simple pass-through jump function, arithmetic jump
4716 function could also introduce argument-direct-pass-through for
4717 self-feeding recursive call. For example,
4719 fn (int i)
4721 fn (i & 1);
4724 Given that i is 0, recursive propagation via (i & 1) also gets
4725 0. */
4726 if (self_recursive_pass_through_p (cs, jump_func, i, false))
4728 gcc_assert (newval);
4729 t = ipa_get_jf_arith_result (
4730 ipa_get_jf_pass_through_operation (jump_func),
4731 newval,
4732 ipa_get_jf_pass_through_operand (jump_func),
4733 type);
4735 else
4736 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func,
4737 type);
4738 if (!t
4739 || (newval
4740 && !values_equal_for_ipcp_p (t, newval))
4741 || (!first && !newval))
4743 newval = NULL_TREE;
4744 break;
4746 else
4747 newval = t;
4748 first = false;
4751 if (newval)
4753 if (dump_file && (dump_flags & TDF_DETAILS))
4755 fprintf (dump_file, " adding an extra known scalar value ");
4756 print_ipcp_constant_value (dump_file, newval);
4757 fprintf (dump_file, " for ");
4758 ipa_dump_param (dump_file, info, i);
4759 fprintf (dump_file, "\n");
4762 known_csts[i] = newval;
4767 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
4768 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
4769 CALLERS. */
4771 static void
4772 find_more_contexts_for_caller_subset (cgraph_node *node,
4773 vec<ipa_polymorphic_call_context>
4774 *known_contexts,
4775 vec<cgraph_edge *> callers)
4777 ipa_node_params *info = IPA_NODE_REF (node);
4778 int i, count = ipa_get_param_count (info);
4780 for (i = 0; i < count; i++)
4782 cgraph_edge *cs;
4784 if (ipa_get_poly_ctx_lat (info, i)->bottom
4785 || (known_contexts->exists ()
4786 && !(*known_contexts)[i].useless_p ()))
4787 continue;
4789 ipa_polymorphic_call_context newval;
4790 bool first = true;
4791 int j;
4793 FOR_EACH_VEC_ELT (callers, j, cs)
4795 if (!IPA_EDGE_REF (cs)
4796 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
4797 return;
4798 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
4800 ipa_polymorphic_call_context ctx;
4801 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
4802 jfunc);
4803 if (first)
4805 newval = ctx;
4806 first = false;
4808 else
4809 newval.meet_with (ctx);
4810 if (newval.useless_p ())
4811 break;
4814 if (!newval.useless_p ())
4816 if (dump_file && (dump_flags & TDF_DETAILS))
4818 fprintf (dump_file, " adding an extra known polymorphic "
4819 "context ");
4820 print_ipcp_constant_value (dump_file, newval);
4821 fprintf (dump_file, " for ");
4822 ipa_dump_param (dump_file, info, i);
4823 fprintf (dump_file, "\n");
4826 if (!known_contexts->exists ())
4827 known_contexts->safe_grow_cleared (ipa_get_param_count (info),
4828 true);
4829 (*known_contexts)[i] = newval;
4835 /* Go through PLATS and create a vector of values consisting of values and
4836 offsets (minus OFFSET) of lattices that contain only a single value. */
4838 static vec<ipa_agg_value>
4839 copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset)
4841 vec<ipa_agg_value> res = vNULL;
4843 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4844 return vNULL;
4846 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
4847 if (aglat->is_single_const ())
4849 struct ipa_agg_value ti;
4850 ti.offset = aglat->offset - offset;
4851 ti.value = aglat->values->value;
4852 res.safe_push (ti);
4854 return res;
4857 /* Intersect all values in INTER with single value lattices in PLATS (while
4858 subtracting OFFSET). */
4860 static void
4861 intersect_with_plats (class ipcp_param_lattices *plats,
4862 vec<ipa_agg_value> *inter,
4863 HOST_WIDE_INT offset)
4865 struct ipcp_agg_lattice *aglat;
4866 struct ipa_agg_value *item;
4867 int k;
4869 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4871 inter->release ();
4872 return;
4875 aglat = plats->aggs;
4876 FOR_EACH_VEC_ELT (*inter, k, item)
4878 bool found = false;
4879 if (!item->value)
4880 continue;
4881 while (aglat)
4883 if (aglat->offset - offset > item->offset)
4884 break;
4885 if (aglat->offset - offset == item->offset)
4887 if (aglat->is_single_const ())
4889 tree value = aglat->values->value;
4891 if (values_equal_for_ipcp_p (item->value, value))
4892 found = true;
4894 break;
4896 aglat = aglat->next;
4898 if (!found)
4899 item->value = NULL_TREE;
4903 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4904 vector result while subtracting OFFSET from the individual value offsets. */
4906 static vec<ipa_agg_value>
4907 agg_replacements_to_vector (struct cgraph_node *node, int index,
4908 HOST_WIDE_INT offset)
4910 struct ipa_agg_replacement_value *av;
4911 vec<ipa_agg_value> res = vNULL;
4913 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4914 if (av->index == index
4915 && (av->offset - offset) >= 0)
4917 struct ipa_agg_value item;
4918 gcc_checking_assert (av->value);
4919 item.offset = av->offset - offset;
4920 item.value = av->value;
4921 res.safe_push (item);
4924 return res;
4927 /* Intersect all values in INTER with those that we have already scheduled to
4928 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4929 (while subtracting OFFSET). */
4931 static void
4932 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4933 vec<ipa_agg_value> *inter,
4934 HOST_WIDE_INT offset)
4936 struct ipa_agg_replacement_value *srcvals;
4937 struct ipa_agg_value *item;
4938 int i;
4940 srcvals = ipa_get_agg_replacements_for_node (node);
4941 if (!srcvals)
4943 inter->release ();
4944 return;
4947 FOR_EACH_VEC_ELT (*inter, i, item)
4949 struct ipa_agg_replacement_value *av;
4950 bool found = false;
4951 if (!item->value)
4952 continue;
4953 for (av = srcvals; av; av = av->next)
4955 gcc_checking_assert (av->value);
4956 if (av->index == index
4957 && av->offset - offset == item->offset)
4959 if (values_equal_for_ipcp_p (item->value, av->value))
4960 found = true;
4961 break;
4964 if (!found)
4965 item->value = NULL_TREE;
4969 /* Intersect values in INTER with aggregate values that come along edge CS to
4970 parameter number INDEX and return it. If INTER does not actually exist yet,
4971 copy all incoming values to it. If we determine we ended up with no values
4972 whatsoever, return a released vector. */
4974 static vec<ipa_agg_value>
4975 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4976 vec<ipa_agg_value> inter)
4978 struct ipa_jump_func *jfunc;
4979 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
4980 if (jfunc->type == IPA_JF_PASS_THROUGH
4981 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4983 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4984 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
4986 if (caller_info->ipcp_orig_node)
4988 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
4989 class ipcp_param_lattices *orig_plats;
4990 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
4991 src_idx);
4992 if (agg_pass_through_permissible_p (orig_plats, jfunc))
4994 if (!inter.exists ())
4995 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
4996 else
4997 intersect_with_agg_replacements (cs->caller, src_idx,
4998 &inter, 0);
4999 return inter;
5002 else
5004 class ipcp_param_lattices *src_plats;
5005 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
5006 if (agg_pass_through_permissible_p (src_plats, jfunc))
5008 /* Currently we do not produce clobber aggregate jump
5009 functions, adjust when we do. */
5010 gcc_checking_assert (!jfunc->agg.items);
5011 if (!inter.exists ())
5012 inter = copy_plats_to_inter (src_plats, 0);
5013 else
5014 intersect_with_plats (src_plats, &inter, 0);
5015 return inter;
5019 else if (jfunc->type == IPA_JF_ANCESTOR
5020 && ipa_get_jf_ancestor_agg_preserved (jfunc))
5022 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5023 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
5024 class ipcp_param_lattices *src_plats;
5025 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
5027 if (caller_info->ipcp_orig_node)
5029 if (!inter.exists ())
5030 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
5031 else
5032 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
5033 delta);
5035 else
5037 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
5038 /* Currently we do not produce clobber aggregate jump
5039 functions, adjust when we do. */
5040 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
5041 if (!inter.exists ())
5042 inter = copy_plats_to_inter (src_plats, delta);
5043 else
5044 intersect_with_plats (src_plats, &inter, delta);
5046 return inter;
5049 if (jfunc->agg.items)
5051 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5052 struct ipa_agg_value *item;
5053 int k;
5055 if (!inter.exists ())
5056 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
5058 struct ipa_agg_jf_item *agg_item = &(*jfunc->agg.items)[i];
5059 tree value = ipa_agg_value_from_node (caller_info, cs->caller,
5060 agg_item);
5061 if (value)
5063 struct ipa_agg_value agg_value;
5065 agg_value.value = value;
5066 agg_value.offset = agg_item->offset;
5067 inter.safe_push (agg_value);
5070 else
5071 FOR_EACH_VEC_ELT (inter, k, item)
5073 int l = 0;
5074 bool found = false;
5076 if (!item->value)
5077 continue;
5079 while ((unsigned) l < jfunc->agg.items->length ())
5081 struct ipa_agg_jf_item *ti;
5082 ti = &(*jfunc->agg.items)[l];
5083 if (ti->offset > item->offset)
5084 break;
5085 if (ti->offset == item->offset)
5087 tree value;
5089 /* Besides simple pass-through aggregate jump function,
5090 arithmetic aggregate jump function could also bring
5091 same aggregate value as parameter passed-in for
5092 self-feeding recursive call. For example,
5094 fn (int *i)
5096 int j = *i & 1;
5097 fn (&j);
5100 Given that *i is 0, recursive propagation via (*i & 1)
5101 also gets 0. */
5102 if (self_recursive_agg_pass_through_p (cs, ti, index,
5103 false))
5104 value = ipa_get_jf_arith_result (
5105 ti->value.pass_through.operation,
5106 item->value,
5107 ti->value.pass_through.operand,
5108 ti->type);
5109 else
5110 value = ipa_agg_value_from_node (caller_info,
5111 cs->caller, ti);
5113 if (value && values_equal_for_ipcp_p (item->value, value))
5114 found = true;
5115 break;
5117 l++;
5119 if (!found)
5120 item->value = NULL;
5123 else
5125 inter.release ();
5126 return vNULL;
5128 return inter;
5131 /* Look at edges in CALLERS and collect all known aggregate values that arrive
5132 from all of them. */
5134 static struct ipa_agg_replacement_value *
5135 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
5136 vec<cgraph_edge *> callers)
5138 class ipa_node_params *dest_info = IPA_NODE_REF (node);
5139 struct ipa_agg_replacement_value *res;
5140 struct ipa_agg_replacement_value **tail = &res;
5141 struct cgraph_edge *cs;
5142 int i, j, count = ipa_get_param_count (dest_info);
5144 FOR_EACH_VEC_ELT (callers, j, cs)
5146 if (!IPA_EDGE_REF (cs))
5148 count = 0;
5149 break;
5151 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
5152 if (c < count)
5153 count = c;
5156 for (i = 0; i < count; i++)
5158 struct cgraph_edge *cs;
5159 vec<ipa_agg_value> inter = vNULL;
5160 struct ipa_agg_value *item;
5161 class ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
5162 int j;
5164 /* Among other things, the following check should deal with all by_ref
5165 mismatches. */
5166 if (plats->aggs_bottom)
5167 continue;
5169 FOR_EACH_VEC_ELT (callers, j, cs)
5171 struct ipa_jump_func *jfunc
5172 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
5173 if (self_recursive_pass_through_p (cs, jfunc, i)
5174 && (!plats->aggs_by_ref
5175 || ipa_get_jf_pass_through_agg_preserved (jfunc)))
5176 continue;
5177 inter = intersect_aggregates_with_edge (cs, i, inter);
5179 if (!inter.exists ())
5180 goto next_param;
5183 FOR_EACH_VEC_ELT (inter, j, item)
5185 struct ipa_agg_replacement_value *v;
5187 if (!item->value)
5188 continue;
5190 v = ggc_alloc<ipa_agg_replacement_value> ();
5191 v->index = i;
5192 v->offset = item->offset;
5193 v->value = item->value;
5194 v->by_ref = plats->aggs_by_ref;
5195 *tail = v;
5196 tail = &v->next;
5199 next_param:
5200 if (inter.exists ())
5201 inter.release ();
5203 *tail = NULL;
5204 return res;
5207 /* Determine whether CS also brings all scalar values that the NODE is
5208 specialized for. */
5210 static bool
5211 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
5212 struct cgraph_node *node)
5214 class ipa_node_params *dest_info = IPA_NODE_REF (node);
5215 int count = ipa_get_param_count (dest_info);
5216 class ipa_node_params *caller_info;
5217 class ipa_edge_args *args;
5218 int i;
5220 caller_info = IPA_NODE_REF (cs->caller);
5221 args = IPA_EDGE_REF (cs);
5222 for (i = 0; i < count; i++)
5224 struct ipa_jump_func *jump_func;
5225 tree val, t;
5227 val = dest_info->known_csts[i];
5228 if (!val)
5229 continue;
5231 if (i >= ipa_get_cs_argument_count (args))
5232 return false;
5233 jump_func = ipa_get_ith_jump_func (args, i);
5234 t = ipa_value_from_jfunc (caller_info, jump_func,
5235 ipa_get_type (dest_info, i));
5236 if (!t || !values_equal_for_ipcp_p (val, t))
5237 return false;
5239 return true;
5242 /* Determine whether CS also brings all aggregate values that NODE is
5243 specialized for. */
5244 static bool
5245 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
5246 struct cgraph_node *node)
5248 class ipa_node_params *orig_node_info;
5249 struct ipa_agg_replacement_value *aggval;
5250 int i, ec, count;
5252 aggval = ipa_get_agg_replacements_for_node (node);
5253 if (!aggval)
5254 return true;
5256 count = ipa_get_param_count (IPA_NODE_REF (node));
5257 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
5258 if (ec < count)
5259 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5260 if (aggval->index >= ec)
5261 return false;
5263 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
5265 for (i = 0; i < count; i++)
5267 class ipcp_param_lattices *plats;
5268 bool interesting = false;
5269 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5270 if (aggval->index == i)
5272 interesting = true;
5273 break;
5275 if (!interesting)
5276 continue;
5278 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
5279 if (plats->aggs_bottom)
5280 return false;
5282 vec<ipa_agg_value> values = intersect_aggregates_with_edge (cs, i, vNULL);
5283 if (!values.exists ())
5284 return false;
5286 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5287 if (aggval->index == i)
5289 struct ipa_agg_value *item;
5290 int j;
5291 bool found = false;
5292 FOR_EACH_VEC_ELT (values, j, item)
5293 if (item->value
5294 && item->offset == av->offset
5295 && values_equal_for_ipcp_p (item->value, av->value))
5297 found = true;
5298 break;
5300 if (!found)
5302 values.release ();
5303 return false;
5306 values.release ();
5308 return true;
5311 /* Given an original NODE and a VAL for which we have already created a
5312 specialized clone, look whether there are incoming edges that still lead
5313 into the old node but now also bring the requested value and also conform to
5314 all other criteria such that they can be redirected the special node.
5315 This function can therefore redirect the final edge in a SCC. */
5317 template <typename valtype>
5318 static void
5319 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
5321 ipcp_value_source<valtype> *src;
5322 profile_count redirected_sum = profile_count::zero ();
5324 for (src = val->sources; src; src = src->next)
5326 struct cgraph_edge *cs = src->cs;
5327 while (cs)
5329 if (cgraph_edge_brings_value_p (cs, src, node, val)
5330 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
5331 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
5333 if (dump_file)
5334 fprintf (dump_file, " - adding an extra caller %s of %s\n",
5335 cs->caller->dump_name (),
5336 val->spec_node->dump_name ());
5338 cs->redirect_callee_duplicating_thunks (val->spec_node);
5339 val->spec_node->expand_all_artificial_thunks ();
5340 if (cs->count.ipa ().initialized_p ())
5341 redirected_sum = redirected_sum + cs->count.ipa ();
5343 cs = get_next_cgraph_edge_clone (cs);
5347 if (redirected_sum.nonzero_p ())
5348 update_specialized_profile (val->spec_node, node, redirected_sum);
5351 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
5353 static bool
5354 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
5356 ipa_polymorphic_call_context *ctx;
5357 int i;
5359 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
5360 if (!ctx->useless_p ())
5361 return true;
5362 return false;
5365 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
5367 static vec<ipa_polymorphic_call_context>
5368 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
5370 if (known_contexts_useful_p (known_contexts))
5371 return known_contexts.copy ();
5372 else
5373 return vNULL;
5376 /* Copy known scalar values from AVALS into KNOWN_CSTS and modify the copy
5377 according to VAL and INDEX. If non-empty, replace KNOWN_CONTEXTS with its
5378 copy too. */
5380 static void
5381 copy_known_vectors_add_val (ipa_auto_call_arg_values *avals,
5382 vec<tree> *known_csts,
5383 vec<ipa_polymorphic_call_context> *known_contexts,
5384 ipcp_value<tree> *val, int index)
5386 *known_csts = avals->m_known_vals.copy ();
5387 *known_contexts = copy_useful_known_contexts (avals->m_known_contexts);
5388 (*known_csts)[index] = val->value;
5391 /* Copy known scalar values from AVALS into KNOWN_CSTS. Similarly, copy
5392 contexts to KNOWN_CONTEXTS and modify the copy according to VAL and
5393 INDEX. */
5395 static void
5396 copy_known_vectors_add_val (ipa_auto_call_arg_values *avals,
5397 vec<tree> *known_csts,
5398 vec<ipa_polymorphic_call_context> *known_contexts,
5399 ipcp_value<ipa_polymorphic_call_context> *val,
5400 int index)
5402 *known_csts = avals->m_known_vals.copy ();
5403 *known_contexts = avals->m_known_contexts.copy ();
5404 (*known_contexts)[index] = val->value;
5407 /* Return true if OFFSET indicates this was not an aggregate value or there is
5408 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
5409 AGGVALS list. */
5411 DEBUG_FUNCTION bool
5412 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
5413 int index, HOST_WIDE_INT offset, tree value)
5415 if (offset == -1)
5416 return true;
5418 while (aggvals)
5420 if (aggvals->index == index
5421 && aggvals->offset == offset
5422 && values_equal_for_ipcp_p (aggvals->value, value))
5423 return true;
5424 aggvals = aggvals->next;
5426 return false;
5429 /* Return true if offset is minus one because source of a polymorphic context
5430 cannot be an aggregate value. */
5432 DEBUG_FUNCTION bool
5433 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
5434 int , HOST_WIDE_INT offset,
5435 ipa_polymorphic_call_context)
5437 return offset == -1;
5440 /* Decide whether to create a special version of NODE for value VAL of
5441 parameter at the given INDEX. If OFFSET is -1, the value is for the
5442 parameter itself, otherwise it is stored at the given OFFSET of the
5443 parameter. AVALS describes the other already known values. */
5445 template <typename valtype>
5446 static bool
5447 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
5448 ipcp_value<valtype> *val, ipa_auto_call_arg_values *avals)
5450 struct ipa_agg_replacement_value *aggvals;
5451 int freq_sum, caller_count;
5452 profile_count count_sum;
5453 vec<cgraph_edge *> callers;
5455 if (val->spec_node)
5457 perhaps_add_new_callers (node, val);
5458 return false;
5460 else if (val->local_size_cost + overall_size > get_max_overall_size (node))
5462 if (dump_file && (dump_flags & TDF_DETAILS))
5463 fprintf (dump_file, " Ignoring candidate value because "
5464 "maximum unit size would be reached with %li.\n",
5465 val->local_size_cost + overall_size);
5466 return false;
5468 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
5469 &caller_count))
5470 return false;
5472 if (!dbg_cnt (ipa_cp_values))
5473 return false;
5475 if (dump_file && (dump_flags & TDF_DETAILS))
5477 fprintf (dump_file, " - considering value ");
5478 print_ipcp_constant_value (dump_file, val->value);
5479 fprintf (dump_file, " for ");
5480 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
5481 if (offset != -1)
5482 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
5483 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
5486 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
5487 freq_sum, count_sum,
5488 val->local_size_cost)
5489 && !good_cloning_opportunity_p (node,
5490 safe_add (val->local_time_benefit,
5491 val->prop_time_benefit),
5492 freq_sum, count_sum,
5493 safe_add (val->local_size_cost,
5494 val->prop_size_cost)))
5495 return false;
5497 if (dump_file)
5498 fprintf (dump_file, " Creating a specialized node of %s.\n",
5499 node->dump_name ());
5501 vec<tree> known_csts;
5502 vec<ipa_polymorphic_call_context> known_contexts;
5504 callers = gather_edges_for_value (val, node, caller_count);
5505 if (offset == -1)
5506 copy_known_vectors_add_val (avals, &known_csts, &known_contexts, val, index);
5507 else
5509 known_csts = avals->m_known_vals.copy ();
5510 known_contexts = copy_useful_known_contexts (avals->m_known_contexts);
5512 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
5513 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
5514 aggvals = find_aggregate_values_for_callers_subset (node, callers);
5515 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
5516 offset, val->value));
5517 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
5518 aggvals, callers);
5519 overall_size += val->local_size_cost;
5520 if (dump_file && (dump_flags & TDF_DETAILS))
5521 fprintf (dump_file, " overall size reached %li\n",
5522 overall_size);
5524 /* TODO: If for some lattice there is only one other known value
5525 left, make a special node for it too. */
5527 return true;
5530 /* Decide whether and what specialized clones of NODE should be created. */
5532 static bool
5533 decide_whether_version_node (struct cgraph_node *node)
5535 class ipa_node_params *info = IPA_NODE_REF (node);
5536 int i, count = ipa_get_param_count (info);
5537 bool ret = false;
5539 if (count == 0)
5540 return false;
5542 if (dump_file && (dump_flags & TDF_DETAILS))
5543 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
5544 node->dump_name ());
5546 ipa_auto_call_arg_values avals;
5547 gather_context_independent_values (info, &avals, false, NULL);
5549 for (i = 0; i < count;i++)
5551 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5552 ipcp_lattice<tree> *lat = &plats->itself;
5553 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
5555 if (!lat->bottom
5556 && !avals.m_known_vals[i])
5558 ipcp_value<tree> *val;
5559 for (val = lat->values; val; val = val->next)
5560 ret |= decide_about_value (node, i, -1, val, &avals);
5563 if (!plats->aggs_bottom)
5565 struct ipcp_agg_lattice *aglat;
5566 ipcp_value<tree> *val;
5567 for (aglat = plats->aggs; aglat; aglat = aglat->next)
5568 if (!aglat->bottom && aglat->values
5569 /* If the following is false, the one value has been considered
5570 for cloning for all contexts. */
5571 && (plats->aggs_contain_variable
5572 || !aglat->is_single_const ()))
5573 for (val = aglat->values; val; val = val->next)
5574 ret |= decide_about_value (node, i, aglat->offset, val, &avals);
5577 if (!ctxlat->bottom
5578 && avals.m_known_contexts[i].useless_p ())
5580 ipcp_value<ipa_polymorphic_call_context> *val;
5581 for (val = ctxlat->values; val; val = val->next)
5582 ret |= decide_about_value (node, i, -1, val, &avals);
5585 info = IPA_NODE_REF (node);
5588 if (info->do_clone_for_all_contexts)
5590 if (!dbg_cnt (ipa_cp_values))
5592 info->do_clone_for_all_contexts = false;
5593 return ret;
5596 struct cgraph_node *clone;
5597 vec<cgraph_edge *> callers = node->collect_callers ();
5599 for (int i = callers.length () - 1; i >= 0; i--)
5601 cgraph_edge *cs = callers[i];
5602 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5604 if (caller_info && caller_info->node_dead)
5605 callers.unordered_remove (i);
5608 if (!adjust_callers_for_value_intersection (callers, node))
5610 /* If node is not called by anyone, or all its caller edges are
5611 self-recursive, the node is not really in use, no need to do
5612 cloning. */
5613 callers.release ();
5614 info->do_clone_for_all_contexts = false;
5615 return ret;
5618 if (dump_file)
5619 fprintf (dump_file, " - Creating a specialized node of %s "
5620 "for all known contexts.\n", node->dump_name ());
5622 vec<tree> known_csts = avals.m_known_vals.copy ();
5623 vec<ipa_polymorphic_call_context> known_contexts
5624 = copy_useful_known_contexts (avals.m_known_contexts);
5625 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
5626 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
5627 ipa_agg_replacement_value *aggvals
5628 = find_aggregate_values_for_callers_subset (node, callers);
5630 if (!known_contexts_useful_p (known_contexts))
5632 known_contexts.release ();
5633 known_contexts = vNULL;
5635 clone = create_specialized_node (node, known_csts, known_contexts,
5636 aggvals, callers);
5637 info = IPA_NODE_REF (node);
5638 info->do_clone_for_all_contexts = false;
5639 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
5640 ret = true;
5643 return ret;
5646 /* Transitively mark all callees of NODE within the same SCC as not dead. */
5648 static void
5649 spread_undeadness (struct cgraph_node *node)
5651 struct cgraph_edge *cs;
5653 for (cs = node->callees; cs; cs = cs->next_callee)
5654 if (ipa_edge_within_scc (cs))
5656 struct cgraph_node *callee;
5657 class ipa_node_params *info;
5659 callee = cs->callee->function_symbol (NULL);
5660 info = IPA_NODE_REF (callee);
5662 if (info && info->node_dead)
5664 info->node_dead = 0;
5665 spread_undeadness (callee);
5670 /* Return true if NODE has a caller from outside of its SCC that is not
5671 dead. Worker callback for cgraph_for_node_and_aliases. */
5673 static bool
5674 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
5675 void *data ATTRIBUTE_UNUSED)
5677 struct cgraph_edge *cs;
5679 for (cs = node->callers; cs; cs = cs->next_caller)
5680 if (cs->caller->thunk
5681 && cs->caller->call_for_symbol_thunks_and_aliases
5682 (has_undead_caller_from_outside_scc_p, NULL, true))
5683 return true;
5684 else if (!ipa_edge_within_scc (cs)
5685 && (!IPA_NODE_REF (cs->caller) /* Unoptimized caller. */
5686 || !IPA_NODE_REF (cs->caller)->node_dead))
5687 return true;
5688 return false;
5692 /* Identify nodes within the same SCC as NODE which are no longer needed
5693 because of new clones and will be removed as unreachable. */
5695 static void
5696 identify_dead_nodes (struct cgraph_node *node)
5698 struct cgraph_node *v;
5699 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5700 if (v->local
5701 && IPA_NODE_REF (v)
5702 && !v->call_for_symbol_thunks_and_aliases
5703 (has_undead_caller_from_outside_scc_p, NULL, true))
5704 IPA_NODE_REF (v)->node_dead = 1;
5706 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5707 if (IPA_NODE_REF (v) && !IPA_NODE_REF (v)->node_dead)
5708 spread_undeadness (v);
5710 if (dump_file && (dump_flags & TDF_DETAILS))
5712 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5713 if (IPA_NODE_REF (v) && IPA_NODE_REF (v)->node_dead)
5714 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
5718 /* The decision stage. Iterate over the topological order of call graph nodes
5719 TOPO and make specialized clones if deemed beneficial. */
5721 static void
5722 ipcp_decision_stage (class ipa_topo_info *topo)
5724 int i;
5726 if (dump_file)
5727 fprintf (dump_file, "\nIPA decision stage:\n\n");
5729 for (i = topo->nnodes - 1; i >= 0; i--)
5731 struct cgraph_node *node = topo->order[i];
5732 bool change = false, iterate = true;
5734 while (iterate)
5736 struct cgraph_node *v;
5737 iterate = false;
5738 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5739 if (v->has_gimple_body_p ()
5740 && ipcp_versionable_function_p (v))
5741 iterate |= decide_whether_version_node (v);
5743 change |= iterate;
5745 if (change)
5746 identify_dead_nodes (node);
5750 /* Look up all the bits information that we have discovered and copy it over
5751 to the transformation summary. */
5753 static void
5754 ipcp_store_bits_results (void)
5756 cgraph_node *node;
5758 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5760 ipa_node_params *info = IPA_NODE_REF (node);
5761 bool dumped_sth = false;
5762 bool found_useful_result = false;
5764 if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
5766 if (dump_file)
5767 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
5768 "; -fipa-bit-cp: disabled.\n",
5769 node->dump_name ());
5770 continue;
5773 if (info->ipcp_orig_node)
5774 info = IPA_NODE_REF (info->ipcp_orig_node);
5775 if (!info->lattices)
5776 /* Newly expanded artificial thunks do not have lattices. */
5777 continue;
5779 unsigned count = ipa_get_param_count (info);
5780 for (unsigned i = 0; i < count; i++)
5782 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5783 if (plats->bits_lattice.constant_p ())
5785 found_useful_result = true;
5786 break;
5790 if (!found_useful_result)
5791 continue;
5793 ipcp_transformation_initialize ();
5794 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5795 vec_safe_reserve_exact (ts->bits, count);
5797 for (unsigned i = 0; i < count; i++)
5799 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5800 ipa_bits *jfbits;
5802 if (plats->bits_lattice.constant_p ())
5804 jfbits
5805 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
5806 plats->bits_lattice.get_mask ());
5807 if (!dbg_cnt (ipa_cp_bits))
5808 jfbits = NULL;
5810 else
5811 jfbits = NULL;
5813 ts->bits->quick_push (jfbits);
5814 if (!dump_file || !jfbits)
5815 continue;
5816 if (!dumped_sth)
5818 fprintf (dump_file, "Propagated bits info for function %s:\n",
5819 node->dump_name ());
5820 dumped_sth = true;
5822 fprintf (dump_file, " param %i: value = ", i);
5823 print_hex (jfbits->value, dump_file);
5824 fprintf (dump_file, ", mask = ");
5825 print_hex (jfbits->mask, dump_file);
5826 fprintf (dump_file, "\n");
5831 /* Look up all VR information that we have discovered and copy it over
5832 to the transformation summary. */
5834 static void
5835 ipcp_store_vr_results (void)
5837 cgraph_node *node;
5839 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5841 ipa_node_params *info = IPA_NODE_REF (node);
5842 bool found_useful_result = false;
5844 if (!info || !opt_for_fn (node->decl, flag_ipa_vrp))
5846 if (dump_file)
5847 fprintf (dump_file, "Not considering %s for VR discovery "
5848 "and propagate; -fipa-ipa-vrp: disabled.\n",
5849 node->dump_name ());
5850 continue;
5853 if (info->ipcp_orig_node)
5854 info = IPA_NODE_REF (info->ipcp_orig_node);
5855 if (!info->lattices)
5856 /* Newly expanded artificial thunks do not have lattices. */
5857 continue;
5859 unsigned count = ipa_get_param_count (info);
5860 for (unsigned i = 0; i < count; i++)
5862 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5863 if (!plats->m_value_range.bottom_p ()
5864 && !plats->m_value_range.top_p ())
5866 found_useful_result = true;
5867 break;
5870 if (!found_useful_result)
5871 continue;
5873 ipcp_transformation_initialize ();
5874 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5875 vec_safe_reserve_exact (ts->m_vr, count);
5877 for (unsigned i = 0; i < count; i++)
5879 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5880 ipa_vr vr;
5882 if (!plats->m_value_range.bottom_p ()
5883 && !plats->m_value_range.top_p ()
5884 && dbg_cnt (ipa_cp_vr))
5886 vr.known = true;
5887 vr.type = plats->m_value_range.m_vr.kind ();
5888 vr.min = wi::to_wide (plats->m_value_range.m_vr.min ());
5889 vr.max = wi::to_wide (plats->m_value_range.m_vr.max ());
5891 else
5893 vr.known = false;
5894 vr.type = VR_VARYING;
5895 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
5897 ts->m_vr->quick_push (vr);
5902 /* The IPCP driver. */
5904 static unsigned int
5905 ipcp_driver (void)
5907 class ipa_topo_info topo;
5909 if (edge_clone_summaries == NULL)
5910 edge_clone_summaries = new edge_clone_summary_t (symtab);
5912 ipa_check_create_node_params ();
5913 ipa_check_create_edge_args ();
5914 clone_num_suffixes = new hash_map<const char *, unsigned>;
5916 if (dump_file)
5918 fprintf (dump_file, "\nIPA structures before propagation:\n");
5919 if (dump_flags & TDF_DETAILS)
5920 ipa_print_all_params (dump_file);
5921 ipa_print_all_jump_functions (dump_file);
5924 /* Topological sort. */
5925 build_toporder_info (&topo);
5926 /* Do the interprocedural propagation. */
5927 ipcp_propagate_stage (&topo);
5928 /* Decide what constant propagation and cloning should be performed. */
5929 ipcp_decision_stage (&topo);
5930 /* Store results of bits propagation. */
5931 ipcp_store_bits_results ();
5932 /* Store results of value range propagation. */
5933 ipcp_store_vr_results ();
5935 /* Free all IPCP structures. */
5936 delete clone_num_suffixes;
5937 free_toporder_info (&topo);
5938 delete edge_clone_summaries;
5939 edge_clone_summaries = NULL;
5940 ipa_free_all_structures_after_ipa_cp ();
5941 if (dump_file)
5942 fprintf (dump_file, "\nIPA constant propagation end\n");
5943 return 0;
5946 /* Initialization and computation of IPCP data structures. This is the initial
5947 intraprocedural analysis of functions, which gathers information to be
5948 propagated later on. */
5950 static void
5951 ipcp_generate_summary (void)
5953 struct cgraph_node *node;
5955 if (dump_file)
5956 fprintf (dump_file, "\nIPA constant propagation start:\n");
5957 ipa_register_cgraph_hooks ();
5959 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5960 ipa_analyze_node (node);
5963 namespace {
5965 const pass_data pass_data_ipa_cp =
5967 IPA_PASS, /* type */
5968 "cp", /* name */
5969 OPTGROUP_NONE, /* optinfo_flags */
5970 TV_IPA_CONSTANT_PROP, /* tv_id */
5971 0, /* properties_required */
5972 0, /* properties_provided */
5973 0, /* properties_destroyed */
5974 0, /* todo_flags_start */
5975 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
5978 class pass_ipa_cp : public ipa_opt_pass_d
5980 public:
5981 pass_ipa_cp (gcc::context *ctxt)
5982 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
5983 ipcp_generate_summary, /* generate_summary */
5984 NULL, /* write_summary */
5985 NULL, /* read_summary */
5986 ipcp_write_transformation_summaries, /*
5987 write_optimization_summary */
5988 ipcp_read_transformation_summaries, /*
5989 read_optimization_summary */
5990 NULL, /* stmt_fixup */
5991 0, /* function_transform_todo_flags_start */
5992 ipcp_transform_function, /* function_transform */
5993 NULL) /* variable_transform */
5996 /* opt_pass methods: */
5997 virtual bool gate (function *)
5999 /* FIXME: We should remove the optimize check after we ensure we never run
6000 IPA passes when not optimizing. */
6001 return (flag_ipa_cp && optimize) || in_lto_p;
6004 virtual unsigned int execute (function *) { return ipcp_driver (); }
6006 }; // class pass_ipa_cp
6008 } // anon namespace
6010 ipa_opt_pass_d *
6011 make_pass_ipa_cp (gcc::context *ctxt)
6013 return new pass_ipa_cp (ctxt);
6016 /* Reset all state within ipa-cp.c so that we can rerun the compiler
6017 within the same process. For use by toplev::finalize. */
6019 void
6020 ipa_cp_c_finalize (void)
6022 max_count = profile_count::uninitialized ();
6023 overall_size = 0;
6024 orig_overall_size = 0;
6025 ipcp_free_transformation_sum ();