1 /* Interprocedural constant propagation
2 Copyright (C) 2005-2015 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"
109 #include "fold-const.h"
110 #include "gimple-fold.h"
111 #include "gimple-expr.h"
114 #include "hard-reg-set.h"
116 #include "alloc-pool.h"
117 #include "symbol-summary.h"
118 #include "ipa-prop.h"
119 #include "tree-pass.h"
121 #include "diagnostic.h"
122 #include "tree-pretty-print.h"
123 #include "tree-inline.h"
125 #include "ipa-inline.h"
126 #include "ipa-utils.h"
128 template <typename valtype
> class ipcp_value
;
130 /* Describes a particular source for an IPA-CP value. */
132 template <typename valtype
>
133 class 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 /* Describes one particular value stored in struct ipcp_lattice. */
168 template <typename valtype
>
169 class ipcp_value
: public ipcp_value_base
172 /* The actual value for the given parameter. */
174 /* The list of sources from which this value originates. */
175 ipcp_value_source
<valtype
> *sources
;
176 /* Next pointers in a linked list of all values in a lattice. */
178 /* Next pointers in a linked list of values in a strongly connected component
180 ipcp_value
*scc_next
;
181 /* Next pointers in a linked list of SCCs of values sorted topologically
182 according their sources. */
183 ipcp_value
*topo_next
;
184 /* A specialized node created for this value, NULL if none has been (so far)
186 cgraph_node
*spec_node
;
187 /* Depth first search number and low link for topological sorting of
190 /* True if this valye is currently on the topo-sort stack. */
193 void add_source (cgraph_edge
*cs
, ipcp_value
*src_val
, int src_idx
,
194 HOST_WIDE_INT offset
);
197 /* Lattice describing potential values of a formal parameter of a function, or
198 a part of an aggreagate. TOP is represented by a lattice with zero values
199 and with contains_variable and bottom flags cleared. BOTTOM is represented
200 by a lattice with the bottom flag set. In that case, values and
201 contains_variable flag should be disregarded. */
203 template <typename valtype
>
207 /* The list of known values and types in this lattice. Note that values are
208 not deallocated if a lattice is set to bottom because there may be value
209 sources referencing them. */
210 ipcp_value
<valtype
> *values
;
211 /* Number of known values and types in this lattice. */
213 /* The lattice contains a variable component (in addition to values). */
214 bool contains_variable
;
215 /* The value of the lattice is bottom (i.e. variable and unusable for any
219 inline bool is_single_const ();
220 inline bool set_to_bottom ();
221 inline bool set_contains_variable ();
222 bool add_value (valtype newval
, cgraph_edge
*cs
,
223 ipcp_value
<valtype
> *src_val
= NULL
,
224 int src_idx
= 0, HOST_WIDE_INT offset
= -1);
225 void print (FILE * f
, bool dump_sources
, bool dump_benefits
);
228 /* Lattice of tree values with an offset to describe a part of an
231 class ipcp_agg_lattice
: public ipcp_lattice
<tree
>
234 /* Offset that is being described by this lattice. */
235 HOST_WIDE_INT offset
;
236 /* Size so that we don't have to re-compute it every time we traverse the
237 list. Must correspond to TYPE_SIZE of all lat values. */
239 /* Next element of the linked list. */
240 struct ipcp_agg_lattice
*next
;
243 /* Structure containing lattices for a parameter itself and for pieces of
244 aggregates that are passed in the parameter or by a reference in a parameter
245 plus some other useful flags. */
247 class ipcp_param_lattices
250 /* Lattice describing the value of the parameter itself. */
251 ipcp_lattice
<tree
> itself
;
252 /* Lattice describing the the polymorphic contexts of a parameter. */
253 ipcp_lattice
<ipa_polymorphic_call_context
> ctxlat
;
254 /* Lattices describing aggregate parts. */
255 ipcp_agg_lattice
*aggs
;
256 /* Alignment information. Very basic one value lattice where !known means
257 TOP and zero alignment bottom. */
258 ipa_alignment alignment
;
259 /* Number of aggregate lattices */
261 /* True if aggregate data were passed by reference (as opposed to by
264 /* All aggregate lattices contain a variable component (in addition to
266 bool aggs_contain_variable
;
267 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
268 for any propagation). */
271 /* There is a virtual call based on this parameter. */
275 /* Allocation pools for values and their sources in ipa-cp. */
277 pool_allocator
<ipcp_value
<tree
> > ipcp_cst_values_pool
278 ("IPA-CP constant values", 32);
280 pool_allocator
<ipcp_value
<ipa_polymorphic_call_context
> >
281 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts", 32);
283 pool_allocator
<ipcp_value_source
<tree
> > ipcp_sources_pool
284 ("IPA-CP value sources", 64);
286 pool_allocator
<ipcp_agg_lattice
> ipcp_agg_lattice_pool
287 ("IPA_CP aggregate lattices", 32);
289 /* Maximal count found in program. */
291 static gcov_type max_count
;
293 /* Original overall size of the program. */
295 static long overall_size
, max_new_size
;
297 /* Return the param lattices structure corresponding to the Ith formal
298 parameter of the function described by INFO. */
299 static inline struct ipcp_param_lattices
*
300 ipa_get_parm_lattices (struct ipa_node_params
*info
, int i
)
302 gcc_assert (i
>= 0 && i
< ipa_get_param_count (info
));
303 gcc_checking_assert (!info
->ipcp_orig_node
);
304 gcc_checking_assert (info
->lattices
);
305 return &(info
->lattices
[i
]);
308 /* Return the lattice corresponding to the scalar value of the Ith formal
309 parameter of the function described by INFO. */
310 static inline ipcp_lattice
<tree
> *
311 ipa_get_scalar_lat (struct ipa_node_params
*info
, int i
)
313 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
314 return &plats
->itself
;
317 /* Return the lattice corresponding to the scalar value of the Ith formal
318 parameter of the function described by INFO. */
319 static inline ipcp_lattice
<ipa_polymorphic_call_context
> *
320 ipa_get_poly_ctx_lat (struct ipa_node_params
*info
, int i
)
322 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
323 return &plats
->ctxlat
;
326 /* Return whether LAT is a lattice with a single constant and without an
329 template <typename valtype
>
331 ipcp_lattice
<valtype
>::is_single_const ()
333 if (bottom
|| contains_variable
|| values_count
!= 1)
339 /* Print V which is extracted from a value in a lattice to F. */
342 print_ipcp_constant_value (FILE * f
, tree v
)
344 if (TREE_CODE (v
) == ADDR_EXPR
345 && TREE_CODE (TREE_OPERAND (v
, 0)) == CONST_DECL
)
348 print_generic_expr (f
, DECL_INITIAL (TREE_OPERAND (v
, 0)), 0);
351 print_generic_expr (f
, v
, 0);
354 /* Print V which is extracted from a value in a lattice to F. */
357 print_ipcp_constant_value (FILE * f
, ipa_polymorphic_call_context v
)
362 /* Print a lattice LAT to F. */
364 template <typename valtype
>
366 ipcp_lattice
<valtype
>::print (FILE * f
, bool dump_sources
, bool dump_benefits
)
368 ipcp_value
<valtype
> *val
;
373 fprintf (f
, "BOTTOM\n");
377 if (!values_count
&& !contains_variable
)
379 fprintf (f
, "TOP\n");
383 if (contains_variable
)
385 fprintf (f
, "VARIABLE");
391 for (val
= values
; val
; val
= val
->next
)
393 if (dump_benefits
&& prev
)
395 else if (!dump_benefits
&& prev
)
400 print_ipcp_constant_value (f
, val
->value
);
404 ipcp_value_source
<valtype
> *s
;
406 fprintf (f
, " [from:");
407 for (s
= val
->sources
; s
; s
= s
->next
)
408 fprintf (f
, " %i(%i)", s
->cs
->caller
->order
,
414 fprintf (f
, " [loc_time: %i, loc_size: %i, "
415 "prop_time: %i, prop_size: %i]\n",
416 val
->local_time_benefit
, val
->local_size_cost
,
417 val
->prop_time_benefit
, val
->prop_size_cost
);
423 /* Print all ipcp_lattices of all functions to F. */
426 print_all_lattices (FILE * f
, bool dump_sources
, bool dump_benefits
)
428 struct cgraph_node
*node
;
431 fprintf (f
, "\nLattices:\n");
432 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
434 struct ipa_node_params
*info
;
436 info
= IPA_NODE_REF (node
);
437 fprintf (f
, " Node: %s/%i:\n", node
->name (),
439 count
= ipa_get_param_count (info
);
440 for (i
= 0; i
< count
; i
++)
442 struct ipcp_agg_lattice
*aglat
;
443 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
444 fprintf (f
, " param [%d]: ", i
);
445 plats
->itself
.print (f
, dump_sources
, dump_benefits
);
446 fprintf (f
, " ctxs: ");
447 plats
->ctxlat
.print (f
, dump_sources
, dump_benefits
);
448 if (plats
->alignment
.known
&& plats
->alignment
.align
> 0)
449 fprintf (f
, " Alignment %u, misalignment %u\n",
450 plats
->alignment
.align
, plats
->alignment
.misalign
);
451 else if (plats
->alignment
.known
)
452 fprintf (f
, " Alignment unusable\n");
454 fprintf (f
, " Alignment unknown\n");
455 if (plats
->virt_call
)
456 fprintf (f
, " virt_call flag set\n");
458 if (plats
->aggs_bottom
)
460 fprintf (f
, " AGGS BOTTOM\n");
463 if (plats
->aggs_contain_variable
)
464 fprintf (f
, " AGGS VARIABLE\n");
465 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
467 fprintf (f
, " %soffset " HOST_WIDE_INT_PRINT_DEC
": ",
468 plats
->aggs_by_ref
? "ref " : "", aglat
->offset
);
469 aglat
->print (f
, dump_sources
, dump_benefits
);
475 /* Determine whether it is at all technically possible to create clones of NODE
476 and store this information in the ipa_node_params structure associated
480 determine_versionability (struct cgraph_node
*node
)
482 const char *reason
= NULL
;
484 /* There are a number of generic reasons functions cannot be versioned. We
485 also cannot remove parameters if there are type attributes such as fnspec
487 if (node
->alias
|| node
->thunk
.thunk_p
)
488 reason
= "alias or thunk";
489 else if (!node
->local
.versionable
)
490 reason
= "not a tree_versionable_function";
491 else if (node
->get_availability () <= AVAIL_INTERPOSABLE
)
492 reason
= "insufficient body availability";
493 else if (!opt_for_fn (node
->decl
, optimize
)
494 || !opt_for_fn (node
->decl
, flag_ipa_cp
))
495 reason
= "non-optimized function";
496 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node
->decl
)))
498 /* Ideally we should clone the SIMD clones themselves and create
499 vector copies of them, so IPA-cp and SIMD clones can happily
500 coexist, but that may not be worth the effort. */
501 reason
= "function has SIMD clones";
503 /* Don't clone decls local to a comdat group; it breaks and for C++
504 decloned constructors, inlining is always better anyway. */
505 else if (node
->comdat_local_p ())
506 reason
= "comdat-local function";
508 if (reason
&& dump_file
&& !node
->alias
&& !node
->thunk
.thunk_p
)
509 fprintf (dump_file
, "Function %s/%i is not versionable, reason: %s.\n",
510 node
->name (), node
->order
, reason
);
512 node
->local
.versionable
= (reason
== NULL
);
515 /* Return true if it is at all technically possible to create clones of a
519 ipcp_versionable_function_p (struct cgraph_node
*node
)
521 return node
->local
.versionable
;
524 /* Structure holding accumulated information about callers of a node. */
526 struct caller_statistics
529 int n_calls
, n_hot_calls
, freq_sum
;
532 /* Initialize fields of STAT to zeroes. */
535 init_caller_stats (struct caller_statistics
*stats
)
537 stats
->count_sum
= 0;
539 stats
->n_hot_calls
= 0;
543 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
544 non-thunk incoming edges to NODE. */
547 gather_caller_stats (struct cgraph_node
*node
, void *data
)
549 struct caller_statistics
*stats
= (struct caller_statistics
*) data
;
550 struct cgraph_edge
*cs
;
552 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
553 if (!cs
->caller
->thunk
.thunk_p
)
555 stats
->count_sum
+= cs
->count
;
556 stats
->freq_sum
+= cs
->frequency
;
558 if (cs
->maybe_hot_p ())
559 stats
->n_hot_calls
++;
565 /* Return true if this NODE is viable candidate for cloning. */
568 ipcp_cloning_candidate_p (struct cgraph_node
*node
)
570 struct caller_statistics stats
;
572 gcc_checking_assert (node
->has_gimple_body_p ());
574 if (!opt_for_fn (node
->decl
, flag_ipa_cp_clone
))
577 fprintf (dump_file
, "Not considering %s for cloning; "
578 "-fipa-cp-clone disabled.\n",
583 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node
->decl
)))
586 fprintf (dump_file
, "Not considering %s for cloning; "
587 "optimizing it for size.\n",
592 init_caller_stats (&stats
);
593 node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
, false);
595 if (inline_summaries
->get (node
)->self_size
< stats
.n_calls
)
598 fprintf (dump_file
, "Considering %s for cloning; code might shrink.\n",
603 /* When profile is available and function is hot, propagate into it even if
604 calls seems cold; constant propagation can improve function's speed
608 if (stats
.count_sum
> node
->count
* 90 / 100)
611 fprintf (dump_file
, "Considering %s for cloning; "
612 "usually called directly.\n",
617 if (!stats
.n_hot_calls
)
620 fprintf (dump_file
, "Not considering %s for cloning; no hot calls.\n",
625 fprintf (dump_file
, "Considering %s for cloning.\n",
630 template <typename valtype
>
631 class value_topo_info
634 /* Head of the linked list of topologically sorted values. */
635 ipcp_value
<valtype
> *values_topo
;
636 /* Stack for creating SCCs, represented by a linked list too. */
637 ipcp_value
<valtype
> *stack
;
638 /* Counter driving the algorithm in add_val_to_toposort. */
641 value_topo_info () : values_topo (NULL
), stack (NULL
), dfs_counter (0)
643 void add_val (ipcp_value
<valtype
> *cur_val
);
644 void propagate_effects ();
647 /* Arrays representing a topological ordering of call graph nodes and a stack
648 of nodes used during constant propagation and also data required to perform
649 topological sort of values and propagation of benefits in the determined
655 /* Array with obtained topological order of cgraph nodes. */
656 struct cgraph_node
**order
;
657 /* Stack of cgraph nodes used during propagation within SCC until all values
658 in the SCC stabilize. */
659 struct cgraph_node
**stack
;
660 int nnodes
, stack_top
;
662 value_topo_info
<tree
> constants
;
663 value_topo_info
<ipa_polymorphic_call_context
> contexts
;
665 ipa_topo_info () : order(NULL
), stack(NULL
), nnodes(0), stack_top(0),
670 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
673 build_toporder_info (struct ipa_topo_info
*topo
)
675 topo
->order
= XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
676 topo
->stack
= XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
678 gcc_checking_assert (topo
->stack_top
== 0);
679 topo
->nnodes
= ipa_reduced_postorder (topo
->order
, true, true, NULL
);
682 /* Free information about strongly connected components and the arrays in
686 free_toporder_info (struct ipa_topo_info
*topo
)
688 ipa_free_postorder_info ();
693 /* Add NODE to the stack in TOPO, unless it is already there. */
696 push_node_to_stack (struct ipa_topo_info
*topo
, struct cgraph_node
*node
)
698 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
699 if (info
->node_enqueued
)
701 info
->node_enqueued
= 1;
702 topo
->stack
[topo
->stack_top
++] = node
;
705 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
708 static struct cgraph_node
*
709 pop_node_from_stack (struct ipa_topo_info
*topo
)
713 struct cgraph_node
*node
;
715 node
= topo
->stack
[topo
->stack_top
];
716 IPA_NODE_REF (node
)->node_enqueued
= 0;
723 /* Set lattice LAT to bottom and return true if it previously was not set as
726 template <typename valtype
>
728 ipcp_lattice
<valtype
>::set_to_bottom ()
735 /* Mark lattice as containing an unknown value and return true if it previously
736 was not marked as such. */
738 template <typename valtype
>
740 ipcp_lattice
<valtype
>::set_contains_variable ()
742 bool ret
= !contains_variable
;
743 contains_variable
= true;
747 /* Set all aggegate lattices in PLATS to bottom and return true if they were
748 not previously set as such. */
751 set_agg_lats_to_bottom (struct ipcp_param_lattices
*plats
)
753 bool ret
= !plats
->aggs_bottom
;
754 plats
->aggs_bottom
= true;
758 /* Mark all aggegate lattices in PLATS as containing an unknown value and
759 return true if they were not previously marked as such. */
762 set_agg_lats_contain_variable (struct ipcp_param_lattices
*plats
)
764 bool ret
= !plats
->aggs_contain_variable
;
765 plats
->aggs_contain_variable
= true;
769 /* Return true if alignment information in PLATS is known to be unusable. */
772 alignment_bottom_p (ipcp_param_lattices
*plats
)
774 return plats
->alignment
.known
&& (plats
->alignment
.align
== 0);
777 /* Set alignment information in PLATS to unusable. Return true if it
778 previously was usable or unknown. */
781 set_alignment_to_bottom (ipcp_param_lattices
*plats
)
783 if (alignment_bottom_p (plats
))
785 plats
->alignment
.known
= true;
786 plats
->alignment
.align
= 0;
790 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
791 return true is any of them has not been marked as such so far. */
794 set_all_contains_variable (struct ipcp_param_lattices
*plats
)
797 ret
= plats
->itself
.set_contains_variable ();
798 ret
|= plats
->ctxlat
.set_contains_variable ();
799 ret
|= set_agg_lats_contain_variable (plats
);
800 ret
|= set_alignment_to_bottom (plats
);
804 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
805 points to by the number of callers to NODE. */
808 count_callers (cgraph_node
*node
, void *data
)
810 int *caller_count
= (int *) data
;
812 for (cgraph_edge
*cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
813 /* Local thunks can be handled transparently, but if the thunk can not
814 be optimized out, count it as a real use. */
815 if (!cs
->caller
->thunk
.thunk_p
|| !cs
->caller
->local
.local
)
820 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
821 the one caller of some other node. Set the caller's corresponding flag. */
824 set_single_call_flag (cgraph_node
*node
, void *)
826 cgraph_edge
*cs
= node
->callers
;
827 /* Local thunks can be handled transparently, skip them. */
828 while (cs
&& cs
->caller
->thunk
.thunk_p
&& cs
->caller
->local
.local
)
829 cs
= cs
->next_caller
;
832 IPA_NODE_REF (cs
->caller
)->node_calling_single_call
= true;
838 /* Initialize ipcp_lattices. */
841 initialize_node_lattices (struct cgraph_node
*node
)
843 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
844 struct cgraph_edge
*ie
;
845 bool disable
= false, variable
= false;
848 gcc_checking_assert (node
->has_gimple_body_p ());
849 if (cgraph_local_p (node
))
851 int caller_count
= 0;
852 node
->call_for_symbol_thunks_and_aliases (count_callers
, &caller_count
,
854 gcc_checking_assert (caller_count
> 0);
855 if (caller_count
== 1)
856 node
->call_for_symbol_thunks_and_aliases (set_single_call_flag
,
861 /* When cloning is allowed, we can assume that externally visible
862 functions are not called. We will compensate this by cloning
864 if (ipcp_versionable_function_p (node
)
865 && ipcp_cloning_candidate_p (node
))
871 if (disable
|| variable
)
873 for (i
= 0; i
< ipa_get_param_count (info
) ; i
++)
875 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
878 plats
->itself
.set_to_bottom ();
879 plats
->ctxlat
.set_to_bottom ();
880 set_agg_lats_to_bottom (plats
);
881 set_alignment_to_bottom (plats
);
884 set_all_contains_variable (plats
);
886 if (dump_file
&& (dump_flags
& TDF_DETAILS
)
887 && !node
->alias
&& !node
->thunk
.thunk_p
)
888 fprintf (dump_file
, "Marking all lattices of %s/%i as %s\n",
889 node
->name (), node
->order
,
890 disable
? "BOTTOM" : "VARIABLE");
893 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
894 if (ie
->indirect_info
->polymorphic
895 && ie
->indirect_info
->param_index
>= 0)
897 gcc_checking_assert (ie
->indirect_info
->param_index
>= 0);
898 ipa_get_parm_lattices (info
,
899 ie
->indirect_info
->param_index
)->virt_call
= 1;
903 /* Return the result of a (possibly arithmetic) pass through jump function
904 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
905 determined or be considered an interprocedural invariant. */
908 ipa_get_jf_pass_through_result (struct ipa_jump_func
*jfunc
, tree input
)
912 gcc_checking_assert (is_gimple_ip_invariant (input
));
913 if (ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
916 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc
))
918 restype
= boolean_type_node
;
920 restype
= TREE_TYPE (input
);
921 res
= fold_binary (ipa_get_jf_pass_through_operation (jfunc
), restype
,
922 input
, ipa_get_jf_pass_through_operand (jfunc
));
924 if (res
&& !is_gimple_ip_invariant (res
))
930 /* Return the result of an ancestor jump function JFUNC on the constant value
931 INPUT. Return NULL_TREE if that cannot be determined. */
934 ipa_get_jf_ancestor_result (struct ipa_jump_func
*jfunc
, tree input
)
936 gcc_checking_assert (TREE_CODE (input
) != TREE_BINFO
);
937 if (TREE_CODE (input
) == ADDR_EXPR
)
939 tree t
= TREE_OPERAND (input
, 0);
940 t
= build_ref_for_offset (EXPR_LOCATION (t
), t
,
941 ipa_get_jf_ancestor_offset (jfunc
),
942 ptr_type_node
, NULL
, false);
943 return build_fold_addr_expr (t
);
949 /* Determine whether JFUNC evaluates to a single known constant value and if
950 so, return it. Otherwise return NULL. INFO describes the caller node or
951 the one it is inlined to, so that pass-through jump functions can be
955 ipa_value_from_jfunc (struct ipa_node_params
*info
, struct ipa_jump_func
*jfunc
)
957 if (jfunc
->type
== IPA_JF_CONST
)
958 return ipa_get_jf_constant (jfunc
);
959 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
960 || jfunc
->type
== IPA_JF_ANCESTOR
)
965 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
966 idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
968 idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
970 if (info
->ipcp_orig_node
)
971 input
= info
->known_csts
[idx
];
974 ipcp_lattice
<tree
> *lat
;
977 || idx
>= ipa_get_param_count (info
))
979 lat
= ipa_get_scalar_lat (info
, idx
);
980 if (!lat
->is_single_const ())
982 input
= lat
->values
->value
;
988 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
989 return ipa_get_jf_pass_through_result (jfunc
, input
);
991 return ipa_get_jf_ancestor_result (jfunc
, input
);
997 /* Determie whether JFUNC evaluates to single known polymorphic context, given
998 that INFO describes the caller node or the one it is inlined to, CS is the
999 call graph edge corresponding to JFUNC and CSIDX index of the described
1002 ipa_polymorphic_call_context
1003 ipa_context_from_jfunc (ipa_node_params
*info
, cgraph_edge
*cs
, int csidx
,
1004 ipa_jump_func
*jfunc
)
1006 ipa_edge_args
*args
= IPA_EDGE_REF (cs
);
1007 ipa_polymorphic_call_context ctx
;
1008 ipa_polymorphic_call_context
*edge_ctx
1009 = cs
? ipa_get_ith_polymorhic_call_context (args
, csidx
) : NULL
;
1011 if (edge_ctx
&& !edge_ctx
->useless_p ())
1014 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1015 || jfunc
->type
== IPA_JF_ANCESTOR
)
1017 ipa_polymorphic_call_context srcctx
;
1019 bool type_preserved
= true;
1020 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1022 if (ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1024 type_preserved
= ipa_get_jf_pass_through_type_preserved (jfunc
);
1025 srcidx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1029 type_preserved
= ipa_get_jf_ancestor_type_preserved (jfunc
);
1030 srcidx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1032 if (info
->ipcp_orig_node
)
1034 if (info
->known_contexts
.exists ())
1035 srcctx
= info
->known_contexts
[srcidx
];
1040 || srcidx
>= ipa_get_param_count (info
))
1042 ipcp_lattice
<ipa_polymorphic_call_context
> *lat
;
1043 lat
= ipa_get_poly_ctx_lat (info
, srcidx
);
1044 if (!lat
->is_single_const ())
1046 srcctx
= lat
->values
->value
;
1048 if (srcctx
.useless_p ())
1050 if (jfunc
->type
== IPA_JF_ANCESTOR
)
1051 srcctx
.offset_by (ipa_get_jf_ancestor_offset (jfunc
));
1052 if (!type_preserved
)
1053 srcctx
.possible_dynamic_type_change (cs
->in_polymorphic_cdtor
);
1054 srcctx
.combine_with (ctx
);
1061 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1062 bottom, not containing a variable component and without any known value at
1066 ipcp_verify_propagated_values (void)
1068 struct cgraph_node
*node
;
1070 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
1072 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
1073 int i
, count
= ipa_get_param_count (info
);
1075 for (i
= 0; i
< count
; i
++)
1077 ipcp_lattice
<tree
> *lat
= ipa_get_scalar_lat (info
, i
);
1080 && !lat
->contains_variable
1081 && lat
->values_count
== 0)
1085 symtab_node::dump_table (dump_file
);
1086 fprintf (dump_file
, "\nIPA lattices after constant "
1087 "propagation, before gcc_unreachable:\n");
1088 print_all_lattices (dump_file
, true, false);
1097 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1100 values_equal_for_ipcp_p (tree x
, tree y
)
1102 gcc_checking_assert (x
!= NULL_TREE
&& y
!= NULL_TREE
);
1107 if (TREE_CODE (x
) == ADDR_EXPR
1108 && TREE_CODE (y
) == ADDR_EXPR
1109 && TREE_CODE (TREE_OPERAND (x
, 0)) == CONST_DECL
1110 && TREE_CODE (TREE_OPERAND (y
, 0)) == CONST_DECL
)
1111 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x
, 0)),
1112 DECL_INITIAL (TREE_OPERAND (y
, 0)), 0);
1114 return operand_equal_p (x
, y
, 0);
1117 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1120 values_equal_for_ipcp_p (ipa_polymorphic_call_context x
,
1121 ipa_polymorphic_call_context y
)
1123 return x
.equal_to (y
);
1127 /* Add a new value source to the value represented by THIS, marking that a
1128 value comes from edge CS and (if the underlying jump function is a
1129 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1130 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1131 scalar value of the parameter itself or the offset within an aggregate. */
1133 template <typename valtype
>
1135 ipcp_value
<valtype
>::add_source (cgraph_edge
*cs
, ipcp_value
*src_val
,
1136 int src_idx
, HOST_WIDE_INT offset
)
1138 ipcp_value_source
<valtype
> *src
;
1140 src
= new (ipcp_sources_pool
.allocate ()) ipcp_value_source
<valtype
>;
1141 src
->offset
= offset
;
1144 src
->index
= src_idx
;
1146 src
->next
= sources
;
1150 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1151 SOURCE and clear all other fields. */
1153 static ipcp_value
<tree
> *
1154 allocate_and_init_ipcp_value (tree source
)
1156 ipcp_value
<tree
> *val
;
1158 val
= ipcp_cst_values_pool
.allocate ();
1159 memset (val
, 0, sizeof (*val
));
1160 val
->value
= source
;
1164 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1165 value to SOURCE and clear all other fields. */
1167 static ipcp_value
<ipa_polymorphic_call_context
> *
1168 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source
)
1170 ipcp_value
<ipa_polymorphic_call_context
> *val
;
1173 val
= ipcp_poly_ctx_values_pool
.allocate ();
1174 memset (val
, 0, sizeof (*val
));
1175 val
->value
= source
;
1179 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1180 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1181 meaning. OFFSET -1 means the source is scalar and not a part of an
1184 template <typename valtype
>
1186 ipcp_lattice
<valtype
>::add_value (valtype newval
, cgraph_edge
*cs
,
1187 ipcp_value
<valtype
> *src_val
,
1188 int src_idx
, HOST_WIDE_INT offset
)
1190 ipcp_value
<valtype
> *val
;
1195 for (val
= values
; val
; val
= val
->next
)
1196 if (values_equal_for_ipcp_p (val
->value
, newval
))
1198 if (ipa_edge_within_scc (cs
))
1200 ipcp_value_source
<valtype
> *s
;
1201 for (s
= val
->sources
; s
; s
= s
->next
)
1208 val
->add_source (cs
, src_val
, src_idx
, offset
);
1212 if (values_count
== PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE
))
1214 /* We can only free sources, not the values themselves, because sources
1215 of other values in this this SCC might point to them. */
1216 for (val
= values
; val
; val
= val
->next
)
1218 while (val
->sources
)
1220 ipcp_value_source
<valtype
> *src
= val
->sources
;
1221 val
->sources
= src
->next
;
1222 ipcp_sources_pool
.remove ((ipcp_value_source
<tree
>*)src
);
1227 return set_to_bottom ();
1231 val
= allocate_and_init_ipcp_value (newval
);
1232 val
->add_source (cs
, src_val
, src_idx
, offset
);
1238 /* Propagate values through a pass-through jump function JFUNC associated with
1239 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1240 is the index of the source parameter. */
1243 propagate_vals_accross_pass_through (cgraph_edge
*cs
,
1244 ipa_jump_func
*jfunc
,
1245 ipcp_lattice
<tree
> *src_lat
,
1246 ipcp_lattice
<tree
> *dest_lat
,
1249 ipcp_value
<tree
> *src_val
;
1252 /* Do not create new values when propagating within an SCC because if there
1253 are arithmetic functions with circular dependencies, there is infinite
1254 number of them and we would just make lattices bottom. */
1255 if ((ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1256 && ipa_edge_within_scc (cs
))
1257 ret
= dest_lat
->set_contains_variable ();
1259 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1261 tree cstval
= ipa_get_jf_pass_through_result (jfunc
, src_val
->value
);
1264 ret
|= dest_lat
->add_value (cstval
, cs
, src_val
, src_idx
);
1266 ret
|= dest_lat
->set_contains_variable ();
1272 /* Propagate values through an ancestor jump function JFUNC associated with
1273 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1274 is the index of the source parameter. */
1277 propagate_vals_accross_ancestor (struct cgraph_edge
*cs
,
1278 struct ipa_jump_func
*jfunc
,
1279 ipcp_lattice
<tree
> *src_lat
,
1280 ipcp_lattice
<tree
> *dest_lat
,
1283 ipcp_value
<tree
> *src_val
;
1286 if (ipa_edge_within_scc (cs
))
1287 return dest_lat
->set_contains_variable ();
1289 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1291 tree t
= ipa_get_jf_ancestor_result (jfunc
, src_val
->value
);
1294 ret
|= dest_lat
->add_value (t
, cs
, src_val
, src_idx
);
1296 ret
|= dest_lat
->set_contains_variable ();
1302 /* Propagate scalar values across jump function JFUNC that is associated with
1303 edge CS and put the values into DEST_LAT. */
1306 propagate_scalar_accross_jump_function (struct cgraph_edge
*cs
,
1307 struct ipa_jump_func
*jfunc
,
1308 ipcp_lattice
<tree
> *dest_lat
)
1310 if (dest_lat
->bottom
)
1313 if (jfunc
->type
== IPA_JF_CONST
)
1315 tree val
= ipa_get_jf_constant (jfunc
);
1316 return dest_lat
->add_value (val
, cs
, NULL
, 0);
1318 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
1319 || jfunc
->type
== IPA_JF_ANCESTOR
)
1321 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1322 ipcp_lattice
<tree
> *src_lat
;
1326 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1327 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1329 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1331 src_lat
= ipa_get_scalar_lat (caller_info
, src_idx
);
1332 if (src_lat
->bottom
)
1333 return dest_lat
->set_contains_variable ();
1335 /* If we would need to clone the caller and cannot, do not propagate. */
1336 if (!ipcp_versionable_function_p (cs
->caller
)
1337 && (src_lat
->contains_variable
1338 || (src_lat
->values_count
> 1)))
1339 return dest_lat
->set_contains_variable ();
1341 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1342 ret
= propagate_vals_accross_pass_through (cs
, jfunc
, src_lat
,
1345 ret
= propagate_vals_accross_ancestor (cs
, jfunc
, src_lat
, dest_lat
,
1348 if (src_lat
->contains_variable
)
1349 ret
|= dest_lat
->set_contains_variable ();
1354 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1355 use it for indirect inlining), we should propagate them too. */
1356 return dest_lat
->set_contains_variable ();
1359 /* Propagate scalar values across jump function JFUNC that is associated with
1360 edge CS and describes argument IDX and put the values into DEST_LAT. */
1363 propagate_context_accross_jump_function (cgraph_edge
*cs
,
1364 ipa_jump_func
*jfunc
, int idx
,
1365 ipcp_lattice
<ipa_polymorphic_call_context
> *dest_lat
)
1367 ipa_edge_args
*args
= IPA_EDGE_REF (cs
);
1368 if (dest_lat
->bottom
)
1371 bool added_sth
= false;
1372 bool type_preserved
= true;
1374 ipa_polymorphic_call_context edge_ctx
, *edge_ctx_ptr
1375 = ipa_get_ith_polymorhic_call_context (args
, idx
);
1378 edge_ctx
= *edge_ctx_ptr
;
1380 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1381 || jfunc
->type
== IPA_JF_ANCESTOR
)
1383 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1385 ipcp_lattice
<ipa_polymorphic_call_context
> *src_lat
;
1387 /* TODO: Once we figure out how to propagate speculations, it will
1388 probably be a good idea to switch to speculation if type_preserved is
1389 not set instead of punting. */
1390 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1392 if (ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1394 type_preserved
= ipa_get_jf_pass_through_type_preserved (jfunc
);
1395 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1399 type_preserved
= ipa_get_jf_ancestor_type_preserved (jfunc
);
1400 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1403 src_lat
= ipa_get_poly_ctx_lat (caller_info
, src_idx
);
1404 /* If we would need to clone the caller and cannot, do not propagate. */
1405 if (!ipcp_versionable_function_p (cs
->caller
)
1406 && (src_lat
->contains_variable
1407 || (src_lat
->values_count
> 1)))
1410 ipcp_value
<ipa_polymorphic_call_context
> *src_val
;
1411 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1413 ipa_polymorphic_call_context cur
= src_val
->value
;
1415 if (!type_preserved
)
1416 cur
.possible_dynamic_type_change (cs
->in_polymorphic_cdtor
);
1417 if (jfunc
->type
== IPA_JF_ANCESTOR
)
1418 cur
.offset_by (ipa_get_jf_ancestor_offset (jfunc
));
1419 /* TODO: In cases we know how the context is going to be used,
1420 we can improve the result by passing proper OTR_TYPE. */
1421 cur
.combine_with (edge_ctx
);
1422 if (!cur
.useless_p ())
1424 if (src_lat
->contains_variable
1425 && !edge_ctx
.equal_to (cur
))
1426 ret
|= dest_lat
->set_contains_variable ();
1427 ret
|= dest_lat
->add_value (cur
, cs
, src_val
, src_idx
);
1437 if (!edge_ctx
.useless_p ())
1438 ret
|= dest_lat
->add_value (edge_ctx
, cs
);
1440 ret
|= dest_lat
->set_contains_variable ();
1446 /* Propagate alignments across jump function JFUNC that is associated with
1447 edge CS and update DEST_LAT accordingly. */
1450 propagate_alignment_accross_jump_function (struct cgraph_edge
*cs
,
1451 struct ipa_jump_func
*jfunc
,
1452 struct ipcp_param_lattices
*dest_lat
)
1454 if (alignment_bottom_p (dest_lat
))
1459 if (jfunc
->alignment
.known
)
1460 cur
= jfunc
->alignment
;
1461 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
1462 || jfunc
->type
== IPA_JF_ANCESTOR
)
1464 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1465 struct ipcp_param_lattices
*src_lats
;
1466 HOST_WIDE_INT offset
= 0;
1469 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1471 enum tree_code op
= ipa_get_jf_pass_through_operation (jfunc
);
1474 if (op
!= POINTER_PLUS_EXPR
1477 tree operand
= ipa_get_jf_pass_through_operand (jfunc
);
1478 if (!tree_fits_shwi_p (operand
))
1480 offset
= tree_to_shwi (operand
);
1482 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1486 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1487 offset
= ipa_get_jf_ancestor_offset (jfunc
) / BITS_PER_UNIT
;;
1490 src_lats
= ipa_get_parm_lattices (caller_info
, src_idx
);
1491 if (!src_lats
->alignment
.known
1492 || alignment_bottom_p (src_lats
))
1495 cur
= src_lats
->alignment
;
1496 cur
.misalign
= (cur
.misalign
+ offset
) % cur
.align
;
1501 if (!dest_lat
->alignment
.known
)
1503 dest_lat
->alignment
= cur
;
1506 else if (dest_lat
->alignment
.align
== cur
.align
1507 && dest_lat
->alignment
.misalign
== cur
.misalign
)
1512 set_alignment_to_bottom (dest_lat
);
1516 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1517 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1518 other cases, return false). If there are no aggregate items, set
1519 aggs_by_ref to NEW_AGGS_BY_REF. */
1522 set_check_aggs_by_ref (struct ipcp_param_lattices
*dest_plats
,
1523 bool new_aggs_by_ref
)
1525 if (dest_plats
->aggs
)
1527 if (dest_plats
->aggs_by_ref
!= new_aggs_by_ref
)
1529 set_agg_lats_to_bottom (dest_plats
);
1534 dest_plats
->aggs_by_ref
= new_aggs_by_ref
;
1538 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1539 already existing lattice for the given OFFSET and SIZE, marking all skipped
1540 lattices as containing variable and checking for overlaps. If there is no
1541 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1542 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1543 unless there are too many already. If there are two many, return false. If
1544 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1545 skipped lattices were newly marked as containing variable, set *CHANGE to
1549 merge_agg_lats_step (struct ipcp_param_lattices
*dest_plats
,
1550 HOST_WIDE_INT offset
, HOST_WIDE_INT val_size
,
1551 struct ipcp_agg_lattice
***aglat
,
1552 bool pre_existing
, bool *change
)
1554 gcc_checking_assert (offset
>= 0);
1556 while (**aglat
&& (**aglat
)->offset
< offset
)
1558 if ((**aglat
)->offset
+ (**aglat
)->size
> offset
)
1560 set_agg_lats_to_bottom (dest_plats
);
1563 *change
|= (**aglat
)->set_contains_variable ();
1564 *aglat
= &(**aglat
)->next
;
1567 if (**aglat
&& (**aglat
)->offset
== offset
)
1569 if ((**aglat
)->size
!= val_size
1571 && (**aglat
)->next
->offset
< offset
+ val_size
))
1573 set_agg_lats_to_bottom (dest_plats
);
1576 gcc_checking_assert (!(**aglat
)->next
1577 || (**aglat
)->next
->offset
>= offset
+ val_size
);
1582 struct ipcp_agg_lattice
*new_al
;
1584 if (**aglat
&& (**aglat
)->offset
< offset
+ val_size
)
1586 set_agg_lats_to_bottom (dest_plats
);
1589 if (dest_plats
->aggs_count
== PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS
))
1591 dest_plats
->aggs_count
++;
1592 new_al
= ipcp_agg_lattice_pool
.allocate ();
1593 memset (new_al
, 0, sizeof (*new_al
));
1595 new_al
->offset
= offset
;
1596 new_al
->size
= val_size
;
1597 new_al
->contains_variable
= pre_existing
;
1599 new_al
->next
= **aglat
;
1605 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1606 containing an unknown value. */
1609 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice
*aglat
)
1614 ret
|= aglat
->set_contains_variable ();
1615 aglat
= aglat
->next
;
1620 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1621 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1622 parameter used for lattice value sources. Return true if DEST_PLATS changed
1626 merge_aggregate_lattices (struct cgraph_edge
*cs
,
1627 struct ipcp_param_lattices
*dest_plats
,
1628 struct ipcp_param_lattices
*src_plats
,
1629 int src_idx
, HOST_WIDE_INT offset_delta
)
1631 bool pre_existing
= dest_plats
->aggs
!= NULL
;
1632 struct ipcp_agg_lattice
**dst_aglat
;
1635 if (set_check_aggs_by_ref (dest_plats
, src_plats
->aggs_by_ref
))
1637 if (src_plats
->aggs_bottom
)
1638 return set_agg_lats_contain_variable (dest_plats
);
1639 if (src_plats
->aggs_contain_variable
)
1640 ret
|= set_agg_lats_contain_variable (dest_plats
);
1641 dst_aglat
= &dest_plats
->aggs
;
1643 for (struct ipcp_agg_lattice
*src_aglat
= src_plats
->aggs
;
1645 src_aglat
= src_aglat
->next
)
1647 HOST_WIDE_INT new_offset
= src_aglat
->offset
- offset_delta
;
1651 if (merge_agg_lats_step (dest_plats
, new_offset
, src_aglat
->size
,
1652 &dst_aglat
, pre_existing
, &ret
))
1654 struct ipcp_agg_lattice
*new_al
= *dst_aglat
;
1656 dst_aglat
= &(*dst_aglat
)->next
;
1657 if (src_aglat
->bottom
)
1659 ret
|= new_al
->set_contains_variable ();
1662 if (src_aglat
->contains_variable
)
1663 ret
|= new_al
->set_contains_variable ();
1664 for (ipcp_value
<tree
> *val
= src_aglat
->values
;
1667 ret
|= new_al
->add_value (val
->value
, cs
, val
, src_idx
,
1670 else if (dest_plats
->aggs_bottom
)
1673 ret
|= set_chain_of_aglats_contains_variable (*dst_aglat
);
1677 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1678 pass-through JFUNC and if so, whether it has conform and conforms to the
1679 rules about propagating values passed by reference. */
1682 agg_pass_through_permissible_p (struct ipcp_param_lattices
*src_plats
,
1683 struct ipa_jump_func
*jfunc
)
1685 return src_plats
->aggs
1686 && (!src_plats
->aggs_by_ref
1687 || ipa_get_jf_pass_through_agg_preserved (jfunc
));
1690 /* Propagate scalar values across jump function JFUNC that is associated with
1691 edge CS and put the values into DEST_LAT. */
1694 propagate_aggs_accross_jump_function (struct cgraph_edge
*cs
,
1695 struct ipa_jump_func
*jfunc
,
1696 struct ipcp_param_lattices
*dest_plats
)
1700 if (dest_plats
->aggs_bottom
)
1703 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1704 && ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
1706 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1707 int src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1708 struct ipcp_param_lattices
*src_plats
;
1710 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
1711 if (agg_pass_through_permissible_p (src_plats
, jfunc
))
1713 /* Currently we do not produce clobber aggregate jump
1714 functions, replace with merging when we do. */
1715 gcc_assert (!jfunc
->agg
.items
);
1716 ret
|= merge_aggregate_lattices (cs
, dest_plats
, src_plats
,
1720 ret
|= set_agg_lats_contain_variable (dest_plats
);
1722 else if (jfunc
->type
== IPA_JF_ANCESTOR
1723 && ipa_get_jf_ancestor_agg_preserved (jfunc
))
1725 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1726 int src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1727 struct ipcp_param_lattices
*src_plats
;
1729 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
1730 if (src_plats
->aggs
&& src_plats
->aggs_by_ref
)
1732 /* Currently we do not produce clobber aggregate jump
1733 functions, replace with merging when we do. */
1734 gcc_assert (!jfunc
->agg
.items
);
1735 ret
|= merge_aggregate_lattices (cs
, dest_plats
, src_plats
, src_idx
,
1736 ipa_get_jf_ancestor_offset (jfunc
));
1738 else if (!src_plats
->aggs_by_ref
)
1739 ret
|= set_agg_lats_to_bottom (dest_plats
);
1741 ret
|= set_agg_lats_contain_variable (dest_plats
);
1743 else if (jfunc
->agg
.items
)
1745 bool pre_existing
= dest_plats
->aggs
!= NULL
;
1746 struct ipcp_agg_lattice
**aglat
= &dest_plats
->aggs
;
1747 struct ipa_agg_jf_item
*item
;
1750 if (set_check_aggs_by_ref (dest_plats
, jfunc
->agg
.by_ref
))
1753 FOR_EACH_VEC_ELT (*jfunc
->agg
.items
, i
, item
)
1755 HOST_WIDE_INT val_size
;
1757 if (item
->offset
< 0)
1759 gcc_checking_assert (is_gimple_ip_invariant (item
->value
));
1760 val_size
= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item
->value
)));
1762 if (merge_agg_lats_step (dest_plats
, item
->offset
, val_size
,
1763 &aglat
, pre_existing
, &ret
))
1765 ret
|= (*aglat
)->add_value (item
->value
, cs
, NULL
, 0, 0);
1766 aglat
= &(*aglat
)->next
;
1768 else if (dest_plats
->aggs_bottom
)
1772 ret
|= set_chain_of_aglats_contains_variable (*aglat
);
1775 ret
|= set_agg_lats_contain_variable (dest_plats
);
1780 /* Propagate constants from the caller to the callee of CS. INFO describes the
1784 propagate_constants_accross_call (struct cgraph_edge
*cs
)
1786 struct ipa_node_params
*callee_info
;
1787 enum availability availability
;
1788 struct cgraph_node
*callee
, *alias_or_thunk
;
1789 struct ipa_edge_args
*args
;
1791 int i
, args_count
, parms_count
;
1793 callee
= cs
->callee
->function_symbol (&availability
);
1794 if (!callee
->definition
)
1796 gcc_checking_assert (callee
->has_gimple_body_p ());
1797 callee_info
= IPA_NODE_REF (callee
);
1799 args
= IPA_EDGE_REF (cs
);
1800 args_count
= ipa_get_cs_argument_count (args
);
1801 parms_count
= ipa_get_param_count (callee_info
);
1802 if (parms_count
== 0)
1805 /* No propagation through instrumentation thunks is available yet.
1806 It should be possible with proper mapping of call args and
1807 instrumented callee params in the propagation loop below. But
1808 this case mostly occurs when legacy code calls instrumented code
1809 and it is not a primary target for optimizations.
1810 We detect instrumentation thunks in aliases and thunks chain by
1811 checking instrumentation_clone flag for chain source and target.
1812 Going through instrumentation thunks we always have it changed
1813 from 0 to 1 and all other nodes do not change it. */
1814 if (!cs
->callee
->instrumentation_clone
1815 && callee
->instrumentation_clone
)
1817 for (i
= 0; i
< parms_count
; i
++)
1818 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
,
1823 /* If this call goes through a thunk we must not propagate to the first (0th)
1824 parameter. However, we might need to uncover a thunk from below a series
1825 of aliases first. */
1826 alias_or_thunk
= cs
->callee
;
1827 while (alias_or_thunk
->alias
)
1828 alias_or_thunk
= alias_or_thunk
->get_alias_target ();
1829 if (alias_or_thunk
->thunk
.thunk_p
)
1831 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
,
1838 for (; (i
< args_count
) && (i
< parms_count
); i
++)
1840 struct ipa_jump_func
*jump_func
= ipa_get_ith_jump_func (args
, i
);
1841 struct ipcp_param_lattices
*dest_plats
;
1843 dest_plats
= ipa_get_parm_lattices (callee_info
, i
);
1844 if (availability
== AVAIL_INTERPOSABLE
)
1845 ret
|= set_all_contains_variable (dest_plats
);
1848 ret
|= propagate_scalar_accross_jump_function (cs
, jump_func
,
1849 &dest_plats
->itself
);
1850 ret
|= propagate_context_accross_jump_function (cs
, jump_func
, i
,
1851 &dest_plats
->ctxlat
);
1852 ret
|= propagate_alignment_accross_jump_function (cs
, jump_func
,
1854 ret
|= propagate_aggs_accross_jump_function (cs
, jump_func
,
1858 for (; i
< parms_count
; i
++)
1859 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
, i
));
1864 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1865 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1866 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
1869 ipa_get_indirect_edge_target_1 (struct cgraph_edge
*ie
,
1870 vec
<tree
> known_csts
,
1871 vec
<ipa_polymorphic_call_context
> known_contexts
,
1872 vec
<ipa_agg_jump_function_p
> known_aggs
,
1873 struct ipa_agg_replacement_value
*agg_reps
,
1876 int param_index
= ie
->indirect_info
->param_index
;
1877 HOST_WIDE_INT anc_offset
;
1881 *speculative
= false;
1883 if (param_index
== -1
1884 || known_csts
.length () <= (unsigned int) param_index
)
1887 if (!ie
->indirect_info
->polymorphic
)
1891 if (ie
->indirect_info
->agg_contents
)
1898 if (agg_reps
->index
== param_index
1899 && agg_reps
->offset
== ie
->indirect_info
->offset
1900 && agg_reps
->by_ref
== ie
->indirect_info
->by_ref
)
1902 t
= agg_reps
->value
;
1905 agg_reps
= agg_reps
->next
;
1908 else if (known_aggs
.length () > (unsigned int) param_index
)
1910 struct ipa_agg_jump_function
*agg
;
1911 agg
= known_aggs
[param_index
];
1912 t
= ipa_find_agg_cst_for_param (agg
, ie
->indirect_info
->offset
,
1913 ie
->indirect_info
->by_ref
);
1919 t
= known_csts
[param_index
];
1922 TREE_CODE (t
) == ADDR_EXPR
1923 && TREE_CODE (TREE_OPERAND (t
, 0)) == FUNCTION_DECL
)
1924 return TREE_OPERAND (t
, 0);
1929 if (!opt_for_fn (ie
->caller
->decl
, flag_devirtualize
))
1932 gcc_assert (!ie
->indirect_info
->agg_contents
);
1933 anc_offset
= ie
->indirect_info
->offset
;
1937 /* Try to work out value of virtual table pointer value in replacemnets. */
1938 if (!t
&& agg_reps
&& !ie
->indirect_info
->by_ref
)
1942 if (agg_reps
->index
== param_index
1943 && agg_reps
->offset
== ie
->indirect_info
->offset
1944 && agg_reps
->by_ref
)
1946 t
= agg_reps
->value
;
1949 agg_reps
= agg_reps
->next
;
1953 /* Try to work out value of virtual table pointer value in known
1954 aggregate values. */
1955 if (!t
&& known_aggs
.length () > (unsigned int) param_index
1956 && !ie
->indirect_info
->by_ref
)
1958 struct ipa_agg_jump_function
*agg
;
1959 agg
= known_aggs
[param_index
];
1960 t
= ipa_find_agg_cst_for_param (agg
, ie
->indirect_info
->offset
,
1964 /* If we found the virtual table pointer, lookup the target. */
1968 unsigned HOST_WIDE_INT offset
;
1969 if (vtable_pointer_value_to_vtable (t
, &vtable
, &offset
))
1971 target
= gimple_get_virt_method_for_vtable (ie
->indirect_info
->otr_token
,
1975 if ((TREE_CODE (TREE_TYPE (target
)) == FUNCTION_TYPE
1976 && DECL_FUNCTION_CODE (target
) == BUILT_IN_UNREACHABLE
)
1977 || !possible_polymorphic_call_target_p
1978 (ie
, cgraph_node::get (target
)))
1979 target
= ipa_impossible_devirt_target (ie
, target
);
1980 *speculative
= ie
->indirect_info
->vptr_changed
;
1987 /* Do we know the constant value of pointer? */
1989 t
= known_csts
[param_index
];
1991 gcc_checking_assert (!t
|| TREE_CODE (t
) != TREE_BINFO
);
1993 ipa_polymorphic_call_context context
;
1994 if (known_contexts
.length () > (unsigned int) param_index
)
1996 context
= known_contexts
[param_index
];
1997 context
.offset_by (anc_offset
);
1998 if (ie
->indirect_info
->vptr_changed
)
1999 context
.possible_dynamic_type_change (ie
->in_polymorphic_cdtor
,
2000 ie
->indirect_info
->otr_type
);
2003 ipa_polymorphic_call_context ctx2
= ipa_polymorphic_call_context
2004 (t
, ie
->indirect_info
->otr_type
, anc_offset
);
2005 if (!ctx2
.useless_p ())
2006 context
.combine_with (ctx2
, ie
->indirect_info
->otr_type
);
2011 context
= ipa_polymorphic_call_context (t
, ie
->indirect_info
->otr_type
,
2013 if (ie
->indirect_info
->vptr_changed
)
2014 context
.possible_dynamic_type_change (ie
->in_polymorphic_cdtor
,
2015 ie
->indirect_info
->otr_type
);
2020 vec
<cgraph_node
*>targets
;
2023 targets
= possible_polymorphic_call_targets
2024 (ie
->indirect_info
->otr_type
,
2025 ie
->indirect_info
->otr_token
,
2027 if (!final
|| targets
.length () > 1)
2029 struct cgraph_node
*node
;
2032 if (!opt_for_fn (ie
->caller
->decl
, flag_devirtualize_speculatively
)
2033 || ie
->speculative
|| !ie
->maybe_hot_p ())
2035 node
= try_speculative_devirtualization (ie
->indirect_info
->otr_type
,
2036 ie
->indirect_info
->otr_token
,
2040 *speculative
= true;
2041 target
= node
->decl
;
2048 *speculative
= false;
2049 if (targets
.length () == 1)
2050 target
= targets
[0]->decl
;
2052 target
= ipa_impossible_devirt_target (ie
, NULL_TREE
);
2055 if (target
&& !possible_polymorphic_call_target_p (ie
,
2056 cgraph_node::get (target
)))
2057 target
= ipa_impossible_devirt_target (ie
, target
);
2063 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2064 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2065 return the destination. */
2068 ipa_get_indirect_edge_target (struct cgraph_edge
*ie
,
2069 vec
<tree
> known_csts
,
2070 vec
<ipa_polymorphic_call_context
> known_contexts
,
2071 vec
<ipa_agg_jump_function_p
> known_aggs
,
2074 return ipa_get_indirect_edge_target_1 (ie
, known_csts
, known_contexts
,
2075 known_aggs
, NULL
, speculative
);
2078 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2079 and KNOWN_CONTEXTS. */
2082 devirtualization_time_bonus (struct cgraph_node
*node
,
2083 vec
<tree
> known_csts
,
2084 vec
<ipa_polymorphic_call_context
> known_contexts
,
2085 vec
<ipa_agg_jump_function_p
> known_aggs
)
2087 struct cgraph_edge
*ie
;
2090 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
2092 struct cgraph_node
*callee
;
2093 struct inline_summary
*isummary
;
2094 enum availability avail
;
2098 target
= ipa_get_indirect_edge_target (ie
, known_csts
, known_contexts
,
2099 known_aggs
, &speculative
);
2103 /* Only bare minimum benefit for clearly un-inlineable targets. */
2105 callee
= cgraph_node::get (target
);
2106 if (!callee
|| !callee
->definition
)
2108 callee
= callee
->function_symbol (&avail
);
2109 if (avail
< AVAIL_AVAILABLE
)
2111 isummary
= inline_summaries
->get (callee
);
2112 if (!isummary
->inlinable
)
2115 /* FIXME: The values below need re-considering and perhaps also
2116 integrating into the cost metrics, at lest in some very basic way. */
2117 if (isummary
->size
<= MAX_INLINE_INSNS_AUTO
/ 4)
2118 res
+= 31 / ((int)speculative
+ 1);
2119 else if (isummary
->size
<= MAX_INLINE_INSNS_AUTO
/ 2)
2120 res
+= 15 / ((int)speculative
+ 1);
2121 else if (isummary
->size
<= MAX_INLINE_INSNS_AUTO
2122 || DECL_DECLARED_INLINE_P (callee
->decl
))
2123 res
+= 7 / ((int)speculative
+ 1);
2129 /* Return time bonus incurred because of HINTS. */
2132 hint_time_bonus (inline_hints hints
)
2135 if (hints
& (INLINE_HINT_loop_iterations
| INLINE_HINT_loop_stride
))
2136 result
+= PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS
);
2137 if (hints
& INLINE_HINT_array_index
)
2138 result
+= PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS
);
2142 /* If there is a reason to penalize the function described by INFO in the
2143 cloning goodness evaluation, do so. */
2145 static inline int64_t
2146 incorporate_penalties (ipa_node_params
*info
, int64_t evaluation
)
2148 if (info
->node_within_scc
)
2149 evaluation
= (evaluation
2150 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY
))) / 100;
2152 if (info
->node_calling_single_call
)
2153 evaluation
= (evaluation
2154 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY
)))
2160 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2161 and SIZE_COST and with the sum of frequencies of incoming edges to the
2162 potential new clone in FREQUENCIES. */
2165 good_cloning_opportunity_p (struct cgraph_node
*node
, int time_benefit
,
2166 int freq_sum
, gcov_type count_sum
, int size_cost
)
2168 if (time_benefit
== 0
2169 || !opt_for_fn (node
->decl
, flag_ipa_cp_clone
)
2170 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node
->decl
)))
2173 gcc_assert (size_cost
> 0);
2175 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2178 int factor
= (count_sum
* 1000) / max_count
;
2179 int64_t evaluation
= (((int64_t) time_benefit
* factor
)
2181 evaluation
= incorporate_penalties (info
, evaluation
);
2183 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2184 fprintf (dump_file
, " good_cloning_opportunity_p (time: %i, "
2185 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2186 "%s%s) -> evaluation: " "%" PRId64
2187 ", threshold: %i\n",
2188 time_benefit
, size_cost
, (HOST_WIDE_INT
) count_sum
,
2189 info
->node_within_scc
? ", scc" : "",
2190 info
->node_calling_single_call
? ", single_call" : "",
2191 evaluation
, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
));
2193 return evaluation
>= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
);
2197 int64_t evaluation
= (((int64_t) time_benefit
* freq_sum
)
2199 evaluation
= incorporate_penalties (info
, evaluation
);
2201 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2202 fprintf (dump_file
, " good_cloning_opportunity_p (time: %i, "
2203 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2204 "%" PRId64
", threshold: %i\n",
2205 time_benefit
, size_cost
, freq_sum
,
2206 info
->node_within_scc
? ", scc" : "",
2207 info
->node_calling_single_call
? ", single_call" : "",
2208 evaluation
, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
));
2210 return evaluation
>= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
);
2214 /* Return all context independent values from aggregate lattices in PLATS in a
2215 vector. Return NULL if there are none. */
2217 static vec
<ipa_agg_jf_item
, va_gc
> *
2218 context_independent_aggregate_values (struct ipcp_param_lattices
*plats
)
2220 vec
<ipa_agg_jf_item
, va_gc
> *res
= NULL
;
2222 if (plats
->aggs_bottom
2223 || plats
->aggs_contain_variable
2224 || plats
->aggs_count
== 0)
2227 for (struct ipcp_agg_lattice
*aglat
= plats
->aggs
;
2229 aglat
= aglat
->next
)
2230 if (aglat
->is_single_const ())
2232 struct ipa_agg_jf_item item
;
2233 item
.offset
= aglat
->offset
;
2234 item
.value
= aglat
->values
->value
;
2235 vec_safe_push (res
, item
);
2240 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2241 populate them with values of parameters that are known independent of the
2242 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2243 non-NULL, the movement cost of all removable parameters will be stored in
2247 gather_context_independent_values (struct ipa_node_params
*info
,
2248 vec
<tree
> *known_csts
,
2249 vec
<ipa_polymorphic_call_context
>
2251 vec
<ipa_agg_jump_function
> *known_aggs
,
2252 int *removable_params_cost
)
2254 int i
, count
= ipa_get_param_count (info
);
2257 known_csts
->create (0);
2258 known_contexts
->create (0);
2259 known_csts
->safe_grow_cleared (count
);
2260 known_contexts
->safe_grow_cleared (count
);
2263 known_aggs
->create (0);
2264 known_aggs
->safe_grow_cleared (count
);
2267 if (removable_params_cost
)
2268 *removable_params_cost
= 0;
2270 for (i
= 0; i
< count
; i
++)
2272 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2273 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
2275 if (lat
->is_single_const ())
2277 ipcp_value
<tree
> *val
= lat
->values
;
2278 gcc_checking_assert (TREE_CODE (val
->value
) != TREE_BINFO
);
2279 (*known_csts
)[i
] = val
->value
;
2280 if (removable_params_cost
)
2281 *removable_params_cost
2282 += estimate_move_cost (TREE_TYPE (val
->value
), false);
2285 else if (removable_params_cost
2286 && !ipa_is_param_used (info
, i
))
2287 *removable_params_cost
2288 += ipa_get_param_move_cost (info
, i
);
2290 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
2291 if (ctxlat
->is_single_const ())
2293 (*known_contexts
)[i
] = ctxlat
->values
->value
;
2299 vec
<ipa_agg_jf_item
, va_gc
> *agg_items
;
2300 struct ipa_agg_jump_function
*ajf
;
2302 agg_items
= context_independent_aggregate_values (plats
);
2303 ajf
= &(*known_aggs
)[i
];
2304 ajf
->items
= agg_items
;
2305 ajf
->by_ref
= plats
->aggs_by_ref
;
2306 ret
|= agg_items
!= NULL
;
2313 /* The current interface in ipa-inline-analysis requires a pointer vector.
2316 FIXME: That interface should be re-worked, this is slightly silly. Still,
2317 I'd like to discuss how to change it first and this demonstrates the
2320 static vec
<ipa_agg_jump_function_p
>
2321 agg_jmp_p_vec_for_t_vec (vec
<ipa_agg_jump_function
> known_aggs
)
2323 vec
<ipa_agg_jump_function_p
> ret
;
2324 struct ipa_agg_jump_function
*ajf
;
2327 ret
.create (known_aggs
.length ());
2328 FOR_EACH_VEC_ELT (known_aggs
, i
, ajf
)
2329 ret
.quick_push (ajf
);
2333 /* Perform time and size measurement of NODE with the context given in
2334 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2335 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2336 all context-independent removable parameters and EST_MOVE_COST of estimated
2337 movement of the considered parameter and store it into VAL. */
2340 perform_estimation_of_a_value (cgraph_node
*node
, vec
<tree
> known_csts
,
2341 vec
<ipa_polymorphic_call_context
> known_contexts
,
2342 vec
<ipa_agg_jump_function_p
> known_aggs_ptrs
,
2343 int base_time
, int removable_params_cost
,
2344 int est_move_cost
, ipcp_value_base
*val
)
2346 int time
, size
, time_benefit
;
2349 estimate_ipcp_clone_size_and_time (node
, known_csts
, known_contexts
,
2350 known_aggs_ptrs
, &size
, &time
,
2352 time_benefit
= base_time
- time
2353 + devirtualization_time_bonus (node
, known_csts
, known_contexts
,
2355 + hint_time_bonus (hints
)
2356 + removable_params_cost
+ est_move_cost
;
2358 gcc_checking_assert (size
>=0);
2359 /* The inliner-heuristics based estimates may think that in certain
2360 contexts some functions do not have any size at all but we want
2361 all specializations to have at least a tiny cost, not least not to
2366 val
->local_time_benefit
= time_benefit
;
2367 val
->local_size_cost
= size
;
2370 /* Iterate over known values of parameters of NODE and estimate the local
2371 effects in terms of time and size they have. */
2374 estimate_local_effects (struct cgraph_node
*node
)
2376 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2377 int i
, count
= ipa_get_param_count (info
);
2378 vec
<tree
> known_csts
;
2379 vec
<ipa_polymorphic_call_context
> known_contexts
;
2380 vec
<ipa_agg_jump_function
> known_aggs
;
2381 vec
<ipa_agg_jump_function_p
> known_aggs_ptrs
;
2383 int base_time
= inline_summaries
->get (node
)->time
;
2384 int removable_params_cost
;
2386 if (!count
|| !ipcp_versionable_function_p (node
))
2389 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2390 fprintf (dump_file
, "\nEstimating effects for %s/%i, base_time: %i.\n",
2391 node
->name (), node
->order
, base_time
);
2393 always_const
= gather_context_independent_values (info
, &known_csts
,
2394 &known_contexts
, &known_aggs
,
2395 &removable_params_cost
);
2396 known_aggs_ptrs
= agg_jmp_p_vec_for_t_vec (known_aggs
);
2399 struct caller_statistics stats
;
2403 init_caller_stats (&stats
);
2404 node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
2406 estimate_ipcp_clone_size_and_time (node
, known_csts
, known_contexts
,
2407 known_aggs_ptrs
, &size
, &time
, &hints
);
2408 time
-= devirtualization_time_bonus (node
, known_csts
, known_contexts
,
2410 time
-= hint_time_bonus (hints
);
2411 time
-= removable_params_cost
;
2412 size
-= stats
.n_calls
* removable_params_cost
;
2415 fprintf (dump_file
, " - context independent values, size: %i, "
2416 "time_benefit: %i\n", size
, base_time
- time
);
2419 || node
->will_be_removed_from_program_if_no_direct_calls_p ())
2421 info
->do_clone_for_all_contexts
= true;
2425 fprintf (dump_file
, " Decided to specialize for all "
2426 "known contexts, code not going to grow.\n");
2428 else if (good_cloning_opportunity_p (node
, base_time
- time
,
2429 stats
.freq_sum
, stats
.count_sum
,
2432 if (size
+ overall_size
<= max_new_size
)
2434 info
->do_clone_for_all_contexts
= true;
2436 overall_size
+= size
;
2439 fprintf (dump_file
, " Decided to specialize for all "
2440 "known contexts, growth deemed beneficial.\n");
2442 else if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2443 fprintf (dump_file
, " Not cloning for all contexts because "
2444 "max_new_size would be reached with %li.\n",
2445 size
+ overall_size
);
2449 for (i
= 0; i
< count
; i
++)
2451 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2452 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
2453 ipcp_value
<tree
> *val
;
2460 for (val
= lat
->values
; val
; val
= val
->next
)
2462 gcc_checking_assert (TREE_CODE (val
->value
) != TREE_BINFO
);
2463 known_csts
[i
] = val
->value
;
2465 int emc
= estimate_move_cost (TREE_TYPE (val
->value
), true);
2466 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
2467 known_aggs_ptrs
, base_time
,
2468 removable_params_cost
, emc
, val
);
2470 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2472 fprintf (dump_file
, " - estimates for value ");
2473 print_ipcp_constant_value (dump_file
, val
->value
);
2474 fprintf (dump_file
, " for ");
2475 ipa_dump_param (dump_file
, info
, i
);
2476 fprintf (dump_file
, ": time_benefit: %i, size: %i\n",
2477 val
->local_time_benefit
, val
->local_size_cost
);
2480 known_csts
[i
] = NULL_TREE
;
2483 for (i
= 0; i
< count
; i
++)
2485 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2487 if (!plats
->virt_call
)
2490 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
2491 ipcp_value
<ipa_polymorphic_call_context
> *val
;
2495 || !known_contexts
[i
].useless_p ())
2498 for (val
= ctxlat
->values
; val
; val
= val
->next
)
2500 known_contexts
[i
] = val
->value
;
2501 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
2502 known_aggs_ptrs
, base_time
,
2503 removable_params_cost
, 0, val
);
2505 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2507 fprintf (dump_file
, " - estimates for polymorphic context ");
2508 print_ipcp_constant_value (dump_file
, val
->value
);
2509 fprintf (dump_file
, " for ");
2510 ipa_dump_param (dump_file
, info
, i
);
2511 fprintf (dump_file
, ": time_benefit: %i, size: %i\n",
2512 val
->local_time_benefit
, val
->local_size_cost
);
2515 known_contexts
[i
] = ipa_polymorphic_call_context ();
2518 for (i
= 0; i
< count
; i
++)
2520 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2521 struct ipa_agg_jump_function
*ajf
;
2522 struct ipcp_agg_lattice
*aglat
;
2524 if (plats
->aggs_bottom
|| !plats
->aggs
)
2527 ajf
= &known_aggs
[i
];
2528 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
2530 ipcp_value
<tree
> *val
;
2531 if (aglat
->bottom
|| !aglat
->values
2532 /* If the following is true, the one value is in known_aggs. */
2533 || (!plats
->aggs_contain_variable
2534 && aglat
->is_single_const ()))
2537 for (val
= aglat
->values
; val
; val
= val
->next
)
2539 struct ipa_agg_jf_item item
;
2541 item
.offset
= aglat
->offset
;
2542 item
.value
= val
->value
;
2543 vec_safe_push (ajf
->items
, item
);
2545 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
2546 known_aggs_ptrs
, base_time
,
2547 removable_params_cost
, 0, val
);
2549 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2551 fprintf (dump_file
, " - estimates for value ");
2552 print_ipcp_constant_value (dump_file
, val
->value
);
2553 fprintf (dump_file
, " for ");
2554 ipa_dump_param (dump_file
, info
, i
);
2555 fprintf (dump_file
, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2556 "]: time_benefit: %i, size: %i\n",
2557 plats
->aggs_by_ref
? "ref " : "",
2559 val
->local_time_benefit
, val
->local_size_cost
);
2567 for (i
= 0; i
< count
; i
++)
2568 vec_free (known_aggs
[i
].items
);
2570 known_csts
.release ();
2571 known_contexts
.release ();
2572 known_aggs
.release ();
2573 known_aggs_ptrs
.release ();
2577 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2578 topological sort of values. */
2580 template <typename valtype
>
2582 value_topo_info
<valtype
>::add_val (ipcp_value
<valtype
> *cur_val
)
2584 ipcp_value_source
<valtype
> *src
;
2590 cur_val
->dfs
= dfs_counter
;
2591 cur_val
->low_link
= dfs_counter
;
2593 cur_val
->topo_next
= stack
;
2595 cur_val
->on_stack
= true;
2597 for (src
= cur_val
->sources
; src
; src
= src
->next
)
2600 if (src
->val
->dfs
== 0)
2603 if (src
->val
->low_link
< cur_val
->low_link
)
2604 cur_val
->low_link
= src
->val
->low_link
;
2606 else if (src
->val
->on_stack
2607 && src
->val
->dfs
< cur_val
->low_link
)
2608 cur_val
->low_link
= src
->val
->dfs
;
2611 if (cur_val
->dfs
== cur_val
->low_link
)
2613 ipcp_value
<valtype
> *v
, *scc_list
= NULL
;
2618 stack
= v
->topo_next
;
2619 v
->on_stack
= false;
2621 v
->scc_next
= scc_list
;
2624 while (v
!= cur_val
);
2626 cur_val
->topo_next
= values_topo
;
2627 values_topo
= cur_val
;
2631 /* Add all values in lattices associated with NODE to the topological sort if
2632 they are not there yet. */
2635 add_all_node_vals_to_toposort (cgraph_node
*node
, ipa_topo_info
*topo
)
2637 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2638 int i
, count
= ipa_get_param_count (info
);
2640 for (i
= 0; i
< count
; i
++)
2642 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2643 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
2644 struct ipcp_agg_lattice
*aglat
;
2648 ipcp_value
<tree
> *val
;
2649 for (val
= lat
->values
; val
; val
= val
->next
)
2650 topo
->constants
.add_val (val
);
2653 if (!plats
->aggs_bottom
)
2654 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
2657 ipcp_value
<tree
> *val
;
2658 for (val
= aglat
->values
; val
; val
= val
->next
)
2659 topo
->constants
.add_val (val
);
2662 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
2663 if (!ctxlat
->bottom
)
2665 ipcp_value
<ipa_polymorphic_call_context
> *ctxval
;
2666 for (ctxval
= ctxlat
->values
; ctxval
; ctxval
= ctxval
->next
)
2667 topo
->contexts
.add_val (ctxval
);
2672 /* One pass of constants propagation along the call graph edges, from callers
2673 to callees (requires topological ordering in TOPO), iterate over strongly
2674 connected components. */
2677 propagate_constants_topo (struct ipa_topo_info
*topo
)
2681 for (i
= topo
->nnodes
- 1; i
>= 0; i
--)
2684 struct cgraph_node
*v
, *node
= topo
->order
[i
];
2685 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
2687 /* First, iteratively propagate within the strongly connected component
2688 until all lattices stabilize. */
2689 FOR_EACH_VEC_ELT (cycle_nodes
, j
, v
)
2690 if (v
->has_gimple_body_p ())
2691 push_node_to_stack (topo
, v
);
2693 v
= pop_node_from_stack (topo
);
2696 struct cgraph_edge
*cs
;
2698 for (cs
= v
->callees
; cs
; cs
= cs
->next_callee
)
2699 if (ipa_edge_within_scc (cs
))
2701 IPA_NODE_REF (v
)->node_within_scc
= true;
2702 if (propagate_constants_accross_call (cs
))
2703 push_node_to_stack (topo
, cs
->callee
->function_symbol ());
2705 v
= pop_node_from_stack (topo
);
2708 /* Afterwards, propagate along edges leading out of the SCC, calculates
2709 the local effects of the discovered constants and all valid values to
2710 their topological sort. */
2711 FOR_EACH_VEC_ELT (cycle_nodes
, j
, v
)
2712 if (v
->has_gimple_body_p ())
2714 struct cgraph_edge
*cs
;
2716 estimate_local_effects (v
);
2717 add_all_node_vals_to_toposort (v
, topo
);
2718 for (cs
= v
->callees
; cs
; cs
= cs
->next_callee
)
2719 if (!ipa_edge_within_scc (cs
))
2720 propagate_constants_accross_call (cs
);
2722 cycle_nodes
.release ();
2727 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2728 the bigger one if otherwise. */
2731 safe_add (int a
, int b
)
2733 if (a
> INT_MAX
/2 || b
> INT_MAX
/2)
2734 return a
> b
? a
: b
;
2740 /* Propagate the estimated effects of individual values along the topological
2741 from the dependent values to those they depend on. */
2743 template <typename valtype
>
2745 value_topo_info
<valtype
>::propagate_effects ()
2747 ipcp_value
<valtype
> *base
;
2749 for (base
= values_topo
; base
; base
= base
->topo_next
)
2751 ipcp_value_source
<valtype
> *src
;
2752 ipcp_value
<valtype
> *val
;
2753 int time
= 0, size
= 0;
2755 for (val
= base
; val
; val
= val
->scc_next
)
2757 time
= safe_add (time
,
2758 val
->local_time_benefit
+ val
->prop_time_benefit
);
2759 size
= safe_add (size
, val
->local_size_cost
+ val
->prop_size_cost
);
2762 for (val
= base
; val
; val
= val
->scc_next
)
2763 for (src
= val
->sources
; src
; src
= src
->next
)
2765 && src
->cs
->maybe_hot_p ())
2767 src
->val
->prop_time_benefit
= safe_add (time
,
2768 src
->val
->prop_time_benefit
);
2769 src
->val
->prop_size_cost
= safe_add (size
,
2770 src
->val
->prop_size_cost
);
2776 /* Propagate constants, polymorphic contexts and their effects from the
2777 summaries interprocedurally. */
2780 ipcp_propagate_stage (struct ipa_topo_info
*topo
)
2782 struct cgraph_node
*node
;
2785 fprintf (dump_file
, "\n Propagating constants:\n\n");
2788 ipa_update_after_lto_read ();
2791 FOR_EACH_DEFINED_FUNCTION (node
)
2793 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2795 determine_versionability (node
);
2796 if (node
->has_gimple_body_p ())
2798 info
->lattices
= XCNEWVEC (struct ipcp_param_lattices
,
2799 ipa_get_param_count (info
));
2800 initialize_node_lattices (node
);
2802 if (node
->definition
&& !node
->alias
)
2803 overall_size
+= inline_summaries
->get (node
)->self_size
;
2804 if (node
->count
> max_count
)
2805 max_count
= node
->count
;
2808 max_new_size
= overall_size
;
2809 if (max_new_size
< PARAM_VALUE (PARAM_LARGE_UNIT_INSNS
))
2810 max_new_size
= PARAM_VALUE (PARAM_LARGE_UNIT_INSNS
);
2811 max_new_size
+= max_new_size
* PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH
) / 100 + 1;
2814 fprintf (dump_file
, "\noverall_size: %li, max_new_size: %li\n",
2815 overall_size
, max_new_size
);
2817 propagate_constants_topo (topo
);
2818 #ifdef ENABLE_CHECKING
2819 ipcp_verify_propagated_values ();
2821 topo
->constants
.propagate_effects ();
2822 topo
->contexts
.propagate_effects ();
2826 fprintf (dump_file
, "\nIPA lattices after all propagation:\n");
2827 print_all_lattices (dump_file
, (dump_flags
& TDF_DETAILS
), true);
2831 /* Discover newly direct outgoing edges from NODE which is a new clone with
2832 known KNOWN_CSTS and make them direct. */
2835 ipcp_discover_new_direct_edges (struct cgraph_node
*node
,
2836 vec
<tree
> known_csts
,
2837 vec
<ipa_polymorphic_call_context
>
2839 struct ipa_agg_replacement_value
*aggvals
)
2841 struct cgraph_edge
*ie
, *next_ie
;
2844 for (ie
= node
->indirect_calls
; ie
; ie
= next_ie
)
2849 next_ie
= ie
->next_callee
;
2850 target
= ipa_get_indirect_edge_target_1 (ie
, known_csts
, known_contexts
,
2851 vNULL
, aggvals
, &speculative
);
2854 bool agg_contents
= ie
->indirect_info
->agg_contents
;
2855 bool polymorphic
= ie
->indirect_info
->polymorphic
;
2856 int param_index
= ie
->indirect_info
->param_index
;
2857 struct cgraph_edge
*cs
= ipa_make_edge_direct_to_target (ie
, target
,
2861 if (cs
&& !agg_contents
&& !polymorphic
)
2863 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2864 int c
= ipa_get_controlled_uses (info
, param_index
);
2865 if (c
!= IPA_UNDESCRIBED_USE
)
2867 struct ipa_ref
*to_del
;
2870 ipa_set_controlled_uses (info
, param_index
, c
);
2871 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2872 fprintf (dump_file
, " controlled uses count of param "
2873 "%i bumped down to %i\n", param_index
, c
);
2875 && (to_del
= node
->find_reference (cs
->callee
, NULL
, 0)))
2877 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2878 fprintf (dump_file
, " and even removing its "
2879 "cloning-created reference\n");
2880 to_del
->remove_reference ();
2886 /* Turning calls to direct calls will improve overall summary. */
2888 inline_update_overall_summary (node
);
2891 /* Vector of pointers which for linked lists of clones of an original crgaph
2894 static vec
<cgraph_edge
*> next_edge_clone
;
2895 static vec
<cgraph_edge
*> prev_edge_clone
;
2898 grow_edge_clone_vectors (void)
2900 if (next_edge_clone
.length ()
2901 <= (unsigned) symtab
->edges_max_uid
)
2902 next_edge_clone
.safe_grow_cleared (symtab
->edges_max_uid
+ 1);
2903 if (prev_edge_clone
.length ()
2904 <= (unsigned) symtab
->edges_max_uid
)
2905 prev_edge_clone
.safe_grow_cleared (symtab
->edges_max_uid
+ 1);
2908 /* Edge duplication hook to grow the appropriate linked list in
2912 ipcp_edge_duplication_hook (struct cgraph_edge
*src
, struct cgraph_edge
*dst
,
2915 grow_edge_clone_vectors ();
2917 struct cgraph_edge
*old_next
= next_edge_clone
[src
->uid
];
2919 prev_edge_clone
[old_next
->uid
] = dst
;
2920 prev_edge_clone
[dst
->uid
] = src
;
2922 next_edge_clone
[dst
->uid
] = old_next
;
2923 next_edge_clone
[src
->uid
] = dst
;
2926 /* Hook that is called by cgraph.c when an edge is removed. */
2929 ipcp_edge_removal_hook (struct cgraph_edge
*cs
, void *)
2931 grow_edge_clone_vectors ();
2933 struct cgraph_edge
*prev
= prev_edge_clone
[cs
->uid
];
2934 struct cgraph_edge
*next
= next_edge_clone
[cs
->uid
];
2936 next_edge_clone
[prev
->uid
] = next
;
2938 prev_edge_clone
[next
->uid
] = prev
;
2941 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2942 parameter with the given INDEX. */
2945 get_clone_agg_value (struct cgraph_node
*node
, HOST_WIDE_INT offset
,
2948 struct ipa_agg_replacement_value
*aggval
;
2950 aggval
= ipa_get_agg_replacements_for_node (node
);
2953 if (aggval
->offset
== offset
2954 && aggval
->index
== index
)
2955 return aggval
->value
;
2956 aggval
= aggval
->next
;
2961 /* Return true is NODE is DEST or its clone for all contexts. */
2964 same_node_or_its_all_contexts_clone_p (cgraph_node
*node
, cgraph_node
*dest
)
2969 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2970 return info
->is_all_contexts_clone
&& info
->ipcp_orig_node
== dest
;
2973 /* Return true if edge CS does bring about the value described by SRC to node
2974 DEST or its clone for all contexts. */
2977 cgraph_edge_brings_value_p (cgraph_edge
*cs
, ipcp_value_source
<tree
> *src
,
2980 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
2981 enum availability availability
;
2982 cgraph_node
*real_dest
= cs
->callee
->function_symbol (&availability
);
2984 if (!same_node_or_its_all_contexts_clone_p (real_dest
, dest
)
2985 || availability
<= AVAIL_INTERPOSABLE
2986 || caller_info
->node_dead
)
2991 if (caller_info
->ipcp_orig_node
)
2994 if (src
->offset
== -1)
2995 t
= caller_info
->known_csts
[src
->index
];
2997 t
= get_clone_agg_value (cs
->caller
, src
->offset
, src
->index
);
2998 return (t
!= NULL_TREE
2999 && values_equal_for_ipcp_p (src
->val
->value
, t
));
3003 struct ipcp_agg_lattice
*aglat
;
3004 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (caller_info
,
3006 if (src
->offset
== -1)
3007 return (plats
->itself
.is_single_const ()
3008 && values_equal_for_ipcp_p (src
->val
->value
,
3009 plats
->itself
.values
->value
));
3012 if (plats
->aggs_bottom
|| plats
->aggs_contain_variable
)
3014 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
3015 if (aglat
->offset
== src
->offset
)
3016 return (aglat
->is_single_const ()
3017 && values_equal_for_ipcp_p (src
->val
->value
,
3018 aglat
->values
->value
));
3024 /* Return true if edge CS does bring about the value described by SRC to node
3025 DEST or its clone for all contexts. */
3028 cgraph_edge_brings_value_p (cgraph_edge
*cs
,
3029 ipcp_value_source
<ipa_polymorphic_call_context
> *src
,
3032 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3033 cgraph_node
*real_dest
= cs
->callee
->function_symbol ();
3035 if (!same_node_or_its_all_contexts_clone_p (real_dest
, dest
)
3036 || caller_info
->node_dead
)
3041 if (caller_info
->ipcp_orig_node
)
3042 return (caller_info
->known_contexts
.length () > (unsigned) src
->index
)
3043 && values_equal_for_ipcp_p (src
->val
->value
,
3044 caller_info
->known_contexts
[src
->index
]);
3046 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (caller_info
,
3048 return plats
->ctxlat
.is_single_const ()
3049 && values_equal_for_ipcp_p (src
->val
->value
,
3050 plats
->ctxlat
.values
->value
);
3053 /* Get the next clone in the linked list of clones of an edge. */
3055 static inline struct cgraph_edge
*
3056 get_next_cgraph_edge_clone (struct cgraph_edge
*cs
)
3058 return next_edge_clone
[cs
->uid
];
3061 /* Given VAL that is intended for DEST, iterate over all its sources and if
3062 they still hold, add their edge frequency and their number into *FREQUENCY
3063 and *CALLER_COUNT respectively. */
3065 template <typename valtype
>
3067 get_info_about_necessary_edges (ipcp_value
<valtype
> *val
, cgraph_node
*dest
,
3069 gcov_type
*count_sum
, int *caller_count
)
3071 ipcp_value_source
<valtype
> *src
;
3072 int freq
= 0, count
= 0;
3076 for (src
= val
->sources
; src
; src
= src
->next
)
3078 struct cgraph_edge
*cs
= src
->cs
;
3081 if (cgraph_edge_brings_value_p (cs
, src
, dest
))
3084 freq
+= cs
->frequency
;
3086 hot
|= cs
->maybe_hot_p ();
3088 cs
= get_next_cgraph_edge_clone (cs
);
3094 *caller_count
= count
;
3098 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3099 is assumed their number is known and equal to CALLER_COUNT. */
3101 template <typename valtype
>
3102 static vec
<cgraph_edge
*>
3103 gather_edges_for_value (ipcp_value
<valtype
> *val
, cgraph_node
*dest
,
3106 ipcp_value_source
<valtype
> *src
;
3107 vec
<cgraph_edge
*> ret
;
3109 ret
.create (caller_count
);
3110 for (src
= val
->sources
; src
; src
= src
->next
)
3112 struct cgraph_edge
*cs
= src
->cs
;
3115 if (cgraph_edge_brings_value_p (cs
, src
, dest
))
3116 ret
.quick_push (cs
);
3117 cs
= get_next_cgraph_edge_clone (cs
);
3124 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3125 Return it or NULL if for some reason it cannot be created. */
3127 static struct ipa_replace_map
*
3128 get_replacement_map (struct ipa_node_params
*info
, tree value
, int parm_num
)
3130 struct ipa_replace_map
*replace_map
;
3133 replace_map
= ggc_alloc
<ipa_replace_map
> ();
3136 fprintf (dump_file
, " replacing ");
3137 ipa_dump_param (dump_file
, info
, parm_num
);
3139 fprintf (dump_file
, " with const ");
3140 print_generic_expr (dump_file
, value
, 0);
3141 fprintf (dump_file
, "\n");
3143 replace_map
->old_tree
= NULL
;
3144 replace_map
->parm_num
= parm_num
;
3145 replace_map
->new_tree
= value
;
3146 replace_map
->replace_p
= true;
3147 replace_map
->ref_p
= false;
3152 /* Dump new profiling counts */
3155 dump_profile_updates (struct cgraph_node
*orig_node
,
3156 struct cgraph_node
*new_node
)
3158 struct cgraph_edge
*cs
;
3160 fprintf (dump_file
, " setting count of the specialized node to "
3161 HOST_WIDE_INT_PRINT_DEC
"\n", (HOST_WIDE_INT
) new_node
->count
);
3162 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3163 fprintf (dump_file
, " edge to %s has count "
3164 HOST_WIDE_INT_PRINT_DEC
"\n",
3165 cs
->callee
->name (), (HOST_WIDE_INT
) cs
->count
);
3167 fprintf (dump_file
, " setting count of the original node to "
3168 HOST_WIDE_INT_PRINT_DEC
"\n", (HOST_WIDE_INT
) orig_node
->count
);
3169 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3170 fprintf (dump_file
, " edge to %s is left with "
3171 HOST_WIDE_INT_PRINT_DEC
"\n",
3172 cs
->callee
->name (), (HOST_WIDE_INT
) cs
->count
);
3175 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3176 their profile information to reflect this. */
3179 update_profiling_info (struct cgraph_node
*orig_node
,
3180 struct cgraph_node
*new_node
)
3182 struct cgraph_edge
*cs
;
3183 struct caller_statistics stats
;
3184 gcov_type new_sum
, orig_sum
;
3185 gcov_type remainder
, orig_node_count
= orig_node
->count
;
3187 if (orig_node_count
== 0)
3190 init_caller_stats (&stats
);
3191 orig_node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
3193 orig_sum
= stats
.count_sum
;
3194 init_caller_stats (&stats
);
3195 new_node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
3197 new_sum
= stats
.count_sum
;
3199 if (orig_node_count
< orig_sum
+ new_sum
)
3202 fprintf (dump_file
, " Problem: node %s/%i has too low count "
3203 HOST_WIDE_INT_PRINT_DEC
" while the sum of incoming "
3204 "counts is " HOST_WIDE_INT_PRINT_DEC
"\n",
3205 orig_node
->name (), orig_node
->order
,
3206 (HOST_WIDE_INT
) orig_node_count
,
3207 (HOST_WIDE_INT
) (orig_sum
+ new_sum
));
3209 orig_node_count
= (orig_sum
+ new_sum
) * 12 / 10;
3211 fprintf (dump_file
, " proceeding by pretending it was "
3212 HOST_WIDE_INT_PRINT_DEC
"\n",
3213 (HOST_WIDE_INT
) orig_node_count
);
3216 new_node
->count
= new_sum
;
3217 remainder
= orig_node_count
- new_sum
;
3218 orig_node
->count
= remainder
;
3220 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3222 cs
->count
= apply_probability (cs
->count
,
3223 GCOV_COMPUTE_SCALE (new_sum
,
3228 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3229 cs
->count
= apply_probability (cs
->count
,
3230 GCOV_COMPUTE_SCALE (remainder
,
3234 dump_profile_updates (orig_node
, new_node
);
3237 /* Update the respective profile of specialized NEW_NODE and the original
3238 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3239 have been redirected to the specialized version. */
3242 update_specialized_profile (struct cgraph_node
*new_node
,
3243 struct cgraph_node
*orig_node
,
3244 gcov_type redirected_sum
)
3246 struct cgraph_edge
*cs
;
3247 gcov_type new_node_count
, orig_node_count
= orig_node
->count
;
3250 fprintf (dump_file
, " the sum of counts of redirected edges is "
3251 HOST_WIDE_INT_PRINT_DEC
"\n", (HOST_WIDE_INT
) redirected_sum
);
3252 if (orig_node_count
== 0)
3255 gcc_assert (orig_node_count
>= redirected_sum
);
3257 new_node_count
= new_node
->count
;
3258 new_node
->count
+= redirected_sum
;
3259 orig_node
->count
-= redirected_sum
;
3261 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3263 cs
->count
+= apply_probability (cs
->count
,
3264 GCOV_COMPUTE_SCALE (redirected_sum
,
3269 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3271 gcov_type dec
= apply_probability (cs
->count
,
3272 GCOV_COMPUTE_SCALE (redirected_sum
,
3274 if (dec
< cs
->count
)
3281 dump_profile_updates (orig_node
, new_node
);
3284 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3285 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3286 redirect all edges in CALLERS to it. */
3288 static struct cgraph_node
*
3289 create_specialized_node (struct cgraph_node
*node
,
3290 vec
<tree
> known_csts
,
3291 vec
<ipa_polymorphic_call_context
> known_contexts
,
3292 struct ipa_agg_replacement_value
*aggvals
,
3293 vec
<cgraph_edge
*> callers
)
3295 struct ipa_node_params
*new_info
, *info
= IPA_NODE_REF (node
);
3296 vec
<ipa_replace_map
*, va_gc
> *replace_trees
= NULL
;
3297 struct ipa_agg_replacement_value
*av
;
3298 struct cgraph_node
*new_node
;
3299 int i
, count
= ipa_get_param_count (info
);
3300 bitmap args_to_skip
;
3302 gcc_assert (!info
->ipcp_orig_node
);
3304 if (node
->local
.can_change_signature
)
3306 args_to_skip
= BITMAP_GGC_ALLOC ();
3307 for (i
= 0; i
< count
; i
++)
3309 tree t
= known_csts
[i
];
3311 if (t
|| !ipa_is_param_used (info
, i
))
3312 bitmap_set_bit (args_to_skip
, i
);
3317 args_to_skip
= NULL
;
3318 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3319 fprintf (dump_file
, " cannot change function signature\n");
3322 for (i
= 0; i
< count
; i
++)
3324 tree t
= known_csts
[i
];
3327 struct ipa_replace_map
*replace_map
;
3329 gcc_checking_assert (TREE_CODE (t
) != TREE_BINFO
);
3330 replace_map
= get_replacement_map (info
, t
, i
);
3332 vec_safe_push (replace_trees
, replace_map
);
3336 new_node
= node
->create_virtual_clone (callers
, replace_trees
,
3337 args_to_skip
, "constprop");
3338 ipa_set_node_agg_value_chain (new_node
, aggvals
);
3339 for (av
= aggvals
; av
; av
= av
->next
)
3340 new_node
->maybe_create_reference (av
->value
, IPA_REF_ADDR
, NULL
);
3342 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3344 fprintf (dump_file
, " the new node is %s/%i.\n",
3345 new_node
->name (), new_node
->order
);
3346 if (known_contexts
.exists ())
3348 for (i
= 0; i
< count
; i
++)
3349 if (!known_contexts
[i
].useless_p ())
3351 fprintf (dump_file
, " known ctx %i is ", i
);
3352 known_contexts
[i
].dump (dump_file
);
3356 ipa_dump_agg_replacement_values (dump_file
, aggvals
);
3358 ipa_check_create_node_params ();
3359 update_profiling_info (node
, new_node
);
3360 new_info
= IPA_NODE_REF (new_node
);
3361 new_info
->ipcp_orig_node
= node
;
3362 new_info
->known_csts
= known_csts
;
3363 new_info
->known_contexts
= known_contexts
;
3365 ipcp_discover_new_direct_edges (new_node
, known_csts
, known_contexts
, aggvals
);
3371 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3372 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3375 find_more_scalar_values_for_callers_subset (struct cgraph_node
*node
,
3376 vec
<tree
> known_csts
,
3377 vec
<cgraph_edge
*> callers
)
3379 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
3380 int i
, count
= ipa_get_param_count (info
);
3382 for (i
= 0; i
< count
; i
++)
3384 struct cgraph_edge
*cs
;
3385 tree newval
= NULL_TREE
;
3389 if (ipa_get_scalar_lat (info
, i
)->bottom
|| known_csts
[i
])
3392 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3394 struct ipa_jump_func
*jump_func
;
3397 if (i
>= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
)))
3402 jump_func
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
), i
);
3403 t
= ipa_value_from_jfunc (IPA_NODE_REF (cs
->caller
), jump_func
);
3406 && !values_equal_for_ipcp_p (t
, newval
))
3407 || (!first
&& !newval
))
3419 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3421 fprintf (dump_file
, " adding an extra known scalar value ");
3422 print_ipcp_constant_value (dump_file
, newval
);
3423 fprintf (dump_file
, " for ");
3424 ipa_dump_param (dump_file
, info
, i
);
3425 fprintf (dump_file
, "\n");
3428 known_csts
[i
] = newval
;
3433 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3434 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3438 find_more_contexts_for_caller_subset (cgraph_node
*node
,
3439 vec
<ipa_polymorphic_call_context
>
3441 vec
<cgraph_edge
*> callers
)
3443 ipa_node_params
*info
= IPA_NODE_REF (node
);
3444 int i
, count
= ipa_get_param_count (info
);
3446 for (i
= 0; i
< count
; i
++)
3450 if (ipa_get_poly_ctx_lat (info
, i
)->bottom
3451 || (known_contexts
->exists ()
3452 && !(*known_contexts
)[i
].useless_p ()))
3455 ipa_polymorphic_call_context newval
;
3459 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3461 if (i
>= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
)))
3463 ipa_jump_func
*jfunc
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
),
3465 ipa_polymorphic_call_context ctx
;
3466 ctx
= ipa_context_from_jfunc (IPA_NODE_REF (cs
->caller
), cs
, i
,
3474 newval
.meet_with (ctx
);
3475 if (newval
.useless_p ())
3479 if (!newval
.useless_p ())
3481 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3483 fprintf (dump_file
, " adding an extra known polymorphic "
3485 print_ipcp_constant_value (dump_file
, newval
);
3486 fprintf (dump_file
, " for ");
3487 ipa_dump_param (dump_file
, info
, i
);
3488 fprintf (dump_file
, "\n");
3491 if (!known_contexts
->exists ())
3492 known_contexts
->safe_grow_cleared (ipa_get_param_count (info
));
3493 (*known_contexts
)[i
] = newval
;
3499 /* Go through PLATS and create a vector of values consisting of values and
3500 offsets (minus OFFSET) of lattices that contain only a single value. */
3502 static vec
<ipa_agg_jf_item
>
3503 copy_plats_to_inter (struct ipcp_param_lattices
*plats
, HOST_WIDE_INT offset
)
3505 vec
<ipa_agg_jf_item
> res
= vNULL
;
3507 if (!plats
->aggs
|| plats
->aggs_contain_variable
|| plats
->aggs_bottom
)
3510 for (struct ipcp_agg_lattice
*aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
3511 if (aglat
->is_single_const ())
3513 struct ipa_agg_jf_item ti
;
3514 ti
.offset
= aglat
->offset
- offset
;
3515 ti
.value
= aglat
->values
->value
;
3521 /* Intersect all values in INTER with single value lattices in PLATS (while
3522 subtracting OFFSET). */
3525 intersect_with_plats (struct ipcp_param_lattices
*plats
,
3526 vec
<ipa_agg_jf_item
> *inter
,
3527 HOST_WIDE_INT offset
)
3529 struct ipcp_agg_lattice
*aglat
;
3530 struct ipa_agg_jf_item
*item
;
3533 if (!plats
->aggs
|| plats
->aggs_contain_variable
|| plats
->aggs_bottom
)
3539 aglat
= plats
->aggs
;
3540 FOR_EACH_VEC_ELT (*inter
, k
, item
)
3547 if (aglat
->offset
- offset
> item
->offset
)
3549 if (aglat
->offset
- offset
== item
->offset
)
3551 gcc_checking_assert (item
->value
);
3552 if (values_equal_for_ipcp_p (item
->value
, aglat
->values
->value
))
3556 aglat
= aglat
->next
;
3559 item
->value
= NULL_TREE
;
3563 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3564 vector result while subtracting OFFSET from the individual value offsets. */
3566 static vec
<ipa_agg_jf_item
>
3567 agg_replacements_to_vector (struct cgraph_node
*node
, int index
,
3568 HOST_WIDE_INT offset
)
3570 struct ipa_agg_replacement_value
*av
;
3571 vec
<ipa_agg_jf_item
> res
= vNULL
;
3573 for (av
= ipa_get_agg_replacements_for_node (node
); av
; av
= av
->next
)
3574 if (av
->index
== index
3575 && (av
->offset
- offset
) >= 0)
3577 struct ipa_agg_jf_item item
;
3578 gcc_checking_assert (av
->value
);
3579 item
.offset
= av
->offset
- offset
;
3580 item
.value
= av
->value
;
3581 res
.safe_push (item
);
3587 /* Intersect all values in INTER with those that we have already scheduled to
3588 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3589 (while subtracting OFFSET). */
3592 intersect_with_agg_replacements (struct cgraph_node
*node
, int index
,
3593 vec
<ipa_agg_jf_item
> *inter
,
3594 HOST_WIDE_INT offset
)
3596 struct ipa_agg_replacement_value
*srcvals
;
3597 struct ipa_agg_jf_item
*item
;
3600 srcvals
= ipa_get_agg_replacements_for_node (node
);
3607 FOR_EACH_VEC_ELT (*inter
, i
, item
)
3609 struct ipa_agg_replacement_value
*av
;
3613 for (av
= srcvals
; av
; av
= av
->next
)
3615 gcc_checking_assert (av
->value
);
3616 if (av
->index
== index
3617 && av
->offset
- offset
== item
->offset
)
3619 if (values_equal_for_ipcp_p (item
->value
, av
->value
))
3625 item
->value
= NULL_TREE
;
3629 /* Intersect values in INTER with aggregate values that come along edge CS to
3630 parameter number INDEX and return it. If INTER does not actually exist yet,
3631 copy all incoming values to it. If we determine we ended up with no values
3632 whatsoever, return a released vector. */
3634 static vec
<ipa_agg_jf_item
>
3635 intersect_aggregates_with_edge (struct cgraph_edge
*cs
, int index
,
3636 vec
<ipa_agg_jf_item
> inter
)
3638 struct ipa_jump_func
*jfunc
;
3639 jfunc
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
), index
);
3640 if (jfunc
->type
== IPA_JF_PASS_THROUGH
3641 && ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
3643 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3644 int src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
3646 if (caller_info
->ipcp_orig_node
)
3648 struct cgraph_node
*orig_node
= caller_info
->ipcp_orig_node
;
3649 struct ipcp_param_lattices
*orig_plats
;
3650 orig_plats
= ipa_get_parm_lattices (IPA_NODE_REF (orig_node
),
3652 if (agg_pass_through_permissible_p (orig_plats
, jfunc
))
3654 if (!inter
.exists ())
3655 inter
= agg_replacements_to_vector (cs
->caller
, src_idx
, 0);
3657 intersect_with_agg_replacements (cs
->caller
, src_idx
,
3668 struct ipcp_param_lattices
*src_plats
;
3669 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
3670 if (agg_pass_through_permissible_p (src_plats
, jfunc
))
3672 /* Currently we do not produce clobber aggregate jump
3673 functions, adjust when we do. */
3674 gcc_checking_assert (!jfunc
->agg
.items
);
3675 if (!inter
.exists ())
3676 inter
= copy_plats_to_inter (src_plats
, 0);
3678 intersect_with_plats (src_plats
, &inter
, 0);
3687 else if (jfunc
->type
== IPA_JF_ANCESTOR
3688 && ipa_get_jf_ancestor_agg_preserved (jfunc
))
3690 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3691 int src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
3692 struct ipcp_param_lattices
*src_plats
;
3693 HOST_WIDE_INT delta
= ipa_get_jf_ancestor_offset (jfunc
);
3695 if (caller_info
->ipcp_orig_node
)
3697 if (!inter
.exists ())
3698 inter
= agg_replacements_to_vector (cs
->caller
, src_idx
, delta
);
3700 intersect_with_agg_replacements (cs
->caller
, src_idx
, &inter
,
3705 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);;
3706 /* Currently we do not produce clobber aggregate jump
3707 functions, adjust when we do. */
3708 gcc_checking_assert (!src_plats
->aggs
|| !jfunc
->agg
.items
);
3709 if (!inter
.exists ())
3710 inter
= copy_plats_to_inter (src_plats
, delta
);
3712 intersect_with_plats (src_plats
, &inter
, delta
);
3715 else if (jfunc
->agg
.items
)
3717 struct ipa_agg_jf_item
*item
;
3720 if (!inter
.exists ())
3721 for (unsigned i
= 0; i
< jfunc
->agg
.items
->length (); i
++)
3722 inter
.safe_push ((*jfunc
->agg
.items
)[i
]);
3724 FOR_EACH_VEC_ELT (inter
, k
, item
)
3727 bool found
= false;;
3732 while ((unsigned) l
< jfunc
->agg
.items
->length ())
3734 struct ipa_agg_jf_item
*ti
;
3735 ti
= &(*jfunc
->agg
.items
)[l
];
3736 if (ti
->offset
> item
->offset
)
3738 if (ti
->offset
== item
->offset
)
3740 gcc_checking_assert (ti
->value
);
3741 if (values_equal_for_ipcp_p (item
->value
,
3755 return vec
<ipa_agg_jf_item
>();
3760 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3761 from all of them. */
3763 static struct ipa_agg_replacement_value
*
3764 find_aggregate_values_for_callers_subset (struct cgraph_node
*node
,
3765 vec
<cgraph_edge
*> callers
)
3767 struct ipa_node_params
*dest_info
= IPA_NODE_REF (node
);
3768 struct ipa_agg_replacement_value
*res
;
3769 struct ipa_agg_replacement_value
**tail
= &res
;
3770 struct cgraph_edge
*cs
;
3771 int i
, j
, count
= ipa_get_param_count (dest_info
);
3773 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3775 int c
= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
));
3780 for (i
= 0; i
< count
; i
++)
3782 struct cgraph_edge
*cs
;
3783 vec
<ipa_agg_jf_item
> inter
= vNULL
;
3784 struct ipa_agg_jf_item
*item
;
3785 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (dest_info
, i
);
3788 /* Among other things, the following check should deal with all by_ref
3790 if (plats
->aggs_bottom
)
3793 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3795 inter
= intersect_aggregates_with_edge (cs
, i
, inter
);
3797 if (!inter
.exists ())
3801 FOR_EACH_VEC_ELT (inter
, j
, item
)
3803 struct ipa_agg_replacement_value
*v
;
3808 v
= ggc_alloc
<ipa_agg_replacement_value
> ();
3810 v
->offset
= item
->offset
;
3811 v
->value
= item
->value
;
3812 v
->by_ref
= plats
->aggs_by_ref
;
3818 if (inter
.exists ())
3825 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3827 static struct ipa_agg_replacement_value
*
3828 known_aggs_to_agg_replacement_list (vec
<ipa_agg_jump_function
> known_aggs
)
3830 struct ipa_agg_replacement_value
*res
;
3831 struct ipa_agg_replacement_value
**tail
= &res
;
3832 struct ipa_agg_jump_function
*aggjf
;
3833 struct ipa_agg_jf_item
*item
;
3836 FOR_EACH_VEC_ELT (known_aggs
, i
, aggjf
)
3837 FOR_EACH_VEC_SAFE_ELT (aggjf
->items
, j
, item
)
3839 struct ipa_agg_replacement_value
*v
;
3840 v
= ggc_alloc
<ipa_agg_replacement_value
> ();
3842 v
->offset
= item
->offset
;
3843 v
->value
= item
->value
;
3844 v
->by_ref
= aggjf
->by_ref
;
3852 /* Determine whether CS also brings all scalar values that the NODE is
3856 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge
*cs
,
3857 struct cgraph_node
*node
)
3859 struct ipa_node_params
*dest_info
= IPA_NODE_REF (node
);
3860 int count
= ipa_get_param_count (dest_info
);
3861 struct ipa_node_params
*caller_info
;
3862 struct ipa_edge_args
*args
;
3865 caller_info
= IPA_NODE_REF (cs
->caller
);
3866 args
= IPA_EDGE_REF (cs
);
3867 for (i
= 0; i
< count
; i
++)
3869 struct ipa_jump_func
*jump_func
;
3872 val
= dest_info
->known_csts
[i
];
3876 if (i
>= ipa_get_cs_argument_count (args
))
3878 jump_func
= ipa_get_ith_jump_func (args
, i
);
3879 t
= ipa_value_from_jfunc (caller_info
, jump_func
);
3880 if (!t
|| !values_equal_for_ipcp_p (val
, t
))
3886 /* Determine whether CS also brings all aggregate values that NODE is
3889 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge
*cs
,
3890 struct cgraph_node
*node
)
3892 struct ipa_node_params
*orig_caller_info
= IPA_NODE_REF (cs
->caller
);
3893 struct ipa_node_params
*orig_node_info
;
3894 struct ipa_agg_replacement_value
*aggval
;
3897 aggval
= ipa_get_agg_replacements_for_node (node
);
3901 count
= ipa_get_param_count (IPA_NODE_REF (node
));
3902 ec
= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
));
3904 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
3905 if (aggval
->index
>= ec
)
3908 orig_node_info
= IPA_NODE_REF (IPA_NODE_REF (node
)->ipcp_orig_node
);
3909 if (orig_caller_info
->ipcp_orig_node
)
3910 orig_caller_info
= IPA_NODE_REF (orig_caller_info
->ipcp_orig_node
);
3912 for (i
= 0; i
< count
; i
++)
3914 static vec
<ipa_agg_jf_item
> values
= vec
<ipa_agg_jf_item
>();
3915 struct ipcp_param_lattices
*plats
;
3916 bool interesting
= false;
3917 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
3918 if (aggval
->index
== i
)
3926 plats
= ipa_get_parm_lattices (orig_node_info
, aggval
->index
);
3927 if (plats
->aggs_bottom
)
3930 values
= intersect_aggregates_with_edge (cs
, i
, values
);
3931 if (!values
.exists ())
3934 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
3935 if (aggval
->index
== i
)
3937 struct ipa_agg_jf_item
*item
;
3940 FOR_EACH_VEC_ELT (values
, j
, item
)
3942 && item
->offset
== av
->offset
3943 && values_equal_for_ipcp_p (item
->value
, av
->value
))
3958 /* Given an original NODE and a VAL for which we have already created a
3959 specialized clone, look whether there are incoming edges that still lead
3960 into the old node but now also bring the requested value and also conform to
3961 all other criteria such that they can be redirected the the special node.
3962 This function can therefore redirect the final edge in a SCC. */
3964 template <typename valtype
>
3966 perhaps_add_new_callers (cgraph_node
*node
, ipcp_value
<valtype
> *val
)
3968 ipcp_value_source
<valtype
> *src
;
3969 gcov_type redirected_sum
= 0;
3971 for (src
= val
->sources
; src
; src
= src
->next
)
3973 struct cgraph_edge
*cs
= src
->cs
;
3976 if (cgraph_edge_brings_value_p (cs
, src
, node
)
3977 && cgraph_edge_brings_all_scalars_for_node (cs
, val
->spec_node
)
3978 && cgraph_edge_brings_all_agg_vals_for_node (cs
, val
->spec_node
))
3981 fprintf (dump_file
, " - adding an extra caller %s/%i"
3983 xstrdup_for_dump (cs
->caller
->name ()),
3985 xstrdup_for_dump (val
->spec_node
->name ()),
3986 val
->spec_node
->order
);
3988 cs
->redirect_callee_duplicating_thunks (val
->spec_node
);
3989 val
->spec_node
->expand_all_artificial_thunks ();
3990 redirected_sum
+= cs
->count
;
3992 cs
= get_next_cgraph_edge_clone (cs
);
3997 update_specialized_profile (val
->spec_node
, node
, redirected_sum
);
4000 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4003 known_contexts_useful_p (vec
<ipa_polymorphic_call_context
> known_contexts
)
4005 ipa_polymorphic_call_context
*ctx
;
4008 FOR_EACH_VEC_ELT (known_contexts
, i
, ctx
)
4009 if (!ctx
->useless_p ())
4014 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4016 static vec
<ipa_polymorphic_call_context
>
4017 copy_useful_known_contexts (vec
<ipa_polymorphic_call_context
> known_contexts
)
4019 if (known_contexts_useful_p (known_contexts
))
4020 return known_contexts
.copy ();
4025 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4026 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4029 modify_known_vectors_with_val (vec
<tree
> *known_csts
,
4030 vec
<ipa_polymorphic_call_context
> *known_contexts
,
4031 ipcp_value
<tree
> *val
,
4034 *known_csts
= known_csts
->copy ();
4035 *known_contexts
= copy_useful_known_contexts (*known_contexts
);
4036 (*known_csts
)[index
] = val
->value
;
4039 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4040 copy according to VAL and INDEX. */
4043 modify_known_vectors_with_val (vec
<tree
> *known_csts
,
4044 vec
<ipa_polymorphic_call_context
> *known_contexts
,
4045 ipcp_value
<ipa_polymorphic_call_context
> *val
,
4048 *known_csts
= known_csts
->copy ();
4049 *known_contexts
= known_contexts
->copy ();
4050 (*known_contexts
)[index
] = val
->value
;
4053 /* Return true if OFFSET indicates this was not an aggregate value or there is
4054 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4058 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value
*aggvals
,
4059 int index
, HOST_WIDE_INT offset
, tree value
)
4066 if (aggvals
->index
== index
4067 && aggvals
->offset
== offset
4068 && values_equal_for_ipcp_p (aggvals
->value
, value
))
4070 aggvals
= aggvals
->next
;
4075 /* Return true if offset is minus one because source of a polymorphic contect
4076 cannot be an aggregate value. */
4079 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value
*,
4080 int , HOST_WIDE_INT offset
,
4081 ipa_polymorphic_call_context
)
4083 return offset
== -1;
4086 /* Decide wheter to create a special version of NODE for value VAL of parameter
4087 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4088 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4089 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4091 template <typename valtype
>
4093 decide_about_value (struct cgraph_node
*node
, int index
, HOST_WIDE_INT offset
,
4094 ipcp_value
<valtype
> *val
, vec
<tree
> known_csts
,
4095 vec
<ipa_polymorphic_call_context
> known_contexts
)
4097 struct ipa_agg_replacement_value
*aggvals
;
4098 int freq_sum
, caller_count
;
4099 gcov_type count_sum
;
4100 vec
<cgraph_edge
*> callers
;
4104 perhaps_add_new_callers (node
, val
);
4107 else if (val
->local_size_cost
+ overall_size
> max_new_size
)
4109 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4110 fprintf (dump_file
, " Ignoring candidate value because "
4111 "max_new_size would be reached with %li.\n",
4112 val
->local_size_cost
+ overall_size
);
4115 else if (!get_info_about_necessary_edges (val
, node
, &freq_sum
, &count_sum
,
4119 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4121 fprintf (dump_file
, " - considering value ");
4122 print_ipcp_constant_value (dump_file
, val
->value
);
4123 fprintf (dump_file
, " for ");
4124 ipa_dump_param (dump_file
, IPA_NODE_REF (node
), index
);
4126 fprintf (dump_file
, ", offset: " HOST_WIDE_INT_PRINT_DEC
, offset
);
4127 fprintf (dump_file
, " (caller_count: %i)\n", caller_count
);
4130 if (!good_cloning_opportunity_p (node
, val
->local_time_benefit
,
4131 freq_sum
, count_sum
,
4132 val
->local_size_cost
)
4133 && !good_cloning_opportunity_p (node
,
4134 val
->local_time_benefit
4135 + val
->prop_time_benefit
,
4136 freq_sum
, count_sum
,
4137 val
->local_size_cost
4138 + val
->prop_size_cost
))
4142 fprintf (dump_file
, " Creating a specialized node of %s/%i.\n",
4143 node
->name (), node
->order
);
4145 callers
= gather_edges_for_value (val
, node
, caller_count
);
4147 modify_known_vectors_with_val (&known_csts
, &known_contexts
, val
, index
);
4150 known_csts
= known_csts
.copy ();
4151 known_contexts
= copy_useful_known_contexts (known_contexts
);
4153 find_more_scalar_values_for_callers_subset (node
, known_csts
, callers
);
4154 find_more_contexts_for_caller_subset (node
, &known_contexts
, callers
);
4155 aggvals
= find_aggregate_values_for_callers_subset (node
, callers
);
4156 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals
, index
,
4157 offset
, val
->value
));
4158 val
->spec_node
= create_specialized_node (node
, known_csts
, known_contexts
,
4160 overall_size
+= val
->local_size_cost
;
4162 /* TODO: If for some lattice there is only one other known value
4163 left, make a special node for it too. */
4168 /* Decide whether and what specialized clones of NODE should be created. */
4171 decide_whether_version_node (struct cgraph_node
*node
)
4173 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
4174 int i
, count
= ipa_get_param_count (info
);
4175 vec
<tree
> known_csts
;
4176 vec
<ipa_polymorphic_call_context
> known_contexts
;
4177 vec
<ipa_agg_jump_function
> known_aggs
= vNULL
;
4183 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4184 fprintf (dump_file
, "\nEvaluating opportunities for %s/%i.\n",
4185 node
->name (), node
->order
);
4187 gather_context_independent_values (info
, &known_csts
, &known_contexts
,
4188 info
->do_clone_for_all_contexts
? &known_aggs
4191 for (i
= 0; i
< count
;i
++)
4193 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
4194 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
4195 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
4200 ipcp_value
<tree
> *val
;
4201 for (val
= lat
->values
; val
; val
= val
->next
)
4202 ret
|= decide_about_value (node
, i
, -1, val
, known_csts
,
4206 if (!plats
->aggs_bottom
)
4208 struct ipcp_agg_lattice
*aglat
;
4209 ipcp_value
<tree
> *val
;
4210 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
4211 if (!aglat
->bottom
&& aglat
->values
4212 /* If the following is false, the one value is in
4214 && (plats
->aggs_contain_variable
4215 || !aglat
->is_single_const ()))
4216 for (val
= aglat
->values
; val
; val
= val
->next
)
4217 ret
|= decide_about_value (node
, i
, aglat
->offset
, val
,
4218 known_csts
, known_contexts
);
4222 && known_contexts
[i
].useless_p ())
4224 ipcp_value
<ipa_polymorphic_call_context
> *val
;
4225 for (val
= ctxlat
->values
; val
; val
= val
->next
)
4226 ret
|= decide_about_value (node
, i
, -1, val
, known_csts
,
4230 info
= IPA_NODE_REF (node
);
4233 if (info
->do_clone_for_all_contexts
)
4235 struct cgraph_node
*clone
;
4236 vec
<cgraph_edge
*> callers
;
4239 fprintf (dump_file
, " - Creating a specialized node of %s/%i "
4240 "for all known contexts.\n", node
->name (),
4243 callers
= node
->collect_callers ();
4245 if (!known_contexts_useful_p (known_contexts
))
4247 known_contexts
.release ();
4248 known_contexts
= vNULL
;
4250 clone
= create_specialized_node (node
, known_csts
, known_contexts
,
4251 known_aggs_to_agg_replacement_list (known_aggs
),
4253 info
= IPA_NODE_REF (node
);
4254 info
->do_clone_for_all_contexts
= false;
4255 IPA_NODE_REF (clone
)->is_all_contexts_clone
= true;
4256 for (i
= 0; i
< count
; i
++)
4257 vec_free (known_aggs
[i
].items
);
4258 known_aggs
.release ();
4263 known_csts
.release ();
4264 known_contexts
.release ();
4270 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4273 spread_undeadness (struct cgraph_node
*node
)
4275 struct cgraph_edge
*cs
;
4277 for (cs
= node
->callees
; cs
; cs
= cs
->next_callee
)
4278 if (ipa_edge_within_scc (cs
))
4280 struct cgraph_node
*callee
;
4281 struct ipa_node_params
*info
;
4283 callee
= cs
->callee
->function_symbol (NULL
);
4284 info
= IPA_NODE_REF (callee
);
4286 if (info
->node_dead
)
4288 info
->node_dead
= 0;
4289 spread_undeadness (callee
);
4294 /* Return true if NODE has a caller from outside of its SCC that is not
4295 dead. Worker callback for cgraph_for_node_and_aliases. */
4298 has_undead_caller_from_outside_scc_p (struct cgraph_node
*node
,
4299 void *data ATTRIBUTE_UNUSED
)
4301 struct cgraph_edge
*cs
;
4303 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
4304 if (cs
->caller
->thunk
.thunk_p
4305 && cs
->caller
->call_for_symbol_thunks_and_aliases
4306 (has_undead_caller_from_outside_scc_p
, NULL
, true))
4308 else if (!ipa_edge_within_scc (cs
)
4309 && !IPA_NODE_REF (cs
->caller
)->node_dead
)
4315 /* Identify nodes within the same SCC as NODE which are no longer needed
4316 because of new clones and will be removed as unreachable. */
4319 identify_dead_nodes (struct cgraph_node
*node
)
4321 struct cgraph_node
*v
;
4322 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4323 if (v
->will_be_removed_from_program_if_no_direct_calls_p ()
4324 && !v
->call_for_symbol_thunks_and_aliases
4325 (has_undead_caller_from_outside_scc_p
, NULL
, true))
4326 IPA_NODE_REF (v
)->node_dead
= 1;
4328 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4329 if (!IPA_NODE_REF (v
)->node_dead
)
4330 spread_undeadness (v
);
4332 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4334 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4335 if (IPA_NODE_REF (v
)->node_dead
)
4336 fprintf (dump_file
, " Marking node as dead: %s/%i.\n",
4337 v
->name (), v
->order
);
4341 /* The decision stage. Iterate over the topological order of call graph nodes
4342 TOPO and make specialized clones if deemed beneficial. */
4345 ipcp_decision_stage (struct ipa_topo_info
*topo
)
4350 fprintf (dump_file
, "\nIPA decision stage:\n\n");
4352 for (i
= topo
->nnodes
- 1; i
>= 0; i
--)
4354 struct cgraph_node
*node
= topo
->order
[i
];
4355 bool change
= false, iterate
= true;
4359 struct cgraph_node
*v
;
4361 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4362 if (v
->has_gimple_body_p ()
4363 && ipcp_versionable_function_p (v
))
4364 iterate
|= decide_whether_version_node (v
);
4369 identify_dead_nodes (node
);
4373 /* Look up all alignment information that we have discovered and copy it over
4374 to the transformation summary. */
4377 ipcp_store_alignment_results (void)
4381 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
4383 ipa_node_params
*info
= IPA_NODE_REF (node
);
4384 bool dumped_sth
= false;
4385 bool found_useful_result
= false;
4387 if (!opt_for_fn (node
->decl
, flag_ipa_cp_alignment
))
4390 fprintf (dump_file
, "Not considering %s for alignment discovery "
4391 "and propagate; -fipa-cp-alignment: disabled.\n",
4396 if (info
->ipcp_orig_node
)
4397 info
= IPA_NODE_REF (info
->ipcp_orig_node
);
4399 unsigned count
= ipa_get_param_count (info
);
4400 for (unsigned i
= 0; i
< count
; i
++)
4402 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
4403 if (plats
->alignment
.known
4404 && plats
->alignment
.align
> 0)
4406 found_useful_result
= true;
4410 if (!found_useful_result
)
4413 ipcp_grow_transformations_if_necessary ();
4414 ipcp_transformation_summary
*ts
= ipcp_get_transformation_summary (node
);
4415 vec_safe_reserve_exact (ts
->alignments
, count
);
4417 for (unsigned i
= 0; i
< count
; i
++)
4419 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
4421 if (plats
->alignment
.align
== 0)
4422 plats
->alignment
.known
= false;
4424 ts
->alignments
->quick_push (plats
->alignment
);
4425 if (!dump_file
|| !plats
->alignment
.known
)
4429 fprintf (dump_file
, "Propagated alignment info for function %s/%i:\n",
4430 node
->name (), node
->order
);
4433 fprintf (dump_file
, " param %i: align: %u, misalign: %u\n",
4434 i
, plats
->alignment
.align
, plats
->alignment
.misalign
);
4439 /* The IPCP driver. */
4444 struct cgraph_2edge_hook_list
*edge_duplication_hook_holder
;
4445 struct cgraph_edge_hook_list
*edge_removal_hook_holder
;
4446 struct ipa_topo_info topo
;
4448 ipa_check_create_node_params ();
4449 ipa_check_create_edge_args ();
4450 grow_edge_clone_vectors ();
4451 edge_duplication_hook_holder
=
4452 symtab
->add_edge_duplication_hook (&ipcp_edge_duplication_hook
, NULL
);
4453 edge_removal_hook_holder
=
4454 symtab
->add_edge_removal_hook (&ipcp_edge_removal_hook
, NULL
);
4458 fprintf (dump_file
, "\nIPA structures before propagation:\n");
4459 if (dump_flags
& TDF_DETAILS
)
4460 ipa_print_all_params (dump_file
);
4461 ipa_print_all_jump_functions (dump_file
);
4464 /* Topological sort. */
4465 build_toporder_info (&topo
);
4466 /* Do the interprocedural propagation. */
4467 ipcp_propagate_stage (&topo
);
4468 /* Decide what constant propagation and cloning should be performed. */
4469 ipcp_decision_stage (&topo
);
4470 /* Store results of alignment propagation. */
4471 ipcp_store_alignment_results ();
4473 /* Free all IPCP structures. */
4474 free_toporder_info (&topo
);
4475 next_edge_clone
.release ();
4476 prev_edge_clone
.release ();
4477 symtab
->remove_edge_removal_hook (edge_removal_hook_holder
);
4478 symtab
->remove_edge_duplication_hook (edge_duplication_hook_holder
);
4479 ipa_free_all_structures_after_ipa_cp ();
4481 fprintf (dump_file
, "\nIPA constant propagation end\n");
4485 /* Initialization and computation of IPCP data structures. This is the initial
4486 intraprocedural analysis of functions, which gathers information to be
4487 propagated later on. */
4490 ipcp_generate_summary (void)
4492 struct cgraph_node
*node
;
4495 fprintf (dump_file
, "\nIPA constant propagation start:\n");
4496 ipa_register_cgraph_hooks ();
4498 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
4500 node
->local
.versionable
4501 = tree_versionable_function_p (node
->decl
);
4502 ipa_analyze_node (node
);
4506 /* Write ipcp summary for nodes in SET. */
4509 ipcp_write_summary (void)
4511 ipa_prop_write_jump_functions ();
4514 /* Read ipcp summary. */
4517 ipcp_read_summary (void)
4519 ipa_prop_read_jump_functions ();
4524 const pass_data pass_data_ipa_cp
=
4526 IPA_PASS
, /* type */
4528 OPTGROUP_NONE
, /* optinfo_flags */
4529 TV_IPA_CONSTANT_PROP
, /* tv_id */
4530 0, /* properties_required */
4531 0, /* properties_provided */
4532 0, /* properties_destroyed */
4533 0, /* todo_flags_start */
4534 ( TODO_dump_symtab
| TODO_remove_functions
), /* todo_flags_finish */
4537 class pass_ipa_cp
: public ipa_opt_pass_d
4540 pass_ipa_cp (gcc::context
*ctxt
)
4541 : ipa_opt_pass_d (pass_data_ipa_cp
, ctxt
,
4542 ipcp_generate_summary
, /* generate_summary */
4543 ipcp_write_summary
, /* write_summary */
4544 ipcp_read_summary
, /* read_summary */
4545 ipcp_write_transformation_summaries
, /*
4546 write_optimization_summary */
4547 ipcp_read_transformation_summaries
, /*
4548 read_optimization_summary */
4549 NULL
, /* stmt_fixup */
4550 0, /* function_transform_todo_flags_start */
4551 ipcp_transform_function
, /* function_transform */
4552 NULL
) /* variable_transform */
4555 /* opt_pass methods: */
4556 virtual bool gate (function
*)
4558 /* FIXME: We should remove the optimize check after we ensure we never run
4559 IPA passes when not optimizing. */
4560 return (flag_ipa_cp
&& optimize
) || in_lto_p
;
4563 virtual unsigned int execute (function
*) { return ipcp_driver (); }
4565 }; // class pass_ipa_cp
4570 make_pass_ipa_cp (gcc::context
*ctxt
)
4572 return new pass_ipa_cp (ctxt
);
4575 /* Reset all state within ipa-cp.c so that we can rerun the compiler
4576 within the same process. For use by toplev::finalize. */
4579 ipa_cp_c_finalize (void)