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 108429840 : opt_pass::gate (function *)
102 : {
103 108429840 : return true;
104 : }
105 :
106 : unsigned int
107 15352689 : opt_pass::execute (function *)
108 : {
109 15352689 : return 0;
110 : }
111 :
112 113421791 : opt_pass::opt_pass (const pass_data &data, context *ctxt)
113 : : pass_data (data),
114 113421791 : sub (NULL),
115 113421791 : next (NULL),
116 113421791 : static_pass_number (0),
117 113421791 : m_ctxt (ctxt)
118 : {
119 113421791 : }
120 :
121 :
122 : void
123 4897 : pass_manager::execute_early_local_passes ()
124 : {
125 4897 : execute_pass_list (cfun, m_pass_build_ssa_passes_1->sub);
126 4897 : execute_pass_list (cfun, m_pass_local_optimization_passes_1->sub);
127 4897 : }
128 :
129 : unsigned int
130 74342 : pass_manager::execute_pass_mode_switching ()
131 : {
132 74342 : 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 451049223 : rest_of_decl_compilation (tree decl,
177 : int top_level,
178 : int at_end)
179 : {
180 451049223 : 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 451049223 : if (!in_lto_p)
185 : {
186 450807360 : tree alias;
187 450807360 : alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
188 450807360 : if (alias)
189 : {
190 5672 : alias = TREE_VALUE (TREE_VALUE (alias));
191 5672 : 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 5672 : DECL_EXTERNAL (decl) = 0;
196 5672 : TREE_STATIC (decl) = 1;
197 5672 : assemble_alias (decl, alias);
198 5672 : finalize = false;
199 : }
200 : }
201 :
202 : /* Can't defer this, because it needs to happen before any
203 : later function definitions are processed. */
204 451049223 : if (HAS_DECL_ASSEMBLER_NAME_P (decl)
205 451049222 : && DECL_ASSEMBLER_NAME_SET_P (decl)
206 479208599 : && 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 411319085 : if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
212 468406039 : || TREE_CODE (decl) == FUNCTION_DECL)
213 : {
214 433923655 : 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 433923655 : if ((at_end
223 237192533 : || !DECL_DEFER_OUTPUT (decl)
224 15702205 : || DECL_INITIAL (decl))
225 418232907 : && (!VAR_P (decl) || !DECL_HAS_VALUE_EXPR_P (decl))
226 852155836 : && !DECL_EXTERNAL (decl))
227 : {
228 : /* When reading LTO unit, we also read varpool, so do not
229 : rebuild it. */
230 36019012 : if (in_lto_p && !at_end)
231 : ;
232 35814885 : else if (finalize && TREE_CODE (decl) != FUNCTION_DECL)
233 35116897 : varpool_node::finalize_decl (decl);
234 : }
235 :
236 : #ifdef ASM_FINISH_DECLARE_OBJECT
237 433923655 : 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 433923655 : if (TREE_CODE (decl) == FUNCTION_DECL)
247 393442177 : targetm.target_option.relayout_function (decl);
248 :
249 433923655 : timevar_pop (TV_VARCONST);
250 : }
251 17125568 : 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 17125568 : && !seen_error ())
255 : {
256 16938721 : timevar_push (TV_SYMOUT);
257 16938721 : debug_hooks->type_decl (decl, !top_level);
258 16938721 : timevar_pop (TV_SYMOUT);
259 : }
260 :
261 : /* Let cgraph know about the existence of variables. */
262 451049223 : if (in_lto_p && !at_end)
263 : ;
264 39754720 : else if (VAR_P (decl) && !DECL_EXTERNAL (decl)
265 486750220 : && TREE_STATIC (decl))
266 35941669 : 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 451049223 : if (!in_lto_p
277 450807360 : && (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 393272087 : || (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 57537171 : && !decl_function_context (decl)
314 53448748 : && !current_function_decl
315 53391576 : && DECL_SOURCE_LOCATION (decl) != BUILTINS_LOCATION
316 50565397 : && (!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 14123824 : || (finalize
326 14123821 : && VAR_P (decl)
327 12510580 : && TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
328 : /* Avoid confusing the debug information machinery when there are
329 : errors. */
330 498787226 : && !seen_error ())
331 46712650 : (*debug_hooks->early_global_decl) (decl);
332 451049223 : }
333 :
334 : /* Called after finishing a record, union or enumeral type. */
335 :
336 : void
337 59654549 : rest_of_type_compilation (tree type, int toplev)
338 : {
339 : /* Avoid confusing the debug information machinery when there are
340 : errors. */
341 59654549 : if (seen_error ())
342 : return;
343 :
344 58722838 : timevar_push (TV_SYMOUT);
345 58722838 : debug_hooks->type_decl (TYPE_STUB_DECL (type), !toplev);
346 58722838 : timevar_pop (TV_SYMOUT);
347 : }
348 :
349 :
350 :
351 : void
352 278943 : pass_manager::
353 : finish_optimization_passes (void)
354 : {
355 278943 : int i;
356 278943 : struct dump_file_info *dfi;
357 278943 : char *name;
358 278943 : gcc::dump_manager *dumps = m_ctxt->get_dumps ();
359 :
360 278943 : timevar_push (TV_DUMP);
361 :
362 : /* Do whatever is necessary to finish printing the graphs. */
363 103195028 : for (i = TDI_end; (dfi = dumps->get_dump_file_info (i)) != NULL; ++i)
364 102637142 : 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 278943 : timevar_pop (TV_DUMP);
372 278943 : }
373 :
374 : static unsigned int
375 232039 : 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 232039 : symtab->state = IPA_SSA;
385 232039 : 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 287872 : pass_build_ssa_passes (gcc::context *ctxt)
409 575744 : : simple_ipa_opt_pass (pass_data_build_ssa_passes, ctxt)
410 : {}
411 :
412 : /* opt_pass methods: */
413 232112 : bool gate (function *) final override
414 : {
415 : /* Don't bother doing anything if the program has errors. */
416 232112 : return (!seen_error () && !in_lto_p);
417 : }
418 :
419 232039 : unsigned int execute (function *) final override
420 : {
421 232039 : 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 287872 : pass_local_optimization_passes (gcc::context *ctxt)
443 575744 : : simple_ipa_opt_pass (pass_data_local_optimization_passes, ctxt)
444 : {}
445 :
446 : /* opt_pass methods: */
447 232112 : bool gate (function *) final override
448 : {
449 : /* Don't bother doing anything if the program has errors. */
450 232112 : 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 287872 : pass_ipa_remove_symbols (gcc::context *ctxt)
472 575744 : : simple_ipa_opt_pass (pass_data_ipa_remove_symbols, ctxt)
473 : {}
474 :
475 : /* opt_pass methods: */
476 232112 : bool gate (function *) final override
477 : {
478 : /* Don't bother doing anything if the program has errors. */
479 232112 : 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 287872 : make_pass_build_ssa_passes (gcc::context *ctxt)
488 : {
489 287872 : return new pass_build_ssa_passes (ctxt);
490 : }
491 :
492 : simple_ipa_opt_pass *
493 287872 : make_pass_local_optimization_passes (gcc::context *ctxt)
494 : {
495 287872 : return new pass_local_optimization_passes (ctxt);
496 : }
497 :
498 : simple_ipa_opt_pass *
499 287872 : make_pass_ipa_remove_symbols (gcc::context *ctxt)
500 : {
501 287872 : 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 287872 : pass_all_early_optimizations (gcc::context *ctxt)
523 575744 : : gimple_opt_pass (pass_data_all_early_optimizations, ctxt)
524 : {}
525 :
526 : /* opt_pass methods: */
527 2853135 : bool gate (function *) final override
528 : {
529 2853135 : return (optimize >= 1
530 : /* Don't bother doing anything if the program has errors. */
531 2853135 : && !seen_error ());
532 : }
533 :
534 : }; // class pass_all_early_optimizations
535 :
536 : } // anon namespace
537 :
538 : static gimple_opt_pass *
539 287872 : make_pass_all_early_optimizations (gcc::context *ctxt)
540 : {
541 287872 : 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 287872 : pass_all_optimizations (gcc::context *ctxt)
563 575744 : : gimple_opt_pass (pass_data_all_optimizations, ctxt)
564 : {}
565 :
566 : /* opt_pass methods: */
567 1481843 : bool gate (function *) final override
568 : {
569 1481843 : return optimize >= 1 && !optimize_debug;
570 : }
571 :
572 : }; // class pass_all_optimizations
573 :
574 : } // anon namespace
575 :
576 : static gimple_opt_pass *
577 287872 : make_pass_all_optimizations (gcc::context *ctxt)
578 : {
579 287872 : 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 287872 : pass_all_optimizations_g (gcc::context *ctxt)
601 575744 : : gimple_opt_pass (pass_data_all_optimizations_g, ctxt)
602 : {}
603 :
604 : /* opt_pass methods: */
605 1481843 : bool gate (function *) final override
606 : {
607 1481843 : return optimize >= 1 && optimize_debug;
608 : }
609 :
610 : }; // class pass_all_optimizations_g
611 :
612 : } // anon namespace
613 :
614 : static gimple_opt_pass *
615 287872 : make_pass_all_optimizations_g (gcc::context *ctxt)
616 : {
617 287872 : 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 287872 : pass_rest_of_compilation (gcc::context *ctxt)
639 575744 : : rtl_opt_pass (pass_data_rest_of_compilation, ctxt)
640 : {}
641 :
642 : /* opt_pass methods: */
643 1481747 : 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 1481747 : 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 287872 : make_pass_rest_of_compilation (gcc::context *ctxt)
656 : {
657 287872 : 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 287872 : pass_postreload (gcc::context *ctxt)
683 575744 : : rtl_opt_pass (pass_data_postreload, ctxt)
684 : {}
685 :
686 : /* opt_pass methods: */
687 1480955 : bool gate (function *) final override
688 : {
689 1480955 : if (reload_completed)
690 1480950 : gcc_checking_assert (!targetm.no_register_allocation);
691 1480955 : return reload_completed;
692 : }
693 :
694 : }; // class pass_postreload
695 :
696 : } // anon namespace
697 :
698 : static rtl_opt_pass *
699 287872 : make_pass_postreload (gcc::context *ctxt)
700 : {
701 287872 : 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 287872 : pass_late_compilation (gcc::context *ctxt)
726 575744 : : rtl_opt_pass (pass_data_late_compilation, ctxt)
727 : {}
728 :
729 : /* opt_pass methods: */
730 1480955 : bool gate (function *) final override
731 : {
732 1480955 : 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 287872 : make_pass_late_compilation (gcc::context *ctxt)
741 : {
742 287872 : 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 287872 : pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
766 575744 : : gimple_opt_pass (pass_data_pre_slp_scalar_cleanup, ctxt)
767 : {
768 : }
769 :
770 : bool
771 240838 : gate (function *fun) final override
772 : {
773 240838 : return flag_tree_slp_vectorize
774 240838 : && (fun->pending_TODOs & PENDING_TODO_force_next_scalar_cleanup);
775 : }
776 :
777 : unsigned int
778 31971 : execute (function *fun) final override
779 : {
780 31971 : fun->pending_TODOs &= ~PENDING_TODO_force_next_scalar_cleanup;
781 31971 : return 0;
782 : }
783 :
784 : }; // class pass_pre_slp_scalar_cleanup
785 :
786 : } // anon namespace
787 :
788 : gimple_opt_pass *
789 287872 : make_pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
790 : {
791 287872 : 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 104497709 : pass_manager::
799 : set_pass_for_id (int id, opt_pass *pass)
800 : {
801 104497709 : pass->static_pass_number = id;
802 104497709 : if (passes_by_id_size <= id)
803 : {
804 104497709 : passes_by_id = XRESIZEVEC (opt_pass *, passes_by_id, id + 1);
805 104497709 : memset (passes_by_id + passes_by_id_size, 0,
806 104497709 : (id + 1 - passes_by_id_size) * sizeof (void *));
807 104497709 : passes_by_id_size = id + 1;
808 : }
809 104497709 : passes_by_id[id] = pass;
810 104497709 : }
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 104497709 : pass_manager::register_one_dump_file (opt_pass *pass)
834 : {
835 104497709 : char *dot_name, *flag_name, *glob_name;
836 104497709 : const char *name, *full_name, *prefix;
837 :
838 : /* Buffer big enough to format a 32-bit UINT_MAX into. */
839 104497709 : char num[11];
840 104497709 : dump_kind dkind;
841 104497709 : int id;
842 104497709 : optgroup_flags_t optgroup_flags = OPTGROUP_NONE;
843 104497709 : gcc::dump_manager *dumps = m_ctxt->get_dumps ();
844 :
845 : /* See below in next_pass_1. */
846 104497709 : num[0] = '\0';
847 104497709 : if (pass->static_pass_number != -1)
848 63043968 : 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 104497709 : name = strchr (pass->name, ' ');
857 104497709 : name = name ? name + 1 : pass->name;
858 104497709 : dot_name = concat (".", name, num, NULL);
859 104497709 : 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 92982816 : else if (pass->type == GIMPLE_PASS)
866 : {
867 : prefix = "tree-";
868 : dkind = DK_tree;
869 : }
870 : else
871 : {
872 28211456 : prefix = "rtl-";
873 28211456 : dkind = DK_rtl;
874 : }
875 :
876 104497709 : flag_name = concat (prefix, name, num, NULL);
877 104497709 : glob_name = concat (prefix, name, NULL);
878 104497709 : 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 104497709 : if (optgroup_flags == OPTGROUP_NONE)
883 76574110 : optgroup_flags = OPTGROUP_OTHER;
884 104497709 : id = dumps->dump_register (dot_name, flag_name, glob_name, dkind,
885 : optgroup_flags,
886 : true);
887 104497709 : set_pass_for_id (id, pass);
888 104497709 : full_name = concat (prefix, pass->name, num, NULL);
889 104497709 : register_pass_name (pass, full_name);
890 104497709 : free (const_cast<char *> (full_name));
891 104497709 : }
892 :
893 : /* Register the dump files for the pass_manager starting at PASS. */
894 :
895 : void
896 7484672 : pass_manager::register_dump_files (opt_pass *pass)
897 : {
898 113421568 : do
899 : {
900 113421568 : if (pass->name && pass->name[0] != '*')
901 104497536 : register_one_dump_file (pass);
902 :
903 113421568 : if (pass->sub)
904 6045312 : register_dump_files (pass->sub);
905 :
906 113421568 : pass = pass->next;
907 : }
908 113421568 : while (pass);
909 7484672 : }
910 :
911 : /* Register PASS with NAME. */
912 :
913 : void
914 104497709 : pass_manager::register_pass_name (opt_pass *pass, const char *name)
915 : {
916 104497709 : if (!m_name_to_pass_map)
917 287872 : m_name_to_pass_map = new hash_map<free_string_hash, opt_pass *> (256);
918 :
919 104497709 : if (m_name_to_pass_map->get (name))
920 287873 : return; /* Ignore plugin passes. */
921 :
922 104209836 : const char *unique_name = xstrdup (name);
923 104209836 : 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 935953944 : is_pass_explicitly_enabled_or_disabled (opt_pass *pass,
1252 : tree func,
1253 : vec<uid_range_p> tab)
1254 : {
1255 935953944 : uid_range_p slot, range;
1256 935953944 : int cgraph_uid;
1257 935953944 : const char *aname = NULL;
1258 :
1259 935953944 : if (!tab.exists ()
1260 78124 : || (unsigned) pass->static_pass_number >= tab.length ()
1261 935953944 : || 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 113421741 : 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 113421741 : if (new_pass != initial_pass)
1322 : {
1323 : /* We're dealing with a clone. */
1324 25908480 : 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 25908480 : if ((new_pass->name && new_pass->name[0] != '*') || track_duplicates)
1331 : {
1332 23893376 : initial_pass->static_pass_number -= 1;
1333 23893376 : 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 87513261 : new_pass->todo_flags_start |= TODO_mark_first_instance;
1340 87513261 : new_pass->static_pass_number = -1;
1341 :
1342 87513261 : invoke_plugin_callbacks (PLUGIN_NEW_PASS, new_pass);
1343 : }
1344 113421741 : }
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 113421568 : 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 113421568 : gcc_assert (pass->name != NULL);
1354 :
1355 113421568 : add_pass_instance (pass, false, initial_pass);
1356 113421568 : *list = pass;
1357 :
1358 113421568 : 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 287872 : pass_manager::pass_manager (context *ctxt)
1578 287872 : : all_passes (NULL), all_small_ipa_passes (NULL), all_lowering_passes (NULL),
1579 287872 : all_regular_ipa_passes (NULL),
1580 287872 : all_late_ipa_passes (NULL), passes_by_id (NULL), passes_by_id_size (0),
1581 287872 : m_ctxt (ctxt), m_name_to_pass_map (NULL)
1582 : {
1583 287872 : 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 287872 : 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 287872 : register_dump_files (all_lowering_passes);
1654 287872 : register_dump_files (all_small_ipa_passes);
1655 287872 : register_dump_files (all_regular_ipa_passes);
1656 287872 : register_dump_files (all_late_ipa_passes);
1657 287872 : register_dump_files (all_passes);
1658 287872 : }
1659 :
1660 : static void
1661 103247690 : delete_pass_tree (opt_pass *pass)
1662 : {
1663 205201550 : while (pass)
1664 : {
1665 : /* Recurse into child passes. */
1666 101953860 : delete_pass_tree (pass->sub);
1667 :
1668 101953860 : opt_pass *next = pass->next;
1669 :
1670 : /* Delete this pass. */
1671 101953860 : delete pass;
1672 :
1673 : /* Iterate onto sibling passes. */
1674 101953860 : pass = next;
1675 : }
1676 103247690 : }
1677 :
1678 258766 : pass_manager::~pass_manager ()
1679 : {
1680 258766 : 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 258766 : GCC_PASS_LISTS
1686 : #undef DEF_PASS_LIST
1687 :
1688 517532 : delete m_name_to_pass_map;
1689 258766 : }
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 1209048088 : do_per_function (void (*callback) (function *, void *data), void *data)
1697 : {
1698 1209048088 : if (current_function_decl)
1699 1190602914 : callback (cfun, data);
1700 : else
1701 : {
1702 18445174 : struct cgraph_node *node;
1703 229503915 : FOR_EACH_DEFINED_FUNCTION (node)
1704 211058549 : if (node->analyzed && (gimple_has_body_p (node->decl) && !in_lto_p)
1705 393515613 : && (!node->clone_of || node->decl != node->clone_of->decl))
1706 160232873 : callback (DECL_STRUCT_FUNCTION (node->decl), data);
1707 : }
1708 1209048088 : }
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 3161836 : remove_cgraph_node_from_order (cgraph_node *node, void *data)
1715 : {
1716 3161836 : hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data;
1717 3161836 : removed_nodes->add (node);
1718 3161836 : }
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 46765 : insert_cgraph_node_to_order (cgraph_node *node, void *data)
1725 : {
1726 46765 : hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data;
1727 46765 : removed_nodes->remove (node);
1728 46765 : }
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 1881166 : duplicate_cgraph_node_to_order (cgraph_node *node, cgraph_node *node2,
1735 : void *data)
1736 : {
1737 1881166 : hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data;
1738 1881166 : gcc_checking_assert (!removed_nodes->contains (node));
1739 1881166 : removed_nodes->remove (node2);
1740 1881166 : }
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 466691 : do_per_function_toporder (void (*callback) (function *, void *data), void *data)
1749 : {
1750 466691 : int i;
1751 :
1752 466691 : if (current_function_decl)
1753 0 : callback (cfun, data);
1754 : else
1755 : {
1756 466691 : hash_set<cgraph_node *> removed_nodes;
1757 466691 : unsigned nnodes = symtab->cgraph_count;
1758 466691 : cgraph_node **order = XNEWVEC (cgraph_node *, nnodes);
1759 :
1760 466691 : nnodes = ipa_reverse_postorder (order);
1761 10531777 : for (i = nnodes - 1; i >= 0; i--)
1762 10065086 : order[i]->process = 1;
1763 466691 : cgraph_node_hook_list *removal_hook
1764 466691 : = symtab->add_cgraph_removal_hook (remove_cgraph_node_from_order,
1765 : &removed_nodes);
1766 466691 : cgraph_node_hook_list *insertion_hook
1767 466691 : = symtab->add_cgraph_insertion_hook (insert_cgraph_node_to_order,
1768 : &removed_nodes);
1769 466691 : cgraph_2node_hook_list *duplication_hook
1770 466691 : = symtab->add_cgraph_duplication_hook (duplicate_cgraph_node_to_order,
1771 : &removed_nodes);
1772 10531777 : for (i = nnodes - 1; i >= 0; i--)
1773 : {
1774 10065086 : cgraph_node *node = order[i];
1775 :
1776 : /* Function could be inlined and removed as unreachable. */
1777 10065086 : if (node == NULL || removed_nodes.contains (node))
1778 107 : continue;
1779 :
1780 10064979 : node->process = 0;
1781 10064979 : if (node->has_gimple_body_p ())
1782 : {
1783 5711221 : struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
1784 5711221 : push_cfun (fn);
1785 5711221 : callback (fn, data);
1786 5711221 : pop_cfun ();
1787 : }
1788 : }
1789 466691 : symtab->remove_cgraph_removal_hook (removal_hook);
1790 466691 : symtab->remove_cgraph_insertion_hook (insertion_hook);
1791 466691 : symtab->remove_cgraph_duplication_hook (duplication_hook);
1792 :
1793 466691 : free (order);
1794 466691 : }
1795 466691 : }
1796 :
1797 : /* Helper function to perform function body dump. */
1798 :
1799 : static void
1800 55386 : execute_function_dump (function *fn, void *data)
1801 : {
1802 55386 : opt_pass *pass = (opt_pass *)data;
1803 :
1804 55386 : if (dump_file)
1805 : {
1806 55386 : push_cfun (fn);
1807 :
1808 55386 : if (fn->curr_properties & PROP_gimple)
1809 51187 : dump_function_to_file (fn->decl, dump_file, dump_flags);
1810 : else
1811 4199 : 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 55386 : fflush (dump_file);
1816 :
1817 55386 : if ((fn->curr_properties & PROP_cfg)
1818 55386 : && (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 55386 : pop_cfun ();
1832 : }
1833 55386 : }
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 643477176 : execute_function_todo (function *fn, void *data)
2059 : {
2060 643477176 : bool from_ipa_pass = (cfun == NULL);
2061 643477176 : unsigned int flags = (size_t)data;
2062 643477176 : if (!flags)
2063 : return;
2064 :
2065 643477176 : push_cfun (fn);
2066 :
2067 : /* If we need to cleanup the CFG let it perform a needed SSA update. */
2068 643477176 : if (flags & TODO_cleanup_cfg)
2069 20538346 : cleanup_tree_cfg (flags & TODO_update_ssa_any);
2070 622938830 : else if (flags & TODO_update_ssa_any)
2071 30948743 : update_ssa (flags & TODO_update_ssa_any);
2072 643477176 : gcc_assert (!need_ssa_update_p (fn));
2073 :
2074 643477176 : if (flag_tree_pta && (flags & TODO_rebuild_alias))
2075 4423004 : compute_may_aliases ();
2076 :
2077 643477176 : if (optimize && (flags & TODO_update_address_taken))
2078 10017239 : execute_update_addresses_taken ();
2079 :
2080 643477176 : if (flags & TODO_remove_unused_locals)
2081 12872141 : remove_unused_locals ();
2082 :
2083 643477176 : if (flags & TODO_rebuild_cgraph_edges)
2084 1700 : cgraph_edge::rebuild_edges ();
2085 :
2086 643477176 : gcc_assert (dom_info_state (fn, CDI_POST_DOMINATORS) == DOM_NONE);
2087 : /* If we've seen errors do not bother running any verifiers. */
2088 643477176 : if (flag_checking && !seen_error ())
2089 : {
2090 642501160 : dom_state pre_verify_state = dom_info_state (fn, CDI_DOMINATORS);
2091 642501160 : dom_state pre_verify_pstate = dom_info_state (fn, CDI_POST_DOMINATORS);
2092 :
2093 642501160 : if (flags & TODO_verify_il)
2094 : {
2095 353153045 : if (cfun->curr_properties & PROP_gimple)
2096 : {
2097 257634948 : 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 243156896 : verify_gimple_in_cfg (cfun, !from_ipa_pass);
2101 : else
2102 14478052 : verify_gimple_in_seq (gimple_body (cfun->decl));
2103 : }
2104 353153045 : 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 220422860 : verify_ssa (true, !from_ipa_pass);
2108 : /* IPA passes leave basic-blocks unsplit, so make sure to
2109 : not trip on that. */
2110 353153045 : if ((cfun->curr_properties & PROP_cfg)
2111 324115944 : && !from_ipa_pass)
2112 283225849 : verify_flow_info ();
2113 353153045 : if (current_loops
2114 353153045 : && ! loops_state_satisfies_p (LOOPS_NEED_FIXUP))
2115 : {
2116 263717219 : verify_loop_structure ();
2117 263717219 : if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
2118 3855270 : verify_loop_closed_ssa (false);
2119 : }
2120 353153045 : if (cfun->curr_properties & PROP_rtl)
2121 94037133 : verify_rtl_sharing ();
2122 : }
2123 :
2124 : /* Make sure verifiers don't change dominator state. */
2125 642501160 : gcc_assert (dom_info_state (fn, CDI_DOMINATORS) == pre_verify_state);
2126 642501160 : gcc_assert (dom_info_state (fn, CDI_POST_DOMINATORS) == pre_verify_pstate);
2127 : }
2128 :
2129 643477176 : pop_cfun ();
2130 :
2131 : /* For IPA passes make sure to release dominator info, it can be
2132 : computed by non-verifying TODOs. */
2133 643477176 : if (from_ipa_pass)
2134 : {
2135 78433576 : free_dominance_info (fn, CDI_DOMINATORS);
2136 78433576 : free_dominance_info (fn, CDI_POST_DOMINATORS);
2137 : }
2138 : }
2139 :
2140 : /* Perform all TODO actions. */
2141 : static void
2142 639839726 : execute_todo (unsigned int flags)
2143 : {
2144 639839726 : if (flag_checking
2145 639830298 : && cfun
2146 1270215376 : && need_ssa_update_p (cfun))
2147 2127428 : gcc_assert (flags & TODO_update_ssa_any);
2148 :
2149 637712298 : statistics_fini_pass ();
2150 :
2151 639839726 : if (flags)
2152 574032256 : 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 639839726 : if (cfun && cfun->gimple_df)
2157 628900761 : 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 639839726 : if (flags & TODO_remove_functions)
2164 : {
2165 971282 : gcc_assert (!cfun);
2166 971282 : symtab->remove_unreachable_nodes (dump_file);
2167 : }
2168 :
2169 639839726 : 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 639839726 : if (flags & TODO_df_finish)
2181 39007488 : df_finish_pass ((flags & TODO_df_verify) != 0);
2182 639839726 : }
2183 :
2184 : /* Verify invariants that should hold between passes. This is a place
2185 : to put simple sanity checks. */
2186 :
2187 : static void
2188 319919767 : verify_interpass_invariants (void)
2189 : {
2190 319919767 : gcc_checking_assert (!fold_deferring_overflow_warnings_p ());
2191 319919767 : }
2192 :
2193 : /* Helper function. Verify that the properties has been turn into the
2194 : properties expected by the pass. */
2195 :
2196 : static void
2197 353656188 : verify_curr_properties (function *fn, void *data)
2198 : {
2199 353656188 : unsigned int props = (size_t)data;
2200 353656188 : gcc_assert ((fn->curr_properties & props) == props);
2201 353656188 : }
2202 :
2203 : /* Release dump file name if set. */
2204 :
2205 : static void
2206 613217030 : release_dump_file_name (void)
2207 : {
2208 613217030 : if (dump_file_name)
2209 : {
2210 55396 : free (const_cast<char *> (dump_file_name));
2211 55396 : dump_file_name = NULL;
2212 : }
2213 613217030 : }
2214 :
2215 : /* Initialize pass dump file. */
2216 : /* This is non-static so that the plugins can use it. */
2217 :
2218 : bool
2219 321335499 : pass_init_dump_file (opt_pass *pass)
2220 : {
2221 : /* If a dump file name is present, open it if enabled. */
2222 321335499 : if (pass->static_pass_number != -1)
2223 : {
2224 291881553 : timevar_push (TV_DUMP);
2225 291881553 : gcc::dump_manager *dumps = g->get_dumps ();
2226 291881553 : bool initializing_dump =
2227 291881553 : !dumps->dump_initialized_p (pass->static_pass_number);
2228 291881553 : release_dump_file_name ();
2229 291881553 : dump_file_name = dumps->get_dump_file_name (pass->static_pass_number);
2230 291881553 : dumps->dump_start (pass->static_pass_number, &dump_flags);
2231 291881553 : if (dump_file && current_function_decl && ! (dump_flags & TDF_GIMPLE))
2232 52601 : dump_function_header (dump_file, current_function_decl, dump_flags);
2233 291881553 : if (initializing_dump
2234 291832923 : && dump_file && (dump_flags & TDF_GRAPH)
2235 291881736 : && 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 291881553 : timevar_pop (TV_DUMP);
2243 291881553 : 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 321335477 : pass_fini_dump_file (opt_pass *pass)
2254 : {
2255 321335477 : timevar_push (TV_DUMP);
2256 :
2257 : /* Flush and close dump file. */
2258 321335477 : release_dump_file_name ();
2259 :
2260 321335477 : g->get_dumps ()->dump_finish (pass->static_pass_number);
2261 321335477 : timevar_pop (TV_DUMP);
2262 321335477 : }
2263 :
2264 : /* After executing the pass, apply expected changes to the function
2265 : properties. */
2266 :
2267 : static void
2268 353647037 : update_properties_after_pass (function *fn, void *data)
2269 : {
2270 353647037 : opt_pass *pass = (opt_pass *) data;
2271 353647037 : fn->curr_properties = (fn->curr_properties | pass->properties_provided)
2272 353647037 : & ~pass->properties_destroyed;
2273 353647037 : }
2274 :
2275 : /* Execute summary generation for all of the passes in IPA_PASS. */
2276 :
2277 : void
2278 231958 : execute_ipa_summary_passes (ipa_opt_pass_d *ipa_pass)
2279 : {
2280 4639173 : while (ipa_pass)
2281 : {
2282 4407215 : opt_pass *pass = ipa_pass;
2283 :
2284 : /* Execute all of the IPA_PASSes in the list. */
2285 4407215 : if (ipa_pass->type == IPA_PASS
2286 4175257 : && pass->gate (cfun)
2287 6768832 : && ipa_pass->generate_summary)
2288 : {
2289 1134353 : pass_init_dump_file (pass);
2290 :
2291 : /* If a timevar is present, start it. */
2292 1134353 : if (pass->tv_id)
2293 1134353 : timevar_push (pass->tv_id);
2294 :
2295 1134353 : current_pass = pass;
2296 1134353 : ipa_pass->generate_summary ();
2297 :
2298 : /* Stop timevar. */
2299 1134353 : if (pass->tv_id)
2300 1134353 : timevar_pop (pass->tv_id);
2301 :
2302 1134353 : pass_fini_dump_file (pass);
2303 : }
2304 4407215 : ipa_pass = (ipa_opt_pass_d *)ipa_pass->next;
2305 : }
2306 231958 : }
2307 :
2308 : /* Execute IPA_PASS function transform on NODE. */
2309 :
2310 : static void
2311 2436682 : execute_one_ipa_transform_pass (struct cgraph_node *node,
2312 : ipa_opt_pass_d *ipa_pass, bool do_not_collect)
2313 : {
2314 2436682 : opt_pass *pass = ipa_pass;
2315 2436682 : unsigned int todo_after = 0;
2316 :
2317 2436682 : current_pass = pass;
2318 2436682 : 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 2436682 : in_gimple_form = (cfun && (cfun->curr_properties & PROP_gimple)) != 0;
2324 :
2325 2436682 : pass_init_dump_file (pass);
2326 :
2327 : /* If a timevar is present, start it. */
2328 2436682 : if (pass->tv_id != TV_NONE)
2329 2436682 : timevar_push (pass->tv_id);
2330 :
2331 2436682 : gcc_checking_assert (!(ipa_pass->function_transform_todo_flags_start & TODO_verify_il));
2332 : /* Run pre-pass verification. */
2333 2436682 : execute_todo (ipa_pass->function_transform_todo_flags_start);
2334 :
2335 : /* Do it! */
2336 2436682 : todo_after = ipa_pass->function_transform (node);
2337 :
2338 : /* Run post-pass cleanup. */
2339 2436682 : gcc_checking_assert (!(todo_after & TODO_verify_il));
2340 2436682 : execute_todo (todo_after);
2341 2436682 : verify_interpass_invariants ();
2342 :
2343 : /* Stop timevar. */
2344 2436682 : if (pass->tv_id != TV_NONE)
2345 2436682 : timevar_pop (pass->tv_id);
2346 :
2347 2436682 : if (dump_file)
2348 1192 : do_per_function (execute_function_dump, pass);
2349 2436682 : pass_fini_dump_file (pass);
2350 :
2351 2436682 : current_pass = NULL;
2352 2436682 : redirect_edge_var_map_empty ();
2353 :
2354 : /* Signal this is a suitable GC collection point. */
2355 2436682 : if (!do_not_collect && !(todo_after & TODO_do_not_ggc_collect))
2356 2414504 : ggc_collect ();
2357 : }
2358 :
2359 : /* For the current function, execute all ipa transforms. */
2360 :
2361 : void
2362 1473341 : execute_all_ipa_transforms (bool do_not_collect)
2363 : {
2364 1473341 : struct cgraph_node *node;
2365 1473341 : node = cgraph_node::get (current_function_decl);
2366 :
2367 :
2368 1473341 : cgraph_node *next_clone;
2369 1730723 : for (cgraph_node *n = node->clones; n; n = next_clone)
2370 : {
2371 257382 : next_clone = n->next_sibling_clone;
2372 257382 : if (n->decl != node->decl)
2373 3146 : n->materialize_clone ();
2374 : }
2375 :
2376 1473341 : int j = 0;
2377 1473341 : gcc::pass_manager *passes = g->get_passes ();
2378 1473341 : 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 6856705 : 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 2436682 : 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 2436682 : execute_one_ipa_transform_pass (node, p, do_not_collect);
2401 : }
2402 : /* Account remaining IPA passes. */
2403 1473341 : 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 1473341 : node->ipa_transforms_to_apply.release ();
2418 1473341 : }
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 467976972 : override_gate_status (opt_pass *pass, tree func, bool gate_status)
2427 : {
2428 467976972 : bool explicitly_enabled = false;
2429 467976972 : bool explicitly_disabled = false;
2430 :
2431 467976972 : explicitly_enabled
2432 467976972 : = is_pass_explicitly_enabled_or_disabled (pass, func,
2433 : enabled_pass_uid_range_tab);
2434 467976972 : explicitly_disabled
2435 467976972 : = is_pass_explicitly_enabled_or_disabled (pass, func,
2436 : disabled_pass_uid_range_tab);
2437 :
2438 467976972 : gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
2439 :
2440 467976972 : 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 317489987 : should_skip_pass_p (opt_pass *pass)
2479 : {
2480 317489987 : if (!cfun)
2481 : return false;
2482 312762330 : 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 467975002 : execute_one_pass (opt_pass *pass)
2580 : {
2581 467975002 : namespace pass_events = gcc::topics::pass_events;
2582 :
2583 467975002 : unsigned int todo_after = 0;
2584 :
2585 467975002 : bool gate_status;
2586 :
2587 467975002 : 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 467975002 : if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
2593 9060607 : gcc_assert (!cfun && !current_function_decl);
2594 : else
2595 458914395 : gcc_assert (cfun && current_function_decl);
2596 :
2597 467975002 : 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 467975002 : gate_status = pass->gate (cfun);
2602 467975002 : gate_status = override_gate_status (pass, current_function_decl, gate_status);
2603 :
2604 : /* Override gate with plugin. */
2605 467975002 : invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
2606 :
2607 467975002 : if (!gate_status)
2608 : {
2609 : /* Run so passes selectively disabling themselves on a given function
2610 : are not miscounted. */
2611 150485015 : 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 150485015 : current_pass = NULL;
2620 150485015 : return false;
2621 : }
2622 :
2623 317489987 : 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 317483277 : invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
2632 :
2633 317483277 : 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 317483277 : in_gimple_form = (cfun && (cfun->curr_properties & PROP_gimple)) != 0;
2639 :
2640 317483277 : pass_init_dump_file (pass);
2641 :
2642 : /* If a timevar is present, start it. */
2643 317483277 : if (pass->tv_id != TV_NONE)
2644 230055371 : timevar_push (pass->tv_id);
2645 :
2646 :
2647 : /* Run pre-pass verification. */
2648 317483277 : gcc_checking_assert (!(pass->todo_flags_start & TODO_verify_il));
2649 317483277 : execute_todo (pass->todo_flags_start);
2650 :
2651 317483277 : if (flag_checking)
2652 317478597 : do_per_function (verify_curr_properties,
2653 317478597 : (void *)(size_t)pass->properties_required);
2654 :
2655 : /* Do it! */
2656 317483277 : todo_after = pass->execute (cfun);
2657 :
2658 317483255 : 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 317483085 : do_per_function (update_properties_after_pass, pass);
2698 :
2699 : /* Run post-pass cleanup and verification. */
2700 317483085 : gcc_checking_assert (!(todo_after & TODO_verify_il));
2701 317483085 : gcc_checking_assert (!(pass->todo_flags_finish & TODO_verify_il));
2702 317483085 : execute_todo (todo_after | pass->todo_flags_finish | TODO_verify_il);
2703 317483085 : 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 317483085 : verify_interpass_invariants ();
2718 :
2719 : /* Stop timevar. */
2720 317483085 : if (pass->tv_id != TV_NONE)
2721 230055262 : timevar_pop (pass->tv_id);
2722 :
2723 317483085 : if (pass->type == IPA_PASS
2724 2395699 : && ((ipa_opt_pass_d *)pass)->function_transform)
2725 : {
2726 360033 : struct cgraph_node *node;
2727 4418458 : FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
2728 4058425 : if (!node->inlined_to)
2729 2743398 : node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
2730 : }
2731 317123052 : else if (dump_file)
2732 52958 : do_per_function (execute_function_dump, pass);
2733 :
2734 317483085 : if (!current_function_decl)
2735 4727657 : symtab->process_new_functions ();
2736 :
2737 317483085 : pass_fini_dump_file (pass);
2738 :
2739 317483085 : if (pass->type != SIMPLE_IPA_PASS && pass->type != IPA_PASS)
2740 312755428 : gcc_assert (!(cfun->curr_properties & PROP_gimple)
2741 : || pass->type != RTL_PASS);
2742 :
2743 317483085 : current_pass = NULL;
2744 317483085 : redirect_edge_var_map_empty ();
2745 :
2746 : /* Signal this is a suitable GC collection point. */
2747 317483085 : if (!((todo_after | pass->todo_flags_finish) & TODO_do_not_ggc_collect))
2748 316002138 : ggc_collect ();
2749 :
2750 317483085 : if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
2751 4727657 : report_heap_memory_use ();
2752 :
2753 317483085 : 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 21762760 : execute_pass_list_1 (opt_pass *pass)
2761 : {
2762 458914565 : do
2763 : {
2764 458914565 : gcc_assert (pass->type == GIMPLE_PASS
2765 : || pass->type == RTL_PASS);
2766 :
2767 458914565 : if (cfun == NULL)
2768 : return;
2769 458914395 : if (execute_one_pass (pass) && pass->sub)
2770 11685992 : execute_pass_list_1 (pass->sub);
2771 458914373 : pass = pass->next;
2772 : }
2773 458914373 : while (pass);
2774 : }
2775 :
2776 : void
2777 10076768 : execute_pass_list (function *fn, opt_pass *pass)
2778 : {
2779 10076768 : gcc_assert (fn == cfun);
2780 10076768 : execute_pass_list_1 (pass);
2781 10076746 : if (cfun && fn->cfg)
2782 : {
2783 8594813 : free_dominance_info (CDI_DOMINATORS);
2784 8594813 : free_dominance_info (CDI_POST_DOMINATORS);
2785 : }
2786 10076746 : }
2787 :
2788 : /* Write out all LTO data. */
2789 : static void
2790 31189 : write_lto (void)
2791 : {
2792 31189 : timevar_push (TV_IPA_LTO_GIMPLE_OUT);
2793 31189 : lto_output ();
2794 31189 : timevar_pop (TV_IPA_LTO_GIMPLE_OUT);
2795 31189 : timevar_push (TV_IPA_LTO_DECL_OUT);
2796 31189 : produce_asm_for_decls ();
2797 31189 : timevar_pop (TV_IPA_LTO_DECL_OUT);
2798 31189 : }
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 22999 : ipa_write_summaries_2 (opt_pass *pass, struct lto_out_decl_state *state)
2806 : {
2807 459980 : while (pass)
2808 : {
2809 436981 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *)pass;
2810 436981 : gcc_assert (!current_function_decl);
2811 436981 : gcc_assert (!cfun);
2812 436981 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
2813 436981 : if (pass->type == IPA_PASS
2814 413982 : && ipa_pass->write_summary
2815 597974 : && pass->gate (cfun))
2816 : {
2817 : /* If a timevar is present, start it. */
2818 148630 : if (pass->tv_id)
2819 148630 : timevar_push (pass->tv_id);
2820 :
2821 148630 : pass_init_dump_file (pass);
2822 :
2823 148630 : current_pass = pass;
2824 148630 : ipa_pass->write_summary ();
2825 :
2826 148630 : pass_fini_dump_file (pass);
2827 :
2828 : /* If a timevar is present, start it. */
2829 148630 : if (pass->tv_id)
2830 148630 : timevar_pop (pass->tv_id);
2831 : }
2832 :
2833 436981 : if (pass->sub && pass->sub->type != GIMPLE_PASS)
2834 0 : ipa_write_summaries_2 (pass->sub, state);
2835 :
2836 436981 : pass = pass->next;
2837 : }
2838 22999 : }
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 22999 : ipa_write_summaries_1 (lto_symtab_encoder_t encoder,
2846 : bool output_offload_tables_p)
2847 : {
2848 22999 : pass_manager *passes = g->get_passes ();
2849 22999 : struct lto_out_decl_state *state = lto_new_out_decl_state ();
2850 22999 : state->symtab_node_encoder = encoder;
2851 22999 : state->output_offload_tables_p = output_offload_tables_p;
2852 :
2853 22999 : lto_output_init_mode_table ();
2854 22999 : lto_push_out_decl_state (state);
2855 :
2856 22999 : gcc_assert (!flag_wpa);
2857 22999 : ipa_write_summaries_2 (passes->all_regular_ipa_passes, state);
2858 :
2859 22999 : write_lto ();
2860 :
2861 22999 : gcc_assert (lto_get_out_decl_state () == state);
2862 22999 : lto_pop_out_decl_state ();
2863 22999 : lto_delete_out_decl_state (state);
2864 22999 : }
2865 :
2866 : /* Write out summaries for all the nodes in the callgraph. */
2867 :
2868 : void
2869 22999 : ipa_write_summaries (void)
2870 : {
2871 22999 : lto_symtab_encoder_t encoder;
2872 22999 : int i, order_pos;
2873 22999 : varpool_node *vnode;
2874 22999 : struct cgraph_node *node;
2875 22999 : struct cgraph_node **order;
2876 :
2877 22999 : if ((!flag_generate_lto && !flag_generate_offload) || seen_error ())
2878 0 : return;
2879 :
2880 22999 : gcc_assert (!dump_file);
2881 22999 : streamer_dump_file = dump_begin (TDI_lto_stream_out, NULL);
2882 :
2883 22999 : select_what_to_stream ();
2884 :
2885 22999 : 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 22999 : order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
2892 22999 : order_pos = ipa_reverse_postorder (order);
2893 22999 : gcc_assert (order_pos == symtab->cgraph_count);
2894 :
2895 360542 : for (i = order_pos - 1; i >= 0; i--)
2896 : {
2897 337543 : struct cgraph_node *node = order[i];
2898 :
2899 337543 : if (node->definition && node->need_lto_streaming)
2900 : {
2901 104665 : if (gimple_has_body_p (node->decl))
2902 101947 : lto_prepare_function_for_streaming (node);
2903 104665 : lto_set_symtab_encoder_in_partition (encoder, node);
2904 : }
2905 : }
2906 :
2907 127664 : FOR_EACH_DEFINED_FUNCTION (node)
2908 104665 : if (node->alias && node->need_lto_streaming)
2909 2433 : lto_set_symtab_encoder_in_partition (encoder, node);
2910 280569 : FOR_EACH_DEFINED_VARIABLE (vnode)
2911 257570 : if (vnode->need_lto_streaming)
2912 257570 : lto_set_symtab_encoder_in_partition (encoder, vnode);
2913 :
2914 22999 : asm_node *anode;
2915 23083 : 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 22999 : ipa_write_summaries_1 (compute_ltrans_boundary (encoder),
2920 22999 : flag_generate_offload);
2921 :
2922 22999 : free (order);
2923 22999 : 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 12211 : ipa_read_summaries_1 (opt_pass *pass)
3004 : {
3005 244220 : while (pass)
3006 : {
3007 232009 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
3008 :
3009 232009 : gcc_assert (!current_function_decl);
3010 232009 : gcc_assert (!cfun);
3011 232009 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
3012 :
3013 232009 : if (pass->gate (cfun))
3014 : {
3015 193334 : if (pass->type == IPA_PASS && ipa_pass->read_summary)
3016 : {
3017 : /* If a timevar is present, start it. */
3018 83417 : if (pass->tv_id)
3019 83417 : timevar_push (pass->tv_id);
3020 83417 : if (!quiet_flag)
3021 0 : fprintf (stderr, " <%s>", pass->name ? pass->name : "");
3022 :
3023 83417 : pass_init_dump_file (pass);
3024 :
3025 83417 : current_pass = pass;
3026 83417 : ipa_pass->read_summary ();
3027 :
3028 83417 : pass_fini_dump_file (pass);
3029 :
3030 : /* Stop timevar. */
3031 83417 : if (pass->tv_id)
3032 83417 : timevar_pop (pass->tv_id);
3033 83417 : ggc_grow ();
3034 83417 : report_heap_memory_use ();
3035 : }
3036 :
3037 193334 : if (pass->sub && pass->sub->type != GIMPLE_PASS)
3038 0 : ipa_read_summaries_1 (pass->sub);
3039 : }
3040 232009 : pass = pass->next;
3041 : }
3042 12211 : }
3043 :
3044 :
3045 : /* Read all the summaries for all_regular_ipa_passes. */
3046 :
3047 : void
3048 12211 : ipa_read_summaries (void)
3049 : {
3050 12211 : pass_manager *passes = g->get_passes ();
3051 12211 : ipa_read_summaries_1 (passes->all_regular_ipa_passes);
3052 12211 : }
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 120839 : 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 120839 : if (pass->sub && pass->sub->type != GIMPLE_PASS)
3091 0 : ipa_read_optimization_summaries_1 (pass->sub);
3092 120839 : ggc_grow ();
3093 120839 : 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 699061 : execute_ipa_pass_list (opt_pass *pass)
3112 : {
3113 9060607 : do
3114 : {
3115 9060607 : gcc_assert (!current_function_decl);
3116 9060607 : gcc_assert (!cfun);
3117 9060607 : gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
3118 9060607 : if (execute_one_pass (pass) && pass->sub)
3119 : {
3120 468718 : if (pass->sub->type == GIMPLE_PASS)
3121 : {
3122 466691 : invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
3123 466691 : do_per_function_toporder ((void (*)(function *, void *))
3124 : execute_pass_list,
3125 466691 : pass->sub);
3126 466691 : invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
3127 : }
3128 2027 : else if (pass->sub->type == SIMPLE_IPA_PASS
3129 2027 : || pass->sub->type == IPA_PASS)
3130 2027 : execute_ipa_pass_list (pass->sub);
3131 : else
3132 0 : gcc_unreachable ();
3133 : }
3134 9060607 : gcc_assert (!current_function_decl);
3135 9060607 : symtab->process_new_functions ();
3136 9060607 : pass = pass->next;
3137 : }
3138 9060607 : while (pass);
3139 699061 : }
3140 :
3141 : /* Execute stmt fixup hooks of all passes in PASS for NODE and STMTS. */
3142 :
3143 : static void
3144 83582 : execute_ipa_stmt_fixups (opt_pass *pass,
3145 : struct cgraph_node *node, gimple **stmts)
3146 : {
3147 1671640 : while (pass)
3148 : {
3149 : /* Execute all of the IPA_PASSes in the list. */
3150 1588058 : if (pass->type == IPA_PASS
3151 1588058 : && pass->gate (cfun))
3152 : {
3153 1210300 : ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
3154 :
3155 1210300 : 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 1210300 : if (pass->sub)
3171 0 : execute_ipa_stmt_fixups (pass->sub, node, stmts);
3172 : }
3173 1588058 : pass = pass->next;
3174 : }
3175 83582 : }
3176 :
3177 : /* Execute stmt fixup hooks of all IPA passes for NODE and STMTS. */
3178 :
3179 : void
3180 83582 : execute_all_ipa_stmt_fixups (struct cgraph_node *node, gimple **stmts)
3181 : {
3182 83582 : pass_manager *passes = g->get_passes ();
3183 83582 : execute_ipa_stmt_fixups (passes->all_regular_ipa_passes, node, stmts);
3184 83582 : }
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 4648671 : function_called_by_processed_nodes_p (void)
3231 : {
3232 4648671 : struct cgraph_edge *e;
3233 4648671 : for (e = cgraph_node::get (current_function_decl)->callers;
3234 11982148 : e;
3235 7333477 : e = e->next_caller)
3236 : {
3237 7336821 : if (e->caller->decl == current_function_decl)
3238 0 : continue;
3239 7336821 : if (!e->caller->has_gimple_body_p ())
3240 0 : continue;
3241 7336821 : if (TREE_ASM_WRITTEN (e->caller->decl))
3242 0 : continue;
3243 7336821 : if (!e->caller->process && !e->caller->inlined_to)
3244 : break;
3245 : }
3246 4648671 : if (dump_file && e)
3247 : {
3248 1 : fprintf (dump_file, "Already processed call to:\n");
3249 1 : e->caller->dump (dump_file);
3250 : }
3251 4648671 : return e != NULL;
3252 : }
|