1/* Function summary pass.
2 Copyright (C) 2003-2024 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21/* Analysis of function bodies used by inter-procedural passes
22
23 We estimate for each function
24 - function body size and size after specializing into given context
25 - average function execution time in a given context
26 - function frame size
27 For each call
28 - call statement size, time and how often the parameters change
29
30 ipa_fn_summary data structures store above information locally (i.e.
31 parameters of the function itself) and globally (i.e. parameters of
32 the function created by applying all the inline decisions already
33 present in the callgraph).
34
35 We provide access to the ipa_fn_summary data structure and
36 basic logic updating the parameters when inlining is performed.
37
38 The summaries are context sensitive. Context means
39 1) partial assignment of known constant values of operands
40 2) whether function is inlined into the call or not.
41 It is easy to add more variants. To represent function size and time
42 that depends on context (i.e. it is known to be optimized away when
43 context is known either by inlining or from IP-CP and cloning),
44 we use predicates.
45
46 estimate_edge_size_and_time can be used to query
47 function size/time in the given context. ipa_merge_fn_summary_after_inlining merges
48 properties of caller and callee after inlining.
49
50 Finally pass_inline_parameters is exported. This is used to drive
51 computation of function parameters used by the early inliner. IPA
52 inlined performs analysis via its analyze_function method. */
53
54#include "config.h"
55#define INCLUDE_VECTOR
56#include "system.h"
57#include "coretypes.h"
58#include "backend.h"
59#include "target.h"
60#include "tree.h"
61#include "gimple.h"
62#include "alloc-pool.h"
63#include "tree-pass.h"
64#include "ssa.h"
65#include "tree-streamer.h"
66#include "cgraph.h"
67#include "diagnostic.h"
68#include "fold-const.h"
69#include "print-tree.h"
70#include "tree-inline.h"
71#include "gimple-pretty-print.h"
72#include "cfganal.h"
73#include "gimple-iterator.h"
74#include "tree-cfg.h"
75#include "tree-ssa-loop-niter.h"
76#include "tree-ssa-loop.h"
77#include "symbol-summary.h"
78#include "sreal.h"
79#include "ipa-cp.h"
80#include "ipa-prop.h"
81#include "ipa-fnsummary.h"
82#include "cfgloop.h"
83#include "tree-scalar-evolution.h"
84#include "ipa-utils.h"
85#include "cfgexpand.h"
86#include "gimplify.h"
87#include "stringpool.h"
88#include "attribs.h"
89#include "tree-into-ssa.h"
90#include "symtab-clones.h"
91#include "gimple-range.h"
92#include "tree-dfa.h"
93
94/* Summaries. */
95fast_function_summary <ipa_fn_summary *, va_gc> *ipa_fn_summaries;
96fast_function_summary <ipa_size_summary *, va_heap> *ipa_size_summaries;
97fast_call_summary <ipa_call_summary *, va_heap> *ipa_call_summaries;
98
99/* Edge predicates goes here. */
100static object_allocator<ipa_predicate> edge_predicate_pool ("edge predicates");
101
102
103/* Dump IPA hints. */
104void
105ipa_dump_hints (FILE *f, ipa_hints hints)
106{
107 if (!hints)
108 return;
109 fprintf (stream: f, format: "IPA hints:");
110 if (hints & INLINE_HINT_indirect_call)
111 {
112 hints &= ~INLINE_HINT_indirect_call;
113 fprintf (stream: f, format: " indirect_call");
114 }
115 if (hints & INLINE_HINT_loop_iterations)
116 {
117 hints &= ~INLINE_HINT_loop_iterations;
118 fprintf (stream: f, format: " loop_iterations");
119 }
120 if (hints & INLINE_HINT_loop_stride)
121 {
122 hints &= ~INLINE_HINT_loop_stride;
123 fprintf (stream: f, format: " loop_stride");
124 }
125 if (hints & INLINE_HINT_same_scc)
126 {
127 hints &= ~INLINE_HINT_same_scc;
128 fprintf (stream: f, format: " same_scc");
129 }
130 if (hints & INLINE_HINT_in_scc)
131 {
132 hints &= ~INLINE_HINT_in_scc;
133 fprintf (stream: f, format: " in_scc");
134 }
135 if (hints & INLINE_HINT_cross_module)
136 {
137 hints &= ~INLINE_HINT_cross_module;
138 fprintf (stream: f, format: " cross_module");
139 }
140 if (hints & INLINE_HINT_declared_inline)
141 {
142 hints &= ~INLINE_HINT_declared_inline;
143 fprintf (stream: f, format: " declared_inline");
144 }
145 if (hints & INLINE_HINT_known_hot)
146 {
147 hints &= ~INLINE_HINT_known_hot;
148 fprintf (stream: f, format: " known_hot");
149 }
150 if (hints & INLINE_HINT_builtin_constant_p)
151 {
152 hints &= ~INLINE_HINT_builtin_constant_p;
153 fprintf (stream: f, format: " builtin_constant_p");
154 }
155 gcc_assert (!hints);
156}
157
158
159/* Record SIZE and TIME to SUMMARY.
160 The accounted code will be executed when EXEC_PRED is true.
161 When NONCONST_PRED is false the code will evaluate to constant and
162 will get optimized out in specialized clones of the function.
163 If CALL is true account to call_size_time_table rather than
164 size_time_table. */
165
166void
167ipa_fn_summary::account_size_time (int size, sreal time,
168 const ipa_predicate &exec_pred,
169 const ipa_predicate &nonconst_pred_in,
170 bool call)
171{
172 size_time_entry *e;
173 bool found = false;
174 int i;
175 ipa_predicate nonconst_pred;
176 vec<size_time_entry> *table = call ? &call_size_time_table : &size_time_table;
177
178 if (exec_pred == false)
179 return;
180
181 nonconst_pred = nonconst_pred_in & exec_pred;
182
183 if (nonconst_pred == false)
184 return;
185
186 /* We need to create initial empty unconditional clause, but otherwise
187 we don't need to account empty times and sizes. */
188 if (!size && time == 0 && table->length ())
189 return;
190
191 /* Only for calls we are unaccounting what we previously recorded. */
192 gcc_checking_assert (time >= 0 || call);
193
194 for (i = 0; table->iterate (ix: i, ptr: &e); i++)
195 if (e->exec_predicate == exec_pred
196 && e->nonconst_predicate == nonconst_pred)
197 {
198 found = true;
199 break;
200 }
201 if (i == max_size_time_table_size)
202 {
203 i = 0;
204 found = true;
205 e = &(*table)[0];
206 if (dump_file && (dump_flags & TDF_DETAILS))
207 fprintf (stream: dump_file,
208 format: "\t\tReached limit on number of entries, "
209 "ignoring the predicate.");
210 }
211 if (dump_file && (dump_flags & TDF_DETAILS) && (time != 0 || size))
212 {
213 fprintf (stream: dump_file,
214 format: "\t\tAccounting size:%3.2f, time:%3.2f on %spredicate exec:",
215 ((double) size) / ipa_fn_summary::size_scale,
216 (time.to_double ()), found ? "" : "new ");
217 exec_pred.dump (f: dump_file, conds, nl: 0);
218 if (exec_pred != nonconst_pred)
219 {
220 fprintf (stream: dump_file, format: " nonconst:");
221 nonconst_pred.dump (f: dump_file, conds);
222 }
223 else
224 fprintf (stream: dump_file, format: "\n");
225 }
226 if (!found)
227 {
228 class size_time_entry new_entry;
229 new_entry.size = size;
230 new_entry.time = time;
231 new_entry.exec_predicate = exec_pred;
232 new_entry.nonconst_predicate = nonconst_pred;
233 if (call)
234 call_size_time_table.safe_push (obj: new_entry);
235 else
236 size_time_table.safe_push (obj: new_entry);
237 }
238 else
239 {
240 e->size += size;
241 e->time += time;
242 /* FIXME: PR bootstrap/92653 gcc_checking_assert (e->time >= -1); */
243 /* Tolerate small roundoff issues. */
244 if (e->time < 0)
245 e->time = 0;
246 }
247}
248
249/* We proved E to be unreachable, redirect it to __builtin_unreachable. */
250
251static struct cgraph_edge *
252redirect_to_unreachable (struct cgraph_edge *e)
253{
254 struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
255 struct cgraph_node *target
256 = cgraph_node::get_create (builtin_decl_unreachable ());
257
258 if (e->speculative)
259 e = cgraph_edge::resolve_speculation (edge: e, callee_decl: target->decl);
260 else if (!e->callee)
261 e = cgraph_edge::make_direct (edge: e, callee: target);
262 else
263 e->redirect_callee (n: target);
264 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
265 e->inline_failed = CIF_UNREACHABLE;
266 e->count = profile_count::zero ();
267 es->call_stmt_size = 0;
268 es->call_stmt_time = 0;
269 if (callee)
270 callee->remove_symbol_and_inline_clones ();
271 return e;
272}
273
274/* Set predicate for edge E. */
275
276static void
277edge_set_predicate (struct cgraph_edge *e, ipa_predicate *predicate)
278{
279 /* If the edge is determined to be never executed, redirect it
280 to BUILTIN_UNREACHABLE to make it clear to IPA passes the call will
281 be optimized out. */
282 if (predicate && *predicate == false
283 /* When handling speculative edges, we need to do the redirection
284 just once. Do it always on the direct edge, so we do not
285 attempt to resolve speculation while duplicating the edge. */
286 && (!e->speculative || e->callee))
287 e = redirect_to_unreachable (e);
288
289 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
290 if (predicate && *predicate != true)
291 {
292 if (!es->predicate)
293 es->predicate = edge_predicate_pool.allocate ();
294 *es->predicate = *predicate;
295 }
296 else
297 {
298 if (es->predicate)
299 edge_predicate_pool.remove (object: es->predicate);
300 es->predicate = NULL;
301 }
302}
303
304/* Set predicate for hint *P. */
305
306static void
307set_hint_predicate (ipa_predicate **p, ipa_predicate new_predicate)
308{
309 if (new_predicate == false || new_predicate == true)
310 {
311 if (*p)
312 edge_predicate_pool.remove (object: *p);
313 *p = NULL;
314 }
315 else
316 {
317 if (!*p)
318 *p = edge_predicate_pool.allocate ();
319 **p = new_predicate;
320 }
321}
322
323/* Find if NEW_PREDICATE is already in V and if so, increment its freq.
324 Otherwise add a new item to the vector with this predicate and frerq equal
325 to add_freq, unless the number of predicates would exceed MAX_NUM_PREDICATES
326 in which case the function does nothing. */
327
328static void
329add_freqcounting_predicate (vec<ipa_freqcounting_predicate, va_gc> **v,
330 const ipa_predicate &new_predicate, sreal add_freq,
331 unsigned max_num_predicates)
332{
333 if (new_predicate == false || new_predicate == true)
334 return;
335 ipa_freqcounting_predicate *f;
336 for (int i = 0; vec_safe_iterate (v: *v, ix: i, ptr: &f); i++)
337 if (new_predicate == f->predicate)
338 {
339 f->freq += add_freq;
340 return;
341 }
342 if (vec_safe_length (v: *v) >= max_num_predicates)
343 /* Too many different predicates to account for. */
344 return;
345
346 ipa_freqcounting_predicate fcp;
347 fcp.predicate = NULL;
348 set_hint_predicate (p: &fcp.predicate, new_predicate);
349 fcp.freq = add_freq;
350 vec_safe_push (v&: *v, obj: fcp);
351 return;
352}
353
354/* Compute what conditions may or may not hold given information about
355 parameters. RET_CLAUSE returns truths that may hold in a specialized copy,
356 while RET_NONSPEC_CLAUSE returns truths that may hold in an nonspecialized
357 copy when called in a given context. It is a bitmask of conditions. Bit
358 0 means that condition is known to be false, while bit 1 means that condition
359 may or may not be true. These differs - for example NOT_INLINED condition
360 is always false in the second and also builtin_constant_p tests cannot use
361 the fact that parameter is indeed a constant.
362
363 When INLINE_P is true, assume that we are inlining. AVAL contains known
364 information about argument values. The function does not modify its content
365 and so AVALs could also be of type ipa_call_arg_values but so far all
366 callers work with the auto version and so we avoid the conversion for
367 convenience.
368
369 ERROR_MARK value of an argument means compile time invariant. */
370
371static void
372evaluate_conditions_for_known_args (struct cgraph_node *node,
373 bool inline_p,
374 ipa_auto_call_arg_values *avals,
375 clause_t *ret_clause,
376 clause_t *ret_nonspec_clause,
377 ipa_call_summary *es)
378{
379 clause_t clause = inline_p ? 0 : 1 << ipa_predicate::not_inlined_condition;
380 clause_t nonspec_clause = 1 << ipa_predicate::not_inlined_condition;
381 class ipa_fn_summary *info = ipa_fn_summaries->get (node);
382 int i;
383 struct condition *c;
384
385 for (i = 0; vec_safe_iterate (v: info->conds, ix: i, ptr: &c); i++)
386 {
387 tree val = NULL;
388 tree res;
389 int j;
390 struct expr_eval_op *op;
391
392 if (c->code == ipa_predicate::not_sra_candidate)
393 {
394 if (!inline_p
395 || !es
396 || (int)es->param.length () <= c->operand_num
397 || !es->param[c->operand_num].points_to_possible_sra_candidate)
398 clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
399 nonspec_clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
400 continue;
401 }
402
403 if (c->agg_contents)
404 {
405 if (c->code == ipa_predicate::changed
406 && !c->by_ref
407 && (avals->safe_sval_at(index: c->operand_num) == error_mark_node))
408 continue;
409
410 if (tree sval = avals->safe_sval_at (index: c->operand_num))
411 val = ipa_find_agg_cst_from_init (scalar: sval, offset: c->offset, by_ref: c->by_ref);
412 if (!val)
413 {
414 ipa_argagg_value_list avs (avals);
415 val = avs.get_value (index: c->operand_num, unit_offset: c->offset / BITS_PER_UNIT,
416 by_ref: c->by_ref);
417 }
418 }
419 else
420 {
421 val = avals->safe_sval_at (index: c->operand_num);
422 if (val && val == error_mark_node
423 && c->code != ipa_predicate::changed)
424 val = NULL_TREE;
425 }
426
427 if (!val
428 && (c->code == ipa_predicate::changed
429 || c->code == ipa_predicate::is_not_constant))
430 {
431 clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
432 nonspec_clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
433 continue;
434 }
435 if (c->code == ipa_predicate::changed)
436 {
437 nonspec_clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
438 continue;
439 }
440
441 if (c->code == ipa_predicate::is_not_constant)
442 {
443 nonspec_clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
444 continue;
445 }
446
447 if (val && TYPE_SIZE (c->type) == TYPE_SIZE (TREE_TYPE (val)))
448 {
449 if (c->type != TREE_TYPE (val))
450 val = fold_unary (VIEW_CONVERT_EXPR, c->type, val);
451 for (j = 0; vec_safe_iterate (v: c->param_ops, ix: j, ptr: &op); j++)
452 {
453 if (!val)
454 break;
455 if (!op->val[0])
456 val = fold_unary (op->code, op->type, val);
457 else if (!op->val[1])
458 val = fold_binary (op->code, op->type,
459 op->index ? op->val[0] : val,
460 op->index ? val : op->val[0]);
461 else if (op->index == 0)
462 val = fold_ternary (op->code, op->type,
463 val, op->val[0], op->val[1]);
464 else if (op->index == 1)
465 val = fold_ternary (op->code, op->type,
466 op->val[0], val, op->val[1]);
467 else if (op->index == 2)
468 val = fold_ternary (op->code, op->type,
469 op->val[0], op->val[1], val);
470 else
471 val = NULL_TREE;
472 }
473
474 res = val
475 ? fold_binary_to_constant (c->code, boolean_type_node, val, c->val)
476 : NULL;
477
478 if (res && integer_zerop (res))
479 continue;
480 if (res && integer_onep (res))
481 {
482 clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
483 nonspec_clause
484 |= 1 << (i + ipa_predicate::first_dynamic_condition);
485 continue;
486 }
487 }
488 if (c->operand_num < (int) avals->m_known_value_ranges.length ()
489 && !c->agg_contents
490 && (!val || TREE_CODE (val) != INTEGER_CST))
491 {
492 Value_Range vr (avals->m_known_value_ranges[c->operand_num]);
493 if (!vr.undefined_p ()
494 && !vr.varying_p ()
495 && (TYPE_SIZE (c->type) == TYPE_SIZE (vr.type ())))
496 {
497 if (!useless_type_conversion_p (c->type, vr.type ()))
498 range_cast (r&: vr, type: c->type);
499
500 for (j = 0; vec_safe_iterate (v: c->param_ops, ix: j, ptr: &op); j++)
501 {
502 if (vr.varying_p () || vr.undefined_p ())
503 break;
504
505 Value_Range res (op->type);
506 if (!op->val[0])
507 {
508 Value_Range varying (op->type);
509 varying.set_varying (op->type);
510 range_op_handler handler (op->code);
511 if (!handler
512 || !res.supports_type_p (type: op->type)
513 || !handler.fold_range (r&: res, type: op->type, lh: vr, rh: varying))
514 res.set_varying (op->type);
515 }
516 else if (!op->val[1])
517 {
518 Value_Range op0 (op->type);
519 range_op_handler handler (op->code);
520
521 ipa_range_set_and_normalize (r&: op0, val: op->val[0]);
522
523 if (!handler
524 || !res.supports_type_p (type: op->type)
525 || !handler.fold_range (r&: res, type: op->type,
526 lh: op->index ? op0 : vr,
527 rh: op->index ? vr : op0))
528 res.set_varying (op->type);
529 }
530 else
531 res.set_varying (op->type);
532 vr = res;
533 }
534 if (!vr.varying_p () && !vr.undefined_p ())
535 {
536 int_range<2> res;
537 Value_Range val_vr (TREE_TYPE (c->val));
538 range_op_handler handler (c->code);
539
540 ipa_range_set_and_normalize (r&: val_vr, val: c->val);
541
542 if (!handler
543 || !val_vr.supports_type_p (TREE_TYPE (c->val))
544 || !handler.fold_range (r&: res, boolean_type_node, lh: vr, rh: val_vr))
545 res.set_varying (boolean_type_node);
546
547 if (res.zero_p ())
548 continue;
549 }
550 }
551 }
552
553 clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
554 nonspec_clause |= 1 << (i + ipa_predicate::first_dynamic_condition);
555 }
556 *ret_clause = clause;
557 if (ret_nonspec_clause)
558 *ret_nonspec_clause = nonspec_clause;
559}
560
561/* Return true if VRP will be exectued on the function.
562 We do not want to anticipate optimizations that will not happen.
563
564 FIXME: This can be confused with -fdisable and debug counters and thus
565 it should not be used for correctness (only to make heuristics work).
566 This means that inliner should do its own optimizations of expressions
567 that it predicts to be constant so wrong code can not be triggered by
568 builtin_constant_p. */
569
570static bool
571vrp_will_run_p (struct cgraph_node *node)
572{
573 return (opt_for_fn (node->decl, optimize)
574 && !opt_for_fn (node->decl, optimize_debug)
575 && opt_for_fn (node->decl, flag_tree_vrp));
576}
577
578/* Similarly about FRE. */
579
580static bool
581fre_will_run_p (struct cgraph_node *node)
582{
583 return (opt_for_fn (node->decl, optimize)
584 && !opt_for_fn (node->decl, optimize_debug)
585 && opt_for_fn (node->decl, flag_tree_fre));
586}
587
588/* Work out what conditions might be true at invocation of E.
589 Compute costs for inlined edge if INLINE_P is true.
590
591 Return in CLAUSE_PTR the evaluated conditions and in NONSPEC_CLAUSE_PTR
592 (if non-NULL) conditions evaluated for nonspecialized clone called
593 in a given context.
594
595 Vectors in AVALS will be populated with useful known information about
596 argument values - information not known to have any uses will be omitted -
597 except for m_known_contexts which will only be calculated if
598 COMPUTE_CONTEXTS is true. */
599
600void
601evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
602 clause_t *clause_ptr,
603 clause_t *nonspec_clause_ptr,
604 ipa_auto_call_arg_values *avals,
605 bool compute_contexts)
606{
607 struct cgraph_node *callee = e->callee->ultimate_alias_target ();
608 class ipa_fn_summary *info = ipa_fn_summaries->get (node: callee);
609 class ipa_edge_args *args;
610 class ipa_call_summary *es = NULL;
611
612 if (clause_ptr)
613 *clause_ptr = inline_p ? 0 : 1 << ipa_predicate::not_inlined_condition;
614
615 if (ipa_node_params_sum
616 && !e->call_stmt_cannot_inline_p
617 && (info->conds || compute_contexts)
618 && (args = ipa_edge_args_sum->get (edge: e)) != NULL)
619 {
620 struct cgraph_node *caller;
621 class ipa_node_params *caller_parms_info, *callee_pi = NULL;
622 int i, count = ipa_get_cs_argument_count (args);
623 es = ipa_call_summaries->get (edge: e);
624
625 if (count)
626 {
627 if (e->caller->inlined_to)
628 caller = e->caller->inlined_to;
629 else
630 caller = e->caller;
631 caller_parms_info = ipa_node_params_sum->get (node: caller);
632 callee_pi = ipa_node_params_sum->get (node: callee);
633
634 /* Watch for thunks. */
635 if (callee_pi)
636 /* Watch for variadic functions. */
637 count = MIN (count, ipa_get_param_count (callee_pi));
638 }
639
640 if (callee_pi)
641 for (i = 0; i < count; i++)
642 {
643 struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
644
645 if (ipa_is_param_used_by_indirect_call (info: callee_pi, i)
646 || ipa_is_param_used_by_ipa_predicates (info: callee_pi, i))
647 {
648 /* Determine if we know constant value of the parameter. */
649 tree type = ipa_get_type (info: callee_pi, i);
650 tree cst = ipa_value_from_jfunc (info: caller_parms_info, jfunc: jf, type);
651
652 if (!cst && e->call_stmt
653 && i < (int)gimple_call_num_args (gs: e->call_stmt))
654 {
655 cst = gimple_call_arg (gs: e->call_stmt, index: i);
656 if (!is_gimple_min_invariant (cst))
657 cst = NULL;
658 }
659 if (cst)
660 {
661 gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO);
662 if (!avals->m_known_vals.length ())
663 avals->m_known_vals.safe_grow_cleared (len: count, exact: true);
664 avals->m_known_vals[i] = cst;
665 }
666 else if (inline_p && !es->param[i].change_prob)
667 {
668 if (!avals->m_known_vals.length ())
669 avals->m_known_vals.safe_grow_cleared (len: count, exact: true);
670 avals->m_known_vals[i] = error_mark_node;
671 }
672
673 /* If we failed to get simple constant, try value range. */
674 if ((!cst || TREE_CODE (cst) != INTEGER_CST)
675 && vrp_will_run_p (node: caller)
676 && ipa_is_param_used_by_ipa_predicates (info: callee_pi, i))
677 {
678 Value_Range vr (type);
679
680 ipa_value_range_from_jfunc (vr, caller_parms_info, e, jf, type);
681 if (!vr.undefined_p () && !vr.varying_p ())
682 {
683 if (!avals->m_known_value_ranges.length ())
684 avals->m_known_value_ranges.safe_grow_cleared (len: count,
685 exact: true);
686 avals->m_known_value_ranges[i] = vr;
687 }
688 }
689
690 /* Determine known aggregate values. */
691 if (fre_will_run_p (node: caller))
692 ipa_push_agg_values_from_jfunc (info: caller_parms_info,
693 node: caller, agg_jfunc: &jf->agg, dst_index: i,
694 res: &avals->m_known_aggs);
695 }
696
697 /* For calls used in polymorphic calls we further determine
698 polymorphic call context. */
699 if (compute_contexts
700 && ipa_is_param_used_by_polymorphic_call (info: callee_pi, i))
701 {
702 ipa_polymorphic_call_context
703 ctx = ipa_context_from_jfunc (caller_parms_info, e, i, jf);
704 if (!ctx.useless_p ())
705 {
706 if (!avals->m_known_contexts.length ())
707 avals->m_known_contexts.safe_grow_cleared (len: count, exact: true);
708 avals->m_known_contexts[i]
709 = ipa_context_from_jfunc (caller_parms_info, e, i, jf);
710 }
711 }
712 }
713 else
714 gcc_assert (!count || callee->thunk);
715 }
716 else if (e->call_stmt && !e->call_stmt_cannot_inline_p && info->conds)
717 {
718 int i, count = (int)gimple_call_num_args (gs: e->call_stmt);
719
720 for (i = 0; i < count; i++)
721 {
722 tree cst = gimple_call_arg (gs: e->call_stmt, index: i);
723 if (!is_gimple_min_invariant (cst))
724 cst = NULL;
725 if (cst)
726 {
727 if (!avals->m_known_vals.length ())
728 avals->m_known_vals.safe_grow_cleared (len: count, exact: true);
729 avals->m_known_vals[i] = cst;
730 }
731 }
732 }
733
734 evaluate_conditions_for_known_args (node: callee, inline_p, avals, ret_clause: clause_ptr,
735 ret_nonspec_clause: nonspec_clause_ptr, es);
736}
737
738
739/* Allocate the function summary. */
740
741static void
742ipa_fn_summary_alloc (void)
743{
744 gcc_checking_assert (!ipa_fn_summaries);
745 ipa_size_summaries = new ipa_size_summary_t (symtab);
746 ipa_fn_summaries = ipa_fn_summary_t::create_ggc (symtab);
747 ipa_call_summaries = new ipa_call_summary_t (symtab);
748}
749
750ipa_call_summary::~ipa_call_summary ()
751{
752 if (predicate)
753 edge_predicate_pool.remove (object: predicate);
754
755 param.release ();
756}
757
758ipa_fn_summary::~ipa_fn_summary ()
759{
760 unsigned len = vec_safe_length (v: loop_iterations);
761 for (unsigned i = 0; i < len; i++)
762 edge_predicate_pool.remove (object: (*loop_iterations)[i].predicate);
763 len = vec_safe_length (v: loop_strides);
764 for (unsigned i = 0; i < len; i++)
765 edge_predicate_pool.remove (object: (*loop_strides)[i].predicate);
766 vec_free (v&: conds);
767 call_size_time_table.release ();
768 vec_free (v&: loop_iterations);
769 vec_free (v&: loop_strides);
770 builtin_constant_p_parms.release ();
771}
772
773void
774ipa_fn_summary_t::remove_callees (cgraph_node *node)
775{
776 cgraph_edge *e;
777 for (e = node->callees; e; e = e->next_callee)
778 ipa_call_summaries->remove (edge: e);
779 for (e = node->indirect_calls; e; e = e->next_callee)
780 ipa_call_summaries->remove (edge: e);
781}
782
783/* Duplicate predicates in loop hint vector, allocating memory for them and
784 remove and deallocate any uninteresting (true or false) ones. Return the
785 result. */
786
787static vec<ipa_freqcounting_predicate, va_gc> *
788remap_freqcounting_preds_after_dup (vec<ipa_freqcounting_predicate, va_gc> *v,
789 clause_t possible_truths)
790{
791 if (vec_safe_length (v) == 0)
792 return NULL;
793
794 vec<ipa_freqcounting_predicate, va_gc> *res = v->copy ();
795 int len = res->length();
796 for (int i = len - 1; i >= 0; i--)
797 {
798 ipa_predicate new_predicate
799 = (*res)[i].predicate->remap_after_duplication (possible_truths);
800 /* We do not want to free previous predicate; it is used by node
801 origin. */
802 (*res)[i].predicate = NULL;
803 set_hint_predicate (p: &(*res)[i].predicate, new_predicate);
804
805 if (!(*res)[i].predicate)
806 res->unordered_remove (ix: i);
807 }
808
809 return res;
810}
811
812
813/* Hook that is called by cgraph.cc when a node is duplicated. */
814void
815ipa_fn_summary_t::duplicate (cgraph_node *src,
816 cgraph_node *dst,
817 ipa_fn_summary *src_info,
818 ipa_fn_summary *info)
819{
820 new (info) ipa_fn_summary (*src_info);
821 /* TODO: as an optimization, we may avoid copying conditions
822 that are known to be false or true. */
823 info->conds = vec_safe_copy (src: info->conds);
824
825 clone_info *cinfo = clone_info::get (node: dst);
826 /* When there are any replacements in the function body, see if we can figure
827 out that something was optimized out. */
828 if (ipa_node_params_sum && cinfo && cinfo->tree_map)
829 {
830 /* Use SRC parm info since it may not be copied yet. */
831 ipa_node_params *parms_info = ipa_node_params_sum->get (node: src);
832 ipa_auto_call_arg_values avals;
833 int count = ipa_get_param_count (info: parms_info);
834 int i, j;
835 clause_t possible_truths;
836 ipa_predicate true_pred = true;
837 size_time_entry *e;
838 int optimized_out_size = 0;
839 bool inlined_to_p = false;
840 struct cgraph_edge *edge, *next;
841
842 info->size_time_table.release ();
843 avals.m_known_vals.safe_grow_cleared (len: count, exact: true);
844 for (i = 0; i < count; i++)
845 {
846 struct ipa_replace_map *r;
847
848 for (j = 0; vec_safe_iterate (v: cinfo->tree_map, ix: j, ptr: &r); j++)
849 {
850 if (r->parm_num == i)
851 {
852 avals.m_known_vals[i] = r->new_tree;
853 break;
854 }
855 }
856 }
857 evaluate_conditions_for_known_args (node: dst, inline_p: false,
858 avals: &avals,
859 ret_clause: &possible_truths,
860 /* We are going to specialize,
861 so ignore nonspec truths. */
862 NULL,
863 NULL);
864
865 info->account_size_time (size: 0, time: 0, exec_pred: true_pred, nonconst_pred_in: true_pred);
866
867 /* Remap size_time vectors.
868 Simplify the predicate by pruning out alternatives that are known
869 to be false.
870 TODO: as on optimization, we can also eliminate conditions known
871 to be true. */
872 for (i = 0; src_info->size_time_table.iterate (ix: i, ptr: &e); i++)
873 {
874 ipa_predicate new_exec_pred;
875 ipa_predicate new_nonconst_pred;
876 new_exec_pred = e->exec_predicate.remap_after_duplication
877 (possible_truths);
878 new_nonconst_pred = e->nonconst_predicate.remap_after_duplication
879 (possible_truths);
880 if (new_exec_pred == false || new_nonconst_pred == false)
881 optimized_out_size += e->size;
882 else
883 info->account_size_time (size: e->size, time: e->time, exec_pred: new_exec_pred,
884 nonconst_pred_in: new_nonconst_pred);
885 }
886
887 /* Remap edge predicates with the same simplification as above.
888 Also copy constantness arrays. */
889 for (edge = dst->callees; edge; edge = next)
890 {
891 ipa_predicate new_predicate;
892 class ipa_call_summary *es = ipa_call_summaries->get (edge);
893 next = edge->next_callee;
894
895 if (!edge->inline_failed)
896 inlined_to_p = true;
897 if (!es->predicate)
898 continue;
899 new_predicate = es->predicate->remap_after_duplication
900 (possible_truths);
901 if (new_predicate == false && *es->predicate != false)
902 optimized_out_size += es->call_stmt_size * ipa_fn_summary::size_scale;
903 edge_set_predicate (e: edge, predicate: &new_predicate);
904 }
905
906 /* Remap indirect edge predicates with the same simplification as above.
907 Also copy constantness arrays. */
908 for (edge = dst->indirect_calls; edge; edge = next)
909 {
910 ipa_predicate new_predicate;
911 class ipa_call_summary *es = ipa_call_summaries->get (edge);
912 next = edge->next_callee;
913
914 gcc_checking_assert (edge->inline_failed);
915 if (!es->predicate)
916 continue;
917 new_predicate = es->predicate->remap_after_duplication
918 (possible_truths);
919 if (new_predicate == false && *es->predicate != false)
920 optimized_out_size
921 += es->call_stmt_size * ipa_fn_summary::size_scale;
922 edge_set_predicate (e: edge, predicate: &new_predicate);
923 }
924 info->loop_iterations
925 = remap_freqcounting_preds_after_dup (v: info->loop_iterations,
926 possible_truths);
927 info->loop_strides
928 = remap_freqcounting_preds_after_dup (v: info->loop_strides,
929 possible_truths);
930 if (info->builtin_constant_p_parms.length())
931 {
932 vec <int, va_heap, vl_ptr> parms = info->builtin_constant_p_parms;
933 int ip;
934 info->builtin_constant_p_parms = vNULL;
935 for (i = 0; parms.iterate (ix: i, ptr: &ip); i++)
936 if (!avals.m_known_vals[ip])
937 info->builtin_constant_p_parms.safe_push (obj: ip);
938 }
939
940 /* If inliner or someone after inliner will ever start producing
941 non-trivial clones, we will get trouble with lack of information
942 about updating self sizes, because size vectors already contains
943 sizes of the callees. */
944 gcc_assert (!inlined_to_p || !optimized_out_size);
945 }
946 else
947 {
948 info->size_time_table = src_info->size_time_table.copy ();
949 info->loop_iterations = vec_safe_copy (src: src_info->loop_iterations);
950 info->loop_strides = vec_safe_copy (src: info->loop_strides);
951
952 info->builtin_constant_p_parms
953 = info->builtin_constant_p_parms.copy ();
954
955 ipa_freqcounting_predicate *f;
956 for (int i = 0; vec_safe_iterate (v: info->loop_iterations, ix: i, ptr: &f); i++)
957 {
958 ipa_predicate p = *f->predicate;
959 f->predicate = NULL;
960 set_hint_predicate (p: &f->predicate, new_predicate: p);
961 }
962 for (int i = 0; vec_safe_iterate (v: info->loop_strides, ix: i, ptr: &f); i++)
963 {
964 ipa_predicate p = *f->predicate;
965 f->predicate = NULL;
966 set_hint_predicate (p: &f->predicate, new_predicate: p);
967 }
968 }
969 if (!dst->inlined_to)
970 ipa_update_overall_fn_summary (node: dst);
971}
972
973
974/* Hook that is called by cgraph.cc when a node is duplicated. */
975
976void
977ipa_call_summary_t::duplicate (struct cgraph_edge *src,
978 struct cgraph_edge *dst,
979 class ipa_call_summary *srcinfo,
980 class ipa_call_summary *info)
981{
982 new (info) ipa_call_summary (*srcinfo);
983 info->predicate = NULL;
984 edge_set_predicate (e: dst, predicate: srcinfo->predicate);
985 info->param = srcinfo->param.copy ();
986 if (!dst->indirect_unknown_callee && src->indirect_unknown_callee)
987 {
988 info->call_stmt_size -= (eni_size_weights.indirect_call_cost
989 - eni_size_weights.call_cost);
990 info->call_stmt_time -= (eni_time_weights.indirect_call_cost
991 - eni_time_weights.call_cost);
992 }
993}
994
995/* Dump edge summaries associated to NODE and recursively to all clones.
996 Indent by INDENT. */
997
998static void
999dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node,
1000 class ipa_fn_summary *info)
1001{
1002 struct cgraph_edge *edge;
1003 for (edge = node->callees; edge; edge = edge->next_callee)
1004 {
1005 class ipa_call_summary *es = ipa_call_summaries->get (edge);
1006 struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
1007 int i;
1008
1009 fprintf (stream: f,
1010 format: "%*s%s %s\n%*s freq:%4.2f",
1011 indent, "", callee->dump_name (),
1012 !edge->inline_failed
1013 ? "inlined" : cgraph_inline_failed_string (edge-> inline_failed),
1014 indent, "", edge->sreal_frequency ().to_double ());
1015
1016 if (cross_module_call_p (edge))
1017 fprintf (stream: f, format: " cross module");
1018
1019 if (es)
1020 fprintf (stream: f, format: " loop depth:%2i size:%2i time: %2i",
1021 es->loop_depth, es->call_stmt_size, es->call_stmt_time);
1022
1023 ipa_fn_summary *s = ipa_fn_summaries->get (node: callee);
1024 ipa_size_summary *ss = ipa_size_summaries->get (node: callee);
1025 if (s != NULL)
1026 fprintf (stream: f, format: " callee size:%2i stack:%2i",
1027 (int) (ss->size / ipa_fn_summary::size_scale),
1028 (int) s->estimated_stack_size);
1029
1030 if (es && es->predicate)
1031 {
1032 fprintf (stream: f, format: " predicate: ");
1033 es->predicate->dump (f, info->conds);
1034 }
1035 else
1036 fprintf (stream: f, format: "\n");
1037 if (es && es->param.exists ())
1038 for (i = 0; i < (int) es->param.length (); i++)
1039 {
1040 int prob = es->param[i].change_prob;
1041
1042 if (!prob)
1043 fprintf (stream: f, format: "%*s op%i is compile time invariant\n",
1044 indent + 2, "", i);
1045 else if (prob != REG_BR_PROB_BASE)
1046 fprintf (stream: f, format: "%*s op%i change %f%% of time\n", indent + 2, "", i,
1047 prob * 100.0 / REG_BR_PROB_BASE);
1048 if (es->param[i].points_to_local_or_readonly_memory)
1049 fprintf (stream: f, format: "%*s op%i points to local or readonly memory\n",
1050 indent + 2, "", i);
1051 if (es->param[i].points_to_possible_sra_candidate)
1052 fprintf (stream: f, format: "%*s op%i points to possible sra candidate\n",
1053 indent + 2, "", i);
1054 }
1055 if (!edge->inline_failed)
1056 {
1057 ipa_size_summary *ss = ipa_size_summaries->get (node: callee);
1058 fprintf (stream: f, format: "%*sStack frame offset %i, callee self size %i\n",
1059 indent + 2, "",
1060 (int) ipa_get_stack_frame_offset (node: callee),
1061 (int) ss->estimated_self_stack_size);
1062 dump_ipa_call_summary (f, indent: indent + 2, node: callee, info);
1063 }
1064 }
1065 for (edge = node->indirect_calls; edge; edge = edge->next_callee)
1066 {
1067 class ipa_call_summary *es = ipa_call_summaries->get (edge);
1068 fprintf (stream: f, format: "%*sindirect call loop depth:%2i freq:%4.2f size:%2i"
1069 " time: %2i",
1070 indent, "",
1071 es->loop_depth,
1072 edge->sreal_frequency ().to_double (), es->call_stmt_size,
1073 es->call_stmt_time);
1074 if (es->predicate)
1075 {
1076 fprintf (stream: f, format: "predicate: ");
1077 es->predicate->dump (f, info->conds);
1078 }
1079 else
1080 fprintf (stream: f, format: "\n");
1081 }
1082}
1083
1084
1085void
1086ipa_dump_fn_summary (FILE *f, struct cgraph_node *node)
1087{
1088 if (node->definition)
1089 {
1090 class ipa_fn_summary *s = ipa_fn_summaries->get (node);
1091 class ipa_size_summary *ss = ipa_size_summaries->get (node);
1092 if (s != NULL)
1093 {
1094 size_time_entry *e;
1095 int i;
1096 fprintf (stream: f, format: "IPA function summary for %s", node->dump_name ());
1097 if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
1098 fprintf (stream: f, format: " always_inline");
1099 if (s->inlinable)
1100 fprintf (stream: f, format: " inlinable");
1101 if (s->fp_expressions)
1102 fprintf (stream: f, format: " fp_expression");
1103 if (s->builtin_constant_p_parms.length ())
1104 {
1105 fprintf (stream: f, format: " builtin_constant_p_parms");
1106 for (unsigned int i = 0;
1107 i < s->builtin_constant_p_parms.length (); i++)
1108 fprintf (stream: f, format: " %i", s->builtin_constant_p_parms[i]);
1109 }
1110 fprintf (stream: f, format: "\n global time: %f\n", s->time.to_double ());
1111 fprintf (stream: f, format: " self size: %i\n", ss->self_size);
1112 fprintf (stream: f, format: " global size: %i\n", ss->size);
1113 fprintf (stream: f, format: " min size: %i\n", s->min_size);
1114 fprintf (stream: f, format: " self stack: %i\n",
1115 (int) ss->estimated_self_stack_size);
1116 fprintf (stream: f, format: " global stack: %i\n", (int) s->estimated_stack_size);
1117 if (s->growth)
1118 fprintf (stream: f, format: " estimated growth:%i\n", (int) s->growth);
1119 if (s->scc_no)
1120 fprintf (stream: f, format: " In SCC: %i\n", (int) s->scc_no);
1121 for (i = 0; s->size_time_table.iterate (ix: i, ptr: &e); i++)
1122 {
1123 fprintf (stream: f, format: " size:%f, time:%f",
1124 (double) e->size / ipa_fn_summary::size_scale,
1125 e->time.to_double ());
1126 if (e->exec_predicate != true)
1127 {
1128 fprintf (stream: f, format: ", executed if:");
1129 e->exec_predicate.dump (f, s->conds, nl: 0);
1130 }
1131 if (e->exec_predicate != e->nonconst_predicate)
1132 {
1133 fprintf (stream: f, format: ", nonconst if:");
1134 e->nonconst_predicate.dump (f, s->conds, nl: 0);
1135 }
1136 fprintf (stream: f, format: "\n");
1137 }
1138 ipa_freqcounting_predicate *fcp;
1139 bool first_fcp = true;
1140 for (int i = 0; vec_safe_iterate (v: s->loop_iterations, ix: i, ptr: &fcp); i++)
1141 {
1142 if (first_fcp)
1143 {
1144 fprintf (stream: f, format: " loop iterations:");
1145 first_fcp = false;
1146 }
1147 fprintf (stream: f, format: " %3.2f for ", fcp->freq.to_double ());
1148 fcp->predicate->dump (f, s->conds);
1149 }
1150 first_fcp = true;
1151 for (int i = 0; vec_safe_iterate (v: s->loop_strides, ix: i, ptr: &fcp); i++)
1152 {
1153 if (first_fcp)
1154 {
1155 fprintf (stream: f, format: " loop strides:");
1156 first_fcp = false;
1157 }
1158 fprintf (stream: f, format: " %3.2f for :", fcp->freq.to_double ());
1159 fcp->predicate->dump (f, s->conds);
1160 }
1161 fprintf (stream: f, format: " calls:\n");
1162 dump_ipa_call_summary (f, indent: 4, node, info: s);
1163 fprintf (stream: f, format: "\n");
1164 if (s->target_info)
1165 fprintf (stream: f, format: " target_info: %x\n", s->target_info);
1166 }
1167 else
1168 fprintf (stream: f, format: "IPA summary for %s is missing.\n", node->dump_name ());
1169 }
1170}
1171
1172DEBUG_FUNCTION void
1173ipa_debug_fn_summary (struct cgraph_node *node)
1174{
1175 ipa_dump_fn_summary (stderr, node);
1176}
1177
1178void
1179ipa_dump_fn_summaries (FILE *f)
1180{
1181 struct cgraph_node *node;
1182
1183 FOR_EACH_DEFINED_FUNCTION (node)
1184 if (!node->inlined_to)
1185 ipa_dump_fn_summary (f, node);
1186}
1187
1188/* Callback of walk_aliased_vdefs. Flags that it has been invoked to the
1189 boolean variable pointed to by DATA. */
1190
1191static bool
1192mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
1193 void *data)
1194{
1195 bool *b = (bool *) data;
1196 *b = true;
1197 return true;
1198}
1199
1200/* If OP refers to value of function parameter, return the corresponding
1201 parameter. If non-NULL, the size of the memory load (or the SSA_NAME of the
1202 PARM_DECL) will be stored to *SIZE_P in that case too. */
1203
1204static tree
1205unmodified_parm_1 (ipa_func_body_info *fbi, gimple *stmt, tree op,
1206 poly_int64 *size_p)
1207{
1208 /* SSA_NAME referring to parm default def? */
1209 if (TREE_CODE (op) == SSA_NAME
1210 && SSA_NAME_IS_DEFAULT_DEF (op)
1211 && TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
1212 {
1213 if (size_p)
1214 *size_p = tree_to_poly_int64 (TYPE_SIZE (TREE_TYPE (op)));
1215 return SSA_NAME_VAR (op);
1216 }
1217 /* Non-SSA parm reference? */
1218 if (TREE_CODE (op) == PARM_DECL
1219 && fbi->aa_walk_budget > 0)
1220 {
1221 bool modified = false;
1222
1223 ao_ref refd;
1224 ao_ref_init (&refd, op);
1225 int walked = walk_aliased_vdefs (&refd, gimple_vuse (g: stmt),
1226 mark_modified, &modified, NULL, NULL,
1227 limit: fbi->aa_walk_budget);
1228 if (walked < 0)
1229 {
1230 fbi->aa_walk_budget = 0;
1231 return NULL_TREE;
1232 }
1233 fbi->aa_walk_budget -= walked;
1234 if (!modified)
1235 {
1236 if (size_p)
1237 *size_p = tree_to_poly_int64 (TYPE_SIZE (TREE_TYPE (op)));
1238 return op;
1239 }
1240 }
1241 return NULL_TREE;
1242}
1243
1244/* If OP refers to value of function parameter, return the corresponding
1245 parameter. Also traverse chains of SSA register assignments. If non-NULL,
1246 the size of the memory load (or the SSA_NAME of the PARM_DECL) will be
1247 stored to *SIZE_P in that case too. */
1248
1249static tree
1250unmodified_parm (ipa_func_body_info *fbi, gimple *stmt, tree op,
1251 poly_int64 *size_p)
1252{
1253 tree res = unmodified_parm_1 (fbi, stmt, op, size_p);
1254 if (res)
1255 return res;
1256
1257 if (TREE_CODE (op) == SSA_NAME
1258 && !SSA_NAME_IS_DEFAULT_DEF (op)
1259 && gimple_assign_single_p (SSA_NAME_DEF_STMT (op)))
1260 return unmodified_parm (fbi, SSA_NAME_DEF_STMT (op),
1261 op: gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op)),
1262 size_p);
1263 return NULL_TREE;
1264}
1265
1266/* If OP refers to a value of a function parameter or value loaded from an
1267 aggregate passed to a parameter (either by value or reference), return TRUE
1268 and store the number of the parameter to *INDEX_P, the access size into
1269 *SIZE_P, and information whether and how it has been loaded from an
1270 aggregate into *AGGPOS. INFO describes the function parameters, STMT is the
1271 statement in which OP is used or loaded. */
1272
1273static bool
1274unmodified_parm_or_parm_agg_item (struct ipa_func_body_info *fbi,
1275 gimple *stmt, tree op, int *index_p,
1276 poly_int64 *size_p,
1277 struct agg_position_info *aggpos)
1278{
1279 tree res = unmodified_parm_1 (fbi, stmt, op, size_p);
1280
1281 gcc_checking_assert (aggpos);
1282 if (res)
1283 {
1284 *index_p = ipa_get_param_decl_index (fbi->info, res);
1285 if (*index_p < 0)
1286 return false;
1287 aggpos->agg_contents = false;
1288 aggpos->by_ref = false;
1289 return true;
1290 }
1291
1292 if (TREE_CODE (op) == SSA_NAME)
1293 {
1294 if (SSA_NAME_IS_DEFAULT_DEF (op)
1295 || !gimple_assign_single_p (SSA_NAME_DEF_STMT (op)))
1296 return false;
1297 stmt = SSA_NAME_DEF_STMT (op);
1298 op = gimple_assign_rhs1 (gs: stmt);
1299 if (!REFERENCE_CLASS_P (op))
1300 return unmodified_parm_or_parm_agg_item (fbi, stmt, op, index_p, size_p,
1301 aggpos);
1302 }
1303
1304 aggpos->agg_contents = true;
1305 return ipa_load_from_parm_agg (fbi, descriptors: fbi->info->descriptors,
1306 stmt, op, index_p, offset_p: &aggpos->offset,
1307 size_p, by_ref: &aggpos->by_ref);
1308}
1309
1310/* If stmt is simple load or store of value pointed to by a function parmaeter,
1311 return its index. */
1312
1313static int
1314load_or_store_of_ptr_parameter (ipa_func_body_info *fbi, gimple *stmt)
1315{
1316 if (!optimize)
1317 return -1;
1318 gassign *assign = dyn_cast <gassign *> (p: stmt);
1319 if (!assign)
1320 return -1;
1321 tree param;
1322 if (gimple_assign_load_p (stmt))
1323 param = gimple_assign_rhs1 (gs: stmt);
1324 else if (gimple_store_p (gs: stmt))
1325 param = gimple_assign_lhs (gs: stmt);
1326 else
1327 return -1;
1328 tree base = get_base_address (t: param);
1329 if (TREE_CODE (base) != MEM_REF
1330 || TREE_CODE (TREE_OPERAND (base, 0)) != SSA_NAME
1331 || !SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (base, 0)))
1332 return -1;
1333 tree p = SSA_NAME_VAR (TREE_OPERAND (base, 0));
1334 if (TREE_CODE (p) != PARM_DECL)
1335 return -1;
1336 return ipa_get_param_decl_index (fbi->info, p);
1337}
1338
1339/* See if statement might disappear after inlining.
1340 0 - means not eliminated
1341 1 - half of statements goes away
1342 2 - for sure it is eliminated.
1343 We are not terribly sophisticated, basically looking for simple abstraction
1344 penalty wrappers. */
1345
1346static int
1347eliminated_by_inlining_prob (ipa_func_body_info *fbi, gimple *stmt)
1348{
1349 enum gimple_code code = gimple_code (g: stmt);
1350 enum tree_code rhs_code;
1351
1352 if (!optimize)
1353 return 0;
1354
1355 switch (code)
1356 {
1357 case GIMPLE_RETURN:
1358 return 2;
1359 case GIMPLE_ASSIGN:
1360 if (gimple_num_ops (gs: stmt) != 2)
1361 return 0;
1362
1363 rhs_code = gimple_assign_rhs_code (gs: stmt);
1364
1365 /* Casts of parameters, loads from parameters passed by reference
1366 and stores to return value or parameters are often free after
1367 inlining due to SRA and further combining.
1368 Assume that half of statements goes away. */
1369 if (CONVERT_EXPR_CODE_P (rhs_code)
1370 || rhs_code == VIEW_CONVERT_EXPR
1371 || rhs_code == ADDR_EXPR
1372 || gimple_assign_rhs_class (gs: stmt) == GIMPLE_SINGLE_RHS)
1373 {
1374 tree rhs = gimple_assign_rhs1 (gs: stmt);
1375 tree lhs = gimple_assign_lhs (gs: stmt);
1376 tree inner_rhs = get_base_address (t: rhs);
1377 tree inner_lhs = get_base_address (t: lhs);
1378 bool rhs_free = false;
1379 bool lhs_free = false;
1380
1381 if (!inner_rhs)
1382 inner_rhs = rhs;
1383 if (!inner_lhs)
1384 inner_lhs = lhs;
1385
1386 /* Reads of parameter are expected to be free. */
1387 if (unmodified_parm (fbi, stmt, op: inner_rhs, NULL))
1388 rhs_free = true;
1389 /* Match expressions of form &this->field. Those will most likely
1390 combine with something upstream after inlining. */
1391 else if (TREE_CODE (inner_rhs) == ADDR_EXPR)
1392 {
1393 tree op = get_base_address (TREE_OPERAND (inner_rhs, 0));
1394 if (TREE_CODE (op) == PARM_DECL)
1395 rhs_free = true;
1396 else if (TREE_CODE (op) == MEM_REF
1397 && unmodified_parm (fbi, stmt, TREE_OPERAND (op, 0),
1398 NULL))
1399 rhs_free = true;
1400 }
1401
1402 /* When parameter is not SSA register because its address is taken
1403 and it is just copied into one, the statement will be completely
1404 free after inlining (we will copy propagate backward). */
1405 if (rhs_free && is_gimple_reg (lhs))
1406 return 2;
1407
1408 /* Reads of parameters passed by reference
1409 expected to be free (i.e. optimized out after inlining). */
1410 if (TREE_CODE (inner_rhs) == MEM_REF
1411 && unmodified_parm (fbi, stmt, TREE_OPERAND (inner_rhs, 0), NULL))
1412 rhs_free = true;
1413
1414 /* Copying parameter passed by reference into gimple register is
1415 probably also going to copy propagate, but we can't be quite
1416 sure. */
1417 if (rhs_free && is_gimple_reg (lhs))
1418 lhs_free = true;
1419
1420 /* Writes to parameters, parameters passed by value and return value
1421 (either directly or passed via invisible reference) are free.
1422
1423 TODO: We ought to handle testcase like
1424 struct a {int a,b;};
1425 struct a
1426 returnstruct (void)
1427 {
1428 struct a a ={1,2};
1429 return a;
1430 }
1431
1432 This translate into:
1433
1434 returnstruct ()
1435 {
1436 int a$b;
1437 int a$a;
1438 struct a a;
1439 struct a D.2739;
1440
1441 <bb 2>:
1442 D.2739.a = 1;
1443 D.2739.b = 2;
1444 return D.2739;
1445
1446 }
1447 For that we either need to copy ipa-split logic detecting writes
1448 to return value. */
1449 if (TREE_CODE (inner_lhs) == PARM_DECL
1450 || TREE_CODE (inner_lhs) == RESULT_DECL
1451 || (TREE_CODE (inner_lhs) == MEM_REF
1452 && (unmodified_parm (fbi, stmt, TREE_OPERAND (inner_lhs, 0),
1453 NULL)
1454 || (TREE_CODE (TREE_OPERAND (inner_lhs, 0)) == SSA_NAME
1455 && SSA_NAME_VAR (TREE_OPERAND (inner_lhs, 0))
1456 && TREE_CODE (SSA_NAME_VAR (TREE_OPERAND
1457 (inner_lhs,
1458 0))) == RESULT_DECL))))
1459 lhs_free = true;
1460 if (lhs_free
1461 && (is_gimple_reg (rhs) || is_gimple_min_invariant (rhs)))
1462 rhs_free = true;
1463 if (lhs_free && rhs_free)
1464 return 1;
1465 }
1466 return 0;
1467 default:
1468 return 0;
1469 }
1470}
1471
1472/* Analyze EXPR if it represents a series of simple operations performed on
1473 a function parameter and return true if so. FBI, STMT, EXPR, INDEX_P and
1474 AGGPOS have the same meaning like in unmodified_parm_or_parm_agg_item.
1475 Type of the parameter or load from an aggregate via the parameter is
1476 stored in *TYPE_P. Operations on the parameter are recorded to
1477 PARAM_OPS_P if it is not NULL. */
1478
1479static bool
1480decompose_param_expr (struct ipa_func_body_info *fbi,
1481 gimple *stmt, tree expr,
1482 int *index_p, tree *type_p,
1483 struct agg_position_info *aggpos,
1484 expr_eval_ops *param_ops_p = NULL)
1485{
1486 int op_limit = opt_for_fn (fbi->node->decl, param_ipa_max_param_expr_ops);
1487 int op_count = 0;
1488
1489 if (param_ops_p)
1490 *param_ops_p = NULL;
1491
1492 while (true)
1493 {
1494 expr_eval_op eval_op;
1495 unsigned rhs_count;
1496 unsigned cst_count = 0;
1497
1498 if (unmodified_parm_or_parm_agg_item (fbi, stmt, op: expr, index_p, NULL,
1499 aggpos))
1500 {
1501 tree type = TREE_TYPE (expr);
1502
1503 if (aggpos->agg_contents)
1504 {
1505 /* Stop if containing bit-field. */
1506 if (TREE_CODE (expr) == BIT_FIELD_REF
1507 || contains_bitfld_component_ref_p (expr))
1508 break;
1509 }
1510
1511 *type_p = type;
1512 return true;
1513 }
1514
1515 if (TREE_CODE (expr) != SSA_NAME || SSA_NAME_IS_DEFAULT_DEF (expr))
1516 break;
1517 stmt = SSA_NAME_DEF_STMT (expr);
1518
1519 if (gcall *call = dyn_cast <gcall *> (p: stmt))
1520 {
1521 int flags = gimple_call_return_flags (call);
1522 if (!(flags & ERF_RETURNS_ARG))
1523 goto fail;
1524 int arg = flags & ERF_RETURN_ARG_MASK;
1525 if (arg >= (int)gimple_call_num_args (gs: call))
1526 goto fail;
1527 expr = gimple_call_arg (gs: stmt, index: arg);
1528 continue;
1529 }
1530
1531 if (!is_gimple_assign (gs: stmt = SSA_NAME_DEF_STMT (expr)))
1532 break;
1533
1534 switch (gimple_assign_rhs_class (gs: stmt))
1535 {
1536 case GIMPLE_SINGLE_RHS:
1537 expr = gimple_assign_rhs1 (gs: stmt);
1538 continue;
1539
1540 case GIMPLE_UNARY_RHS:
1541 rhs_count = 1;
1542 break;
1543
1544 case GIMPLE_BINARY_RHS:
1545 rhs_count = 2;
1546 break;
1547
1548 case GIMPLE_TERNARY_RHS:
1549 rhs_count = 3;
1550 break;
1551
1552 default:
1553 goto fail;
1554 }
1555
1556 /* Stop if expression is too complex. */
1557 if (op_count++ == op_limit)
1558 break;
1559
1560 if (param_ops_p)
1561 {
1562 eval_op.code = gimple_assign_rhs_code (gs: stmt);
1563 eval_op.type = TREE_TYPE (gimple_assign_lhs (stmt));
1564 eval_op.val[0] = NULL_TREE;
1565 eval_op.val[1] = NULL_TREE;
1566 }
1567
1568 expr = NULL_TREE;
1569 for (unsigned i = 0; i < rhs_count; i++)
1570 {
1571 tree op = gimple_op (gs: stmt, i: i + 1);
1572
1573 gcc_assert (op && !TYPE_P (op));
1574 if (is_gimple_ip_invariant (op))
1575 {
1576 if (++cst_count == rhs_count)
1577 goto fail;
1578
1579 eval_op.val[cst_count - 1] = op;
1580 }
1581 else if (!expr)
1582 {
1583 /* Found a non-constant operand, and record its index in rhs
1584 operands. */
1585 eval_op.index = i;
1586 expr = op;
1587 }
1588 else
1589 {
1590 /* Found more than one non-constant operands. */
1591 goto fail;
1592 }
1593 }
1594
1595 if (param_ops_p)
1596 vec_safe_insert (v&: *param_ops_p, ix: 0, obj: eval_op);
1597 }
1598
1599 /* Failed to decompose, free resource and return. */
1600fail:
1601 if (param_ops_p)
1602 vec_free (v&: *param_ops_p);
1603
1604 return false;
1605}
1606
1607/* Record to SUMMARY that PARM is used by builtin_constant_p. */
1608
1609static void
1610add_builtin_constant_p_parm (class ipa_fn_summary *summary, int parm)
1611{
1612 int ip;
1613
1614 /* Avoid duplicates. */
1615 for (unsigned int i = 0;
1616 summary->builtin_constant_p_parms.iterate (ix: i, ptr: &ip); i++)
1617 if (ip == parm)
1618 return;
1619 summary->builtin_constant_p_parms.safe_push (obj: parm);
1620}
1621
1622/* If BB ends by a conditional we can turn into predicates, attach corresponding
1623 predicates to the CFG edges. */
1624
1625static void
1626set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
1627 class ipa_fn_summary *summary,
1628 class ipa_node_params *params_summary,
1629 basic_block bb)
1630{
1631 tree op, op2;
1632 int index;
1633 struct agg_position_info aggpos;
1634 enum tree_code code, inverted_code;
1635 edge e;
1636 edge_iterator ei;
1637 gimple *set_stmt;
1638 tree param_type;
1639 expr_eval_ops param_ops;
1640
1641 gcond *last = safe_dyn_cast <gcond *> (p: *gsi_last_bb (bb));
1642 if (!last)
1643 return;
1644 if (!is_gimple_ip_invariant (gimple_cond_rhs (gs: last)))
1645 return;
1646 op = gimple_cond_lhs (gs: last);
1647
1648 if (decompose_param_expr (fbi, stmt: last, expr: op, index_p: &index, type_p: &param_type, aggpos: &aggpos,
1649 param_ops_p: &param_ops))
1650 {
1651 code = gimple_cond_code (gs: last);
1652 inverted_code = invert_tree_comparison (code, HONOR_NANS (op));
1653
1654 FOR_EACH_EDGE (e, ei, bb->succs)
1655 {
1656 enum tree_code this_code = (e->flags & EDGE_TRUE_VALUE
1657 ? code : inverted_code);
1658 /* invert_tree_comparison will return ERROR_MARK on FP
1659 comparisons that are not EQ/NE instead of returning proper
1660 unordered one. Be sure it is not confused with NON_CONSTANT.
1661
1662 And if the edge's target is the final block of diamond CFG graph
1663 of this conditional statement, we do not need to compute
1664 predicate for the edge because the final block's predicate must
1665 be at least as that of the first block of the statement. */
1666 if (this_code != ERROR_MARK
1667 && !dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest))
1668 {
1669 ipa_predicate p
1670 = add_condition (summary, params_summary, operand_num: index,
1671 type: param_type, aggpos: &aggpos,
1672 code: this_code, val: gimple_cond_rhs (gs: last), param_ops);
1673 e->aux = edge_predicate_pool.allocate ();
1674 *(ipa_predicate *) e->aux = p;
1675 }
1676 }
1677 vec_free (v&: param_ops);
1678 return;
1679 }
1680
1681 if (TREE_CODE (op) != SSA_NAME)
1682 return;
1683 /* Special case
1684 if (builtin_constant_p (op))
1685 constant_code
1686 else
1687 nonconstant_code.
1688 Here we can predicate nonconstant_code. We can't
1689 really handle constant_code since we have no predicate
1690 for this and also the constant code is not known to be
1691 optimized away when inliner doesn't see operand is constant.
1692 Other optimizers might think otherwise. */
1693 if (gimple_cond_code (gs: last) != NE_EXPR
1694 || !integer_zerop (gimple_cond_rhs (gs: last)))
1695 return;
1696 set_stmt = SSA_NAME_DEF_STMT (op);
1697 if (!gimple_call_builtin_p (set_stmt, BUILT_IN_CONSTANT_P)
1698 || gimple_call_num_args (gs: set_stmt) != 1)
1699 return;
1700 op2 = gimple_call_arg (gs: set_stmt, index: 0);
1701 if (!decompose_param_expr (fbi, stmt: set_stmt, expr: op2, index_p: &index, type_p: &param_type, aggpos: &aggpos))
1702 return;
1703 if (!aggpos.by_ref)
1704 add_builtin_constant_p_parm (summary, parm: index);
1705 FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE)
1706 {
1707 ipa_predicate p = add_condition (summary, params_summary, operand_num: index,
1708 type: param_type, aggpos: &aggpos,
1709 code: ipa_predicate::is_not_constant, NULL_TREE);
1710 e->aux = edge_predicate_pool.allocate ();
1711 *(ipa_predicate *) e->aux = p;
1712 }
1713}
1714
1715
1716/* If BB ends by a switch we can turn into predicates, attach corresponding
1717 predicates to the CFG edges. */
1718
1719static void
1720set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
1721 class ipa_fn_summary *summary,
1722 class ipa_node_params *params_summary,
1723 basic_block bb)
1724{
1725 tree op;
1726 int index;
1727 struct agg_position_info aggpos;
1728 edge e;
1729 edge_iterator ei;
1730 size_t n;
1731 size_t case_idx;
1732 tree param_type;
1733 expr_eval_ops param_ops;
1734
1735 gswitch *last = safe_dyn_cast <gswitch *> (p: *gsi_last_bb (bb));
1736 if (!last)
1737 return;
1738 op = gimple_switch_index (gs: last);
1739 if (!decompose_param_expr (fbi, stmt: last, expr: op, index_p: &index, type_p: &param_type, aggpos: &aggpos,
1740 param_ops_p: &param_ops))
1741 return;
1742
1743 auto_vec<std::pair<tree, tree> > ranges;
1744 tree type = TREE_TYPE (op);
1745 int bound_limit = opt_for_fn (fbi->node->decl,
1746 param_ipa_max_switch_predicate_bounds);
1747 int bound_count = 0;
1748 // This can safely be an integer range, as switches can only hold
1749 // integers.
1750 int_range<2> vr;
1751
1752 get_range_query (cfun)->range_of_expr (r&: vr, expr: op);
1753 if (vr.undefined_p ())
1754 vr.set_varying (TREE_TYPE (op));
1755 tree vr_min, vr_max;
1756 // TODO: This entire function could use a rewrite to use the irange
1757 // API, instead of trying to recreate its intersection/union logic.
1758 // Any use of get_legacy_range() is a serious code smell.
1759 value_range_kind vr_type = get_legacy_range (vr, min&: vr_min, max&: vr_max);
1760 wide_int vr_wmin = wi::to_wide (t: vr_min);
1761 wide_int vr_wmax = wi::to_wide (t: vr_max);
1762
1763 FOR_EACH_EDGE (e, ei, bb->succs)
1764 {
1765 e->aux = edge_predicate_pool.allocate ();
1766 *(ipa_predicate *) e->aux = false;
1767 }
1768
1769 e = gimple_switch_edge (cfun, last, 0);
1770 /* Set BOUND_COUNT to maximum count to bypass computing predicate for
1771 default case if its target basic block is in convergence point of all
1772 switch cases, which can be determined by checking whether it
1773 post-dominates the switch statement. */
1774 if (dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest))
1775 bound_count = INT_MAX;
1776
1777 n = gimple_switch_num_labels (gs: last);
1778 for (case_idx = 1; case_idx < n; ++case_idx)
1779 {
1780 tree cl = gimple_switch_label (gs: last, index: case_idx);
1781 tree min = CASE_LOW (cl);
1782 tree max = CASE_HIGH (cl);
1783 ipa_predicate p;
1784
1785 e = gimple_switch_edge (cfun, last, case_idx);
1786
1787 /* The case value might not have same type as switch expression,
1788 extend the value based on the expression type. */
1789 if (TREE_TYPE (min) != type)
1790 min = wide_int_to_tree (type, cst: wi::to_wide (t: min));
1791
1792 if (!max)
1793 max = min;
1794 else if (TREE_TYPE (max) != type)
1795 max = wide_int_to_tree (type, cst: wi::to_wide (t: max));
1796
1797 /* The case's target basic block is in convergence point of all switch
1798 cases, its predicate should be at least as that of the switch
1799 statement. */
1800 if (dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest))
1801 p = true;
1802 else if (min == max)
1803 p = add_condition (summary, params_summary, operand_num: index, type: param_type,
1804 aggpos: &aggpos, code: EQ_EXPR, val: min, param_ops);
1805 else
1806 {
1807 ipa_predicate p1, p2;
1808 p1 = add_condition (summary, params_summary, operand_num: index, type: param_type,
1809 aggpos: &aggpos, code: GE_EXPR, val: min, param_ops);
1810 p2 = add_condition (summary, params_summary,operand_num: index, type: param_type,
1811 aggpos: &aggpos, code: LE_EXPR, val: max, param_ops);
1812 p = p1 & p2;
1813 }
1814 *(ipa_predicate *) e->aux
1815 = p.or_with (summary->conds, *(ipa_predicate *) e->aux);
1816
1817 /* If there are too many disjoint case ranges, predicate for default
1818 case might become too complicated. So add a limit here. */
1819 if (bound_count > bound_limit)
1820 continue;
1821
1822 bool new_range = true;
1823
1824 if (!ranges.is_empty ())
1825 {
1826 wide_int curr_wmin = wi::to_wide (t: min);
1827 wide_int last_wmax = wi::to_wide (t: ranges.last ().second);
1828
1829 /* Merge case ranges if they are continuous. */
1830 if (curr_wmin == last_wmax + 1)
1831 new_range = false;
1832 else if (vr_type == VR_ANTI_RANGE)
1833 {
1834 /* If two disjoint case ranges can be connected by anti-range
1835 of switch index, combine them to one range. */
1836 if (wi::lt_p (x: vr_wmax, y: curr_wmin - 1, TYPE_SIGN (type)))
1837 vr_type = VR_UNDEFINED;
1838 else if (wi::le_p (x: vr_wmin, y: last_wmax + 1, TYPE_SIGN (type)))
1839 new_range = false;
1840 }
1841 }
1842
1843 /* Create/extend a case range. And we count endpoints of range set,
1844 this number nearly equals to number of conditions that we will create
1845 for predicate of default case. */
1846 if (new_range)
1847 {
1848 bound_count += (min == max) ? 1 : 2;
1849 ranges.safe_push (obj: std::make_pair (x&: min, y&: max));
1850 }
1851 else
1852 {
1853 bound_count += (ranges.last ().first == ranges.last ().second);
1854 ranges.last ().second = max;
1855 }
1856 }
1857
1858 e = gimple_switch_edge (cfun, last, 0);
1859 if (bound_count > bound_limit)
1860 {
1861 *(ipa_predicate *) e->aux = true;
1862 vec_free (v&: param_ops);
1863 return;
1864 }
1865
1866 ipa_predicate p_seg = true;
1867 ipa_predicate p_all = false;
1868
1869 if (vr_type != VR_RANGE)
1870 {
1871 vr_wmin = wi::to_wide (TYPE_MIN_VALUE (type));
1872 vr_wmax = wi::to_wide (TYPE_MAX_VALUE (type));
1873 }
1874
1875 /* Construct predicate to represent default range set that is negation of
1876 all case ranges. Case range is classified as containing single/non-single
1877 values. Suppose a piece of case ranges in the following.
1878
1879 [D1...D2] [S1] ... [Sn] [D3...D4]
1880
1881 To represent default case's range sets between two non-single value
1882 case ranges (From D2 to D3), we construct predicate as:
1883
1884 D2 < x < D3 && x != S1 && ... && x != Sn
1885 */
1886 for (size_t i = 0; i < ranges.length (); i++)
1887 {
1888 tree min = ranges[i].first;
1889 tree max = ranges[i].second;
1890
1891 if (min == max)
1892 p_seg &= add_condition (summary, params_summary, operand_num: index,
1893 type: param_type, aggpos: &aggpos, code: NE_EXPR,
1894 val: min, param_ops);
1895 else
1896 {
1897 /* Do not create sub-predicate for range that is beyond low bound
1898 of switch index. */
1899 if (wi::lt_p (x: vr_wmin, y: wi::to_wide (t: min), TYPE_SIGN (type)))
1900 {
1901 p_seg &= add_condition (summary, params_summary, operand_num: index,
1902 type: param_type, aggpos: &aggpos,
1903 code: LT_EXPR, val: min, param_ops);
1904 p_all = p_all.or_with (summary->conds, p_seg);
1905 }
1906
1907 /* Do not create sub-predicate for range that is beyond up bound
1908 of switch index. */
1909 if (wi::le_p (x: vr_wmax, y: wi::to_wide (t: max), TYPE_SIGN (type)))
1910 {
1911 p_seg = false;
1912 break;
1913 }
1914
1915 p_seg = add_condition (summary, params_summary, operand_num: index,
1916 type: param_type, aggpos: &aggpos, code: GT_EXPR,
1917 val: max, param_ops);
1918 }
1919 }
1920
1921 p_all = p_all.or_with (summary->conds, p_seg);
1922 *(ipa_predicate *) e->aux
1923 = p_all.or_with (summary->conds, *(ipa_predicate *) e->aux);
1924
1925 vec_free (v&: param_ops);
1926}
1927
1928
1929/* For each BB in NODE attach to its AUX pointer predicate under
1930 which it is executable. */
1931
1932static void
1933compute_bb_predicates (struct ipa_func_body_info *fbi,
1934 struct cgraph_node *node,
1935 class ipa_fn_summary *summary,
1936 class ipa_node_params *params_summary)
1937{
1938 struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
1939 bool done = false;
1940 basic_block bb;
1941
1942 FOR_EACH_BB_FN (bb, my_function)
1943 {
1944 set_cond_stmt_execution_predicate (fbi, summary, params_summary, bb);
1945 set_switch_stmt_execution_predicate (fbi, summary, params_summary, bb);
1946 }
1947
1948 /* Entry block is always executable. */
1949 ENTRY_BLOCK_PTR_FOR_FN (my_function)->aux
1950 = edge_predicate_pool.allocate ();
1951 *(ipa_predicate *) ENTRY_BLOCK_PTR_FOR_FN (my_function)->aux = true;
1952
1953 /* A simple dataflow propagation of predicates forward in the CFG.
1954 TODO: work in reverse postorder. */
1955 while (!done)
1956 {
1957 done = true;
1958 FOR_EACH_BB_FN (bb, my_function)
1959 {
1960 ipa_predicate p = false;
1961 edge e;
1962 edge_iterator ei;
1963 FOR_EACH_EDGE (e, ei, bb->preds)
1964 {
1965 if (e->src->aux)
1966 {
1967 ipa_predicate this_bb_predicate
1968 = *(ipa_predicate *) e->src->aux;
1969 if (e->aux)
1970 this_bb_predicate &= (*(ipa_predicate *) e->aux);
1971 p = p.or_with (summary->conds, this_bb_predicate);
1972 if (p == true)
1973 break;
1974 }
1975 }
1976 if (p != false)
1977 {
1978 basic_block pdom_bb;
1979
1980 if (!bb->aux)
1981 {
1982 done = false;
1983 bb->aux = edge_predicate_pool.allocate ();
1984 *((ipa_predicate *) bb->aux) = p;
1985 }
1986 else if (p != *(ipa_predicate *) bb->aux)
1987 {
1988 /* This OR operation is needed to ensure monotonous data flow
1989 in the case we hit the limit on number of clauses and the
1990 and/or operations above give approximate answers. */
1991 p = p.or_with (summary->conds, *(ipa_predicate *)bb->aux);
1992 if (p != *(ipa_predicate *)bb->aux)
1993 {
1994 done = false;
1995 *((ipa_predicate *)bb->aux) = p;
1996 }
1997 }
1998
1999 /* For switch/if statement, we can OR-combine predicates of all
2000 its cases/branches to get predicate for basic block in their
2001 convergence point, but sometimes this will generate very
2002 complicated predicate. Actually, we can get simplified
2003 predicate in another way by using the fact that predicate
2004 for a basic block must also hold true for its post dominators.
2005 To be specific, basic block in convergence point of
2006 conditional statement should include predicate of the
2007 statement. */
2008 pdom_bb = get_immediate_dominator (CDI_POST_DOMINATORS, bb);
2009 if (pdom_bb == EXIT_BLOCK_PTR_FOR_FN (my_function) || !pdom_bb)
2010 ;
2011 else if (!pdom_bb->aux)
2012 {
2013 done = false;
2014 pdom_bb->aux = edge_predicate_pool.allocate ();
2015 *((ipa_predicate *)pdom_bb->aux) = p;
2016 }
2017 else if (p != *(ipa_predicate *)pdom_bb->aux)
2018 {
2019 p = p.or_with (summary->conds,
2020 *(ipa_predicate *)pdom_bb->aux);
2021 if (p != *(ipa_predicate *)pdom_bb->aux)
2022 {
2023 done = false;
2024 *((ipa_predicate *)pdom_bb->aux) = p;
2025 }
2026 }
2027 }
2028 }
2029 }
2030}
2031
2032
2033/* Return predicate specifying when the STMT might have result that is not
2034 a compile time constant. */
2035
2036static ipa_predicate
2037will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
2038 class ipa_fn_summary *summary,
2039 class ipa_node_params *params_summary,
2040 tree expr,
2041 vec<ipa_predicate> nonconstant_names)
2042{
2043 tree parm;
2044 int index;
2045
2046 while (UNARY_CLASS_P (expr))
2047 expr = TREE_OPERAND (expr, 0);
2048
2049 parm = unmodified_parm (fbi, NULL, op: expr, NULL);
2050 if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
2051 return add_condition (summary, params_summary, operand_num: index, TREE_TYPE (parm), NULL,
2052 code: ipa_predicate::changed, NULL_TREE);
2053 if (is_gimple_min_invariant (expr))
2054 return false;
2055 if (TREE_CODE (expr) == SSA_NAME)
2056 return nonconstant_names[SSA_NAME_VERSION (expr)];
2057 if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr))
2058 {
2059 ipa_predicate p1
2060 = will_be_nonconstant_expr_predicate (fbi, summary,
2061 params_summary,
2062 TREE_OPERAND (expr, 0),
2063 nonconstant_names);
2064 if (p1 == true)
2065 return p1;
2066
2067 ipa_predicate p2
2068 = will_be_nonconstant_expr_predicate (fbi, summary,
2069 params_summary,
2070 TREE_OPERAND (expr, 1),
2071 nonconstant_names);
2072 return p1.or_with (summary->conds, p2);
2073 }
2074 else if (TREE_CODE (expr) == COND_EXPR)
2075 {
2076 ipa_predicate p1
2077 = will_be_nonconstant_expr_predicate (fbi, summary,
2078 params_summary,
2079 TREE_OPERAND (expr, 0),
2080 nonconstant_names);
2081 if (p1 == true)
2082 return p1;
2083
2084 ipa_predicate p2
2085 = will_be_nonconstant_expr_predicate (fbi, summary,
2086 params_summary,
2087 TREE_OPERAND (expr, 1),
2088 nonconstant_names);
2089 if (p2 == true)
2090 return p2;
2091 p1 = p1.or_with (summary->conds, p2);
2092 p2 = will_be_nonconstant_expr_predicate (fbi, summary,
2093 params_summary,
2094 TREE_OPERAND (expr, 2),
2095 nonconstant_names);
2096 return p2.or_with (summary->conds, p1);
2097 }
2098 else if (TREE_CODE (expr) == CALL_EXPR)
2099 return true;
2100 else
2101 {
2102 debug_tree (expr);
2103 gcc_unreachable ();
2104 }
2105}
2106
2107
2108/* Return predicate specifying when the STMT might have result that is not
2109 a compile time constant. */
2110
2111static ipa_predicate
2112will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
2113 class ipa_fn_summary *summary,
2114 class ipa_node_params *params_summary,
2115 gimple *stmt,
2116 vec<ipa_predicate> nonconstant_names)
2117{
2118 ipa_predicate p = true;
2119 ssa_op_iter iter;
2120 tree use;
2121 tree param_type = NULL_TREE;
2122 ipa_predicate op_non_const;
2123 bool is_load;
2124 int base_index;
2125 struct agg_position_info aggpos;
2126
2127 /* What statements might be optimized away
2128 when their arguments are constant. */
2129 if (gimple_code (g: stmt) != GIMPLE_ASSIGN
2130 && gimple_code (g: stmt) != GIMPLE_COND
2131 && gimple_code (g: stmt) != GIMPLE_SWITCH
2132 && (gimple_code (g: stmt) != GIMPLE_CALL
2133 || !(gimple_call_flags (stmt) & ECF_CONST)))
2134 return p;
2135
2136 /* Stores will stay anyway. */
2137 if (gimple_store_p (gs: stmt))
2138 return p;
2139
2140 is_load = gimple_assign_load_p (stmt);
2141
2142 /* Loads can be optimized when the value is known. */
2143 if (is_load)
2144 {
2145 tree op = gimple_assign_rhs1 (gs: stmt);
2146 if (!decompose_param_expr (fbi, stmt, expr: op, index_p: &base_index, type_p: &param_type,
2147 aggpos: &aggpos))
2148 return p;
2149 }
2150 else
2151 base_index = -1;
2152
2153 /* See if we understand all operands before we start
2154 adding conditionals. */
2155 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
2156 {
2157 tree parm = unmodified_parm (fbi, stmt, op: use, NULL);
2158 /* For arguments we can build a condition. */
2159 if (parm && ipa_get_param_decl_index (fbi->info, parm) >= 0)
2160 continue;
2161 if (TREE_CODE (use) != SSA_NAME)
2162 return p;
2163 /* If we know when operand is constant,
2164 we still can say something useful. */
2165 if (nonconstant_names[SSA_NAME_VERSION (use)] != true)
2166 continue;
2167 return p;
2168 }
2169
2170 if (is_load)
2171 op_non_const =
2172 add_condition (summary, params_summary,
2173 operand_num: base_index, type: param_type, aggpos: &aggpos,
2174 code: ipa_predicate::changed, NULL_TREE);
2175 else
2176 op_non_const = false;
2177 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
2178 {
2179 tree parm = unmodified_parm (fbi, stmt, op: use, NULL);
2180 int index;
2181
2182 if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
2183 {
2184 if (index != base_index)
2185 p = add_condition (summary, params_summary, operand_num: index,
2186 TREE_TYPE (parm), NULL,
2187 code: ipa_predicate::changed, NULL_TREE);
2188 else
2189 continue;
2190 }
2191 else
2192 p = nonconstant_names[SSA_NAME_VERSION (use)];
2193 op_non_const = p.or_with (summary->conds, op_non_const);
2194 }
2195 if ((gimple_code (g: stmt) == GIMPLE_ASSIGN || gimple_code (g: stmt) == GIMPLE_CALL)
2196 && gimple_op (gs: stmt, i: 0)
2197 && TREE_CODE (gimple_op (stmt, 0)) == SSA_NAME)
2198 nonconstant_names[SSA_NAME_VERSION (gimple_op (stmt, 0))]
2199 = op_non_const;
2200 return op_non_const;
2201}
2202
2203struct record_modified_bb_info
2204{
2205 tree op;
2206 bitmap bb_set;
2207 gimple *stmt;
2208};
2209
2210/* Value is initialized in INIT_BB and used in USE_BB. We want to compute
2211 probability how often it changes between USE_BB.
2212 INIT_BB->count/USE_BB->count is an estimate, but if INIT_BB
2213 is in different loop nest, we can do better.
2214 This is all just estimate. In theory we look for minimal cut separating
2215 INIT_BB and USE_BB, but we only want to anticipate loop invariant motion
2216 anyway. */
2217
2218static basic_block
2219get_minimal_bb (basic_block init_bb, basic_block use_bb)
2220{
2221 class loop *l = find_common_loop (init_bb->loop_father, use_bb->loop_father);
2222 if (l && l->header->count < init_bb->count)
2223 return l->header;
2224 return init_bb;
2225}
2226
2227/* Callback of walk_aliased_vdefs. Records basic blocks where the value may be
2228 set except for info->stmt. */
2229
2230static bool
2231record_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
2232{
2233 struct record_modified_bb_info *info =
2234 (struct record_modified_bb_info *) data;
2235 if (SSA_NAME_DEF_STMT (vdef) == info->stmt)
2236 return false;
2237 if (gimple_clobber_p (SSA_NAME_DEF_STMT (vdef)))
2238 return false;
2239 bitmap_set_bit (info->bb_set,
2240 SSA_NAME_IS_DEFAULT_DEF (vdef)
2241 ? ENTRY_BLOCK_PTR_FOR_FN (cfun)->index
2242 : get_minimal_bb
2243 (init_bb: gimple_bb (SSA_NAME_DEF_STMT (vdef)),
2244 use_bb: gimple_bb (g: info->stmt))->index);
2245 if (dump_file)
2246 {
2247 fprintf (stream: dump_file, format: " Param ");
2248 print_generic_expr (dump_file, info->op, TDF_SLIM);
2249 fprintf (stream: dump_file, format: " changed at bb %i, minimal: %i stmt: ",
2250 gimple_bb (SSA_NAME_DEF_STMT (vdef))->index,
2251 get_minimal_bb
2252 (init_bb: gimple_bb (SSA_NAME_DEF_STMT (vdef)),
2253 use_bb: gimple_bb (g: info->stmt))->index);
2254 print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (vdef), 0);
2255 }
2256 return false;
2257}
2258
2259/* Return probability (based on REG_BR_PROB_BASE) that I-th parameter of STMT
2260 will change since last invocation of STMT.
2261
2262 Value 0 is reserved for compile time invariants.
2263 For common parameters it is REG_BR_PROB_BASE. For loop invariants it
2264 ought to be REG_BR_PROB_BASE / estimated_iters. */
2265
2266static int
2267param_change_prob (ipa_func_body_info *fbi, gimple *stmt, int i)
2268{
2269 tree op = gimple_call_arg (gs: stmt, index: i);
2270 basic_block bb = gimple_bb (g: stmt);
2271
2272 if (TREE_CODE (op) == WITH_SIZE_EXPR)
2273 op = TREE_OPERAND (op, 0);
2274
2275 tree base = get_base_address (t: op);
2276
2277 /* Global invariants never change. */
2278 if (is_gimple_min_invariant (base))
2279 return 0;
2280
2281 /* We would have to do non-trivial analysis to really work out what
2282 is the probability of value to change (i.e. when init statement
2283 is in a sibling loop of the call).
2284
2285 We do an conservative estimate: when call is executed N times more often
2286 than the statement defining value, we take the frequency 1/N. */
2287 if (TREE_CODE (base) == SSA_NAME)
2288 {
2289 profile_count init_count;
2290
2291 if (!bb->count.nonzero_p ())
2292 return REG_BR_PROB_BASE;
2293
2294 if (SSA_NAME_IS_DEFAULT_DEF (base))
2295 init_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
2296 else
2297 init_count = get_minimal_bb
2298 (init_bb: gimple_bb (SSA_NAME_DEF_STMT (base)),
2299 use_bb: gimple_bb (g: stmt))->count;
2300
2301 if (init_count < bb->count)
2302 return MAX ((init_count.to_sreal_scale (bb->count)
2303 * REG_BR_PROB_BASE).to_int (), 1);
2304 return REG_BR_PROB_BASE;
2305 }
2306 else
2307 {
2308 ao_ref refd;
2309 profile_count max = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
2310 struct record_modified_bb_info info;
2311 tree init = ctor_for_folding (base);
2312
2313 if (init != error_mark_node)
2314 return 0;
2315 if (!bb->count.nonzero_p () || fbi->aa_walk_budget == 0)
2316 return REG_BR_PROB_BASE;
2317 if (dump_file)
2318 {
2319 fprintf (stream: dump_file, format: " Analyzing param change probability of ");
2320 print_generic_expr (dump_file, op, TDF_SLIM);
2321 fprintf (stream: dump_file, format: "\n");
2322 }
2323 ao_ref_init (&refd, op);
2324 info.op = op;
2325 info.stmt = stmt;
2326 info.bb_set = BITMAP_ALLOC (NULL);
2327 int walked
2328 = walk_aliased_vdefs (&refd, gimple_vuse (g: stmt), record_modified, &info,
2329 NULL, NULL, limit: fbi->aa_walk_budget);
2330 if (walked > 0)
2331 fbi->aa_walk_budget -= walked;
2332 if (walked < 0 || bitmap_bit_p (info.bb_set, bb->index))
2333 {
2334 if (walked < 0)
2335 fbi->aa_walk_budget = 0;
2336 if (dump_file)
2337 {
2338 if (walked < 0)
2339 fprintf (stream: dump_file, format: " Ran out of AA walking budget.\n");
2340 else
2341 fprintf (stream: dump_file, format: " Set in same BB as used.\n");
2342 }
2343 BITMAP_FREE (info.bb_set);
2344 return REG_BR_PROB_BASE;
2345 }
2346
2347 bitmap_iterator bi;
2348 unsigned index;
2349 /* Lookup the most frequent update of the value and believe that
2350 it dominates all the other; precise analysis here is difficult. */
2351 EXECUTE_IF_SET_IN_BITMAP (info.bb_set, 0, index, bi)
2352 max = max.max (BASIC_BLOCK_FOR_FN (cfun, index)->count);
2353 if (dump_file)
2354 {
2355 fprintf (stream: dump_file, format: " Set with count ");
2356 max.dump (f: dump_file);
2357 fprintf (stream: dump_file, format: " and used with count ");
2358 bb->count.dump (f: dump_file);
2359 fprintf (stream: dump_file, format: " freq %f\n",
2360 max.to_sreal_scale (in: bb->count).to_double ());
2361 }
2362
2363 BITMAP_FREE (info.bb_set);
2364 if (max < bb->count)
2365 return MAX ((max.to_sreal_scale (bb->count)
2366 * REG_BR_PROB_BASE).to_int (), 1);
2367 return REG_BR_PROB_BASE;
2368 }
2369}
2370
2371/* Find whether a basic block BB is the final block of a (half) diamond CFG
2372 sub-graph and if the predicate the condition depends on is known. If so,
2373 return true and store the pointer the predicate in *P. */
2374
2375static bool
2376phi_result_unknown_predicate (ipa_func_body_info *fbi,
2377 ipa_fn_summary *summary,
2378 class ipa_node_params *params_summary,
2379 basic_block bb,
2380 ipa_predicate *p,
2381 vec<ipa_predicate> nonconstant_names)
2382{
2383 edge e;
2384 edge_iterator ei;
2385 basic_block first_bb = NULL;
2386
2387 if (single_pred_p (bb))
2388 {
2389 *p = false;
2390 return true;
2391 }
2392
2393 FOR_EACH_EDGE (e, ei, bb->preds)
2394 {
2395 if (single_succ_p (bb: e->src))
2396 {
2397 if (!single_pred_p (bb: e->src))
2398 return false;
2399 if (!first_bb)
2400 first_bb = single_pred (bb: e->src);
2401 else if (single_pred (bb: e->src) != first_bb)
2402 return false;
2403 }
2404 else
2405 {
2406 if (!first_bb)
2407 first_bb = e->src;
2408 else if (e->src != first_bb)
2409 return false;
2410 }
2411 }
2412
2413 if (!first_bb)
2414 return false;
2415
2416 gcond *stmt = safe_dyn_cast <gcond *> (p: *gsi_last_bb (bb: first_bb));
2417 if (!stmt
2418 || !is_gimple_ip_invariant (gimple_cond_rhs (gs: stmt)))
2419 return false;
2420
2421 *p = will_be_nonconstant_expr_predicate (fbi, summary, params_summary,
2422 expr: gimple_cond_lhs (gs: stmt),
2423 nonconstant_names);
2424 if (*p == true)
2425 return false;
2426 else
2427 return true;
2428}
2429
2430/* Given a PHI statement in a function described by inline properties SUMMARY
2431 and *P being the predicate describing whether the selected PHI argument is
2432 known, store a predicate for the result of the PHI statement into
2433 NONCONSTANT_NAMES, if possible. */
2434
2435static void
2436predicate_for_phi_result (class ipa_fn_summary *summary, gphi *phi,
2437 ipa_predicate *p,
2438 vec<ipa_predicate> nonconstant_names)
2439{
2440 unsigned i;
2441
2442 for (i = 0; i < gimple_phi_num_args (gs: phi); i++)
2443 {
2444 tree arg = gimple_phi_arg (gs: phi, index: i)->def;
2445 if (!is_gimple_min_invariant (arg))
2446 {
2447 gcc_assert (TREE_CODE (arg) == SSA_NAME);
2448 *p = p->or_with (summary->conds,
2449 nonconstant_names[SSA_NAME_VERSION (arg)]);
2450 if (*p == true)
2451 return;
2452 }
2453 }
2454
2455 if (dump_file && (dump_flags & TDF_DETAILS))
2456 {
2457 fprintf (stream: dump_file, format: "\t\tphi predicate: ");
2458 p->dump (f: dump_file, summary->conds);
2459 }
2460 nonconstant_names[SSA_NAME_VERSION (gimple_phi_result (phi))] = *p;
2461}
2462
2463/* For a typical usage of __builtin_expect (a<b, 1), we
2464 may introduce an extra relation stmt:
2465 With the builtin, we have
2466 t1 = a <= b;
2467 t2 = (long int) t1;
2468 t3 = __builtin_expect (t2, 1);
2469 if (t3 != 0)
2470 goto ...
2471 Without the builtin, we have
2472 if (a<=b)
2473 goto...
2474 This affects the size/time estimation and may have
2475 an impact on the earlier inlining.
2476 Here find this pattern and fix it up later. */
2477
2478static gimple *
2479find_foldable_builtin_expect (basic_block bb)
2480{
2481 gimple_stmt_iterator bsi;
2482
2483 for (bsi = gsi_start_bb (bb); !gsi_end_p (i: bsi); gsi_next (i: &bsi))
2484 {
2485 gimple *stmt = gsi_stmt (i: bsi);
2486 if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT)
2487 || gimple_call_builtin_p (stmt, BUILT_IN_EXPECT_WITH_PROBABILITY)
2488 || gimple_call_internal_p (gs: stmt, fn: IFN_BUILTIN_EXPECT))
2489 {
2490 tree var = gimple_call_lhs (gs: stmt);
2491 tree arg = gimple_call_arg (gs: stmt, index: 0);
2492 use_operand_p use_p;
2493 gimple *use_stmt;
2494 bool match = false;
2495 bool done = false;
2496
2497 if (!var || !arg)
2498 continue;
2499 gcc_assert (TREE_CODE (var) == SSA_NAME);
2500
2501 while (TREE_CODE (arg) == SSA_NAME)
2502 {
2503 gimple *stmt_tmp = SSA_NAME_DEF_STMT (arg);
2504 if (!is_gimple_assign (gs: stmt_tmp))
2505 break;
2506 switch (gimple_assign_rhs_code (gs: stmt_tmp))
2507 {
2508 case LT_EXPR:
2509 case LE_EXPR:
2510 case GT_EXPR:
2511 case GE_EXPR:
2512 case EQ_EXPR:
2513 case NE_EXPR:
2514 match = true;
2515 done = true;
2516 break;
2517 CASE_CONVERT:
2518 break;
2519 default:
2520 done = true;
2521 break;
2522 }
2523 if (done)
2524 break;
2525 arg = gimple_assign_rhs1 (gs: stmt_tmp);
2526 }
2527
2528 if (match && single_imm_use (var, use_p: &use_p, stmt: &use_stmt)
2529 && gimple_code (g: use_stmt) == GIMPLE_COND)
2530 return use_stmt;
2531 }
2532 }
2533 return NULL;
2534}
2535
2536/* Return true when the basic blocks contains only clobbers followed by RESX.
2537 Such BBs are kept around to make removal of dead stores possible with
2538 presence of EH and will be optimized out by optimize_clobbers later in the
2539 game.
2540
2541 NEED_EH is used to recurse in case the clobber has non-EH predecessors
2542 that can be clobber only, too.. When it is false, the RESX is not necessary
2543 on the end of basic block. */
2544
2545static bool
2546clobber_only_eh_bb_p (basic_block bb, bool need_eh = true)
2547{
2548 gimple_stmt_iterator gsi = gsi_last_bb (bb);
2549 edge_iterator ei;
2550 edge e;
2551
2552 if (need_eh)
2553 {
2554 if (gsi_end_p (i: gsi))
2555 return false;
2556 if (gimple_code (g: gsi_stmt (i: gsi)) != GIMPLE_RESX)
2557 return false;
2558 gsi_prev (i: &gsi);
2559 }
2560 else if (!single_succ_p (bb))
2561 return false;
2562
2563 for (; !gsi_end_p (i: gsi); gsi_prev (i: &gsi))
2564 {
2565 gimple *stmt = gsi_stmt (i: gsi);
2566 if (is_gimple_debug (gs: stmt))
2567 continue;
2568 if (gimple_clobber_p (s: stmt))
2569 continue;
2570 if (gimple_code (g: stmt) == GIMPLE_LABEL)
2571 break;
2572 return false;
2573 }
2574
2575 /* See if all predecessors are either throws or clobber only BBs. */
2576 FOR_EACH_EDGE (e, ei, bb->preds)
2577 if (!(e->flags & EDGE_EH)
2578 && !clobber_only_eh_bb_p (bb: e->src, need_eh: false))
2579 return false;
2580
2581 return true;
2582}
2583
2584/* Return true if STMT compute a floating point expression that may be affected
2585 by -ffast-math and similar flags. */
2586
2587static bool
2588fp_expression_p (gimple *stmt)
2589{
2590 ssa_op_iter i;
2591 tree op;
2592
2593 FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_DEF|SSA_OP_USE)
2594 if (FLOAT_TYPE_P (TREE_TYPE (op)))
2595 return true;
2596 return false;
2597}
2598
2599/* Return true if T references memory location that is local
2600 for the function (that means, dead after return) or read-only. */
2601
2602bool
2603refs_local_or_readonly_memory_p (tree t)
2604{
2605 /* Non-escaping memory is fine. */
2606 t = get_base_address (t);
2607 if ((TREE_CODE (t) == MEM_REF
2608 || TREE_CODE (t) == TARGET_MEM_REF))
2609 return points_to_local_or_readonly_memory_p (TREE_OPERAND (t, 0));
2610
2611 /* Automatic variables are fine. */
2612 if (DECL_P (t)
2613 && auto_var_in_fn_p (t, current_function_decl))
2614 return true;
2615
2616 /* Read-only variables are fine. */
2617 if (DECL_P (t) && TREE_READONLY (t))
2618 return true;
2619
2620 return false;
2621}
2622
2623/* Return true if T is a pointer pointing to memory location that is local
2624 for the function (that means, dead after return) or read-only. */
2625
2626bool
2627points_to_local_or_readonly_memory_p (tree t)
2628{
2629 /* See if memory location is clearly invalid. */
2630 if (integer_zerop (t))
2631 return flag_delete_null_pointer_checks;
2632 if (TREE_CODE (t) == SSA_NAME)
2633 {
2634 /* For IPA passes we can consinder accesses to return slot local
2635 even if it is not local in the sense that memory is dead by
2636 the end of founction.
2637 The outer function will see a store in the call assignment
2638 and thus this will do right thing for all uses of this
2639 function in the current IPA passes (modref, pure/const discovery
2640 and inlining heuristics). */
2641 if (DECL_RESULT (current_function_decl)
2642 && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))
2643 && t == ssa_default_def (cfun, DECL_RESULT (current_function_decl)))
2644 return true;
2645 return !ptr_deref_may_alias_global_p (t, false);
2646 }
2647 if (TREE_CODE (t) == ADDR_EXPR)
2648 return refs_local_or_readonly_memory_p (TREE_OPERAND (t, 0));
2649 return false;
2650}
2651
2652/* Return true if T is a pointer pointing to memory location that is possible
2653 sra candidate if all functions it is passed to are inlined. */
2654
2655static bool
2656points_to_possible_sra_candidate_p (tree t)
2657{
2658 if (TREE_CODE (t) != ADDR_EXPR)
2659 return false;
2660
2661 t = get_base_address (TREE_OPERAND (t, 0));
2662
2663 /* Automatic variables are fine. */
2664 if (DECL_P (t)
2665 && auto_var_in_fn_p (t, current_function_decl))
2666 return true;
2667 return false;
2668}
2669
2670/* Analyze function body for NODE.
2671 EARLY indicates run from early optimization pipeline. */
2672
2673static void
2674analyze_function_body (struct cgraph_node *node, bool early)
2675{
2676 sreal time = opt_for_fn (node->decl, param_uninlined_function_time);
2677 /* Estimate static overhead for function prologue/epilogue and alignment. */
2678 int size = opt_for_fn (node->decl, param_uninlined_function_insns);
2679 /* Benefits are scaled by probability of elimination that is in range
2680 <0,2>. */
2681 basic_block bb;
2682 struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
2683 sreal freq;
2684 class ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
2685 ipa_node_params *params_summary
2686 = early ? NULL : ipa_node_params_sum->get (node);
2687 ipa_predicate bb_predicate;
2688 struct ipa_func_body_info fbi;
2689 vec<ipa_predicate> nonconstant_names = vNULL;
2690 int nblocks, n;
2691 int *order;
2692 gimple *fix_builtin_expect_stmt;
2693
2694 gcc_assert (my_function && my_function->cfg);
2695 gcc_assert (cfun == my_function);
2696
2697 memset(s: &fbi, c: 0, n: sizeof(fbi));
2698 vec_free (v&: info->conds);
2699 info->conds = NULL;
2700 info->size_time_table.release ();
2701 info->call_size_time_table.release ();
2702
2703 /* When optimizing and analyzing for IPA inliner, initialize loop optimizer
2704 so we can produce proper inline hints.
2705
2706 When optimizing and analyzing for early inliner, initialize node params
2707 so we can produce correct BB predicates. */
2708
2709 if (opt_for_fn (node->decl, optimize))
2710 {
2711 calculate_dominance_info (CDI_DOMINATORS);
2712 calculate_dominance_info (CDI_POST_DOMINATORS);
2713 if (!early)
2714 loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
2715 else
2716 {
2717 ipa_check_create_node_params ();
2718 ipa_initialize_node_params (node);
2719 }
2720
2721 if (ipa_node_params_sum)
2722 {
2723 fbi.node = node;
2724 fbi.info = ipa_node_params_sum->get (node);
2725 fbi.bb_infos = vNULL;
2726 fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun), exact: true);
2727 fbi.param_count = count_formal_params (fndecl: node->decl);
2728 fbi.aa_walk_budget = opt_for_fn (node->decl, param_ipa_max_aa_steps);
2729
2730 nonconstant_names.safe_grow_cleared
2731 (SSANAMES (my_function)->length (), exact: true);
2732 }
2733 }
2734
2735 if (dump_file)
2736 fprintf (stream: dump_file, format: "\nAnalyzing function body size: %s\n",
2737 node->dump_name ());
2738
2739 /* When we run into maximal number of entries, we assign everything to the
2740 constant truth case. Be sure to have it in list. */
2741 bb_predicate = true;
2742 info->account_size_time (size: 0, time: 0, exec_pred: bb_predicate, nonconst_pred_in: bb_predicate);
2743
2744 bb_predicate = ipa_predicate::not_inlined ();
2745 info->account_size_time (opt_for_fn (node->decl,
2746 param_uninlined_function_insns)
2747 * ipa_fn_summary::size_scale,
2748 opt_for_fn (node->decl,
2749 param_uninlined_function_time),
2750 exec_pred: bb_predicate,
2751 nonconst_pred_in: bb_predicate);
2752
2753 /* Only look for target information for inlinable functions. */
2754 bool scan_for_target_info =
2755 info->inlinable
2756 && targetm.target_option.need_ipa_fn_target_info (node->decl,
2757 info->target_info);
2758
2759 if (fbi.info)
2760 compute_bb_predicates (fbi: &fbi, node, summary: info, params_summary);
2761 const profile_count entry_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
2762 order = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
2763 nblocks = pre_and_rev_post_order_compute (NULL, order, false);
2764 for (n = 0; n < nblocks; n++)
2765 {
2766 bb = BASIC_BLOCK_FOR_FN (cfun, order[n]);
2767 freq = bb->count.to_sreal_scale (in: entry_count);
2768 if (clobber_only_eh_bb_p (bb))
2769 {
2770 if (dump_file && (dump_flags & TDF_DETAILS))
2771 fprintf (stream: dump_file, format: "\n Ignoring BB %i;"
2772 " it will be optimized away by cleanup_clobbers\n",
2773 bb->index);
2774 continue;
2775 }
2776
2777 /* TODO: Obviously predicates can be propagated down across CFG. */
2778 if (fbi.info)
2779 {
2780 if (bb->aux)
2781 bb_predicate = *(ipa_predicate *)bb->aux;
2782 else
2783 bb_predicate = false;
2784 }
2785 else
2786 bb_predicate = true;
2787
2788 if (dump_file && (dump_flags & TDF_DETAILS))
2789 {
2790 fprintf (stream: dump_file, format: "\n BB %i predicate:", bb->index);
2791 bb_predicate.dump (f: dump_file, info->conds);
2792 }
2793
2794 if (fbi.info && nonconstant_names.exists ())
2795 {
2796 ipa_predicate phi_predicate;
2797 bool first_phi = true;
2798
2799 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (i: bsi);
2800 gsi_next (i: &bsi))
2801 {
2802 if (first_phi
2803 && !phi_result_unknown_predicate (fbi: &fbi, summary: info,
2804 params_summary,
2805 bb,
2806 p: &phi_predicate,
2807 nonconstant_names))
2808 break;
2809 first_phi = false;
2810 if (dump_file && (dump_flags & TDF_DETAILS))
2811 {
2812 fprintf (stream: dump_file, format: " ");
2813 print_gimple_stmt (dump_file, gsi_stmt (i: bsi), 0);
2814 }
2815 predicate_for_phi_result (summary: info, phi: bsi.phi (), p: &phi_predicate,
2816 nonconstant_names);
2817 }
2818 }
2819
2820 fix_builtin_expect_stmt = find_foldable_builtin_expect (bb);
2821
2822 for (gimple_stmt_iterator bsi = gsi_start_nondebug_bb (bb);
2823 !gsi_end_p (i: bsi); gsi_next_nondebug (i: &bsi))
2824 {
2825 gimple *stmt = gsi_stmt (i: bsi);
2826 int this_size = estimate_num_insns (stmt, &eni_size_weights);
2827 int this_time = estimate_num_insns (stmt, &eni_time_weights);
2828 int prob;
2829 ipa_predicate will_be_nonconstant;
2830
2831 /* This relation stmt should be folded after we remove
2832 __builtin_expect call. Adjust the cost here. */
2833 if (stmt == fix_builtin_expect_stmt)
2834 {
2835 this_size--;
2836 this_time--;
2837 }
2838
2839 if (dump_file && (dump_flags & TDF_DETAILS))
2840 {
2841 fprintf (stream: dump_file, format: " ");
2842 print_gimple_stmt (dump_file, stmt, 0);
2843 fprintf (stream: dump_file, format: "\t\tfreq:%3.2f size:%3i time:%3i\n",
2844 freq.to_double (), this_size,
2845 this_time);
2846 }
2847
2848 if (is_gimple_call (gs: stmt)
2849 && !gimple_call_internal_p (gs: stmt))
2850 {
2851 struct cgraph_edge *edge = node->get_edge (call_stmt: stmt);
2852 ipa_call_summary *es = ipa_call_summaries->get_create (edge);
2853
2854 /* Special case: results of BUILT_IN_CONSTANT_P will be always
2855 resolved as constant. We however don't want to optimize
2856 out the cgraph edges. */
2857 if (nonconstant_names.exists ()
2858 && gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P)
2859 && gimple_call_lhs (gs: stmt)
2860 && TREE_CODE (gimple_call_lhs (stmt)) == SSA_NAME)
2861 {
2862 ipa_predicate false_p = false;
2863 nonconstant_names[SSA_NAME_VERSION (gimple_call_lhs (stmt))]
2864 = false_p;
2865 }
2866 if (ipa_node_params_sum)
2867 {
2868 int count = gimple_call_num_args (gs: stmt);
2869 int i;
2870
2871 if (count)
2872 es->param.safe_grow_cleared (len: count, exact: true);
2873 for (i = 0; i < count; i++)
2874 {
2875 int prob = param_change_prob (fbi: &fbi, stmt, i);
2876 gcc_assert (prob >= 0 && prob <= REG_BR_PROB_BASE);
2877 es->param[i].change_prob = prob;
2878 es->param[i].points_to_local_or_readonly_memory
2879 = points_to_local_or_readonly_memory_p
2880 (t: gimple_call_arg (gs: stmt, index: i));
2881 es->param[i].points_to_possible_sra_candidate
2882 = points_to_possible_sra_candidate_p
2883 (t: gimple_call_arg (gs: stmt, index: i));
2884 }
2885 }
2886 /* We cannot setup VLA parameters during inlining. */
2887 for (unsigned int i = 0; i < gimple_call_num_args (gs: stmt); ++i)
2888 if (TREE_CODE (gimple_call_arg (stmt, i)) == WITH_SIZE_EXPR)
2889 {
2890 edge->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
2891 break;
2892 }
2893 es->call_stmt_size = this_size;
2894 es->call_stmt_time = this_time;
2895 es->loop_depth = bb_loop_depth (bb);
2896 edge_set_predicate (e: edge, predicate: &bb_predicate);
2897 if (edge->speculative)
2898 {
2899 cgraph_edge *indirect
2900 = edge->speculative_call_indirect_edge ();
2901 ipa_call_summary *es2
2902 = ipa_call_summaries->get_create (edge: indirect);
2903 ipa_call_summaries->duplicate (edge, indirect,
2904 es, es2);
2905
2906 /* Edge is the first direct call.
2907 create and duplicate call summaries for multiple
2908 speculative call targets. */
2909 for (cgraph_edge *direct
2910 = edge->next_speculative_call_target ();
2911 direct;
2912 direct = direct->next_speculative_call_target ())
2913 {
2914 ipa_call_summary *es3
2915 = ipa_call_summaries->get_create (edge: direct);
2916 ipa_call_summaries->duplicate (edge, direct,
2917 es, es3);
2918 }
2919 }
2920 }
2921
2922 /* TODO: When conditional jump or switch is known to be constant, but
2923 we did not translate it into the predicates, we really can account
2924 just maximum of the possible paths. */
2925 if (fbi.info)
2926 will_be_nonconstant
2927 = will_be_nonconstant_predicate (fbi: &fbi, summary: info, params_summary,
2928 stmt, nonconstant_names);
2929 else
2930 will_be_nonconstant = true;
2931 if (this_time || this_size)
2932 {
2933 sreal final_time = (sreal)this_time * freq;
2934 prob = eliminated_by_inlining_prob (fbi: &fbi, stmt);
2935 if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS))
2936 fprintf (stream: dump_file,
2937 format: "\t\t50%% will be eliminated by inlining\n");
2938 if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS))
2939 fprintf (stream: dump_file, format: "\t\tWill be eliminated by inlining\n");
2940
2941 ipa_predicate p = bb_predicate & will_be_nonconstant;
2942 int parm = load_or_store_of_ptr_parameter (fbi: &fbi, stmt);
2943 ipa_predicate sra_predicate = true;
2944 if (parm != -1)
2945 sra_predicate &= add_condition (summary: info, params_summary, operand_num: parm,
2946 ptr_type_node, NULL,
2947 code: ipa_predicate::not_sra_candidate, NULL, param_ops: 0);
2948
2949 /* We can ignore statement when we proved it is never going
2950 to happen, but we cannot do that for call statements
2951 because edges are accounted specially. */
2952
2953 if (*(is_gimple_call (gs: stmt) ? &bb_predicate : &p) != false)
2954 {
2955 time += final_time;
2956 size += this_size;
2957 }
2958
2959 /* We account everything but the calls. Calls have their own
2960 size/time info attached to cgraph edges. This is necessary
2961 in order to make the cost disappear after inlining. */
2962 if (!is_gimple_call (gs: stmt))
2963 {
2964 if (prob)
2965 {
2966 ipa_predicate ip
2967 = bb_predicate & ipa_predicate::not_inlined () & sra_predicate;
2968 info->account_size_time (size: this_size * prob,
2969 time: (final_time * prob) / 2, exec_pred: ip,
2970 nonconst_pred_in: p);
2971 }
2972 if (prob != 2)
2973 info->account_size_time (size: this_size * (2 - prob),
2974 time: (final_time * (2 - prob) / 2),
2975 exec_pred: bb_predicate & sra_predicate,
2976 nonconst_pred_in: p);
2977 }
2978
2979 if (!info->fp_expressions && fp_expression_p (stmt))
2980 {
2981 info->fp_expressions = true;
2982 if (dump_file)
2983 fprintf (stream: dump_file, format: " fp_expression set\n");
2984 }
2985 }
2986
2987 /* For target specific information, we want to scan all statements
2988 rather than those statements with non-zero weights, to avoid
2989 missing to scan something interesting for target information,
2990 such as: internal function calls. */
2991 if (scan_for_target_info)
2992 scan_for_target_info =
2993 targetm.target_option.update_ipa_fn_target_info
2994 (info->target_info, stmt);
2995
2996 /* Account cost of address calculations in the statements. */
2997 for (unsigned int i = 0; i < gimple_num_ops (gs: stmt); i++)
2998 {
2999 for (tree op = gimple_op (gs: stmt, i);
3000 op && handled_component_p (t: op);
3001 op = TREE_OPERAND (op, 0))
3002 if ((TREE_CODE (op) == ARRAY_REF
3003 || TREE_CODE (op) == ARRAY_RANGE_REF)
3004 && TREE_CODE (TREE_OPERAND (op, 1)) == SSA_NAME)
3005 {
3006 ipa_predicate p = bb_predicate;
3007 if (fbi.info)
3008 p = p & will_be_nonconstant_expr_predicate
3009 (fbi: &fbi, summary: info, params_summary,
3010 TREE_OPERAND (op, 1),
3011 nonconstant_names);
3012 if (p != false)
3013 {
3014 time += freq;
3015 size += 1;
3016 if (dump_file)
3017 fprintf (stream: dump_file,
3018 format: "\t\tAccounting address calculation.\n");
3019 info->account_size_time (size: ipa_fn_summary::size_scale,
3020 time: freq,
3021 exec_pred: bb_predicate,
3022 nonconst_pred_in: p);
3023 }
3024 }
3025 }
3026
3027 }
3028 }
3029 free (ptr: order);
3030
3031 if (nonconstant_names.exists () && !early)
3032 {
3033 ipa_fn_summary *s = ipa_fn_summaries->get (node);
3034 unsigned max_loop_predicates = opt_for_fn (node->decl,
3035 param_ipa_max_loop_predicates);
3036
3037 if (dump_file && (dump_flags & TDF_DETAILS))
3038 flow_loops_dump (dump_file, NULL, 0);
3039 scev_initialize ();
3040 for (auto loop : loops_list (cfun, 0))
3041 {
3042 ipa_predicate loop_iterations = true;
3043 sreal header_freq;
3044 edge ex;
3045 unsigned int j;
3046 class tree_niter_desc niter_desc;
3047 if (!loop->header->aux)
3048 continue;
3049
3050 profile_count phdr_count = loop_preheader_edge (loop)->count ();
3051 sreal phdr_freq = phdr_count.to_sreal_scale (in: entry_count);
3052
3053 bb_predicate = *(ipa_predicate *)loop->header->aux;
3054 auto_vec<edge> exits = get_loop_exit_edges (loop);
3055 FOR_EACH_VEC_ELT (exits, j, ex)
3056 if (number_of_iterations_exit (loop, ex, niter: &niter_desc, false)
3057 && !is_gimple_min_invariant (niter_desc.niter))
3058 {
3059 ipa_predicate will_be_nonconstant
3060 = will_be_nonconstant_expr_predicate (fbi: &fbi, summary: info,
3061 params_summary,
3062 expr: niter_desc.niter,
3063 nonconstant_names);
3064 if (will_be_nonconstant != true)
3065 will_be_nonconstant = bb_predicate & will_be_nonconstant;
3066 if (will_be_nonconstant != true
3067 && will_be_nonconstant != false)
3068 loop_iterations &= will_be_nonconstant;
3069 }
3070 add_freqcounting_predicate (v: &s->loop_iterations, new_predicate: loop_iterations,
3071 add_freq: phdr_freq, max_num_predicates: max_loop_predicates);
3072 }
3073
3074 /* To avoid quadratic behavior we analyze stride predicates only
3075 with respect to the containing loop. Thus we simply iterate
3076 over all defs in the outermost loop body. */
3077 for (class loop *loop = loops_for_fn (cfun)->tree_root->inner;
3078 loop != NULL; loop = loop->next)
3079 {
3080 ipa_predicate loop_stride = true;
3081 basic_block *body = get_loop_body (loop);
3082 profile_count phdr_count = loop_preheader_edge (loop)->count ();
3083 sreal phdr_freq = phdr_count.to_sreal_scale (in: entry_count);
3084 for (unsigned i = 0; i < loop->num_nodes; i++)
3085 {
3086 gimple_stmt_iterator gsi;
3087 if (!body[i]->aux)
3088 continue;
3089
3090 bb_predicate = *(ipa_predicate *)body[i]->aux;
3091 for (gsi = gsi_start_bb (bb: body[i]); !gsi_end_p (i: gsi);
3092 gsi_next (i: &gsi))
3093 {
3094 gimple *stmt = gsi_stmt (i: gsi);
3095
3096 if (!is_gimple_assign (gs: stmt))
3097 continue;
3098
3099 tree def = gimple_assign_lhs (gs: stmt);
3100 if (TREE_CODE (def) != SSA_NAME)
3101 continue;
3102
3103 affine_iv iv;
3104 if (!simple_iv (loop_containing_stmt (stmt),
3105 loop_containing_stmt (stmt),
3106 def, &iv, true)
3107 || is_gimple_min_invariant (iv.step))
3108 continue;
3109
3110 ipa_predicate will_be_nonconstant
3111 = will_be_nonconstant_expr_predicate (fbi: &fbi, summary: info,
3112 params_summary,
3113 expr: iv.step,
3114 nonconstant_names);
3115 if (will_be_nonconstant != true)
3116 will_be_nonconstant = bb_predicate & will_be_nonconstant;
3117 if (will_be_nonconstant != true
3118 && will_be_nonconstant != false)
3119 loop_stride = loop_stride & will_be_nonconstant;
3120 }
3121 }
3122 add_freqcounting_predicate (v: &s->loop_strides, new_predicate: loop_stride,
3123 add_freq: phdr_freq, max_num_predicates: max_loop_predicates);
3124 free (ptr: body);
3125 }
3126 scev_finalize ();
3127 }
3128 FOR_ALL_BB_FN (bb, my_function)
3129 {
3130 edge e;
3131 edge_iterator ei;
3132
3133 if (bb->aux)
3134 edge_predicate_pool.remove (object: (ipa_predicate *)bb->aux);
3135 bb->aux = NULL;
3136 FOR_EACH_EDGE (e, ei, bb->succs)
3137 {
3138 if (e->aux)
3139 edge_predicate_pool.remove (object: (ipa_predicate *)e->aux);
3140 e->aux = NULL;
3141 }
3142 }
3143 ipa_fn_summary *s = ipa_fn_summaries->get (node);
3144 ipa_size_summary *ss = ipa_size_summaries->get (node);
3145 s->time = time;
3146 ss->self_size = size;
3147 nonconstant_names.release ();
3148 ipa_release_body_info (&fbi);
3149 if (opt_for_fn (node->decl, optimize))
3150 {
3151 if (!early)
3152 loop_optimizer_finalize ();
3153 else if (!ipa_edge_args_sum)
3154 ipa_free_all_node_params ();
3155 free_dominance_info (CDI_DOMINATORS);
3156 free_dominance_info (CDI_POST_DOMINATORS);
3157 }
3158 if (dump_file)
3159 {
3160 fprintf (stream: dump_file, format: "\n");
3161 ipa_dump_fn_summary (f: dump_file, node);
3162 }
3163}
3164
3165
3166/* Compute function summary.
3167 EARLY is true when we compute parameters during early opts. */
3168
3169void
3170compute_fn_summary (struct cgraph_node *node, bool early)
3171{
3172 HOST_WIDE_INT self_stack_size;
3173 struct cgraph_edge *e;
3174
3175 gcc_assert (!node->inlined_to);
3176
3177 if (!ipa_fn_summaries)
3178 ipa_fn_summary_alloc ();
3179
3180 /* Create a new ipa_fn_summary. */
3181 ((ipa_fn_summary_t *)ipa_fn_summaries)->remove_callees (node);
3182 ipa_fn_summaries->remove (node);
3183 class ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
3184 class ipa_size_summary *size_info = ipa_size_summaries->get_create (node);
3185
3186 /* Estimate the stack size for the function if we're optimizing. */
3187 self_stack_size = optimize && !node->thunk
3188 ? estimated_stack_frame_size (node) : 0;
3189 size_info->estimated_self_stack_size = self_stack_size;
3190 info->estimated_stack_size = self_stack_size;
3191
3192 if (node->thunk)
3193 {
3194 ipa_call_summary *es = ipa_call_summaries->get_create (edge: node->callees);
3195 ipa_predicate t = true;
3196
3197 node->can_change_signature = false;
3198 es->call_stmt_size = eni_size_weights.call_cost;
3199 es->call_stmt_time = eni_time_weights.call_cost;
3200 info->account_size_time (size: ipa_fn_summary::size_scale
3201 * opt_for_fn (node->decl,
3202 param_uninlined_function_thunk_insns),
3203 opt_for_fn (node->decl,
3204 param_uninlined_function_thunk_time), exec_pred: t, nonconst_pred_in: t);
3205 t = ipa_predicate::not_inlined ();
3206 info->account_size_time (size: 2 * ipa_fn_summary::size_scale, time: 0, exec_pred: t, nonconst_pred_in: t);
3207 ipa_update_overall_fn_summary (node);
3208 size_info->self_size = size_info->size;
3209 if (stdarg_p (TREE_TYPE (node->decl)))
3210 {
3211 info->inlinable = false;
3212 node->callees->inline_failed = CIF_VARIADIC_THUNK;
3213 }
3214 else
3215 info->inlinable = true;
3216 }
3217 else
3218 {
3219 /* Even is_gimple_min_invariant rely on current_function_decl. */
3220 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
3221
3222 /* During IPA profile merging we may be called w/o virtual SSA form
3223 built. */
3224 update_ssa (TODO_update_ssa_only_virtuals);
3225
3226 /* Can this function be inlined at all? */
3227 if (!opt_for_fn (node->decl, optimize)
3228 && !lookup_attribute (attr_name: "always_inline",
3229 DECL_ATTRIBUTES (node->decl)))
3230 info->inlinable = false;
3231 else
3232 info->inlinable = tree_inlinable_function_p (node->decl);
3233
3234 bool no_signature = false;
3235 /* Type attributes can use parameter indices to describe them.
3236 Special case fn spec since we can safely preserve them in
3237 modref summaries. */
3238 for (tree list = TYPE_ATTRIBUTES (TREE_TYPE (node->decl));
3239 list && !no_signature; list = TREE_CHAIN (list))
3240 if (!ipa_param_adjustments::type_attribute_allowed_p
3241 (get_attribute_name (list)))
3242 {
3243 if (dump_file)
3244 {
3245 fprintf (stream: dump_file, format: "No signature change:"
3246 " function type has unhandled attribute %s.\n",
3247 IDENTIFIER_POINTER (get_attribute_name (list)));
3248 }
3249 no_signature = true;
3250 }
3251 for (tree parm = DECL_ARGUMENTS (node->decl);
3252 parm && !no_signature; parm = DECL_CHAIN (parm))
3253 if (variably_modified_type_p (TREE_TYPE (parm), node->decl))
3254 {
3255 if (dump_file)
3256 {
3257 fprintf (stream: dump_file, format: "No signature change:"
3258 " has parameter with variably modified type.\n");
3259 }
3260 no_signature = true;
3261 }
3262
3263 /* Likewise for #pragma omp declare simd functions or functions
3264 with simd attribute. */
3265 if (no_signature
3266 || lookup_attribute (attr_name: "omp declare simd",
3267 DECL_ATTRIBUTES (node->decl)))
3268 node->can_change_signature = false;
3269 else
3270 {
3271 /* Otherwise, inlinable functions always can change signature. */
3272 if (info->inlinable)
3273 node->can_change_signature = true;
3274 else
3275 {
3276 /* Functions calling builtin_apply cannot change signature. */
3277 for (e = node->callees; e; e = e->next_callee)
3278 {
3279 tree cdecl = e->callee->decl;
3280 if (fndecl_built_in_p (node: cdecl, name1: BUILT_IN_APPLY_ARGS,
3281 names: BUILT_IN_VA_START))
3282 break;
3283 }
3284 node->can_change_signature = !e;
3285 }
3286 }
3287 analyze_function_body (node, early);
3288 pop_cfun ();
3289 }
3290
3291 /* Inlining characteristics are maintained by the cgraph_mark_inline. */
3292 size_info->size = size_info->self_size;
3293 info->estimated_stack_size = size_info->estimated_self_stack_size;
3294
3295 /* Code above should compute exactly the same result as
3296 ipa_update_overall_fn_summary except for case when speculative
3297 edges are present since these are accounted to size but not
3298 self_size. Do not compare time since different order the roundoff
3299 errors result in slight changes. */
3300 ipa_update_overall_fn_summary (node);
3301 if (flag_checking)
3302 {
3303 for (e = node->indirect_calls; e; e = e->next_callee)
3304 if (e->speculative)
3305 break;
3306 gcc_assert (e || size_info->size == size_info->self_size);
3307 }
3308}
3309
3310
3311/* Compute parameters of functions used by inliner using
3312 current_function_decl. */
3313
3314static unsigned int
3315compute_fn_summary_for_current (void)
3316{
3317 compute_fn_summary (node: cgraph_node::get (decl: current_function_decl), early: true);
3318 return 0;
3319}
3320
3321/* Estimate benefit devirtualizing indirect edge IE and return true if it can
3322 be devirtualized and inlined, provided m_known_vals, m_known_contexts and
3323 m_known_aggs in AVALS. Return false straight away if AVALS is NULL. */
3324
3325static bool
3326estimate_edge_devirt_benefit (struct cgraph_edge *ie,
3327 int *size, int *time,
3328 ipa_call_arg_values *avals)
3329{
3330 tree target;
3331 struct cgraph_node *callee;
3332 class ipa_fn_summary *isummary;
3333 enum availability avail;
3334 bool speculative;
3335
3336 if (!avals
3337 || (!avals->m_known_vals.length() && !avals->m_known_contexts.length ()))
3338 return false;
3339 if (!opt_for_fn (ie->caller->decl, flag_indirect_inlining))
3340 return false;
3341
3342 target = ipa_get_indirect_edge_target (ie, avals, speculative: &speculative);
3343 if (!target || speculative)
3344 return false;
3345
3346 /* Account for difference in cost between indirect and direct calls. */
3347 *size -= (eni_size_weights.indirect_call_cost - eni_size_weights.call_cost);
3348 *time -= (eni_time_weights.indirect_call_cost - eni_time_weights.call_cost);
3349 gcc_checking_assert (*time >= 0);
3350 gcc_checking_assert (*size >= 0);
3351
3352 callee = cgraph_node::get (decl: target);
3353 if (!callee || !callee->definition)
3354 return false;
3355 callee = callee->function_symbol (avail: &avail);
3356 if (avail < AVAIL_AVAILABLE)
3357 return false;
3358 isummary = ipa_fn_summaries->get (node: callee);
3359 if (isummary == NULL)
3360 return false;
3361
3362 return isummary->inlinable;
3363}
3364
3365/* Increase SIZE, MIN_SIZE (if non-NULL) and TIME for size and time needed to
3366 handle edge E with probability PROB. Set HINTS accordingly if edge may be
3367 devirtualized. AVALS, if non-NULL, describes the context of the call site
3368 as far as values of parameters are concerened. */
3369
3370static inline void
3371estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size,
3372 sreal *time, ipa_call_arg_values *avals,
3373 ipa_hints *hints)
3374{
3375 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
3376 int call_size = es->call_stmt_size;
3377 int call_time = es->call_stmt_time;
3378 int cur_size;
3379
3380 if (!e->callee && hints && e->maybe_hot_p ()
3381 && estimate_edge_devirt_benefit (ie: e, size: &call_size, time: &call_time, avals))
3382 *hints |= INLINE_HINT_indirect_call;
3383 cur_size = call_size * ipa_fn_summary::size_scale;
3384 *size += cur_size;
3385 if (min_size)
3386 *min_size += cur_size;
3387 if (time)
3388 *time += ((sreal)call_time) * e->sreal_frequency ();
3389}
3390
3391
3392/* Increase SIZE, MIN_SIZE and TIME for size and time needed to handle all
3393 calls in NODE. POSSIBLE_TRUTHS and AVALS describe the context of the call
3394 site.
3395
3396 Helper for estimate_calls_size_and_time which does the same but
3397 (in most cases) faster. */
3398
3399static void
3400estimate_calls_size_and_time_1 (struct cgraph_node *node, int *size,
3401 int *min_size, sreal *time,
3402 ipa_hints *hints,
3403 clause_t possible_truths,
3404 ipa_call_arg_values *avals)
3405{
3406 struct cgraph_edge *e;
3407 for (e = node->callees; e; e = e->next_callee)
3408 {
3409 if (!e->inline_failed)
3410 {
3411 gcc_checking_assert (!ipa_call_summaries->get (e));
3412 estimate_calls_size_and_time_1 (node: e->callee, size, min_size, time,
3413 hints, possible_truths, avals);
3414
3415 continue;
3416 }
3417 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
3418
3419 /* Do not care about zero sized builtins. */
3420 if (!es->call_stmt_size)
3421 {
3422 gcc_checking_assert (!es->call_stmt_time);
3423 continue;
3424 }
3425 if (!es->predicate
3426 || es->predicate->evaluate (possible_truths))
3427 {
3428 /* Predicates of calls shall not use NOT_CHANGED codes,
3429 so we do not need to compute probabilities. */
3430 estimate_edge_size_and_time (e, size,
3431 min_size: es->predicate ? NULL : min_size,
3432 time, avals, hints);
3433 }
3434 }
3435 for (e = node->indirect_calls; e; e = e->next_callee)
3436 {
3437 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
3438 if (!es->predicate
3439 || es->predicate->evaluate (possible_truths))
3440 estimate_edge_size_and_time (e, size,
3441 min_size: es->predicate ? NULL : min_size,
3442 time, avals, hints);
3443 }
3444}
3445
3446/* Populate sum->call_size_time_table for edges from NODE. */
3447
3448static void
3449summarize_calls_size_and_time (struct cgraph_node *node,
3450 ipa_fn_summary *sum)
3451{
3452 struct cgraph_edge *e;
3453 for (e = node->callees; e; e = e->next_callee)
3454 {
3455 if (!e->inline_failed)
3456 {
3457 gcc_checking_assert (!ipa_call_summaries->get (e));
3458 summarize_calls_size_and_time (node: e->callee, sum);
3459 continue;
3460 }
3461 int size = 0;
3462 sreal time = 0;
3463
3464 estimate_edge_size_and_time (e, size: &size, NULL, time: &time, NULL, NULL);
3465
3466 ipa_predicate pred = true;
3467 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
3468
3469 if (es->predicate)
3470 pred = *es->predicate;
3471 sum->account_size_time (size, time, exec_pred: pred, nonconst_pred_in: pred, call: true);
3472 }
3473 for (e = node->indirect_calls; e; e = e->next_callee)
3474 {
3475 int size = 0;
3476 sreal time = 0;
3477
3478 estimate_edge_size_and_time (e, size: &size, NULL, time: &time, NULL, NULL);
3479 ipa_predicate pred = true;
3480 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
3481
3482 if (es->predicate)
3483 pred = *es->predicate;
3484 sum->account_size_time (size, time, exec_pred: pred, nonconst_pred_in: pred, call: true);
3485 }
3486}
3487
3488/* Increase SIZE, MIN_SIZE and TIME for size and time needed to handle all
3489 calls in NODE. POSSIBLE_TRUTHS and AVALS (the latter if non-NULL) describe
3490 context of the call site. */
3491
3492static void
3493estimate_calls_size_and_time (struct cgraph_node *node, int *size,
3494 int *min_size, sreal *time,
3495 ipa_hints *hints,
3496 clause_t possible_truths,
3497 ipa_call_arg_values *avals)
3498{
3499 class ipa_fn_summary *sum = ipa_fn_summaries->get (node);
3500 bool use_table = true;
3501
3502 gcc_assert (node->callees || node->indirect_calls);
3503
3504 /* During early inlining we do not calculate info for very
3505 large functions and thus there is no need for producing
3506 summaries. */
3507 if (!ipa_node_params_sum)
3508 use_table = false;
3509 /* Do not calculate summaries for simple wrappers; it is waste
3510 of memory. */
3511 else if (node->callees && node->indirect_calls
3512 && node->callees->inline_failed && !node->callees->next_callee)
3513 use_table = false;
3514 /* If there is an indirect edge that may be optimized, we need
3515 to go the slow way. */
3516 else if (avals && hints
3517 && (avals->m_known_vals.length ()
3518 || avals->m_known_contexts.length ()
3519 || avals->m_known_aggs.length ()))
3520 {
3521 ipa_node_params *params_summary = ipa_node_params_sum->get (node);
3522 unsigned int nargs = params_summary
3523 ? ipa_get_param_count (info: params_summary) : 0;
3524
3525 for (unsigned int i = 0; i < nargs && use_table; i++)
3526 {
3527 if (ipa_is_param_used_by_indirect_call (info: params_summary, i)
3528 && (avals->safe_sval_at (index: i)
3529 || (ipa_argagg_value_list (avals).value_for_index_p (index: i))))
3530 use_table = false;
3531 else if (ipa_is_param_used_by_polymorphic_call (info: params_summary, i)
3532 && (avals->m_known_contexts.length () > i
3533 && !avals->m_known_contexts[i].useless_p ()))
3534 use_table = false;
3535 }
3536 }
3537
3538 /* Fast path is via the call size time table. */
3539 if (use_table)
3540 {
3541 /* Build summary if it is absent. */
3542 if (!sum->call_size_time_table.length ())
3543 {
3544 ipa_predicate true_pred = true;
3545 sum->account_size_time (size: 0, time: 0, exec_pred: true_pred, nonconst_pred_in: true_pred, call: true);
3546 summarize_calls_size_and_time (node, sum);
3547 }
3548
3549 int old_size = *size;
3550 sreal old_time = time ? *time : 0;
3551
3552 if (min_size)
3553 *min_size += sum->call_size_time_table[0].size;
3554
3555 unsigned int i;
3556 size_time_entry *e;
3557
3558 /* Walk the table and account sizes and times. */
3559 for (i = 0; sum->call_size_time_table.iterate (ix: i, ptr: &e);
3560 i++)
3561 if (e->exec_predicate.evaluate (possible_truths))
3562 {
3563 *size += e->size;
3564 if (time)
3565 *time += e->time;
3566 }
3567
3568 /* Be careful and see if both methods agree. */
3569 if ((flag_checking || dump_file)
3570 /* Do not try to sanity check when we know we lost some
3571 precision. */
3572 && sum->call_size_time_table.length ()
3573 < ipa_fn_summary::max_size_time_table_size)
3574 {
3575 estimate_calls_size_and_time_1 (node, size: &old_size, NULL, time: &old_time, NULL,
3576 possible_truths, avals);
3577 gcc_assert (*size == old_size);
3578 if (time && (*time - old_time > 1 || *time - old_time < -1)
3579 && dump_file)
3580 fprintf (stream: dump_file, format: "Time mismatch in call summary %f!=%f\n",
3581 old_time.to_double (),
3582 time->to_double ());
3583 }
3584 }
3585 /* Slow path by walking all edges. */
3586 else
3587 estimate_calls_size_and_time_1 (node, size, min_size, time, hints,
3588 possible_truths, avals);
3589}
3590
3591/* Main constructor for ipa call context. Memory allocation of ARG_VALUES
3592 is owned by the caller. INLINE_PARAM_SUMMARY is also owned by the
3593 caller. */
3594
3595ipa_call_context::ipa_call_context (cgraph_node *node, clause_t possible_truths,
3596 clause_t nonspec_possible_truths,
3597 vec<inline_param_summary>
3598 inline_param_summary,
3599 ipa_auto_call_arg_values *arg_values)
3600: m_node (node), m_possible_truths (possible_truths),
3601 m_nonspec_possible_truths (nonspec_possible_truths),
3602 m_inline_param_summary (inline_param_summary),
3603 m_avals (arg_values)
3604{
3605}
3606
3607/* Set THIS to be a duplicate of CTX. Copy all relevant info. */
3608
3609void
3610ipa_cached_call_context::duplicate_from (const ipa_call_context &ctx)
3611{
3612 m_node = ctx.m_node;
3613 m_possible_truths = ctx.m_possible_truths;
3614 m_nonspec_possible_truths = ctx.m_nonspec_possible_truths;
3615 ipa_node_params *params_summary = ipa_node_params_sum->get (node: m_node);
3616 unsigned int nargs = params_summary
3617 ? ipa_get_param_count (info: params_summary) : 0;
3618
3619 m_inline_param_summary = vNULL;
3620 /* Copy the info only if there is at least one useful entry. */
3621 if (ctx.m_inline_param_summary.exists ())
3622 {
3623 unsigned int n = MIN (ctx.m_inline_param_summary.length (), nargs);
3624
3625 for (unsigned int i = 0; i < n; i++)
3626 if (ipa_is_param_used_by_ipa_predicates (info: params_summary, i)
3627 && !ctx.m_inline_param_summary[i].useless_p ())
3628 {
3629 m_inline_param_summary
3630 = ctx.m_inline_param_summary.copy ();
3631 break;
3632 }
3633 }
3634 m_avals.m_known_vals = vNULL;
3635 if (ctx.m_avals.m_known_vals.exists ())
3636 {
3637 unsigned int n = MIN (ctx.m_avals.m_known_vals.length (), nargs);
3638
3639 for (unsigned int i = 0; i < n; i++)
3640 if (ipa_is_param_used_by_indirect_call (info: params_summary, i)
3641 && ctx.m_avals.m_known_vals[i])
3642 {
3643 m_avals.m_known_vals = ctx.m_avals.m_known_vals.copy ();
3644 break;
3645 }
3646 }
3647
3648 m_avals.m_known_contexts = vNULL;
3649 if (ctx.m_avals.m_known_contexts.exists ())
3650 {
3651 unsigned int n = MIN (ctx.m_avals.m_known_contexts.length (), nargs);
3652
3653 for (unsigned int i = 0; i < n; i++)
3654 if (ipa_is_param_used_by_polymorphic_call (info: params_summary, i)
3655 && !ctx.m_avals.m_known_contexts[i].useless_p ())
3656 {
3657 m_avals.m_known_contexts = ctx.m_avals.m_known_contexts.copy ();
3658 break;
3659 }
3660 }
3661
3662 m_avals.m_known_aggs = vNULL;
3663 if (ctx.m_avals.m_known_aggs.exists ())
3664 {
3665 const ipa_argagg_value_list avl (&ctx.m_avals);
3666 for (unsigned int i = 0; i < nargs; i++)
3667 if (ipa_is_param_used_by_indirect_call (info: params_summary, i)
3668 && avl.value_for_index_p (index: i))
3669 {
3670 m_avals.m_known_aggs = ctx.m_avals.m_known_aggs.copy ();
3671 break;
3672 }
3673 }
3674
3675 m_avals.m_known_value_ranges = vNULL;
3676}
3677
3678/* Release memory used by known_vals/contexts/aggs vectors. and
3679 inline_param_summary. */
3680
3681void
3682ipa_cached_call_context::release ()
3683{
3684 /* See if context is initialized at first place. */
3685 if (!m_node)
3686 return;
3687 m_avals.m_known_aggs.release ();
3688 m_avals.m_known_vals.release ();
3689 m_avals.m_known_contexts.release ();
3690 m_inline_param_summary.release ();
3691}
3692
3693/* Return true if CTX describes the same call context as THIS. */
3694
3695bool
3696ipa_call_context::equal_to (const ipa_call_context &ctx)
3697{
3698 if (m_node != ctx.m_node
3699 || m_possible_truths != ctx.m_possible_truths
3700 || m_nonspec_possible_truths != ctx.m_nonspec_possible_truths)
3701 return false;
3702
3703 ipa_node_params *params_summary = ipa_node_params_sum->get (node: m_node);
3704 unsigned int nargs = params_summary
3705 ? ipa_get_param_count (info: params_summary) : 0;
3706
3707 if (m_inline_param_summary.exists () || ctx.m_inline_param_summary.exists ())
3708 {
3709 for (unsigned int i = 0; i < nargs; i++)
3710 {
3711 if (!ipa_is_param_used_by_ipa_predicates (info: params_summary, i))
3712 continue;
3713 if (i >= m_inline_param_summary.length ()
3714 || m_inline_param_summary[i].useless_p ())
3715 {
3716 if (i < ctx.m_inline_param_summary.length ()
3717 && !ctx.m_inline_param_summary[i].useless_p ())
3718 return false;
3719 continue;
3720 }
3721 if (i >= ctx.m_inline_param_summary.length ()
3722 || ctx.m_inline_param_summary[i].useless_p ())
3723 {
3724 if (i < m_inline_param_summary.length ()
3725 && !m_inline_param_summary[i].useless_p ())
3726 return false;
3727 continue;
3728 }
3729 if (!m_inline_param_summary[i].equal_to
3730 (other: ctx.m_inline_param_summary[i]))
3731 return false;
3732 }
3733 }
3734 if (m_avals.m_known_vals.exists () || ctx.m_avals.m_known_vals.exists ())
3735 {
3736 for (unsigned int i = 0; i < nargs; i++)
3737 {
3738 if (!ipa_is_param_used_by_indirect_call (info: params_summary, i))
3739 continue;
3740 if (i >= m_avals.m_known_vals.length () || !m_avals.m_known_vals[i])
3741 {
3742 if (i < ctx.m_avals.m_known_vals.length ()
3743 && ctx.m_avals.m_known_vals[i])
3744 return false;
3745 continue;
3746 }
3747 if (i >= ctx.m_avals.m_known_vals.length ()
3748 || !ctx.m_avals.m_known_vals[i])
3749 {
3750 if (i < m_avals.m_known_vals.length () && m_avals.m_known_vals[i])
3751 return false;
3752 continue;
3753 }
3754 if (m_avals.m_known_vals[i] != ctx.m_avals.m_known_vals[i])
3755 return false;
3756 }
3757 }
3758 if (m_avals.m_known_contexts.exists ()
3759 || ctx.m_avals.m_known_contexts.exists ())
3760 {
3761 for (unsigned int i = 0; i < nargs; i++)
3762 {
3763 if (!ipa_is_param_used_by_polymorphic_call (info: params_summary, i))
3764 continue;
3765 if (i >= m_avals.m_known_contexts.length ()
3766 || m_avals.m_known_contexts[i].useless_p ())
3767 {
3768 if (i < ctx.m_avals.m_known_contexts.length ()
3769 && !ctx.m_avals.m_known_contexts[i].useless_p ())
3770 return false;
3771 continue;
3772 }
3773 if (i >= ctx.m_avals.m_known_contexts.length ()
3774 || ctx.m_avals.m_known_contexts[i].useless_p ())
3775 {
3776 if (i < m_avals.m_known_contexts.length ()
3777 && !m_avals.m_known_contexts[i].useless_p ())
3778 return false;
3779 continue;
3780 }
3781 if (!m_avals.m_known_contexts[i].equal_to
3782 (x: ctx.m_avals.m_known_contexts[i]))
3783 return false;
3784 }
3785 }
3786 if (m_avals.m_known_aggs.exists () || ctx.m_avals.m_known_aggs.exists ())
3787 {
3788 unsigned i = 0, j = 0;
3789 while (i < m_avals.m_known_aggs.length ()
3790 || j < ctx.m_avals.m_known_aggs.length ())
3791 {
3792 if (i >= m_avals.m_known_aggs.length ())
3793 {
3794 int idx2 = ctx.m_avals.m_known_aggs[j].index;
3795 if (ipa_is_param_used_by_indirect_call (info: params_summary, i: idx2))
3796 return false;
3797 j++;
3798 continue;
3799 }
3800 if (j >= ctx.m_avals.m_known_aggs.length ())
3801 {
3802 int idx1 = m_avals.m_known_aggs[i].index;
3803 if (ipa_is_param_used_by_indirect_call (info: params_summary, i: idx1))
3804 return false;
3805 i++;
3806 continue;
3807 }
3808
3809 int idx1 = m_avals.m_known_aggs[i].index;
3810 int idx2 = ctx.m_avals.m_known_aggs[j].index;
3811 if (idx1 < idx2)
3812 {
3813 if (ipa_is_param_used_by_indirect_call (info: params_summary, i: idx1))
3814 return false;
3815 i++;
3816 continue;
3817 }
3818 if (idx1 > idx2)
3819 {
3820 if (ipa_is_param_used_by_indirect_call (info: params_summary, i: idx2))
3821 return false;
3822 j++;
3823 continue;
3824 }
3825 if (!ipa_is_param_used_by_indirect_call (info: params_summary, i: idx1))
3826 {
3827 i++;
3828 j++;
3829 continue;
3830 }
3831
3832 if ((m_avals.m_known_aggs[i].unit_offset
3833 != ctx.m_avals.m_known_aggs[j].unit_offset)
3834 || (m_avals.m_known_aggs[i].by_ref
3835 != ctx.m_avals.m_known_aggs[j].by_ref)
3836 || !operand_equal_p (m_avals.m_known_aggs[i].value,
3837 ctx.m_avals.m_known_aggs[j].value))
3838 return false;
3839 i++;
3840 j++;
3841 }
3842 }
3843 return true;
3844}
3845
3846/* Fill in the selected fields in ESTIMATES with value estimated for call in
3847 this context. Always compute size and min_size. Only compute time and
3848 nonspecialized_time if EST_TIMES is true. Only compute hints if EST_HINTS
3849 is true. */
3850
3851void
3852ipa_call_context::estimate_size_and_time (ipa_call_estimates *estimates,
3853 bool est_times, bool est_hints)
3854{
3855 class ipa_fn_summary *info = ipa_fn_summaries->get (node: m_node);
3856 size_time_entry *e;
3857 int size = 0;
3858 sreal time = 0;
3859 int min_size = 0;
3860 ipa_hints hints = 0;
3861 sreal loops_with_known_iterations = 0;
3862 sreal loops_with_known_strides = 0;
3863 int i;
3864
3865 if (dump_file && (dump_flags & TDF_DETAILS))
3866 {
3867 bool found = false;
3868 fprintf (stream: dump_file, format: " Estimating body: %s\n"
3869 " Known to be false: ", m_node->dump_name ());
3870
3871 for (i = ipa_predicate::not_inlined_condition;
3872 i < (ipa_predicate::first_dynamic_condition
3873 + (int) vec_safe_length (v: info->conds)); i++)
3874 if (!(m_possible_truths & (1 << i)))
3875 {
3876 if (found)
3877 fprintf (stream: dump_file, format: ", ");
3878 found = true;
3879 dump_condition (f: dump_file, conditions: info->conds, cond: i);
3880 }
3881 }
3882
3883 if (m_node->callees || m_node->indirect_calls)
3884 estimate_calls_size_and_time (node: m_node, size: &size, min_size: &min_size,
3885 time: est_times ? &time : NULL,
3886 hints: est_hints ? &hints : NULL, possible_truths: m_possible_truths,
3887 avals: &m_avals);
3888
3889 sreal nonspecialized_time = time;
3890
3891 min_size += info->size_time_table[0].size;
3892 for (i = 0; info->size_time_table.iterate (ix: i, ptr: &e); i++)
3893 {
3894 bool exec = e->exec_predicate.evaluate (m_nonspec_possible_truths);
3895
3896 /* Because predicates are conservative, it can happen that nonconst is 1
3897 but exec is 0. */
3898 if (exec)
3899 {
3900 bool nonconst = e->nonconst_predicate.evaluate (m_possible_truths);
3901
3902 gcc_checking_assert (e->time >= 0);
3903 gcc_checking_assert (time >= 0);
3904
3905 /* We compute specialized size only because size of nonspecialized
3906 copy is context independent.
3907
3908 The difference between nonspecialized execution and specialized is
3909 that nonspecialized is not going to have optimized out computations
3910 known to be constant in a specialized setting. */
3911 if (nonconst)
3912 size += e->size;
3913 if (!est_times)
3914 continue;
3915 nonspecialized_time += e->time;
3916 if (!nonconst)
3917 ;
3918 else if (!m_inline_param_summary.exists ())
3919 {
3920 if (nonconst)
3921 time += e->time;
3922 }
3923 else
3924 {
3925 int prob = e->nonconst_predicate.probability
3926 (info->conds, m_possible_truths,
3927 m_inline_param_summary);
3928 gcc_checking_assert (prob >= 0);
3929 gcc_checking_assert (prob <= REG_BR_PROB_BASE);
3930 if (prob == REG_BR_PROB_BASE)
3931 time += e->time;
3932 else
3933 time += e->time * prob / REG_BR_PROB_BASE;
3934 }
3935 gcc_checking_assert (time >= 0);
3936 }
3937 }
3938 gcc_checking_assert (info->size_time_table[0].exec_predicate == true);
3939 gcc_checking_assert (info->size_time_table[0].nonconst_predicate == true);
3940 gcc_checking_assert (min_size >= 0);
3941 gcc_checking_assert (size >= 0);
3942 gcc_checking_assert (time >= 0);
3943 /* nonspecialized_time should be always bigger than specialized time.
3944 Roundoff issues however may get into the way. */
3945 gcc_checking_assert ((nonspecialized_time - time * 99 / 100) >= -1);
3946
3947 /* Roundoff issues may make specialized time bigger than nonspecialized
3948 time. We do not really want that to happen because some heuristics
3949 may get confused by seeing negative speedups. */
3950 if (time > nonspecialized_time)
3951 time = nonspecialized_time;
3952
3953 if (est_hints)
3954 {
3955 if (info->scc_no)
3956 hints |= INLINE_HINT_in_scc;
3957 if (DECL_DECLARED_INLINE_P (m_node->decl))
3958 hints |= INLINE_HINT_declared_inline;
3959 if (info->builtin_constant_p_parms.length ()
3960 && DECL_DECLARED_INLINE_P (m_node->decl))
3961 hints |= INLINE_HINT_builtin_constant_p;
3962
3963 ipa_freqcounting_predicate *fcp;
3964 for (i = 0; vec_safe_iterate (v: info->loop_iterations, ix: i, ptr: &fcp); i++)
3965 if (!fcp->predicate->evaluate (m_possible_truths))
3966 {
3967 hints |= INLINE_HINT_loop_iterations;
3968 loops_with_known_iterations += fcp->freq;
3969 }
3970 estimates->loops_with_known_iterations = loops_with_known_iterations;
3971
3972 for (i = 0; vec_safe_iterate (v: info->loop_strides, ix: i, ptr: &fcp); i++)
3973 if (!fcp->predicate->evaluate (m_possible_truths))
3974 {
3975 hints |= INLINE_HINT_loop_stride;
3976 loops_with_known_strides += fcp->freq;
3977 }
3978 estimates->loops_with_known_strides = loops_with_known_strides;
3979 }
3980
3981 size = RDIV (size, ipa_fn_summary::size_scale);
3982 min_size = RDIV (min_size, ipa_fn_summary::size_scale);
3983
3984 if (dump_file && (dump_flags & TDF_DETAILS))
3985 {
3986 fprintf (stream: dump_file, format: "\n size:%i", (int) size);
3987 if (est_times)
3988 fprintf (stream: dump_file, format: " time:%f nonspec time:%f",
3989 time.to_double (), nonspecialized_time.to_double ());
3990 if (est_hints)
3991 fprintf (stream: dump_file, format: " loops with known iterations:%f "
3992 "known strides:%f", loops_with_known_iterations.to_double (),
3993 loops_with_known_strides.to_double ());
3994 fprintf (stream: dump_file, format: "\n");
3995 }
3996 if (est_times)
3997 {
3998 estimates->time = time;
3999 estimates->nonspecialized_time = nonspecialized_time;
4000 }
4001 estimates->size = size;
4002 estimates->min_size = min_size;
4003 if (est_hints)
4004 estimates->hints = hints;
4005 return;
4006}
4007
4008
4009/* Estimate size and time needed to execute callee of EDGE assuming that
4010 parameters known to be constant at caller of EDGE are propagated.
4011 KNOWN_VALS and KNOWN_CONTEXTS are vectors of assumed known constant values
4012 and types for parameters. */
4013
4014void
4015estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
4016 ipa_auto_call_arg_values *avals,
4017 ipa_call_estimates *estimates)
4018{
4019 clause_t clause, nonspec_clause;
4020
4021 evaluate_conditions_for_known_args (node, inline_p: false, avals, ret_clause: &clause,
4022 ret_nonspec_clause: &nonspec_clause, NULL);
4023 ipa_call_context ctx (node, clause, nonspec_clause, vNULL, avals);
4024 ctx.estimate_size_and_time (estimates);
4025}
4026
4027/* Return stack frame offset where frame of NODE is supposed to start inside
4028 of the function it is inlined to.
4029 Return 0 for functions that are not inlined. */
4030
4031HOST_WIDE_INT
4032ipa_get_stack_frame_offset (struct cgraph_node *node)
4033{
4034 HOST_WIDE_INT offset = 0;
4035 if (!node->inlined_to)
4036 return 0;
4037 node = node->callers->caller;
4038 while (true)
4039 {
4040 offset += ipa_size_summaries->get (node)->estimated_self_stack_size;
4041 if (!node->inlined_to)
4042 return offset;
4043 node = node->callers->caller;
4044 }
4045}
4046
4047
4048/* Update summary information of inline clones after inlining.
4049 Compute peak stack usage. */
4050
4051static void
4052inline_update_callee_summaries (struct cgraph_node *node, int depth)
4053{
4054 struct cgraph_edge *e;
4055
4056 ipa_propagate_frequency (node);
4057 for (e = node->callees; e; e = e->next_callee)
4058 {
4059 if (!e->inline_failed)
4060 inline_update_callee_summaries (node: e->callee, depth);
4061 else
4062 ipa_call_summaries->get (edge: e)->loop_depth += depth;
4063 }
4064 for (e = node->indirect_calls; e; e = e->next_callee)
4065 ipa_call_summaries->get (edge: e)->loop_depth += depth;
4066}
4067
4068/* Update change_prob and points_to_local_or_readonly_memory of EDGE after
4069 INLINED_EDGE has been inlined.
4070
4071 When function A is inlined in B and A calls C with parameter that
4072 changes with probability PROB1 and C is known to be passthrough
4073 of argument if B that change with probability PROB2, the probability
4074 of change is now PROB1*PROB2. */
4075
4076static void
4077remap_edge_params (struct cgraph_edge *inlined_edge,
4078 struct cgraph_edge *edge)
4079{
4080 if (ipa_node_params_sum)
4081 {
4082 int i;
4083 ipa_edge_args *args = ipa_edge_args_sum->get (edge);
4084 if (!args)
4085 return;
4086 class ipa_call_summary *es = ipa_call_summaries->get (edge);
4087 class ipa_call_summary *inlined_es
4088 = ipa_call_summaries->get (edge: inlined_edge);
4089
4090 if (es->param.length () == 0)
4091 return;
4092
4093 for (i = 0; i < ipa_get_cs_argument_count (args); i++)
4094 {
4095 struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, i);
4096 if (jfunc->type == IPA_JF_PASS_THROUGH
4097 || jfunc->type == IPA_JF_ANCESTOR)
4098 {
4099 int id = jfunc->type == IPA_JF_PASS_THROUGH
4100 ? ipa_get_jf_pass_through_formal_id (jfunc)
4101 : ipa_get_jf_ancestor_formal_id (jfunc);
4102 if (id < (int) inlined_es->param.length ())
4103 {
4104 int prob1 = es->param[i].change_prob;
4105 int prob2 = inlined_es->param[id].change_prob;
4106 int prob = combine_probabilities (prob1, prob2);
4107
4108 if (prob1 && prob2 && !prob)
4109 prob = 1;
4110
4111 es->param[i].change_prob = prob;
4112
4113 if (inlined_es
4114 ->param[id].points_to_local_or_readonly_memory)
4115 es->param[i].points_to_local_or_readonly_memory = true;
4116 if (inlined_es
4117 ->param[id].points_to_possible_sra_candidate)
4118 es->param[i].points_to_possible_sra_candidate = true;
4119 }
4120 if (!es->param[i].points_to_local_or_readonly_memory
4121 && jfunc->type == IPA_JF_CONST
4122 && points_to_local_or_readonly_memory_p
4123 (t: ipa_get_jf_constant (jfunc)))
4124 es->param[i].points_to_local_or_readonly_memory = true;
4125 }
4126 }
4127 }
4128}
4129
4130/* Update edge summaries of NODE after INLINED_EDGE has been inlined.
4131
4132 Remap predicates of callees of NODE. Rest of arguments match
4133 remap_predicate.
4134
4135 Also update change probabilities. */
4136
4137static void
4138remap_edge_summaries (struct cgraph_edge *inlined_edge,
4139 struct cgraph_node *node,
4140 class ipa_fn_summary *info,
4141 class ipa_node_params *params_summary,
4142 class ipa_fn_summary *callee_info,
4143 const vec<int> &operand_map,
4144 const vec<HOST_WIDE_INT> &offset_map,
4145 clause_t possible_truths,
4146 ipa_predicate *toplev_predicate)
4147{
4148 struct cgraph_edge *e, *next;
4149 for (e = node->callees; e; e = next)
4150 {
4151 ipa_predicate p;
4152 next = e->next_callee;
4153
4154 if (e->inline_failed)
4155 {
4156 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
4157 remap_edge_params (inlined_edge, edge: e);
4158
4159 if (es->predicate)
4160 {
4161 p = es->predicate->remap_after_inlining
4162 (info, params_summary,
4163 callee_info, operand_map,
4164 offset_map, possible_truths,
4165 *toplev_predicate);
4166 edge_set_predicate (e, predicate: &p);
4167 }
4168 else
4169 edge_set_predicate (e, predicate: toplev_predicate);
4170 }
4171 else
4172 remap_edge_summaries (inlined_edge, node: e->callee, info,
4173 params_summary, callee_info,
4174 operand_map, offset_map, possible_truths,
4175 toplev_predicate);
4176 }
4177 for (e = node->indirect_calls; e; e = next)
4178 {
4179 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
4180 ipa_predicate p;
4181 next = e->next_callee;
4182
4183 remap_edge_params (inlined_edge, edge: e);
4184 if (es->predicate)
4185 {
4186 p = es->predicate->remap_after_inlining
4187 (info, params_summary,
4188 callee_info, operand_map, offset_map,
4189 possible_truths, *toplev_predicate);
4190 edge_set_predicate (e, predicate: &p);
4191 }
4192 else
4193 edge_set_predicate (e, predicate: toplev_predicate);
4194 }
4195}
4196
4197/* Run remap_after_inlining on each predicate in V. */
4198
4199static void
4200remap_freqcounting_predicate (class ipa_fn_summary *info,
4201 class ipa_node_params *params_summary,
4202 class ipa_fn_summary *callee_info,
4203 vec<ipa_freqcounting_predicate, va_gc> *v,
4204 const vec<int> &operand_map,
4205 const vec<HOST_WIDE_INT> &offset_map,
4206 clause_t possible_truths,
4207 ipa_predicate *toplev_predicate)
4208
4209{
4210 ipa_freqcounting_predicate *fcp;
4211 for (int i = 0; vec_safe_iterate (v, ix: i, ptr: &fcp); i++)
4212 {
4213 ipa_predicate p
4214 = fcp->predicate->remap_after_inlining (info, params_summary,
4215 callee_info, operand_map,
4216 offset_map, possible_truths,
4217 *toplev_predicate);
4218 if (p != false && p != true)
4219 *fcp->predicate &= p;
4220 }
4221}
4222
4223/* We inlined EDGE. Update summary of the function we inlined into. */
4224
4225void
4226ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
4227{
4228 ipa_fn_summary *callee_info = ipa_fn_summaries->get (node: edge->callee);
4229 struct cgraph_node *to = (edge->caller->inlined_to
4230 ? edge->caller->inlined_to : edge->caller);
4231 class ipa_fn_summary *info = ipa_fn_summaries->get (node: to);
4232 clause_t clause = 0; /* not_inline is known to be false. */
4233 size_time_entry *e;
4234 auto_vec<int, 8> operand_map;
4235 auto_vec<HOST_WIDE_INT, 8> offset_map;
4236 int i;
4237 ipa_predicate toplev_predicate;
4238 class ipa_call_summary *es = ipa_call_summaries->get (edge);
4239 ipa_node_params *params_summary = (ipa_node_params_sum
4240 ? ipa_node_params_sum->get (node: to) : NULL);
4241
4242 if (es->predicate)
4243 toplev_predicate = *es->predicate;
4244 else
4245 toplev_predicate = true;
4246
4247 info->fp_expressions |= callee_info->fp_expressions;
4248 info->target_info |= callee_info->target_info;
4249
4250 if (callee_info->conds)
4251 {
4252 ipa_auto_call_arg_values avals;
4253 evaluate_properties_for_edge (e: edge, inline_p: true, clause_ptr: &clause, NULL, avals: &avals, compute_contexts: false);
4254 }
4255 if (ipa_node_params_sum && callee_info->conds)
4256 {
4257 ipa_edge_args *args = ipa_edge_args_sum->get (edge);
4258 int count = args ? ipa_get_cs_argument_count (args) : 0;
4259 int i;
4260
4261 if (count)
4262 {
4263 operand_map.safe_grow_cleared (len: count, exact: true);
4264 offset_map.safe_grow_cleared (len: count, exact: true);
4265 }
4266 for (i = 0; i < count; i++)
4267 {
4268 struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, i);
4269 int map = -1;
4270
4271 /* TODO: handle non-NOPs when merging. */
4272 if (jfunc->type == IPA_JF_PASS_THROUGH)
4273 {
4274 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
4275 map = ipa_get_jf_pass_through_formal_id (jfunc);
4276 if (!ipa_get_jf_pass_through_agg_preserved (jfunc))
4277 offset_map[i] = -1;
4278 }
4279 else if (jfunc->type == IPA_JF_ANCESTOR)
4280 {
4281 HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc);
4282 if (offset >= 0 && offset < INT_MAX)
4283 {
4284 map = ipa_get_jf_ancestor_formal_id (jfunc);
4285 if (!ipa_get_jf_ancestor_agg_preserved (jfunc))
4286 offset = -1;
4287 offset_map[i] = offset;
4288 }
4289 }
4290 operand_map[i] = map;
4291 gcc_assert (map < ipa_get_param_count (params_summary));
4292 }
4293
4294 int ip;
4295 for (i = 0; callee_info->builtin_constant_p_parms.iterate (ix: i, ptr: &ip); i++)
4296 if (ip < count && operand_map[ip] >= 0)
4297 add_builtin_constant_p_parm (summary: info, parm: operand_map[ip]);
4298 }
4299 sreal freq = edge->sreal_frequency ();
4300 for (i = 0; callee_info->size_time_table.iterate (ix: i, ptr: &e); i++)
4301 {
4302 ipa_predicate p;
4303 p = e->exec_predicate.remap_after_inlining
4304 (info, params_summary,
4305 callee_info, operand_map,
4306 offset_map, clause,
4307 toplev_predicate);
4308 ipa_predicate nonconstp;
4309 nonconstp = e->nonconst_predicate.remap_after_inlining
4310 (info, params_summary,
4311 callee_info, operand_map,
4312 offset_map, clause,
4313 toplev_predicate);
4314 if (p != false && nonconstp != false)
4315 {
4316 sreal add_time = ((sreal)e->time * freq);
4317 int prob = e->nonconst_predicate.probability (callee_info->conds,
4318 clause, es->param);
4319 if (prob != REG_BR_PROB_BASE)
4320 add_time = add_time * prob / REG_BR_PROB_BASE;
4321 if (prob != REG_BR_PROB_BASE
4322 && dump_file && (dump_flags & TDF_DETAILS))
4323 {
4324 fprintf (stream: dump_file, format: "\t\tScaling time by probability:%f\n",
4325 (double) prob / REG_BR_PROB_BASE);
4326 }
4327 info->account_size_time (size: e->size, time: add_time, exec_pred: p, nonconst_pred_in: nonconstp);
4328 }
4329 }
4330 remap_edge_summaries (inlined_edge: edge, node: edge->callee, info, params_summary,
4331 callee_info, operand_map,
4332 offset_map, possible_truths: clause, toplev_predicate: &toplev_predicate);
4333 remap_freqcounting_predicate (info, params_summary, callee_info,
4334 v: info->loop_iterations, operand_map,
4335 offset_map, possible_truths: clause, toplev_predicate: &toplev_predicate);
4336 remap_freqcounting_predicate (info, params_summary, callee_info,
4337 v: info->loop_strides, operand_map,
4338 offset_map, possible_truths: clause, toplev_predicate: &toplev_predicate);
4339
4340 HOST_WIDE_INT stack_frame_offset = ipa_get_stack_frame_offset (node: edge->callee);
4341 HOST_WIDE_INT peak = stack_frame_offset + callee_info->estimated_stack_size;
4342
4343 if (info->estimated_stack_size < peak)
4344 info->estimated_stack_size = peak;
4345
4346 inline_update_callee_summaries (node: edge->callee, depth: es->loop_depth);
4347 if (info->call_size_time_table.length ())
4348 {
4349 int edge_size = 0;
4350 sreal edge_time = 0;
4351
4352 estimate_edge_size_and_time (e: edge, size: &edge_size, NULL, time: &edge_time, NULL, hints: 0);
4353 /* Unaccount size and time of the optimized out call. */
4354 info->account_size_time (size: -edge_size, time: -edge_time,
4355 exec_pred: es->predicate ? *es->predicate : true,
4356 nonconst_pred_in: es->predicate ? *es->predicate : true,
4357 call: true);
4358 /* Account new calls. */
4359 summarize_calls_size_and_time (node: edge->callee, sum: info);
4360 }
4361
4362 /* Free summaries that are not maintained for inline clones/edges. */
4363 ipa_call_summaries->remove (edge);
4364 ipa_fn_summaries->remove (node: edge->callee);
4365 ipa_remove_from_growth_caches (edge);
4366}
4367
4368/* For performance reasons ipa_merge_fn_summary_after_inlining is not updating
4369 overall size and time. Recompute it.
4370 If RESET is true also recompute call_time_size_table. */
4371
4372void
4373ipa_update_overall_fn_summary (struct cgraph_node *node, bool reset)
4374{
4375 class ipa_fn_summary *info = ipa_fn_summaries->get (node);
4376 class ipa_size_summary *size_info = ipa_size_summaries->get (node);
4377 size_time_entry *e;
4378 int i;
4379
4380 size_info->size = 0;
4381 info->time = 0;
4382 for (i = 0; info->size_time_table.iterate (ix: i, ptr: &e); i++)
4383 {
4384 size_info->size += e->size;
4385 info->time += e->time;
4386 }
4387 info->min_size = info->size_time_table[0].size;
4388 if (reset)
4389 info->call_size_time_table.release ();
4390 if (node->callees || node->indirect_calls)
4391 estimate_calls_size_and_time (node, size: &size_info->size, min_size: &info->min_size,
4392 time: &info->time, NULL,
4393 possible_truths: ~(clause_t) (1 << ipa_predicate::false_condition),
4394 NULL);
4395 size_info->size = RDIV (size_info->size, ipa_fn_summary::size_scale);
4396 info->min_size = RDIV (info->min_size, ipa_fn_summary::size_scale);
4397}
4398
4399
4400/* This function performs intraprocedural analysis in NODE that is required to
4401 inline indirect calls. */
4402
4403static void
4404inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
4405{
4406 ipa_analyze_node (node);
4407 if (dump_file && (dump_flags & TDF_DETAILS))
4408 {
4409 ipa_print_node_params (dump_file, node);
4410 ipa_print_node_jump_functions (f: dump_file, node);
4411 }
4412}
4413
4414
4415/* Note function body size. */
4416
4417void
4418inline_analyze_function (struct cgraph_node *node)
4419{
4420 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
4421
4422 if (dump_file)
4423 fprintf (stream: dump_file, format: "\nAnalyzing function: %s\n", node->dump_name ());
4424 if (opt_for_fn (node->decl, optimize) && !node->thunk)
4425 inline_indirect_intraprocedural_analysis (node);
4426 compute_fn_summary (node, early: false);
4427 if (!optimize)
4428 {
4429 struct cgraph_edge *e;
4430 for (e = node->callees; e; e = e->next_callee)
4431 e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
4432 for (e = node->indirect_calls; e; e = e->next_callee)
4433 e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
4434 }
4435
4436 pop_cfun ();
4437}
4438
4439
4440/* Called when new function is inserted to callgraph late. */
4441
4442void
4443ipa_fn_summary_t::insert (struct cgraph_node *node, ipa_fn_summary *)
4444{
4445 inline_analyze_function (node);
4446}
4447
4448/* Note function body size. */
4449
4450static void
4451ipa_fn_summary_generate (void)
4452{
4453 struct cgraph_node *node;
4454
4455 FOR_EACH_DEFINED_FUNCTION (node)
4456 if (DECL_STRUCT_FUNCTION (node->decl))
4457 node->versionable = tree_versionable_function_p (node->decl);
4458
4459 ipa_fn_summary_alloc ();
4460
4461 ipa_fn_summaries->enable_insertion_hook ();
4462
4463 ipa_register_cgraph_hooks ();
4464
4465 FOR_EACH_DEFINED_FUNCTION (node)
4466 if (!node->alias
4467 && (flag_generate_lto || flag_generate_offload|| flag_wpa
4468 || opt_for_fn (node->decl, optimize)))
4469 inline_analyze_function (node);
4470}
4471
4472
4473/* Write inline summary for edge E to OB. */
4474
4475static void
4476read_ipa_call_summary (class lto_input_block *ib, struct cgraph_edge *e,
4477 bool prevails)
4478{
4479 class ipa_call_summary *es = prevails
4480 ? ipa_call_summaries->get_create (edge: e) : NULL;
4481 ipa_predicate p;
4482 int length, i;
4483
4484 int size = streamer_read_uhwi (ib);
4485 int time = streamer_read_uhwi (ib);
4486 int depth = streamer_read_uhwi (ib);
4487
4488 if (es)
4489 {
4490 es->call_stmt_size = size;
4491 es->call_stmt_time = time;
4492 es->loop_depth = depth;
4493 }
4494
4495 bitpack_d bp = streamer_read_bitpack (ib);
4496 if (es)
4497 es->is_return_callee_uncaptured = bp_unpack_value (bp: &bp, nbits: 1);
4498 else
4499 bp_unpack_value (bp: &bp, nbits: 1);
4500
4501 p.stream_in (ib);
4502 if (es)
4503 edge_set_predicate (e, predicate: &p);
4504 length = streamer_read_uhwi (ib);
4505 if (length && es
4506 && (e->possibly_call_in_translation_unit_p ()
4507 /* Also stream in jump functions to builtins in hope that they
4508 will get fnspecs. */
4509 || fndecl_built_in_p (node: e->callee->decl, klass: BUILT_IN_NORMAL)))
4510 {
4511 es->param.safe_grow_cleared (len: length, exact: true);
4512 for (i = 0; i < length; i++)
4513 {
4514 es->param[i].change_prob = streamer_read_uhwi (ib);
4515 bitpack_d bp = streamer_read_bitpack (ib);
4516 es->param[i].points_to_local_or_readonly_memory
4517 = bp_unpack_value (bp: &bp, nbits: 1);
4518 es->param[i].points_to_possible_sra_candidate
4519 = bp_unpack_value (bp: &bp, nbits: 1);
4520 }
4521 }
4522 else
4523 {
4524 for (i = 0; i < length; i++)
4525 {
4526 streamer_read_uhwi (ib);
4527 streamer_read_uhwi (ib);
4528 }
4529 }
4530}
4531
4532
4533/* Stream in inline summaries from the section. */
4534
4535static void
4536inline_read_section (struct lto_file_decl_data *file_data, const char *data,
4537 size_t len)
4538{
4539 const struct lto_function_header *header =
4540 (const struct lto_function_header *) data;
4541 const int cfg_offset = sizeof (struct lto_function_header);
4542 const int main_offset = cfg_offset + header->cfg_size;
4543 const int string_offset = main_offset + header->main_size;
4544 class data_in *data_in;
4545 unsigned int i, count2, j;
4546 unsigned int f_count;
4547
4548 lto_input_block ib ((const char *) data + main_offset, header->main_size,
4549 file_data);
4550
4551 data_in =
4552 lto_data_in_create (file_data, (const char *) data + string_offset,
4553 header->string_size, vNULL);
4554 f_count = streamer_read_uhwi (&ib);
4555 for (i = 0; i < f_count; i++)
4556 {
4557 unsigned int index;
4558 struct cgraph_node *node;
4559 class ipa_fn_summary *info;
4560 class ipa_node_params *params_summary;
4561 class ipa_size_summary *size_info;
4562 lto_symtab_encoder_t encoder;
4563 struct bitpack_d bp;
4564 struct cgraph_edge *e;
4565 ipa_predicate p;
4566
4567 index = streamer_read_uhwi (&ib);
4568 encoder = file_data->symtab_node_encoder;
4569 node = dyn_cast<cgraph_node *> (p: lto_symtab_encoder_deref (encoder,
4570 ref: index));
4571 info = node->prevailing_p () ? ipa_fn_summaries->get_create (node) : NULL;
4572 params_summary = node->prevailing_p ()
4573 ? ipa_node_params_sum->get (node) : NULL;
4574 size_info = node->prevailing_p ()
4575 ? ipa_size_summaries->get_create (node) : NULL;
4576
4577 int stack_size = streamer_read_uhwi (&ib);
4578 int size = streamer_read_uhwi (&ib);
4579 sreal time = sreal::stream_in (&ib);
4580
4581 if (info)
4582 {
4583 info->estimated_stack_size
4584 = size_info->estimated_self_stack_size = stack_size;
4585 size_info->size = size_info->self_size = size;
4586 info->time = time;
4587 }
4588
4589 bp = streamer_read_bitpack (ib: &ib);
4590 if (info)
4591 {
4592 info->inlinable = bp_unpack_value (bp: &bp, nbits: 1);
4593 info->fp_expressions = bp_unpack_value (bp: &bp, nbits: 1);
4594 if (!lto_stream_offload_p)
4595 info->target_info = streamer_read_uhwi (&ib);
4596 }
4597 else
4598 {
4599 bp_unpack_value (bp: &bp, nbits: 1);
4600 bp_unpack_value (bp: &bp, nbits: 1);
4601 if (!lto_stream_offload_p)
4602 streamer_read_uhwi (&ib);
4603 }
4604
4605 count2 = streamer_read_uhwi (&ib);
4606 gcc_assert (!info || !info->conds);
4607 if (info)
4608 vec_safe_reserve_exact (v&: info->conds, nelems: count2);
4609 for (j = 0; j < count2; j++)
4610 {
4611 struct condition c;
4612 unsigned int k, count3;
4613 c.operand_num = streamer_read_uhwi (&ib);
4614 c.code = (enum tree_code) streamer_read_uhwi (&ib);
4615 c.type = stream_read_tree (&ib, data_in);
4616 c.val = stream_read_tree (&ib, data_in);
4617 bp = streamer_read_bitpack (ib: &ib);
4618 c.agg_contents = bp_unpack_value (bp: &bp, nbits: 1);
4619 c.by_ref = bp_unpack_value (bp: &bp, nbits: 1);
4620 if (c.agg_contents)
4621 c.offset = streamer_read_uhwi (&ib);
4622 count3 = streamer_read_uhwi (&ib);
4623 c.param_ops = NULL;
4624 if (info)
4625 vec_safe_reserve_exact (v&: c.param_ops, nelems: count3);
4626 if (params_summary)
4627 ipa_set_param_used_by_ipa_predicates
4628 (info: params_summary, i: c.operand_num, val: true);
4629 for (k = 0; k < count3; k++)
4630 {
4631 struct expr_eval_op op;
4632 enum gimple_rhs_class rhs_class;
4633 op.code = (enum tree_code) streamer_read_uhwi (&ib);
4634 op.type = stream_read_tree (&ib, data_in);
4635 switch (rhs_class = get_gimple_rhs_class (code: op.code))
4636 {
4637 case GIMPLE_UNARY_RHS:
4638 op.index = 0;
4639 op.val[0] = NULL_TREE;
4640 op.val[1] = NULL_TREE;
4641 break;
4642
4643 case GIMPLE_BINARY_RHS:
4644 case GIMPLE_TERNARY_RHS:
4645 bp = streamer_read_bitpack (ib: &ib);
4646 op.index = bp_unpack_value (bp: &bp, nbits: 2);
4647 op.val[0] = stream_read_tree (&ib, data_in);
4648 if (rhs_class == GIMPLE_BINARY_RHS)
4649 op.val[1] = NULL_TREE;
4650 else
4651 op.val[1] = stream_read_tree (&ib, data_in);
4652 break;
4653
4654 default:
4655 fatal_error (UNKNOWN_LOCATION,
4656 "invalid fnsummary in LTO stream");
4657 }
4658 if (info)
4659 c.param_ops->quick_push (obj: op);
4660 }
4661 if (info)
4662 info->conds->quick_push (obj: c);
4663 }
4664 count2 = streamer_read_uhwi (&ib);
4665 gcc_assert (!info || !info->size_time_table.length ());
4666 if (info && count2)
4667 info->size_time_table.reserve_exact (nelems: count2);
4668 for (j = 0; j < count2; j++)
4669 {
4670 class size_time_entry e;
4671
4672 e.size = streamer_read_uhwi (&ib);
4673 e.time = sreal::stream_in (&ib);
4674 e.exec_predicate.stream_in (&ib);
4675 e.nonconst_predicate.stream_in (&ib);
4676
4677 if (info)
4678 info->size_time_table.quick_push (obj: e);
4679 }
4680
4681 count2 = streamer_read_uhwi (&ib);
4682 for (j = 0; j < count2; j++)
4683 {
4684 p.stream_in (&ib);
4685 sreal fcp_freq = sreal::stream_in (&ib);
4686 if (info)
4687 {
4688 ipa_freqcounting_predicate fcp;
4689 fcp.predicate = NULL;
4690 set_hint_predicate (p: &fcp.predicate, new_predicate: p);
4691 fcp.freq = fcp_freq;
4692 vec_safe_push (v&: info->loop_iterations, obj: fcp);
4693 }
4694 }
4695 count2 = streamer_read_uhwi (&ib);
4696 for (j = 0; j < count2; j++)
4697 {
4698 p.stream_in (&ib);
4699 sreal fcp_freq = sreal::stream_in (&ib);
4700 if (info)
4701 {
4702 ipa_freqcounting_predicate fcp;
4703 fcp.predicate = NULL;
4704 set_hint_predicate (p: &fcp.predicate, new_predicate: p);
4705 fcp.freq = fcp_freq;
4706 vec_safe_push (v&: info->loop_strides, obj: fcp);
4707 }
4708 }
4709 count2 = streamer_read_uhwi (&ib);
4710 if (info && count2)
4711 info->builtin_constant_p_parms.reserve_exact (nelems: count2);
4712 for (j = 0; j < count2; j++)
4713 {
4714 int parm = streamer_read_uhwi (&ib);
4715 if (info)
4716 info->builtin_constant_p_parms.quick_push (obj: parm);
4717 }
4718 for (e = node->callees; e; e = e->next_callee)
4719 read_ipa_call_summary (ib: &ib, e, prevails: info != NULL);
4720 for (e = node->indirect_calls; e; e = e->next_callee)
4721 read_ipa_call_summary (ib: &ib, e, prevails: info != NULL);
4722 }
4723
4724 lto_free_section_data (file_data, LTO_section_ipa_fn_summary, NULL, data,
4725 len);
4726 lto_data_in_delete (data_in);
4727}
4728
4729
4730/* Read inline summary. Jump functions are shared among ipa-cp
4731 and inliner, so when ipa-cp is active, we don't need to write them
4732 twice. */
4733
4734static void
4735ipa_fn_summary_read (void)
4736{
4737 struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
4738 struct lto_file_decl_data *file_data;
4739 unsigned int j = 0;
4740
4741 ipa_prop_read_jump_functions ();
4742 ipa_fn_summary_alloc ();
4743
4744 while ((file_data = file_data_vec[j++]))
4745 {
4746 size_t len;
4747 const char *data
4748 = lto_get_summary_section_data (file_data, LTO_section_ipa_fn_summary,
4749 &len);
4750 if (data)
4751 inline_read_section (file_data, data, len);
4752 else
4753 /* Fatal error here. We do not want to support compiling ltrans units
4754 with different version of compiler or different flags than the WPA
4755 unit, so this should never happen. */
4756 fatal_error (input_location,
4757 "ipa inline summary is missing in input file");
4758 }
4759 ipa_register_cgraph_hooks ();
4760
4761 gcc_assert (ipa_fn_summaries);
4762 ipa_fn_summaries->enable_insertion_hook ();
4763}
4764
4765
4766/* Write inline summary for edge E to OB. */
4767
4768static void
4769write_ipa_call_summary (struct output_block *ob, struct cgraph_edge *e)
4770{
4771 class ipa_call_summary *es = ipa_call_summaries->get (edge: e);
4772 int i;
4773
4774 streamer_write_uhwi (ob, es->call_stmt_size);
4775 streamer_write_uhwi (ob, es->call_stmt_time);
4776 streamer_write_uhwi (ob, es->loop_depth);
4777
4778 bitpack_d bp = bitpack_create (s: ob->main_stream);
4779 bp_pack_value (bp: &bp, val: es->is_return_callee_uncaptured, nbits: 1);
4780 streamer_write_bitpack (bp: &bp);
4781
4782 if (es->predicate)
4783 es->predicate->stream_out (ob);
4784 else
4785 streamer_write_uhwi (ob, 0);
4786 streamer_write_uhwi (ob, es->param.length ());
4787 for (i = 0; i < (int) es->param.length (); i++)
4788 {
4789 streamer_write_uhwi (ob, es->param[i].change_prob);
4790 bp = bitpack_create (s: ob->main_stream);
4791 bp_pack_value (bp: &bp, val: es->param[i].points_to_local_or_readonly_memory, nbits: 1);
4792 bp_pack_value (bp: &bp, val: es->param[i].points_to_possible_sra_candidate, nbits: 1);
4793 streamer_write_bitpack (bp: &bp);
4794 }
4795}
4796
4797
4798/* Write inline summary for node in SET.
4799 Jump functions are shared among ipa-cp and inliner, so when ipa-cp is
4800 active, we don't need to write them twice. */
4801
4802static void
4803ipa_fn_summary_write (void)
4804{
4805 struct output_block *ob = create_output_block (LTO_section_ipa_fn_summary);
4806 lto_symtab_encoder_iterator lsei;
4807 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
4808 unsigned int count = 0;
4809
4810 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
4811 lsei_next_function_in_partition (lsei: &lsei))
4812 {
4813 cgraph_node *cnode = lsei_cgraph_node (lsei);
4814 if (cnode->definition && !cnode->alias)
4815 count++;
4816 }
4817 streamer_write_uhwi (ob, count);
4818
4819 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
4820 lsei_next_function_in_partition (lsei: &lsei))
4821 {
4822 cgraph_node *cnode = lsei_cgraph_node (lsei);
4823 if (cnode->definition && !cnode->alias)
4824 {
4825 class ipa_fn_summary *info = ipa_fn_summaries->get (node: cnode);
4826 class ipa_size_summary *size_info = ipa_size_summaries->get (node: cnode);
4827 struct bitpack_d bp;
4828 struct cgraph_edge *edge;
4829 int i;
4830 size_time_entry *e;
4831 struct condition *c;
4832
4833 streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder, cnode));
4834 streamer_write_hwi (ob, size_info->estimated_self_stack_size);
4835 streamer_write_hwi (ob, size_info->self_size);
4836 info->time.stream_out (ob);
4837 bp = bitpack_create (s: ob->main_stream);
4838 bp_pack_value (bp: &bp, val: info->inlinable, nbits: 1);
4839 bp_pack_value (bp: &bp, val: info->fp_expressions, nbits: 1);
4840 streamer_write_bitpack (bp: &bp);
4841 if (!lto_stream_offload_p)
4842 streamer_write_uhwi (ob, info->target_info);
4843 streamer_write_uhwi (ob, vec_safe_length (v: info->conds));
4844 for (i = 0; vec_safe_iterate (v: info->conds, ix: i, ptr: &c); i++)
4845 {
4846 int j;
4847 struct expr_eval_op *op;
4848
4849 streamer_write_uhwi (ob, c->operand_num);
4850 streamer_write_uhwi (ob, c->code);
4851 stream_write_tree (ob, c->type, true);
4852 stream_write_tree (ob, c->val, true);
4853 bp = bitpack_create (s: ob->main_stream);
4854 bp_pack_value (bp: &bp, val: c->agg_contents, nbits: 1);
4855 bp_pack_value (bp: &bp, val: c->by_ref, nbits: 1);
4856 streamer_write_bitpack (bp: &bp);
4857 if (c->agg_contents)
4858 streamer_write_uhwi (ob, c->offset);
4859 streamer_write_uhwi (ob, vec_safe_length (v: c->param_ops));
4860 for (j = 0; vec_safe_iterate (v: c->param_ops, ix: j, ptr: &op); j++)
4861 {
4862 streamer_write_uhwi (ob, op->code);
4863 stream_write_tree (ob, op->type, true);
4864 if (op->val[0])
4865 {
4866 bp = bitpack_create (s: ob->main_stream);
4867 bp_pack_value (bp: &bp, val: op->index, nbits: 2);
4868 streamer_write_bitpack (bp: &bp);
4869 stream_write_tree (ob, op->val[0], true);
4870 if (op->val[1])
4871 stream_write_tree (ob, op->val[1], true);
4872 }
4873 }
4874 }
4875 streamer_write_uhwi (ob, info->size_time_table.length ());
4876 for (i = 0; info->size_time_table.iterate (ix: i, ptr: &e); i++)
4877 {
4878 streamer_write_uhwi (ob, e->size);
4879 e->time.stream_out (ob);
4880 e->exec_predicate.stream_out (ob);
4881 e->nonconst_predicate.stream_out (ob);
4882 }
4883 ipa_freqcounting_predicate *fcp;
4884 streamer_write_uhwi (ob, vec_safe_length (v: info->loop_iterations));
4885 for (i = 0; vec_safe_iterate (v: info->loop_iterations, ix: i, ptr: &fcp); i++)
4886 {
4887 fcp->predicate->stream_out (ob);
4888 fcp->freq.stream_out (ob);
4889 }
4890 streamer_write_uhwi (ob, vec_safe_length (v: info->loop_strides));
4891 for (i = 0; vec_safe_iterate (v: info->loop_strides, ix: i, ptr: &fcp); i++)
4892 {
4893 fcp->predicate->stream_out (ob);
4894 fcp->freq.stream_out (ob);
4895 }
4896 streamer_write_uhwi (ob, info->builtin_constant_p_parms.length ());
4897 int ip;
4898 for (i = 0; info->builtin_constant_p_parms.iterate (ix: i, ptr: &ip);
4899 i++)
4900 streamer_write_uhwi (ob, ip);
4901 for (edge = cnode->callees; edge; edge = edge->next_callee)
4902 write_ipa_call_summary (ob, e: edge);
4903 for (edge = cnode->indirect_calls; edge; edge = edge->next_callee)
4904 write_ipa_call_summary (ob, e: edge);
4905 }
4906 }
4907 streamer_write_char_stream (obs: ob->main_stream, c: 0);
4908 produce_asm (ob, NULL);
4909 destroy_output_block (ob);
4910
4911 ipa_prop_write_jump_functions ();
4912}
4913
4914
4915/* Release function summary. */
4916
4917void
4918ipa_free_fn_summary (void)
4919{
4920 if (!ipa_call_summaries)
4921 return;
4922 ggc_delete (ptr: ipa_fn_summaries);
4923 ipa_fn_summaries = NULL;
4924 delete ipa_call_summaries;
4925 ipa_call_summaries = NULL;
4926 edge_predicate_pool.release ();
4927 /* During IPA this is one of largest datastructures to release. */
4928 if (flag_wpa)
4929 ggc_trim ();
4930}
4931
4932/* Release function summary. */
4933
4934void
4935ipa_free_size_summary (void)
4936{
4937 if (!ipa_size_summaries)
4938 return;
4939 delete ipa_size_summaries;
4940 ipa_size_summaries = NULL;
4941}
4942
4943namespace {
4944
4945const pass_data pass_data_local_fn_summary =
4946{
4947 .type: GIMPLE_PASS, /* type */
4948 .name: "local-fnsummary", /* name */
4949 .optinfo_flags: OPTGROUP_INLINE, /* optinfo_flags */
4950 .tv_id: TV_INLINE_PARAMETERS, /* tv_id */
4951 .properties_required: 0, /* properties_required */
4952 .properties_provided: 0, /* properties_provided */
4953 .properties_destroyed: 0, /* properties_destroyed */
4954 .todo_flags_start: 0, /* todo_flags_start */
4955 .todo_flags_finish: 0, /* todo_flags_finish */
4956};
4957
4958class pass_local_fn_summary : public gimple_opt_pass
4959{
4960public:
4961 pass_local_fn_summary (gcc::context *ctxt)
4962 : gimple_opt_pass (pass_data_local_fn_summary, ctxt)
4963 {}
4964
4965 /* opt_pass methods: */
4966 opt_pass * clone () final override
4967 {
4968 return new pass_local_fn_summary (m_ctxt);
4969 }
4970 unsigned int execute (function *) final override
4971 {
4972 return compute_fn_summary_for_current ();
4973 }
4974
4975}; // class pass_local_fn_summary
4976
4977} // anon namespace
4978
4979gimple_opt_pass *
4980make_pass_local_fn_summary (gcc::context *ctxt)
4981{
4982 return new pass_local_fn_summary (ctxt);
4983}
4984
4985
4986/* Free inline summary. */
4987
4988namespace {
4989
4990const pass_data pass_data_ipa_free_fn_summary =
4991{
4992 .type: SIMPLE_IPA_PASS, /* type */
4993 .name: "free-fnsummary", /* name */
4994 .optinfo_flags: OPTGROUP_NONE, /* optinfo_flags */
4995 .tv_id: TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */
4996 .properties_required: 0, /* properties_required */
4997 .properties_provided: 0, /* properties_provided */
4998 .properties_destroyed: 0, /* properties_destroyed */
4999 .todo_flags_start: 0, /* todo_flags_start */
5000 .todo_flags_finish: 0, /* todo_flags_finish */
5001};
5002
5003class pass_ipa_free_fn_summary : public simple_ipa_opt_pass
5004{
5005public:
5006 pass_ipa_free_fn_summary (gcc::context *ctxt)
5007 : simple_ipa_opt_pass (pass_data_ipa_free_fn_summary, ctxt),
5008 small_p (false)
5009 {}
5010
5011 /* opt_pass methods: */
5012 opt_pass *clone () final override
5013 {
5014 return new pass_ipa_free_fn_summary (m_ctxt);
5015 }
5016 void set_pass_param (unsigned int n, bool param) final override
5017 {
5018 gcc_assert (n == 0);
5019 small_p = param;
5020 }
5021 bool gate (function *) final override { return true; }
5022 unsigned int execute (function *) final override
5023 {
5024 ipa_free_fn_summary ();
5025 /* Free ipa-prop structures if they are no longer needed. */
5026 ipa_free_all_structures_after_iinln ();
5027 if (!flag_wpa)
5028 ipa_free_size_summary ();
5029 return 0;
5030 }
5031
5032private:
5033 bool small_p;
5034}; // class pass_ipa_free_fn_summary
5035
5036} // anon namespace
5037
5038simple_ipa_opt_pass *
5039make_pass_ipa_free_fn_summary (gcc::context *ctxt)
5040{
5041 return new pass_ipa_free_fn_summary (ctxt);
5042}
5043
5044namespace {
5045
5046const pass_data pass_data_ipa_fn_summary =
5047{
5048 .type: IPA_PASS, /* type */
5049 .name: "fnsummary", /* name */
5050 .optinfo_flags: OPTGROUP_INLINE, /* optinfo_flags */
5051 .tv_id: TV_IPA_FNSUMMARY, /* tv_id */
5052 .properties_required: 0, /* properties_required */
5053 .properties_provided: 0, /* properties_provided */
5054 .properties_destroyed: 0, /* properties_destroyed */
5055 .todo_flags_start: 0, /* todo_flags_start */
5056 .todo_flags_finish: ( TODO_dump_symtab ), /* todo_flags_finish */
5057};
5058
5059class pass_ipa_fn_summary : public ipa_opt_pass_d
5060{
5061public:
5062 pass_ipa_fn_summary (gcc::context *ctxt)
5063 : ipa_opt_pass_d (pass_data_ipa_fn_summary, ctxt,
5064 ipa_fn_summary_generate, /* generate_summary */
5065 ipa_fn_summary_write, /* write_summary */
5066 ipa_fn_summary_read, /* read_summary */
5067 NULL, /* write_optimization_summary */
5068 NULL, /* read_optimization_summary */
5069 NULL, /* stmt_fixup */
5070 0, /* function_transform_todo_flags_start */
5071 NULL, /* function_transform */
5072 NULL) /* variable_transform */
5073 {}
5074
5075 /* opt_pass methods: */
5076 unsigned int execute (function *) final override { return 0; }
5077
5078}; // class pass_ipa_fn_summary
5079
5080} // anon namespace
5081
5082ipa_opt_pass_d *
5083make_pass_ipa_fn_summary (gcc::context *ctxt)
5084{
5085 return new pass_ipa_fn_summary (ctxt);
5086}
5087
5088/* Reset all state within ipa-fnsummary.cc so that we can rerun the compiler
5089 within the same process. For use by toplev::finalize. */
5090
5091void
5092ipa_fnsummary_cc_finalize (void)
5093{
5094 ipa_free_fn_summary ();
5095 ipa_free_size_summary ();
5096}
5097

source code of gcc/ipa-fnsummary.cc