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"
115 #include "hard-reg-set.h"
117 #include "alloc-pool.h"
118 #include "symbol-summary.h"
119 #include "ipa-prop.h"
120 #include "tree-pass.h"
122 #include "diagnostic.h"
123 #include "tree-pretty-print.h"
124 #include "tree-inline.h"
126 #include "ipa-inline.h"
127 #include "ipa-utils.h"
129 template <typename valtype
> class ipcp_value
;
131 /* Describes a particular source for an IPA-CP value. */
133 template <typename valtype
>
134 class ipcp_value_source
137 /* Aggregate offset of the source, negative if the source is scalar value of
138 the argument itself. */
139 HOST_WIDE_INT offset
;
140 /* The incoming edge that brought the value. */
142 /* If the jump function that resulted into his value was a pass-through or an
143 ancestor, this is the ipcp_value of the caller from which the described
144 value has been derived. Otherwise it is NULL. */
145 ipcp_value
<valtype
> *val
;
146 /* Next pointer in a linked list of sources of a value. */
147 ipcp_value_source
*next
;
148 /* If the jump function that resulted into his value was a pass-through or an
149 ancestor, this is the index of the parameter of the caller the jump
150 function references. */
154 /* Common ancestor for all ipcp_value instantiations. */
156 class ipcp_value_base
159 /* Time benefit and size cost that specializing the function for this value
160 would bring about in this function alone. */
161 int local_time_benefit
, local_size_cost
;
162 /* Time benefit and size cost that specializing the function for this value
163 can bring about in it's callees (transitively). */
164 int prop_time_benefit
, prop_size_cost
;
167 /* Describes one particular value stored in struct ipcp_lattice. */
169 template <typename valtype
>
170 class ipcp_value
: public ipcp_value_base
173 /* The actual value for the given parameter. */
175 /* The list of sources from which this value originates. */
176 ipcp_value_source
<valtype
> *sources
;
177 /* Next pointers in a linked list of all values in a lattice. */
179 /* Next pointers in a linked list of values in a strongly connected component
181 ipcp_value
*scc_next
;
182 /* Next pointers in a linked list of SCCs of values sorted topologically
183 according their sources. */
184 ipcp_value
*topo_next
;
185 /* A specialized node created for this value, NULL if none has been (so far)
187 cgraph_node
*spec_node
;
188 /* Depth first search number and low link for topological sorting of
191 /* True if this valye is currently on the topo-sort stack. */
194 void add_source (cgraph_edge
*cs
, ipcp_value
*src_val
, int src_idx
,
195 HOST_WIDE_INT offset
);
198 /* Lattice describing potential values of a formal parameter of a function, or
199 a part of an aggreagate. TOP is represented by a lattice with zero values
200 and with contains_variable and bottom flags cleared. BOTTOM is represented
201 by a lattice with the bottom flag set. In that case, values and
202 contains_variable flag should be disregarded. */
204 template <typename valtype
>
208 /* The list of known values and types in this lattice. Note that values are
209 not deallocated if a lattice is set to bottom because there may be value
210 sources referencing them. */
211 ipcp_value
<valtype
> *values
;
212 /* Number of known values and types in this lattice. */
214 /* The lattice contains a variable component (in addition to values). */
215 bool contains_variable
;
216 /* The value of the lattice is bottom (i.e. variable and unusable for any
220 inline bool is_single_const ();
221 inline bool set_to_bottom ();
222 inline bool set_contains_variable ();
223 bool add_value (valtype newval
, cgraph_edge
*cs
,
224 ipcp_value
<valtype
> *src_val
= NULL
,
225 int src_idx
= 0, HOST_WIDE_INT offset
= -1);
226 void print (FILE * f
, bool dump_sources
, bool dump_benefits
);
229 /* Lattice of tree values with an offset to describe a part of an
232 class ipcp_agg_lattice
: public ipcp_lattice
<tree
>
235 /* Offset that is being described by this lattice. */
236 HOST_WIDE_INT offset
;
237 /* Size so that we don't have to re-compute it every time we traverse the
238 list. Must correspond to TYPE_SIZE of all lat values. */
240 /* Next element of the linked list. */
241 struct ipcp_agg_lattice
*next
;
244 /* Structure containing lattices for a parameter itself and for pieces of
245 aggregates that are passed in the parameter or by a reference in a parameter
246 plus some other useful flags. */
248 class ipcp_param_lattices
251 /* Lattice describing the value of the parameter itself. */
252 ipcp_lattice
<tree
> itself
;
253 /* Lattice describing the polymorphic contexts of a parameter. */
254 ipcp_lattice
<ipa_polymorphic_call_context
> ctxlat
;
255 /* Lattices describing aggregate parts. */
256 ipcp_agg_lattice
*aggs
;
257 /* Alignment information. Very basic one value lattice where !known means
258 TOP and zero alignment bottom. */
259 ipa_alignment alignment
;
260 /* Number of aggregate lattices */
262 /* True if aggregate data were passed by reference (as opposed to by
265 /* All aggregate lattices contain a variable component (in addition to
267 bool aggs_contain_variable
;
268 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
269 for any propagation). */
272 /* There is a virtual call based on this parameter. */
276 /* Allocation pools for values and their sources in ipa-cp. */
278 object_allocator
<ipcp_value
<tree
> > ipcp_cst_values_pool
279 ("IPA-CP constant values", 32);
281 object_allocator
<ipcp_value
<ipa_polymorphic_call_context
> >
282 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts", 32);
284 object_allocator
<ipcp_value_source
<tree
> > ipcp_sources_pool
285 ("IPA-CP value sources", 64);
287 object_allocator
<ipcp_agg_lattice
> ipcp_agg_lattice_pool
288 ("IPA_CP aggregate lattices", 32);
290 /* Maximal count found in program. */
292 static gcov_type max_count
;
294 /* Original overall size of the program. */
296 static long overall_size
, max_new_size
;
298 /* Return the param lattices structure corresponding to the Ith formal
299 parameter of the function described by INFO. */
300 static inline struct ipcp_param_lattices
*
301 ipa_get_parm_lattices (struct ipa_node_params
*info
, int i
)
303 gcc_assert (i
>= 0 && i
< ipa_get_param_count (info
));
304 gcc_checking_assert (!info
->ipcp_orig_node
);
305 gcc_checking_assert (info
->lattices
);
306 return &(info
->lattices
[i
]);
309 /* Return the lattice corresponding to the scalar value of the Ith formal
310 parameter of the function described by INFO. */
311 static inline ipcp_lattice
<tree
> *
312 ipa_get_scalar_lat (struct ipa_node_params
*info
, int i
)
314 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
315 return &plats
->itself
;
318 /* Return the lattice corresponding to the scalar value of the Ith formal
319 parameter of the function described by INFO. */
320 static inline ipcp_lattice
<ipa_polymorphic_call_context
> *
321 ipa_get_poly_ctx_lat (struct ipa_node_params
*info
, int i
)
323 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
324 return &plats
->ctxlat
;
327 /* Return whether LAT is a lattice with a single constant and without an
330 template <typename valtype
>
332 ipcp_lattice
<valtype
>::is_single_const ()
334 if (bottom
|| contains_variable
|| values_count
!= 1)
340 /* Print V which is extracted from a value in a lattice to F. */
343 print_ipcp_constant_value (FILE * f
, tree v
)
345 if (TREE_CODE (v
) == ADDR_EXPR
346 && TREE_CODE (TREE_OPERAND (v
, 0)) == CONST_DECL
)
349 print_generic_expr (f
, DECL_INITIAL (TREE_OPERAND (v
, 0)), 0);
352 print_generic_expr (f
, v
, 0);
355 /* Print V which is extracted from a value in a lattice to F. */
358 print_ipcp_constant_value (FILE * f
, ipa_polymorphic_call_context v
)
363 /* Print a lattice LAT to F. */
365 template <typename valtype
>
367 ipcp_lattice
<valtype
>::print (FILE * f
, bool dump_sources
, bool dump_benefits
)
369 ipcp_value
<valtype
> *val
;
374 fprintf (f
, "BOTTOM\n");
378 if (!values_count
&& !contains_variable
)
380 fprintf (f
, "TOP\n");
384 if (contains_variable
)
386 fprintf (f
, "VARIABLE");
392 for (val
= values
; val
; val
= val
->next
)
394 if (dump_benefits
&& prev
)
396 else if (!dump_benefits
&& prev
)
401 print_ipcp_constant_value (f
, val
->value
);
405 ipcp_value_source
<valtype
> *s
;
407 fprintf (f
, " [from:");
408 for (s
= val
->sources
; s
; s
= s
->next
)
409 fprintf (f
, " %i(%i)", s
->cs
->caller
->order
,
415 fprintf (f
, " [loc_time: %i, loc_size: %i, "
416 "prop_time: %i, prop_size: %i]\n",
417 val
->local_time_benefit
, val
->local_size_cost
,
418 val
->prop_time_benefit
, val
->prop_size_cost
);
424 /* Print all ipcp_lattices of all functions to F. */
427 print_all_lattices (FILE * f
, bool dump_sources
, bool dump_benefits
)
429 struct cgraph_node
*node
;
432 fprintf (f
, "\nLattices:\n");
433 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
435 struct ipa_node_params
*info
;
437 info
= IPA_NODE_REF (node
);
438 fprintf (f
, " Node: %s/%i:\n", node
->name (),
440 count
= ipa_get_param_count (info
);
441 for (i
= 0; i
< count
; i
++)
443 struct ipcp_agg_lattice
*aglat
;
444 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
445 fprintf (f
, " param [%d]: ", i
);
446 plats
->itself
.print (f
, dump_sources
, dump_benefits
);
447 fprintf (f
, " ctxs: ");
448 plats
->ctxlat
.print (f
, dump_sources
, dump_benefits
);
449 if (plats
->alignment
.known
&& plats
->alignment
.align
> 0)
450 fprintf (f
, " Alignment %u, misalignment %u\n",
451 plats
->alignment
.align
, plats
->alignment
.misalign
);
452 else if (plats
->alignment
.known
)
453 fprintf (f
, " Alignment unusable\n");
455 fprintf (f
, " Alignment unknown\n");
456 if (plats
->virt_call
)
457 fprintf (f
, " virt_call flag set\n");
459 if (plats
->aggs_bottom
)
461 fprintf (f
, " AGGS BOTTOM\n");
464 if (plats
->aggs_contain_variable
)
465 fprintf (f
, " AGGS VARIABLE\n");
466 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
468 fprintf (f
, " %soffset " HOST_WIDE_INT_PRINT_DEC
": ",
469 plats
->aggs_by_ref
? "ref " : "", aglat
->offset
);
470 aglat
->print (f
, dump_sources
, dump_benefits
);
476 /* Determine whether it is at all technically possible to create clones of NODE
477 and store this information in the ipa_node_params structure associated
481 determine_versionability (struct cgraph_node
*node
)
483 const char *reason
= NULL
;
485 /* There are a number of generic reasons functions cannot be versioned. We
486 also cannot remove parameters if there are type attributes such as fnspec
488 if (node
->alias
|| node
->thunk
.thunk_p
)
489 reason
= "alias or thunk";
490 else if (!node
->local
.versionable
)
491 reason
= "not a tree_versionable_function";
492 else if (node
->get_availability () <= AVAIL_INTERPOSABLE
)
493 reason
= "insufficient body availability";
494 else if (!opt_for_fn (node
->decl
, optimize
)
495 || !opt_for_fn (node
->decl
, flag_ipa_cp
))
496 reason
= "non-optimized function";
497 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node
->decl
)))
499 /* Ideally we should clone the SIMD clones themselves and create
500 vector copies of them, so IPA-cp and SIMD clones can happily
501 coexist, but that may not be worth the effort. */
502 reason
= "function has SIMD clones";
504 /* Don't clone decls local to a comdat group; it breaks and for C++
505 decloned constructors, inlining is always better anyway. */
506 else if (node
->comdat_local_p ())
507 reason
= "comdat-local function";
509 if (reason
&& dump_file
&& !node
->alias
&& !node
->thunk
.thunk_p
)
510 fprintf (dump_file
, "Function %s/%i is not versionable, reason: %s.\n",
511 node
->name (), node
->order
, reason
);
513 node
->local
.versionable
= (reason
== NULL
);
516 /* Return true if it is at all technically possible to create clones of a
520 ipcp_versionable_function_p (struct cgraph_node
*node
)
522 return node
->local
.versionable
;
525 /* Structure holding accumulated information about callers of a node. */
527 struct caller_statistics
530 int n_calls
, n_hot_calls
, freq_sum
;
533 /* Initialize fields of STAT to zeroes. */
536 init_caller_stats (struct caller_statistics
*stats
)
538 stats
->count_sum
= 0;
540 stats
->n_hot_calls
= 0;
544 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
545 non-thunk incoming edges to NODE. */
548 gather_caller_stats (struct cgraph_node
*node
, void *data
)
550 struct caller_statistics
*stats
= (struct caller_statistics
*) data
;
551 struct cgraph_edge
*cs
;
553 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
554 if (!cs
->caller
->thunk
.thunk_p
)
556 stats
->count_sum
+= cs
->count
;
557 stats
->freq_sum
+= cs
->frequency
;
559 if (cs
->maybe_hot_p ())
560 stats
->n_hot_calls
++;
566 /* Return true if this NODE is viable candidate for cloning. */
569 ipcp_cloning_candidate_p (struct cgraph_node
*node
)
571 struct caller_statistics stats
;
573 gcc_checking_assert (node
->has_gimple_body_p ());
575 if (!opt_for_fn (node
->decl
, flag_ipa_cp_clone
))
578 fprintf (dump_file
, "Not considering %s for cloning; "
579 "-fipa-cp-clone disabled.\n",
584 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node
->decl
)))
587 fprintf (dump_file
, "Not considering %s for cloning; "
588 "optimizing it for size.\n",
593 init_caller_stats (&stats
);
594 node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
, false);
596 if (inline_summaries
->get (node
)->self_size
< stats
.n_calls
)
599 fprintf (dump_file
, "Considering %s for cloning; code might shrink.\n",
604 /* When profile is available and function is hot, propagate into it even if
605 calls seems cold; constant propagation can improve function's speed
609 if (stats
.count_sum
> node
->count
* 90 / 100)
612 fprintf (dump_file
, "Considering %s for cloning; "
613 "usually called directly.\n",
618 if (!stats
.n_hot_calls
)
621 fprintf (dump_file
, "Not considering %s for cloning; no hot calls.\n",
626 fprintf (dump_file
, "Considering %s for cloning.\n",
631 template <typename valtype
>
632 class value_topo_info
635 /* Head of the linked list of topologically sorted values. */
636 ipcp_value
<valtype
> *values_topo
;
637 /* Stack for creating SCCs, represented by a linked list too. */
638 ipcp_value
<valtype
> *stack
;
639 /* Counter driving the algorithm in add_val_to_toposort. */
642 value_topo_info () : values_topo (NULL
), stack (NULL
), dfs_counter (0)
644 void add_val (ipcp_value
<valtype
> *cur_val
);
645 void propagate_effects ();
648 /* Arrays representing a topological ordering of call graph nodes and a stack
649 of nodes used during constant propagation and also data required to perform
650 topological sort of values and propagation of benefits in the determined
656 /* Array with obtained topological order of cgraph nodes. */
657 struct cgraph_node
**order
;
658 /* Stack of cgraph nodes used during propagation within SCC until all values
659 in the SCC stabilize. */
660 struct cgraph_node
**stack
;
661 int nnodes
, stack_top
;
663 value_topo_info
<tree
> constants
;
664 value_topo_info
<ipa_polymorphic_call_context
> contexts
;
666 ipa_topo_info () : order(NULL
), stack(NULL
), nnodes(0), stack_top(0),
671 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
674 build_toporder_info (struct ipa_topo_info
*topo
)
676 topo
->order
= XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
677 topo
->stack
= XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
679 gcc_checking_assert (topo
->stack_top
== 0);
680 topo
->nnodes
= ipa_reduced_postorder (topo
->order
, true, true, NULL
);
683 /* Free information about strongly connected components and the arrays in
687 free_toporder_info (struct ipa_topo_info
*topo
)
689 ipa_free_postorder_info ();
694 /* Add NODE to the stack in TOPO, unless it is already there. */
697 push_node_to_stack (struct ipa_topo_info
*topo
, struct cgraph_node
*node
)
699 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
700 if (info
->node_enqueued
)
702 info
->node_enqueued
= 1;
703 topo
->stack
[topo
->stack_top
++] = node
;
706 /* Pop a node from the stack in TOPO and return it or return NULL if the stack
709 static struct cgraph_node
*
710 pop_node_from_stack (struct ipa_topo_info
*topo
)
714 struct cgraph_node
*node
;
716 node
= topo
->stack
[topo
->stack_top
];
717 IPA_NODE_REF (node
)->node_enqueued
= 0;
724 /* Set lattice LAT to bottom and return true if it previously was not set as
727 template <typename valtype
>
729 ipcp_lattice
<valtype
>::set_to_bottom ()
736 /* Mark lattice as containing an unknown value and return true if it previously
737 was not marked as such. */
739 template <typename valtype
>
741 ipcp_lattice
<valtype
>::set_contains_variable ()
743 bool ret
= !contains_variable
;
744 contains_variable
= true;
748 /* Set all aggegate lattices in PLATS to bottom and return true if they were
749 not previously set as such. */
752 set_agg_lats_to_bottom (struct ipcp_param_lattices
*plats
)
754 bool ret
= !plats
->aggs_bottom
;
755 plats
->aggs_bottom
= true;
759 /* Mark all aggegate lattices in PLATS as containing an unknown value and
760 return true if they were not previously marked as such. */
763 set_agg_lats_contain_variable (struct ipcp_param_lattices
*plats
)
765 bool ret
= !plats
->aggs_contain_variable
;
766 plats
->aggs_contain_variable
= true;
770 /* Return true if alignment information in PLATS is known to be unusable. */
773 alignment_bottom_p (ipcp_param_lattices
*plats
)
775 return plats
->alignment
.known
&& (plats
->alignment
.align
== 0);
778 /* Set alignment information in PLATS to unusable. Return true if it
779 previously was usable or unknown. */
782 set_alignment_to_bottom (ipcp_param_lattices
*plats
)
784 if (alignment_bottom_p (plats
))
786 plats
->alignment
.known
= true;
787 plats
->alignment
.align
= 0;
791 /* Mark bot aggregate and scalar lattices as containing an unknown variable,
792 return true is any of them has not been marked as such so far. */
795 set_all_contains_variable (struct ipcp_param_lattices
*plats
)
798 ret
= plats
->itself
.set_contains_variable ();
799 ret
|= plats
->ctxlat
.set_contains_variable ();
800 ret
|= set_agg_lats_contain_variable (plats
);
801 ret
|= set_alignment_to_bottom (plats
);
805 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
806 points to by the number of callers to NODE. */
809 count_callers (cgraph_node
*node
, void *data
)
811 int *caller_count
= (int *) data
;
813 for (cgraph_edge
*cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
814 /* Local thunks can be handled transparently, but if the thunk can not
815 be optimized out, count it as a real use. */
816 if (!cs
->caller
->thunk
.thunk_p
|| !cs
->caller
->local
.local
)
821 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
822 the one caller of some other node. Set the caller's corresponding flag. */
825 set_single_call_flag (cgraph_node
*node
, void *)
827 cgraph_edge
*cs
= node
->callers
;
828 /* Local thunks can be handled transparently, skip them. */
829 while (cs
&& cs
->caller
->thunk
.thunk_p
&& cs
->caller
->local
.local
)
830 cs
= cs
->next_caller
;
833 IPA_NODE_REF (cs
->caller
)->node_calling_single_call
= true;
839 /* Initialize ipcp_lattices. */
842 initialize_node_lattices (struct cgraph_node
*node
)
844 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
845 struct cgraph_edge
*ie
;
846 bool disable
= false, variable
= false;
849 gcc_checking_assert (node
->has_gimple_body_p ());
850 if (cgraph_local_p (node
))
852 int caller_count
= 0;
853 node
->call_for_symbol_thunks_and_aliases (count_callers
, &caller_count
,
855 gcc_checking_assert (caller_count
> 0);
856 if (caller_count
== 1)
857 node
->call_for_symbol_thunks_and_aliases (set_single_call_flag
,
862 /* When cloning is allowed, we can assume that externally visible
863 functions are not called. We will compensate this by cloning
865 if (ipcp_versionable_function_p (node
)
866 && ipcp_cloning_candidate_p (node
))
872 if (disable
|| variable
)
874 for (i
= 0; i
< ipa_get_param_count (info
) ; i
++)
876 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
879 plats
->itself
.set_to_bottom ();
880 plats
->ctxlat
.set_to_bottom ();
881 set_agg_lats_to_bottom (plats
);
882 set_alignment_to_bottom (plats
);
885 set_all_contains_variable (plats
);
887 if (dump_file
&& (dump_flags
& TDF_DETAILS
)
888 && !node
->alias
&& !node
->thunk
.thunk_p
)
889 fprintf (dump_file
, "Marking all lattices of %s/%i as %s\n",
890 node
->name (), node
->order
,
891 disable
? "BOTTOM" : "VARIABLE");
894 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
895 if (ie
->indirect_info
->polymorphic
896 && ie
->indirect_info
->param_index
>= 0)
898 gcc_checking_assert (ie
->indirect_info
->param_index
>= 0);
899 ipa_get_parm_lattices (info
,
900 ie
->indirect_info
->param_index
)->virt_call
= 1;
904 /* Return the result of a (possibly arithmetic) pass through jump function
905 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
906 determined or be considered an interprocedural invariant. */
909 ipa_get_jf_pass_through_result (struct ipa_jump_func
*jfunc
, tree input
)
913 gcc_checking_assert (is_gimple_ip_invariant (input
));
914 if (ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
917 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc
))
919 restype
= boolean_type_node
;
921 restype
= TREE_TYPE (input
);
922 res
= fold_binary (ipa_get_jf_pass_through_operation (jfunc
), restype
,
923 input
, ipa_get_jf_pass_through_operand (jfunc
));
925 if (res
&& !is_gimple_ip_invariant (res
))
931 /* Return the result of an ancestor jump function JFUNC on the constant value
932 INPUT. Return NULL_TREE if that cannot be determined. */
935 ipa_get_jf_ancestor_result (struct ipa_jump_func
*jfunc
, tree input
)
937 gcc_checking_assert (TREE_CODE (input
) != TREE_BINFO
);
938 if (TREE_CODE (input
) == ADDR_EXPR
)
940 tree t
= TREE_OPERAND (input
, 0);
941 t
= build_ref_for_offset (EXPR_LOCATION (t
), t
,
942 ipa_get_jf_ancestor_offset (jfunc
),
943 ptr_type_node
, NULL
, false);
944 return build_fold_addr_expr (t
);
950 /* Determine whether JFUNC evaluates to a single known constant value and if
951 so, return it. Otherwise return NULL. INFO describes the caller node or
952 the one it is inlined to, so that pass-through jump functions can be
956 ipa_value_from_jfunc (struct ipa_node_params
*info
, struct ipa_jump_func
*jfunc
)
958 if (jfunc
->type
== IPA_JF_CONST
)
959 return ipa_get_jf_constant (jfunc
);
960 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
961 || jfunc
->type
== IPA_JF_ANCESTOR
)
966 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
967 idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
969 idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
971 if (info
->ipcp_orig_node
)
972 input
= info
->known_csts
[idx
];
975 ipcp_lattice
<tree
> *lat
;
978 || idx
>= ipa_get_param_count (info
))
980 lat
= ipa_get_scalar_lat (info
, idx
);
981 if (!lat
->is_single_const ())
983 input
= lat
->values
->value
;
989 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
990 return ipa_get_jf_pass_through_result (jfunc
, input
);
992 return ipa_get_jf_ancestor_result (jfunc
, input
);
998 /* Determie whether JFUNC evaluates to single known polymorphic context, given
999 that INFO describes the caller node or the one it is inlined to, CS is the
1000 call graph edge corresponding to JFUNC and CSIDX index of the described
1003 ipa_polymorphic_call_context
1004 ipa_context_from_jfunc (ipa_node_params
*info
, cgraph_edge
*cs
, int csidx
,
1005 ipa_jump_func
*jfunc
)
1007 ipa_edge_args
*args
= IPA_EDGE_REF (cs
);
1008 ipa_polymorphic_call_context ctx
;
1009 ipa_polymorphic_call_context
*edge_ctx
1010 = cs
? ipa_get_ith_polymorhic_call_context (args
, csidx
) : NULL
;
1012 if (edge_ctx
&& !edge_ctx
->useless_p ())
1015 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1016 || jfunc
->type
== IPA_JF_ANCESTOR
)
1018 ipa_polymorphic_call_context srcctx
;
1020 bool type_preserved
= true;
1021 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1023 if (ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1025 type_preserved
= ipa_get_jf_pass_through_type_preserved (jfunc
);
1026 srcidx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1030 type_preserved
= ipa_get_jf_ancestor_type_preserved (jfunc
);
1031 srcidx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1033 if (info
->ipcp_orig_node
)
1035 if (info
->known_contexts
.exists ())
1036 srcctx
= info
->known_contexts
[srcidx
];
1041 || srcidx
>= ipa_get_param_count (info
))
1043 ipcp_lattice
<ipa_polymorphic_call_context
> *lat
;
1044 lat
= ipa_get_poly_ctx_lat (info
, srcidx
);
1045 if (!lat
->is_single_const ())
1047 srcctx
= lat
->values
->value
;
1049 if (srcctx
.useless_p ())
1051 if (jfunc
->type
== IPA_JF_ANCESTOR
)
1052 srcctx
.offset_by (ipa_get_jf_ancestor_offset (jfunc
));
1053 if (!type_preserved
)
1054 srcctx
.possible_dynamic_type_change (cs
->in_polymorphic_cdtor
);
1055 srcctx
.combine_with (ctx
);
1062 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1063 bottom, not containing a variable component and without any known value at
1067 ipcp_verify_propagated_values (void)
1069 struct cgraph_node
*node
;
1071 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
1073 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
1074 int i
, count
= ipa_get_param_count (info
);
1076 for (i
= 0; i
< count
; i
++)
1078 ipcp_lattice
<tree
> *lat
= ipa_get_scalar_lat (info
, i
);
1081 && !lat
->contains_variable
1082 && lat
->values_count
== 0)
1086 symtab_node::dump_table (dump_file
);
1087 fprintf (dump_file
, "\nIPA lattices after constant "
1088 "propagation, before gcc_unreachable:\n");
1089 print_all_lattices (dump_file
, true, false);
1098 /* Return true iff X and Y should be considered equal values by IPA-CP. */
1101 values_equal_for_ipcp_p (tree x
, tree y
)
1103 gcc_checking_assert (x
!= NULL_TREE
&& y
!= NULL_TREE
);
1108 if (TREE_CODE (x
) == ADDR_EXPR
1109 && TREE_CODE (y
) == ADDR_EXPR
1110 && TREE_CODE (TREE_OPERAND (x
, 0)) == CONST_DECL
1111 && TREE_CODE (TREE_OPERAND (y
, 0)) == CONST_DECL
)
1112 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x
, 0)),
1113 DECL_INITIAL (TREE_OPERAND (y
, 0)), 0);
1115 return operand_equal_p (x
, y
, 0);
1118 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1121 values_equal_for_ipcp_p (ipa_polymorphic_call_context x
,
1122 ipa_polymorphic_call_context y
)
1124 return x
.equal_to (y
);
1128 /* Add a new value source to the value represented by THIS, marking that a
1129 value comes from edge CS and (if the underlying jump function is a
1130 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1131 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1132 scalar value of the parameter itself or the offset within an aggregate. */
1134 template <typename valtype
>
1136 ipcp_value
<valtype
>::add_source (cgraph_edge
*cs
, ipcp_value
*src_val
,
1137 int src_idx
, HOST_WIDE_INT offset
)
1139 ipcp_value_source
<valtype
> *src
;
1141 src
= new (ipcp_sources_pool
.allocate ()) ipcp_value_source
<valtype
>;
1142 src
->offset
= offset
;
1145 src
->index
= src_idx
;
1147 src
->next
= sources
;
1151 /* Allocate a new ipcp_value holding a tree constant, initialize its value to
1152 SOURCE and clear all other fields. */
1154 static ipcp_value
<tree
> *
1155 allocate_and_init_ipcp_value (tree source
)
1157 ipcp_value
<tree
> *val
;
1159 val
= ipcp_cst_values_pool
.allocate ();
1160 memset (val
, 0, sizeof (*val
));
1161 val
->value
= source
;
1165 /* Allocate a new ipcp_value holding a polymorphic context, initialize its
1166 value to SOURCE and clear all other fields. */
1168 static ipcp_value
<ipa_polymorphic_call_context
> *
1169 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source
)
1171 ipcp_value
<ipa_polymorphic_call_context
> *val
;
1174 val
= ipcp_poly_ctx_values_pool
.allocate ();
1175 memset (val
, 0, sizeof (*val
));
1176 val
->value
= source
;
1180 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1181 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1182 meaning. OFFSET -1 means the source is scalar and not a part of an
1185 template <typename valtype
>
1187 ipcp_lattice
<valtype
>::add_value (valtype newval
, cgraph_edge
*cs
,
1188 ipcp_value
<valtype
> *src_val
,
1189 int src_idx
, HOST_WIDE_INT offset
)
1191 ipcp_value
<valtype
> *val
;
1196 for (val
= values
; val
; val
= val
->next
)
1197 if (values_equal_for_ipcp_p (val
->value
, newval
))
1199 if (ipa_edge_within_scc (cs
))
1201 ipcp_value_source
<valtype
> *s
;
1202 for (s
= val
->sources
; s
; s
= s
->next
)
1209 val
->add_source (cs
, src_val
, src_idx
, offset
);
1213 if (values_count
== PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE
))
1215 /* We can only free sources, not the values themselves, because sources
1216 of other values in this SCC might point to them. */
1217 for (val
= values
; val
; val
= val
->next
)
1219 while (val
->sources
)
1221 ipcp_value_source
<valtype
> *src
= val
->sources
;
1222 val
->sources
= src
->next
;
1223 ipcp_sources_pool
.remove ((ipcp_value_source
<tree
>*)src
);
1228 return set_to_bottom ();
1232 val
= allocate_and_init_ipcp_value (newval
);
1233 val
->add_source (cs
, src_val
, src_idx
, offset
);
1239 /* Propagate values through a pass-through jump function JFUNC associated with
1240 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1241 is the index of the source parameter. */
1244 propagate_vals_accross_pass_through (cgraph_edge
*cs
,
1245 ipa_jump_func
*jfunc
,
1246 ipcp_lattice
<tree
> *src_lat
,
1247 ipcp_lattice
<tree
> *dest_lat
,
1250 ipcp_value
<tree
> *src_val
;
1253 /* Do not create new values when propagating within an SCC because if there
1254 are arithmetic functions with circular dependencies, there is infinite
1255 number of them and we would just make lattices bottom. */
1256 if ((ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1257 && ipa_edge_within_scc (cs
))
1258 ret
= dest_lat
->set_contains_variable ();
1260 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1262 tree cstval
= ipa_get_jf_pass_through_result (jfunc
, src_val
->value
);
1265 ret
|= dest_lat
->add_value (cstval
, cs
, src_val
, src_idx
);
1267 ret
|= dest_lat
->set_contains_variable ();
1273 /* Propagate values through an ancestor jump function JFUNC associated with
1274 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1275 is the index of the source parameter. */
1278 propagate_vals_accross_ancestor (struct cgraph_edge
*cs
,
1279 struct ipa_jump_func
*jfunc
,
1280 ipcp_lattice
<tree
> *src_lat
,
1281 ipcp_lattice
<tree
> *dest_lat
,
1284 ipcp_value
<tree
> *src_val
;
1287 if (ipa_edge_within_scc (cs
))
1288 return dest_lat
->set_contains_variable ();
1290 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1292 tree t
= ipa_get_jf_ancestor_result (jfunc
, src_val
->value
);
1295 ret
|= dest_lat
->add_value (t
, cs
, src_val
, src_idx
);
1297 ret
|= dest_lat
->set_contains_variable ();
1303 /* Propagate scalar values across jump function JFUNC that is associated with
1304 edge CS and put the values into DEST_LAT. */
1307 propagate_scalar_accross_jump_function (struct cgraph_edge
*cs
,
1308 struct ipa_jump_func
*jfunc
,
1309 ipcp_lattice
<tree
> *dest_lat
)
1311 if (dest_lat
->bottom
)
1314 if (jfunc
->type
== IPA_JF_CONST
)
1316 tree val
= ipa_get_jf_constant (jfunc
);
1317 return dest_lat
->add_value (val
, cs
, NULL
, 0);
1319 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
1320 || jfunc
->type
== IPA_JF_ANCESTOR
)
1322 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1323 ipcp_lattice
<tree
> *src_lat
;
1327 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1328 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1330 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1332 src_lat
= ipa_get_scalar_lat (caller_info
, src_idx
);
1333 if (src_lat
->bottom
)
1334 return dest_lat
->set_contains_variable ();
1336 /* If we would need to clone the caller and cannot, do not propagate. */
1337 if (!ipcp_versionable_function_p (cs
->caller
)
1338 && (src_lat
->contains_variable
1339 || (src_lat
->values_count
> 1)))
1340 return dest_lat
->set_contains_variable ();
1342 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1343 ret
= propagate_vals_accross_pass_through (cs
, jfunc
, src_lat
,
1346 ret
= propagate_vals_accross_ancestor (cs
, jfunc
, src_lat
, dest_lat
,
1349 if (src_lat
->contains_variable
)
1350 ret
|= dest_lat
->set_contains_variable ();
1355 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1356 use it for indirect inlining), we should propagate them too. */
1357 return dest_lat
->set_contains_variable ();
1360 /* Propagate scalar values across jump function JFUNC that is associated with
1361 edge CS and describes argument IDX and put the values into DEST_LAT. */
1364 propagate_context_accross_jump_function (cgraph_edge
*cs
,
1365 ipa_jump_func
*jfunc
, int idx
,
1366 ipcp_lattice
<ipa_polymorphic_call_context
> *dest_lat
)
1368 ipa_edge_args
*args
= IPA_EDGE_REF (cs
);
1369 if (dest_lat
->bottom
)
1372 bool added_sth
= false;
1373 bool type_preserved
= true;
1375 ipa_polymorphic_call_context edge_ctx
, *edge_ctx_ptr
1376 = ipa_get_ith_polymorhic_call_context (args
, idx
);
1379 edge_ctx
= *edge_ctx_ptr
;
1381 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1382 || jfunc
->type
== IPA_JF_ANCESTOR
)
1384 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1386 ipcp_lattice
<ipa_polymorphic_call_context
> *src_lat
;
1388 /* TODO: Once we figure out how to propagate speculations, it will
1389 probably be a good idea to switch to speculation if type_preserved is
1390 not set instead of punting. */
1391 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1393 if (ipa_get_jf_pass_through_operation (jfunc
) != NOP_EXPR
)
1395 type_preserved
= ipa_get_jf_pass_through_type_preserved (jfunc
);
1396 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1400 type_preserved
= ipa_get_jf_ancestor_type_preserved (jfunc
);
1401 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1404 src_lat
= ipa_get_poly_ctx_lat (caller_info
, src_idx
);
1405 /* If we would need to clone the caller and cannot, do not propagate. */
1406 if (!ipcp_versionable_function_p (cs
->caller
)
1407 && (src_lat
->contains_variable
1408 || (src_lat
->values_count
> 1)))
1411 ipcp_value
<ipa_polymorphic_call_context
> *src_val
;
1412 for (src_val
= src_lat
->values
; src_val
; src_val
= src_val
->next
)
1414 ipa_polymorphic_call_context cur
= src_val
->value
;
1416 if (!type_preserved
)
1417 cur
.possible_dynamic_type_change (cs
->in_polymorphic_cdtor
);
1418 if (jfunc
->type
== IPA_JF_ANCESTOR
)
1419 cur
.offset_by (ipa_get_jf_ancestor_offset (jfunc
));
1420 /* TODO: In cases we know how the context is going to be used,
1421 we can improve the result by passing proper OTR_TYPE. */
1422 cur
.combine_with (edge_ctx
);
1423 if (!cur
.useless_p ())
1425 if (src_lat
->contains_variable
1426 && !edge_ctx
.equal_to (cur
))
1427 ret
|= dest_lat
->set_contains_variable ();
1428 ret
|= dest_lat
->add_value (cur
, cs
, src_val
, src_idx
);
1438 if (!edge_ctx
.useless_p ())
1439 ret
|= dest_lat
->add_value (edge_ctx
, cs
);
1441 ret
|= dest_lat
->set_contains_variable ();
1447 /* Propagate alignments across jump function JFUNC that is associated with
1448 edge CS and update DEST_LAT accordingly. */
1451 propagate_alignment_accross_jump_function (struct cgraph_edge
*cs
,
1452 struct ipa_jump_func
*jfunc
,
1453 struct ipcp_param_lattices
*dest_lat
)
1455 if (alignment_bottom_p (dest_lat
))
1460 if (jfunc
->alignment
.known
)
1461 cur
= jfunc
->alignment
;
1462 else if (jfunc
->type
== IPA_JF_PASS_THROUGH
1463 || jfunc
->type
== IPA_JF_ANCESTOR
)
1465 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1466 struct ipcp_param_lattices
*src_lats
;
1467 HOST_WIDE_INT offset
= 0;
1470 if (jfunc
->type
== IPA_JF_PASS_THROUGH
)
1472 enum tree_code op
= ipa_get_jf_pass_through_operation (jfunc
);
1475 if (op
!= POINTER_PLUS_EXPR
1478 tree operand
= ipa_get_jf_pass_through_operand (jfunc
);
1479 if (!tree_fits_shwi_p (operand
))
1481 offset
= tree_to_shwi (operand
);
1483 src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1487 src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1488 offset
= ipa_get_jf_ancestor_offset (jfunc
) / BITS_PER_UNIT
;;
1491 src_lats
= ipa_get_parm_lattices (caller_info
, src_idx
);
1492 if (!src_lats
->alignment
.known
1493 || alignment_bottom_p (src_lats
))
1496 cur
= src_lats
->alignment
;
1497 cur
.misalign
= (cur
.misalign
+ offset
) % cur
.align
;
1502 if (!dest_lat
->alignment
.known
)
1504 dest_lat
->alignment
= cur
;
1507 else if (dest_lat
->alignment
.align
== cur
.align
1508 && dest_lat
->alignment
.misalign
== cur
.misalign
)
1513 set_alignment_to_bottom (dest_lat
);
1517 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1518 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1519 other cases, return false). If there are no aggregate items, set
1520 aggs_by_ref to NEW_AGGS_BY_REF. */
1523 set_check_aggs_by_ref (struct ipcp_param_lattices
*dest_plats
,
1524 bool new_aggs_by_ref
)
1526 if (dest_plats
->aggs
)
1528 if (dest_plats
->aggs_by_ref
!= new_aggs_by_ref
)
1530 set_agg_lats_to_bottom (dest_plats
);
1535 dest_plats
->aggs_by_ref
= new_aggs_by_ref
;
1539 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1540 already existing lattice for the given OFFSET and SIZE, marking all skipped
1541 lattices as containing variable and checking for overlaps. If there is no
1542 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1543 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1544 unless there are too many already. If there are two many, return false. If
1545 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1546 skipped lattices were newly marked as containing variable, set *CHANGE to
1550 merge_agg_lats_step (struct ipcp_param_lattices
*dest_plats
,
1551 HOST_WIDE_INT offset
, HOST_WIDE_INT val_size
,
1552 struct ipcp_agg_lattice
***aglat
,
1553 bool pre_existing
, bool *change
)
1555 gcc_checking_assert (offset
>= 0);
1557 while (**aglat
&& (**aglat
)->offset
< offset
)
1559 if ((**aglat
)->offset
+ (**aglat
)->size
> offset
)
1561 set_agg_lats_to_bottom (dest_plats
);
1564 *change
|= (**aglat
)->set_contains_variable ();
1565 *aglat
= &(**aglat
)->next
;
1568 if (**aglat
&& (**aglat
)->offset
== offset
)
1570 if ((**aglat
)->size
!= val_size
1572 && (**aglat
)->next
->offset
< offset
+ val_size
))
1574 set_agg_lats_to_bottom (dest_plats
);
1577 gcc_checking_assert (!(**aglat
)->next
1578 || (**aglat
)->next
->offset
>= offset
+ val_size
);
1583 struct ipcp_agg_lattice
*new_al
;
1585 if (**aglat
&& (**aglat
)->offset
< offset
+ val_size
)
1587 set_agg_lats_to_bottom (dest_plats
);
1590 if (dest_plats
->aggs_count
== PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS
))
1592 dest_plats
->aggs_count
++;
1593 new_al
= ipcp_agg_lattice_pool
.allocate ();
1594 memset (new_al
, 0, sizeof (*new_al
));
1596 new_al
->offset
= offset
;
1597 new_al
->size
= val_size
;
1598 new_al
->contains_variable
= pre_existing
;
1600 new_al
->next
= **aglat
;
1606 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1607 containing an unknown value. */
1610 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice
*aglat
)
1615 ret
|= aglat
->set_contains_variable ();
1616 aglat
= aglat
->next
;
1621 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1622 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1623 parameter used for lattice value sources. Return true if DEST_PLATS changed
1627 merge_aggregate_lattices (struct cgraph_edge
*cs
,
1628 struct ipcp_param_lattices
*dest_plats
,
1629 struct ipcp_param_lattices
*src_plats
,
1630 int src_idx
, HOST_WIDE_INT offset_delta
)
1632 bool pre_existing
= dest_plats
->aggs
!= NULL
;
1633 struct ipcp_agg_lattice
**dst_aglat
;
1636 if (set_check_aggs_by_ref (dest_plats
, src_plats
->aggs_by_ref
))
1638 if (src_plats
->aggs_bottom
)
1639 return set_agg_lats_contain_variable (dest_plats
);
1640 if (src_plats
->aggs_contain_variable
)
1641 ret
|= set_agg_lats_contain_variable (dest_plats
);
1642 dst_aglat
= &dest_plats
->aggs
;
1644 for (struct ipcp_agg_lattice
*src_aglat
= src_plats
->aggs
;
1646 src_aglat
= src_aglat
->next
)
1648 HOST_WIDE_INT new_offset
= src_aglat
->offset
- offset_delta
;
1652 if (merge_agg_lats_step (dest_plats
, new_offset
, src_aglat
->size
,
1653 &dst_aglat
, pre_existing
, &ret
))
1655 struct ipcp_agg_lattice
*new_al
= *dst_aglat
;
1657 dst_aglat
= &(*dst_aglat
)->next
;
1658 if (src_aglat
->bottom
)
1660 ret
|= new_al
->set_contains_variable ();
1663 if (src_aglat
->contains_variable
)
1664 ret
|= new_al
->set_contains_variable ();
1665 for (ipcp_value
<tree
> *val
= src_aglat
->values
;
1668 ret
|= new_al
->add_value (val
->value
, cs
, val
, src_idx
,
1671 else if (dest_plats
->aggs_bottom
)
1674 ret
|= set_chain_of_aglats_contains_variable (*dst_aglat
);
1678 /* Determine whether there is anything to propagate FROM SRC_PLATS through a
1679 pass-through JFUNC and if so, whether it has conform and conforms to the
1680 rules about propagating values passed by reference. */
1683 agg_pass_through_permissible_p (struct ipcp_param_lattices
*src_plats
,
1684 struct ipa_jump_func
*jfunc
)
1686 return src_plats
->aggs
1687 && (!src_plats
->aggs_by_ref
1688 || ipa_get_jf_pass_through_agg_preserved (jfunc
));
1691 /* Propagate scalar values across jump function JFUNC that is associated with
1692 edge CS and put the values into DEST_LAT. */
1695 propagate_aggs_accross_jump_function (struct cgraph_edge
*cs
,
1696 struct ipa_jump_func
*jfunc
,
1697 struct ipcp_param_lattices
*dest_plats
)
1701 if (dest_plats
->aggs_bottom
)
1704 if (jfunc
->type
== IPA_JF_PASS_THROUGH
1705 && ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
1707 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1708 int src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
1709 struct ipcp_param_lattices
*src_plats
;
1711 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
1712 if (agg_pass_through_permissible_p (src_plats
, jfunc
))
1714 /* Currently we do not produce clobber aggregate jump
1715 functions, replace with merging when we do. */
1716 gcc_assert (!jfunc
->agg
.items
);
1717 ret
|= merge_aggregate_lattices (cs
, dest_plats
, src_plats
,
1721 ret
|= set_agg_lats_contain_variable (dest_plats
);
1723 else if (jfunc
->type
== IPA_JF_ANCESTOR
1724 && ipa_get_jf_ancestor_agg_preserved (jfunc
))
1726 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
1727 int src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
1728 struct ipcp_param_lattices
*src_plats
;
1730 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
1731 if (src_plats
->aggs
&& src_plats
->aggs_by_ref
)
1733 /* Currently we do not produce clobber aggregate jump
1734 functions, replace with merging when we do. */
1735 gcc_assert (!jfunc
->agg
.items
);
1736 ret
|= merge_aggregate_lattices (cs
, dest_plats
, src_plats
, src_idx
,
1737 ipa_get_jf_ancestor_offset (jfunc
));
1739 else if (!src_plats
->aggs_by_ref
)
1740 ret
|= set_agg_lats_to_bottom (dest_plats
);
1742 ret
|= set_agg_lats_contain_variable (dest_plats
);
1744 else if (jfunc
->agg
.items
)
1746 bool pre_existing
= dest_plats
->aggs
!= NULL
;
1747 struct ipcp_agg_lattice
**aglat
= &dest_plats
->aggs
;
1748 struct ipa_agg_jf_item
*item
;
1751 if (set_check_aggs_by_ref (dest_plats
, jfunc
->agg
.by_ref
))
1754 FOR_EACH_VEC_ELT (*jfunc
->agg
.items
, i
, item
)
1756 HOST_WIDE_INT val_size
;
1758 if (item
->offset
< 0)
1760 gcc_checking_assert (is_gimple_ip_invariant (item
->value
));
1761 val_size
= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item
->value
)));
1763 if (merge_agg_lats_step (dest_plats
, item
->offset
, val_size
,
1764 &aglat
, pre_existing
, &ret
))
1766 ret
|= (*aglat
)->add_value (item
->value
, cs
, NULL
, 0, 0);
1767 aglat
= &(*aglat
)->next
;
1769 else if (dest_plats
->aggs_bottom
)
1773 ret
|= set_chain_of_aglats_contains_variable (*aglat
);
1776 ret
|= set_agg_lats_contain_variable (dest_plats
);
1781 /* Propagate constants from the caller to the callee of CS. INFO describes the
1785 propagate_constants_accross_call (struct cgraph_edge
*cs
)
1787 struct ipa_node_params
*callee_info
;
1788 enum availability availability
;
1789 struct cgraph_node
*callee
, *alias_or_thunk
;
1790 struct ipa_edge_args
*args
;
1792 int i
, args_count
, parms_count
;
1794 callee
= cs
->callee
->function_symbol (&availability
);
1795 if (!callee
->definition
)
1797 gcc_checking_assert (callee
->has_gimple_body_p ());
1798 callee_info
= IPA_NODE_REF (callee
);
1800 args
= IPA_EDGE_REF (cs
);
1801 args_count
= ipa_get_cs_argument_count (args
);
1802 parms_count
= ipa_get_param_count (callee_info
);
1803 if (parms_count
== 0)
1806 /* No propagation through instrumentation thunks is available yet.
1807 It should be possible with proper mapping of call args and
1808 instrumented callee params in the propagation loop below. But
1809 this case mostly occurs when legacy code calls instrumented code
1810 and it is not a primary target for optimizations.
1811 We detect instrumentation thunks in aliases and thunks chain by
1812 checking instrumentation_clone flag for chain source and target.
1813 Going through instrumentation thunks we always have it changed
1814 from 0 to 1 and all other nodes do not change it. */
1815 if (!cs
->callee
->instrumentation_clone
1816 && callee
->instrumentation_clone
)
1818 for (i
= 0; i
< parms_count
; i
++)
1819 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
,
1824 /* If this call goes through a thunk we must not propagate to the first (0th)
1825 parameter. However, we might need to uncover a thunk from below a series
1826 of aliases first. */
1827 alias_or_thunk
= cs
->callee
;
1828 while (alias_or_thunk
->alias
)
1829 alias_or_thunk
= alias_or_thunk
->get_alias_target ();
1830 if (alias_or_thunk
->thunk
.thunk_p
)
1832 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
,
1839 for (; (i
< args_count
) && (i
< parms_count
); i
++)
1841 struct ipa_jump_func
*jump_func
= ipa_get_ith_jump_func (args
, i
);
1842 struct ipcp_param_lattices
*dest_plats
;
1844 dest_plats
= ipa_get_parm_lattices (callee_info
, i
);
1845 if (availability
== AVAIL_INTERPOSABLE
)
1846 ret
|= set_all_contains_variable (dest_plats
);
1849 ret
|= propagate_scalar_accross_jump_function (cs
, jump_func
,
1850 &dest_plats
->itself
);
1851 ret
|= propagate_context_accross_jump_function (cs
, jump_func
, i
,
1852 &dest_plats
->ctxlat
);
1853 ret
|= propagate_alignment_accross_jump_function (cs
, jump_func
,
1855 ret
|= propagate_aggs_accross_jump_function (cs
, jump_func
,
1859 for (; i
< parms_count
; i
++)
1860 ret
|= set_all_contains_variable (ipa_get_parm_lattices (callee_info
, i
));
1865 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
1866 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1867 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
1870 ipa_get_indirect_edge_target_1 (struct cgraph_edge
*ie
,
1871 vec
<tree
> known_csts
,
1872 vec
<ipa_polymorphic_call_context
> known_contexts
,
1873 vec
<ipa_agg_jump_function_p
> known_aggs
,
1874 struct ipa_agg_replacement_value
*agg_reps
,
1877 int param_index
= ie
->indirect_info
->param_index
;
1878 HOST_WIDE_INT anc_offset
;
1882 *speculative
= false;
1884 if (param_index
== -1
1885 || known_csts
.length () <= (unsigned int) param_index
)
1888 if (!ie
->indirect_info
->polymorphic
)
1892 if (ie
->indirect_info
->agg_contents
)
1899 if (agg_reps
->index
== param_index
1900 && agg_reps
->offset
== ie
->indirect_info
->offset
1901 && agg_reps
->by_ref
== ie
->indirect_info
->by_ref
)
1903 t
= agg_reps
->value
;
1906 agg_reps
= agg_reps
->next
;
1909 else if (known_aggs
.length () > (unsigned int) param_index
)
1911 struct ipa_agg_jump_function
*agg
;
1912 agg
= known_aggs
[param_index
];
1913 t
= ipa_find_agg_cst_for_param (agg
, ie
->indirect_info
->offset
,
1914 ie
->indirect_info
->by_ref
);
1920 t
= known_csts
[param_index
];
1923 TREE_CODE (t
) == ADDR_EXPR
1924 && TREE_CODE (TREE_OPERAND (t
, 0)) == FUNCTION_DECL
)
1925 return TREE_OPERAND (t
, 0);
1930 if (!opt_for_fn (ie
->caller
->decl
, flag_devirtualize
))
1933 gcc_assert (!ie
->indirect_info
->agg_contents
);
1934 anc_offset
= ie
->indirect_info
->offset
;
1938 /* Try to work out value of virtual table pointer value in replacemnets. */
1939 if (!t
&& agg_reps
&& !ie
->indirect_info
->by_ref
)
1943 if (agg_reps
->index
== param_index
1944 && agg_reps
->offset
== ie
->indirect_info
->offset
1945 && agg_reps
->by_ref
)
1947 t
= agg_reps
->value
;
1950 agg_reps
= agg_reps
->next
;
1954 /* Try to work out value of virtual table pointer value in known
1955 aggregate values. */
1956 if (!t
&& known_aggs
.length () > (unsigned int) param_index
1957 && !ie
->indirect_info
->by_ref
)
1959 struct ipa_agg_jump_function
*agg
;
1960 agg
= known_aggs
[param_index
];
1961 t
= ipa_find_agg_cst_for_param (agg
, ie
->indirect_info
->offset
,
1965 /* If we found the virtual table pointer, lookup the target. */
1969 unsigned HOST_WIDE_INT offset
;
1970 if (vtable_pointer_value_to_vtable (t
, &vtable
, &offset
))
1972 target
= gimple_get_virt_method_for_vtable (ie
->indirect_info
->otr_token
,
1976 if ((TREE_CODE (TREE_TYPE (target
)) == FUNCTION_TYPE
1977 && DECL_FUNCTION_CODE (target
) == BUILT_IN_UNREACHABLE
)
1978 || !possible_polymorphic_call_target_p
1979 (ie
, cgraph_node::get (target
)))
1980 target
= ipa_impossible_devirt_target (ie
, target
);
1981 *speculative
= ie
->indirect_info
->vptr_changed
;
1988 /* Do we know the constant value of pointer? */
1990 t
= known_csts
[param_index
];
1992 gcc_checking_assert (!t
|| TREE_CODE (t
) != TREE_BINFO
);
1994 ipa_polymorphic_call_context context
;
1995 if (known_contexts
.length () > (unsigned int) param_index
)
1997 context
= known_contexts
[param_index
];
1998 context
.offset_by (anc_offset
);
1999 if (ie
->indirect_info
->vptr_changed
)
2000 context
.possible_dynamic_type_change (ie
->in_polymorphic_cdtor
,
2001 ie
->indirect_info
->otr_type
);
2004 ipa_polymorphic_call_context ctx2
= ipa_polymorphic_call_context
2005 (t
, ie
->indirect_info
->otr_type
, anc_offset
);
2006 if (!ctx2
.useless_p ())
2007 context
.combine_with (ctx2
, ie
->indirect_info
->otr_type
);
2012 context
= ipa_polymorphic_call_context (t
, ie
->indirect_info
->otr_type
,
2014 if (ie
->indirect_info
->vptr_changed
)
2015 context
.possible_dynamic_type_change (ie
->in_polymorphic_cdtor
,
2016 ie
->indirect_info
->otr_type
);
2021 vec
<cgraph_node
*>targets
;
2024 targets
= possible_polymorphic_call_targets
2025 (ie
->indirect_info
->otr_type
,
2026 ie
->indirect_info
->otr_token
,
2028 if (!final
|| targets
.length () > 1)
2030 struct cgraph_node
*node
;
2033 if (!opt_for_fn (ie
->caller
->decl
, flag_devirtualize_speculatively
)
2034 || ie
->speculative
|| !ie
->maybe_hot_p ())
2036 node
= try_speculative_devirtualization (ie
->indirect_info
->otr_type
,
2037 ie
->indirect_info
->otr_token
,
2041 *speculative
= true;
2042 target
= node
->decl
;
2049 *speculative
= false;
2050 if (targets
.length () == 1)
2051 target
= targets
[0]->decl
;
2053 target
= ipa_impossible_devirt_target (ie
, NULL_TREE
);
2056 if (target
&& !possible_polymorphic_call_target_p (ie
,
2057 cgraph_node::get (target
)))
2058 target
= ipa_impossible_devirt_target (ie
, target
);
2064 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2065 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2066 return the destination. */
2069 ipa_get_indirect_edge_target (struct cgraph_edge
*ie
,
2070 vec
<tree
> known_csts
,
2071 vec
<ipa_polymorphic_call_context
> known_contexts
,
2072 vec
<ipa_agg_jump_function_p
> known_aggs
,
2075 return ipa_get_indirect_edge_target_1 (ie
, known_csts
, known_contexts
,
2076 known_aggs
, NULL
, speculative
);
2079 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
2080 and KNOWN_CONTEXTS. */
2083 devirtualization_time_bonus (struct cgraph_node
*node
,
2084 vec
<tree
> known_csts
,
2085 vec
<ipa_polymorphic_call_context
> known_contexts
,
2086 vec
<ipa_agg_jump_function_p
> known_aggs
)
2088 struct cgraph_edge
*ie
;
2091 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
2093 struct cgraph_node
*callee
;
2094 struct inline_summary
*isummary
;
2095 enum availability avail
;
2099 target
= ipa_get_indirect_edge_target (ie
, known_csts
, known_contexts
,
2100 known_aggs
, &speculative
);
2104 /* Only bare minimum benefit for clearly un-inlineable targets. */
2106 callee
= cgraph_node::get (target
);
2107 if (!callee
|| !callee
->definition
)
2109 callee
= callee
->function_symbol (&avail
);
2110 if (avail
< AVAIL_AVAILABLE
)
2112 isummary
= inline_summaries
->get (callee
);
2113 if (!isummary
->inlinable
)
2116 /* FIXME: The values below need re-considering and perhaps also
2117 integrating into the cost metrics, at lest in some very basic way. */
2118 if (isummary
->size
<= MAX_INLINE_INSNS_AUTO
/ 4)
2119 res
+= 31 / ((int)speculative
+ 1);
2120 else if (isummary
->size
<= MAX_INLINE_INSNS_AUTO
/ 2)
2121 res
+= 15 / ((int)speculative
+ 1);
2122 else if (isummary
->size
<= MAX_INLINE_INSNS_AUTO
2123 || DECL_DECLARED_INLINE_P (callee
->decl
))
2124 res
+= 7 / ((int)speculative
+ 1);
2130 /* Return time bonus incurred because of HINTS. */
2133 hint_time_bonus (inline_hints hints
)
2136 if (hints
& (INLINE_HINT_loop_iterations
| INLINE_HINT_loop_stride
))
2137 result
+= PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS
);
2138 if (hints
& INLINE_HINT_array_index
)
2139 result
+= PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS
);
2143 /* If there is a reason to penalize the function described by INFO in the
2144 cloning goodness evaluation, do so. */
2146 static inline int64_t
2147 incorporate_penalties (ipa_node_params
*info
, int64_t evaluation
)
2149 if (info
->node_within_scc
)
2150 evaluation
= (evaluation
2151 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY
))) / 100;
2153 if (info
->node_calling_single_call
)
2154 evaluation
= (evaluation
2155 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY
)))
2161 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2162 and SIZE_COST and with the sum of frequencies of incoming edges to the
2163 potential new clone in FREQUENCIES. */
2166 good_cloning_opportunity_p (struct cgraph_node
*node
, int time_benefit
,
2167 int freq_sum
, gcov_type count_sum
, int size_cost
)
2169 if (time_benefit
== 0
2170 || !opt_for_fn (node
->decl
, flag_ipa_cp_clone
)
2171 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node
->decl
)))
2174 gcc_assert (size_cost
> 0);
2176 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2179 int factor
= (count_sum
* 1000) / max_count
;
2180 int64_t evaluation
= (((int64_t) time_benefit
* factor
)
2182 evaluation
= incorporate_penalties (info
, evaluation
);
2184 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2185 fprintf (dump_file
, " good_cloning_opportunity_p (time: %i, "
2186 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
2187 "%s%s) -> evaluation: " "%" PRId64
2188 ", threshold: %i\n",
2189 time_benefit
, size_cost
, (HOST_WIDE_INT
) count_sum
,
2190 info
->node_within_scc
? ", scc" : "",
2191 info
->node_calling_single_call
? ", single_call" : "",
2192 evaluation
, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
));
2194 return evaluation
>= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
);
2198 int64_t evaluation
= (((int64_t) time_benefit
* freq_sum
)
2200 evaluation
= incorporate_penalties (info
, evaluation
);
2202 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2203 fprintf (dump_file
, " good_cloning_opportunity_p (time: %i, "
2204 "size: %i, freq_sum: %i%s%s) -> evaluation: "
2205 "%" PRId64
", threshold: %i\n",
2206 time_benefit
, size_cost
, freq_sum
,
2207 info
->node_within_scc
? ", scc" : "",
2208 info
->node_calling_single_call
? ", single_call" : "",
2209 evaluation
, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
));
2211 return evaluation
>= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD
);
2215 /* Return all context independent values from aggregate lattices in PLATS in a
2216 vector. Return NULL if there are none. */
2218 static vec
<ipa_agg_jf_item
, va_gc
> *
2219 context_independent_aggregate_values (struct ipcp_param_lattices
*plats
)
2221 vec
<ipa_agg_jf_item
, va_gc
> *res
= NULL
;
2223 if (plats
->aggs_bottom
2224 || plats
->aggs_contain_variable
2225 || plats
->aggs_count
== 0)
2228 for (struct ipcp_agg_lattice
*aglat
= plats
->aggs
;
2230 aglat
= aglat
->next
)
2231 if (aglat
->is_single_const ())
2233 struct ipa_agg_jf_item item
;
2234 item
.offset
= aglat
->offset
;
2235 item
.value
= aglat
->values
->value
;
2236 vec_safe_push (res
, item
);
2241 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2242 populate them with values of parameters that are known independent of the
2243 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2244 non-NULL, the movement cost of all removable parameters will be stored in
2248 gather_context_independent_values (struct ipa_node_params
*info
,
2249 vec
<tree
> *known_csts
,
2250 vec
<ipa_polymorphic_call_context
>
2252 vec
<ipa_agg_jump_function
> *known_aggs
,
2253 int *removable_params_cost
)
2255 int i
, count
= ipa_get_param_count (info
);
2258 known_csts
->create (0);
2259 known_contexts
->create (0);
2260 known_csts
->safe_grow_cleared (count
);
2261 known_contexts
->safe_grow_cleared (count
);
2264 known_aggs
->create (0);
2265 known_aggs
->safe_grow_cleared (count
);
2268 if (removable_params_cost
)
2269 *removable_params_cost
= 0;
2271 for (i
= 0; i
< count
; i
++)
2273 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2274 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
2276 if (lat
->is_single_const ())
2278 ipcp_value
<tree
> *val
= lat
->values
;
2279 gcc_checking_assert (TREE_CODE (val
->value
) != TREE_BINFO
);
2280 (*known_csts
)[i
] = val
->value
;
2281 if (removable_params_cost
)
2282 *removable_params_cost
2283 += estimate_move_cost (TREE_TYPE (val
->value
), false);
2286 else if (removable_params_cost
2287 && !ipa_is_param_used (info
, i
))
2288 *removable_params_cost
2289 += ipa_get_param_move_cost (info
, i
);
2291 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
2292 if (ctxlat
->is_single_const ())
2294 (*known_contexts
)[i
] = ctxlat
->values
->value
;
2300 vec
<ipa_agg_jf_item
, va_gc
> *agg_items
;
2301 struct ipa_agg_jump_function
*ajf
;
2303 agg_items
= context_independent_aggregate_values (plats
);
2304 ajf
= &(*known_aggs
)[i
];
2305 ajf
->items
= agg_items
;
2306 ajf
->by_ref
= plats
->aggs_by_ref
;
2307 ret
|= agg_items
!= NULL
;
2314 /* The current interface in ipa-inline-analysis requires a pointer vector.
2317 FIXME: That interface should be re-worked, this is slightly silly. Still,
2318 I'd like to discuss how to change it first and this demonstrates the
2321 static vec
<ipa_agg_jump_function_p
>
2322 agg_jmp_p_vec_for_t_vec (vec
<ipa_agg_jump_function
> known_aggs
)
2324 vec
<ipa_agg_jump_function_p
> ret
;
2325 struct ipa_agg_jump_function
*ajf
;
2328 ret
.create (known_aggs
.length ());
2329 FOR_EACH_VEC_ELT (known_aggs
, i
, ajf
)
2330 ret
.quick_push (ajf
);
2334 /* Perform time and size measurement of NODE with the context given in
2335 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
2336 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2337 all context-independent removable parameters and EST_MOVE_COST of estimated
2338 movement of the considered parameter and store it into VAL. */
2341 perform_estimation_of_a_value (cgraph_node
*node
, vec
<tree
> known_csts
,
2342 vec
<ipa_polymorphic_call_context
> known_contexts
,
2343 vec
<ipa_agg_jump_function_p
> known_aggs_ptrs
,
2344 int base_time
, int removable_params_cost
,
2345 int est_move_cost
, ipcp_value_base
*val
)
2347 int time
, size
, time_benefit
;
2350 estimate_ipcp_clone_size_and_time (node
, known_csts
, known_contexts
,
2351 known_aggs_ptrs
, &size
, &time
,
2353 time_benefit
= base_time
- time
2354 + devirtualization_time_bonus (node
, known_csts
, known_contexts
,
2356 + hint_time_bonus (hints
)
2357 + removable_params_cost
+ est_move_cost
;
2359 gcc_checking_assert (size
>=0);
2360 /* The inliner-heuristics based estimates may think that in certain
2361 contexts some functions do not have any size at all but we want
2362 all specializations to have at least a tiny cost, not least not to
2367 val
->local_time_benefit
= time_benefit
;
2368 val
->local_size_cost
= size
;
2371 /* Iterate over known values of parameters of NODE and estimate the local
2372 effects in terms of time and size they have. */
2375 estimate_local_effects (struct cgraph_node
*node
)
2377 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2378 int i
, count
= ipa_get_param_count (info
);
2379 vec
<tree
> known_csts
;
2380 vec
<ipa_polymorphic_call_context
> known_contexts
;
2381 vec
<ipa_agg_jump_function
> known_aggs
;
2382 vec
<ipa_agg_jump_function_p
> known_aggs_ptrs
;
2384 int base_time
= inline_summaries
->get (node
)->time
;
2385 int removable_params_cost
;
2387 if (!count
|| !ipcp_versionable_function_p (node
))
2390 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2391 fprintf (dump_file
, "\nEstimating effects for %s/%i, base_time: %i.\n",
2392 node
->name (), node
->order
, base_time
);
2394 always_const
= gather_context_independent_values (info
, &known_csts
,
2395 &known_contexts
, &known_aggs
,
2396 &removable_params_cost
);
2397 known_aggs_ptrs
= agg_jmp_p_vec_for_t_vec (known_aggs
);
2400 struct caller_statistics stats
;
2404 init_caller_stats (&stats
);
2405 node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
2407 estimate_ipcp_clone_size_and_time (node
, known_csts
, known_contexts
,
2408 known_aggs_ptrs
, &size
, &time
, &hints
);
2409 time
-= devirtualization_time_bonus (node
, known_csts
, known_contexts
,
2411 time
-= hint_time_bonus (hints
);
2412 time
-= removable_params_cost
;
2413 size
-= stats
.n_calls
* removable_params_cost
;
2416 fprintf (dump_file
, " - context independent values, size: %i, "
2417 "time_benefit: %i\n", size
, base_time
- time
);
2420 || node
->will_be_removed_from_program_if_no_direct_calls_p ())
2422 info
->do_clone_for_all_contexts
= true;
2426 fprintf (dump_file
, " Decided to specialize for all "
2427 "known contexts, code not going to grow.\n");
2429 else if (good_cloning_opportunity_p (node
, base_time
- time
,
2430 stats
.freq_sum
, stats
.count_sum
,
2433 if (size
+ overall_size
<= max_new_size
)
2435 info
->do_clone_for_all_contexts
= true;
2437 overall_size
+= size
;
2440 fprintf (dump_file
, " Decided to specialize for all "
2441 "known contexts, growth deemed beneficial.\n");
2443 else if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2444 fprintf (dump_file
, " Not cloning for all contexts because "
2445 "max_new_size would be reached with %li.\n",
2446 size
+ overall_size
);
2450 for (i
= 0; i
< count
; i
++)
2452 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2453 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
2454 ipcp_value
<tree
> *val
;
2461 for (val
= lat
->values
; val
; val
= val
->next
)
2463 gcc_checking_assert (TREE_CODE (val
->value
) != TREE_BINFO
);
2464 known_csts
[i
] = val
->value
;
2466 int emc
= estimate_move_cost (TREE_TYPE (val
->value
), true);
2467 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
2468 known_aggs_ptrs
, base_time
,
2469 removable_params_cost
, emc
, val
);
2471 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2473 fprintf (dump_file
, " - estimates for value ");
2474 print_ipcp_constant_value (dump_file
, val
->value
);
2475 fprintf (dump_file
, " for ");
2476 ipa_dump_param (dump_file
, info
, i
);
2477 fprintf (dump_file
, ": time_benefit: %i, size: %i\n",
2478 val
->local_time_benefit
, val
->local_size_cost
);
2481 known_csts
[i
] = NULL_TREE
;
2484 for (i
= 0; i
< count
; i
++)
2486 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2488 if (!plats
->virt_call
)
2491 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
2492 ipcp_value
<ipa_polymorphic_call_context
> *val
;
2496 || !known_contexts
[i
].useless_p ())
2499 for (val
= ctxlat
->values
; val
; val
= val
->next
)
2501 known_contexts
[i
] = val
->value
;
2502 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
2503 known_aggs_ptrs
, base_time
,
2504 removable_params_cost
, 0, val
);
2506 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2508 fprintf (dump_file
, " - estimates for polymorphic context ");
2509 print_ipcp_constant_value (dump_file
, val
->value
);
2510 fprintf (dump_file
, " for ");
2511 ipa_dump_param (dump_file
, info
, i
);
2512 fprintf (dump_file
, ": time_benefit: %i, size: %i\n",
2513 val
->local_time_benefit
, val
->local_size_cost
);
2516 known_contexts
[i
] = ipa_polymorphic_call_context ();
2519 for (i
= 0; i
< count
; i
++)
2521 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2522 struct ipa_agg_jump_function
*ajf
;
2523 struct ipcp_agg_lattice
*aglat
;
2525 if (plats
->aggs_bottom
|| !plats
->aggs
)
2528 ajf
= &known_aggs
[i
];
2529 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
2531 ipcp_value
<tree
> *val
;
2532 if (aglat
->bottom
|| !aglat
->values
2533 /* If the following is true, the one value is in known_aggs. */
2534 || (!plats
->aggs_contain_variable
2535 && aglat
->is_single_const ()))
2538 for (val
= aglat
->values
; val
; val
= val
->next
)
2540 struct ipa_agg_jf_item item
;
2542 item
.offset
= aglat
->offset
;
2543 item
.value
= val
->value
;
2544 vec_safe_push (ajf
->items
, item
);
2546 perform_estimation_of_a_value (node
, known_csts
, known_contexts
,
2547 known_aggs_ptrs
, base_time
,
2548 removable_params_cost
, 0, val
);
2550 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2552 fprintf (dump_file
, " - estimates for value ");
2553 print_ipcp_constant_value (dump_file
, val
->value
);
2554 fprintf (dump_file
, " for ");
2555 ipa_dump_param (dump_file
, info
, i
);
2556 fprintf (dump_file
, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
2557 "]: time_benefit: %i, size: %i\n",
2558 plats
->aggs_by_ref
? "ref " : "",
2560 val
->local_time_benefit
, val
->local_size_cost
);
2568 for (i
= 0; i
< count
; i
++)
2569 vec_free (known_aggs
[i
].items
);
2571 known_csts
.release ();
2572 known_contexts
.release ();
2573 known_aggs
.release ();
2574 known_aggs_ptrs
.release ();
2578 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2579 topological sort of values. */
2581 template <typename valtype
>
2583 value_topo_info
<valtype
>::add_val (ipcp_value
<valtype
> *cur_val
)
2585 ipcp_value_source
<valtype
> *src
;
2591 cur_val
->dfs
= dfs_counter
;
2592 cur_val
->low_link
= dfs_counter
;
2594 cur_val
->topo_next
= stack
;
2596 cur_val
->on_stack
= true;
2598 for (src
= cur_val
->sources
; src
; src
= src
->next
)
2601 if (src
->val
->dfs
== 0)
2604 if (src
->val
->low_link
< cur_val
->low_link
)
2605 cur_val
->low_link
= src
->val
->low_link
;
2607 else if (src
->val
->on_stack
2608 && src
->val
->dfs
< cur_val
->low_link
)
2609 cur_val
->low_link
= src
->val
->dfs
;
2612 if (cur_val
->dfs
== cur_val
->low_link
)
2614 ipcp_value
<valtype
> *v
, *scc_list
= NULL
;
2619 stack
= v
->topo_next
;
2620 v
->on_stack
= false;
2622 v
->scc_next
= scc_list
;
2625 while (v
!= cur_val
);
2627 cur_val
->topo_next
= values_topo
;
2628 values_topo
= cur_val
;
2632 /* Add all values in lattices associated with NODE to the topological sort if
2633 they are not there yet. */
2636 add_all_node_vals_to_toposort (cgraph_node
*node
, ipa_topo_info
*topo
)
2638 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2639 int i
, count
= ipa_get_param_count (info
);
2641 for (i
= 0; i
< count
; i
++)
2643 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
2644 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
2645 struct ipcp_agg_lattice
*aglat
;
2649 ipcp_value
<tree
> *val
;
2650 for (val
= lat
->values
; val
; val
= val
->next
)
2651 topo
->constants
.add_val (val
);
2654 if (!plats
->aggs_bottom
)
2655 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
2658 ipcp_value
<tree
> *val
;
2659 for (val
= aglat
->values
; val
; val
= val
->next
)
2660 topo
->constants
.add_val (val
);
2663 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
2664 if (!ctxlat
->bottom
)
2666 ipcp_value
<ipa_polymorphic_call_context
> *ctxval
;
2667 for (ctxval
= ctxlat
->values
; ctxval
; ctxval
= ctxval
->next
)
2668 topo
->contexts
.add_val (ctxval
);
2673 /* One pass of constants propagation along the call graph edges, from callers
2674 to callees (requires topological ordering in TOPO), iterate over strongly
2675 connected components. */
2678 propagate_constants_topo (struct ipa_topo_info
*topo
)
2682 for (i
= topo
->nnodes
- 1; i
>= 0; i
--)
2685 struct cgraph_node
*v
, *node
= topo
->order
[i
];
2686 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
2688 /* First, iteratively propagate within the strongly connected component
2689 until all lattices stabilize. */
2690 FOR_EACH_VEC_ELT (cycle_nodes
, j
, v
)
2691 if (v
->has_gimple_body_p ())
2692 push_node_to_stack (topo
, v
);
2694 v
= pop_node_from_stack (topo
);
2697 struct cgraph_edge
*cs
;
2699 for (cs
= v
->callees
; cs
; cs
= cs
->next_callee
)
2700 if (ipa_edge_within_scc (cs
))
2702 IPA_NODE_REF (v
)->node_within_scc
= true;
2703 if (propagate_constants_accross_call (cs
))
2704 push_node_to_stack (topo
, cs
->callee
->function_symbol ());
2706 v
= pop_node_from_stack (topo
);
2709 /* Afterwards, propagate along edges leading out of the SCC, calculates
2710 the local effects of the discovered constants and all valid values to
2711 their topological sort. */
2712 FOR_EACH_VEC_ELT (cycle_nodes
, j
, v
)
2713 if (v
->has_gimple_body_p ())
2715 struct cgraph_edge
*cs
;
2717 estimate_local_effects (v
);
2718 add_all_node_vals_to_toposort (v
, topo
);
2719 for (cs
= v
->callees
; cs
; cs
= cs
->next_callee
)
2720 if (!ipa_edge_within_scc (cs
))
2721 propagate_constants_accross_call (cs
);
2723 cycle_nodes
.release ();
2728 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2729 the bigger one if otherwise. */
2732 safe_add (int a
, int b
)
2734 if (a
> INT_MAX
/2 || b
> INT_MAX
/2)
2735 return a
> b
? a
: b
;
2741 /* Propagate the estimated effects of individual values along the topological
2742 from the dependent values to those they depend on. */
2744 template <typename valtype
>
2746 value_topo_info
<valtype
>::propagate_effects ()
2748 ipcp_value
<valtype
> *base
;
2750 for (base
= values_topo
; base
; base
= base
->topo_next
)
2752 ipcp_value_source
<valtype
> *src
;
2753 ipcp_value
<valtype
> *val
;
2754 int time
= 0, size
= 0;
2756 for (val
= base
; val
; val
= val
->scc_next
)
2758 time
= safe_add (time
,
2759 val
->local_time_benefit
+ val
->prop_time_benefit
);
2760 size
= safe_add (size
, val
->local_size_cost
+ val
->prop_size_cost
);
2763 for (val
= base
; val
; val
= val
->scc_next
)
2764 for (src
= val
->sources
; src
; src
= src
->next
)
2766 && src
->cs
->maybe_hot_p ())
2768 src
->val
->prop_time_benefit
= safe_add (time
,
2769 src
->val
->prop_time_benefit
);
2770 src
->val
->prop_size_cost
= safe_add (size
,
2771 src
->val
->prop_size_cost
);
2777 /* Propagate constants, polymorphic contexts and their effects from the
2778 summaries interprocedurally. */
2781 ipcp_propagate_stage (struct ipa_topo_info
*topo
)
2783 struct cgraph_node
*node
;
2786 fprintf (dump_file
, "\n Propagating constants:\n\n");
2789 ipa_update_after_lto_read ();
2792 FOR_EACH_DEFINED_FUNCTION (node
)
2794 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2796 determine_versionability (node
);
2797 if (node
->has_gimple_body_p ())
2799 info
->lattices
= XCNEWVEC (struct ipcp_param_lattices
,
2800 ipa_get_param_count (info
));
2801 initialize_node_lattices (node
);
2803 if (node
->definition
&& !node
->alias
)
2804 overall_size
+= inline_summaries
->get (node
)->self_size
;
2805 if (node
->count
> max_count
)
2806 max_count
= node
->count
;
2809 max_new_size
= overall_size
;
2810 if (max_new_size
< PARAM_VALUE (PARAM_LARGE_UNIT_INSNS
))
2811 max_new_size
= PARAM_VALUE (PARAM_LARGE_UNIT_INSNS
);
2812 max_new_size
+= max_new_size
* PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH
) / 100 + 1;
2815 fprintf (dump_file
, "\noverall_size: %li, max_new_size: %li\n",
2816 overall_size
, max_new_size
);
2818 propagate_constants_topo (topo
);
2819 #ifdef ENABLE_CHECKING
2820 ipcp_verify_propagated_values ();
2822 topo
->constants
.propagate_effects ();
2823 topo
->contexts
.propagate_effects ();
2827 fprintf (dump_file
, "\nIPA lattices after all propagation:\n");
2828 print_all_lattices (dump_file
, (dump_flags
& TDF_DETAILS
), true);
2832 /* Discover newly direct outgoing edges from NODE which is a new clone with
2833 known KNOWN_CSTS and make them direct. */
2836 ipcp_discover_new_direct_edges (struct cgraph_node
*node
,
2837 vec
<tree
> known_csts
,
2838 vec
<ipa_polymorphic_call_context
>
2840 struct ipa_agg_replacement_value
*aggvals
)
2842 struct cgraph_edge
*ie
, *next_ie
;
2845 for (ie
= node
->indirect_calls
; ie
; ie
= next_ie
)
2850 next_ie
= ie
->next_callee
;
2851 target
= ipa_get_indirect_edge_target_1 (ie
, known_csts
, known_contexts
,
2852 vNULL
, aggvals
, &speculative
);
2855 bool agg_contents
= ie
->indirect_info
->agg_contents
;
2856 bool polymorphic
= ie
->indirect_info
->polymorphic
;
2857 int param_index
= ie
->indirect_info
->param_index
;
2858 struct cgraph_edge
*cs
= ipa_make_edge_direct_to_target (ie
, target
,
2862 if (cs
&& !agg_contents
&& !polymorphic
)
2864 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2865 int c
= ipa_get_controlled_uses (info
, param_index
);
2866 if (c
!= IPA_UNDESCRIBED_USE
)
2868 struct ipa_ref
*to_del
;
2871 ipa_set_controlled_uses (info
, param_index
, c
);
2872 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2873 fprintf (dump_file
, " controlled uses count of param "
2874 "%i bumped down to %i\n", param_index
, c
);
2876 && (to_del
= node
->find_reference (cs
->callee
, NULL
, 0)))
2878 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2879 fprintf (dump_file
, " and even removing its "
2880 "cloning-created reference\n");
2881 to_del
->remove_reference ();
2887 /* Turning calls to direct calls will improve overall summary. */
2889 inline_update_overall_summary (node
);
2892 /* Vector of pointers which for linked lists of clones of an original crgaph
2895 static vec
<cgraph_edge
*> next_edge_clone
;
2896 static vec
<cgraph_edge
*> prev_edge_clone
;
2899 grow_edge_clone_vectors (void)
2901 if (next_edge_clone
.length ()
2902 <= (unsigned) symtab
->edges_max_uid
)
2903 next_edge_clone
.safe_grow_cleared (symtab
->edges_max_uid
+ 1);
2904 if (prev_edge_clone
.length ()
2905 <= (unsigned) symtab
->edges_max_uid
)
2906 prev_edge_clone
.safe_grow_cleared (symtab
->edges_max_uid
+ 1);
2909 /* Edge duplication hook to grow the appropriate linked list in
2913 ipcp_edge_duplication_hook (struct cgraph_edge
*src
, struct cgraph_edge
*dst
,
2916 grow_edge_clone_vectors ();
2918 struct cgraph_edge
*old_next
= next_edge_clone
[src
->uid
];
2920 prev_edge_clone
[old_next
->uid
] = dst
;
2921 prev_edge_clone
[dst
->uid
] = src
;
2923 next_edge_clone
[dst
->uid
] = old_next
;
2924 next_edge_clone
[src
->uid
] = dst
;
2927 /* Hook that is called by cgraph.c when an edge is removed. */
2930 ipcp_edge_removal_hook (struct cgraph_edge
*cs
, void *)
2932 grow_edge_clone_vectors ();
2934 struct cgraph_edge
*prev
= prev_edge_clone
[cs
->uid
];
2935 struct cgraph_edge
*next
= next_edge_clone
[cs
->uid
];
2937 next_edge_clone
[prev
->uid
] = next
;
2939 prev_edge_clone
[next
->uid
] = prev
;
2942 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2943 parameter with the given INDEX. */
2946 get_clone_agg_value (struct cgraph_node
*node
, HOST_WIDE_INT offset
,
2949 struct ipa_agg_replacement_value
*aggval
;
2951 aggval
= ipa_get_agg_replacements_for_node (node
);
2954 if (aggval
->offset
== offset
2955 && aggval
->index
== index
)
2956 return aggval
->value
;
2957 aggval
= aggval
->next
;
2962 /* Return true is NODE is DEST or its clone for all contexts. */
2965 same_node_or_its_all_contexts_clone_p (cgraph_node
*node
, cgraph_node
*dest
)
2970 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
2971 return info
->is_all_contexts_clone
&& info
->ipcp_orig_node
== dest
;
2974 /* Return true if edge CS does bring about the value described by SRC to node
2975 DEST or its clone for all contexts. */
2978 cgraph_edge_brings_value_p (cgraph_edge
*cs
, ipcp_value_source
<tree
> *src
,
2981 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
2982 enum availability availability
;
2983 cgraph_node
*real_dest
= cs
->callee
->function_symbol (&availability
);
2985 if (!same_node_or_its_all_contexts_clone_p (real_dest
, dest
)
2986 || availability
<= AVAIL_INTERPOSABLE
2987 || caller_info
->node_dead
)
2992 if (caller_info
->ipcp_orig_node
)
2995 if (src
->offset
== -1)
2996 t
= caller_info
->known_csts
[src
->index
];
2998 t
= get_clone_agg_value (cs
->caller
, src
->offset
, src
->index
);
2999 return (t
!= NULL_TREE
3000 && values_equal_for_ipcp_p (src
->val
->value
, t
));
3004 struct ipcp_agg_lattice
*aglat
;
3005 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (caller_info
,
3007 if (src
->offset
== -1)
3008 return (plats
->itself
.is_single_const ()
3009 && values_equal_for_ipcp_p (src
->val
->value
,
3010 plats
->itself
.values
->value
));
3013 if (plats
->aggs_bottom
|| plats
->aggs_contain_variable
)
3015 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
3016 if (aglat
->offset
== src
->offset
)
3017 return (aglat
->is_single_const ()
3018 && values_equal_for_ipcp_p (src
->val
->value
,
3019 aglat
->values
->value
));
3025 /* Return true if edge CS does bring about the value described by SRC to node
3026 DEST or its clone for all contexts. */
3029 cgraph_edge_brings_value_p (cgraph_edge
*cs
,
3030 ipcp_value_source
<ipa_polymorphic_call_context
> *src
,
3033 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3034 cgraph_node
*real_dest
= cs
->callee
->function_symbol ();
3036 if (!same_node_or_its_all_contexts_clone_p (real_dest
, dest
)
3037 || caller_info
->node_dead
)
3042 if (caller_info
->ipcp_orig_node
)
3043 return (caller_info
->known_contexts
.length () > (unsigned) src
->index
)
3044 && values_equal_for_ipcp_p (src
->val
->value
,
3045 caller_info
->known_contexts
[src
->index
]);
3047 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (caller_info
,
3049 return plats
->ctxlat
.is_single_const ()
3050 && values_equal_for_ipcp_p (src
->val
->value
,
3051 plats
->ctxlat
.values
->value
);
3054 /* Get the next clone in the linked list of clones of an edge. */
3056 static inline struct cgraph_edge
*
3057 get_next_cgraph_edge_clone (struct cgraph_edge
*cs
)
3059 return next_edge_clone
[cs
->uid
];
3062 /* Given VAL that is intended for DEST, iterate over all its sources and if
3063 they still hold, add their edge frequency and their number into *FREQUENCY
3064 and *CALLER_COUNT respectively. */
3066 template <typename valtype
>
3068 get_info_about_necessary_edges (ipcp_value
<valtype
> *val
, cgraph_node
*dest
,
3070 gcov_type
*count_sum
, int *caller_count
)
3072 ipcp_value_source
<valtype
> *src
;
3073 int freq
= 0, count
= 0;
3077 for (src
= val
->sources
; src
; src
= src
->next
)
3079 struct cgraph_edge
*cs
= src
->cs
;
3082 if (cgraph_edge_brings_value_p (cs
, src
, dest
))
3085 freq
+= cs
->frequency
;
3087 hot
|= cs
->maybe_hot_p ();
3089 cs
= get_next_cgraph_edge_clone (cs
);
3095 *caller_count
= count
;
3099 /* Return a vector of incoming edges that do bring value VAL to node DEST. It
3100 is assumed their number is known and equal to CALLER_COUNT. */
3102 template <typename valtype
>
3103 static vec
<cgraph_edge
*>
3104 gather_edges_for_value (ipcp_value
<valtype
> *val
, cgraph_node
*dest
,
3107 ipcp_value_source
<valtype
> *src
;
3108 vec
<cgraph_edge
*> ret
;
3110 ret
.create (caller_count
);
3111 for (src
= val
->sources
; src
; src
= src
->next
)
3113 struct cgraph_edge
*cs
= src
->cs
;
3116 if (cgraph_edge_brings_value_p (cs
, src
, dest
))
3117 ret
.quick_push (cs
);
3118 cs
= get_next_cgraph_edge_clone (cs
);
3125 /* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3126 Return it or NULL if for some reason it cannot be created. */
3128 static struct ipa_replace_map
*
3129 get_replacement_map (struct ipa_node_params
*info
, tree value
, int parm_num
)
3131 struct ipa_replace_map
*replace_map
;
3134 replace_map
= ggc_alloc
<ipa_replace_map
> ();
3137 fprintf (dump_file
, " replacing ");
3138 ipa_dump_param (dump_file
, info
, parm_num
);
3140 fprintf (dump_file
, " with const ");
3141 print_generic_expr (dump_file
, value
, 0);
3142 fprintf (dump_file
, "\n");
3144 replace_map
->old_tree
= NULL
;
3145 replace_map
->parm_num
= parm_num
;
3146 replace_map
->new_tree
= value
;
3147 replace_map
->replace_p
= true;
3148 replace_map
->ref_p
= false;
3153 /* Dump new profiling counts */
3156 dump_profile_updates (struct cgraph_node
*orig_node
,
3157 struct cgraph_node
*new_node
)
3159 struct cgraph_edge
*cs
;
3161 fprintf (dump_file
, " setting count of the specialized node to "
3162 HOST_WIDE_INT_PRINT_DEC
"\n", (HOST_WIDE_INT
) new_node
->count
);
3163 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3164 fprintf (dump_file
, " edge to %s has count "
3165 HOST_WIDE_INT_PRINT_DEC
"\n",
3166 cs
->callee
->name (), (HOST_WIDE_INT
) cs
->count
);
3168 fprintf (dump_file
, " setting count of the original node to "
3169 HOST_WIDE_INT_PRINT_DEC
"\n", (HOST_WIDE_INT
) orig_node
->count
);
3170 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3171 fprintf (dump_file
, " edge to %s is left with "
3172 HOST_WIDE_INT_PRINT_DEC
"\n",
3173 cs
->callee
->name (), (HOST_WIDE_INT
) cs
->count
);
3176 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3177 their profile information to reflect this. */
3180 update_profiling_info (struct cgraph_node
*orig_node
,
3181 struct cgraph_node
*new_node
)
3183 struct cgraph_edge
*cs
;
3184 struct caller_statistics stats
;
3185 gcov_type new_sum
, orig_sum
;
3186 gcov_type remainder
, orig_node_count
= orig_node
->count
;
3188 if (orig_node_count
== 0)
3191 init_caller_stats (&stats
);
3192 orig_node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
3194 orig_sum
= stats
.count_sum
;
3195 init_caller_stats (&stats
);
3196 new_node
->call_for_symbol_thunks_and_aliases (gather_caller_stats
, &stats
,
3198 new_sum
= stats
.count_sum
;
3200 if (orig_node_count
< orig_sum
+ new_sum
)
3203 fprintf (dump_file
, " Problem: node %s/%i has too low count "
3204 HOST_WIDE_INT_PRINT_DEC
" while the sum of incoming "
3205 "counts is " HOST_WIDE_INT_PRINT_DEC
"\n",
3206 orig_node
->name (), orig_node
->order
,
3207 (HOST_WIDE_INT
) orig_node_count
,
3208 (HOST_WIDE_INT
) (orig_sum
+ new_sum
));
3210 orig_node_count
= (orig_sum
+ new_sum
) * 12 / 10;
3212 fprintf (dump_file
, " proceeding by pretending it was "
3213 HOST_WIDE_INT_PRINT_DEC
"\n",
3214 (HOST_WIDE_INT
) orig_node_count
);
3217 new_node
->count
= new_sum
;
3218 remainder
= orig_node_count
- new_sum
;
3219 orig_node
->count
= remainder
;
3221 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3223 cs
->count
= apply_probability (cs
->count
,
3224 GCOV_COMPUTE_SCALE (new_sum
,
3229 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3230 cs
->count
= apply_probability (cs
->count
,
3231 GCOV_COMPUTE_SCALE (remainder
,
3235 dump_profile_updates (orig_node
, new_node
);
3238 /* Update the respective profile of specialized NEW_NODE and the original
3239 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3240 have been redirected to the specialized version. */
3243 update_specialized_profile (struct cgraph_node
*new_node
,
3244 struct cgraph_node
*orig_node
,
3245 gcov_type redirected_sum
)
3247 struct cgraph_edge
*cs
;
3248 gcov_type new_node_count
, orig_node_count
= orig_node
->count
;
3251 fprintf (dump_file
, " the sum of counts of redirected edges is "
3252 HOST_WIDE_INT_PRINT_DEC
"\n", (HOST_WIDE_INT
) redirected_sum
);
3253 if (orig_node_count
== 0)
3256 gcc_assert (orig_node_count
>= redirected_sum
);
3258 new_node_count
= new_node
->count
;
3259 new_node
->count
+= redirected_sum
;
3260 orig_node
->count
-= redirected_sum
;
3262 for (cs
= new_node
->callees
; cs
; cs
= cs
->next_callee
)
3264 cs
->count
+= apply_probability (cs
->count
,
3265 GCOV_COMPUTE_SCALE (redirected_sum
,
3270 for (cs
= orig_node
->callees
; cs
; cs
= cs
->next_callee
)
3272 gcov_type dec
= apply_probability (cs
->count
,
3273 GCOV_COMPUTE_SCALE (redirected_sum
,
3275 if (dec
< cs
->count
)
3282 dump_profile_updates (orig_node
, new_node
);
3285 /* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3286 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3287 redirect all edges in CALLERS to it. */
3289 static struct cgraph_node
*
3290 create_specialized_node (struct cgraph_node
*node
,
3291 vec
<tree
> known_csts
,
3292 vec
<ipa_polymorphic_call_context
> known_contexts
,
3293 struct ipa_agg_replacement_value
*aggvals
,
3294 vec
<cgraph_edge
*> callers
)
3296 struct ipa_node_params
*new_info
, *info
= IPA_NODE_REF (node
);
3297 vec
<ipa_replace_map
*, va_gc
> *replace_trees
= NULL
;
3298 struct ipa_agg_replacement_value
*av
;
3299 struct cgraph_node
*new_node
;
3300 int i
, count
= ipa_get_param_count (info
);
3301 bitmap args_to_skip
;
3303 gcc_assert (!info
->ipcp_orig_node
);
3305 if (node
->local
.can_change_signature
)
3307 args_to_skip
= BITMAP_GGC_ALLOC ();
3308 for (i
= 0; i
< count
; i
++)
3310 tree t
= known_csts
[i
];
3312 if (t
|| !ipa_is_param_used (info
, i
))
3313 bitmap_set_bit (args_to_skip
, i
);
3318 args_to_skip
= NULL
;
3319 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3320 fprintf (dump_file
, " cannot change function signature\n");
3323 for (i
= 0; i
< count
; i
++)
3325 tree t
= known_csts
[i
];
3328 struct ipa_replace_map
*replace_map
;
3330 gcc_checking_assert (TREE_CODE (t
) != TREE_BINFO
);
3331 replace_map
= get_replacement_map (info
, t
, i
);
3333 vec_safe_push (replace_trees
, replace_map
);
3337 new_node
= node
->create_virtual_clone (callers
, replace_trees
,
3338 args_to_skip
, "constprop");
3339 ipa_set_node_agg_value_chain (new_node
, aggvals
);
3340 for (av
= aggvals
; av
; av
= av
->next
)
3341 new_node
->maybe_create_reference (av
->value
, IPA_REF_ADDR
, NULL
);
3343 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3345 fprintf (dump_file
, " the new node is %s/%i.\n",
3346 new_node
->name (), new_node
->order
);
3347 if (known_contexts
.exists ())
3349 for (i
= 0; i
< count
; i
++)
3350 if (!known_contexts
[i
].useless_p ())
3352 fprintf (dump_file
, " known ctx %i is ", i
);
3353 known_contexts
[i
].dump (dump_file
);
3357 ipa_dump_agg_replacement_values (dump_file
, aggvals
);
3359 ipa_check_create_node_params ();
3360 update_profiling_info (node
, new_node
);
3361 new_info
= IPA_NODE_REF (new_node
);
3362 new_info
->ipcp_orig_node
= node
;
3363 new_info
->known_csts
= known_csts
;
3364 new_info
->known_contexts
= known_contexts
;
3366 ipcp_discover_new_direct_edges (new_node
, known_csts
, known_contexts
, aggvals
);
3372 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
3373 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3376 find_more_scalar_values_for_callers_subset (struct cgraph_node
*node
,
3377 vec
<tree
> known_csts
,
3378 vec
<cgraph_edge
*> callers
)
3380 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
3381 int i
, count
= ipa_get_param_count (info
);
3383 for (i
= 0; i
< count
; i
++)
3385 struct cgraph_edge
*cs
;
3386 tree newval
= NULL_TREE
;
3390 if (ipa_get_scalar_lat (info
, i
)->bottom
|| known_csts
[i
])
3393 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3395 struct ipa_jump_func
*jump_func
;
3398 if (i
>= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
)))
3403 jump_func
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
), i
);
3404 t
= ipa_value_from_jfunc (IPA_NODE_REF (cs
->caller
), jump_func
);
3407 && !values_equal_for_ipcp_p (t
, newval
))
3408 || (!first
&& !newval
))
3420 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3422 fprintf (dump_file
, " adding an extra known scalar value ");
3423 print_ipcp_constant_value (dump_file
, newval
);
3424 fprintf (dump_file
, " for ");
3425 ipa_dump_param (dump_file
, info
, i
);
3426 fprintf (dump_file
, "\n");
3429 known_csts
[i
] = newval
;
3434 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3435 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3439 find_more_contexts_for_caller_subset (cgraph_node
*node
,
3440 vec
<ipa_polymorphic_call_context
>
3442 vec
<cgraph_edge
*> callers
)
3444 ipa_node_params
*info
= IPA_NODE_REF (node
);
3445 int i
, count
= ipa_get_param_count (info
);
3447 for (i
= 0; i
< count
; i
++)
3451 if (ipa_get_poly_ctx_lat (info
, i
)->bottom
3452 || (known_contexts
->exists ()
3453 && !(*known_contexts
)[i
].useless_p ()))
3456 ipa_polymorphic_call_context newval
;
3460 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3462 if (i
>= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
)))
3464 ipa_jump_func
*jfunc
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
),
3466 ipa_polymorphic_call_context ctx
;
3467 ctx
= ipa_context_from_jfunc (IPA_NODE_REF (cs
->caller
), cs
, i
,
3475 newval
.meet_with (ctx
);
3476 if (newval
.useless_p ())
3480 if (!newval
.useless_p ())
3482 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3484 fprintf (dump_file
, " adding an extra known polymorphic "
3486 print_ipcp_constant_value (dump_file
, newval
);
3487 fprintf (dump_file
, " for ");
3488 ipa_dump_param (dump_file
, info
, i
);
3489 fprintf (dump_file
, "\n");
3492 if (!known_contexts
->exists ())
3493 known_contexts
->safe_grow_cleared (ipa_get_param_count (info
));
3494 (*known_contexts
)[i
] = newval
;
3500 /* Go through PLATS and create a vector of values consisting of values and
3501 offsets (minus OFFSET) of lattices that contain only a single value. */
3503 static vec
<ipa_agg_jf_item
>
3504 copy_plats_to_inter (struct ipcp_param_lattices
*plats
, HOST_WIDE_INT offset
)
3506 vec
<ipa_agg_jf_item
> res
= vNULL
;
3508 if (!plats
->aggs
|| plats
->aggs_contain_variable
|| plats
->aggs_bottom
)
3511 for (struct ipcp_agg_lattice
*aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
3512 if (aglat
->is_single_const ())
3514 struct ipa_agg_jf_item ti
;
3515 ti
.offset
= aglat
->offset
- offset
;
3516 ti
.value
= aglat
->values
->value
;
3522 /* Intersect all values in INTER with single value lattices in PLATS (while
3523 subtracting OFFSET). */
3526 intersect_with_plats (struct ipcp_param_lattices
*plats
,
3527 vec
<ipa_agg_jf_item
> *inter
,
3528 HOST_WIDE_INT offset
)
3530 struct ipcp_agg_lattice
*aglat
;
3531 struct ipa_agg_jf_item
*item
;
3534 if (!plats
->aggs
|| plats
->aggs_contain_variable
|| plats
->aggs_bottom
)
3540 aglat
= plats
->aggs
;
3541 FOR_EACH_VEC_ELT (*inter
, k
, item
)
3548 if (aglat
->offset
- offset
> item
->offset
)
3550 if (aglat
->offset
- offset
== item
->offset
)
3552 gcc_checking_assert (item
->value
);
3553 if (values_equal_for_ipcp_p (item
->value
, aglat
->values
->value
))
3557 aglat
= aglat
->next
;
3560 item
->value
= NULL_TREE
;
3564 /* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3565 vector result while subtracting OFFSET from the individual value offsets. */
3567 static vec
<ipa_agg_jf_item
>
3568 agg_replacements_to_vector (struct cgraph_node
*node
, int index
,
3569 HOST_WIDE_INT offset
)
3571 struct ipa_agg_replacement_value
*av
;
3572 vec
<ipa_agg_jf_item
> res
= vNULL
;
3574 for (av
= ipa_get_agg_replacements_for_node (node
); av
; av
= av
->next
)
3575 if (av
->index
== index
3576 && (av
->offset
- offset
) >= 0)
3578 struct ipa_agg_jf_item item
;
3579 gcc_checking_assert (av
->value
);
3580 item
.offset
= av
->offset
- offset
;
3581 item
.value
= av
->value
;
3582 res
.safe_push (item
);
3588 /* Intersect all values in INTER with those that we have already scheduled to
3589 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3590 (while subtracting OFFSET). */
3593 intersect_with_agg_replacements (struct cgraph_node
*node
, int index
,
3594 vec
<ipa_agg_jf_item
> *inter
,
3595 HOST_WIDE_INT offset
)
3597 struct ipa_agg_replacement_value
*srcvals
;
3598 struct ipa_agg_jf_item
*item
;
3601 srcvals
= ipa_get_agg_replacements_for_node (node
);
3608 FOR_EACH_VEC_ELT (*inter
, i
, item
)
3610 struct ipa_agg_replacement_value
*av
;
3614 for (av
= srcvals
; av
; av
= av
->next
)
3616 gcc_checking_assert (av
->value
);
3617 if (av
->index
== index
3618 && av
->offset
- offset
== item
->offset
)
3620 if (values_equal_for_ipcp_p (item
->value
, av
->value
))
3626 item
->value
= NULL_TREE
;
3630 /* Intersect values in INTER with aggregate values that come along edge CS to
3631 parameter number INDEX and return it. If INTER does not actually exist yet,
3632 copy all incoming values to it. If we determine we ended up with no values
3633 whatsoever, return a released vector. */
3635 static vec
<ipa_agg_jf_item
>
3636 intersect_aggregates_with_edge (struct cgraph_edge
*cs
, int index
,
3637 vec
<ipa_agg_jf_item
> inter
)
3639 struct ipa_jump_func
*jfunc
;
3640 jfunc
= ipa_get_ith_jump_func (IPA_EDGE_REF (cs
), index
);
3641 if (jfunc
->type
== IPA_JF_PASS_THROUGH
3642 && ipa_get_jf_pass_through_operation (jfunc
) == NOP_EXPR
)
3644 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3645 int src_idx
= ipa_get_jf_pass_through_formal_id (jfunc
);
3647 if (caller_info
->ipcp_orig_node
)
3649 struct cgraph_node
*orig_node
= caller_info
->ipcp_orig_node
;
3650 struct ipcp_param_lattices
*orig_plats
;
3651 orig_plats
= ipa_get_parm_lattices (IPA_NODE_REF (orig_node
),
3653 if (agg_pass_through_permissible_p (orig_plats
, jfunc
))
3655 if (!inter
.exists ())
3656 inter
= agg_replacements_to_vector (cs
->caller
, src_idx
, 0);
3658 intersect_with_agg_replacements (cs
->caller
, src_idx
,
3669 struct ipcp_param_lattices
*src_plats
;
3670 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);
3671 if (agg_pass_through_permissible_p (src_plats
, jfunc
))
3673 /* Currently we do not produce clobber aggregate jump
3674 functions, adjust when we do. */
3675 gcc_checking_assert (!jfunc
->agg
.items
);
3676 if (!inter
.exists ())
3677 inter
= copy_plats_to_inter (src_plats
, 0);
3679 intersect_with_plats (src_plats
, &inter
, 0);
3688 else if (jfunc
->type
== IPA_JF_ANCESTOR
3689 && ipa_get_jf_ancestor_agg_preserved (jfunc
))
3691 struct ipa_node_params
*caller_info
= IPA_NODE_REF (cs
->caller
);
3692 int src_idx
= ipa_get_jf_ancestor_formal_id (jfunc
);
3693 struct ipcp_param_lattices
*src_plats
;
3694 HOST_WIDE_INT delta
= ipa_get_jf_ancestor_offset (jfunc
);
3696 if (caller_info
->ipcp_orig_node
)
3698 if (!inter
.exists ())
3699 inter
= agg_replacements_to_vector (cs
->caller
, src_idx
, delta
);
3701 intersect_with_agg_replacements (cs
->caller
, src_idx
, &inter
,
3706 src_plats
= ipa_get_parm_lattices (caller_info
, src_idx
);;
3707 /* Currently we do not produce clobber aggregate jump
3708 functions, adjust when we do. */
3709 gcc_checking_assert (!src_plats
->aggs
|| !jfunc
->agg
.items
);
3710 if (!inter
.exists ())
3711 inter
= copy_plats_to_inter (src_plats
, delta
);
3713 intersect_with_plats (src_plats
, &inter
, delta
);
3716 else if (jfunc
->agg
.items
)
3718 struct ipa_agg_jf_item
*item
;
3721 if (!inter
.exists ())
3722 for (unsigned i
= 0; i
< jfunc
->agg
.items
->length (); i
++)
3723 inter
.safe_push ((*jfunc
->agg
.items
)[i
]);
3725 FOR_EACH_VEC_ELT (inter
, k
, item
)
3728 bool found
= false;;
3733 while ((unsigned) l
< jfunc
->agg
.items
->length ())
3735 struct ipa_agg_jf_item
*ti
;
3736 ti
= &(*jfunc
->agg
.items
)[l
];
3737 if (ti
->offset
> item
->offset
)
3739 if (ti
->offset
== item
->offset
)
3741 gcc_checking_assert (ti
->value
);
3742 if (values_equal_for_ipcp_p (item
->value
,
3756 return vec
<ipa_agg_jf_item
>();
3761 /* Look at edges in CALLERS and collect all known aggregate values that arrive
3762 from all of them. */
3764 static struct ipa_agg_replacement_value
*
3765 find_aggregate_values_for_callers_subset (struct cgraph_node
*node
,
3766 vec
<cgraph_edge
*> callers
)
3768 struct ipa_node_params
*dest_info
= IPA_NODE_REF (node
);
3769 struct ipa_agg_replacement_value
*res
;
3770 struct ipa_agg_replacement_value
**tail
= &res
;
3771 struct cgraph_edge
*cs
;
3772 int i
, j
, count
= ipa_get_param_count (dest_info
);
3774 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3776 int c
= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
));
3781 for (i
= 0; i
< count
; i
++)
3783 struct cgraph_edge
*cs
;
3784 vec
<ipa_agg_jf_item
> inter
= vNULL
;
3785 struct ipa_agg_jf_item
*item
;
3786 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (dest_info
, i
);
3789 /* Among other things, the following check should deal with all by_ref
3791 if (plats
->aggs_bottom
)
3794 FOR_EACH_VEC_ELT (callers
, j
, cs
)
3796 inter
= intersect_aggregates_with_edge (cs
, i
, inter
);
3798 if (!inter
.exists ())
3802 FOR_EACH_VEC_ELT (inter
, j
, item
)
3804 struct ipa_agg_replacement_value
*v
;
3809 v
= ggc_alloc
<ipa_agg_replacement_value
> ();
3811 v
->offset
= item
->offset
;
3812 v
->value
= item
->value
;
3813 v
->by_ref
= plats
->aggs_by_ref
;
3819 if (inter
.exists ())
3826 /* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3828 static struct ipa_agg_replacement_value
*
3829 known_aggs_to_agg_replacement_list (vec
<ipa_agg_jump_function
> known_aggs
)
3831 struct ipa_agg_replacement_value
*res
;
3832 struct ipa_agg_replacement_value
**tail
= &res
;
3833 struct ipa_agg_jump_function
*aggjf
;
3834 struct ipa_agg_jf_item
*item
;
3837 FOR_EACH_VEC_ELT (known_aggs
, i
, aggjf
)
3838 FOR_EACH_VEC_SAFE_ELT (aggjf
->items
, j
, item
)
3840 struct ipa_agg_replacement_value
*v
;
3841 v
= ggc_alloc
<ipa_agg_replacement_value
> ();
3843 v
->offset
= item
->offset
;
3844 v
->value
= item
->value
;
3845 v
->by_ref
= aggjf
->by_ref
;
3853 /* Determine whether CS also brings all scalar values that the NODE is
3857 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge
*cs
,
3858 struct cgraph_node
*node
)
3860 struct ipa_node_params
*dest_info
= IPA_NODE_REF (node
);
3861 int count
= ipa_get_param_count (dest_info
);
3862 struct ipa_node_params
*caller_info
;
3863 struct ipa_edge_args
*args
;
3866 caller_info
= IPA_NODE_REF (cs
->caller
);
3867 args
= IPA_EDGE_REF (cs
);
3868 for (i
= 0; i
< count
; i
++)
3870 struct ipa_jump_func
*jump_func
;
3873 val
= dest_info
->known_csts
[i
];
3877 if (i
>= ipa_get_cs_argument_count (args
))
3879 jump_func
= ipa_get_ith_jump_func (args
, i
);
3880 t
= ipa_value_from_jfunc (caller_info
, jump_func
);
3881 if (!t
|| !values_equal_for_ipcp_p (val
, t
))
3887 /* Determine whether CS also brings all aggregate values that NODE is
3890 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge
*cs
,
3891 struct cgraph_node
*node
)
3893 struct ipa_node_params
*orig_caller_info
= IPA_NODE_REF (cs
->caller
);
3894 struct ipa_node_params
*orig_node_info
;
3895 struct ipa_agg_replacement_value
*aggval
;
3898 aggval
= ipa_get_agg_replacements_for_node (node
);
3902 count
= ipa_get_param_count (IPA_NODE_REF (node
));
3903 ec
= ipa_get_cs_argument_count (IPA_EDGE_REF (cs
));
3905 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
3906 if (aggval
->index
>= ec
)
3909 orig_node_info
= IPA_NODE_REF (IPA_NODE_REF (node
)->ipcp_orig_node
);
3910 if (orig_caller_info
->ipcp_orig_node
)
3911 orig_caller_info
= IPA_NODE_REF (orig_caller_info
->ipcp_orig_node
);
3913 for (i
= 0; i
< count
; i
++)
3915 static vec
<ipa_agg_jf_item
> values
= vec
<ipa_agg_jf_item
>();
3916 struct ipcp_param_lattices
*plats
;
3917 bool interesting
= false;
3918 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
3919 if (aggval
->index
== i
)
3927 plats
= ipa_get_parm_lattices (orig_node_info
, aggval
->index
);
3928 if (plats
->aggs_bottom
)
3931 values
= intersect_aggregates_with_edge (cs
, i
, values
);
3932 if (!values
.exists ())
3935 for (struct ipa_agg_replacement_value
*av
= aggval
; av
; av
= av
->next
)
3936 if (aggval
->index
== i
)
3938 struct ipa_agg_jf_item
*item
;
3941 FOR_EACH_VEC_ELT (values
, j
, item
)
3943 && item
->offset
== av
->offset
3944 && values_equal_for_ipcp_p (item
->value
, av
->value
))
3959 /* Given an original NODE and a VAL for which we have already created a
3960 specialized clone, look whether there are incoming edges that still lead
3961 into the old node but now also bring the requested value and also conform to
3962 all other criteria such that they can be redirected the special node.
3963 This function can therefore redirect the final edge in a SCC. */
3965 template <typename valtype
>
3967 perhaps_add_new_callers (cgraph_node
*node
, ipcp_value
<valtype
> *val
)
3969 ipcp_value_source
<valtype
> *src
;
3970 gcov_type redirected_sum
= 0;
3972 for (src
= val
->sources
; src
; src
= src
->next
)
3974 struct cgraph_edge
*cs
= src
->cs
;
3977 if (cgraph_edge_brings_value_p (cs
, src
, node
)
3978 && cgraph_edge_brings_all_scalars_for_node (cs
, val
->spec_node
)
3979 && cgraph_edge_brings_all_agg_vals_for_node (cs
, val
->spec_node
))
3982 fprintf (dump_file
, " - adding an extra caller %s/%i"
3984 xstrdup_for_dump (cs
->caller
->name ()),
3986 xstrdup_for_dump (val
->spec_node
->name ()),
3987 val
->spec_node
->order
);
3989 cs
->redirect_callee_duplicating_thunks (val
->spec_node
);
3990 val
->spec_node
->expand_all_artificial_thunks ();
3991 redirected_sum
+= cs
->count
;
3993 cs
= get_next_cgraph_edge_clone (cs
);
3998 update_specialized_profile (val
->spec_node
, node
, redirected_sum
);
4001 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */
4004 known_contexts_useful_p (vec
<ipa_polymorphic_call_context
> known_contexts
)
4006 ipa_polymorphic_call_context
*ctx
;
4009 FOR_EACH_VEC_ELT (known_contexts
, i
, ctx
)
4010 if (!ctx
->useless_p ())
4015 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4017 static vec
<ipa_polymorphic_call_context
>
4018 copy_useful_known_contexts (vec
<ipa_polymorphic_call_context
> known_contexts
)
4020 if (known_contexts_useful_p (known_contexts
))
4021 return known_contexts
.copy ();
4026 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4027 non-empty, replace KNOWN_CONTEXTS with its copy too. */
4030 modify_known_vectors_with_val (vec
<tree
> *known_csts
,
4031 vec
<ipa_polymorphic_call_context
> *known_contexts
,
4032 ipcp_value
<tree
> *val
,
4035 *known_csts
= known_csts
->copy ();
4036 *known_contexts
= copy_useful_known_contexts (*known_contexts
);
4037 (*known_csts
)[index
] = val
->value
;
4040 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4041 copy according to VAL and INDEX. */
4044 modify_known_vectors_with_val (vec
<tree
> *known_csts
,
4045 vec
<ipa_polymorphic_call_context
> *known_contexts
,
4046 ipcp_value
<ipa_polymorphic_call_context
> *val
,
4049 *known_csts
= known_csts
->copy ();
4050 *known_contexts
= known_contexts
->copy ();
4051 (*known_contexts
)[index
] = val
->value
;
4054 /* Return true if OFFSET indicates this was not an aggregate value or there is
4055 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4059 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value
*aggvals
,
4060 int index
, HOST_WIDE_INT offset
, tree value
)
4067 if (aggvals
->index
== index
4068 && aggvals
->offset
== offset
4069 && values_equal_for_ipcp_p (aggvals
->value
, value
))
4071 aggvals
= aggvals
->next
;
4076 /* Return true if offset is minus one because source of a polymorphic contect
4077 cannot be an aggregate value. */
4080 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value
*,
4081 int , HOST_WIDE_INT offset
,
4082 ipa_polymorphic_call_context
)
4084 return offset
== -1;
4087 /* Decide wheter to create a special version of NODE for value VAL of parameter
4088 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4089 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
4090 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
4092 template <typename valtype
>
4094 decide_about_value (struct cgraph_node
*node
, int index
, HOST_WIDE_INT offset
,
4095 ipcp_value
<valtype
> *val
, vec
<tree
> known_csts
,
4096 vec
<ipa_polymorphic_call_context
> known_contexts
)
4098 struct ipa_agg_replacement_value
*aggvals
;
4099 int freq_sum
, caller_count
;
4100 gcov_type count_sum
;
4101 vec
<cgraph_edge
*> callers
;
4105 perhaps_add_new_callers (node
, val
);
4108 else if (val
->local_size_cost
+ overall_size
> max_new_size
)
4110 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4111 fprintf (dump_file
, " Ignoring candidate value because "
4112 "max_new_size would be reached with %li.\n",
4113 val
->local_size_cost
+ overall_size
);
4116 else if (!get_info_about_necessary_edges (val
, node
, &freq_sum
, &count_sum
,
4120 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4122 fprintf (dump_file
, " - considering value ");
4123 print_ipcp_constant_value (dump_file
, val
->value
);
4124 fprintf (dump_file
, " for ");
4125 ipa_dump_param (dump_file
, IPA_NODE_REF (node
), index
);
4127 fprintf (dump_file
, ", offset: " HOST_WIDE_INT_PRINT_DEC
, offset
);
4128 fprintf (dump_file
, " (caller_count: %i)\n", caller_count
);
4131 if (!good_cloning_opportunity_p (node
, val
->local_time_benefit
,
4132 freq_sum
, count_sum
,
4133 val
->local_size_cost
)
4134 && !good_cloning_opportunity_p (node
,
4135 val
->local_time_benefit
4136 + val
->prop_time_benefit
,
4137 freq_sum
, count_sum
,
4138 val
->local_size_cost
4139 + val
->prop_size_cost
))
4143 fprintf (dump_file
, " Creating a specialized node of %s/%i.\n",
4144 node
->name (), node
->order
);
4146 callers
= gather_edges_for_value (val
, node
, caller_count
);
4148 modify_known_vectors_with_val (&known_csts
, &known_contexts
, val
, index
);
4151 known_csts
= known_csts
.copy ();
4152 known_contexts
= copy_useful_known_contexts (known_contexts
);
4154 find_more_scalar_values_for_callers_subset (node
, known_csts
, callers
);
4155 find_more_contexts_for_caller_subset (node
, &known_contexts
, callers
);
4156 aggvals
= find_aggregate_values_for_callers_subset (node
, callers
);
4157 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals
, index
,
4158 offset
, val
->value
));
4159 val
->spec_node
= create_specialized_node (node
, known_csts
, known_contexts
,
4161 overall_size
+= val
->local_size_cost
;
4163 /* TODO: If for some lattice there is only one other known value
4164 left, make a special node for it too. */
4169 /* Decide whether and what specialized clones of NODE should be created. */
4172 decide_whether_version_node (struct cgraph_node
*node
)
4174 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
4175 int i
, count
= ipa_get_param_count (info
);
4176 vec
<tree
> known_csts
;
4177 vec
<ipa_polymorphic_call_context
> known_contexts
;
4178 vec
<ipa_agg_jump_function
> known_aggs
= vNULL
;
4184 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4185 fprintf (dump_file
, "\nEvaluating opportunities for %s/%i.\n",
4186 node
->name (), node
->order
);
4188 gather_context_independent_values (info
, &known_csts
, &known_contexts
,
4189 info
->do_clone_for_all_contexts
? &known_aggs
4192 for (i
= 0; i
< count
;i
++)
4194 struct ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
4195 ipcp_lattice
<tree
> *lat
= &plats
->itself
;
4196 ipcp_lattice
<ipa_polymorphic_call_context
> *ctxlat
= &plats
->ctxlat
;
4201 ipcp_value
<tree
> *val
;
4202 for (val
= lat
->values
; val
; val
= val
->next
)
4203 ret
|= decide_about_value (node
, i
, -1, val
, known_csts
,
4207 if (!plats
->aggs_bottom
)
4209 struct ipcp_agg_lattice
*aglat
;
4210 ipcp_value
<tree
> *val
;
4211 for (aglat
= plats
->aggs
; aglat
; aglat
= aglat
->next
)
4212 if (!aglat
->bottom
&& aglat
->values
4213 /* If the following is false, the one value is in
4215 && (plats
->aggs_contain_variable
4216 || !aglat
->is_single_const ()))
4217 for (val
= aglat
->values
; val
; val
= val
->next
)
4218 ret
|= decide_about_value (node
, i
, aglat
->offset
, val
,
4219 known_csts
, known_contexts
);
4223 && known_contexts
[i
].useless_p ())
4225 ipcp_value
<ipa_polymorphic_call_context
> *val
;
4226 for (val
= ctxlat
->values
; val
; val
= val
->next
)
4227 ret
|= decide_about_value (node
, i
, -1, val
, known_csts
,
4231 info
= IPA_NODE_REF (node
);
4234 if (info
->do_clone_for_all_contexts
)
4236 struct cgraph_node
*clone
;
4237 vec
<cgraph_edge
*> callers
;
4240 fprintf (dump_file
, " - Creating a specialized node of %s/%i "
4241 "for all known contexts.\n", node
->name (),
4244 callers
= node
->collect_callers ();
4246 if (!known_contexts_useful_p (known_contexts
))
4248 known_contexts
.release ();
4249 known_contexts
= vNULL
;
4251 clone
= create_specialized_node (node
, known_csts
, known_contexts
,
4252 known_aggs_to_agg_replacement_list (known_aggs
),
4254 info
= IPA_NODE_REF (node
);
4255 info
->do_clone_for_all_contexts
= false;
4256 IPA_NODE_REF (clone
)->is_all_contexts_clone
= true;
4257 for (i
= 0; i
< count
; i
++)
4258 vec_free (known_aggs
[i
].items
);
4259 known_aggs
.release ();
4264 known_csts
.release ();
4265 known_contexts
.release ();
4271 /* Transitively mark all callees of NODE within the same SCC as not dead. */
4274 spread_undeadness (struct cgraph_node
*node
)
4276 struct cgraph_edge
*cs
;
4278 for (cs
= node
->callees
; cs
; cs
= cs
->next_callee
)
4279 if (ipa_edge_within_scc (cs
))
4281 struct cgraph_node
*callee
;
4282 struct ipa_node_params
*info
;
4284 callee
= cs
->callee
->function_symbol (NULL
);
4285 info
= IPA_NODE_REF (callee
);
4287 if (info
->node_dead
)
4289 info
->node_dead
= 0;
4290 spread_undeadness (callee
);
4295 /* Return true if NODE has a caller from outside of its SCC that is not
4296 dead. Worker callback for cgraph_for_node_and_aliases. */
4299 has_undead_caller_from_outside_scc_p (struct cgraph_node
*node
,
4300 void *data ATTRIBUTE_UNUSED
)
4302 struct cgraph_edge
*cs
;
4304 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
4305 if (cs
->caller
->thunk
.thunk_p
4306 && cs
->caller
->call_for_symbol_thunks_and_aliases
4307 (has_undead_caller_from_outside_scc_p
, NULL
, true))
4309 else if (!ipa_edge_within_scc (cs
)
4310 && !IPA_NODE_REF (cs
->caller
)->node_dead
)
4316 /* Identify nodes within the same SCC as NODE which are no longer needed
4317 because of new clones and will be removed as unreachable. */
4320 identify_dead_nodes (struct cgraph_node
*node
)
4322 struct cgraph_node
*v
;
4323 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4324 if (v
->will_be_removed_from_program_if_no_direct_calls_p ()
4325 && !v
->call_for_symbol_thunks_and_aliases
4326 (has_undead_caller_from_outside_scc_p
, NULL
, true))
4327 IPA_NODE_REF (v
)->node_dead
= 1;
4329 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4330 if (!IPA_NODE_REF (v
)->node_dead
)
4331 spread_undeadness (v
);
4333 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4335 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4336 if (IPA_NODE_REF (v
)->node_dead
)
4337 fprintf (dump_file
, " Marking node as dead: %s/%i.\n",
4338 v
->name (), v
->order
);
4342 /* The decision stage. Iterate over the topological order of call graph nodes
4343 TOPO and make specialized clones if deemed beneficial. */
4346 ipcp_decision_stage (struct ipa_topo_info
*topo
)
4351 fprintf (dump_file
, "\nIPA decision stage:\n\n");
4353 for (i
= topo
->nnodes
- 1; i
>= 0; i
--)
4355 struct cgraph_node
*node
= topo
->order
[i
];
4356 bool change
= false, iterate
= true;
4360 struct cgraph_node
*v
;
4362 for (v
= node
; v
; v
= ((struct ipa_dfs_info
*) v
->aux
)->next_cycle
)
4363 if (v
->has_gimple_body_p ()
4364 && ipcp_versionable_function_p (v
))
4365 iterate
|= decide_whether_version_node (v
);
4370 identify_dead_nodes (node
);
4374 /* Look up all alignment information that we have discovered and copy it over
4375 to the transformation summary. */
4378 ipcp_store_alignment_results (void)
4382 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
4384 ipa_node_params
*info
= IPA_NODE_REF (node
);
4385 bool dumped_sth
= false;
4386 bool found_useful_result
= false;
4388 if (!opt_for_fn (node
->decl
, flag_ipa_cp_alignment
))
4391 fprintf (dump_file
, "Not considering %s for alignment discovery "
4392 "and propagate; -fipa-cp-alignment: disabled.\n",
4397 if (info
->ipcp_orig_node
)
4398 info
= IPA_NODE_REF (info
->ipcp_orig_node
);
4400 unsigned count
= ipa_get_param_count (info
);
4401 for (unsigned i
= 0; i
< count
; i
++)
4403 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
4404 if (plats
->alignment
.known
4405 && plats
->alignment
.align
> 0)
4407 found_useful_result
= true;
4411 if (!found_useful_result
)
4414 ipcp_grow_transformations_if_necessary ();
4415 ipcp_transformation_summary
*ts
= ipcp_get_transformation_summary (node
);
4416 vec_safe_reserve_exact (ts
->alignments
, count
);
4418 for (unsigned i
= 0; i
< count
; i
++)
4420 ipcp_param_lattices
*plats
= ipa_get_parm_lattices (info
, i
);
4422 if (plats
->alignment
.align
== 0)
4423 plats
->alignment
.known
= false;
4425 ts
->alignments
->quick_push (plats
->alignment
);
4426 if (!dump_file
|| !plats
->alignment
.known
)
4430 fprintf (dump_file
, "Propagated alignment info for function %s/%i:\n",
4431 node
->name (), node
->order
);
4434 fprintf (dump_file
, " param %i: align: %u, misalign: %u\n",
4435 i
, plats
->alignment
.align
, plats
->alignment
.misalign
);
4440 /* The IPCP driver. */
4445 struct cgraph_2edge_hook_list
*edge_duplication_hook_holder
;
4446 struct cgraph_edge_hook_list
*edge_removal_hook_holder
;
4447 struct ipa_topo_info topo
;
4449 ipa_check_create_node_params ();
4450 ipa_check_create_edge_args ();
4451 grow_edge_clone_vectors ();
4452 edge_duplication_hook_holder
=
4453 symtab
->add_edge_duplication_hook (&ipcp_edge_duplication_hook
, NULL
);
4454 edge_removal_hook_holder
=
4455 symtab
->add_edge_removal_hook (&ipcp_edge_removal_hook
, NULL
);
4459 fprintf (dump_file
, "\nIPA structures before propagation:\n");
4460 if (dump_flags
& TDF_DETAILS
)
4461 ipa_print_all_params (dump_file
);
4462 ipa_print_all_jump_functions (dump_file
);
4465 /* Topological sort. */
4466 build_toporder_info (&topo
);
4467 /* Do the interprocedural propagation. */
4468 ipcp_propagate_stage (&topo
);
4469 /* Decide what constant propagation and cloning should be performed. */
4470 ipcp_decision_stage (&topo
);
4471 /* Store results of alignment propagation. */
4472 ipcp_store_alignment_results ();
4474 /* Free all IPCP structures. */
4475 free_toporder_info (&topo
);
4476 next_edge_clone
.release ();
4477 prev_edge_clone
.release ();
4478 symtab
->remove_edge_removal_hook (edge_removal_hook_holder
);
4479 symtab
->remove_edge_duplication_hook (edge_duplication_hook_holder
);
4480 ipa_free_all_structures_after_ipa_cp ();
4482 fprintf (dump_file
, "\nIPA constant propagation end\n");
4486 /* Initialization and computation of IPCP data structures. This is the initial
4487 intraprocedural analysis of functions, which gathers information to be
4488 propagated later on. */
4491 ipcp_generate_summary (void)
4493 struct cgraph_node
*node
;
4496 fprintf (dump_file
, "\nIPA constant propagation start:\n");
4497 ipa_register_cgraph_hooks ();
4499 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
4501 node
->local
.versionable
4502 = tree_versionable_function_p (node
->decl
);
4503 ipa_analyze_node (node
);
4507 /* Write ipcp summary for nodes in SET. */
4510 ipcp_write_summary (void)
4512 ipa_prop_write_jump_functions ();
4515 /* Read ipcp summary. */
4518 ipcp_read_summary (void)
4520 ipa_prop_read_jump_functions ();
4525 const pass_data pass_data_ipa_cp
=
4527 IPA_PASS
, /* type */
4529 OPTGROUP_NONE
, /* optinfo_flags */
4530 TV_IPA_CONSTANT_PROP
, /* tv_id */
4531 0, /* properties_required */
4532 0, /* properties_provided */
4533 0, /* properties_destroyed */
4534 0, /* todo_flags_start */
4535 ( TODO_dump_symtab
| TODO_remove_functions
), /* todo_flags_finish */
4538 class pass_ipa_cp
: public ipa_opt_pass_d
4541 pass_ipa_cp (gcc::context
*ctxt
)
4542 : ipa_opt_pass_d (pass_data_ipa_cp
, ctxt
,
4543 ipcp_generate_summary
, /* generate_summary */
4544 ipcp_write_summary
, /* write_summary */
4545 ipcp_read_summary
, /* read_summary */
4546 ipcp_write_transformation_summaries
, /*
4547 write_optimization_summary */
4548 ipcp_read_transformation_summaries
, /*
4549 read_optimization_summary */
4550 NULL
, /* stmt_fixup */
4551 0, /* function_transform_todo_flags_start */
4552 ipcp_transform_function
, /* function_transform */
4553 NULL
) /* variable_transform */
4556 /* opt_pass methods: */
4557 virtual bool gate (function
*)
4559 /* FIXME: We should remove the optimize check after we ensure we never run
4560 IPA passes when not optimizing. */
4561 return (flag_ipa_cp
&& optimize
) || in_lto_p
;
4564 virtual unsigned int execute (function
*) { return ipcp_driver (); }
4566 }; // class pass_ipa_cp
4571 make_pass_ipa_cp (gcc::context
*ctxt
)
4573 return new pass_ipa_cp (ctxt
);
4576 /* Reset all state within ipa-cp.c so that we can rerun the compiler
4577 within the same process. For use by toplev::finalize. */
4580 ipa_cp_c_finalize (void)