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