]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-cp.c
2015-07-07 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / ipa-cp.c
CommitLineData
3b22db66 1/* Interprocedural constant propagation
d353bf18 2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
821d0e0f 3
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
5 <mjambor@suse.cz>
48e1416a 6
3b22db66 7This file is part of GCC.
48e1416a 8
3b22db66 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
8c4c00c1 11Software Foundation; either version 3, or (at your option) any later
3b22db66 12version.
48e1416a 13
3b22db66 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.
48e1416a 18
3b22db66 19You should have received a copy of the GNU General Public License
8c4c00c1 20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
3b22db66 22
821d0e0f 23/* Interprocedural constant propagation (IPA-CP).
48e1416a 24
821d0e0f 25 The goal of this transformation is to
d60eadfa 26
821d0e0f 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
d60eadfa 30
821d0e0f 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.
48e1416a 35
821d0e0f 36 The algorithm also propagates types and attempts to perform type based
37 devirtualization. Types are propagated much like constants.
48e1416a 38
821d0e0f 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.
d60eadfa 47
821d0e0f 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.
48e1416a 52
3b22db66 53
54 First stage - intraprocedural analysis
55 =======================================
821d0e0f 56
d60eadfa 57 This phase computes jump_function and modification flags.
48e1416a 58
821d0e0f 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.
85694bac 65 Constant - a constant is passed as an actual argument.
3b22db66 66 Unknown - neither of the above.
48e1416a 67
821d0e0f 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.
48e1416a 70
821d0e0f 71 ipcp_generate_summary() is the main function of the first stage.
3b22db66 72
73 Second stage - interprocedural analysis
74 ========================================
48e1416a 75
821d0e0f 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.
48e1416a 79
821d0e0f 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
9d75589a 84 propagate cumulative information about these effects from dependent values
821d0e0f 85 to those on which they depend.
3b22db66 86
821d0e0f 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.
3b22db66 92
821d0e0f 93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
94 third stage.
95
96 Third phase - materialization of clones, call statement updates.
3b22db66 97 ============================================
821d0e0f 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. */
3b22db66 102
103#include "config.h"
104#include "system.h"
105#include "coretypes.h"
b20a8bb4 106#include "alias.h"
3b22db66 107#include "tree.h"
9ef16211 108#include "options.h"
b20a8bb4 109#include "fold-const.h"
bc61cadb 110#include "gimple-fold.h"
111#include "gimple-expr.h"
3b22db66 112#include "target.h"
9ef16211 113#include "backend.h"
1140c305 114#include "hard-reg-set.h"
1140c305 115#include "cgraph.h"
116#include "alloc-pool.h"
2cc80ac3 117#include "symbol-summary.h"
3b22db66 118#include "ipa-prop.h"
3b22db66 119#include "tree-pass.h"
120#include "flags.h"
3b22db66 121#include "diagnostic.h"
ce084dfc 122#include "tree-pretty-print.h"
8624b7fc 123#include "tree-inline.h"
2a15795f 124#include "params.h"
c7b2cc59 125#include "ipa-inline.h"
821d0e0f 126#include "ipa-utils.h"
3b22db66 127
9bfdb7bc 128template <typename valtype> class ipcp_value;
11b73810 129
821d0e0f 130/* Describes a particular source for an IPA-CP value. */
11b73810 131
9bfdb7bc 132template <typename valtype>
133class ipcp_value_source
821d0e0f 134{
9bfdb7bc 135public:
803a7988 136 /* Aggregate offset of the source, negative if the source is scalar value of
137 the argument itself. */
138 HOST_WIDE_INT offset;
821d0e0f 139 /* The incoming edge that brought the value. */
9bfdb7bc 140 cgraph_edge *cs;
821d0e0f 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. */
9bfdb7bc 144 ipcp_value<valtype> *val;
821d0e0f 145 /* Next pointer in a linked list of sources of a value. */
9bfdb7bc 146 ipcp_value_source *next;
821d0e0f 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};
11b73810 152
9bfdb7bc 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
821d0e0f 166/* Describes one particular value stored in struct ipcp_lattice. */
11b73810 167
9bfdb7bc 168template <typename valtype>
169class ipcp_value : public ipcp_value_base
3b22db66 170{
9bfdb7bc 171public:
172 /* The actual value for the given parameter. */
173 valtype value;
821d0e0f 174 /* The list of sources from which this value originates. */
9bfdb7bc 175 ipcp_value_source <valtype> *sources;
821d0e0f 176 /* Next pointers in a linked list of all values in a lattice. */
9bfdb7bc 177 ipcp_value *next;
821d0e0f 178 /* Next pointers in a linked list of values in a strongly connected component
179 of values. */
9bfdb7bc 180 ipcp_value *scc_next;
821d0e0f 181 /* Next pointers in a linked list of SCCs of values sorted topologically
182 according their sources. */
9bfdb7bc 183 ipcp_value *topo_next;
821d0e0f 184 /* A specialized node created for this value, NULL if none has been (so far)
185 created. */
9bfdb7bc 186 cgraph_node *spec_node;
821d0e0f 187 /* Depth first search number and low link for topological sorting of
188 values. */
189 int dfs, low_link;
821d0e0f 190 /* True if this valye is currently on the topo-sort stack. */
191 bool on_stack;
9bfdb7bc 192
193 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
194 HOST_WIDE_INT offset);
821d0e0f 195};
3b22db66 196
803a7988 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
821d0e0f 201 contains_variable flag should be disregarded. */
202
9bfdb7bc 203template <typename valtype>
204class ipcp_lattice
3b22db66 205{
9bfdb7bc 206public:
821d0e0f 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. */
9bfdb7bc 210 ipcp_value<valtype> *values;
821d0e0f 211 /* Number of known values and types in this lattice. */
212 int values_count;
803a7988 213 /* The lattice contains a variable component (in addition to values). */
821d0e0f 214 bool contains_variable;
215 /* The value of the lattice is bottom (i.e. variable and unusable for any
216 propagation). */
217 bool bottom;
9bfdb7bc 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);
803a7988 226};
227
9bfdb7bc 228/* Lattice of tree values with an offset to describe a part of an
229 aggregate. */
803a7988 230
9bfdb7bc 231class ipcp_agg_lattice : public ipcp_lattice<tree>
803a7988 232{
9bfdb7bc 233public:
803a7988 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
9bfdb7bc 247class ipcp_param_lattices
803a7988 248{
9bfdb7bc 249public:
803a7988 250 /* Lattice describing the value of the parameter itself. */
9bfdb7bc 251 ipcp_lattice<tree> itself;
245ab191 252 /* Lattice describing the the polymorphic contexts of a parameter. */
253 ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
803a7988 254 /* Lattices describing aggregate parts. */
9bfdb7bc 255 ipcp_agg_lattice *aggs;
ae7b7bc8 256 /* Alignment information. Very basic one value lattice where !known means
257 TOP and zero alignment bottom. */
258 ipa_alignment alignment;
803a7988 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
821d0e0f 271 /* There is a virtual call based on this parameter. */
272 bool virt_call;
273};
3b22db66 274
803a7988 275/* Allocation pools for values and their sources in ipa-cp. */
276
8361d32f 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);
803a7988 288
821d0e0f 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
803a7988 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)
3b22db66 301{
03f99d3c 302 gcc_assert (i >= 0 && i < ipa_get_param_count (info));
821d0e0f 303 gcc_checking_assert (!info->ipcp_orig_node);
304 gcc_checking_assert (info->lattices);
305 return &(info->lattices[i]);
3b22db66 306}
307
803a7988 308/* Return the lattice corresponding to the scalar value of the Ith formal
309 parameter of the function described by INFO. */
9bfdb7bc 310static inline ipcp_lattice<tree> *
803a7988 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
245ab191 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
821d0e0f 326/* Return whether LAT is a lattice with a single constant and without an
327 undefined value. */
328
9bfdb7bc 329template <typename valtype>
330inline bool
331ipcp_lattice<valtype>::is_single_const ()
3b22db66 332{
9bfdb7bc 333 if (bottom || contains_variable || values_count != 1)
3b22db66 334 return false;
821d0e0f 335 else
336 return true;
3b22db66 337}
338
821d0e0f 339/* Print V which is extracted from a value in a lattice to F. */
340
3b22db66 341static void
821d0e0f 342print_ipcp_constant_value (FILE * f, tree v)
3b22db66 343{
693010ae 344 if (TREE_CODE (v) == ADDR_EXPR
821d0e0f 345 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
3b22db66 346 {
821d0e0f 347 fprintf (f, "& ");
348 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0);
3b22db66 349 }
821d0e0f 350 else
351 print_generic_expr (f, v, 0);
3b22db66 352}
353
245ab191 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
803a7988 362/* Print a lattice LAT to F. */
363
9bfdb7bc 364template <typename valtype>
365void
366ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
803a7988 367{
9bfdb7bc 368 ipcp_value<valtype> *val;
803a7988 369 bool prev = false;
370
9bfdb7bc 371 if (bottom)
803a7988 372 {
373 fprintf (f, "BOTTOM\n");
374 return;
375 }
376
9bfdb7bc 377 if (!values_count && !contains_variable)
803a7988 378 {
379 fprintf (f, "TOP\n");
380 return;
381 }
382
9bfdb7bc 383 if (contains_variable)
803a7988 384 {
385 fprintf (f, "VARIABLE");
386 prev = true;
387 if (dump_benefits)
388 fprintf (f, "\n");
389 }
390
9bfdb7bc 391 for (val = values; val; val = val->next)
803a7988 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 {
9bfdb7bc 404 ipcp_value_source<valtype> *s;
803a7988 405
406 fprintf (f, " [from:");
407 for (s = val->sources; s; s = s->next)
02774f2d 408 fprintf (f, " %i(%i)", s->cs->caller->order,
15c999e3 409 s->cs->frequency);
803a7988 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
d60eadfa 423/* Print all ipcp_lattices of all functions to F. */
821d0e0f 424
3b22db66 425static void
821d0e0f 426print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
3b22db66 427{
428 struct cgraph_node *node;
429 int i, count;
8624b7fc 430
821d0e0f 431 fprintf (f, "\nLattices:\n");
432 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3b22db66 433 {
86c96e3a 434 struct ipa_node_params *info;
435
86c96e3a 436 info = IPA_NODE_REF (node);
f1c8b4d7 437 fprintf (f, " Node: %s/%i:\n", node->name (),
02774f2d 438 node->order);
d60eadfa 439 count = ipa_get_param_count (info);
3b22db66 440 for (i = 0; i < count; i++)
441 {
803a7988 442 struct ipcp_agg_lattice *aglat;
443 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
11b73810 444 fprintf (f, " param [%d]: ", i);
9bfdb7bc 445 plats->itself.print (f, dump_sources, dump_benefits);
245ab191 446 fprintf (f, " ctxs: ");
447 plats->ctxlat.print (f, dump_sources, dump_benefits);
ae7b7bc8 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");
803a7988 455 if (plats->virt_call)
456 fprintf (f, " virt_call flag set\n");
457
458 if (plats->aggs_bottom)
821d0e0f 459 {
803a7988 460 fprintf (f, " AGGS BOTTOM\n");
821d0e0f 461 continue;
462 }
803a7988 463 if (plats->aggs_contain_variable)
464 fprintf (f, " AGGS VARIABLE\n");
465 for (aglat = plats->aggs; aglat; aglat = aglat->next)
821d0e0f 466 {
803a7988 467 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
468 plats->aggs_by_ref ? "ref " : "", aglat->offset);
9bfdb7bc 469 aglat->print (f, dump_sources, dump_benefits);
821d0e0f 470 }
3b22db66 471 }
472 }
473}
474
821d0e0f 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. */
d747fdfb 478
821d0e0f 479static void
480determine_versionability (struct cgraph_node *node)
d747fdfb 481{
821d0e0f 482 const char *reason = NULL;
eae7682a 483
77b05e95 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. */
02774f2d 487 if (node->alias || node->thunk.thunk_p)
821d0e0f 488 reason = "alias or thunk";
c8d92fc1 489 else if (!node->local.versionable)
03f99d3c 490 reason = "not a tree_versionable_function";
415d1b9a 491 else if (node->get_availability () <= AVAIL_INTERPOSABLE)
821d0e0f 492 reason = "insufficient body availability";
83167671 493 else if (!opt_for_fn (node->decl, optimize)
494 || !opt_for_fn (node->decl, flag_ipa_cp))
495 reason = "non-optimized function";
d09768a4 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 }
468088ac 503 /* Don't clone decls local to a comdat group; it breaks and for C++
504 decloned constructors, inlining is always better anyway. */
415d1b9a 505 else if (node->comdat_local_p ())
468088ac 506 reason = "comdat-local function";
d747fdfb 507
02774f2d 508 if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
821d0e0f 509 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
f1c8b4d7 510 node->name (), node->order, reason);
d747fdfb 511
c8d92fc1 512 node->local.versionable = (reason == NULL);
d747fdfb 513}
514
821d0e0f 515/* Return true if it is at all technically possible to create clones of a
516 NODE. */
517
11b73810 518static bool
821d0e0f 519ipcp_versionable_function_p (struct cgraph_node *node)
11b73810 520{
c8d92fc1 521 return node->local.versionable;
821d0e0f 522}
11b73810 523
821d0e0f 524/* Structure holding accumulated information about callers of a node. */
4855a75d 525
821d0e0f 526struct caller_statistics
527{
528 gcov_type count_sum;
529 int n_calls, n_hot_calls, freq_sum;
530};
11b73810 531
821d0e0f 532/* Initialize fields of STAT to zeroes. */
7f74ac6b 533
821d0e0f 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)
675f1812 553 if (!cs->caller->thunk.thunk_p)
821d0e0f 554 {
555 stats->count_sum += cs->count;
556 stats->freq_sum += cs->frequency;
557 stats->n_calls++;
35ee1c66 558 if (cs->maybe_hot_p ())
821d0e0f 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
415d1b9a 572 gcc_checking_assert (node->has_gimple_body_p ());
48e1416a 573
d1f68cd8 574 if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
11b73810 575 {
576 if (dump_file)
821d0e0f 577 fprintf (dump_file, "Not considering %s for cloning; "
578 "-fipa-cp-clone disabled.\n",
f1c8b4d7 579 node->name ());
11b73810 580 return false;
581 }
11b73810 582
02774f2d 583 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
11b73810 584 {
585 if (dump_file)
821d0e0f 586 fprintf (dump_file, "Not considering %s for cloning; "
587 "optimizing it for size.\n",
f1c8b4d7 588 node->name ());
11b73810 589 return false;
590 }
591
821d0e0f 592 init_caller_stats (&stats);
415d1b9a 593 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
821d0e0f 594
b4bae7a0 595 if (inline_summaries->get (node)->self_size < stats.n_calls)
11b73810 596 {
597 if (dump_file)
821d0e0f 598 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
f1c8b4d7 599 node->name ());
821d0e0f 600 return true;
11b73810 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
0a10fd82 605 significantly. */
11b73810 606 if (max_count)
607 {
821d0e0f 608 if (stats.count_sum > node->count * 90 / 100)
11b73810 609 {
610 if (dump_file)
821d0e0f 611 fprintf (dump_file, "Considering %s for cloning; "
612 "usually called directly.\n",
f1c8b4d7 613 node->name ());
11b73810 614 return true;
615 }
616 }
821d0e0f 617 if (!stats.n_hot_calls)
11b73810 618 {
619 if (dump_file)
620 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
f1c8b4d7 621 node->name ());
a111083a 622 return false;
11b73810 623 }
624 if (dump_file)
625 fprintf (dump_file, "Considering %s for cloning.\n",
f1c8b4d7 626 node->name ());
11b73810 627 return true;
628}
629
9bfdb7bc 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
821d0e0f 647/* Arrays representing a topological ordering of call graph nodes and a stack
9bfdb7bc 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. */
1caef38b 651
9bfdb7bc 652class ipa_topo_info
1caef38b 653{
9bfdb7bc 654public:
655 /* Array with obtained topological order of cgraph nodes. */
821d0e0f 656 struct cgraph_node **order;
9bfdb7bc 657 /* Stack of cgraph nodes used during propagation within SCC until all values
658 in the SCC stabilize. */
821d0e0f 659 struct cgraph_node **stack;
660 int nnodes, stack_top;
9bfdb7bc 661
662 value_topo_info<tree> constants;
245ab191 663 value_topo_info<ipa_polymorphic_call_context> contexts;
9bfdb7bc 664
665 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
666 constants ()
667 {}
821d0e0f 668};
669
670/* Allocate the arrays in TOPO and topologically sort the nodes into order. */
671
672static void
9908fe4d 673build_toporder_info (struct ipa_topo_info *topo)
821d0e0f 674{
35ee1c66 675 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
676 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
677
9bfdb7bc 678 gcc_checking_assert (topo->stack_top == 0);
821d0e0f 679 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
1caef38b 680}
681
821d0e0f 682/* Free information about strongly connected components and the arrays in
683 TOPO. */
684
3b22db66 685static void
9908fe4d 686free_toporder_info (struct ipa_topo_info *topo)
821d0e0f 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
9908fe4d 696push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node)
3b22db66 697{
d60eadfa 698 struct ipa_node_params *info = IPA_NODE_REF (node);
821d0e0f 699 if (info->node_enqueued)
700 return;
701 info->node_enqueued = 1;
702 topo->stack[topo->stack_top++] = node;
703}
3b22db66 704
821d0e0f 705/* Pop a node from the stack in TOPO and return it or return NULL if the stack
706 is empty. */
11b73810 707
821d0e0f 708static struct cgraph_node *
9908fe4d 709pop_node_from_stack (struct ipa_topo_info *topo)
821d0e0f 710{
711 if (topo->stack_top)
1caef38b 712 {
821d0e0f 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;
1caef38b 718 }
821d0e0f 719 else
720 return NULL;
3b22db66 721}
722
821d0e0f 723/* Set lattice LAT to bottom and return true if it previously was not set as
724 such. */
725
9bfdb7bc 726template <typename valtype>
727inline bool
728ipcp_lattice<valtype>::set_to_bottom ()
3b22db66 729{
9bfdb7bc 730 bool ret = !bottom;
731 bottom = true;
821d0e0f 732 return ret;
733}
3b22db66 734
821d0e0f 735/* Mark lattice as containing an unknown value and return true if it previously
736 was not marked as such. */
50828ed8 737
9bfdb7bc 738template <typename valtype>
739inline bool
740ipcp_lattice<valtype>::set_contains_variable ()
821d0e0f 741{
9bfdb7bc 742 bool ret = !contains_variable;
743 contains_variable = true;
821d0e0f 744 return ret;
3b22db66 745}
746
803a7988 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
ae7b7bc8 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
803a7988 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{
245ab191 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);
ae7b7bc8 800 ret |= set_alignment_to_bottom (plats);
803a7988 801 return ret;
802}
803
39fcd838 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 {
39fcd838 832 IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
833 return true;
834 }
835 return false;
836}
837
821d0e0f 838/* Initialize ipcp_lattices. */
5fce5299 839
3b22db66 840static void
821d0e0f 841initialize_node_lattices (struct cgraph_node *node)
3b22db66 842{
821d0e0f 843 struct ipa_node_params *info = IPA_NODE_REF (node);
844 struct cgraph_edge *ie;
845 bool disable = false, variable = false;
846 int i;
3b22db66 847
415d1b9a 848 gcc_checking_assert (node->has_gimple_body_p ());
39fcd838 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
821d0e0f 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 }
3b22db66 870
821d0e0f 871 if (disable || variable)
872 {
873 for (i = 0; i < ipa_get_param_count (info) ; i++)
874 {
803a7988 875 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
821d0e0f 876 if (disable)
803a7988 877 {
9bfdb7bc 878 plats->itself.set_to_bottom ();
245ab191 879 plats->ctxlat.set_to_bottom ();
803a7988 880 set_agg_lats_to_bottom (plats);
ae7b7bc8 881 set_alignment_to_bottom (plats);
803a7988 882 }
821d0e0f 883 else
803a7988 884 set_all_contains_variable (plats);
821d0e0f 885 }
886 if (dump_file && (dump_flags & TDF_DETAILS)
02774f2d 887 && !node->alias && !node->thunk.thunk_p)
821d0e0f 888 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
f1c8b4d7 889 node->name (), node->order,
821d0e0f 890 disable ? "BOTTOM" : "VARIABLE");
891 }
3b22db66 892
821d0e0f 893 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
f5e35fed 894 if (ie->indirect_info->polymorphic
895 && ie->indirect_info->param_index >= 0)
eae7682a 896 {
821d0e0f 897 gcc_checking_assert (ie->indirect_info->param_index >= 0);
803a7988 898 ipa_get_parm_lattices (info,
899 ie->indirect_info->param_index)->virt_call = 1;
eae7682a 900 }
3b22db66 901}
902
821d0e0f 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
ad4a8b28 905 determined or be considered an interprocedural invariant. */
1caef38b 906
821d0e0f 907static tree
908ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
1caef38b 909{
821d0e0f 910 tree restype, res;
1caef38b 911
693010ae 912 gcc_checking_assert (is_gimple_ip_invariant (input));
4fa83f96 913 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
821d0e0f 914 return input;
1caef38b 915
4fa83f96 916 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
821d0e0f 917 == tcc_comparison)
918 restype = boolean_type_node;
919 else
920 restype = TREE_TYPE (input);
4fa83f96 921 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
922 input, ipa_get_jf_pass_through_operand (jfunc));
1caef38b 923
821d0e0f 924 if (res && !is_gimple_ip_invariant (res))
925 return NULL_TREE;
1caef38b 926
821d0e0f 927 return res;
1caef38b 928}
929
821d0e0f 930/* Return the result of an ancestor jump function JFUNC on the constant value
931 INPUT. Return NULL_TREE if that cannot be determined. */
1caef38b 932
821d0e0f 933static tree
934ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
1caef38b 935{
245ab191 936 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO);
937 if (TREE_CODE (input) == ADDR_EXPR)
1caef38b 938 {
821d0e0f 939 tree t = TREE_OPERAND (input, 0);
940 t = build_ref_for_offset (EXPR_LOCATION (t), t,
4fa83f96 941 ipa_get_jf_ancestor_offset (jfunc),
693010ae 942 ptr_type_node, NULL, false);
821d0e0f 943 return build_fold_addr_expr (t);
1caef38b 944 }
945 else
821d0e0f 946 return NULL_TREE;
947}
1caef38b 948
245ab191 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
821d0e0f 952 evaluated. */
953
20da2013 954tree
821d0e0f 955ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
956{
957 if (jfunc->type == IPA_JF_CONST)
4fa83f96 958 return ipa_get_jf_constant (jfunc);
821d0e0f 959 else if (jfunc->type == IPA_JF_PASS_THROUGH
960 || jfunc->type == IPA_JF_ANCESTOR)
1caef38b 961 {
821d0e0f 962 tree input;
963 int idx;
1caef38b 964
821d0e0f 965 if (jfunc->type == IPA_JF_PASS_THROUGH)
4fa83f96 966 idx = ipa_get_jf_pass_through_formal_id (jfunc);
821d0e0f 967 else
4fa83f96 968 idx = ipa_get_jf_ancestor_formal_id (jfunc);
1caef38b 969
821d0e0f 970 if (info->ipcp_orig_node)
245ab191 971 input = info->known_csts[idx];
821d0e0f 972 else
1caef38b 973 {
9bfdb7bc 974 ipcp_lattice<tree> *lat;
821d0e0f 975
49c97b81 976 if (!info->lattices
977 || idx >= ipa_get_param_count (info))
d1f68cd8 978 return NULL_TREE;
803a7988 979 lat = ipa_get_scalar_lat (info, idx);
9bfdb7bc 980 if (!lat->is_single_const ())
821d0e0f 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)
4fa83f96 989 return ipa_get_jf_pass_through_result (jfunc, input);
821d0e0f 990 else
4fa83f96 991 return ipa_get_jf_ancestor_result (jfunc, input);
1caef38b 992 }
821d0e0f 993 else
994 return NULL_TREE;
1caef38b 995}
996
245ab191 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;
9a271891 1019 bool type_preserved = true;
245ab191 1020 if (jfunc->type == IPA_JF_PASS_THROUGH)
1021 {
9a271891 1022 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
245ab191 1023 return ctx;
9a271891 1024 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
245ab191 1025 srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
1026 }
1027 else
1028 {
9a271891 1029 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
245ab191 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 {
49c97b81 1039 if (!info->lattices
1040 || srcidx >= ipa_get_param_count (info))
d1f68cd8 1041 return ctx;
245ab191 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));
9a271891 1052 if (!type_preserved)
1053 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
1054 srcctx.combine_with (ctx);
1055 return srcctx;
245ab191 1056 }
1057
1058 return ctx;
1059}
1caef38b 1060
821d0e0f 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. */
1caef38b 1064
821d0e0f 1065DEBUG_FUNCTION void
1066ipcp_verify_propagated_values (void)
3b22db66 1067{
821d0e0f 1068 struct cgraph_node *node;
11b73810 1069
821d0e0f 1070 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3b22db66 1071 {
d60eadfa 1072 struct ipa_node_params *info = IPA_NODE_REF (node);
821d0e0f 1073 int i, count = ipa_get_param_count (info);
d60eadfa 1074
821d0e0f 1075 for (i = 0; i < count; i++)
3b22db66 1076 {
9bfdb7bc 1077 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
d60eadfa 1078
821d0e0f 1079 if (!lat->bottom
1080 && !lat->contains_variable
1081 && lat->values_count == 0)
3b22db66 1082 {
821d0e0f 1083 if (dump_file)
3b22db66 1084 {
415d1b9a 1085 symtab_node::dump_table (dump_file);
821d0e0f 1086 fprintf (dump_file, "\nIPA lattices after constant "
3083a0b3 1087 "propagation, before gcc_unreachable:\n");
821d0e0f 1088 print_all_lattices (dump_file, true, false);
3b22db66 1089 }
1caef38b 1090
821d0e0f 1091 gcc_unreachable ();
3b22db66 1092 }
1093 }
1094 }
1095}
1096
821d0e0f 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
821d0e0f 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
245ab191 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
9bfdb7bc 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. */
821d0e0f 1132
9bfdb7bc 1133template <typename valtype>
1134void
1135ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
1136 int src_idx, HOST_WIDE_INT offset)
3b22db66 1137{
9bfdb7bc 1138 ipcp_value_source<valtype> *src;
11b73810 1139
8361d32f 1140 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>;
803a7988 1141 src->offset = offset;
821d0e0f 1142 src->cs = cs;
1143 src->val = src_val;
1144 src->index = src_idx;
8867b500 1145
9bfdb7bc 1146 src->next = sources;
1147 sources = src;
821d0e0f 1148}
1149
9bfdb7bc 1150/* Allocate a new ipcp_value holding a tree constant, initialize its value to
1151 SOURCE and clear all other fields. */
821d0e0f 1152
9bfdb7bc 1153static ipcp_value<tree> *
1154allocate_and_init_ipcp_value (tree source)
821d0e0f 1155{
9bfdb7bc 1156 ipcp_value<tree> *val;
821d0e0f 1157
8361d32f 1158 val = ipcp_cst_values_pool.allocate ();
245ab191 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
8361d32f 1172 // TODO
1173 val = ipcp_poly_ctx_values_pool.allocate ();
9bfdb7bc 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)
821d0e0f 1193 return false;
1194
9bfdb7bc 1195 for (val = values; val; val = val->next)
821d0e0f 1196 if (values_equal_for_ipcp_p (val->value, newval))
1197 {
a0255a70 1198 if (ipa_edge_within_scc (cs))
821d0e0f 1199 {
9bfdb7bc 1200 ipcp_value_source<valtype> *s;
821d0e0f 1201 for (s = val->sources; s ; s = s->next)
1202 if (s->cs == cs)
1203 break;
1204 if (s)
1205 return false;
1206 }
1207
9bfdb7bc 1208 val->add_source (cs, src_val, src_idx, offset);
821d0e0f 1209 return false;
1210 }
1211
9bfdb7bc 1212 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
821d0e0f 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. */
9bfdb7bc 1216 for (val = values; val; val = val->next)
821d0e0f 1217 {
1218 while (val->sources)
1219 {
9bfdb7bc 1220 ipcp_value_source<valtype> *src = val->sources;
821d0e0f 1221 val->sources = src->next;
8361d32f 1222 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
821d0e0f 1223 }
1224 }
1225
9bfdb7bc 1226 values = NULL;
1227 return set_to_bottom ();
821d0e0f 1228 }
1229
9bfdb7bc 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;
821d0e0f 1235 return true;
1236}
8867b500 1237
821d0e0f 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
9bfdb7bc 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,
821d0e0f 1247 int src_idx)
1248{
9bfdb7bc 1249 ipcp_value<tree> *src_val;
821d0e0f 1250 bool ret = false;
1251
821d0e0f 1252 /* Do not create new values when propagating within an SCC because if there
4fa83f96 1253 are arithmetic functions with circular dependencies, there is infinite
1254 number of them and we would just make lattices bottom. */
ad4a8b28 1255 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
a0255a70 1256 && ipa_edge_within_scc (cs))
9bfdb7bc 1257 ret = dest_lat->set_contains_variable ();
821d0e0f 1258 else
1259 for (src_val = src_lat->values; src_val; src_val = src_val->next)
eae7682a 1260 {
ad4a8b28 1261 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
821d0e0f 1262
1263 if (cstval)
9bfdb7bc 1264 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
821d0e0f 1265 else
9bfdb7bc 1266 ret |= dest_lat->set_contains_variable ();
eae7682a 1267 }
821d0e0f 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,
9bfdb7bc 1279 ipcp_lattice<tree> *src_lat,
1280 ipcp_lattice<tree> *dest_lat,
821d0e0f 1281 int src_idx)
1282{
9bfdb7bc 1283 ipcp_value<tree> *src_val;
821d0e0f 1284 bool ret = false;
1285
a0255a70 1286 if (ipa_edge_within_scc (cs))
9bfdb7bc 1287 return dest_lat->set_contains_variable ();
821d0e0f 1288
1289 for (src_val = src_lat->values; src_val; src_val = src_val->next)
1290 {
4fa83f96 1291 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
821d0e0f 1292
1293 if (t)
9bfdb7bc 1294 ret |= dest_lat->add_value (t, cs, src_val, src_idx);
821d0e0f 1295 else
9bfdb7bc 1296 ret |= dest_lat->set_contains_variable ();
821d0e0f 1297 }
1298
1299 return ret;
1300}
1301
803a7988 1302/* Propagate scalar values across jump function JFUNC that is associated with
1303 edge CS and put the values into DEST_LAT. */
821d0e0f 1304
1305static bool
803a7988 1306propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
1307 struct ipa_jump_func *jfunc,
9bfdb7bc 1308 ipcp_lattice<tree> *dest_lat)
821d0e0f 1309{
1310 if (dest_lat->bottom)
1311 return false;
1312
245ab191 1313 if (jfunc->type == IPA_JF_CONST)
821d0e0f 1314 {
245ab191 1315 tree val = ipa_get_jf_constant (jfunc);
9bfdb7bc 1316 return dest_lat->add_value (val, cs, NULL, 0);
821d0e0f 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);
9bfdb7bc 1322 ipcp_lattice<tree> *src_lat;
821d0e0f 1323 int src_idx;
1324 bool ret;
1325
1326 if (jfunc->type == IPA_JF_PASS_THROUGH)
4fa83f96 1327 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
821d0e0f 1328 else
4fa83f96 1329 src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
821d0e0f 1330
803a7988 1331 src_lat = ipa_get_scalar_lat (caller_info, src_idx);
821d0e0f 1332 if (src_lat->bottom)
9bfdb7bc 1333 return dest_lat->set_contains_variable ();
821d0e0f 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)))
9bfdb7bc 1339 return dest_lat->set_contains_variable ();
821d0e0f 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)
9bfdb7bc 1349 ret |= dest_lat->set_contains_variable ();
821d0e0f 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. */
9bfdb7bc 1356 return dest_lat->set_contains_variable ();
821d0e0f 1357}
1358
245ab191 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;
9a271891 1372 bool type_preserved = true;
245ab191 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)
9a271891 1378 edge_ctx = *edge_ctx_ptr;
245ab191 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 {
9a271891 1392 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
245ab191 1393 goto prop_fail;
9a271891 1394 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
245ab191 1395 src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
1396 }
1397 else
1398 {
9a271891 1399 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
245ab191 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;
245ab191 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;
9a271891 1414
1415 if (!type_preserved)
1416 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
245ab191 1417 if (jfunc->type == IPA_JF_ANCESTOR)
1418 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
9a271891 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);
245ab191 1422 if (!cur.useless_p ())
1423 {
9a271891 1424 if (src_lat->contains_variable
1425 && !edge_ctx.equal_to (cur))
1426 ret |= dest_lat->set_contains_variable ();
245ab191 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
ae7b7bc8 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
f8298177 1475 && op != PLUS_EXPR)
ae7b7bc8 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);
f8298177 1487 offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;;
ae7b7bc8 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
803a7988 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 }
9bfdb7bc 1563 *change |= (**aglat)->set_contains_variable ();
803a7988 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++;
8361d32f 1592 new_al = ipcp_agg_lattice_pool.allocate ();
803a7988 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 {
9bfdb7bc 1614 ret |= aglat->set_contains_variable ();
803a7988 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);
36bcc547 1639 if (src_plats->aggs_contain_variable)
1640 ret |= set_agg_lats_contain_variable (dest_plats);
803a7988 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 {
9bfdb7bc 1659 ret |= new_al->set_contains_variable ();
803a7988 1660 continue;
1661 }
1662 if (src_aglat->contains_variable)
9bfdb7bc 1663 ret |= new_al->set_contains_variable ();
1664 for (ipcp_value<tree> *val = src_aglat->values;
803a7988 1665 val;
1666 val = val->next)
9bfdb7bc 1667 ret |= new_al->add_value (val->value, cs, val, src_idx,
1668 src_aglat->offset);
803a7988 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
e3f929ed 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
803a7988 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);
e3f929ed 1711 if (agg_pass_through_permissible_p (src_plats, jfunc))
803a7988 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
f1f41a6c 1753 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item)
803a7988 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));
6a0712d4 1760 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
803a7988 1761
1762 if (merge_agg_lats_step (dest_plats, item->offset, val_size,
1763 &aglat, pre_existing, &ret))
1764 {
9bfdb7bc 1765 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
803a7988 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
821d0e0f 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;
03f99d3c 1791 int i, args_count, parms_count;
821d0e0f 1792
415d1b9a 1793 callee = cs->callee->function_symbol (&availability);
02774f2d 1794 if (!callee->definition)
821d0e0f 1795 return false;
415d1b9a 1796 gcc_checking_assert (callee->has_gimple_body_p ());
821d0e0f 1797 callee_info = IPA_NODE_REF (callee);
821d0e0f 1798
1799 args = IPA_EDGE_REF (cs);
03f99d3c 1800 args_count = ipa_get_cs_argument_count (args);
1801 parms_count = ipa_get_param_count (callee_info);
019885b0 1802 if (parms_count == 0)
1803 return false;
821d0e0f 1804
058a1b7a 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
821d0e0f 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;
02774f2d 1827 while (alias_or_thunk->alias)
415d1b9a 1828 alias_or_thunk = alias_or_thunk->get_alias_target ();
821d0e0f 1829 if (alias_or_thunk->thunk.thunk_p)
1830 {
803a7988 1831 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
1832 0));
821d0e0f 1833 i = 1;
1834 }
1835 else
1836 i = 0;
1837
03f99d3c 1838 for (; (i < args_count) && (i < parms_count); i++)
821d0e0f 1839 {
1840 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
803a7988 1841 struct ipcp_param_lattices *dest_plats;
821d0e0f 1842
803a7988 1843 dest_plats = ipa_get_parm_lattices (callee_info, i);
415d1b9a 1844 if (availability == AVAIL_INTERPOSABLE)
803a7988 1845 ret |= set_all_contains_variable (dest_plats);
821d0e0f 1846 else
803a7988 1847 {
1848 ret |= propagate_scalar_accross_jump_function (cs, jump_func,
1849 &dest_plats->itself);
245ab191 1850 ret |= propagate_context_accross_jump_function (cs, jump_func, i,
1851 &dest_plats->ctxlat);
ae7b7bc8 1852 ret |= propagate_alignment_accross_jump_function (cs, jump_func,
1853 dest_plats);
803a7988 1854 ret |= propagate_aggs_accross_jump_function (cs, jump_func,
1855 dest_plats);
1856 }
821d0e0f 1857 }
03f99d3c 1858 for (; i < parms_count; i++)
803a7988 1859 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i));
03f99d3c 1860
821d0e0f 1861 return ret;
1862}
1863
1864/* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
693010ae 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. */
821d0e0f 1867
265c4eb2 1868static tree
1869ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
245ab191 1870 vec<tree> known_csts,
1871 vec<ipa_polymorphic_call_context> known_contexts,
265c4eb2 1872 vec<ipa_agg_jump_function_p> known_aggs,
f21a87d8 1873 struct ipa_agg_replacement_value *agg_reps,
1874 bool *speculative)
821d0e0f 1875{
1876 int param_index = ie->indirect_info->param_index;
245ab191 1877 HOST_WIDE_INT anc_offset;
821d0e0f 1878 tree t;
02636da3 1879 tree target = NULL;
821d0e0f 1880
f21a87d8 1881 *speculative = false;
1882
fd8b458b 1883 if (param_index == -1
245ab191 1884 || known_csts.length () <= (unsigned int) param_index)
821d0e0f 1885 return NULL_TREE;
1886
1887 if (!ie->indirect_info->polymorphic)
1888 {
a4f60e55 1889 tree t;
1890
1891 if (ie->indirect_info->agg_contents)
1892 {
265c4eb2 1893 if (agg_reps)
1894 {
1895 t = NULL;
1896 while (agg_reps)
1897 {
1898 if (agg_reps->index == param_index
c42e4f2e 1899 && agg_reps->offset == ie->indirect_info->offset
1900 && agg_reps->by_ref == ie->indirect_info->by_ref)
265c4eb2 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)
a4f60e55 1909 {
1910 struct ipa_agg_jump_function *agg;
f1f41a6c 1911 agg = known_aggs[param_index];
a4f60e55 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
245ab191 1919 t = known_csts[param_index];
a4f60e55 1920
821d0e0f 1921 if (t &&
1922 TREE_CODE (t) == ADDR_EXPR
1923 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
d4e80e2b 1924 return TREE_OPERAND (t, 0);
821d0e0f 1925 else
1926 return NULL_TREE;
1927 }
1928
d1f68cd8 1929 if (!opt_for_fn (ie->caller->decl, flag_devirtualize))
02636da3 1930 return NULL_TREE;
1931
a4f60e55 1932 gcc_assert (!ie->indirect_info->agg_contents);
0d491188 1933 anc_offset = ie->indirect_info->offset;
821d0e0f 1934
02636da3 1935 t = NULL;
1936
1937 /* Try to work out value of virtual table pointer value in replacemnets. */
f21a87d8 1938 if (!t && agg_reps && !ie->indirect_info->by_ref)
02636da3 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
f21a87d8 1956 && !ie->indirect_info->by_ref)
02636da3 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
6750de5f 1964 /* If we found the virtual table pointer, lookup the target. */
02636da3 1965 if (t)
6750de5f 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);
bc58d800 1973 if (target)
6750de5f 1974 {
bc58d800 1975 if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
1976 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
1977 || !possible_polymorphic_call_target_p
415d1b9a 1978 (ie, cgraph_node::get (target)))
3bc62a51 1979 target = ipa_impossible_devirt_target (ie, target);
f21a87d8 1980 *speculative = ie->indirect_info->vptr_changed;
1981 if (!*speculative)
1982 return target;
6750de5f 1983 }
6750de5f 1984 }
1985 }
02636da3 1986
245ab191 1987 /* Do we know the constant value of pointer? */
02636da3 1988 if (!t)
245ab191 1989 t = known_csts[param_index];
821d0e0f 1990
245ab191 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)
821d0e0f 1995 {
245ab191 1996 context = known_contexts[param_index];
9a271891 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);
245ab191 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 }
821d0e0f 2008 }
245ab191 2009 else if (t)
2c9d5cb8 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 }
821d0e0f 2017 else
245ab191 2018 return NULL_TREE;
821d0e0f 2019
245ab191 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)
f21a87d8 2028 {
2029 struct cgraph_node *node;
2030 if (*speculative)
2031 return target;
d1f68cd8 2032 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)
2033 || ie->speculative || !ie->maybe_hot_p ())
f21a87d8 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 }
245ab191 2046 else
f21a87d8 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 }
9a225e5a 2054
2055 if (target && !possible_polymorphic_call_target_p (ie,
415d1b9a 2056 cgraph_node::get (target)))
3bc62a51 2057 target = ipa_impossible_devirt_target (ie, target);
10fba9c0 2058
2059 return target;
821d0e0f 2060}
2061
265c4eb2 2062
245ab191 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. */
265c4eb2 2066
2067tree
2068ipa_get_indirect_edge_target (struct cgraph_edge *ie,
245ab191 2069 vec<tree> known_csts,
2070 vec<ipa_polymorphic_call_context> known_contexts,
f21a87d8 2071 vec<ipa_agg_jump_function_p> known_aggs,
2072 bool *speculative)
265c4eb2 2073{
245ab191 2074 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
f21a87d8 2075 known_aggs, NULL, speculative);
265c4eb2 2076}
2077
821d0e0f 2078/* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
245ab191 2079 and KNOWN_CONTEXTS. */
821d0e0f 2080
2081static int
2082devirtualization_time_bonus (struct cgraph_node *node,
f1f41a6c 2083 vec<tree> known_csts,
245ab191 2084 vec<ipa_polymorphic_call_context> known_contexts,
265c4eb2 2085 vec<ipa_agg_jump_function_p> known_aggs)
821d0e0f 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;
f28422b6 2094 enum availability avail;
d4e80e2b 2095 tree target;
f21a87d8 2096 bool speculative;
821d0e0f 2097
245ab191 2098 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
f21a87d8 2099 known_aggs, &speculative);
821d0e0f 2100 if (!target)
2101 continue;
2102
2103 /* Only bare minimum benefit for clearly un-inlineable targets. */
2104 res += 1;
415d1b9a 2105 callee = cgraph_node::get (target);
02774f2d 2106 if (!callee || !callee->definition)
821d0e0f 2107 continue;
415d1b9a 2108 callee = callee->function_symbol (&avail);
f28422b6 2109 if (avail < AVAIL_AVAILABLE)
2110 continue;
b4bae7a0 2111 isummary = inline_summaries->get (callee);
821d0e0f 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)
f21a87d8 2118 res += 31 / ((int)speculative + 1);
821d0e0f 2119 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
f21a87d8 2120 res += 15 / ((int)speculative + 1);
821d0e0f 2121 else if (isummary->size <= MAX_INLINE_INSNS_AUTO
02774f2d 2122 || DECL_DECLARED_INLINE_P (callee->decl))
f21a87d8 2123 res += 7 / ((int)speculative + 1);
821d0e0f 2124 }
2125
2126 return res;
2127}
2128
803a7988 2129/* Return time bonus incurred because of HINTS. */
2130
2131static int
2132hint_time_bonus (inline_hints hints)
2133{
3a1cb879 2134 int result = 0;
803a7988 2135 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
3a1cb879 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;
803a7988 2140}
2141
39fcd838 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
821d0e0f 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
d1f68cd8 2169 || !opt_for_fn (node->decl, flag_ipa_cp_clone)
02774f2d 2170 || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
821d0e0f 2171 return false;
2172
29bb06c7 2173 gcc_assert (size_cost > 0);
821d0e0f 2174
39fcd838 2175 struct ipa_node_params *info = IPA_NODE_REF (node);
821d0e0f 2176 if (max_count)
2177 {
29bb06c7 2178 int factor = (count_sum * 1000) / max_count;
3a4303e7 2179 int64_t evaluation = (((int64_t) time_benefit * factor)
29bb06c7 2180 / size_cost);
39fcd838 2181 evaluation = incorporate_penalties (info, evaluation);
821d0e0f 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
f03df321 2186 "%s%s) -> evaluation: " "%" PRId64
29bb06c7 2187 ", threshold: %i\n",
821d0e0f 2188 time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
39fcd838 2189 info->node_within_scc ? ", scc" : "",
2190 info->node_calling_single_call ? ", single_call" : "",
cfb368a3 2191 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
821d0e0f 2192
2193 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2194 }
2195 else
2196 {
3a4303e7 2197 int64_t evaluation = (((int64_t) time_benefit * freq_sum)
29bb06c7 2198 / size_cost);
39fcd838 2199 evaluation = incorporate_penalties (info, evaluation);
821d0e0f 2200
2201 if (dump_file && (dump_flags & TDF_DETAILS))
2202 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
39fcd838 2203 "size: %i, freq_sum: %i%s%s) -> evaluation: "
f03df321 2204 "%" PRId64 ", threshold: %i\n",
39fcd838 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));
821d0e0f 2209
2210 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
2211 }
2212}
2213
803a7988 2214/* Return all context independent values from aggregate lattices in PLATS in a
2215 vector. Return NULL if there are none. */
2216
b3e7c666 2217static vec<ipa_agg_jf_item, va_gc> *
803a7988 2218context_independent_aggregate_values (struct ipcp_param_lattices *plats)
2219{
b3e7c666 2220 vec<ipa_agg_jf_item, va_gc> *res = NULL;
803a7988 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)
9bfdb7bc 2230 if (aglat->is_single_const ())
803a7988 2231 {
2232 struct ipa_agg_jf_item item;
2233 item.offset = aglat->offset;
2234 item.value = aglat->values->value;
f1f41a6c 2235 vec_safe_push (res, item);
803a7988 2236 }
2237 return res;
2238}
821d0e0f 2239
245ab191 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. */
821d0e0f 2245
2246static bool
2247gather_context_independent_values (struct ipa_node_params *info,
245ab191 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)
821d0e0f 2253{
2254 int i, count = ipa_get_param_count (info);
2255 bool ret = false;
2256
f1f41a6c 2257 known_csts->create (0);
245ab191 2258 known_contexts->create (0);
f1f41a6c 2259 known_csts->safe_grow_cleared (count);
245ab191 2260 known_contexts->safe_grow_cleared (count);
803a7988 2261 if (known_aggs)
2262 {
f1f41a6c 2263 known_aggs->create (0);
2264 known_aggs->safe_grow_cleared (count);
803a7988 2265 }
821d0e0f 2266
2267 if (removable_params_cost)
2268 *removable_params_cost = 0;
2269
2270 for (i = 0; i < count ; i++)
2271 {
803a7988 2272 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
9bfdb7bc 2273 ipcp_lattice<tree> *lat = &plats->itself;
821d0e0f 2274
9bfdb7bc 2275 if (lat->is_single_const ())
821d0e0f 2276 {
9bfdb7bc 2277 ipcp_value<tree> *val = lat->values;
245ab191 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;
821d0e0f 2284 }
2285 else if (removable_params_cost
2286 && !ipa_is_param_used (info, i))
2287 *removable_params_cost
09ab6335 2288 += ipa_get_param_move_cost (info, i);
803a7988 2289
245ab191 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
803a7988 2297 if (known_aggs)
2298 {
b3e7c666 2299 vec<ipa_agg_jf_item, va_gc> *agg_items;
803a7988 2300 struct ipa_agg_jump_function *ajf;
2301
2302 agg_items = context_independent_aggregate_values (plats);
f1f41a6c 2303 ajf = &(*known_aggs)[i];
803a7988 2304 ajf->items = agg_items;
2305 ajf->by_ref = plats->aggs_by_ref;
2306 ret |= agg_items != NULL;
2307 }
821d0e0f 2308 }
2309
2310 return ret;
2311}
2312
803a7988 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
f1f41a6c 2320static vec<ipa_agg_jump_function_p>
b3e7c666 2321agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
803a7988 2322{
f1f41a6c 2323 vec<ipa_agg_jump_function_p> ret;
803a7988 2324 struct ipa_agg_jump_function *ajf;
2325 int i;
2326
f1f41a6c 2327 ret.create (known_aggs.length ());
2328 FOR_EACH_VEC_ELT (known_aggs, i, ajf)
2329 ret.quick_push (ajf);
803a7988 2330 return ret;
2331}
2332
9bfdb7bc 2333/* Perform time and size measurement of NODE with the context given in
245ab191 2334 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost
9bfdb7bc 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,
245ab191 2341 vec<ipa_polymorphic_call_context> known_contexts,
9bfdb7bc 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
245ab191 2349 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
9bfdb7bc 2350 known_aggs_ptrs, &size, &time,
2351 &hints);
2352 time_benefit = base_time - time
245ab191 2353 + devirtualization_time_bonus (node, known_csts, known_contexts,
9bfdb7bc 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
821d0e0f 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);
245ab191 2378 vec<tree> known_csts;
2379 vec<ipa_polymorphic_call_context> known_contexts;
b3e7c666 2380 vec<ipa_agg_jump_function> known_aggs;
f1f41a6c 2381 vec<ipa_agg_jump_function_p> known_aggs_ptrs;
821d0e0f 2382 bool always_const;
b4bae7a0 2383 int base_time = inline_summaries->get (node)->time;
821d0e0f 2384 int removable_params_cost;
2385
2386 if (!count || !ipcp_versionable_function_p (node))
2387 return;
2388
11b73810 2389 if (dump_file && (dump_flags & TDF_DETAILS))
821d0e0f 2390 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
f1c8b4d7 2391 node->name (), node->order, base_time);
821d0e0f 2392
2393 always_const = gather_context_independent_values (info, &known_csts,
245ab191 2394 &known_contexts, &known_aggs,
821d0e0f 2395 &removable_params_cost);
803a7988 2396 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
821d0e0f 2397 if (always_const)
11b73810 2398 {
821d0e0f 2399 struct caller_statistics stats;
803a7988 2400 inline_hints hints;
821d0e0f 2401 int time, size;
2402
2403 init_caller_stats (&stats);
415d1b9a 2404 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
2405 false);
245ab191 2406 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
803a7988 2407 known_aggs_ptrs, &size, &time, &hints);
245ab191 2408 time -= devirtualization_time_bonus (node, known_csts, known_contexts,
265c4eb2 2409 known_aggs_ptrs);
803a7988 2410 time -= hint_time_bonus (hints);
821d0e0f 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
415d1b9a 2419 || node->will_be_removed_from_program_if_no_direct_calls_p ())
821d0e0f 2420 {
87228246 2421 info->do_clone_for_all_contexts = true;
821d0e0f 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 {
87228246 2434 info->do_clone_for_all_contexts = true;
821d0e0f 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 }
11b73810 2447 }
2448
821d0e0f 2449 for (i = 0; i < count ; i++)
11b73810 2450 {
803a7988 2451 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
9bfdb7bc 2452 ipcp_lattice<tree> *lat = &plats->itself;
2453 ipcp_value<tree> *val;
821d0e0f 2454
2455 if (lat->bottom
2456 || !lat->values
245ab191 2457 || known_csts[i])
821d0e0f 2458 continue;
2459
2460 for (val = lat->values; val; val = val->next)
2461 {
245ab191 2462 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO);
2463 known_csts[i] = val->value;
821d0e0f 2464
245ab191 2465 int emc = estimate_move_cost (TREE_TYPE (val->value), true);
2466 perform_estimation_of_a_value (node, known_csts, known_contexts,
9bfdb7bc 2467 known_aggs_ptrs, base_time,
2468 removable_params_cost, emc, val);
ae56707d 2469
821d0e0f 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);
09ab6335 2474 fprintf (dump_file, " for ");
2475 ipa_dump_param (dump_file, info, i);
821d0e0f 2476 fprintf (dump_file, ": time_benefit: %i, size: %i\n",
9bfdb7bc 2477 val->local_time_benefit, val->local_size_cost);
821d0e0f 2478 }
821d0e0f 2479 }
f1f41a6c 2480 known_csts[i] = NULL_TREE;
803a7988 2481 }
2482
245ab191 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
803a7988 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
f1f41a6c 2527 ajf = &known_aggs[i];
803a7988 2528 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2529 {
9bfdb7bc 2530 ipcp_value<tree> *val;
803a7988 2531 if (aglat->bottom || !aglat->values
2532 /* If the following is true, the one value is in known_aggs. */
2533 || (!plats->aggs_contain_variable
9bfdb7bc 2534 && aglat->is_single_const ()))
803a7988 2535 continue;
2536
2537 for (val = aglat->values; val; val = val->next)
2538 {
803a7988 2539 struct ipa_agg_jf_item item;
803a7988 2540
2541 item.offset = aglat->offset;
2542 item.value = val->value;
f1f41a6c 2543 vec_safe_push (ajf->items, item);
803a7988 2544
245ab191 2545 perform_estimation_of_a_value (node, known_csts, known_contexts,
9bfdb7bc 2546 known_aggs_ptrs, base_time,
2547 removable_params_cost, 0, val);
803a7988 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);
09ab6335 2553 fprintf (dump_file, " for ");
2554 ipa_dump_param (dump_file, info, i);
803a7988 2555 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
9bfdb7bc 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);
803a7988 2560 }
2561
f1f41a6c 2562 ajf->items->pop ();
803a7988 2563 }
2564 }
2565 }
2566
2567 for (i = 0; i < count ; i++)
f1f41a6c 2568 vec_free (known_aggs[i].items);
821d0e0f 2569
f1f41a6c 2570 known_csts.release ();
245ab191 2571 known_contexts.release ();
f1f41a6c 2572 known_aggs.release ();
2573 known_aggs_ptrs.release ();
821d0e0f 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
9bfdb7bc 2580template <typename valtype>
2581void
2582value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
821d0e0f 2583{
9bfdb7bc 2584 ipcp_value_source<valtype> *src;
821d0e0f 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 {
9bfdb7bc 2602 add_val (src->val);
821d0e0f 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)
11b73810 2612 {
9bfdb7bc 2613 ipcp_value<valtype> *v, *scc_list = NULL;
821d0e0f 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;
11b73810 2628 }
3b22db66 2629}
2630
821d0e0f 2631/* Add all values in lattices associated with NODE to the topological sort if
2632 they are not there yet. */
2633
2634static void
9bfdb7bc 2635add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
3b22db66 2636{
821d0e0f 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 {
803a7988 2642 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
9bfdb7bc 2643 ipcp_lattice<tree> *lat = &plats->itself;
803a7988 2644 struct ipcp_agg_lattice *aglat;
821d0e0f 2645
803a7988 2646 if (!lat->bottom)
245ab191 2647 {
2648 ipcp_value<tree> *val;
2649 for (val = lat->values; val; val = val->next)
2650 topo->constants.add_val (val);
2651 }
803a7988 2652
2653 if (!plats->aggs_bottom)
2654 for (aglat = plats->aggs; aglat; aglat = aglat->next)
2655 if (!aglat->bottom)
245ab191 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 }
821d0e0f 2669 }
3b22db66 2670}
2671
821d0e0f 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
3b22db66 2676static void
9908fe4d 2677propagate_constants_topo (struct ipa_topo_info *topo)
3b22db66 2678{
821d0e0f 2679 int i;
3b22db66 2680
821d0e0f 2681 for (i = topo->nnodes - 1; i >= 0; i--)
3b22db66 2682 {
3ffe0ea9 2683 unsigned j;
821d0e0f 2684 struct cgraph_node *v, *node = topo->order[i];
415d1b9a 2685 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
821d0e0f 2686
821d0e0f 2687 /* First, iteratively propagate within the strongly connected component
2688 until all lattices stabilize. */
3ffe0ea9 2689 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
415d1b9a 2690 if (v->has_gimple_body_p ())
821d0e0f 2691 push_node_to_stack (topo, v);
821d0e0f 2692
3ffe0ea9 2693 v = pop_node_from_stack (topo);
821d0e0f 2694 while (v)
2695 {
2696 struct cgraph_edge *cs;
2697
2698 for (cs = v->callees; cs; cs = cs->next_callee)
39fcd838 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 }
821d0e0f 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. */
3ffe0ea9 2711 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
415d1b9a 2712 if (v->has_gimple_body_p ())
3ffe0ea9 2713 {
2714 struct cgraph_edge *cs;
821d0e0f 2715
3ffe0ea9 2716 estimate_local_effects (v);
9bfdb7bc 2717 add_all_node_vals_to_toposort (v, topo);
3ffe0ea9 2718 for (cs = v->callees; cs; cs = cs->next_callee)
a0255a70 2719 if (!ipa_edge_within_scc (cs))
3ffe0ea9 2720 propagate_constants_accross_call (cs);
2721 }
2722 cycle_nodes.release ();
3b22db66 2723 }
2724}
2725
29bb06c7 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
821d0e0f 2740/* Propagate the estimated effects of individual values along the topological
9d75589a 2741 from the dependent values to those they depend on. */
821d0e0f 2742
9bfdb7bc 2743template <typename valtype>
2744void
2745value_topo_info<valtype>::propagate_effects ()
3b22db66 2746{
9bfdb7bc 2747 ipcp_value<valtype> *base;
3b22db66 2748
821d0e0f 2749 for (base = values_topo; base; base = base->topo_next)
3b22db66 2750 {
9bfdb7bc 2751 ipcp_value_source<valtype> *src;
2752 ipcp_value<valtype> *val;
821d0e0f 2753 int time = 0, size = 0;
2754
2755 for (val = base; val; val = val->scc_next)
2756 {
29bb06c7 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);
821d0e0f 2760 }
2761
2762 for (val = base; val; val = val->scc_next)
2763 for (src = val->sources; src; src = src->next)
2764 if (src->val
35ee1c66 2765 && src->cs->maybe_hot_p ())
821d0e0f 2766 {
29bb06c7 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);
821d0e0f 2771 }
3b22db66 2772 }
2773}
2774
821d0e0f 2775
245ab191 2776/* Propagate constants, polymorphic contexts and their effects from the
2777 summaries interprocedurally. */
821d0e0f 2778
3b22db66 2779static void
9908fe4d 2780ipcp_propagate_stage (struct ipa_topo_info *topo)
3b22db66 2781{
2782 struct cgraph_node *node;
3b22db66 2783
821d0e0f 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);
415d1b9a 2796 if (node->has_gimple_body_p ())
821d0e0f 2797 {
803a7988 2798 info->lattices = XCNEWVEC (struct ipcp_param_lattices,
821d0e0f 2799 ipa_get_param_count (info));
2800 initialize_node_lattices (node);
2801 }
02774f2d 2802 if (node->definition && !node->alias)
b4bae7a0 2803 overall_size += inline_summaries->get (node)->self_size;
821d0e0f 2804 if (node->count > max_count)
2805 max_count = node->count;
821d0e0f 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
9bfdb7bc 2821 topo->constants.propagate_effects ();
245ab191 2822 topo->contexts.propagate_effects ();
821d0e0f 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
245ab191 2832 known KNOWN_CSTS and make them direct. */
821d0e0f 2833
2834static void
2835ipcp_discover_new_direct_edges (struct cgraph_node *node,
245ab191 2836 vec<tree> known_csts,
2837 vec<ipa_polymorphic_call_context>
2838 known_contexts,
265c4eb2 2839 struct ipa_agg_replacement_value *aggvals)
821d0e0f 2840{
2841 struct cgraph_edge *ie, *next_ie;
18b64b34 2842 bool found = false;
821d0e0f 2843
2844 for (ie = node->indirect_calls; ie; ie = next_ie)
2845 {
d4e80e2b 2846 tree target;
f21a87d8 2847 bool speculative;
821d0e0f 2848
2849 next_ie = ie->next_callee;
245ab191 2850 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
f21a87d8 2851 vNULL, aggvals, &speculative);
821d0e0f 2852 if (target)
18b64b34 2853 {
4d044066 2854 bool agg_contents = ie->indirect_info->agg_contents;
2855 bool polymorphic = ie->indirect_info->polymorphic;
436b29f7 2856 int param_index = ie->indirect_info->param_index;
f21a87d8 2857 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
2858 speculative);
18b64b34 2859 found = true;
096295f6 2860
4d044066 2861 if (cs && !agg_contents && !polymorphic)
096295f6 2862 {
2863 struct ipa_node_params *info = IPA_NODE_REF (node);
096295f6 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
51ce5652 2875 && (to_del = node->find_reference (cs->callee, NULL, 0)))
096295f6 2876 {
2877 if (dump_file && (dump_flags & TDF_DETAILS))
2878 fprintf (dump_file, " and even removing its "
2879 "cloning-created reference\n");
51ce5652 2880 to_del->remove_reference ();
096295f6 2881 }
2882 }
2883 }
18b64b34 2884 }
821d0e0f 2885 }
18b64b34 2886 /* Turning calls to direct calls will improve overall summary. */
2887 if (found)
2888 inline_update_overall_summary (node);
821d0e0f 2889}
2890
2891/* Vector of pointers which for linked lists of clones of an original crgaph
2892 edge. */
2893
415d1b9a 2894static vec<cgraph_edge *> next_edge_clone;
2895static vec<cgraph_edge *> prev_edge_clone;
821d0e0f 2896
2897static inline void
948ccfa6 2898grow_edge_clone_vectors (void)
821d0e0f 2899{
f1f41a6c 2900 if (next_edge_clone.length ()
35ee1c66 2901 <= (unsigned) symtab->edges_max_uid)
2902 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
948ccfa6 2903 if (prev_edge_clone.length ()
35ee1c66 2904 <= (unsigned) symtab->edges_max_uid)
2905 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
821d0e0f 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,
948ccfa6 2913 void *)
821d0e0f 2914{
948ccfa6 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;
f1f41a6c 2923 next_edge_clone[src->uid] = dst;
821d0e0f 2924}
2925
948ccfa6 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
803a7988 2941/* See if NODE is a clone with a known aggregate value at a given OFFSET of a
2942 parameter with the given INDEX. */
821d0e0f 2943
803a7988 2944static tree
3a4303e7 2945get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
803a7988 2946 int index)
821d0e0f 2947{
803a7988 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;
821d0e0f 2959}
2960
3cc99d11 2961/* Return true is NODE is DEST or its clone for all contexts. */
821d0e0f 2962
2963static bool
3cc99d11 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)
821d0e0f 2979{
2980 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3cc99d11 2981 enum availability availability;
2982 cgraph_node *real_dest = cs->callee->function_symbol (&availability);
821d0e0f 2983
3cc99d11 2984 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
2985 || availability <= AVAIL_INTERPOSABLE
821d0e0f 2986 || caller_info->node_dead)
2987 return false;
2988 if (!src->val)
2989 return true;
2990
2991 if (caller_info->ipcp_orig_node)
2992 {
803a7988 2993 tree t;
2994 if (src->offset == -1)
245ab191 2995 t = caller_info->known_csts[src->index];
803a7988 2996 else
2997 t = get_clone_agg_value (cs->caller, src->offset, src->index);
821d0e0f 2998 return (t != NULL_TREE
2999 && values_equal_for_ipcp_p (src->val->value, t));
3000 }
3001 else
3b22db66 3002 {
803a7988 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)
9bfdb7bc 3007 return (plats->itself.is_single_const ()
803a7988 3008 && values_equal_for_ipcp_p (src->val->value,
3009 plats->itself.values->value));
821d0e0f 3010 else
803a7988 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)
9bfdb7bc 3016 return (aglat->is_single_const ()
803a7988 3017 && values_equal_for_ipcp_p (src->val->value,
3018 aglat->values->value));
3019 }
3020 return false;
821d0e0f 3021 }
3022}
3023
3cc99d11 3024/* Return true if edge CS does bring about the value described by SRC to node
3025 DEST or its clone for all contexts. */
245ab191 3026
3027static bool
3cc99d11 3028cgraph_edge_brings_value_p (cgraph_edge *cs,
3029 ipcp_value_source<ipa_polymorphic_call_context> *src,
3030 cgraph_node *dest)
245ab191 3031{
3032 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
3033 cgraph_node *real_dest = cs->callee->function_symbol ();
245ab191 3034
3cc99d11 3035 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
245ab191 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
803a7988 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{
f1f41a6c 3058 return next_edge_clone[cs->uid];
803a7988 3059}
3060
3cc99d11 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. */
821d0e0f 3064
9bfdb7bc 3065template <typename valtype>
821d0e0f 3066static bool
3cc99d11 3067get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
3068 int *freq_sum,
821d0e0f 3069 gcov_type *count_sum, int *caller_count)
3070{
9bfdb7bc 3071 ipcp_value_source<valtype> *src;
821d0e0f 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)
3b22db66 3080 {
3cc99d11 3081 if (cgraph_edge_brings_value_p (cs, src, dest))
821d0e0f 3082 {
3083 count++;
3084 freq += cs->frequency;
3085 cnt += cs->count;
35ee1c66 3086 hot |= cs->maybe_hot_p ();
821d0e0f 3087 }
3088 cs = get_next_cgraph_edge_clone (cs);
3b22db66 3089 }
3090 }
821d0e0f 3091
3092 *freq_sum = freq;
3093 *count_sum = cnt;
3094 *caller_count = count;
3095 return hot;
3b22db66 3096}
3097
3cc99d11 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. */
821d0e0f 3100
9bfdb7bc 3101template <typename valtype>
415d1b9a 3102static vec<cgraph_edge *>
3cc99d11 3103gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest,
3104 int caller_count)
3b22db66 3105{
9bfdb7bc 3106 ipcp_value_source<valtype> *src;
415d1b9a 3107 vec<cgraph_edge *> ret;
821d0e0f 3108
f1f41a6c 3109 ret.create (caller_count);
821d0e0f 3110 for (src = val->sources; src; src = src->next)
3111 {
3112 struct cgraph_edge *cs = src->cs;
3113 while (cs)
3114 {
3cc99d11 3115 if (cgraph_edge_brings_value_p (cs, src, dest))
f1f41a6c 3116 ret.quick_push (cs);
821d0e0f 3117 cs = get_next_cgraph_edge_clone (cs);
3118 }
3119 }
3120
3121 return ret;
3b22db66 3122}
3123
821d0e0f 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
3b22db66 3127static struct ipa_replace_map *
09ab6335 3128get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
3b22db66 3129{
3130 struct ipa_replace_map *replace_map;
3b22db66 3131
821d0e0f 3132
25a27413 3133 replace_map = ggc_alloc<ipa_replace_map> ();
5afe38fe 3134 if (dump_file)
3135 {
09ab6335 3136 fprintf (dump_file, " replacing ");
3137 ipa_dump_param (dump_file, info, parm_num);
3138
5afe38fe 3139 fprintf (dump_file, " with const ");
821d0e0f 3140 print_generic_expr (dump_file, value, 0);
5afe38fe 3141 fprintf (dump_file, "\n");
3142 }
79e830ee 3143 replace_map->old_tree = NULL;
3144 replace_map->parm_num = parm_num;
821d0e0f 3145 replace_map->new_tree = value;
13e50f08 3146 replace_map->replace_p = true;
3147 replace_map->ref_p = false;
3b22db66 3148
3149 return replace_map;
3150}
3151
821d0e0f 3152/* Dump new profiling counts */
3b22db66 3153
3b22db66 3154static void
821d0e0f 3155dump_profile_updates (struct cgraph_node *orig_node,
3156 struct cgraph_node *new_node)
3b22db66 3157{
821d0e0f 3158 struct cgraph_edge *cs;
3b22db66 3159
821d0e0f 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",
f1c8b4d7 3165 cs->callee->name (), (HOST_WIDE_INT) cs->count);
821d0e0f 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",
f1c8b4d7 3172 cs->callee->name (), (HOST_WIDE_INT) cs->count);
821d0e0f 3173}
5afe38fe 3174
821d0e0f 3175/* After a specialized NEW_NODE version of ORIG_NODE has been created, update
3176 their profile information to reflect this. */
3b22db66 3177
3b22db66 3178static void
821d0e0f 3179update_profiling_info (struct cgraph_node *orig_node,
3180 struct cgraph_node *new_node)
3b22db66 3181{
3b22db66 3182 struct cgraph_edge *cs;
821d0e0f 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;
3b22db66 3189
821d0e0f 3190 init_caller_stats (&stats);
415d1b9a 3191 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3192 false);
821d0e0f 3193 orig_sum = stats.count_sum;
3194 init_caller_stats (&stats);
415d1b9a 3195 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
3196 false);
821d0e0f 3197 new_sum = stats.count_sum;
3198
3199 if (orig_node_count < orig_sum + new_sum)
3b22db66 3200 {
821d0e0f 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",
f1c8b4d7 3205 orig_node->name (), orig_node->order,
821d0e0f 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);
3b22db66 3214 }
821d0e0f 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)
f9d4b7f4 3222 cs->count = apply_probability (cs->count,
3223 GCOV_COMPUTE_SCALE (new_sum,
3224 orig_node_count));
821d0e0f 3225 else
3226 cs->count = 0;
3227
3228 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
f9d4b7f4 3229 cs->count = apply_probability (cs->count,
3230 GCOV_COMPUTE_SCALE (remainder,
3231 orig_node_count));
821d0e0f 3232
3233 if (dump_file)
3234 dump_profile_updates (orig_node, new_node);
3b22db66 3235}
3236
821d0e0f 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)
2a15795f 3245{
614b82b2 3246 struct cgraph_edge *cs;
821d0e0f 3247 gcov_type new_node_count, orig_node_count = orig_node->count;
2a15795f 3248
821d0e0f 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;
614b82b2 3254
821d0e0f 3255 gcc_assert (orig_node_count >= redirected_sum);
2a15795f 3256
821d0e0f 3257 new_node_count = new_node->count;
3258 new_node->count += redirected_sum;
3259 orig_node->count -= redirected_sum;
614b82b2 3260
821d0e0f 3261 for (cs = new_node->callees; cs ; cs = cs->next_callee)
3262 if (cs->frequency)
f9d4b7f4 3263 cs->count += apply_probability (cs->count,
3264 GCOV_COMPUTE_SCALE (redirected_sum,
3265 new_node_count));
821d0e0f 3266 else
3267 cs->count = 0;
614b82b2 3268
821d0e0f 3269 for (cs = orig_node->callees; cs ; cs = cs->next_callee)
3270 {
f9d4b7f4 3271 gcov_type dec = apply_probability (cs->count,
3272 GCOV_COMPUTE_SCALE (redirected_sum,
3273 orig_node_count));
821d0e0f 3274 if (dec < cs->count)
3275 cs->count -= dec;
3276 else
3277 cs->count = 0;
3278 }
614b82b2 3279
821d0e0f 3280 if (dump_file)
3281 dump_profile_updates (orig_node, new_node);
2a15795f 3282}
3283
245ab191 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. */
614b82b2 3287
821d0e0f 3288static struct cgraph_node *
3289create_specialized_node (struct cgraph_node *node,
245ab191 3290 vec<tree> known_csts,
3291 vec<ipa_polymorphic_call_context> known_contexts,
803a7988 3292 struct ipa_agg_replacement_value *aggvals,
415d1b9a 3293 vec<cgraph_edge *> callers)
2a15795f 3294{
821d0e0f 3295 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node);
415d1b9a 3296 vec<ipa_replace_map *, va_gc> *replace_trees = NULL;
3c0fe71b 3297 struct ipa_agg_replacement_value *av;
821d0e0f 3298 struct cgraph_node *new_node;
3299 int i, count = ipa_get_param_count (info);
3300 bitmap args_to_skip;
2a15795f 3301
821d0e0f 3302 gcc_assert (!info->ipcp_orig_node);
3303
3304 if (node->local.can_change_signature)
2a15795f 3305 {
821d0e0f 3306 args_to_skip = BITMAP_GGC_ALLOC ();
3307 for (i = 0; i < count; i++)
3308 {
245ab191 3309 tree t = known_csts[i];
821d0e0f 3310
245ab191 3311 if (t || !ipa_is_param_used (info, i))
821d0e0f 3312 bitmap_set_bit (args_to_skip, i);
3313 }
3314 }
3315 else
03f99d3c 3316 {
3317 args_to_skip = NULL;
3318 if (dump_file && (dump_flags & TDF_DETAILS))
3319 fprintf (dump_file, " cannot change function signature\n");
3320 }
821d0e0f 3321
3322 for (i = 0; i < count ; i++)
3323 {
245ab191 3324 tree t = known_csts[i];
3325 if (t)
821d0e0f 3326 {
3327 struct ipa_replace_map *replace_map;
3328
245ab191 3329 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO);
09ab6335 3330 replace_map = get_replacement_map (info, t, i);
821d0e0f 3331 if (replace_map)
f1f41a6c 3332 vec_safe_push (replace_trees, replace_map);
821d0e0f 3333 }
2a15795f 3334 }
3335
415d1b9a 3336 new_node = node->create_virtual_clone (callers, replace_trees,
3337 args_to_skip, "constprop");
803a7988 3338 ipa_set_node_agg_value_chain (new_node, aggvals);
3c0fe71b 3339 for (av = aggvals; av; av = av->next)
35ee1c66 3340 new_node->maybe_create_reference (av->value, IPA_REF_ADDR, NULL);
3c0fe71b 3341
821d0e0f 3342 if (dump_file && (dump_flags & TDF_DETAILS))
803a7988 3343 {
3344 fprintf (dump_file, " the new node is %s/%i.\n",
f1c8b4d7 3345 new_node->name (), new_node->order);
245ab191 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 }
803a7988 3355 if (aggvals)
3356 ipa_dump_agg_replacement_values (dump_file, aggvals);
3357 }
5a7ad253 3358 ipa_check_create_node_params ();
821d0e0f 3359 update_profiling_info (node, new_node);
3360 new_info = IPA_NODE_REF (new_node);
3361 new_info->ipcp_orig_node = node;
245ab191 3362 new_info->known_csts = known_csts;
3363 new_info->known_contexts = known_contexts;
2a15795f 3364
245ab191 3365 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals);
821d0e0f 3366
f1f41a6c 3367 callers.release ();
821d0e0f 3368 return new_node;
2a15795f 3369}
3370
821d0e0f 3371/* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
245ab191 3372 KNOWN_CSTS with constants that are also known for all of the CALLERS. */
1caef38b 3373
3374static void
803a7988 3375find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
245ab191 3376 vec<tree> known_csts,
415d1b9a 3377 vec<cgraph_edge *> callers)
1caef38b 3378{
3379 struct ipa_node_params *info = IPA_NODE_REF (node);
821d0e0f 3380 int i, count = ipa_get_param_count (info);
1caef38b 3381
821d0e0f 3382 for (i = 0; i < count ; i++)
1caef38b 3383 {
821d0e0f 3384 struct cgraph_edge *cs;
3385 tree newval = NULL_TREE;
3386 int j;
9a271891 3387 bool first = true;
1caef38b 3388
245ab191 3389 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
1caef38b 3390 continue;
3391
f1f41a6c 3392 FOR_EACH_VEC_ELT (callers, j, cs)
3658fd1d 3393 {
821d0e0f 3394 struct ipa_jump_func *jump_func;
3395 tree t;
09a2b4db 3396
c8fc6b84 3397 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)))
3398 {
3399 newval = NULL_TREE;
3400 break;
3401 }
821d0e0f 3402 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
821d0e0f 3403 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
3404 if (!t
3405 || (newval
9a271891 3406 && !values_equal_for_ipcp_p (t, newval))
3407 || (!first && !newval))
1caef38b 3408 {
821d0e0f 3409 newval = NULL_TREE;
3410 break;
1caef38b 3411 }
821d0e0f 3412 else
3413 newval = t;
9a271891 3414 first = false;
1caef38b 3415 }
3416
821d0e0f 3417 if (newval)
3418 {
3419 if (dump_file && (dump_flags & TDF_DETAILS))
3420 {
803a7988 3421 fprintf (dump_file, " adding an extra known scalar value ");
821d0e0f 3422 print_ipcp_constant_value (dump_file, newval);
09ab6335 3423 fprintf (dump_file, " for ");
3424 ipa_dump_param (dump_file, info, i);
821d0e0f 3425 fprintf (dump_file, "\n");
3426 }
2a15795f 3427
245ab191 3428 known_csts[i] = newval;
821d0e0f 3429 }
2a15795f 3430 }
2a15795f 3431}
3432
245ab191 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;
9a271891 3456 bool first = true;
245ab191 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);
9a271891 3468 if (first)
245ab191 3469 {
245ab191 3470 newval = ctx;
9a271891 3471 first = false;
245ab191 3472 }
9a271891 3473 else
3474 newval.meet_with (ctx);
3475 if (newval.useless_p ())
3476 break;
245ab191 3477 }
3478
9a271891 3479 if (!newval.useless_p ())
245ab191 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
803a7988 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
b3e7c666 3502static vec<ipa_agg_jf_item>
803a7988 3503copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
3504{
b3e7c666 3505 vec<ipa_agg_jf_item> res = vNULL;
803a7988 3506
3507 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom)
1e094109 3508 return vNULL;
803a7988 3509
3510 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
9bfdb7bc 3511 if (aglat->is_single_const ())
803a7988 3512 {
3513 struct ipa_agg_jf_item ti;
3514 ti.offset = aglat->offset - offset;
3515 ti.value = aglat->values->value;
f1f41a6c 3516 res.safe_push (ti);
803a7988 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,
b3e7c666 3526 vec<ipa_agg_jf_item> *inter,
803a7988 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 {
f1f41a6c 3535 inter->release ();
803a7988 3536 return;
3537 }
3538
3539 aglat = plats->aggs;
f1f41a6c 3540 FOR_EACH_VEC_ELT (*inter, k, item)
803a7988 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
b3e7c666 3566static vec<ipa_agg_jf_item>
9bd3a517 3567agg_replacements_to_vector (struct cgraph_node *node, int index,
3568 HOST_WIDE_INT offset)
803a7988 3569{
3570 struct ipa_agg_replacement_value *av;
b3e7c666 3571 vec<ipa_agg_jf_item> res = vNULL;
803a7988 3572
3573 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next)
9bd3a517 3574 if (av->index == index
3575 && (av->offset - offset) >= 0)
803a7988 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;
f1f41a6c 3581 res.safe_push (item);
803a7988 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,
b3e7c666 3593 vec<ipa_agg_jf_item> *inter,
803a7988 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 {
f1f41a6c 3603 inter->release ();
803a7988 3604 return;
3605 }
3606
f1f41a6c 3607 FOR_EACH_VEC_ELT (*inter, i, item)
803a7988 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
7e8091c8 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
b3e7c666 3634static vec<ipa_agg_jf_item>
7e8091c8 3635intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
b3e7c666 3636 vec<ipa_agg_jf_item> inter)
7e8091c8 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 ())
9bd3a517 3655 inter = agg_replacements_to_vector (cs->caller, src_idx, 0);
7e8091c8 3656 else
3657 intersect_with_agg_replacements (cs->caller, src_idx,
3658 &inter, 0);
3659 }
371e3118 3660 else
3661 {
3662 inter.release ();
3663 return vNULL;
3664 }
7e8091c8 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 }
371e3118 3680 else
3681 {
3682 inter.release ();
3683 return vNULL;
3684 }
7e8091c8 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 ())
9bd3a517 3698 inter = agg_replacements_to_vector (cs->caller, src_idx, delta);
7e8091c8 3699 else
9bd3a517 3700 intersect_with_agg_replacements (cs->caller, src_idx, &inter,
7e8091c8 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 {
9af5ce0c 3754 inter.release ();
b3e7c666 3755 return vec<ipa_agg_jf_item>();
7e8091c8 3756 }
3757 return inter;
3758}
3759
803a7988 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,
415d1b9a 3765 vec<cgraph_edge *> callers)
803a7988 3766{
91af92ef 3767 struct ipa_node_params *dest_info = IPA_NODE_REF (node);
60531eda 3768 struct ipa_agg_replacement_value *res;
3769 struct ipa_agg_replacement_value **tail = &res;
803a7988 3770 struct cgraph_edge *cs;
91af92ef 3771 int i, j, count = ipa_get_param_count (dest_info);
803a7988 3772
f1f41a6c 3773 FOR_EACH_VEC_ELT (callers, j, cs)
803a7988 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;
b3e7c666 3783 vec<ipa_agg_jf_item> inter = vNULL;
803a7988 3784 struct ipa_agg_jf_item *item;
c42e4f2e 3785 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i);
803a7988 3786 int j;
3787
3788 /* Among other things, the following check should deal with all by_ref
3789 mismatches. */
c42e4f2e 3790 if (plats->aggs_bottom)
803a7988 3791 continue;
3792
f1f41a6c 3793 FOR_EACH_VEC_ELT (callers, j, cs)
803a7988 3794 {
7e8091c8 3795 inter = intersect_aggregates_with_edge (cs, i, inter);
803a7988 3796
f1f41a6c 3797 if (!inter.exists ())
803a7988 3798 goto next_param;
3799 }
3800
f1f41a6c 3801 FOR_EACH_VEC_ELT (inter, j, item)
803a7988 3802 {
3803 struct ipa_agg_replacement_value *v;
3804
3805 if (!item->value)
3806 continue;
3807
25a27413 3808 v = ggc_alloc<ipa_agg_replacement_value> ();
803a7988 3809 v->index = i;
3810 v->offset = item->offset;
3811 v->value = item->value;
c42e4f2e 3812 v->by_ref = plats->aggs_by_ref;
60531eda 3813 *tail = v;
3814 tail = &v->next;
803a7988 3815 }
3816
3817 next_param:
f1f41a6c 3818 if (inter.exists ())
3819 inter.release ();
803a7988 3820 }
60531eda 3821 *tail = NULL;
803a7988 3822 return res;
3823}
3824
3825/* Turn KNOWN_AGGS into a list of aggreate replacement values. */
3826
3827static struct ipa_agg_replacement_value *
b3e7c666 3828known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
803a7988 3829{
60531eda 3830 struct ipa_agg_replacement_value *res;
3831 struct ipa_agg_replacement_value **tail = &res;
803a7988 3832 struct ipa_agg_jump_function *aggjf;
3833 struct ipa_agg_jf_item *item;
3834 int i, j;
3835
f1f41a6c 3836 FOR_EACH_VEC_ELT (known_aggs, i, aggjf)
3837 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
803a7988 3838 {
3839 struct ipa_agg_replacement_value *v;
25a27413 3840 v = ggc_alloc<ipa_agg_replacement_value> ();
803a7988 3841 v->index = i;
3842 v->offset = item->offset;
3843 v->value = item->value;
c42e4f2e 3844 v->by_ref = aggjf->by_ref;
60531eda 3845 *tail = v;
3846 tail = &v->next;
803a7988 3847 }
60531eda 3848 *tail = NULL;
803a7988 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
245ab191 3872 val = dest_info->known_csts[i];
803a7988 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{
7e8091c8 3892 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
fc635e81 3893 struct ipa_node_params *orig_node_info;
803a7988 3894 struct ipa_agg_replacement_value *aggval;
7e8091c8 3895 int i, ec, count;
803a7988 3896
3897 aggval = ipa_get_agg_replacements_for_node (node);
7e8091c8 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
fc635e81 3908 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
7e8091c8 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++)
803a7988 3913 {
b3e7c666 3914 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>();
803a7988 3915 struct ipcp_param_lattices *plats;
7e8091c8 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
fc635e81 3926 plats = ipa_get_parm_lattices (orig_node_info, aggval->index);
7e8091c8 3927 if (plats->aggs_bottom)
803a7988 3928 return false;
803a7988 3929
7e8091c8 3930 values = intersect_aggregates_with_edge (cs, i, values);
9af5ce0c 3931 if (!values.exists ())
803a7988 3932 return false;
3933
7e8091c8 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))
9ea71c42 3944 {
3945 found = true;
3946 break;
3947 }
7e8091c8 3948 if (!found)
3949 {
9af5ce0c 3950 values.release ();
7e8091c8 3951 return false;
3952 }
3953 }
803a7988 3954 }
3955 return true;
3956}
3957
821d0e0f 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. */
7428ee1f 3963
9bfdb7bc 3964template <typename valtype>
7428ee1f 3965static void
9bfdb7bc 3966perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
7428ee1f 3967{
9bfdb7bc 3968 ipcp_value_source<valtype> *src;
821d0e0f 3969 gcov_type redirected_sum = 0;
7428ee1f 3970
821d0e0f 3971 for (src = val->sources; src; src = src->next)
7428ee1f 3972 {
821d0e0f 3973 struct cgraph_edge *cs = src->cs;
3974 while (cs)
3975 {
3cc99d11 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))
821d0e0f 3979 {
3cc99d11 3980 if (dump_file)
3981 fprintf (dump_file, " - adding an extra caller %s/%i"
3982 " of %s/%i\n",
5ae49d3e 3983 xstrdup_for_dump (cs->caller->name ()),
3cc99d11 3984 cs->caller->order,
5ae49d3e 3985 xstrdup_for_dump (val->spec_node->name ()),
3cc99d11 3986 val->spec_node->order);
3987
fe3c9f1e 3988 cs->redirect_callee_duplicating_thunks (val->spec_node);
3989 val->spec_node->expand_all_artificial_thunks ();
3cc99d11 3990 redirected_sum += cs->count;
821d0e0f 3991 }
3992 cs = get_next_cgraph_edge_clone (cs);
3993 }
7428ee1f 3994 }
821d0e0f 3995
3996 if (redirected_sum)
3997 update_specialized_profile (val->spec_node, node, redirected_sum);
7428ee1f 3998}
3999
245ab191 4000/* Return true if KNOWN_CONTEXTS contain at least one useful context. */
7428ee1f 4001
245ab191 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. */
821d0e0f 4027
3b22db66 4028static void
245ab191 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)
3b22db66 4033{
245ab191 4034 *known_csts = known_csts->copy ();
4035 *known_contexts = copy_useful_known_contexts (*known_contexts);
4036 (*known_csts)[index] = val->value;
4037}
3b22db66 4038
245ab191 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;
821d0e0f 4051}
2a15795f 4052
245ab191 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. */
803a7988 4056
4057DEBUG_FUNCTION bool
245ab191 4058ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals,
4059 int index, HOST_WIDE_INT offset, tree value)
803a7988 4060{
245ab191 4061 if (offset == -1)
4062 return true;
4063
803a7988 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
245ab191 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
803a7988 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,
245ab191 4089 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */
803a7988 4090
9bfdb7bc 4091template <typename valtype>
803a7988 4092static bool
4093decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
9bfdb7bc 4094 ipcp_value<valtype> *val, vec<tree> known_csts,
245ab191 4095 vec<ipa_polymorphic_call_context> known_contexts)
803a7988 4096{
4097 struct ipa_agg_replacement_value *aggvals;
4098 int freq_sum, caller_count;
4099 gcov_type count_sum;
415d1b9a 4100 vec<cgraph_edge *> callers;
803a7988 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 }
3cc99d11 4115 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum,
803a7988 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);
09ab6335 4123 fprintf (dump_file, " for ");
4124 ipa_dump_param (dump_file, IPA_NODE_REF (node), index);
803a7988 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",
f1c8b4d7 4143 node->name (), node->order);
803a7988 4144
3cc99d11 4145 callers = gather_edges_for_value (val, node, caller_count);
803a7988 4146 if (offset == -1)
245ab191 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);
803a7988 4155 aggvals = find_aggregate_values_for_callers_subset (node, callers);
245ab191 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);
803a7988 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}
2a15795f 4167
821d0e0f 4168/* Decide whether and what specialized clones of NODE should be created. */
2a15795f 4169
821d0e0f 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);
245ab191 4175 vec<tree> known_csts;
4176 vec<ipa_polymorphic_call_context> known_contexts;
b3e7c666 4177 vec<ipa_agg_jump_function> known_aggs = vNULL;
821d0e0f 4178 bool ret = false;
2a15795f 4179
821d0e0f 4180 if (count == 0)
4181 return false;
2a15795f 4182
821d0e0f 4183 if (dump_file && (dump_flags & TDF_DETAILS))
4184 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
f1c8b4d7 4185 node->name (), node->order);
2a15795f 4186
245ab191 4187 gather_context_independent_values (info, &known_csts, &known_contexts,
87228246 4188 info->do_clone_for_all_contexts ? &known_aggs
4189 : NULL, NULL);
2a15795f 4190
803a7988 4191 for (i = 0; i < count ;i++)
821d0e0f 4192 {
803a7988 4193 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
9bfdb7bc 4194 ipcp_lattice<tree> *lat = &plats->itself;
245ab191 4195 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
2a15795f 4196
803a7988 4197 if (!lat->bottom
245ab191 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 }
3c97c75d 4205
87228246 4206 if (!plats->aggs_bottom)
3b22db66 4207 {
803a7988 4208 struct ipcp_agg_lattice *aglat;
9bfdb7bc 4209 ipcp_value<tree> *val;
803a7988 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
9bfdb7bc 4215 || !aglat->is_single_const ()))
803a7988 4216 for (val = aglat->values; val; val = val->next)
4217 ret |= decide_about_value (node, i, aglat->offset, val,
245ab191 4218 known_csts, known_contexts);
f9e9b574 4219 }
245ab191 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
803a7988 4230 info = IPA_NODE_REF (node);
821d0e0f 4231 }
f9e9b574 4232
87228246 4233 if (info->do_clone_for_all_contexts)
821d0e0f 4234 {
87228246 4235 struct cgraph_node *clone;
415d1b9a 4236 vec<cgraph_edge *> callers;
f9e9b574 4237
821d0e0f 4238 if (dump_file)
4239 fprintf (dump_file, " - Creating a specialized node of %s/%i "
f1c8b4d7 4240 "for all known contexts.\n", node->name (),
02774f2d 4241 node->order);
2a15795f 4242
415d1b9a 4243 callers = node->collect_callers ();
245ab191 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,
803a7988 4251 known_aggs_to_agg_replacement_list (known_aggs),
4252 callers);
821d0e0f 4253 info = IPA_NODE_REF (node);
87228246 4254 info->do_clone_for_all_contexts = false;
4255 IPA_NODE_REF (clone)->is_all_contexts_clone = true;
e4898110 4256 for (i = 0; i < count ; i++)
4257 vec_free (known_aggs[i].items);
4258 known_aggs.release ();
821d0e0f 4259 ret = true;
4260 }
4261 else
245ab191 4262 {
4263 known_csts.release ();
4264 known_contexts.release ();
4265 }
2a15795f 4266
821d0e0f 4267 return ret;
4268}
ccf4ab6b 4269
821d0e0f 4270/* Transitively mark all callees of NODE within the same SCC as not dead. */
1caef38b 4271
821d0e0f 4272static void
4273spread_undeadness (struct cgraph_node *node)
4274{
4275 struct cgraph_edge *cs;
2a15795f 4276
821d0e0f 4277 for (cs = node->callees; cs; cs = cs->next_callee)
a0255a70 4278 if (ipa_edge_within_scc (cs))
821d0e0f 4279 {
4280 struct cgraph_node *callee;
4281 struct ipa_node_params *info;
50828ed8 4282
415d1b9a 4283 callee = cs->callee->function_symbol (NULL);
821d0e0f 4284 info = IPA_NODE_REF (callee);
2a15795f 4285
821d0e0f 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
415d1b9a 4305 && cs->caller->call_for_symbol_thunks_and_aliases
4306 (has_undead_caller_from_outside_scc_p, NULL, true))
821d0e0f 4307 return true;
a0255a70 4308 else if (!ipa_edge_within_scc (cs)
821d0e0f 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;
02774f2d 4322 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
415d1b9a 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))
821d0e0f 4326 IPA_NODE_REF (v)->node_dead = 1;
4327
02774f2d 4328 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
821d0e0f 4329 if (!IPA_NODE_REF (v)->node_dead)
4330 spread_undeadness (v);
4331
4332 if (dump_file && (dump_flags & TDF_DETAILS))
4333 {
02774f2d 4334 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
821d0e0f 4335 if (IPA_NODE_REF (v)->node_dead)
4336 fprintf (dump_file, " Marking node as dead: %s/%i.\n",
f1c8b4d7 4337 v->name (), v->order);
2a15795f 4338 }
821d0e0f 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
9908fe4d 4345ipcp_decision_stage (struct ipa_topo_info *topo)
821d0e0f 4346{
4347 int i;
4348
4349 if (dump_file)
4350 fprintf (dump_file, "\nIPA decision stage:\n\n");
2a15795f 4351
821d0e0f 4352 for (i = topo->nnodes - 1; i >= 0; i--)
2a15795f 4353 {
821d0e0f 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;
02774f2d 4361 for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
415d1b9a 4362 if (v->has_gimple_body_p ()
821d0e0f 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);
3b22db66 4370 }
3b22db66 4371}
4372
ae7b7bc8 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
7715e0c8 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
ae7b7bc8 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
3b22db66 4439/* The IPCP driver. */
821d0e0f 4440
8624b7fc 4441static unsigned int
3b22db66 4442ipcp_driver (void)
4443{
821d0e0f 4444 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
948ccfa6 4445 struct cgraph_edge_hook_list *edge_removal_hook_holder;
9908fe4d 4446 struct ipa_topo_info topo;
821d0e0f 4447
821d0e0f 4448 ipa_check_create_node_params ();
4449 ipa_check_create_edge_args ();
948ccfa6 4450 grow_edge_clone_vectors ();
821d0e0f 4451 edge_duplication_hook_holder =
35ee1c66 4452 symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
948ccfa6 4453 edge_removal_hook_holder =
35ee1c66 4454 symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
948ccfa6 4455
3b22db66 4456 if (dump_file)
4457 {
11b73810 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);
3b22db66 4462 }
821d0e0f 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);
ae7b7bc8 4470 /* Store results of alignment propagation. */
4471 ipcp_store_alignment_results ();
821d0e0f 4472
3b22db66 4473 /* Free all IPCP structures. */
821d0e0f 4474 free_toporder_info (&topo);
f1f41a6c 4475 next_edge_clone.release ();
71fe79b2 4476 prev_edge_clone.release ();
35ee1c66 4477 symtab->remove_edge_removal_hook (edge_removal_hook_holder);
4478 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
799c8711 4479 ipa_free_all_structures_after_ipa_cp ();
3b22db66 4480 if (dump_file)
4481 fprintf (dump_file, "\nIPA constant propagation end\n");
2a1990e9 4482 return 0;
3b22db66 4483}
4484
1caef38b 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
50828ed8 4489static void
4490ipcp_generate_summary (void)
4491{
1caef38b 4492 struct cgraph_node *node;
4493
50828ed8 4494 if (dump_file)
4495 fprintf (dump_file, "\nIPA constant propagation start:\n");
50828ed8 4496 ipa_register_cgraph_hooks ();
1caef38b 4497
91bf9d9a 4498 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1caef38b 4499 {
7d0d0ce1 4500 node->local.versionable
02774f2d 4501 = tree_versionable_function_p (node->decl);
1caef38b 4502 ipa_analyze_node (node);
4503 }
50828ed8 4504}
4505
8867b500 4506/* Write ipcp summary for nodes in SET. */
821d0e0f 4507
8867b500 4508static void
eab36a5a 4509ipcp_write_summary (void)
8867b500 4510{
eab36a5a 4511 ipa_prop_write_jump_functions ();
8867b500 4512}
4513
4514/* Read ipcp summary. */
821d0e0f 4515
8867b500 4516static void
4517ipcp_read_summary (void)
4518{
4519 ipa_prop_read_jump_functions ();
4520}
4521
cbe8bda8 4522namespace {
4523
4524const pass_data pass_data_ipa_cp =
4525{
4526 IPA_PASS, /* type */
4527 "cp", /* name */
4528 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 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 */
3b22db66 4535};
cbe8bda8 4536
4537class pass_ipa_cp : public ipa_opt_pass_d
4538{
4539public:
9af5ce0c 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 */
ae7b7bc8 4545 ipcp_write_transformation_summaries, /*
9af5ce0c 4546 write_optimization_summary */
ae7b7bc8 4547 ipcp_read_transformation_summaries, /*
9af5ce0c 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 */
cbe8bda8 4553 {}
4554
4555 /* opt_pass methods: */
31315c24 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. */
d1f68cd8 4560 return (flag_ipa_cp && optimize) || in_lto_p;
31315c24 4561 }
4562
65b0537f 4563 virtual unsigned int execute (function *) { return ipcp_driver (); }
cbe8bda8 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}
415309e2 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;
415309e2 4584}