xref: /dflybsd-src/contrib/gcc-8.0/gcc/passes.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Top level of GCC compilers (cc1, cc1plus, etc.)
238fd1498Szrj    Copyright (C) 1987-2018 Free Software Foundation, Inc.
338fd1498Szrj 
438fd1498Szrj This file is part of GCC.
538fd1498Szrj 
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
738fd1498Szrj the terms of the GNU General Public License as published by the Free
838fd1498Szrj Software Foundation; either version 3, or (at your option) any later
938fd1498Szrj version.
1038fd1498Szrj 
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1238fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1338fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1438fd1498Szrj for more details.
1538fd1498Szrj 
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3.  If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>.  */
1938fd1498Szrj 
2038fd1498Szrj /* This is the top level of cc1/c++.
2138fd1498Szrj    It parses command args, opens files, invokes the various passes
2238fd1498Szrj    in the proper order, and counts the time used by each.
2338fd1498Szrj    Error messages and low-level interface to malloc also handled here.  */
2438fd1498Szrj 
2538fd1498Szrj #include "config.h"
2638fd1498Szrj #include "system.h"
2738fd1498Szrj #include "coretypes.h"
2838fd1498Szrj #include "backend.h"
2938fd1498Szrj #include "target.h"
3038fd1498Szrj #include "rtl.h"
3138fd1498Szrj #include "tree.h"
3238fd1498Szrj #include "gimple.h"
3338fd1498Szrj #include "cfghooks.h"
3438fd1498Szrj #include "df.h"
3538fd1498Szrj #include "memmodel.h"
3638fd1498Szrj #include "tm_p.h"
3738fd1498Szrj #include "ssa.h"
3838fd1498Szrj #include "emit-rtl.h"
3938fd1498Szrj #include "cgraph.h"
4038fd1498Szrj #include "lto-streamer.h"
4138fd1498Szrj #include "fold-const.h"
4238fd1498Szrj #include "varasm.h"
4338fd1498Szrj #include "output.h"
4438fd1498Szrj #include "graph.h"
4538fd1498Szrj #include "debug.h"
4638fd1498Szrj #include "cfgloop.h"
4738fd1498Szrj #include "value-prof.h"
4838fd1498Szrj #include "tree-cfg.h"
4938fd1498Szrj #include "tree-ssa-loop-manip.h"
5038fd1498Szrj #include "tree-into-ssa.h"
5138fd1498Szrj #include "tree-dfa.h"
5238fd1498Szrj #include "tree-ssa.h"
5338fd1498Szrj #include "tree-pass.h"
5438fd1498Szrj #include "plugin.h"
5538fd1498Szrj #include "ipa-utils.h"
5638fd1498Szrj #include "tree-pretty-print.h" /* for dump_function_header */
5738fd1498Szrj #include "context.h"
5838fd1498Szrj #include "pass_manager.h"
5938fd1498Szrj #include "cfgrtl.h"
6038fd1498Szrj #include "tree-ssa-live.h"  /* For remove_unused_locals.  */
6138fd1498Szrj #include "tree-cfgcleanup.h"
6238fd1498Szrj #include "insn-addr.h" /* for INSN_ADDRESSES_ALLOC.  */
6338fd1498Szrj #include "diagnostic-core.h" /* for fnotice */
6438fd1498Szrj #include "stringpool.h"
6538fd1498Szrj #include "attribs.h"
6638fd1498Szrj 
6738fd1498Szrj using namespace gcc;
6838fd1498Szrj 
6938fd1498Szrj /* This is used for debugging.  It allows the current pass to printed
7038fd1498Szrj    from anywhere in compilation.
7138fd1498Szrj    The variable current_pass is also used for statistics and plugins.  */
7238fd1498Szrj opt_pass *current_pass;
7338fd1498Szrj 
7438fd1498Szrj /* Most passes are single-instance (within their context) and thus don't
7538fd1498Szrj    need to implement cloning, but passes that support multiple instances
7638fd1498Szrj    *must* provide their own implementation of the clone method.
7738fd1498Szrj 
7838fd1498Szrj    Handle this by providing a default implemenation, but make it a fatal
7938fd1498Szrj    error to call it.  */
8038fd1498Szrj 
8138fd1498Szrj opt_pass *
clone()8238fd1498Szrj opt_pass::clone ()
8338fd1498Szrj {
8438fd1498Szrj   internal_error ("pass %s does not support cloning", name);
8538fd1498Szrj }
8638fd1498Szrj 
8738fd1498Szrj void
set_pass_param(unsigned int,bool)8838fd1498Szrj opt_pass::set_pass_param (unsigned int, bool)
8938fd1498Szrj {
9038fd1498Szrj   internal_error ("pass %s needs a set_pass_param implementation to handle the"
9138fd1498Szrj 		  " extra argument in NEXT_PASS", name);
9238fd1498Szrj }
9338fd1498Szrj 
9438fd1498Szrj bool
gate(function *)9538fd1498Szrj opt_pass::gate (function *)
9638fd1498Szrj {
9738fd1498Szrj   return true;
9838fd1498Szrj }
9938fd1498Szrj 
10038fd1498Szrj unsigned int
execute(function *)10138fd1498Szrj opt_pass::execute (function *)
10238fd1498Szrj {
10338fd1498Szrj   return 0;
10438fd1498Szrj }
10538fd1498Szrj 
opt_pass(const pass_data & data,context * ctxt)10638fd1498Szrj opt_pass::opt_pass (const pass_data &data, context *ctxt)
10738fd1498Szrj   : pass_data (data),
10838fd1498Szrj     sub (NULL),
10938fd1498Szrj     next (NULL),
11038fd1498Szrj     static_pass_number (0),
11138fd1498Szrj     m_ctxt (ctxt)
11238fd1498Szrj {
11338fd1498Szrj }
11438fd1498Szrj 
11538fd1498Szrj 
11638fd1498Szrj void
execute_early_local_passes()11738fd1498Szrj pass_manager::execute_early_local_passes ()
11838fd1498Szrj {
11938fd1498Szrj   execute_pass_list (cfun, pass_build_ssa_passes_1->sub);
12038fd1498Szrj   if (flag_check_pointer_bounds)
12138fd1498Szrj     execute_pass_list (cfun, pass_chkp_instrumentation_passes_1->sub);
12238fd1498Szrj   execute_pass_list (cfun, pass_local_optimization_passes_1->sub);
12338fd1498Szrj }
12438fd1498Szrj 
12538fd1498Szrj unsigned int
execute_pass_mode_switching()12638fd1498Szrj pass_manager::execute_pass_mode_switching ()
12738fd1498Szrj {
12838fd1498Szrj   return pass_mode_switching_1->execute (cfun);
12938fd1498Szrj }
13038fd1498Szrj 
13138fd1498Szrj 
13238fd1498Szrj /* Call from anywhere to find out what pass this is.  Useful for
13338fd1498Szrj    printing out debugging information deep inside an service
13438fd1498Szrj    routine.  */
13538fd1498Szrj void
print_current_pass(FILE * file)13638fd1498Szrj print_current_pass (FILE *file)
13738fd1498Szrj {
13838fd1498Szrj   if (current_pass)
13938fd1498Szrj     fprintf (file, "current pass = %s (%d)\n",
14038fd1498Szrj 	     current_pass->name, current_pass->static_pass_number);
14138fd1498Szrj   else
14238fd1498Szrj     fprintf (file, "no current pass.\n");
14338fd1498Szrj }
14438fd1498Szrj 
14538fd1498Szrj 
14638fd1498Szrj /* Call from the debugger to get the current pass name.  */
14738fd1498Szrj DEBUG_FUNCTION void
debug_pass(void)14838fd1498Szrj debug_pass (void)
14938fd1498Szrj {
15038fd1498Szrj   print_current_pass (stderr);
15138fd1498Szrj }
15238fd1498Szrj 
15338fd1498Szrj 
15438fd1498Szrj 
15538fd1498Szrj /* Global variables used to communicate with passes.  */
15638fd1498Szrj bool in_gimple_form;
15738fd1498Szrj 
15838fd1498Szrj 
15938fd1498Szrj /* This is called from various places for FUNCTION_DECL, VAR_DECL,
16038fd1498Szrj    and TYPE_DECL nodes.
16138fd1498Szrj 
16238fd1498Szrj    This does nothing for local (non-static) variables, unless the
16338fd1498Szrj    variable is a register variable with DECL_ASSEMBLER_NAME set.  In
16438fd1498Szrj    that case, or if the variable is not an automatic, it sets up the
16538fd1498Szrj    RTL and outputs any assembler code (label definition, storage
16638fd1498Szrj    allocation and initialization).
16738fd1498Szrj 
16838fd1498Szrj    DECL is the declaration.  TOP_LEVEL is nonzero
16938fd1498Szrj    if this declaration is not within a function.  */
17038fd1498Szrj 
17138fd1498Szrj void
rest_of_decl_compilation(tree decl,int top_level,int at_end)17238fd1498Szrj rest_of_decl_compilation (tree decl,
17338fd1498Szrj 			  int top_level,
17438fd1498Szrj 			  int at_end)
17538fd1498Szrj {
17638fd1498Szrj   bool finalize = true;
17738fd1498Szrj 
17838fd1498Szrj   /* We deferred calling assemble_alias so that we could collect
17938fd1498Szrj      other attributes such as visibility.  Emit the alias now.  */
18038fd1498Szrj   if (!in_lto_p)
18138fd1498Szrj   {
18238fd1498Szrj     tree alias;
18338fd1498Szrj     alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
18438fd1498Szrj     if (alias)
18538fd1498Szrj       {
18638fd1498Szrj 	alias = TREE_VALUE (TREE_VALUE (alias));
18738fd1498Szrj 	alias = get_identifier (TREE_STRING_POINTER (alias));
18838fd1498Szrj 	/* A quirk of the initial implementation of aliases required that the
18938fd1498Szrj 	   user add "extern" to all of them.  Which is silly, but now
19038fd1498Szrj 	   historical.  Do note that the symbol is in fact locally defined.  */
19138fd1498Szrj 	DECL_EXTERNAL (decl) = 0;
19238fd1498Szrj 	TREE_STATIC (decl) = 1;
19338fd1498Szrj 	assemble_alias (decl, alias);
19438fd1498Szrj 	finalize = false;
19538fd1498Szrj       }
19638fd1498Szrj   }
19738fd1498Szrj 
19838fd1498Szrj   /* Can't defer this, because it needs to happen before any
19938fd1498Szrj      later function definitions are processed.  */
20038fd1498Szrj   if (HAS_DECL_ASSEMBLER_NAME_P (decl)
20138fd1498Szrj       && DECL_ASSEMBLER_NAME_SET_P (decl)
20238fd1498Szrj       && DECL_REGISTER (decl))
20338fd1498Szrj     make_decl_rtl (decl);
20438fd1498Szrj 
20538fd1498Szrj   /* Forward declarations for nested functions are not "external",
20638fd1498Szrj      but we need to treat them as if they were.  */
20738fd1498Szrj   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
20838fd1498Szrj       || TREE_CODE (decl) == FUNCTION_DECL)
20938fd1498Szrj     {
21038fd1498Szrj       timevar_push (TV_VARCONST);
21138fd1498Szrj 
21238fd1498Szrj       /* Don't output anything when a tentative file-scope definition
21338fd1498Szrj 	 is seen.  But at end of compilation, do output code for them.
21438fd1498Szrj 
21538fd1498Szrj 	 We do output all variables and rely on
21638fd1498Szrj 	 callgraph code to defer them except for forward declarations
21738fd1498Szrj 	 (see gcc.c-torture/compile/920624-1.c) */
21838fd1498Szrj       if ((at_end
21938fd1498Szrj 	   || !DECL_DEFER_OUTPUT (decl)
22038fd1498Szrj 	   || DECL_INITIAL (decl))
22138fd1498Szrj 	  && (!VAR_P (decl) || !DECL_HAS_VALUE_EXPR_P (decl))
22238fd1498Szrj 	  && !DECL_EXTERNAL (decl))
22338fd1498Szrj 	{
22438fd1498Szrj 	  /* When reading LTO unit, we also read varpool, so do not
22538fd1498Szrj 	     rebuild it.  */
22638fd1498Szrj 	  if (in_lto_p && !at_end)
22738fd1498Szrj 	    ;
22838fd1498Szrj 	  else if (finalize && TREE_CODE (decl) != FUNCTION_DECL)
22938fd1498Szrj 	    varpool_node::finalize_decl (decl);
23038fd1498Szrj 	}
23138fd1498Szrj 
23238fd1498Szrj #ifdef ASM_FINISH_DECLARE_OBJECT
23338fd1498Szrj       if (decl == last_assemble_variable_decl)
23438fd1498Szrj 	{
23538fd1498Szrj 	  ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
23638fd1498Szrj 				     top_level, at_end);
23738fd1498Szrj 	}
23838fd1498Szrj #endif
23938fd1498Szrj 
24038fd1498Szrj       /* Now that we have activated any function-specific attributes
24138fd1498Szrj 	 that might affect function decl, particularly align, relayout it.  */
24238fd1498Szrj       if (TREE_CODE (decl) == FUNCTION_DECL)
24338fd1498Szrj 	targetm.target_option.relayout_function (decl);
24438fd1498Szrj 
24538fd1498Szrj       timevar_pop (TV_VARCONST);
24638fd1498Szrj     }
24738fd1498Szrj   else if (TREE_CODE (decl) == TYPE_DECL
24838fd1498Szrj 	   /* Like in rest_of_type_compilation, avoid confusing the debug
24938fd1498Szrj 	      information machinery when there are errors.  */
25038fd1498Szrj 	   && !seen_error ())
25138fd1498Szrj     {
25238fd1498Szrj       timevar_push (TV_SYMOUT);
25338fd1498Szrj       debug_hooks->type_decl (decl, !top_level);
25438fd1498Szrj       timevar_pop (TV_SYMOUT);
25538fd1498Szrj     }
25638fd1498Szrj 
25738fd1498Szrj   /* Let cgraph know about the existence of variables.  */
25838fd1498Szrj   if (in_lto_p && !at_end)
25938fd1498Szrj     ;
26038fd1498Szrj   else if (VAR_P (decl) && !DECL_EXTERNAL (decl)
26138fd1498Szrj 	   && TREE_STATIC (decl))
26238fd1498Szrj     varpool_node::get_create (decl);
26338fd1498Szrj 
26438fd1498Szrj   /* Generate early debug for global variables.  Any local variables will
26538fd1498Szrj      be handled by either handling reachable functions from
26638fd1498Szrj      finalize_compilation_unit (and by consequence, locally scoped
26738fd1498Szrj      symbols), or by rest_of_type_compilation below.
26838fd1498Szrj 
26938fd1498Szrj      For Go's hijack of the debug_hooks to implement -fdump-go-spec, pick up
27038fd1498Szrj      function prototypes.  Go's debug_hooks will not forward them to the
27138fd1498Szrj      wrapped hooks.  */
27238fd1498Szrj   if (!in_lto_p
27338fd1498Szrj       && (TREE_CODE (decl) != FUNCTION_DECL
27438fd1498Szrj 	  /* This will pick up function prototypes with no bodies,
27538fd1498Szrj 	     which are not visible in finalize_compilation_unit()
27638fd1498Szrj 	     while iterating with FOR_EACH_*_FUNCTION through the
27738fd1498Szrj 	     symbol table.  */
27838fd1498Szrj 	  || (flag_dump_go_spec != NULL
27938fd1498Szrj 	      && !DECL_SAVED_TREE (decl)
28038fd1498Szrj 	      && DECL_STRUCT_FUNCTION (decl) == NULL))
28138fd1498Szrj 
28238fd1498Szrj       /* We need to check both decl_function_context and
28338fd1498Szrj 	 current_function_decl here to make sure local extern
28438fd1498Szrj 	 declarations end up with the correct context.
28538fd1498Szrj 
28638fd1498Szrj 	 For local extern declarations, decl_function_context is
28738fd1498Szrj 	 empty, but current_function_decl is set to the function where
28838fd1498Szrj 	 the extern was declared .  Without the check for
28938fd1498Szrj 	 !current_function_decl below, the local extern ends up
29038fd1498Szrj 	 incorrectly with a top-level context.
29138fd1498Szrj 
29238fd1498Szrj 	 For example:
29338fd1498Szrj 
29438fd1498Szrj 	 namespace S
29538fd1498Szrj 	 {
29638fd1498Szrj 	   int
29738fd1498Szrj 	   f()
29838fd1498Szrj 	   {
29938fd1498Szrj 	     {
30038fd1498Szrj 	       int i = 42;
30138fd1498Szrj 	       {
30238fd1498Szrj 	         extern int i; // Local extern declaration.
30338fd1498Szrj 		 return i;
30438fd1498Szrj 	       }
30538fd1498Szrj 	     }
30638fd1498Szrj 	   }
30738fd1498Szrj 	 }
30838fd1498Szrj       */
30938fd1498Szrj       && !decl_function_context (decl)
31038fd1498Szrj       && !current_function_decl
31138fd1498Szrj       && DECL_SOURCE_LOCATION (decl) != BUILTINS_LOCATION
31238fd1498Szrj       && (!decl_type_context (decl)
31338fd1498Szrj 	  /* If we created a varpool node for the decl make sure to
31438fd1498Szrj 	     call early_global_decl.  Otherwise we miss changes
31538fd1498Szrj 	     introduced by member definitions like
31638fd1498Szrj 		struct A { static int staticdatamember; };
31738fd1498Szrj 		int A::staticdatamember;
31838fd1498Szrj 	     and thus have incomplete early debug and late debug
31938fd1498Szrj 	     called from varpool node removal fails to handle it
32038fd1498Szrj 	     properly.  */
32138fd1498Szrj 	  || (finalize
32238fd1498Szrj 	      && VAR_P (decl)
32338fd1498Szrj 	      && TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
32438fd1498Szrj       /* Avoid confusing the debug information machinery when there are
32538fd1498Szrj 	 errors.  */
32638fd1498Szrj       && !seen_error ())
32738fd1498Szrj     (*debug_hooks->early_global_decl) (decl);
32838fd1498Szrj }
32938fd1498Szrj 
33038fd1498Szrj /* Called after finishing a record, union or enumeral type.  */
33138fd1498Szrj 
33238fd1498Szrj void
rest_of_type_compilation(tree type,int toplev)33338fd1498Szrj rest_of_type_compilation (tree type, int toplev)
33438fd1498Szrj {
33538fd1498Szrj   /* Avoid confusing the debug information machinery when there are
33638fd1498Szrj      errors.  */
33738fd1498Szrj   if (seen_error ())
33838fd1498Szrj     return;
33938fd1498Szrj 
34038fd1498Szrj   timevar_push (TV_SYMOUT);
34138fd1498Szrj   debug_hooks->type_decl (TYPE_STUB_DECL (type), !toplev);
34238fd1498Szrj   timevar_pop (TV_SYMOUT);
34338fd1498Szrj }
34438fd1498Szrj 
34538fd1498Szrj 
34638fd1498Szrj 
34738fd1498Szrj void
34838fd1498Szrj pass_manager::
finish_optimization_passes(void)34938fd1498Szrj finish_optimization_passes (void)
35038fd1498Szrj {
35138fd1498Szrj   int i;
35238fd1498Szrj   struct dump_file_info *dfi;
35338fd1498Szrj   char *name;
35438fd1498Szrj   gcc::dump_manager *dumps = m_ctxt->get_dumps ();
35538fd1498Szrj 
35638fd1498Szrj   timevar_push (TV_DUMP);
35738fd1498Szrj   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
35838fd1498Szrj     {
35938fd1498Szrj       dumps->dump_start (pass_profile_1->static_pass_number, NULL);
36038fd1498Szrj       end_branch_prob ();
36138fd1498Szrj       dumps->dump_finish (pass_profile_1->static_pass_number);
36238fd1498Szrj     }
36338fd1498Szrj 
36438fd1498Szrj   if (optimize > 0)
36538fd1498Szrj     {
36658e805e6Szrj       dumps->dump_start (pass_combine_1->static_pass_number, NULL);
36738fd1498Szrj       print_combine_total_stats ();
36858e805e6Szrj       dumps->dump_finish (pass_combine_1->static_pass_number);
36938fd1498Szrj     }
37038fd1498Szrj 
37138fd1498Szrj   /* Do whatever is necessary to finish printing the graphs.  */
37238fd1498Szrj   for (i = TDI_end; (dfi = dumps->get_dump_file_info (i)) != NULL; ++i)
37338fd1498Szrj     if (dfi->graph_dump_initialized)
37438fd1498Szrj       {
37538fd1498Szrj 	name = dumps->get_dump_file_name (dfi);
37638fd1498Szrj 	finish_graph_dump_file (name);
37738fd1498Szrj 	free (name);
37838fd1498Szrj       }
37938fd1498Szrj 
38038fd1498Szrj   timevar_pop (TV_DUMP);
38138fd1498Szrj }
38238fd1498Szrj 
38338fd1498Szrj static unsigned int
execute_build_ssa_passes(void)38438fd1498Szrj execute_build_ssa_passes (void)
38538fd1498Szrj {
38638fd1498Szrj   /* Once this pass (and its sub-passes) are complete, all functions
38738fd1498Szrj      will be in SSA form.  Technically this state change is happening
38838fd1498Szrj      a tad early, since the sub-passes have not yet run, but since
38938fd1498Szrj      none of the sub-passes are IPA passes and do not create new
39038fd1498Szrj      functions, this is ok.  We're setting this value for the benefit
39138fd1498Szrj      of IPA passes that follow.  */
39238fd1498Szrj   if (symtab->state < IPA_SSA)
39338fd1498Szrj     symtab->state = IPA_SSA;
39438fd1498Szrj   return 0;
39538fd1498Szrj }
39638fd1498Szrj 
39738fd1498Szrj namespace {
39838fd1498Szrj 
39938fd1498Szrj const pass_data pass_data_build_ssa_passes =
40038fd1498Szrj {
40138fd1498Szrj   SIMPLE_IPA_PASS, /* type */
40238fd1498Szrj   "build_ssa_passes", /* name */
40338fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
40438fd1498Szrj   TV_EARLY_LOCAL, /* tv_id */
40538fd1498Szrj   0, /* properties_required */
40638fd1498Szrj   0, /* properties_provided */
40738fd1498Szrj   0, /* properties_destroyed */
40838fd1498Szrj   0, /* todo_flags_start */
40938fd1498Szrj   /* todo_flags_finish is executed before subpases. For this reason
41038fd1498Szrj      it makes no sense to remove unreachable functions here.  */
41138fd1498Szrj   0, /* todo_flags_finish */
41238fd1498Szrj };
41338fd1498Szrj 
41438fd1498Szrj class pass_build_ssa_passes : public simple_ipa_opt_pass
41538fd1498Szrj {
41638fd1498Szrj public:
pass_build_ssa_passes(gcc::context * ctxt)41738fd1498Szrj   pass_build_ssa_passes (gcc::context *ctxt)
41838fd1498Szrj     : simple_ipa_opt_pass (pass_data_build_ssa_passes, ctxt)
41938fd1498Szrj   {}
42038fd1498Szrj 
42138fd1498Szrj   /* opt_pass methods: */
gate(function *)42238fd1498Szrj   virtual bool gate (function *)
42338fd1498Szrj     {
42438fd1498Szrj       /* Don't bother doing anything if the program has errors.  */
42538fd1498Szrj       return (!seen_error () && !in_lto_p);
42638fd1498Szrj     }
42738fd1498Szrj 
execute(function *)42838fd1498Szrj   virtual unsigned int execute (function *)
42938fd1498Szrj     {
43038fd1498Szrj       return execute_build_ssa_passes ();
43138fd1498Szrj     }
43238fd1498Szrj 
43338fd1498Szrj }; // class pass_build_ssa_passes
43438fd1498Szrj 
43538fd1498Szrj const pass_data pass_data_chkp_instrumentation_passes =
43638fd1498Szrj {
43738fd1498Szrj   SIMPLE_IPA_PASS, /* type */
43838fd1498Szrj   "chkp_passes", /* name */
43938fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
44038fd1498Szrj   TV_NONE, /* tv_id */
44138fd1498Szrj   0, /* properties_required */
44238fd1498Szrj   0, /* properties_provided */
44338fd1498Szrj   0, /* properties_destroyed */
44438fd1498Szrj   0, /* todo_flags_start */
44538fd1498Szrj   0, /* todo_flags_finish */
44638fd1498Szrj };
44738fd1498Szrj 
44838fd1498Szrj class pass_chkp_instrumentation_passes : public simple_ipa_opt_pass
44938fd1498Szrj {
45038fd1498Szrj public:
pass_chkp_instrumentation_passes(gcc::context * ctxt)45138fd1498Szrj   pass_chkp_instrumentation_passes (gcc::context *ctxt)
45238fd1498Szrj     : simple_ipa_opt_pass (pass_data_chkp_instrumentation_passes, ctxt)
45338fd1498Szrj   {}
45438fd1498Szrj 
45538fd1498Szrj   /* opt_pass methods: */
gate(function *)45638fd1498Szrj   virtual bool gate (function *)
45738fd1498Szrj     {
45838fd1498Szrj       /* Don't bother doing anything if the program has errors.  */
45938fd1498Szrj       return (flag_check_pointer_bounds
46038fd1498Szrj 	      && !seen_error () && !in_lto_p);
46138fd1498Szrj     }
46238fd1498Szrj 
46338fd1498Szrj }; // class pass_chkp_instrumentation_passes
46438fd1498Szrj 
46538fd1498Szrj const pass_data pass_data_local_optimization_passes =
46638fd1498Szrj {
46738fd1498Szrj   SIMPLE_IPA_PASS, /* type */
46838fd1498Szrj   "opt_local_passes", /* name */
46938fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
47038fd1498Szrj   TV_NONE, /* tv_id */
47138fd1498Szrj   0, /* properties_required */
47238fd1498Szrj   0, /* properties_provided */
47338fd1498Szrj   0, /* properties_destroyed */
47438fd1498Szrj   0, /* todo_flags_start */
47538fd1498Szrj   0, /* todo_flags_finish */
47638fd1498Szrj };
47738fd1498Szrj 
47838fd1498Szrj class pass_local_optimization_passes : public simple_ipa_opt_pass
47938fd1498Szrj {
48038fd1498Szrj public:
pass_local_optimization_passes(gcc::context * ctxt)48138fd1498Szrj   pass_local_optimization_passes (gcc::context *ctxt)
48238fd1498Szrj     : simple_ipa_opt_pass (pass_data_local_optimization_passes, ctxt)
48338fd1498Szrj   {}
48438fd1498Szrj 
48538fd1498Szrj   /* opt_pass methods: */
gate(function *)48638fd1498Szrj   virtual bool gate (function *)
48738fd1498Szrj     {
48838fd1498Szrj       /* Don't bother doing anything if the program has errors.  */
48938fd1498Szrj       return (!seen_error () && !in_lto_p);
49038fd1498Szrj     }
49138fd1498Szrj 
49238fd1498Szrj }; // class pass_local_optimization_passes
49338fd1498Szrj 
49438fd1498Szrj } // anon namespace
49538fd1498Szrj 
49638fd1498Szrj simple_ipa_opt_pass *
make_pass_build_ssa_passes(gcc::context * ctxt)49738fd1498Szrj make_pass_build_ssa_passes (gcc::context *ctxt)
49838fd1498Szrj {
49938fd1498Szrj   return new pass_build_ssa_passes (ctxt);
50038fd1498Szrj }
50138fd1498Szrj 
50238fd1498Szrj simple_ipa_opt_pass *
make_pass_chkp_instrumentation_passes(gcc::context * ctxt)50338fd1498Szrj make_pass_chkp_instrumentation_passes (gcc::context *ctxt)
50438fd1498Szrj {
50538fd1498Szrj   return new pass_chkp_instrumentation_passes (ctxt);
50638fd1498Szrj }
50738fd1498Szrj 
50838fd1498Szrj simple_ipa_opt_pass *
make_pass_local_optimization_passes(gcc::context * ctxt)50938fd1498Szrj make_pass_local_optimization_passes (gcc::context *ctxt)
51038fd1498Szrj {
51138fd1498Szrj   return new pass_local_optimization_passes (ctxt);
51238fd1498Szrj }
51338fd1498Szrj 
51438fd1498Szrj namespace {
51538fd1498Szrj 
51638fd1498Szrj const pass_data pass_data_all_early_optimizations =
51738fd1498Szrj {
51838fd1498Szrj   GIMPLE_PASS, /* type */
51938fd1498Szrj   "early_optimizations", /* name */
52038fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
52138fd1498Szrj   TV_NONE, /* tv_id */
52238fd1498Szrj   0, /* properties_required */
52338fd1498Szrj   0, /* properties_provided */
52438fd1498Szrj   0, /* properties_destroyed */
52538fd1498Szrj   0, /* todo_flags_start */
52638fd1498Szrj   0, /* todo_flags_finish */
52738fd1498Szrj };
52838fd1498Szrj 
52938fd1498Szrj class pass_all_early_optimizations : public gimple_opt_pass
53038fd1498Szrj {
53138fd1498Szrj public:
pass_all_early_optimizations(gcc::context * ctxt)53238fd1498Szrj   pass_all_early_optimizations (gcc::context *ctxt)
53338fd1498Szrj     : gimple_opt_pass (pass_data_all_early_optimizations, ctxt)
53438fd1498Szrj   {}
53538fd1498Szrj 
53638fd1498Szrj   /* opt_pass methods: */
gate(function *)53738fd1498Szrj   virtual bool gate (function *)
53838fd1498Szrj     {
53938fd1498Szrj       return (optimize >= 1
54038fd1498Szrj 	      /* Don't bother doing anything if the program has errors.  */
54138fd1498Szrj 	      && !seen_error ());
54238fd1498Szrj     }
54338fd1498Szrj 
54438fd1498Szrj }; // class pass_all_early_optimizations
54538fd1498Szrj 
54638fd1498Szrj } // anon namespace
54738fd1498Szrj 
54838fd1498Szrj static gimple_opt_pass *
make_pass_all_early_optimizations(gcc::context * ctxt)54938fd1498Szrj make_pass_all_early_optimizations (gcc::context *ctxt)
55038fd1498Szrj {
55138fd1498Szrj   return new pass_all_early_optimizations (ctxt);
55238fd1498Szrj }
55338fd1498Szrj 
55438fd1498Szrj namespace {
55538fd1498Szrj 
55638fd1498Szrj const pass_data pass_data_all_optimizations =
55738fd1498Szrj {
55838fd1498Szrj   GIMPLE_PASS, /* type */
55938fd1498Szrj   "*all_optimizations", /* name */
56038fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
56138fd1498Szrj   TV_OPTIMIZE, /* tv_id */
56238fd1498Szrj   0, /* properties_required */
56338fd1498Szrj   0, /* properties_provided */
56438fd1498Szrj   0, /* properties_destroyed */
56538fd1498Szrj   0, /* todo_flags_start */
56638fd1498Szrj   0, /* todo_flags_finish */
56738fd1498Szrj };
56838fd1498Szrj 
56938fd1498Szrj class pass_all_optimizations : public gimple_opt_pass
57038fd1498Szrj {
57138fd1498Szrj public:
pass_all_optimizations(gcc::context * ctxt)57238fd1498Szrj   pass_all_optimizations (gcc::context *ctxt)
57338fd1498Szrj     : gimple_opt_pass (pass_data_all_optimizations, ctxt)
57438fd1498Szrj   {}
57538fd1498Szrj 
57638fd1498Szrj   /* opt_pass methods: */
gate(function *)57738fd1498Szrj   virtual bool gate (function *) { return optimize >= 1 && !optimize_debug; }
57838fd1498Szrj 
57938fd1498Szrj }; // class pass_all_optimizations
58038fd1498Szrj 
58138fd1498Szrj } // anon namespace
58238fd1498Szrj 
58338fd1498Szrj static gimple_opt_pass *
make_pass_all_optimizations(gcc::context * ctxt)58438fd1498Szrj make_pass_all_optimizations (gcc::context *ctxt)
58538fd1498Szrj {
58638fd1498Szrj   return new pass_all_optimizations (ctxt);
58738fd1498Szrj }
58838fd1498Szrj 
58938fd1498Szrj namespace {
59038fd1498Szrj 
59138fd1498Szrj const pass_data pass_data_all_optimizations_g =
59238fd1498Szrj {
59338fd1498Szrj   GIMPLE_PASS, /* type */
59438fd1498Szrj   "*all_optimizations_g", /* name */
59538fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
59638fd1498Szrj   TV_OPTIMIZE, /* tv_id */
59738fd1498Szrj   0, /* properties_required */
59838fd1498Szrj   0, /* properties_provided */
59938fd1498Szrj   0, /* properties_destroyed */
60038fd1498Szrj   0, /* todo_flags_start */
60138fd1498Szrj   0, /* todo_flags_finish */
60238fd1498Szrj };
60338fd1498Szrj 
60438fd1498Szrj class pass_all_optimizations_g : public gimple_opt_pass
60538fd1498Szrj {
60638fd1498Szrj public:
pass_all_optimizations_g(gcc::context * ctxt)60738fd1498Szrj   pass_all_optimizations_g (gcc::context *ctxt)
60838fd1498Szrj     : gimple_opt_pass (pass_data_all_optimizations_g, ctxt)
60938fd1498Szrj   {}
61038fd1498Szrj 
61138fd1498Szrj   /* opt_pass methods: */
gate(function *)61238fd1498Szrj   virtual bool gate (function *) { return optimize >= 1 && optimize_debug; }
61338fd1498Szrj 
61438fd1498Szrj }; // class pass_all_optimizations_g
61538fd1498Szrj 
61638fd1498Szrj } // anon namespace
61738fd1498Szrj 
61838fd1498Szrj static gimple_opt_pass *
make_pass_all_optimizations_g(gcc::context * ctxt)61938fd1498Szrj make_pass_all_optimizations_g (gcc::context *ctxt)
62038fd1498Szrj {
62138fd1498Szrj   return new pass_all_optimizations_g (ctxt);
62238fd1498Szrj }
62338fd1498Szrj 
62438fd1498Szrj namespace {
62538fd1498Szrj 
62638fd1498Szrj const pass_data pass_data_rest_of_compilation =
62738fd1498Szrj {
62838fd1498Szrj   RTL_PASS, /* type */
62938fd1498Szrj   "*rest_of_compilation", /* name */
63038fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
63138fd1498Szrj   TV_REST_OF_COMPILATION, /* tv_id */
63238fd1498Szrj   PROP_rtl, /* properties_required */
63338fd1498Szrj   0, /* properties_provided */
63438fd1498Szrj   0, /* properties_destroyed */
63538fd1498Szrj   0, /* todo_flags_start */
63638fd1498Szrj   0, /* todo_flags_finish */
63738fd1498Szrj };
63838fd1498Szrj 
63938fd1498Szrj class pass_rest_of_compilation : public rtl_opt_pass
64038fd1498Szrj {
64138fd1498Szrj public:
pass_rest_of_compilation(gcc::context * ctxt)64238fd1498Szrj   pass_rest_of_compilation (gcc::context *ctxt)
64338fd1498Szrj     : rtl_opt_pass (pass_data_rest_of_compilation, ctxt)
64438fd1498Szrj   {}
64538fd1498Szrj 
64638fd1498Szrj   /* opt_pass methods: */
gate(function *)64738fd1498Szrj   virtual bool gate (function *)
64838fd1498Szrj     {
64938fd1498Szrj       /* Early return if there were errors.  We can run afoul of our
65038fd1498Szrj 	 consistency checks, and there's not really much point in fixing them.  */
65138fd1498Szrj       return !(rtl_dump_and_exit || flag_syntax_only || seen_error ());
65238fd1498Szrj     }
65338fd1498Szrj 
65438fd1498Szrj }; // class pass_rest_of_compilation
65538fd1498Szrj 
65638fd1498Szrj } // anon namespace
65738fd1498Szrj 
65838fd1498Szrj static rtl_opt_pass *
make_pass_rest_of_compilation(gcc::context * ctxt)65938fd1498Szrj make_pass_rest_of_compilation (gcc::context *ctxt)
66038fd1498Szrj {
66138fd1498Szrj   return new pass_rest_of_compilation (ctxt);
66238fd1498Szrj }
66338fd1498Szrj 
66438fd1498Szrj namespace {
66538fd1498Szrj 
66638fd1498Szrj const pass_data pass_data_postreload =
66738fd1498Szrj {
66838fd1498Szrj   RTL_PASS, /* type */
66938fd1498Szrj   "*all-postreload", /* name */
67038fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
67138fd1498Szrj   TV_POSTRELOAD, /* tv_id */
67238fd1498Szrj   PROP_rtl, /* properties_required */
67338fd1498Szrj   0, /* properties_provided */
67438fd1498Szrj   0, /* properties_destroyed */
67538fd1498Szrj   0, /* todo_flags_start */
67638fd1498Szrj   0, /* todo_flags_finish */
67738fd1498Szrj };
67838fd1498Szrj 
67938fd1498Szrj class pass_postreload : public rtl_opt_pass
68038fd1498Szrj {
68138fd1498Szrj public:
pass_postreload(gcc::context * ctxt)68238fd1498Szrj   pass_postreload (gcc::context *ctxt)
68338fd1498Szrj     : rtl_opt_pass (pass_data_postreload, ctxt)
68438fd1498Szrj   {}
68538fd1498Szrj 
68638fd1498Szrj   /* opt_pass methods: */
gate(function *)68738fd1498Szrj   virtual bool gate (function *) { return reload_completed; }
68838fd1498Szrj 
68938fd1498Szrj }; // class pass_postreload
69038fd1498Szrj 
69138fd1498Szrj } // anon namespace
69238fd1498Szrj 
69338fd1498Szrj static rtl_opt_pass *
make_pass_postreload(gcc::context * ctxt)69438fd1498Szrj make_pass_postreload (gcc::context *ctxt)
69538fd1498Szrj {
69638fd1498Szrj   return new pass_postreload (ctxt);
69738fd1498Szrj }
69838fd1498Szrj 
69938fd1498Szrj namespace {
70038fd1498Szrj 
70138fd1498Szrj const pass_data pass_data_late_compilation =
70238fd1498Szrj {
70338fd1498Szrj   RTL_PASS, /* type */
70438fd1498Szrj   "*all-late_compilation", /* name */
70538fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
70638fd1498Szrj   TV_LATE_COMPILATION, /* tv_id */
70738fd1498Szrj   PROP_rtl, /* properties_required */
70838fd1498Szrj   0, /* properties_provided */
70938fd1498Szrj   0, /* properties_destroyed */
71038fd1498Szrj   0, /* todo_flags_start */
71138fd1498Szrj   0, /* todo_flags_finish */
71238fd1498Szrj };
71338fd1498Szrj 
71438fd1498Szrj class pass_late_compilation : public rtl_opt_pass
71538fd1498Szrj {
71638fd1498Szrj public:
pass_late_compilation(gcc::context * ctxt)71738fd1498Szrj   pass_late_compilation (gcc::context *ctxt)
71838fd1498Szrj     : rtl_opt_pass (pass_data_late_compilation, ctxt)
71938fd1498Szrj   {}
72038fd1498Szrj 
72138fd1498Szrj   /* opt_pass methods: */
gate(function *)72238fd1498Szrj   virtual bool gate (function *)
72338fd1498Szrj   {
72438fd1498Szrj     return reload_completed || targetm.no_register_allocation;
72538fd1498Szrj   }
72638fd1498Szrj 
72738fd1498Szrj }; // class pass_late_compilation
72838fd1498Szrj 
72938fd1498Szrj } // anon namespace
73038fd1498Szrj 
73138fd1498Szrj static rtl_opt_pass *
make_pass_late_compilation(gcc::context * ctxt)73238fd1498Szrj make_pass_late_compilation (gcc::context *ctxt)
73338fd1498Szrj {
73438fd1498Szrj   return new pass_late_compilation (ctxt);
73538fd1498Szrj }
73638fd1498Szrj 
73738fd1498Szrj 
73838fd1498Szrj 
73938fd1498Szrj /* Set the static pass number of pass PASS to ID and record that
74038fd1498Szrj    in the mapping from static pass number to pass.  */
74138fd1498Szrj 
74238fd1498Szrj void
74338fd1498Szrj pass_manager::
set_pass_for_id(int id,opt_pass * pass)74438fd1498Szrj set_pass_for_id (int id, opt_pass *pass)
74538fd1498Szrj {
74638fd1498Szrj   pass->static_pass_number = id;
74738fd1498Szrj   if (passes_by_id_size <= id)
74838fd1498Szrj     {
74938fd1498Szrj       passes_by_id = XRESIZEVEC (opt_pass *, passes_by_id, id + 1);
75038fd1498Szrj       memset (passes_by_id + passes_by_id_size, 0,
75138fd1498Szrj 	      (id + 1 - passes_by_id_size) * sizeof (void *));
75238fd1498Szrj       passes_by_id_size = id + 1;
75338fd1498Szrj     }
75438fd1498Szrj   passes_by_id[id] = pass;
75538fd1498Szrj }
75638fd1498Szrj 
75738fd1498Szrj /* Return the pass with the static pass number ID.  */
75838fd1498Szrj 
75938fd1498Szrj opt_pass *
get_pass_for_id(int id)76038fd1498Szrj pass_manager::get_pass_for_id (int id) const
76138fd1498Szrj {
76238fd1498Szrj   if (id >= passes_by_id_size)
76338fd1498Szrj     return NULL;
76438fd1498Szrj   return passes_by_id[id];
76538fd1498Szrj }
76638fd1498Szrj 
76738fd1498Szrj /* Iterate over the pass tree allocating dump file numbers.  We want
76838fd1498Szrj    to do this depth first, and independent of whether the pass is
76938fd1498Szrj    enabled or not.  */
77038fd1498Szrj 
77138fd1498Szrj void
register_one_dump_file(opt_pass * pass)77238fd1498Szrj register_one_dump_file (opt_pass *pass)
77338fd1498Szrj {
77438fd1498Szrj   g->get_passes ()->register_one_dump_file (pass);
77538fd1498Szrj }
77638fd1498Szrj 
77738fd1498Szrj void
register_one_dump_file(opt_pass * pass)77838fd1498Szrj pass_manager::register_one_dump_file (opt_pass *pass)
77938fd1498Szrj {
78038fd1498Szrj   char *dot_name, *flag_name, *glob_name;
78138fd1498Szrj   const char *name, *full_name, *prefix;
78238fd1498Szrj 
78338fd1498Szrj   /* Buffer big enough to format a 32-bit UINT_MAX into.  */
78438fd1498Szrj   char num[11];
78538fd1498Szrj   dump_kind dkind;
78638fd1498Szrj   int id;
78738fd1498Szrj   int optgroup_flags = OPTGROUP_NONE;
78838fd1498Szrj   gcc::dump_manager *dumps = m_ctxt->get_dumps ();
78938fd1498Szrj 
79038fd1498Szrj   /* See below in next_pass_1.  */
79138fd1498Szrj   num[0] = '\0';
79238fd1498Szrj   if (pass->static_pass_number != -1)
79338fd1498Szrj     sprintf (num, "%u", ((int) pass->static_pass_number < 0
79438fd1498Szrj 			 ? 1 : pass->static_pass_number));
79538fd1498Szrj 
79638fd1498Szrj   /* The name is both used to identify the pass for the purposes of plugins,
79738fd1498Szrj      and to specify dump file name and option.
79838fd1498Szrj      The latter two might want something short which is not quite unique; for
79938fd1498Szrj      that reason, we may have a disambiguating prefix, followed by a space
80038fd1498Szrj      to mark the start of the following dump file name / option string.  */
80138fd1498Szrj   name = strchr (pass->name, ' ');
80238fd1498Szrj   name = name ? name + 1 : pass->name;
80338fd1498Szrj   dot_name = concat (".", name, num, NULL);
80438fd1498Szrj   if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
80538fd1498Szrj     {
80638fd1498Szrj       prefix = "ipa-";
80738fd1498Szrj       dkind = DK_ipa;
80838fd1498Szrj       optgroup_flags |= OPTGROUP_IPA;
80938fd1498Szrj     }
81038fd1498Szrj   else if (pass->type == GIMPLE_PASS)
81138fd1498Szrj     {
81238fd1498Szrj       prefix = "tree-";
81338fd1498Szrj       dkind = DK_tree;
81438fd1498Szrj     }
81538fd1498Szrj   else
81638fd1498Szrj     {
81738fd1498Szrj       prefix = "rtl-";
81838fd1498Szrj       dkind = DK_rtl;
81938fd1498Szrj     }
82038fd1498Szrj 
82138fd1498Szrj   flag_name = concat (prefix, name, num, NULL);
82238fd1498Szrj   glob_name = concat (prefix, name, NULL);
82338fd1498Szrj   optgroup_flags |= pass->optinfo_flags;
82438fd1498Szrj   /* For any passes that do not have an optgroup set, and which are not
82538fd1498Szrj      IPA passes setup above, set the optgroup to OPTGROUP_OTHER so that
82638fd1498Szrj      any dump messages are emitted properly under -fopt-info(-optall).  */
82738fd1498Szrj   if (optgroup_flags == OPTGROUP_NONE)
82838fd1498Szrj     optgroup_flags = OPTGROUP_OTHER;
82938fd1498Szrj   id = dumps->dump_register (dot_name, flag_name, glob_name, dkind,
83038fd1498Szrj 			     optgroup_flags,
83138fd1498Szrj 			     true);
83238fd1498Szrj   set_pass_for_id (id, pass);
83338fd1498Szrj   full_name = concat (prefix, pass->name, num, NULL);
83438fd1498Szrj   register_pass_name (pass, full_name);
83538fd1498Szrj   free (CONST_CAST (char *, full_name));
83638fd1498Szrj }
83738fd1498Szrj 
83838fd1498Szrj /* Register the dump files for the pass_manager starting at PASS. */
83938fd1498Szrj 
84038fd1498Szrj void
register_dump_files(opt_pass * pass)84138fd1498Szrj pass_manager::register_dump_files (opt_pass *pass)
84238fd1498Szrj {
84338fd1498Szrj   do
84438fd1498Szrj     {
84538fd1498Szrj       if (pass->name && pass->name[0] != '*')
84638fd1498Szrj         register_one_dump_file (pass);
84738fd1498Szrj 
84838fd1498Szrj       if (pass->sub)
84938fd1498Szrj         register_dump_files (pass->sub);
85038fd1498Szrj 
85138fd1498Szrj       pass = pass->next;
85238fd1498Szrj     }
85338fd1498Szrj   while (pass);
85438fd1498Szrj }
85538fd1498Szrj 
85638fd1498Szrj /* Register PASS with NAME.  */
85738fd1498Szrj 
85838fd1498Szrj void
register_pass_name(opt_pass * pass,const char * name)85938fd1498Szrj pass_manager::register_pass_name (opt_pass *pass, const char *name)
86038fd1498Szrj {
86138fd1498Szrj   if (!m_name_to_pass_map)
86238fd1498Szrj     m_name_to_pass_map = new hash_map<nofree_string_hash, opt_pass *> (256);
86338fd1498Szrj 
86438fd1498Szrj   if (m_name_to_pass_map->get (name))
86538fd1498Szrj     return; /* Ignore plugin passes.  */
86638fd1498Szrj 
86738fd1498Szrj   const char *unique_name = xstrdup (name);
86838fd1498Szrj   m_name_to_pass_map->put (unique_name, pass);
86938fd1498Szrj }
87038fd1498Szrj 
87138fd1498Szrj /* Map from pass id to canonicalized pass name.  */
87238fd1498Szrj 
87338fd1498Szrj typedef const char *char_ptr;
87438fd1498Szrj static vec<char_ptr> pass_tab;
87538fd1498Szrj 
87638fd1498Szrj /* Callback function for traversing NAME_TO_PASS_MAP.  */
87738fd1498Szrj 
87838fd1498Szrj bool
passes_pass_traverse(const char * const & name,opt_pass * const & pass,void *)87938fd1498Szrj passes_pass_traverse (const char *const &name, opt_pass *const &pass, void *)
88038fd1498Szrj {
88138fd1498Szrj   gcc_assert (pass->static_pass_number > 0);
88238fd1498Szrj   gcc_assert (pass_tab.exists ());
88338fd1498Szrj 
88438fd1498Szrj   pass_tab[pass->static_pass_number] = name;
88538fd1498Szrj 
88638fd1498Szrj   return 1;
88738fd1498Szrj }
88838fd1498Szrj 
88938fd1498Szrj /* The function traverses NAME_TO_PASS_MAP and creates a pass info
89038fd1498Szrj    table for dumping purpose.  */
89138fd1498Szrj 
89238fd1498Szrj void
create_pass_tab(void)89338fd1498Szrj pass_manager::create_pass_tab (void) const
89438fd1498Szrj {
89538fd1498Szrj   if (!flag_dump_passes)
89638fd1498Szrj     return;
89738fd1498Szrj 
89838fd1498Szrj   pass_tab.safe_grow_cleared (passes_by_id_size + 1);
89938fd1498Szrj   m_name_to_pass_map->traverse <void *, passes_pass_traverse> (NULL);
90038fd1498Szrj }
90138fd1498Szrj 
90238fd1498Szrj static bool override_gate_status (opt_pass *, tree, bool);
90338fd1498Szrj 
90438fd1498Szrj /* Dump the instantiated name for PASS. IS_ON indicates if PASS
90538fd1498Szrj    is turned on or not.  */
90638fd1498Szrj 
90738fd1498Szrj static void
dump_one_pass(opt_pass * pass,int pass_indent)90838fd1498Szrj dump_one_pass (opt_pass *pass, int pass_indent)
90938fd1498Szrj {
91038fd1498Szrj   int indent = 3 * pass_indent;
91138fd1498Szrj   const char *pn;
91238fd1498Szrj   bool is_on, is_really_on;
91338fd1498Szrj 
91438fd1498Szrj   is_on = pass->gate (cfun);
91538fd1498Szrj   is_really_on = override_gate_status (pass, current_function_decl, is_on);
91638fd1498Szrj 
91738fd1498Szrj   if (pass->static_pass_number <= 0)
91838fd1498Szrj     pn = pass->name;
91938fd1498Szrj   else
92038fd1498Szrj     pn = pass_tab[pass->static_pass_number];
92138fd1498Szrj 
92238fd1498Szrj   fprintf (stderr, "%*s%-40s%*s:%s%s\n", indent, " ", pn,
92338fd1498Szrj            (15 - indent < 0 ? 0 : 15 - indent), " ",
92438fd1498Szrj            is_on ? "  ON" : "  OFF",
92538fd1498Szrj            ((!is_on) == (!is_really_on) ? ""
92638fd1498Szrj             : (is_really_on ? " (FORCED_ON)" : " (FORCED_OFF)")));
92738fd1498Szrj }
92838fd1498Szrj 
92938fd1498Szrj /* Dump pass list PASS with indentation INDENT.  */
93038fd1498Szrj 
93138fd1498Szrj static void
dump_pass_list(opt_pass * pass,int indent)93238fd1498Szrj dump_pass_list (opt_pass *pass, int indent)
93338fd1498Szrj {
93438fd1498Szrj   do
93538fd1498Szrj     {
93638fd1498Szrj       dump_one_pass (pass, indent);
93738fd1498Szrj       if (pass->sub)
93838fd1498Szrj         dump_pass_list (pass->sub, indent + 1);
93938fd1498Szrj       pass = pass->next;
94038fd1498Szrj     }
94138fd1498Szrj   while (pass);
94238fd1498Szrj }
94338fd1498Szrj 
94438fd1498Szrj /* Dump all optimization passes.  */
94538fd1498Szrj 
94638fd1498Szrj void
dump_passes(void)94738fd1498Szrj dump_passes (void)
94838fd1498Szrj {
94938fd1498Szrj   g->get_passes ()->dump_passes ();
95038fd1498Szrj }
95138fd1498Szrj 
95238fd1498Szrj void
dump_passes()95338fd1498Szrj pass_manager::dump_passes () const
95438fd1498Szrj {
95538fd1498Szrj   push_dummy_function (true);
95638fd1498Szrj 
95738fd1498Szrj   create_pass_tab ();
95838fd1498Szrj 
95938fd1498Szrj   dump_pass_list (all_lowering_passes, 1);
96038fd1498Szrj   dump_pass_list (all_small_ipa_passes, 1);
96138fd1498Szrj   dump_pass_list (all_regular_ipa_passes, 1);
96238fd1498Szrj   dump_pass_list (all_late_ipa_passes, 1);
96338fd1498Szrj   dump_pass_list (all_passes, 1);
96438fd1498Szrj 
96538fd1498Szrj   pop_dummy_function ();
96638fd1498Szrj }
96738fd1498Szrj 
96838fd1498Szrj /* Returns the pass with NAME.  */
96938fd1498Szrj 
97038fd1498Szrj opt_pass *
get_pass_by_name(const char * name)97138fd1498Szrj pass_manager::get_pass_by_name (const char *name)
97238fd1498Szrj {
97338fd1498Szrj   opt_pass **p = m_name_to_pass_map->get (name);
97438fd1498Szrj   if (p)
97538fd1498Szrj     return *p;
97638fd1498Szrj 
97738fd1498Szrj   return NULL;
97838fd1498Szrj }
97938fd1498Szrj 
98038fd1498Szrj 
98138fd1498Szrj /* Range [start, last].  */
98238fd1498Szrj 
98338fd1498Szrj struct uid_range
98438fd1498Szrj {
98538fd1498Szrj   unsigned int start;
98638fd1498Szrj   unsigned int last;
98738fd1498Szrj   const char *assem_name;
98838fd1498Szrj   struct uid_range *next;
98938fd1498Szrj };
99038fd1498Szrj 
99138fd1498Szrj typedef struct uid_range *uid_range_p;
99238fd1498Szrj 
99338fd1498Szrj 
99438fd1498Szrj static vec<uid_range_p> enabled_pass_uid_range_tab;
99538fd1498Szrj static vec<uid_range_p> disabled_pass_uid_range_tab;
99638fd1498Szrj 
99738fd1498Szrj 
99838fd1498Szrj /* Parse option string for -fdisable- and -fenable-
99938fd1498Szrj    The syntax of the options:
100038fd1498Szrj 
100138fd1498Szrj    -fenable-<pass_name>
100238fd1498Szrj    -fdisable-<pass_name>
100338fd1498Szrj 
100438fd1498Szrj    -fenable-<pass_name>=s1:e1,s2:e2,...
100538fd1498Szrj    -fdisable-<pass_name>=s1:e1,s2:e2,...
100638fd1498Szrj */
100738fd1498Szrj 
100838fd1498Szrj static void
enable_disable_pass(const char * arg,bool is_enable)100938fd1498Szrj enable_disable_pass (const char *arg, bool is_enable)
101038fd1498Szrj {
101138fd1498Szrj   opt_pass *pass;
101238fd1498Szrj   char *range_str, *phase_name;
101338fd1498Szrj   char *argstr = xstrdup (arg);
101438fd1498Szrj   vec<uid_range_p> *tab = 0;
101538fd1498Szrj 
101638fd1498Szrj   range_str = strchr (argstr,'=');
101738fd1498Szrj   if (range_str)
101838fd1498Szrj     {
101938fd1498Szrj       *range_str = '\0';
102038fd1498Szrj       range_str++;
102138fd1498Szrj     }
102238fd1498Szrj 
102338fd1498Szrj   phase_name = argstr;
102438fd1498Szrj   if (!*phase_name)
102538fd1498Szrj     {
102638fd1498Szrj       if (is_enable)
102738fd1498Szrj         error ("unrecognized option -fenable");
102838fd1498Szrj       else
102938fd1498Szrj         error ("unrecognized option -fdisable");
103038fd1498Szrj       free (argstr);
103138fd1498Szrj       return;
103238fd1498Szrj     }
103338fd1498Szrj   pass = g->get_passes ()->get_pass_by_name (phase_name);
103438fd1498Szrj   if (!pass || pass->static_pass_number == -1)
103538fd1498Szrj     {
103638fd1498Szrj       if (is_enable)
103738fd1498Szrj         error ("unknown pass %s specified in -fenable", phase_name);
103838fd1498Szrj       else
103938fd1498Szrj         error ("unknown pass %s specified in -fdisable", phase_name);
104038fd1498Szrj       free (argstr);
104138fd1498Szrj       return;
104238fd1498Szrj     }
104338fd1498Szrj 
104438fd1498Szrj   if (is_enable)
104538fd1498Szrj     tab = &enabled_pass_uid_range_tab;
104638fd1498Szrj   else
104738fd1498Szrj     tab = &disabled_pass_uid_range_tab;
104838fd1498Szrj 
104938fd1498Szrj   if ((unsigned) pass->static_pass_number >= tab->length ())
105038fd1498Szrj     tab->safe_grow_cleared (pass->static_pass_number + 1);
105138fd1498Szrj 
105238fd1498Szrj   if (!range_str)
105338fd1498Szrj     {
105438fd1498Szrj       uid_range_p slot;
105538fd1498Szrj       uid_range_p new_range = XCNEW (struct uid_range);
105638fd1498Szrj 
105738fd1498Szrj       new_range->start = 0;
105838fd1498Szrj       new_range->last = (unsigned)-1;
105938fd1498Szrj 
106038fd1498Szrj       slot = (*tab)[pass->static_pass_number];
106138fd1498Szrj       new_range->next = slot;
106238fd1498Szrj       (*tab)[pass->static_pass_number] = new_range;
106338fd1498Szrj       if (is_enable)
106438fd1498Szrj         inform (UNKNOWN_LOCATION, "enable pass %s for functions in the range "
106538fd1498Szrj                 "of [%u, %u]", phase_name, new_range->start, new_range->last);
106638fd1498Szrj       else
106738fd1498Szrj         inform (UNKNOWN_LOCATION, "disable pass %s for functions in the range "
106838fd1498Szrj                 "of [%u, %u]", phase_name, new_range->start, new_range->last);
106938fd1498Szrj     }
107038fd1498Szrj   else
107138fd1498Szrj     {
107238fd1498Szrj       char *next_range = NULL;
107338fd1498Szrj       char *one_range = range_str;
107438fd1498Szrj       char *end_val = NULL;
107538fd1498Szrj 
107638fd1498Szrj       do
107738fd1498Szrj 	{
107838fd1498Szrj 	  uid_range_p slot;
107938fd1498Szrj 	  uid_range_p new_range;
108038fd1498Szrj 	  char *invalid = NULL;
108138fd1498Szrj 	  long start;
108238fd1498Szrj 	  char *func_name = NULL;
108338fd1498Szrj 
108438fd1498Szrj 	  next_range = strchr (one_range, ',');
108538fd1498Szrj 	  if (next_range)
108638fd1498Szrj 	    {
108738fd1498Szrj 	      *next_range = '\0';
108838fd1498Szrj 	      next_range++;
108938fd1498Szrj 	    }
109038fd1498Szrj 
109138fd1498Szrj 	  end_val = strchr (one_range, ':');
109238fd1498Szrj 	  if (end_val)
109338fd1498Szrj 	    {
109438fd1498Szrj 	      *end_val = '\0';
109538fd1498Szrj 	      end_val++;
109638fd1498Szrj 	    }
109738fd1498Szrj 	  start = strtol (one_range, &invalid, 10);
109838fd1498Szrj 	  if (*invalid || start < 0)
109938fd1498Szrj 	    {
110038fd1498Szrj               if (end_val || (one_range[0] >= '0'
110138fd1498Szrj 			      && one_range[0] <= '9'))
110238fd1498Szrj                 {
110338fd1498Szrj                   error ("Invalid range %s in option %s",
110438fd1498Szrj                          one_range,
110538fd1498Szrj                          is_enable ? "-fenable" : "-fdisable");
110638fd1498Szrj                   free (argstr);
110738fd1498Szrj                   return;
110838fd1498Szrj                 }
110938fd1498Szrj 	      func_name = one_range;
111038fd1498Szrj 	    }
111138fd1498Szrj 	  if (!end_val)
111238fd1498Szrj 	    {
111338fd1498Szrj 	      new_range = XCNEW (struct uid_range);
111438fd1498Szrj               if (!func_name)
111538fd1498Szrj                 {
111638fd1498Szrj                   new_range->start = (unsigned) start;
111738fd1498Szrj                   new_range->last = (unsigned) start;
111838fd1498Szrj                 }
111938fd1498Szrj               else
112038fd1498Szrj                 {
112138fd1498Szrj                   new_range->start = (unsigned) -1;
112238fd1498Szrj                   new_range->last = (unsigned) -1;
112338fd1498Szrj                   new_range->assem_name = xstrdup (func_name);
112438fd1498Szrj                 }
112538fd1498Szrj 	    }
112638fd1498Szrj 	  else
112738fd1498Szrj 	    {
112838fd1498Szrj 	      long last = strtol (end_val, &invalid, 10);
112938fd1498Szrj 	      if (*invalid || last < start)
113038fd1498Szrj 		{
113138fd1498Szrj 		  error ("Invalid range %s in option %s",
113238fd1498Szrj 			 end_val,
113338fd1498Szrj 			 is_enable ? "-fenable" : "-fdisable");
113438fd1498Szrj 		  free (argstr);
113538fd1498Szrj 		  return;
113638fd1498Szrj 		}
113738fd1498Szrj 	      new_range = XCNEW (struct uid_range);
113838fd1498Szrj 	      new_range->start = (unsigned) start;
113938fd1498Szrj 	      new_range->last = (unsigned) last;
114038fd1498Szrj 	    }
114138fd1498Szrj 
114238fd1498Szrj           slot = (*tab)[pass->static_pass_number];
114338fd1498Szrj           new_range->next = slot;
114438fd1498Szrj           (*tab)[pass->static_pass_number] = new_range;
114538fd1498Szrj           if (is_enable)
114638fd1498Szrj             {
114738fd1498Szrj               if (new_range->assem_name)
114838fd1498Szrj                 inform (UNKNOWN_LOCATION,
114938fd1498Szrj                         "enable pass %s for function %s",
115038fd1498Szrj                         phase_name, new_range->assem_name);
115138fd1498Szrj               else
115238fd1498Szrj                 inform (UNKNOWN_LOCATION,
115338fd1498Szrj                         "enable pass %s for functions in the range of [%u, %u]",
115438fd1498Szrj                         phase_name, new_range->start, new_range->last);
115538fd1498Szrj             }
115638fd1498Szrj           else
115738fd1498Szrj             {
115838fd1498Szrj               if (new_range->assem_name)
115938fd1498Szrj                 inform (UNKNOWN_LOCATION,
116038fd1498Szrj                         "disable pass %s for function %s",
116138fd1498Szrj                         phase_name, new_range->assem_name);
116238fd1498Szrj               else
116338fd1498Szrj                 inform (UNKNOWN_LOCATION,
116438fd1498Szrj                         "disable pass %s for functions in the range of [%u, %u]",
116538fd1498Szrj                         phase_name, new_range->start, new_range->last);
116638fd1498Szrj             }
116738fd1498Szrj 
116838fd1498Szrj 	  one_range = next_range;
116938fd1498Szrj 	} while (next_range);
117038fd1498Szrj     }
117138fd1498Szrj 
117238fd1498Szrj   free (argstr);
117338fd1498Szrj }
117438fd1498Szrj 
117538fd1498Szrj /* Enable pass specified by ARG.  */
117638fd1498Szrj 
117738fd1498Szrj void
enable_pass(const char * arg)117838fd1498Szrj enable_pass (const char *arg)
117938fd1498Szrj {
118038fd1498Szrj   enable_disable_pass (arg, true);
118138fd1498Szrj }
118238fd1498Szrj 
118338fd1498Szrj /* Disable pass specified by ARG.  */
118438fd1498Szrj 
118538fd1498Szrj void
disable_pass(const char * arg)118638fd1498Szrj disable_pass (const char *arg)
118738fd1498Szrj {
118838fd1498Szrj   enable_disable_pass (arg, false);
118938fd1498Szrj }
119038fd1498Szrj 
119138fd1498Szrj /* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
119238fd1498Szrj 
119338fd1498Szrj static bool
is_pass_explicitly_enabled_or_disabled(opt_pass * pass,tree func,vec<uid_range_p> tab)119438fd1498Szrj is_pass_explicitly_enabled_or_disabled (opt_pass *pass,
119538fd1498Szrj 					tree func,
119638fd1498Szrj 					vec<uid_range_p> tab)
119738fd1498Szrj {
119838fd1498Szrj   uid_range_p slot, range;
119938fd1498Szrj   int cgraph_uid;
120038fd1498Szrj   const char *aname = NULL;
120138fd1498Szrj 
120238fd1498Szrj   if (!tab.exists ()
120338fd1498Szrj       || (unsigned) pass->static_pass_number >= tab.length ()
120438fd1498Szrj       || pass->static_pass_number == -1)
120538fd1498Szrj     return false;
120638fd1498Szrj 
120738fd1498Szrj   slot = tab[pass->static_pass_number];
120838fd1498Szrj   if (!slot)
120938fd1498Szrj     return false;
121038fd1498Szrj 
121138fd1498Szrj   cgraph_uid = func ? cgraph_node::get (func)->uid : 0;
121238fd1498Szrj   if (func && DECL_ASSEMBLER_NAME_SET_P (func))
121338fd1498Szrj     aname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func));
121438fd1498Szrj 
121538fd1498Szrj   range = slot;
121638fd1498Szrj   while (range)
121738fd1498Szrj     {
121838fd1498Szrj       if ((unsigned) cgraph_uid >= range->start
121938fd1498Szrj 	  && (unsigned) cgraph_uid <= range->last)
122038fd1498Szrj 	return true;
122138fd1498Szrj       if (range->assem_name && aname
122238fd1498Szrj           && !strcmp (range->assem_name, aname))
122338fd1498Szrj         return true;
122438fd1498Szrj       range = range->next;
122538fd1498Szrj     }
122638fd1498Szrj 
122738fd1498Szrj   return false;
122838fd1498Szrj }
122938fd1498Szrj 
123038fd1498Szrj 
123138fd1498Szrj /* Update static_pass_number for passes (and the flag
123238fd1498Szrj    TODO_mark_first_instance).
123338fd1498Szrj 
123438fd1498Szrj    Passes are constructed with static_pass_number preinitialized to 0
123538fd1498Szrj 
123638fd1498Szrj    This field is used in two different ways: initially as instance numbers
123738fd1498Szrj    of their kind, and then as ids within the entire pass manager.
123838fd1498Szrj 
123938fd1498Szrj    Within pass_manager::pass_manager:
124038fd1498Szrj 
124138fd1498Szrj    * In add_pass_instance(), as called by next_pass_1 in
124238fd1498Szrj      NEXT_PASS in init_optimization_passes
124338fd1498Szrj 
124438fd1498Szrj    * When the initial instance of a pass within a pass manager is seen,
124538fd1498Szrj      it is flagged, and its static_pass_number is set to -1
124638fd1498Szrj 
124738fd1498Szrj    * On subsequent times that it is seen, the static pass number
124838fd1498Szrj      is decremented each time, so that if there are e.g. 4 dups,
124938fd1498Szrj      they have static_pass_number -4, 2, 3, 4 respectively (note
125038fd1498Szrj      how the initial one is negative and gives the count); these
125138fd1498Szrj      can be thought of as instance numbers of the specific pass
125238fd1498Szrj 
125338fd1498Szrj    * Within the register_dump_files () traversal, set_pass_for_id()
125438fd1498Szrj      is called on each pass, using these instance numbers to create
125538fd1498Szrj      dumpfile switches, and then overwriting them with a pass id,
125638fd1498Szrj      which are global to the whole pass manager (based on
125738fd1498Szrj      (TDI_end + current value of extra_dump_files_in_use) )  */
125838fd1498Szrj 
125938fd1498Szrj static void
add_pass_instance(opt_pass * new_pass,bool track_duplicates,opt_pass * initial_pass)126038fd1498Szrj add_pass_instance (opt_pass *new_pass, bool track_duplicates,
126138fd1498Szrj 		   opt_pass *initial_pass)
126238fd1498Szrj {
126338fd1498Szrj   /* Are we dealing with the first pass of its kind, or a clone?  */
126438fd1498Szrj   if (new_pass != initial_pass)
126538fd1498Szrj     {
126638fd1498Szrj       /* We're dealing with a clone.  */
126738fd1498Szrj       new_pass->todo_flags_start &= ~TODO_mark_first_instance;
126838fd1498Szrj 
126938fd1498Szrj       /* Indicate to register_dump_files that this pass has duplicates,
127038fd1498Szrj          and so it should rename the dump file.  The first instance will
127138fd1498Szrj          be -1, and be number of duplicates = -static_pass_number - 1.
127238fd1498Szrj          Subsequent instances will be > 0 and just the duplicate number.  */
127338fd1498Szrj       if ((new_pass->name && new_pass->name[0] != '*') || track_duplicates)
127438fd1498Szrj         {
127538fd1498Szrj           initial_pass->static_pass_number -= 1;
127638fd1498Szrj           new_pass->static_pass_number = -initial_pass->static_pass_number;
127738fd1498Szrj 	}
127838fd1498Szrj     }
127938fd1498Szrj   else
128038fd1498Szrj     {
128138fd1498Szrj       /* We're dealing with the first pass of its kind.  */
128238fd1498Szrj       new_pass->todo_flags_start |= TODO_mark_first_instance;
128338fd1498Szrj       new_pass->static_pass_number = -1;
128438fd1498Szrj 
128538fd1498Szrj       invoke_plugin_callbacks (PLUGIN_NEW_PASS, new_pass);
128638fd1498Szrj     }
128738fd1498Szrj }
128838fd1498Szrj 
128938fd1498Szrj /* Add a pass to the pass list. Duplicate the pass if it's already
129038fd1498Szrj    in the list.  */
129138fd1498Szrj 
129238fd1498Szrj static opt_pass **
next_pass_1(opt_pass ** list,opt_pass * pass,opt_pass * initial_pass)129338fd1498Szrj next_pass_1 (opt_pass **list, opt_pass *pass, opt_pass *initial_pass)
129438fd1498Szrj {
129538fd1498Szrj   /* Every pass should have a name so that plugins can refer to them.  */
129638fd1498Szrj   gcc_assert (pass->name != NULL);
129738fd1498Szrj 
129838fd1498Szrj   add_pass_instance (pass, false, initial_pass);
129938fd1498Szrj   *list = pass;
130038fd1498Szrj 
130138fd1498Szrj   return &(*list)->next;
130238fd1498Szrj }
130338fd1498Szrj 
130438fd1498Szrj /* List node for an inserted pass instance. We need to keep track of all
130538fd1498Szrj    the newly-added pass instances (with 'added_pass_nodes' defined below)
130638fd1498Szrj    so that we can register their dump files after pass-positioning is finished.
130738fd1498Szrj    Registering dumping files needs to be post-processed or the
130838fd1498Szrj    static_pass_number of the opt_pass object would be modified and mess up
130938fd1498Szrj    the dump file names of future pass instances to be added.  */
131038fd1498Szrj 
131138fd1498Szrj struct pass_list_node
131238fd1498Szrj {
131338fd1498Szrj   opt_pass *pass;
131438fd1498Szrj   struct pass_list_node *next;
131538fd1498Szrj };
131638fd1498Szrj 
131738fd1498Szrj static struct pass_list_node *added_pass_nodes = NULL;
131838fd1498Szrj static struct pass_list_node *prev_added_pass_node;
131938fd1498Szrj 
132038fd1498Szrj /* Insert the pass at the proper position. Return true if the pass
132138fd1498Szrj    is successfully added.
132238fd1498Szrj 
132338fd1498Szrj    NEW_PASS_INFO - new pass to be inserted
132438fd1498Szrj    PASS_LIST - root of the pass list to insert the new pass to  */
132538fd1498Szrj 
132638fd1498Szrj static bool
position_pass(struct register_pass_info * new_pass_info,opt_pass ** pass_list)132738fd1498Szrj position_pass (struct register_pass_info *new_pass_info, opt_pass **pass_list)
132838fd1498Szrj {
132938fd1498Szrj   opt_pass *pass = *pass_list, *prev_pass = NULL;
133038fd1498Szrj   bool success = false;
133138fd1498Szrj 
133238fd1498Szrj   for ( ; pass; prev_pass = pass, pass = pass->next)
133338fd1498Szrj     {
133438fd1498Szrj       /* Check if the current pass is of the same type as the new pass and
133538fd1498Szrj          matches the name and the instance number of the reference pass.  */
133638fd1498Szrj       if (pass->type == new_pass_info->pass->type
133738fd1498Szrj           && pass->name
133838fd1498Szrj           && !strcmp (pass->name, new_pass_info->reference_pass_name)
133938fd1498Szrj           && ((new_pass_info->ref_pass_instance_number == 0)
134038fd1498Szrj               || (new_pass_info->ref_pass_instance_number ==
134138fd1498Szrj                   pass->static_pass_number)
134238fd1498Szrj               || (new_pass_info->ref_pass_instance_number == 1
134338fd1498Szrj                   && pass->todo_flags_start & TODO_mark_first_instance)))
134438fd1498Szrj         {
134538fd1498Szrj           opt_pass *new_pass;
134638fd1498Szrj           struct pass_list_node *new_pass_node;
134738fd1498Szrj 
134838fd1498Szrj 	  if (new_pass_info->ref_pass_instance_number == 0)
134938fd1498Szrj 	    {
135038fd1498Szrj 	      new_pass = new_pass_info->pass->clone ();
135138fd1498Szrj 	      add_pass_instance (new_pass, true, new_pass_info->pass);
135238fd1498Szrj 	    }
135338fd1498Szrj 	  else
135438fd1498Szrj 	    {
135538fd1498Szrj 	      new_pass = new_pass_info->pass;
135638fd1498Szrj 	      add_pass_instance (new_pass, true, new_pass);
135738fd1498Szrj 	    }
135838fd1498Szrj 
135938fd1498Szrj           /* Insert the new pass instance based on the positioning op.  */
136038fd1498Szrj           switch (new_pass_info->pos_op)
136138fd1498Szrj             {
136238fd1498Szrj               case PASS_POS_INSERT_AFTER:
136338fd1498Szrj                 new_pass->next = pass->next;
136438fd1498Szrj                 pass->next = new_pass;
136538fd1498Szrj 
136638fd1498Szrj 		/* Skip newly inserted pass to avoid repeated
136738fd1498Szrj 		   insertions in the case where the new pass and the
136838fd1498Szrj 		   existing one have the same name.  */
136938fd1498Szrj                 pass = new_pass;
137038fd1498Szrj                 break;
137138fd1498Szrj               case PASS_POS_INSERT_BEFORE:
137238fd1498Szrj                 new_pass->next = pass;
137338fd1498Szrj                 if (prev_pass)
137438fd1498Szrj                   prev_pass->next = new_pass;
137538fd1498Szrj                 else
137638fd1498Szrj                   *pass_list = new_pass;
137738fd1498Szrj                 break;
137838fd1498Szrj               case PASS_POS_REPLACE:
137938fd1498Szrj                 new_pass->next = pass->next;
138038fd1498Szrj                 if (prev_pass)
138138fd1498Szrj                   prev_pass->next = new_pass;
138238fd1498Szrj                 else
138338fd1498Szrj                   *pass_list = new_pass;
138438fd1498Szrj                 new_pass->sub = pass->sub;
138538fd1498Szrj                 new_pass->tv_id = pass->tv_id;
138638fd1498Szrj                 pass = new_pass;
138738fd1498Szrj                 break;
138838fd1498Szrj               default:
138938fd1498Szrj                 error ("invalid pass positioning operation");
139038fd1498Szrj                 return false;
139138fd1498Szrj             }
139238fd1498Szrj 
139338fd1498Szrj           /* Save the newly added pass (instance) in the added_pass_nodes
139438fd1498Szrj              list so that we can register its dump file later. Note that
139538fd1498Szrj              we cannot register the dump file now because doing so will modify
139638fd1498Szrj              the static_pass_number of the opt_pass object and therefore
139738fd1498Szrj              mess up the dump file name of future instances.  */
139838fd1498Szrj           new_pass_node = XCNEW (struct pass_list_node);
139938fd1498Szrj           new_pass_node->pass = new_pass;
140038fd1498Szrj           if (!added_pass_nodes)
140138fd1498Szrj             added_pass_nodes = new_pass_node;
140238fd1498Szrj           else
140338fd1498Szrj             prev_added_pass_node->next = new_pass_node;
140438fd1498Szrj           prev_added_pass_node = new_pass_node;
140538fd1498Szrj 
140638fd1498Szrj           success = true;
140738fd1498Szrj         }
140838fd1498Szrj 
140938fd1498Szrj       if (pass->sub && position_pass (new_pass_info, &pass->sub))
141038fd1498Szrj         success = true;
141138fd1498Szrj     }
141238fd1498Szrj 
141338fd1498Szrj   return success;
141438fd1498Szrj }
141538fd1498Szrj 
141638fd1498Szrj /* Hooks a new pass into the pass lists.
141738fd1498Szrj 
141838fd1498Szrj    PASS_INFO   - pass information that specifies the opt_pass object,
141938fd1498Szrj                  reference pass, instance number, and how to position
142038fd1498Szrj                  the pass  */
142138fd1498Szrj 
142238fd1498Szrj void
register_pass(struct register_pass_info * pass_info)142338fd1498Szrj register_pass (struct register_pass_info *pass_info)
142438fd1498Szrj {
142538fd1498Szrj   g->get_passes ()->register_pass (pass_info);
142638fd1498Szrj }
142738fd1498Szrj 
142838fd1498Szrj void
register_pass(opt_pass * pass,pass_positioning_ops pos,const char * ref_pass_name,int ref_pass_inst_number)142938fd1498Szrj register_pass (opt_pass* pass, pass_positioning_ops pos,
143038fd1498Szrj 	       const char* ref_pass_name, int ref_pass_inst_number)
143138fd1498Szrj {
143238fd1498Szrj   register_pass_info i;
143338fd1498Szrj   i.pass = pass;
143438fd1498Szrj   i.reference_pass_name = ref_pass_name;
143538fd1498Szrj   i.ref_pass_instance_number = ref_pass_inst_number;
143638fd1498Szrj   i.pos_op = pos;
143738fd1498Szrj 
143838fd1498Szrj   g->get_passes ()->register_pass (&i);
143938fd1498Szrj }
144038fd1498Szrj 
144138fd1498Szrj void
register_pass(struct register_pass_info * pass_info)144238fd1498Szrj pass_manager::register_pass (struct register_pass_info *pass_info)
144338fd1498Szrj {
144438fd1498Szrj   bool all_instances, success;
144538fd1498Szrj   gcc::dump_manager *dumps = m_ctxt->get_dumps ();
144638fd1498Szrj 
144738fd1498Szrj   /* The checks below could fail in buggy plugins.  Existing GCC
144838fd1498Szrj      passes should never fail these checks, so we mention plugin in
144938fd1498Szrj      the messages.  */
145038fd1498Szrj   if (!pass_info->pass)
145138fd1498Szrj       fatal_error (input_location, "plugin cannot register a missing pass");
145238fd1498Szrj 
145338fd1498Szrj   if (!pass_info->pass->name)
145438fd1498Szrj       fatal_error (input_location, "plugin cannot register an unnamed pass");
145538fd1498Szrj 
145638fd1498Szrj   if (!pass_info->reference_pass_name)
145738fd1498Szrj       fatal_error
145838fd1498Szrj 	(input_location,
145938fd1498Szrj 	 "plugin cannot register pass %qs without reference pass name",
146038fd1498Szrj 	 pass_info->pass->name);
146138fd1498Szrj 
146238fd1498Szrj   /* Try to insert the new pass to the pass lists.  We need to check
146338fd1498Szrj      all five lists as the reference pass could be in one (or all) of
146438fd1498Szrj      them.  */
146538fd1498Szrj   all_instances = pass_info->ref_pass_instance_number == 0;
146638fd1498Szrj   success = position_pass (pass_info, &all_lowering_passes);
146738fd1498Szrj   if (!success || all_instances)
146838fd1498Szrj     success |= position_pass (pass_info, &all_small_ipa_passes);
146938fd1498Szrj   if (!success || all_instances)
147038fd1498Szrj     success |= position_pass (pass_info, &all_regular_ipa_passes);
147138fd1498Szrj   if (!success || all_instances)
147238fd1498Szrj     success |= position_pass (pass_info, &all_late_ipa_passes);
147338fd1498Szrj   if (!success || all_instances)
147438fd1498Szrj     success |= position_pass (pass_info, &all_passes);
147538fd1498Szrj   if (!success)
147638fd1498Szrj     fatal_error
147738fd1498Szrj       (input_location,
147838fd1498Szrj        "pass %qs not found but is referenced by new pass %qs",
147938fd1498Szrj        pass_info->reference_pass_name, pass_info->pass->name);
148038fd1498Szrj 
148138fd1498Szrj   /* OK, we have successfully inserted the new pass. We need to register
148238fd1498Szrj      the dump files for the newly added pass and its duplicates (if any).
148338fd1498Szrj      Because the registration of plugin/backend passes happens after the
148438fd1498Szrj      command-line options are parsed, the options that specify single
148538fd1498Szrj      pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
148638fd1498Szrj      passes. Therefore we currently can only enable dumping of
148738fd1498Szrj      new passes when the 'dump-all' flags (e.g. -fdump-tree-all)
148838fd1498Szrj      are specified. While doing so, we also delete the pass_list_node
148938fd1498Szrj      objects created during pass positioning.  */
149038fd1498Szrj   while (added_pass_nodes)
149138fd1498Szrj     {
149238fd1498Szrj       struct pass_list_node *next_node = added_pass_nodes->next;
149338fd1498Szrj       enum tree_dump_index tdi;
149438fd1498Szrj       register_one_dump_file (added_pass_nodes->pass);
149538fd1498Szrj       if (added_pass_nodes->pass->type == SIMPLE_IPA_PASS
149638fd1498Szrj           || added_pass_nodes->pass->type == IPA_PASS)
149738fd1498Szrj         tdi = TDI_ipa_all;
149838fd1498Szrj       else if (added_pass_nodes->pass->type == GIMPLE_PASS)
149938fd1498Szrj         tdi = TDI_tree_all;
150038fd1498Szrj       else
150138fd1498Szrj         tdi = TDI_rtl_all;
150238fd1498Szrj       /* Check if dump-all flag is specified.  */
150338fd1498Szrj       if (dumps->get_dump_file_info (tdi)->pstate)
150438fd1498Szrj 	{
150538fd1498Szrj 	  dumps->get_dump_file_info (added_pass_nodes->pass->static_pass_number)
150638fd1498Szrj             ->pstate = dumps->get_dump_file_info (tdi)->pstate;
150738fd1498Szrj 	  dumps->get_dump_file_info (added_pass_nodes->pass->static_pass_number)
150838fd1498Szrj 	    ->pflags = dumps->get_dump_file_info (tdi)->pflags;
150938fd1498Szrj 	}
151038fd1498Szrj       XDELETE (added_pass_nodes);
151138fd1498Szrj       added_pass_nodes = next_node;
151238fd1498Szrj     }
151338fd1498Szrj }
151438fd1498Szrj 
151538fd1498Szrj /* Construct the pass tree.  The sequencing of passes is driven by
151638fd1498Szrj    the cgraph routines:
151738fd1498Szrj 
151838fd1498Szrj    finalize_compilation_unit ()
151938fd1498Szrj        for each node N in the cgraph
152038fd1498Szrj 	   cgraph_analyze_function (N)
152138fd1498Szrj 	       cgraph_lower_function (N) -> all_lowering_passes
152238fd1498Szrj 
152338fd1498Szrj    If we are optimizing, compile is then invoked:
152438fd1498Szrj 
152538fd1498Szrj    compile ()
152638fd1498Szrj        ipa_passes () 			-> all_small_ipa_passes
152738fd1498Szrj 					-> Analysis of all_regular_ipa_passes
152838fd1498Szrj 	* possible LTO streaming at copmilation time *
152938fd1498Szrj 					-> Execution of all_regular_ipa_passes
153038fd1498Szrj 	* possible LTO streaming at link time *
153138fd1498Szrj 					-> all_late_ipa_passes
153238fd1498Szrj        expand_all_functions ()
153338fd1498Szrj            for each node N in the cgraph
153438fd1498Szrj 	       expand_function (N)      -> Transformation of all_regular_ipa_passes
153538fd1498Szrj 				        -> all_passes
153638fd1498Szrj */
153738fd1498Szrj 
pass_manager(context * ctxt)153838fd1498Szrj pass_manager::pass_manager (context *ctxt)
153938fd1498Szrj : all_passes (NULL), all_small_ipa_passes (NULL), all_lowering_passes (NULL),
154038fd1498Szrj   all_regular_ipa_passes (NULL),
154138fd1498Szrj   all_late_ipa_passes (NULL), passes_by_id (NULL), passes_by_id_size (0),
154238fd1498Szrj   m_ctxt (ctxt), m_name_to_pass_map (NULL)
154338fd1498Szrj {
154438fd1498Szrj   opt_pass **p;
154538fd1498Szrj 
154638fd1498Szrj   /* Zero-initialize pass members.  */
154738fd1498Szrj #define INSERT_PASSES_AFTER(PASS)
154838fd1498Szrj #define PUSH_INSERT_PASSES_WITHIN(PASS)
154938fd1498Szrj #define POP_INSERT_PASSES()
155038fd1498Szrj #define NEXT_PASS(PASS, NUM) PASS ## _ ## NUM = NULL
155138fd1498Szrj #define NEXT_PASS_WITH_ARG(PASS, NUM, ARG) NEXT_PASS (PASS, NUM)
155238fd1498Szrj #define TERMINATE_PASS_LIST(PASS)
155338fd1498Szrj #include "pass-instances.def"
155438fd1498Szrj #undef INSERT_PASSES_AFTER
155538fd1498Szrj #undef PUSH_INSERT_PASSES_WITHIN
155638fd1498Szrj #undef POP_INSERT_PASSES
155738fd1498Szrj #undef NEXT_PASS
155838fd1498Szrj #undef NEXT_PASS_WITH_ARG
155938fd1498Szrj #undef TERMINATE_PASS_LIST
156038fd1498Szrj 
156138fd1498Szrj   /* Initialize the pass_lists array.  */
156238fd1498Szrj #define DEF_PASS_LIST(LIST) pass_lists[PASS_LIST_NO_##LIST] = &LIST;
156338fd1498Szrj   GCC_PASS_LISTS
156438fd1498Szrj #undef DEF_PASS_LIST
156538fd1498Szrj 
156638fd1498Szrj   /* Build the tree of passes.  */
156738fd1498Szrj 
156838fd1498Szrj #define INSERT_PASSES_AFTER(PASS)		\
156938fd1498Szrj   {						\
157038fd1498Szrj     opt_pass **p_start;				\
157138fd1498Szrj     p_start = p = &(PASS);
157238fd1498Szrj 
157338fd1498Szrj #define TERMINATE_PASS_LIST(PASS)		\
157438fd1498Szrj     gcc_assert (p_start == &PASS);		\
157538fd1498Szrj     *p = NULL;					\
157638fd1498Szrj   }
157738fd1498Szrj 
157838fd1498Szrj #define PUSH_INSERT_PASSES_WITHIN(PASS) \
157938fd1498Szrj   { \
158038fd1498Szrj     opt_pass **p = &(PASS ## _1)->sub;
158138fd1498Szrj 
158238fd1498Szrj #define POP_INSERT_PASSES() \
158338fd1498Szrj   }
158438fd1498Szrj 
158538fd1498Szrj #define NEXT_PASS(PASS, NUM) \
158638fd1498Szrj   do { \
158738fd1498Szrj     gcc_assert (PASS ## _ ## NUM == NULL); \
158838fd1498Szrj     if ((NUM) == 1)                              \
158938fd1498Szrj       PASS ## _1 = make_##PASS (m_ctxt);          \
159038fd1498Szrj     else                                         \
159138fd1498Szrj       {                                          \
159238fd1498Szrj         gcc_assert (PASS ## _1);                 \
159338fd1498Szrj         PASS ## _ ## NUM = PASS ## _1->clone (); \
159438fd1498Szrj       }                                          \
159538fd1498Szrj     p = next_pass_1 (p, PASS ## _ ## NUM, PASS ## _1);  \
159638fd1498Szrj   } while (0)
159738fd1498Szrj 
159838fd1498Szrj #define NEXT_PASS_WITH_ARG(PASS, NUM, ARG)		\
159938fd1498Szrj     do {						\
160038fd1498Szrj       NEXT_PASS (PASS, NUM);				\
160138fd1498Szrj       PASS ## _ ## NUM->set_pass_param (0, ARG);	\
160238fd1498Szrj     } while (0)
160338fd1498Szrj 
160438fd1498Szrj #include "pass-instances.def"
160538fd1498Szrj 
160638fd1498Szrj #undef INSERT_PASSES_AFTER
160738fd1498Szrj #undef PUSH_INSERT_PASSES_WITHIN
160838fd1498Szrj #undef POP_INSERT_PASSES
160938fd1498Szrj #undef NEXT_PASS
161038fd1498Szrj #undef NEXT_PASS_WITH_ARG
161138fd1498Szrj #undef TERMINATE_PASS_LIST
161238fd1498Szrj 
161338fd1498Szrj   /* Register the passes with the tree dump code.  */
161438fd1498Szrj   register_dump_files (all_lowering_passes);
161538fd1498Szrj   register_dump_files (all_small_ipa_passes);
161638fd1498Szrj   register_dump_files (all_regular_ipa_passes);
161738fd1498Szrj   register_dump_files (all_late_ipa_passes);
161838fd1498Szrj   register_dump_files (all_passes);
161938fd1498Szrj }
162038fd1498Szrj 
162138fd1498Szrj static void
delete_pass_tree(opt_pass * pass)162238fd1498Szrj delete_pass_tree (opt_pass *pass)
162338fd1498Szrj {
162438fd1498Szrj   while (pass)
162538fd1498Szrj     {
162638fd1498Szrj       /* Recurse into child passes.  */
162738fd1498Szrj       delete_pass_tree (pass->sub);
162838fd1498Szrj 
162938fd1498Szrj       opt_pass *next = pass->next;
163038fd1498Szrj 
163138fd1498Szrj       /* Delete this pass.  */
163238fd1498Szrj       delete pass;
163338fd1498Szrj 
163438fd1498Szrj       /* Iterate onto sibling passes.  */
163538fd1498Szrj       pass = next;
163638fd1498Szrj     }
163738fd1498Szrj }
163838fd1498Szrj 
~pass_manager()163938fd1498Szrj pass_manager::~pass_manager ()
164038fd1498Szrj {
164138fd1498Szrj   XDELETEVEC (passes_by_id);
164238fd1498Szrj 
164338fd1498Szrj   /* Call delete_pass_tree on each of the pass_lists.  */
164438fd1498Szrj #define DEF_PASS_LIST(LIST) \
164538fd1498Szrj     delete_pass_tree (*pass_lists[PASS_LIST_NO_##LIST]);
164638fd1498Szrj   GCC_PASS_LISTS
164738fd1498Szrj #undef DEF_PASS_LIST
164838fd1498Szrj 
164938fd1498Szrj }
165038fd1498Szrj 
165138fd1498Szrj /* If we are in IPA mode (i.e., current_function_decl is NULL), call
165238fd1498Szrj    function CALLBACK for every function in the call graph.  Otherwise,
165338fd1498Szrj    call CALLBACK on the current function.  */
165438fd1498Szrj 
165538fd1498Szrj static void
do_per_function(void (* callback)(function *,void * data),void * data)165638fd1498Szrj do_per_function (void (*callback) (function *, void *data), void *data)
165738fd1498Szrj {
165838fd1498Szrj   if (current_function_decl)
165938fd1498Szrj     callback (cfun, data);
166038fd1498Szrj   else
166138fd1498Szrj     {
166238fd1498Szrj       struct cgraph_node *node;
166338fd1498Szrj       FOR_EACH_DEFINED_FUNCTION (node)
166438fd1498Szrj 	if (node->analyzed && (gimple_has_body_p (node->decl) && !in_lto_p)
166538fd1498Szrj 	    && (!node->clone_of || node->decl != node->clone_of->decl))
166638fd1498Szrj 	  callback (DECL_STRUCT_FUNCTION (node->decl), data);
166738fd1498Szrj     }
166838fd1498Szrj }
166938fd1498Szrj 
167038fd1498Szrj /* Because inlining might remove no-longer reachable nodes, we need to
167138fd1498Szrj    keep the array visible to garbage collector to avoid reading collected
167238fd1498Szrj    out nodes.  */
167338fd1498Szrj static int nnodes;
167438fd1498Szrj static GTY ((length ("nnodes"))) cgraph_node **order;
167538fd1498Szrj 
167638fd1498Szrj /* Hook called when NODE is removed and therefore should be
167738fd1498Szrj    excluded from order vector.  DATA is an array of integers.
167838fd1498Szrj    DATA[0] holds max index it may be accessed by.  For cgraph
167938fd1498Szrj    node DATA[node->uid + 1] holds index of this node in order
168038fd1498Szrj    vector.  */
168138fd1498Szrj static void
remove_cgraph_node_from_order(cgraph_node * node,void * data)168238fd1498Szrj remove_cgraph_node_from_order (cgraph_node *node, void *data)
168338fd1498Szrj {
168438fd1498Szrj   int *order_idx = (int *)data;
168538fd1498Szrj 
168638fd1498Szrj   if (node->uid >= order_idx[0])
168738fd1498Szrj     return;
168838fd1498Szrj 
168938fd1498Szrj   int idx = order_idx[node->uid + 1];
169038fd1498Szrj   if (idx >= 0 && idx < nnodes && order[idx] == node)
169138fd1498Szrj     order[idx] = NULL;
169238fd1498Szrj }
169338fd1498Szrj 
169438fd1498Szrj /* If we are in IPA mode (i.e., current_function_decl is NULL), call
169538fd1498Szrj    function CALLBACK for every function in the call graph.  Otherwise,
169638fd1498Szrj    call CALLBACK on the current function.
169738fd1498Szrj    This function is global so that plugins can use it.  */
169838fd1498Szrj void
do_per_function_toporder(void (* callback)(function *,void * data),void * data)169938fd1498Szrj do_per_function_toporder (void (*callback) (function *, void *data), void *data)
170038fd1498Szrj {
170138fd1498Szrj   int i;
170238fd1498Szrj 
170338fd1498Szrj   if (current_function_decl)
170438fd1498Szrj     callback (cfun, data);
170538fd1498Szrj   else
170638fd1498Szrj     {
170738fd1498Szrj       cgraph_node_hook_list *hook;
170838fd1498Szrj       int *order_idx;
170938fd1498Szrj       gcc_assert (!order);
171038fd1498Szrj       order = ggc_vec_alloc<cgraph_node *> (symtab->cgraph_count);
171138fd1498Szrj 
171238fd1498Szrj       order_idx = XALLOCAVEC (int, symtab->cgraph_max_uid + 1);
171338fd1498Szrj       memset (order_idx + 1, -1, sizeof (int) * symtab->cgraph_max_uid);
171438fd1498Szrj       order_idx[0] = symtab->cgraph_max_uid;
171538fd1498Szrj 
171638fd1498Szrj       nnodes = ipa_reverse_postorder (order);
171738fd1498Szrj       for (i = nnodes - 1; i >= 0; i--)
171838fd1498Szrj 	{
171938fd1498Szrj 	  order[i]->process = 1;
172038fd1498Szrj 	  order_idx[order[i]->uid + 1] = i;
172138fd1498Szrj 	}
172238fd1498Szrj       hook = symtab->add_cgraph_removal_hook (remove_cgraph_node_from_order,
172338fd1498Szrj 					      order_idx);
172438fd1498Szrj       for (i = nnodes - 1; i >= 0; i--)
172538fd1498Szrj 	{
172638fd1498Szrj 	  /* Function could be inlined and removed as unreachable.  */
172738fd1498Szrj 	  if (!order[i])
172838fd1498Szrj 	    continue;
172938fd1498Szrj 
173038fd1498Szrj 	  struct cgraph_node *node = order[i];
173138fd1498Szrj 
173238fd1498Szrj 	  /* Allow possibly removed nodes to be garbage collected.  */
173338fd1498Szrj 	  order[i] = NULL;
173438fd1498Szrj 	  node->process = 0;
173538fd1498Szrj 	  if (node->has_gimple_body_p ())
173638fd1498Szrj 	    {
173738fd1498Szrj 	      struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
173838fd1498Szrj 	      push_cfun (fn);
173938fd1498Szrj 	      callback (fn, data);
174038fd1498Szrj 	      pop_cfun ();
174138fd1498Szrj 	    }
174238fd1498Szrj 	}
174338fd1498Szrj       symtab->remove_cgraph_removal_hook (hook);
174438fd1498Szrj     }
174538fd1498Szrj   ggc_free (order);
174638fd1498Szrj   order = NULL;
174738fd1498Szrj   nnodes = 0;
174838fd1498Szrj }
174938fd1498Szrj 
175038fd1498Szrj /* Helper function to perform function body dump.  */
175138fd1498Szrj 
175238fd1498Szrj static void
execute_function_dump(function * fn,void * data)175338fd1498Szrj execute_function_dump (function *fn, void *data)
175438fd1498Szrj {
175538fd1498Szrj   opt_pass *pass = (opt_pass *)data;
175638fd1498Szrj 
175738fd1498Szrj   if (dump_file)
175838fd1498Szrj     {
175938fd1498Szrj       push_cfun (fn);
176038fd1498Szrj 
176138fd1498Szrj       if (fn->curr_properties & PROP_trees)
176238fd1498Szrj         dump_function_to_file (fn->decl, dump_file, dump_flags);
176338fd1498Szrj       else
176438fd1498Szrj 	print_rtl_with_bb (dump_file, get_insns (), dump_flags);
176538fd1498Szrj 
176638fd1498Szrj       /* Flush the file.  If verification fails, we won't be able to
176738fd1498Szrj 	 close the file before aborting.  */
176838fd1498Szrj       fflush (dump_file);
176938fd1498Szrj 
177038fd1498Szrj       if ((fn->curr_properties & PROP_cfg)
177138fd1498Szrj 	  && (dump_flags & TDF_GRAPH))
177238fd1498Szrj 	{
177338fd1498Szrj 	  gcc::dump_manager *dumps = g->get_dumps ();
177438fd1498Szrj 	  struct dump_file_info *dfi
177538fd1498Szrj 	    = dumps->get_dump_file_info (pass->static_pass_number);
177638fd1498Szrj 	  if (!dfi->graph_dump_initialized)
177738fd1498Szrj 	    {
177838fd1498Szrj 	      clean_graph_dump_file (dump_file_name);
177938fd1498Szrj 	      dfi->graph_dump_initialized = true;
178038fd1498Szrj 	    }
178138fd1498Szrj 	  print_graph_cfg (dump_file_name, fn);
178238fd1498Szrj 	}
178338fd1498Szrj 
178438fd1498Szrj       pop_cfun ();
178538fd1498Szrj     }
178638fd1498Szrj }
178738fd1498Szrj 
178838fd1498Szrj /* This function is called when an internal compiler error is encountered.
178938fd1498Szrj    Ensure that function dump is made available before compiler is aborted.  */
179038fd1498Szrj 
179138fd1498Szrj void
emergency_dump_function()179238fd1498Szrj emergency_dump_function ()
179338fd1498Szrj {
179438fd1498Szrj   if (!current_pass)
179538fd1498Szrj     return;
179638fd1498Szrj   enum opt_pass_type pt = current_pass->type;
179738fd1498Szrj   fnotice (stderr, "during %s pass: %s\n",
179838fd1498Szrj 	   pt == GIMPLE_PASS ? "GIMPLE" : pt == RTL_PASS ? "RTL" : "IPA",
179938fd1498Szrj 	   current_pass->name);
180038fd1498Szrj   if (!dump_file || !cfun)
180138fd1498Szrj     return;
180238fd1498Szrj   fnotice (stderr, "dump file: %s\n", dump_file_name);
180338fd1498Szrj   fprintf (dump_file, "\n\n\nEMERGENCY DUMP:\n\n");
180438fd1498Szrj   execute_function_dump (cfun, current_pass);
180538fd1498Szrj }
180638fd1498Szrj 
180738fd1498Szrj static struct profile_record *profile_record;
180838fd1498Szrj 
180938fd1498Szrj /* Do profile consistency book-keeping for the pass with static number INDEX.
181038fd1498Szrj    If SUBPASS is zero, we run _before_ the pass, and if SUBPASS is one, then
181138fd1498Szrj    we run _after_ the pass.  RUN is true if the pass really runs, or FALSE
181238fd1498Szrj    if we are only book-keeping on passes that may have selectively disabled
181338fd1498Szrj    themselves on a given function.  */
181438fd1498Szrj static void
check_profile_consistency(int index,int subpass,bool run)181538fd1498Szrj check_profile_consistency (int index, int subpass, bool run)
181638fd1498Szrj {
181738fd1498Szrj   pass_manager *passes = g->get_passes ();
181838fd1498Szrj   if (index == -1)
181938fd1498Szrj     return;
182038fd1498Szrj   if (!profile_record)
182138fd1498Szrj     profile_record = XCNEWVEC (struct profile_record,
182238fd1498Szrj 			       passes->passes_by_id_size);
182338fd1498Szrj   gcc_assert (index < passes->passes_by_id_size && index >= 0);
182438fd1498Szrj   gcc_assert (subpass < 2);
182538fd1498Szrj   profile_record[index].run |= run;
182638fd1498Szrj   account_profile_record (&profile_record[index], subpass);
182738fd1498Szrj }
182838fd1498Szrj 
182938fd1498Szrj /* Output profile consistency.  */
183038fd1498Szrj 
183138fd1498Szrj void
dump_profile_report(void)183238fd1498Szrj dump_profile_report (void)
183338fd1498Szrj {
183438fd1498Szrj   g->get_passes ()->dump_profile_report ();
183538fd1498Szrj }
183638fd1498Szrj 
183738fd1498Szrj void
dump_profile_report()183838fd1498Szrj pass_manager::dump_profile_report () const
183938fd1498Szrj {
184038fd1498Szrj   int i, j;
184138fd1498Szrj   int last_freq_in = 0, last_count_in = 0, last_freq_out = 0, last_count_out = 0;
184238fd1498Szrj   gcov_type last_time = 0, last_size = 0;
184338fd1498Szrj   double rel_time_change, rel_size_change;
184438fd1498Szrj   int last_reported = 0;
184538fd1498Szrj 
184638fd1498Szrj   if (!profile_record)
184738fd1498Szrj     return;
184838fd1498Szrj   fprintf (stderr, "\nProfile consistency report:\n\n");
184938fd1498Szrj   fprintf (stderr, "Pass name                        |mismatch in |mismated out|Overall\n");
185038fd1498Szrj   fprintf (stderr, "                                 |freq count  |freq count  |size      time\n");
185138fd1498Szrj 
185238fd1498Szrj   for (i = 0; i < passes_by_id_size; i++)
185338fd1498Szrj     for (j = 0 ; j < 2; j++)
185438fd1498Szrj       if (profile_record[i].run)
185538fd1498Szrj 	{
185638fd1498Szrj 	  if (last_time)
185738fd1498Szrj 	    rel_time_change = (profile_record[i].time[j]
185838fd1498Szrj 			       - (double)last_time) * 100 / (double)last_time;
185938fd1498Szrj 	  else
186038fd1498Szrj 	    rel_time_change = 0;
186138fd1498Szrj 	  if (last_size)
186238fd1498Szrj 	    rel_size_change = (profile_record[i].size[j]
186338fd1498Szrj 			       - (double)last_size) * 100 / (double)last_size;
186438fd1498Szrj 	  else
186538fd1498Szrj 	    rel_size_change = 0;
186638fd1498Szrj 
186738fd1498Szrj 	  if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in
186838fd1498Szrj 	      || profile_record[i].num_mismatched_freq_out[j] != last_freq_out
186938fd1498Szrj 	      || profile_record[i].num_mismatched_count_in[j] != last_count_in
187038fd1498Szrj 	      || profile_record[i].num_mismatched_count_out[j] != last_count_out
187138fd1498Szrj 	      || rel_time_change || rel_size_change)
187238fd1498Szrj 	    {
187338fd1498Szrj 	      last_reported = i;
187438fd1498Szrj               fprintf (stderr, "%-20s %s",
187538fd1498Szrj 		       passes_by_id [i]->name,
187638fd1498Szrj 		       j ? "(after TODO)" : "            ");
187738fd1498Szrj 	      if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in)
187838fd1498Szrj 		fprintf (stderr, "| %+5i",
187938fd1498Szrj 		         profile_record[i].num_mismatched_freq_in[j]
188038fd1498Szrj 			  - last_freq_in);
188138fd1498Szrj 	      else
188238fd1498Szrj 		fprintf (stderr, "|      ");
188338fd1498Szrj 	      if (profile_record[i].num_mismatched_count_in[j] != last_count_in)
188438fd1498Szrj 		fprintf (stderr, " %+5i",
188538fd1498Szrj 		         profile_record[i].num_mismatched_count_in[j]
188638fd1498Szrj 			  - last_count_in);
188738fd1498Szrj 	      else
188838fd1498Szrj 		fprintf (stderr, "      ");
188938fd1498Szrj 	      if (profile_record[i].num_mismatched_freq_out[j] != last_freq_out)
189038fd1498Szrj 		fprintf (stderr, "| %+5i",
189138fd1498Szrj 		         profile_record[i].num_mismatched_freq_out[j]
189238fd1498Szrj 			  - last_freq_out);
189338fd1498Szrj 	      else
189438fd1498Szrj 		fprintf (stderr, "|      ");
189538fd1498Szrj 	      if (profile_record[i].num_mismatched_count_out[j] != last_count_out)
189638fd1498Szrj 		fprintf (stderr, " %+5i",
189738fd1498Szrj 		         profile_record[i].num_mismatched_count_out[j]
189838fd1498Szrj 			  - last_count_out);
189938fd1498Szrj 	      else
190038fd1498Szrj 		fprintf (stderr, "      ");
190138fd1498Szrj 
190238fd1498Szrj 	      /* Size/time units change across gimple and RTL.  */
190338fd1498Szrj 	      if (i == pass_expand_1->static_pass_number)
190438fd1498Szrj 		fprintf (stderr, "|----------");
190538fd1498Szrj 	      else
190638fd1498Szrj 		{
190738fd1498Szrj 		  if (rel_size_change)
190838fd1498Szrj 		    fprintf (stderr, "| %+8.4f%%", rel_size_change);
190938fd1498Szrj 		  else
191038fd1498Szrj 		    fprintf (stderr, "|          ");
191138fd1498Szrj 		  if (rel_time_change)
191238fd1498Szrj 		    fprintf (stderr, " %+8.4f%%", rel_time_change);
191338fd1498Szrj 		}
191438fd1498Szrj 	      fprintf (stderr, "\n");
191538fd1498Szrj 	      last_freq_in = profile_record[i].num_mismatched_freq_in[j];
191638fd1498Szrj 	      last_freq_out = profile_record[i].num_mismatched_freq_out[j];
191738fd1498Szrj 	      last_count_in = profile_record[i].num_mismatched_count_in[j];
191838fd1498Szrj 	      last_count_out = profile_record[i].num_mismatched_count_out[j];
191938fd1498Szrj 	    }
192038fd1498Szrj 	  else if (j && last_reported != i)
192138fd1498Szrj 	    {
192238fd1498Szrj 	      last_reported = i;
192338fd1498Szrj               fprintf (stderr, "%-20s ------------|            |            |\n",
192438fd1498Szrj 		       passes_by_id [i]->name);
192538fd1498Szrj 	    }
192638fd1498Szrj 	  last_time = profile_record[i].time[j];
192738fd1498Szrj 	  last_size = profile_record[i].size[j];
192838fd1498Szrj 	}
192938fd1498Szrj }
193038fd1498Szrj 
193138fd1498Szrj /* Perform all TODO actions that ought to be done on each function.  */
193238fd1498Szrj 
193338fd1498Szrj static void
execute_function_todo(function * fn,void * data)193438fd1498Szrj execute_function_todo (function *fn, void *data)
193538fd1498Szrj {
193638fd1498Szrj   bool from_ipa_pass = (cfun == NULL);
193738fd1498Szrj   unsigned int flags = (size_t)data;
193838fd1498Szrj   flags &= ~fn->last_verified;
193938fd1498Szrj   if (!flags)
194038fd1498Szrj     return;
194138fd1498Szrj 
194238fd1498Szrj   push_cfun (fn);
194338fd1498Szrj 
194438fd1498Szrj   /* Always cleanup the CFG before trying to update SSA.  */
194538fd1498Szrj   if (flags & TODO_cleanup_cfg)
194638fd1498Szrj     {
1947*e215fc28Szrj       cleanup_tree_cfg (flags & TODO_update_ssa_any);
194838fd1498Szrj 
194938fd1498Szrj       /* When cleanup_tree_cfg merges consecutive blocks, it may
195038fd1498Szrj 	 perform some simplistic propagation when removing single
195138fd1498Szrj 	 valued PHI nodes.  This propagation may, in turn, cause the
195238fd1498Szrj 	 SSA form to become out-of-date (see PR 22037).  So, even
195338fd1498Szrj 	 if the parent pass had not scheduled an SSA update, we may
195438fd1498Szrj 	 still need to do one.  */
195538fd1498Szrj       if (!(flags & TODO_update_ssa_any) && need_ssa_update_p (cfun))
195638fd1498Szrj 	flags |= TODO_update_ssa;
195738fd1498Szrj     }
195838fd1498Szrj 
195938fd1498Szrj   if (flags & TODO_update_ssa_any)
196038fd1498Szrj     {
196138fd1498Szrj       unsigned update_flags = flags & TODO_update_ssa_any;
196238fd1498Szrj       update_ssa (update_flags);
196338fd1498Szrj     }
196438fd1498Szrj 
196538fd1498Szrj   if (flag_tree_pta && (flags & TODO_rebuild_alias))
196638fd1498Szrj     compute_may_aliases ();
196738fd1498Szrj 
196838fd1498Szrj   if (optimize && (flags & TODO_update_address_taken))
196938fd1498Szrj     execute_update_addresses_taken ();
197038fd1498Szrj 
197138fd1498Szrj   if (flags & TODO_remove_unused_locals)
197238fd1498Szrj     remove_unused_locals ();
197338fd1498Szrj 
197438fd1498Szrj   if (flags & TODO_rebuild_frequencies)
197538fd1498Szrj     rebuild_frequencies ();
197638fd1498Szrj 
197738fd1498Szrj   if (flags & TODO_rebuild_cgraph_edges)
197838fd1498Szrj     cgraph_edge::rebuild_edges ();
197938fd1498Szrj 
198038fd1498Szrj   gcc_assert (dom_info_state (fn, CDI_POST_DOMINATORS) == DOM_NONE);
198138fd1498Szrj   /* If we've seen errors do not bother running any verifiers.  */
198238fd1498Szrj   if (flag_checking && !seen_error ())
198338fd1498Szrj     {
198438fd1498Szrj       dom_state pre_verify_state = dom_info_state (fn, CDI_DOMINATORS);
198538fd1498Szrj       dom_state pre_verify_pstate = dom_info_state (fn, CDI_POST_DOMINATORS);
198638fd1498Szrj 
198738fd1498Szrj       if (flags & TODO_verify_il)
198838fd1498Szrj 	{
198938fd1498Szrj 	  if (cfun->curr_properties & PROP_trees)
199038fd1498Szrj 	    {
199138fd1498Szrj 	      if (cfun->curr_properties & PROP_cfg)
199238fd1498Szrj 		/* IPA passes leave stmts to be fixed up, so make sure to
199338fd1498Szrj 		   not verify stmts really throw.  */
199438fd1498Szrj 		verify_gimple_in_cfg (cfun, !from_ipa_pass);
199538fd1498Szrj 	      else
199638fd1498Szrj 		verify_gimple_in_seq (gimple_body (cfun->decl));
199738fd1498Szrj 	    }
199838fd1498Szrj 	  if (cfun->curr_properties & PROP_ssa)
199938fd1498Szrj 	    /* IPA passes leave stmts to be fixed up, so make sure to
200038fd1498Szrj 	       not verify SSA operands whose verifier will choke on that.  */
200138fd1498Szrj 	    verify_ssa (true, !from_ipa_pass);
200238fd1498Szrj 	  /* IPA passes leave basic-blocks unsplit, so make sure to
200338fd1498Szrj 	     not trip on that.  */
200438fd1498Szrj 	  if ((cfun->curr_properties & PROP_cfg)
200538fd1498Szrj 	      && !from_ipa_pass)
200638fd1498Szrj 	    verify_flow_info ();
200738fd1498Szrj 	  if (current_loops
200838fd1498Szrj 	      && ! loops_state_satisfies_p (LOOPS_NEED_FIXUP))
200938fd1498Szrj 	    {
201038fd1498Szrj 	      verify_loop_structure ();
201138fd1498Szrj 	      if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
201238fd1498Szrj 		verify_loop_closed_ssa (false);
201338fd1498Szrj 	    }
201438fd1498Szrj 	  if (cfun->curr_properties & PROP_rtl)
201538fd1498Szrj 	    verify_rtl_sharing ();
201638fd1498Szrj 	}
201738fd1498Szrj 
201838fd1498Szrj       /* Make sure verifiers don't change dominator state.  */
201938fd1498Szrj       gcc_assert (dom_info_state (fn, CDI_DOMINATORS) == pre_verify_state);
202038fd1498Szrj       gcc_assert (dom_info_state (fn, CDI_POST_DOMINATORS) == pre_verify_pstate);
202138fd1498Szrj     }
202238fd1498Szrj 
202338fd1498Szrj   fn->last_verified = flags & TODO_verify_all;
202438fd1498Szrj 
202538fd1498Szrj   pop_cfun ();
202638fd1498Szrj 
202738fd1498Szrj   /* For IPA passes make sure to release dominator info, it can be
202838fd1498Szrj      computed by non-verifying TODOs.  */
202938fd1498Szrj   if (from_ipa_pass)
203038fd1498Szrj     {
203138fd1498Szrj       free_dominance_info (fn, CDI_DOMINATORS);
203238fd1498Szrj       free_dominance_info (fn, CDI_POST_DOMINATORS);
203338fd1498Szrj     }
203438fd1498Szrj }
203538fd1498Szrj 
203638fd1498Szrj /* Perform all TODO actions.  */
203738fd1498Szrj static void
execute_todo(unsigned int flags)203838fd1498Szrj execute_todo (unsigned int flags)
203938fd1498Szrj {
204038fd1498Szrj   if (flag_checking
204138fd1498Szrj       && cfun
204238fd1498Szrj       && need_ssa_update_p (cfun))
204338fd1498Szrj     gcc_assert (flags & TODO_update_ssa_any);
204438fd1498Szrj 
204538fd1498Szrj   statistics_fini_pass ();
204638fd1498Szrj 
204738fd1498Szrj   if (flags)
204838fd1498Szrj     do_per_function (execute_function_todo, (void *)(size_t) flags);
204938fd1498Szrj 
205038fd1498Szrj   /* At this point we should not have any unreachable code in the
205138fd1498Szrj      CFG, so it is safe to flush the pending freelist for SSA_NAMES.  */
205238fd1498Szrj   if (cfun && cfun->gimple_df)
205338fd1498Szrj     flush_ssaname_freelist ();
205438fd1498Szrj 
205538fd1498Szrj   /* Always remove functions just as before inlining: IPA passes might be
205638fd1498Szrj      interested to see bodies of extern inline functions that are not inlined
205738fd1498Szrj      to analyze side effects.  The full removal is done just at the end
205838fd1498Szrj      of IPA pass queue.  */
205938fd1498Szrj   if (flags & TODO_remove_functions)
206038fd1498Szrj     {
206138fd1498Szrj       gcc_assert (!cfun);
206238fd1498Szrj       symtab->remove_unreachable_nodes (dump_file);
206338fd1498Szrj     }
206438fd1498Szrj 
206538fd1498Szrj   if ((flags & TODO_dump_symtab) && dump_file && !current_function_decl)
206638fd1498Szrj     {
206738fd1498Szrj       gcc_assert (!cfun);
206838fd1498Szrj       symtab->dump (dump_file);
206938fd1498Szrj       /* Flush the file.  If verification fails, we won't be able to
207038fd1498Szrj 	 close the file before aborting.  */
207138fd1498Szrj       fflush (dump_file);
207238fd1498Szrj     }
207338fd1498Szrj 
207438fd1498Szrj   /* Now that the dumping has been done, we can get rid of the optional
207538fd1498Szrj      df problems.  */
207638fd1498Szrj   if (flags & TODO_df_finish)
207738fd1498Szrj     df_finish_pass ((flags & TODO_df_verify) != 0);
207838fd1498Szrj }
207938fd1498Szrj 
208038fd1498Szrj /* Verify invariants that should hold between passes.  This is a place
208138fd1498Szrj    to put simple sanity checks.  */
208238fd1498Szrj 
208338fd1498Szrj static void
verify_interpass_invariants(void)208438fd1498Szrj verify_interpass_invariants (void)
208538fd1498Szrj {
208638fd1498Szrj   gcc_checking_assert (!fold_deferring_overflow_warnings_p ());
208738fd1498Szrj }
208838fd1498Szrj 
208938fd1498Szrj /* Clear the last verified flag.  */
209038fd1498Szrj 
209138fd1498Szrj static void
clear_last_verified(function * fn,void * data ATTRIBUTE_UNUSED)209238fd1498Szrj clear_last_verified (function *fn, void *data ATTRIBUTE_UNUSED)
209338fd1498Szrj {
209438fd1498Szrj   fn->last_verified = 0;
209538fd1498Szrj }
209638fd1498Szrj 
209738fd1498Szrj /* Helper function. Verify that the properties has been turn into the
209838fd1498Szrj    properties expected by the pass.  */
209938fd1498Szrj 
210038fd1498Szrj static void
verify_curr_properties(function * fn,void * data)210138fd1498Szrj verify_curr_properties (function *fn, void *data)
210238fd1498Szrj {
210338fd1498Szrj   unsigned int props = (size_t)data;
210438fd1498Szrj   gcc_assert ((fn->curr_properties & props) == props);
210538fd1498Szrj }
210638fd1498Szrj 
210738fd1498Szrj /* Release dump file name if set.  */
210838fd1498Szrj 
210938fd1498Szrj static void
release_dump_file_name(void)211038fd1498Szrj release_dump_file_name (void)
211138fd1498Szrj {
211238fd1498Szrj   if (dump_file_name)
211338fd1498Szrj     {
211438fd1498Szrj       free (CONST_CAST (char *, dump_file_name));
211538fd1498Szrj       dump_file_name = NULL;
211638fd1498Szrj     }
211738fd1498Szrj }
211838fd1498Szrj 
211938fd1498Szrj /* Initialize pass dump file.  */
212038fd1498Szrj /* This is non-static so that the plugins can use it.  */
212138fd1498Szrj 
212238fd1498Szrj bool
pass_init_dump_file(opt_pass * pass)212338fd1498Szrj pass_init_dump_file (opt_pass *pass)
212438fd1498Szrj {
212538fd1498Szrj   /* If a dump file name is present, open it if enabled.  */
212638fd1498Szrj   if (pass->static_pass_number != -1)
212738fd1498Szrj     {
212838fd1498Szrj       timevar_push (TV_DUMP);
212938fd1498Szrj       gcc::dump_manager *dumps = g->get_dumps ();
213038fd1498Szrj       bool initializing_dump =
213138fd1498Szrj 	!dumps->dump_initialized_p (pass->static_pass_number);
213238fd1498Szrj       release_dump_file_name ();
213338fd1498Szrj       dump_file_name = dumps->get_dump_file_name (pass->static_pass_number);
213438fd1498Szrj       dumps->dump_start (pass->static_pass_number, &dump_flags);
213538fd1498Szrj       if (dump_file && current_function_decl && ! (dump_flags & TDF_GIMPLE))
213638fd1498Szrj         dump_function_header (dump_file, current_function_decl, dump_flags);
213738fd1498Szrj       if (initializing_dump
213838fd1498Szrj 	  && dump_file && (dump_flags & TDF_GRAPH)
213938fd1498Szrj 	  && cfun && (cfun->curr_properties & PROP_cfg))
214038fd1498Szrj 	{
214138fd1498Szrj 	  clean_graph_dump_file (dump_file_name);
214238fd1498Szrj 	  struct dump_file_info *dfi
214338fd1498Szrj 	    = dumps->get_dump_file_info (pass->static_pass_number);
214438fd1498Szrj 	  dfi->graph_dump_initialized = true;
214538fd1498Szrj 	}
214638fd1498Szrj       timevar_pop (TV_DUMP);
214738fd1498Szrj       return initializing_dump;
214838fd1498Szrj     }
214938fd1498Szrj   else
215038fd1498Szrj     return false;
215138fd1498Szrj }
215238fd1498Szrj 
215338fd1498Szrj /* Flush PASS dump file.  */
215438fd1498Szrj /* This is non-static so that plugins can use it.  */
215538fd1498Szrj 
215638fd1498Szrj void
pass_fini_dump_file(opt_pass * pass)215738fd1498Szrj pass_fini_dump_file (opt_pass *pass)
215838fd1498Szrj {
215938fd1498Szrj   timevar_push (TV_DUMP);
216038fd1498Szrj 
216138fd1498Szrj   /* Flush and close dump file.  */
216238fd1498Szrj   release_dump_file_name ();
216338fd1498Szrj 
216438fd1498Szrj   g->get_dumps ()->dump_finish (pass->static_pass_number);
216538fd1498Szrj   timevar_pop (TV_DUMP);
216638fd1498Szrj }
216738fd1498Szrj 
216838fd1498Szrj /* After executing the pass, apply expected changes to the function
216938fd1498Szrj    properties. */
217038fd1498Szrj 
217138fd1498Szrj static void
update_properties_after_pass(function * fn,void * data)217238fd1498Szrj update_properties_after_pass (function *fn, void *data)
217338fd1498Szrj {
217438fd1498Szrj   opt_pass *pass = (opt_pass *) data;
217538fd1498Szrj   fn->curr_properties = (fn->curr_properties | pass->properties_provided)
217638fd1498Szrj 		         & ~pass->properties_destroyed;
217738fd1498Szrj }
217838fd1498Szrj 
217938fd1498Szrj /* Execute summary generation for all of the passes in IPA_PASS.  */
218038fd1498Szrj 
218138fd1498Szrj void
execute_ipa_summary_passes(ipa_opt_pass_d * ipa_pass)218238fd1498Szrj execute_ipa_summary_passes (ipa_opt_pass_d *ipa_pass)
218338fd1498Szrj {
218438fd1498Szrj   while (ipa_pass)
218538fd1498Szrj     {
218638fd1498Szrj       opt_pass *pass = ipa_pass;
218738fd1498Szrj 
218838fd1498Szrj       /* Execute all of the IPA_PASSes in the list.  */
218938fd1498Szrj       if (ipa_pass->type == IPA_PASS
219038fd1498Szrj 	  && pass->gate (cfun)
219138fd1498Szrj 	  && ipa_pass->generate_summary)
219238fd1498Szrj 	{
219338fd1498Szrj 	  pass_init_dump_file (pass);
219438fd1498Szrj 
219538fd1498Szrj 	  /* If a timevar is present, start it.  */
219638fd1498Szrj 	  if (pass->tv_id)
219738fd1498Szrj 	    timevar_push (pass->tv_id);
219838fd1498Szrj 
219938fd1498Szrj 	  current_pass = pass;
220038fd1498Szrj 	  ipa_pass->generate_summary ();
220138fd1498Szrj 
220238fd1498Szrj 	  /* Stop timevar.  */
220338fd1498Szrj 	  if (pass->tv_id)
220438fd1498Szrj 	    timevar_pop (pass->tv_id);
220538fd1498Szrj 
220638fd1498Szrj 	  pass_fini_dump_file (pass);
220738fd1498Szrj 	}
220838fd1498Szrj       ipa_pass = (ipa_opt_pass_d *)ipa_pass->next;
220938fd1498Szrj     }
221038fd1498Szrj }
221138fd1498Szrj 
221238fd1498Szrj /* Execute IPA_PASS function transform on NODE.  */
221338fd1498Szrj 
221438fd1498Szrj static void
execute_one_ipa_transform_pass(struct cgraph_node * node,ipa_opt_pass_d * ipa_pass)221538fd1498Szrj execute_one_ipa_transform_pass (struct cgraph_node *node,
221638fd1498Szrj 				ipa_opt_pass_d *ipa_pass)
221738fd1498Szrj {
221838fd1498Szrj   opt_pass *pass = ipa_pass;
221938fd1498Szrj   unsigned int todo_after = 0;
222038fd1498Szrj 
222138fd1498Szrj   current_pass = pass;
222238fd1498Szrj   if (!ipa_pass->function_transform)
222338fd1498Szrj     return;
222438fd1498Szrj 
222538fd1498Szrj   /* Note that the folders should only create gimple expressions.
222638fd1498Szrj      This is a hack until the new folder is ready.  */
222738fd1498Szrj   in_gimple_form = (cfun && (cfun->curr_properties & PROP_trees)) != 0;
222838fd1498Szrj 
222938fd1498Szrj   pass_init_dump_file (pass);
223038fd1498Szrj 
223138fd1498Szrj   /* If a timevar is present, start it.  */
223238fd1498Szrj   if (pass->tv_id != TV_NONE)
223338fd1498Szrj     timevar_push (pass->tv_id);
223438fd1498Szrj 
223538fd1498Szrj   /* Run pre-pass verification.  */
223638fd1498Szrj   execute_todo (ipa_pass->function_transform_todo_flags_start);
223738fd1498Szrj 
223838fd1498Szrj   /* Do it!  */
223938fd1498Szrj   todo_after = ipa_pass->function_transform (node);
224038fd1498Szrj 
224138fd1498Szrj   if (profile_report && cfun && (cfun->curr_properties & PROP_cfg))
224238fd1498Szrj     check_profile_consistency (pass->static_pass_number, 0, true);
224338fd1498Szrj 
224438fd1498Szrj   /* Run post-pass cleanup and verification.  */
224538fd1498Szrj   execute_todo (todo_after);
224638fd1498Szrj   verify_interpass_invariants ();
224738fd1498Szrj   if (profile_report && cfun && (cfun->curr_properties & PROP_cfg))
224838fd1498Szrj     check_profile_consistency (pass->static_pass_number, 1, true);
224938fd1498Szrj 
225038fd1498Szrj   /* Stop timevar.  */
225138fd1498Szrj   if (pass->tv_id != TV_NONE)
225238fd1498Szrj     timevar_pop (pass->tv_id);
225338fd1498Szrj 
225438fd1498Szrj   if (dump_file)
225538fd1498Szrj     do_per_function (execute_function_dump, pass);
225638fd1498Szrj   pass_fini_dump_file (pass);
225738fd1498Szrj 
225838fd1498Szrj   current_pass = NULL;
225938fd1498Szrj   redirect_edge_var_map_empty ();
226038fd1498Szrj 
226138fd1498Szrj   /* Signal this is a suitable GC collection point.  */
226238fd1498Szrj   if (!(todo_after & TODO_do_not_ggc_collect))
226338fd1498Szrj     ggc_collect ();
226438fd1498Szrj }
226538fd1498Szrj 
226638fd1498Szrj /* For the current function, execute all ipa transforms. */
226738fd1498Szrj 
226838fd1498Szrj void
execute_all_ipa_transforms(void)226938fd1498Szrj execute_all_ipa_transforms (void)
227038fd1498Szrj {
227138fd1498Szrj   struct cgraph_node *node;
227238fd1498Szrj   if (!cfun)
227338fd1498Szrj     return;
227438fd1498Szrj   node = cgraph_node::get (current_function_decl);
227538fd1498Szrj 
227638fd1498Szrj   if (node->ipa_transforms_to_apply.exists ())
227738fd1498Szrj     {
227838fd1498Szrj       unsigned int i;
227938fd1498Szrj 
228038fd1498Szrj       for (i = 0; i < node->ipa_transforms_to_apply.length (); i++)
228138fd1498Szrj 	execute_one_ipa_transform_pass (node, node->ipa_transforms_to_apply[i]);
228238fd1498Szrj       node->ipa_transforms_to_apply.release ();
228338fd1498Szrj     }
228438fd1498Szrj }
228538fd1498Szrj 
228638fd1498Szrj /* Check if PASS is explicitly disabled or enabled and return
228738fd1498Szrj    the gate status.  FUNC is the function to be processed, and
228838fd1498Szrj    GATE_STATUS is the gate status determined by pass manager by
228938fd1498Szrj    default.  */
229038fd1498Szrj 
229138fd1498Szrj static bool
override_gate_status(opt_pass * pass,tree func,bool gate_status)229238fd1498Szrj override_gate_status (opt_pass *pass, tree func, bool gate_status)
229338fd1498Szrj {
229438fd1498Szrj   bool explicitly_enabled = false;
229538fd1498Szrj   bool explicitly_disabled = false;
229638fd1498Szrj 
229738fd1498Szrj   explicitly_enabled
229838fd1498Szrj    = is_pass_explicitly_enabled_or_disabled (pass, func,
229938fd1498Szrj                                              enabled_pass_uid_range_tab);
230038fd1498Szrj   explicitly_disabled
230138fd1498Szrj    = is_pass_explicitly_enabled_or_disabled (pass, func,
230238fd1498Szrj                                              disabled_pass_uid_range_tab);
230338fd1498Szrj 
230438fd1498Szrj   gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
230538fd1498Szrj 
230638fd1498Szrj   return gate_status;
230738fd1498Szrj }
230838fd1498Szrj 
230938fd1498Szrj /* Determine if PASS_NAME matches CRITERION.
231038fd1498Szrj    Not a pure predicate, since it can update CRITERION, to support
231138fd1498Szrj    matching the Nth invocation of a pass.
231238fd1498Szrj    Subroutine of should_skip_pass_p.  */
231338fd1498Szrj 
231438fd1498Szrj static bool
determine_pass_name_match(const char * pass_name,char * criterion)231538fd1498Szrj determine_pass_name_match (const char *pass_name, char *criterion)
231638fd1498Szrj {
231738fd1498Szrj   size_t namelen = strlen (pass_name);
231838fd1498Szrj   if (! strncmp (pass_name, criterion, namelen))
231938fd1498Szrj     {
232038fd1498Szrj       /* The following supports starting with the Nth invocation
232138fd1498Szrj 	 of a pass (where N does not necessarily is equal to the
232238fd1498Szrj 	 dump file suffix).  */
232338fd1498Szrj       if (criterion[namelen] == '\0'
232438fd1498Szrj 	  || (criterion[namelen] == '1'
232538fd1498Szrj 	      && criterion[namelen + 1] == '\0'))
232638fd1498Szrj 	return true;
232738fd1498Szrj       else
232838fd1498Szrj 	{
232938fd1498Szrj 	  if (criterion[namelen + 1] == '\0')
233038fd1498Szrj 	    --criterion[namelen];
233138fd1498Szrj 	  return false;
233238fd1498Szrj 	}
233338fd1498Szrj     }
233438fd1498Szrj   else
233538fd1498Szrj     return false;
233638fd1498Szrj }
233738fd1498Szrj 
233838fd1498Szrj /* For skipping passes until "startwith" pass.
233938fd1498Szrj    Return true iff PASS should be skipped.
234038fd1498Szrj    Clear cfun->pass_startwith when encountering the "startwith" pass,
234138fd1498Szrj    so that all subsequent passes are run.  */
234238fd1498Szrj 
234338fd1498Szrj static bool
should_skip_pass_p(opt_pass * pass)234438fd1498Szrj should_skip_pass_p (opt_pass *pass)
234538fd1498Szrj {
234638fd1498Szrj   if (!cfun)
234738fd1498Szrj     return false;
234838fd1498Szrj   if (!cfun->pass_startwith)
234938fd1498Szrj     return false;
235038fd1498Szrj 
235138fd1498Szrj   /* For __GIMPLE functions, we have to at least start when we leave
235238fd1498Szrj      SSA.  Hence, we need to detect the "expand" pass, and stop skipping
235338fd1498Szrj      when we encounter it.  A cheap way to identify "expand" is it to
235438fd1498Szrj      detect the destruction of PROP_ssa.
235538fd1498Szrj      For __RTL functions, we invoke "rest_of_compilation" directly, which
235638fd1498Szrj      is after "expand", and hence we don't reach this conditional.  */
235738fd1498Szrj   if (pass->properties_destroyed & PROP_ssa)
235838fd1498Szrj     {
235938fd1498Szrj       if (!quiet_flag)
236038fd1498Szrj 	fprintf (stderr, "starting anyway when leaving SSA: %s\n", pass->name);
236138fd1498Szrj       cfun->pass_startwith = NULL;
236238fd1498Szrj       return false;
236338fd1498Szrj     }
236438fd1498Szrj 
236538fd1498Szrj   if (determine_pass_name_match (pass->name, cfun->pass_startwith))
236638fd1498Szrj     {
236738fd1498Szrj       if (!quiet_flag)
236838fd1498Szrj 	fprintf (stderr, "found starting pass: %s\n", pass->name);
236938fd1498Szrj       cfun->pass_startwith = NULL;
237038fd1498Szrj       return false;
237138fd1498Szrj     }
237238fd1498Szrj 
237338fd1498Szrj   /* For GIMPLE passes, run any property provider (but continue skipping
237438fd1498Szrj      afterwards).
237538fd1498Szrj      We don't want to force running RTL passes that are property providers:
237638fd1498Szrj      "expand" is covered above, and the only pass other than "expand" that
237738fd1498Szrj      provides a property is "into_cfglayout" (PROP_cfglayout), which does
237838fd1498Szrj      too much for a dumped __RTL function.  */
237938fd1498Szrj   if (pass->type == GIMPLE_PASS
238038fd1498Szrj       && pass->properties_provided != 0)
238138fd1498Szrj     return false;
238238fd1498Szrj 
238338fd1498Szrj   /* Don't skip df init; later RTL passes need it.  */
238438fd1498Szrj   if (strstr (pass->name, "dfinit") != NULL)
238538fd1498Szrj     return false;
238638fd1498Szrj 
238738fd1498Szrj   if (!quiet_flag)
238838fd1498Szrj     fprintf (stderr, "skipping pass: %s\n", pass->name);
238938fd1498Szrj 
239038fd1498Szrj   /* If we get here, then we have a "startwith" that we haven't seen yet;
239138fd1498Szrj      skip the pass.  */
239238fd1498Szrj   return true;
239338fd1498Szrj }
239438fd1498Szrj 
239538fd1498Szrj /* Skip the given pass, for handling passes before "startwith"
239638fd1498Szrj    in __GIMPLE and__RTL-marked functions.
239738fd1498Szrj    In theory, this ought to be a no-op, but some of the RTL passes
239838fd1498Szrj    need additional processing here.  */
239938fd1498Szrj 
240038fd1498Szrj static void
skip_pass(opt_pass * pass)240138fd1498Szrj skip_pass (opt_pass *pass)
240238fd1498Szrj {
240338fd1498Szrj   /* Pass "reload" sets the global "reload_completed", and many
240438fd1498Szrj      things depend on this (e.g. instructions in .md files).  */
240538fd1498Szrj   if (strcmp (pass->name, "reload") == 0)
240638fd1498Szrj     reload_completed = 1;
240738fd1498Szrj 
240838fd1498Szrj   /* The INSN_ADDRESSES vec is normally set up by
240938fd1498Szrj      shorten_branches; set it up for the benefit of passes that
241038fd1498Szrj      run after this.  */
241138fd1498Szrj   if (strcmp (pass->name, "shorten") == 0)
241238fd1498Szrj     INSN_ADDRESSES_ALLOC (get_max_uid ());
241338fd1498Szrj 
241438fd1498Szrj   /* Update the cfg hooks as appropriate.  */
241538fd1498Szrj   if (strcmp (pass->name, "into_cfglayout") == 0)
241638fd1498Szrj     {
241738fd1498Szrj       cfg_layout_rtl_register_cfg_hooks ();
241838fd1498Szrj       cfun->curr_properties |= PROP_cfglayout;
241938fd1498Szrj     }
242038fd1498Szrj   if (strcmp (pass->name, "outof_cfglayout") == 0)
242138fd1498Szrj     {
242238fd1498Szrj       rtl_register_cfg_hooks ();
242338fd1498Szrj       cfun->curr_properties &= ~PROP_cfglayout;
242438fd1498Szrj     }
242538fd1498Szrj }
242638fd1498Szrj 
242738fd1498Szrj /* Execute PASS. */
242838fd1498Szrj 
242938fd1498Szrj bool
execute_one_pass(opt_pass * pass)243038fd1498Szrj execute_one_pass (opt_pass *pass)
243138fd1498Szrj {
243238fd1498Szrj   unsigned int todo_after = 0;
243338fd1498Szrj 
243438fd1498Szrj   bool gate_status;
243538fd1498Szrj 
243638fd1498Szrj   /* IPA passes are executed on whole program, so cfun should be NULL.
243738fd1498Szrj      Other passes need function context set.  */
243838fd1498Szrj   if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
243938fd1498Szrj     gcc_assert (!cfun && !current_function_decl);
244038fd1498Szrj   else
244138fd1498Szrj     gcc_assert (cfun && current_function_decl);
244238fd1498Szrj 
244338fd1498Szrj   current_pass = pass;
244438fd1498Szrj 
244538fd1498Szrj   /* Check whether gate check should be avoided.
244638fd1498Szrj      User controls the value of the gate through the parameter "gate_status". */
244738fd1498Szrj   gate_status = pass->gate (cfun);
244838fd1498Szrj   gate_status = override_gate_status (pass, current_function_decl, gate_status);
244938fd1498Szrj 
245038fd1498Szrj   /* Override gate with plugin.  */
245138fd1498Szrj   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
245238fd1498Szrj 
245338fd1498Szrj   if (!gate_status)
245438fd1498Szrj     {
245538fd1498Szrj       /* Run so passes selectively disabling themselves on a given function
245638fd1498Szrj 	 are not miscounted.  */
245738fd1498Szrj       if (profile_report && cfun && (cfun->curr_properties & PROP_cfg))
245838fd1498Szrj 	{
245938fd1498Szrj           check_profile_consistency (pass->static_pass_number, 0, false);
246038fd1498Szrj           check_profile_consistency (pass->static_pass_number, 1, false);
246138fd1498Szrj 	}
246238fd1498Szrj       current_pass = NULL;
246338fd1498Szrj       return false;
246438fd1498Szrj     }
246538fd1498Szrj 
246638fd1498Szrj   if (should_skip_pass_p (pass))
246738fd1498Szrj     {
246838fd1498Szrj       skip_pass (pass);
246938fd1498Szrj       return true;
247038fd1498Szrj     }
247138fd1498Szrj 
247238fd1498Szrj   /* Pass execution event trigger: useful to identify passes being
247338fd1498Szrj      executed.  */
247438fd1498Szrj   invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
247538fd1498Szrj 
247638fd1498Szrj   if (!quiet_flag && !cfun)
247738fd1498Szrj     fprintf (stderr, " <%s>", pass->name ? pass->name : "");
247838fd1498Szrj 
247938fd1498Szrj   /* Note that the folders should only create gimple expressions.
248038fd1498Szrj      This is a hack until the new folder is ready.  */
248138fd1498Szrj   in_gimple_form = (cfun && (cfun->curr_properties & PROP_trees)) != 0;
248238fd1498Szrj 
248338fd1498Szrj   pass_init_dump_file (pass);
248438fd1498Szrj 
248538fd1498Szrj   /* If a timevar is present, start it.  */
248638fd1498Szrj   if (pass->tv_id != TV_NONE)
248738fd1498Szrj     timevar_push (pass->tv_id);
248838fd1498Szrj 
248938fd1498Szrj   /* Run pre-pass verification.  */
249038fd1498Szrj   execute_todo (pass->todo_flags_start);
249138fd1498Szrj 
249238fd1498Szrj   if (flag_checking)
249338fd1498Szrj     do_per_function (verify_curr_properties,
249438fd1498Szrj 		     (void *)(size_t)pass->properties_required);
249538fd1498Szrj 
249638fd1498Szrj   /* Do it!  */
249738fd1498Szrj   todo_after = pass->execute (cfun);
249838fd1498Szrj 
249938fd1498Szrj   if (todo_after & TODO_discard_function)
250038fd1498Szrj     {
250138fd1498Szrj       /* Stop timevar.  */
250238fd1498Szrj       if (pass->tv_id != TV_NONE)
250338fd1498Szrj 	timevar_pop (pass->tv_id);
250438fd1498Szrj 
250538fd1498Szrj       pass_fini_dump_file (pass);
250638fd1498Szrj 
250738fd1498Szrj       gcc_assert (cfun);
250838fd1498Szrj       /* As cgraph_node::release_body expects release dominators info,
250938fd1498Szrj 	 we have to release it.  */
251038fd1498Szrj       if (dom_info_available_p (CDI_DOMINATORS))
251138fd1498Szrj        free_dominance_info (CDI_DOMINATORS);
251238fd1498Szrj 
251338fd1498Szrj       if (dom_info_available_p (CDI_POST_DOMINATORS))
251438fd1498Szrj        free_dominance_info (CDI_POST_DOMINATORS);
251538fd1498Szrj 
251638fd1498Szrj       tree fn = cfun->decl;
251738fd1498Szrj       pop_cfun ();
251838fd1498Szrj       gcc_assert (!cfun);
251938fd1498Szrj       cgraph_node::get (fn)->release_body ();
252038fd1498Szrj 
252138fd1498Szrj       current_pass = NULL;
252238fd1498Szrj       redirect_edge_var_map_empty ();
252338fd1498Szrj 
252438fd1498Szrj       ggc_collect ();
252538fd1498Szrj 
252638fd1498Szrj       return true;
252738fd1498Szrj     }
252838fd1498Szrj 
252938fd1498Szrj   do_per_function (clear_last_verified, NULL);
253038fd1498Szrj 
253138fd1498Szrj   do_per_function (update_properties_after_pass, pass);
253238fd1498Szrj 
253338fd1498Szrj   if (profile_report && cfun && (cfun->curr_properties & PROP_cfg))
253438fd1498Szrj     check_profile_consistency (pass->static_pass_number, 0, true);
253538fd1498Szrj 
253638fd1498Szrj   /* Run post-pass cleanup and verification.  */
253738fd1498Szrj   execute_todo (todo_after | pass->todo_flags_finish | TODO_verify_il);
253838fd1498Szrj   if (profile_report && cfun && (cfun->curr_properties & PROP_cfg))
253938fd1498Szrj     check_profile_consistency (pass->static_pass_number, 1, true);
254038fd1498Szrj 
254138fd1498Szrj   verify_interpass_invariants ();
254238fd1498Szrj 
254338fd1498Szrj   /* Stop timevar.  */
254438fd1498Szrj   if (pass->tv_id != TV_NONE)
254538fd1498Szrj     timevar_pop (pass->tv_id);
254638fd1498Szrj 
254738fd1498Szrj   if (pass->type == IPA_PASS
254838fd1498Szrj       && ((ipa_opt_pass_d *)pass)->function_transform)
254938fd1498Szrj     {
255038fd1498Szrj       struct cgraph_node *node;
255138fd1498Szrj       FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
255238fd1498Szrj 	node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
255338fd1498Szrj     }
255438fd1498Szrj   else if (dump_file)
255538fd1498Szrj     do_per_function (execute_function_dump, pass);
255638fd1498Szrj 
255738fd1498Szrj   if (!current_function_decl)
255838fd1498Szrj     symtab->process_new_functions ();
255938fd1498Szrj 
256038fd1498Szrj   pass_fini_dump_file (pass);
256138fd1498Szrj 
256238fd1498Szrj   if (pass->type != SIMPLE_IPA_PASS && pass->type != IPA_PASS)
256338fd1498Szrj     gcc_assert (!(cfun->curr_properties & PROP_trees)
256438fd1498Szrj 		|| pass->type != RTL_PASS);
256538fd1498Szrj 
256638fd1498Szrj   current_pass = NULL;
256738fd1498Szrj   redirect_edge_var_map_empty ();
256838fd1498Szrj 
256938fd1498Szrj   /* Signal this is a suitable GC collection point.  */
257038fd1498Szrj   if (!((todo_after | pass->todo_flags_finish) & TODO_do_not_ggc_collect))
257138fd1498Szrj     ggc_collect ();
257238fd1498Szrj 
257338fd1498Szrj   return true;
257438fd1498Szrj }
257538fd1498Szrj 
257638fd1498Szrj static void
execute_pass_list_1(opt_pass * pass)257738fd1498Szrj execute_pass_list_1 (opt_pass *pass)
257838fd1498Szrj {
257938fd1498Szrj   do
258038fd1498Szrj     {
258138fd1498Szrj       gcc_assert (pass->type == GIMPLE_PASS
258238fd1498Szrj 		  || pass->type == RTL_PASS);
258338fd1498Szrj 
258438fd1498Szrj       if (cfun == NULL)
258538fd1498Szrj 	return;
258638fd1498Szrj       if (execute_one_pass (pass) && pass->sub)
258738fd1498Szrj 	execute_pass_list_1 (pass->sub);
258838fd1498Szrj       pass = pass->next;
258938fd1498Szrj     }
259038fd1498Szrj   while (pass);
259138fd1498Szrj }
259238fd1498Szrj 
259338fd1498Szrj void
execute_pass_list(function * fn,opt_pass * pass)259438fd1498Szrj execute_pass_list (function *fn, opt_pass *pass)
259538fd1498Szrj {
259638fd1498Szrj   gcc_assert (fn == cfun);
259738fd1498Szrj   execute_pass_list_1 (pass);
259838fd1498Szrj   if (cfun && fn->cfg)
259938fd1498Szrj     {
260038fd1498Szrj       free_dominance_info (CDI_DOMINATORS);
260138fd1498Szrj       free_dominance_info (CDI_POST_DOMINATORS);
260238fd1498Szrj     }
260338fd1498Szrj }
260438fd1498Szrj 
260538fd1498Szrj /* Write out all LTO data.  */
260638fd1498Szrj static void
write_lto(void)260738fd1498Szrj write_lto (void)
260838fd1498Szrj {
260938fd1498Szrj   timevar_push (TV_IPA_LTO_GIMPLE_OUT);
261038fd1498Szrj   lto_output ();
261138fd1498Szrj   timevar_pop (TV_IPA_LTO_GIMPLE_OUT);
261238fd1498Szrj   timevar_push (TV_IPA_LTO_DECL_OUT);
261338fd1498Szrj   produce_asm_for_decls ();
261438fd1498Szrj   timevar_pop (TV_IPA_LTO_DECL_OUT);
261538fd1498Szrj }
261638fd1498Szrj 
261738fd1498Szrj /* Same as execute_pass_list but assume that subpasses of IPA passes
261838fd1498Szrj    are local passes. If SET is not NULL, write out summaries of only
261938fd1498Szrj    those node in SET. */
262038fd1498Szrj 
262138fd1498Szrj static void
ipa_write_summaries_2(opt_pass * pass,struct lto_out_decl_state * state)262238fd1498Szrj ipa_write_summaries_2 (opt_pass *pass, struct lto_out_decl_state *state)
262338fd1498Szrj {
262438fd1498Szrj   while (pass)
262538fd1498Szrj     {
262638fd1498Szrj       ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *)pass;
262738fd1498Szrj       gcc_assert (!current_function_decl);
262838fd1498Szrj       gcc_assert (!cfun);
262938fd1498Szrj       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
263038fd1498Szrj       if (pass->type == IPA_PASS
263138fd1498Szrj 	  && ipa_pass->write_summary
263238fd1498Szrj 	  && pass->gate (cfun))
263338fd1498Szrj 	{
263438fd1498Szrj 	  /* If a timevar is present, start it.  */
263538fd1498Szrj 	  if (pass->tv_id)
263638fd1498Szrj 	    timevar_push (pass->tv_id);
263738fd1498Szrj 
263838fd1498Szrj           pass_init_dump_file (pass);
263938fd1498Szrj 
264038fd1498Szrj 	  current_pass = pass;
264138fd1498Szrj 	  ipa_pass->write_summary ();
264238fd1498Szrj 
264338fd1498Szrj           pass_fini_dump_file (pass);
264438fd1498Szrj 
264538fd1498Szrj 	  /* If a timevar is present, start it.  */
264638fd1498Szrj 	  if (pass->tv_id)
264738fd1498Szrj 	    timevar_pop (pass->tv_id);
264838fd1498Szrj 	}
264938fd1498Szrj 
265038fd1498Szrj       if (pass->sub && pass->sub->type != GIMPLE_PASS)
265138fd1498Szrj 	ipa_write_summaries_2 (pass->sub, state);
265238fd1498Szrj 
265338fd1498Szrj       pass = pass->next;
265438fd1498Szrj     }
265538fd1498Szrj }
265638fd1498Szrj 
265738fd1498Szrj /* Helper function of ipa_write_summaries. Creates and destroys the
265838fd1498Szrj    decl state and calls ipa_write_summaries_2 for all passes that have
265938fd1498Szrj    summaries.  SET is the set of nodes to be written.  */
266038fd1498Szrj 
266138fd1498Szrj static void
ipa_write_summaries_1(lto_symtab_encoder_t encoder)266238fd1498Szrj ipa_write_summaries_1 (lto_symtab_encoder_t encoder)
266338fd1498Szrj {
266438fd1498Szrj   pass_manager *passes = g->get_passes ();
266538fd1498Szrj   struct lto_out_decl_state *state = lto_new_out_decl_state ();
266638fd1498Szrj   state->symtab_node_encoder = encoder;
266738fd1498Szrj 
266838fd1498Szrj   lto_output_init_mode_table ();
266938fd1498Szrj   lto_push_out_decl_state (state);
267038fd1498Szrj 
267138fd1498Szrj   gcc_assert (!flag_wpa);
267238fd1498Szrj   ipa_write_summaries_2 (passes->all_regular_ipa_passes, state);
267338fd1498Szrj 
267438fd1498Szrj   write_lto ();
267538fd1498Szrj 
267638fd1498Szrj   gcc_assert (lto_get_out_decl_state () == state);
267738fd1498Szrj   lto_pop_out_decl_state ();
267838fd1498Szrj   lto_delete_out_decl_state (state);
267938fd1498Szrj }
268038fd1498Szrj 
268138fd1498Szrj /* Write out summaries for all the nodes in the callgraph.  */
268238fd1498Szrj 
268338fd1498Szrj void
ipa_write_summaries(void)268438fd1498Szrj ipa_write_summaries (void)
268538fd1498Szrj {
268638fd1498Szrj   lto_symtab_encoder_t encoder;
268738fd1498Szrj   int i, order_pos;
268838fd1498Szrj   varpool_node *vnode;
268938fd1498Szrj   struct cgraph_node *node;
269038fd1498Szrj   struct cgraph_node **order;
269138fd1498Szrj 
269238fd1498Szrj   if ((!flag_generate_lto && !flag_generate_offload) || seen_error ())
269338fd1498Szrj     return;
269438fd1498Szrj 
269538fd1498Szrj   select_what_to_stream ();
269638fd1498Szrj 
269738fd1498Szrj   encoder = lto_symtab_encoder_new (false);
269838fd1498Szrj 
269938fd1498Szrj   /* Create the callgraph set in the same order used in
270038fd1498Szrj      cgraph_expand_all_functions.  This mostly facilitates debugging,
270138fd1498Szrj      since it causes the gimple file to be processed in the same order
270238fd1498Szrj      as the source code.  */
270338fd1498Szrj   order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
270438fd1498Szrj   order_pos = ipa_reverse_postorder (order);
270538fd1498Szrj   gcc_assert (order_pos == symtab->cgraph_count);
270638fd1498Szrj 
270738fd1498Szrj   for (i = order_pos - 1; i >= 0; i--)
270838fd1498Szrj     {
270938fd1498Szrj       struct cgraph_node *node = order[i];
271038fd1498Szrj 
271138fd1498Szrj       if (node->has_gimple_body_p ())
271238fd1498Szrj 	{
271338fd1498Szrj 	  /* When streaming out references to statements as part of some IPA
271438fd1498Szrj 	     pass summary, the statements need to have uids assigned and the
271538fd1498Szrj 	     following does that for all the IPA passes here. Naturally, this
271638fd1498Szrj 	     ordering then matches the one IPA-passes get in their stmt_fixup
271738fd1498Szrj 	     hooks.  */
271838fd1498Szrj 
271938fd1498Szrj 	  push_cfun (DECL_STRUCT_FUNCTION (node->decl));
272038fd1498Szrj 	  renumber_gimple_stmt_uids ();
272138fd1498Szrj 	  pop_cfun ();
272238fd1498Szrj 	}
272338fd1498Szrj       if (node->definition && node->need_lto_streaming)
272438fd1498Szrj         lto_set_symtab_encoder_in_partition (encoder, node);
272538fd1498Szrj     }
272638fd1498Szrj 
272738fd1498Szrj   FOR_EACH_DEFINED_FUNCTION (node)
272838fd1498Szrj     if (node->alias && node->need_lto_streaming)
272938fd1498Szrj       lto_set_symtab_encoder_in_partition (encoder, node);
273038fd1498Szrj   FOR_EACH_DEFINED_VARIABLE (vnode)
273138fd1498Szrj     if (vnode->need_lto_streaming)
273238fd1498Szrj       lto_set_symtab_encoder_in_partition (encoder, vnode);
273338fd1498Szrj 
273438fd1498Szrj   ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
273538fd1498Szrj 
273638fd1498Szrj   free (order);
273738fd1498Szrj }
273838fd1498Szrj 
273938fd1498Szrj /* Same as execute_pass_list but assume that subpasses of IPA passes
274038fd1498Szrj    are local passes. If SET is not NULL, write out optimization summaries of
274138fd1498Szrj    only those node in SET. */
274238fd1498Szrj 
274338fd1498Szrj static void
ipa_write_optimization_summaries_1(opt_pass * pass,struct lto_out_decl_state * state)274438fd1498Szrj ipa_write_optimization_summaries_1 (opt_pass *pass,
274538fd1498Szrj 				    struct lto_out_decl_state *state)
274638fd1498Szrj {
274738fd1498Szrj   while (pass)
274838fd1498Szrj     {
274938fd1498Szrj       ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *)pass;
275038fd1498Szrj       gcc_assert (!current_function_decl);
275138fd1498Szrj       gcc_assert (!cfun);
275238fd1498Szrj       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
275338fd1498Szrj       if (pass->type == IPA_PASS
275438fd1498Szrj 	  && ipa_pass->write_optimization_summary
275538fd1498Szrj 	  && pass->gate (cfun))
275638fd1498Szrj 	{
275738fd1498Szrj 	  /* If a timevar is present, start it.  */
275838fd1498Szrj 	  if (pass->tv_id)
275938fd1498Szrj 	    timevar_push (pass->tv_id);
276038fd1498Szrj 
276138fd1498Szrj           pass_init_dump_file (pass);
276238fd1498Szrj 
276338fd1498Szrj 	  current_pass = pass;
276438fd1498Szrj 	  ipa_pass->write_optimization_summary ();
276538fd1498Szrj 
276638fd1498Szrj           pass_fini_dump_file (pass);
276738fd1498Szrj 
276838fd1498Szrj 	  /* If a timevar is present, start it.  */
276938fd1498Szrj 	  if (pass->tv_id)
277038fd1498Szrj 	    timevar_pop (pass->tv_id);
277138fd1498Szrj 	}
277238fd1498Szrj 
277338fd1498Szrj       if (pass->sub && pass->sub->type != GIMPLE_PASS)
277438fd1498Szrj 	ipa_write_optimization_summaries_1 (pass->sub, state);
277538fd1498Szrj 
277638fd1498Szrj       pass = pass->next;
277738fd1498Szrj     }
277838fd1498Szrj }
277938fd1498Szrj 
278038fd1498Szrj /* Write all the optimization summaries for the cgraph nodes in SET.  If SET is
278138fd1498Szrj    NULL, write out all summaries of all nodes. */
278238fd1498Szrj 
278338fd1498Szrj void
ipa_write_optimization_summaries(lto_symtab_encoder_t encoder)278438fd1498Szrj ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
278538fd1498Szrj {
278638fd1498Szrj   struct lto_out_decl_state *state = lto_new_out_decl_state ();
278738fd1498Szrj   lto_symtab_encoder_iterator lsei;
278838fd1498Szrj   state->symtab_node_encoder = encoder;
278938fd1498Szrj 
279038fd1498Szrj   lto_output_init_mode_table ();
279138fd1498Szrj   lto_push_out_decl_state (state);
279238fd1498Szrj   for (lsei = lsei_start_function_in_partition (encoder);
279338fd1498Szrj        !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
279438fd1498Szrj     {
279538fd1498Szrj       struct cgraph_node *node = lsei_cgraph_node (lsei);
279638fd1498Szrj       /* When streaming out references to statements as part of some IPA
279738fd1498Szrj 	 pass summary, the statements need to have uids assigned.
279838fd1498Szrj 
279938fd1498Szrj 	 For functions newly born at WPA stage we need to initialize
280038fd1498Szrj 	 the uids here.  */
280138fd1498Szrj       if (node->definition
280238fd1498Szrj 	  && gimple_has_body_p (node->decl))
280338fd1498Szrj 	{
280438fd1498Szrj 	  push_cfun (DECL_STRUCT_FUNCTION (node->decl));
280538fd1498Szrj 	  renumber_gimple_stmt_uids ();
280638fd1498Szrj 	  pop_cfun ();
280738fd1498Szrj 	}
280838fd1498Szrj     }
280938fd1498Szrj 
281038fd1498Szrj   gcc_assert (flag_wpa);
281138fd1498Szrj   pass_manager *passes = g->get_passes ();
281238fd1498Szrj   ipa_write_optimization_summaries_1 (passes->all_regular_ipa_passes, state);
281338fd1498Szrj 
281438fd1498Szrj   write_lto ();
281538fd1498Szrj 
281638fd1498Szrj   gcc_assert (lto_get_out_decl_state () == state);
281738fd1498Szrj   lto_pop_out_decl_state ();
281838fd1498Szrj   lto_delete_out_decl_state (state);
281938fd1498Szrj }
282038fd1498Szrj 
282138fd1498Szrj /* Same as execute_pass_list but assume that subpasses of IPA passes
282238fd1498Szrj    are local passes.  */
282338fd1498Szrj 
282438fd1498Szrj static void
ipa_read_summaries_1(opt_pass * pass)282538fd1498Szrj ipa_read_summaries_1 (opt_pass *pass)
282638fd1498Szrj {
282738fd1498Szrj   while (pass)
282838fd1498Szrj     {
282938fd1498Szrj       ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
283038fd1498Szrj 
283138fd1498Szrj       gcc_assert (!current_function_decl);
283238fd1498Szrj       gcc_assert (!cfun);
283338fd1498Szrj       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
283438fd1498Szrj 
283538fd1498Szrj       if (pass->gate (cfun))
283638fd1498Szrj 	{
283738fd1498Szrj 	  if (pass->type == IPA_PASS && ipa_pass->read_summary)
283838fd1498Szrj 	    {
283938fd1498Szrj 	      /* If a timevar is present, start it.  */
284038fd1498Szrj 	      if (pass->tv_id)
284138fd1498Szrj 		timevar_push (pass->tv_id);
284238fd1498Szrj 
284338fd1498Szrj 	      pass_init_dump_file (pass);
284438fd1498Szrj 
284538fd1498Szrj 	      current_pass = pass;
284638fd1498Szrj 	      ipa_pass->read_summary ();
284738fd1498Szrj 
284838fd1498Szrj 	      pass_fini_dump_file (pass);
284938fd1498Szrj 
285038fd1498Szrj 	      /* Stop timevar.  */
285138fd1498Szrj 	      if (pass->tv_id)
285238fd1498Szrj 		timevar_pop (pass->tv_id);
285338fd1498Szrj 	    }
285438fd1498Szrj 
285538fd1498Szrj 	  if (pass->sub && pass->sub->type != GIMPLE_PASS)
285638fd1498Szrj 	    ipa_read_summaries_1 (pass->sub);
285738fd1498Szrj 	}
285838fd1498Szrj       pass = pass->next;
285938fd1498Szrj     }
286038fd1498Szrj }
286138fd1498Szrj 
286238fd1498Szrj 
286338fd1498Szrj /* Read all the summaries for all_regular_ipa_passes.  */
286438fd1498Szrj 
286538fd1498Szrj void
ipa_read_summaries(void)286638fd1498Szrj ipa_read_summaries (void)
286738fd1498Szrj {
286838fd1498Szrj   pass_manager *passes = g->get_passes ();
286938fd1498Szrj   ipa_read_summaries_1 (passes->all_regular_ipa_passes);
287038fd1498Szrj }
287138fd1498Szrj 
287238fd1498Szrj /* Same as execute_pass_list but assume that subpasses of IPA passes
287338fd1498Szrj    are local passes.  */
287438fd1498Szrj 
287538fd1498Szrj static void
ipa_read_optimization_summaries_1(opt_pass * pass)287638fd1498Szrj ipa_read_optimization_summaries_1 (opt_pass *pass)
287738fd1498Szrj {
287838fd1498Szrj   while (pass)
287938fd1498Szrj     {
288038fd1498Szrj       ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
288138fd1498Szrj 
288238fd1498Szrj       gcc_assert (!current_function_decl);
288338fd1498Szrj       gcc_assert (!cfun);
288438fd1498Szrj       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
288538fd1498Szrj 
288638fd1498Szrj       if (pass->gate (cfun))
288738fd1498Szrj 	{
288838fd1498Szrj 	  if (pass->type == IPA_PASS && ipa_pass->read_optimization_summary)
288938fd1498Szrj 	    {
289038fd1498Szrj 	      /* If a timevar is present, start it.  */
289138fd1498Szrj 	      if (pass->tv_id)
289238fd1498Szrj 		timevar_push (pass->tv_id);
289338fd1498Szrj 
289438fd1498Szrj 	      pass_init_dump_file (pass);
289538fd1498Szrj 
289638fd1498Szrj 	      current_pass = pass;
289738fd1498Szrj 	      ipa_pass->read_optimization_summary ();
289838fd1498Szrj 
289938fd1498Szrj 	      pass_fini_dump_file (pass);
290038fd1498Szrj 
290138fd1498Szrj 	      /* Stop timevar.  */
290238fd1498Szrj 	      if (pass->tv_id)
290338fd1498Szrj 		timevar_pop (pass->tv_id);
290438fd1498Szrj 	    }
290538fd1498Szrj 
290638fd1498Szrj 	  if (pass->sub && pass->sub->type != GIMPLE_PASS)
290738fd1498Szrj 	    ipa_read_optimization_summaries_1 (pass->sub);
290838fd1498Szrj 	}
290938fd1498Szrj       pass = pass->next;
291038fd1498Szrj     }
291138fd1498Szrj }
291238fd1498Szrj 
291338fd1498Szrj /* Read all the summaries for all_regular_ipa_passes.  */
291438fd1498Szrj 
291538fd1498Szrj void
ipa_read_optimization_summaries(void)291638fd1498Szrj ipa_read_optimization_summaries (void)
291738fd1498Szrj {
291838fd1498Szrj   pass_manager *passes = g->get_passes ();
291938fd1498Szrj   ipa_read_optimization_summaries_1 (passes->all_regular_ipa_passes);
292038fd1498Szrj }
292138fd1498Szrj 
292238fd1498Szrj /* Same as execute_pass_list but assume that subpasses of IPA passes
292338fd1498Szrj    are local passes.  */
292438fd1498Szrj void
execute_ipa_pass_list(opt_pass * pass)292538fd1498Szrj execute_ipa_pass_list (opt_pass *pass)
292638fd1498Szrj {
292738fd1498Szrj   do
292838fd1498Szrj     {
292938fd1498Szrj       gcc_assert (!current_function_decl);
293038fd1498Szrj       gcc_assert (!cfun);
293138fd1498Szrj       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
293238fd1498Szrj       if (execute_one_pass (pass) && pass->sub)
293338fd1498Szrj 	{
293438fd1498Szrj 	  if (pass->sub->type == GIMPLE_PASS)
293538fd1498Szrj 	    {
293638fd1498Szrj 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
293738fd1498Szrj 	      do_per_function_toporder ((void (*)(function *, void *))
293838fd1498Szrj 					  execute_pass_list,
293938fd1498Szrj 					pass->sub);
294038fd1498Szrj 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
294138fd1498Szrj 	    }
294238fd1498Szrj 	  else if (pass->sub->type == SIMPLE_IPA_PASS
294338fd1498Szrj 		   || pass->sub->type == IPA_PASS)
294438fd1498Szrj 	    execute_ipa_pass_list (pass->sub);
294538fd1498Szrj 	  else
294638fd1498Szrj 	    gcc_unreachable ();
294738fd1498Szrj 	}
294838fd1498Szrj       gcc_assert (!current_function_decl);
294938fd1498Szrj       symtab->process_new_functions ();
295038fd1498Szrj       pass = pass->next;
295138fd1498Szrj     }
295238fd1498Szrj   while (pass);
295338fd1498Szrj }
295438fd1498Szrj 
295538fd1498Szrj /* Execute stmt fixup hooks of all passes in PASS for NODE and STMTS.  */
295638fd1498Szrj 
295738fd1498Szrj static void
execute_ipa_stmt_fixups(opt_pass * pass,struct cgraph_node * node,gimple ** stmts)295838fd1498Szrj execute_ipa_stmt_fixups (opt_pass *pass,
295938fd1498Szrj 			 struct cgraph_node *node, gimple **stmts)
296038fd1498Szrj {
296138fd1498Szrj   while (pass)
296238fd1498Szrj     {
296338fd1498Szrj       /* Execute all of the IPA_PASSes in the list.  */
296438fd1498Szrj       if (pass->type == IPA_PASS
296538fd1498Szrj 	  && pass->gate (cfun))
296638fd1498Szrj 	{
296738fd1498Szrj 	  ipa_opt_pass_d *ipa_pass = (ipa_opt_pass_d *) pass;
296838fd1498Szrj 
296938fd1498Szrj 	  if (ipa_pass->stmt_fixup)
297038fd1498Szrj 	    {
297138fd1498Szrj 	      pass_init_dump_file (pass);
297238fd1498Szrj 	      /* If a timevar is present, start it.  */
297338fd1498Szrj 	      if (pass->tv_id)
297438fd1498Szrj 		timevar_push (pass->tv_id);
297538fd1498Szrj 
297638fd1498Szrj 	      current_pass = pass;
297738fd1498Szrj 	      ipa_pass->stmt_fixup (node, stmts);
297838fd1498Szrj 
297938fd1498Szrj 	      /* Stop timevar.  */
298038fd1498Szrj 	      if (pass->tv_id)
298138fd1498Szrj 		timevar_pop (pass->tv_id);
298238fd1498Szrj 	      pass_fini_dump_file (pass);
298338fd1498Szrj 	    }
298438fd1498Szrj 	  if (pass->sub)
298538fd1498Szrj 	    execute_ipa_stmt_fixups (pass->sub, node, stmts);
298638fd1498Szrj 	}
298738fd1498Szrj       pass = pass->next;
298838fd1498Szrj     }
298938fd1498Szrj }
299038fd1498Szrj 
299138fd1498Szrj /* Execute stmt fixup hooks of all IPA passes for NODE and STMTS.  */
299238fd1498Szrj 
299338fd1498Szrj void
execute_all_ipa_stmt_fixups(struct cgraph_node * node,gimple ** stmts)299438fd1498Szrj execute_all_ipa_stmt_fixups (struct cgraph_node *node, gimple **stmts)
299538fd1498Szrj {
299638fd1498Szrj   pass_manager *passes = g->get_passes ();
299738fd1498Szrj   execute_ipa_stmt_fixups (passes->all_regular_ipa_passes, node, stmts);
299838fd1498Szrj }
299938fd1498Szrj 
300038fd1498Szrj 
300138fd1498Szrj extern void debug_properties (unsigned int);
300238fd1498Szrj extern void dump_properties (FILE *, unsigned int);
300338fd1498Szrj 
300438fd1498Szrj DEBUG_FUNCTION void
dump_properties(FILE * dump,unsigned int props)300538fd1498Szrj dump_properties (FILE *dump, unsigned int props)
300638fd1498Szrj {
300738fd1498Szrj   fprintf (dump, "Properties:\n");
300838fd1498Szrj   if (props & PROP_gimple_any)
300938fd1498Szrj     fprintf (dump, "PROP_gimple_any\n");
301038fd1498Szrj   if (props & PROP_gimple_lcf)
301138fd1498Szrj     fprintf (dump, "PROP_gimple_lcf\n");
301238fd1498Szrj   if (props & PROP_gimple_leh)
301338fd1498Szrj     fprintf (dump, "PROP_gimple_leh\n");
301438fd1498Szrj   if (props & PROP_cfg)
301538fd1498Szrj     fprintf (dump, "PROP_cfg\n");
301638fd1498Szrj   if (props & PROP_ssa)
301738fd1498Szrj     fprintf (dump, "PROP_ssa\n");
301838fd1498Szrj   if (props & PROP_no_crit_edges)
301938fd1498Szrj     fprintf (dump, "PROP_no_crit_edges\n");
302038fd1498Szrj   if (props & PROP_rtl)
302138fd1498Szrj     fprintf (dump, "PROP_rtl\n");
302238fd1498Szrj   if (props & PROP_gimple_lomp)
302338fd1498Szrj     fprintf (dump, "PROP_gimple_lomp\n");
302438fd1498Szrj   if (props & PROP_gimple_lomp_dev)
302538fd1498Szrj     fprintf (dump, "PROP_gimple_lomp_dev\n");
302638fd1498Szrj   if (props & PROP_gimple_lcx)
302738fd1498Szrj     fprintf (dump, "PROP_gimple_lcx\n");
302838fd1498Szrj   if (props & PROP_gimple_lvec)
302938fd1498Szrj     fprintf (dump, "PROP_gimple_lvec\n");
303038fd1498Szrj   if (props & PROP_cfglayout)
303138fd1498Szrj     fprintf (dump, "PROP_cfglayout\n");
303238fd1498Szrj }
303338fd1498Szrj 
303438fd1498Szrj DEBUG_FUNCTION void
debug_properties(unsigned int props)303538fd1498Szrj debug_properties (unsigned int props)
303638fd1498Szrj {
303738fd1498Szrj   dump_properties (stderr, props);
303838fd1498Szrj }
303938fd1498Szrj 
304038fd1498Szrj /* Called by local passes to see if function is called by already processed nodes.
304138fd1498Szrj    Because we process nodes in topological order, this means that function is
304238fd1498Szrj    in recursive cycle or we introduced new direct calls.  */
304338fd1498Szrj bool
function_called_by_processed_nodes_p(void)304438fd1498Szrj function_called_by_processed_nodes_p (void)
304538fd1498Szrj {
304638fd1498Szrj   struct cgraph_edge *e;
304738fd1498Szrj   for (e = cgraph_node::get (current_function_decl)->callers;
304838fd1498Szrj        e;
304938fd1498Szrj        e = e->next_caller)
305038fd1498Szrj     {
305138fd1498Szrj       if (e->caller->decl == current_function_decl)
305238fd1498Szrj         continue;
305338fd1498Szrj       if (!e->caller->has_gimple_body_p ())
305438fd1498Szrj         continue;
305538fd1498Szrj       if (TREE_ASM_WRITTEN (e->caller->decl))
305638fd1498Szrj         continue;
305738fd1498Szrj       if (!e->caller->process && !e->caller->global.inlined_to)
305838fd1498Szrj       	break;
305938fd1498Szrj     }
306038fd1498Szrj   if (dump_file && e)
306138fd1498Szrj     {
306238fd1498Szrj       fprintf (dump_file, "Already processed call to:\n");
306338fd1498Szrj       e->caller->dump (dump_file);
306438fd1498Szrj     }
306538fd1498Szrj   return e != NULL;
306638fd1498Szrj }
306738fd1498Szrj 
306838fd1498Szrj #include "gt-passes.h"
3069