MAINTAINERS: Add myself as arc port maintainer
[official-gcc.git] / gcc / ipa-cp.c
bloba06b4d151dd7d0bcaa7caa7be10ef3d4c252251f
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 that specializing the function for this value would bring
160 about in this function alone. */
161 sreal local_time_benefit;
162 /* Time benefit that specializing the function for this value can bring about
163 in it's callees. */
164 sreal prop_time_benefit;
165 /* Size cost that specializing the function for this value would bring about
166 in this function alone. */
167 int local_size_cost;
168 /* Size cost that specializing the function for this value can bring about in
169 it's callees. */
170 int prop_size_cost;
172 ipcp_value_base ()
173 : local_time_benefit (0), prop_time_benefit (0),
174 local_size_cost (0), prop_size_cost (0) {}
177 /* Describes one particular value stored in struct ipcp_lattice. */
179 template <typename valtype>
180 class ipcp_value : public ipcp_value_base
182 public:
183 /* The actual value for the given parameter. */
184 valtype value;
185 /* The list of sources from which this value originates. */
186 ipcp_value_source <valtype> *sources;
187 /* Next pointers in a linked list of all values in a lattice. */
188 ipcp_value *next;
189 /* Next pointers in a linked list of values in a strongly connected component
190 of values. */
191 ipcp_value *scc_next;
192 /* Next pointers in a linked list of SCCs of values sorted topologically
193 according their sources. */
194 ipcp_value *topo_next;
195 /* A specialized node created for this value, NULL if none has been (so far)
196 created. */
197 cgraph_node *spec_node;
198 /* Depth first search number and low link for topological sorting of
199 values. */
200 int dfs, low_link;
201 /* True if this value is currently on the topo-sort stack. */
202 bool on_stack;
204 ipcp_value()
205 : sources (0), next (0), scc_next (0), topo_next (0),
206 spec_node (0), dfs (0), low_link (0), on_stack (false) {}
208 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
209 HOST_WIDE_INT offset);
212 /* Lattice describing potential values of a formal parameter of a function, or
213 a part of an aggregate. TOP is represented by a lattice with zero values
214 and with contains_variable and bottom flags cleared. BOTTOM is represented
215 by a lattice with the bottom flag set. In that case, values and
216 contains_variable flag should be disregarded. */
218 template <typename valtype>
219 struct ipcp_lattice
221 public:
222 /* The list of known values and types in this lattice. Note that values are
223 not deallocated if a lattice is set to bottom because there may be value
224 sources referencing them. */
225 ipcp_value<valtype> *values;
226 /* Number of known values and types in this lattice. */
227 int values_count;
228 /* The lattice contains a variable component (in addition to values). */
229 bool contains_variable;
230 /* The value of the lattice is bottom (i.e. variable and unusable for any
231 propagation). */
232 bool bottom;
234 inline bool is_single_const ();
235 inline bool set_to_bottom ();
236 inline bool set_contains_variable ();
237 bool add_value (valtype newval, cgraph_edge *cs,
238 ipcp_value<valtype> *src_val = NULL,
239 int src_idx = 0, HOST_WIDE_INT offset = -1,
240 ipcp_value<valtype> **val_p = NULL,
241 bool unlimited = false);
242 void print (FILE * f, bool dump_sources, bool dump_benefits);
245 /* Lattice of tree values with an offset to describe a part of an
246 aggregate. */
248 struct ipcp_agg_lattice : public ipcp_lattice<tree>
250 public:
251 /* Offset that is being described by this lattice. */
252 HOST_WIDE_INT offset;
253 /* Size so that we don't have to re-compute it every time we traverse the
254 list. Must correspond to TYPE_SIZE of all lat values. */
255 HOST_WIDE_INT size;
256 /* Next element of the linked list. */
257 struct ipcp_agg_lattice *next;
260 /* Lattice of known bits, only capable of holding one value.
261 Bitwise constant propagation propagates which bits of a
262 value are constant.
263 For eg:
264 int f(int x)
266 return some_op (x);
269 int f1(int y)
271 if (cond)
272 return f (y & 0xff);
273 else
274 return f (y & 0xf);
277 In the above case, the param 'x' will always have all
278 the bits (except the bits in lsb) set to 0.
279 Hence the mask of 'x' would be 0xff. The mask
280 reflects that the bits in lsb are unknown.
281 The actual propagated value is given by m_value & ~m_mask. */
283 class ipcp_bits_lattice
285 public:
286 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; }
287 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; }
288 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; }
289 bool set_to_bottom ();
290 bool set_to_constant (widest_int, widest_int);
292 widest_int get_value () { return m_value; }
293 widest_int get_mask () { return m_mask; }
295 bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
296 enum tree_code, tree);
298 bool meet_with (widest_int, widest_int, unsigned);
300 void print (FILE *);
302 private:
303 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
305 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
306 If a bit in mask is set to 0, then the corresponding bit in
307 value is known to be constant. */
308 widest_int m_value, m_mask;
310 bool meet_with_1 (widest_int, widest_int, unsigned);
311 void get_value_and_mask (tree, widest_int *, widest_int *);
314 /* Lattice of value ranges. */
316 class ipcp_vr_lattice
318 public:
319 value_range m_vr;
321 inline bool bottom_p () const;
322 inline bool top_p () const;
323 inline bool set_to_bottom ();
324 bool meet_with (const value_range *p_vr);
325 bool meet_with (const ipcp_vr_lattice &other);
326 void init () { gcc_assert (m_vr.undefined_p ()); }
327 void print (FILE * f);
329 private:
330 bool meet_with_1 (const value_range *other_vr);
333 /* Structure containing lattices for a parameter itself and for pieces of
334 aggregates that are passed in the parameter or by a reference in a parameter
335 plus some other useful flags. */
337 class ipcp_param_lattices
339 public:
340 /* Lattice describing the value of the parameter itself. */
341 ipcp_lattice<tree> itself;
342 /* Lattice describing the polymorphic contexts of a parameter. */
343 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
344 /* Lattices describing aggregate parts. */
345 ipcp_agg_lattice *aggs;
346 /* Lattice describing known bits. */
347 ipcp_bits_lattice bits_lattice;
348 /* Lattice describing value range. */
349 ipcp_vr_lattice m_value_range;
350 /* Number of aggregate lattices */
351 int aggs_count;
352 /* True if aggregate data were passed by reference (as opposed to by
353 value). */
354 bool aggs_by_ref;
355 /* All aggregate lattices contain a variable component (in addition to
356 values). */
357 bool aggs_contain_variable;
358 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
359 for any propagation). */
360 bool aggs_bottom;
362 /* There is a virtual call based on this parameter. */
363 bool virt_call;
366 /* Allocation pools for values and their sources in ipa-cp. */
368 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
369 ("IPA-CP constant values");
371 object_allocator<ipcp_value<ipa_polymorphic_call_context> >
372 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
374 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
375 ("IPA-CP value sources");
377 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
378 ("IPA_CP aggregate lattices");
380 /* Maximal count found in program. */
382 static profile_count max_count;
384 /* Original overall size of the program. */
386 static long overall_size, orig_overall_size;
388 /* Node name to unique clone suffix number map. */
389 static hash_map<const char *, unsigned> *clone_num_suffixes;
391 /* Return the param lattices structure corresponding to the Ith formal
392 parameter of the function described by INFO. */
393 static inline class ipcp_param_lattices *
394 ipa_get_parm_lattices (class ipa_node_params *info, int i)
396 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
397 gcc_checking_assert (!info->ipcp_orig_node);
398 gcc_checking_assert (info->lattices);
399 return &(info->lattices[i]);
402 /* Return the lattice corresponding to the scalar value of the Ith formal
403 parameter of the function described by INFO. */
404 static inline ipcp_lattice<tree> *
405 ipa_get_scalar_lat (class ipa_node_params *info, int i)
407 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
408 return &plats->itself;
411 /* Return the lattice corresponding to the scalar value of the Ith formal
412 parameter of the function described by INFO. */
413 static inline ipcp_lattice<ipa_polymorphic_call_context> *
414 ipa_get_poly_ctx_lat (class ipa_node_params *info, int i)
416 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
417 return &plats->ctxlat;
420 /* Return whether LAT is a lattice with a single constant and without an
421 undefined value. */
423 template <typename valtype>
424 inline bool
425 ipcp_lattice<valtype>::is_single_const ()
427 if (bottom || contains_variable || values_count != 1)
428 return false;
429 else
430 return true;
433 /* Print V which is extracted from a value in a lattice to F. */
435 static void
436 print_ipcp_constant_value (FILE * f, tree v)
438 if (TREE_CODE (v) == ADDR_EXPR
439 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
441 fprintf (f, "& ");
442 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)));
444 else
445 print_generic_expr (f, v);
448 /* Print V which is extracted from a value in a lattice to F. */
450 static void
451 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
453 v.dump(f, false);
456 /* Print a lattice LAT to F. */
458 template <typename valtype>
459 void
460 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
462 ipcp_value<valtype> *val;
463 bool prev = false;
465 if (bottom)
467 fprintf (f, "BOTTOM\n");
468 return;
471 if (!values_count && !contains_variable)
473 fprintf (f, "TOP\n");
474 return;
477 if (contains_variable)
479 fprintf (f, "VARIABLE");
480 prev = true;
481 if (dump_benefits)
482 fprintf (f, "\n");
485 for (val = values; val; val = val->next)
487 if (dump_benefits && prev)
488 fprintf (f, " ");
489 else if (!dump_benefits && prev)
490 fprintf (f, ", ");
491 else
492 prev = true;
494 print_ipcp_constant_value (f, val->value);
496 if (dump_sources)
498 ipcp_value_source<valtype> *s;
500 fprintf (f, " [from:");
501 for (s = val->sources; s; s = s->next)
502 fprintf (f, " %i(%f)", s->cs->caller->order,
503 s->cs->sreal_frequency ().to_double ());
504 fprintf (f, "]");
507 if (dump_benefits)
508 fprintf (f, " [loc_time: %g, loc_size: %i, "
509 "prop_time: %g, prop_size: %i]\n",
510 val->local_time_benefit.to_double (), val->local_size_cost,
511 val->prop_time_benefit.to_double (), val->prop_size_cost);
513 if (!dump_benefits)
514 fprintf (f, "\n");
517 void
518 ipcp_bits_lattice::print (FILE *f)
520 if (top_p ())
521 fprintf (f, " Bits unknown (TOP)\n");
522 else if (bottom_p ())
523 fprintf (f, " Bits unusable (BOTTOM)\n");
524 else
526 fprintf (f, " Bits: value = "); print_hex (get_value (), f);
527 fprintf (f, ", mask = "); print_hex (get_mask (), f);
528 fprintf (f, "\n");
532 /* Print value range lattice to F. */
534 void
535 ipcp_vr_lattice::print (FILE * f)
537 dump_value_range (f, &m_vr);
540 /* Print all ipcp_lattices of all functions to F. */
542 static void
543 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
545 struct cgraph_node *node;
546 int i, count;
548 fprintf (f, "\nLattices:\n");
549 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
551 class ipa_node_params *info;
553 info = IPA_NODE_REF (node);
554 /* Skip unoptimized functions and constprop clones since we don't make
555 lattices for them. */
556 if (!info || info->ipcp_orig_node)
557 continue;
558 fprintf (f, " Node: %s:\n", node->dump_name ());
559 count = ipa_get_param_count (info);
560 for (i = 0; i < count; i++)
562 struct ipcp_agg_lattice *aglat;
563 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
564 fprintf (f, " param [%d]: ", i);
565 plats->itself.print (f, dump_sources, dump_benefits);
566 fprintf (f, " ctxs: ");
567 plats->ctxlat.print (f, dump_sources, dump_benefits);
568 plats->bits_lattice.print (f);
569 fprintf (f, " ");
570 plats->m_value_range.print (f);
571 fprintf (f, "\n");
572 if (plats->virt_call)
573 fprintf (f, " virt_call flag set\n");
575 if (plats->aggs_bottom)
577 fprintf (f, " AGGS BOTTOM\n");
578 continue;
580 if (plats->aggs_contain_variable)
581 fprintf (f, " AGGS VARIABLE\n");
582 for (aglat = plats->aggs; aglat; aglat = aglat->next)
584 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
585 plats->aggs_by_ref ? "ref " : "", aglat->offset);
586 aglat->print (f, dump_sources, dump_benefits);
592 /* Determine whether it is at all technically possible to create clones of NODE
593 and store this information in the ipa_node_params structure associated
594 with NODE. */
596 static void
597 determine_versionability (struct cgraph_node *node,
598 class ipa_node_params *info)
600 const char *reason = NULL;
602 /* There are a number of generic reasons functions cannot be versioned. We
603 also cannot remove parameters if there are type attributes such as fnspec
604 present. */
605 if (node->alias || node->thunk)
606 reason = "alias or thunk";
607 else if (!node->versionable)
608 reason = "not a tree_versionable_function";
609 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
610 reason = "insufficient body availability";
611 else if (!opt_for_fn (node->decl, optimize)
612 || !opt_for_fn (node->decl, flag_ipa_cp))
613 reason = "non-optimized function";
614 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
616 /* Ideally we should clone the SIMD clones themselves and create
617 vector copies of them, so IPA-cp and SIMD clones can happily
618 coexist, but that may not be worth the effort. */
619 reason = "function has SIMD clones";
621 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)))
623 /* Ideally we should clone the target clones themselves and create
624 copies of them, so IPA-cp and target clones can happily
625 coexist, but that may not be worth the effort. */
626 reason = "function target_clones attribute";
628 /* Don't clone decls local to a comdat group; it breaks and for C++
629 decloned constructors, inlining is always better anyway. */
630 else if (node->comdat_local_p ())
631 reason = "comdat-local function";
632 else if (node->calls_comdat_local)
634 /* TODO: call is versionable if we make sure that all
635 callers are inside of a comdat group. */
636 reason = "calls comdat-local function";
639 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
640 work only when inlined. Cloning them may still lead to better code
641 because ipa-cp will not give up on cloning further. If the function is
642 external this however leads to wrong code because we may end up producing
643 offline copy of the function. */
644 if (DECL_EXTERNAL (node->decl))
645 for (cgraph_edge *edge = node->callees; !reason && edge;
646 edge = edge->next_callee)
647 if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL))
649 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
650 reason = "external function which calls va_arg_pack";
651 if (DECL_FUNCTION_CODE (edge->callee->decl)
652 == BUILT_IN_VA_ARG_PACK_LEN)
653 reason = "external function which calls va_arg_pack_len";
656 if (reason && dump_file && !node->alias && !node->thunk)
657 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n",
658 node->dump_name (), reason);
660 info->versionable = (reason == NULL);
663 /* Return true if it is at all technically possible to create clones of a
664 NODE. */
666 static bool
667 ipcp_versionable_function_p (struct cgraph_node *node)
669 return IPA_NODE_REF (node) && IPA_NODE_REF (node)->versionable;
672 /* Structure holding accumulated information about callers of a node. */
674 struct caller_statistics
676 profile_count count_sum;
677 sreal freq_sum;
678 int n_calls, n_hot_calls;
681 /* Initialize fields of STAT to zeroes. */
683 static inline void
684 init_caller_stats (struct caller_statistics *stats)
686 stats->count_sum = profile_count::zero ();
687 stats->n_calls = 0;
688 stats->n_hot_calls = 0;
689 stats->freq_sum = 0;
692 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
693 non-thunk incoming edges to NODE. */
695 static bool
696 gather_caller_stats (struct cgraph_node *node, void *data)
698 struct caller_statistics *stats = (struct caller_statistics *) data;
699 struct cgraph_edge *cs;
701 for (cs = node->callers; cs; cs = cs->next_caller)
702 if (!cs->caller->thunk)
704 if (cs->count.ipa ().initialized_p ())
705 stats->count_sum += cs->count.ipa ();
706 stats->freq_sum += cs->sreal_frequency ();
707 stats->n_calls++;
708 if (cs->maybe_hot_p ())
709 stats->n_hot_calls ++;
711 return false;
715 /* Return true if this NODE is viable candidate for cloning. */
717 static bool
718 ipcp_cloning_candidate_p (struct cgraph_node *node)
720 struct caller_statistics stats;
722 gcc_checking_assert (node->has_gimple_body_p ());
724 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
726 if (dump_file)
727 fprintf (dump_file, "Not considering %s for cloning; "
728 "-fipa-cp-clone disabled.\n",
729 node->dump_name ());
730 return false;
733 if (node->optimize_for_size_p ())
735 if (dump_file)
736 fprintf (dump_file, "Not considering %s for cloning; "
737 "optimizing it for size.\n",
738 node->dump_name ());
739 return false;
742 init_caller_stats (&stats);
743 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
745 if (ipa_size_summaries->get (node)->self_size < stats.n_calls)
747 if (dump_file)
748 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
749 node->dump_name ());
750 return true;
753 /* When profile is available and function is hot, propagate into it even if
754 calls seems cold; constant propagation can improve function's speed
755 significantly. */
756 if (max_count > profile_count::zero ())
758 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100))
760 if (dump_file)
761 fprintf (dump_file, "Considering %s for cloning; "
762 "usually called directly.\n",
763 node->dump_name ());
764 return true;
767 if (!stats.n_hot_calls)
769 if (dump_file)
770 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
771 node->dump_name ());
772 return false;
774 if (dump_file)
775 fprintf (dump_file, "Considering %s for cloning.\n",
776 node->dump_name ());
777 return true;
780 template <typename valtype>
781 class value_topo_info
783 public:
784 /* Head of the linked list of topologically sorted values. */
785 ipcp_value<valtype> *values_topo;
786 /* Stack for creating SCCs, represented by a linked list too. */
787 ipcp_value<valtype> *stack;
788 /* Counter driving the algorithm in add_val_to_toposort. */
789 int dfs_counter;
791 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
793 void add_val (ipcp_value<valtype> *cur_val);
794 void propagate_effects ();
797 /* Arrays representing a topological ordering of call graph nodes and a stack
798 of nodes used during constant propagation and also data required to perform
799 topological sort of values and propagation of benefits in the determined
800 order. */
802 class ipa_topo_info
804 public:
805 /* Array with obtained topological order of cgraph nodes. */
806 struct cgraph_node **order;
807 /* Stack of cgraph nodes used during propagation within SCC until all values
808 in the SCC stabilize. */
809 struct cgraph_node **stack;
810 int nnodes, stack_top;
812 value_topo_info<tree> constants;
813 value_topo_info<ipa_polymorphic_call_context> contexts;
815 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
816 constants ()
820 /* Skip edges from and to nodes without ipa_cp enabled.
821 Ignore not available symbols. */
823 static bool
824 ignore_edge_p (cgraph_edge *e)
826 enum availability avail;
827 cgraph_node *ultimate_target
828 = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
830 return (avail <= AVAIL_INTERPOSABLE
831 || !opt_for_fn (ultimate_target->decl, optimize)
832 || !opt_for_fn (ultimate_target->decl, flag_ipa_cp));
835 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
837 static void
838 build_toporder_info (class ipa_topo_info *topo)
840 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
841 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
843 gcc_checking_assert (topo->stack_top == 0);
844 topo->nnodes = ipa_reduced_postorder (topo->order, true,
845 ignore_edge_p);
848 /* Free information about strongly connected components and the arrays in
849 TOPO. */
851 static void
852 free_toporder_info (class ipa_topo_info *topo)
854 ipa_free_postorder_info ();
855 free (topo->order);
856 free (topo->stack);
859 /* Add NODE to the stack in TOPO, unless it is already there. */
861 static inline void
862 push_node_to_stack (class ipa_topo_info *topo, struct cgraph_node *node)
864 class ipa_node_params *info = IPA_NODE_REF (node);
865 if (info->node_enqueued)
866 return;
867 info->node_enqueued = 1;
868 topo->stack[topo->stack_top++] = node;
871 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
872 is empty. */
874 static struct cgraph_node *
875 pop_node_from_stack (class ipa_topo_info *topo)
877 if (topo->stack_top)
879 struct cgraph_node *node;
880 topo->stack_top--;
881 node = topo->stack[topo->stack_top];
882 IPA_NODE_REF (node)->node_enqueued = 0;
883 return node;
885 else
886 return NULL;
889 /* Set lattice LAT to bottom and return true if it previously was not set as
890 such. */
892 template <typename valtype>
893 inline bool
894 ipcp_lattice<valtype>::set_to_bottom ()
896 bool ret = !bottom;
897 bottom = true;
898 return ret;
901 /* Mark lattice as containing an unknown value and return true if it previously
902 was not marked as such. */
904 template <typename valtype>
905 inline bool
906 ipcp_lattice<valtype>::set_contains_variable ()
908 bool ret = !contains_variable;
909 contains_variable = true;
910 return ret;
913 /* Set all aggregate lattices in PLATS to bottom and return true if they were
914 not previously set as such. */
916 static inline bool
917 set_agg_lats_to_bottom (class ipcp_param_lattices *plats)
919 bool ret = !plats->aggs_bottom;
920 plats->aggs_bottom = true;
921 return ret;
924 /* Mark all aggregate lattices in PLATS as containing an unknown value and
925 return true if they were not previously marked as such. */
927 static inline bool
928 set_agg_lats_contain_variable (class ipcp_param_lattices *plats)
930 bool ret = !plats->aggs_contain_variable;
931 plats->aggs_contain_variable = true;
932 return ret;
935 bool
936 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
938 return meet_with_1 (&other.m_vr);
941 /* Meet the current value of the lattice with value range described by VR
942 lattice. */
944 bool
945 ipcp_vr_lattice::meet_with (const value_range *p_vr)
947 return meet_with_1 (p_vr);
950 /* Meet the current value of the lattice with value range described by
951 OTHER_VR lattice. Return TRUE if anything changed. */
953 bool
954 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
956 if (bottom_p ())
957 return false;
959 if (other_vr->varying_p ())
960 return set_to_bottom ();
962 value_range save (m_vr);
963 m_vr.union_ (other_vr);
964 return !m_vr.equal_p (save);
967 /* Return true if value range information in the lattice is yet unknown. */
969 bool
970 ipcp_vr_lattice::top_p () const
972 return m_vr.undefined_p ();
975 /* Return true if value range information in the lattice is known to be
976 unusable. */
978 bool
979 ipcp_vr_lattice::bottom_p () const
981 return m_vr.varying_p ();
984 /* Set value range information in the lattice to bottom. Return true if it
985 previously was in a different state. */
987 bool
988 ipcp_vr_lattice::set_to_bottom ()
990 if (m_vr.varying_p ())
991 return false;
992 /* ?? We create all sorts of VARYING ranges for floats, structures,
993 and other types which we cannot handle as ranges. We should
994 probably avoid handling them throughout the pass, but it's easier
995 to create a sensible VARYING here and let the lattice
996 propagate. */
997 m_vr.set_varying (integer_type_node);
998 return true;
1001 /* Set lattice value to bottom, if it already isn't the case. */
1003 bool
1004 ipcp_bits_lattice::set_to_bottom ()
1006 if (bottom_p ())
1007 return false;
1008 m_lattice_val = IPA_BITS_VARYING;
1009 m_value = 0;
1010 m_mask = -1;
1011 return true;
1014 /* Set to constant if it isn't already. Only meant to be called
1015 when switching state from TOP. */
1017 bool
1018 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask)
1020 gcc_assert (top_p ());
1021 m_lattice_val = IPA_BITS_CONSTANT;
1022 m_value = wi::bit_and (wi::bit_not (mask), value);
1023 m_mask = mask;
1024 return true;
1027 /* Convert operand to value, mask form. */
1029 void
1030 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp)
1032 wide_int get_nonzero_bits (const_tree);
1034 if (TREE_CODE (operand) == INTEGER_CST)
1036 *valuep = wi::to_widest (operand);
1037 *maskp = 0;
1039 else
1041 *valuep = 0;
1042 *maskp = -1;
1046 /* Meet operation, similar to ccp_lattice_meet, we xor values
1047 if this->value, value have different values at same bit positions, we want
1048 to drop that bit to varying. Return true if mask is changed.
1049 This function assumes that the lattice value is in CONSTANT state */
1051 bool
1052 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask,
1053 unsigned precision)
1055 gcc_assert (constant_p ());
1057 widest_int old_mask = m_mask;
1058 m_mask = (m_mask | mask) | (m_value ^ value);
1059 m_value &= ~m_mask;
1061 if (wi::sext (m_mask, precision) == -1)
1062 return set_to_bottom ();
1064 return m_mask != old_mask;
1067 /* Meet the bits lattice with operand
1068 described by <value, mask, sgn, precision. */
1070 bool
1071 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask,
1072 unsigned precision)
1074 if (bottom_p ())
1075 return false;
1077 if (top_p ())
1079 if (wi::sext (mask, precision) == -1)
1080 return set_to_bottom ();
1081 return set_to_constant (value, mask);
1084 return meet_with_1 (value, mask, precision);
1087 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1088 if code is binary operation or bit_value_unop (other) if code is unary op.
1089 In the case when code is nop_expr, no adjustment is required. */
1091 bool
1092 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
1093 signop sgn, enum tree_code code, tree operand)
1095 if (other.bottom_p ())
1096 return set_to_bottom ();
1098 if (bottom_p () || other.top_p ())
1099 return false;
1101 widest_int adjusted_value, adjusted_mask;
1103 if (TREE_CODE_CLASS (code) == tcc_binary)
1105 tree type = TREE_TYPE (operand);
1106 widest_int o_value, o_mask;
1107 get_value_and_mask (operand, &o_value, &o_mask);
1109 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask,
1110 sgn, precision, other.get_value (), other.get_mask (),
1111 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask);
1113 if (wi::sext (adjusted_mask, precision) == -1)
1114 return set_to_bottom ();
1117 else if (TREE_CODE_CLASS (code) == tcc_unary)
1119 bit_value_unop (code, sgn, precision, &adjusted_value,
1120 &adjusted_mask, sgn, precision, other.get_value (),
1121 other.get_mask ());
1123 if (wi::sext (adjusted_mask, precision) == -1)
1124 return set_to_bottom ();
1127 else
1128 return set_to_bottom ();
1130 if (top_p ())
1132 if (wi::sext (adjusted_mask, precision) == -1)
1133 return set_to_bottom ();
1134 return set_to_constant (adjusted_value, adjusted_mask);
1136 else
1137 return meet_with_1 (adjusted_value, adjusted_mask, precision);
1140 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1141 return true is any of them has not been marked as such so far. */
1143 static inline bool
1144 set_all_contains_variable (class ipcp_param_lattices *plats)
1146 bool ret;
1147 ret = plats->itself.set_contains_variable ();
1148 ret |= plats->ctxlat.set_contains_variable ();
1149 ret |= set_agg_lats_contain_variable (plats);
1150 ret |= plats->bits_lattice.set_to_bottom ();
1151 ret |= plats->m_value_range.set_to_bottom ();
1152 return ret;
1155 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1156 points to by the number of callers to NODE. */
1158 static bool
1159 count_callers (cgraph_node *node, void *data)
1161 int *caller_count = (int *) data;
1163 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
1164 /* Local thunks can be handled transparently, but if the thunk cannot
1165 be optimized out, count it as a real use. */
1166 if (!cs->caller->thunk || !cs->caller->local)
1167 ++*caller_count;
1168 return false;
1171 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1172 the one caller of some other node. Set the caller's corresponding flag. */
1174 static bool
1175 set_single_call_flag (cgraph_node *node, void *)
1177 cgraph_edge *cs = node->callers;
1178 /* Local thunks can be handled transparently, skip them. */
1179 while (cs && cs->caller->thunk && cs->caller->local)
1180 cs = cs->next_caller;
1181 if (cs && IPA_NODE_REF (cs->caller))
1183 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
1184 return true;
1186 return false;
1189 /* Initialize ipcp_lattices. */
1191 static void
1192 initialize_node_lattices (struct cgraph_node *node)
1194 class ipa_node_params *info = IPA_NODE_REF (node);
1195 struct cgraph_edge *ie;
1196 bool disable = false, variable = false;
1197 int i;
1199 gcc_checking_assert (node->has_gimple_body_p ());
1201 if (!ipa_get_param_count (info))
1202 disable = true;
1203 else if (node->local)
1205 int caller_count = 0;
1206 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
1207 true);
1208 gcc_checking_assert (caller_count > 0);
1209 if (caller_count == 1)
1210 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
1211 NULL, true);
1213 else
1215 /* When cloning is allowed, we can assume that externally visible
1216 functions are not called. We will compensate this by cloning
1217 later. */
1218 if (ipcp_versionable_function_p (node)
1219 && ipcp_cloning_candidate_p (node))
1220 variable = true;
1221 else
1222 disable = true;
1225 if (dump_file && (dump_flags & TDF_DETAILS)
1226 && !node->alias && !node->thunk)
1228 fprintf (dump_file, "Initializing lattices of %s\n",
1229 node->dump_name ());
1230 if (disable || variable)
1231 fprintf (dump_file, " Marking all lattices as %s\n",
1232 disable ? "BOTTOM" : "VARIABLE");
1235 auto_vec<bool, 16> surviving_params;
1236 bool pre_modified = false;
1238 clone_info *cinfo = clone_info::get (node);
1240 if (!disable && cinfo && cinfo->param_adjustments)
1242 /* At the moment all IPA optimizations should use the number of
1243 parameters of the prevailing decl as the m_always_copy_start.
1244 Handling any other value would complicate the code below, so for the
1245 time bing let's only assert it is so. */
1246 gcc_assert ((cinfo->param_adjustments->m_always_copy_start
1247 == ipa_get_param_count (info))
1248 || cinfo->param_adjustments->m_always_copy_start < 0);
1250 pre_modified = true;
1251 cinfo->param_adjustments->get_surviving_params (&surviving_params);
1253 if (dump_file && (dump_flags & TDF_DETAILS)
1254 && !node->alias && !node->thunk)
1256 bool first = true;
1257 for (int j = 0; j < ipa_get_param_count (info); j++)
1259 if (j < (int) surviving_params.length ()
1260 && surviving_params[j])
1261 continue;
1262 if (first)
1264 fprintf (dump_file,
1265 " The following parameters are dead on arrival:");
1266 first = false;
1268 fprintf (dump_file, " %u", j);
1270 if (!first)
1271 fprintf (dump_file, "\n");
1275 for (i = 0; i < ipa_get_param_count (info); i++)
1277 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
1278 if (disable
1279 || (pre_modified && (surviving_params.length () <= (unsigned) i
1280 || !surviving_params[i])))
1282 plats->itself.set_to_bottom ();
1283 plats->ctxlat.set_to_bottom ();
1284 set_agg_lats_to_bottom (plats);
1285 plats->bits_lattice.set_to_bottom ();
1286 plats->m_value_range.m_vr = value_range ();
1287 plats->m_value_range.set_to_bottom ();
1289 else
1291 plats->m_value_range.init ();
1292 if (variable)
1293 set_all_contains_variable (plats);
1297 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1298 if (ie->indirect_info->polymorphic
1299 && ie->indirect_info->param_index >= 0)
1301 gcc_checking_assert (ie->indirect_info->param_index >= 0);
1302 ipa_get_parm_lattices (info,
1303 ie->indirect_info->param_index)->virt_call = 1;
1307 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1309 static bool
1310 values_equal_for_ipcp_p (tree x, tree y)
1312 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1314 if (x == y)
1315 return true;
1317 if (TREE_CODE (x) == ADDR_EXPR
1318 && TREE_CODE (y) == ADDR_EXPR
1319 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1320 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1321 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1322 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1323 else
1324 return operand_equal_p (x, y, 0);
1327 /* Return the result of a (possibly arithmetic) operation on the constant
1328 value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is
1329 the type of the parameter to which the result is passed. Return
1330 NULL_TREE if that cannot be determined or be considered an
1331 interprocedural invariant. */
1333 static tree
1334 ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand,
1335 tree res_type)
1337 tree res;
1339 if (opcode == NOP_EXPR)
1340 return input;
1341 if (!is_gimple_ip_invariant (input))
1342 return NULL_TREE;
1344 if (opcode == ASSERT_EXPR)
1346 if (values_equal_for_ipcp_p (input, operand))
1347 return input;
1348 else
1349 return NULL_TREE;
1352 if (!res_type)
1354 if (TREE_CODE_CLASS (opcode) == tcc_comparison)
1355 res_type = boolean_type_node;
1356 else if (expr_type_first_operand_type_p (opcode))
1357 res_type = TREE_TYPE (input);
1358 else
1359 return NULL_TREE;
1362 if (TREE_CODE_CLASS (opcode) == tcc_unary)
1363 res = fold_unary (opcode, res_type, input);
1364 else
1365 res = fold_binary (opcode, res_type, input, operand);
1367 if (res && !is_gimple_ip_invariant (res))
1368 return NULL_TREE;
1370 return res;
1373 /* Return the result of a (possibly arithmetic) pass through jump function
1374 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter
1375 to which the result is passed. Return NULL_TREE if that cannot be
1376 determined or be considered an interprocedural invariant. */
1378 static tree
1379 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input,
1380 tree res_type)
1382 return ipa_get_jf_arith_result (ipa_get_jf_pass_through_operation (jfunc),
1383 input,
1384 ipa_get_jf_pass_through_operand (jfunc),
1385 res_type);
1388 /* Return the result of an ancestor jump function JFUNC on the constant value
1389 INPUT. Return NULL_TREE if that cannot be determined. */
1391 static tree
1392 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1394 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1395 if (TREE_CODE (input) == ADDR_EXPR)
1397 gcc_checking_assert (is_gimple_ip_invariant_address (input));
1398 poly_int64 off = ipa_get_jf_ancestor_offset (jfunc);
1399 if (known_eq (off, 0))
1400 return input;
1401 poly_int64 byte_offset = exact_div (off, BITS_PER_UNIT);
1402 return build1 (ADDR_EXPR, TREE_TYPE (input),
1403 fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (input)), input,
1404 build_int_cst (ptr_type_node, byte_offset)));
1406 else
1407 return NULL_TREE;
1410 /* Determine whether JFUNC evaluates to a single known constant value and if
1411 so, return it. Otherwise return NULL. INFO describes the caller node or
1412 the one it is inlined to, so that pass-through jump functions can be
1413 evaluated. PARM_TYPE is the type of the parameter to which the result is
1414 passed. */
1416 tree
1417 ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc,
1418 tree parm_type)
1420 if (jfunc->type == IPA_JF_CONST)
1421 return ipa_get_jf_constant (jfunc);
1422 else if (jfunc->type == IPA_JF_PASS_THROUGH
1423 || jfunc->type == IPA_JF_ANCESTOR)
1425 tree input;
1426 int idx;
1428 if (jfunc->type == IPA_JF_PASS_THROUGH)
1429 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1430 else
1431 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1433 if (info->ipcp_orig_node)
1434 input = info->known_csts[idx];
1435 else
1437 ipcp_lattice<tree> *lat;
1439 if (!info->lattices
1440 || idx >= ipa_get_param_count (info))
1441 return NULL_TREE;
1442 lat = ipa_get_scalar_lat (info, idx);
1443 if (!lat->is_single_const ())
1444 return NULL_TREE;
1445 input = lat->values->value;
1448 if (!input)
1449 return NULL_TREE;
1451 if (jfunc->type == IPA_JF_PASS_THROUGH)
1452 return ipa_get_jf_pass_through_result (jfunc, input, parm_type);
1453 else
1454 return ipa_get_jf_ancestor_result (jfunc, input);
1456 else
1457 return NULL_TREE;
1460 /* Determine whether JFUNC evaluates to single known polymorphic context, given
1461 that INFO describes the caller node or the one it is inlined to, CS is the
1462 call graph edge corresponding to JFUNC and CSIDX index of the described
1463 parameter. */
1465 ipa_polymorphic_call_context
1466 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1467 ipa_jump_func *jfunc)
1469 ipa_edge_args *args = IPA_EDGE_REF (cs);
1470 ipa_polymorphic_call_context ctx;
1471 ipa_polymorphic_call_context *edge_ctx
1472 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1474 if (edge_ctx && !edge_ctx->useless_p ())
1475 ctx = *edge_ctx;
1477 if (jfunc->type == IPA_JF_PASS_THROUGH
1478 || jfunc->type == IPA_JF_ANCESTOR)
1480 ipa_polymorphic_call_context srcctx;
1481 int srcidx;
1482 bool type_preserved = true;
1483 if (jfunc->type == IPA_JF_PASS_THROUGH)
1485 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
1486 return ctx;
1487 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
1488 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1490 else
1492 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
1493 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1495 if (info->ipcp_orig_node)
1497 if (info->known_contexts.exists ())
1498 srcctx = info->known_contexts[srcidx];
1500 else
1502 if (!info->lattices
1503 || srcidx >= ipa_get_param_count (info))
1504 return ctx;
1505 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1506 lat = ipa_get_poly_ctx_lat (info, srcidx);
1507 if (!lat->is_single_const ())
1508 return ctx;
1509 srcctx = lat->values->value;
1511 if (srcctx.useless_p ())
1512 return ctx;
1513 if (jfunc->type == IPA_JF_ANCESTOR)
1514 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
1515 if (!type_preserved)
1516 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1517 srcctx.combine_with (ctx);
1518 return srcctx;
1521 return ctx;
1524 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1525 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1526 the result is a range or an anti-range. */
1528 static bool
1529 ipa_vr_operation_and_type_effects (value_range *dst_vr,
1530 value_range *src_vr,
1531 enum tree_code operation,
1532 tree dst_type, tree src_type)
1534 range_fold_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
1535 if (dst_vr->varying_p () || dst_vr->undefined_p ())
1536 return false;
1537 return true;
1540 /* Determine value_range of JFUNC given that INFO describes the caller node or
1541 the one it is inlined to, CS is the call graph edge corresponding to JFUNC
1542 and PARM_TYPE of the parameter. */
1544 value_range
1545 ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs,
1546 ipa_jump_func *jfunc, tree parm_type)
1548 value_range vr;
1549 return vr;
1550 if (jfunc->m_vr)
1551 ipa_vr_operation_and_type_effects (&vr,
1552 jfunc->m_vr,
1553 NOP_EXPR, parm_type,
1554 jfunc->m_vr->type ());
1555 if (vr.singleton_p ())
1556 return vr;
1557 if (jfunc->type == IPA_JF_PASS_THROUGH)
1559 int idx;
1560 ipcp_transformation *sum
1561 = ipcp_get_transformation_summary (cs->caller->inlined_to
1562 ? cs->caller->inlined_to
1563 : cs->caller);
1564 if (!sum || !sum->m_vr)
1565 return vr;
1567 idx = ipa_get_jf_pass_through_formal_id (jfunc);
1569 if (!(*sum->m_vr)[idx].known)
1570 return vr;
1571 tree vr_type = ipa_get_type (info, idx);
1572 value_range srcvr (wide_int_to_tree (vr_type, (*sum->m_vr)[idx].min),
1573 wide_int_to_tree (vr_type, (*sum->m_vr)[idx].max),
1574 (*sum->m_vr)[idx].type);
1576 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
1578 if (TREE_CODE_CLASS (operation) == tcc_unary)
1580 value_range res;
1582 if (ipa_vr_operation_and_type_effects (&res,
1583 &srcvr,
1584 operation, parm_type,
1585 vr_type))
1586 vr.intersect (res);
1588 else
1590 value_range op_res, res;
1591 tree op = ipa_get_jf_pass_through_operand (jfunc);
1592 value_range op_vr (op, op);
1594 range_fold_binary_expr (&op_res, operation, vr_type, &srcvr, &op_vr);
1595 if (ipa_vr_operation_and_type_effects (&res,
1596 &op_res,
1597 NOP_EXPR, parm_type,
1598 vr_type))
1599 vr.intersect (res);
1602 return vr;
1605 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
1606 parameter with the given INDEX. */
1608 static tree
1609 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
1610 int index)
1612 struct ipa_agg_replacement_value *aggval;
1614 aggval = ipa_get_agg_replacements_for_node (node);
1615 while (aggval)
1617 if (aggval->offset == offset
1618 && aggval->index == index)
1619 return aggval->value;
1620 aggval = aggval->next;
1622 return NULL_TREE;
1625 /* Determine whether ITEM, jump function for an aggregate part, evaluates to a
1626 single known constant value and if so, return it. Otherwise return NULL.
1627 NODE and INFO describes the caller node or the one it is inlined to, and
1628 its related info. */
1630 static tree
1631 ipa_agg_value_from_node (class ipa_node_params *info,
1632 struct cgraph_node *node,
1633 struct ipa_agg_jf_item *item)
1635 tree value = NULL_TREE;
1636 int src_idx;
1638 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN)
1639 return NULL_TREE;
1641 if (item->jftype == IPA_JF_CONST)
1642 return item->value.constant;
1644 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
1645 || item->jftype == IPA_JF_LOAD_AGG);
1647 src_idx = item->value.pass_through.formal_id;
1649 if (info->ipcp_orig_node)
1651 if (item->jftype == IPA_JF_PASS_THROUGH)
1652 value = info->known_csts[src_idx];
1653 else
1654 value = get_clone_agg_value (node, item->value.load_agg.offset,
1655 src_idx);
1657 else if (info->lattices)
1659 class ipcp_param_lattices *src_plats
1660 = ipa_get_parm_lattices (info, src_idx);
1662 if (item->jftype == IPA_JF_PASS_THROUGH)
1664 struct ipcp_lattice<tree> *lat = &src_plats->itself;
1666 if (!lat->is_single_const ())
1667 return NULL_TREE;
1669 value = lat->values->value;
1671 else if (src_plats->aggs
1672 && !src_plats->aggs_bottom
1673 && !src_plats->aggs_contain_variable
1674 && src_plats->aggs_by_ref == item->value.load_agg.by_ref)
1676 struct ipcp_agg_lattice *aglat;
1678 for (aglat = src_plats->aggs; aglat; aglat = aglat->next)
1680 if (aglat->offset > item->value.load_agg.offset)
1681 break;
1683 if (aglat->offset == item->value.load_agg.offset)
1685 if (aglat->is_single_const ())
1686 value = aglat->values->value;
1687 break;
1693 if (!value)
1694 return NULL_TREE;
1696 if (item->jftype == IPA_JF_LOAD_AGG)
1698 tree load_type = item->value.load_agg.type;
1699 tree value_type = TREE_TYPE (value);
1701 /* Ensure value type is compatible with load type. */
1702 if (!useless_type_conversion_p (load_type, value_type))
1703 return NULL_TREE;
1706 return ipa_get_jf_arith_result (item->value.pass_through.operation,
1707 value,
1708 item->value.pass_through.operand,
1709 item->type);
1712 /* Determine whether AGG_JFUNC evaluates to a set of known constant value for
1713 an aggregate and if so, return it. Otherwise return an empty set. NODE
1714 and INFO describes the caller node or the one it is inlined to, and its
1715 related info. */
1717 struct ipa_agg_value_set
1718 ipa_agg_value_set_from_jfunc (class ipa_node_params *info, cgraph_node *node,
1719 struct ipa_agg_jump_function *agg_jfunc)
1721 struct ipa_agg_value_set agg;
1722 struct ipa_agg_jf_item *item;
1723 int i;
1725 agg.items = vNULL;
1726 agg.by_ref = agg_jfunc->by_ref;
1728 FOR_EACH_VEC_SAFE_ELT (agg_jfunc->items, i, item)
1730 tree value = ipa_agg_value_from_node (info, node, item);
1732 if (value)
1734 struct ipa_agg_value value_item;
1736 value_item.offset = item->offset;
1737 value_item.value = value;
1739 agg.items.safe_push (value_item);
1742 return agg;
1745 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1746 bottom, not containing a variable component and without any known value at
1747 the same time. */
1749 DEBUG_FUNCTION void
1750 ipcp_verify_propagated_values (void)
1752 struct cgraph_node *node;
1754 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1756 class ipa_node_params *info = IPA_NODE_REF (node);
1757 if (!opt_for_fn (node->decl, flag_ipa_cp)
1758 || !opt_for_fn (node->decl, optimize))
1759 continue;
1760 int i, count = ipa_get_param_count (info);
1762 for (i = 0; i < count; i++)
1764 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
1766 if (!lat->bottom
1767 && !lat->contains_variable
1768 && lat->values_count == 0)
1770 if (dump_file)
1772 symtab->dump (dump_file);
1773 fprintf (dump_file, "\nIPA lattices after constant "
1774 "propagation, before gcc_unreachable:\n");
1775 print_all_lattices (dump_file, true, false);
1778 gcc_unreachable ();
1784 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1786 static bool
1787 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1788 ipa_polymorphic_call_context y)
1790 return x.equal_to (y);
1794 /* Add a new value source to the value represented by THIS, marking that a
1795 value comes from edge CS and (if the underlying jump function is a
1796 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1797 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1798 scalar value of the parameter itself or the offset within an aggregate. */
1800 template <typename valtype>
1801 void
1802 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1803 int src_idx, HOST_WIDE_INT offset)
1805 ipcp_value_source<valtype> *src;
1807 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
1808 src->offset = offset;
1809 src->cs = cs;
1810 src->val = src_val;
1811 src->index = src_idx;
1813 src->next = sources;
1814 sources = src;
1817 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1818 SOURCE and clear all other fields. */
1820 static ipcp_value<tree> *
1821 allocate_and_init_ipcp_value (tree source)
1823 ipcp_value<tree> *val;
1825 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
1826 val->value = source;
1827 return val;
1830 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1831 value to SOURCE and clear all other fields. */
1833 static ipcp_value<ipa_polymorphic_call_context> *
1834 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1836 ipcp_value<ipa_polymorphic_call_context> *val;
1838 // TODO
1839 val = new (ipcp_poly_ctx_values_pool.allocate ())
1840 ipcp_value<ipa_polymorphic_call_context>();
1841 val->value = source;
1842 return val;
1845 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1846 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1847 meaning. OFFSET -1 means the source is scalar and not a part of an
1848 aggregate. If non-NULL, VAL_P records address of existing or newly added
1849 ipcp_value. UNLIMITED means whether value count should not exceed the limit
1850 given by PARAM_IPA_CP_VALUE_LIST_SIZE. */
1852 template <typename valtype>
1853 bool
1854 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1855 ipcp_value<valtype> *src_val,
1856 int src_idx, HOST_WIDE_INT offset,
1857 ipcp_value<valtype> **val_p,
1858 bool unlimited)
1860 ipcp_value<valtype> *val, *last_val = NULL;
1862 if (val_p)
1863 *val_p = NULL;
1865 if (bottom)
1866 return false;
1868 for (val = values; val; last_val = val, val = val->next)
1869 if (values_equal_for_ipcp_p (val->value, newval))
1871 if (val_p)
1872 *val_p = val;
1874 if (ipa_edge_within_scc (cs))
1876 ipcp_value_source<valtype> *s;
1877 for (s = val->sources; s; s = s->next)
1878 if (s->cs == cs && s->val == src_val)
1879 break;
1880 if (s)
1881 return false;
1884 val->add_source (cs, src_val, src_idx, offset);
1885 return false;
1888 if (!unlimited && values_count == opt_for_fn (cs->caller->decl,
1889 param_ipa_cp_value_list_size))
1891 /* We can only free sources, not the values themselves, because sources
1892 of other values in this SCC might point to them. */
1893 for (val = values; val; val = val->next)
1895 while (val->sources)
1897 ipcp_value_source<valtype> *src = val->sources;
1898 val->sources = src->next;
1899 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
1902 values = NULL;
1903 return set_to_bottom ();
1906 values_count++;
1907 val = allocate_and_init_ipcp_value (newval);
1908 val->add_source (cs, src_val, src_idx, offset);
1909 val->next = NULL;
1911 /* Add the new value to end of value list, which can reduce iterations
1912 of propagation stage for recursive function. */
1913 if (last_val)
1914 last_val->next = val;
1915 else
1916 values = val;
1918 if (val_p)
1919 *val_p = val;
1921 return true;
1924 /* Return true, if a ipcp_value VAL is orginated from parameter value of
1925 self-feeding recursive function via some kind of pass-through jump
1926 function. */
1928 static bool
1929 self_recursively_generated_p (ipcp_value<tree> *val)
1931 class ipa_node_params *info = NULL;
1933 for (ipcp_value_source<tree> *src = val->sources; src; src = src->next)
1935 cgraph_edge *cs = src->cs;
1937 if (!src->val || cs->caller != cs->callee->function_symbol ())
1938 return false;
1940 if (src->val == val)
1941 continue;
1943 if (!info)
1944 info = IPA_NODE_REF (cs->caller);
1946 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info,
1947 src->index);
1948 ipcp_lattice<tree> *src_lat;
1949 ipcp_value<tree> *src_val;
1951 if (src->offset == -1)
1952 src_lat = &plats->itself;
1953 else
1955 struct ipcp_agg_lattice *src_aglat;
1957 for (src_aglat = plats->aggs; src_aglat; src_aglat = src_aglat->next)
1958 if (src_aglat->offset == src->offset)
1959 break;
1961 if (!src_aglat)
1962 return false;
1964 src_lat = src_aglat;
1967 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1968 if (src_val == val)
1969 break;
1971 if (!src_val)
1972 return false;
1975 return true;
1978 /* A helper function that returns result of operation specified by OPCODE on
1979 the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the
1980 value of SRC_VAL. If the operation is binary, OPND2 is a constant value
1981 acting as its second operand. If non-NULL, RES_TYPE is expected type of
1982 the result. */
1984 static tree
1985 get_val_across_arith_op (enum tree_code opcode,
1986 tree opnd1_type,
1987 tree opnd2,
1988 ipcp_value<tree> *src_val,
1989 tree res_type)
1991 tree opnd1 = src_val->value;
1993 /* Skip source values that is incompatible with specified type. */
1994 if (opnd1_type
1995 && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1)))
1996 return NULL_TREE;
1998 return ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type);
2001 /* Propagate values through an arithmetic transformation described by a jump
2002 function associated with edge CS, taking values from SRC_LAT and putting
2003 them into DEST_LAT. OPND1_TYPE is expected type for the values in SRC_LAT.
2004 OPND2 is a constant value if transformation is a binary operation.
2005 SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice of
2006 a part of the aggregate. SRC_IDX is the index of the source parameter.
2007 RES_TYPE is the value type of result being propagated into. Return true if
2008 DEST_LAT changed. */
2010 static bool
2011 propagate_vals_across_arith_jfunc (cgraph_edge *cs,
2012 enum tree_code opcode,
2013 tree opnd1_type,
2014 tree opnd2,
2015 ipcp_lattice<tree> *src_lat,
2016 ipcp_lattice<tree> *dest_lat,
2017 HOST_WIDE_INT src_offset,
2018 int src_idx,
2019 tree res_type)
2021 ipcp_value<tree> *src_val;
2022 bool ret = false;
2024 /* Due to circular dependencies, propagating within an SCC through arithmetic
2025 transformation would create infinite number of values. But for
2026 self-feeding recursive function, we could allow propagation in a limited
2027 count, and this can enable a simple kind of recursive function versioning.
2028 For other scenario, we would just make lattices bottom. */
2029 if (opcode != NOP_EXPR && ipa_edge_within_scc (cs))
2031 int i;
2033 int max_recursive_depth = opt_for_fn(cs->caller->decl,
2034 param_ipa_cp_max_recursive_depth);
2035 if (src_lat != dest_lat || max_recursive_depth < 1)
2036 return dest_lat->set_contains_variable ();
2038 /* No benefit if recursive execution is in low probability. */
2039 if (cs->sreal_frequency () * 100
2040 <= ((sreal) 1) * opt_for_fn (cs->caller->decl,
2041 param_ipa_cp_min_recursive_probability))
2042 return dest_lat->set_contains_variable ();
2044 auto_vec<ipcp_value<tree> *, 8> val_seeds;
2046 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2048 /* Now we do not use self-recursively generated value as propagation
2049 source, this is absolutely conservative, but could avoid explosion
2050 of lattice's value space, especially when one recursive function
2051 calls another recursive. */
2052 if (self_recursively_generated_p (src_val))
2054 ipcp_value_source<tree> *s;
2056 /* If the lattice has already been propagated for the call site,
2057 no need to do that again. */
2058 for (s = src_val->sources; s; s = s->next)
2059 if (s->cs == cs)
2060 return dest_lat->set_contains_variable ();
2062 else
2063 val_seeds.safe_push (src_val);
2066 gcc_assert ((int) val_seeds.length () <= param_ipa_cp_value_list_size);
2068 /* Recursively generate lattice values with a limited count. */
2069 FOR_EACH_VEC_ELT (val_seeds, i, src_val)
2071 for (int j = 1; j < max_recursive_depth; j++)
2073 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2074 src_val, res_type);
2075 if (!cstval)
2076 break;
2078 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2079 src_offset, &src_val, true);
2080 gcc_checking_assert (src_val);
2083 ret |= dest_lat->set_contains_variable ();
2085 else
2086 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2088 /* Now we do not use self-recursively generated value as propagation
2089 source, otherwise it is easy to make value space of normal lattice
2090 overflow. */
2091 if (self_recursively_generated_p (src_val))
2093 ret |= dest_lat->set_contains_variable ();
2094 continue;
2097 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
2098 src_val, res_type);
2099 if (cstval)
2100 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
2101 src_offset);
2102 else
2103 ret |= dest_lat->set_contains_variable ();
2106 return ret;
2109 /* Propagate values through a pass-through jump function JFUNC associated with
2110 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2111 is the index of the source parameter. PARM_TYPE is the type of the
2112 parameter to which the result is passed. */
2114 static bool
2115 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc,
2116 ipcp_lattice<tree> *src_lat,
2117 ipcp_lattice<tree> *dest_lat, int src_idx,
2118 tree parm_type)
2120 return propagate_vals_across_arith_jfunc (cs,
2121 ipa_get_jf_pass_through_operation (jfunc),
2122 NULL_TREE,
2123 ipa_get_jf_pass_through_operand (jfunc),
2124 src_lat, dest_lat, -1, src_idx, parm_type);
2127 /* Propagate values through an ancestor jump function JFUNC associated with
2128 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
2129 is the index of the source parameter. */
2131 static bool
2132 propagate_vals_across_ancestor (struct cgraph_edge *cs,
2133 struct ipa_jump_func *jfunc,
2134 ipcp_lattice<tree> *src_lat,
2135 ipcp_lattice<tree> *dest_lat, int src_idx)
2137 ipcp_value<tree> *src_val;
2138 bool ret = false;
2140 if (ipa_edge_within_scc (cs))
2141 return dest_lat->set_contains_variable ();
2143 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2145 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
2147 if (t)
2148 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
2149 else
2150 ret |= dest_lat->set_contains_variable ();
2153 return ret;
2156 /* Propagate scalar values across jump function JFUNC that is associated with
2157 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the
2158 parameter to which the result is passed. */
2160 static bool
2161 propagate_scalar_across_jump_function (struct cgraph_edge *cs,
2162 struct ipa_jump_func *jfunc,
2163 ipcp_lattice<tree> *dest_lat,
2164 tree param_type)
2166 if (dest_lat->bottom)
2167 return false;
2169 if (jfunc->type == IPA_JF_CONST)
2171 tree val = ipa_get_jf_constant (jfunc);
2172 return dest_lat->add_value (val, cs, NULL, 0);
2174 else if (jfunc->type == IPA_JF_PASS_THROUGH
2175 || jfunc->type == IPA_JF_ANCESTOR)
2177 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2178 ipcp_lattice<tree> *src_lat;
2179 int src_idx;
2180 bool ret;
2182 if (jfunc->type == IPA_JF_PASS_THROUGH)
2183 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2184 else
2185 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2187 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
2188 if (src_lat->bottom)
2189 return dest_lat->set_contains_variable ();
2191 /* If we would need to clone the caller and cannot, do not propagate. */
2192 if (!ipcp_versionable_function_p (cs->caller)
2193 && (src_lat->contains_variable
2194 || (src_lat->values_count > 1)))
2195 return dest_lat->set_contains_variable ();
2197 if (jfunc->type == IPA_JF_PASS_THROUGH)
2198 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
2199 dest_lat, src_idx, param_type);
2200 else
2201 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
2202 src_idx);
2204 if (src_lat->contains_variable)
2205 ret |= dest_lat->set_contains_variable ();
2207 return ret;
2210 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
2211 use it for indirect inlining), we should propagate them too. */
2212 return dest_lat->set_contains_variable ();
2215 /* Propagate scalar values across jump function JFUNC that is associated with
2216 edge CS and describes argument IDX and put the values into DEST_LAT. */
2218 static bool
2219 propagate_context_across_jump_function (cgraph_edge *cs,
2220 ipa_jump_func *jfunc, int idx,
2221 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
2223 ipa_edge_args *args = IPA_EDGE_REF (cs);
2224 if (dest_lat->bottom)
2225 return false;
2226 bool ret = false;
2227 bool added_sth = false;
2228 bool type_preserved = true;
2230 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
2231 = ipa_get_ith_polymorhic_call_context (args, idx);
2233 if (edge_ctx_ptr)
2234 edge_ctx = *edge_ctx_ptr;
2236 if (jfunc->type == IPA_JF_PASS_THROUGH
2237 || jfunc->type == IPA_JF_ANCESTOR)
2239 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2240 int src_idx;
2241 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
2243 /* TODO: Once we figure out how to propagate speculations, it will
2244 probably be a good idea to switch to speculation if type_preserved is
2245 not set instead of punting. */
2246 if (jfunc->type == IPA_JF_PASS_THROUGH)
2248 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
2249 goto prop_fail;
2250 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
2251 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2253 else
2255 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
2256 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2259 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
2260 /* If we would need to clone the caller and cannot, do not propagate. */
2261 if (!ipcp_versionable_function_p (cs->caller)
2262 && (src_lat->contains_variable
2263 || (src_lat->values_count > 1)))
2264 goto prop_fail;
2266 ipcp_value<ipa_polymorphic_call_context> *src_val;
2267 for (src_val = src_lat->values; src_val; src_val = src_val->next)
2269 ipa_polymorphic_call_context cur = src_val->value;
2271 if (!type_preserved)
2272 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
2273 if (jfunc->type == IPA_JF_ANCESTOR)
2274 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
2275 /* TODO: In cases we know how the context is going to be used,
2276 we can improve the result by passing proper OTR_TYPE. */
2277 cur.combine_with (edge_ctx);
2278 if (!cur.useless_p ())
2280 if (src_lat->contains_variable
2281 && !edge_ctx.equal_to (cur))
2282 ret |= dest_lat->set_contains_variable ();
2283 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
2284 added_sth = true;
2289 prop_fail:
2290 if (!added_sth)
2292 if (!edge_ctx.useless_p ())
2293 ret |= dest_lat->add_value (edge_ctx, cs);
2294 else
2295 ret |= dest_lat->set_contains_variable ();
2298 return ret;
2301 /* Propagate bits across jfunc that is associated with
2302 edge cs and update dest_lattice accordingly. */
2304 bool
2305 propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
2306 ipa_jump_func *jfunc,
2307 ipcp_bits_lattice *dest_lattice)
2309 if (dest_lattice->bottom_p ())
2310 return false;
2312 enum availability availability;
2313 cgraph_node *callee = cs->callee->function_symbol (&availability);
2314 class ipa_node_params *callee_info = IPA_NODE_REF (callee);
2315 tree parm_type = ipa_get_type (callee_info, idx);
2317 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the
2318 transform for these cases. Similarly, we can have bad type mismatches
2319 with LTO, avoid doing anything with those too. */
2320 if (!parm_type
2321 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type)))
2323 if (dump_file && (dump_flags & TDF_DETAILS))
2324 fprintf (dump_file, "Setting dest_lattice to bottom, because type of "
2325 "param %i of %s is NULL or unsuitable for bits propagation\n",
2326 idx, cs->callee->dump_name ());
2328 return dest_lattice->set_to_bottom ();
2331 unsigned precision = TYPE_PRECISION (parm_type);
2332 signop sgn = TYPE_SIGN (parm_type);
2334 if (jfunc->type == IPA_JF_PASS_THROUGH
2335 || jfunc->type == IPA_JF_ANCESTOR)
2337 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2338 tree operand = NULL_TREE;
2339 enum tree_code code;
2340 unsigned src_idx;
2342 if (jfunc->type == IPA_JF_PASS_THROUGH)
2344 code = ipa_get_jf_pass_through_operation (jfunc);
2345 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2346 if (code != NOP_EXPR)
2347 operand = ipa_get_jf_pass_through_operand (jfunc);
2349 else
2351 code = POINTER_PLUS_EXPR;
2352 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2353 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
2354 operand = build_int_cstu (size_type_node, offset);
2357 class ipcp_param_lattices *src_lats
2358 = ipa_get_parm_lattices (caller_info, src_idx);
2360 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
2361 for eg consider:
2362 int f(int x)
2364 g (x & 0xff);
2366 Assume lattice for x is bottom, however we can still propagate
2367 result of x & 0xff == 0xff, which gets computed during ccp1 pass
2368 and we store it in jump function during analysis stage. */
2370 if (src_lats->bits_lattice.bottom_p ()
2371 && jfunc->bits)
2372 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
2373 precision);
2374 else
2375 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
2376 code, operand);
2379 else if (jfunc->type == IPA_JF_ANCESTOR)
2380 return dest_lattice->set_to_bottom ();
2381 else if (jfunc->bits)
2382 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
2383 precision);
2384 else
2385 return dest_lattice->set_to_bottom ();
2388 /* Propagate value range across jump function JFUNC that is associated with
2389 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
2390 accordingly. */
2392 static bool
2393 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
2394 class ipcp_param_lattices *dest_plats,
2395 tree param_type)
2397 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
2399 if (dest_lat->bottom_p ())
2400 return false;
2402 if (!param_type
2403 || (!INTEGRAL_TYPE_P (param_type)
2404 && !POINTER_TYPE_P (param_type)))
2405 return dest_lat->set_to_bottom ();
2407 if (jfunc->type == IPA_JF_PASS_THROUGH)
2409 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
2410 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2411 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2412 class ipcp_param_lattices *src_lats
2413 = ipa_get_parm_lattices (caller_info, src_idx);
2414 tree operand_type = ipa_get_type (caller_info, src_idx);
2416 if (src_lats->m_value_range.bottom_p ())
2417 return dest_lat->set_to_bottom ();
2419 value_range vr;
2420 if (TREE_CODE_CLASS (operation) == tcc_unary)
2421 ipa_vr_operation_and_type_effects (&vr,
2422 &src_lats->m_value_range.m_vr,
2423 operation, param_type,
2424 operand_type);
2425 /* A crude way to prevent unbounded number of value range updates
2426 in SCC components. We should allow limited number of updates within
2427 SCC, too. */
2428 else if (!ipa_edge_within_scc (cs))
2430 tree op = ipa_get_jf_pass_through_operand (jfunc);
2431 value_range op_vr (op, op);
2432 value_range op_res,res;
2434 range_fold_binary_expr (&op_res, operation, operand_type,
2435 &src_lats->m_value_range.m_vr, &op_vr);
2436 ipa_vr_operation_and_type_effects (&vr,
2437 &op_res,
2438 NOP_EXPR, param_type,
2439 operand_type);
2441 if (!vr.undefined_p () && !vr.varying_p ())
2443 if (jfunc->m_vr)
2445 value_range jvr;
2446 if (ipa_vr_operation_and_type_effects (&jvr, jfunc->m_vr,
2447 NOP_EXPR,
2448 param_type,
2449 jfunc->m_vr->type ()))
2450 vr.intersect (jvr);
2452 return dest_lat->meet_with (&vr);
2455 else if (jfunc->type == IPA_JF_CONST)
2457 tree val = ipa_get_jf_constant (jfunc);
2458 if (TREE_CODE (val) == INTEGER_CST)
2460 val = fold_convert (param_type, val);
2461 if (TREE_OVERFLOW_P (val))
2462 val = drop_tree_overflow (val);
2464 value_range tmpvr (val, val);
2465 return dest_lat->meet_with (&tmpvr);
2469 value_range vr;
2470 if (jfunc->m_vr
2471 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
2472 param_type,
2473 jfunc->m_vr->type ()))
2474 return dest_lat->meet_with (&vr);
2475 else
2476 return dest_lat->set_to_bottom ();
2479 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
2480 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
2481 other cases, return false). If there are no aggregate items, set
2482 aggs_by_ref to NEW_AGGS_BY_REF. */
2484 static bool
2485 set_check_aggs_by_ref (class ipcp_param_lattices *dest_plats,
2486 bool new_aggs_by_ref)
2488 if (dest_plats->aggs)
2490 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
2492 set_agg_lats_to_bottom (dest_plats);
2493 return true;
2496 else
2497 dest_plats->aggs_by_ref = new_aggs_by_ref;
2498 return false;
2501 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
2502 already existing lattice for the given OFFSET and SIZE, marking all skipped
2503 lattices as containing variable and checking for overlaps. If there is no
2504 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
2505 it with offset, size and contains_variable to PRE_EXISTING, and return true,
2506 unless there are too many already. If there are two many, return false. If
2507 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
2508 skipped lattices were newly marked as containing variable, set *CHANGE to
2509 true. MAX_AGG_ITEMS is the maximum number of lattices. */
2511 static bool
2512 merge_agg_lats_step (class ipcp_param_lattices *dest_plats,
2513 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
2514 struct ipcp_agg_lattice ***aglat,
2515 bool pre_existing, bool *change, int max_agg_items)
2517 gcc_checking_assert (offset >= 0);
2519 while (**aglat && (**aglat)->offset < offset)
2521 if ((**aglat)->offset + (**aglat)->size > offset)
2523 set_agg_lats_to_bottom (dest_plats);
2524 return false;
2526 *change |= (**aglat)->set_contains_variable ();
2527 *aglat = &(**aglat)->next;
2530 if (**aglat && (**aglat)->offset == offset)
2532 if ((**aglat)->size != val_size)
2534 set_agg_lats_to_bottom (dest_plats);
2535 return false;
2537 gcc_assert (!(**aglat)->next
2538 || (**aglat)->next->offset >= offset + val_size);
2539 return true;
2541 else
2543 struct ipcp_agg_lattice *new_al;
2545 if (**aglat && (**aglat)->offset < offset + val_size)
2547 set_agg_lats_to_bottom (dest_plats);
2548 return false;
2550 if (dest_plats->aggs_count == max_agg_items)
2551 return false;
2552 dest_plats->aggs_count++;
2553 new_al = ipcp_agg_lattice_pool.allocate ();
2554 memset (new_al, 0, sizeof (*new_al));
2556 new_al->offset = offset;
2557 new_al->size = val_size;
2558 new_al->contains_variable = pre_existing;
2560 new_al->next = **aglat;
2561 **aglat = new_al;
2562 return true;
2566 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2567 containing an unknown value. */
2569 static bool
2570 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
2572 bool ret = false;
2573 while (aglat)
2575 ret |= aglat->set_contains_variable ();
2576 aglat = aglat->next;
2578 return ret;
2581 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2582 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2583 parameter used for lattice value sources. Return true if DEST_PLATS changed
2584 in any way. */
2586 static bool
2587 merge_aggregate_lattices (struct cgraph_edge *cs,
2588 class ipcp_param_lattices *dest_plats,
2589 class ipcp_param_lattices *src_plats,
2590 int src_idx, HOST_WIDE_INT offset_delta)
2592 bool pre_existing = dest_plats->aggs != NULL;
2593 struct ipcp_agg_lattice **dst_aglat;
2594 bool ret = false;
2596 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
2597 return true;
2598 if (src_plats->aggs_bottom)
2599 return set_agg_lats_contain_variable (dest_plats);
2600 if (src_plats->aggs_contain_variable)
2601 ret |= set_agg_lats_contain_variable (dest_plats);
2602 dst_aglat = &dest_plats->aggs;
2604 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2605 param_ipa_max_agg_items);
2606 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
2607 src_aglat;
2608 src_aglat = src_aglat->next)
2610 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
2612 if (new_offset < 0)
2613 continue;
2614 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
2615 &dst_aglat, pre_existing, &ret, max_agg_items))
2617 struct ipcp_agg_lattice *new_al = *dst_aglat;
2619 dst_aglat = &(*dst_aglat)->next;
2620 if (src_aglat->bottom)
2622 ret |= new_al->set_contains_variable ();
2623 continue;
2625 if (src_aglat->contains_variable)
2626 ret |= new_al->set_contains_variable ();
2627 for (ipcp_value<tree> *val = src_aglat->values;
2628 val;
2629 val = val->next)
2630 ret |= new_al->add_value (val->value, cs, val, src_idx,
2631 src_aglat->offset);
2633 else if (dest_plats->aggs_bottom)
2634 return true;
2636 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
2637 return ret;
2640 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2641 pass-through JFUNC and if so, whether it has conform and conforms to the
2642 rules about propagating values passed by reference. */
2644 static bool
2645 agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats,
2646 struct ipa_jump_func *jfunc)
2648 return src_plats->aggs
2649 && (!src_plats->aggs_by_ref
2650 || ipa_get_jf_pass_through_agg_preserved (jfunc));
2653 /* Propagate values through ITEM, jump function for a part of an aggregate,
2654 into corresponding aggregate lattice AGLAT. CS is the call graph edge
2655 associated with the jump function. Return true if AGLAT changed in any
2656 way. */
2658 static bool
2659 propagate_aggregate_lattice (struct cgraph_edge *cs,
2660 struct ipa_agg_jf_item *item,
2661 struct ipcp_agg_lattice *aglat)
2663 class ipa_node_params *caller_info;
2664 class ipcp_param_lattices *src_plats;
2665 struct ipcp_lattice<tree> *src_lat;
2666 HOST_WIDE_INT src_offset;
2667 int src_idx;
2668 tree load_type;
2669 bool ret;
2671 if (item->jftype == IPA_JF_CONST)
2673 tree value = item->value.constant;
2675 gcc_checking_assert (is_gimple_ip_invariant (value));
2676 return aglat->add_value (value, cs, NULL, 0);
2679 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH
2680 || item->jftype == IPA_JF_LOAD_AGG);
2682 caller_info = IPA_NODE_REF (cs->caller);
2683 src_idx = item->value.pass_through.formal_id;
2684 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2686 if (item->jftype == IPA_JF_PASS_THROUGH)
2688 load_type = NULL_TREE;
2689 src_lat = &src_plats->itself;
2690 src_offset = -1;
2692 else
2694 HOST_WIDE_INT load_offset = item->value.load_agg.offset;
2695 struct ipcp_agg_lattice *src_aglat;
2697 for (src_aglat = src_plats->aggs; src_aglat; src_aglat = src_aglat->next)
2698 if (src_aglat->offset >= load_offset)
2699 break;
2701 load_type = item->value.load_agg.type;
2702 if (!src_aglat
2703 || src_aglat->offset > load_offset
2704 || src_aglat->size != tree_to_shwi (TYPE_SIZE (load_type))
2705 || src_plats->aggs_by_ref != item->value.load_agg.by_ref)
2706 return aglat->set_contains_variable ();
2708 src_lat = src_aglat;
2709 src_offset = load_offset;
2712 if (src_lat->bottom
2713 || (!ipcp_versionable_function_p (cs->caller)
2714 && !src_lat->is_single_const ()))
2715 return aglat->set_contains_variable ();
2717 ret = propagate_vals_across_arith_jfunc (cs,
2718 item->value.pass_through.operation,
2719 load_type,
2720 item->value.pass_through.operand,
2721 src_lat, aglat,
2722 src_offset,
2723 src_idx,
2724 item->type);
2726 if (src_lat->contains_variable)
2727 ret |= aglat->set_contains_variable ();
2729 return ret;
2732 /* Propagate scalar values across jump function JFUNC that is associated with
2733 edge CS and put the values into DEST_LAT. */
2735 static bool
2736 propagate_aggs_across_jump_function (struct cgraph_edge *cs,
2737 struct ipa_jump_func *jfunc,
2738 class ipcp_param_lattices *dest_plats)
2740 bool ret = false;
2742 if (dest_plats->aggs_bottom)
2743 return false;
2745 if (jfunc->type == IPA_JF_PASS_THROUGH
2746 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
2748 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2749 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
2750 class ipcp_param_lattices *src_plats;
2752 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2753 if (agg_pass_through_permissible_p (src_plats, jfunc))
2755 /* Currently we do not produce clobber aggregate jump
2756 functions, replace with merging when we do. */
2757 gcc_assert (!jfunc->agg.items);
2758 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
2759 src_idx, 0);
2760 return ret;
2763 else if (jfunc->type == IPA_JF_ANCESTOR
2764 && ipa_get_jf_ancestor_agg_preserved (jfunc))
2766 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
2767 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
2768 class ipcp_param_lattices *src_plats;
2770 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
2771 if (src_plats->aggs && src_plats->aggs_by_ref)
2773 /* Currently we do not produce clobber aggregate jump
2774 functions, replace with merging when we do. */
2775 gcc_assert (!jfunc->agg.items);
2776 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
2777 ipa_get_jf_ancestor_offset (jfunc));
2779 else if (!src_plats->aggs_by_ref)
2780 ret |= set_agg_lats_to_bottom (dest_plats);
2781 else
2782 ret |= set_agg_lats_contain_variable (dest_plats);
2783 return ret;
2786 if (jfunc->agg.items)
2788 bool pre_existing = dest_plats->aggs != NULL;
2789 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
2790 struct ipa_agg_jf_item *item;
2791 int i;
2793 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
2794 return true;
2796 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl,
2797 param_ipa_max_agg_items);
2798 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2800 HOST_WIDE_INT val_size;
2802 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN)
2803 continue;
2804 val_size = tree_to_shwi (TYPE_SIZE (item->type));
2806 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
2807 &aglat, pre_existing, &ret, max_agg_items))
2809 ret |= propagate_aggregate_lattice (cs, item, *aglat);
2810 aglat = &(*aglat)->next;
2812 else if (dest_plats->aggs_bottom)
2813 return true;
2816 ret |= set_chain_of_aglats_contains_variable (*aglat);
2818 else
2819 ret |= set_agg_lats_contain_variable (dest_plats);
2821 return ret;
2824 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2825 non-thunk) destination, the call passes through a thunk. */
2827 static bool
2828 call_passes_through_thunk (cgraph_edge *cs)
2830 cgraph_node *alias_or_thunk = cs->callee;
2831 while (alias_or_thunk->alias)
2832 alias_or_thunk = alias_or_thunk->get_alias_target ();
2833 return alias_or_thunk->thunk;
2836 /* Propagate constants from the caller to the callee of CS. INFO describes the
2837 caller. */
2839 static bool
2840 propagate_constants_across_call (struct cgraph_edge *cs)
2842 class ipa_node_params *callee_info;
2843 enum availability availability;
2844 cgraph_node *callee;
2845 class ipa_edge_args *args;
2846 bool ret = false;
2847 int i, args_count, parms_count;
2849 callee = cs->callee->function_symbol (&availability);
2850 if (!callee->definition)
2851 return false;
2852 gcc_checking_assert (callee->has_gimple_body_p ());
2853 callee_info = IPA_NODE_REF (callee);
2854 if (!callee_info)
2855 return false;
2857 args = IPA_EDGE_REF (cs);
2858 parms_count = ipa_get_param_count (callee_info);
2859 if (parms_count == 0)
2860 return false;
2861 if (!args
2862 || !opt_for_fn (cs->caller->decl, flag_ipa_cp)
2863 || !opt_for_fn (cs->caller->decl, optimize))
2865 for (i = 0; i < parms_count; i++)
2866 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2867 i));
2868 return ret;
2870 args_count = ipa_get_cs_argument_count (args);
2872 /* If this call goes through a thunk we must not propagate to the first (0th)
2873 parameter. However, we might need to uncover a thunk from below a series
2874 of aliases first. */
2875 if (call_passes_through_thunk (cs))
2877 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
2878 0));
2879 i = 1;
2881 else
2882 i = 0;
2884 for (; (i < args_count) && (i < parms_count); i++)
2886 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2887 class ipcp_param_lattices *dest_plats;
2888 tree param_type = ipa_get_type (callee_info, i);
2890 dest_plats = ipa_get_parm_lattices (callee_info, i);
2891 if (availability == AVAIL_INTERPOSABLE)
2892 ret |= set_all_contains_variable (dest_plats);
2893 else
2895 ret |= propagate_scalar_across_jump_function (cs, jump_func,
2896 &dest_plats->itself,
2897 param_type);
2898 ret |= propagate_context_across_jump_function (cs, jump_func, i,
2899 &dest_plats->ctxlat);
2901 |= propagate_bits_across_jump_function (cs, i, jump_func,
2902 &dest_plats->bits_lattice);
2903 ret |= propagate_aggs_across_jump_function (cs, jump_func,
2904 dest_plats);
2905 if (opt_for_fn (callee->decl, flag_ipa_vrp))
2906 ret |= propagate_vr_across_jump_function (cs, jump_func,
2907 dest_plats, param_type);
2908 else
2909 ret |= dest_plats->m_value_range.set_to_bottom ();
2912 for (; i < parms_count; i++)
2913 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
2915 return ret;
2918 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2919 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2920 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2922 static tree
2923 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
2924 vec<tree> known_csts,
2925 vec<ipa_polymorphic_call_context> known_contexts,
2926 vec<ipa_agg_value_set> known_aggs,
2927 struct ipa_agg_replacement_value *agg_reps,
2928 bool *speculative)
2930 int param_index = ie->indirect_info->param_index;
2931 HOST_WIDE_INT anc_offset;
2932 tree t = NULL;
2933 tree target = NULL;
2935 *speculative = false;
2937 if (param_index == -1)
2938 return NULL_TREE;
2940 if (!ie->indirect_info->polymorphic)
2942 tree t = NULL;
2944 if (ie->indirect_info->agg_contents)
2946 t = NULL;
2947 if (agg_reps && ie->indirect_info->guaranteed_unmodified)
2949 while (agg_reps)
2951 if (agg_reps->index == param_index
2952 && agg_reps->offset == ie->indirect_info->offset
2953 && agg_reps->by_ref == ie->indirect_info->by_ref)
2955 t = agg_reps->value;
2956 break;
2958 agg_reps = agg_reps->next;
2961 if (!t)
2963 struct ipa_agg_value_set *agg;
2964 if (known_aggs.length () > (unsigned int) param_index)
2965 agg = &known_aggs[param_index];
2966 else
2967 agg = NULL;
2968 bool from_global_constant;
2969 t = ipa_find_agg_cst_for_param (agg,
2970 (unsigned) param_index
2971 < known_csts.length ()
2972 ? known_csts[param_index]
2973 : NULL,
2974 ie->indirect_info->offset,
2975 ie->indirect_info->by_ref,
2976 &from_global_constant);
2977 if (t
2978 && !from_global_constant
2979 && !ie->indirect_info->guaranteed_unmodified)
2980 t = NULL_TREE;
2983 else if ((unsigned) param_index < known_csts.length ())
2984 t = known_csts[param_index];
2986 if (t
2987 && TREE_CODE (t) == ADDR_EXPR
2988 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
2989 return TREE_OPERAND (t, 0);
2990 else
2991 return NULL_TREE;
2994 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
2995 return NULL_TREE;
2997 gcc_assert (!ie->indirect_info->agg_contents);
2998 anc_offset = ie->indirect_info->offset;
3000 t = NULL;
3002 /* Try to work out value of virtual table pointer value in replacements. */
3003 if (!t && agg_reps && !ie->indirect_info->by_ref)
3005 while (agg_reps)
3007 if (agg_reps->index == param_index
3008 && agg_reps->offset == ie->indirect_info->offset
3009 && agg_reps->by_ref)
3011 t = agg_reps->value;
3012 break;
3014 agg_reps = agg_reps->next;
3018 /* Try to work out value of virtual table pointer value in known
3019 aggregate values. */
3020 if (!t && known_aggs.length () > (unsigned int) param_index
3021 && !ie->indirect_info->by_ref)
3023 struct ipa_agg_value_set *agg = &known_aggs[param_index];
3024 t = ipa_find_agg_cst_for_param (agg,
3025 (unsigned) param_index
3026 < known_csts.length ()
3027 ? known_csts[param_index] : NULL,
3028 ie->indirect_info->offset, true);
3031 /* If we found the virtual table pointer, lookup the target. */
3032 if (t)
3034 tree vtable;
3035 unsigned HOST_WIDE_INT offset;
3036 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
3038 bool can_refer;
3039 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
3040 vtable, offset, &can_refer);
3041 if (can_refer)
3043 if (!target
3044 || fndecl_built_in_p (target, BUILT_IN_UNREACHABLE)
3045 || !possible_polymorphic_call_target_p
3046 (ie, cgraph_node::get (target)))
3048 /* Do not speculate builtin_unreachable, it is stupid! */
3049 if (ie->indirect_info->vptr_changed)
3050 return NULL;
3051 target = ipa_impossible_devirt_target (ie, target);
3053 *speculative = ie->indirect_info->vptr_changed;
3054 if (!*speculative)
3055 return target;
3060 /* Do we know the constant value of pointer? */
3061 if (!t && (unsigned) param_index < known_csts.length ())
3062 t = known_csts[param_index];
3064 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
3066 ipa_polymorphic_call_context context;
3067 if (known_contexts.length () > (unsigned int) param_index)
3069 context = known_contexts[param_index];
3070 context.offset_by (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);
3074 if (t)
3076 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
3077 (t, ie->indirect_info->otr_type, anc_offset);
3078 if (!ctx2.useless_p ())
3079 context.combine_with (ctx2, ie->indirect_info->otr_type);
3082 else if (t)
3084 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
3085 anc_offset);
3086 if (ie->indirect_info->vptr_changed)
3087 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
3088 ie->indirect_info->otr_type);
3090 else
3091 return NULL_TREE;
3093 vec <cgraph_node *>targets;
3094 bool final;
3096 targets = possible_polymorphic_call_targets
3097 (ie->indirect_info->otr_type,
3098 ie->indirect_info->otr_token,
3099 context, &final);
3100 if (!final || targets.length () > 1)
3102 struct cgraph_node *node;
3103 if (*speculative)
3104 return target;
3105 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
3106 || ie->speculative || !ie->maybe_hot_p ())
3107 return NULL;
3108 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
3109 ie->indirect_info->otr_token,
3110 context);
3111 if (node)
3113 *speculative = true;
3114 target = node->decl;
3116 else
3117 return NULL;
3119 else
3121 *speculative = false;
3122 if (targets.length () == 1)
3123 target = targets[0]->decl;
3124 else
3125 target = ipa_impossible_devirt_target (ie, NULL_TREE);
3128 if (target && !possible_polymorphic_call_target_p (ie,
3129 cgraph_node::get (target)))
3131 if (*speculative)
3132 return NULL;
3133 target = ipa_impossible_devirt_target (ie, target);
3136 return target;
3139 /* If an indirect edge IE can be turned into a direct one based on data in
3140 AVALS, return the destination. Store into *SPECULATIVE a boolean determinig
3141 whether the discovered target is only speculative guess. */
3143 tree
3144 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
3145 ipa_call_arg_values *avals,
3146 bool *speculative)
3148 return ipa_get_indirect_edge_target_1 (ie, avals->m_known_vals,
3149 avals->m_known_contexts,
3150 avals->m_known_aggs,
3151 NULL, speculative);
3154 /* The same functionality as above overloaded for ipa_auto_call_arg_values. */
3156 tree
3157 ipa_get_indirect_edge_target (struct cgraph_edge *ie,
3158 ipa_auto_call_arg_values *avals,
3159 bool *speculative)
3161 return ipa_get_indirect_edge_target_1 (ie, avals->m_known_vals,
3162 avals->m_known_contexts,
3163 avals->m_known_aggs,
3164 NULL, speculative);
3167 /* Calculate devirtualization time bonus for NODE, assuming we know information
3168 about arguments stored in AVALS. */
3170 static int
3171 devirtualization_time_bonus (struct cgraph_node *node,
3172 ipa_auto_call_arg_values *avals)
3174 struct cgraph_edge *ie;
3175 int res = 0;
3177 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
3179 struct cgraph_node *callee;
3180 class ipa_fn_summary *isummary;
3181 enum availability avail;
3182 tree target;
3183 bool speculative;
3185 target = ipa_get_indirect_edge_target (ie, avals, &speculative);
3186 if (!target)
3187 continue;
3189 /* Only bare minimum benefit for clearly un-inlineable targets. */
3190 res += 1;
3191 callee = cgraph_node::get (target);
3192 if (!callee || !callee->definition)
3193 continue;
3194 callee = callee->function_symbol (&avail);
3195 if (avail < AVAIL_AVAILABLE)
3196 continue;
3197 isummary = ipa_fn_summaries->get (callee);
3198 if (!isummary || !isummary->inlinable)
3199 continue;
3201 int size = ipa_size_summaries->get (callee)->size;
3202 /* FIXME: The values below need re-considering and perhaps also
3203 integrating into the cost metrics, at lest in some very basic way. */
3204 int max_inline_insns_auto
3205 = opt_for_fn (callee->decl, param_max_inline_insns_auto);
3206 if (size <= max_inline_insns_auto / 4)
3207 res += 31 / ((int)speculative + 1);
3208 else if (size <= max_inline_insns_auto / 2)
3209 res += 15 / ((int)speculative + 1);
3210 else if (size <= max_inline_insns_auto
3211 || DECL_DECLARED_INLINE_P (callee->decl))
3212 res += 7 / ((int)speculative + 1);
3215 return res;
3218 /* Return time bonus incurred because of hints stored in ESTIMATES. */
3220 static int
3221 hint_time_bonus (cgraph_node *node, const ipa_call_estimates &estimates)
3223 int result = 0;
3224 ipa_hints hints = estimates.hints;
3225 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
3226 result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
3228 sreal bonus_for_one = opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
3230 if (hints & INLINE_HINT_loop_iterations)
3231 result += (estimates.loops_with_known_iterations * bonus_for_one).to_int ();
3233 if (hints & INLINE_HINT_loop_stride)
3234 result += (estimates.loops_with_known_strides * bonus_for_one).to_int ();
3236 return result;
3239 /* If there is a reason to penalize the function described by INFO in the
3240 cloning goodness evaluation, do so. */
3242 static inline sreal
3243 incorporate_penalties (cgraph_node *node, ipa_node_params *info,
3244 sreal evaluation)
3246 if (info->node_within_scc && !info->node_is_self_scc)
3247 evaluation = (evaluation
3248 * (100 - opt_for_fn (node->decl,
3249 param_ipa_cp_recursion_penalty))) / 100;
3251 if (info->node_calling_single_call)
3252 evaluation = (evaluation
3253 * (100 - opt_for_fn (node->decl,
3254 param_ipa_cp_single_call_penalty)))
3255 / 100;
3257 return evaluation;
3260 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
3261 and SIZE_COST and with the sum of frequencies of incoming edges to the
3262 potential new clone in FREQUENCIES. */
3264 static bool
3265 good_cloning_opportunity_p (struct cgraph_node *node, sreal time_benefit,
3266 sreal freq_sum, profile_count count_sum,
3267 int size_cost)
3269 if (time_benefit == 0
3270 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
3271 || node->optimize_for_size_p ())
3272 return false;
3274 gcc_assert (size_cost > 0);
3275 if (size_cost == INT_MAX)
3277 if (dump_file && (dump_flags & TDF_DETAILS))
3278 fprintf (dump_file, " good_cloning_opportunity_p returning "
3279 "false because of size overflow.\n");
3280 return false;
3283 class ipa_node_params *info = IPA_NODE_REF (node);
3284 int eval_threshold = opt_for_fn (node->decl, param_ipa_cp_eval_threshold);
3285 if (max_count > profile_count::zero ())
3288 sreal factor = count_sum.probability_in (max_count).to_sreal ();
3289 sreal evaluation = (time_benefit * factor) / size_cost;
3290 evaluation = incorporate_penalties (node, info, evaluation);
3291 evaluation *= 1000;
3293 if (dump_file && (dump_flags & TDF_DETAILS))
3295 fprintf (dump_file, " good_cloning_opportunity_p (time: %g, "
3296 "size: %i, count_sum: ", time_benefit.to_double (),
3297 size_cost);
3298 count_sum.dump (dump_file);
3299 fprintf (dump_file, "%s%s) -> evaluation: %.2f, threshold: %i\n",
3300 info->node_within_scc
3301 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3302 info->node_calling_single_call ? ", single_call" : "",
3303 evaluation.to_double (), eval_threshold);
3306 return evaluation.to_int () >= eval_threshold;
3308 else
3310 sreal evaluation = (time_benefit * freq_sum) / size_cost;
3311 evaluation = incorporate_penalties (node, info, evaluation);
3312 evaluation *= 1000;
3314 if (dump_file && (dump_flags & TDF_DETAILS))
3315 fprintf (dump_file, " good_cloning_opportunity_p (time: %g, "
3316 "size: %i, freq_sum: %g%s%s) -> evaluation: %.2f, "
3317 "threshold: %i\n",
3318 time_benefit.to_double (), size_cost, freq_sum.to_double (),
3319 info->node_within_scc
3320 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
3321 info->node_calling_single_call ? ", single_call" : "",
3322 evaluation.to_double (), eval_threshold);
3324 return evaluation.to_int () >= eval_threshold;
3328 /* Return all context independent values from aggregate lattices in PLATS in a
3329 vector. Return NULL if there are none. */
3331 static vec<ipa_agg_value>
3332 context_independent_aggregate_values (class ipcp_param_lattices *plats)
3334 vec<ipa_agg_value> res = vNULL;
3336 if (plats->aggs_bottom
3337 || plats->aggs_contain_variable
3338 || plats->aggs_count == 0)
3339 return vNULL;
3341 for (struct ipcp_agg_lattice *aglat = plats->aggs;
3342 aglat;
3343 aglat = aglat->next)
3344 if (aglat->is_single_const ())
3346 struct ipa_agg_value item;
3347 item.offset = aglat->offset;
3348 item.value = aglat->values->value;
3349 res.safe_push (item);
3351 return res;
3354 /* Grow vectors in AVALS and fill them with information about values of
3355 parameters that are known to be independent of the context. Only calculate
3356 m_known_aggs if CALCULATE_AGGS is true. INFO describes the function. If
3357 REMOVABLE_PARAMS_COST is non-NULL, the movement cost of all removable
3358 parameters will be stored in it.
3360 TODO: Also grow context independent value range vectors. */
3362 static bool
3363 gather_context_independent_values (class ipa_node_params *info,
3364 ipa_auto_call_arg_values *avals,
3365 bool calculate_aggs,
3366 int *removable_params_cost)
3368 int i, count = ipa_get_param_count (info);
3369 bool ret = false;
3371 avals->m_known_vals.safe_grow_cleared (count, true);
3372 avals->m_known_contexts.safe_grow_cleared (count, true);
3373 if (calculate_aggs)
3374 avals->m_known_aggs.safe_grow_cleared (count, true);
3376 if (removable_params_cost)
3377 *removable_params_cost = 0;
3379 for (i = 0; i < count; i++)
3381 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3382 ipcp_lattice<tree> *lat = &plats->itself;
3384 if (lat->is_single_const ())
3386 ipcp_value<tree> *val = lat->values;
3387 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3388 avals->m_known_vals[i] = val->value;
3389 if (removable_params_cost)
3390 *removable_params_cost
3391 += estimate_move_cost (TREE_TYPE (val->value), false);
3392 ret = true;
3394 else if (removable_params_cost
3395 && !ipa_is_param_used (info, i))
3396 *removable_params_cost
3397 += ipa_get_param_move_cost (info, i);
3399 if (!ipa_is_param_used (info, i))
3400 continue;
3402 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3403 /* Do not account known context as reason for cloning. We can see
3404 if it permits devirtualization. */
3405 if (ctxlat->is_single_const ())
3406 avals->m_known_contexts[i] = ctxlat->values->value;
3408 if (calculate_aggs)
3410 vec<ipa_agg_value> agg_items;
3411 struct ipa_agg_value_set *agg;
3413 agg_items = context_independent_aggregate_values (plats);
3414 agg = &avals->m_known_aggs[i];
3415 agg->items = agg_items;
3416 agg->by_ref = plats->aggs_by_ref;
3417 ret |= !agg_items.is_empty ();
3421 return ret;
3424 /* Perform time and size measurement of NODE with the context given in AVALS,
3425 calculate the benefit compared to the node without specialization and store
3426 it into VAL. Take into account REMOVABLE_PARAMS_COST of all
3427 context-independent or unused removable parameters and EST_MOVE_COST, the
3428 estimated movement of the considered parameter. */
3430 static void
3431 perform_estimation_of_a_value (cgraph_node *node,
3432 ipa_auto_call_arg_values *avals,
3433 int removable_params_cost, int est_move_cost,
3434 ipcp_value_base *val)
3436 sreal time_benefit;
3437 ipa_call_estimates estimates;
3439 estimate_ipcp_clone_size_and_time (node, avals, &estimates);
3441 /* Extern inline functions have no cloning local time benefits because they
3442 will be inlined anyway. The only reason to clone them is if it enables
3443 optimization in any of the functions they call. */
3444 if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl))
3445 time_benefit = 0;
3446 else
3447 time_benefit = (estimates.nonspecialized_time - estimates.time)
3448 + (devirtualization_time_bonus (node, avals)
3449 + hint_time_bonus (node, estimates)
3450 + removable_params_cost + est_move_cost);
3452 int size = estimates.size;
3453 gcc_checking_assert (size >=0);
3454 /* The inliner-heuristics based estimates may think that in certain
3455 contexts some functions do not have any size at all but we want
3456 all specializations to have at least a tiny cost, not least not to
3457 divide by zero. */
3458 if (size == 0)
3459 size = 1;
3461 val->local_time_benefit = time_benefit;
3462 val->local_size_cost = size;
3465 /* Get the overall limit oof growth based on parameters extracted from growth.
3466 it does not really make sense to mix functions with different overall growth
3467 limits but it is possible and if it happens, we do not want to select one
3468 limit at random. */
3470 static long
3471 get_max_overall_size (cgraph_node *node)
3473 long max_new_size = orig_overall_size;
3474 long large_unit = opt_for_fn (node->decl, param_ipa_cp_large_unit_insns);
3475 if (max_new_size < large_unit)
3476 max_new_size = large_unit;
3477 int unit_growth = opt_for_fn (node->decl, param_ipa_cp_unit_growth);
3478 max_new_size += max_new_size * unit_growth / 100 + 1;
3479 return max_new_size;
3482 /* Iterate over known values of parameters of NODE and estimate the local
3483 effects in terms of time and size they have. */
3485 static void
3486 estimate_local_effects (struct cgraph_node *node)
3488 class ipa_node_params *info = IPA_NODE_REF (node);
3489 int i, count = ipa_get_param_count (info);
3490 bool always_const;
3491 int removable_params_cost;
3493 if (!count || !ipcp_versionable_function_p (node))
3494 return;
3496 if (dump_file && (dump_flags & TDF_DETAILS))
3497 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ());
3499 ipa_auto_call_arg_values avals;
3500 always_const = gather_context_independent_values (info, &avals, true,
3501 &removable_params_cost);
3502 int devirt_bonus = devirtualization_time_bonus (node, &avals);
3503 if (always_const || devirt_bonus
3504 || (removable_params_cost && node->can_change_signature))
3506 struct caller_statistics stats;
3507 ipa_call_estimates estimates;
3509 init_caller_stats (&stats);
3510 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3511 false);
3512 estimate_ipcp_clone_size_and_time (node, &avals, &estimates);
3513 sreal time = estimates.nonspecialized_time - estimates.time;
3514 time += devirt_bonus;
3515 time += hint_time_bonus (node, estimates);
3516 time += removable_params_cost;
3517 int size = estimates.size - stats.n_calls * removable_params_cost;
3519 if (dump_file)
3520 fprintf (dump_file, " - context independent values, size: %i, "
3521 "time_benefit: %f\n", size, (time).to_double ());
3523 if (size <= 0 || node->local)
3525 info->do_clone_for_all_contexts = true;
3527 if (dump_file)
3528 fprintf (dump_file, " Decided to specialize for all "
3529 "known contexts, code not going to grow.\n");
3531 else if (good_cloning_opportunity_p (node, time, stats.freq_sum,
3532 stats.count_sum, size))
3534 if (size + overall_size <= get_max_overall_size (node))
3536 info->do_clone_for_all_contexts = true;
3537 overall_size += size;
3539 if (dump_file)
3540 fprintf (dump_file, " Decided to specialize for all "
3541 "known contexts, growth (to %li) deemed "
3542 "beneficial.\n", overall_size);
3544 else if (dump_file && (dump_flags & TDF_DETAILS))
3545 fprintf (dump_file, " Not cloning for all contexts because "
3546 "maximum unit size would be reached with %li.\n",
3547 size + overall_size);
3549 else if (dump_file && (dump_flags & TDF_DETAILS))
3550 fprintf (dump_file, " Not cloning for all contexts because "
3551 "!good_cloning_opportunity_p.\n");
3555 for (i = 0; i < count; i++)
3557 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3558 ipcp_lattice<tree> *lat = &plats->itself;
3559 ipcp_value<tree> *val;
3561 if (lat->bottom
3562 || !lat->values
3563 || avals.m_known_vals[i])
3564 continue;
3566 for (val = lat->values; val; val = val->next)
3568 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
3569 avals.m_known_vals[i] = val->value;
3571 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
3572 perform_estimation_of_a_value (node, &avals, removable_params_cost,
3573 emc, val);
3575 if (dump_file && (dump_flags & TDF_DETAILS))
3577 fprintf (dump_file, " - estimates for value ");
3578 print_ipcp_constant_value (dump_file, val->value);
3579 fprintf (dump_file, " for ");
3580 ipa_dump_param (dump_file, info, i);
3581 fprintf (dump_file, ": time_benefit: %g, size: %i\n",
3582 val->local_time_benefit.to_double (),
3583 val->local_size_cost);
3586 avals.m_known_vals[i] = NULL_TREE;
3589 for (i = 0; i < count; i++)
3591 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3593 if (!plats->virt_call)
3594 continue;
3596 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3597 ipcp_value<ipa_polymorphic_call_context> *val;
3599 if (ctxlat->bottom
3600 || !ctxlat->values
3601 || !avals.m_known_contexts[i].useless_p ())
3602 continue;
3604 for (val = ctxlat->values; val; val = val->next)
3606 avals.m_known_contexts[i] = val->value;
3607 perform_estimation_of_a_value (node, &avals, removable_params_cost,
3608 0, val);
3610 if (dump_file && (dump_flags & TDF_DETAILS))
3612 fprintf (dump_file, " - estimates for polymorphic context ");
3613 print_ipcp_constant_value (dump_file, val->value);
3614 fprintf (dump_file, " for ");
3615 ipa_dump_param (dump_file, info, i);
3616 fprintf (dump_file, ": time_benefit: %g, size: %i\n",
3617 val->local_time_benefit.to_double (),
3618 val->local_size_cost);
3621 avals.m_known_contexts[i] = ipa_polymorphic_call_context ();
3624 for (i = 0; i < count; i++)
3626 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3628 if (plats->aggs_bottom || !plats->aggs)
3629 continue;
3631 ipa_agg_value_set *agg = &avals.m_known_aggs[i];
3632 for (ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
3634 ipcp_value<tree> *val;
3635 if (aglat->bottom || !aglat->values
3636 /* If the following is true, the one value is in known_aggs. */
3637 || (!plats->aggs_contain_variable
3638 && aglat->is_single_const ()))
3639 continue;
3641 for (val = aglat->values; val; val = val->next)
3643 struct ipa_agg_value item;
3645 item.offset = aglat->offset;
3646 item.value = val->value;
3647 agg->items.safe_push (item);
3649 perform_estimation_of_a_value (node, &avals,
3650 removable_params_cost, 0, val);
3652 if (dump_file && (dump_flags & TDF_DETAILS))
3654 fprintf (dump_file, " - estimates for value ");
3655 print_ipcp_constant_value (dump_file, val->value);
3656 fprintf (dump_file, " for ");
3657 ipa_dump_param (dump_file, info, i);
3658 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3659 "]: time_benefit: %g, size: %i\n",
3660 plats->aggs_by_ref ? "ref " : "",
3661 aglat->offset,
3662 val->local_time_benefit.to_double (),
3663 val->local_size_cost);
3666 agg->items.pop ();
3673 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3674 topological sort of values. */
3676 template <typename valtype>
3677 void
3678 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
3680 ipcp_value_source<valtype> *src;
3682 if (cur_val->dfs)
3683 return;
3685 dfs_counter++;
3686 cur_val->dfs = dfs_counter;
3687 cur_val->low_link = dfs_counter;
3689 cur_val->topo_next = stack;
3690 stack = cur_val;
3691 cur_val->on_stack = true;
3693 for (src = cur_val->sources; src; src = src->next)
3694 if (src->val)
3696 if (src->val->dfs == 0)
3698 add_val (src->val);
3699 if (src->val->low_link < cur_val->low_link)
3700 cur_val->low_link = src->val->low_link;
3702 else if (src->val->on_stack
3703 && src->val->dfs < cur_val->low_link)
3704 cur_val->low_link = src->val->dfs;
3707 if (cur_val->dfs == cur_val->low_link)
3709 ipcp_value<valtype> *v, *scc_list = NULL;
3713 v = stack;
3714 stack = v->topo_next;
3715 v->on_stack = false;
3717 v->scc_next = scc_list;
3718 scc_list = v;
3720 while (v != cur_val);
3722 cur_val->topo_next = values_topo;
3723 values_topo = cur_val;
3727 /* Add all values in lattices associated with NODE to the topological sort if
3728 they are not there yet. */
3730 static void
3731 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3733 class ipa_node_params *info = IPA_NODE_REF (node);
3734 int i, count = ipa_get_param_count (info);
3736 for (i = 0; i < count; i++)
3738 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
3739 ipcp_lattice<tree> *lat = &plats->itself;
3740 struct ipcp_agg_lattice *aglat;
3742 if (!lat->bottom)
3744 ipcp_value<tree> *val;
3745 for (val = lat->values; val; val = val->next)
3746 topo->constants.add_val (val);
3749 if (!plats->aggs_bottom)
3750 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3751 if (!aglat->bottom)
3753 ipcp_value<tree> *val;
3754 for (val = aglat->values; val; val = val->next)
3755 topo->constants.add_val (val);
3758 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
3759 if (!ctxlat->bottom)
3761 ipcp_value<ipa_polymorphic_call_context> *ctxval;
3762 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
3763 topo->contexts.add_val (ctxval);
3768 /* One pass of constants propagation along the call graph edges, from callers
3769 to callees (requires topological ordering in TOPO), iterate over strongly
3770 connected components. */
3772 static void
3773 propagate_constants_topo (class ipa_topo_info *topo)
3775 int i;
3777 for (i = topo->nnodes - 1; i >= 0; i--)
3779 unsigned j;
3780 struct cgraph_node *v, *node = topo->order[i];
3781 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
3783 /* First, iteratively propagate within the strongly connected component
3784 until all lattices stabilize. */
3785 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3786 if (v->has_gimple_body_p ())
3788 if (opt_for_fn (v->decl, flag_ipa_cp)
3789 && opt_for_fn (v->decl, optimize))
3790 push_node_to_stack (topo, v);
3791 /* When V is not optimized, we can not push it to stack, but
3792 still we need to set all its callees lattices to bottom. */
3793 else
3795 for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
3796 propagate_constants_across_call (cs);
3800 v = pop_node_from_stack (topo);
3801 while (v)
3803 struct cgraph_edge *cs;
3804 class ipa_node_params *info = NULL;
3805 bool self_scc = true;
3807 for (cs = v->callees; cs; cs = cs->next_callee)
3808 if (ipa_edge_within_scc (cs))
3810 cgraph_node *callee = cs->callee->function_symbol ();
3812 if (v != callee)
3813 self_scc = false;
3815 if (!info)
3817 info = IPA_NODE_REF (v);
3818 info->node_within_scc = true;
3821 if (propagate_constants_across_call (cs))
3822 push_node_to_stack (topo, callee);
3825 if (info)
3826 info->node_is_self_scc = self_scc;
3828 v = pop_node_from_stack (topo);
3831 /* Afterwards, propagate along edges leading out of the SCC, calculates
3832 the local effects of the discovered constants and all valid values to
3833 their topological sort. */
3834 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3835 if (v->has_gimple_body_p ()
3836 && opt_for_fn (v->decl, flag_ipa_cp)
3837 && opt_for_fn (v->decl, optimize))
3839 struct cgraph_edge *cs;
3841 estimate_local_effects (v);
3842 add_all_node_vals_to_toposort (v, topo);
3843 for (cs = v->callees; cs; cs = cs->next_callee)
3844 if (!ipa_edge_within_scc (cs))
3845 propagate_constants_across_call (cs);
3847 cycle_nodes.release ();
3852 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3853 INT_MAX. */
3855 static int
3856 safe_add (int a, int b)
3858 if (a > INT_MAX/2 || b > INT_MAX/2)
3859 return INT_MAX;
3860 else
3861 return a + b;
3865 /* Propagate the estimated effects of individual values along the topological
3866 from the dependent values to those they depend on. */
3868 template <typename valtype>
3869 void
3870 value_topo_info<valtype>::propagate_effects ()
3872 ipcp_value<valtype> *base;
3874 for (base = values_topo; base; base = base->topo_next)
3876 ipcp_value_source<valtype> *src;
3877 ipcp_value<valtype> *val;
3878 sreal time = 0;
3879 int size = 0;
3881 for (val = base; val; val = val->scc_next)
3883 time = time + val->local_time_benefit + val->prop_time_benefit;
3884 size = safe_add (size, safe_add (val->local_size_cost,
3885 val->prop_size_cost));
3888 for (val = base; val; val = val->scc_next)
3889 for (src = val->sources; src; src = src->next)
3890 if (src->val
3891 && src->cs->maybe_hot_p ())
3893 src->val->prop_time_benefit = time + src->val->prop_time_benefit;
3894 src->val->prop_size_cost = safe_add (size,
3895 src->val->prop_size_cost);
3901 /* Propagate constants, polymorphic contexts and their effects from the
3902 summaries interprocedurally. */
3904 static void
3905 ipcp_propagate_stage (class ipa_topo_info *topo)
3907 struct cgraph_node *node;
3909 if (dump_file)
3910 fprintf (dump_file, "\n Propagating constants:\n\n");
3912 max_count = profile_count::uninitialized ();
3914 FOR_EACH_DEFINED_FUNCTION (node)
3916 if (node->has_gimple_body_p ()
3917 && opt_for_fn (node->decl, flag_ipa_cp)
3918 && opt_for_fn (node->decl, optimize))
3920 class ipa_node_params *info = IPA_NODE_REF (node);
3921 determine_versionability (node, info);
3923 unsigned nlattices = ipa_get_param_count (info);
3924 void *chunk = XCNEWVEC (class ipcp_param_lattices, nlattices);
3925 info->lattices = new (chunk) ipcp_param_lattices[nlattices];
3926 initialize_node_lattices (node);
3928 ipa_size_summary *s = ipa_size_summaries->get (node);
3929 if (node->definition && !node->alias && s != NULL)
3930 overall_size += s->self_size;
3931 max_count = max_count.max (node->count.ipa ());
3934 orig_overall_size = overall_size;
3936 if (dump_file)
3937 fprintf (dump_file, "\noverall_size: %li\n", overall_size);
3939 propagate_constants_topo (topo);
3940 if (flag_checking)
3941 ipcp_verify_propagated_values ();
3942 topo->constants.propagate_effects ();
3943 topo->contexts.propagate_effects ();
3945 if (dump_file)
3947 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
3948 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
3952 /* Discover newly direct outgoing edges from NODE which is a new clone with
3953 known KNOWN_CSTS and make them direct. */
3955 static void
3956 ipcp_discover_new_direct_edges (struct cgraph_node *node,
3957 vec<tree> known_csts,
3958 vec<ipa_polymorphic_call_context>
3959 known_contexts,
3960 struct ipa_agg_replacement_value *aggvals)
3962 struct cgraph_edge *ie, *next_ie;
3963 bool found = false;
3965 for (ie = node->indirect_calls; ie; ie = next_ie)
3967 tree target;
3968 bool speculative;
3970 next_ie = ie->next_callee;
3971 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
3972 vNULL, aggvals, &speculative);
3973 if (target)
3975 bool agg_contents = ie->indirect_info->agg_contents;
3976 bool polymorphic = ie->indirect_info->polymorphic;
3977 int param_index = ie->indirect_info->param_index;
3978 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
3979 speculative);
3980 found = true;
3982 if (cs && !agg_contents && !polymorphic)
3984 class ipa_node_params *info = IPA_NODE_REF (node);
3985 int c = ipa_get_controlled_uses (info, param_index);
3986 if (c != IPA_UNDESCRIBED_USE)
3988 struct ipa_ref *to_del;
3990 c--;
3991 ipa_set_controlled_uses (info, param_index, c);
3992 if (dump_file && (dump_flags & TDF_DETAILS))
3993 fprintf (dump_file, " controlled uses count of param "
3994 "%i bumped down to %i\n", param_index, c);
3995 if (c == 0
3996 && (to_del = node->find_reference (cs->callee, NULL, 0)))
3998 if (dump_file && (dump_flags & TDF_DETAILS))
3999 fprintf (dump_file, " and even removing its "
4000 "cloning-created reference\n");
4001 to_del->remove_reference ();
4007 /* Turning calls to direct calls will improve overall summary. */
4008 if (found)
4009 ipa_update_overall_fn_summary (node);
4012 class edge_clone_summary;
4013 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL;
4015 /* Edge clone summary. */
4017 class edge_clone_summary
4019 public:
4020 /* Default constructor. */
4021 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
4023 /* Default destructor. */
4024 ~edge_clone_summary ()
4026 if (prev_clone)
4027 edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
4028 if (next_clone)
4029 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
4032 cgraph_edge *prev_clone;
4033 cgraph_edge *next_clone;
4036 class edge_clone_summary_t:
4037 public call_summary <edge_clone_summary *>
4039 public:
4040 edge_clone_summary_t (symbol_table *symtab):
4041 call_summary <edge_clone_summary *> (symtab)
4043 m_initialize_when_cloning = true;
4046 virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4047 edge_clone_summary *src_data,
4048 edge_clone_summary *dst_data);
4051 /* Edge duplication hook. */
4053 void
4054 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
4055 edge_clone_summary *src_data,
4056 edge_clone_summary *dst_data)
4058 if (src_data->next_clone)
4059 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
4060 dst_data->prev_clone = src_edge;
4061 dst_data->next_clone = src_data->next_clone;
4062 src_data->next_clone = dst_edge;
4065 /* Return true is CS calls DEST or its clone for all contexts. When
4066 ALLOW_RECURSION_TO_CLONE is false, also return false for self-recursive
4067 edges from/to an all-context clone. */
4069 static bool
4070 calls_same_node_or_its_all_contexts_clone_p (cgraph_edge *cs, cgraph_node *dest,
4071 bool allow_recursion_to_clone)
4073 enum availability availability;
4074 cgraph_node *callee = cs->callee->function_symbol (&availability);
4076 if (availability <= AVAIL_INTERPOSABLE)
4077 return false;
4078 if (callee == dest)
4079 return true;
4080 if (!allow_recursion_to_clone && cs->caller == callee)
4081 return false;
4083 class ipa_node_params *info = IPA_NODE_REF (callee);
4084 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
4087 /* Return true if edge CS does bring about the value described by SRC to
4088 DEST_VAL of node DEST or its clone for all contexts. */
4090 static bool
4091 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
4092 cgraph_node *dest, ipcp_value<tree> *dest_val)
4094 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4096 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, !src->val)
4097 || caller_info->node_dead)
4098 return false;
4100 if (!src->val)
4101 return true;
4103 if (caller_info->ipcp_orig_node)
4105 tree t;
4106 if (src->offset == -1)
4107 t = caller_info->known_csts[src->index];
4108 else
4109 t = get_clone_agg_value (cs->caller, src->offset, src->index);
4110 return (t != NULL_TREE
4111 && values_equal_for_ipcp_p (src->val->value, t));
4113 else
4115 if (src->val == dest_val)
4116 return true;
4118 struct ipcp_agg_lattice *aglat;
4119 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4120 src->index);
4121 if (src->offset == -1)
4122 return (plats->itself.is_single_const ()
4123 && values_equal_for_ipcp_p (src->val->value,
4124 plats->itself.values->value));
4125 else
4127 if (plats->aggs_bottom || plats->aggs_contain_variable)
4128 return false;
4129 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4130 if (aglat->offset == src->offset)
4131 return (aglat->is_single_const ()
4132 && values_equal_for_ipcp_p (src->val->value,
4133 aglat->values->value));
4135 return false;
4139 /* Return true if edge CS does bring about the value described by SRC to
4140 DST_VAL of node DEST or its clone for all contexts. */
4142 static bool
4143 cgraph_edge_brings_value_p (cgraph_edge *cs,
4144 ipcp_value_source<ipa_polymorphic_call_context> *src,
4145 cgraph_node *dest,
4146 ipcp_value<ipa_polymorphic_call_context> *)
4148 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
4150 if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest, true)
4151 || caller_info->node_dead)
4152 return false;
4153 if (!src->val)
4154 return true;
4156 if (caller_info->ipcp_orig_node)
4157 return (caller_info->known_contexts.length () > (unsigned) src->index)
4158 && values_equal_for_ipcp_p (src->val->value,
4159 caller_info->known_contexts[src->index]);
4161 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
4162 src->index);
4163 return plats->ctxlat.is_single_const ()
4164 && values_equal_for_ipcp_p (src->val->value,
4165 plats->ctxlat.values->value);
4168 /* Get the next clone in the linked list of clones of an edge. */
4170 static inline struct cgraph_edge *
4171 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
4173 edge_clone_summary *s = edge_clone_summaries->get (cs);
4174 return s != NULL ? s->next_clone : NULL;
4177 /* Given VAL that is intended for DEST, iterate over all its sources and if any
4178 of them is viable and hot, return true. In that case, for those that still
4179 hold, add their edge frequency and their number into *FREQUENCY and
4180 *CALLER_COUNT respectively. */
4182 template <typename valtype>
4183 static bool
4184 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
4185 sreal *freq_sum, profile_count *count_sum,
4186 int *caller_count)
4188 ipcp_value_source<valtype> *src;
4189 sreal freq = 0;
4190 int count = 0;
4191 profile_count cnt = profile_count::zero ();
4192 bool hot = false;
4193 bool non_self_recursive = false;
4195 for (src = val->sources; src; src = src->next)
4197 struct cgraph_edge *cs = src->cs;
4198 while (cs)
4200 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4202 count++;
4203 freq += cs->sreal_frequency ();
4204 if (cs->count.ipa ().initialized_p ())
4205 cnt += cs->count.ipa ();
4206 hot |= cs->maybe_hot_p ();
4207 if (cs->caller != dest)
4208 non_self_recursive = true;
4210 cs = get_next_cgraph_edge_clone (cs);
4214 /* If the only edges bringing a value are self-recursive ones, do not bother
4215 evaluating it. */
4216 if (!non_self_recursive)
4217 return false;
4219 *freq_sum = freq;
4220 *count_sum = cnt;
4221 *caller_count = count;
4223 if (!hot && IPA_NODE_REF (dest)->node_within_scc)
4225 struct cgraph_edge *cs;
4227 /* Cold non-SCC source edge could trigger hot recursive execution of
4228 function. Consider the case as hot and rely on following cost model
4229 computation to further select right one. */
4230 for (cs = dest->callers; cs; cs = cs->next_caller)
4231 if (cs->caller == dest && cs->maybe_hot_p ())
4232 return true;
4235 return hot;
4238 /* Given a NODE, and a set of its CALLERS, try to adjust order of the callers
4239 to let a non-self-recursive caller be the first element. Thus, we can
4240 simplify intersecting operations on values that arrive from all of these
4241 callers, especially when there exists self-recursive call. Return true if
4242 this kind of adjustment is possible. */
4244 static bool
4245 adjust_callers_for_value_intersection (vec<cgraph_edge *> callers,
4246 cgraph_node *node)
4248 for (unsigned i = 0; i < callers.length (); i++)
4250 cgraph_edge *cs = callers[i];
4252 if (cs->caller != node)
4254 if (i > 0)
4256 callers[i] = callers[0];
4257 callers[0] = cs;
4259 return true;
4262 return false;
4265 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
4266 is assumed their number is known and equal to CALLER_COUNT. */
4268 template <typename valtype>
4269 static vec<cgraph_edge *>
4270 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
4271 int caller_count)
4273 ipcp_value_source<valtype> *src;
4274 vec<cgraph_edge *> ret;
4276 ret.create (caller_count);
4277 for (src = val->sources; src; src = src->next)
4279 struct cgraph_edge *cs = src->cs;
4280 while (cs)
4282 if (cgraph_edge_brings_value_p (cs, src, dest, val))
4283 ret.quick_push (cs);
4284 cs = get_next_cgraph_edge_clone (cs);
4288 if (caller_count > 1)
4289 adjust_callers_for_value_intersection (ret, dest);
4291 return ret;
4294 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
4295 Return it or NULL if for some reason it cannot be created. */
4297 static struct ipa_replace_map *
4298 get_replacement_map (class ipa_node_params *info, tree value, int parm_num)
4300 struct ipa_replace_map *replace_map;
4302 replace_map = ggc_alloc<ipa_replace_map> ();
4303 if (dump_file)
4305 fprintf (dump_file, " replacing ");
4306 ipa_dump_param (dump_file, info, parm_num);
4308 fprintf (dump_file, " with const ");
4309 print_generic_expr (dump_file, value);
4310 fprintf (dump_file, "\n");
4312 replace_map->parm_num = parm_num;
4313 replace_map->new_tree = value;
4314 return replace_map;
4317 /* Dump new profiling counts */
4319 static void
4320 dump_profile_updates (struct cgraph_node *orig_node,
4321 struct cgraph_node *new_node)
4323 struct cgraph_edge *cs;
4325 fprintf (dump_file, " setting count of the specialized node to ");
4326 new_node->count.dump (dump_file);
4327 fprintf (dump_file, "\n");
4328 for (cs = new_node->callees; cs; cs = cs->next_callee)
4330 fprintf (dump_file, " edge to %s has count ",
4331 cs->callee->dump_name ());
4332 cs->count.dump (dump_file);
4333 fprintf (dump_file, "\n");
4336 fprintf (dump_file, " setting count of the original node to ");
4337 orig_node->count.dump (dump_file);
4338 fprintf (dump_file, "\n");
4339 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4341 fprintf (dump_file, " edge to %s is left with ",
4342 cs->callee->dump_name ());
4343 cs->count.dump (dump_file);
4344 fprintf (dump_file, "\n");
4348 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
4349 their profile information to reflect this. */
4351 static void
4352 update_profiling_info (struct cgraph_node *orig_node,
4353 struct cgraph_node *new_node)
4355 struct cgraph_edge *cs;
4356 struct caller_statistics stats;
4357 profile_count new_sum, orig_sum;
4358 profile_count remainder, orig_node_count = orig_node->count;
4359 profile_count orig_new_node_count = new_node->count;
4361 if (!(orig_node_count.ipa () > profile_count::zero ()))
4362 return;
4364 init_caller_stats (&stats);
4365 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
4366 false);
4367 orig_sum = stats.count_sum;
4368 init_caller_stats (&stats);
4369 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
4370 false);
4371 new_sum = stats.count_sum;
4373 if (orig_node_count < orig_sum + new_sum)
4375 if (dump_file)
4377 fprintf (dump_file, " Problem: node %s has too low count ",
4378 orig_node->dump_name ());
4379 orig_node_count.dump (dump_file);
4380 fprintf (dump_file, "while the sum of incoming count is ");
4381 (orig_sum + new_sum).dump (dump_file);
4382 fprintf (dump_file, "\n");
4385 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10);
4386 if (dump_file)
4388 fprintf (dump_file, " proceeding by pretending it was ");
4389 orig_node_count.dump (dump_file);
4390 fprintf (dump_file, "\n");
4394 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
4395 - new_sum.ipa ());
4397 /* With partial train run we do not want to assume that original's
4398 count is zero whenever we redurect all executed edges to clone.
4399 Simply drop profile to local one in this case. */
4400 if (remainder.ipa_p () && !remainder.ipa ().nonzero_p ()
4401 && orig_node->count.ipa_p () && orig_node->count.ipa ().nonzero_p ()
4402 && flag_profile_partial_training)
4403 remainder = remainder.guessed_local ();
4405 new_sum = orig_node_count.combine_with_ipa_count (new_sum);
4406 new_node->count = new_sum;
4407 orig_node->count = remainder;
4409 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_new_node_count);
4410 for (cs = new_node->callees; cs; cs = cs->next_callee)
4411 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4412 for (cs = new_node->indirect_calls; cs; cs = cs->next_callee)
4413 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
4415 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
4416 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4417 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4418 for (cs = orig_node->indirect_calls; cs; cs = cs->next_callee)
4419 cs->count = cs->count.apply_scale (remainder, orig_node_count);
4421 if (dump_file)
4422 dump_profile_updates (orig_node, new_node);
4425 /* Update the respective profile of specialized NEW_NODE and the original
4426 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
4427 have been redirected to the specialized version. */
4429 static void
4430 update_specialized_profile (struct cgraph_node *new_node,
4431 struct cgraph_node *orig_node,
4432 profile_count redirected_sum)
4434 struct cgraph_edge *cs;
4435 profile_count new_node_count, orig_node_count = orig_node->count;
4437 if (dump_file)
4439 fprintf (dump_file, " the sum of counts of redirected edges is ");
4440 redirected_sum.dump (dump_file);
4441 fprintf (dump_file, "\n");
4443 if (!(orig_node_count > profile_count::zero ()))
4444 return;
4446 gcc_assert (orig_node_count >= redirected_sum);
4448 new_node_count = new_node->count;
4449 new_node->count += redirected_sum;
4450 orig_node->count -= redirected_sum;
4452 for (cs = new_node->callees; cs; cs = cs->next_callee)
4453 cs->count += cs->count.apply_scale (redirected_sum, new_node_count);
4455 for (cs = orig_node->callees; cs; cs = cs->next_callee)
4457 profile_count dec = cs->count.apply_scale (redirected_sum,
4458 orig_node_count);
4459 cs->count -= dec;
4462 if (dump_file)
4463 dump_profile_updates (orig_node, new_node);
4466 /* Return true if we would like to remove a parameter from NODE when cloning it
4467 with KNOWN_CSTS scalar constants. */
4469 static bool
4470 want_remove_some_param_p (cgraph_node *node, vec<tree> known_csts)
4472 auto_vec<bool, 16> surviving;
4473 bool filled_vec = false;
4474 ipa_node_params *info = IPA_NODE_REF (node);
4475 int i, count = ipa_get_param_count (info);
4477 for (i = 0; i < count; i++)
4479 if (!known_csts[i] && ipa_is_param_used (info, i))
4480 continue;
4482 if (!filled_vec)
4484 clone_info *info = clone_info::get (node);
4485 if (!info || !info->param_adjustments)
4486 return true;
4487 info->param_adjustments->get_surviving_params (&surviving);
4488 filled_vec = true;
4490 if (surviving.length() < (unsigned) i && surviving[i])
4491 return true;
4493 return false;
4496 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
4497 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
4498 redirect all edges in CALLERS to it. */
4500 static struct cgraph_node *
4501 create_specialized_node (struct cgraph_node *node,
4502 vec<tree> known_csts,
4503 vec<ipa_polymorphic_call_context> known_contexts,
4504 struct ipa_agg_replacement_value *aggvals,
4505 vec<cgraph_edge *> callers)
4507 class ipa_node_params *new_info, *info = IPA_NODE_REF (node);
4508 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
4509 vec<ipa_adjusted_param, va_gc> *new_params = NULL;
4510 struct ipa_agg_replacement_value *av;
4511 struct cgraph_node *new_node;
4512 int i, count = ipa_get_param_count (info);
4513 clone_info *cinfo = clone_info::get (node);
4514 ipa_param_adjustments *old_adjustments = cinfo
4515 ? cinfo->param_adjustments : NULL;
4516 ipa_param_adjustments *new_adjustments;
4517 gcc_assert (!info->ipcp_orig_node);
4518 gcc_assert (node->can_change_signature
4519 || !old_adjustments);
4521 if (old_adjustments)
4523 /* At the moment all IPA optimizations should use the number of
4524 parameters of the prevailing decl as the m_always_copy_start.
4525 Handling any other value would complicate the code below, so for the
4526 time bing let's only assert it is so. */
4527 gcc_assert (old_adjustments->m_always_copy_start == count
4528 || old_adjustments->m_always_copy_start < 0);
4529 int old_adj_count = vec_safe_length (old_adjustments->m_adj_params);
4530 for (i = 0; i < old_adj_count; i++)
4532 ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
4533 if (!node->can_change_signature
4534 || old_adj->op != IPA_PARAM_OP_COPY
4535 || (!known_csts[old_adj->base_index]
4536 && ipa_is_param_used (info, old_adj->base_index)))
4538 ipa_adjusted_param new_adj = *old_adj;
4540 new_adj.prev_clone_adjustment = true;
4541 new_adj.prev_clone_index = i;
4542 vec_safe_push (new_params, new_adj);
4545 bool skip_return = old_adjustments->m_skip_return;
4546 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
4547 ipa_param_adjustments (new_params, count,
4548 skip_return));
4550 else if (node->can_change_signature
4551 && want_remove_some_param_p (node, known_csts))
4553 ipa_adjusted_param adj;
4554 memset (&adj, 0, sizeof (adj));
4555 adj.op = IPA_PARAM_OP_COPY;
4556 for (i = 0; i < count; i++)
4557 if (!known_csts[i] && ipa_is_param_used (info, i))
4559 adj.base_index = i;
4560 adj.prev_clone_index = i;
4561 vec_safe_push (new_params, adj);
4563 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ())
4564 ipa_param_adjustments (new_params, count, false));
4566 else
4567 new_adjustments = NULL;
4569 replace_trees = cinfo ? vec_safe_copy (cinfo->tree_map) : NULL;
4570 for (i = 0; i < count; i++)
4572 tree t = known_csts[i];
4573 if (t)
4575 struct ipa_replace_map *replace_map;
4577 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
4578 replace_map = get_replacement_map (info, t, i);
4579 if (replace_map)
4580 vec_safe_push (replace_trees, replace_map);
4583 auto_vec<cgraph_edge *, 2> self_recursive_calls;
4584 for (i = callers.length () - 1; i >= 0; i--)
4586 cgraph_edge *cs = callers[i];
4587 if (cs->caller == node)
4589 self_recursive_calls.safe_push (cs);
4590 callers.unordered_remove (i);
4594 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
4595 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
4596 node->decl)));
4597 new_node = node->create_virtual_clone (callers, replace_trees,
4598 new_adjustments, "constprop",
4599 suffix_counter);
4600 suffix_counter++;
4602 bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
4603 for (unsigned j = 0; j < self_recursive_calls.length (); j++)
4605 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
4606 /* Cloned edges can disappear during cloning as speculation can be
4607 resolved, check that we have one and that it comes from the last
4608 cloning. */
4609 if (cs && cs->caller == new_node)
4610 cs->redirect_callee_duplicating_thunks (new_node);
4611 /* Any future code that would make more than one clone of an outgoing
4612 edge would confuse this mechanism, so let's check that does not
4613 happen. */
4614 gcc_checking_assert (!cs
4615 || !get_next_cgraph_edge_clone (cs)
4616 || get_next_cgraph_edge_clone (cs)->caller != new_node);
4618 if (have_self_recursive_calls)
4619 new_node->expand_all_artificial_thunks ();
4621 ipa_set_node_agg_value_chain (new_node, aggvals);
4622 for (av = aggvals; av; av = av->next)
4623 new_node->maybe_create_reference (av->value, NULL);
4625 if (dump_file && (dump_flags & TDF_DETAILS))
4627 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ());
4628 if (known_contexts.exists ())
4630 for (i = 0; i < count; i++)
4631 if (!known_contexts[i].useless_p ())
4633 fprintf (dump_file, " known ctx %i is ", i);
4634 known_contexts[i].dump (dump_file);
4637 if (aggvals)
4638 ipa_dump_agg_replacement_values (dump_file, aggvals);
4640 ipa_check_create_node_params ();
4641 update_profiling_info (node, new_node);
4642 new_info = IPA_NODE_REF (new_node);
4643 new_info->ipcp_orig_node = node;
4644 new_node->ipcp_clone = true;
4645 new_info->known_csts = known_csts;
4646 new_info->known_contexts = known_contexts;
4648 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
4650 callers.release ();
4651 return new_node;
4654 /* Return true if JFUNC, which describes a i-th parameter of call CS, is a
4655 pass-through function to itself when the cgraph_node involved is not an
4656 IPA-CP clone. When SIMPLE is true, further check if JFUNC is a simple
4657 no-operation pass-through. */
4659 static bool
4660 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i,
4661 bool simple = true)
4663 enum availability availability;
4664 if (cs->caller == cs->callee->function_symbol (&availability)
4665 && availability > AVAIL_INTERPOSABLE
4666 && jfunc->type == IPA_JF_PASS_THROUGH
4667 && (!simple || ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4668 && ipa_get_jf_pass_through_formal_id (jfunc) == i
4669 && IPA_NODE_REF (cs->caller)
4670 && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
4671 return true;
4672 return false;
4675 /* Return true if JFUNC, which describes a part of an aggregate represented or
4676 pointed to by the i-th parameter of call CS, is a pass-through function to
4677 itself when the cgraph_node involved is not an IPA-CP clone.. When
4678 SIMPLE is true, further check if JFUNC is a simple no-operation
4679 pass-through. */
4681 static bool
4682 self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
4683 int i, bool simple = true)
4685 enum availability availability;
4686 if (cs->caller == cs->callee->function_symbol (&availability)
4687 && availability > AVAIL_INTERPOSABLE
4688 && jfunc->jftype == IPA_JF_LOAD_AGG
4689 && jfunc->offset == jfunc->value.load_agg.offset
4690 && (!simple || jfunc->value.pass_through.operation == NOP_EXPR)
4691 && jfunc->value.pass_through.formal_id == i
4692 && useless_type_conversion_p (jfunc->value.load_agg.type, jfunc->type)
4693 && IPA_NODE_REF (cs->caller)
4694 && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
4695 return true;
4696 return false;
4699 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
4700 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
4702 static void
4703 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
4704 vec<tree> known_csts,
4705 vec<cgraph_edge *> callers)
4707 class ipa_node_params *info = IPA_NODE_REF (node);
4708 int i, count = ipa_get_param_count (info);
4710 for (i = 0; i < count; i++)
4712 struct cgraph_edge *cs;
4713 tree newval = NULL_TREE;
4714 int j;
4715 bool first = true;
4716 tree type = ipa_get_type (info, i);
4718 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
4719 continue;
4721 FOR_EACH_VEC_ELT (callers, j, cs)
4723 struct ipa_jump_func *jump_func;
4724 tree t;
4726 if (!IPA_EDGE_REF (cs)
4727 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
4728 || (i == 0
4729 && call_passes_through_thunk (cs)))
4731 newval = NULL_TREE;
4732 break;
4734 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
4736 /* Besides simple pass-through jump function, arithmetic jump
4737 function could also introduce argument-direct-pass-through for
4738 self-feeding recursive call. For example,
4740 fn (int i)
4742 fn (i & 1);
4745 Given that i is 0, recursive propagation via (i & 1) also gets
4746 0. */
4747 if (self_recursive_pass_through_p (cs, jump_func, i, false))
4749 gcc_assert (newval);
4750 t = ipa_get_jf_arith_result (
4751 ipa_get_jf_pass_through_operation (jump_func),
4752 newval,
4753 ipa_get_jf_pass_through_operand (jump_func),
4754 type);
4756 else
4757 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func,
4758 type);
4759 if (!t
4760 || (newval
4761 && !values_equal_for_ipcp_p (t, newval))
4762 || (!first && !newval))
4764 newval = NULL_TREE;
4765 break;
4767 else
4768 newval = t;
4769 first = false;
4772 if (newval)
4774 if (dump_file && (dump_flags & TDF_DETAILS))
4776 fprintf (dump_file, " adding an extra known scalar value ");
4777 print_ipcp_constant_value (dump_file, newval);
4778 fprintf (dump_file, " for ");
4779 ipa_dump_param (dump_file, info, i);
4780 fprintf (dump_file, "\n");
4783 known_csts[i] = newval;
4788 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
4789 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
4790 CALLERS. */
4792 static void
4793 find_more_contexts_for_caller_subset (cgraph_node *node,
4794 vec<ipa_polymorphic_call_context>
4795 *known_contexts,
4796 vec<cgraph_edge *> callers)
4798 ipa_node_params *info = IPA_NODE_REF (node);
4799 int i, count = ipa_get_param_count (info);
4801 for (i = 0; i < count; i++)
4803 cgraph_edge *cs;
4805 if (ipa_get_poly_ctx_lat (info, i)->bottom
4806 || (known_contexts->exists ()
4807 && !(*known_contexts)[i].useless_p ()))
4808 continue;
4810 ipa_polymorphic_call_context newval;
4811 bool first = true;
4812 int j;
4814 FOR_EACH_VEC_ELT (callers, j, cs)
4816 if (!IPA_EDGE_REF (cs)
4817 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
4818 return;
4819 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
4821 ipa_polymorphic_call_context ctx;
4822 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
4823 jfunc);
4824 if (first)
4826 newval = ctx;
4827 first = false;
4829 else
4830 newval.meet_with (ctx);
4831 if (newval.useless_p ())
4832 break;
4835 if (!newval.useless_p ())
4837 if (dump_file && (dump_flags & TDF_DETAILS))
4839 fprintf (dump_file, " adding an extra known polymorphic "
4840 "context ");
4841 print_ipcp_constant_value (dump_file, newval);
4842 fprintf (dump_file, " for ");
4843 ipa_dump_param (dump_file, info, i);
4844 fprintf (dump_file, "\n");
4847 if (!known_contexts->exists ())
4848 known_contexts->safe_grow_cleared (ipa_get_param_count (info),
4849 true);
4850 (*known_contexts)[i] = newval;
4856 /* Go through PLATS and create a vector of values consisting of values and
4857 offsets (minus OFFSET) of lattices that contain only a single value. */
4859 static vec<ipa_agg_value>
4860 copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset)
4862 vec<ipa_agg_value> res = vNULL;
4864 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4865 return vNULL;
4867 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
4868 if (aglat->is_single_const ())
4870 struct ipa_agg_value ti;
4871 ti.offset = aglat->offset - offset;
4872 ti.value = aglat->values->value;
4873 res.safe_push (ti);
4875 return res;
4878 /* Intersect all values in INTER with single value lattices in PLATS (while
4879 subtracting OFFSET). */
4881 static void
4882 intersect_with_plats (class ipcp_param_lattices *plats,
4883 vec<ipa_agg_value> *inter,
4884 HOST_WIDE_INT offset)
4886 struct ipcp_agg_lattice *aglat;
4887 struct ipa_agg_value *item;
4888 int k;
4890 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
4892 inter->release ();
4893 return;
4896 aglat = plats->aggs;
4897 FOR_EACH_VEC_ELT (*inter, k, item)
4899 bool found = false;
4900 if (!item->value)
4901 continue;
4902 while (aglat)
4904 if (aglat->offset - offset > item->offset)
4905 break;
4906 if (aglat->offset - offset == item->offset)
4908 if (aglat->is_single_const ())
4910 tree value = aglat->values->value;
4912 if (values_equal_for_ipcp_p (item->value, value))
4913 found = true;
4915 break;
4917 aglat = aglat->next;
4919 if (!found)
4920 item->value = NULL_TREE;
4924 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4925 vector result while subtracting OFFSET from the individual value offsets. */
4927 static vec<ipa_agg_value>
4928 agg_replacements_to_vector (struct cgraph_node *node, int index,
4929 HOST_WIDE_INT offset)
4931 struct ipa_agg_replacement_value *av;
4932 vec<ipa_agg_value> res = vNULL;
4934 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
4935 if (av->index == index
4936 && (av->offset - offset) >= 0)
4938 struct ipa_agg_value item;
4939 gcc_checking_assert (av->value);
4940 item.offset = av->offset - offset;
4941 item.value = av->value;
4942 res.safe_push (item);
4945 return res;
4948 /* Intersect all values in INTER with those that we have already scheduled to
4949 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4950 (while subtracting OFFSET). */
4952 static void
4953 intersect_with_agg_replacements (struct cgraph_node *node, int index,
4954 vec<ipa_agg_value> *inter,
4955 HOST_WIDE_INT offset)
4957 struct ipa_agg_replacement_value *srcvals;
4958 struct ipa_agg_value *item;
4959 int i;
4961 srcvals = ipa_get_agg_replacements_for_node (node);
4962 if (!srcvals)
4964 inter->release ();
4965 return;
4968 FOR_EACH_VEC_ELT (*inter, i, item)
4970 struct ipa_agg_replacement_value *av;
4971 bool found = false;
4972 if (!item->value)
4973 continue;
4974 for (av = srcvals; av; av = av->next)
4976 gcc_checking_assert (av->value);
4977 if (av->index == index
4978 && av->offset - offset == item->offset)
4980 if (values_equal_for_ipcp_p (item->value, av->value))
4981 found = true;
4982 break;
4985 if (!found)
4986 item->value = NULL_TREE;
4990 /* Intersect values in INTER with aggregate values that come along edge CS to
4991 parameter number INDEX and return it. If INTER does not actually exist yet,
4992 copy all incoming values to it. If we determine we ended up with no values
4993 whatsoever, return a released vector. */
4995 static vec<ipa_agg_value>
4996 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
4997 vec<ipa_agg_value> inter)
4999 struct ipa_jump_func *jfunc;
5000 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
5001 if (jfunc->type == IPA_JF_PASS_THROUGH
5002 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
5004 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5005 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
5007 if (caller_info->ipcp_orig_node)
5009 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
5010 class ipcp_param_lattices *orig_plats;
5011 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
5012 src_idx);
5013 if (agg_pass_through_permissible_p (orig_plats, jfunc))
5015 if (!inter.exists ())
5016 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
5017 else
5018 intersect_with_agg_replacements (cs->caller, src_idx,
5019 &inter, 0);
5020 return inter;
5023 else
5025 class ipcp_param_lattices *src_plats;
5026 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
5027 if (agg_pass_through_permissible_p (src_plats, jfunc))
5029 /* Currently we do not produce clobber aggregate jump
5030 functions, adjust when we do. */
5031 gcc_checking_assert (!jfunc->agg.items);
5032 if (!inter.exists ())
5033 inter = copy_plats_to_inter (src_plats, 0);
5034 else
5035 intersect_with_plats (src_plats, &inter, 0);
5036 return inter;
5040 else if (jfunc->type == IPA_JF_ANCESTOR
5041 && ipa_get_jf_ancestor_agg_preserved (jfunc))
5043 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5044 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
5045 class ipcp_param_lattices *src_plats;
5046 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
5048 if (caller_info->ipcp_orig_node)
5050 if (!inter.exists ())
5051 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
5052 else
5053 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
5054 delta);
5056 else
5058 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
5059 /* Currently we do not produce clobber aggregate jump
5060 functions, adjust when we do. */
5061 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
5062 if (!inter.exists ())
5063 inter = copy_plats_to_inter (src_plats, delta);
5064 else
5065 intersect_with_plats (src_plats, &inter, delta);
5067 return inter;
5070 if (jfunc->agg.items)
5072 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5073 struct ipa_agg_value *item;
5074 int k;
5076 if (!inter.exists ())
5077 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
5079 struct ipa_agg_jf_item *agg_item = &(*jfunc->agg.items)[i];
5080 tree value = ipa_agg_value_from_node (caller_info, cs->caller,
5081 agg_item);
5082 if (value)
5084 struct ipa_agg_value agg_value;
5086 agg_value.value = value;
5087 agg_value.offset = agg_item->offset;
5088 inter.safe_push (agg_value);
5091 else
5092 FOR_EACH_VEC_ELT (inter, k, item)
5094 int l = 0;
5095 bool found = false;
5097 if (!item->value)
5098 continue;
5100 while ((unsigned) l < jfunc->agg.items->length ())
5102 struct ipa_agg_jf_item *ti;
5103 ti = &(*jfunc->agg.items)[l];
5104 if (ti->offset > item->offset)
5105 break;
5106 if (ti->offset == item->offset)
5108 tree value;
5110 /* Besides simple pass-through aggregate jump function,
5111 arithmetic aggregate jump function could also bring
5112 same aggregate value as parameter passed-in for
5113 self-feeding recursive call. For example,
5115 fn (int *i)
5117 int j = *i & 1;
5118 fn (&j);
5121 Given that *i is 0, recursive propagation via (*i & 1)
5122 also gets 0. */
5123 if (self_recursive_agg_pass_through_p (cs, ti, index,
5124 false))
5125 value = ipa_get_jf_arith_result (
5126 ti->value.pass_through.operation,
5127 item->value,
5128 ti->value.pass_through.operand,
5129 ti->type);
5130 else
5131 value = ipa_agg_value_from_node (caller_info,
5132 cs->caller, ti);
5134 if (value && values_equal_for_ipcp_p (item->value, value))
5135 found = true;
5136 break;
5138 l++;
5140 if (!found)
5141 item->value = NULL;
5144 else
5146 inter.release ();
5147 return vNULL;
5149 return inter;
5152 /* Look at edges in CALLERS and collect all known aggregate values that arrive
5153 from all of them. */
5155 static struct ipa_agg_replacement_value *
5156 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
5157 vec<cgraph_edge *> callers)
5159 class ipa_node_params *dest_info = IPA_NODE_REF (node);
5160 struct ipa_agg_replacement_value *res;
5161 struct ipa_agg_replacement_value **tail = &res;
5162 struct cgraph_edge *cs;
5163 int i, j, count = ipa_get_param_count (dest_info);
5165 FOR_EACH_VEC_ELT (callers, j, cs)
5167 if (!IPA_EDGE_REF (cs))
5169 count = 0;
5170 break;
5172 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
5173 if (c < count)
5174 count = c;
5177 for (i = 0; i < count; i++)
5179 struct cgraph_edge *cs;
5180 vec<ipa_agg_value> inter = vNULL;
5181 struct ipa_agg_value *item;
5182 class ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
5183 int j;
5185 /* Among other things, the following check should deal with all by_ref
5186 mismatches. */
5187 if (plats->aggs_bottom)
5188 continue;
5190 FOR_EACH_VEC_ELT (callers, j, cs)
5192 struct ipa_jump_func *jfunc
5193 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
5194 if (self_recursive_pass_through_p (cs, jfunc, i)
5195 && (!plats->aggs_by_ref
5196 || ipa_get_jf_pass_through_agg_preserved (jfunc)))
5197 continue;
5198 inter = intersect_aggregates_with_edge (cs, i, inter);
5200 if (!inter.exists ())
5201 goto next_param;
5204 FOR_EACH_VEC_ELT (inter, j, item)
5206 struct ipa_agg_replacement_value *v;
5208 if (!item->value)
5209 continue;
5211 v = ggc_alloc<ipa_agg_replacement_value> ();
5212 v->index = i;
5213 v->offset = item->offset;
5214 v->value = item->value;
5215 v->by_ref = plats->aggs_by_ref;
5216 *tail = v;
5217 tail = &v->next;
5220 next_param:
5221 if (inter.exists ())
5222 inter.release ();
5224 *tail = NULL;
5225 return res;
5228 /* Determine whether CS also brings all scalar values that the NODE is
5229 specialized for. */
5231 static bool
5232 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
5233 struct cgraph_node *node)
5235 class ipa_node_params *dest_info = IPA_NODE_REF (node);
5236 int count = ipa_get_param_count (dest_info);
5237 class ipa_node_params *caller_info;
5238 class ipa_edge_args *args;
5239 int i;
5241 caller_info = IPA_NODE_REF (cs->caller);
5242 args = IPA_EDGE_REF (cs);
5243 for (i = 0; i < count; i++)
5245 struct ipa_jump_func *jump_func;
5246 tree val, t;
5248 val = dest_info->known_csts[i];
5249 if (!val)
5250 continue;
5252 if (i >= ipa_get_cs_argument_count (args))
5253 return false;
5254 jump_func = ipa_get_ith_jump_func (args, i);
5255 t = ipa_value_from_jfunc (caller_info, jump_func,
5256 ipa_get_type (dest_info, i));
5257 if (!t || !values_equal_for_ipcp_p (val, t))
5258 return false;
5260 return true;
5263 /* Determine whether CS also brings all aggregate values that NODE is
5264 specialized for. */
5265 static bool
5266 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
5267 struct cgraph_node *node)
5269 class ipa_node_params *orig_node_info;
5270 struct ipa_agg_replacement_value *aggval;
5271 int i, ec, count;
5273 aggval = ipa_get_agg_replacements_for_node (node);
5274 if (!aggval)
5275 return true;
5277 count = ipa_get_param_count (IPA_NODE_REF (node));
5278 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
5279 if (ec < count)
5280 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5281 if (aggval->index >= ec)
5282 return false;
5284 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
5286 for (i = 0; i < count; i++)
5288 class ipcp_param_lattices *plats;
5289 bool interesting = false;
5290 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5291 if (aggval->index == i)
5293 interesting = true;
5294 break;
5296 if (!interesting)
5297 continue;
5299 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
5300 if (plats->aggs_bottom)
5301 return false;
5303 vec<ipa_agg_value> values = intersect_aggregates_with_edge (cs, i, vNULL);
5304 if (!values.exists ())
5305 return false;
5307 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
5308 if (aggval->index == i)
5310 struct ipa_agg_value *item;
5311 int j;
5312 bool found = false;
5313 FOR_EACH_VEC_ELT (values, j, item)
5314 if (item->value
5315 && item->offset == av->offset
5316 && values_equal_for_ipcp_p (item->value, av->value))
5318 found = true;
5319 break;
5321 if (!found)
5323 values.release ();
5324 return false;
5327 values.release ();
5329 return true;
5332 /* Given an original NODE and a VAL for which we have already created a
5333 specialized clone, look whether there are incoming edges that still lead
5334 into the old node but now also bring the requested value and also conform to
5335 all other criteria such that they can be redirected the special node.
5336 This function can therefore redirect the final edge in a SCC. */
5338 template <typename valtype>
5339 static void
5340 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
5342 ipcp_value_source<valtype> *src;
5343 profile_count redirected_sum = profile_count::zero ();
5345 for (src = val->sources; src; src = src->next)
5347 struct cgraph_edge *cs = src->cs;
5348 while (cs)
5350 if (cgraph_edge_brings_value_p (cs, src, node, val)
5351 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
5352 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
5354 if (dump_file)
5355 fprintf (dump_file, " - adding an extra caller %s of %s\n",
5356 cs->caller->dump_name (),
5357 val->spec_node->dump_name ());
5359 cs->redirect_callee_duplicating_thunks (val->spec_node);
5360 val->spec_node->expand_all_artificial_thunks ();
5361 if (cs->count.ipa ().initialized_p ())
5362 redirected_sum = redirected_sum + cs->count.ipa ();
5364 cs = get_next_cgraph_edge_clone (cs);
5368 if (redirected_sum.nonzero_p ())
5369 update_specialized_profile (val->spec_node, node, redirected_sum);
5372 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
5374 static bool
5375 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
5377 ipa_polymorphic_call_context *ctx;
5378 int i;
5380 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
5381 if (!ctx->useless_p ())
5382 return true;
5383 return false;
5386 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
5388 static vec<ipa_polymorphic_call_context>
5389 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
5391 if (known_contexts_useful_p (known_contexts))
5392 return known_contexts.copy ();
5393 else
5394 return vNULL;
5397 /* Copy known scalar values from AVALS into KNOWN_CSTS and modify the copy
5398 according to VAL and INDEX. If non-empty, replace KNOWN_CONTEXTS with its
5399 copy too. */
5401 static void
5402 copy_known_vectors_add_val (ipa_auto_call_arg_values *avals,
5403 vec<tree> *known_csts,
5404 vec<ipa_polymorphic_call_context> *known_contexts,
5405 ipcp_value<tree> *val, int index)
5407 *known_csts = avals->m_known_vals.copy ();
5408 *known_contexts = copy_useful_known_contexts (avals->m_known_contexts);
5409 (*known_csts)[index] = val->value;
5412 /* Copy known scalar values from AVALS into KNOWN_CSTS. Similarly, copy
5413 contexts to KNOWN_CONTEXTS and modify the copy according to VAL and
5414 INDEX. */
5416 static void
5417 copy_known_vectors_add_val (ipa_auto_call_arg_values *avals,
5418 vec<tree> *known_csts,
5419 vec<ipa_polymorphic_call_context> *known_contexts,
5420 ipcp_value<ipa_polymorphic_call_context> *val,
5421 int index)
5423 *known_csts = avals->m_known_vals.copy ();
5424 *known_contexts = avals->m_known_contexts.copy ();
5425 (*known_contexts)[index] = val->value;
5428 /* Return true if OFFSET indicates this was not an aggregate value or there is
5429 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
5430 AGGVALS list. */
5432 DEBUG_FUNCTION bool
5433 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
5434 int index, HOST_WIDE_INT offset, tree value)
5436 if (offset == -1)
5437 return true;
5439 while (aggvals)
5441 if (aggvals->index == index
5442 && aggvals->offset == offset
5443 && values_equal_for_ipcp_p (aggvals->value, value))
5444 return true;
5445 aggvals = aggvals->next;
5447 return false;
5450 /* Return true if offset is minus one because source of a polymorphic context
5451 cannot be an aggregate value. */
5453 DEBUG_FUNCTION bool
5454 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
5455 int , HOST_WIDE_INT offset,
5456 ipa_polymorphic_call_context)
5458 return offset == -1;
5461 /* Decide whether to create a special version of NODE for value VAL of
5462 parameter at the given INDEX. If OFFSET is -1, the value is for the
5463 parameter itself, otherwise it is stored at the given OFFSET of the
5464 parameter. AVALS describes the other already known values. */
5466 template <typename valtype>
5467 static bool
5468 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
5469 ipcp_value<valtype> *val, ipa_auto_call_arg_values *avals)
5471 struct ipa_agg_replacement_value *aggvals;
5472 int caller_count;
5473 sreal freq_sum;
5474 profile_count count_sum;
5475 vec<cgraph_edge *> callers;
5477 if (val->spec_node)
5479 perhaps_add_new_callers (node, val);
5480 return false;
5482 else if (val->local_size_cost + overall_size > get_max_overall_size (node))
5484 if (dump_file && (dump_flags & TDF_DETAILS))
5485 fprintf (dump_file, " Ignoring candidate value because "
5486 "maximum unit size would be reached with %li.\n",
5487 val->local_size_cost + overall_size);
5488 return false;
5490 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
5491 &caller_count))
5492 return false;
5494 if (!dbg_cnt (ipa_cp_values))
5495 return false;
5497 if (dump_file && (dump_flags & TDF_DETAILS))
5499 fprintf (dump_file, " - considering value ");
5500 print_ipcp_constant_value (dump_file, val->value);
5501 fprintf (dump_file, " for ");
5502 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
5503 if (offset != -1)
5504 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
5505 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
5508 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
5509 freq_sum, count_sum,
5510 val->local_size_cost)
5511 && !good_cloning_opportunity_p (node,
5512 val->local_time_benefit
5513 + val->prop_time_benefit,
5514 freq_sum, count_sum,
5515 safe_add (val->local_size_cost,
5516 val->prop_size_cost)))
5517 return false;
5519 if (dump_file)
5520 fprintf (dump_file, " Creating a specialized node of %s.\n",
5521 node->dump_name ());
5523 vec<tree> known_csts;
5524 vec<ipa_polymorphic_call_context> known_contexts;
5526 callers = gather_edges_for_value (val, node, caller_count);
5527 if (offset == -1)
5528 copy_known_vectors_add_val (avals, &known_csts, &known_contexts, val, index);
5529 else
5531 known_csts = avals->m_known_vals.copy ();
5532 known_contexts = copy_useful_known_contexts (avals->m_known_contexts);
5534 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
5535 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
5536 aggvals = find_aggregate_values_for_callers_subset (node, callers);
5537 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
5538 offset, val->value));
5539 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
5540 aggvals, callers);
5541 overall_size += val->local_size_cost;
5542 if (dump_file && (dump_flags & TDF_DETAILS))
5543 fprintf (dump_file, " overall size reached %li\n",
5544 overall_size);
5546 /* TODO: If for some lattice there is only one other known value
5547 left, make a special node for it too. */
5549 return true;
5552 /* Decide whether and what specialized clones of NODE should be created. */
5554 static bool
5555 decide_whether_version_node (struct cgraph_node *node)
5557 class ipa_node_params *info = IPA_NODE_REF (node);
5558 int i, count = ipa_get_param_count (info);
5559 bool ret = false;
5561 if (count == 0)
5562 return false;
5564 if (dump_file && (dump_flags & TDF_DETAILS))
5565 fprintf (dump_file, "\nEvaluating opportunities for %s.\n",
5566 node->dump_name ());
5568 ipa_auto_call_arg_values avals;
5569 gather_context_independent_values (info, &avals, false, NULL);
5571 for (i = 0; i < count;i++)
5573 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5574 ipcp_lattice<tree> *lat = &plats->itself;
5575 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
5577 if (!lat->bottom
5578 && !avals.m_known_vals[i])
5580 ipcp_value<tree> *val;
5581 for (val = lat->values; val; val = val->next)
5582 ret |= decide_about_value (node, i, -1, val, &avals);
5585 if (!plats->aggs_bottom)
5587 struct ipcp_agg_lattice *aglat;
5588 ipcp_value<tree> *val;
5589 for (aglat = plats->aggs; aglat; aglat = aglat->next)
5590 if (!aglat->bottom && aglat->values
5591 /* If the following is false, the one value has been considered
5592 for cloning for all contexts. */
5593 && (plats->aggs_contain_variable
5594 || !aglat->is_single_const ()))
5595 for (val = aglat->values; val; val = val->next)
5596 ret |= decide_about_value (node, i, aglat->offset, val, &avals);
5599 if (!ctxlat->bottom
5600 && avals.m_known_contexts[i].useless_p ())
5602 ipcp_value<ipa_polymorphic_call_context> *val;
5603 for (val = ctxlat->values; val; val = val->next)
5604 ret |= decide_about_value (node, i, -1, val, &avals);
5607 info = IPA_NODE_REF (node);
5610 if (info->do_clone_for_all_contexts)
5612 if (!dbg_cnt (ipa_cp_values))
5614 info->do_clone_for_all_contexts = false;
5615 return ret;
5618 struct cgraph_node *clone;
5619 vec<cgraph_edge *> callers = node->collect_callers ();
5621 for (int i = callers.length () - 1; i >= 0; i--)
5623 cgraph_edge *cs = callers[i];
5624 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
5626 if (caller_info && caller_info->node_dead)
5627 callers.unordered_remove (i);
5630 if (!adjust_callers_for_value_intersection (callers, node))
5632 /* If node is not called by anyone, or all its caller edges are
5633 self-recursive, the node is not really in use, no need to do
5634 cloning. */
5635 callers.release ();
5636 info->do_clone_for_all_contexts = false;
5637 return ret;
5640 if (dump_file)
5641 fprintf (dump_file, " - Creating a specialized node of %s "
5642 "for all known contexts.\n", node->dump_name ());
5644 vec<tree> known_csts = avals.m_known_vals.copy ();
5645 vec<ipa_polymorphic_call_context> known_contexts
5646 = copy_useful_known_contexts (avals.m_known_contexts);
5647 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
5648 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
5649 ipa_agg_replacement_value *aggvals
5650 = find_aggregate_values_for_callers_subset (node, callers);
5652 if (!known_contexts_useful_p (known_contexts))
5654 known_contexts.release ();
5655 known_contexts = vNULL;
5657 clone = create_specialized_node (node, known_csts, known_contexts,
5658 aggvals, callers);
5659 info = IPA_NODE_REF (node);
5660 info->do_clone_for_all_contexts = false;
5661 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
5662 ret = true;
5665 return ret;
5668 /* Transitively mark all callees of NODE within the same SCC as not dead. */
5670 static void
5671 spread_undeadness (struct cgraph_node *node)
5673 struct cgraph_edge *cs;
5675 for (cs = node->callees; cs; cs = cs->next_callee)
5676 if (ipa_edge_within_scc (cs))
5678 struct cgraph_node *callee;
5679 class ipa_node_params *info;
5681 callee = cs->callee->function_symbol (NULL);
5682 info = IPA_NODE_REF (callee);
5684 if (info && info->node_dead)
5686 info->node_dead = 0;
5687 spread_undeadness (callee);
5692 /* Return true if NODE has a caller from outside of its SCC that is not
5693 dead. Worker callback for cgraph_for_node_and_aliases. */
5695 static bool
5696 has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
5697 void *data ATTRIBUTE_UNUSED)
5699 struct cgraph_edge *cs;
5701 for (cs = node->callers; cs; cs = cs->next_caller)
5702 if (cs->caller->thunk
5703 && cs->caller->call_for_symbol_thunks_and_aliases
5704 (has_undead_caller_from_outside_scc_p, NULL, true))
5705 return true;
5706 else if (!ipa_edge_within_scc (cs)
5707 && (!IPA_NODE_REF (cs->caller) /* Unoptimized caller. */
5708 || !IPA_NODE_REF (cs->caller)->node_dead))
5709 return true;
5710 return false;
5714 /* Identify nodes within the same SCC as NODE which are no longer needed
5715 because of new clones and will be removed as unreachable. */
5717 static void
5718 identify_dead_nodes (struct cgraph_node *node)
5720 struct cgraph_node *v;
5721 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5722 if (v->local
5723 && IPA_NODE_REF (v)
5724 && !v->call_for_symbol_thunks_and_aliases
5725 (has_undead_caller_from_outside_scc_p, NULL, true))
5726 IPA_NODE_REF (v)->node_dead = 1;
5728 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5729 if (IPA_NODE_REF (v) && !IPA_NODE_REF (v)->node_dead)
5730 spread_undeadness (v);
5732 if (dump_file && (dump_flags & TDF_DETAILS))
5734 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5735 if (IPA_NODE_REF (v) && IPA_NODE_REF (v)->node_dead)
5736 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ());
5740 /* The decision stage. Iterate over the topological order of call graph nodes
5741 TOPO and make specialized clones if deemed beneficial. */
5743 static void
5744 ipcp_decision_stage (class ipa_topo_info *topo)
5746 int i;
5748 if (dump_file)
5749 fprintf (dump_file, "\nIPA decision stage:\n\n");
5751 for (i = topo->nnodes - 1; i >= 0; i--)
5753 struct cgraph_node *node = topo->order[i];
5754 bool change = false, iterate = true;
5756 while (iterate)
5758 struct cgraph_node *v;
5759 iterate = false;
5760 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
5761 if (v->has_gimple_body_p ()
5762 && ipcp_versionable_function_p (v))
5763 iterate |= decide_whether_version_node (v);
5765 change |= iterate;
5767 if (change)
5768 identify_dead_nodes (node);
5772 /* Look up all the bits information that we have discovered and copy it over
5773 to the transformation summary. */
5775 static void
5776 ipcp_store_bits_results (void)
5778 cgraph_node *node;
5780 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5782 ipa_node_params *info = IPA_NODE_REF (node);
5783 bool dumped_sth = false;
5784 bool found_useful_result = false;
5786 if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
5788 if (dump_file)
5789 fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
5790 "; -fipa-bit-cp: disabled.\n",
5791 node->dump_name ());
5792 continue;
5795 if (info->ipcp_orig_node)
5796 info = IPA_NODE_REF (info->ipcp_orig_node);
5797 if (!info->lattices)
5798 /* Newly expanded artificial thunks do not have lattices. */
5799 continue;
5801 unsigned count = ipa_get_param_count (info);
5802 for (unsigned i = 0; i < count; i++)
5804 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5805 if (plats->bits_lattice.constant_p ())
5807 found_useful_result = true;
5808 break;
5812 if (!found_useful_result)
5813 continue;
5815 ipcp_transformation_initialize ();
5816 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5817 vec_safe_reserve_exact (ts->bits, count);
5819 for (unsigned i = 0; i < count; i++)
5821 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5822 ipa_bits *jfbits;
5824 if (plats->bits_lattice.constant_p ())
5826 jfbits
5827 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
5828 plats->bits_lattice.get_mask ());
5829 if (!dbg_cnt (ipa_cp_bits))
5830 jfbits = NULL;
5832 else
5833 jfbits = NULL;
5835 ts->bits->quick_push (jfbits);
5836 if (!dump_file || !jfbits)
5837 continue;
5838 if (!dumped_sth)
5840 fprintf (dump_file, "Propagated bits info for function %s:\n",
5841 node->dump_name ());
5842 dumped_sth = true;
5844 fprintf (dump_file, " param %i: value = ", i);
5845 print_hex (jfbits->value, dump_file);
5846 fprintf (dump_file, ", mask = ");
5847 print_hex (jfbits->mask, dump_file);
5848 fprintf (dump_file, "\n");
5853 /* Look up all VR information that we have discovered and copy it over
5854 to the transformation summary. */
5856 static void
5857 ipcp_store_vr_results (void)
5859 cgraph_node *node;
5861 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5863 ipa_node_params *info = IPA_NODE_REF (node);
5864 bool found_useful_result = false;
5866 if (!info || !opt_for_fn (node->decl, flag_ipa_vrp))
5868 if (dump_file)
5869 fprintf (dump_file, "Not considering %s for VR discovery "
5870 "and propagate; -fipa-ipa-vrp: disabled.\n",
5871 node->dump_name ());
5872 continue;
5875 if (info->ipcp_orig_node)
5876 info = IPA_NODE_REF (info->ipcp_orig_node);
5877 if (!info->lattices)
5878 /* Newly expanded artificial thunks do not have lattices. */
5879 continue;
5881 unsigned count = ipa_get_param_count (info);
5882 for (unsigned i = 0; i < count; i++)
5884 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5885 if (!plats->m_value_range.bottom_p ()
5886 && !plats->m_value_range.top_p ())
5888 found_useful_result = true;
5889 break;
5892 if (!found_useful_result)
5893 continue;
5895 ipcp_transformation_initialize ();
5896 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
5897 vec_safe_reserve_exact (ts->m_vr, count);
5899 for (unsigned i = 0; i < count; i++)
5901 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
5902 ipa_vr vr;
5904 if (!plats->m_value_range.bottom_p ()
5905 && !plats->m_value_range.top_p ()
5906 && dbg_cnt (ipa_cp_vr))
5908 vr.known = true;
5909 vr.type = plats->m_value_range.m_vr.kind ();
5910 vr.min = wi::to_wide (plats->m_value_range.m_vr.min ());
5911 vr.max = wi::to_wide (plats->m_value_range.m_vr.max ());
5913 else
5915 vr.known = false;
5916 vr.type = VR_VARYING;
5917 vr.min = vr.max = wi::zero (INT_TYPE_SIZE);
5919 ts->m_vr->quick_push (vr);
5924 /* The IPCP driver. */
5926 static unsigned int
5927 ipcp_driver (void)
5929 class ipa_topo_info topo;
5931 if (edge_clone_summaries == NULL)
5932 edge_clone_summaries = new edge_clone_summary_t (symtab);
5934 ipa_check_create_node_params ();
5935 ipa_check_create_edge_args ();
5936 clone_num_suffixes = new hash_map<const char *, unsigned>;
5938 if (dump_file)
5940 fprintf (dump_file, "\nIPA structures before propagation:\n");
5941 if (dump_flags & TDF_DETAILS)
5942 ipa_print_all_params (dump_file);
5943 ipa_print_all_jump_functions (dump_file);
5946 /* Topological sort. */
5947 build_toporder_info (&topo);
5948 /* Do the interprocedural propagation. */
5949 ipcp_propagate_stage (&topo);
5950 /* Decide what constant propagation and cloning should be performed. */
5951 ipcp_decision_stage (&topo);
5952 /* Store results of bits propagation. */
5953 ipcp_store_bits_results ();
5954 /* Store results of value range propagation. */
5955 ipcp_store_vr_results ();
5957 /* Free all IPCP structures. */
5958 delete clone_num_suffixes;
5959 free_toporder_info (&topo);
5960 delete edge_clone_summaries;
5961 edge_clone_summaries = NULL;
5962 ipa_free_all_structures_after_ipa_cp ();
5963 if (dump_file)
5964 fprintf (dump_file, "\nIPA constant propagation end\n");
5965 return 0;
5968 /* Initialization and computation of IPCP data structures. This is the initial
5969 intraprocedural analysis of functions, which gathers information to be
5970 propagated later on. */
5972 static void
5973 ipcp_generate_summary (void)
5975 struct cgraph_node *node;
5977 if (dump_file)
5978 fprintf (dump_file, "\nIPA constant propagation start:\n");
5979 ipa_register_cgraph_hooks ();
5981 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5982 ipa_analyze_node (node);
5985 namespace {
5987 const pass_data pass_data_ipa_cp =
5989 IPA_PASS, /* type */
5990 "cp", /* name */
5991 OPTGROUP_NONE, /* optinfo_flags */
5992 TV_IPA_CONSTANT_PROP, /* tv_id */
5993 0, /* properties_required */
5994 0, /* properties_provided */
5995 0, /* properties_destroyed */
5996 0, /* todo_flags_start */
5997 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
6000 class pass_ipa_cp : public ipa_opt_pass_d
6002 public:
6003 pass_ipa_cp (gcc::context *ctxt)
6004 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
6005 ipcp_generate_summary, /* generate_summary */
6006 NULL, /* write_summary */
6007 NULL, /* read_summary */
6008 ipcp_write_transformation_summaries, /*
6009 write_optimization_summary */
6010 ipcp_read_transformation_summaries, /*
6011 read_optimization_summary */
6012 NULL, /* stmt_fixup */
6013 0, /* function_transform_todo_flags_start */
6014 ipcp_transform_function, /* function_transform */
6015 NULL) /* variable_transform */
6018 /* opt_pass methods: */
6019 virtual bool gate (function *)
6021 /* FIXME: We should remove the optimize check after we ensure we never run
6022 IPA passes when not optimizing. */
6023 return (flag_ipa_cp && optimize) || in_lto_p;
6026 virtual unsigned int execute (function *) { return ipcp_driver (); }
6028 }; // class pass_ipa_cp
6030 } // anon namespace
6032 ipa_opt_pass_d *
6033 make_pass_ipa_cp (gcc::context *ctxt)
6035 return new pass_ipa_cp (ctxt);
6038 /* Reset all state within ipa-cp.c so that we can rerun the compiler
6039 within the same process. For use by toplev::finalize. */
6041 void
6042 ipa_cp_c_finalize (void)
6044 max_count = profile_count::uninitialized ();
6045 overall_size = 0;
6046 orig_overall_size = 0;
6047 ipcp_free_transformation_sum ();