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