DECL_INITIAL (ctor) = make_node (BLOCK);
TREE_USED (DECL_INITIAL (ctor)) = 1;
- rest_of_compilation (ctor);
+ rest_of_compilation ();
if (! quiet_flag)
fflush (asm_out_file);
#include "intl.h"
#include "tm_p.h"
#include "tree-iterator.h"
+#include "tree-pass.h"
+#include "tree-flow.h"
#include "target.h"
+#include "timevar.h"
/* Decide whether a function's arguments should be processed
from first to last or from last to first.
#endif
static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
static rtx const_vector_from_tree (tree);
+static void execute_expand (void);
/* Record for each mode whether we can move a register directly to or
from an object of that mode in memory. If we can't, we won't try
return gen_rtx_raw_CONST_VECTOR (mode, v);
}
+\f
+/* Called to move the SAVE_EXPRs for parameter declarations in a
+ nested function into the nested function. DATA is really the
+ nested FUNCTION_DECL. */
+
+static tree
+set_save_expr_context (tree *tp,
+ int *walk_subtrees,
+ void *data)
+{
+ if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
+ SAVE_EXPR_CONTEXT (*tp) = (tree) data;
+ /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
+ circularity. */
+ else if (DECL_P (*tp))
+ *walk_subtrees = 0;
+
+ return NULL;
+}
+
+
+static void
+execute_expand (void)
+{
+ /* If the function has a variably modified type, there may be
+ SAVE_EXPRs in the parameter types. Their context must be set to
+ refer to this function; they cannot be expanded in the containing
+ function. */
+ if (decl_function_context (current_function_decl) == current_function_decl
+ && variably_modified_type_p (TREE_TYPE (current_function_decl)))
+ walk_tree (&TREE_TYPE (current_function_decl), set_save_expr_context,
+ current_function_decl, NULL);
+
+ /* Expand the variables recorded during gimple lowering. This must
+ occur before the call to expand_function_start to ensure that
+ all used variables are expanded before we expand anything on the
+ PENDING_SIZES list. */
+ expand_used_vars ();
+
+ /* Set up parameters and prepare for return, for the function. */
+ expand_function_start (current_function_decl, 0);
+
+ /* If this function is `main', emit a call to `__main'
+ to run global initializers, etc. */
+ if (DECL_NAME (current_function_decl)
+ && MAIN_NAME_P (DECL_NAME (current_function_decl))
+ && DECL_FILE_SCOPE_P (current_function_decl))
+ expand_main_function ();
+
+ /* Generate the RTL for this function. */
+ expand_expr_stmt_value (DECL_SAVED_TREE (current_function_decl), 0, 0);
+
+ /* We hard-wired immediate_size_expand to zero above.
+ expand_function_end will decrement this variable. So, we set the
+ variable to one here, so that after the decrement it will remain
+ zero. */
+ immediate_size_expand = 1;
+
+ /* Make sure the locus is set to the end of the function, so that
+ epilogue line numbers and warnings are set properly. */
+ if (cfun->function_end_locus.file)
+ input_location = cfun->function_end_locus;
+
+ /* The following insns belong to the top scope. */
+ record_block_change (DECL_INITIAL (current_function_decl));
+
+ /* Generate rtl for function exit. */
+ expand_function_end ();
+}
+
+struct tree_opt_pass pass_expand =
+{
+ "expand", /* name */
+ NULL, /* gate */
+ execute_expand, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_EXPAND, /* tv_id */
+ /* ??? If TER is enabled, we actually receive GENERIC. */
+ PROP_gimple_leh, /* properties_required */
+ PROP_rtl, /* properties_provided */
+ PROP_cfg | PROP_gimple_leh, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+};
+
#include "gt-expr.h"
input_location = DECL_SOURCE_LOCATION (init_decl);
expand_function_end ();
poplevel (1, 0, 1);
- rest_of_compilation (init_decl);
+ rest_of_compilation ();
current_function_decl = NULL_TREE;
if (targetm.have_ctors_dtors)
poplevel (1, 0, 1);
/* rest_of_compilation forces generation even if -finline-functions. */
- rest_of_compilation (init_decl);
+ rest_of_compilation ();
current_function_decl = NULL_TREE;
if (targetm.have_ctors_dtors)
#include "coverage.h"
#include "value-prof.h"
#include "alloc-pool.h"
+#include "tree-pass.h"
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
#include "dwarf2out.h"
static void
rest_of_handle_final (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_FINAL);
{
rtx x;
static void
rest_of_handle_delay_slots (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_DBR_SCHED);
open_dump_file (DFI_dbr, decl);
static void
rest_of_handle_stack_regs (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
#if defined (HAVE_ATTR_length)
/* If flow2 creates new instructions which need splitting
and scheduling after reload is not done, they might not be
static void
rest_of_handle_variable_tracking (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_VAR_TRACKING);
open_dump_file (DFI_vartrack, decl);
static void
rest_of_handle_machine_reorg (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_MACH_DEP);
open_dump_file (DFI_mach, decl);
{
int failure;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
delete_trivially_dead_insns (insns, max_reg_num ());
reg_alloc ();
int failure;
int rebuild_notes;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
/* Allocate the reg_renumber array. */
allocate_reg_info (max_regno, FALSE, TRUE);
static void
rest_of_handle_regrename (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_RENAME_REGISTERS);
open_dump_file (DFI_rnreg, decl);
bool changed;
open_dump_file (DFI_bbro, decl);
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
/* Last attempt to optimize CFG, as scheduling, peepholing and insn
splitting possibly introduced more crossjumping opportunities. */
changed = cleanup_cfg (CLEANUP_EXPENSIVE
static void
rest_of_handle_sched (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_SMS);
if (optimize > 0 && flag_modulo_sched)
{
static void
rest_of_handle_sched2 (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_SCHED2);
open_dump_file (DFI_sched2, decl);
static void
rest_of_handle_gcse2 (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_gcse2, decl);
gcse_after_reload_main (insns, dump_file);
static void
rest_of_handle_regmove (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_REGMOVE);
open_dump_file (DFI_regmove, decl);
static void
rest_of_handle_tracer (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_tracer, decl);
if (dump_file)
dump_flow_info (dump_file);
static void
rest_of_handle_if_conversion (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_ce1, decl);
if (flag_if_conversion)
{
static void
rest_of_handle_if_after_combine (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_IFCVT);
open_dump_file (DFI_ce2, decl);
static void
rest_of_handle_web (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_web, decl);
timevar_push (TV_WEB);
web_main ();
rest_of_handle_branch_prob (tree decl, rtx insns)
{
struct loops loops;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
timevar_push (TV_BRANCH_PROB);
open_dump_file (DFI_bp, decl);
static void
rest_of_handle_value_profile_transformations (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_vpt, decl);
timevar_push (TV_VPT);
static void
rest_of_handle_cfg (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_cfg, decl);
if (dump_file)
dump_flow_info (dump_file);
static void
rest_of_handle_addressof (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_addressof, decl);
purge_addressof (insns);
static void
rest_of_handle_jump_bypass (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_BYPASS);
open_dump_file (DFI_bypass, decl);
{
int rebuild_jump_labels_after_combine = 0;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_COMBINE);
open_dump_file (DFI_combine, decl);
static void
rest_of_handle_life (tree decl, rtx insns)
{
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
open_dump_file (DFI_life, decl);
regclass_init ();
rest_of_handle_cse (tree decl, rtx insns)
{
int tem;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
open_dump_file (DFI_cse, decl);
if (dump_file)
rest_of_handle_cse2 (tree decl, rtx insns)
{
int tem;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
timevar_push (TV_CSE2);
open_dump_file (DFI_cse2, decl);
{
int save_csb, save_cfj;
int tem2 = 0, tem;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
timevar_push (TV_GCSE);
open_dump_file (DFI_gcse, decl);
{
int do_unroll, do_prefetch;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
timevar_push (TV_LOOP);
delete_dead_jumptables ();
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
struct loops *loops;
basic_block bb;
+ if (decl != current_function_decl || insns != get_insns ())
+ abort ();
+
if (!flag_unswitch_loops
&& !flag_peel_loops
&& !flag_unroll_loops
After we return, the tree storage is freed. */
void
-rest_of_compilation (tree decl)
+rest_of_compilation (void)
{
+ tree decl = current_function_decl;
rtx insns;
- timevar_push (TV_REST_OF_COMPILATION);
+
+ /* There's no need to defer outputting this function any more; we
+ know we want to output it. */
+ DECL_DEFER_OUTPUT (current_function_decl) = 0;
/* There's no need to defer outputting this function any more; we
know we want to output it. */
/* We're done with this function. Free up memory if we can. */
free_after_parsing (cfun);
-
- ggc_collect ();
-
- timevar_pop (TV_REST_OF_COMPILATION);
}
void
return matched;
}
+
+struct tree_opt_pass pass_rest_of_compilation =
+{
+ "rest of compilation", /* name */
+ NULL, /* gate */
+ rest_of_compilation, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_REST_OF_COMPILATION, /* tv_id */
+ PROP_rtl, /* properties_required */
+ 0, /* properties_provided */
+ PROP_rtl, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_ggc_collect /* todo_flags_finish */
+};
+
+
pass->static_pass_number = dump_register (dot_name, flag_name);
}
-static void
-register_dump_files (struct tree_opt_pass *pass)
+static int
+register_dump_files (struct tree_opt_pass *pass, int properties)
{
do
{
- register_one_dump_file (pass);
+ /* Verify that all required properties are present. */
+ if (pass->properties_required & ~properties)
+ abort ();
+
+ if (pass->properties_destroyed & pass->properties_provided)
+ abort ();
+
+ pass->properties_required = properties;
+ pass->properties_provided = properties =
+ (properties | pass->properties_provided) & ~pass->properties_destroyed;
+
+ if (properties & PROP_trees)
+ register_one_dump_file (pass);
if (pass->sub)
- register_dump_files (pass->sub);
+ properties = register_dump_files (pass->sub, properties);
pass = pass->next;
}
while (pass);
+
+ return properties;
}
/* Duplicate a pass that's to be run more than once. */
NEXT_PASS (pass_all_optimizations);
NEXT_PASS (pass_mudflap_2);
NEXT_PASS (pass_rebuild_bind);
+ NEXT_PASS (pass_expand);
+ NEXT_PASS (pass_rest_of_compilation);
*p = NULL;
p = &pass_all_optimizations.sub;
#undef DUP_PASS
/* Register the passes with the tree dump code. */
- register_dump_files (all_passes);
+ register_dump_files (all_passes, 0);
}
static void execute_pass_list (struct tree_opt_pass *);
-static unsigned int current_properties;
static unsigned int last_verified;
static void
if (pass->gate && !pass->gate ())
return false;
- /* Verify that all required properties are present. */
- if (pass->properties_required & ~current_properties)
- abort ();
+ /* Note that the folders should only create gimple expressions.
+ This is a hack until the new folder is ready. */
+ in_gimple_form = (pass->properties_provided & PROP_trees) != 0;
/* Run pre-pass verification. */
todo = pass->todo_flags_start & ~last_verified;
if (todo)
execute_todo (todo);
- /* Update properties. */
- current_properties &= ~pass->properties_destroyed;
- current_properties |= pass->properties_provided;
-
/* Close down timevar and dump file. */
if (pass->tv_id)
timevar_pop (pass->tv_id);
}
\f
-/* Called to move the SAVE_EXPRs for parameter declarations in a
- nested function into the nested function. DATA is really the
- nested FUNCTION_DECL. */
-
-static tree
-set_save_expr_context (tree *tp,
- int *walk_subtrees,
- void *data)
-{
- if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
- SAVE_EXPR_CONTEXT (*tp) = (tree) data;
- /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
- circularity. */
- else if (DECL_P (*tp))
- *walk_subtrees = 0;
-
- return NULL;
-}
-
/* For functions-as-trees languages, this performs all optimization and
compilation for FNDECL. */
}
}
- /* Note that the folders should only create gimple expressions.
- This is a hack until the new folder is ready. */
- in_gimple_form = true;
-
- /* Perform all tree transforms and optimizations. */
- execute_pass_list (all_passes);
-
- /* Note that the folders can create non-gimple expressions again. */
- in_gimple_form = false;
-
- /* If the function has a variably modified type, there may be
- SAVE_EXPRs in the parameter types. Their context must be set to
- refer to this function; they cannot be expanded in the containing
- function. */
- if (decl_function_context (fndecl) == current_function_decl
- && variably_modified_type_p (TREE_TYPE (fndecl)))
- walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
- NULL);
-
- /* Expand the variables recorded during gimple lowering. This must
- occur before the call to expand_function_start to ensure that
- all used variables are expanded before we expand anything on the
- PENDING_SIZES list. */
- expand_used_vars ();
-
- /* Set up parameters and prepare for return, for the function. */
- expand_function_start (fndecl, 0);
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && MAIN_NAME_P (DECL_NAME (fndecl))
- && DECL_FILE_SCOPE_P (fndecl))
- expand_main_function ();
-
- /* Generate the RTL for this function. */
- expand_expr_stmt_value (DECL_SAVED_TREE (fndecl), 0, 0);
-
- /* We hard-wired immediate_size_expand to zero above.
- expand_function_end will decrement this variable. So, we set the
- variable to one here, so that after the decrement it will remain
- zero. */
- immediate_size_expand = 1;
-
- /* Make sure the locus is set to the end of the function, so that
- epilogue line numbers and warnings are set properly. */
- if (cfun->function_end_locus.file)
- input_location = cfun->function_end_locus;
-
- /* The following insns belong to the top scope. */
- record_block_change (DECL_INITIAL (current_function_decl));
-
- /* Generate rtl for function exit. */
- expand_function_end ();
-
/* If this is a nested function, protect the local variables in the stack
above us from being collected while we're compiling this function. */
if (nested_p)
ggc_push_context ();
- /* Run the optimizers and output the assembler code for this function. */
- rest_of_compilation (fndecl);
+ /* Perform all tree transforms and optimizations. */
+ execute_pass_list (all_passes);
/* Restore original body if still needed. */
if (cfun->saved_tree)
#define PROP_pta (1 << 5)
#define PROP_ssa (1 << 6)
#define PROP_no_crit_edges (1 << 7)
+#define PROP_rtl (1 << 8)
+
+#define PROP_trees \
+ (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh)
/* To-do flags. */
#define TODO_dump_func (1 << 0) /* pass doesn't dump itself */
extern struct tree_opt_pass pass_nrv;
extern struct tree_opt_pass pass_remove_useless_vars;
extern struct tree_opt_pass pass_rename_ssa_copies;
+extern struct tree_opt_pass pass_expand;
+extern struct tree_opt_pass pass_rest_of_compilation;
#endif /* GCC_TREE_PASS_H */