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