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

source code of gcc/passes.cc