Branch data Line data Source code
1 : : /* Top level of GCC compilers (cc1, cc1plus, etc.)
2 : : Copyright (C) 1987-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : /* This is the top level of cc1/c++.
21 : : It parses command args, opens files, invokes the various passes
22 : : in the proper order, and counts the time used by each.
23 : : Error messages and low-level interface to malloc also handled here. */
24 : :
25 : : #include "config.h"
26 : : #include "system.h"
27 : : #include "coretypes.h"
28 : : #include "backend.h"
29 : : #include "target.h"
30 : : #include "rtl.h"
31 : : #include "tree.h"
32 : : #include "gimple.h"
33 : : #include "cfghooks.h"
34 : : #include "df.h"
35 : : #include "memmodel.h"
36 : : #include "tm_p.h"
37 : : #include "ssa.h"
38 : : #include "emit-rtl.h"
39 : : #include "cgraph.h"
40 : : #include "lto-streamer.h"
41 : : #include "fold-const.h"
42 : : #include "varasm.h"
43 : : #include "output.h"
44 : : #include "graph.h"
45 : : #include "debug.h"
46 : : #include "cfgloop.h"
47 : : #include "value-prof.h"
48 : : #include "tree-cfg.h"
49 : : #include "tree-ssa-loop-manip.h"
50 : : #include "tree-into-ssa.h"
51 : : #include "tree-dfa.h"
52 : : #include "tree-ssa.h"
53 : : #include "tree-pass.h"
54 : : #include "plugin.h"
55 : : #include "ipa-utils.h"
56 : : #include "tree-pretty-print.h" /* for dump_function_header */
57 : : #include "context.h"
58 : : #include "pass_manager.h"
59 : : #include "cfgrtl.h"
60 : : #include "tree-ssa-live.h" /* For remove_unused_locals. */
61 : : #include "tree-cfgcleanup.h"
62 : : #include "insn-addr.h" /* for INSN_ADDRESSES_ALLOC. */
63 : : #include "diagnostic-core.h" /* for fnotice */
64 : : #include "stringpool.h"
65 : : #include "attribs.h"
66 : :
67 : : using namespace gcc;
68 : :
69 : : /* This is used for debugging. It allows the current pass to printed
70 : : from anywhere in compilation.
71 : : The variable current_pass is also used for statistics and plugins. */
72 : : opt_pass *current_pass;
73 : :
74 : : /* Most passes are single-instance (within their context) and thus don't
75 : : need to implement cloning, but passes that support multiple instances
76 : : *must* provide their own implementation of the clone method.
77 : :
78 : : Handle this by providing a default implemenation, but make it a fatal
79 : : error to call it. */
80 : :
81 : : opt_pass *
82 : 0 : opt_pass::clone ()
83 : : {
84 : 0 : internal_error ("pass %s does not support cloning", name);
85 : : }
86 : :
87 : : void
88 : 0 : opt_pass::set_pass_param (unsigned int, bool)
89 : : {
90 : 0 : internal_error ("pass %s needs a %<set_pass_param%> implementation "
91 : : "to handle the extra argument in %<NEXT_PASS%>", name);
92 : : }
93 : :
94 : : bool
95 : 100858975 : opt_pass::gate (function *)
96 : : {
97 : 100858975 : return true;
98 : : }
99 : :
100 : : unsigned int
101 : 14227057 : opt_pass::execute (function *)
102 : : {
103 : 14227057 : return 0;
104 : : }
105 : :
106 : 105731741 : opt_pass::opt_pass (const pass_data &data, context *ctxt)
107 : : : pass_data (data),
108 : 105731741 : sub (NULL),
109 : 105731741 : next (NULL),
110 : 105731741 : static_pass_number (0),
111 : 105731741 : m_ctxt (ctxt)
112 : : {
113 : 105731741 : }
114 : :
115 : :
116 : : void
117 : 4893 : pass_manager::execute_early_local_passes ()
118 : : {
119 : 4893 : execute_pass_list (cfun, pass_build_ssa_passes_1->sub);
120 : 4893 : execute_pass_list (cfun, pass_local_optimization_passes_1->sub);
121 : 4893 : }
122 : :
123 : : unsigned int
124 : 65746 : pass_manager::execute_pass_mode_switching ()
125 : : {
126 : 65746 : return pass_mode_switching_1->execute (cfun);
127 : : }
128 : :
129 : :
130 : : /* Call from anywhere to find out what pass this is. Useful for
131 : : printing out debugging information deep inside an service
132 : : routine. */
133 : : void
134 : 0 : print_current_pass (FILE *file)
135 : : {
136 : 0 : if (current_pass)
137 : 0 : fprintf (file, "current pass = %s (%d)\n",
138 : : current_pass->name, current_pass->static_pass_number);
139 : : else
140 : 0 : fprintf (file, "no current pass.\n");
141 : 0 : }
142 : :
143 : :
144 : : /* Call from the debugger to get the current pass name. */
145 : : DEBUG_FUNCTION void
146 : 0 : debug_pass (void)
147 : : {
148 : 0 : print_current_pass (stderr);
149 : 0 : }
150 : :
151 : :
152 : :
153 : : /* Global variables used to communicate with passes. */
154 : : bool in_gimple_form;
155 : :
156 : :
157 : : /* This is called from various places for FUNCTION_DECL, VAR_DECL,
158 : : and TYPE_DECL nodes.
159 : :
160 : : This does nothing for local (non-static) variables, unless the
161 : : variable is a register variable with DECL_ASSEMBLER_NAME set. In
162 : : that case, or if the variable is not an automatic, it sets up the
163 : : RTL and outputs any assembler code (label definition, storage
164 : : allocation and initialization).
165 : :
166 : : DECL is the declaration. TOP_LEVEL is nonzero
167 : : if this declaration is not within a function. */
168 : :
169 : : void
170 : 339485095 : rest_of_decl_compilation (tree decl,
171 : : int top_level,
172 : : int at_end)
173 : : {
174 : 339485095 : bool finalize = true;
175 : :
176 : : /* We deferred calling assemble_alias so that we could collect
177 : : other attributes such as visibility. Emit the alias now. */
178 : 339485095 : if (!in_lto_p)
179 : : {
180 : 339284724 : tree alias;
181 : 339284724 : alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
182 : 339284724 : if (alias)
183 : : {
184 : 9590 : alias = TREE_VALUE (TREE_VALUE (alias));
185 : 9590 : alias = get_identifier (TREE_STRING_POINTER (alias));
186 : : /* A quirk of the initial implementation of aliases required that the
187 : : user add "extern" to all of them. Which is silly, but now
188 : : historical. Do note that the symbol is in fact locally defined. */
189 : 9590 : DECL_EXTERNAL (decl) = 0;
190 : 9590 : TREE_STATIC (decl) = 1;
191 : 9590 : assemble_alias (decl, alias);
192 : 9590 : finalize = false;
193 : : }
194 : : }
195 : :
196 : : /* Can't defer this, because it needs to happen before any
197 : : later function definitions are processed. */
198 : 339485095 : if (HAS_DECL_ASSEMBLER_NAME_P (decl)
199 : 339485095 : && DECL_ASSEMBLER_NAME_SET_P (decl)
200 : 364751640 : && DECL_REGISTER (decl))
201 : 1281 : make_decl_rtl (decl);
202 : :
203 : : /* Forward declarations for nested functions are not "external",
204 : : but we need to treat them as if they were. */
205 : 320133285 : if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
206 : 353052507 : || TREE_CODE (decl) == FUNCTION_DECL)
207 : : {
208 : 325993845 : timevar_push (TV_VARCONST);
209 : :
210 : : /* Don't output anything when a tentative file-scope definition
211 : : is seen. But at end of compilation, do output code for them.
212 : :
213 : : We do output all variables and rely on
214 : : callgraph code to defer them except for forward declarations
215 : : (see gcc.c-torture/compile/920624-1.c) */
216 : 325993845 : if ((at_end
217 : 183811447 : || !DECL_DEFER_OUTPUT (decl)
218 : 13416467 : || DECL_INITIAL (decl))
219 : 312593153 : && (!VAR_P (decl) || !DECL_HAS_VALUE_EXPR_P (decl))
220 : 638586324 : && !DECL_EXTERNAL (decl))
221 : : {
222 : : /* When reading LTO unit, we also read varpool, so do not
223 : : rebuild it. */
224 : 15825069 : if (in_lto_p && !at_end)
225 : : ;
226 : 15625240 : else if (finalize && TREE_CODE (decl) != FUNCTION_DECL)
227 : 15175239 : varpool_node::finalize_decl (decl);
228 : : }
229 : :
230 : : #ifdef ASM_FINISH_DECLARE_OBJECT
231 : 325993845 : if (decl == last_assemble_variable_decl)
232 : : {
233 : 0 : ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
234 : : top_level, at_end);
235 : : }
236 : : #endif
237 : :
238 : : /* Now that we have activated any function-specific attributes
239 : : that might affect function decl, particularly align, relayout it. */
240 : 325993845 : if (TREE_CODE (decl) == FUNCTION_DECL)
241 : 305941662 : targetm.target_option.relayout_function (decl);
242 : :
243 : 325993845 : timevar_pop (TV_VARCONST);
244 : : }
245 : 13491250 : else if (TREE_CODE (decl) == TYPE_DECL
246 : : /* Like in rest_of_type_compilation, avoid confusing the debug
247 : : information machinery when there are errors. */
248 : 13491250 : && !seen_error ())
249 : : {
250 : 13377399 : timevar_push (TV_SYMOUT);
251 : 13377399 : debug_hooks->type_decl (decl, !top_level);
252 : 13377399 : timevar_pop (TV_SYMOUT);
253 : : }
254 : :
255 : : /* Let cgraph know about the existence of variables. */
256 : 339485095 : if (in_lto_p && !at_end)
257 : : ;
258 : 19464322 : else if (VAR_P (decl) && !DECL_EXTERNAL (decl)
259 : 355279384 : && TREE_STATIC (decl))
260 : 15993620 : varpool_node::get_create (decl);
261 : :
262 : : /* Generate early debug for global variables. Any local variables will
263 : : be handled by either handling reachable functions from
264 : : finalize_compilation_unit (and by consequence, locally scoped
265 : : symbols), or by rest_of_type_compilation below.
266 : :
267 : : For Go's hijack of the debug_hooks to implement -fdump-go-spec, pick up
268 : : function prototypes. Go's debug_hooks will not forward them to the
269 : : wrapped hooks. */
270 : 339485095 : if (!in_lto_p
271 : 339284724 : && (TREE_CODE (decl) != FUNCTION_DECL
272 : : /* This will pick up function prototypes with no bodies,
273 : : which are not visible in finalize_compilation_unit()
274 : : while iterating with FOR_EACH_*_FUNCTION through the
275 : : symbol table. */
276 : 305811686 : || (flag_dump_go_spec != NULL
277 : 1876 : && !DECL_SAVED_TREE (decl)
278 : 1876 : && DECL_STRUCT_FUNCTION (decl) == NULL))
279 : :
280 : : /* We need to check both decl_function_context and
281 : : current_function_decl here to make sure local extern
282 : : declarations end up with the correct context.
283 : :
284 : : For local extern declarations, decl_function_context is
285 : : empty, but current_function_decl is set to the function where
286 : : the extern was declared . Without the check for
287 : : !current_function_decl below, the local extern ends up
288 : : incorrectly with a top-level context.
289 : :
290 : : For example:
291 : :
292 : : namespace S
293 : : {
294 : : int
295 : : f()
296 : : {
297 : : {
298 : : int i = 42;
299 : : {
300 : : extern int i; // Local extern declaration.
301 : : return i;
302 : : }
303 : : }
304 : : }
305 : : }
306 : : */
307 : 33474914 : && !decl_function_context (decl)
308 : 31404745 : && !current_function_decl
309 : 31354449 : && DECL_SOURCE_LOCATION (decl) != BUILTINS_LOCATION
310 : 28737864 : && (!decl_type_context (decl)
311 : : /* If we created a varpool node for the decl make sure to
312 : : call early_global_decl. Otherwise we miss changes
313 : : introduced by member definitions like
314 : : struct A { static int staticdatamember; };
315 : : int A::staticdatamember;
316 : : and thus have incomplete early debug and late debug
317 : : called from varpool node removal fails to handle it
318 : : properly. */
319 : 9513621 : || (finalize
320 : : && VAR_P (decl)
321 : 9513617 : && TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
322 : : /* Avoid confusing the debug information machinery when there are
323 : : errors. */
324 : 366037696 : && !seen_error ())
325 : 26209745 : (*debug_hooks->early_global_decl) (decl);
326 : 339485095 : }
327 : :
328 : : /* Called after finishing a record, union or enumeral type. */
329 : :
330 : : void
331 : 39427642 : rest_of_type_compilation (tree type, int toplev)
332 : : {
333 : : /* Avoid confusing the debug information machinery when there are
334 : : errors. */
335 : 39427642 : if (seen_error ())
336 : : return;
337 : :
338 : 38973973 : timevar_push (TV_SYMOUT);
339 : 38973973 : debug_hooks->type_decl (TYPE_STUB_DECL (type), !toplev);
340 : 38973973 : timevar_pop (TV_SYMOUT);
341 : : }
342 : :
343 : :
344 : :
345 : : void
346 : 273339 : pass_manager::
347 : : finish_optimization_passes (void)
348 : : {
349 : 273339 : int i;
350 : 273339 : struct dump_file_info *dfi;
351 : 273339 : char *name;
352 : 273339 : gcc::dump_manager *dumps = m_ctxt->get_dumps ();
353 : :
354 : 273339 : timevar_push (TV_DUMP);
355 : 273339 : if (profile_arc_flag || condition_coverage_flag || flag_test_coverage
356 : 272906 : || flag_branch_probabilities)
357 : : {
358 : 600 : dumps->dump_start (pass_profile_1->static_pass_number, NULL);
359 : 600 : end_branch_prob ();
360 : 600 : dumps->dump_finish (pass_profile_1->static_pass_number);
361 : : }
362 : :
363 : : /* Do whatever is necessary to finish printing the graphs. */
364 : 96033247 : for (i = TDI_end; (dfi = dumps->get_dump_file_info (i)) != NULL; ++i)
365 : 95759908 : if (dfi->graph_dump_initialized)
366 : : {
367 : 156 : name = dumps->get_dump_file_name (dfi);
368 : 156 : finish_graph_dump_file (name);
369 : 156 : free (name);
370 : : }
371 : :
372 : 273339 : timevar_pop (TV_DUMP);
373 : 273339 : }
374 : :
375 : : static unsigned int
376 : 225092 : execute_build_ssa_passes (void)
377 : : {
378 : : /* Once this pass (and its sub-passes) are complete, all functions
379 : : will be in SSA form. Technically this state change is happening
380 : : a tad early, since the sub-passes have not yet run, but since
381 : : none of the sub-passes are IPA passes and do not create new
382 : : functions, this is ok. We're setting this value for the benefit
383 : : of IPA passes that follow. */
384 : 0 : if (symtab->state < IPA_SSA)
385 : 225092 : symtab->state = IPA_SSA;
386 : 225092 : return 0;
387 : : }
388 : :
389 : : namespace {
390 : :
391 : : const pass_data pass_data_build_ssa_passes =
392 : : {
393 : : SIMPLE_IPA_PASS, /* type */
394 : : "build_ssa_passes", /* name */
395 : : OPTGROUP_NONE, /* optinfo_flags */
396 : : TV_EARLY_LOCAL, /* tv_id */
397 : : 0, /* properties_required */
398 : : 0, /* properties_provided */
399 : : 0, /* properties_destroyed */
400 : : 0, /* todo_flags_start */
401 : : /* todo_flags_finish is executed before subpases. For this reason
402 : : it makes no sense to remove unreachable functions here. */
403 : : 0, /* todo_flags_finish */
404 : : };
405 : :
406 : : class pass_build_ssa_passes : public simple_ipa_opt_pass
407 : : {
408 : : public:
409 : 280455 : pass_build_ssa_passes (gcc::context *ctxt)
410 : 560910 : : simple_ipa_opt_pass (pass_data_build_ssa_passes, ctxt)
411 : : {}
412 : :
413 : : /* opt_pass methods: */
414 : 225167 : bool gate (function *) final override
415 : : {
416 : : /* Don't bother doing anything if the program has errors. */
417 : 225167 : return (!seen_error () && !in_lto_p);
418 : : }
419 : :
420 : 225092 : unsigned int execute (function *) final override
421 : : {
422 : 225092 : return execute_build_ssa_passes ();
423 : : }
424 : :
425 : : }; // class pass_build_ssa_passes
426 : :
427 : : const pass_data pass_data_local_optimization_passes =
428 : : {
429 : : SIMPLE_IPA_PASS, /* type */
430 : : "opt_local_passes", /* name */
431 : : OPTGROUP_NONE, /* optinfo_flags */
432 : : TV_NONE, /* tv_id */
433 : : 0, /* properties_required */
434 : : 0, /* properties_provided */
435 : : 0, /* properties_destroyed */
436 : : 0, /* todo_flags_start */
437 : : 0, /* todo_flags_finish */
438 : : };
439 : :
440 : : class pass_local_optimization_passes : public simple_ipa_opt_pass
441 : : {
442 : : public:
443 : 280455 : pass_local_optimization_passes (gcc::context *ctxt)
444 : 560910 : : simple_ipa_opt_pass (pass_data_local_optimization_passes, ctxt)
445 : : {}
446 : :
447 : : /* opt_pass methods: */
448 : 225167 : bool gate (function *) final override
449 : : {
450 : : /* Don't bother doing anything if the program has errors. */
451 : 225167 : return (!seen_error () && !in_lto_p);
452 : : }
453 : :
454 : : }; // class pass_local_optimization_passes
455 : :
456 : : const pass_data pass_data_ipa_remove_symbols =
457 : : {
458 : : SIMPLE_IPA_PASS, /* type */
459 : : "remove_symbols", /* name */
460 : : OPTGROUP_NONE, /* optinfo_flags */
461 : : TV_NONE, /* tv_id */
462 : : 0, /* properties_required */
463 : : 0, /* properties_provided */
464 : : 0, /* properties_destroyed */
465 : : 0, /* todo_flags_start */
466 : : TODO_remove_functions | TODO_dump_symtab, /* todo_flags_finish */
467 : : };
468 : :
469 : : class pass_ipa_remove_symbols : public simple_ipa_opt_pass
470 : : {
471 : : public:
472 : 280455 : pass_ipa_remove_symbols (gcc::context *ctxt)
473 : 560910 : : simple_ipa_opt_pass (pass_data_ipa_remove_symbols, ctxt)
474 : : {}
475 : :
476 : : /* opt_pass methods: */
477 : 225167 : bool gate (function *) final override
478 : : {
479 : : /* Don't bother doing anything if the program has errors. */
480 : 225167 : return (!seen_error () && !in_lto_p);
481 : : }
482 : :
483 : : }; // class pass_local_optimization_passes
484 : :
485 : : } // anon namespace
486 : :
487 : : simple_ipa_opt_pass *
488 : 280455 : make_pass_build_ssa_passes (gcc::context *ctxt)
489 : : {
490 : 280455 : return new pass_build_ssa_passes (ctxt);
491 : : }
492 : :
493 : : simple_ipa_opt_pass *
494 : 280455 : make_pass_local_optimization_passes (gcc::context *ctxt)
495 : : {
496 : 280455 : return new pass_local_optimization_passes (ctxt);
497 : : }
498 : :
499 : : simple_ipa_opt_pass *
500 : 280455 : make_pass_ipa_remove_symbols (gcc::context *ctxt)
501 : : {
502 : 280455 : return new pass_ipa_remove_symbols (ctxt);
503 : : }
504 : :
505 : : namespace {
506 : :
507 : : const pass_data pass_data_all_early_optimizations =
508 : : {
509 : : GIMPLE_PASS, /* type */
510 : : "early_optimizations", /* name */
511 : : OPTGROUP_NONE, /* optinfo_flags */
512 : : TV_NONE, /* tv_id */
513 : : 0, /* properties_required */
514 : : 0, /* properties_provided */
515 : : 0, /* properties_destroyed */
516 : : 0, /* todo_flags_start */
517 : : 0, /* todo_flags_finish */
518 : : };
519 : :
520 : : class pass_all_early_optimizations : public gimple_opt_pass
521 : : {
522 : : public:
523 : 280455 : pass_all_early_optimizations (gcc::context *ctxt)
524 : 560910 : : gimple_opt_pass (pass_data_all_early_optimizations, ctxt)
525 : : {}
526 : :
527 : : /* opt_pass methods: */
528 : 2580458 : bool gate (function *) final override
529 : : {
530 : 2580458 : return (optimize >= 1
531 : : /* Don't bother doing anything if the program has errors. */
532 : 2580458 : && !seen_error ());
533 : : }
534 : :
535 : : }; // class pass_all_early_optimizations
536 : :
537 : : } // anon namespace
538 : :
539 : : static gimple_opt_pass *
540 : 280455 : make_pass_all_early_optimizations (gcc::context *ctxt)
541 : : {
542 : 280455 : return new pass_all_early_optimizations (ctxt);
543 : : }
544 : :
545 : : namespace {
546 : :
547 : : const pass_data pass_data_all_optimizations =
548 : : {
549 : : GIMPLE_PASS, /* type */
550 : : "*all_optimizations", /* name */
551 : : OPTGROUP_NONE, /* optinfo_flags */
552 : : TV_OPTIMIZE, /* tv_id */
553 : : 0, /* properties_required */
554 : : 0, /* properties_provided */
555 : : 0, /* properties_destroyed */
556 : : 0, /* todo_flags_start */
557 : : 0, /* todo_flags_finish */
558 : : };
559 : :
560 : : class pass_all_optimizations : public gimple_opt_pass
561 : : {
562 : : public:
563 : 280455 : pass_all_optimizations (gcc::context *ctxt)
564 : 560910 : : gimple_opt_pass (pass_data_all_optimizations, ctxt)
565 : : {}
566 : :
567 : : /* opt_pass methods: */
568 : 1393075 : bool gate (function *) final override
569 : : {
570 : 1393075 : return optimize >= 1 && !optimize_debug;
571 : : }
572 : :
573 : : }; // class pass_all_optimizations
574 : :
575 : : } // anon namespace
576 : :
577 : : static gimple_opt_pass *
578 : 280455 : make_pass_all_optimizations (gcc::context *ctxt)
579 : : {
580 : 280455 : return new pass_all_optimizations (ctxt);
581 : : }
582 : :
583 : : namespace {
584 : :
585 : : const pass_data pass_data_all_optimizations_g =
586 : : {
587 : : GIMPLE_PASS, /* type */
588 : : "*all_optimizations_g", /* name */
589 : : OPTGROUP_NONE, /* optinfo_flags */
590 : : TV_OPTIMIZE, /* tv_id */
591 : : 0, /* properties_required */
592 : : 0, /* properties_provided */
593 : : 0, /* properties_destroyed */
594 : : 0, /* todo_flags_start */
595 : : 0, /* todo_flags_finish */
596 : : };
597 : :
598 : : class pass_all_optimizations_g : public gimple_opt_pass
599 : : {
600 : : public:
601 : 280455 : pass_all_optimizations_g (gcc::context *ctxt)
602 : 560910 : : gimple_opt_pass (pass_data_all_optimizations_g, ctxt)
603 : : {}
604 : :
605 : : /* opt_pass methods: */
606 : 1393075 : bool gate (function *) final override
607 : : {
608 : 1393075 : return optimize >= 1 && optimize_debug;
609 : : }
610 : :
611 : : }; // class pass_all_optimizations_g
612 : :
613 : : } // anon namespace
614 : :
615 : : static gimple_opt_pass *
616 : 280455 : make_pass_all_optimizations_g (gcc::context *ctxt)
617 : : {
618 : 280455 : return new pass_all_optimizations_g (ctxt);
619 : : }
620 : :
621 : : namespace {
622 : :
623 : : const pass_data pass_data_rest_of_compilation =
624 : : {
625 : : RTL_PASS, /* type */
626 : : "*rest_of_compilation", /* name */
627 : : OPTGROUP_NONE, /* optinfo_flags */
628 : : TV_REST_OF_COMPILATION, /* tv_id */
629 : : PROP_rtl, /* properties_required */
630 : : 0, /* properties_provided */
631 : : 0, /* properties_destroyed */
632 : : 0, /* todo_flags_start */
633 : : 0, /* todo_flags_finish */
634 : : };
635 : :
636 : : class pass_rest_of_compilation : public rtl_opt_pass
637 : : {
638 : : public:
639 : 280455 : pass_rest_of_compilation (gcc::context *ctxt)
640 : 560910 : : rtl_opt_pass (pass_data_rest_of_compilation, ctxt)
641 : : {}
642 : :
643 : : /* opt_pass methods: */
644 : 1392984 : bool gate (function *) final override
645 : : {
646 : : /* Early return if there were errors. We can run afoul of our
647 : : consistency checks, and there's not really much point in fixing them. */
648 : 1392984 : return !(rtl_dump_and_exit || flag_syntax_only || seen_error ());
649 : : }
650 : :
651 : : }; // class pass_rest_of_compilation
652 : :
653 : : } // anon namespace
654 : :
655 : : static rtl_opt_pass *
656 : 280455 : make_pass_rest_of_compilation (gcc::context *ctxt)
657 : : {
658 : 280455 : return new pass_rest_of_compilation (ctxt);
659 : : }
660 : :
661 : : namespace {
662 : :
663 : : const pass_data pass_data_postreload =
664 : : {
665 : : RTL_PASS, /* type */
666 : : "*all-postreload", /* name */
667 : : OPTGROUP_NONE, /* optinfo_flags */
668 : : TV_POSTRELOAD, /* tv_id */
669 : : PROP_rtl, /* properties_required */
670 : : 0, /* properties_provided */
671 : : 0, /* properties_destroyed */
672 : : 0, /* todo_flags_start */
673 : : 0, /* todo_flags_finish */
674 : : };
675 : :
676 : : class pass_postreload : public rtl_opt_pass
677 : : {
678 : : public:
679 : 280455 : pass_postreload (gcc::context *ctxt)
680 : 560910 : : rtl_opt_pass (pass_data_postreload, ctxt)
681 : : {}
682 : :
683 : : /* opt_pass methods: */
684 : 1392368 : bool gate (function *) final override { return reload_completed; }
685 : :
686 : : }; // class pass_postreload
687 : :
688 : : } // anon namespace
689 : :
690 : : static rtl_opt_pass *
691 : 280455 : make_pass_postreload (gcc::context *ctxt)
692 : : {
693 : 280455 : return new pass_postreload (ctxt);
694 : : }
695 : :
696 : : namespace {
697 : :
698 : : const pass_data pass_data_late_compilation =
699 : : {
700 : : RTL_PASS, /* type */
701 : : "*all-late_compilation", /* name */
702 : : OPTGROUP_NONE, /* optinfo_flags */
703 : : TV_LATE_COMPILATION, /* tv_id */
704 : : PROP_rtl, /* properties_required */
705 : : 0, /* properties_provided */
706 : : 0, /* properties_destroyed */
707 : : 0, /* todo_flags_start */
708 : : 0, /* todo_flags_finish */
709 : : };
710 : :
711 : : class pass_late_compilation : public rtl_opt_pass
712 : : {
713 : : public:
714 : 280455 : pass_late_compilation (gcc::context *ctxt)
715 : 560910 : : rtl_opt_pass (pass_data_late_compilation, ctxt)
716 : : {}
717 : :
718 : : /* opt_pass methods: */
719 : 1392368 : bool gate (function *) final override
720 : : {
721 : 1392368 : return reload_completed || targetm.no_register_allocation;
722 : : }
723 : :
724 : : }; // class pass_late_compilation
725 : :
726 : : } // anon namespace
727 : :
728 : : static rtl_opt_pass *
729 : 280455 : make_pass_late_compilation (gcc::context *ctxt)
730 : : {
731 : 280455 : return new pass_late_compilation (ctxt);
732 : : }
733 : :
734 : : /* Pre-SLP scalar cleanup, it has several cleanup passes like FRE, DSE. */
735 : :
736 : : namespace {
737 : :
738 : : const pass_data pass_data_pre_slp_scalar_cleanup =
739 : : {
740 : : GIMPLE_PASS, /* type */
741 : : "*pre_slp_scalar_cleanup", /* name */
742 : : OPTGROUP_LOOP, /* optinfo_flags */
743 : : TV_SCALAR_CLEANUP, /* tv_id */
744 : : ( PROP_cfg | PROP_ssa ), /* properties_required */
745 : : 0, /* properties_provided */
746 : : 0, /* properties_destroyed */
747 : : 0, /* todo_flags_start */
748 : : 0, /* todo_flags_finish */
749 : : };
750 : :
751 : : class pass_pre_slp_scalar_cleanup : public gimple_opt_pass
752 : : {
753 : : public:
754 : 280455 : pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
755 : 560910 : : gimple_opt_pass (pass_data_pre_slp_scalar_cleanup, ctxt)
756 : : {
757 : : }
758 : :
759 : : bool
760 : 217395 : gate (function *fun) final override
761 : : {
762 : 217395 : return flag_tree_slp_vectorize
763 : 217395 : && (fun->pending_TODOs & PENDING_TODO_force_next_scalar_cleanup);
764 : : }
765 : :
766 : : unsigned int
767 : 17724 : execute (function *fun) final override
768 : : {
769 : 17724 : fun->pending_TODOs &= ~PENDING_TODO_force_next_scalar_cleanup;
770 : 17724 : return 0;
771 : : }
772 : :
773 : : }; // class pass_pre_slp_scalar_cleanup
774 : :
775 : : } // anon namespace
776 : :
777 : : gimple_opt_pass *
778 : 280455 : make_pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
779 : : {
780 : 280455 : return new pass_pre_slp_scalar_cleanup (ctxt);
781 : : }
782 : :
783 : : /* Set the static pass number of pass PASS to ID and record that
784 : : in the mapping from static pass number to pass. */
785 : :
786 : : void
787 : 97037586 : pass_manager::
788 : : set_pass_for_id (int id, opt_pass *pass)
789 : : {
790 : 97037586 : pass->static_pass_number = id;
791 : 97037586 : if (passes_by_id_size <= id)
792 : : {
793 : 97037586 : passes_by_id = XRESIZEVEC (opt_pass *, passes_by_id, id + 1);
794 : 97037586 : memset (passes_by_id + passes_by_id_size, 0,
795 : 97037586 : (id + 1 - passes_by_id_size) * sizeof (void *));
796 : 97037586 : passes_by_id_size = id + 1;
797 : : }
798 : 97037586 : passes_by_id[id] = pass;
799 : 97037586 : }
800 : :
801 : : /* Return the pass with the static pass number ID. */
802 : :
803 : : opt_pass *
804 : 14 : pass_manager::get_pass_for_id (int id) const
805 : : {
806 : 14 : if (id >= passes_by_id_size)
807 : : return NULL;
808 : 14 : return passes_by_id[id];
809 : : }
810 : :
811 : : /* Iterate over the pass tree allocating dump file numbers. We want
812 : : to do this depth first, and independent of whether the pass is
813 : : enabled or not. */
814 : :
815 : : void
816 : 156 : register_one_dump_file (opt_pass *pass)
817 : : {
818 : 156 : g->get_passes ()->register_one_dump_file (pass);
819 : 156 : }
820 : :
821 : : void
822 : 97037586 : pass_manager::register_one_dump_file (opt_pass *pass)
823 : : {
824 : 97037586 : char *dot_name, *flag_name, *glob_name;
825 : 97037586 : const char *name, *full_name, *prefix;
826 : :
827 : : /* Buffer big enough to format a 32-bit UINT_MAX into. */
828 : 97037586 : char num[11];
829 : 97037586 : dump_kind dkind;
830 : 97037586 : int id;
831 : 97037586 : optgroup_flags_t optgroup_flags = OPTGROUP_NONE;
832 : 97037586 : gcc::dump_manager *dumps = m_ctxt->get_dumps ();
833 : :
834 : : /* See below in next_pass_1. */
835 : 97037586 : num[0] = '\0';
836 : 97037586 : if (pass->static_pass_number != -1)
837 : 58895550 : sprintf (num, "%u", ((int) pass->static_pass_number < 0
838 : : ? 1 : pass->static_pass_number));
839 : :
840 : : /* The name is both used to identify the pass for the purposes of plugins,
841 : : and to specify dump file name and option.
842 : : The latter two might want something short which is not quite unique; for
843 : : that reason, we may have a disambiguating prefix, followed by a space
844 : : to mark the start of the following dump file name / option string. */
845 : 97037586 : name = strchr (pass->name, ' ');
846 : 97037586 : name = name ? name + 1 : pass->name;
847 : 97037586 : dot_name = concat (".", name, num, NULL);
848 : 97037586 : if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
849 : : {
850 : : prefix = "ipa-";
851 : : dkind = DK_ipa;
852 : : optgroup_flags |= OPTGROUP_IPA;
853 : : }
854 : 87221647 : else if (pass->type == GIMPLE_PASS)
855 : : {
856 : : prefix = "tree-";
857 : : dkind = DK_tree;
858 : : }
859 : : else
860 : : {
861 : 24680040 : prefix = "rtl-";
862 : 24680040 : dkind = DK_rtl;
863 : : }
864 : :
865 : 97037586 : flag_name = concat (prefix, name, num, NULL);
866 : 97037586 : glob_name = concat (prefix, name, NULL);
867 : 97037586 : optgroup_flags |= pass->optinfo_flags;
868 : : /* For any passes that do not have an optgroup set, and which are not
869 : : IPA passes setup above, set the optgroup to OPTGROUP_OTHER so that
870 : : any dump messages are emitted properly under -fopt-info(-optall). */
871 : 97037586 : if (optgroup_flags == OPTGROUP_NONE)
872 : 71235710 : optgroup_flags = OPTGROUP_OTHER;
873 : 97037586 : id = dumps->dump_register (dot_name, flag_name, glob_name, dkind,
874 : : optgroup_flags,
875 : : true);
876 : 97037586 : set_pass_for_id (id, pass);
877 : 97037586 : full_name = concat (prefix, pass->name, num, NULL);
878 : 97037586 : register_pass_name (pass, full_name);
879 : 97037586 : free (CONST_CAST (char *, full_name));
880 : 97037586 : }
881 : :
882 : : /* Register the dump files for the pass_manager starting at PASS. */
883 : :
884 : : void
885 : 7011375 : pass_manager::register_dump_files (opt_pass *pass)
886 : : {
887 : 105731535 : do
888 : : {
889 : 105731535 : if (pass->name && pass->name[0] != '*')
890 : 97037430 : register_one_dump_file (pass);
891 : :
892 : 105731535 : if (pass->sub)
893 : 5609100 : register_dump_files (pass->sub);
894 : :
895 : 105731535 : pass = pass->next;
896 : : }
897 : 105731535 : while (pass);
898 : 7011375 : }
899 : :
900 : : /* Register PASS with NAME. */
901 : :
902 : : void
903 : 97037586 : pass_manager::register_pass_name (opt_pass *pass, const char *name)
904 : : {
905 : 97037586 : if (!m_name_to_pass_map)
906 : 280455 : m_name_to_pass_map = new hash_map<free_string_hash, opt_pass *> (256);
907 : :
908 : 97037586 : if (m_name_to_pass_map->get (name))
909 : 1 : return; /* Ignore plugin passes. */
910 : :
911 : 97037585 : const char *unique_name = xstrdup (name);
912 : 97037585 : m_name_to_pass_map->put (unique_name, pass);
913 : : }
914 : :
915 : : /* Map from pass id to canonicalized pass name. */
916 : :
917 : : typedef const char *char_ptr;
918 : : static vec<char_ptr> pass_tab;
919 : :
920 : : /* Callback function for traversing NAME_TO_PASS_MAP. */
921 : :
922 : : bool
923 : 2076 : passes_pass_traverse (const char *const &name, opt_pass *const &pass, void *)
924 : : {
925 : 2076 : gcc_assert (pass->static_pass_number > 0);
926 : 2076 : gcc_assert (pass_tab.exists ());
927 : :
928 : 2076 : pass_tab[pass->static_pass_number] = name;
929 : :
930 : 2076 : return 1;
931 : : }
932 : :
933 : : /* The function traverses NAME_TO_PASS_MAP and creates a pass info
934 : : table for dumping purpose. */
935 : :
936 : : void
937 : 6 : pass_manager::create_pass_tab (void) const
938 : : {
939 : 6 : if (!flag_dump_passes)
940 : : return;
941 : :
942 : 6 : pass_tab.safe_grow_cleared (passes_by_id_size + 1, true);
943 : 6 : m_name_to_pass_map->traverse <void *, passes_pass_traverse> (NULL);
944 : : }
945 : :
946 : : static bool override_gate_status (opt_pass *, tree, bool);
947 : :
948 : : /* Dump the instantiated name for PASS. IS_ON indicates if PASS
949 : : is turned on or not. */
950 : :
951 : : static void
952 : 2262 : dump_one_pass (opt_pass *pass, int pass_indent)
953 : : {
954 : 2262 : int indent = 3 * pass_indent;
955 : 2262 : const char *pn;
956 : 2262 : bool is_on, is_really_on;
957 : :
958 : 2262 : is_on = pass->gate (cfun);
959 : 2262 : is_really_on = override_gate_status (pass, current_function_decl, is_on);
960 : :
961 : 2262 : if (pass->static_pass_number <= 0)
962 : 186 : pn = pass->name;
963 : : else
964 : 2076 : pn = pass_tab[pass->static_pass_number];
965 : :
966 : 2262 : fprintf (stderr, "%*s%-40s%*s:%s%s\n", indent, " ", pn,
967 : 2262 : (15 - indent < 0 ? 0 : 15 - indent), " ",
968 : : is_on ? " ON" : " OFF",
969 : : ((!is_on) == (!is_really_on) ? ""
970 : 0 : : (is_really_on ? " (FORCED_ON)" : " (FORCED_OFF)")));
971 : 2262 : }
972 : :
973 : : /* Dump pass list PASS with indentation INDENT. */
974 : :
975 : : static void
976 : 150 : dump_pass_list (opt_pass *pass, int indent)
977 : : {
978 : 2262 : do
979 : : {
980 : 2262 : dump_one_pass (pass, indent);
981 : 2262 : if (pass->sub)
982 : 120 : dump_pass_list (pass->sub, indent + 1);
983 : 2262 : pass = pass->next;
984 : : }
985 : 2262 : while (pass);
986 : 150 : }
987 : :
988 : : /* Dump all optimization passes. */
989 : :
990 : : void
991 : 6 : dump_passes (void)
992 : : {
993 : 6 : g->get_passes ()->dump_passes ();
994 : 6 : }
995 : :
996 : : void
997 : 6 : pass_manager::dump_passes () const
998 : : {
999 : 6 : push_dummy_function (true);
1000 : 6 : cgraph_node *node = cgraph_node::get_create (current_function_decl);
1001 : :
1002 : 6 : create_pass_tab ();
1003 : :
1004 : 6 : dump_pass_list (all_lowering_passes, 1);
1005 : 6 : dump_pass_list (all_small_ipa_passes, 1);
1006 : 6 : dump_pass_list (all_regular_ipa_passes, 1);
1007 : 6 : dump_pass_list (all_late_ipa_passes, 1);
1008 : 6 : dump_pass_list (all_passes, 1);
1009 : :
1010 : 6 : node->remove ();
1011 : 6 : pop_dummy_function ();
1012 : 6 : }
1013 : :
1014 : : /* Returns the pass with NAME. */
1015 : :
1016 : : opt_pass *
1017 : 203 : pass_manager::get_pass_by_name (const char *name)
1018 : : {
1019 : 203 : opt_pass **p = m_name_to_pass_map->get (name);
1020 : 203 : if (p)
1021 : 203 : return *p;
1022 : :
1023 : : return NULL;
1024 : : }
1025 : :
1026 : :
1027 : : /* Range [start, last]. */
1028 : :
1029 : : struct uid_range
1030 : : {
1031 : : unsigned int start;
1032 : : unsigned int last;
1033 : : const char *assem_name;
1034 : : struct uid_range *next;
1035 : : };
1036 : :
1037 : : typedef struct uid_range *uid_range_p;
1038 : :
1039 : :
1040 : : static vec<uid_range_p> enabled_pass_uid_range_tab;
1041 : : static vec<uid_range_p> disabled_pass_uid_range_tab;
1042 : :
1043 : :
1044 : : /* Parse option string for -fdisable- and -fenable-
1045 : : The syntax of the options:
1046 : :
1047 : : -fenable-<pass_name>
1048 : : -fdisable-<pass_name>
1049 : :
1050 : : -fenable-<pass_name>=s1:e1,s2:e2,...
1051 : : -fdisable-<pass_name>=s1:e1,s2:e2,...
1052 : : */
1053 : :
1054 : : static void
1055 : 203 : enable_disable_pass (const char *arg, bool is_enable)
1056 : : {
1057 : 203 : opt_pass *pass;
1058 : 203 : char *range_str, *phase_name;
1059 : 203 : char *argstr = xstrdup (arg);
1060 : 203 : vec<uid_range_p> *tab = 0;
1061 : :
1062 : 203 : range_str = strchr (argstr,'=');
1063 : 203 : if (range_str)
1064 : : {
1065 : 9 : *range_str = '\0';
1066 : 9 : range_str++;
1067 : : }
1068 : :
1069 : 203 : phase_name = argstr;
1070 : 203 : if (!*phase_name)
1071 : : {
1072 : 0 : if (is_enable)
1073 : 0 : error ("unrecognized option %<-fenable%>");
1074 : : else
1075 : 0 : error ("unrecognized option %<-fdisable%>");
1076 : 0 : free (argstr);
1077 : 0 : return;
1078 : : }
1079 : 203 : pass = g->get_passes ()->get_pass_by_name (phase_name);
1080 : 203 : if (!pass || pass->static_pass_number == -1)
1081 : : {
1082 : 0 : if (is_enable)
1083 : 0 : error ("unknown pass %s specified in %<-fenable%>", phase_name);
1084 : : else
1085 : 0 : error ("unknown pass %s specified in %<-fdisable%>", phase_name);
1086 : 0 : free (argstr);
1087 : 0 : return;
1088 : : }
1089 : :
1090 : 203 : if (is_enable)
1091 : : tab = &enabled_pass_uid_range_tab;
1092 : : else
1093 : 199 : tab = &disabled_pass_uid_range_tab;
1094 : :
1095 : 240 : if ((unsigned) pass->static_pass_number >= tab->length ())
1096 : 190 : tab->safe_grow_cleared (pass->static_pass_number + 1, true);
1097 : :
1098 : 203 : if (!range_str)
1099 : : {
1100 : 194 : uid_range_p slot;
1101 : 194 : uid_range_p new_range = XCNEW (struct uid_range);
1102 : :
1103 : 194 : new_range->start = 0;
1104 : 194 : new_range->last = (unsigned)-1;
1105 : :
1106 : 194 : slot = (*tab)[pass->static_pass_number];
1107 : 194 : new_range->next = slot;
1108 : 194 : (*tab)[pass->static_pass_number] = new_range;
1109 : 194 : if (is_enable)
1110 : 1 : inform (UNKNOWN_LOCATION, "enable pass %s for functions in the range "
1111 : : "of [%u, %u]", phase_name, new_range->start, new_range->last);
1112 : : else
1113 : 193 : inform (UNKNOWN_LOCATION, "disable pass %s for functions in the range "
1114 : : "of [%u, %u]", phase_name, new_range->start, new_range->last);
1115 : : }
1116 : : else
1117 : : {
1118 : 10 : char *next_range = NULL;
1119 : : char *one_range = range_str;
1120 : 10 : char *end_val = NULL;
1121 : :
1122 : 10 : do
1123 : : {
1124 : 10 : uid_range_p slot;
1125 : 10 : uid_range_p new_range;
1126 : 10 : char *invalid = NULL;
1127 : 10 : long start;
1128 : 10 : char *func_name = NULL;
1129 : :
1130 : 10 : next_range = strchr (one_range, ',');
1131 : 10 : if (next_range)
1132 : : {
1133 : 1 : *next_range = '\0';
1134 : 1 : next_range++;
1135 : : }
1136 : :
1137 : 10 : end_val = strchr (one_range, ':');
1138 : 10 : if (end_val)
1139 : : {
1140 : 1 : *end_val = '\0';
1141 : 1 : end_val++;
1142 : : }
1143 : 10 : start = strtol (one_range, &invalid, 10);
1144 : 10 : if (*invalid || start < 0)
1145 : : {
1146 : 9 : if (end_val || (one_range[0] >= '0'
1147 : 9 : && one_range[0] <= '9'))
1148 : : {
1149 : 0 : error ("Invalid range %s in option %s",
1150 : : one_range,
1151 : : is_enable ? "-fenable" : "-fdisable");
1152 : 0 : free (argstr);
1153 : 0 : return;
1154 : : }
1155 : : func_name = one_range;
1156 : : }
1157 : 10 : if (!end_val)
1158 : : {
1159 : 9 : new_range = XCNEW (struct uid_range);
1160 : 9 : if (!func_name)
1161 : : {
1162 : 0 : new_range->start = (unsigned) start;
1163 : 0 : new_range->last = (unsigned) start;
1164 : : }
1165 : : else
1166 : : {
1167 : 9 : new_range->start = (unsigned) -1;
1168 : 9 : new_range->last = (unsigned) -1;
1169 : 9 : new_range->assem_name = xstrdup (func_name);
1170 : : }
1171 : : }
1172 : : else
1173 : : {
1174 : 1 : long last = strtol (end_val, &invalid, 10);
1175 : 1 : if (*invalid || last < start)
1176 : : {
1177 : 0 : error ("Invalid range %s in option %s",
1178 : : end_val,
1179 : : is_enable ? "-fenable" : "-fdisable");
1180 : 0 : free (argstr);
1181 : 0 : return;
1182 : : }
1183 : 1 : new_range = XCNEW (struct uid_range);
1184 : 1 : new_range->start = (unsigned) start;
1185 : 1 : new_range->last = (unsigned) last;
1186 : : }
1187 : :
1188 : 10 : slot = (*tab)[pass->static_pass_number];
1189 : 10 : new_range->next = slot;
1190 : 10 : (*tab)[pass->static_pass_number] = new_range;
1191 : 10 : if (is_enable)
1192 : : {
1193 : 3 : if (new_range->assem_name)
1194 : 3 : inform (UNKNOWN_LOCATION,
1195 : : "enable pass %s for function %s",
1196 : : phase_name, new_range->assem_name);
1197 : : else
1198 : 0 : inform (UNKNOWN_LOCATION,
1199 : : "enable pass %s for functions in the range of [%u, %u]",
1200 : : phase_name, new_range->start, new_range->last);
1201 : : }
1202 : : else
1203 : : {
1204 : 7 : if (new_range->assem_name)
1205 : 6 : inform (UNKNOWN_LOCATION,
1206 : : "disable pass %s for function %s",
1207 : : phase_name, new_range->assem_name);
1208 : : else
1209 : 1 : inform (UNKNOWN_LOCATION,
1210 : : "disable pass %s for functions in the range of [%u, %u]",
1211 : : phase_name, new_range->start, new_range->last);
1212 : : }
1213 : :
1214 : 10 : one_range = next_range;
1215 : 10 : } while (next_range);
1216 : : }
1217 : :
1218 : 203 : free (argstr);
1219 : : }
1220 : :
1221 : : /* Enable pass specified by ARG. */
1222 : :
1223 : : void
1224 : 4 : enable_pass (const char *arg)
1225 : : {
1226 : 4 : enable_disable_pass (arg, true);
1227 : 4 : }
1228 : :
1229 : : /* Disable pass specified by ARG. */
1230 : :
1231 : : void
1232 : 199 : disable_pass (const char *arg)
1233 : : {
1234 : 199 : enable_disable_pass (arg, false);
1235 : 199 : }
1236 : :
1237 : : /* Returns true if PASS is explicitly enabled/disabled for FUNC. */
1238 : :
1239 : : static bool
1240 : 834005178 : is_pass_explicitly_enabled_or_disabled (opt_pass *pass,
1241 : : tree func,
1242 : : vec<uid_range_p> tab)
1243 : : {
1244 : 834005178 : uid_range_p slot, range;
1245 : 834005178 : int cgraph_uid;
1246 : 834005178 : const char *aname = NULL;
1247 : :
1248 : 834005178 : if (!tab.exists ()
1249 : 834023694 : || (unsigned) pass->static_pass_number >= tab.length ()
1250 : 834005178 : || pass->static_pass_number == -1)
1251 : : return false;
1252 : :
1253 : 18804 : slot = tab[pass->static_pass_number];
1254 : 18804 : if (!slot)
1255 : : return false;
1256 : :
1257 : 297 : cgraph_uid = func ? cgraph_node::get (func)->get_uid () : 0;
1258 : 293 : if (func && DECL_ASSEMBLER_NAME_SET_P (func))
1259 : 293 : aname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func));
1260 : :
1261 : 297 : range = slot;
1262 : 308 : while (range)
1263 : : {
1264 : 299 : if ((unsigned) cgraph_uid >= range->start
1265 : 279 : && (unsigned) cgraph_uid <= range->last)
1266 : : return true;
1267 : 20 : if (range->assem_name && aname
1268 : 20 : && !strcmp (range->assem_name, aname))
1269 : : return true;
1270 : 11 : range = range->next;
1271 : : }
1272 : :
1273 : : return false;
1274 : : }
1275 : :
1276 : :
1277 : : /* Update static_pass_number for passes (and the flag
1278 : : TODO_mark_first_instance).
1279 : :
1280 : : Passes are constructed with static_pass_number preinitialized to 0
1281 : :
1282 : : This field is used in two different ways: initially as instance numbers
1283 : : of their kind, and then as ids within the entire pass manager.
1284 : :
1285 : : Within pass_manager::pass_manager:
1286 : :
1287 : : * In add_pass_instance(), as called by next_pass_1 in
1288 : : NEXT_PASS in init_optimization_passes
1289 : :
1290 : : * When the initial instance of a pass within a pass manager is seen,
1291 : : it is flagged, and its static_pass_number is set to -1
1292 : :
1293 : : * On subsequent times that it is seen, the static pass number
1294 : : is decremented each time, so that if there are e.g. 4 dups,
1295 : : they have static_pass_number -4, 2, 3, 4 respectively (note
1296 : : how the initial one is negative and gives the count); these
1297 : : can be thought of as instance numbers of the specific pass
1298 : :
1299 : : * Within the register_dump_files () traversal, set_pass_for_id()
1300 : : is called on each pass, using these instance numbers to create
1301 : : dumpfile switches, and then overwriting them with a pass id,
1302 : : which are global to the whole pass manager (based on
1303 : : (TDI_end + current value of extra_dump_files_in_use) ) */
1304 : :
1305 : : static void
1306 : 105731691 : add_pass_instance (opt_pass *new_pass, bool track_duplicates,
1307 : : opt_pass *initial_pass)
1308 : : {
1309 : : /* Are we dealing with the first pass of its kind, or a clone? */
1310 : 105731691 : if (new_pass != initial_pass)
1311 : : {
1312 : : /* We're dealing with a clone. */
1313 : 24399585 : new_pass->todo_flags_start &= ~TODO_mark_first_instance;
1314 : :
1315 : : /* Indicate to register_dump_files that this pass has duplicates,
1316 : : and so it should rename the dump file. The first instance will
1317 : : be -1, and be number of duplicates = -static_pass_number - 1.
1318 : : Subsequent instances will be > 0 and just the duplicate number. */
1319 : 24399585 : if ((new_pass->name && new_pass->name[0] != '*') || track_duplicates)
1320 : : {
1321 : 22436400 : initial_pass->static_pass_number -= 1;
1322 : 22436400 : new_pass->static_pass_number = -initial_pass->static_pass_number;
1323 : : }
1324 : : }
1325 : : else
1326 : : {
1327 : : /* We're dealing with the first pass of its kind. */
1328 : 81332106 : new_pass->todo_flags_start |= TODO_mark_first_instance;
1329 : 81332106 : new_pass->static_pass_number = -1;
1330 : :
1331 : 81332106 : invoke_plugin_callbacks (PLUGIN_NEW_PASS, new_pass);
1332 : : }
1333 : 105731691 : }
1334 : :
1335 : : /* Add a pass to the pass list. Duplicate the pass if it's already
1336 : : in the list. */
1337 : :
1338 : : static opt_pass **
1339 : 105731535 : next_pass_1 (opt_pass **list, opt_pass *pass, opt_pass *initial_pass)
1340 : : {
1341 : : /* Every pass should have a name so that plugins can refer to them. */
1342 : 105731535 : gcc_assert (pass->name != NULL);
1343 : :
1344 : 105731535 : add_pass_instance (pass, false, initial_pass);
1345 : 105731535 : *list = pass;
1346 : :
1347 : 105731535 : return &(*list)->next;
1348 : : }
1349 : :
1350 : : /* List node for an inserted pass instance. We need to keep track of all
1351 : : the newly-added pass instances (with 'added_pass_nodes' defined below)
1352 : : so that we can register their dump files after pass-positioning is finished.
1353 : : Registering dumping files needs to be post-processed or the
1354 : : static_pass_number of the opt_pass object would be modified and mess up
1355 : : the dump file names of future pass instances to be added. */
1356 : :
1357 : : struct pass_list_node
1358 : : {
1359 : : opt_pass *pass;
1360 : : struct pass_list_node *next;
1361 : : };
1362 : :
1363 : : static struct pass_list_node *added_pass_nodes = NULL;
1364 : : static struct pass_list_node *prev_added_pass_node;
1365 : :
1366 : : /* Insert the pass at the proper position. Return true if the pass
1367 : : is successfully added.
1368 : :
1369 : : NEW_PASS_INFO - new pass to be inserted
1370 : : PASS_LIST - root of the pass list to insert the new pass to */
1371 : :
1372 : : static bool
1373 : 3266 : position_pass (struct register_pass_info *new_pass_info, opt_pass **pass_list)
1374 : : {
1375 : 3266 : opt_pass *pass = *pass_list, *prev_pass = NULL;
1376 : 3266 : bool success = false;
1377 : :
1378 : 50566 : for ( ; pass; prev_pass = pass, pass = pass->next)
1379 : : {
1380 : : /* Check if the current pass is of the same type as the new pass and
1381 : : matches the name and the instance number of the reference pass. */
1382 : 47300 : if (pass->type == new_pass_info->pass->type
1383 : 30359 : && pass->name
1384 : 30359 : && !strcmp (pass->name, new_pass_info->reference_pass_name)
1385 : 156 : && ((new_pass_info->ref_pass_instance_number == 0)
1386 : 156 : || (new_pass_info->ref_pass_instance_number ==
1387 : 156 : pass->static_pass_number)
1388 : 156 : || (new_pass_info->ref_pass_instance_number == 1
1389 : 156 : && pass->todo_flags_start & TODO_mark_first_instance)))
1390 : : {
1391 : 156 : opt_pass *new_pass;
1392 : 156 : struct pass_list_node *new_pass_node;
1393 : :
1394 : 156 : if (new_pass_info->ref_pass_instance_number == 0)
1395 : : {
1396 : 0 : new_pass = new_pass_info->pass->clone ();
1397 : 0 : add_pass_instance (new_pass, true, new_pass_info->pass);
1398 : : }
1399 : : else
1400 : : {
1401 : 156 : new_pass = new_pass_info->pass;
1402 : 156 : add_pass_instance (new_pass, true, new_pass);
1403 : : }
1404 : :
1405 : : /* Insert the new pass instance based on the positioning op. */
1406 : 156 : switch (new_pass_info->pos_op)
1407 : : {
1408 : 142 : case PASS_POS_INSERT_AFTER:
1409 : 142 : new_pass->next = pass->next;
1410 : 142 : pass->next = new_pass;
1411 : :
1412 : : /* Skip newly inserted pass to avoid repeated
1413 : : insertions in the case where the new pass and the
1414 : : existing one have the same name. */
1415 : 142 : pass = new_pass;
1416 : 142 : break;
1417 : 14 : case PASS_POS_INSERT_BEFORE:
1418 : 14 : new_pass->next = pass;
1419 : 14 : if (prev_pass)
1420 : 14 : prev_pass->next = new_pass;
1421 : : else
1422 : 0 : *pass_list = new_pass;
1423 : : break;
1424 : 0 : case PASS_POS_REPLACE:
1425 : 0 : new_pass->next = pass->next;
1426 : 0 : if (prev_pass)
1427 : 0 : prev_pass->next = new_pass;
1428 : : else
1429 : 0 : *pass_list = new_pass;
1430 : 0 : new_pass->sub = pass->sub;
1431 : 0 : new_pass->tv_id = pass->tv_id;
1432 : 0 : pass = new_pass;
1433 : 0 : break;
1434 : 0 : default:
1435 : 0 : error ("invalid pass positioning operation");
1436 : 0 : return false;
1437 : : }
1438 : :
1439 : : /* Save the newly added pass (instance) in the added_pass_nodes
1440 : : list so that we can register its dump file later. Note that
1441 : : we cannot register the dump file now because doing so will modify
1442 : : the static_pass_number of the opt_pass object and therefore
1443 : : mess up the dump file name of future instances. */
1444 : 156 : new_pass_node = XCNEW (struct pass_list_node);
1445 : 156 : new_pass_node->pass = new_pass;
1446 : 156 : if (!added_pass_nodes)
1447 : 156 : added_pass_nodes = new_pass_node;
1448 : : else
1449 : 0 : prev_added_pass_node->next = new_pass_node;
1450 : 156 : prev_added_pass_node = new_pass_node;
1451 : :
1452 : 156 : success = true;
1453 : : }
1454 : :
1455 : 47300 : if (pass->sub && position_pass (new_pass_info, &pass->sub))
1456 : : success = true;
1457 : : }
1458 : :
1459 : : return success;
1460 : : }
1461 : :
1462 : : /* Hooks a new pass into the pass lists.
1463 : :
1464 : : PASS_INFO - pass information that specifies the opt_pass object,
1465 : : reference pass, instance number, and how to position
1466 : : the pass */
1467 : :
1468 : : void
1469 : 156 : register_pass (struct register_pass_info *pass_info)
1470 : : {
1471 : 156 : g->get_passes ()->register_pass (pass_info);
1472 : 156 : }
1473 : :
1474 : : void
1475 : 0 : register_pass (opt_pass* pass, pass_positioning_ops pos,
1476 : : const char* ref_pass_name, int ref_pass_inst_number)
1477 : : {
1478 : 0 : register_pass_info i;
1479 : 0 : i.pass = pass;
1480 : 0 : i.reference_pass_name = ref_pass_name;
1481 : 0 : i.ref_pass_instance_number = ref_pass_inst_number;
1482 : 0 : i.pos_op = pos;
1483 : :
1484 : 0 : g->get_passes ()->register_pass (&i);
1485 : 0 : }
1486 : :
1487 : : void
1488 : 156 : pass_manager::register_pass (struct register_pass_info *pass_info)
1489 : : {
1490 : 156 : bool all_instances, success;
1491 : :
1492 : : /* The checks below could fail in buggy plugins. Existing GCC
1493 : : passes should never fail these checks, so we mention plugin in
1494 : : the messages. */
1495 : 156 : if (!pass_info->pass)
1496 : 0 : fatal_error (input_location, "plugin cannot register a missing pass");
1497 : :
1498 : 156 : if (!pass_info->pass->name)
1499 : 0 : fatal_error (input_location, "plugin cannot register an unnamed pass");
1500 : :
1501 : 156 : if (!pass_info->reference_pass_name)
1502 : 0 : fatal_error
1503 : 0 : (input_location,
1504 : : "plugin cannot register pass %qs without reference pass name",
1505 : : pass_info->pass->name);
1506 : :
1507 : : /* Try to insert the new pass to the pass lists. We need to check
1508 : : all five lists as the reference pass could be in one (or all) of
1509 : : them. */
1510 : 156 : all_instances = pass_info->ref_pass_instance_number == 0;
1511 : 156 : success = position_pass (pass_info, &all_lowering_passes);
1512 : 156 : if (!success || all_instances)
1513 : 155 : success |= position_pass (pass_info, &all_small_ipa_passes);
1514 : 156 : if (!success || all_instances)
1515 : 130 : success |= position_pass (pass_info, &all_regular_ipa_passes);
1516 : 156 : if (!success || all_instances)
1517 : 116 : success |= position_pass (pass_info, &all_late_ipa_passes);
1518 : 156 : if (!success || all_instances)
1519 : 116 : success |= position_pass (pass_info, &all_passes);
1520 : 116 : if (!success)
1521 : 0 : fatal_error
1522 : 0 : (input_location,
1523 : : "pass %qs not found but is referenced by new pass %qs",
1524 : 0 : pass_info->reference_pass_name, pass_info->pass->name);
1525 : :
1526 : : /* OK, we have successfully inserted the new pass. We need to register
1527 : : the dump files for the newly added pass and its duplicates (if any).
1528 : : While doing so, we also delete the pass_list_node
1529 : : objects created during pass positioning. */
1530 : 156 : gcc::dump_manager *dumps = m_ctxt->get_dumps ();
1531 : 468 : while (added_pass_nodes)
1532 : : {
1533 : 156 : struct pass_list_node *next_node = added_pass_nodes->next;
1534 : :
1535 : : /* Handle -fdump-* and -fopt-info. */
1536 : 156 : dumps->register_pass (added_pass_nodes->pass);
1537 : :
1538 : 156 : XDELETE (added_pass_nodes);
1539 : 156 : added_pass_nodes = next_node;
1540 : : }
1541 : 156 : }
1542 : :
1543 : : /* Construct the pass tree. The sequencing of passes is driven by
1544 : : the cgraph routines:
1545 : :
1546 : : finalize_compilation_unit ()
1547 : : for each node N in the cgraph
1548 : : cgraph_analyze_function (N)
1549 : : cgraph_lower_function (N) -> all_lowering_passes
1550 : :
1551 : : If we are optimizing, compile is then invoked:
1552 : :
1553 : : compile ()
1554 : : ipa_passes () -> all_small_ipa_passes
1555 : : -> Analysis of all_regular_ipa_passes
1556 : : * possible LTO streaming at compilation time *
1557 : : -> Execution of all_regular_ipa_passes
1558 : : * possible LTO streaming at link time *
1559 : : -> all_late_ipa_passes
1560 : : expand_all_functions ()
1561 : : for each node N in the cgraph
1562 : : expand_function (N) -> Transformation of all_regular_ipa_passes
1563 : : -> all_passes
1564 : : */
1565 : :
1566 : 280455 : pass_manager::pass_manager (context *ctxt)
1567 : 280455 : : all_passes (NULL), all_small_ipa_passes (NULL), all_lowering_passes (NULL),
1568 : 280455 : all_regular_ipa_passes (NULL),
1569 : 280455 : all_late_ipa_passes (NULL), passes_by_id (NULL), passes_by_id_size (0),
1570 : 280455 : m_ctxt (ctxt), m_name_to_pass_map (NULL)
1571 : : {
1572 : 280455 : opt_pass **p;
1573 : :
1574 : : /* Zero-initialize pass members. */
1575 : : #define INSERT_PASSES_AFTER(PASS)
1576 : : #define PUSH_INSERT_PASSES_WITHIN(PASS)
1577 : : #define POP_INSERT_PASSES()
1578 : : #define NEXT_PASS(PASS, NUM) PASS ## _ ## NUM = NULL
1579 : : #define NEXT_PASS_WITH_ARG(PASS, NUM, ARG) NEXT_PASS (PASS, NUM)
1580 : : #define TERMINATE_PASS_LIST(PASS)
1581 : : #include "pass-instances.def"
1582 : : #undef INSERT_PASSES_AFTER
1583 : : #undef PUSH_INSERT_PASSES_WITHIN
1584 : : #undef POP_INSERT_PASSES
1585 : : #undef NEXT_PASS
1586 : : #undef NEXT_PASS_WITH_ARG
1587 : : #undef TERMINATE_PASS_LIST
1588 : :
1589 : : /* Initialize the pass_lists array. */
1590 : : #define DEF_PASS_LIST(LIST) pass_lists[PASS_LIST_NO_##LIST] = &LIST;
1591 : 280455 : GCC_PASS_LISTS
1592 : : #undef DEF_PASS_LIST
1593 : :
1594 : : /* Build the tree of passes. */
1595 : :
1596 : : #define INSERT_PASSES_AFTER(PASS) \
1597 : : { \
1598 : : opt_pass **p_start; \
1599 : : p_start = p = &(PASS);
1600 : :
1601 : : #define TERMINATE_PASS_LIST(PASS) \
1602 : : gcc_assert (p_start == &PASS); \
1603 : : *p = NULL; \
1604 : : }
1605 : :
1606 : : #define PUSH_INSERT_PASSES_WITHIN(PASS) \
1607 : : { \
1608 : : opt_pass **p = &(PASS ## _1)->sub;
1609 : :
1610 : : #define POP_INSERT_PASSES() \
1611 : : }
1612 : :
1613 : : #define NEXT_PASS(PASS, NUM) \
1614 : : do { \
1615 : : gcc_assert (PASS ## _ ## NUM == NULL); \
1616 : : if ((NUM) == 1) \
1617 : : PASS ## _1 = make_##PASS (m_ctxt); \
1618 : : else \
1619 : : { \
1620 : : gcc_assert (PASS ## _1); \
1621 : : PASS ## _ ## NUM = PASS ## _1->clone (); \
1622 : : } \
1623 : : p = next_pass_1 (p, PASS ## _ ## NUM, PASS ## _1); \
1624 : : } while (0)
1625 : :
1626 : : #define NEXT_PASS_WITH_ARG(PASS, NUM, ARG) \
1627 : : do { \
1628 : : NEXT_PASS (PASS, NUM); \
1629 : : PASS ## _ ## NUM->set_pass_param (0, ARG); \
1630 : : } while (0)
1631 : :
1632 : : #include "pass-instances.def"
1633 : :
1634 : : #undef INSERT_PASSES_AFTER
1635 : : #undef PUSH_INSERT_PASSES_WITHIN
1636 : : #undef POP_INSERT_PASSES
1637 : : #undef NEXT_PASS
1638 : : #undef NEXT_PASS_WITH_ARG
1639 : : #undef TERMINATE_PASS_LIST
1640 : :
1641 : : /* Register the passes with the tree dump code. */
1642 : 280455 : register_dump_files (all_lowering_passes);
1643 : 280455 : register_dump_files (all_small_ipa_passes);
1644 : 280455 : register_dump_files (all_regular_ipa_passes);
1645 : 280455 : register_dump_files (all_late_ipa_passes);
1646 : 280455 : register_dump_files (all_passes);
1647 : 280455 : }
1648 : :
1649 : : static void
1650 : 96359936 : delete_pass_tree (opt_pass *pass)
1651 : : {
1652 : 191458617 : while (pass)
1653 : : {
1654 : : /* Recurse into child passes. */
1655 : 95098681 : delete_pass_tree (pass->sub);
1656 : :
1657 : 95098681 : opt_pass *next = pass->next;
1658 : :
1659 : : /* Delete this pass. */
1660 : 95098681 : delete pass;
1661 : :
1662 : : /* Iterate onto sibling passes. */
1663 : 95098681 : pass = next;
1664 : : }
1665 : 96359936 : }
1666 : :
1667 : 252251 : pass_manager::~pass_manager ()
1668 : : {
1669 : 252251 : XDELETEVEC (passes_by_id);
1670 : :
1671 : : /* Call delete_pass_tree on each of the pass_lists. */
1672 : : #define DEF_PASS_LIST(LIST) \
1673 : : delete_pass_tree (*pass_lists[PASS_LIST_NO_##LIST]);
1674 : 252251 : GCC_PASS_LISTS
1675 : : #undef DEF_PASS_LIST
1676 : :
1677 : 504502 : delete m_name_to_pass_map;
1678 : 252251 : }
1679 : :
1680 : : /* If we are in IPA mode (i.e., current_function_decl is NULL), call
1681 : : function CALLBACK for every function in the call graph. Otherwise,
1682 : : call CALLBACK on the current function. */
1683 : :
1684 : : static void
1685 : 1376362631 : do_per_function (void (*callback) (function *, void *data), void *data)
1686 : : {
1687 : 1376362631 : if (current_function_decl)
1688 : 1354856973 : callback (cfun, data);
1689 : : else
1690 : : {
1691 : 21505658 : struct cgraph_node *node;
1692 : 247801959 : FOR_EACH_DEFINED_FUNCTION (node)
1693 : 226296074 : if (node->analyzed && (gimple_has_body_p (node->decl) && !in_lto_p)
1694 : 421654741 : && (!node->clone_of || node->decl != node->clone_of->decl))
1695 : 173579931 : callback (DECL_STRUCT_FUNCTION (node->decl), data);
1696 : : }
1697 : 1376362631 : }
1698 : :
1699 : : /* Hook called when NODE is removed and therefore should be
1700 : : excluded from order vector. DATA is a hash set with removed nodes. */
1701 : :
1702 : : static void
1703 : 2582588 : remove_cgraph_node_from_order (cgraph_node *node, void *data)
1704 : : {
1705 : 2582588 : hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data;
1706 : 2582588 : removed_nodes->add (node);
1707 : 2582588 : }
1708 : :
1709 : : /* Hook called when NODE is insert and therefore should be
1710 : : excluded from removed_nodes. DATA is a hash set with removed nodes. */
1711 : :
1712 : : static void
1713 : 41778 : insert_cgraph_node_to_order (cgraph_node *node, void *data)
1714 : : {
1715 : 41778 : hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data;
1716 : 41778 : removed_nodes->remove (node);
1717 : 41778 : }
1718 : :
1719 : : /* Hook called when NODE is duplicated and therefore should be
1720 : : excluded from removed_nodes. DATA is a hash set with removed nodes. */
1721 : :
1722 : : static void
1723 : 1475384 : duplicate_cgraph_node_to_order (cgraph_node *node, cgraph_node *node2,
1724 : : void *data)
1725 : : {
1726 : 1475384 : hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data;
1727 : 1475384 : gcc_checking_assert (!removed_nodes->contains (node));
1728 : 1475384 : removed_nodes->remove (node2);
1729 : 1475384 : }
1730 : :
1731 : :
1732 : : /* If we are in IPA mode (i.e., current_function_decl is NULL), call
1733 : : function CALLBACK for every function in the call graph. Otherwise,
1734 : : call CALLBACK on the current function.
1735 : : This function is global so that plugins can use it. */
1736 : : void
1737 : 452816 : do_per_function_toporder (void (*callback) (function *, void *data), void *data)
1738 : : {
1739 : 452816 : int i;
1740 : :
1741 : 452816 : if (current_function_decl)
1742 : 0 : callback (cfun, data);
1743 : : else
1744 : : {
1745 : 452816 : hash_set<cgraph_node *> removed_nodes;
1746 : 452816 : unsigned nnodes = symtab->cgraph_count;
1747 : 452816 : cgraph_node **order = XNEWVEC (cgraph_node *, nnodes);
1748 : :
1749 : 452816 : nnodes = ipa_reverse_postorder (order);
1750 : 9830781 : for (i = nnodes - 1; i >= 0; i--)
1751 : 9377965 : order[i]->process = 1;
1752 : 452816 : cgraph_node_hook_list *removal_hook
1753 : 452816 : = symtab->add_cgraph_removal_hook (remove_cgraph_node_from_order,
1754 : : &removed_nodes);
1755 : 452816 : cgraph_node_hook_list *insertion_hook
1756 : 452816 : = symtab->add_cgraph_insertion_hook (insert_cgraph_node_to_order,
1757 : : &removed_nodes);
1758 : 452816 : cgraph_2node_hook_list *duplication_hook
1759 : 452816 : = symtab->add_cgraph_duplication_hook (duplicate_cgraph_node_to_order,
1760 : : &removed_nodes);
1761 : 9830781 : for (i = nnodes - 1; i >= 0; i--)
1762 : : {
1763 : 9377965 : cgraph_node *node = order[i];
1764 : :
1765 : : /* Function could be inlined and removed as unreachable. */
1766 : 9377965 : if (node == NULL || removed_nodes.contains (node))
1767 : 118 : continue;
1768 : :
1769 : 9377847 : node->process = 0;
1770 : 9377847 : if (node->has_gimple_body_p ())
1771 : : {
1772 : 5165173 : struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
1773 : 5165173 : push_cfun (fn);
1774 : 5165173 : callback (fn, data);
1775 : 5165173 : pop_cfun ();
1776 : : }
1777 : : }
1778 : 452816 : symtab->remove_cgraph_removal_hook (removal_hook);
1779 : 452816 : symtab->remove_cgraph_insertion_hook (insertion_hook);
1780 : 452816 : symtab->remove_cgraph_duplication_hook (duplication_hook);
1781 : :
1782 : 452816 : free (order);
1783 : 452816 : }
1784 : 452816 : }
1785 : :
1786 : : /* Helper function to perform function body dump. */
1787 : :
1788 : : static void
1789 : 51043 : execute_function_dump (function *fn, void *data)
1790 : : {
1791 : 51043 : opt_pass *pass = (opt_pass *)data;
1792 : :
1793 : 51043 : if (dump_file)
1794 : : {
1795 : 51043 : push_cfun (fn);
1796 : :
1797 : 51043 : if (fn->curr_properties & PROP_gimple)
1798 : 46924 : dump_function_to_file (fn->decl, dump_file, dump_flags);
1799 : : else
1800 : 4119 : print_rtl_with_bb (dump_file, get_insns (), dump_flags);
1801 : :
1802 : : /* Flush the file. If verification fails, we won't be able to
1803 : : close the file before aborting. */
1804 : 51043 : fflush (dump_file);
1805 : :
1806 : 51043 : if ((fn->curr_properties & PROP_cfg)
1807 : 51043 : && (dump_flags & TDF_GRAPH))
1808 : : {
1809 : 216 : gcc::dump_manager *dumps = g->get_dumps ();
1810 : 216 : struct dump_file_info *dfi
1811 : 216 : = dumps->get_dump_file_info (pass->static_pass_number);
1812 : 216 : if (!dfi->graph_dump_initialized)
1813 : : {
1814 : 59 : clean_graph_dump_file (dump_file_name);
1815 : 59 : dfi->graph_dump_initialized = true;
1816 : : }
1817 : 216 : print_graph_cfg (dump_file_name, fn);
1818 : : }
1819 : :
1820 : 51043 : pop_cfun ();
1821 : : }
1822 : 51043 : }
1823 : :
1824 : : /* This function is called when an internal compiler error is encountered.
1825 : : Ensure that function dump is made available before compiler is aborted. */
1826 : :
1827 : : void
1828 : 43 : emergency_dump_function ()
1829 : : {
1830 : 43 : if (!current_pass)
1831 : : return;
1832 : 12 : enum opt_pass_type pt = current_pass->type;
1833 : 12 : fnotice (stderr, "during %s pass: %s\n",
1834 : : pt == GIMPLE_PASS ? "GIMPLE" : pt == RTL_PASS ? "RTL" : "IPA",
1835 : : current_pass->name);
1836 : 12 : if (!dump_file || !cfun)
1837 : : return;
1838 : 0 : fnotice (stderr, "dump file: %s\n", dump_file_name);
1839 : 0 : fprintf (dump_file, "\n\n\nEMERGENCY DUMP:\n\n");
1840 : 0 : execute_function_dump (cfun, current_pass);
1841 : :
1842 : : /* Normally the passmanager will close the graphs as a pass could be wanting
1843 : : to print multiple digraphs. But during an emergency dump there can only be
1844 : : one and we must finish the graph manually. */
1845 : 0 : if ((cfun->curr_properties & PROP_cfg)
1846 : 0 : && (dump_flags & TDF_GRAPH))
1847 : 0 : finish_graph_dump_file (dump_file_name);
1848 : :
1849 : 0 : if (symtab && current_pass->type == IPA_PASS)
1850 : 0 : symtab->dump (dump_file);
1851 : : }
1852 : :
1853 : : static struct profile_record *profile_record;
1854 : :
1855 : : /* Do profile consistency book-keeping for the pass with static number INDEX.
1856 : : RUN is true if the pass really runs, or FALSE
1857 : : if we are only book-keeping on passes that may have selectively disabled
1858 : : themselves on a given function. */
1859 : :
1860 : : static void
1861 : 0 : check_profile_consistency (int index, bool run)
1862 : : {
1863 : 0 : pass_manager *passes = g->get_passes ();
1864 : 0 : if (index == -1)
1865 : : return;
1866 : 0 : if (!profile_record)
1867 : 0 : profile_record = XCNEWVEC (struct profile_record,
1868 : : passes->passes_by_id_size);
1869 : 0 : gcc_assert (index < passes->passes_by_id_size && index >= 0);
1870 : 0 : profile_record[index].run |= run;
1871 : 0 : profile_record_check_consistency (&profile_record[index]);
1872 : : }
1873 : :
1874 : : /* Account profile the pass with static number INDEX.
1875 : : RUN is true if the pass really runs, or FALSE
1876 : : if we are only book-keeping on passes that may have selectively disabled
1877 : : themselves on a given function. */
1878 : :
1879 : : static void
1880 : 0 : account_profile (int index, bool run)
1881 : : {
1882 : 0 : pass_manager *passes = g->get_passes ();
1883 : 0 : if (index == -1)
1884 : : return;
1885 : 0 : if (!profile_record)
1886 : 0 : profile_record = XCNEWVEC (struct profile_record,
1887 : : passes->passes_by_id_size);
1888 : 0 : gcc_assert (index < passes->passes_by_id_size && index >= 0);
1889 : 0 : profile_record[index].run |= run;
1890 : 0 : profile_record_account_profile (&profile_record[index]);
1891 : : }
1892 : :
1893 : : /* Account profile for IPA pass. Callback for do_per_function. */
1894 : :
1895 : : static void
1896 : 0 : account_profile_1 (function *fn, void *data)
1897 : : {
1898 : 0 : opt_pass *pass = (opt_pass *)data;
1899 : :
1900 : 0 : push_cfun (fn);
1901 : 0 : check_profile_consistency (pass->static_pass_number, true);
1902 : 0 : account_profile (pass->static_pass_number, true);
1903 : 0 : pop_cfun ();
1904 : 0 : }
1905 : :
1906 : : /* Account profile chnages to all passes in list starting in SUB. */
1907 : :
1908 : : static void
1909 : 0 : account_profile_in_list (opt_pass *sub)
1910 : : {
1911 : 0 : for (; sub; sub = sub->next)
1912 : : {
1913 : 0 : check_profile_consistency (sub->static_pass_number, false);
1914 : 0 : account_profile (sub->static_pass_number, false);
1915 : 0 : if (sub->sub)
1916 : 0 : account_profile_in_list (sub->sub);
1917 : : }
1918 : 0 : }
1919 : :
1920 : : /* Output profile consistency. */
1921 : :
1922 : : void
1923 : 0 : dump_profile_report (void)
1924 : : {
1925 : 0 : g->get_passes ()->dump_profile_report ();
1926 : 0 : }
1927 : :
1928 : : void
1929 : 0 : pass_manager::dump_profile_report () const
1930 : : {
1931 : 0 : int last_count_in = 0, last_prob_out = 0;
1932 : 0 : double last_dyn_count_in = 0, last_dyn_prob_out = 0;
1933 : 0 : double last_time = 0;
1934 : 0 : int last_size = 0;
1935 : 0 : double rel_time_change, rel_size_change;
1936 : 0 : gcc::dump_manager *dumps = m_ctxt->get_dumps ();
1937 : :
1938 : 0 : if (!profile_record)
1939 : : return;
1940 : :
1941 : 0 : FILE *dump_file = dump_begin (TDI_profile_report, NULL);
1942 : 0 : if (dump_file == NULL)
1943 : 0 : dump_file = stderr;
1944 : :
1945 : 0 : fprintf (dump_file, "Profile consistency report:\n\n");
1946 : 0 : fprintf (dump_file,
1947 : : "Pass dump id and name |static mismatch "
1948 : : "|dynamic mismatch "
1949 : : "|overall |\n");
1950 : 0 : fprintf (dump_file,
1951 : : " |in count |out prob "
1952 : : "|in count |out prob "
1953 : : "|size |time |\n");
1954 : :
1955 : 0 : for (int i = 1; i < passes_by_id_size; i++)
1956 : 0 : if (profile_record[i].run)
1957 : : {
1958 : 0 : if (last_time)
1959 : 0 : rel_time_change = (profile_record[i].time
1960 : 0 : - last_time) * 100 / last_time;
1961 : : else
1962 : : rel_time_change = 0;
1963 : 0 : if (last_size)
1964 : 0 : rel_size_change = (profile_record[i].size
1965 : 0 : - (double)last_size) * 100 / (double)last_size;
1966 : : else
1967 : : rel_size_change = 0;
1968 : :
1969 : 0 : dump_file_info *dfi = dumps->get_dump_file_info (i);
1970 : :
1971 : 0 : fprintf (dump_file, "%3i%c %-28s| %6i",
1972 : : dfi->num,
1973 : 0 : passes_by_id[i]->type == GIMPLE_PASS ? 't'
1974 : : : passes_by_id[i]->type == RTL_PASS ? 'r'
1975 : : : 'i',
1976 : 0 : passes_by_id[i]->name,
1977 : 0 : profile_record[i].num_mismatched_count_in);
1978 : 0 : if (profile_record[i].num_mismatched_count_in != last_count_in)
1979 : 0 : fprintf (dump_file, " %+5i",
1980 : : profile_record[i].num_mismatched_count_in
1981 : : - last_count_in);
1982 : : else
1983 : 0 : fprintf (dump_file, " ");
1984 : 0 : fprintf (dump_file, "| %6i",
1985 : 0 : profile_record[i].num_mismatched_prob_out);
1986 : 0 : if (profile_record[i].num_mismatched_prob_out != last_prob_out)
1987 : 0 : fprintf (dump_file, " %+5i",
1988 : : profile_record[i].num_mismatched_prob_out
1989 : : - last_prob_out);
1990 : : else
1991 : 0 : fprintf (dump_file, " ");
1992 : :
1993 : 0 : fprintf (dump_file, "| %12.0f",
1994 : 0 : profile_record[i].dyn_mismatched_count_in);
1995 : 0 : if (profile_record[i].dyn_mismatched_count_in != last_dyn_count_in)
1996 : 0 : fprintf (dump_file, " %+12.0f",
1997 : : profile_record[i].dyn_mismatched_count_in
1998 : : - last_dyn_count_in);
1999 : : else
2000 : 0 : fprintf (dump_file, " ");
2001 : 0 : fprintf (dump_file, "| %12.0f",
2002 : 0 : profile_record[i].dyn_mismatched_prob_out);
2003 : 0 : if (profile_record[i].dyn_mismatched_prob_out != last_dyn_prob_out)
2004 : 0 : fprintf (dump_file, " %+12.0f",
2005 : : profile_record[i].dyn_mismatched_prob_out
2006 : : - last_dyn_prob_out);
2007 : : else
2008 : 0 : fprintf (dump_file, " ");
2009 : :
2010 : : /* Size/time units change across gimple and RTL. */
2011 : 0 : if (i == pass_expand_1->static_pass_number)
2012 : 0 : fprintf (dump_file,
2013 : : "|-------------------|--------------------------");
2014 : : else
2015 : : {
2016 : 0 : fprintf (dump_file, "| %8i", profile_record[i].size);
2017 : 0 : if (rel_size_change)
2018 : 0 : fprintf (dump_file, " %+8.1f%%", rel_size_change);
2019 : : else
2020 : 0 : fprintf (dump_file, " ");
2021 : 0 : fprintf (dump_file, "| %12.0f", profile_record[i].time);
2022 : : /* Time units changes with profile estimate and feedback. */
2023 : 0 : if (i == pass_profile_1->static_pass_number
2024 : 0 : || i == pass_ipa_tree_profile_1->static_pass_number)
2025 : 0 : fprintf (dump_file, "-------------");
2026 : 0 : else if (rel_time_change)
2027 : 0 : fprintf (dump_file, " %+11.1f%%", rel_time_change);
2028 : : else
2029 : 0 : fprintf (dump_file, " ");
2030 : : }
2031 : 0 : fprintf (dump_file, "|\n");
2032 : 0 : last_prob_out = profile_record[i].num_mismatched_prob_out;
2033 : 0 : last_count_in = profile_record[i].num_mismatched_count_in;
2034 : 0 : last_dyn_prob_out = profile_record[i].dyn_mismatched_prob_out;
2035 : 0 : last_dyn_count_in = profile_record[i].dyn_mismatched_count_in;
2036 : 0 : last_time = profile_record[i].time;
2037 : 0 : last_size = profile_record[i].size;
2038 : : }
2039 : :
2040 : 0 : dump_end (TDI_profile_report, dump_file);
2041 : : }
2042 : :
2043 : : /* Perform all TODO actions that ought to be done on each function. */
2044 : :
2045 : : static void
2046 : 577811458 : execute_function_todo (function *fn, void *data)
2047 : : {
2048 : 577811458 : bool from_ipa_pass = (cfun == NULL);
2049 : 577811458 : unsigned int flags = (size_t)data;
2050 : 577811458 : flags &= ~fn->last_verified;
2051 : 577811458 : if (!flags)
2052 : : return;
2053 : :
2054 : 577811458 : push_cfun (fn);
2055 : :
2056 : : /* If we need to cleanup the CFG let it perform a needed SSA update. */
2057 : 577811458 : if (flags & TODO_cleanup_cfg)
2058 : 21748308 : cleanup_tree_cfg (flags & TODO_update_ssa_any);
2059 : 556063150 : else if (flags & TODO_update_ssa_any)
2060 : 31962532 : update_ssa (flags & TODO_update_ssa_any);
2061 : 577811458 : gcc_assert (!need_ssa_update_p (fn));
2062 : :
2063 : 577811458 : if (flag_tree_pta && (flags & TODO_rebuild_alias))
2064 : 4049568 : compute_may_aliases ();
2065 : :
2066 : 577811458 : if (optimize && (flags & TODO_update_address_taken))
2067 : 9173343 : execute_update_addresses_taken ();
2068 : :
2069 : 577811458 : if (flags & TODO_remove_unused_locals)
2070 : 8554574 : remove_unused_locals ();
2071 : :
2072 : 577811458 : if (flags & TODO_rebuild_cgraph_edges)
2073 : 1834 : cgraph_edge::rebuild_edges ();
2074 : :
2075 : 577811458 : gcc_assert (dom_info_state (fn, CDI_POST_DOMINATORS) == DOM_NONE);
2076 : : /* If we've seen errors do not bother running any verifiers. */
2077 : 577811458 : if (flag_checking && !seen_error ())
2078 : : {
2079 : 576904798 : dom_state pre_verify_state = dom_info_state (fn, CDI_DOMINATORS);
2080 : 576904798 : dom_state pre_verify_pstate = dom_info_state (fn, CDI_POST_DOMINATORS);
2081 : :
2082 : 576904798 : if (flags & TODO_verify_il)
2083 : : {
2084 : 316397023 : if (cfun->curr_properties & PROP_gimple)
2085 : : {
2086 : 233088672 : if (cfun->curr_properties & PROP_cfg)
2087 : : /* IPA passes leave stmts to be fixed up, so make sure to
2088 : : not verify stmts really throw. */
2089 : 221111176 : verify_gimple_in_cfg (cfun, !from_ipa_pass);
2090 : : else
2091 : 11977496 : verify_gimple_in_seq (gimple_body (cfun->decl));
2092 : : }
2093 : 316397023 : if (cfun->curr_properties & PROP_ssa)
2094 : : /* IPA passes leave stmts to be fixed up, so make sure to
2095 : : not verify SSA operands whose verifier will choke on that. */
2096 : 200566964 : verify_ssa (true, !from_ipa_pass);
2097 : : /* IPA passes leave basic-blocks unsplit, so make sure to
2098 : : not trip on that. */
2099 : 316397023 : if ((cfun->curr_properties & PROP_cfg)
2100 : 291660798 : && !from_ipa_pass)
2101 : 256656259 : verify_flow_info ();
2102 : 316397023 : if (current_loops
2103 : 316397023 : && ! loops_state_satisfies_p (LOOPS_NEED_FIXUP))
2104 : : {
2105 : 240211511 : verify_loop_structure ();
2106 : 240211511 : if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
2107 : 3241836 : verify_loop_closed_ssa (false);
2108 : : }
2109 : 316397023 : if (cfun->curr_properties & PROP_rtl)
2110 : 81915984 : verify_rtl_sharing ();
2111 : : }
2112 : :
2113 : : /* Make sure verifiers don't change dominator state. */
2114 : 576904798 : gcc_assert (dom_info_state (fn, CDI_DOMINATORS) == pre_verify_state);
2115 : 576904798 : gcc_assert (dom_info_state (fn, CDI_POST_DOMINATORS) == pre_verify_pstate);
2116 : : }
2117 : :
2118 : 577811458 : fn->last_verified = flags & TODO_verify_all;
2119 : :
2120 : 577811458 : pop_cfun ();
2121 : :
2122 : : /* For IPA passes make sure to release dominator info, it can be
2123 : : computed by non-verifying TODOs. */
2124 : 577811458 : if (from_ipa_pass)
2125 : : {
2126 : 68543536 : free_dominance_info (fn, CDI_DOMINATORS);
2127 : 68543536 : free_dominance_info (fn, CDI_POST_DOMINATORS);
2128 : : }
2129 : : }
2130 : :
2131 : : /* Perform all TODO actions. */
2132 : : static void
2133 : 576968942 : execute_todo (unsigned int flags)
2134 : : {
2135 : 576968942 : if (flag_checking
2136 : 576957792 : && cfun
2137 : 1145234856 : && need_ssa_update_p (cfun))
2138 : 1842296 : gcc_assert (flags & TODO_update_ssa_any);
2139 : :
2140 : 575126646 : statistics_fini_pass ();
2141 : :
2142 : 576968942 : if (flags)
2143 : 517733501 : do_per_function (execute_function_todo, (void *)(size_t) flags);
2144 : :
2145 : : /* At this point we should not have any unreachable code in the
2146 : : CFG, so it is safe to flush the pending freelist for SSA_NAMES. */
2147 : 576968942 : if (cfun && cfun->gimple_df)
2148 : 566882582 : flush_ssaname_freelist ();
2149 : :
2150 : : /* Always remove functions just as before inlining: IPA passes might be
2151 : : interested to see bodies of extern inline functions that are not inlined
2152 : : to analyze side effects. The full removal is done just at the end
2153 : : of IPA pass queue. */
2154 : 576968942 : if (flags & TODO_remove_functions)
2155 : : {
2156 : 937032 : gcc_assert (!cfun);
2157 : 937032 : symtab->remove_unreachable_nodes (dump_file);
2158 : : }
2159 : :
2160 : 576968942 : if ((flags & TODO_dump_symtab) && dump_file && !current_function_decl)
2161 : : {
2162 : 812 : gcc_assert (!cfun);
2163 : 812 : symtab->dump (dump_file);
2164 : : /* Flush the file. If verification fails, we won't be able to
2165 : : close the file before aborting. */
2166 : 812 : fflush (dump_file);
2167 : : }
2168 : :
2169 : : /* Now that the dumping has been done, we can get rid of the optional
2170 : : df problems. */
2171 : 576968942 : if (flags & TODO_df_finish)
2172 : 32064473 : df_finish_pass ((flags & TODO_df_verify) != 0);
2173 : 576968942 : }
2174 : :
2175 : : /* Verify invariants that should hold between passes. This is a place
2176 : : to put simple sanity checks. */
2177 : :
2178 : : static void
2179 : 288484375 : verify_interpass_invariants (void)
2180 : : {
2181 : 288484375 : gcc_checking_assert (!fold_deferring_overflow_warnings_p ());
2182 : 288484375 : }
2183 : :
2184 : : /* Clear the last verified flag. */
2185 : :
2186 : : static void
2187 : 316854786 : clear_last_verified (function *fn, void *data ATTRIBUTE_UNUSED)
2188 : : {
2189 : 316854786 : fn->last_verified = 0;
2190 : 316854786 : }
2191 : :
2192 : : /* Helper function. Verify that the properties has been turn into the
2193 : : properties expected by the pass. */
2194 : :
2195 : : static void
2196 : 316864831 : verify_curr_properties (function *fn, void *data)
2197 : : {
2198 : 316864831 : unsigned int props = (size_t)data;
2199 : 316864831 : gcc_assert ((fn->curr_properties & props) == props);
2200 : 316864831 : }
2201 : :
2202 : : /* Release dump file name if set. */
2203 : :
2204 : : static void
2205 : 552627052 : release_dump_file_name (void)
2206 : : {
2207 : 552627052 : if (dump_file_name)
2208 : : {
2209 : 51013 : free (CONST_CAST (char *, dump_file_name));
2210 : 51013 : dump_file_name = NULL;
2211 : : }
2212 : 552627052 : }
2213 : :
2214 : : /* Initialize pass dump file. */
2215 : : /* This is non-static so that the plugins can use it. */
2216 : :
2217 : : bool
2218 : 289855092 : pass_init_dump_file (opt_pass *pass)
2219 : : {
2220 : : /* If a dump file name is present, open it if enabled. */
2221 : 289855092 : if (pass->static_pass_number != -1)
2222 : : {
2223 : 262771981 : timevar_push (TV_DUMP);
2224 : 262771981 : gcc::dump_manager *dumps = g->get_dumps ();
2225 : 262771981 : bool initializing_dump =
2226 : 262771981 : !dumps->dump_initialized_p (pass->static_pass_number);
2227 : 262771981 : release_dump_file_name ();
2228 : 262771981 : dump_file_name = dumps->get_dump_file_name (pass->static_pass_number);
2229 : 262771981 : dumps->dump_start (pass->static_pass_number, &dump_flags);
2230 : 262771981 : if (dump_file && current_function_decl && ! (dump_flags & TDF_GIMPLE))
2231 : 48141 : dump_function_header (dump_file, current_function_decl, dump_flags);
2232 : 262771981 : if (initializing_dump
2233 : 262725552 : && dump_file && (dump_flags & TDF_GRAPH)
2234 : 262772154 : && cfun && (cfun->curr_properties & PROP_cfg))
2235 : : {
2236 : 97 : clean_graph_dump_file (dump_file_name);
2237 : 97 : struct dump_file_info *dfi
2238 : 97 : = dumps->get_dump_file_info (pass->static_pass_number);
2239 : 97 : dfi->graph_dump_initialized = true;
2240 : : }
2241 : 262771981 : timevar_pop (TV_DUMP);
2242 : 262771981 : return initializing_dump;
2243 : : }
2244 : : else
2245 : : return false;
2246 : : }
2247 : :
2248 : : /* Flush PASS dump file. */
2249 : : /* This is non-static so that plugins can use it. */
2250 : :
2251 : : void
2252 : 289855071 : pass_fini_dump_file (opt_pass *pass)
2253 : : {
2254 : 289855071 : timevar_push (TV_DUMP);
2255 : :
2256 : : /* Flush and close dump file. */
2257 : 289855071 : release_dump_file_name ();
2258 : :
2259 : 289855071 : g->get_dumps ()->dump_finish (pass->static_pass_number);
2260 : 289855071 : timevar_pop (TV_DUMP);
2261 : 289855071 : }
2262 : :
2263 : : /* After executing the pass, apply expected changes to the function
2264 : : properties. */
2265 : :
2266 : : static void
2267 : 316854786 : update_properties_after_pass (function *fn, void *data)
2268 : : {
2269 : 316854786 : opt_pass *pass = (opt_pass *) data;
2270 : 316854786 : fn->curr_properties = (fn->curr_properties | pass->properties_provided)
2271 : 316854786 : & ~pass->properties_destroyed;
2272 : 316854786 : }
2273 : :
2274 : : /* Execute summary generation for all of the passes in IPA_PASS. */
2275 : :
2276 : : void
2277 : 225017 : execute_ipa_summary_passes (ipa_opt_pass_d *ipa_pass)
2278 : : {
2279 : 4050320 : while (ipa_pass)
2280 : : {
2281 : 3825303 : opt_pass *pass = ipa_pass;
2282 : :
2283 : : /* Execute all of the IPA_PASSes in the list. */
2284 : 3825303 : if (ipa_pass->type == IPA_PASS
2285 : 3600286 : && pass->gate (cfun)
2286 : 6099322 : && ipa_pass->generate_summary)
2287 : : {
2288 : 1087307 : pass_init_dump_file (pass);
2289 : :
2290 : : /* If a timevar is present, start it. */
2291 : 1087307 : if (pass->tv_id)
2292 : 1087307 : timevar_push (pass->tv_id);
2293 : :
2294 : 1087307 : current_pass = pass;
2295 : 1087307 : ipa_pass->generate_summary ();
2296 : :
2297 : : /* Stop timevar. */
2298 : 1087307 : if (pass->tv_id)
2299 : 1087307 : timevar_pop (pass->tv_id);
2300 : :
2301 : 1087307 : pass_fini_dump_file (pass);
2302 : : }
2303 : 3825303 : ipa_pass = (ipa_opt_pass_d *)ipa_pass->next;
2304 : : }
2305 : 225017 : }
2306 : :
2307 : : /* Execute IPA_PASS function transform on NODE. */
2308 : :
2309 : : static void
2310 : 2289446 : execute_one_ipa_transform_pass (struct cgraph_node *node,
2311 : : ipa_opt_pass_d *ipa_pass, bool do_not_collect)
2312 : : {
2313 : 2289446 : opt_pass *pass = ipa_pass;
2314 : 2289446 : unsigned int todo_after = 0;
2315 : :
2316 : 2289446 : current_pass = pass;
2317 : 2289446 : if (!ipa_pass->function_transform)
2318 : : return;
2319 : :
2320 : : /* Note that the folders should only create gimple expressions.
2321 : : This is a hack until the new folder is ready. */
2322 : 2289446 : in_gimple_form = (cfun && (cfun->curr_properties & PROP_gimple)) != 0;
2323 : :
2324 : 2289446 : pass_init_dump_file (pass);
2325 : :
2326 : : /* If a timevar is present, start it. */
2327 : 2289446 : if (pass->tv_id != TV_NONE)
2328 : 2289446 : timevar_push (pass->tv_id);
2329 : :
2330 : : /* Run pre-pass verification. */
2331 : 2289446 : execute_todo (ipa_pass->function_transform_todo_flags_start);
2332 : :
2333 : : /* Do it! */
2334 : 2289446 : todo_after = ipa_pass->function_transform (node);
2335 : :
2336 : : /* Run post-pass cleanup and verification. */
2337 : 2289446 : execute_todo (todo_after);
2338 : 2289446 : verify_interpass_invariants ();
2339 : :
2340 : : /* Stop timevar. */
2341 : 2289446 : if (pass->tv_id != TV_NONE)
2342 : 2289446 : timevar_pop (pass->tv_id);
2343 : :
2344 : 2289446 : if (dump_file)
2345 : 1362 : do_per_function (execute_function_dump, pass);
2346 : 2289446 : pass_fini_dump_file (pass);
2347 : :
2348 : 2289446 : current_pass = NULL;
2349 : 2289446 : redirect_edge_var_map_empty ();
2350 : :
2351 : : /* Signal this is a suitable GC collection point. */
2352 : 2289446 : if (!do_not_collect && !(todo_after & TODO_do_not_ggc_collect))
2353 : 2267759 : ggc_collect ();
2354 : : }
2355 : :
2356 : : /* For the current function, execute all ipa transforms. */
2357 : :
2358 : : void
2359 : 1384170 : execute_all_ipa_transforms (bool do_not_collect)
2360 : : {
2361 : 1384170 : struct cgraph_node *node;
2362 : 1384170 : node = cgraph_node::get (current_function_decl);
2363 : :
2364 : :
2365 : 1384170 : cgraph_node *next_clone;
2366 : 1572194 : for (cgraph_node *n = node->clones; n; n = next_clone)
2367 : : {
2368 : 188024 : next_clone = n->next_sibling_clone;
2369 : 188024 : if (n->decl != node->decl)
2370 : 2215 : n->materialize_clone ();
2371 : : }
2372 : :
2373 : 1384170 : int j = 0;
2374 : 1384170 : gcc::pass_manager *passes = g->get_passes ();
2375 : 1384170 : bool report = profile_report && (cfun->curr_properties & PROP_gimple) != 0;
2376 : :
2377 : 0 : if (report)
2378 : 0 : push_cfun (DECL_STRUCT_FUNCTION (node->decl));
2379 : :
2380 : 6441956 : for (auto p : node->ipa_transforms_to_apply)
2381 : : {
2382 : : /* To get consistent statistics, we need to account each functio
2383 : : to each IPA pass. */
2384 : 2289446 : if (report)
2385 : : {
2386 : 0 : for (;j < p->static_pass_number; j++)
2387 : 0 : if (passes->get_pass_for_id (j)
2388 : 0 : && passes->get_pass_for_id (j)->type == IPA_PASS
2389 : 0 : && ((ipa_opt_pass_d *)passes->get_pass_for_id (j))
2390 : 0 : ->function_transform)
2391 : : {
2392 : 0 : check_profile_consistency (j, true);
2393 : 0 : account_profile (j, true);
2394 : : }
2395 : 0 : gcc_checking_assert (passes->get_pass_for_id (j) == p);
2396 : : }
2397 : 2289446 : execute_one_ipa_transform_pass (node, p, do_not_collect);
2398 : : }
2399 : : /* Account remaining IPA passes. */
2400 : 1384170 : if (report)
2401 : : {
2402 : 0 : for (;!passes->get_pass_for_id (j)
2403 : 0 : || passes->get_pass_for_id (j)->type != RTL_PASS; j++)
2404 : 0 : if (passes->get_pass_for_id (j)
2405 : 0 : && passes->get_pass_for_id (j)->type == IPA_PASS
2406 : 0 : && ((ipa_opt_pass_d *)passes->get_pass_for_id (j))
2407 : 0 : ->function_transform)
2408 : : {
2409 : 0 : check_profile_consistency (j, true);
2410 : 0 : account_profile (j, true);
2411 : : }
2412 : 0 : pop_cfun ();
2413 : : }
2414 : 1384170 : node->ipa_transforms_to_apply.release ();
2415 : 1384170 : }
2416 : :
2417 : : /* Check if PASS is explicitly disabled or enabled and return
2418 : : the gate status. FUNC is the function to be processed, and
2419 : : GATE_STATUS is the gate status determined by pass manager by
2420 : : default. */
2421 : :
2422 : : static bool
2423 : 417002589 : override_gate_status (opt_pass *pass, tree func, bool gate_status)
2424 : : {
2425 : 417002589 : bool explicitly_enabled = false;
2426 : 417002589 : bool explicitly_disabled = false;
2427 : :
2428 : 417002589 : explicitly_enabled
2429 : 417002589 : = is_pass_explicitly_enabled_or_disabled (pass, func,
2430 : : enabled_pass_uid_range_tab);
2431 : 417002589 : explicitly_disabled
2432 : 417002589 : = is_pass_explicitly_enabled_or_disabled (pass, func,
2433 : : disabled_pass_uid_range_tab);
2434 : :
2435 : 417002589 : gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
2436 : :
2437 : 417002589 : return gate_status;
2438 : : }
2439 : :
2440 : : /* Determine if PASS_NAME matches CRITERION.
2441 : : Not a pure predicate, since it can update CRITERION, to support
2442 : : matching the Nth invocation of a pass.
2443 : : Subroutine of should_skip_pass_p. */
2444 : :
2445 : : static bool
2446 : 5080 : determine_pass_name_match (const char *pass_name, char *criterion)
2447 : : {
2448 : 5080 : size_t namelen = strlen (pass_name);
2449 : 5080 : if (! strncmp (pass_name, criterion, namelen))
2450 : : {
2451 : : /* The following supports starting with the Nth invocation
2452 : : of a pass (where N does not necessarily is equal to the
2453 : : dump file suffix). */
2454 : 122 : if (criterion[namelen] == '\0'
2455 : 45 : || (criterion[namelen] == '1'
2456 : 24 : && criterion[namelen + 1] == '\0'))
2457 : : return true;
2458 : : else
2459 : : {
2460 : 21 : if (criterion[namelen + 1] == '\0')
2461 : 21 : --criterion[namelen];
2462 : 21 : return false;
2463 : : }
2464 : : }
2465 : : else
2466 : : return false;
2467 : : }
2468 : :
2469 : : /* For skipping passes until "startwith" pass.
2470 : : Return true iff PASS should be skipped.
2471 : : Clear cfun->pass_startwith when encountering the "startwith" pass,
2472 : : so that all subsequent passes are run. */
2473 : :
2474 : : static bool
2475 : 286199521 : should_skip_pass_p (opt_pass *pass)
2476 : : {
2477 : 286199521 : if (!cfun)
2478 : : return false;
2479 : 281853221 : if (!cfun->pass_startwith)
2480 : : return false;
2481 : :
2482 : : /* For __GIMPLE functions, we have to at least start when we leave
2483 : : SSA. Hence, we need to detect the "expand" pass, and stop skipping
2484 : : when we encounter it. A cheap way to identify "expand" is it to
2485 : : detect the destruction of PROP_ssa.
2486 : : For __RTL functions, we invoke "rest_of_compilation" directly, which
2487 : : is after "expand", and hence we don't reach this conditional. */
2488 : 5083 : if (pass->properties_destroyed & PROP_ssa)
2489 : : {
2490 : 3 : if (!quiet_flag)
2491 : 0 : fprintf (stderr, "starting anyway when leaving SSA: %s\n", pass->name);
2492 : 3 : cfun->pass_startwith = NULL;
2493 : 3 : return false;
2494 : : }
2495 : :
2496 : 5080 : if (determine_pass_name_match (pass->name, cfun->pass_startwith))
2497 : : {
2498 : 101 : if (!quiet_flag)
2499 : 0 : fprintf (stderr, "found starting pass: %s\n", pass->name);
2500 : 101 : cfun->pass_startwith = NULL;
2501 : 101 : return false;
2502 : : }
2503 : :
2504 : : /* For GIMPLE passes, run any property provider (but continue skipping
2505 : : afterwards).
2506 : : We don't want to force running RTL passes that are property providers:
2507 : : "expand" is covered above, and the only pass other than "expand" that
2508 : : provides a property is "into_cfglayout" (PROP_cfglayout), which does
2509 : : too much for a dumped __RTL function. */
2510 : 4979 : if (pass->type == GIMPLE_PASS
2511 : 4868 : && pass->properties_provided != 0)
2512 : : return false;
2513 : :
2514 : : /* We need to (re-)build cgraph edges as needed. */
2515 : 4650 : if (strstr (pass->name, "build_cgraph_edges") != NULL)
2516 : : return false;
2517 : :
2518 : : /* We need to run ISEL as that lowers VEC_COND_EXPR but doesn't provide
2519 : : a property. */
2520 : 4409 : if (strstr (pass->name, "isel") != NULL)
2521 : : return false;
2522 : :
2523 : : /* Don't skip df init; later RTL passes need it. */
2524 : 4406 : if (strstr (pass->name, "dfinit") != NULL
2525 : 4401 : || strstr (pass->name, "dfinish") != NULL)
2526 : : return false;
2527 : :
2528 : 4400 : if (!quiet_flag)
2529 : 0 : fprintf (stderr, "skipping pass: %s\n", pass->name);
2530 : :
2531 : : /* If we get here, then we have a "startwith" that we haven't seen yet;
2532 : : skip the pass. */
2533 : : return true;
2534 : : }
2535 : :
2536 : : /* Skip the given pass, for handling passes before "startwith"
2537 : : in __GIMPLE and__RTL-marked functions.
2538 : : In theory, this ought to be a no-op, but some of the RTL passes
2539 : : need additional processing here. */
2540 : :
2541 : : static void
2542 : 4400 : skip_pass (opt_pass *pass)
2543 : : {
2544 : : /* Pass "reload" sets the global "reload_completed", and many
2545 : : things depend on this (e.g. instructions in .md files). */
2546 : 4400 : if (strcmp (pass->name, "reload") == 0)
2547 : 3 : reload_completed = 1;
2548 : :
2549 : : /* Similar for pass "pro_and_epilogue" and the "epilogue_completed" global
2550 : : variable. */
2551 : 4400 : if (strcmp (pass->name, "pro_and_epilogue") == 0)
2552 : 2 : epilogue_completed = 1;
2553 : :
2554 : : /* The INSN_ADDRESSES vec is normally set up by
2555 : : shorten_branches; set it up for the benefit of passes that
2556 : : run after this. */
2557 : 4400 : if (strcmp (pass->name, "shorten") == 0)
2558 : 4 : INSN_ADDRESSES_ALLOC (get_max_uid ());
2559 : :
2560 : : /* Update the cfg hooks as appropriate. */
2561 : 4400 : if (strcmp (pass->name, "into_cfglayout") == 0)
2562 : : {
2563 : 6 : cfg_layout_rtl_register_cfg_hooks ();
2564 : 6 : cfun->curr_properties |= PROP_cfglayout;
2565 : : }
2566 : 4400 : if (strcmp (pass->name, "outof_cfglayout") == 0)
2567 : : {
2568 : 5 : rtl_register_cfg_hooks ();
2569 : 5 : cfun->curr_properties &= ~PROP_cfglayout;
2570 : : }
2571 : 4400 : }
2572 : :
2573 : : /* Execute PASS. */
2574 : :
2575 : : bool
2576 : 417000327 : execute_one_pass (opt_pass *pass)
2577 : : {
2578 : 417000327 : unsigned int todo_after = 0;
2579 : :
2580 : 417000327 : bool gate_status;
2581 : :
2582 : : /* IPA passes are executed on whole program, so cfun should be NULL.
2583 : : Other passes need function context set. */
2584 : 417000327 : if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
2585 : 7650061 : gcc_assert (!cfun && !current_function_decl);
2586 : : else
2587 : 409350266 : gcc_assert (cfun && current_function_decl);
2588 : :
2589 : 417000327 : current_pass = pass;
2590 : :
2591 : : /* Check whether gate check should be avoided.
2592 : : User controls the value of the gate through the parameter "gate_status". */
2593 : 417000327 : gate_status = pass->gate (cfun);
2594 : 417000327 : gate_status = override_gate_status (pass, current_function_decl, gate_status);
2595 : :
2596 : : /* Override gate with plugin. */
2597 : 417000327 : invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
2598 : :
2599 : 417000327 : if (!gate_status)
2600 : : {
2601 : : /* Run so passes selectively disabling themselves on a given function
2602 : : are not miscounted. */
2603 : 130800806 : if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)
2604 : 0 : && pass->type != IPA_PASS && pass->type != SIMPLE_IPA_PASS)
2605 : : {
2606 : 0 : check_profile_consistency (pass->static_pass_number, false);
2607 : 0 : account_profile (pass->static_pass_number, false);
2608 : 0 : if (pass->sub)
2609 : 0 : account_profile_in_list (pass->sub);
2610 : : }
2611 : 130800806 : current_pass = NULL;
2612 : 130800806 : return false;
2613 : : }
2614 : :
2615 : 286199521 : if (should_skip_pass_p (pass))
2616 : : {
2617 : 4400 : skip_pass (pass);
2618 : 4400 : return true;
2619 : : }
2620 : :
2621 : : /* Pass execution event trigger: useful to identify passes being
2622 : : executed. */
2623 : 286195121 : invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
2624 : :
2625 : 286195121 : if (!quiet_flag && !cfun)
2626 : 0 : fprintf (stderr, " <%s>", pass->name ? pass->name : "");
2627 : :
2628 : : /* Note that the folders should only create gimple expressions.
2629 : : This is a hack until the new folder is ready. */
2630 : 286195121 : in_gimple_form = (cfun && (cfun->curr_properties & PROP_gimple)) != 0;
2631 : :
2632 : 286195121 : pass_init_dump_file (pass);
2633 : :
2634 : : /* If a timevar is present, start it. */
2635 : 286195121 : if (pass->tv_id != TV_NONE)
2636 : 206864305 : timevar_push (pass->tv_id);
2637 : :
2638 : :
2639 : : /* Run pre-pass verification. */
2640 : 286195121 : execute_todo (pass->todo_flags_start);
2641 : :
2642 : 286195121 : if (flag_checking)
2643 : 286189587 : do_per_function (verify_curr_properties,
2644 : 286189587 : (void *)(size_t)pass->properties_required);
2645 : :
2646 : : /* Do it! */
2647 : 286195121 : todo_after = pass->execute (cfun);
2648 : :
2649 : 286195100 : if (todo_after & TODO_discard_function)
2650 : : {
2651 : : /* Stop timevar. */
2652 : 171 : if (pass->tv_id != TV_NONE)
2653 : 101 : timevar_pop (pass->tv_id);
2654 : :
2655 : 171 : pass_fini_dump_file (pass);
2656 : :
2657 : 171 : gcc_assert (cfun);
2658 : : /* As cgraph_node::release_body expects release dominators info,
2659 : : we have to release it. */
2660 : 171 : if (dom_info_available_p (CDI_DOMINATORS))
2661 : 108 : free_dominance_info (CDI_DOMINATORS);
2662 : :
2663 : 171 : if (dom_info_available_p (CDI_POST_DOMINATORS))
2664 : 0 : free_dominance_info (CDI_POST_DOMINATORS);
2665 : :
2666 : 171 : if (cfun->assume_function)
2667 : : {
2668 : : /* For assume functions, don't release body, keep it around. */
2669 : 101 : cfun->curr_properties |= PROP_assumptions_done;
2670 : 101 : pop_cfun ();
2671 : 101 : current_pass = NULL;
2672 : 101 : return true;
2673 : : }
2674 : :
2675 : 70 : tree fn = cfun->decl;
2676 : 70 : pop_cfun ();
2677 : 70 : gcc_assert (!cfun);
2678 : 70 : cgraph_node::get (fn)->release_body ();
2679 : :
2680 : 70 : current_pass = NULL;
2681 : 70 : redirect_edge_var_map_empty ();
2682 : :
2683 : 70 : ggc_collect ();
2684 : :
2685 : 70 : return true;
2686 : : }
2687 : :
2688 : 286194929 : do_per_function (clear_last_verified, NULL);
2689 : :
2690 : 286194929 : do_per_function (update_properties_after_pass, pass);
2691 : :
2692 : : /* Run post-pass cleanup and verification. */
2693 : 286194929 : execute_todo (todo_after | pass->todo_flags_finish | TODO_verify_il);
2694 : 286194929 : if (profile_report)
2695 : : {
2696 : : /* IPA passes are accounted at transform time. */
2697 : 0 : if (pass->type == IPA_PASS)
2698 : : ;
2699 : 0 : else if (pass->type == SIMPLE_IPA_PASS)
2700 : 0 : do_per_function (account_profile_1, pass);
2701 : 0 : else if (cfun && (cfun->curr_properties & PROP_cfg))
2702 : : {
2703 : 0 : check_profile_consistency (pass->static_pass_number, true);
2704 : 0 : account_profile (pass->static_pass_number, true);
2705 : : }
2706 : : }
2707 : :
2708 : 286194929 : verify_interpass_invariants ();
2709 : :
2710 : : /* Stop timevar. */
2711 : 286194929 : if (pass->tv_id != TV_NONE)
2712 : 206864204 : timevar_pop (pass->tv_id);
2713 : :
2714 : 286194929 : if (pass->type == IPA_PASS
2715 : 2310028 : && ((ipa_opt_pass_d *)pass)->function_transform)
2716 : : {
2717 : 347222 : struct cgraph_node *node;
2718 : 3938090 : FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
2719 : 3590868 : if (!node->inlined_to)
2720 : 2553746 : node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
2721 : : }
2722 : 285847707 : else if (dump_file)
2723 : 48323 : do_per_function (execute_function_dump, pass);
2724 : :
2725 : 286194929 : if (!current_function_decl)
2726 : 4346300 : symtab->process_new_functions ();
2727 : :
2728 : 286194929 : pass_fini_dump_file (pass);
2729 : :
2730 : 286194929 : if (pass->type != SIMPLE_IPA_PASS && pass->type != IPA_PASS)
2731 : 281848629 : gcc_assert (!(cfun->curr_properties & PROP_gimple)
2732 : : || pass->type != RTL_PASS);
2733 : :
2734 : 286194929 : current_pass = NULL;
2735 : 286194929 : redirect_edge_var_map_empty ();
2736 : :
2737 : : /* Signal this is a suitable GC collection point. */
2738 : 286194929 : if (!((todo_after | pass->todo_flags_finish) & TODO_do_not_ggc_collect))
2739 : 284802570 : ggc_collect ();
2740 : :
2741 : 286194929 : if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
2742 : 4346300 : report_heap_memory_use ();
2743 : : return true;
2744 : : }
2745 : :
2746 : : static void
2747 : 20019917 : execute_pass_list_1 (opt_pass *pass)
2748 : : {
2749 : 409350437 : do
2750 : : {
2751 : 409350437 : gcc_assert (pass->type == GIMPLE_PASS
2752 : : || pass->type == RTL_PASS);
2753 : :
2754 : 409350437 : if (cfun == NULL)
2755 : : return;
2756 : 409350266 : if (execute_one_pass (pass) && pass->sub)
2757 : 10852932 : execute_pass_list_1 (pass->sub);
2758 : 409350245 : pass = pass->next;
2759 : : }
2760 : 409350245 : while (pass);
2761 : : }
2762 : :
2763 : : void
2764 : 9166985 : execute_pass_list (function *fn, opt_pass *pass)
2765 : : {
2766 : 9166985 : gcc_assert (fn == cfun);
2767 : 9166985 : execute_pass_list_1 (pass);
2768 : 9166964 : if (cfun && fn->cfg)
2769 : : {
2770 : 7773801 : free_dominance_info (CDI_DOMINATORS);
2771 : 7773801 : free_dominance_info (CDI_POST_DOMINATORS);
2772 : : }
2773 : 9166964 : }
2774 : :
2775 : : /* Write out all LTO data. */
2776 : : static void
2777 : 32309 : write_lto (void)
2778 : : {
2779 : 32309 : timevar_push (TV_IPA_LTO_GIMPLE_OUT);
2780 : 32309 : lto_output ();
2781 : 32309 : timevar_pop (TV_IPA_LTO_GIMPLE_OUT);
2782 : 32309 : timevar_push (TV_IPA_LTO_DECL_OUT);
2783 : 32309 : produce_asm_for_decls ();
2784 : 32309 : timevar_pop (TV_IPA_LTO_DECL_OUT);
2785 : 32309 : }
2786 : :
2787 : : /* Same as execute_pass_list but assume that subpasses of IPA passes
2788 : : are local passes. If SET is not NULL, write out summaries of only
2789 : : those node in SET. */
2790 : :
2791 : : static void
2792 : 23298 : ipa_write_summaries_2 (opt_pass *pass, struct lto_out_decl_state *state)
2793 : : {
2794 : 419364 : while (pass)
2795 : : {
2796 : 396066 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *)pass;
2797 : 396066 : gcc_assert (!current_function_decl);
2798 : 396066 : gcc_assert (!cfun);
2799 : 396066 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
2800 : 396066 : if (pass->type == IPA_PASS
2801 : 372768 : && ipa_pass->write_summary
2802 : 559152 : && pass->gate (cfun))
2803 : : {
2804 : : /* If a timevar is present, start it. */
2805 : 143450 : if (pass->tv_id)
2806 : 143450 : timevar_push (pass->tv_id);
2807 : :
2808 : 143450 : pass_init_dump_file (pass);
2809 : :
2810 : 143450 : current_pass = pass;
2811 : 143450 : ipa_pass->write_summary ();
2812 : :
2813 : 143450 : pass_fini_dump_file (pass);
2814 : :
2815 : : /* If a timevar is present, start it. */
2816 : 143450 : if (pass->tv_id)
2817 : 143450 : timevar_pop (pass->tv_id);
2818 : : }
2819 : :
2820 : 396066 : if (pass->sub && pass->sub->type != GIMPLE_PASS)
2821 : 0 : ipa_write_summaries_2 (pass->sub, state);
2822 : :
2823 : 396066 : pass = pass->next;
2824 : : }
2825 : 23298 : }
2826 : :
2827 : : /* Helper function of ipa_write_summaries. Creates and destroys the
2828 : : decl state and calls ipa_write_summaries_2 for all passes that have
2829 : : summaries. SET is the set of nodes to be written. */
2830 : :
2831 : : static void
2832 : 23298 : ipa_write_summaries_1 (lto_symtab_encoder_t encoder)
2833 : : {
2834 : 23298 : pass_manager *passes = g->get_passes ();
2835 : 23298 : struct lto_out_decl_state *state = lto_new_out_decl_state ();
2836 : 23298 : state->symtab_node_encoder = encoder;
2837 : :
2838 : 23298 : lto_output_init_mode_table ();
2839 : 23298 : lto_push_out_decl_state (state);
2840 : :
2841 : 23298 : gcc_assert (!flag_wpa);
2842 : 23298 : ipa_write_summaries_2 (passes->all_regular_ipa_passes, state);
2843 : :
2844 : 23298 : write_lto ();
2845 : :
2846 : 23298 : gcc_assert (lto_get_out_decl_state () == state);
2847 : 23298 : lto_pop_out_decl_state ();
2848 : 23298 : lto_delete_out_decl_state (state);
2849 : 23298 : }
2850 : :
2851 : : /* Write out summaries for all the nodes in the callgraph. */
2852 : :
2853 : : void
2854 : 23298 : ipa_write_summaries (void)
2855 : : {
2856 : 23298 : lto_symtab_encoder_t encoder;
2857 : 23298 : int i, order_pos;
2858 : 23298 : varpool_node *vnode;
2859 : 23298 : struct cgraph_node *node;
2860 : 23298 : struct cgraph_node **order;
2861 : :
2862 : 23298 : if ((!flag_generate_lto && !flag_generate_offload) || seen_error ())
2863 : 0 : return;
2864 : :
2865 : 23298 : gcc_assert (!dump_file);
2866 : 23298 : streamer_dump_file = dump_begin (TDI_lto_stream_out, NULL);
2867 : :
2868 : 23298 : select_what_to_stream ();
2869 : :
2870 : 23298 : encoder = lto_symtab_encoder_new (false);
2871 : :
2872 : : /* Create the callgraph set in the same order used in
2873 : : cgraph_expand_all_functions. This mostly facilitates debugging,
2874 : : since it causes the gimple file to be processed in the same order
2875 : : as the source code. */
2876 : 23298 : order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
2877 : 23298 : order_pos = ipa_reverse_postorder (order);
2878 : 23298 : gcc_assert (order_pos == symtab->cgraph_count);
2879 : :
2880 : 355592 : for (i = order_pos - 1; i >= 0; i--)
2881 : : {
2882 : 332294 : struct cgraph_node *node = order[i];
2883 : :
2884 : 332294 : if ((node->definition || node->declare_variant_alt)
2885 : 101940 : && node->need_lto_streaming)
2886 : : {
2887 : 101940 : if (gimple_has_body_p (node->decl))
2888 : 99224 : lto_prepare_function_for_streaming (node);
2889 : 101940 : lto_set_symtab_encoder_in_partition (encoder, node);
2890 : : }
2891 : : }
2892 : :
2893 : 125237 : FOR_EACH_DEFINED_FUNCTION (node)
2894 : 101939 : if (node->alias && node->need_lto_streaming)
2895 : 2430 : lto_set_symtab_encoder_in_partition (encoder, node);
2896 : 278354 : FOR_EACH_DEFINED_VARIABLE (vnode)
2897 : 255056 : if (vnode->need_lto_streaming)
2898 : 255056 : lto_set_symtab_encoder_in_partition (encoder, vnode);
2899 : :
2900 : 23298 : ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
2901 : :
2902 : 23298 : free (order);
2903 : 23298 : if (streamer_dump_file)
2904 : : {
2905 : 4 : dump_end (TDI_lto_stream_out, streamer_dump_file);
2906 : 4 : streamer_dump_file = NULL;
2907 : : }
2908 : : }
2909 : :
2910 : : /* Same as execute_pass_list but assume that subpasses of IPA passes
2911 : : are local passes. If SET is not NULL, write out optimization summaries of
2912 : : only those node in SET. */
2913 : :
2914 : : static void
2915 : 9011 : ipa_write_optimization_summaries_1 (opt_pass *pass,
2916 : : struct lto_out_decl_state *state)
2917 : : {
2918 : 162198 : while (pass)
2919 : : {
2920 : 153187 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *)pass;
2921 : 153187 : gcc_assert (!current_function_decl);
2922 : 153187 : gcc_assert (!cfun);
2923 : 153187 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
2924 : 153187 : if (pass->type == IPA_PASS
2925 : 144176 : && ipa_pass->write_optimization_summary
2926 : 180220 : && pass->gate (cfun))
2927 : : {
2928 : : /* If a timevar is present, start it. */
2929 : 27033 : if (pass->tv_id)
2930 : 27033 : timevar_push (pass->tv_id);
2931 : :
2932 : 27033 : pass_init_dump_file (pass);
2933 : :
2934 : 27033 : current_pass = pass;
2935 : 27033 : ipa_pass->write_optimization_summary ();
2936 : :
2937 : 27033 : pass_fini_dump_file (pass);
2938 : :
2939 : : /* If a timevar is present, start it. */
2940 : 27033 : if (pass->tv_id)
2941 : 27033 : timevar_pop (pass->tv_id);
2942 : : }
2943 : :
2944 : 153187 : if (pass->sub && pass->sub->type != GIMPLE_PASS)
2945 : 0 : ipa_write_optimization_summaries_1 (pass->sub, state);
2946 : :
2947 : 153187 : pass = pass->next;
2948 : : }
2949 : 9011 : }
2950 : :
2951 : : /* Write all the optimization summaries for the cgraph nodes in SET. If SET is
2952 : : NULL, write out all summaries of all nodes. */
2953 : :
2954 : : void
2955 : 9011 : ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
2956 : : {
2957 : 9011 : struct lto_out_decl_state *state = lto_new_out_decl_state ();
2958 : 9011 : state->symtab_node_encoder = encoder;
2959 : :
2960 : 9011 : lto_output_init_mode_table ();
2961 : 9011 : lto_push_out_decl_state (state);
2962 : :
2963 : : /* Be sure that we did not forget to renumber stmt uids. */
2964 : 9011 : gcc_checking_assert (flag_wpa);
2965 : :
2966 : 9011 : gcc_assert (flag_wpa);
2967 : 9011 : pass_manager *passes = g->get_passes ();
2968 : 9011 : ipa_write_optimization_summaries_1 (passes->all_regular_ipa_passes, state);
2969 : :
2970 : 9011 : write_lto ();
2971 : :
2972 : 9011 : gcc_assert (lto_get_out_decl_state () == state);
2973 : 9011 : lto_pop_out_decl_state ();
2974 : 9011 : lto_delete_out_decl_state (state);
2975 : 9011 : }
2976 : :
2977 : : /* Same as execute_pass_list but assume that subpasses of IPA passes
2978 : : are local passes. */
2979 : :
2980 : : static void
2981 : 12737 : ipa_read_summaries_1 (opt_pass *pass)
2982 : : {
2983 : 229266 : while (pass)
2984 : : {
2985 : 216529 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
2986 : :
2987 : 216529 : gcc_assert (!current_function_decl);
2988 : 216529 : gcc_assert (!cfun);
2989 : 216529 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
2990 : :
2991 : 216529 : if (pass->gate (cfun))
2992 : : {
2993 : 200348 : if (pass->type == IPA_PASS && ipa_pass->read_summary)
2994 : : {
2995 : : /* If a timevar is present, start it. */
2996 : 85702 : if (pass->tv_id)
2997 : 85702 : timevar_push (pass->tv_id);
2998 : 85702 : if (!quiet_flag)
2999 : 0 : fprintf (stderr, " <%s>", pass->name ? pass->name : "");
3000 : :
3001 : 85702 : pass_init_dump_file (pass);
3002 : :
3003 : 85702 : current_pass = pass;
3004 : 85702 : ipa_pass->read_summary ();
3005 : :
3006 : 85702 : pass_fini_dump_file (pass);
3007 : :
3008 : : /* Stop timevar. */
3009 : 85702 : if (pass->tv_id)
3010 : 85702 : timevar_pop (pass->tv_id);
3011 : 85702 : ggc_grow ();
3012 : 85702 : report_heap_memory_use ();
3013 : : }
3014 : :
3015 : 200348 : if (pass->sub && pass->sub->type != GIMPLE_PASS)
3016 : 0 : ipa_read_summaries_1 (pass->sub);
3017 : : }
3018 : 216529 : pass = pass->next;
3019 : : }
3020 : 12737 : }
3021 : :
3022 : :
3023 : : /* Read all the summaries for all_regular_ipa_passes. */
3024 : :
3025 : : void
3026 : 12737 : ipa_read_summaries (void)
3027 : : {
3028 : 12737 : pass_manager *passes = g->get_passes ();
3029 : 12737 : ipa_read_summaries_1 (passes->all_regular_ipa_passes);
3030 : 12737 : }
3031 : :
3032 : : /* Same as execute_pass_list but assume that subpasses of IPA passes
3033 : : are local passes. */
3034 : :
3035 : : static void
3036 : 9011 : ipa_read_optimization_summaries_1 (opt_pass *pass)
3037 : : {
3038 : 162198 : while (pass)
3039 : : {
3040 : 153187 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
3041 : :
3042 : 153187 : gcc_assert (!current_function_decl);
3043 : 153187 : gcc_assert (!cfun);
3044 : 153187 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
3045 : :
3046 : 153187 : if (pass->gate (cfun))
3047 : : {
3048 : 131756 : if (pass->type == IPA_PASS && ipa_pass->read_optimization_summary)
3049 : : {
3050 : : /* If a timevar is present, start it. */
3051 : 27033 : if (pass->tv_id)
3052 : 27033 : timevar_push (pass->tv_id);
3053 : 27033 : if (!quiet_flag)
3054 : 0 : fprintf (stderr, " <%s>", pass->name ? pass->name : "");
3055 : :
3056 : 27033 : pass_init_dump_file (pass);
3057 : :
3058 : 27033 : current_pass = pass;
3059 : 27033 : ipa_pass->read_optimization_summary ();
3060 : :
3061 : 27033 : pass_fini_dump_file (pass);
3062 : :
3063 : : /* Stop timevar. */
3064 : 27033 : if (pass->tv_id)
3065 : 27033 : timevar_pop (pass->tv_id);
3066 : : }
3067 : :
3068 : 131756 : if (pass->sub && pass->sub->type != GIMPLE_PASS)
3069 : 0 : ipa_read_optimization_summaries_1 (pass->sub);
3070 : 131756 : ggc_grow ();
3071 : 131756 : report_heap_memory_use ();
3072 : : }
3073 : 153187 : pass = pass->next;
3074 : : }
3075 : 9011 : }
3076 : :
3077 : : /* Read all the summaries for all_regular_ipa_passes. */
3078 : :
3079 : : void
3080 : 9011 : ipa_read_optimization_summaries (void)
3081 : : {
3082 : 9011 : pass_manager *passes = g->get_passes ();
3083 : 9011 : ipa_read_optimization_summaries_1 (passes->all_regular_ipa_passes);
3084 : 9011 : }
3085 : :
3086 : : /* Same as execute_pass_list but assume that subpasses of IPA passes
3087 : : are local passes. */
3088 : : void
3089 : 676812 : execute_ipa_pass_list (opt_pass *pass)
3090 : : {
3091 : 7650061 : do
3092 : : {
3093 : 7650061 : gcc_assert (!current_function_decl);
3094 : 7650061 : gcc_assert (!cfun);
3095 : 7650061 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
3096 : 7650061 : if (execute_one_pass (pass) && pass->sub)
3097 : : {
3098 : 454876 : if (pass->sub->type == GIMPLE_PASS)
3099 : : {
3100 : 452816 : invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
3101 : 452816 : do_per_function_toporder ((void (*)(function *, void *))
3102 : : execute_pass_list,
3103 : 452816 : pass->sub);
3104 : 452816 : invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
3105 : : }
3106 : 2060 : else if (pass->sub->type == SIMPLE_IPA_PASS
3107 : 2060 : || pass->sub->type == IPA_PASS)
3108 : 2060 : execute_ipa_pass_list (pass->sub);
3109 : : else
3110 : 0 : gcc_unreachable ();
3111 : : }
3112 : 7650061 : gcc_assert (!current_function_decl);
3113 : 7650061 : symtab->process_new_functions ();
3114 : 7650061 : pass = pass->next;
3115 : : }
3116 : 7650061 : while (pass);
3117 : 676812 : }
3118 : :
3119 : : /* Execute stmt fixup hooks of all passes in PASS for NODE and STMTS. */
3120 : :
3121 : : static void
3122 : 81792 : execute_ipa_stmt_fixups (opt_pass *pass,
3123 : : struct cgraph_node *node, gimple **stmts)
3124 : : {
3125 : 1472256 : while (pass)
3126 : : {
3127 : : /* Execute all of the IPA_PASSes in the list. */
3128 : 1390464 : if (pass->type == IPA_PASS
3129 : 1390464 : && pass->gate (cfun))
3130 : : {
3131 : 1182739 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
3132 : :
3133 : 1182739 : if (ipa_pass->stmt_fixup)
3134 : : {
3135 : 0 : pass_init_dump_file (pass);
3136 : : /* If a timevar is present, start it. */
3137 : 0 : if (pass->tv_id)
3138 : 0 : timevar_push (pass->tv_id);
3139 : :
3140 : 0 : current_pass = pass;
3141 : 0 : ipa_pass->stmt_fixup (node, stmts);
3142 : :
3143 : : /* Stop timevar. */
3144 : 0 : if (pass->tv_id)
3145 : 0 : timevar_pop (pass->tv_id);
3146 : 0 : pass_fini_dump_file (pass);
3147 : : }
3148 : 1182739 : if (pass->sub)
3149 : 0 : execute_ipa_stmt_fixups (pass->sub, node, stmts);
3150 : : }
3151 : 1390464 : pass = pass->next;
3152 : : }
3153 : 81792 : }
3154 : :
3155 : : /* Execute stmt fixup hooks of all IPA passes for NODE and STMTS. */
3156 : :
3157 : : void
3158 : 81792 : execute_all_ipa_stmt_fixups (struct cgraph_node *node, gimple **stmts)
3159 : : {
3160 : 81792 : pass_manager *passes = g->get_passes ();
3161 : 81792 : execute_ipa_stmt_fixups (passes->all_regular_ipa_passes, node, stmts);
3162 : 81792 : }
3163 : :
3164 : :
3165 : : extern void debug_properties (unsigned int);
3166 : : extern void dump_properties (FILE *, unsigned int);
3167 : :
3168 : : DEBUG_FUNCTION void
3169 : 0 : dump_properties (FILE *dump, unsigned int props)
3170 : : {
3171 : 0 : fprintf (dump, "Properties:\n");
3172 : 0 : if (props & PROP_gimple_any)
3173 : 0 : fprintf (dump, "PROP_gimple_any\n");
3174 : 0 : if (props & PROP_gimple_lcf)
3175 : 0 : fprintf (dump, "PROP_gimple_lcf\n");
3176 : 0 : if (props & PROP_gimple_leh)
3177 : 0 : fprintf (dump, "PROP_gimple_leh\n");
3178 : 0 : if (props & PROP_cfg)
3179 : 0 : fprintf (dump, "PROP_cfg\n");
3180 : 0 : if (props & PROP_ssa)
3181 : 0 : fprintf (dump, "PROP_ssa\n");
3182 : 0 : if (props & PROP_no_crit_edges)
3183 : 0 : fprintf (dump, "PROP_no_crit_edges\n");
3184 : 0 : if (props & PROP_rtl)
3185 : 0 : fprintf (dump, "PROP_rtl\n");
3186 : 0 : if (props & PROP_gimple_lomp)
3187 : 0 : fprintf (dump, "PROP_gimple_lomp\n");
3188 : 0 : if (props & PROP_gimple_lomp_dev)
3189 : 0 : fprintf (dump, "PROP_gimple_lomp_dev\n");
3190 : 0 : if (props & PROP_gimple_lcx)
3191 : 0 : fprintf (dump, "PROP_gimple_lcx\n");
3192 : 0 : if (props & PROP_gimple_lvec)
3193 : 0 : fprintf (dump, "PROP_gimple_lvec\n");
3194 : 0 : if (props & PROP_cfglayout)
3195 : 0 : fprintf (dump, "PROP_cfglayout\n");
3196 : 0 : }
3197 : :
3198 : : DEBUG_FUNCTION void
3199 : 0 : debug_properties (unsigned int props)
3200 : : {
3201 : 0 : dump_properties (stderr, props);
3202 : 0 : }
3203 : :
3204 : : /* Called by local passes to see if function is called by already processed nodes.
3205 : : Because we process nodes in topological order, this means that function is
3206 : : in recursive cycle or we introduced new direct calls. */
3207 : : bool
3208 : 4214357 : function_called_by_processed_nodes_p (void)
3209 : : {
3210 : 4214357 : struct cgraph_edge *e;
3211 : 4214357 : for (e = cgraph_node::get (current_function_decl)->callers;
3212 : 10430040 : e;
3213 : 6215683 : e = e->next_caller)
3214 : : {
3215 : 6220293 : if (e->caller->decl == current_function_decl)
3216 : 0 : continue;
3217 : 6220293 : if (!e->caller->has_gimple_body_p ())
3218 : 0 : continue;
3219 : 6220293 : if (TREE_ASM_WRITTEN (e->caller->decl))
3220 : 0 : continue;
3221 : 6220293 : if (!e->caller->process && !e->caller->inlined_to)
3222 : : break;
3223 : : }
3224 : 4214357 : if (dump_file && e)
3225 : : {
3226 : 1 : fprintf (dump_file, "Already processed call to:\n");
3227 : 1 : e->caller->dump (dump_file);
3228 : : }
3229 : 4214357 : return e != NULL;
3230 : : }
|