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