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