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