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