1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2019 Free Software Foundation, Inc.
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
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
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
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
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
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
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
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
105 #include "coretypes.h"
108 #include "gimple-expr.h"
110 #include "alloc-pool.h"
111 #include "tree-pass.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"
122 #include "ipa-fnsummary.h"
123 #include "ipa-utils.h"
124 #include "tree-ssa-ccp.h"
125 #include "stringpool.h"
128 template <typename valtype
> class ipcp_value
;
130 /* Describes a particular source for an IPA-CP value. */
132 template <typename valtype
>
133 struct ipcp_value_source
136 /* Aggregate offset of the source, negative if the source is scalar value of
137 the argument itself. */
138 HOST_WIDE_INT offset
;
139 /* The incoming edge that brought the value. */
141 /* If the jump function that resulted into his value was a pass-through or an
142 ancestor, this is the ipcp_value of the caller from which the described
143 value has been derived. Otherwise it is NULL. */
144 ipcp_value
<valtype
> *val
;
145 /* Next pointer in a linked list of sources of a value. */
146 ipcp_value_source
*next
;
147 /* If the jump function that resulted into his value was a pass-through or an
148 ancestor, this is the index of the parameter of the caller the jump
149 function references. */
153 /* Common ancestor for all ipcp_value instantiations. */
155 class ipcp_value_base
158 /* Time benefit and size cost that specializing the function for this value
159 would bring about in this function alone. */
160 int local_time_benefit
, local_size_cost
;
161 /* Time benefit and size cost that specializing the function for this value
162 can bring about in it's callees (transitively). */
163 int prop_time_benefit
, prop_size_cost
;
166 : local_time_benefit (0), local_size_cost (0),
167 prop_time_benefit (0), prop_size_cost (0) {}
170 /* Describes one particular value stored in struct ipcp_lattice. */
172 template <typename valtype
>
173 class ipcp_value
: public ipcp_value_base
176 /* The actual value for the given parameter. */
178 /* The list of sources from which this value originates. */
179 ipcp_value_source
<valtype
> *sources
;
180 /* Next pointers in a linked list of all values in a lattice. */
182 /* Next pointers in a linked list of values in a strongly connected component
184 ipcp_value
*scc_next
;
185 /* Next pointers in a linked list of SCCs of values sorted topologically
186 according their sources. */
187 ipcp_value
*topo_next
;
188 /* A specialized node created for this value, NULL if none has been (so far)
190 cgraph_node
*spec_node
;
191 /* Depth first search number and low link for topological sorting of
194 /* True if this value is currently on the topo-sort stack. */
198 : sources (0), next (0), scc_next (0), topo_next (0),
199 spec_node (0), dfs (0), low_link (0), on_stack (false) {}
201 void add_source (cgraph_edge
*cs
, ipcp_value
*src_val
, int src_idx
,
202 HOST_WIDE_INT offset
);
205 /* Lattice describing potential values of a formal parameter of a function, or
206 a part of an aggregate. TOP is represented by a lattice with zero values
207 and with contains_variable and bottom flags cleared. BOTTOM is represented
208 by a lattice with the bottom flag set. In that case, values and
209 contains_variable flag should be disregarded. */
211 template <typename valtype
>
215 /* The list of known values and types in this lattice. Note that values are
216 not deallocated if a lattice is set to bottom because there may be value
217 sources referencing them. */
218 ipcp_value
<valtype
> *values
;
219 /* Number of known values and types in this lattice. */
221 /* The lattice contains a variable component (in addition to values). */
222 bool contains_variable
;
223 /* The value of the lattice is bottom (i.e. variable and unusable for any
227 inline bool is_single_const ();
228 inline bool set_to_bottom ();
229 inline bool set_contains_variable ();
230 bool add_value (valtype newval
, cgraph_edge
*cs
,
231 ipcp_value
<valtype
> *src_val
= NULL
,
232 int src_idx
= 0, HOST_WIDE_INT offset
= -1);
233 void print (FILE * f
, bool dump_sources
, bool dump_benefits
);
236 /* Lattice of tree values with an offset to describe a part of an
239 struct ipcp_agg_lattice
: public ipcp_lattice
<tree
>
242 /* Offset that is being described by this lattice. */
243 HOST_WIDE_INT offset
;
244 /* Size so that we don't have to re-compute it every time we traverse the
245 list. Must correspond to TYPE_SIZE of all lat values. */
247 /* Next element of the linked list. */
248 struct ipcp_agg_lattice
*next
;
251 /* Lattice of known bits, only capable of holding one value.
252 Bitwise constant propagation propagates which bits of a
268 In the above case, the param 'x' will always have all
269 the bits (except the bits in lsb) set to 0.
270 Hence the mask of 'x' would be 0xff. The mask
271 reflects that the bits in lsb are unknown.
272 The actual propagated value is given by m_value & ~m_mask. */
274 class ipcp_bits_lattice
277 bool bottom_p () { return m_lattice_val
== IPA_BITS_VARYING
; }
278 bool top_p () { return m_lattice_val
== IPA_BITS_UNDEFINED
; }
279 bool constant_p () { return m_lattice_val
== IPA_BITS_CONSTANT
; }
280 bool set_to_bottom ();
281 bool set_to_constant (widest_int
, widest_int
);
283 widest_int
get_value () { return m_value
; }
284 widest_int
get_mask () { return m_mask
; }
286 bool meet_with (ipcp_bits_lattice
& other
, unsigned, signop
,
287 enum tree_code
, tree
);
289 bool meet_with (widest_int
, widest_int
, unsigned);
294 enum { IPA_BITS_UNDEFINED
, IPA_BITS_CONSTANT
, IPA_BITS_VARYING
} m_lattice_val
;
296 /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
297 If a bit in mask is set to 0, then the corresponding bit in
298 value is known to be constant. */
299 widest_int m_value
, m_mask
;
301 bool meet_with_1 (widest_int
, widest_int
, unsigned);
302 void get_value_and_mask (tree
, widest_int
*, widest_int
*);
305 /* Lattice of value ranges. */
307 class ipcp_vr_lattice
312 inline bool bottom_p () const;
313 inline bool top_p () const;
314 inline bool set_to_bottom ();
315 bool meet_with (const value_range
*p_vr
);
316 bool meet_with (const ipcp_vr_lattice
&other
);
317 void init () { gcc_assert (m_vr
.undefined_p ()); }
318 void print (FILE * f
);
321 bool meet_with_1 (const value_range
*other_vr
);
324 /* Structure containing lattices for a parameter itself and for pieces of
325 aggregates that are passed in the parameter or by a reference in a parameter
326 plus some other useful flags. */
328 class ipcp_param_lattices
331 /* Lattice describing the value of the parameter itself. */
332 ipcp_lattice
<tree
> itself
;
333 /* Lattice describing the polymorphic contexts of a parameter. */
334 ipcp_lattice
<ipa_polymorphic_call_context
> ctxlat
;
335 /* Lattices describing aggregate parts. */
336 ipcp_agg_lattice
*aggs
;
337 /* Lattice describing known bits. */
338 ipcp_bits_lattice bits_lattice
;
339 /* Lattice describing value range. */
340 ipcp_vr_lattice m_value_range
;
341 /* Number of aggregate lattices */
343 /* True if aggregate data were passed by reference (as opposed to by
346 /* All aggregate lattices contain a variable component (in addition to
348 bool aggs_contain_variable
;
349 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
350 for any propagation). */
353 /* There is a virtual call based on this parameter. */
357 /* Allocation pools for values and their sources in ipa-cp. */
359 object_allocator
<ipcp_value
<tree
> > ipcp_cst_values_pool
360 ("IPA-CP constant values");
362 object_allocator
<ipcp_value
<ipa_polymorphic_call_context
> >
363 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
365 object_allocator
<ipcp_value_source
<tree
> > ipcp_sources_pool
366 ("IPA-CP value sources");
368 object_allocator
<ipcp_agg_lattice
> ipcp_agg_lattice_pool
369 ("IPA_CP aggregate lattices");
371 /* Maximal count found in program. */
373 static profile_count max_count
;
375 /* Original overall size of the program. */
377 static long overall_size
, max_new_size
;
379 /* Node name to unique clone suffix number map. */
380 static hash_map
<const char *, unsigned> *clone_num_suffixes
;
382 /* Return the param lattices structure corresponding to the Ith formal
383 parameter of the function described by INFO. */
384 static inline class ipcp_param_lattices
*
385 ipa_get_parm_lattices (class ipa_node_params
*info
, int i
)
387 gcc_assert (i
>= 0 && i
< ipa_get_param_count (info
));
388 gcc_checking_assert (!info
->ipcp_orig_node
);
389 gcc_checking_assert (info
->lattices
);
390 return &(info
->lattices
[i
]);
393 /* Return the lattice corresponding to the scalar value of the Ith formal
394 parameter of the function described by INFO. */
395 static inline ipcp_lattice
<tree
> *
396 ipa_get_scalar_lat (class ipa_node_params
*info
, int i
)
398 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
399 return &plats
->itself
;
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
<ipa_polymorphic_call_context
> *
405 ipa_get_poly_ctx_lat (class ipa_node_params
*info
, int i
)
407 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
408 return &plats
->ctxlat
;
411 /* Return whether LAT is a lattice with a single constant and without an
414 template <typename valtype
>
416 ipcp_lattice
<valtype
>::is_single_const ()
418 if (bottom
|| contains_variable
|| values_count
!= 1)
424 /* Print V which is extracted from a value in a lattice to F. */
427 print_ipcp_constant_value (FILE * f
, tree v
)
429 if (TREE_CODE (v
) == ADDR_EXPR
430 && TREE_CODE (TREE_OPERAND (v
, 0)) == CONST_DECL
)
433 print_generic_expr (f
, DECL_INITIAL (TREE_OPERAND (v
, 0)));
436 print_generic_expr (f
, v
);
439 /* Print V which is extracted from a value in a lattice to F. */
442 print_ipcp_constant_value (FILE * f
, ipa_polymorphic_call_context v
)
447 /* Print a lattice LAT to F. */
449 template <typename valtype
>
451 ipcp_lattice
<valtype
>::print (FILE * f
, bool dump_sources
, bool dump_benefits
)
453 ipcp_value
<valtype
> *val
;
458 fprintf (f
, "BOTTOM\n");
462 if (!values_count
&& !contains_variable
)
464 fprintf (f
, "TOP\n");
468 if (contains_variable
)
470 fprintf (f
, "VARIABLE");
476 for (val
= values
; val
; val
= val
->next
)
478 if (dump_benefits
&& prev
)
480 else if (!dump_benefits
&& prev
)
485 print_ipcp_constant_value (f
, val
->value
);
489 ipcp_value_source
<valtype
> *s
;
491 fprintf (f
, " [from:");
492 for (s
= val
->sources
; s
; s
= s
->next
)
493 fprintf (f
, " %i(%f)", s
->cs
->caller
->order
,
494 s
->cs
->sreal_frequency ().to_double ());
499 fprintf (f
, " [loc_time: %i, loc_size: %i, "
500 "prop_time: %i, prop_size: %i]\n",
501 val
->local_time_benefit
, val
->local_size_cost
,
502 val
->prop_time_benefit
, val
->prop_size_cost
);
509 ipcp_bits_lattice::print (FILE *f
)
512 fprintf (f
, " Bits unknown (TOP)\n");
513 else if (bottom_p ())
514 fprintf (f
, " Bits unusable (BOTTOM)\n");
517 fprintf (f
, " Bits: value = "); print_hex (get_value (), f
);
518 fprintf (f
, ", mask = "); print_hex (get_mask (), f
);
523 /* Print value range lattice to F. */
526 ipcp_vr_lattice::print (FILE * f
)
528 dump_value_range (f
, &m_vr
);
531 /* Print all ipcp_lattices of all functions to F. */
534 print_all_lattices (FILE * f
, bool dump_sources
, bool dump_benefits
)
536 struct cgraph_node
*node
;
539 fprintf (f
, "\nLattices:\n");
540 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
542 class ipa_node_params
*info
;
544 info
= IPA_NODE_REF (node
);
545 /* Skip constprop clones since we don't make lattices for them. */
546 if (info
->ipcp_orig_node
)
548 fprintf (f
, " Node: %s:\n", node
->dump_name ());
549 count
= ipa_get_param_count (info
);
550 for (i
= 0; i
< count
; i
++)
552 struct ipcp_agg_lattice
*aglat
;
553 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
554 fprintf (f
, " param [%d]: ", i
);
555 plats
->itself
.print (f
, dump_sources
, dump_benefits
);
556 fprintf (f
, " ctxs: ");
557 plats
->ctxlat
.print (f
, dump_sources
, dump_benefits
);
558 plats
->bits_lattice
.print (f
);
560 plats
->m_value_range
.print (f
);
562 if (plats
->virt_call
)
563 fprintf (f
, " virt_call flag set\n");
565 if (plats
->aggs_bottom
)
567 fprintf (f
, " AGGS BOTTOM\n");
570 if (plats
->aggs_contain_variable
)
571 fprintf (f
, " AGGS VARIABLE\n");
572 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
574 fprintf (f
, " %soffset " HOST_WIDE_INT_PRINT_DEC
": ",
575 plats
->aggs_by_ref
? "ref " : "", aglat
->offset
);
576 aglat
->print (f
, dump_sources
, dump_benefits
);
582 /* Determine whether it is at all technically possible to create clones of NODE
583 and store this information in the ipa_node_params structure associated
587 determine_versionability (struct cgraph_node
*node
,
588 class ipa_node_params
*info
)
590 const char *reason
= NULL
;
592 /* There are a number of generic reasons functions cannot be versioned. We
593 also cannot remove parameters if there are type attributes such as fnspec
595 if (node
->alias
|| node
->thunk
.thunk_p
)
596 reason
= "alias or thunk";
597 else if (!node
->versionable
)
598 reason
= "not a tree_versionable_function";
599 else if (node
->get_availability () <= AVAIL_INTERPOSABLE
)
600 reason
= "insufficient body availability";
601 else if (!opt_for_fn (node
->decl
, optimize
)
602 || !opt_for_fn (node
->decl
, flag_ipa_cp
))
603 reason
= "non-optimized function";
604 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node
->decl
)))
606 /* Ideally we should clone the SIMD clones themselves and create
607 vector copies of them, so IPA-cp and SIMD clones can happily
608 coexist, but that may not be worth the effort. */
609 reason
= "function has SIMD clones";
611 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node
->decl
)))
613 /* Ideally we should clone the target clones themselves and create
614 copies of them, so IPA-cp and target clones can happily
615 coexist, but that may not be worth the effort. */
616 reason
= "function target_clones attribute";
618 /* Don't clone decls local to a comdat group; it breaks and for C++
619 decloned constructors, inlining is always better anyway. */
620 else if (node
->comdat_local_p ())
621 reason
= "comdat-local function";
622 else if (node
->calls_comdat_local
)
624 /* TODO: call is versionable if we make sure that all
625 callers are inside of a comdat group. */
626 reason
= "calls comdat-local function";
629 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
630 work only when inlined. Cloning them may still lead to better code
631 because ipa-cp will not give up on cloning further. If the function is
632 external this however leads to wrong code because we may end up producing
633 offline copy of the function. */
634 if (DECL_EXTERNAL (node
->decl
))
635 for (cgraph_edge
*edge
= node
->callees
; !reason
&& edge
;
636 edge
= edge
->next_callee
)
637 if (fndecl_built_in_p (edge
->callee
->decl
, BUILT_IN_NORMAL
))
639 if (DECL_FUNCTION_CODE (edge
->callee
->decl
) == BUILT_IN_VA_ARG_PACK
)
640 reason
= "external function which calls va_arg_pack";
641 if (DECL_FUNCTION_CODE (edge
->callee
->decl
)
642 == BUILT_IN_VA_ARG_PACK_LEN
)
643 reason
= "external function which calls va_arg_pack_len";
646 if (reason
&& dump_file
&& !node
->alias
&& !node
->thunk
.thunk_p
)
647 fprintf (dump_file
, "Function %s is not versionable, reason: %s.\n",
648 node
->dump_name (), reason
);
650 info
->versionable
= (reason
== NULL
);
653 /* Return true if it is at all technically possible to create clones of a
657 ipcp_versionable_function_p (struct cgraph_node
*node
)
659 return IPA_NODE_REF (node
) && IPA_NODE_REF (node
)->versionable
;
662 /* Structure holding accumulated information about callers of a node. */
664 struct caller_statistics
666 profile_count count_sum
;
667 int n_calls
, n_hot_calls
, freq_sum
;
670 /* Initialize fields of STAT to zeroes. */
673 init_caller_stats (struct caller_statistics
*stats
)
675 stats
->count_sum
= profile_count::zero ();
677 stats
->n_hot_calls
= 0;
681 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
682 non-thunk incoming edges to NODE. */
685 gather_caller_stats (struct cgraph_node
*node
, void *data
)
687 struct caller_statistics
*stats
= (struct caller_statistics
*) data
;
688 struct cgraph_edge
*cs
;
690 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
691 if (!cs
->caller
->thunk
.thunk_p
)
693 if (cs
->count
.ipa ().initialized_p ())
694 stats
->count_sum
+= cs
->count
.ipa ();
695 stats
->freq_sum
+= cs
->frequency ();
697 if (cs
->maybe_hot_p ())
698 stats
->n_hot_calls
++;
704 /* Return true if this NODE is viable candidate for cloning. */
707 ipcp_cloning_candidate_p (struct cgraph_node
*node
)
709 struct caller_statistics stats
;
711 gcc_checking_assert (node
->has_gimple_body_p ());
713 if (!opt_for_fn (node
->decl
, flag_ipa_cp_clone
))
716 fprintf (dump_file
, "Not considering %s for cloning; "
717 "-fipa-cp-clone disabled.\n",
722 if (node
->optimize_for_size_p ())
725 fprintf (dump_file
, "Not considering %s for cloning; "
726 "optimizing it for size.\n",
731 init_caller_stats (&stats
);
732 node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
, false);
734 if (ipa_size_summaries
->get (node
)->self_size
< stats
.n_calls
)
737 fprintf (dump_file
, "Considering %s for cloning; code might shrink.\n",
742 /* When profile is available and function is hot, propagate into it even if
743 calls seems cold; constant propagation can improve function's speed
745 if (max_count
> profile_count::zero ())
747 if (stats
.count_sum
> node
->count
.ipa ().apply_scale (90, 100))
750 fprintf (dump_file
, "Considering %s for cloning; "
751 "usually called directly.\n",
756 if (!stats
.n_hot_calls
)
759 fprintf (dump_file
, "Not considering %s for cloning; no hot calls.\n",
764 fprintf (dump_file
, "Considering %s for cloning.\n",
769 template <typename valtype
>
770 class value_topo_info
773 /* Head of the linked list of topologically sorted values. */
774 ipcp_value
<valtype
> *values_topo
;
775 /* Stack for creating SCCs, represented by a linked list too. */
776 ipcp_value
<valtype
> *stack
;
777 /* Counter driving the algorithm in add_val_to_toposort. */
780 value_topo_info () : values_topo (NULL
), stack (NULL
), dfs_counter (0)
782 void add_val (ipcp_value
<valtype
> *cur_val
);
783 void propagate_effects ();
786 /* Arrays representing a topological ordering of call graph nodes and a stack
787 of nodes used during constant propagation and also data required to perform
788 topological sort of values and propagation of benefits in the determined
794 /* Array with obtained topological order of cgraph nodes. */
795 struct cgraph_node
**order
;
796 /* Stack of cgraph nodes used during propagation within SCC until all values
797 in the SCC stabilize. */
798 struct cgraph_node
**stack
;
799 int nnodes
, stack_top
;
801 value_topo_info
<tree
> constants
;
802 value_topo_info
<ipa_polymorphic_call_context
> contexts
;
804 ipa_topo_info () : order(NULL
), stack(NULL
), nnodes(0), stack_top(0),
809 /* Skip edges from and to nodes without ipa_cp enabled.
810 Ignore not available symbols. */
813 ignore_edge_p (cgraph_edge
*e
)
815 enum availability avail
;
816 cgraph_node
*ultimate_target
817 = e
->callee
->function_or_virtual_thunk_symbol (&avail
, e
->caller
);
819 return (avail
<= AVAIL_INTERPOSABLE
820 || !opt_for_fn (e
->caller
->decl
, flag_ipa_cp
)
821 || !opt_for_fn (ultimate_target
->decl
, flag_ipa_cp
));
824 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
827 build_toporder_info (class ipa_topo_info
*topo
)
829 topo
->order
= XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
830 topo
->stack
= XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
832 gcc_checking_assert (topo
->stack_top
== 0);
833 topo
->nnodes
= ipa_reduced_postorder (topo
->order
, true,
837 /* Free information about strongly connected components and the arrays in
841 free_toporder_info (class ipa_topo_info
*topo
)
843 ipa_free_postorder_info ();
848 /* Add NODE to the stack in TOPO, unless it is already there. */
851 push_node_to_stack (class ipa_topo_info
*topo
, struct cgraph_node
*node
)
853 class ipa_node_params
*info
= IPA_NODE_REF (node
);
854 if (info
->node_enqueued
)
856 info
->node_enqueued
= 1;
857 topo
->stack
[topo
->stack_top
++] = node
;
860 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
863 static struct cgraph_node
*
864 pop_node_from_stack (class ipa_topo_info
*topo
)
868 struct cgraph_node
*node
;
870 node
= topo
->stack
[topo
->stack_top
];
871 IPA_NODE_REF (node
)->node_enqueued
= 0;
878 /* Set lattice LAT to bottom and return true if it previously was not set as
881 template <typename valtype
>
883 ipcp_lattice
<valtype
>::set_to_bottom ()
890 /* Mark lattice as containing an unknown value and return true if it previously
891 was not marked as such. */
893 template <typename valtype
>
895 ipcp_lattice
<valtype
>::set_contains_variable ()
897 bool ret
= !contains_variable
;
898 contains_variable
= true;
902 /* Set all aggregate lattices in PLATS to bottom and return true if they were
903 not previously set as such. */
906 set_agg_lats_to_bottom (class ipcp_param_lattices
*plats
)
908 bool ret
= !plats
->aggs_bottom
;
909 plats
->aggs_bottom
= true;
913 /* Mark all aggregate lattices in PLATS as containing an unknown value and
914 return true if they were not previously marked as such. */
917 set_agg_lats_contain_variable (class ipcp_param_lattices
*plats
)
919 bool ret
= !plats
->aggs_contain_variable
;
920 plats
->aggs_contain_variable
= true;
925 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice
&other
)
927 return meet_with_1 (&other
.m_vr
);
930 /* Meet the current value of the lattice with value range described by VR
934 ipcp_vr_lattice::meet_with (const value_range
*p_vr
)
936 return meet_with_1 (p_vr
);
939 /* Meet the current value of the lattice with value range described by
940 OTHER_VR lattice. Return TRUE if anything changed. */
943 ipcp_vr_lattice::meet_with_1 (const value_range
*other_vr
)
948 if (other_vr
->varying_p ())
949 return set_to_bottom ();
951 value_range
save (m_vr
);
952 m_vr
.union_ (other_vr
);
953 return !m_vr
.equal_p (save
);
956 /* Return true if value range information in the lattice is yet unknown. */
959 ipcp_vr_lattice::top_p () const
961 return m_vr
.undefined_p ();
964 /* Return true if value range information in the lattice is known to be
968 ipcp_vr_lattice::bottom_p () const
970 return m_vr
.varying_p ();
973 /* Set value range information in the lattice to bottom. Return true if it
974 previously was in a different state. */
977 ipcp_vr_lattice::set_to_bottom ()
979 if (m_vr
.varying_p ())
981 /* ?? We create all sorts of VARYING ranges for floats, structures,
982 and other types which we cannot handle as ranges. We should
983 probably avoid handling them throughout the pass, but it's easier
984 to create a sensible VARYING here and let the lattice
986 m_vr
.set_varying (integer_type_node
);
990 /* Set lattice value to bottom, if it already isn't the case. */
993 ipcp_bits_lattice::set_to_bottom ()
997 m_lattice_val
= IPA_BITS_VARYING
;
1003 /* Set to constant if it isn't already. Only meant to be called
1004 when switching state from TOP. */
1007 ipcp_bits_lattice::set_to_constant (widest_int value
, widest_int mask
)
1009 gcc_assert (top_p ());
1010 m_lattice_val
= IPA_BITS_CONSTANT
;
1016 /* Convert operand to value, mask form. */
1019 ipcp_bits_lattice::get_value_and_mask (tree operand
, widest_int
*valuep
, widest_int
*maskp
)
1021 wide_int
get_nonzero_bits (const_tree
);
1023 if (TREE_CODE (operand
) == INTEGER_CST
)
1025 *valuep
= wi::to_widest (operand
);
1035 /* Meet operation, similar to ccp_lattice_meet, we xor values
1036 if this->value, value have different values at same bit positions, we want
1037 to drop that bit to varying. Return true if mask is changed.
1038 This function assumes that the lattice value is in CONSTANT state */
1041 ipcp_bits_lattice::meet_with_1 (widest_int value
, widest_int mask
,
1044 gcc_assert (constant_p ());
1046 widest_int old_mask
= m_mask
;
1047 m_mask
= (m_mask
| mask
) | (m_value
^ value
);
1049 if (wi::sext (m_mask
, precision
) == -1)
1050 return set_to_bottom ();
1052 return m_mask
!= old_mask
;
1055 /* Meet the bits lattice with operand
1056 described by <value, mask, sgn, precision. */
1059 ipcp_bits_lattice::meet_with (widest_int value
, widest_int mask
,
1067 if (wi::sext (mask
, precision
) == -1)
1068 return set_to_bottom ();
1069 return set_to_constant (value
, mask
);
1072 return meet_with_1 (value
, mask
, precision
);
1075 /* Meet bits lattice with the result of bit_value_binop (other, operand)
1076 if code is binary operation or bit_value_unop (other) if code is unary op.
1077 In the case when code is nop_expr, no adjustment is required. */
1080 ipcp_bits_lattice::meet_with (ipcp_bits_lattice
& other
, unsigned precision
,
1081 signop sgn
, enum tree_code code
, tree operand
)
1083 if (other
.bottom_p ())
1084 return set_to_bottom ();
1086 if (bottom_p () || other
.top_p ())
1089 widest_int adjusted_value
, adjusted_mask
;
1091 if (TREE_CODE_CLASS (code
) == tcc_binary
)
1093 tree type
= TREE_TYPE (operand
);
1094 widest_int o_value
, o_mask
;
1095 get_value_and_mask (operand
, &o_value
, &o_mask
);
1097 bit_value_binop (code
, sgn
, precision
, &adjusted_value
, &adjusted_mask
,
1098 sgn
, precision
, other
.get_value (), other
.get_mask (),
1099 TYPE_SIGN (type
), TYPE_PRECISION (type
), o_value
, o_mask
);
1101 if (wi::sext (adjusted_mask
, precision
) == -1)
1102 return set_to_bottom ();
1105 else if (TREE_CODE_CLASS (code
) == tcc_unary
)
1107 bit_value_unop (code
, sgn
, precision
, &adjusted_value
,
1108 &adjusted_mask
, sgn
, precision
, other
.get_value (),
1111 if (wi::sext (adjusted_mask
, precision
) == -1)
1112 return set_to_bottom ();
1116 return set_to_bottom ();
1120 if (wi::sext (adjusted_mask
, precision
) == -1)
1121 return set_to_bottom ();
1122 return set_to_constant (adjusted_value
, adjusted_mask
);
1125 return meet_with_1 (adjusted_value
, adjusted_mask
, precision
);
1128 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
1129 return true is any of them has not been marked as such so far. */
1132 set_all_contains_variable (class ipcp_param_lattices
*plats
)
1135 ret
= plats
->itself
.set_contains_variable ();
1136 ret
|= plats
->ctxlat
.set_contains_variable ();
1137 ret
|= set_agg_lats_contain_variable (plats
);
1138 ret
|= plats
->bits_lattice
.set_to_bottom ();
1139 ret
|= plats
->m_value_range
.set_to_bottom ();
1143 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
1144 points to by the number of callers to NODE. */
1147 count_callers (cgraph_node
*node
, void *data
)
1149 int *caller_count
= (int *) data
;
1151 for (cgraph_edge
*cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
1152 /* Local thunks can be handled transparently, but if the thunk cannot
1153 be optimized out, count it as a real use. */
1154 if (!cs
->caller
->thunk
.thunk_p
|| !cs
->caller
->local
)
1159 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
1160 the one caller of some other node. Set the caller's corresponding flag. */
1163 set_single_call_flag (cgraph_node
*node
, void *)
1165 cgraph_edge
*cs
= node
->callers
;
1166 /* Local thunks can be handled transparently, skip them. */
1167 while (cs
&& cs
->caller
->thunk
.thunk_p
&& cs
->caller
->local
)
1168 cs
= cs
->next_caller
;
1171 IPA_NODE_REF (cs
->caller
)->node_calling_single_call
= true;
1177 /* Initialize ipcp_lattices. */
1180 initialize_node_lattices (struct cgraph_node
*node
)
1182 class ipa_node_params
*info
= IPA_NODE_REF (node
);
1183 struct cgraph_edge
*ie
;
1184 bool disable
= false, variable
= false;
1187 gcc_checking_assert (node
->has_gimple_body_p ());
1189 if (!ipa_get_param_count (info
))
1191 else if (node
->local
)
1193 int caller_count
= 0;
1194 node
->call_for_symbol_thunks_and_aliases (count_callers
, &caller_count
,
1196 gcc_checking_assert (caller_count
> 0);
1197 if (caller_count
== 1)
1198 node
->call_for_symbol_thunks_and_aliases (set_single_call_flag
,
1203 /* When cloning is allowed, we can assume that externally visible
1204 functions are not called. We will compensate this by cloning
1206 if (ipcp_versionable_function_p (node
)
1207 && ipcp_cloning_candidate_p (node
))
1213 if (dump_file
&& (dump_flags
& TDF_DETAILS
)
1214 && !node
->alias
&& !node
->thunk
.thunk_p
)
1216 fprintf (dump_file
, "Initializing lattices of %s\n",
1217 node
->dump_name ());
1218 if (disable
|| variable
)
1219 fprintf (dump_file
, " Marking all lattices as %s\n",
1220 disable
? "BOTTOM" : "VARIABLE");
1223 auto_vec
<bool, 16> surviving_params
;
1224 bool pre_modified
= false;
1225 if (!disable
&& node
->clone
.param_adjustments
)
1227 /* At the moment all IPA optimizations should use the number of
1228 parameters of the prevailing decl as the m_always_copy_start.
1229 Handling any other value would complicate the code below, so for the
1230 time bing let's only assert it is so. */
1231 gcc_assert ((node
->clone
.param_adjustments
->m_always_copy_start
1232 == ipa_get_param_count (info
))
1233 || node
->clone
.param_adjustments
->m_always_copy_start
< 0);
1235 pre_modified
= true;
1236 node
->clone
.param_adjustments
->get_surviving_params (&surviving_params
);
1238 if (dump_file
&& (dump_flags
& TDF_DETAILS
)
1239 && !node
->alias
&& !node
->thunk
.thunk_p
)
1242 for (int j
= 0; j
< ipa_get_param_count (info
); j
++)
1244 if (j
< (int) surviving_params
.length ()
1245 && surviving_params
[j
])
1250 " The following parameters are dead on arrival:");
1253 fprintf (dump_file
, " %u", j
);
1256 fprintf (dump_file
, "\n");
1260 for (i
= 0; i
< ipa_get_param_count (info
); i
++)
1262 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
1264 || (pre_modified
&& (surviving_params
.length () <= (unsigned) i
1265 || !surviving_params
[i
])))
1267 plats
->itself
.set_to_bottom ();
1268 plats
->ctxlat
.set_to_bottom ();
1269 set_agg_lats_to_bottom (plats
);
1270 plats
->bits_lattice
.set_to_bottom ();
1271 plats
->m_value_range
.set_to_bottom ();
1275 plats
->m_value_range
.init ();
1277 set_all_contains_variable (plats
);
1281 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
1282 if (ie
->indirect_info
->polymorphic
1283 && ie
->indirect_info
->param_index
>= 0)
1285 gcc_checking_assert (ie
->indirect_info
->param_index
>= 0);
1286 ipa_get_parm_lattices (info
,
1287 ie
->indirect_info
->param_index
)->virt_call
= 1;
1291 /* Return the result of a (possibly arithmetic) pass through jump function
1292 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter
1293 to which the result is passed. Return NULL_TREE if that cannot be
1294 determined or be considered an interprocedural invariant. */
1297 ipa_get_jf_pass_through_result (struct ipa_jump_func
*jfunc
, tree input
,
1302 if (ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
1304 if (!is_gimple_ip_invariant (input
))
1307 tree_code opcode
= ipa_get_jf_pass_through_operation (jfunc
);
1310 if (TREE_CODE_CLASS (opcode
) == tcc_comparison
)
1311 res_type
= boolean_type_node
;
1312 else if (expr_type_first_operand_type_p (opcode
))
1313 res_type
= TREE_TYPE (input
);
1318 if (TREE_CODE_CLASS (opcode
) == tcc_unary
)
1319 res
= fold_unary (opcode
, res_type
, input
);
1321 res
= fold_binary (opcode
, res_type
, input
,
1322 ipa_get_jf_pass_through_operand (jfunc
));
1324 if (res
&& !is_gimple_ip_invariant (res
))
1330 /* Return the result of an ancestor jump function JFUNC on the constant value
1331 INPUT. Return NULL_TREE if that cannot be determined. */
1334 ipa_get_jf_ancestor_result (struct ipa_jump_func
*jfunc
, tree input
)
1336 gcc_checking_assert (TREE_CODE (input
) != TREE_BINFO
);
1337 if (TREE_CODE (input
) == ADDR_EXPR
)
1339 tree t
= TREE_OPERAND (input
, 0);
1340 t
= build_ref_for_offset (EXPR_LOCATION (t
), t
,
1341 ipa_get_jf_ancestor_offset (jfunc
), false,
1342 ptr_type_node
, NULL
, false);
1343 return build_fold_addr_expr (t
);
1349 /* Determine whether JFUNC evaluates to a single known constant value and if
1350 so, return it. Otherwise return NULL. INFO describes the caller node or
1351 the one it is inlined to, so that pass-through jump functions can be
1352 evaluated. PARM_TYPE is the type of the parameter to which the result is
1356 ipa_value_from_jfunc (class ipa_node_params
*info
, struct ipa_jump_func
*jfunc
,
1359 if (jfunc
->type
== IPA_JF_CONST
)
1360 return ipa_get_jf_constant (jfunc
);
1361 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
1362 || jfunc
->type
== IPA_JF_ANCESTOR
)
1367 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1368 idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1370 idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1372 if (info
->ipcp_orig_node
)
1373 input
= info
->known_csts
[idx
];
1376 ipcp_lattice
<tree
> *lat
;
1379 || idx
>= ipa_get_param_count (info
))
1381 lat
= ipa_get_scalar_lat (info
, idx
);
1382 if (!lat
->is_single_const ())
1384 input
= lat
->values
->value
;
1390 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1391 return ipa_get_jf_pass_through_result (jfunc
, input
, parm_type
);
1393 return ipa_get_jf_ancestor_result (jfunc
, input
);
1399 /* Determine whether JFUNC evaluates to single known polymorphic context, given
1400 that INFO describes the caller node or the one it is inlined to, CS is the
1401 call graph edge corresponding to JFUNC and CSIDX index of the described
1404 ipa_polymorphic_call_context
1405 ipa_context_from_jfunc (ipa_node_params
*info
, cgraph_edge
*cs
, int csidx
,
1406 ipa_jump_func
*jfunc
)
1408 ipa_edge_args
*args
= IPA_EDGE_REF (cs
);
1409 ipa_polymorphic_call_context ctx
;
1410 ipa_polymorphic_call_context
*edge_ctx
1411 = cs
? ipa_get_ith_polymorhic_call_context (args
, csidx
) : NULL
;
1413 if (edge_ctx
&& !edge_ctx
->useless_p ())
1416 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1417 || jfunc
->type
== IPA_JF_ANCESTOR
)
1419 ipa_polymorphic_call_context srcctx
;
1421 bool type_preserved
= true;
1422 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1424 if (ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1426 type_preserved
= ipa_get_jf_pass_through_type_preserved (jfunc
);
1427 srcidx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1431 type_preserved
= ipa_get_jf_ancestor_type_preserved (jfunc
);
1432 srcidx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1434 if (info
->ipcp_orig_node
)
1436 if (info
->known_contexts
.exists ())
1437 srcctx
= info
->known_contexts
[srcidx
];
1442 || srcidx
>= ipa_get_param_count (info
))
1444 ipcp_lattice
<ipa_polymorphic_call_context
> *lat
;
1445 lat
= ipa_get_poly_ctx_lat (info
, srcidx
);
1446 if (!lat
->is_single_const ())
1448 srcctx
= lat
->values
->value
;
1450 if (srcctx
.useless_p ())
1452 if (jfunc
->type
== IPA_JF_ANCESTOR
)
1453 srcctx
.offset_by (ipa_get_jf_ancestor_offset (jfunc
));
1454 if (!type_preserved
)
1455 srcctx
.possible_dynamic_type_change (cs
->in_polymorphic_cdtor
);
1456 srcctx
.combine_with (ctx
);
1463 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1464 bottom, not containing a variable component and without any known value at
1468 ipcp_verify_propagated_values (void)
1470 struct cgraph_node
*node
;
1472 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
1474 class ipa_node_params
*info
= IPA_NODE_REF (node
);
1475 if (!opt_for_fn (node
->decl
, flag_ipa_cp
))
1477 int i
, count
= ipa_get_param_count (info
);
1479 for (i
= 0; i
< count
; i
++)
1481 ipcp_lattice
<tree
> *lat
= ipa_get_scalar_lat (info
, i
);
1484 && !lat
->contains_variable
1485 && lat
->values_count
== 0)
1489 symtab
->dump (dump_file
);
1490 fprintf (dump_file
, "\nIPA lattices after constant "
1491 "propagation, before gcc_unreachable:\n");
1492 print_all_lattices (dump_file
, true, false);
1501 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1504 values_equal_for_ipcp_p (tree x
, tree y
)
1506 gcc_checking_assert (x
!= NULL_TREE
&& y
!= NULL_TREE
);
1511 if (TREE_CODE (x
) == ADDR_EXPR
1512 && TREE_CODE (y
) == ADDR_EXPR
1513 && TREE_CODE (TREE_OPERAND (x
, 0)) == CONST_DECL
1514 && TREE_CODE (TREE_OPERAND (y
, 0)) == CONST_DECL
)
1515 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x
, 0)),
1516 DECL_INITIAL (TREE_OPERAND (y
, 0)), 0);
1518 return operand_equal_p (x
, y
, 0);
1521 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1524 values_equal_for_ipcp_p (ipa_polymorphic_call_context x
,
1525 ipa_polymorphic_call_context y
)
1527 return x
.equal_to (y
);
1531 /* Add a new value source to the value represented by THIS, marking that a
1532 value comes from edge CS and (if the underlying jump function is a
1533 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1534 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1535 scalar value of the parameter itself or the offset within an aggregate. */
1537 template <typename valtype
>
1539 ipcp_value
<valtype
>::add_source (cgraph_edge
*cs
, ipcp_value
*src_val
,
1540 int src_idx
, HOST_WIDE_INT offset
)
1542 ipcp_value_source
<valtype
> *src
;
1544 src
= new (ipcp_sources_pool
.allocate ()) ipcp_value_source
<valtype
>;
1545 src
->offset
= offset
;
1548 src
->index
= src_idx
;
1550 src
->next
= sources
;
1554 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1555 SOURCE and clear all other fields. */
1557 static ipcp_value
<tree
> *
1558 allocate_and_init_ipcp_value (tree source
)
1560 ipcp_value
<tree
> *val
;
1562 val
= new (ipcp_cst_values_pool
.allocate ()) ipcp_value
<tree
>();
1563 val
->value
= source
;
1567 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1568 value to SOURCE and clear all other fields. */
1570 static ipcp_value
<ipa_polymorphic_call_context
> *
1571 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source
)
1573 ipcp_value
<ipa_polymorphic_call_context
> *val
;
1576 val
= new (ipcp_poly_ctx_values_pool
.allocate ())
1577 ipcp_value
<ipa_polymorphic_call_context
>();
1578 val
->value
= source
;
1582 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1583 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1584 meaning. OFFSET -1 means the source is scalar and not a part of an
1587 template <typename valtype
>
1589 ipcp_lattice
<valtype
>::add_value (valtype newval
, cgraph_edge
*cs
,
1590 ipcp_value
<valtype
> *src_val
,
1591 int src_idx
, HOST_WIDE_INT offset
)
1593 ipcp_value
<valtype
> *val
;
1598 for (val
= values
; val
; val
= val
->next
)
1599 if (values_equal_for_ipcp_p (val
->value
, newval
))
1601 if (ipa_edge_within_scc (cs
))
1603 ipcp_value_source
<valtype
> *s
;
1604 for (s
= val
->sources
; s
; s
= s
->next
)
1611 val
->add_source (cs
, src_val
, src_idx
, offset
);
1615 if (values_count
== param_ipa_cp_value_list_size
)
1617 /* We can only free sources, not the values themselves, because sources
1618 of other values in this SCC might point to them. */
1619 for (val
= values
; val
; val
= val
->next
)
1621 while (val
->sources
)
1623 ipcp_value_source
<valtype
> *src
= val
->sources
;
1624 val
->sources
= src
->next
;
1625 ipcp_sources_pool
.remove ((ipcp_value_source
<tree
>*)src
);
1630 return set_to_bottom ();
1634 val
= allocate_and_init_ipcp_value (newval
);
1635 val
->add_source (cs
, src_val
, src_idx
, offset
);
1641 /* Propagate values through a pass-through jump function JFUNC associated with
1642 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1643 is the index of the source parameter. PARM_TYPE is the type of the
1644 parameter to which the result is passed. */
1647 propagate_vals_across_pass_through (cgraph_edge
*cs
, ipa_jump_func
*jfunc
,
1648 ipcp_lattice
<tree
> *src_lat
,
1649 ipcp_lattice
<tree
> *dest_lat
, int src_idx
,
1652 ipcp_value
<tree
> *src_val
;
1655 /* Do not create new values when propagating within an SCC because if there
1656 are arithmetic functions with circular dependencies, there is infinite
1657 number of them and we would just make lattices bottom. If this condition
1658 is ever relaxed we have to detect self-feeding recursive calls in
1659 cgraph_edge_brings_value_p in a smarter way. */
1660 if ((ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1661 && ipa_edge_within_scc (cs
))
1662 ret
= dest_lat
->set_contains_variable ();
1664 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1666 tree cstval
= ipa_get_jf_pass_through_result (jfunc
, src_val
->value
,
1670 ret
|= dest_lat
->add_value (cstval
, cs
, src_val
, src_idx
);
1672 ret
|= dest_lat
->set_contains_variable ();
1678 /* Propagate values through an ancestor jump function JFUNC associated with
1679 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1680 is the index of the source parameter. */
1683 propagate_vals_across_ancestor (struct cgraph_edge
*cs
,
1684 struct ipa_jump_func
*jfunc
,
1685 ipcp_lattice
<tree
> *src_lat
,
1686 ipcp_lattice
<tree
> *dest_lat
, int src_idx
)
1688 ipcp_value
<tree
> *src_val
;
1691 if (ipa_edge_within_scc (cs
))
1692 return dest_lat
->set_contains_variable ();
1694 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1696 tree t
= ipa_get_jf_ancestor_result (jfunc
, src_val
->value
);
1699 ret
|= dest_lat
->add_value (t
, cs
, src_val
, src_idx
);
1701 ret
|= dest_lat
->set_contains_variable ();
1707 /* Propagate scalar values across jump function JFUNC that is associated with
1708 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the
1709 parameter to which the result is passed. */
1712 propagate_scalar_across_jump_function (struct cgraph_edge
*cs
,
1713 struct ipa_jump_func
*jfunc
,
1714 ipcp_lattice
<tree
> *dest_lat
,
1717 if (dest_lat
->bottom
)
1720 if (jfunc
->type
== IPA_JF_CONST
)
1722 tree val
= ipa_get_jf_constant (jfunc
);
1723 return dest_lat
->add_value (val
, cs
, NULL
, 0);
1725 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
1726 || jfunc
->type
== IPA_JF_ANCESTOR
)
1728 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1729 ipcp_lattice
<tree
> *src_lat
;
1733 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1734 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1736 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1738 src_lat
= ipa_get_scalar_lat (caller_info
, src_idx
);
1739 if (src_lat
->bottom
)
1740 return dest_lat
->set_contains_variable ();
1742 /* If we would need to clone the caller and cannot, do not propagate. */
1743 if (!ipcp_versionable_function_p (cs
->caller
)
1744 && (src_lat
->contains_variable
1745 || (src_lat
->values_count
> 1)))
1746 return dest_lat
->set_contains_variable ();
1748 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1749 ret
= propagate_vals_across_pass_through (cs
, jfunc
, src_lat
,
1750 dest_lat
, src_idx
, param_type
);
1752 ret
= propagate_vals_across_ancestor (cs
, jfunc
, src_lat
, dest_lat
,
1755 if (src_lat
->contains_variable
)
1756 ret
|= dest_lat
->set_contains_variable ();
1761 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1762 use it for indirect inlining), we should propagate them too. */
1763 return dest_lat
->set_contains_variable ();
1766 /* Propagate scalar values across jump function JFUNC that is associated with
1767 edge CS and describes argument IDX and put the values into DEST_LAT. */
1770 propagate_context_across_jump_function (cgraph_edge
*cs
,
1771 ipa_jump_func
*jfunc
, int idx
,
1772 ipcp_lattice
<ipa_polymorphic_call_context
> *dest_lat
)
1774 ipa_edge_args
*args
= IPA_EDGE_REF (cs
);
1775 if (dest_lat
->bottom
)
1778 bool added_sth
= false;
1779 bool type_preserved
= true;
1781 ipa_polymorphic_call_context edge_ctx
, *edge_ctx_ptr
1782 = ipa_get_ith_polymorhic_call_context (args
, idx
);
1785 edge_ctx
= *edge_ctx_ptr
;
1787 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1788 || jfunc
->type
== IPA_JF_ANCESTOR
)
1790 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1792 ipcp_lattice
<ipa_polymorphic_call_context
> *src_lat
;
1794 /* TODO: Once we figure out how to propagate speculations, it will
1795 probably be a good idea to switch to speculation if type_preserved is
1796 not set instead of punting. */
1797 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1799 if (ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1801 type_preserved
= ipa_get_jf_pass_through_type_preserved (jfunc
);
1802 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1806 type_preserved
= ipa_get_jf_ancestor_type_preserved (jfunc
);
1807 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1810 src_lat
= ipa_get_poly_ctx_lat (caller_info
, src_idx
);
1811 /* If we would need to clone the caller and cannot, do not propagate. */
1812 if (!ipcp_versionable_function_p (cs
->caller
)
1813 && (src_lat
->contains_variable
1814 || (src_lat
->values_count
> 1)))
1817 ipcp_value
<ipa_polymorphic_call_context
> *src_val
;
1818 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1820 ipa_polymorphic_call_context cur
= src_val
->value
;
1822 if (!type_preserved
)
1823 cur
.possible_dynamic_type_change (cs
->in_polymorphic_cdtor
);
1824 if (jfunc
->type
== IPA_JF_ANCESTOR
)
1825 cur
.offset_by (ipa_get_jf_ancestor_offset (jfunc
));
1826 /* TODO: In cases we know how the context is going to be used,
1827 we can improve the result by passing proper OTR_TYPE. */
1828 cur
.combine_with (edge_ctx
);
1829 if (!cur
.useless_p ())
1831 if (src_lat
->contains_variable
1832 && !edge_ctx
.equal_to (cur
))
1833 ret
|= dest_lat
->set_contains_variable ();
1834 ret
|= dest_lat
->add_value (cur
, cs
, src_val
, src_idx
);
1844 if (!edge_ctx
.useless_p ())
1845 ret
|= dest_lat
->add_value (edge_ctx
, cs
);
1847 ret
|= dest_lat
->set_contains_variable ();
1853 /* Propagate bits across jfunc that is associated with
1854 edge cs and update dest_lattice accordingly. */
1857 propagate_bits_across_jump_function (cgraph_edge
*cs
, int idx
,
1858 ipa_jump_func
*jfunc
,
1859 ipcp_bits_lattice
*dest_lattice
)
1861 if (dest_lattice
->bottom_p ())
1864 enum availability availability
;
1865 cgraph_node
*callee
= cs
->callee
->function_symbol (&availability
);
1866 class ipa_node_params
*callee_info
= IPA_NODE_REF (callee
);
1867 tree parm_type
= ipa_get_type (callee_info
, idx
);
1869 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the
1870 transform for these cases. Similarly, we can have bad type mismatches
1871 with LTO, avoid doing anything with those too. */
1873 || (!INTEGRAL_TYPE_P (parm_type
) && !POINTER_TYPE_P (parm_type
)))
1875 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1876 fprintf (dump_file
, "Setting dest_lattice to bottom, because type of "
1877 "param %i of %s is NULL or unsuitable for bits propagation\n",
1878 idx
, cs
->callee
->name ());
1880 return dest_lattice
->set_to_bottom ();
1883 unsigned precision
= TYPE_PRECISION (parm_type
);
1884 signop sgn
= TYPE_SIGN (parm_type
);
1886 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1887 || jfunc
->type
== IPA_JF_ANCESTOR
)
1889 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1890 tree operand
= NULL_TREE
;
1891 enum tree_code code
;
1894 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1896 code
= ipa_get_jf_pass_through_operation (jfunc
);
1897 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1898 if (code
!= NOP_EXPR
)
1899 operand
= ipa_get_jf_pass_through_operand (jfunc
);
1903 code
= POINTER_PLUS_EXPR
;
1904 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1905 unsigned HOST_WIDE_INT offset
= ipa_get_jf_ancestor_offset (jfunc
) / BITS_PER_UNIT
;
1906 operand
= build_int_cstu (size_type_node
, offset
);
1909 class ipcp_param_lattices
*src_lats
1910 = ipa_get_parm_lattices (caller_info
, src_idx
);
1912 /* Try to propagate bits if src_lattice is bottom, but jfunc is known.
1918 Assume lattice for x is bottom, however we can still propagate
1919 result of x & 0xff == 0xff, which gets computed during ccp1 pass
1920 and we store it in jump function during analysis stage. */
1922 if (src_lats
->bits_lattice
.bottom_p ()
1924 return dest_lattice
->meet_with (jfunc
->bits
->value
, jfunc
->bits
->mask
,
1927 return dest_lattice
->meet_with (src_lats
->bits_lattice
, precision
, sgn
,
1931 else if (jfunc
->type
== IPA_JF_ANCESTOR
)
1932 return dest_lattice
->set_to_bottom ();
1933 else if (jfunc
->bits
)
1934 return dest_lattice
->meet_with (jfunc
->bits
->value
, jfunc
->bits
->mask
,
1937 return dest_lattice
->set_to_bottom ();
1940 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
1941 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
1942 the result is a range or an anti-range. */
1945 ipa_vr_operation_and_type_effects (value_range
*dst_vr
,
1946 value_range
*src_vr
,
1947 enum tree_code operation
,
1948 tree dst_type
, tree src_type
)
1950 range_fold_unary_expr (dst_vr
, operation
, dst_type
, src_vr
, src_type
);
1951 if (dst_vr
->varying_p () || dst_vr
->undefined_p ())
1956 /* Propagate value range across jump function JFUNC that is associated with
1957 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
1961 propagate_vr_across_jump_function (cgraph_edge
*cs
, ipa_jump_func
*jfunc
,
1962 class ipcp_param_lattices
*dest_plats
,
1965 ipcp_vr_lattice
*dest_lat
= &dest_plats
->m_value_range
;
1967 if (dest_lat
->bottom_p ())
1971 || (!INTEGRAL_TYPE_P (param_type
)
1972 && !POINTER_TYPE_P (param_type
)))
1973 return dest_lat
->set_to_bottom ();
1975 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1977 enum tree_code operation
= ipa_get_jf_pass_through_operation (jfunc
);
1979 if (TREE_CODE_CLASS (operation
) == tcc_unary
)
1981 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1982 int src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1983 tree operand_type
= ipa_get_type (caller_info
, src_idx
);
1984 class ipcp_param_lattices
*src_lats
1985 = ipa_get_parm_lattices (caller_info
, src_idx
);
1987 if (src_lats
->m_value_range
.bottom_p ())
1988 return dest_lat
->set_to_bottom ();
1990 if (ipa_vr_operation_and_type_effects (&vr
,
1991 &src_lats
->m_value_range
.m_vr
,
1992 operation
, param_type
,
1994 return dest_lat
->meet_with (&vr
);
1997 else if (jfunc
->type
== IPA_JF_CONST
)
1999 tree val
= ipa_get_jf_constant (jfunc
);
2000 if (TREE_CODE (val
) == INTEGER_CST
)
2002 val
= fold_convert (param_type
, val
);
2003 if (TREE_OVERFLOW_P (val
))
2004 val
= drop_tree_overflow (val
);
2006 value_range
tmpvr (VR_RANGE
, val
, val
);
2007 return dest_lat
->meet_with (&tmpvr
);
2013 && ipa_vr_operation_and_type_effects (&vr
, jfunc
->m_vr
, NOP_EXPR
,
2015 jfunc
->m_vr
->type ()))
2016 return dest_lat
->meet_with (&vr
);
2018 return dest_lat
->set_to_bottom ();
2021 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
2022 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
2023 other cases, return false). If there are no aggregate items, set
2024 aggs_by_ref to NEW_AGGS_BY_REF. */
2027 set_check_aggs_by_ref (class ipcp_param_lattices
*dest_plats
,
2028 bool new_aggs_by_ref
)
2030 if (dest_plats
->aggs
)
2032 if (dest_plats
->aggs_by_ref
!= new_aggs_by_ref
)
2034 set_agg_lats_to_bottom (dest_plats
);
2039 dest_plats
->aggs_by_ref
= new_aggs_by_ref
;
2043 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
2044 already existing lattice for the given OFFSET and SIZE, marking all skipped
2045 lattices as containing variable and checking for overlaps. If there is no
2046 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
2047 it with offset, size and contains_variable to PRE_EXISTING, and return true,
2048 unless there are too many already. If there are two many, return false. If
2049 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
2050 skipped lattices were newly marked as containing variable, set *CHANGE to
2054 merge_agg_lats_step (class ipcp_param_lattices
*dest_plats
,
2055 HOST_WIDE_INT offset
, HOST_WIDE_INT val_size
,
2056 struct ipcp_agg_lattice
***aglat
,
2057 bool pre_existing
, bool *change
)
2059 gcc_checking_assert (offset
>= 0);
2061 while (**aglat
&& (**aglat
)->offset
< offset
)
2063 if ((**aglat
)->offset
+ (**aglat
)->size
> offset
)
2065 set_agg_lats_to_bottom (dest_plats
);
2068 *change
|= (**aglat
)->set_contains_variable ();
2069 *aglat
= &(**aglat
)->next
;
2072 if (**aglat
&& (**aglat
)->offset
== offset
)
2074 if ((**aglat
)->size
!= val_size
)
2076 set_agg_lats_to_bottom (dest_plats
);
2079 gcc_assert (!(**aglat
)->next
2080 || (**aglat
)->next
->offset
>= offset
+ val_size
);
2085 struct ipcp_agg_lattice
*new_al
;
2087 if (**aglat
&& (**aglat
)->offset
< offset
+ val_size
)
2089 set_agg_lats_to_bottom (dest_plats
);
2092 if (dest_plats
->aggs_count
== param_ipa_max_agg_items
)
2094 dest_plats
->aggs_count
++;
2095 new_al
= ipcp_agg_lattice_pool
.allocate ();
2096 memset (new_al
, 0, sizeof (*new_al
));
2098 new_al
->offset
= offset
;
2099 new_al
->size
= val_size
;
2100 new_al
->contains_variable
= pre_existing
;
2102 new_al
->next
= **aglat
;
2108 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
2109 containing an unknown value. */
2112 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice
*aglat
)
2117 ret
|= aglat
->set_contains_variable ();
2118 aglat
= aglat
->next
;
2123 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
2124 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
2125 parameter used for lattice value sources. Return true if DEST_PLATS changed
2129 merge_aggregate_lattices (struct cgraph_edge
*cs
,
2130 class ipcp_param_lattices
*dest_plats
,
2131 class ipcp_param_lattices
*src_plats
,
2132 int src_idx
, HOST_WIDE_INT offset_delta
)
2134 bool pre_existing
= dest_plats
->aggs
!= NULL
;
2135 struct ipcp_agg_lattice
**dst_aglat
;
2138 if (set_check_aggs_by_ref (dest_plats
, src_plats
->aggs_by_ref
))
2140 if (src_plats
->aggs_bottom
)
2141 return set_agg_lats_contain_variable (dest_plats
);
2142 if (src_plats
->aggs_contain_variable
)
2143 ret
|= set_agg_lats_contain_variable (dest_plats
);
2144 dst_aglat
= &dest_plats
->aggs
;
2146 for (struct ipcp_agg_lattice
*src_aglat
= src_plats
->aggs
;
2148 src_aglat
= src_aglat
->next
)
2150 HOST_WIDE_INT new_offset
= src_aglat
->offset
- offset_delta
;
2154 if (merge_agg_lats_step (dest_plats
, new_offset
, src_aglat
->size
,
2155 &dst_aglat
, pre_existing
, &ret
))
2157 struct ipcp_agg_lattice
*new_al
= *dst_aglat
;
2159 dst_aglat
= &(*dst_aglat
)->next
;
2160 if (src_aglat
->bottom
)
2162 ret
|= new_al
->set_contains_variable ();
2165 if (src_aglat
->contains_variable
)
2166 ret
|= new_al
->set_contains_variable ();
2167 for (ipcp_value
<tree
> *val
= src_aglat
->values
;
2170 ret
|= new_al
->add_value (val
->value
, cs
, val
, src_idx
,
2173 else if (dest_plats
->aggs_bottom
)
2176 ret
|= set_chain_of_aglats_contains_variable (*dst_aglat
);
2180 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
2181 pass-through JFUNC and if so, whether it has conform and conforms to the
2182 rules about propagating values passed by reference. */
2185 agg_pass_through_permissible_p (class ipcp_param_lattices
*src_plats
,
2186 struct ipa_jump_func
*jfunc
)
2188 return src_plats
->aggs
2189 && (!src_plats
->aggs_by_ref
2190 || ipa_get_jf_pass_through_agg_preserved (jfunc
));
2193 /* Propagate scalar values across jump function JFUNC that is associated with
2194 edge CS and put the values into DEST_LAT. */
2197 propagate_aggs_across_jump_function (struct cgraph_edge
*cs
,
2198 struct ipa_jump_func
*jfunc
,
2199 class ipcp_param_lattices
*dest_plats
)
2203 if (dest_plats
->aggs_bottom
)
2206 if (jfunc
->type
== IPA_JF_PASS_THROUGH
2207 && ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
2209 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
2210 int src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
2211 class ipcp_param_lattices
*src_plats
;
2213 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
2214 if (agg_pass_through_permissible_p (src_plats
, jfunc
))
2216 /* Currently we do not produce clobber aggregate jump
2217 functions, replace with merging when we do. */
2218 gcc_assert (!jfunc
->agg
.items
);
2219 ret
|= merge_aggregate_lattices (cs
, dest_plats
, src_plats
,
2223 ret
|= set_agg_lats_contain_variable (dest_plats
);
2225 else if (jfunc
->type
== IPA_JF_ANCESTOR
2226 && ipa_get_jf_ancestor_agg_preserved (jfunc
))
2228 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
2229 int src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
2230 class ipcp_param_lattices
*src_plats
;
2232 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
2233 if (src_plats
->aggs
&& src_plats
->aggs_by_ref
)
2235 /* Currently we do not produce clobber aggregate jump
2236 functions, replace with merging when we do. */
2237 gcc_assert (!jfunc
->agg
.items
);
2238 ret
|= merge_aggregate_lattices (cs
, dest_plats
, src_plats
, src_idx
,
2239 ipa_get_jf_ancestor_offset (jfunc
));
2241 else if (!src_plats
->aggs_by_ref
)
2242 ret
|= set_agg_lats_to_bottom (dest_plats
);
2244 ret
|= set_agg_lats_contain_variable (dest_plats
);
2246 else if (jfunc
->agg
.items
)
2248 bool pre_existing
= dest_plats
->aggs
!= NULL
;
2249 struct ipcp_agg_lattice
**aglat
= &dest_plats
->aggs
;
2250 struct ipa_agg_jf_item
*item
;
2253 if (set_check_aggs_by_ref (dest_plats
, jfunc
->agg
.by_ref
))
2256 FOR_EACH_VEC_ELT (*jfunc
->agg
.items
, i
, item
)
2258 HOST_WIDE_INT val_size
;
2260 if (item
->offset
< 0)
2262 gcc_checking_assert (is_gimple_ip_invariant (item
->value
));
2263 val_size
= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item
->value
)));
2265 if (merge_agg_lats_step (dest_plats
, item
->offset
, val_size
,
2266 &aglat
, pre_existing
, &ret
))
2268 ret
|= (*aglat
)->add_value (item
->value
, cs
, NULL
, 0, 0);
2269 aglat
= &(*aglat
)->next
;
2271 else if (dest_plats
->aggs_bottom
)
2275 ret
|= set_chain_of_aglats_contains_variable (*aglat
);
2278 ret
|= set_agg_lats_contain_variable (dest_plats
);
2283 /* Return true if on the way cfrom CS->caller to the final (non-alias and
2284 non-thunk) destination, the call passes through a thunk. */
2287 call_passes_through_thunk_p (cgraph_edge
*cs
)
2289 cgraph_node
*alias_or_thunk
= cs
->callee
;
2290 while (alias_or_thunk
->alias
)
2291 alias_or_thunk
= alias_or_thunk
->get_alias_target ();
2292 return alias_or_thunk
->thunk
.thunk_p
;
2295 /* Propagate constants from the caller to the callee of CS. INFO describes the
2299 propagate_constants_across_call (struct cgraph_edge
*cs
)
2301 class ipa_node_params
*callee_info
;
2302 enum availability availability
;
2303 cgraph_node
*callee
;
2304 class ipa_edge_args
*args
;
2306 int i
, args_count
, parms_count
;
2308 callee
= cs
->callee
->function_symbol (&availability
);
2309 if (!callee
->definition
)
2311 gcc_checking_assert (callee
->has_gimple_body_p ());
2312 callee_info
= IPA_NODE_REF (callee
);
2316 args
= IPA_EDGE_REF (cs
);
2317 parms_count
= ipa_get_param_count (callee_info
);
2318 if (parms_count
== 0)
2322 for (i
= 0; i
< parms_count
; i
++)
2323 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
,
2327 args_count
= ipa_get_cs_argument_count (args
);
2329 /* If this call goes through a thunk we must not propagate to the first (0th)
2330 parameter. However, we might need to uncover a thunk from below a series
2331 of aliases first. */
2332 if (call_passes_through_thunk_p (cs
))
2334 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
,
2341 for (; (i
< args_count
) && (i
< parms_count
); i
++)
2343 struct ipa_jump_func
*jump_func
= ipa_get_ith_jump_func (args
, i
);
2344 class ipcp_param_lattices
*dest_plats
;
2345 tree param_type
= ipa_get_type (callee_info
, i
);
2347 dest_plats
= ipa_get_parm_lattices (callee_info
, i
);
2348 if (availability
== AVAIL_INTERPOSABLE
)
2349 ret
|= set_all_contains_variable (dest_plats
);
2352 ret
|= propagate_scalar_across_jump_function (cs
, jump_func
,
2353 &dest_plats
->itself
,
2355 ret
|= propagate_context_across_jump_function (cs
, jump_func
, i
,
2356 &dest_plats
->ctxlat
);
2358 |= propagate_bits_across_jump_function (cs
, i
, jump_func
,
2359 &dest_plats
->bits_lattice
);
2360 ret
|= propagate_aggs_across_jump_function (cs
, jump_func
,
2362 if (opt_for_fn (callee
->decl
, flag_ipa_vrp
))
2363 ret
|= propagate_vr_across_jump_function (cs
, jump_func
,
2364 dest_plats
, param_type
);
2366 ret
|= dest_plats
->m_value_range
.set_to_bottom ();
2369 for (; i
< parms_count
; i
++)
2370 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
, i
));
2375 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
2376 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
2377 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
2380 ipa_get_indirect_edge_target_1 (struct cgraph_edge
*ie
,
2381 vec
<tree
> known_csts
,
2382 vec
<ipa_polymorphic_call_context
> known_contexts
,
2383 vec
<ipa_agg_jump_function_p
> known_aggs
,
2384 struct ipa_agg_replacement_value
*agg_reps
,
2387 int param_index
= ie
->indirect_info
->param_index
;
2388 HOST_WIDE_INT anc_offset
;
2392 *speculative
= false;
2394 if (param_index
== -1
2395 || known_csts
.length () <= (unsigned int) param_index
)
2398 if (!ie
->indirect_info
->polymorphic
)
2402 if (ie
->indirect_info
->agg_contents
)
2405 if (agg_reps
&& ie
->indirect_info
->guaranteed_unmodified
)
2409 if (agg_reps
->index
== param_index
2410 && agg_reps
->offset
== ie
->indirect_info
->offset
2411 && agg_reps
->by_ref
== ie
->indirect_info
->by_ref
)
2413 t
= agg_reps
->value
;
2416 agg_reps
= agg_reps
->next
;
2421 struct ipa_agg_jump_function
*agg
;
2422 if (known_aggs
.length () > (unsigned int) param_index
)
2423 agg
= known_aggs
[param_index
];
2426 bool from_global_constant
;
2427 t
= ipa_find_agg_cst_for_param (agg
, known_csts
[param_index
],
2428 ie
->indirect_info
->offset
,
2429 ie
->indirect_info
->by_ref
,
2430 &from_global_constant
);
2432 && !from_global_constant
2433 && !ie
->indirect_info
->guaranteed_unmodified
)
2438 t
= known_csts
[param_index
];
2441 && TREE_CODE (t
) == ADDR_EXPR
2442 && TREE_CODE (TREE_OPERAND (t
, 0)) == FUNCTION_DECL
)
2443 return TREE_OPERAND (t
, 0);
2448 if (!opt_for_fn (ie
->caller
->decl
, flag_devirtualize
))
2451 gcc_assert (!ie
->indirect_info
->agg_contents
);
2452 anc_offset
= ie
->indirect_info
->offset
;
2456 /* Try to work out value of virtual table pointer value in replacements. */
2457 if (!t
&& agg_reps
&& !ie
->indirect_info
->by_ref
)
2461 if (agg_reps
->index
== param_index
2462 && agg_reps
->offset
== ie
->indirect_info
->offset
2463 && agg_reps
->by_ref
)
2465 t
= agg_reps
->value
;
2468 agg_reps
= agg_reps
->next
;
2472 /* Try to work out value of virtual table pointer value in known
2473 aggregate values. */
2474 if (!t
&& known_aggs
.length () > (unsigned int) param_index
2475 && !ie
->indirect_info
->by_ref
)
2477 struct ipa_agg_jump_function
*agg
;
2478 agg
= known_aggs
[param_index
];
2479 t
= ipa_find_agg_cst_for_param (agg
, known_csts
[param_index
],
2480 ie
->indirect_info
->offset
, true);
2483 /* If we found the virtual table pointer, lookup the target. */
2487 unsigned HOST_WIDE_INT offset
;
2488 if (vtable_pointer_value_to_vtable (t
, &vtable
, &offset
))
2491 target
= gimple_get_virt_method_for_vtable (ie
->indirect_info
->otr_token
,
2492 vtable
, offset
, &can_refer
);
2496 || fndecl_built_in_p (target
, BUILT_IN_UNREACHABLE
)
2497 || !possible_polymorphic_call_target_p
2498 (ie
, cgraph_node::get (target
)))
2500 /* Do not speculate builtin_unreachable, it is stupid! */
2501 if (ie
->indirect_info
->vptr_changed
)
2503 target
= ipa_impossible_devirt_target (ie
, target
);
2505 *speculative
= ie
->indirect_info
->vptr_changed
;
2512 /* Do we know the constant value of pointer? */
2514 t
= known_csts
[param_index
];
2516 gcc_checking_assert (!t
|| TREE_CODE (t
) != TREE_BINFO
);
2518 ipa_polymorphic_call_context context
;
2519 if (known_contexts
.length () > (unsigned int) param_index
)
2521 context
= known_contexts
[param_index
];
2522 context
.offset_by (anc_offset
);
2523 if (ie
->indirect_info
->vptr_changed
)
2524 context
.possible_dynamic_type_change (ie
->in_polymorphic_cdtor
,
2525 ie
->indirect_info
->otr_type
);
2528 ipa_polymorphic_call_context ctx2
= ipa_polymorphic_call_context
2529 (t
, ie
->indirect_info
->otr_type
, anc_offset
);
2530 if (!ctx2
.useless_p ())
2531 context
.combine_with (ctx2
, ie
->indirect_info
->otr_type
);
2536 context
= ipa_polymorphic_call_context (t
, ie
->indirect_info
->otr_type
,
2538 if (ie
->indirect_info
->vptr_changed
)
2539 context
.possible_dynamic_type_change (ie
->in_polymorphic_cdtor
,
2540 ie
->indirect_info
->otr_type
);
2545 vec
<cgraph_node
*>targets
;
2548 targets
= possible_polymorphic_call_targets
2549 (ie
->indirect_info
->otr_type
,
2550 ie
->indirect_info
->otr_token
,
2552 if (!final
|| targets
.length () > 1)
2554 struct cgraph_node
*node
;
2557 if (!opt_for_fn (ie
->caller
->decl
, flag_devirtualize_speculatively
)
2558 || ie
->speculative
|| !ie
->maybe_hot_p ())
2560 node
= try_speculative_devirtualization (ie
->indirect_info
->otr_type
,
2561 ie
->indirect_info
->otr_token
,
2565 *speculative
= true;
2566 target
= node
->decl
;
2573 *speculative
= false;
2574 if (targets
.length () == 1)
2575 target
= targets
[0]->decl
;
2577 target
= ipa_impossible_devirt_target (ie
, NULL_TREE
);
2580 if (target
&& !possible_polymorphic_call_target_p (ie
,
2581 cgraph_node::get (target
)))
2585 target
= ipa_impossible_devirt_target (ie
, target
);
2592 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2593 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2594 return the destination. */
2597 ipa_get_indirect_edge_target (struct cgraph_edge
*ie
,
2598 vec
<tree
> known_csts
,
2599 vec
<ipa_polymorphic_call_context
> known_contexts
,
2600 vec
<ipa_agg_jump_function_p
> known_aggs
,
2603 return ipa_get_indirect_edge_target_1 (ie
, known_csts
, known_contexts
,
2604 known_aggs
, NULL
, speculative
);
2607 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2608 and KNOWN_CONTEXTS. */
2611 devirtualization_time_bonus (struct cgraph_node
*node
,
2612 vec
<tree
> known_csts
,
2613 vec
<ipa_polymorphic_call_context
> known_contexts
,
2614 vec
<ipa_agg_jump_function_p
> known_aggs
)
2616 struct cgraph_edge
*ie
;
2619 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
2621 struct cgraph_node
*callee
;
2622 class ipa_fn_summary
*isummary
;
2623 enum availability avail
;
2627 target
= ipa_get_indirect_edge_target (ie
, known_csts
, known_contexts
,
2628 known_aggs
, &speculative
);
2632 /* Only bare minimum benefit for clearly un-inlineable targets. */
2634 callee
= cgraph_node::get (target
);
2635 if (!callee
|| !callee
->definition
)
2637 callee
= callee
->function_symbol (&avail
);
2638 if (avail
< AVAIL_AVAILABLE
)
2640 isummary
= ipa_fn_summaries
->get (callee
);
2641 if (!isummary
->inlinable
)
2644 int size
= ipa_size_summaries
->get (callee
)->size
;
2645 /* FIXME: The values below need re-considering and perhaps also
2646 integrating into the cost metrics, at lest in some very basic way. */
2647 if (size
<= param_max_inline_insns_auto
/ 4)
2648 res
+= 31 / ((int)speculative
+ 1);
2649 else if (size
<= param_max_inline_insns_auto
/ 2)
2650 res
+= 15 / ((int)speculative
+ 1);
2651 else if (size
<= param_max_inline_insns_auto
2652 || DECL_DECLARED_INLINE_P (callee
->decl
))
2653 res
+= 7 / ((int)speculative
+ 1);
2659 /* Return time bonus incurred because of HINTS. */
2662 hint_time_bonus (ipa_hints hints
)
2665 if (hints
& (INLINE_HINT_loop_iterations
| INLINE_HINT_loop_stride
))
2666 result
+= param_ipa_cp_loop_hint_bonus
;
2670 /* If there is a reason to penalize the function described by INFO in the
2671 cloning goodness evaluation, do so. */
2673 static inline int64_t
2674 incorporate_penalties (ipa_node_params
*info
, int64_t evaluation
)
2676 if (info
->node_within_scc
)
2677 evaluation
= (evaluation
2678 * (100 - param_ipa_cp_recursion_penalty
)) / 100;
2680 if (info
->node_calling_single_call
)
2681 evaluation
= (evaluation
2682 * (100 - param_ipa_cp_single_call_penalty
))
2688 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2689 and SIZE_COST and with the sum of frequencies of incoming edges to the
2690 potential new clone in FREQUENCIES. */
2693 good_cloning_opportunity_p (struct cgraph_node
*node
, int time_benefit
,
2694 int freq_sum
, profile_count count_sum
, int size_cost
)
2696 if (time_benefit
== 0
2697 || !opt_for_fn (node
->decl
, flag_ipa_cp_clone
)
2698 || node
->optimize_for_size_p ())
2701 gcc_assert (size_cost
> 0);
2703 class ipa_node_params
*info
= IPA_NODE_REF (node
);
2704 if (max_count
> profile_count::zero ())
2706 int factor
= RDIV (count_sum
.probability_in
2707 (max_count
).to_reg_br_prob_base ()
2708 * 1000, REG_BR_PROB_BASE
);
2709 int64_t evaluation
= (((int64_t) time_benefit
* factor
)
2711 evaluation
= incorporate_penalties (info
, evaluation
);
2713 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2715 fprintf (dump_file
, " good_cloning_opportunity_p (time: %i, "
2716 "size: %i, count_sum: ", time_benefit
, size_cost
);
2717 count_sum
.dump (dump_file
);
2718 fprintf (dump_file
, "%s%s) -> evaluation: " "%" PRId64
2719 ", threshold: %i\n",
2720 info
->node_within_scc
? ", scc" : "",
2721 info
->node_calling_single_call
? ", single_call" : "",
2722 evaluation
, param_ipa_cp_eval_threshold
);
2725 return evaluation
>= param_ipa_cp_eval_threshold
;
2729 int64_t evaluation
= (((int64_t) time_benefit
* freq_sum
)
2731 evaluation
= incorporate_penalties (info
, evaluation
);
2733 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2734 fprintf (dump_file
, " good_cloning_opportunity_p (time: %i, "
2735 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2736 "%" PRId64
", threshold: %i\n",
2737 time_benefit
, size_cost
, freq_sum
,
2738 info
->node_within_scc
? ", scc" : "",
2739 info
->node_calling_single_call
? ", single_call" : "",
2740 evaluation
, param_ipa_cp_eval_threshold
);
2742 return evaluation
>= param_ipa_cp_eval_threshold
;
2746 /* Return all context independent values from aggregate lattices in PLATS in a
2747 vector. Return NULL if there are none. */
2749 static vec
<ipa_agg_jf_item
, va_gc
> *
2750 context_independent_aggregate_values (class ipcp_param_lattices
*plats
)
2752 vec
<ipa_agg_jf_item
, va_gc
> *res
= NULL
;
2754 if (plats
->aggs_bottom
2755 || plats
->aggs_contain_variable
2756 || plats
->aggs_count
== 0)
2759 for (struct ipcp_agg_lattice
*aglat
= plats
->aggs
;
2761 aglat
= aglat
->next
)
2762 if (aglat
->is_single_const ())
2764 struct ipa_agg_jf_item item
;
2765 item
.offset
= aglat
->offset
;
2766 item
.value
= aglat
->values
->value
;
2767 vec_safe_push (res
, item
);
2772 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2773 populate them with values of parameters that are known independent of the
2774 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2775 non-NULL, the movement cost of all removable parameters will be stored in
2779 gather_context_independent_values (class ipa_node_params
*info
,
2780 vec
<tree
> *known_csts
,
2781 vec
<ipa_polymorphic_call_context
>
2783 vec
<ipa_agg_jump_function
> *known_aggs
,
2784 int *removable_params_cost
)
2786 int i
, count
= ipa_get_param_count (info
);
2789 known_csts
->create (0);
2790 known_contexts
->create (0);
2791 known_csts
->safe_grow_cleared (count
);
2792 known_contexts
->safe_grow_cleared (count
);
2795 known_aggs
->create (0);
2796 known_aggs
->safe_grow_cleared (count
);
2799 if (removable_params_cost
)
2800 *removable_params_cost
= 0;
2802 for (i
= 0; i
< count
; i
++)
2804 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2805 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
2807 if (lat
->is_single_const ())
2809 ipcp_value
<tree
> *val
= lat
->values
;
2810 gcc_checking_assert (TREE_CODE (val
->value
) != TREE_BINFO
);
2811 (*known_csts
)[i
] = val
->value
;
2812 if (removable_params_cost
)
2813 *removable_params_cost
2814 += estimate_move_cost (TREE_TYPE (val
->value
), false);
2817 else if (removable_params_cost
2818 && !ipa_is_param_used (info
, i
))
2819 *removable_params_cost
2820 += ipa_get_param_move_cost (info
, i
);
2822 if (!ipa_is_param_used (info
, i
))
2825 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
2826 /* Do not account known context as reason for cloning. We can see
2827 if it permits devirtualization. */
2828 if (ctxlat
->is_single_const ())
2829 (*known_contexts
)[i
] = ctxlat
->values
->value
;
2833 vec
<ipa_agg_jf_item
, va_gc
> *agg_items
;
2834 struct ipa_agg_jump_function
*ajf
;
2836 agg_items
= context_independent_aggregate_values (plats
);
2837 ajf
= &(*known_aggs
)[i
];
2838 ajf
->items
= agg_items
;
2839 ajf
->by_ref
= plats
->aggs_by_ref
;
2840 ret
|= agg_items
!= NULL
;
2847 /* The current interface in ipa-inline-analysis requires a pointer vector.
2850 FIXME: That interface should be re-worked, this is slightly silly. Still,
2851 I'd like to discuss how to change it first and this demonstrates the
2854 static vec
<ipa_agg_jump_function_p
>
2855 agg_jmp_p_vec_for_t_vec (vec
<ipa_agg_jump_function
> known_aggs
)
2857 vec
<ipa_agg_jump_function_p
> ret
;
2858 struct ipa_agg_jump_function
*ajf
;
2861 ret
.create (known_aggs
.length ());
2862 FOR_EACH_VEC_ELT (known_aggs
, i
, ajf
)
2863 ret
.quick_push (ajf
);
2867 /* Perform time and size measurement of NODE with the context given in
2868 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2869 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2870 all context-independent removable parameters and EST_MOVE_COST of estimated
2871 movement of the considered parameter and store it into VAL. */
2874 perform_estimation_of_a_value (cgraph_node
*node
, vec
<tree
> known_csts
,
2875 vec
<ipa_polymorphic_call_context
> known_contexts
,
2876 vec
<ipa_agg_jump_function_p
> known_aggs_ptrs
,
2877 int removable_params_cost
,
2878 int est_move_cost
, ipcp_value_base
*val
)
2880 int size
, time_benefit
;
2881 sreal time
, base_time
;
2884 estimate_ipcp_clone_size_and_time (node
, known_csts
, known_contexts
,
2885 known_aggs_ptrs
, &size
, &time
,
2886 &base_time
, &hints
);
2888 if (base_time
> 65535)
2891 /* Extern inline functions have no cloning local time benefits because they
2892 will be inlined anyway. The only reason to clone them is if it enables
2893 optimization in any of the functions they call. */
2894 if (DECL_EXTERNAL (node
->decl
) && DECL_DECLARED_INLINE_P (node
->decl
))
2897 time_benefit
= base_time
.to_int ()
2898 + devirtualization_time_bonus (node
, known_csts
, known_contexts
,
2900 + hint_time_bonus (hints
)
2901 + removable_params_cost
+ est_move_cost
;
2903 gcc_checking_assert (size
>=0);
2904 /* The inliner-heuristics based estimates may think that in certain
2905 contexts some functions do not have any size at all but we want
2906 all specializations to have at least a tiny cost, not least not to
2911 val
->local_time_benefit
= time_benefit
;
2912 val
->local_size_cost
= size
;
2915 /* Iterate over known values of parameters of NODE and estimate the local
2916 effects in terms of time and size they have. */
2919 estimate_local_effects (struct cgraph_node
*node
)
2921 class ipa_node_params
*info
= IPA_NODE_REF (node
);
2922 int i
, count
= ipa_get_param_count (info
);
2923 vec
<tree
> known_csts
;
2924 vec
<ipa_polymorphic_call_context
> known_contexts
;
2925 vec
<ipa_agg_jump_function
> known_aggs
;
2926 vec
<ipa_agg_jump_function_p
> known_aggs_ptrs
;
2928 int removable_params_cost
;
2930 if (!count
|| !ipcp_versionable_function_p (node
))
2933 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2934 fprintf (dump_file
, "\nEstimating effects for %s.\n", node
->dump_name ());
2936 always_const
= gather_context_independent_values (info
, &known_csts
,
2937 &known_contexts
, &known_aggs
,
2938 &removable_params_cost
);
2939 known_aggs_ptrs
= agg_jmp_p_vec_for_t_vec (known_aggs
);
2940 int devirt_bonus
= devirtualization_time_bonus (node
, known_csts
,
2941 known_contexts
, known_aggs_ptrs
);
2942 if (always_const
|| devirt_bonus
2943 || (removable_params_cost
&& node
->can_change_signature
))
2945 struct caller_statistics stats
;
2947 sreal time
, base_time
;
2950 init_caller_stats (&stats
);
2951 node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
2953 estimate_ipcp_clone_size_and_time (node
, known_csts
, known_contexts
,
2954 known_aggs_ptrs
, &size
, &time
,
2955 &base_time
, &hints
);
2956 time
-= devirt_bonus
;
2957 time
-= hint_time_bonus (hints
);
2958 time
-= removable_params_cost
;
2959 size
-= stats
.n_calls
* removable_params_cost
;
2962 fprintf (dump_file
, " - context independent values, size: %i, "
2963 "time_benefit: %f\n", size
, (base_time
- time
).to_double ());
2965 if (size
<= 0 || node
->local
)
2967 info
->do_clone_for_all_contexts
= true;
2970 fprintf (dump_file
, " Decided to specialize for all "
2971 "known contexts, code not going to grow.\n");
2973 else if (good_cloning_opportunity_p (node
,
2974 MIN ((base_time
- time
).to_int (),
2976 stats
.freq_sum
, stats
.count_sum
,
2979 if (size
+ overall_size
<= max_new_size
)
2981 info
->do_clone_for_all_contexts
= true;
2982 overall_size
+= size
;
2985 fprintf (dump_file
, " Decided to specialize for all "
2986 "known contexts, growth deemed beneficial.\n");
2988 else if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2989 fprintf (dump_file
, " Not cloning for all contexts because "
2990 "max_new_size would be reached with %li.\n",
2991 size
+ overall_size
);
2993 else if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2994 fprintf (dump_file
, " Not cloning for all contexts because "
2995 "!good_cloning_opportunity_p.\n");
2999 for (i
= 0; i
< count
; i
++)
3001 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
3002 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
3003 ipcp_value
<tree
> *val
;
3010 for (val
= lat
->values
; val
; val
= val
->next
)
3012 gcc_checking_assert (TREE_CODE (val
->value
) != TREE_BINFO
);
3013 known_csts
[i
] = val
->value
;
3015 int emc
= estimate_move_cost (TREE_TYPE (val
->value
), true);
3016 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
3018 removable_params_cost
, emc
, val
);
3020 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3022 fprintf (dump_file
, " - estimates for value ");
3023 print_ipcp_constant_value (dump_file
, val
->value
);
3024 fprintf (dump_file
, " for ");
3025 ipa_dump_param (dump_file
, info
, i
);
3026 fprintf (dump_file
, ": time_benefit: %i, size: %i\n",
3027 val
->local_time_benefit
, val
->local_size_cost
);
3030 known_csts
[i
] = NULL_TREE
;
3033 for (i
= 0; i
< count
; i
++)
3035 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
3037 if (!plats
->virt_call
)
3040 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
3041 ipcp_value
<ipa_polymorphic_call_context
> *val
;
3045 || !known_contexts
[i
].useless_p ())
3048 for (val
= ctxlat
->values
; val
; val
= val
->next
)
3050 known_contexts
[i
] = val
->value
;
3051 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
3053 removable_params_cost
, 0, val
);
3055 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3057 fprintf (dump_file
, " - estimates for polymorphic context ");
3058 print_ipcp_constant_value (dump_file
, val
->value
);
3059 fprintf (dump_file
, " for ");
3060 ipa_dump_param (dump_file
, info
, i
);
3061 fprintf (dump_file
, ": time_benefit: %i, size: %i\n",
3062 val
->local_time_benefit
, val
->local_size_cost
);
3065 known_contexts
[i
] = ipa_polymorphic_call_context ();
3068 for (i
= 0; i
< count
; i
++)
3070 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
3071 struct ipa_agg_jump_function
*ajf
;
3072 struct ipcp_agg_lattice
*aglat
;
3074 if (plats
->aggs_bottom
|| !plats
->aggs
)
3077 ajf
= &known_aggs
[i
];
3078 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
3080 ipcp_value
<tree
> *val
;
3081 if (aglat
->bottom
|| !aglat
->values
3082 /* If the following is true, the one value is in known_aggs. */
3083 || (!plats
->aggs_contain_variable
3084 && aglat
->is_single_const ()))
3087 for (val
= aglat
->values
; val
; val
= val
->next
)
3089 struct ipa_agg_jf_item item
;
3091 item
.offset
= aglat
->offset
;
3092 item
.value
= val
->value
;
3093 vec_safe_push (ajf
->items
, item
);
3095 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
3097 removable_params_cost
, 0, val
);
3099 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3101 fprintf (dump_file
, " - estimates for value ");
3102 print_ipcp_constant_value (dump_file
, val
->value
);
3103 fprintf (dump_file
, " for ");
3104 ipa_dump_param (dump_file
, info
, i
);
3105 fprintf (dump_file
, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
3106 "]: time_benefit: %i, size: %i\n",
3107 plats
->aggs_by_ref
? "ref " : "",
3109 val
->local_time_benefit
, val
->local_size_cost
);
3117 for (i
= 0; i
< count
; i
++)
3118 vec_free (known_aggs
[i
].items
);
3120 known_csts
.release ();
3121 known_contexts
.release ();
3122 known_aggs
.release ();
3123 known_aggs_ptrs
.release ();
3127 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
3128 topological sort of values. */
3130 template <typename valtype
>
3132 value_topo_info
<valtype
>::add_val (ipcp_value
<valtype
> *cur_val
)
3134 ipcp_value_source
<valtype
> *src
;
3140 cur_val
->dfs
= dfs_counter
;
3141 cur_val
->low_link
= dfs_counter
;
3143 cur_val
->topo_next
= stack
;
3145 cur_val
->on_stack
= true;
3147 for (src
= cur_val
->sources
; src
; src
= src
->next
)
3150 if (src
->val
->dfs
== 0)
3153 if (src
->val
->low_link
< cur_val
->low_link
)
3154 cur_val
->low_link
= src
->val
->low_link
;
3156 else if (src
->val
->on_stack
3157 && src
->val
->dfs
< cur_val
->low_link
)
3158 cur_val
->low_link
= src
->val
->dfs
;
3161 if (cur_val
->dfs
== cur_val
->low_link
)
3163 ipcp_value
<valtype
> *v
, *scc_list
= NULL
;
3168 stack
= v
->topo_next
;
3169 v
->on_stack
= false;
3171 v
->scc_next
= scc_list
;
3174 while (v
!= cur_val
);
3176 cur_val
->topo_next
= values_topo
;
3177 values_topo
= cur_val
;
3181 /* Add all values in lattices associated with NODE to the topological sort if
3182 they are not there yet. */
3185 add_all_node_vals_to_toposort (cgraph_node
*node
, ipa_topo_info
*topo
)
3187 class ipa_node_params
*info
= IPA_NODE_REF (node
);
3188 int i
, count
= ipa_get_param_count (info
);
3190 for (i
= 0; i
< count
; i
++)
3192 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
3193 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
3194 struct ipcp_agg_lattice
*aglat
;
3198 ipcp_value
<tree
> *val
;
3199 for (val
= lat
->values
; val
; val
= val
->next
)
3200 topo
->constants
.add_val (val
);
3203 if (!plats
->aggs_bottom
)
3204 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
3207 ipcp_value
<tree
> *val
;
3208 for (val
= aglat
->values
; val
; val
= val
->next
)
3209 topo
->constants
.add_val (val
);
3212 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
3213 if (!ctxlat
->bottom
)
3215 ipcp_value
<ipa_polymorphic_call_context
> *ctxval
;
3216 for (ctxval
= ctxlat
->values
; ctxval
; ctxval
= ctxval
->next
)
3217 topo
->contexts
.add_val (ctxval
);
3222 /* One pass of constants propagation along the call graph edges, from callers
3223 to callees (requires topological ordering in TOPO), iterate over strongly
3224 connected components. */
3227 propagate_constants_topo (class ipa_topo_info
*topo
)
3231 for (i
= topo
->nnodes
- 1; i
>= 0; i
--)
3234 struct cgraph_node
*v
, *node
= topo
->order
[i
];
3235 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
3237 /* First, iteratively propagate within the strongly connected component
3238 until all lattices stabilize. */
3239 FOR_EACH_VEC_ELT (cycle_nodes
, j
, v
)
3240 if (v
->has_gimple_body_p ())
3242 if (opt_for_fn (v
->decl
, flag_ipa_cp
))
3243 push_node_to_stack (topo
, v
);
3244 /* When V is not optimized, we can not push it to stac, but
3245 still we need to set all its callees lattices to bottom. */
3248 for (cgraph_edge
*cs
= v
->callees
; cs
; cs
= cs
->next_callee
)
3249 propagate_constants_across_call (cs
);
3253 v
= pop_node_from_stack (topo
);
3256 struct cgraph_edge
*cs
;
3258 for (cs
= v
->callees
; cs
; cs
= cs
->next_callee
)
3259 if (ipa_edge_within_scc (cs
))
3261 IPA_NODE_REF (v
)->node_within_scc
= true;
3262 if (propagate_constants_across_call (cs
))
3263 push_node_to_stack (topo
, cs
->callee
->function_symbol ());
3265 v
= pop_node_from_stack (topo
);
3268 /* Afterwards, propagate along edges leading out of the SCC, calculates
3269 the local effects of the discovered constants and all valid values to
3270 their topological sort. */
3271 FOR_EACH_VEC_ELT (cycle_nodes
, j
, v
)
3272 if (v
->has_gimple_body_p ()
3273 && opt_for_fn (v
->decl
, flag_ipa_cp
))
3275 struct cgraph_edge
*cs
;
3277 estimate_local_effects (v
);
3278 add_all_node_vals_to_toposort (v
, topo
);
3279 for (cs
= v
->callees
; cs
; cs
= cs
->next_callee
)
3280 if (!ipa_edge_within_scc (cs
))
3281 propagate_constants_across_call (cs
);
3283 cycle_nodes
.release ();
3288 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
3289 the bigger one if otherwise. */
3292 safe_add (int a
, int b
)
3294 if (a
> INT_MAX
/2 || b
> INT_MAX
/2)
3295 return a
> b
? a
: b
;
3301 /* Propagate the estimated effects of individual values along the topological
3302 from the dependent values to those they depend on. */
3304 template <typename valtype
>
3306 value_topo_info
<valtype
>::propagate_effects ()
3308 ipcp_value
<valtype
> *base
;
3310 for (base
= values_topo
; base
; base
= base
->topo_next
)
3312 ipcp_value_source
<valtype
> *src
;
3313 ipcp_value
<valtype
> *val
;
3314 int time
= 0, size
= 0;
3316 for (val
= base
; val
; val
= val
->scc_next
)
3318 time
= safe_add (time
,
3319 val
->local_time_benefit
+ val
->prop_time_benefit
);
3320 size
= safe_add (size
, val
->local_size_cost
+ val
->prop_size_cost
);
3323 for (val
= base
; val
; val
= val
->scc_next
)
3324 for (src
= val
->sources
; src
; src
= src
->next
)
3326 && src
->cs
->maybe_hot_p ())
3328 src
->val
->prop_time_benefit
= safe_add (time
,
3329 src
->val
->prop_time_benefit
);
3330 src
->val
->prop_size_cost
= safe_add (size
,
3331 src
->val
->prop_size_cost
);
3337 /* Propagate constants, polymorphic contexts and their effects from the
3338 summaries interprocedurally. */
3341 ipcp_propagate_stage (class ipa_topo_info
*topo
)
3343 struct cgraph_node
*node
;
3346 fprintf (dump_file
, "\n Propagating constants:\n\n");
3348 max_count
= profile_count::uninitialized ();
3350 FOR_EACH_DEFINED_FUNCTION (node
)
3352 if (node
->has_gimple_body_p () && opt_for_fn (node
->decl
, flag_ipa_cp
))
3354 class ipa_node_params
*info
= IPA_NODE_REF (node
);
3355 determine_versionability (node
, info
);
3356 info
->lattices
= XCNEWVEC (class ipcp_param_lattices
,
3357 ipa_get_param_count (info
));
3358 initialize_node_lattices (node
);
3360 ipa_size_summary
*s
= ipa_size_summaries
->get (node
);
3361 if (node
->definition
&& !node
->alias
&& s
!= NULL
)
3362 overall_size
+= s
->self_size
;
3363 max_count
= max_count
.max (node
->count
.ipa ());
3366 max_new_size
= overall_size
;
3367 if (max_new_size
< param_large_unit_insns
)
3368 max_new_size
= param_large_unit_insns
;
3369 max_new_size
+= max_new_size
* param_ipcp_unit_growth
/ 100 + 1;
3372 fprintf (dump_file
, "\noverall_size: %li, max_new_size: %li\n",
3373 overall_size
, max_new_size
);
3375 propagate_constants_topo (topo
);
3377 ipcp_verify_propagated_values ();
3378 topo
->constants
.propagate_effects ();
3379 topo
->contexts
.propagate_effects ();
3383 fprintf (dump_file
, "\nIPA lattices after all propagation:\n");
3384 print_all_lattices (dump_file
, (dump_flags
& TDF_DETAILS
), true);
3388 /* Discover newly direct outgoing edges from NODE which is a new clone with
3389 known KNOWN_CSTS and make them direct. */
3392 ipcp_discover_new_direct_edges (struct cgraph_node
*node
,
3393 vec
<tree
> known_csts
,
3394 vec
<ipa_polymorphic_call_context
>
3396 struct ipa_agg_replacement_value
*aggvals
)
3398 struct cgraph_edge
*ie
, *next_ie
;
3401 for (ie
= node
->indirect_calls
; ie
; ie
= next_ie
)
3406 next_ie
= ie
->next_callee
;
3407 target
= ipa_get_indirect_edge_target_1 (ie
, known_csts
, known_contexts
,
3408 vNULL
, aggvals
, &speculative
);
3411 bool agg_contents
= ie
->indirect_info
->agg_contents
;
3412 bool polymorphic
= ie
->indirect_info
->polymorphic
;
3413 int param_index
= ie
->indirect_info
->param_index
;
3414 struct cgraph_edge
*cs
= ipa_make_edge_direct_to_target (ie
, target
,
3418 if (cs
&& !agg_contents
&& !polymorphic
)
3420 class ipa_node_params
*info
= IPA_NODE_REF (node
);
3421 int c
= ipa_get_controlled_uses (info
, param_index
);
3422 if (c
!= IPA_UNDESCRIBED_USE
)
3424 struct ipa_ref
*to_del
;
3427 ipa_set_controlled_uses (info
, param_index
, c
);
3428 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3429 fprintf (dump_file
, " controlled uses count of param "
3430 "%i bumped down to %i\n", param_index
, c
);
3432 && (to_del
= node
->find_reference (cs
->callee
, NULL
, 0)))
3434 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3435 fprintf (dump_file
, " and even removing its "
3436 "cloning-created reference\n");
3437 to_del
->remove_reference ();
3443 /* Turning calls to direct calls will improve overall summary. */
3445 ipa_update_overall_fn_summary (node
);
3448 class edge_clone_summary
;
3449 static call_summary
<edge_clone_summary
*> *edge_clone_summaries
= NULL
;
3451 /* Edge clone summary. */
3453 class edge_clone_summary
3456 /* Default constructor. */
3457 edge_clone_summary (): prev_clone (NULL
), next_clone (NULL
) {}
3459 /* Default destructor. */
3460 ~edge_clone_summary ()
3463 edge_clone_summaries
->get (prev_clone
)->next_clone
= next_clone
;
3465 edge_clone_summaries
->get (next_clone
)->prev_clone
= prev_clone
;
3468 cgraph_edge
*prev_clone
;
3469 cgraph_edge
*next_clone
;
3472 class edge_clone_summary_t
:
3473 public call_summary
<edge_clone_summary
*>
3476 edge_clone_summary_t (symbol_table
*symtab
):
3477 call_summary
<edge_clone_summary
*> (symtab
)
3479 m_initialize_when_cloning
= true;
3482 virtual void duplicate (cgraph_edge
*src_edge
, cgraph_edge
*dst_edge
,
3483 edge_clone_summary
*src_data
,
3484 edge_clone_summary
*dst_data
);
3487 /* Edge duplication hook. */
3490 edge_clone_summary_t::duplicate (cgraph_edge
*src_edge
, cgraph_edge
*dst_edge
,
3491 edge_clone_summary
*src_data
,
3492 edge_clone_summary
*dst_data
)
3494 if (src_data
->next_clone
)
3495 edge_clone_summaries
->get (src_data
->next_clone
)->prev_clone
= dst_edge
;
3496 dst_data
->prev_clone
= src_edge
;
3497 dst_data
->next_clone
= src_data
->next_clone
;
3498 src_data
->next_clone
= dst_edge
;
3501 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3502 parameter with the given INDEX. */
3505 get_clone_agg_value (struct cgraph_node
*node
, HOST_WIDE_INT offset
,
3508 struct ipa_agg_replacement_value
*aggval
;
3510 aggval
= ipa_get_agg_replacements_for_node (node
);
3513 if (aggval
->offset
== offset
3514 && aggval
->index
== index
)
3515 return aggval
->value
;
3516 aggval
= aggval
->next
;
3521 /* Return true is NODE is DEST or its clone for all contexts. */
3524 same_node_or_its_all_contexts_clone_p (cgraph_node
*node
, cgraph_node
*dest
)
3529 class ipa_node_params
*info
= IPA_NODE_REF (node
);
3530 return info
->is_all_contexts_clone
&& info
->ipcp_orig_node
== dest
;
3533 /* Return true if edge CS does bring about the value described by SRC to
3534 DEST_VAL of node DEST or its clone for all contexts. */
3537 cgraph_edge_brings_value_p (cgraph_edge
*cs
, ipcp_value_source
<tree
> *src
,
3538 cgraph_node
*dest
, ipcp_value
<tree
> *dest_val
)
3540 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3541 enum availability availability
;
3542 cgraph_node
*real_dest
= cs
->callee
->function_symbol (&availability
);
3544 if (availability
<= AVAIL_INTERPOSABLE
3545 || !same_node_or_its_all_contexts_clone_p (real_dest
, dest
)
3546 || caller_info
->node_dead
)
3552 if (caller_info
->ipcp_orig_node
)
3555 if (src
->offset
== -1)
3556 t
= caller_info
->known_csts
[src
->index
];
3558 t
= get_clone_agg_value (cs
->caller
, src
->offset
, src
->index
);
3559 return (t
!= NULL_TREE
3560 && values_equal_for_ipcp_p (src
->val
->value
, t
));
3564 /* At the moment we do not propagate over arithmetic jump functions in
3565 SCCs, so it is safe to detect self-feeding recursive calls in this
3567 if (src
->val
== dest_val
)
3570 struct ipcp_agg_lattice
*aglat
;
3571 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (caller_info
,
3573 if (src
->offset
== -1)
3574 return (plats
->itself
.is_single_const ()
3575 && values_equal_for_ipcp_p (src
->val
->value
,
3576 plats
->itself
.values
->value
));
3579 if (plats
->aggs_bottom
|| plats
->aggs_contain_variable
)
3581 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
3582 if (aglat
->offset
== src
->offset
)
3583 return (aglat
->is_single_const ()
3584 && values_equal_for_ipcp_p (src
->val
->value
,
3585 aglat
->values
->value
));
3591 /* Return true if edge CS does bring about the value described by SRC to
3592 DST_VAL of node DEST or its clone for all contexts. */
3595 cgraph_edge_brings_value_p (cgraph_edge
*cs
,
3596 ipcp_value_source
<ipa_polymorphic_call_context
> *src
,
3598 ipcp_value
<ipa_polymorphic_call_context
> *)
3600 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3601 enum availability avail
;
3602 cgraph_node
*real_dest
= cs
->callee
->function_symbol (&avail
);
3604 if (avail
<= AVAIL_INTERPOSABLE
3605 || !same_node_or_its_all_contexts_clone_p (real_dest
, dest
)
3606 || caller_info
->node_dead
)
3611 if (caller_info
->ipcp_orig_node
)
3612 return (caller_info
->known_contexts
.length () > (unsigned) src
->index
)
3613 && values_equal_for_ipcp_p (src
->val
->value
,
3614 caller_info
->known_contexts
[src
->index
]);
3616 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (caller_info
,
3618 return plats
->ctxlat
.is_single_const ()
3619 && values_equal_for_ipcp_p (src
->val
->value
,
3620 plats
->ctxlat
.values
->value
);
3623 /* Get the next clone in the linked list of clones of an edge. */
3625 static inline struct cgraph_edge
*
3626 get_next_cgraph_edge_clone (struct cgraph_edge
*cs
)
3628 edge_clone_summary
*s
= edge_clone_summaries
->get (cs
);
3629 return s
!= NULL
? s
->next_clone
: NULL
;
3632 /* Given VAL that is intended for DEST, iterate over all its sources and if any
3633 of them is viable and hot, return true. In that case, for those that still
3634 hold, add their edge frequency and their number into *FREQUENCY and
3635 *CALLER_COUNT respectively. */
3637 template <typename valtype
>
3639 get_info_about_necessary_edges (ipcp_value
<valtype
> *val
, cgraph_node
*dest
,
3641 profile_count
*count_sum
, int *caller_count
)
3643 ipcp_value_source
<valtype
> *src
;
3644 int freq
= 0, count
= 0;
3645 profile_count cnt
= profile_count::zero ();
3647 bool non_self_recursive
= false;
3649 for (src
= val
->sources
; src
; src
= src
->next
)
3651 struct cgraph_edge
*cs
= src
->cs
;
3654 if (cgraph_edge_brings_value_p (cs
, src
, dest
, val
))
3657 freq
+= cs
->frequency ();
3658 if (cs
->count
.ipa ().initialized_p ())
3659 cnt
+= cs
->count
.ipa ();
3660 hot
|= cs
->maybe_hot_p ();
3661 if (cs
->caller
!= dest
)
3662 non_self_recursive
= true;
3664 cs
= get_next_cgraph_edge_clone (cs
);
3668 /* If the only edges bringing a value are self-recursive ones, do not bother
3670 if (!non_self_recursive
)
3675 *caller_count
= count
;
3679 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3680 is assumed their number is known and equal to CALLER_COUNT. */
3682 template <typename valtype
>
3683 static vec
<cgraph_edge
*>
3684 gather_edges_for_value (ipcp_value
<valtype
> *val
, cgraph_node
*dest
,
3687 ipcp_value_source
<valtype
> *src
;
3688 vec
<cgraph_edge
*> ret
;
3690 ret
.create (caller_count
);
3691 for (src
= val
->sources
; src
; src
= src
->next
)
3693 struct cgraph_edge
*cs
= src
->cs
;
3696 if (cgraph_edge_brings_value_p (cs
, src
, dest
, val
))
3697 ret
.quick_push (cs
);
3698 cs
= get_next_cgraph_edge_clone (cs
);
3705 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3706 Return it or NULL if for some reason it cannot be created. */
3708 static struct ipa_replace_map
*
3709 get_replacement_map (class ipa_node_params
*info
, tree value
, int parm_num
)
3711 struct ipa_replace_map
*replace_map
;
3714 replace_map
= ggc_alloc
<ipa_replace_map
> ();
3717 fprintf (dump_file
, " replacing ");
3718 ipa_dump_param (dump_file
, info
, parm_num
);
3720 fprintf (dump_file
, " with const ");
3721 print_generic_expr (dump_file
, value
);
3722 fprintf (dump_file
, "\n");
3724 replace_map
->parm_num
= parm_num
;
3725 replace_map
->new_tree
= value
;
3729 /* Dump new profiling counts */
3732 dump_profile_updates (struct cgraph_node
*orig_node
,
3733 struct cgraph_node
*new_node
)
3735 struct cgraph_edge
*cs
;
3737 fprintf (dump_file
, " setting count of the specialized node to ");
3738 new_node
->count
.dump (dump_file
);
3739 fprintf (dump_file
, "\n");
3740 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3742 fprintf (dump_file
, " edge to %s has count ",
3743 cs
->callee
->name ());
3744 cs
->count
.dump (dump_file
);
3745 fprintf (dump_file
, "\n");
3748 fprintf (dump_file
, " setting count of the original node to ");
3749 orig_node
->count
.dump (dump_file
);
3750 fprintf (dump_file
, "\n");
3751 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3753 fprintf (dump_file
, " edge to %s is left with ",
3754 cs
->callee
->name ());
3755 cs
->count
.dump (dump_file
);
3756 fprintf (dump_file
, "\n");
3760 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3761 their profile information to reflect this. */
3764 update_profiling_info (struct cgraph_node
*orig_node
,
3765 struct cgraph_node
*new_node
)
3767 struct cgraph_edge
*cs
;
3768 struct caller_statistics stats
;
3769 profile_count new_sum
, orig_sum
;
3770 profile_count remainder
, orig_node_count
= orig_node
->count
;
3772 if (!(orig_node_count
.ipa () > profile_count::zero ()))
3775 init_caller_stats (&stats
);
3776 orig_node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
3778 orig_sum
= stats
.count_sum
;
3779 init_caller_stats (&stats
);
3780 new_node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
3782 new_sum
= stats
.count_sum
;
3784 if (orig_node_count
< orig_sum
+ new_sum
)
3788 fprintf (dump_file
, " Problem: node %s has too low count ",
3789 orig_node
->dump_name ());
3790 orig_node_count
.dump (dump_file
);
3791 fprintf (dump_file
, "while the sum of incoming count is ");
3792 (orig_sum
+ new_sum
).dump (dump_file
);
3793 fprintf (dump_file
, "\n");
3796 orig_node_count
= (orig_sum
+ new_sum
).apply_scale (12, 10);
3799 fprintf (dump_file
, " proceeding by pretending it was ");
3800 orig_node_count
.dump (dump_file
);
3801 fprintf (dump_file
, "\n");
3805 remainder
= orig_node_count
.combine_with_ipa_count (orig_node_count
.ipa ()
3807 new_sum
= orig_node_count
.combine_with_ipa_count (new_sum
);
3808 orig_node
->count
= remainder
;
3810 profile_count::adjust_for_ipa_scaling (&new_sum
, &orig_node_count
);
3811 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3812 cs
->count
= cs
->count
.apply_scale (new_sum
, orig_node_count
);
3814 profile_count::adjust_for_ipa_scaling (&remainder
, &orig_node_count
);
3815 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3816 cs
->count
= cs
->count
.apply_scale (remainder
, orig_node_count
);
3819 dump_profile_updates (orig_node
, new_node
);
3822 /* Update the respective profile of specialized NEW_NODE and the original
3823 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3824 have been redirected to the specialized version. */
3827 update_specialized_profile (struct cgraph_node
*new_node
,
3828 struct cgraph_node
*orig_node
,
3829 profile_count redirected_sum
)
3831 struct cgraph_edge
*cs
;
3832 profile_count new_node_count
, orig_node_count
= orig_node
->count
;
3836 fprintf (dump_file
, " the sum of counts of redirected edges is ");
3837 redirected_sum
.dump (dump_file
);
3838 fprintf (dump_file
, "\n");
3840 if (!(orig_node_count
> profile_count::zero ()))
3843 gcc_assert (orig_node_count
>= redirected_sum
);
3845 new_node_count
= new_node
->count
;
3846 new_node
->count
+= redirected_sum
;
3847 orig_node
->count
-= redirected_sum
;
3849 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3850 cs
->count
+= cs
->count
.apply_scale (redirected_sum
, new_node_count
);
3852 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3854 profile_count dec
= cs
->count
.apply_scale (redirected_sum
,
3860 dump_profile_updates (orig_node
, new_node
);
3863 /* Return true if we would like to remove a parameter from NODE when cloning it
3864 with KNOWN_CSTS scalar constants. */
3867 want_remove_some_param_p (cgraph_node
*node
, vec
<tree
> known_csts
)
3869 auto_vec
<bool, 16> surviving
;
3870 bool filled_vec
= false;
3871 ipa_node_params
*info
= IPA_NODE_REF (node
);
3872 int i
, count
= ipa_get_param_count (info
);
3874 for (i
= 0; i
< count
; i
++)
3876 if (!known_csts
[i
] && ipa_is_param_used (info
, i
))
3881 if (!node
->clone
.param_adjustments
)
3883 node
->clone
.param_adjustments
->get_surviving_params (&surviving
);
3886 if (surviving
.length() < (unsigned) i
&& surviving
[i
])
3892 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3893 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3894 redirect all edges in CALLERS to it. */
3896 static struct cgraph_node
*
3897 create_specialized_node (struct cgraph_node
*node
,
3898 vec
<tree
> known_csts
,
3899 vec
<ipa_polymorphic_call_context
> known_contexts
,
3900 struct ipa_agg_replacement_value
*aggvals
,
3901 vec
<cgraph_edge
*> callers
)
3903 class ipa_node_params
*new_info
, *info
= IPA_NODE_REF (node
);
3904 vec
<ipa_replace_map
*, va_gc
> *replace_trees
= NULL
;
3905 vec
<ipa_adjusted_param
, va_gc
> *new_params
= NULL
;
3906 struct ipa_agg_replacement_value
*av
;
3907 struct cgraph_node
*new_node
;
3908 int i
, count
= ipa_get_param_count (info
);
3909 ipa_param_adjustments
*old_adjustments
= node
->clone
.param_adjustments
;
3910 ipa_param_adjustments
*new_adjustments
;
3911 gcc_assert (!info
->ipcp_orig_node
);
3912 gcc_assert (node
->can_change_signature
3913 || !old_adjustments
);
3915 if (old_adjustments
)
3917 /* At the moment all IPA optimizations should use the number of
3918 parameters of the prevailing decl as the m_always_copy_start.
3919 Handling any other value would complicate the code below, so for the
3920 time bing let's only assert it is so. */
3921 gcc_assert (old_adjustments
->m_always_copy_start
== count
3922 || old_adjustments
->m_always_copy_start
< 0);
3923 int old_adj_count
= vec_safe_length (old_adjustments
->m_adj_params
);
3924 for (i
= 0; i
< old_adj_count
; i
++)
3926 ipa_adjusted_param
*old_adj
= &(*old_adjustments
->m_adj_params
)[i
];
3927 if (!node
->can_change_signature
3928 || old_adj
->op
!= IPA_PARAM_OP_COPY
3929 || (!known_csts
[old_adj
->base_index
]
3930 && ipa_is_param_used (info
, old_adj
->base_index
)))
3932 ipa_adjusted_param new_adj
= *old_adj
;
3934 new_adj
.prev_clone_adjustment
= true;
3935 new_adj
.prev_clone_index
= i
;
3936 vec_safe_push (new_params
, new_adj
);
3939 bool skip_return
= old_adjustments
->m_skip_return
;
3940 new_adjustments
= (new (ggc_alloc
<ipa_param_adjustments
> ())
3941 ipa_param_adjustments (new_params
, count
,
3944 else if (node
->can_change_signature
3945 && want_remove_some_param_p (node
, known_csts
))
3947 ipa_adjusted_param adj
;
3948 memset (&adj
, 0, sizeof (adj
));
3949 adj
.op
= IPA_PARAM_OP_COPY
;
3950 for (i
= 0; i
< count
; i
++)
3951 if (!known_csts
[i
] && ipa_is_param_used (info
, i
))
3954 adj
.prev_clone_index
= i
;
3955 vec_safe_push (new_params
, adj
);
3957 new_adjustments
= (new (ggc_alloc
<ipa_param_adjustments
> ())
3958 ipa_param_adjustments (new_params
, count
, false));
3961 new_adjustments
= NULL
;
3963 replace_trees
= vec_safe_copy (node
->clone
.tree_map
);
3964 for (i
= 0; i
< count
; i
++)
3966 tree t
= known_csts
[i
];
3969 struct ipa_replace_map
*replace_map
;
3971 gcc_checking_assert (TREE_CODE (t
) != TREE_BINFO
);
3972 replace_map
= get_replacement_map (info
, t
, i
);
3974 vec_safe_push (replace_trees
, replace_map
);
3977 auto_vec
<cgraph_edge
*, 2> self_recursive_calls
;
3978 for (i
= callers
.length () - 1; i
>= 0; i
--)
3980 cgraph_edge
*cs
= callers
[i
];
3981 if (cs
->caller
== node
)
3983 self_recursive_calls
.safe_push (cs
);
3984 callers
.unordered_remove (i
);
3988 unsigned &suffix_counter
= clone_num_suffixes
->get_or_insert (
3989 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
3991 new_node
= node
->create_virtual_clone (callers
, replace_trees
,
3992 new_adjustments
, "constprop",
3996 bool have_self_recursive_calls
= !self_recursive_calls
.is_empty ();
3997 for (unsigned j
= 0; j
< self_recursive_calls
.length (); j
++)
3999 cgraph_edge
*cs
= get_next_cgraph_edge_clone (self_recursive_calls
[j
]);
4000 /* Cloned edges can disappear during cloning as speculation can be
4001 resolved, check that we have one and that it comes from the last
4003 if (cs
&& cs
->caller
== new_node
)
4004 cs
->redirect_callee_duplicating_thunks (new_node
);
4005 /* Any future code that would make more than one clone of an outgoing
4006 edge would confuse this mechanism, so let's check that does not
4008 gcc_checking_assert (!cs
4009 || !get_next_cgraph_edge_clone (cs
)
4010 || get_next_cgraph_edge_clone (cs
)->caller
!= new_node
);
4012 if (have_self_recursive_calls
)
4013 new_node
->expand_all_artificial_thunks ();
4015 ipa_set_node_agg_value_chain (new_node
, aggvals
);
4016 for (av
= aggvals
; av
; av
= av
->next
)
4017 new_node
->maybe_create_reference (av
->value
, NULL
);
4019 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4021 fprintf (dump_file
, " the new node is %s.\n", new_node
->dump_name ());
4022 if (known_contexts
.exists ())
4024 for (i
= 0; i
< count
; i
++)
4025 if (!known_contexts
[i
].useless_p ())
4027 fprintf (dump_file
, " known ctx %i is ", i
);
4028 known_contexts
[i
].dump (dump_file
);
4032 ipa_dump_agg_replacement_values (dump_file
, aggvals
);
4034 ipa_check_create_node_params ();
4035 update_profiling_info (node
, new_node
);
4036 new_info
= IPA_NODE_REF (new_node
);
4037 new_info
->ipcp_orig_node
= node
;
4038 new_node
->ipcp_clone
= true;
4039 new_info
->known_csts
= known_csts
;
4040 new_info
->known_contexts
= known_contexts
;
4042 ipcp_discover_new_direct_edges (new_node
, known_csts
, known_contexts
, aggvals
);
4048 /* Return true, if JFUNC, which describes a i-th parameter of call CS, is a
4049 simple no-operation pass-through function to itself. */
4052 self_recursive_pass_through_p (cgraph_edge
*cs
, ipa_jump_func
*jfunc
, int i
)
4054 enum availability availability
;
4055 if (cs
->caller
== cs
->callee
->function_symbol (&availability
)
4056 && availability
> AVAIL_INTERPOSABLE
4057 && jfunc
->type
== IPA_JF_PASS_THROUGH
4058 && ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
4059 && ipa_get_jf_pass_through_formal_id (jfunc
) == i
)
4064 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
4065 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
4068 find_more_scalar_values_for_callers_subset (struct cgraph_node
*node
,
4069 vec
<tree
> known_csts
,
4070 vec
<cgraph_edge
*> callers
)
4072 class ipa_node_params
*info
= IPA_NODE_REF (node
);
4073 int i
, count
= ipa_get_param_count (info
);
4075 for (i
= 0; i
< count
; i
++)
4077 struct cgraph_edge
*cs
;
4078 tree newval
= NULL_TREE
;
4081 tree type
= ipa_get_type (info
, i
);
4083 if (ipa_get_scalar_lat (info
, i
)->bottom
|| known_csts
[i
])
4086 FOR_EACH_VEC_ELT (callers
, j
, cs
)
4088 struct ipa_jump_func
*jump_func
;
4091 if (IPA_NODE_REF (cs
->caller
)->node_dead
)
4094 if (!IPA_EDGE_REF (cs
)
4095 || i
>= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
))
4097 && call_passes_through_thunk_p (cs
)))
4102 jump_func
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
), i
);
4103 if (self_recursive_pass_through_p (cs
, jump_func
, i
))
4106 t
= ipa_value_from_jfunc (IPA_NODE_REF (cs
->caller
), jump_func
, type
);
4109 && !values_equal_for_ipcp_p (t
, newval
))
4110 || (!first
&& !newval
))
4122 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4124 fprintf (dump_file
, " adding an extra known scalar value ");
4125 print_ipcp_constant_value (dump_file
, newval
);
4126 fprintf (dump_file
, " for ");
4127 ipa_dump_param (dump_file
, info
, i
);
4128 fprintf (dump_file
, "\n");
4131 known_csts
[i
] = newval
;
4136 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
4137 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
4141 find_more_contexts_for_caller_subset (cgraph_node
*node
,
4142 vec
<ipa_polymorphic_call_context
>
4144 vec
<cgraph_edge
*> callers
)
4146 ipa_node_params
*info
= IPA_NODE_REF (node
);
4147 int i
, count
= ipa_get_param_count (info
);
4149 for (i
= 0; i
< count
; i
++)
4153 if (ipa_get_poly_ctx_lat (info
, i
)->bottom
4154 || (known_contexts
->exists ()
4155 && !(*known_contexts
)[i
].useless_p ()))
4158 ipa_polymorphic_call_context newval
;
4162 FOR_EACH_VEC_ELT (callers
, j
, cs
)
4164 if (!IPA_EDGE_REF (cs
)
4165 || i
>= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
)))
4167 ipa_jump_func
*jfunc
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
),
4169 ipa_polymorphic_call_context ctx
;
4170 ctx
= ipa_context_from_jfunc (IPA_NODE_REF (cs
->caller
), cs
, i
,
4178 newval
.meet_with (ctx
);
4179 if (newval
.useless_p ())
4183 if (!newval
.useless_p ())
4185 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4187 fprintf (dump_file
, " adding an extra known polymorphic "
4189 print_ipcp_constant_value (dump_file
, newval
);
4190 fprintf (dump_file
, " for ");
4191 ipa_dump_param (dump_file
, info
, i
);
4192 fprintf (dump_file
, "\n");
4195 if (!known_contexts
->exists ())
4196 known_contexts
->safe_grow_cleared (ipa_get_param_count (info
));
4197 (*known_contexts
)[i
] = newval
;
4203 /* Go through PLATS and create a vector of values consisting of values and
4204 offsets (minus OFFSET) of lattices that contain only a single value. */
4206 static vec
<ipa_agg_jf_item
>
4207 copy_plats_to_inter (class ipcp_param_lattices
*plats
, HOST_WIDE_INT offset
)
4209 vec
<ipa_agg_jf_item
> res
= vNULL
;
4211 if (!plats
->aggs
|| plats
->aggs_contain_variable
|| plats
->aggs_bottom
)
4214 for (struct ipcp_agg_lattice
*aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
4215 if (aglat
->is_single_const ())
4217 struct ipa_agg_jf_item ti
;
4218 ti
.offset
= aglat
->offset
- offset
;
4219 ti
.value
= aglat
->values
->value
;
4225 /* Intersect all values in INTER with single value lattices in PLATS (while
4226 subtracting OFFSET). */
4229 intersect_with_plats (class ipcp_param_lattices
*plats
,
4230 vec
<ipa_agg_jf_item
> *inter
,
4231 HOST_WIDE_INT offset
)
4233 struct ipcp_agg_lattice
*aglat
;
4234 struct ipa_agg_jf_item
*item
;
4237 if (!plats
->aggs
|| plats
->aggs_contain_variable
|| plats
->aggs_bottom
)
4243 aglat
= plats
->aggs
;
4244 FOR_EACH_VEC_ELT (*inter
, k
, item
)
4251 if (aglat
->offset
- offset
> item
->offset
)
4253 if (aglat
->offset
- offset
== item
->offset
)
4255 gcc_checking_assert (item
->value
);
4256 if (aglat
->is_single_const ()
4257 && values_equal_for_ipcp_p (item
->value
,
4258 aglat
->values
->value
))
4262 aglat
= aglat
->next
;
4265 item
->value
= NULL_TREE
;
4269 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the
4270 vector result while subtracting OFFSET from the individual value offsets. */
4272 static vec
<ipa_agg_jf_item
>
4273 agg_replacements_to_vector (struct cgraph_node
*node
, int index
,
4274 HOST_WIDE_INT offset
)
4276 struct ipa_agg_replacement_value
*av
;
4277 vec
<ipa_agg_jf_item
> res
= vNULL
;
4279 for (av
= ipa_get_agg_replacements_for_node (node
); av
; av
= av
->next
)
4280 if (av
->index
== index
4281 && (av
->offset
- offset
) >= 0)
4283 struct ipa_agg_jf_item item
;
4284 gcc_checking_assert (av
->value
);
4285 item
.offset
= av
->offset
- offset
;
4286 item
.value
= av
->value
;
4287 res
.safe_push (item
);
4293 /* Intersect all values in INTER with those that we have already scheduled to
4294 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
4295 (while subtracting OFFSET). */
4298 intersect_with_agg_replacements (struct cgraph_node
*node
, int index
,
4299 vec
<ipa_agg_jf_item
> *inter
,
4300 HOST_WIDE_INT offset
)
4302 struct ipa_agg_replacement_value
*srcvals
;
4303 struct ipa_agg_jf_item
*item
;
4306 srcvals
= ipa_get_agg_replacements_for_node (node
);
4313 FOR_EACH_VEC_ELT (*inter
, i
, item
)
4315 struct ipa_agg_replacement_value
*av
;
4319 for (av
= srcvals
; av
; av
= av
->next
)
4321 gcc_checking_assert (av
->value
);
4322 if (av
->index
== index
4323 && av
->offset
- offset
== item
->offset
)
4325 if (values_equal_for_ipcp_p (item
->value
, av
->value
))
4331 item
->value
= NULL_TREE
;
4335 /* Intersect values in INTER with aggregate values that come along edge CS to
4336 parameter number INDEX and return it. If INTER does not actually exist yet,
4337 copy all incoming values to it. If we determine we ended up with no values
4338 whatsoever, return a released vector. */
4340 static vec
<ipa_agg_jf_item
>
4341 intersect_aggregates_with_edge (struct cgraph_edge
*cs
, int index
,
4342 vec
<ipa_agg_jf_item
> inter
)
4344 struct ipa_jump_func
*jfunc
;
4345 jfunc
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
), index
);
4346 if (jfunc
->type
== IPA_JF_PASS_THROUGH
4347 && ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
4349 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
4350 int src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
4352 if (caller_info
->ipcp_orig_node
)
4354 struct cgraph_node
*orig_node
= caller_info
->ipcp_orig_node
;
4355 class ipcp_param_lattices
*orig_plats
;
4356 orig_plats
= ipa_get_parm_lattices (IPA_NODE_REF (orig_node
),
4358 if (agg_pass_through_permissible_p (orig_plats
, jfunc
))
4360 if (!inter
.exists ())
4361 inter
= agg_replacements_to_vector (cs
->caller
, src_idx
, 0);
4363 intersect_with_agg_replacements (cs
->caller
, src_idx
,
4374 class ipcp_param_lattices
*src_plats
;
4375 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
4376 if (agg_pass_through_permissible_p (src_plats
, jfunc
))
4378 /* Currently we do not produce clobber aggregate jump
4379 functions, adjust when we do. */
4380 gcc_checking_assert (!jfunc
->agg
.items
);
4381 if (!inter
.exists ())
4382 inter
= copy_plats_to_inter (src_plats
, 0);
4384 intersect_with_plats (src_plats
, &inter
, 0);
4393 else if (jfunc
->type
== IPA_JF_ANCESTOR
4394 && ipa_get_jf_ancestor_agg_preserved (jfunc
))
4396 class ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
4397 int src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
4398 class ipcp_param_lattices
*src_plats
;
4399 HOST_WIDE_INT delta
= ipa_get_jf_ancestor_offset (jfunc
);
4401 if (caller_info
->ipcp_orig_node
)
4403 if (!inter
.exists ())
4404 inter
= agg_replacements_to_vector (cs
->caller
, src_idx
, delta
);
4406 intersect_with_agg_replacements (cs
->caller
, src_idx
, &inter
,
4411 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
4412 /* Currently we do not produce clobber aggregate jump
4413 functions, adjust when we do. */
4414 gcc_checking_assert (!src_plats
->aggs
|| !jfunc
->agg
.items
);
4415 if (!inter
.exists ())
4416 inter
= copy_plats_to_inter (src_plats
, delta
);
4418 intersect_with_plats (src_plats
, &inter
, delta
);
4421 else if (jfunc
->agg
.items
)
4423 struct ipa_agg_jf_item
*item
;
4426 if (!inter
.exists ())
4427 for (unsigned i
= 0; i
< jfunc
->agg
.items
->length (); i
++)
4428 inter
.safe_push ((*jfunc
->agg
.items
)[i
]);
4430 FOR_EACH_VEC_ELT (inter
, k
, item
)
4438 while ((unsigned) l
< jfunc
->agg
.items
->length ())
4440 struct ipa_agg_jf_item
*ti
;
4441 ti
= &(*jfunc
->agg
.items
)[l
];
4442 if (ti
->offset
> item
->offset
)
4444 if (ti
->offset
== item
->offset
)
4446 gcc_checking_assert (ti
->value
);
4447 if (values_equal_for_ipcp_p (item
->value
,
4461 return vec
<ipa_agg_jf_item
>();
4466 /* Look at edges in CALLERS and collect all known aggregate values that arrive
4467 from all of them. */
4469 static struct ipa_agg_replacement_value
*
4470 find_aggregate_values_for_callers_subset (struct cgraph_node
*node
,
4471 vec
<cgraph_edge
*> callers
)
4473 class ipa_node_params
*dest_info
= IPA_NODE_REF (node
);
4474 struct ipa_agg_replacement_value
*res
;
4475 struct ipa_agg_replacement_value
**tail
= &res
;
4476 struct cgraph_edge
*cs
;
4477 int i
, j
, count
= ipa_get_param_count (dest_info
);
4479 FOR_EACH_VEC_ELT (callers
, j
, cs
)
4481 if (!IPA_EDGE_REF (cs
))
4486 int c
= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
));
4491 for (i
= 0; i
< count
; i
++)
4493 struct cgraph_edge
*cs
;
4494 vec
<ipa_agg_jf_item
> inter
= vNULL
;
4495 struct ipa_agg_jf_item
*item
;
4496 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (dest_info
, i
);
4499 /* Among other things, the following check should deal with all by_ref
4501 if (plats
->aggs_bottom
)
4504 FOR_EACH_VEC_ELT (callers
, j
, cs
)
4506 struct ipa_jump_func
*jfunc
4507 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs
), i
);
4508 if (self_recursive_pass_through_p (cs
, jfunc
, i
)
4509 && (!plats
->aggs_by_ref
4510 || ipa_get_jf_pass_through_agg_preserved (jfunc
)))
4512 inter
= intersect_aggregates_with_edge (cs
, i
, inter
);
4514 if (!inter
.exists ())
4518 FOR_EACH_VEC_ELT (inter
, j
, item
)
4520 struct ipa_agg_replacement_value
*v
;
4525 v
= ggc_alloc
<ipa_agg_replacement_value
> ();
4527 v
->offset
= item
->offset
;
4528 v
->value
= item
->value
;
4529 v
->by_ref
= plats
->aggs_by_ref
;
4535 if (inter
.exists ())
4542 /* Determine whether CS also brings all scalar values that the NODE is
4546 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge
*cs
,
4547 struct cgraph_node
*node
)
4549 class ipa_node_params
*dest_info
= IPA_NODE_REF (node
);
4550 int count
= ipa_get_param_count (dest_info
);
4551 class ipa_node_params
*caller_info
;
4552 class ipa_edge_args
*args
;
4555 caller_info
= IPA_NODE_REF (cs
->caller
);
4556 args
= IPA_EDGE_REF (cs
);
4557 for (i
= 0; i
< count
; i
++)
4559 struct ipa_jump_func
*jump_func
;
4562 val
= dest_info
->known_csts
[i
];
4566 if (i
>= ipa_get_cs_argument_count (args
))
4568 jump_func
= ipa_get_ith_jump_func (args
, i
);
4569 t
= ipa_value_from_jfunc (caller_info
, jump_func
,
4570 ipa_get_type (dest_info
, i
));
4571 if (!t
|| !values_equal_for_ipcp_p (val
, t
))
4577 /* Determine whether CS also brings all aggregate values that NODE is
4580 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge
*cs
,
4581 struct cgraph_node
*node
)
4583 class ipa_node_params
*orig_node_info
;
4584 struct ipa_agg_replacement_value
*aggval
;
4587 aggval
= ipa_get_agg_replacements_for_node (node
);
4591 count
= ipa_get_param_count (IPA_NODE_REF (node
));
4592 ec
= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
));
4594 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
4595 if (aggval
->index
>= ec
)
4598 orig_node_info
= IPA_NODE_REF (IPA_NODE_REF (node
)->ipcp_orig_node
);
4600 for (i
= 0; i
< count
; i
++)
4602 static vec
<ipa_agg_jf_item
> values
= vec
<ipa_agg_jf_item
>();
4603 class ipcp_param_lattices
*plats
;
4604 bool interesting
= false;
4605 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
4606 if (aggval
->index
== i
)
4614 plats
= ipa_get_parm_lattices (orig_node_info
, aggval
->index
);
4615 if (plats
->aggs_bottom
)
4618 values
= intersect_aggregates_with_edge (cs
, i
, values
);
4619 if (!values
.exists ())
4622 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
4623 if (aggval
->index
== i
)
4625 struct ipa_agg_jf_item
*item
;
4628 FOR_EACH_VEC_ELT (values
, j
, item
)
4630 && item
->offset
== av
->offset
4631 && values_equal_for_ipcp_p (item
->value
, av
->value
))
4646 /* Given an original NODE and a VAL for which we have already created a
4647 specialized clone, look whether there are incoming edges that still lead
4648 into the old node but now also bring the requested value and also conform to
4649 all other criteria such that they can be redirected the special node.
4650 This function can therefore redirect the final edge in a SCC. */
4652 template <typename valtype
>
4654 perhaps_add_new_callers (cgraph_node
*node
, ipcp_value
<valtype
> *val
)
4656 ipcp_value_source
<valtype
> *src
;
4657 profile_count redirected_sum
= profile_count::zero ();
4659 for (src
= val
->sources
; src
; src
= src
->next
)
4661 struct cgraph_edge
*cs
= src
->cs
;
4664 if (cgraph_edge_brings_value_p (cs
, src
, node
, val
)
4665 && cgraph_edge_brings_all_scalars_for_node (cs
, val
->spec_node
)
4666 && cgraph_edge_brings_all_agg_vals_for_node (cs
, val
->spec_node
))
4669 fprintf (dump_file
, " - adding an extra caller %s of %s\n",
4670 cs
->caller
->dump_name (),
4671 val
->spec_node
->dump_name ());
4673 cs
->redirect_callee_duplicating_thunks (val
->spec_node
);
4674 val
->spec_node
->expand_all_artificial_thunks ();
4675 if (cs
->count
.ipa ().initialized_p ())
4676 redirected_sum
= redirected_sum
+ cs
->count
.ipa ();
4678 cs
= get_next_cgraph_edge_clone (cs
);
4682 if (redirected_sum
.nonzero_p ())
4683 update_specialized_profile (val
->spec_node
, node
, redirected_sum
);
4686 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4689 known_contexts_useful_p (vec
<ipa_polymorphic_call_context
> known_contexts
)
4691 ipa_polymorphic_call_context
*ctx
;
4694 FOR_EACH_VEC_ELT (known_contexts
, i
, ctx
)
4695 if (!ctx
->useless_p ())
4700 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4702 static vec
<ipa_polymorphic_call_context
>
4703 copy_useful_known_contexts (vec
<ipa_polymorphic_call_context
> known_contexts
)
4705 if (known_contexts_useful_p (known_contexts
))
4706 return known_contexts
.copy ();
4711 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4712 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4715 modify_known_vectors_with_val (vec
<tree
> *known_csts
,
4716 vec
<ipa_polymorphic_call_context
> *known_contexts
,
4717 ipcp_value
<tree
> *val
,
4720 *known_csts
= known_csts
->copy ();
4721 *known_contexts
= copy_useful_known_contexts (*known_contexts
);
4722 (*known_csts
)[index
] = val
->value
;
4725 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4726 copy according to VAL and INDEX. */
4729 modify_known_vectors_with_val (vec
<tree
> *known_csts
,
4730 vec
<ipa_polymorphic_call_context
> *known_contexts
,
4731 ipcp_value
<ipa_polymorphic_call_context
> *val
,
4734 *known_csts
= known_csts
->copy ();
4735 *known_contexts
= known_contexts
->copy ();
4736 (*known_contexts
)[index
] = val
->value
;
4739 /* Return true if OFFSET indicates this was not an aggregate value or there is
4740 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4744 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value
*aggvals
,
4745 int index
, HOST_WIDE_INT offset
, tree value
)
4752 if (aggvals
->index
== index
4753 && aggvals
->offset
== offset
4754 && values_equal_for_ipcp_p (aggvals
->value
, value
))
4756 aggvals
= aggvals
->next
;
4761 /* Return true if offset is minus one because source of a polymorphic context
4762 cannot be an aggregate value. */
4765 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value
*,
4766 int , HOST_WIDE_INT offset
,
4767 ipa_polymorphic_call_context
)
4769 return offset
== -1;
4772 /* Decide whether to create a special version of NODE for value VAL of parameter
4773 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4774 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4775 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4777 template <typename valtype
>
4779 decide_about_value (struct cgraph_node
*node
, int index
, HOST_WIDE_INT offset
,
4780 ipcp_value
<valtype
> *val
, vec
<tree
> known_csts
,
4781 vec
<ipa_polymorphic_call_context
> known_contexts
)
4783 struct ipa_agg_replacement_value
*aggvals
;
4784 int freq_sum
, caller_count
;
4785 profile_count count_sum
;
4786 vec
<cgraph_edge
*> callers
;
4790 perhaps_add_new_callers (node
, val
);
4793 else if (val
->local_size_cost
+ overall_size
> max_new_size
)
4795 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4796 fprintf (dump_file
, " Ignoring candidate value because "
4797 "max_new_size would be reached with %li.\n",
4798 val
->local_size_cost
+ overall_size
);
4801 else if (!get_info_about_necessary_edges (val
, node
, &freq_sum
, &count_sum
,
4805 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4807 fprintf (dump_file
, " - considering value ");
4808 print_ipcp_constant_value (dump_file
, val
->value
);
4809 fprintf (dump_file
, " for ");
4810 ipa_dump_param (dump_file
, IPA_NODE_REF (node
), index
);
4812 fprintf (dump_file
, ", offset: " HOST_WIDE_INT_PRINT_DEC
, offset
);
4813 fprintf (dump_file
, " (caller_count: %i)\n", caller_count
);
4816 if (!good_cloning_opportunity_p (node
, val
->local_time_benefit
,
4817 freq_sum
, count_sum
,
4818 val
->local_size_cost
)
4819 && !good_cloning_opportunity_p (node
,
4820 val
->local_time_benefit
4821 + val
->prop_time_benefit
,
4822 freq_sum
, count_sum
,
4823 val
->local_size_cost
4824 + val
->prop_size_cost
))
4828 fprintf (dump_file
, " Creating a specialized node of %s.\n",
4829 node
->dump_name ());
4831 callers
= gather_edges_for_value (val
, node
, caller_count
);
4833 modify_known_vectors_with_val (&known_csts
, &known_contexts
, val
, index
);
4836 known_csts
= known_csts
.copy ();
4837 known_contexts
= copy_useful_known_contexts (known_contexts
);
4839 find_more_scalar_values_for_callers_subset (node
, known_csts
, callers
);
4840 find_more_contexts_for_caller_subset (node
, &known_contexts
, callers
);
4841 aggvals
= find_aggregate_values_for_callers_subset (node
, callers
);
4842 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals
, index
,
4843 offset
, val
->value
));
4844 val
->spec_node
= create_specialized_node (node
, known_csts
, known_contexts
,
4846 overall_size
+= val
->local_size_cost
;
4848 /* TODO: If for some lattice there is only one other known value
4849 left, make a special node for it too. */
4854 /* Decide whether and what specialized clones of NODE should be created. */
4857 decide_whether_version_node (struct cgraph_node
*node
)
4859 class ipa_node_params
*info
= IPA_NODE_REF (node
);
4860 int i
, count
= ipa_get_param_count (info
);
4861 vec
<tree
> known_csts
;
4862 vec
<ipa_polymorphic_call_context
> known_contexts
;
4863 vec
<ipa_agg_jump_function
> known_aggs
= vNULL
;
4869 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4870 fprintf (dump_file
, "\nEvaluating opportunities for %s.\n",
4871 node
->dump_name ());
4873 gather_context_independent_values (info
, &known_csts
, &known_contexts
,
4874 info
->do_clone_for_all_contexts
? &known_aggs
4877 for (i
= 0; i
< count
;i
++)
4879 class ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
4880 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
4881 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
4886 ipcp_value
<tree
> *val
;
4887 for (val
= lat
->values
; val
; val
= val
->next
)
4888 ret
|= decide_about_value (node
, i
, -1, val
, known_csts
,
4892 if (!plats
->aggs_bottom
)
4894 struct ipcp_agg_lattice
*aglat
;
4895 ipcp_value
<tree
> *val
;
4896 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
4897 if (!aglat
->bottom
&& aglat
->values
4898 /* If the following is false, the one value is in
4900 && (plats
->aggs_contain_variable
4901 || !aglat
->is_single_const ()))
4902 for (val
= aglat
->values
; val
; val
= val
->next
)
4903 ret
|= decide_about_value (node
, i
, aglat
->offset
, val
,
4904 known_csts
, known_contexts
);
4908 && known_contexts
[i
].useless_p ())
4910 ipcp_value
<ipa_polymorphic_call_context
> *val
;
4911 for (val
= ctxlat
->values
; val
; val
= val
->next
)
4912 ret
|= decide_about_value (node
, i
, -1, val
, known_csts
,
4916 info
= IPA_NODE_REF (node
);
4919 if (info
->do_clone_for_all_contexts
)
4921 struct cgraph_node
*clone
;
4922 vec
<cgraph_edge
*> callers
;
4925 fprintf (dump_file
, " - Creating a specialized node of %s "
4926 "for all known contexts.\n", node
->dump_name ());
4928 callers
= node
->collect_callers ();
4929 find_more_scalar_values_for_callers_subset (node
, known_csts
, callers
);
4930 find_more_contexts_for_caller_subset (node
, &known_contexts
, callers
);
4931 ipa_agg_replacement_value
*aggvals
4932 = find_aggregate_values_for_callers_subset (node
, callers
);
4934 if (!known_contexts_useful_p (known_contexts
))
4936 known_contexts
.release ();
4937 known_contexts
= vNULL
;
4939 clone
= create_specialized_node (node
, known_csts
, known_contexts
,
4941 info
= IPA_NODE_REF (node
);
4942 info
->do_clone_for_all_contexts
= false;
4943 IPA_NODE_REF (clone
)->is_all_contexts_clone
= true;
4944 for (i
= 0; i
< count
; i
++)
4945 vec_free (known_aggs
[i
].items
);
4946 known_aggs
.release ();
4951 known_csts
.release ();
4952 known_contexts
.release ();
4958 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4961 spread_undeadness (struct cgraph_node
*node
)
4963 struct cgraph_edge
*cs
;
4965 for (cs
= node
->callees
; cs
; cs
= cs
->next_callee
)
4966 if (ipa_edge_within_scc (cs
))
4968 struct cgraph_node
*callee
;
4969 class ipa_node_params
*info
;
4971 callee
= cs
->callee
->function_symbol (NULL
);
4972 info
= IPA_NODE_REF (callee
);
4974 if (info
->node_dead
)
4976 info
->node_dead
= 0;
4977 spread_undeadness (callee
);
4982 /* Return true if NODE has a caller from outside of its SCC that is not
4983 dead. Worker callback for cgraph_for_node_and_aliases. */
4986 has_undead_caller_from_outside_scc_p (struct cgraph_node
*node
,
4987 void *data ATTRIBUTE_UNUSED
)
4989 struct cgraph_edge
*cs
;
4991 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
4992 if (cs
->caller
->thunk
.thunk_p
4993 && cs
->caller
->call_for_symbol_thunks_and_aliases
4994 (has_undead_caller_from_outside_scc_p
, NULL
, true))
4996 else if (!ipa_edge_within_scc (cs
)
4997 && !IPA_NODE_REF (cs
->caller
)->node_dead
)
5003 /* Identify nodes within the same SCC as NODE which are no longer needed
5004 because of new clones and will be removed as unreachable. */
5007 identify_dead_nodes (struct cgraph_node
*node
)
5009 struct cgraph_node
*v
;
5010 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
5012 && !v
->call_for_symbol_thunks_and_aliases
5013 (has_undead_caller_from_outside_scc_p
, NULL
, true))
5014 IPA_NODE_REF (v
)->node_dead
= 1;
5016 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
5017 if (!IPA_NODE_REF (v
)->node_dead
)
5018 spread_undeadness (v
);
5020 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
5022 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
5023 if (IPA_NODE_REF (v
)->node_dead
)
5024 fprintf (dump_file
, " Marking node as dead: %s.\n", v
->dump_name ());
5028 /* The decision stage. Iterate over the topological order of call graph nodes
5029 TOPO and make specialized clones if deemed beneficial. */
5032 ipcp_decision_stage (class ipa_topo_info
*topo
)
5037 fprintf (dump_file
, "\nIPA decision stage:\n\n");
5039 for (i
= topo
->nnodes
- 1; i
>= 0; i
--)
5041 struct cgraph_node
*node
= topo
->order
[i
];
5042 bool change
= false, iterate
= true;
5046 struct cgraph_node
*v
;
5048 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
5049 if (v
->has_gimple_body_p ()
5050 && ipcp_versionable_function_p (v
))
5051 iterate
|= decide_whether_version_node (v
);
5056 identify_dead_nodes (node
);
5060 /* Look up all the bits information that we have discovered and copy it over
5061 to the transformation summary. */
5064 ipcp_store_bits_results (void)
5068 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
5070 ipa_node_params
*info
= IPA_NODE_REF (node
);
5071 bool dumped_sth
= false;
5072 bool found_useful_result
= false;
5074 if (!opt_for_fn (node
->decl
, flag_ipa_bit_cp
) || !info
)
5077 fprintf (dump_file
, "Not considering %s for ipa bitwise propagation "
5078 "; -fipa-bit-cp: disabled.\n",
5083 if (info
->ipcp_orig_node
)
5084 info
= IPA_NODE_REF (info
->ipcp_orig_node
);
5086 unsigned count
= ipa_get_param_count (info
);
5087 for (unsigned i
= 0; i
< count
; i
++)
5089 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
5090 if (plats
->bits_lattice
.constant_p ())
5092 found_useful_result
= true;
5097 if (!found_useful_result
)
5100 ipcp_transformation_initialize ();
5101 ipcp_transformation
*ts
= ipcp_transformation_sum
->get_create (node
);
5102 vec_safe_reserve_exact (ts
->bits
, count
);
5104 for (unsigned i
= 0; i
< count
; i
++)
5106 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
5109 if (plats
->bits_lattice
.constant_p ())
5111 = ipa_get_ipa_bits_for_value (plats
->bits_lattice
.get_value (),
5112 plats
->bits_lattice
.get_mask ());
5116 ts
->bits
->quick_push (jfbits
);
5117 if (!dump_file
|| !jfbits
)
5121 fprintf (dump_file
, "Propagated bits info for function %s:\n",
5122 node
->dump_name ());
5125 fprintf (dump_file
, " param %i: value = ", i
);
5126 print_hex (jfbits
->value
, dump_file
);
5127 fprintf (dump_file
, ", mask = ");
5128 print_hex (jfbits
->mask
, dump_file
);
5129 fprintf (dump_file
, "\n");
5134 /* Look up all VR information that we have discovered and copy it over
5135 to the transformation summary. */
5138 ipcp_store_vr_results (void)
5142 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
5144 ipa_node_params
*info
= IPA_NODE_REF (node
);
5145 bool found_useful_result
= false;
5147 if (!opt_for_fn (node
->decl
, flag_ipa_vrp
))
5150 fprintf (dump_file
, "Not considering %s for VR discovery "
5151 "and propagate; -fipa-ipa-vrp: disabled.\n",
5156 if (info
->ipcp_orig_node
)
5157 info
= IPA_NODE_REF (info
->ipcp_orig_node
);
5159 unsigned count
= ipa_get_param_count (info
);
5160 for (unsigned i
= 0; i
< count
; i
++)
5162 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
5163 if (!plats
->m_value_range
.bottom_p ()
5164 && !plats
->m_value_range
.top_p ())
5166 found_useful_result
= true;
5170 if (!found_useful_result
)
5173 ipcp_transformation_initialize ();
5174 ipcp_transformation
*ts
= ipcp_transformation_sum
->get_create (node
);
5175 vec_safe_reserve_exact (ts
->m_vr
, count
);
5177 for (unsigned i
= 0; i
< count
; i
++)
5179 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
5182 if (!plats
->m_value_range
.bottom_p ()
5183 && !plats
->m_value_range
.top_p ())
5186 vr
.type
= plats
->m_value_range
.m_vr
.kind ();
5187 vr
.min
= wi::to_wide (plats
->m_value_range
.m_vr
.min ());
5188 vr
.max
= wi::to_wide (plats
->m_value_range
.m_vr
.max ());
5193 vr
.type
= VR_VARYING
;
5194 vr
.min
= vr
.max
= wi::zero (INT_TYPE_SIZE
);
5196 ts
->m_vr
->quick_push (vr
);
5201 /* The IPCP driver. */
5206 class ipa_topo_info topo
;
5208 if (edge_clone_summaries
== NULL
)
5209 edge_clone_summaries
= new edge_clone_summary_t (symtab
);
5211 ipa_check_create_node_params ();
5212 ipa_check_create_edge_args ();
5213 clone_num_suffixes
= new hash_map
<const char *, unsigned>;
5217 fprintf (dump_file
, "\nIPA structures before propagation:\n");
5218 if (dump_flags
& TDF_DETAILS
)
5219 ipa_print_all_params (dump_file
);
5220 ipa_print_all_jump_functions (dump_file
);
5223 /* Topological sort. */
5224 build_toporder_info (&topo
);
5225 /* Do the interprocedural propagation. */
5226 ipcp_propagate_stage (&topo
);
5227 /* Decide what constant propagation and cloning should be performed. */
5228 ipcp_decision_stage (&topo
);
5229 /* Store results of bits propagation. */
5230 ipcp_store_bits_results ();
5231 /* Store results of value range propagation. */
5232 ipcp_store_vr_results ();
5234 /* Free all IPCP structures. */
5235 delete clone_num_suffixes
;
5236 free_toporder_info (&topo
);
5237 delete edge_clone_summaries
;
5238 edge_clone_summaries
= NULL
;
5239 ipa_free_all_structures_after_ipa_cp ();
5241 fprintf (dump_file
, "\nIPA constant propagation end\n");
5245 /* Initialization and computation of IPCP data structures. This is the initial
5246 intraprocedural analysis of functions, which gathers information to be
5247 propagated later on. */
5250 ipcp_generate_summary (void)
5252 struct cgraph_node
*node
;
5255 fprintf (dump_file
, "\nIPA constant propagation start:\n");
5256 ipa_register_cgraph_hooks ();
5258 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
5259 ipa_analyze_node (node
);
5262 /* Write ipcp summary for nodes in SET. */
5265 ipcp_write_summary (void)
5267 ipa_prop_write_jump_functions ();
5270 /* Read ipcp summary. */
5273 ipcp_read_summary (void)
5275 ipa_prop_read_jump_functions ();
5280 const pass_data pass_data_ipa_cp
=
5282 IPA_PASS
, /* type */
5284 OPTGROUP_NONE
, /* optinfo_flags */
5285 TV_IPA_CONSTANT_PROP
, /* tv_id */
5286 0, /* properties_required */
5287 0, /* properties_provided */
5288 0, /* properties_destroyed */
5289 0, /* todo_flags_start */
5290 ( TODO_dump_symtab
| TODO_remove_functions
), /* todo_flags_finish */
5293 class pass_ipa_cp
: public ipa_opt_pass_d
5296 pass_ipa_cp (gcc::context
*ctxt
)
5297 : ipa_opt_pass_d (pass_data_ipa_cp
, ctxt
,
5298 ipcp_generate_summary
, /* generate_summary */
5299 ipcp_write_summary
, /* write_summary */
5300 ipcp_read_summary
, /* read_summary */
5301 ipcp_write_transformation_summaries
, /*
5302 write_optimization_summary */
5303 ipcp_read_transformation_summaries
, /*
5304 read_optimization_summary */
5305 NULL
, /* stmt_fixup */
5306 0, /* function_transform_todo_flags_start */
5307 ipcp_transform_function
, /* function_transform */
5308 NULL
) /* variable_transform */
5311 /* opt_pass methods: */
5312 virtual bool gate (function
*)
5314 /* FIXME: We should remove the optimize check after we ensure we never run
5315 IPA passes when not optimizing. */
5316 return (flag_ipa_cp
&& optimize
) || in_lto_p
;
5319 virtual unsigned int execute (function
*) { return ipcp_driver (); }
5321 }; // class pass_ipa_cp
5326 make_pass_ipa_cp (gcc::context
*ctxt
)
5328 return new pass_ipa_cp (ctxt
);
5331 /* Reset all state within ipa-cp.c so that we can rerun the compiler
5332 within the same process. For use by toplev::finalize. */
5335 ipa_cp_c_finalize (void)
5337 max_count
= profile_count::uninitialized ();
5340 ipcp_free_transformation_sum ();