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