]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-cp.c
Daily bump.
[thirdparty/gcc.git] / gcc / ipa-cp.c
CommitLineData
518dc859 1/* Interprocedural constant propagation
5624e564 2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
310bc633
MJ
3
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
b8698a0f 6
518dc859 7This file is part of GCC.
b8698a0f 8
518dc859
RL
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
9dcd6f09 11Software Foundation; either version 3, or (at your option) any later
518dc859 12version.
b8698a0f 13
518dc859
RL
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
b8698a0f 18
518dc859 19You should have received a copy of the GNU General Public License
9dcd6f09
NC
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
518dc859 22
310bc633 23/* Interprocedural constant propagation (IPA-CP).
b8698a0f 24
310bc633 25 The goal of this transformation is to
c43f07af 26
310bc633
MJ
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
c43f07af 30
310bc633
MJ
31 2) partial specialization - create specialized versions of functions
32 transformed in this way if some parameters are known constants only in
33 certain contexts but the estimated tradeoff between speedup and cost size
34 is deemed good.
b8698a0f 35
310bc633
MJ
36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
b8698a0f 38
310bc633
MJ
39 The algorithm basically consists of three stages. In the first, functions
40 are analyzed one at a time and jump functions are constructed for all known
41 call-sites. In the second phase, the pass propagates information from the
42 jump functions across the call to reveal what values are available at what
43 call sites, performs estimations of effects of known values on functions and
44 their callees, and finally decides what specialized extra versions should be
45 created. In the third, the special versions materialize and appropriate
46 calls are redirected.
c43f07af 47
310bc633
MJ
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.
b8698a0f 52
518dc859
RL
53
54 First stage - intraprocedural analysis
55 =======================================
310bc633 56
c43f07af 57 This phase computes jump_function and modification flags.
b8698a0f 58
310bc633
MJ
59 A jump function for a call-site represents the values passed as an actual
60 arguments of a given call-site. In principle, there are three types of
61 values:
62
63 Pass through - the caller's formal parameter is passed as an actual
64 argument, plus an operation on it can be performed.
ea2c620c 65 Constant - a constant is passed as an actual argument.
518dc859 66 Unknown - neither of the above.
b8698a0f 67
310bc633
MJ
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.
b8698a0f 70
310bc633 71 ipcp_generate_summary() is the main function of the first stage.
518dc859
RL
72
73 Second stage - interprocedural analysis
74 ========================================
b8698a0f 75
310bc633
MJ
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.
b8698a0f 79
310bc633
MJ
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
073a8998 84 propagate cumulative information about these effects from dependent values
310bc633 85 to those on which they depend.
518dc859 86
310bc633
MJ
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.
518dc859 92
310bc633
MJ
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
95
96 Third phase - materialization of clones, call statement updates.
518dc859 97 ============================================
310bc633
MJ
98
99 This stage is currently performed by call graph code (mainly in cgraphunit.c
100 and tree-inline.c) according to instructions inserted to the call graph by
101 the second stage. */
518dc859
RL
102
103#include "config.h"
104#include "system.h"
105#include "coretypes.h"
40e23961 106#include "alias.h"
518dc859 107#include "tree.h"
c7131fb2 108#include "options.h"
40e23961 109#include "fold-const.h"
2fb9a547
AM
110#include "gimple-fold.h"
111#include "gimple-expr.h"
518dc859 112#include "target.h"
c7131fb2 113#include "backend.h"
9fdcd34e 114#include "predict.h"
c582198b 115#include "hard-reg-set.h"
c582198b
AM
116#include "cgraph.h"
117#include "alloc-pool.h"
dd912cb8 118#include "symbol-summary.h"
518dc859 119#include "ipa-prop.h"
518dc859
RL
120#include "tree-pass.h"
121#include "flags.h"
518dc859 122#include "diagnostic.h"
cf835838 123#include "tree-pretty-print.h"
3cc1cccc 124#include "tree-inline.h"
5e45130d 125#include "params.h"
10a5dd5d 126#include "ipa-inline.h"
310bc633 127#include "ipa-utils.h"
518dc859 128
c0cb5055 129template <typename valtype> class ipcp_value;
ca30a539 130
310bc633 131/* Describes a particular source for an IPA-CP value. */
ca30a539 132
c0cb5055
MJ
133template <typename valtype>
134class ipcp_value_source
310bc633 135{
c0cb5055 136public:
2c9561b5
MJ
137 /* Aggregate offset of the source, negative if the source is scalar value of
138 the argument itself. */
139 HOST_WIDE_INT offset;
310bc633 140 /* The incoming edge that brought the value. */
c0cb5055 141 cgraph_edge *cs;
310bc633
MJ
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. */
c0cb5055 145 ipcp_value<valtype> *val;
310bc633 146 /* Next pointer in a linked list of sources of a value. */
c0cb5055 147 ipcp_value_source *next;
310bc633
MJ
148 /* If the jump function that resulted into his value was a pass-through or an
149 ancestor, this is the index of the parameter of the caller the jump
150 function references. */
151 int index;
152};
ca30a539 153
c0cb5055
MJ
154/* Common ancestor for all ipcp_value instantiations. */
155
156class ipcp_value_base
157{
158public:
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;
165};
166
310bc633 167/* Describes one particular value stored in struct ipcp_lattice. */
ca30a539 168
c0cb5055
MJ
169template <typename valtype>
170class ipcp_value : public ipcp_value_base
518dc859 171{
c0cb5055
MJ
172public:
173 /* The actual value for the given parameter. */
174 valtype value;
310bc633 175 /* The list of sources from which this value originates. */
c0cb5055 176 ipcp_value_source <valtype> *sources;
310bc633 177 /* Next pointers in a linked list of all values in a lattice. */
c0cb5055 178 ipcp_value *next;
310bc633
MJ
179 /* Next pointers in a linked list of values in a strongly connected component
180 of values. */
c0cb5055 181 ipcp_value *scc_next;
310bc633
MJ
182 /* Next pointers in a linked list of SCCs of values sorted topologically
183 according their sources. */
c0cb5055 184 ipcp_value *topo_next;
310bc633
MJ
185 /* A specialized node created for this value, NULL if none has been (so far)
186 created. */
c0cb5055 187 cgraph_node *spec_node;
310bc633
MJ
188 /* Depth first search number and low link for topological sorting of
189 values. */
190 int dfs, low_link;
310bc633
MJ
191 /* True if this valye is currently on the topo-sort stack. */
192 bool on_stack;
c0cb5055
MJ
193
194 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
195 HOST_WIDE_INT offset);
310bc633 196};
518dc859 197
2c9561b5
MJ
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
310bc633
MJ
202 contains_variable flag should be disregarded. */
203
c0cb5055
MJ
204template <typename valtype>
205class ipcp_lattice
518dc859 206{
c0cb5055 207public:
310bc633
MJ
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. */
c0cb5055 211 ipcp_value<valtype> *values;
310bc633
MJ
212 /* Number of known values and types in this lattice. */
213 int values_count;
2c9561b5 214 /* The lattice contains a variable component (in addition to values). */
310bc633
MJ
215 bool contains_variable;
216 /* The value of the lattice is bottom (i.e. variable and unusable for any
217 propagation). */
218 bool bottom;
c0cb5055
MJ
219
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);
2c9561b5
MJ
227};
228
c0cb5055
MJ
229/* Lattice of tree values with an offset to describe a part of an
230 aggregate. */
2c9561b5 231
c0cb5055 232class ipcp_agg_lattice : public ipcp_lattice<tree>
2c9561b5 233{
c0cb5055 234public:
2c9561b5
MJ
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. */
239 HOST_WIDE_INT size;
240 /* Next element of the linked list. */
241 struct ipcp_agg_lattice *next;
242};
243
c8710b5c
MJ
244/* Lattice of pointer alignment. Unlike the previous types of lattices, this
245 one is only capable of holding one value. */
246
247class ipcp_alignment_lattice
248{
249public:
250 /* If bottom and top are both false, these two fields hold values as given by
251 ptr_info_def and get_pointer_alignment_1. */
252 unsigned align;
253 unsigned misalign;
254
255 inline bool bottom_p () const;
256 inline bool top_p () const;
257 inline bool set_to_bottom ();
258 bool meet_with (unsigned new_align, unsigned new_misalign);
259 bool meet_with (const ipcp_alignment_lattice &other, HOST_WIDE_INT offset);
260 void print (FILE * f);
261private:
262 /* If set, this lattice is bottom and all other fields should be
263 disregarded. */
264 bool bottom;
265 /* If bottom and not_top are false, the lattice is TOP. If not_top is true,
266 the known alignment is stored in the fields align and misalign. The field
267 is negated so that memset to zero initializes the lattice to TOP
268 state. */
269 bool not_top;
270
271 bool meet_with_1 (unsigned new_align, unsigned new_misalign);
272};
273
2c9561b5
MJ
274/* Structure containing lattices for a parameter itself and for pieces of
275 aggregates that are passed in the parameter or by a reference in a parameter
276 plus some other useful flags. */
277
c0cb5055 278class ipcp_param_lattices
2c9561b5 279{
c0cb5055 280public:
2c9561b5 281 /* Lattice describing the value of the parameter itself. */
c0cb5055 282 ipcp_lattice<tree> itself;
026c3cfd 283 /* Lattice describing the polymorphic contexts of a parameter. */
44210a96 284 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
2c9561b5 285 /* Lattices describing aggregate parts. */
c0cb5055 286 ipcp_agg_lattice *aggs;
c8710b5c
MJ
287 /* Lattice describing known alignment. */
288 ipcp_alignment_lattice alignment;
2c9561b5
MJ
289 /* Number of aggregate lattices */
290 int aggs_count;
291 /* True if aggregate data were passed by reference (as opposed to by
292 value). */
293 bool aggs_by_ref;
294 /* All aggregate lattices contain a variable component (in addition to
295 values). */
296 bool aggs_contain_variable;
297 /* The value of all aggregate lattices is bottom (i.e. variable and unusable
298 for any propagation). */
299 bool aggs_bottom;
300
310bc633
MJ
301 /* There is a virtual call based on this parameter. */
302 bool virt_call;
303};
518dc859 304
2c9561b5
MJ
305/* Allocation pools for values and their sources in ipa-cp. */
306
fb0b2914 307object_allocator<ipcp_value<tree> > ipcp_cst_values_pool
fcb87c50 308 ("IPA-CP constant values");
2651e637 309
fb0b2914 310object_allocator<ipcp_value<ipa_polymorphic_call_context> >
fcb87c50 311 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts");
2651e637 312
fb0b2914 313object_allocator<ipcp_value_source<tree> > ipcp_sources_pool
fcb87c50 314 ("IPA-CP value sources");
2651e637 315
fb0b2914 316object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool
fcb87c50 317 ("IPA_CP aggregate lattices");
2c9561b5 318
310bc633
MJ
319/* Maximal count found in program. */
320
321static gcov_type max_count;
322
323/* Original overall size of the program. */
324
325static long overall_size, max_new_size;
326
2c9561b5
MJ
327/* Return the param lattices structure corresponding to the Ith formal
328 parameter of the function described by INFO. */
329static inline struct ipcp_param_lattices *
330ipa_get_parm_lattices (struct ipa_node_params *info, int i)
518dc859 331{
d7da5cc8 332 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
310bc633
MJ
333 gcc_checking_assert (!info->ipcp_orig_node);
334 gcc_checking_assert (info->lattices);
335 return &(info->lattices[i]);
518dc859
RL
336}
337
2c9561b5
MJ
338/* Return the lattice corresponding to the scalar value of the Ith formal
339 parameter of the function described by INFO. */
c0cb5055 340static inline ipcp_lattice<tree> *
2c9561b5
MJ
341ipa_get_scalar_lat (struct ipa_node_params *info, int i)
342{
343 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
344 return &plats->itself;
345}
346
44210a96
MJ
347/* Return the lattice corresponding to the scalar value of the Ith formal
348 parameter of the function described by INFO. */
349static inline ipcp_lattice<ipa_polymorphic_call_context> *
350ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
351{
352 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
353 return &plats->ctxlat;
354}
355
310bc633
MJ
356/* Return whether LAT is a lattice with a single constant and without an
357 undefined value. */
358
c0cb5055
MJ
359template <typename valtype>
360inline bool
361ipcp_lattice<valtype>::is_single_const ()
518dc859 362{
c0cb5055 363 if (bottom || contains_variable || values_count != 1)
518dc859 364 return false;
310bc633
MJ
365 else
366 return true;
518dc859
RL
367}
368
310bc633
MJ
369/* Print V which is extracted from a value in a lattice to F. */
370
518dc859 371static void
310bc633 372print_ipcp_constant_value (FILE * f, tree v)
518dc859 373{
3b97a5c7 374 if (TREE_CODE (v) == ADDR_EXPR
310bc633 375 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
518dc859 376 {
310bc633
MJ
377 fprintf (f, "& ");
378 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
518dc859 379 }
310bc633
MJ
380 else
381 print_generic_expr (f, v, 0);
518dc859
RL
382}
383
44210a96
MJ
384/* Print V which is extracted from a value in a lattice to F. */
385
386static void
387print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v)
388{
389 v.dump(f, false);
390}
391
2c9561b5
MJ
392/* Print a lattice LAT to F. */
393
c0cb5055
MJ
394template <typename valtype>
395void
396ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
2c9561b5 397{
c0cb5055 398 ipcp_value<valtype> *val;
2c9561b5
MJ
399 bool prev = false;
400
c0cb5055 401 if (bottom)
2c9561b5
MJ
402 {
403 fprintf (f, "BOTTOM\n");
404 return;
405 }
406
c0cb5055 407 if (!values_count && !contains_variable)
2c9561b5
MJ
408 {
409 fprintf (f, "TOP\n");
410 return;
411 }
412
c0cb5055 413 if (contains_variable)
2c9561b5
MJ
414 {
415 fprintf (f, "VARIABLE");
416 prev = true;
417 if (dump_benefits)
418 fprintf (f, "\n");
419 }
420
c0cb5055 421 for (val = values; val; val = val->next)
2c9561b5
MJ
422 {
423 if (dump_benefits && prev)
424 fprintf (f, " ");
425 else if (!dump_benefits && prev)
426 fprintf (f, ", ");
427 else
428 prev = true;
429
430 print_ipcp_constant_value (f, val->value);
431
432 if (dump_sources)
433 {
c0cb5055 434 ipcp_value_source<valtype> *s;
2c9561b5
MJ
435
436 fprintf (f, " [from:");
437 for (s = val->sources; s; s = s->next)
67348ccc 438 fprintf (f, " %i(%i)", s->cs->caller->order,
9de04252 439 s->cs->frequency);
2c9561b5
MJ
440 fprintf (f, "]");
441 }
442
443 if (dump_benefits)
444 fprintf (f, " [loc_time: %i, loc_size: %i, "
445 "prop_time: %i, prop_size: %i]\n",
446 val->local_time_benefit, val->local_size_cost,
447 val->prop_time_benefit, val->prop_size_cost);
448 }
449 if (!dump_benefits)
450 fprintf (f, "\n");
451}
452
c8710b5c
MJ
453/* Print alignment lattice to F. */
454
455void
456ipcp_alignment_lattice::print (FILE * f)
457{
458 if (top_p ())
459 fprintf (f, " Alignment unknown (TOP)\n");
460 else if (bottom_p ())
461 fprintf (f, " Alignment unusable (BOTTOM)\n");
462 else
463 fprintf (f, " Alignment %u, misalignment %u\n", align, misalign);
464}
465
c43f07af 466/* Print all ipcp_lattices of all functions to F. */
310bc633 467
518dc859 468static void
310bc633 469print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
518dc859
RL
470{
471 struct cgraph_node *node;
472 int i, count;
3cc1cccc 473
310bc633
MJ
474 fprintf (f, "\nLattices:\n");
475 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
518dc859 476 {
0eae6bab
MJ
477 struct ipa_node_params *info;
478
0eae6bab 479 info = IPA_NODE_REF (node);
fec39fa6 480 fprintf (f, " Node: %s/%i:\n", node->name (),
67348ccc 481 node->order);
c43f07af 482 count = ipa_get_param_count (info);
518dc859
RL
483 for (i = 0; i < count; i++)
484 {
2c9561b5
MJ
485 struct ipcp_agg_lattice *aglat;
486 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
ca30a539 487 fprintf (f, " param [%d]: ", i);
c0cb5055 488 plats->itself.print (f, dump_sources, dump_benefits);
44210a96
MJ
489 fprintf (f, " ctxs: ");
490 plats->ctxlat.print (f, dump_sources, dump_benefits);
c8710b5c 491 plats->alignment.print (f);
2c9561b5
MJ
492 if (plats->virt_call)
493 fprintf (f, " virt_call flag set\n");
494
495 if (plats->aggs_bottom)
310bc633 496 {
2c9561b5 497 fprintf (f, " AGGS BOTTOM\n");
310bc633
MJ
498 continue;
499 }
2c9561b5
MJ
500 if (plats->aggs_contain_variable)
501 fprintf (f, " AGGS VARIABLE\n");
502 for (aglat = plats->aggs; aglat; aglat = aglat->next)
310bc633 503 {
2c9561b5
MJ
504 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
505 plats->aggs_by_ref ? "ref " : "", aglat->offset);
c0cb5055 506 aglat->print (f, dump_sources, dump_benefits);
310bc633 507 }
518dc859
RL
508 }
509 }
510}
511
310bc633
MJ
512/* Determine whether it is at all technically possible to create clones of NODE
513 and store this information in the ipa_node_params structure associated
514 with NODE. */
27dbd3ac 515
310bc633 516static void
7e729474
ML
517determine_versionability (struct cgraph_node *node,
518 struct ipa_node_params *info)
27dbd3ac 519{
310bc633 520 const char *reason = NULL;
0818c24c 521
aa229804
MJ
522 /* There are a number of generic reasons functions cannot be versioned. We
523 also cannot remove parameters if there are type attributes such as fnspec
524 present. */
67348ccc 525 if (node->alias || node->thunk.thunk_p)
310bc633 526 reason = "alias or thunk";
124f1be6 527 else if (!node->local.versionable)
d7da5cc8 528 reason = "not a tree_versionable_function";
d52f5295 529 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
310bc633 530 reason = "insufficient body availability";
d31d42c7
JJ
531 else if (!opt_for_fn (node->decl, optimize)
532 || !opt_for_fn (node->decl, flag_ipa_cp))
533 reason = "non-optimized function";
0136f8f0
AH
534 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl)))
535 {
536 /* Ideally we should clone the SIMD clones themselves and create
537 vector copies of them, so IPA-cp and SIMD clones can happily
538 coexist, but that may not be worth the effort. */
539 reason = "function has SIMD clones";
540 }
1f26ac87
JM
541 /* Don't clone decls local to a comdat group; it breaks and for C++
542 decloned constructors, inlining is always better anyway. */
d52f5295 543 else if (node->comdat_local_p ())
1f26ac87 544 reason = "comdat-local function";
27dbd3ac 545
67348ccc 546 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
310bc633 547 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
fec39fa6 548 node->name (), node->order, reason);
27dbd3ac 549
7e729474 550 info->versionable = (reason == NULL);
27dbd3ac
RH
551}
552
310bc633
MJ
553/* Return true if it is at all technically possible to create clones of a
554 NODE. */
555
ca30a539 556static bool
310bc633 557ipcp_versionable_function_p (struct cgraph_node *node)
ca30a539 558{
7e729474 559 return IPA_NODE_REF (node)->versionable;
310bc633 560}
ca30a539 561
310bc633 562/* Structure holding accumulated information about callers of a node. */
749f25d8 563
310bc633
MJ
564struct caller_statistics
565{
566 gcov_type count_sum;
567 int n_calls, n_hot_calls, freq_sum;
568};
ca30a539 569
310bc633 570/* Initialize fields of STAT to zeroes. */
530f3a1b 571
310bc633
MJ
572static inline void
573init_caller_stats (struct caller_statistics *stats)
574{
575 stats->count_sum = 0;
576 stats->n_calls = 0;
577 stats->n_hot_calls = 0;
578 stats->freq_sum = 0;
579}
580
581/* Worker callback of cgraph_for_node_and_aliases accumulating statistics of
582 non-thunk incoming edges to NODE. */
583
584static bool
585gather_caller_stats (struct cgraph_node *node, void *data)
586{
587 struct caller_statistics *stats = (struct caller_statistics *) data;
588 struct cgraph_edge *cs;
589
590 for (cs = node->callers; cs; cs = cs->next_caller)
94a2f772 591 if (!cs->caller->thunk.thunk_p)
310bc633
MJ
592 {
593 stats->count_sum += cs->count;
594 stats->freq_sum += cs->frequency;
595 stats->n_calls++;
3dafb85c 596 if (cs->maybe_hot_p ())
310bc633
MJ
597 stats->n_hot_calls ++;
598 }
599 return false;
600
601}
602
603/* Return true if this NODE is viable candidate for cloning. */
604
605static bool
606ipcp_cloning_candidate_p (struct cgraph_node *node)
607{
608 struct caller_statistics stats;
609
d52f5295 610 gcc_checking_assert (node->has_gimple_body_p ());
b8698a0f 611
2bf86c84 612 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
ca30a539
JH
613 {
614 if (dump_file)
310bc633
MJ
615 fprintf (dump_file, "Not considering %s for cloning; "
616 "-fipa-cp-clone disabled.\n",
fec39fa6 617 node->name ());
ca30a539
JH
618 return false;
619 }
ca30a539 620
67348ccc 621 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
ca30a539
JH
622 {
623 if (dump_file)
310bc633
MJ
624 fprintf (dump_file, "Not considering %s for cloning; "
625 "optimizing it for size.\n",
fec39fa6 626 node->name ());
ca30a539
JH
627 return false;
628 }
629
310bc633 630 init_caller_stats (&stats);
d52f5295 631 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
310bc633 632
9a1e784a 633 if (inline_summaries->get (node)->self_size < stats.n_calls)
ca30a539
JH
634 {
635 if (dump_file)
310bc633 636 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
fec39fa6 637 node->name ());
310bc633 638 return true;
ca30a539
JH
639 }
640
641 /* When profile is available and function is hot, propagate into it even if
642 calls seems cold; constant propagation can improve function's speed
61502ca8 643 significantly. */
ca30a539
JH
644 if (max_count)
645 {
310bc633 646 if (stats.count_sum > node->count * 90 / 100)
ca30a539
JH
647 {
648 if (dump_file)
310bc633
MJ
649 fprintf (dump_file, "Considering %s for cloning; "
650 "usually called directly.\n",
fec39fa6 651 node->name ());
ca30a539
JH
652 return true;
653 }
654 }
310bc633 655 if (!stats.n_hot_calls)
ca30a539
JH
656 {
657 if (dump_file)
658 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
fec39fa6 659 node->name ());
ed102b70 660 return false;
ca30a539
JH
661 }
662 if (dump_file)
663 fprintf (dump_file, "Considering %s for cloning.\n",
fec39fa6 664 node->name ());
ca30a539
JH
665 return true;
666}
667
c0cb5055
MJ
668template <typename valtype>
669class value_topo_info
670{
671public:
672 /* Head of the linked list of topologically sorted values. */
673 ipcp_value<valtype> *values_topo;
674 /* Stack for creating SCCs, represented by a linked list too. */
675 ipcp_value<valtype> *stack;
676 /* Counter driving the algorithm in add_val_to_toposort. */
677 int dfs_counter;
678
679 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
680 {}
681 void add_val (ipcp_value<valtype> *cur_val);
682 void propagate_effects ();
683};
684
310bc633 685/* Arrays representing a topological ordering of call graph nodes and a stack
c0cb5055
MJ
686 of nodes used during constant propagation and also data required to perform
687 topological sort of values and propagation of benefits in the determined
688 order. */
3949c4a7 689
c0cb5055 690class ipa_topo_info
3949c4a7 691{
c0cb5055
MJ
692public:
693 /* Array with obtained topological order of cgraph nodes. */
310bc633 694 struct cgraph_node **order;
c0cb5055
MJ
695 /* Stack of cgraph nodes used during propagation within SCC until all values
696 in the SCC stabilize. */
310bc633
MJ
697 struct cgraph_node **stack;
698 int nnodes, stack_top;
c0cb5055
MJ
699
700 value_topo_info<tree> constants;
44210a96 701 value_topo_info<ipa_polymorphic_call_context> contexts;
c0cb5055
MJ
702
703 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
704 constants ()
705 {}
310bc633
MJ
706};
707
708/* Allocate the arrays in TOPO and topologically sort the nodes into order. */
709
710static void
11478306 711build_toporder_info (struct ipa_topo_info *topo)
310bc633 712{
3dafb85c
ML
713 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
714 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
715
c0cb5055 716 gcc_checking_assert (topo->stack_top == 0);
310bc633 717 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
3949c4a7
MJ
718}
719
310bc633
MJ
720/* Free information about strongly connected components and the arrays in
721 TOPO. */
722
518dc859 723static void
11478306 724free_toporder_info (struct ipa_topo_info *topo)
310bc633
MJ
725{
726 ipa_free_postorder_info ();
727 free (topo->order);
728 free (topo->stack);
729}
730
731/* Add NODE to the stack in TOPO, unless it is already there. */
732
733static inline void
11478306 734push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
518dc859 735{
c43f07af 736 struct ipa_node_params *info = IPA_NODE_REF (node);
310bc633
MJ
737 if (info->node_enqueued)
738 return;
739 info->node_enqueued = 1;
740 topo->stack[topo->stack_top++] = node;
741}
518dc859 742
310bc633
MJ
743/* Pop a node from the stack in TOPO and return it or return NULL if the stack
744 is empty. */
ca30a539 745
310bc633 746static struct cgraph_node *
11478306 747pop_node_from_stack (struct ipa_topo_info *topo)
310bc633
MJ
748{
749 if (topo->stack_top)
3949c4a7 750 {
310bc633
MJ
751 struct cgraph_node *node;
752 topo->stack_top--;
753 node = topo->stack[topo->stack_top];
754 IPA_NODE_REF (node)->node_enqueued = 0;
755 return node;
3949c4a7 756 }
310bc633
MJ
757 else
758 return NULL;
518dc859
RL
759}
760
310bc633
MJ
761/* Set lattice LAT to bottom and return true if it previously was not set as
762 such. */
763
c0cb5055
MJ
764template <typename valtype>
765inline bool
766ipcp_lattice<valtype>::set_to_bottom ()
518dc859 767{
c0cb5055
MJ
768 bool ret = !bottom;
769 bottom = true;
310bc633
MJ
770 return ret;
771}
518dc859 772
310bc633
MJ
773/* Mark lattice as containing an unknown value and return true if it previously
774 was not marked as such. */
129a37fc 775
c0cb5055
MJ
776template <typename valtype>
777inline bool
778ipcp_lattice<valtype>::set_contains_variable ()
310bc633 779{
c0cb5055
MJ
780 bool ret = !contains_variable;
781 contains_variable = true;
310bc633 782 return ret;
518dc859
RL
783}
784
2c9561b5
MJ
785/* Set all aggegate lattices in PLATS to bottom and return true if they were
786 not previously set as such. */
787
788static inline bool
789set_agg_lats_to_bottom (struct ipcp_param_lattices *plats)
790{
791 bool ret = !plats->aggs_bottom;
792 plats->aggs_bottom = true;
793 return ret;
794}
795
796/* Mark all aggegate lattices in PLATS as containing an unknown value and
797 return true if they were not previously marked as such. */
798
799static inline bool
800set_agg_lats_contain_variable (struct ipcp_param_lattices *plats)
801{
802 bool ret = !plats->aggs_contain_variable;
803 plats->aggs_contain_variable = true;
804 return ret;
805}
806
c8710b5c 807/* Return true if alignment information in the lattice is yet unknown. */
04be694e 808
c8710b5c
MJ
809bool
810ipcp_alignment_lattice::top_p () const
04be694e 811{
c8710b5c 812 return !bottom && !not_top;
04be694e
MJ
813}
814
c8710b5c
MJ
815/* Return true if alignment information in the lattice is known to be
816 unusable. */
04be694e 817
c8710b5c
MJ
818bool
819ipcp_alignment_lattice::bottom_p () const
820{
821 return bottom;
822}
823
824/* Set alignment information in the lattice to bottom. Return true if it
825 previously was in a different state. */
826
827bool
828ipcp_alignment_lattice::set_to_bottom ()
04be694e 829{
c8710b5c 830 if (bottom_p ())
04be694e 831 return false;
c8710b5c 832 bottom = true;
04be694e
MJ
833 return true;
834}
835
c8710b5c
MJ
836/* Meet the current value of the lattice with alignment described by NEW_ALIGN
837 and NEW_MISALIGN, assuming that we know the current value is neither TOP nor
838 BOTTOM. Return true if the value of lattice has changed. */
839
840bool
841ipcp_alignment_lattice::meet_with_1 (unsigned new_align, unsigned new_misalign)
842{
843 gcc_checking_assert (new_align != 0);
844 if (align == new_align && misalign == new_misalign)
845 return false;
846
847 bool changed = false;
848 if (align > new_align)
849 {
850 align = new_align;
851 misalign = misalign % new_align;
852 changed = true;
853 }
854 if (misalign != (new_misalign % align))
855 {
170f473b
MJ
856 int diff = abs ((int) misalign - (int) (new_misalign % align));
857 align = (unsigned) diff & -diff;
c8710b5c
MJ
858 if (align)
859 misalign = misalign % align;
860 else
861 set_to_bottom ();
862 changed = true;
863 }
864 gcc_checking_assert (bottom_p () || align != 0);
865 return changed;
866}
867
868/* Meet the current value of the lattice with alignment described by NEW_ALIGN
869 and NEW_MISALIGN. Return true if the value of lattice has changed. */
870
871bool
872ipcp_alignment_lattice::meet_with (unsigned new_align, unsigned new_misalign)
873{
874 gcc_assert (new_align != 0);
875 if (bottom_p ())
876 return false;
877 if (top_p ())
878 {
879 not_top = true;
880 align = new_align;
881 misalign = new_misalign;
882 return true;
883 }
884 return meet_with_1 (new_align, new_misalign);
885}
886
887/* Meet the current value of the lattice with OTHER, taking into account that
888 OFFSET has been added to the pointer value. Return true if the value of
889 lattice has changed. */
890
891bool
892ipcp_alignment_lattice::meet_with (const ipcp_alignment_lattice &other,
893 HOST_WIDE_INT offset)
894{
895 if (other.bottom_p ())
896 return set_to_bottom ();
897 if (bottom_p () || other.top_p ())
898 return false;
899
900 unsigned adjusted_misalign = (other.misalign + offset) % other.align;
901 if (top_p ())
902 {
903 not_top = true;
904 align = other.align;
905 misalign = adjusted_misalign;
906 return true;
907 }
908
909 return meet_with_1 (other.align, adjusted_misalign);
910}
911
2c9561b5
MJ
912/* Mark bot aggregate and scalar lattices as containing an unknown variable,
913 return true is any of them has not been marked as such so far. */
914
915static inline bool
916set_all_contains_variable (struct ipcp_param_lattices *plats)
917{
44210a96
MJ
918 bool ret;
919 ret = plats->itself.set_contains_variable ();
920 ret |= plats->ctxlat.set_contains_variable ();
921 ret |= set_agg_lats_contain_variable (plats);
c8710b5c 922 ret |= plats->alignment.set_to_bottom ();
2c9561b5
MJ
923 return ret;
924}
925
af21714c
MJ
926/* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
927 points to by the number of callers to NODE. */
928
929static bool
930count_callers (cgraph_node *node, void *data)
931{
932 int *caller_count = (int *) data;
933
934 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
935 /* Local thunks can be handled transparently, but if the thunk can not
936 be optimized out, count it as a real use. */
937 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local)
938 ++*caller_count;
939 return false;
940}
941
942/* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
943 the one caller of some other node. Set the caller's corresponding flag. */
944
945static bool
946set_single_call_flag (cgraph_node *node, void *)
947{
948 cgraph_edge *cs = node->callers;
949 /* Local thunks can be handled transparently, skip them. */
950 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local)
951 cs = cs->next_caller;
952 if (cs)
953 {
af21714c
MJ
954 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
955 return true;
956 }
957 return false;
958}
959
310bc633 960/* Initialize ipcp_lattices. */
43558bcc 961
518dc859 962static void
310bc633 963initialize_node_lattices (struct cgraph_node *node)
518dc859 964{
310bc633
MJ
965 struct ipa_node_params *info = IPA_NODE_REF (node);
966 struct cgraph_edge *ie;
967 bool disable = false, variable = false;
968 int i;
518dc859 969
d52f5295 970 gcc_checking_assert (node->has_gimple_body_p ());
af21714c
MJ
971 if (cgraph_local_p (node))
972 {
973 int caller_count = 0;
974 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
975 true);
976 gcc_checking_assert (caller_count > 0);
977 if (caller_count == 1)
978 node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
979 NULL, true);
980 }
981 else
310bc633
MJ
982 {
983 /* When cloning is allowed, we can assume that externally visible
984 functions are not called. We will compensate this by cloning
985 later. */
986 if (ipcp_versionable_function_p (node)
987 && ipcp_cloning_candidate_p (node))
988 variable = true;
989 else
990 disable = true;
991 }
518dc859 992
310bc633
MJ
993 if (disable || variable)
994 {
995 for (i = 0; i < ipa_get_param_count (info) ; i++)
996 {
2c9561b5 997 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
310bc633 998 if (disable)
2c9561b5 999 {
c0cb5055 1000 plats->itself.set_to_bottom ();
44210a96 1001 plats->ctxlat.set_to_bottom ();
2c9561b5 1002 set_agg_lats_to_bottom (plats);
c8710b5c 1003 plats->alignment.set_to_bottom ();
2c9561b5 1004 }
310bc633 1005 else
2c9561b5 1006 set_all_contains_variable (plats);
310bc633
MJ
1007 }
1008 if (dump_file && (dump_flags & TDF_DETAILS)
67348ccc 1009 && !node->alias && !node->thunk.thunk_p)
310bc633 1010 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
fec39fa6 1011 node->name (), node->order,
310bc633
MJ
1012 disable ? "BOTTOM" : "VARIABLE");
1013 }
518dc859 1014
310bc633 1015 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
1d5755ef
JH
1016 if (ie->indirect_info->polymorphic
1017 && ie->indirect_info->param_index >= 0)
0818c24c 1018 {
310bc633 1019 gcc_checking_assert (ie->indirect_info->param_index >= 0);
2c9561b5
MJ
1020 ipa_get_parm_lattices (info,
1021 ie->indirect_info->param_index)->virt_call = 1;
0818c24c 1022 }
518dc859
RL
1023}
1024
310bc633
MJ
1025/* Return the result of a (possibly arithmetic) pass through jump function
1026 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be
b8f6e610 1027 determined or be considered an interprocedural invariant. */
3949c4a7 1028
310bc633
MJ
1029static tree
1030ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
3949c4a7 1031{
310bc633 1032 tree restype, res;
3949c4a7 1033
3b97a5c7 1034 gcc_checking_assert (is_gimple_ip_invariant (input));
7b872d9e 1035 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
310bc633 1036 return input;
3949c4a7 1037
7b872d9e 1038 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
310bc633
MJ
1039 == tcc_comparison)
1040 restype = boolean_type_node;
1041 else
1042 restype = TREE_TYPE (input);
7b872d9e
MJ
1043 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
1044 input, ipa_get_jf_pass_through_operand (jfunc));
3949c4a7 1045
310bc633
MJ
1046 if (res && !is_gimple_ip_invariant (res))
1047 return NULL_TREE;
3949c4a7 1048
310bc633 1049 return res;
3949c4a7
MJ
1050}
1051
310bc633
MJ
1052/* Return the result of an ancestor jump function JFUNC on the constant value
1053 INPUT. Return NULL_TREE if that cannot be determined. */
3949c4a7 1054
310bc633
MJ
1055static tree
1056ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
3949c4a7 1057{
44210a96
MJ
1058 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
1059 if (TREE_CODE (input) == ADDR_EXPR)
3949c4a7 1060 {
310bc633
MJ
1061 tree t = TREE_OPERAND (input, 0);
1062 t = build_ref_for_offset (EXPR_LOCATION (t), t,
7b872d9e 1063 ipa_get_jf_ancestor_offset (jfunc),
3b97a5c7 1064 ptr_type_node, NULL, false);
310bc633 1065 return build_fold_addr_expr (t);
3949c4a7
MJ
1066 }
1067 else
310bc633
MJ
1068 return NULL_TREE;
1069}
3949c4a7 1070
44210a96
MJ
1071/* Determine whether JFUNC evaluates to a single known constant value and if
1072 so, return it. Otherwise return NULL. INFO describes the caller node or
1073 the one it is inlined to, so that pass-through jump functions can be
310bc633
MJ
1074 evaluated. */
1075
d2d668fb 1076tree
310bc633
MJ
1077ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
1078{
1079 if (jfunc->type == IPA_JF_CONST)
7b872d9e 1080 return ipa_get_jf_constant (jfunc);
310bc633
MJ
1081 else if (jfunc->type == IPA_JF_PASS_THROUGH
1082 || jfunc->type == IPA_JF_ANCESTOR)
3949c4a7 1083 {
310bc633
MJ
1084 tree input;
1085 int idx;
3949c4a7 1086
310bc633 1087 if (jfunc->type == IPA_JF_PASS_THROUGH)
7b872d9e 1088 idx = ipa_get_jf_pass_through_formal_id (jfunc);
310bc633 1089 else
7b872d9e 1090 idx = ipa_get_jf_ancestor_formal_id (jfunc);
3949c4a7 1091
310bc633 1092 if (info->ipcp_orig_node)
44210a96 1093 input = info->known_csts[idx];
310bc633 1094 else
3949c4a7 1095 {
c0cb5055 1096 ipcp_lattice<tree> *lat;
310bc633 1097
370a7814
JH
1098 if (!info->lattices
1099 || idx >= ipa_get_param_count (info))
2bf86c84 1100 return NULL_TREE;
2c9561b5 1101 lat = ipa_get_scalar_lat (info, idx);
c0cb5055 1102 if (!lat->is_single_const ())
310bc633
MJ
1103 return NULL_TREE;
1104 input = lat->values->value;
1105 }
1106
1107 if (!input)
1108 return NULL_TREE;
1109
1110 if (jfunc->type == IPA_JF_PASS_THROUGH)
7b872d9e 1111 return ipa_get_jf_pass_through_result (jfunc, input);
310bc633 1112 else
7b872d9e 1113 return ipa_get_jf_ancestor_result (jfunc, input);
3949c4a7 1114 }
310bc633
MJ
1115 else
1116 return NULL_TREE;
3949c4a7
MJ
1117}
1118
44210a96
MJ
1119/* Determie whether JFUNC evaluates to single known polymorphic context, given
1120 that INFO describes the caller node or the one it is inlined to, CS is the
1121 call graph edge corresponding to JFUNC and CSIDX index of the described
1122 parameter. */
1123
1124ipa_polymorphic_call_context
1125ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
1126 ipa_jump_func *jfunc)
1127{
1128 ipa_edge_args *args = IPA_EDGE_REF (cs);
1129 ipa_polymorphic_call_context ctx;
1130 ipa_polymorphic_call_context *edge_ctx
1131 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL;
1132
1133 if (edge_ctx && !edge_ctx->useless_p ())
1134 ctx = *edge_ctx;
1135
1136 if (jfunc->type == IPA_JF_PASS_THROUGH
1137 || jfunc->type == IPA_JF_ANCESTOR)
1138 {
1139 ipa_polymorphic_call_context srcctx;
1140 int srcidx;
df0d8136 1141 bool type_preserved = true;
44210a96
MJ
1142 if (jfunc->type == IPA_JF_PASS_THROUGH)
1143 {
df0d8136 1144 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
44210a96 1145 return ctx;
df0d8136 1146 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
44210a96
MJ
1147 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1148 }
1149 else
1150 {
df0d8136 1151 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
44210a96
MJ
1152 srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
1153 }
1154 if (info->ipcp_orig_node)
1155 {
1156 if (info->known_contexts.exists ())
1157 srcctx = info->known_contexts[srcidx];
1158 }
1159 else
1160 {
370a7814
JH
1161 if (!info->lattices
1162 || srcidx >= ipa_get_param_count (info))
2bf86c84 1163 return ctx;
44210a96
MJ
1164 ipcp_lattice<ipa_polymorphic_call_context> *lat;
1165 lat = ipa_get_poly_ctx_lat (info, srcidx);
1166 if (!lat->is_single_const ())
1167 return ctx;
1168 srcctx = lat->values->value;
1169 }
1170 if (srcctx.useless_p ())
1171 return ctx;
1172 if (jfunc->type == IPA_JF_ANCESTOR)
1173 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
df0d8136
JH
1174 if (!type_preserved)
1175 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1176 srcctx.combine_with (ctx);
1177 return srcctx;
44210a96
MJ
1178 }
1179
1180 return ctx;
1181}
3949c4a7 1182
310bc633
MJ
1183/* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
1184 bottom, not containing a variable component and without any known value at
1185 the same time. */
3949c4a7 1186
310bc633
MJ
1187DEBUG_FUNCTION void
1188ipcp_verify_propagated_values (void)
518dc859 1189{
310bc633 1190 struct cgraph_node *node;
ca30a539 1191
310bc633 1192 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
518dc859 1193 {
c43f07af 1194 struct ipa_node_params *info = IPA_NODE_REF (node);
310bc633 1195 int i, count = ipa_get_param_count (info);
c43f07af 1196
310bc633 1197 for (i = 0; i < count; i++)
518dc859 1198 {
c0cb5055 1199 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
c43f07af 1200
310bc633
MJ
1201 if (!lat->bottom
1202 && !lat->contains_variable
1203 && lat->values_count == 0)
518dc859 1204 {
310bc633 1205 if (dump_file)
518dc859 1206 {
d52f5295 1207 symtab_node::dump_table (dump_file);
310bc633 1208 fprintf (dump_file, "\nIPA lattices after constant "
5bed50e8 1209 "propagation, before gcc_unreachable:\n");
310bc633 1210 print_all_lattices (dump_file, true, false);
518dc859 1211 }
3949c4a7 1212
310bc633 1213 gcc_unreachable ();
518dc859
RL
1214 }
1215 }
1216 }
1217}
1218
310bc633
MJ
1219/* Return true iff X and Y should be considered equal values by IPA-CP. */
1220
1221static bool
1222values_equal_for_ipcp_p (tree x, tree y)
1223{
1224 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
1225
1226 if (x == y)
1227 return true;
1228
310bc633
MJ
1229 if (TREE_CODE (x) == ADDR_EXPR
1230 && TREE_CODE (y) == ADDR_EXPR
1231 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
1232 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
1233 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
1234 DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
1235 else
1236 return operand_equal_p (x, y, 0);
1237}
1238
44210a96
MJ
1239/* Return true iff X and Y should be considered equal contexts by IPA-CP. */
1240
1241static bool
1242values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
1243 ipa_polymorphic_call_context y)
1244{
1245 return x.equal_to (y);
1246}
1247
1248
c0cb5055
MJ
1249/* Add a new value source to the value represented by THIS, marking that a
1250 value comes from edge CS and (if the underlying jump function is a
1251 pass-through or an ancestor one) from a caller value SRC_VAL of a caller
1252 parameter described by SRC_INDEX. OFFSET is negative if the source was the
1253 scalar value of the parameter itself or the offset within an aggregate. */
310bc633 1254
c0cb5055
MJ
1255template <typename valtype>
1256void
1257ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1258 int src_idx, HOST_WIDE_INT offset)
518dc859 1259{
c0cb5055 1260 ipcp_value_source<valtype> *src;
ca30a539 1261
2651e637 1262 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
2c9561b5 1263 src->offset = offset;
310bc633
MJ
1264 src->cs = cs;
1265 src->val = src_val;
1266 src->index = src_idx;
fb3f88cc 1267
c0cb5055
MJ
1268 src->next = sources;
1269 sources = src;
310bc633
MJ
1270}
1271
c0cb5055
MJ
1272/* Allocate a new ipcp_value holding a tree constant, initialize its value to
1273 SOURCE and clear all other fields. */
310bc633 1274
c0cb5055
MJ
1275static ipcp_value<tree> *
1276allocate_and_init_ipcp_value (tree source)
310bc633 1277{
c0cb5055 1278 ipcp_value<tree> *val;
310bc633 1279
2651e637 1280 val = ipcp_cst_values_pool.allocate ();
44210a96
MJ
1281 memset (val, 0, sizeof (*val));
1282 val->value = source;
1283 return val;
1284}
1285
1286/* Allocate a new ipcp_value holding a polymorphic context, initialize its
1287 value to SOURCE and clear all other fields. */
1288
1289static ipcp_value<ipa_polymorphic_call_context> *
1290allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
1291{
1292 ipcp_value<ipa_polymorphic_call_context> *val;
1293
2651e637
ML
1294 // TODO
1295 val = ipcp_poly_ctx_values_pool.allocate ();
c0cb5055
MJ
1296 memset (val, 0, sizeof (*val));
1297 val->value = source;
1298 return val;
1299}
1300
1301/* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
1302 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
1303 meaning. OFFSET -1 means the source is scalar and not a part of an
1304 aggregate. */
1305
1306template <typename valtype>
1307bool
1308ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
1309 ipcp_value<valtype> *src_val,
1310 int src_idx, HOST_WIDE_INT offset)
1311{
1312 ipcp_value<valtype> *val;
1313
1314 if (bottom)
310bc633
MJ
1315 return false;
1316
c0cb5055 1317 for (val = values; val; val = val->next)
310bc633
MJ
1318 if (values_equal_for_ipcp_p (val->value, newval))
1319 {
4cb13597 1320 if (ipa_edge_within_scc (cs))
310bc633 1321 {
c0cb5055 1322 ipcp_value_source<valtype> *s;
310bc633
MJ
1323 for (s = val->sources; s ; s = s->next)
1324 if (s->cs == cs)
1325 break;
1326 if (s)
1327 return false;
1328 }
1329
c0cb5055 1330 val->add_source (cs, src_val, src_idx, offset);
310bc633
MJ
1331 return false;
1332 }
1333
c0cb5055 1334 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
310bc633
MJ
1335 {
1336 /* We can only free sources, not the values themselves, because sources
026c3cfd 1337 of other values in this SCC might point to them. */
c0cb5055 1338 for (val = values; val; val = val->next)
310bc633
MJ
1339 {
1340 while (val->sources)
1341 {
c0cb5055 1342 ipcp_value_source<valtype> *src = val->sources;
310bc633 1343 val->sources = src->next;
2651e637 1344 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
310bc633
MJ
1345 }
1346 }
1347
c0cb5055
MJ
1348 values = NULL;
1349 return set_to_bottom ();
310bc633
MJ
1350 }
1351
c0cb5055
MJ
1352 values_count++;
1353 val = allocate_and_init_ipcp_value (newval);
1354 val->add_source (cs, src_val, src_idx, offset);
1355 val->next = values;
1356 values = val;
310bc633
MJ
1357 return true;
1358}
fb3f88cc 1359
310bc633
MJ
1360/* Propagate values through a pass-through jump function JFUNC associated with
1361 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1362 is the index of the source parameter. */
1363
1364static bool
c0cb5055
MJ
1365propagate_vals_accross_pass_through (cgraph_edge *cs,
1366 ipa_jump_func *jfunc,
1367 ipcp_lattice<tree> *src_lat,
1368 ipcp_lattice<tree> *dest_lat,
310bc633
MJ
1369 int src_idx)
1370{
c0cb5055 1371 ipcp_value<tree> *src_val;
310bc633
MJ
1372 bool ret = false;
1373
310bc633 1374 /* Do not create new values when propagating within an SCC because if there
7b872d9e
MJ
1375 are arithmetic functions with circular dependencies, there is infinite
1376 number of them and we would just make lattices bottom. */
b8f6e610 1377 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
4cb13597 1378 && ipa_edge_within_scc (cs))
c0cb5055 1379 ret = dest_lat->set_contains_variable ();
310bc633
MJ
1380 else
1381 for (src_val = src_lat->values; src_val; src_val = src_val->next)
0818c24c 1382 {
b8f6e610 1383 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
310bc633
MJ
1384
1385 if (cstval)
c0cb5055 1386 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
310bc633 1387 else
c0cb5055 1388 ret |= dest_lat->set_contains_variable ();
0818c24c 1389 }
310bc633
MJ
1390
1391 return ret;
1392}
1393
1394/* Propagate values through an ancestor jump function JFUNC associated with
1395 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
1396 is the index of the source parameter. */
1397
1398static bool
1399propagate_vals_accross_ancestor (struct cgraph_edge *cs,
1400 struct ipa_jump_func *jfunc,
c0cb5055
MJ
1401 ipcp_lattice<tree> *src_lat,
1402 ipcp_lattice<tree> *dest_lat,
310bc633
MJ
1403 int src_idx)
1404{
c0cb5055 1405 ipcp_value<tree> *src_val;
310bc633
MJ
1406 bool ret = false;
1407
4cb13597 1408 if (ipa_edge_within_scc (cs))
c0cb5055 1409 return dest_lat->set_contains_variable ();
310bc633
MJ
1410
1411 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1412 {
7b872d9e 1413 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
310bc633
MJ
1414
1415 if (t)
c0cb5055 1416 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
310bc633 1417 else
c0cb5055 1418 ret |= dest_lat->set_contains_variable ();
310bc633
MJ
1419 }
1420
1421 return ret;
1422}
1423
2c9561b5
MJ
1424/* Propagate scalar values across jump function JFUNC that is associated with
1425 edge CS and put the values into DEST_LAT. */
310bc633
MJ
1426
1427static bool
2c9561b5
MJ
1428propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1429 struct ipa_jump_func *jfunc,
c0cb5055 1430 ipcp_lattice<tree> *dest_lat)
310bc633
MJ
1431{
1432 if (dest_lat->bottom)
1433 return false;
1434
44210a96 1435 if (jfunc->type == IPA_JF_CONST)
310bc633 1436 {
44210a96 1437 tree val = ipa_get_jf_constant (jfunc);
c0cb5055 1438 return dest_lat->add_value (val, cs, NULL, 0);
310bc633
MJ
1439 }
1440 else if (jfunc->type == IPA_JF_PASS_THROUGH
1441 || jfunc->type == IPA_JF_ANCESTOR)
1442 {
1443 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
c0cb5055 1444 ipcp_lattice<tree> *src_lat;
310bc633
MJ
1445 int src_idx;
1446 bool ret;
1447
1448 if (jfunc->type == IPA_JF_PASS_THROUGH)
7b872d9e 1449 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
310bc633 1450 else
7b872d9e 1451 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
310bc633 1452
2c9561b5 1453 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
310bc633 1454 if (src_lat->bottom)
c0cb5055 1455 return dest_lat->set_contains_variable ();
310bc633
MJ
1456
1457 /* If we would need to clone the caller and cannot, do not propagate. */
1458 if (!ipcp_versionable_function_p (cs->caller)
1459 && (src_lat->contains_variable
1460 || (src_lat->values_count > 1)))
c0cb5055 1461 return dest_lat->set_contains_variable ();
310bc633
MJ
1462
1463 if (jfunc->type == IPA_JF_PASS_THROUGH)
1464 ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
1465 dest_lat, src_idx);
1466 else
1467 ret = propagate_vals_accross_ancestor (cs, jfunc, src_lat, dest_lat,
1468 src_idx);
1469
1470 if (src_lat->contains_variable)
c0cb5055 1471 ret |= dest_lat->set_contains_variable ();
310bc633
MJ
1472
1473 return ret;
1474 }
1475
1476 /* TODO: We currently do not handle member method pointers in IPA-CP (we only
1477 use it for indirect inlining), we should propagate them too. */
c0cb5055 1478 return dest_lat->set_contains_variable ();
310bc633
MJ
1479}
1480
44210a96
MJ
1481/* Propagate scalar values across jump function JFUNC that is associated with
1482 edge CS and describes argument IDX and put the values into DEST_LAT. */
1483
1484static bool
1485propagate_context_accross_jump_function (cgraph_edge *cs,
1486 ipa_jump_func *jfunc, int idx,
1487 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat)
1488{
1489 ipa_edge_args *args = IPA_EDGE_REF (cs);
1490 if (dest_lat->bottom)
1491 return false;
1492 bool ret = false;
1493 bool added_sth = false;
df0d8136 1494 bool type_preserved = true;
44210a96
MJ
1495
1496 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
1497 = ipa_get_ith_polymorhic_call_context (args, idx);
1498
1499 if (edge_ctx_ptr)
df0d8136 1500 edge_ctx = *edge_ctx_ptr;
44210a96
MJ
1501
1502 if (jfunc->type == IPA_JF_PASS_THROUGH
1503 || jfunc->type == IPA_JF_ANCESTOR)
1504 {
1505 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1506 int src_idx;
1507 ipcp_lattice<ipa_polymorphic_call_context> *src_lat;
1508
1509 /* TODO: Once we figure out how to propagate speculations, it will
1510 probably be a good idea to switch to speculation if type_preserved is
1511 not set instead of punting. */
1512 if (jfunc->type == IPA_JF_PASS_THROUGH)
1513 {
df0d8136 1514 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
44210a96 1515 goto prop_fail;
df0d8136 1516 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
44210a96
MJ
1517 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1518 }
1519 else
1520 {
df0d8136 1521 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
44210a96
MJ
1522 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1523 }
1524
1525 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx);
1526 /* If we would need to clone the caller and cannot, do not propagate. */
1527 if (!ipcp_versionable_function_p (cs->caller)
1528 && (src_lat->contains_variable
1529 || (src_lat->values_count > 1)))
1530 goto prop_fail;
44210a96
MJ
1531
1532 ipcp_value<ipa_polymorphic_call_context> *src_val;
1533 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1534 {
1535 ipa_polymorphic_call_context cur = src_val->value;
df0d8136
JH
1536
1537 if (!type_preserved)
1538 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
44210a96
MJ
1539 if (jfunc->type == IPA_JF_ANCESTOR)
1540 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
df0d8136
JH
1541 /* TODO: In cases we know how the context is going to be used,
1542 we can improve the result by passing proper OTR_TYPE. */
1543 cur.combine_with (edge_ctx);
44210a96
MJ
1544 if (!cur.useless_p ())
1545 {
df0d8136
JH
1546 if (src_lat->contains_variable
1547 && !edge_ctx.equal_to (cur))
1548 ret |= dest_lat->set_contains_variable ();
44210a96
MJ
1549 ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
1550 added_sth = true;
1551 }
1552 }
1553
1554 }
1555
1556 prop_fail:
1557 if (!added_sth)
1558 {
1559 if (!edge_ctx.useless_p ())
1560 ret |= dest_lat->add_value (edge_ctx, cs);
1561 else
1562 ret |= dest_lat->set_contains_variable ();
1563 }
1564
1565 return ret;
1566}
1567
04be694e
MJ
1568/* Propagate alignments across jump function JFUNC that is associated with
1569 edge CS and update DEST_LAT accordingly. */
1570
1571static bool
c8710b5c
MJ
1572propagate_alignment_accross_jump_function (cgraph_edge *cs,
1573 ipa_jump_func *jfunc,
1574 ipcp_alignment_lattice *dest_lat)
04be694e 1575{
c8710b5c 1576 if (dest_lat->bottom_p ())
04be694e
MJ
1577 return false;
1578
c8710b5c 1579 if (jfunc->type == IPA_JF_PASS_THROUGH
04be694e
MJ
1580 || jfunc->type == IPA_JF_ANCESTOR)
1581 {
1582 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
04be694e
MJ
1583 HOST_WIDE_INT offset = 0;
1584 int src_idx;
1585
1586 if (jfunc->type == IPA_JF_PASS_THROUGH)
1587 {
1588 enum tree_code op = ipa_get_jf_pass_through_operation (jfunc);
1589 if (op != NOP_EXPR)
1590 {
1591 if (op != POINTER_PLUS_EXPR
81d43c6b 1592 && op != PLUS_EXPR)
c8710b5c 1593 return dest_lat->set_to_bottom ();
04be694e
MJ
1594 tree operand = ipa_get_jf_pass_through_operand (jfunc);
1595 if (!tree_fits_shwi_p (operand))
c8710b5c 1596 return dest_lat->set_to_bottom ();
04be694e
MJ
1597 offset = tree_to_shwi (operand);
1598 }
1599 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1600 }
1601 else
1602 {
1603 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
c8710b5c 1604 offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;
04be694e
MJ
1605 }
1606
c8710b5c 1607 struct ipcp_param_lattices *src_lats;
04be694e 1608 src_lats = ipa_get_parm_lattices (caller_info, src_idx);
c8710b5c 1609 return dest_lat->meet_with (src_lats->alignment, offset);
04be694e 1610 }
c8710b5c 1611 else
04be694e 1612 {
c8710b5c
MJ
1613 if (jfunc->alignment.known)
1614 return dest_lat->meet_with (jfunc->alignment.align,
1615 jfunc->alignment.misalign);
1616 else
1617 return dest_lat->set_to_bottom ();
04be694e 1618 }
04be694e
MJ
1619}
1620
2c9561b5
MJ
1621/* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
1622 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
1623 other cases, return false). If there are no aggregate items, set
1624 aggs_by_ref to NEW_AGGS_BY_REF. */
1625
1626static bool
1627set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats,
1628 bool new_aggs_by_ref)
1629{
1630 if (dest_plats->aggs)
1631 {
1632 if (dest_plats->aggs_by_ref != new_aggs_by_ref)
1633 {
1634 set_agg_lats_to_bottom (dest_plats);
1635 return true;
1636 }
1637 }
1638 else
1639 dest_plats->aggs_by_ref = new_aggs_by_ref;
1640 return false;
1641}
1642
1643/* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
1644 already existing lattice for the given OFFSET and SIZE, marking all skipped
1645 lattices as containing variable and checking for overlaps. If there is no
1646 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
1647 it with offset, size and contains_variable to PRE_EXISTING, and return true,
1648 unless there are too many already. If there are two many, return false. If
1649 there are overlaps turn whole DEST_PLATS to bottom and return false. If any
1650 skipped lattices were newly marked as containing variable, set *CHANGE to
1651 true. */
1652
1653static bool
1654merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
1655 HOST_WIDE_INT offset, HOST_WIDE_INT val_size,
1656 struct ipcp_agg_lattice ***aglat,
1657 bool pre_existing, bool *change)
1658{
1659 gcc_checking_assert (offset >= 0);
1660
1661 while (**aglat && (**aglat)->offset < offset)
1662 {
1663 if ((**aglat)->offset + (**aglat)->size > offset)
1664 {
1665 set_agg_lats_to_bottom (dest_plats);
1666 return false;
1667 }
c0cb5055 1668 *change |= (**aglat)->set_contains_variable ();
2c9561b5
MJ
1669 *aglat = &(**aglat)->next;
1670 }
1671
1672 if (**aglat && (**aglat)->offset == offset)
1673 {
1674 if ((**aglat)->size != val_size
1675 || ((**aglat)->next
1676 && (**aglat)->next->offset < offset + val_size))
1677 {
1678 set_agg_lats_to_bottom (dest_plats);
1679 return false;
1680 }
1681 gcc_checking_assert (!(**aglat)->next
1682 || (**aglat)->next->offset >= offset + val_size);
1683 return true;
1684 }
1685 else
1686 {
1687 struct ipcp_agg_lattice *new_al;
1688
1689 if (**aglat && (**aglat)->offset < offset + val_size)
1690 {
1691 set_agg_lats_to_bottom (dest_plats);
1692 return false;
1693 }
1694 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
1695 return false;
1696 dest_plats->aggs_count++;
2651e637 1697 new_al = ipcp_agg_lattice_pool.allocate ();
2c9561b5
MJ
1698 memset (new_al, 0, sizeof (*new_al));
1699
1700 new_al->offset = offset;
1701 new_al->size = val_size;
1702 new_al->contains_variable = pre_existing;
1703
1704 new_al->next = **aglat;
1705 **aglat = new_al;
1706 return true;
1707 }
1708}
1709
1710/* Set all AGLAT and all other aggregate lattices reachable by next pointers as
1711 containing an unknown value. */
1712
1713static bool
1714set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
1715{
1716 bool ret = false;
1717 while (aglat)
1718 {
c0cb5055 1719 ret |= aglat->set_contains_variable ();
2c9561b5
MJ
1720 aglat = aglat->next;
1721 }
1722 return ret;
1723}
1724
1725/* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
1726 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source
1727 parameter used for lattice value sources. Return true if DEST_PLATS changed
1728 in any way. */
1729
1730static bool
1731merge_aggregate_lattices (struct cgraph_edge *cs,
1732 struct ipcp_param_lattices *dest_plats,
1733 struct ipcp_param_lattices *src_plats,
1734 int src_idx, HOST_WIDE_INT offset_delta)
1735{
1736 bool pre_existing = dest_plats->aggs != NULL;
1737 struct ipcp_agg_lattice **dst_aglat;
1738 bool ret = false;
1739
1740 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref))
1741 return true;
1742 if (src_plats->aggs_bottom)
1743 return set_agg_lats_contain_variable (dest_plats);
3e452a28
MJ
1744 if (src_plats->aggs_contain_variable)
1745 ret |= set_agg_lats_contain_variable (dest_plats);
2c9561b5
MJ
1746 dst_aglat = &dest_plats->aggs;
1747
1748 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs;
1749 src_aglat;
1750 src_aglat = src_aglat->next)
1751 {
1752 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta;
1753
1754 if (new_offset < 0)
1755 continue;
1756 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size,
1757 &dst_aglat, pre_existing, &ret))
1758 {
1759 struct ipcp_agg_lattice *new_al = *dst_aglat;
1760
1761 dst_aglat = &(*dst_aglat)->next;
1762 if (src_aglat->bottom)
1763 {
c0cb5055 1764 ret |= new_al->set_contains_variable ();
2c9561b5
MJ
1765 continue;
1766 }
1767 if (src_aglat->contains_variable)
c0cb5055
MJ
1768 ret |= new_al->set_contains_variable ();
1769 for (ipcp_value<tree> *val = src_aglat->values;
2c9561b5
MJ
1770 val;
1771 val = val->next)
c0cb5055
MJ
1772 ret |= new_al->add_value (val->value, cs, val, src_idx,
1773 src_aglat->offset);
2c9561b5
MJ
1774 }
1775 else if (dest_plats->aggs_bottom)
1776 return true;
1777 }
1778 ret |= set_chain_of_aglats_contains_variable (*dst_aglat);
1779 return ret;
1780}
1781
324e93f1
MJ
1782/* Determine whether there is anything to propagate FROM SRC_PLATS through a
1783 pass-through JFUNC and if so, whether it has conform and conforms to the
1784 rules about propagating values passed by reference. */
1785
1786static bool
1787agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats,
1788 struct ipa_jump_func *jfunc)
1789{
1790 return src_plats->aggs
1791 && (!src_plats->aggs_by_ref
1792 || ipa_get_jf_pass_through_agg_preserved (jfunc));
1793}
1794
2c9561b5
MJ
1795/* Propagate scalar values across jump function JFUNC that is associated with
1796 edge CS and put the values into DEST_LAT. */
1797
1798static bool
1799propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
1800 struct ipa_jump_func *jfunc,
1801 struct ipcp_param_lattices *dest_plats)
1802{
1803 bool ret = false;
1804
1805 if (dest_plats->aggs_bottom)
1806 return false;
1807
1808 if (jfunc->type == IPA_JF_PASS_THROUGH
1809 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
1810 {
1811 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1812 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1813 struct ipcp_param_lattices *src_plats;
1814
1815 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
324e93f1 1816 if (agg_pass_through_permissible_p (src_plats, jfunc))
2c9561b5
MJ
1817 {
1818 /* Currently we do not produce clobber aggregate jump
1819 functions, replace with merging when we do. */
1820 gcc_assert (!jfunc->agg.items);
1821 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats,
1822 src_idx, 0);
1823 }
1824 else
1825 ret |= set_agg_lats_contain_variable (dest_plats);
1826 }
1827 else if (jfunc->type == IPA_JF_ANCESTOR
1828 && ipa_get_jf_ancestor_agg_preserved (jfunc))
1829 {
1830 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
1831 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
1832 struct ipcp_param_lattices *src_plats;
1833
1834 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
1835 if (src_plats->aggs && src_plats->aggs_by_ref)
1836 {
1837 /* Currently we do not produce clobber aggregate jump
1838 functions, replace with merging when we do. */
1839 gcc_assert (!jfunc->agg.items);
1840 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx,
1841 ipa_get_jf_ancestor_offset (jfunc));
1842 }
1843 else if (!src_plats->aggs_by_ref)
1844 ret |= set_agg_lats_to_bottom (dest_plats);
1845 else
1846 ret |= set_agg_lats_contain_variable (dest_plats);
1847 }
1848 else if (jfunc->agg.items)
1849 {
1850 bool pre_existing = dest_plats->aggs != NULL;
1851 struct ipcp_agg_lattice **aglat = &dest_plats->aggs;
1852 struct ipa_agg_jf_item *item;
1853 int i;
1854
1855 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref))
1856 return true;
1857
9771b263 1858 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
2c9561b5
MJ
1859 {
1860 HOST_WIDE_INT val_size;
1861
1862 if (item->offset < 0)
1863 continue;
1864 gcc_checking_assert (is_gimple_ip_invariant (item->value));
ae7e9ddd 1865 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
2c9561b5
MJ
1866
1867 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1868 &aglat, pre_existing, &ret))
1869 {
c0cb5055 1870 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
2c9561b5
MJ
1871 aglat = &(*aglat)->next;
1872 }
1873 else if (dest_plats->aggs_bottom)
1874 return true;
1875 }
1876
1877 ret |= set_chain_of_aglats_contains_variable (*aglat);
1878 }
1879 else
1880 ret |= set_agg_lats_contain_variable (dest_plats);
1881
1882 return ret;
1883}
1884
310bc633
MJ
1885/* Propagate constants from the caller to the callee of CS. INFO describes the
1886 caller. */
1887
1888static bool
1889propagate_constants_accross_call (struct cgraph_edge *cs)
1890{
1891 struct ipa_node_params *callee_info;
1892 enum availability availability;
1893 struct cgraph_node *callee, *alias_or_thunk;
1894 struct ipa_edge_args *args;
1895 bool ret = false;
d7da5cc8 1896 int i, args_count, parms_count;
310bc633 1897
d52f5295 1898 callee = cs->callee->function_symbol (&availability);
67348ccc 1899 if (!callee->definition)
310bc633 1900 return false;
d52f5295 1901 gcc_checking_assert (callee->has_gimple_body_p ());
310bc633 1902 callee_info = IPA_NODE_REF (callee);
310bc633
MJ
1903
1904 args = IPA_EDGE_REF (cs);
d7da5cc8
MJ
1905 args_count = ipa_get_cs_argument_count (args);
1906 parms_count = ipa_get_param_count (callee_info);
f3fec19f
MJ
1907 if (parms_count == 0)
1908 return false;
310bc633 1909
d5e254e1
IE
1910 /* No propagation through instrumentation thunks is available yet.
1911 It should be possible with proper mapping of call args and
1912 instrumented callee params in the propagation loop below. But
1913 this case mostly occurs when legacy code calls instrumented code
1914 and it is not a primary target for optimizations.
1915 We detect instrumentation thunks in aliases and thunks chain by
1916 checking instrumentation_clone flag for chain source and target.
1917 Going through instrumentation thunks we always have it changed
1918 from 0 to 1 and all other nodes do not change it. */
1919 if (!cs->callee->instrumentation_clone
1920 && callee->instrumentation_clone)
1921 {
1922 for (i = 0; i < parms_count; i++)
1923 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1924 i));
1925 return ret;
1926 }
1927
310bc633
MJ
1928 /* If this call goes through a thunk we must not propagate to the first (0th)
1929 parameter. However, we might need to uncover a thunk from below a series
1930 of aliases first. */
1931 alias_or_thunk = cs->callee;
67348ccc 1932 while (alias_or_thunk->alias)
d52f5295 1933 alias_or_thunk = alias_or_thunk->get_alias_target ();
310bc633
MJ
1934 if (alias_or_thunk->thunk.thunk_p)
1935 {
2c9561b5
MJ
1936 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1937 0));
310bc633
MJ
1938 i = 1;
1939 }
1940 else
1941 i = 0;
1942
d7da5cc8 1943 for (; (i < args_count) && (i < parms_count); i++)
310bc633
MJ
1944 {
1945 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
2c9561b5 1946 struct ipcp_param_lattices *dest_plats;
310bc633 1947
2c9561b5 1948 dest_plats = ipa_get_parm_lattices (callee_info, i);
d52f5295 1949 if (availability == AVAIL_INTERPOSABLE)
2c9561b5 1950 ret |= set_all_contains_variable (dest_plats);
310bc633 1951 else
2c9561b5
MJ
1952 {
1953 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1954 &dest_plats->itself);
44210a96
MJ
1955 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
1956 &dest_plats->ctxlat);
04be694e 1957 ret |= propagate_alignment_accross_jump_function (cs, jump_func,
c8710b5c 1958 &dest_plats->alignment);
2c9561b5
MJ
1959 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1960 dest_plats);
1961 }
310bc633 1962 }
d7da5cc8 1963 for (; i < parms_count; i++)
2c9561b5 1964 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
d7da5cc8 1965
310bc633
MJ
1966 return ret;
1967}
1968
1969/* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
3b97a5c7
MJ
1970 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
1971 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
310bc633 1972
162712de
MJ
1973static tree
1974ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
44210a96
MJ
1975 vec<tree> known_csts,
1976 vec<ipa_polymorphic_call_context> known_contexts,
162712de 1977 vec<ipa_agg_jump_function_p> known_aggs,
231b4916
JH
1978 struct ipa_agg_replacement_value *agg_reps,
1979 bool *speculative)
310bc633
MJ
1980{
1981 int param_index = ie->indirect_info->param_index;
44210a96 1982 HOST_WIDE_INT anc_offset;
310bc633 1983 tree t;
85942f45 1984 tree target = NULL;
310bc633 1985
231b4916
JH
1986 *speculative = false;
1987
97756c0e 1988 if (param_index == -1
44210a96 1989 || known_csts.length () <= (unsigned int) param_index)
310bc633
MJ
1990 return NULL_TREE;
1991
1992 if (!ie->indirect_info->polymorphic)
1993 {
8810cc52
MJ
1994 tree t;
1995
1996 if (ie->indirect_info->agg_contents)
1997 {
162712de
MJ
1998 if (agg_reps)
1999 {
2000 t = NULL;
2001 while (agg_reps)
2002 {
2003 if (agg_reps->index == param_index
7b920a9a
MJ
2004 && agg_reps->offset == ie->indirect_info->offset
2005 && agg_reps->by_ref == ie->indirect_info->by_ref)
162712de
MJ
2006 {
2007 t = agg_reps->value;
2008 break;
2009 }
2010 agg_reps = agg_reps->next;
2011 }
2012 }
2013 else if (known_aggs.length () > (unsigned int) param_index)
8810cc52
MJ
2014 {
2015 struct ipa_agg_jump_function *agg;
9771b263 2016 agg = known_aggs[param_index];
8810cc52
MJ
2017 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
2018 ie->indirect_info->by_ref);
2019 }
2020 else
2021 t = NULL;
2022 }
2023 else
44210a96 2024 t = known_csts[param_index];
8810cc52 2025
310bc633
MJ
2026 if (t &&
2027 TREE_CODE (t) == ADDR_EXPR
2028 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
81fa35bd 2029 return TREE_OPERAND (t, 0);
310bc633
MJ
2030 else
2031 return NULL_TREE;
2032 }
2033
2bf86c84 2034 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
85942f45
JH
2035 return NULL_TREE;
2036
8810cc52 2037 gcc_assert (!ie->indirect_info->agg_contents);
8b7773a4 2038 anc_offset = ie->indirect_info->offset;
310bc633 2039
85942f45
JH
2040 t = NULL;
2041
2042 /* Try to work out value of virtual table pointer value in replacemnets. */
231b4916 2043 if (!t && agg_reps && !ie->indirect_info->by_ref)
85942f45
JH
2044 {
2045 while (agg_reps)
2046 {
2047 if (agg_reps->index == param_index
2048 && agg_reps->offset == ie->indirect_info->offset
2049 && agg_reps->by_ref)
2050 {
2051 t = agg_reps->value;
2052 break;
2053 }
2054 agg_reps = agg_reps->next;
2055 }
2056 }
2057
2058 /* Try to work out value of virtual table pointer value in known
2059 aggregate values. */
2060 if (!t && known_aggs.length () > (unsigned int) param_index
231b4916 2061 && !ie->indirect_info->by_ref)
85942f45
JH
2062 {
2063 struct ipa_agg_jump_function *agg;
2064 agg = known_aggs[param_index];
2065 t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
2066 true);
2067 }
2068
9de2f554 2069 /* If we found the virtual table pointer, lookup the target. */
85942f45 2070 if (t)
9de2f554
JH
2071 {
2072 tree vtable;
2073 unsigned HOST_WIDE_INT offset;
2074 if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
2075 {
2076 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
2077 vtable, offset);
8472fa80 2078 if (target)
9de2f554 2079 {
8472fa80
MT
2080 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
2081 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
2082 || !possible_polymorphic_call_target_p
d52f5295 2083 (ie, cgraph_node::get (target)))
72972c22 2084 target = ipa_impossible_devirt_target (ie, target);
231b4916
JH
2085 *speculative = ie->indirect_info->vptr_changed;
2086 if (!*speculative)
2087 return target;
9de2f554 2088 }
9de2f554
JH
2089 }
2090 }
85942f45 2091
44210a96 2092 /* Do we know the constant value of pointer? */
85942f45 2093 if (!t)
44210a96 2094 t = known_csts[param_index];
310bc633 2095
44210a96
MJ
2096 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO);
2097
2098 ipa_polymorphic_call_context context;
2099 if (known_contexts.length () > (unsigned int) param_index)
310bc633 2100 {
44210a96 2101 context = known_contexts[param_index];
df0d8136
JH
2102 context.offset_by (anc_offset);
2103 if (ie->indirect_info->vptr_changed)
2104 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2105 ie->indirect_info->otr_type);
44210a96
MJ
2106 if (t)
2107 {
2108 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
2109 (t, ie->indirect_info->otr_type, anc_offset);
2110 if (!ctx2.useless_p ())
2111 context.combine_with (ctx2, ie->indirect_info->otr_type);
2112 }
310bc633 2113 }
44210a96 2114 else if (t)
33c3b6be
JH
2115 {
2116 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type,
2117 anc_offset);
2118 if (ie->indirect_info->vptr_changed)
2119 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
2120 ie->indirect_info->otr_type);
2121 }
310bc633 2122 else
44210a96 2123 return NULL_TREE;
310bc633 2124
44210a96
MJ
2125 vec <cgraph_node *>targets;
2126 bool final;
2127
2128 targets = possible_polymorphic_call_targets
2129 (ie->indirect_info->otr_type,
2130 ie->indirect_info->otr_token,
2131 context, &final);
2132 if (!final || targets.length () > 1)
231b4916
JH
2133 {
2134 struct cgraph_node *node;
2135 if (*speculative)
2136 return target;
2bf86c84
JH
2137 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2138 || ie->speculative || !ie->maybe_hot_p ())
231b4916
JH
2139 return NULL;
2140 node = try_speculative_devirtualization (ie->indirect_info->otr_type,
2141 ie->indirect_info->otr_token,
2142 context);
2143 if (node)
2144 {
2145 *speculative = true;
2146 target = node->decl;
2147 }
2148 else
2149 return NULL;
2150 }
44210a96 2151 else
231b4916
JH
2152 {
2153 *speculative = false;
2154 if (targets.length () == 1)
2155 target = targets[0]->decl;
2156 else
2157 target = ipa_impossible_devirt_target (ie, NULL_TREE);
2158 }
b5165eb0
MJ
2159
2160 if (target && !possible_polymorphic_call_target_p (ie,
d52f5295 2161 cgraph_node::get (target)))
72972c22 2162 target = ipa_impossible_devirt_target (ie, target);
450ad0cd
JH
2163
2164 return target;
310bc633
MJ
2165}
2166
162712de 2167
44210a96
MJ
2168/* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS,
2169 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL)
2170 return the destination. */
162712de
MJ
2171
2172tree
2173ipa_get_indirect_edge_target (struct cgraph_edge *ie,
44210a96
MJ
2174 vec<tree> known_csts,
2175 vec<ipa_polymorphic_call_context> known_contexts,
231b4916
JH
2176 vec<ipa_agg_jump_function_p> known_aggs,
2177 bool *speculative)
162712de 2178{
44210a96 2179 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
231b4916 2180 known_aggs, NULL, speculative);
162712de
MJ
2181}
2182
310bc633 2183/* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
44210a96 2184 and KNOWN_CONTEXTS. */
310bc633
MJ
2185
2186static int
2187devirtualization_time_bonus (struct cgraph_node *node,
9771b263 2188 vec<tree> known_csts,
44210a96 2189 vec<ipa_polymorphic_call_context> known_contexts,
162712de 2190 vec<ipa_agg_jump_function_p> known_aggs)
310bc633
MJ
2191{
2192 struct cgraph_edge *ie;
2193 int res = 0;
2194
2195 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
2196 {
2197 struct cgraph_node *callee;
2198 struct inline_summary *isummary;
8ad274d2 2199 enum availability avail;
81fa35bd 2200 tree target;
231b4916 2201 bool speculative;
310bc633 2202
44210a96 2203 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
231b4916 2204 known_aggs, &speculative);
310bc633
MJ
2205 if (!target)
2206 continue;
2207
2208 /* Only bare minimum benefit for clearly un-inlineable targets. */
2209 res += 1;
d52f5295 2210 callee = cgraph_node::get (target);
67348ccc 2211 if (!callee || !callee->definition)
310bc633 2212 continue;
d52f5295 2213 callee = callee->function_symbol (&avail);
8ad274d2
JH
2214 if (avail < AVAIL_AVAILABLE)
2215 continue;
9a1e784a 2216 isummary = inline_summaries->get (callee);
310bc633
MJ
2217 if (!isummary->inlinable)
2218 continue;
2219
2220 /* FIXME: The values below need re-considering and perhaps also
2221 integrating into the cost metrics, at lest in some very basic way. */
2222 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
231b4916 2223 res += 31 / ((int)speculative + 1);
310bc633 2224 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
231b4916 2225 res += 15 / ((int)speculative + 1);
310bc633 2226 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
67348ccc 2227 || DECL_DECLARED_INLINE_P (callee->decl))
231b4916 2228 res += 7 / ((int)speculative + 1);
310bc633
MJ
2229 }
2230
2231 return res;
2232}
2233
2c9561b5
MJ
2234/* Return time bonus incurred because of HINTS. */
2235
2236static int
2237hint_time_bonus (inline_hints hints)
2238{
19321415 2239 int result = 0;
2c9561b5 2240 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
19321415
MJ
2241 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
2242 if (hints & INLINE_HINT_array_index)
2243 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
2244 return result;
2c9561b5
MJ
2245}
2246
af21714c
MJ
2247/* If there is a reason to penalize the function described by INFO in the
2248 cloning goodness evaluation, do so. */
2249
2250static inline int64_t
2251incorporate_penalties (ipa_node_params *info, int64_t evaluation)
2252{
2253 if (info->node_within_scc)
2254 evaluation = (evaluation
2255 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
2256
2257 if (info->node_calling_single_call)
2258 evaluation = (evaluation
2259 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
2260 / 100;
2261
2262 return evaluation;
2263}
2264
310bc633
MJ
2265/* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT
2266 and SIZE_COST and with the sum of frequencies of incoming edges to the
2267 potential new clone in FREQUENCIES. */
2268
2269static bool
2270good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
2271 int freq_sum, gcov_type count_sum, int size_cost)
2272{
2273 if (time_benefit == 0
2bf86c84 2274 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
67348ccc 2275 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
310bc633
MJ
2276 return false;
2277
df0227c4 2278 gcc_assert (size_cost > 0);
310bc633 2279
af21714c 2280 struct ipa_node_params *info = IPA_NODE_REF (node);
310bc633
MJ
2281 if (max_count)
2282 {
df0227c4 2283 int factor = (count_sum * 1000) / max_count;
a9243bfc 2284 int64_t evaluation = (((int64_t) time_benefit * factor)
df0227c4 2285 / size_cost);
af21714c 2286 evaluation = incorporate_penalties (info, evaluation);
310bc633
MJ
2287
2288 if (dump_file && (dump_flags & TDF_DETAILS))
2289 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
2290 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
16998094 2291 "%s%s) -> evaluation: " "%" PRId64
df0227c4 2292 ", threshold: %i\n",
310bc633 2293 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
af21714c
MJ
2294 info->node_within_scc ? ", scc" : "",
2295 info->node_calling_single_call ? ", single_call" : "",
7a92038b 2296 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
310bc633
MJ
2297
2298 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2299 }
2300 else
2301 {
a9243bfc 2302 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
df0227c4 2303 / size_cost);
af21714c 2304 evaluation = incorporate_penalties (info, evaluation);
310bc633
MJ
2305
2306 if (dump_file && (dump_flags & TDF_DETAILS))
2307 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
af21714c 2308 "size: %i, freq_sum: %i%s%s) -> evaluation: "
16998094 2309 "%" PRId64 ", threshold: %i\n",
af21714c
MJ
2310 time_benefit, size_cost, freq_sum,
2311 info->node_within_scc ? ", scc" : "",
2312 info->node_calling_single_call ? ", single_call" : "",
2313 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
310bc633
MJ
2314
2315 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2316 }
2317}
2318
2c9561b5
MJ
2319/* Return all context independent values from aggregate lattices in PLATS in a
2320 vector. Return NULL if there are none. */
2321
84562394 2322static vec<ipa_agg_jf_item, va_gc> *
2c9561b5
MJ
2323context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2324{
84562394 2325 vec<ipa_agg_jf_item, va_gc> *res = NULL;
2c9561b5
MJ
2326
2327 if (plats->aggs_bottom
2328 || plats->aggs_contain_variable
2329 || plats->aggs_count == 0)
2330 return NULL;
2331
2332 for (struct ipcp_agg_lattice *aglat = plats->aggs;
2333 aglat;
2334 aglat = aglat->next)
c0cb5055 2335 if (aglat->is_single_const ())
2c9561b5
MJ
2336 {
2337 struct ipa_agg_jf_item item;
2338 item.offset = aglat->offset;
2339 item.value = aglat->values->value;
9771b263 2340 vec_safe_push (res, item);
2c9561b5
MJ
2341 }
2342 return res;
2343}
310bc633 2344
44210a96
MJ
2345/* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and
2346 populate them with values of parameters that are known independent of the
2347 context. INFO describes the function. If REMOVABLE_PARAMS_COST is
2348 non-NULL, the movement cost of all removable parameters will be stored in
2349 it. */
310bc633
MJ
2350
2351static bool
2352gather_context_independent_values (struct ipa_node_params *info,
44210a96
MJ
2353 vec<tree> *known_csts,
2354 vec<ipa_polymorphic_call_context>
2355 *known_contexts,
2356 vec<ipa_agg_jump_function> *known_aggs,
2357 int *removable_params_cost)
310bc633
MJ
2358{
2359 int i, count = ipa_get_param_count (info);
2360 bool ret = false;
2361
9771b263 2362 known_csts->create (0);
44210a96 2363 known_contexts->create (0);
9771b263 2364 known_csts->safe_grow_cleared (count);
44210a96 2365 known_contexts->safe_grow_cleared (count);
2c9561b5
MJ
2366 if (known_aggs)
2367 {
9771b263
DN
2368 known_aggs->create (0);
2369 known_aggs->safe_grow_cleared (count);
2c9561b5 2370 }
310bc633
MJ
2371
2372 if (removable_params_cost)
2373 *removable_params_cost = 0;
2374
2375 for (i = 0; i < count ; i++)
2376 {
2c9561b5 2377 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
c0cb5055 2378 ipcp_lattice<tree> *lat = &plats->itself;
310bc633 2379
c0cb5055 2380 if (lat->is_single_const ())
310bc633 2381 {
c0cb5055 2382 ipcp_value<tree> *val = lat->values;
44210a96
MJ
2383 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2384 (*known_csts)[i] = val->value;
2385 if (removable_params_cost)
2386 *removable_params_cost
2387 += estimate_move_cost (TREE_TYPE (val->value), false);
2388 ret = true;
310bc633
MJ
2389 }
2390 else if (removable_params_cost
2391 && !ipa_is_param_used (info, i))
2392 *removable_params_cost
0e8853ee 2393 += ipa_get_param_move_cost (info, i);
2c9561b5 2394
44210a96
MJ
2395 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2396 if (ctxlat->is_single_const ())
2397 {
2398 (*known_contexts)[i] = ctxlat->values->value;
2399 ret = true;
2400 }
2401
2c9561b5
MJ
2402 if (known_aggs)
2403 {
84562394 2404 vec<ipa_agg_jf_item, va_gc> *agg_items;
2c9561b5
MJ
2405 struct ipa_agg_jump_function *ajf;
2406
2407 agg_items = context_independent_aggregate_values (plats);
9771b263 2408 ajf = &(*known_aggs)[i];
2c9561b5
MJ
2409 ajf->items = agg_items;
2410 ajf->by_ref = plats->aggs_by_ref;
2411 ret |= agg_items != NULL;
2412 }
310bc633
MJ
2413 }
2414
2415 return ret;
2416}
2417
2c9561b5
MJ
2418/* The current interface in ipa-inline-analysis requires a pointer vector.
2419 Create it.
2420
2421 FIXME: That interface should be re-worked, this is slightly silly. Still,
2422 I'd like to discuss how to change it first and this demonstrates the
2423 issue. */
2424
9771b263 2425static vec<ipa_agg_jump_function_p>
84562394 2426agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
2c9561b5 2427{
9771b263 2428 vec<ipa_agg_jump_function_p> ret;
2c9561b5
MJ
2429 struct ipa_agg_jump_function *ajf;
2430 int i;
2431
9771b263
DN
2432 ret.create (known_aggs.length ());
2433 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2434 ret.quick_push (ajf);
2c9561b5
MJ
2435 return ret;
2436}
2437
c0cb5055 2438/* Perform time and size measurement of NODE with the context given in
44210a96 2439 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
c0cb5055
MJ
2440 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
2441 all context-independent removable parameters and EST_MOVE_COST of estimated
2442 movement of the considered parameter and store it into VAL. */
2443
2444static void
2445perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
44210a96 2446 vec<ipa_polymorphic_call_context> known_contexts,
c0cb5055
MJ
2447 vec<ipa_agg_jump_function_p> known_aggs_ptrs,
2448 int base_time, int removable_params_cost,
2449 int est_move_cost, ipcp_value_base *val)
2450{
2451 int time, size, time_benefit;
2452 inline_hints hints;
2453
44210a96 2454 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
c0cb5055
MJ
2455 known_aggs_ptrs, &size, &time,
2456 &hints);
2457 time_benefit = base_time - time
44210a96 2458 + devirtualization_time_bonus (node, known_csts, known_contexts,
c0cb5055
MJ
2459 known_aggs_ptrs)
2460 + hint_time_bonus (hints)
2461 + removable_params_cost + est_move_cost;
2462
2463 gcc_checking_assert (size >=0);
2464 /* The inliner-heuristics based estimates may think that in certain
2465 contexts some functions do not have any size at all but we want
2466 all specializations to have at least a tiny cost, not least not to
2467 divide by zero. */
2468 if (size == 0)
2469 size = 1;
2470
2471 val->local_time_benefit = time_benefit;
2472 val->local_size_cost = size;
2473}
2474
310bc633
MJ
2475/* Iterate over known values of parameters of NODE and estimate the local
2476 effects in terms of time and size they have. */
2477
2478static void
2479estimate_local_effects (struct cgraph_node *node)
2480{
2481 struct ipa_node_params *info = IPA_NODE_REF (node);
2482 int i, count = ipa_get_param_count (info);
44210a96
MJ
2483 vec<tree> known_csts;
2484 vec<ipa_polymorphic_call_context> known_contexts;
84562394 2485 vec<ipa_agg_jump_function> known_aggs;
9771b263 2486 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
310bc633 2487 bool always_const;
9a1e784a 2488 int base_time = inline_summaries->get (node)->time;
310bc633
MJ
2489 int removable_params_cost;
2490
2491 if (!count || !ipcp_versionable_function_p (node))
2492 return;
2493
ca30a539 2494 if (dump_file && (dump_flags & TDF_DETAILS))
310bc633 2495 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
fec39fa6 2496 node->name (), node->order, base_time);
310bc633
MJ
2497
2498 always_const = gather_context_independent_values (info, &known_csts,
44210a96 2499 &known_contexts, &known_aggs,
310bc633 2500 &removable_params_cost);
2c9561b5 2501 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
310bc633 2502 if (always_const)
ca30a539 2503 {
310bc633 2504 struct caller_statistics stats;
2c9561b5 2505 inline_hints hints;
310bc633
MJ
2506 int time, size;
2507
2508 init_caller_stats (&stats);
d52f5295
ML
2509 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2510 false);
44210a96 2511 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
2c9561b5 2512 known_aggs_ptrs, &size, &time, &hints);
44210a96 2513 time -= devirtualization_time_bonus (node, known_csts, known_contexts,
162712de 2514 known_aggs_ptrs);
2c9561b5 2515 time -= hint_time_bonus (hints);
310bc633
MJ
2516 time -= removable_params_cost;
2517 size -= stats.n_calls * removable_params_cost;
2518
2519 if (dump_file)
2520 fprintf (dump_file, " - context independent values, size: %i, "
2521 "time_benefit: %i\n", size, base_time - time);
2522
2523 if (size <= 0
d52f5295 2524 || node->will_be_removed_from_program_if_no_direct_calls_p ())
310bc633 2525 {
eb20b778 2526 info->do_clone_for_all_contexts = true;
310bc633
MJ
2527 base_time = time;
2528
2529 if (dump_file)
2530 fprintf (dump_file, " Decided to specialize for all "
2531 "known contexts, code not going to grow.\n");
2532 }
2533 else if (good_cloning_opportunity_p (node, base_time - time,
2534 stats.freq_sum, stats.count_sum,
2535 size))
2536 {
2537 if (size + overall_size <= max_new_size)
2538 {
eb20b778 2539 info->do_clone_for_all_contexts = true;
310bc633
MJ
2540 base_time = time;
2541 overall_size += size;
2542
2543 if (dump_file)
2544 fprintf (dump_file, " Decided to specialize for all "
2545 "known contexts, growth deemed beneficial.\n");
2546 }
2547 else if (dump_file && (dump_flags & TDF_DETAILS))
2548 fprintf (dump_file, " Not cloning for all contexts because "
2549 "max_new_size would be reached with %li.\n",
2550 size + overall_size);
2551 }
ca30a539
JH
2552 }
2553
310bc633 2554 for (i = 0; i < count ; i++)
ca30a539 2555 {
2c9561b5 2556 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
c0cb5055
MJ
2557 ipcp_lattice<tree> *lat = &plats->itself;
2558 ipcp_value<tree> *val;
310bc633
MJ
2559
2560 if (lat->bottom
2561 || !lat->values
44210a96 2562 || known_csts[i])
310bc633
MJ
2563 continue;
2564
2565 for (val = lat->values; val; val = val->next)
2566 {
44210a96
MJ
2567 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2568 known_csts[i] = val->value;
310bc633 2569
44210a96
MJ
2570 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2571 perform_estimation_of_a_value (node, known_csts, known_contexts,
c0cb5055
MJ
2572 known_aggs_ptrs, base_time,
2573 removable_params_cost, emc, val);
0318fc77 2574
310bc633
MJ
2575 if (dump_file && (dump_flags & TDF_DETAILS))
2576 {
2577 fprintf (dump_file, " - estimates for value ");
2578 print_ipcp_constant_value (dump_file, val->value);
0e8853ee
JH
2579 fprintf (dump_file, " for ");
2580 ipa_dump_param (dump_file, info, i);
310bc633 2581 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
c0cb5055 2582 val->local_time_benefit, val->local_size_cost);
310bc633 2583 }
310bc633 2584 }
9771b263 2585 known_csts[i] = NULL_TREE;
2c9561b5
MJ
2586 }
2587
44210a96
MJ
2588 for (i = 0; i < count; i++)
2589 {
2590 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2591
2592 if (!plats->virt_call)
2593 continue;
2594
2595 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2596 ipcp_value<ipa_polymorphic_call_context> *val;
2597
2598 if (ctxlat->bottom
2599 || !ctxlat->values
2600 || !known_contexts[i].useless_p ())
2601 continue;
2602
2603 for (val = ctxlat->values; val; val = val->next)
2604 {
2605 known_contexts[i] = val->value;
2606 perform_estimation_of_a_value (node, known_csts, known_contexts,
2607 known_aggs_ptrs, base_time,
2608 removable_params_cost, 0, val);
2609
2610 if (dump_file && (dump_flags & TDF_DETAILS))
2611 {
2612 fprintf (dump_file, " - estimates for polymorphic context ");
2613 print_ipcp_constant_value (dump_file, val->value);
2614 fprintf (dump_file, " for ");
2615 ipa_dump_param (dump_file, info, i);
2616 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
2617 val->local_time_benefit, val->local_size_cost);
2618 }
2619 }
2620 known_contexts[i] = ipa_polymorphic_call_context ();
2621 }
2622
2c9561b5
MJ
2623 for (i = 0; i < count ; i++)
2624 {
2625 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
2626 struct ipa_agg_jump_function *ajf;
2627 struct ipcp_agg_lattice *aglat;
2628
2629 if (plats->aggs_bottom || !plats->aggs)
2630 continue;
2631
9771b263 2632 ajf = &known_aggs[i];
2c9561b5
MJ
2633 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2634 {
c0cb5055 2635 ipcp_value<tree> *val;
2c9561b5
MJ
2636 if (aglat->bottom || !aglat->values
2637 /* If the following is true, the one value is in known_aggs. */
2638 || (!plats->aggs_contain_variable
c0cb5055 2639 && aglat->is_single_const ()))
2c9561b5
MJ
2640 continue;
2641
2642 for (val = aglat->values; val; val = val->next)
2643 {
2c9561b5 2644 struct ipa_agg_jf_item item;
2c9561b5
MJ
2645
2646 item.offset = aglat->offset;
2647 item.value = val->value;
9771b263 2648 vec_safe_push (ajf->items, item);
2c9561b5 2649
44210a96 2650 perform_estimation_of_a_value (node, known_csts, known_contexts,
c0cb5055
MJ
2651 known_aggs_ptrs, base_time,
2652 removable_params_cost, 0, val);
2c9561b5
MJ
2653
2654 if (dump_file && (dump_flags & TDF_DETAILS))
2655 {
2656 fprintf (dump_file, " - estimates for value ");
2657 print_ipcp_constant_value (dump_file, val->value);
0e8853ee
JH
2658 fprintf (dump_file, " for ");
2659 ipa_dump_param (dump_file, info, i);
2c9561b5 2660 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
c0cb5055
MJ
2661 "]: time_benefit: %i, size: %i\n",
2662 plats->aggs_by_ref ? "ref " : "",
2663 aglat->offset,
2664 val->local_time_benefit, val->local_size_cost);
2c9561b5
MJ
2665 }
2666
9771b263 2667 ajf->items->pop ();
2c9561b5
MJ
2668 }
2669 }
2670 }
2671
2672 for (i = 0; i < count ; i++)
9771b263 2673 vec_free (known_aggs[i].items);
310bc633 2674
9771b263 2675 known_csts.release ();
44210a96 2676 known_contexts.release ();
9771b263
DN
2677 known_aggs.release ();
2678 known_aggs_ptrs.release ();
310bc633
MJ
2679}
2680
2681
2682/* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
2683 topological sort of values. */
2684
c0cb5055
MJ
2685template <typename valtype>
2686void
2687value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
310bc633 2688{
c0cb5055 2689 ipcp_value_source<valtype> *src;
310bc633
MJ
2690
2691 if (cur_val->dfs)
2692 return;
2693
2694 dfs_counter++;
2695 cur_val->dfs = dfs_counter;
2696 cur_val->low_link = dfs_counter;
2697
2698 cur_val->topo_next = stack;
2699 stack = cur_val;
2700 cur_val->on_stack = true;
2701
2702 for (src = cur_val->sources; src; src = src->next)
2703 if (src->val)
2704 {
2705 if (src->val->dfs == 0)
2706 {
c0cb5055 2707 add_val (src->val);
310bc633
MJ
2708 if (src->val->low_link < cur_val->low_link)
2709 cur_val->low_link = src->val->low_link;
2710 }
2711 else if (src->val->on_stack
2712 && src->val->dfs < cur_val->low_link)
2713 cur_val->low_link = src->val->dfs;
2714 }
2715
2716 if (cur_val->dfs == cur_val->low_link)
ca30a539 2717 {
c0cb5055 2718 ipcp_value<valtype> *v, *scc_list = NULL;
310bc633
MJ
2719
2720 do
2721 {
2722 v = stack;
2723 stack = v->topo_next;
2724 v->on_stack = false;
2725
2726 v->scc_next = scc_list;
2727 scc_list = v;
2728 }
2729 while (v != cur_val);
2730
2731 cur_val->topo_next = values_topo;
2732 values_topo = cur_val;
ca30a539 2733 }
518dc859
RL
2734}
2735
310bc633
MJ
2736/* Add all values in lattices associated with NODE to the topological sort if
2737 they are not there yet. */
2738
2739static void
c0cb5055 2740add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
518dc859 2741{
310bc633
MJ
2742 struct ipa_node_params *info = IPA_NODE_REF (node);
2743 int i, count = ipa_get_param_count (info);
2744
2745 for (i = 0; i < count ; i++)
2746 {
2c9561b5 2747 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
c0cb5055 2748 ipcp_lattice<tree> *lat = &plats->itself;
2c9561b5 2749 struct ipcp_agg_lattice *aglat;
310bc633 2750
2c9561b5 2751 if (!lat->bottom)
44210a96
MJ
2752 {
2753 ipcp_value<tree> *val;
2754 for (val = lat->values; val; val = val->next)
2755 topo->constants.add_val (val);
2756 }
2c9561b5
MJ
2757
2758 if (!plats->aggs_bottom)
2759 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2760 if (!aglat->bottom)
44210a96
MJ
2761 {
2762 ipcp_value<tree> *val;
2763 for (val = aglat->values; val; val = val->next)
2764 topo->constants.add_val (val);
2765 }
2766
2767 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2768 if (!ctxlat->bottom)
2769 {
2770 ipcp_value<ipa_polymorphic_call_context> *ctxval;
2771 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next)
2772 topo->contexts.add_val (ctxval);
2773 }
310bc633 2774 }
518dc859
RL
2775}
2776
310bc633
MJ
2777/* One pass of constants propagation along the call graph edges, from callers
2778 to callees (requires topological ordering in TOPO), iterate over strongly
2779 connected components. */
2780
518dc859 2781static void
11478306 2782propagate_constants_topo (struct ipa_topo_info *topo)
518dc859 2783{
310bc633 2784 int i;
518dc859 2785
310bc633 2786 for (i = topo->nnodes - 1; i >= 0; i--)
518dc859 2787 {
39e87baf 2788 unsigned j;
310bc633 2789 struct cgraph_node *v, *node = topo->order[i];
d52f5295 2790 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
310bc633 2791
310bc633
MJ
2792 /* First, iteratively propagate within the strongly connected component
2793 until all lattices stabilize. */
39e87baf 2794 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
d52f5295 2795 if (v->has_gimple_body_p ())
310bc633 2796 push_node_to_stack (topo, v);
310bc633 2797
39e87baf 2798 v = pop_node_from_stack (topo);
310bc633
MJ
2799 while (v)
2800 {
2801 struct cgraph_edge *cs;
2802
2803 for (cs = v->callees; cs; cs = cs->next_callee)
af21714c
MJ
2804 if (ipa_edge_within_scc (cs))
2805 {
2806 IPA_NODE_REF (v)->node_within_scc = true;
2807 if (propagate_constants_accross_call (cs))
2808 push_node_to_stack (topo, cs->callee->function_symbol ());
2809 }
310bc633
MJ
2810 v = pop_node_from_stack (topo);
2811 }
2812
2813 /* Afterwards, propagate along edges leading out of the SCC, calculates
2814 the local effects of the discovered constants and all valid values to
2815 their topological sort. */
39e87baf 2816 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
d52f5295 2817 if (v->has_gimple_body_p ())
39e87baf
MJ
2818 {
2819 struct cgraph_edge *cs;
310bc633 2820
39e87baf 2821 estimate_local_effects (v);
c0cb5055 2822 add_all_node_vals_to_toposort (v, topo);
39e87baf 2823 for (cs = v->callees; cs; cs = cs->next_callee)
4cb13597 2824 if (!ipa_edge_within_scc (cs))
39e87baf
MJ
2825 propagate_constants_accross_call (cs);
2826 }
2827 cycle_nodes.release ();
518dc859
RL
2828 }
2829}
2830
df0227c4
MJ
2831
2832/* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
2833 the bigger one if otherwise. */
2834
2835static int
2836safe_add (int a, int b)
2837{
2838 if (a > INT_MAX/2 || b > INT_MAX/2)
2839 return a > b ? a : b;
2840 else
2841 return a + b;
2842}
2843
2844
310bc633 2845/* Propagate the estimated effects of individual values along the topological
073a8998 2846 from the dependent values to those they depend on. */
310bc633 2847
c0cb5055
MJ
2848template <typename valtype>
2849void
2850value_topo_info<valtype>::propagate_effects ()
518dc859 2851{
c0cb5055 2852 ipcp_value<valtype> *base;
518dc859 2853
310bc633 2854 for (base = values_topo; base; base = base->topo_next)
518dc859 2855 {
c0cb5055
MJ
2856 ipcp_value_source<valtype> *src;
2857 ipcp_value<valtype> *val;
310bc633
MJ
2858 int time = 0, size = 0;
2859
2860 for (val = base; val; val = val->scc_next)
2861 {
df0227c4
MJ
2862 time = safe_add (time,
2863 val->local_time_benefit + val->prop_time_benefit);
2864 size = safe_add (size, val->local_size_cost + val->prop_size_cost);
310bc633
MJ
2865 }
2866
2867 for (val = base; val; val = val->scc_next)
2868 for (src = val->sources; src; src = src->next)
2869 if (src->val
3dafb85c 2870 && src->cs->maybe_hot_p ())
310bc633 2871 {
df0227c4
MJ
2872 src->val->prop_time_benefit = safe_add (time,
2873 src->val->prop_time_benefit);
2874 src->val->prop_size_cost = safe_add (size,
2875 src->val->prop_size_cost);
310bc633 2876 }
518dc859
RL
2877 }
2878}
2879
310bc633 2880
44210a96
MJ
2881/* Propagate constants, polymorphic contexts and their effects from the
2882 summaries interprocedurally. */
310bc633 2883
518dc859 2884static void
11478306 2885ipcp_propagate_stage (struct ipa_topo_info *topo)
518dc859
RL
2886{
2887 struct cgraph_node *node;
518dc859 2888
310bc633
MJ
2889 if (dump_file)
2890 fprintf (dump_file, "\n Propagating constants:\n\n");
2891
2892 if (in_lto_p)
2893 ipa_update_after_lto_read ();
2894
2895
2896 FOR_EACH_DEFINED_FUNCTION (node)
2897 {
2898 struct ipa_node_params *info = IPA_NODE_REF (node);
2899
7e729474 2900 determine_versionability (node, info);
d52f5295 2901 if (node->has_gimple_body_p ())
310bc633 2902 {
2c9561b5 2903 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
310bc633
MJ
2904 ipa_get_param_count (info));
2905 initialize_node_lattices (node);
2906 }
67348ccc 2907 if (node->definition && !node->alias)
9a1e784a 2908 overall_size += inline_summaries->get (node)->self_size;
310bc633
MJ
2909 if (node->count > max_count)
2910 max_count = node->count;
310bc633
MJ
2911 }
2912
2913 max_new_size = overall_size;
2914 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
2915 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
2916 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
2917
2918 if (dump_file)
2919 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
2920 overall_size, max_new_size);
2921
2922 propagate_constants_topo (topo);
2923#ifdef ENABLE_CHECKING
2924 ipcp_verify_propagated_values ();
2925#endif
c0cb5055 2926 topo->constants.propagate_effects ();
44210a96 2927 topo->contexts.propagate_effects ();
310bc633
MJ
2928
2929 if (dump_file)
2930 {
2931 fprintf (dump_file, "\nIPA lattices after all propagation:\n");
2932 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true);
2933 }
2934}
2935
2936/* Discover newly direct outgoing edges from NODE which is a new clone with
44210a96 2937 known KNOWN_CSTS and make them direct. */
310bc633
MJ
2938
2939static void
2940ipcp_discover_new_direct_edges (struct cgraph_node *node,
44210a96
MJ
2941 vec<tree> known_csts,
2942 vec<ipa_polymorphic_call_context>
2943 known_contexts,
162712de 2944 struct ipa_agg_replacement_value *aggvals)
310bc633
MJ
2945{
2946 struct cgraph_edge *ie, *next_ie;
0f378cb5 2947 bool found = false;
310bc633
MJ
2948
2949 for (ie = node->indirect_calls; ie; ie = next_ie)
2950 {
81fa35bd 2951 tree target;
231b4916 2952 bool speculative;
310bc633
MJ
2953
2954 next_ie = ie->next_callee;
44210a96 2955 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
231b4916 2956 vNULL, aggvals, &speculative);
310bc633 2957 if (target)
0f378cb5 2958 {
042ae7d2
JH
2959 bool agg_contents = ie->indirect_info->agg_contents;
2960 bool polymorphic = ie->indirect_info->polymorphic;
a4e33812 2961 int param_index = ie->indirect_info->param_index;
231b4916
JH
2962 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
2963 speculative);
0f378cb5 2964 found = true;
4502fe8d 2965
042ae7d2 2966 if (cs && !agg_contents && !polymorphic)
4502fe8d
MJ
2967 {
2968 struct ipa_node_params *info = IPA_NODE_REF (node);
4502fe8d
MJ
2969 int c = ipa_get_controlled_uses (info, param_index);
2970 if (c != IPA_UNDESCRIBED_USE)
2971 {
2972 struct ipa_ref *to_del;
2973
2974 c--;
2975 ipa_set_controlled_uses (info, param_index, c);
2976 if (dump_file && (dump_flags & TDF_DETAILS))
2977 fprintf (dump_file, " controlled uses count of param "
2978 "%i bumped down to %i\n", param_index, c);
2979 if (c == 0
d122681a 2980 && (to_del = node->find_reference (cs->callee, NULL, 0)))
4502fe8d
MJ
2981 {
2982 if (dump_file && (dump_flags & TDF_DETAILS))
2983 fprintf (dump_file, " and even removing its "
2984 "cloning-created reference\n");
d122681a 2985 to_del->remove_reference ();
4502fe8d
MJ
2986 }
2987 }
2988 }
0f378cb5 2989 }
310bc633 2990 }
0f378cb5
JH
2991 /* Turning calls to direct calls will improve overall summary. */
2992 if (found)
2993 inline_update_overall_summary (node);
310bc633
MJ
2994}
2995
2996/* Vector of pointers which for linked lists of clones of an original crgaph
2997 edge. */
2998
d52f5295
ML
2999static vec<cgraph_edge *> next_edge_clone;
3000static vec<cgraph_edge *> prev_edge_clone;
310bc633
MJ
3001
3002static inline void
aef83682 3003grow_edge_clone_vectors (void)
310bc633 3004{
9771b263 3005 if (next_edge_clone.length ()
3dafb85c
ML
3006 <= (unsigned) symtab->edges_max_uid)
3007 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
aef83682 3008 if (prev_edge_clone.length ()
3dafb85c
ML
3009 <= (unsigned) symtab->edges_max_uid)
3010 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
310bc633
MJ
3011}
3012
3013/* Edge duplication hook to grow the appropriate linked list in
3014 next_edge_clone. */
3015
3016static void
3017ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
aef83682 3018 void *)
310bc633 3019{
aef83682
MJ
3020 grow_edge_clone_vectors ();
3021
3022 struct cgraph_edge *old_next = next_edge_clone[src->uid];
3023 if (old_next)
3024 prev_edge_clone[old_next->uid] = dst;
3025 prev_edge_clone[dst->uid] = src;
3026
3027 next_edge_clone[dst->uid] = old_next;
9771b263 3028 next_edge_clone[src->uid] = dst;
310bc633
MJ
3029}
3030
aef83682
MJ
3031/* Hook that is called by cgraph.c when an edge is removed. */
3032
3033static void
3034ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
3035{
3036 grow_edge_clone_vectors ();
3037
3038 struct cgraph_edge *prev = prev_edge_clone[cs->uid];
3039 struct cgraph_edge *next = next_edge_clone[cs->uid];
3040 if (prev)
3041 next_edge_clone[prev->uid] = next;
3042 if (next)
3043 prev_edge_clone[next->uid] = prev;
3044}
3045
2c9561b5
MJ
3046/* See if NODE is a clone with a known aggregate value at a given OFFSET of a
3047 parameter with the given INDEX. */
310bc633 3048
2c9561b5 3049static tree
a9243bfc 3050get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
2c9561b5 3051 int index)
310bc633 3052{
2c9561b5
MJ
3053 struct ipa_agg_replacement_value *aggval;
3054
3055 aggval = ipa_get_agg_replacements_for_node (node);
3056 while (aggval)
3057 {
3058 if (aggval->offset == offset
3059 && aggval->index == index)
3060 return aggval->value;
3061 aggval = aggval->next;
3062 }
3063 return NULL_TREE;
310bc633
MJ
3064}
3065
47f4756e 3066/* Return true is NODE is DEST or its clone for all contexts. */
310bc633
MJ
3067
3068static bool
47f4756e
MJ
3069same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest)
3070{
3071 if (node == dest)
3072 return true;
3073
3074 struct ipa_node_params *info = IPA_NODE_REF (node);
3075 return info->is_all_contexts_clone && info->ipcp_orig_node == dest;
3076}
3077
3078/* Return true if edge CS does bring about the value described by SRC to node
3079 DEST or its clone for all contexts. */
3080
3081static bool
3082cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src,
3083 cgraph_node *dest)
310bc633
MJ
3084{
3085 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
47f4756e
MJ
3086 enum availability availability;
3087 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
310bc633 3088
47f4756e
MJ
3089 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
3090 || availability <= AVAIL_INTERPOSABLE
310bc633
MJ
3091 || caller_info->node_dead)
3092 return false;
3093 if (!src->val)
3094 return true;
3095
3096 if (caller_info->ipcp_orig_node)
3097 {
2c9561b5
MJ
3098 tree t;
3099 if (src->offset == -1)
44210a96 3100 t = caller_info->known_csts[src->index];
2c9561b5
MJ
3101 else
3102 t = get_clone_agg_value (cs->caller, src->offset, src->index);
310bc633
MJ
3103 return (t != NULL_TREE
3104 && values_equal_for_ipcp_p (src->val->value, t));
3105 }
3106 else
518dc859 3107 {
2c9561b5
MJ
3108 struct ipcp_agg_lattice *aglat;
3109 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3110 src->index);
3111 if (src->offset == -1)
c0cb5055 3112 return (plats->itself.is_single_const ()
2c9561b5
MJ
3113 && values_equal_for_ipcp_p (src->val->value,
3114 plats->itself.values->value));
310bc633 3115 else
2c9561b5
MJ
3116 {
3117 if (plats->aggs_bottom || plats->aggs_contain_variable)
3118 return false;
3119 for (aglat = plats->aggs; aglat; aglat = aglat->next)
3120 if (aglat->offset == src->offset)
c0cb5055 3121 return (aglat->is_single_const ()
2c9561b5
MJ
3122 && values_equal_for_ipcp_p (src->val->value,
3123 aglat->values->value));
3124 }
3125 return false;
310bc633
MJ
3126 }
3127}
3128
47f4756e
MJ
3129/* Return true if edge CS does bring about the value described by SRC to node
3130 DEST or its clone for all contexts. */
44210a96
MJ
3131
3132static bool
47f4756e
MJ
3133cgraph_edge_brings_value_p (cgraph_edge *cs,
3134 ipcp_value_source<ipa_polymorphic_call_context> *src,
3135 cgraph_node *dest)
44210a96
MJ
3136{
3137 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3138 cgraph_node *real_dest = cs->callee->function_symbol ();
44210a96 3139
47f4756e 3140 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
44210a96
MJ
3141 || caller_info->node_dead)
3142 return false;
3143 if (!src->val)
3144 return true;
3145
3146 if (caller_info->ipcp_orig_node)
3147 return (caller_info->known_contexts.length () > (unsigned) src->index)
3148 && values_equal_for_ipcp_p (src->val->value,
3149 caller_info->known_contexts[src->index]);
3150
3151 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
3152 src->index);
3153 return plats->ctxlat.is_single_const ()
3154 && values_equal_for_ipcp_p (src->val->value,
3155 plats->ctxlat.values->value);
3156}
3157
2c9561b5
MJ
3158/* Get the next clone in the linked list of clones of an edge. */
3159
3160static inline struct cgraph_edge *
3161get_next_cgraph_edge_clone (struct cgraph_edge *cs)
3162{
9771b263 3163 return next_edge_clone[cs->uid];
2c9561b5
MJ
3164}
3165
47f4756e
MJ
3166/* Given VAL that is intended for DEST, iterate over all its sources and if
3167 they still hold, add their edge frequency and their number into *FREQUENCY
3168 and *CALLER_COUNT respectively. */
310bc633 3169
c0cb5055 3170template <typename valtype>
310bc633 3171static bool
47f4756e
MJ
3172get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3173 int *freq_sum,
310bc633
MJ
3174 gcov_type *count_sum, int *caller_count)
3175{
c0cb5055 3176 ipcp_value_source<valtype> *src;
310bc633
MJ
3177 int freq = 0, count = 0;
3178 gcov_type cnt = 0;
3179 bool hot = false;
3180
3181 for (src = val->sources; src; src = src->next)
3182 {
3183 struct cgraph_edge *cs = src->cs;
3184 while (cs)
518dc859 3185 {
47f4756e 3186 if (cgraph_edge_brings_value_p (cs, src, dest))
310bc633
MJ
3187 {
3188 count++;
3189 freq += cs->frequency;
3190 cnt += cs->count;
3dafb85c 3191 hot |= cs->maybe_hot_p ();
310bc633
MJ
3192 }
3193 cs = get_next_cgraph_edge_clone (cs);
518dc859
RL
3194 }
3195 }
310bc633
MJ
3196
3197 *freq_sum = freq;
3198 *count_sum = cnt;
3199 *caller_count = count;
3200 return hot;
518dc859
RL
3201}
3202
47f4756e
MJ
3203/* Return a vector of incoming edges that do bring value VAL to node DEST. It
3204 is assumed their number is known and equal to CALLER_COUNT. */
310bc633 3205
c0cb5055 3206template <typename valtype>
d52f5295 3207static vec<cgraph_edge *>
47f4756e
MJ
3208gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3209 int caller_count)
518dc859 3210{
c0cb5055 3211 ipcp_value_source<valtype> *src;
d52f5295 3212 vec<cgraph_edge *> ret;
310bc633 3213
9771b263 3214 ret.create (caller_count);
310bc633
MJ
3215 for (src = val->sources; src; src = src->next)
3216 {
3217 struct cgraph_edge *cs = src->cs;
3218 while (cs)
3219 {
47f4756e 3220 if (cgraph_edge_brings_value_p (cs, src, dest))
9771b263 3221 ret.quick_push (cs);
310bc633
MJ
3222 cs = get_next_cgraph_edge_clone (cs);
3223 }
3224 }
3225
3226 return ret;
518dc859
RL
3227}
3228
310bc633
MJ
3229/* Construct a replacement map for a know VALUE for a formal parameter PARAM.
3230 Return it or NULL if for some reason it cannot be created. */
3231
518dc859 3232static struct ipa_replace_map *
0e8853ee 3233get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
518dc859
RL
3234{
3235 struct ipa_replace_map *replace_map;
518dc859 3236
310bc633 3237
766090c2 3238 replace_map = ggc_alloc<ipa_replace_map> ();
c6f7cfc1
JH
3239 if (dump_file)
3240 {
0e8853ee
JH
3241 fprintf (dump_file, " replacing ");
3242 ipa_dump_param (dump_file, info, parm_num);
3243
c6f7cfc1 3244 fprintf (dump_file, " with const ");
310bc633 3245 print_generic_expr (dump_file, value, 0);
c6f7cfc1
JH
3246 fprintf (dump_file, "\n");
3247 }
49bde175
JH
3248 replace_map->old_tree = NULL;
3249 replace_map->parm_num = parm_num;
310bc633 3250 replace_map->new_tree = value;
0f1961a2
JH
3251 replace_map->replace_p = true;
3252 replace_map->ref_p = false;
518dc859
RL
3253
3254 return replace_map;
3255}
3256
310bc633 3257/* Dump new profiling counts */
518dc859 3258
518dc859 3259static void
310bc633
MJ
3260dump_profile_updates (struct cgraph_node *orig_node,
3261 struct cgraph_node *new_node)
518dc859 3262{
310bc633 3263 struct cgraph_edge *cs;
518dc859 3264
310bc633
MJ
3265 fprintf (dump_file, " setting count of the specialized node to "
3266 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count);
3267 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3268 fprintf (dump_file, " edge to %s has count "
3269 HOST_WIDE_INT_PRINT_DEC "\n",
fec39fa6 3270 cs->callee->name (), (HOST_WIDE_INT) cs->count);
310bc633
MJ
3271
3272 fprintf (dump_file, " setting count of the original node to "
3273 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count);
3274 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3275 fprintf (dump_file, " edge to %s is left with "
3276 HOST_WIDE_INT_PRINT_DEC "\n",
fec39fa6 3277 cs->callee->name (), (HOST_WIDE_INT) cs->count);
310bc633 3278}
c6f7cfc1 3279
310bc633
MJ
3280/* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3281 their profile information to reflect this. */
518dc859 3282
518dc859 3283static void
310bc633
MJ
3284update_profiling_info (struct cgraph_node *orig_node,
3285 struct cgraph_node *new_node)
518dc859 3286{
518dc859 3287 struct cgraph_edge *cs;
310bc633
MJ
3288 struct caller_statistics stats;
3289 gcov_type new_sum, orig_sum;
3290 gcov_type remainder, orig_node_count = orig_node->count;
3291
3292 if (orig_node_count == 0)
3293 return;
518dc859 3294
310bc633 3295 init_caller_stats (&stats);
d52f5295
ML
3296 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3297 false);
310bc633
MJ
3298 orig_sum = stats.count_sum;
3299 init_caller_stats (&stats);
d52f5295
ML
3300 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3301 false);
310bc633
MJ
3302 new_sum = stats.count_sum;
3303
3304 if (orig_node_count < orig_sum + new_sum)
518dc859 3305 {
310bc633
MJ
3306 if (dump_file)
3307 fprintf (dump_file, " Problem: node %s/%i has too low count "
3308 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
3309 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
fec39fa6 3310 orig_node->name (), orig_node->order,
310bc633
MJ
3311 (HOST_WIDE_INT) orig_node_count,
3312 (HOST_WIDE_INT) (orig_sum + new_sum));
3313
3314 orig_node_count = (orig_sum + new_sum) * 12 / 10;
3315 if (dump_file)
3316 fprintf (dump_file, " proceeding by pretending it was "
3317 HOST_WIDE_INT_PRINT_DEC "\n",
3318 (HOST_WIDE_INT) orig_node_count);
518dc859 3319 }
310bc633
MJ
3320
3321 new_node->count = new_sum;
3322 remainder = orig_node_count - new_sum;
3323 orig_node->count = remainder;
3324
3325 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3326 if (cs->frequency)
8ddb5a29
TJ
3327 cs->count = apply_probability (cs->count,
3328 GCOV_COMPUTE_SCALE (new_sum,
3329 orig_node_count));
310bc633
MJ
3330 else
3331 cs->count = 0;
3332
3333 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
8ddb5a29
TJ
3334 cs->count = apply_probability (cs->count,
3335 GCOV_COMPUTE_SCALE (remainder,
3336 orig_node_count));
310bc633
MJ
3337
3338 if (dump_file)
3339 dump_profile_updates (orig_node, new_node);
518dc859
RL
3340}
3341
310bc633
MJ
3342/* Update the respective profile of specialized NEW_NODE and the original
3343 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
3344 have been redirected to the specialized version. */
3345
3346static void
3347update_specialized_profile (struct cgraph_node *new_node,
3348 struct cgraph_node *orig_node,
3349 gcov_type redirected_sum)
5e45130d 3350{
a065d52e 3351 struct cgraph_edge *cs;
310bc633 3352 gcov_type new_node_count, orig_node_count = orig_node->count;
5e45130d 3353
310bc633
MJ
3354 if (dump_file)
3355 fprintf (dump_file, " the sum of counts of redirected edges is "
3356 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum);
3357 if (orig_node_count == 0)
3358 return;
a065d52e 3359
310bc633 3360 gcc_assert (orig_node_count >= redirected_sum);
5e45130d 3361
310bc633
MJ
3362 new_node_count = new_node->count;
3363 new_node->count += redirected_sum;
3364 orig_node->count -= redirected_sum;
a065d52e 3365
310bc633
MJ
3366 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3367 if (cs->frequency)
8ddb5a29
TJ
3368 cs->count += apply_probability (cs->count,
3369 GCOV_COMPUTE_SCALE (redirected_sum,
3370 new_node_count));
310bc633
MJ
3371 else
3372 cs->count = 0;
a065d52e 3373
310bc633
MJ
3374 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3375 {
8ddb5a29
TJ
3376 gcov_type dec = apply_probability (cs->count,
3377 GCOV_COMPUTE_SCALE (redirected_sum,
3378 orig_node_count));
310bc633
MJ
3379 if (dec < cs->count)
3380 cs->count -= dec;
3381 else
3382 cs->count = 0;
3383 }
a065d52e 3384
310bc633
MJ
3385 if (dump_file)
3386 dump_profile_updates (orig_node, new_node);
5e45130d
JH
3387}
3388
44210a96
MJ
3389/* Create a specialized version of NODE with known constants in KNOWN_CSTS,
3390 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and
3391 redirect all edges in CALLERS to it. */
a065d52e 3392
310bc633
MJ
3393static struct cgraph_node *
3394create_specialized_node (struct cgraph_node *node,
44210a96
MJ
3395 vec<tree> known_csts,
3396 vec<ipa_polymorphic_call_context> known_contexts,
2c9561b5 3397 struct ipa_agg_replacement_value *aggvals,
d52f5295 3398 vec<cgraph_edge *> callers)
5e45130d 3399{
310bc633 3400 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
d52f5295 3401 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
79ee9826 3402 struct ipa_agg_replacement_value *av;
310bc633
MJ
3403 struct cgraph_node *new_node;
3404 int i, count = ipa_get_param_count (info);
3405 bitmap args_to_skip;
5e45130d 3406
310bc633
MJ
3407 gcc_assert (!info->ipcp_orig_node);
3408
3409 if (node->local.can_change_signature)
5e45130d 3410 {
310bc633
MJ
3411 args_to_skip = BITMAP_GGC_ALLOC ();
3412 for (i = 0; i < count; i++)
3413 {
44210a96 3414 tree t = known_csts[i];
310bc633 3415
44210a96 3416 if (t || !ipa_is_param_used (info, i))
310bc633
MJ
3417 bitmap_set_bit (args_to_skip, i);
3418 }
3419 }
3420 else
d7da5cc8
MJ
3421 {
3422 args_to_skip = NULL;
3423 if (dump_file && (dump_flags & TDF_DETAILS))
3424 fprintf (dump_file, " cannot change function signature\n");
3425 }
310bc633
MJ
3426
3427 for (i = 0; i < count ; i++)
3428 {
44210a96
MJ
3429 tree t = known_csts[i];
3430 if (t)
310bc633
MJ
3431 {
3432 struct ipa_replace_map *replace_map;
3433
44210a96 3434 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
0e8853ee 3435 replace_map = get_replacement_map (info, t, i);
310bc633 3436 if (replace_map)
9771b263 3437 vec_safe_push (replace_trees, replace_map);
310bc633 3438 }
5e45130d
JH
3439 }
3440
d52f5295
ML
3441 new_node = node->create_virtual_clone (callers, replace_trees,
3442 args_to_skip, "constprop");
2c9561b5 3443 ipa_set_node_agg_value_chain (new_node, aggvals);
79ee9826 3444 for (av = aggvals; av; av = av->next)
3dafb85c 3445 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
79ee9826 3446
310bc633 3447 if (dump_file && (dump_flags & TDF_DETAILS))
2c9561b5
MJ
3448 {
3449 fprintf (dump_file, " the new node is %s/%i.\n",
fec39fa6 3450 new_node->name (), new_node->order);
44210a96
MJ
3451 if (known_contexts.exists ())
3452 {
3453 for (i = 0; i < count ; i++)
3454 if (!known_contexts[i].useless_p ())
3455 {
3456 fprintf (dump_file, " known ctx %i is ", i);
3457 known_contexts[i].dump (dump_file);
3458 }
3459 }
2c9561b5
MJ
3460 if (aggvals)
3461 ipa_dump_agg_replacement_values (dump_file, aggvals);
3462 }
9de6f6c3 3463 ipa_check_create_node_params ();
310bc633
MJ
3464 update_profiling_info (node, new_node);
3465 new_info = IPA_NODE_REF (new_node);
3466 new_info->ipcp_orig_node = node;
44210a96
MJ
3467 new_info->known_csts = known_csts;
3468 new_info->known_contexts = known_contexts;
5e45130d 3469
44210a96 3470 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
310bc633 3471
9771b263 3472 callers.release ();
310bc633 3473 return new_node;
5e45130d
JH
3474}
3475
310bc633 3476/* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
44210a96 3477 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
3949c4a7
MJ
3478
3479static void
2c9561b5 3480find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
44210a96 3481 vec<tree> known_csts,
d52f5295 3482 vec<cgraph_edge *> callers)
3949c4a7
MJ
3483{
3484 struct ipa_node_params *info = IPA_NODE_REF (node);
310bc633 3485 int i, count = ipa_get_param_count (info);
3949c4a7 3486
310bc633 3487 for (i = 0; i < count ; i++)
3949c4a7 3488 {
310bc633
MJ
3489 struct cgraph_edge *cs;
3490 tree newval = NULL_TREE;
3491 int j;
df0d8136 3492 bool first = true;
3949c4a7 3493
44210a96 3494 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
3949c4a7
MJ
3495 continue;
3496
9771b263 3497 FOR_EACH_VEC_ELT (callers, j, cs)
49c471e3 3498 {
310bc633
MJ
3499 struct ipa_jump_func *jump_func;
3500 tree t;
40591473 3501
128c61ee
MJ
3502 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3503 {
3504 newval = NULL_TREE;
3505 break;
3506 }
310bc633 3507 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
310bc633
MJ
3508 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3509 if (!t
3510 || (newval
df0d8136
JH
3511 && !values_equal_for_ipcp_p (t, newval))
3512 || (!first && !newval))
3949c4a7 3513 {
310bc633
MJ
3514 newval = NULL_TREE;
3515 break;
3949c4a7 3516 }
310bc633
MJ
3517 else
3518 newval = t;
df0d8136 3519 first = false;
3949c4a7
MJ
3520 }
3521
310bc633
MJ
3522 if (newval)
3523 {
3524 if (dump_file && (dump_flags & TDF_DETAILS))
3525 {
2c9561b5 3526 fprintf (dump_file, " adding an extra known scalar value ");
310bc633 3527 print_ipcp_constant_value (dump_file, newval);
0e8853ee
JH
3528 fprintf (dump_file, " for ");
3529 ipa_dump_param (dump_file, info, i);
310bc633
MJ
3530 fprintf (dump_file, "\n");
3531 }
5e45130d 3532
44210a96 3533 known_csts[i] = newval;
310bc633 3534 }
5e45130d 3535 }
5e45130d
JH
3536}
3537
44210a96
MJ
3538/* Given a NODE and a subset of its CALLERS, try to populate plank slots in
3539 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
3540 CALLERS. */
3541
3542static void
3543find_more_contexts_for_caller_subset (cgraph_node *node,
3544 vec<ipa_polymorphic_call_context>
3545 *known_contexts,
3546 vec<cgraph_edge *> callers)
3547{
3548 ipa_node_params *info = IPA_NODE_REF (node);
3549 int i, count = ipa_get_param_count (info);
3550
3551 for (i = 0; i < count ; i++)
3552 {
3553 cgraph_edge *cs;
3554
3555 if (ipa_get_poly_ctx_lat (info, i)->bottom
3556 || (known_contexts->exists ()
3557 && !(*known_contexts)[i].useless_p ()))
3558 continue;
3559
3560 ipa_polymorphic_call_context newval;
df0d8136 3561 bool first = true;
44210a96
MJ
3562 int j;
3563
3564 FOR_EACH_VEC_ELT (callers, j, cs)
3565 {
3566 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3567 return;
3568 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs),
3569 i);
3570 ipa_polymorphic_call_context ctx;
3571 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
3572 jfunc);
df0d8136 3573 if (first)
44210a96 3574 {
44210a96 3575 newval = ctx;
df0d8136 3576 first = false;
44210a96 3577 }
df0d8136
JH
3578 else
3579 newval.meet_with (ctx);
3580 if (newval.useless_p ())
3581 break;
44210a96
MJ
3582 }
3583
df0d8136 3584 if (!newval.useless_p ())
44210a96
MJ
3585 {
3586 if (dump_file && (dump_flags & TDF_DETAILS))
3587 {
3588 fprintf (dump_file, " adding an extra known polymorphic "
3589 "context ");
3590 print_ipcp_constant_value (dump_file, newval);
3591 fprintf (dump_file, " for ");
3592 ipa_dump_param (dump_file, info, i);
3593 fprintf (dump_file, "\n");
3594 }
3595
3596 if (!known_contexts->exists ())
3597 known_contexts->safe_grow_cleared (ipa_get_param_count (info));
3598 (*known_contexts)[i] = newval;
3599 }
3600
3601 }
3602}
3603
2c9561b5
MJ
3604/* Go through PLATS and create a vector of values consisting of values and
3605 offsets (minus OFFSET) of lattices that contain only a single value. */
3606
84562394 3607static vec<ipa_agg_jf_item>
2c9561b5
MJ
3608copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3609{
84562394 3610 vec<ipa_agg_jf_item> res = vNULL;
2c9561b5
MJ
3611
3612 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
6e1aa848 3613 return vNULL;
2c9561b5
MJ
3614
3615 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
c0cb5055 3616 if (aglat->is_single_const ())
2c9561b5
MJ
3617 {
3618 struct ipa_agg_jf_item ti;
3619 ti.offset = aglat->offset - offset;
3620 ti.value = aglat->values->value;
9771b263 3621 res.safe_push (ti);
2c9561b5
MJ
3622 }
3623 return res;
3624}
3625
3626/* Intersect all values in INTER with single value lattices in PLATS (while
3627 subtracting OFFSET). */
3628
3629static void
3630intersect_with_plats (struct ipcp_param_lattices *plats,
84562394 3631 vec<ipa_agg_jf_item> *inter,
2c9561b5
MJ
3632 HOST_WIDE_INT offset)
3633{
3634 struct ipcp_agg_lattice *aglat;
3635 struct ipa_agg_jf_item *item;
3636 int k;
3637
3638 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
3639 {
9771b263 3640 inter->release ();
2c9561b5
MJ
3641 return;
3642 }
3643
3644 aglat = plats->aggs;
9771b263 3645 FOR_EACH_VEC_ELT (*inter, k, item)
2c9561b5
MJ
3646 {
3647 bool found = false;
3648 if (!item->value)
3649 continue;
3650 while (aglat)
3651 {
3652 if (aglat->offset - offset > item->offset)
3653 break;
3654 if (aglat->offset - offset == item->offset)
3655 {
3656 gcc_checking_assert (item->value);
3657 if (values_equal_for_ipcp_p (item->value, aglat->values->value))
3658 found = true;
3659 break;
3660 }
3661 aglat = aglat->next;
3662 }
3663 if (!found)
3664 item->value = NULL_TREE;
3665 }
3666}
3667
3668/* Copy agggregate replacement values of NODE (which is an IPA-CP clone) to the
3669 vector result while subtracting OFFSET from the individual value offsets. */
3670
84562394 3671static vec<ipa_agg_jf_item>
0fd44da3
MJ
3672agg_replacements_to_vector (struct cgraph_node *node, int index,
3673 HOST_WIDE_INT offset)
2c9561b5
MJ
3674{
3675 struct ipa_agg_replacement_value *av;
84562394 3676 vec<ipa_agg_jf_item> res = vNULL;
2c9561b5
MJ
3677
3678 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
0fd44da3
MJ
3679 if (av->index == index
3680 && (av->offset - offset) >= 0)
2c9561b5
MJ
3681 {
3682 struct ipa_agg_jf_item item;
3683 gcc_checking_assert (av->value);
3684 item.offset = av->offset - offset;
3685 item.value = av->value;
9771b263 3686 res.safe_push (item);
2c9561b5
MJ
3687 }
3688
3689 return res;
3690}
3691
3692/* Intersect all values in INTER with those that we have already scheduled to
3693 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone
3694 (while subtracting OFFSET). */
3695
3696static void
3697intersect_with_agg_replacements (struct cgraph_node *node, int index,
84562394 3698 vec<ipa_agg_jf_item> *inter,
2c9561b5
MJ
3699 HOST_WIDE_INT offset)
3700{
3701 struct ipa_agg_replacement_value *srcvals;
3702 struct ipa_agg_jf_item *item;
3703 int i;
3704
3705 srcvals = ipa_get_agg_replacements_for_node (node);
3706 if (!srcvals)
3707 {
9771b263 3708 inter->release ();
2c9561b5
MJ
3709 return;
3710 }
3711
9771b263 3712 FOR_EACH_VEC_ELT (*inter, i, item)
2c9561b5
MJ
3713 {
3714 struct ipa_agg_replacement_value *av;
3715 bool found = false;
3716 if (!item->value)
3717 continue;
3718 for (av = srcvals; av; av = av->next)
3719 {
3720 gcc_checking_assert (av->value);
3721 if (av->index == index
3722 && av->offset - offset == item->offset)
3723 {
3724 if (values_equal_for_ipcp_p (item->value, av->value))
3725 found = true;
3726 break;
3727 }
3728 }
3729 if (!found)
3730 item->value = NULL_TREE;
3731 }
3732}
3733
7e9f2b6e
MJ
3734/* Intersect values in INTER with aggregate values that come along edge CS to
3735 parameter number INDEX and return it. If INTER does not actually exist yet,
3736 copy all incoming values to it. If we determine we ended up with no values
3737 whatsoever, return a released vector. */
3738
84562394 3739static vec<ipa_agg_jf_item>
7e9f2b6e 3740intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
84562394 3741 vec<ipa_agg_jf_item> inter)
7e9f2b6e
MJ
3742{
3743 struct ipa_jump_func *jfunc;
3744 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
3745 if (jfunc->type == IPA_JF_PASS_THROUGH
3746 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
3747 {
3748 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3749 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
3750
3751 if (caller_info->ipcp_orig_node)
3752 {
3753 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
3754 struct ipcp_param_lattices *orig_plats;
3755 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
3756 src_idx);
3757 if (agg_pass_through_permissible_p (orig_plats, jfunc))
3758 {
3759 if (!inter.exists ())
0fd44da3 3760 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
7e9f2b6e
MJ
3761 else
3762 intersect_with_agg_replacements (cs->caller, src_idx,
3763 &inter, 0);
3764 }
c8f40352
MJ
3765 else
3766 {
3767 inter.release ();
3768 return vNULL;
3769 }
7e9f2b6e
MJ
3770 }
3771 else
3772 {
3773 struct ipcp_param_lattices *src_plats;
3774 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
3775 if (agg_pass_through_permissible_p (src_plats, jfunc))
3776 {
3777 /* Currently we do not produce clobber aggregate jump
3778 functions, adjust when we do. */
3779 gcc_checking_assert (!jfunc->agg.items);
3780 if (!inter.exists ())
3781 inter = copy_plats_to_inter (src_plats, 0);
3782 else
3783 intersect_with_plats (src_plats, &inter, 0);
3784 }
c8f40352
MJ
3785 else
3786 {
3787 inter.release ();
3788 return vNULL;
3789 }
7e9f2b6e
MJ
3790 }
3791 }
3792 else if (jfunc->type == IPA_JF_ANCESTOR
3793 && ipa_get_jf_ancestor_agg_preserved (jfunc))
3794 {
3795 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3796 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
3797 struct ipcp_param_lattices *src_plats;
3798 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
3799
3800 if (caller_info->ipcp_orig_node)
3801 {
3802 if (!inter.exists ())
0fd44da3 3803 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
7e9f2b6e 3804 else
0fd44da3 3805 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
7e9f2b6e
MJ
3806 delta);
3807 }
3808 else
3809 {
3810 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
3811 /* Currently we do not produce clobber aggregate jump
3812 functions, adjust when we do. */
3813 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
3814 if (!inter.exists ())
3815 inter = copy_plats_to_inter (src_plats, delta);
3816 else
3817 intersect_with_plats (src_plats, &inter, delta);
3818 }
3819 }
3820 else if (jfunc->agg.items)
3821 {
3822 struct ipa_agg_jf_item *item;
3823 int k;
3824
3825 if (!inter.exists ())
3826 for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
3827 inter.safe_push ((*jfunc->agg.items)[i]);
3828 else
3829 FOR_EACH_VEC_ELT (inter, k, item)
3830 {
3831 int l = 0;
3832 bool found = false;;
3833
3834 if (!item->value)
3835 continue;
3836
3837 while ((unsigned) l < jfunc->agg.items->length ())
3838 {
3839 struct ipa_agg_jf_item *ti;
3840 ti = &(*jfunc->agg.items)[l];
3841 if (ti->offset > item->offset)
3842 break;
3843 if (ti->offset == item->offset)
3844 {
3845 gcc_checking_assert (ti->value);
3846 if (values_equal_for_ipcp_p (item->value,
3847 ti->value))
3848 found = true;
3849 break;
3850 }
3851 l++;
3852 }
3853 if (!found)
3854 item->value = NULL;
3855 }
3856 }
3857 else
3858 {
c3284718 3859 inter.release ();
84562394 3860 return vec<ipa_agg_jf_item>();
7e9f2b6e
MJ
3861 }
3862 return inter;
3863}
3864
2c9561b5
MJ
3865/* Look at edges in CALLERS and collect all known aggregate values that arrive
3866 from all of them. */
3867
3868static struct ipa_agg_replacement_value *
3869find_aggregate_values_for_callers_subset (struct cgraph_node *node,
d52f5295 3870 vec<cgraph_edge *> callers)
2c9561b5 3871{
dffdd6e5 3872 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
6f9549ee
MJ
3873 struct ipa_agg_replacement_value *res;
3874 struct ipa_agg_replacement_value **tail = &res;
2c9561b5 3875 struct cgraph_edge *cs;
dffdd6e5 3876 int i, j, count = ipa_get_param_count (dest_info);
2c9561b5 3877
9771b263 3878 FOR_EACH_VEC_ELT (callers, j, cs)
2c9561b5
MJ
3879 {
3880 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
3881 if (c < count)
3882 count = c;
3883 }
3884
3885 for (i = 0; i < count ; i++)
3886 {
3887 struct cgraph_edge *cs;
84562394 3888 vec<ipa_agg_jf_item> inter = vNULL;
2c9561b5 3889 struct ipa_agg_jf_item *item;
7b920a9a 3890 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
2c9561b5
MJ
3891 int j;
3892
3893 /* Among other things, the following check should deal with all by_ref
3894 mismatches. */
7b920a9a 3895 if (plats->aggs_bottom)
2c9561b5
MJ
3896 continue;
3897
9771b263 3898 FOR_EACH_VEC_ELT (callers, j, cs)
2c9561b5 3899 {
7e9f2b6e 3900 inter = intersect_aggregates_with_edge (cs, i, inter);
2c9561b5 3901
9771b263 3902 if (!inter.exists ())
2c9561b5
MJ
3903 goto next_param;
3904 }
3905
9771b263 3906 FOR_EACH_VEC_ELT (inter, j, item)
2c9561b5
MJ
3907 {
3908 struct ipa_agg_replacement_value *v;
3909
3910 if (!item->value)
3911 continue;
3912
766090c2 3913 v = ggc_alloc<ipa_agg_replacement_value> ();
2c9561b5
MJ
3914 v->index = i;
3915 v->offset = item->offset;
3916 v->value = item->value;
7b920a9a 3917 v->by_ref = plats->aggs_by_ref;
6f9549ee
MJ
3918 *tail = v;
3919 tail = &v->next;
2c9561b5
MJ
3920 }
3921
3922 next_param:
9771b263
DN
3923 if (inter.exists ())
3924 inter.release ();
2c9561b5 3925 }
6f9549ee 3926 *tail = NULL;
2c9561b5
MJ
3927 return res;
3928}
3929
3930/* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3931
3932static struct ipa_agg_replacement_value *
84562394 3933known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
2c9561b5 3934{
6f9549ee
MJ
3935 struct ipa_agg_replacement_value *res;
3936 struct ipa_agg_replacement_value **tail = &res;
2c9561b5
MJ
3937 struct ipa_agg_jump_function *aggjf;
3938 struct ipa_agg_jf_item *item;
3939 int i, j;
3940
9771b263
DN
3941 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3942 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
2c9561b5
MJ
3943 {
3944 struct ipa_agg_replacement_value *v;
766090c2 3945 v = ggc_alloc<ipa_agg_replacement_value> ();
2c9561b5
MJ
3946 v->index = i;
3947 v->offset = item->offset;
3948 v->value = item->value;
7b920a9a 3949 v->by_ref = aggjf->by_ref;
6f9549ee
MJ
3950 *tail = v;
3951 tail = &v->next;
2c9561b5 3952 }
6f9549ee 3953 *tail = NULL;
2c9561b5
MJ
3954 return res;
3955}
3956
3957/* Determine whether CS also brings all scalar values that the NODE is
3958 specialized for. */
3959
3960static bool
3961cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs,
3962 struct cgraph_node *node)
3963{
3964 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
3965 int count = ipa_get_param_count (dest_info);
3966 struct ipa_node_params *caller_info;
3967 struct ipa_edge_args *args;
3968 int i;
3969
3970 caller_info = IPA_NODE_REF (cs->caller);
3971 args = IPA_EDGE_REF (cs);
3972 for (i = 0; i < count; i++)
3973 {
3974 struct ipa_jump_func *jump_func;
3975 tree val, t;
3976
44210a96 3977 val = dest_info->known_csts[i];
2c9561b5
MJ
3978 if (!val)
3979 continue;
3980
3981 if (i >= ipa_get_cs_argument_count (args))
3982 return false;
3983 jump_func = ipa_get_ith_jump_func (args, i);
3984 t = ipa_value_from_jfunc (caller_info, jump_func);
3985 if (!t || !values_equal_for_ipcp_p (val, t))
3986 return false;
3987 }
3988 return true;
3989}
3990
3991/* Determine whether CS also brings all aggregate values that NODE is
3992 specialized for. */
3993static bool
3994cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
3995 struct cgraph_node *node)
3996{
7e9f2b6e 3997 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
9576e7b1 3998 struct ipa_node_params *orig_node_info;
2c9561b5 3999 struct ipa_agg_replacement_value *aggval;
7e9f2b6e 4000 int i, ec, count;
2c9561b5
MJ
4001
4002 aggval = ipa_get_agg_replacements_for_node (node);
7e9f2b6e
MJ
4003 if (!aggval)
4004 return true;
4005
4006 count = ipa_get_param_count (IPA_NODE_REF (node));
4007 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
4008 if (ec < count)
4009 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4010 if (aggval->index >= ec)
4011 return false;
4012
9576e7b1 4013 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
7e9f2b6e
MJ
4014 if (orig_caller_info->ipcp_orig_node)
4015 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
4016
4017 for (i = 0; i < count; i++)
2c9561b5 4018 {
84562394 4019 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
2c9561b5 4020 struct ipcp_param_lattices *plats;
7e9f2b6e
MJ
4021 bool interesting = false;
4022 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4023 if (aggval->index == i)
4024 {
4025 interesting = true;
4026 break;
4027 }
4028 if (!interesting)
4029 continue;
4030
9576e7b1 4031 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
7e9f2b6e 4032 if (plats->aggs_bottom)
2c9561b5 4033 return false;
2c9561b5 4034
7e9f2b6e 4035 values = intersect_aggregates_with_edge (cs, i, values);
c3284718 4036 if (!values.exists ())
2c9561b5
MJ
4037 return false;
4038
7e9f2b6e
MJ
4039 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
4040 if (aggval->index == i)
4041 {
4042 struct ipa_agg_jf_item *item;
4043 int j;
4044 bool found = false;
4045 FOR_EACH_VEC_ELT (values, j, item)
4046 if (item->value
4047 && item->offset == av->offset
4048 && values_equal_for_ipcp_p (item->value, av->value))
c3272a92
PCC
4049 {
4050 found = true;
4051 break;
4052 }
7e9f2b6e
MJ
4053 if (!found)
4054 {
c3284718 4055 values.release ();
7e9f2b6e
MJ
4056 return false;
4057 }
4058 }
2c9561b5
MJ
4059 }
4060 return true;
4061}
4062
310bc633
MJ
4063/* Given an original NODE and a VAL for which we have already created a
4064 specialized clone, look whether there are incoming edges that still lead
4065 into the old node but now also bring the requested value and also conform to
026c3cfd 4066 all other criteria such that they can be redirected the special node.
310bc633 4067 This function can therefore redirect the final edge in a SCC. */
3e66255c 4068
c0cb5055 4069template <typename valtype>
3e66255c 4070static void
c0cb5055 4071perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
3e66255c 4072{
c0cb5055 4073 ipcp_value_source<valtype> *src;
310bc633 4074 gcov_type redirected_sum = 0;
3e66255c 4075
310bc633 4076 for (src = val->sources; src; src = src->next)
3e66255c 4077 {
310bc633
MJ
4078 struct cgraph_edge *cs = src->cs;
4079 while (cs)
4080 {
47f4756e
MJ
4081 if (cgraph_edge_brings_value_p (cs, src, node)
4082 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node)
4083 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node))
310bc633 4084 {
47f4756e
MJ
4085 if (dump_file)
4086 fprintf (dump_file, " - adding an extra caller %s/%i"
4087 " of %s/%i\n",
2a72a953 4088 xstrdup_for_dump (cs->caller->name ()),
47f4756e 4089 cs->caller->order,
2a72a953 4090 xstrdup_for_dump (val->spec_node->name ()),
47f4756e
MJ
4091 val->spec_node->order);
4092
6a4bad95
MJ
4093 cs->redirect_callee_duplicating_thunks (val->spec_node);
4094 val->spec_node->expand_all_artificial_thunks ();
47f4756e 4095 redirected_sum += cs->count;
310bc633
MJ
4096 }
4097 cs = get_next_cgraph_edge_clone (cs);
4098 }
3e66255c 4099 }
310bc633
MJ
4100
4101 if (redirected_sum)
4102 update_specialized_profile (val->spec_node, node, redirected_sum);
3e66255c
MJ
4103}
4104
44210a96 4105/* Return true if KNOWN_CONTEXTS contain at least one useful context. */
3e66255c 4106
44210a96
MJ
4107static bool
4108known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
4109{
4110 ipa_polymorphic_call_context *ctx;
4111 int i;
4112
4113 FOR_EACH_VEC_ELT (known_contexts, i, ctx)
4114 if (!ctx->useless_p ())
4115 return true;
4116 return false;
4117}
4118
4119/* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */
4120
4121static vec<ipa_polymorphic_call_context>
4122copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
4123{
4124 if (known_contexts_useful_p (known_contexts))
4125 return known_contexts.copy ();
4126 else
4127 return vNULL;
4128}
4129
4130/* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If
4131 non-empty, replace KNOWN_CONTEXTS with its copy too. */
310bc633 4132
518dc859 4133static void
44210a96
MJ
4134modify_known_vectors_with_val (vec<tree> *known_csts,
4135 vec<ipa_polymorphic_call_context> *known_contexts,
4136 ipcp_value<tree> *val,
4137 int index)
518dc859 4138{
44210a96
MJ
4139 *known_csts = known_csts->copy ();
4140 *known_contexts = copy_useful_known_contexts (*known_contexts);
4141 (*known_csts)[index] = val->value;
4142}
518dc859 4143
44210a96
MJ
4144/* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the
4145 copy according to VAL and INDEX. */
4146
4147static void
4148modify_known_vectors_with_val (vec<tree> *known_csts,
4149 vec<ipa_polymorphic_call_context> *known_contexts,
4150 ipcp_value<ipa_polymorphic_call_context> *val,
4151 int index)
4152{
4153 *known_csts = known_csts->copy ();
4154 *known_contexts = known_contexts->copy ();
4155 (*known_contexts)[index] = val->value;
310bc633 4156}
5e45130d 4157
44210a96
MJ
4158/* Return true if OFFSET indicates this was not an aggregate value or there is
4159 a replacement equivalent to VALUE, INDEX and OFFSET among those in the
4160 AGGVALS list. */
2c9561b5
MJ
4161
4162DEBUG_FUNCTION bool
44210a96
MJ
4163ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4164 int index, HOST_WIDE_INT offset, tree value)
2c9561b5 4165{
44210a96
MJ
4166 if (offset == -1)
4167 return true;
4168
2c9561b5
MJ
4169 while (aggvals)
4170 {
4171 if (aggvals->index == index
4172 && aggvals->offset == offset
4173 && values_equal_for_ipcp_p (aggvals->value, value))
4174 return true;
4175 aggvals = aggvals->next;
4176 }
4177 return false;
4178}
4179
44210a96
MJ
4180/* Return true if offset is minus one because source of a polymorphic contect
4181 cannot be an aggregate value. */
4182
4183DEBUG_FUNCTION bool
4184ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *,
4185 int , HOST_WIDE_INT offset,
4186 ipa_polymorphic_call_context)
4187{
4188 return offset == -1;
4189}
4190
2c9561b5
MJ
4191/* Decide wheter to create a special version of NODE for value VAL of parameter
4192 at the given INDEX. If OFFSET is -1, the value is for the parameter itself,
4193 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
44210a96 4194 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
2c9561b5 4195
c0cb5055 4196template <typename valtype>
2c9561b5
MJ
4197static bool
4198decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
c0cb5055 4199 ipcp_value<valtype> *val, vec<tree> known_csts,
44210a96 4200 vec<ipa_polymorphic_call_context> known_contexts)
2c9561b5
MJ
4201{
4202 struct ipa_agg_replacement_value *aggvals;
4203 int freq_sum, caller_count;
4204 gcov_type count_sum;
d52f5295 4205 vec<cgraph_edge *> callers;
2c9561b5
MJ
4206
4207 if (val->spec_node)
4208 {
4209 perhaps_add_new_callers (node, val);
4210 return false;
4211 }
4212 else if (val->local_size_cost + overall_size > max_new_size)
4213 {
4214 if (dump_file && (dump_flags & TDF_DETAILS))
4215 fprintf (dump_file, " Ignoring candidate value because "
4216 "max_new_size would be reached with %li.\n",
4217 val->local_size_cost + overall_size);
4218 return false;
4219 }
47f4756e 4220 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
2c9561b5
MJ
4221 &caller_count))
4222 return false;
4223
4224 if (dump_file && (dump_flags & TDF_DETAILS))
4225 {
4226 fprintf (dump_file, " - considering value ");
4227 print_ipcp_constant_value (dump_file, val->value);
0e8853ee
JH
4228 fprintf (dump_file, " for ");
4229 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
2c9561b5
MJ
4230 if (offset != -1)
4231 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset);
4232 fprintf (dump_file, " (caller_count: %i)\n", caller_count);
4233 }
4234
4235 if (!good_cloning_opportunity_p (node, val->local_time_benefit,
4236 freq_sum, count_sum,
4237 val->local_size_cost)
4238 && !good_cloning_opportunity_p (node,
4239 val->local_time_benefit
4240 + val->prop_time_benefit,
4241 freq_sum, count_sum,
4242 val->local_size_cost
4243 + val->prop_size_cost))
4244 return false;
4245
4246 if (dump_file)
4247 fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
fec39fa6 4248 node->name (), node->order);
2c9561b5 4249
47f4756e 4250 callers = gather_edges_for_value (val, node, caller_count);
2c9561b5 4251 if (offset == -1)
44210a96
MJ
4252 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index);
4253 else
4254 {
4255 known_csts = known_csts.copy ();
4256 known_contexts = copy_useful_known_contexts (known_contexts);
4257 }
4258 find_more_scalar_values_for_callers_subset (node, known_csts, callers);
4259 find_more_contexts_for_caller_subset (node, &known_contexts, callers);
2c9561b5 4260 aggvals = find_aggregate_values_for_callers_subset (node, callers);
44210a96
MJ
4261 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index,
4262 offset, val->value));
4263 val->spec_node = create_specialized_node (node, known_csts, known_contexts,
4264 aggvals, callers);
2c9561b5
MJ
4265 overall_size += val->local_size_cost;
4266
4267 /* TODO: If for some lattice there is only one other known value
4268 left, make a special node for it too. */
4269
4270 return true;
4271}
5e45130d 4272
310bc633 4273/* Decide whether and what specialized clones of NODE should be created. */
5e45130d 4274
310bc633
MJ
4275static bool
4276decide_whether_version_node (struct cgraph_node *node)
4277{
4278 struct ipa_node_params *info = IPA_NODE_REF (node);
4279 int i, count = ipa_get_param_count (info);
44210a96
MJ
4280 vec<tree> known_csts;
4281 vec<ipa_polymorphic_call_context> known_contexts;
84562394 4282 vec<ipa_agg_jump_function> known_aggs = vNULL;
310bc633 4283 bool ret = false;
5e45130d 4284
310bc633
MJ
4285 if (count == 0)
4286 return false;
5e45130d 4287
310bc633
MJ
4288 if (dump_file && (dump_flags & TDF_DETAILS))
4289 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
fec39fa6 4290 node->name (), node->order);
5e45130d 4291
44210a96 4292 gather_context_independent_values (info, &known_csts, &known_contexts,
eb20b778
MJ
4293 info->do_clone_for_all_contexts ? &known_aggs
4294 : NULL, NULL);
5e45130d 4295
2c9561b5 4296 for (i = 0; i < count ;i++)
310bc633 4297 {
2c9561b5 4298 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
c0cb5055 4299 ipcp_lattice<tree> *lat = &plats->itself;
44210a96 4300 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
5e45130d 4301
2c9561b5 4302 if (!lat->bottom
44210a96
MJ
4303 && !known_csts[i])
4304 {
4305 ipcp_value<tree> *val;
4306 for (val = lat->values; val; val = val->next)
4307 ret |= decide_about_value (node, i, -1, val, known_csts,
4308 known_contexts);
4309 }
61e03ffc 4310
eb20b778 4311 if (!plats->aggs_bottom)
518dc859 4312 {
2c9561b5 4313 struct ipcp_agg_lattice *aglat;
c0cb5055 4314 ipcp_value<tree> *val;
2c9561b5
MJ
4315 for (aglat = plats->aggs; aglat; aglat = aglat->next)
4316 if (!aglat->bottom && aglat->values
4317 /* If the following is false, the one value is in
4318 known_aggs. */
4319 && (plats->aggs_contain_variable
c0cb5055 4320 || !aglat->is_single_const ()))
2c9561b5
MJ
4321 for (val = aglat->values; val; val = val->next)
4322 ret |= decide_about_value (node, i, aglat->offset, val,
44210a96 4323 known_csts, known_contexts);
cc58ceee 4324 }
44210a96
MJ
4325
4326 if (!ctxlat->bottom
4327 && known_contexts[i].useless_p ())
4328 {
4329 ipcp_value<ipa_polymorphic_call_context> *val;
4330 for (val = ctxlat->values; val; val = val->next)
4331 ret |= decide_about_value (node, i, -1, val, known_csts,
4332 known_contexts);
4333 }
4334
2c9561b5 4335 info = IPA_NODE_REF (node);
310bc633 4336 }
cc58ceee 4337
eb20b778 4338 if (info->do_clone_for_all_contexts)
310bc633 4339 {
eb20b778 4340 struct cgraph_node *clone;
d52f5295 4341 vec<cgraph_edge *> callers;
cc58ceee 4342
310bc633
MJ
4343 if (dump_file)
4344 fprintf (dump_file, " - Creating a specialized node of %s/%i "
fec39fa6 4345 "for all known contexts.\n", node->name (),
67348ccc 4346 node->order);
5e45130d 4347
d52f5295 4348 callers = node->collect_callers ();
44210a96
MJ
4349
4350 if (!known_contexts_useful_p (known_contexts))
4351 {
4352 known_contexts.release ();
4353 known_contexts = vNULL;
4354 }
4355 clone = create_specialized_node (node, known_csts, known_contexts,
2c9561b5
MJ
4356 known_aggs_to_agg_replacement_list (known_aggs),
4357 callers);
310bc633 4358 info = IPA_NODE_REF (node);
eb20b778
MJ
4359 info->do_clone_for_all_contexts = false;
4360 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
90e709fd
JJ
4361 for (i = 0; i < count ; i++)
4362 vec_free (known_aggs[i].items);
4363 known_aggs.release ();
310bc633
MJ
4364 ret = true;
4365 }
4366 else
44210a96
MJ
4367 {
4368 known_csts.release ();
4369 known_contexts.release ();
4370 }
5e45130d 4371
310bc633
MJ
4372 return ret;
4373}
9187e02d 4374
310bc633 4375/* Transitively mark all callees of NODE within the same SCC as not dead. */
3949c4a7 4376
310bc633
MJ
4377static void
4378spread_undeadness (struct cgraph_node *node)
4379{
4380 struct cgraph_edge *cs;
5e45130d 4381
310bc633 4382 for (cs = node->callees; cs; cs = cs->next_callee)
4cb13597 4383 if (ipa_edge_within_scc (cs))
310bc633
MJ
4384 {
4385 struct cgraph_node *callee;
4386 struct ipa_node_params *info;
129a37fc 4387
d52f5295 4388 callee = cs->callee->function_symbol (NULL);
310bc633 4389 info = IPA_NODE_REF (callee);
5e45130d 4390
310bc633
MJ
4391 if (info->node_dead)
4392 {
4393 info->node_dead = 0;
4394 spread_undeadness (callee);
4395 }
4396 }
4397}
4398
4399/* Return true if NODE has a caller from outside of its SCC that is not
4400 dead. Worker callback for cgraph_for_node_and_aliases. */
4401
4402static bool
4403has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
4404 void *data ATTRIBUTE_UNUSED)
4405{
4406 struct cgraph_edge *cs;
4407
4408 for (cs = node->callers; cs; cs = cs->next_caller)
4409 if (cs->caller->thunk.thunk_p
d52f5295
ML
4410 && cs->caller->call_for_symbol_thunks_and_aliases
4411 (has_undead_caller_from_outside_scc_p, NULL, true))
310bc633 4412 return true;
4cb13597 4413 else if (!ipa_edge_within_scc (cs)
310bc633
MJ
4414 && !IPA_NODE_REF (cs->caller)->node_dead)
4415 return true;
4416 return false;
4417}
4418
4419
4420/* Identify nodes within the same SCC as NODE which are no longer needed
4421 because of new clones and will be removed as unreachable. */
4422
4423static void
4424identify_dead_nodes (struct cgraph_node *node)
4425{
4426 struct cgraph_node *v;
67348ccc 4427 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
d52f5295
ML
4428 if (v->will_be_removed_from_program_if_no_direct_calls_p ()
4429 && !v->call_for_symbol_thunks_and_aliases
4430 (has_undead_caller_from_outside_scc_p, NULL, true))
310bc633
MJ
4431 IPA_NODE_REF (v)->node_dead = 1;
4432
67348ccc 4433 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
310bc633
MJ
4434 if (!IPA_NODE_REF (v)->node_dead)
4435 spread_undeadness (v);
4436
4437 if (dump_file && (dump_flags & TDF_DETAILS))
4438 {
67348ccc 4439 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
310bc633
MJ
4440 if (IPA_NODE_REF (v)->node_dead)
4441 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
fec39fa6 4442 v->name (), v->order);
5e45130d 4443 }
310bc633
MJ
4444}
4445
4446/* The decision stage. Iterate over the topological order of call graph nodes
4447 TOPO and make specialized clones if deemed beneficial. */
4448
4449static void
11478306 4450ipcp_decision_stage (struct ipa_topo_info *topo)
310bc633
MJ
4451{
4452 int i;
4453
4454 if (dump_file)
4455 fprintf (dump_file, "\nIPA decision stage:\n\n");
5e45130d 4456
310bc633 4457 for (i = topo->nnodes - 1; i >= 0; i--)
5e45130d 4458 {
310bc633
MJ
4459 struct cgraph_node *node = topo->order[i];
4460 bool change = false, iterate = true;
4461
4462 while (iterate)
4463 {
4464 struct cgraph_node *v;
4465 iterate = false;
67348ccc 4466 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
d52f5295 4467 if (v->has_gimple_body_p ()
310bc633
MJ
4468 && ipcp_versionable_function_p (v))
4469 iterate |= decide_whether_version_node (v);
4470
4471 change |= iterate;
4472 }
4473 if (change)
4474 identify_dead_nodes (node);
518dc859 4475 }
518dc859
RL
4476}
4477
04be694e
MJ
4478/* Look up all alignment information that we have discovered and copy it over
4479 to the transformation summary. */
4480
4481static void
4482ipcp_store_alignment_results (void)
4483{
4484 cgraph_node *node;
4485
4486 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4487 {
4488 ipa_node_params *info = IPA_NODE_REF (node);
4489 bool dumped_sth = false;
4490 bool found_useful_result = false;
4491
3c99176a
L
4492 if (!opt_for_fn (node->decl, flag_ipa_cp_alignment))
4493 {
4494 if (dump_file)
4495 fprintf (dump_file, "Not considering %s for alignment discovery "
4496 "and propagate; -fipa-cp-alignment: disabled.\n",
4497 node->name ());
4498 continue;
4499 }
4500
04be694e
MJ
4501 if (info->ipcp_orig_node)
4502 info = IPA_NODE_REF (info->ipcp_orig_node);
4503
4504 unsigned count = ipa_get_param_count (info);
4505 for (unsigned i = 0; i < count ; i++)
4506 {
4507 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
c8710b5c
MJ
4508 if (!plats->alignment.bottom_p ()
4509 && !plats->alignment.top_p ())
04be694e 4510 {
c8710b5c 4511 gcc_checking_assert (plats->alignment.align > 0);
04be694e
MJ
4512 found_useful_result = true;
4513 break;
4514 }
4515 }
4516 if (!found_useful_result)
4517 continue;
4518
c8710b5c 4519 ipcp_grow_transformations_if_necessary ();
04be694e
MJ
4520 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
4521 vec_safe_reserve_exact (ts->alignments, count);
4522
4523 for (unsigned i = 0; i < count ; i++)
4524 {
4525 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
c8710b5c 4526 ipa_alignment al;
04be694e 4527
c8710b5c
MJ
4528 if (!plats->alignment.bottom_p ()
4529 && !plats->alignment.top_p ())
4530 {
4531 al.known = true;
4532 al.align = plats->alignment.align;
4533 al.misalign = plats->alignment.misalign;
4534 }
4535 else
4536 al.known = false;
04be694e 4537
c8710b5c
MJ
4538 ts->alignments->quick_push (al);
4539 if (!dump_file || !al.known)
04be694e
MJ
4540 continue;
4541 if (!dumped_sth)
4542 {
4543 fprintf (dump_file, "Propagated alignment info for function %s/%i:\n",
4544 node->name (), node->order);
4545 dumped_sth = true;
4546 }
4547 fprintf (dump_file, " param %i: align: %u, misalign: %u\n",
c8710b5c 4548 i, al.align, al.misalign);
04be694e
MJ
4549 }
4550 }
4551}
4552
518dc859 4553/* The IPCP driver. */
310bc633 4554
3cc1cccc 4555static unsigned int
518dc859
RL
4556ipcp_driver (void)
4557{
310bc633 4558 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
aef83682 4559 struct cgraph_edge_hook_list *edge_removal_hook_holder;
11478306 4560 struct ipa_topo_info topo;
310bc633 4561
310bc633
MJ
4562 ipa_check_create_node_params ();
4563 ipa_check_create_edge_args ();
aef83682 4564 grow_edge_clone_vectors ();
310bc633 4565 edge_duplication_hook_holder =
3dafb85c 4566 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
aef83682 4567 edge_removal_hook_holder =
3dafb85c 4568 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
aef83682 4569
518dc859
RL
4570 if (dump_file)
4571 {
ca30a539
JH
4572 fprintf (dump_file, "\nIPA structures before propagation:\n");
4573 if (dump_flags & TDF_DETAILS)
4574 ipa_print_all_params (dump_file);
4575 ipa_print_all_jump_functions (dump_file);
518dc859 4576 }
310bc633
MJ
4577
4578 /* Topological sort. */
4579 build_toporder_info (&topo);
4580 /* Do the interprocedural propagation. */
4581 ipcp_propagate_stage (&topo);
4582 /* Decide what constant propagation and cloning should be performed. */
4583 ipcp_decision_stage (&topo);
04be694e
MJ
4584 /* Store results of alignment propagation. */
4585 ipcp_store_alignment_results ();
310bc633 4586
518dc859 4587 /* Free all IPCP structures. */
310bc633 4588 free_toporder_info (&topo);
9771b263 4589 next_edge_clone.release ();
31b27938 4590 prev_edge_clone.release ();
3dafb85c
ML
4591 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4592 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
e33c6cd6 4593 ipa_free_all_structures_after_ipa_cp ();
518dc859
RL
4594 if (dump_file)
4595 fprintf (dump_file, "\nIPA constant propagation end\n");
c2924966 4596 return 0;
518dc859
RL
4597}
4598
3949c4a7
MJ
4599/* Initialization and computation of IPCP data structures. This is the initial
4600 intraprocedural analysis of functions, which gathers information to be
4601 propagated later on. */
4602
129a37fc
JH
4603static void
4604ipcp_generate_summary (void)
4605{
3949c4a7
MJ
4606 struct cgraph_node *node;
4607
129a37fc
JH
4608 if (dump_file)
4609 fprintf (dump_file, "\nIPA constant propagation start:\n");
129a37fc 4610 ipa_register_cgraph_hooks ();
3949c4a7 4611
c47d0034 4612 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
7e729474 4613 ipa_analyze_node (node);
129a37fc
JH
4614}
4615
fb3f88cc 4616/* Write ipcp summary for nodes in SET. */
310bc633 4617
fb3f88cc 4618static void
f27c1867 4619ipcp_write_summary (void)
fb3f88cc 4620{
f27c1867 4621 ipa_prop_write_jump_functions ();
fb3f88cc
JH
4622}
4623
4624/* Read ipcp summary. */
310bc633 4625
fb3f88cc
JH
4626static void
4627ipcp_read_summary (void)
4628{
4629 ipa_prop_read_jump_functions ();
4630}
4631
27a4cd48
DM
4632namespace {
4633
4634const pass_data pass_data_ipa_cp =
4635{
4636 IPA_PASS, /* type */
4637 "cp", /* name */
4638 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
4639 TV_IPA_CONSTANT_PROP, /* tv_id */
4640 0, /* properties_required */
4641 0, /* properties_provided */
4642 0, /* properties_destroyed */
4643 0, /* todo_flags_start */
4644 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
518dc859 4645};
27a4cd48
DM
4646
4647class pass_ipa_cp : public ipa_opt_pass_d
4648{
4649public:
c3284718
RS
4650 pass_ipa_cp (gcc::context *ctxt)
4651 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
4652 ipcp_generate_summary, /* generate_summary */
4653 ipcp_write_summary, /* write_summary */
4654 ipcp_read_summary, /* read_summary */
04be694e 4655 ipcp_write_transformation_summaries, /*
c3284718 4656 write_optimization_summary */
04be694e 4657 ipcp_read_transformation_summaries, /*
c3284718
RS
4658 read_optimization_summary */
4659 NULL, /* stmt_fixup */
4660 0, /* function_transform_todo_flags_start */
4661 ipcp_transform_function, /* function_transform */
4662 NULL) /* variable_transform */
27a4cd48
DM
4663 {}
4664
4665 /* opt_pass methods: */
1a3d085c
TS
4666 virtual bool gate (function *)
4667 {
4668 /* FIXME: We should remove the optimize check after we ensure we never run
4669 IPA passes when not optimizing. */
2bf86c84 4670 return (flag_ipa_cp && optimize) || in_lto_p;
1a3d085c
TS
4671 }
4672
be55bfe6 4673 virtual unsigned int execute (function *) { return ipcp_driver (); }
27a4cd48
DM
4674
4675}; // class pass_ipa_cp
4676
4677} // anon namespace
4678
4679ipa_opt_pass_d *
4680make_pass_ipa_cp (gcc::context *ctxt)
4681{
4682 return new pass_ipa_cp (ctxt);
4683}
3edf64aa
DM
4684
4685/* Reset all state within ipa-cp.c so that we can rerun the compiler
4686 within the same process. For use by toplev::finalize. */
4687
4688void
4689ipa_cp_c_finalize (void)
4690{
4691 max_count = 0;
4692 overall_size = 0;
4693 max_new_size = 0;
3edf64aa 4694}