/* Top level of GNU C compiler
- Copyright (C) 1987, 88, 89, 92-98, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "ggc.h"
#include "graph.h"
#include "loop.h"
+#include "regs.h"
+#include "timevar.h"
+
+#ifndef ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 0
+#endif
#ifdef DWARF_DEBUGGING_INFO
#include "dwarfout.h"
#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
#endif
-#if ! (defined (VMS) || defined (OS2))
+#ifdef NEED_DECLARATION_ENVIRON
extern char **environ;
#endif
-extern char *version_string;
/* Carry information from ASM_DECLARE_OBJECT_NAME
to ASM_FINISH_DECLARE_OBJECT. */
extern int size_directive_output;
extern tree last_assemble_variable_decl;
-static void set_target_switch PROTO((const char *));
-static const char *decl_name PROTO((tree, int));
+static void set_target_switch PARAMS ((const char *));
+static const char *decl_name PARAMS ((tree, int));
-extern void set_fatal_function PROTO((void (*)(const char *, va_list)));
-static void float_signal PROTO((int)) ATTRIBUTE_NORETURN;
-static void pipe_closed PROTO((int)) ATTRIBUTE_NORETURN;
+static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
+static void pipe_closed PARAMS ((int)) ATTRIBUTE_NORETURN;
#ifdef ASM_IDENTIFY_LANGUAGE
/* This might or might not be used in ASM_IDENTIFY_LANGUAGE. */
-static void output_lang_identify PROTO((FILE *)) ATTRIBUTE_UNUSED;
+static void output_lang_identify PARAMS ((FILE *)) ATTRIBUTE_UNUSED;
#endif
-static void open_dump_file PROTO((const char *, const char *));
-static void close_dump_file PROTO((void (*) (FILE *, rtx), rtx));
-static void dump_rtl PROTO((const char *, tree, void (*) (FILE *, rtx), rtx));
-static void clean_dump_file PROTO((const char *));
-static void compile_file PROTO((char *));
-static void display_help PROTO ((void));
-static void mark_file_stack PROTO ((void *));
-
-static void decode_d_option PROTO ((const char *));
-static int decode_f_option PROTO ((const char *));
-static int decode_W_option PROTO ((const char *));
-static int decode_g_option PROTO ((const char *));
-static unsigned independent_decode_option PROTO ((int, char **, unsigned));
-
-static void print_version PROTO((FILE *, const char *));
-static int print_single_switch PROTO((FILE *, int, int, const char *,
+static void compile_file PARAMS ((char *));
+static void display_help PARAMS ((void));
+static void mark_file_stack PARAMS ((void *));
+
+static void decode_d_option PARAMS ((const char *));
+static int decode_f_option PARAMS ((const char *));
+static int decode_W_option PARAMS ((const char *));
+static int decode_g_option PARAMS ((const char *));
+static unsigned int independent_decode_option PARAMS ((int, char **,
+ unsigned int));
+
+static void print_version PARAMS ((FILE *, const char *));
+static int print_single_switch PARAMS ((FILE *, int, int, const char *,
const char *, const char *,
const char *, const char *));
-static void print_switch_values PROTO((FILE *, int, int, const char *,
+static void print_switch_values PARAMS ((FILE *, int, int, const char *,
const char *, const char *));
/* Length of line when printing switch values. */
extern int target_flags;
-/* Flags saying which kinds of debugging dump have been requested. */
-
-int rtl_dump = 0;
-int rtl_dump_and_exit = 0;
-int jump_opt_dump = 0;
-int addressof_dump = 0;
-int cse_dump = 0;
-int gcse_dump = 0;
-int loop_dump = 0;
-int cse2_dump = 0;
-int branch_prob_dump = 0;
-int flow_dump = 0;
-int combine_dump = 0;
-int regmove_dump = 0;
-int sched_dump = 0;
-int local_reg_dump = 0;
-int global_reg_dump = 0;
-int flow2_dump = 0;
-int peephole2_dump = 0;
-int sched2_dump = 0;
-int jump2_opt_dump = 0;
-#ifdef DELAY_SLOTS
-int dbr_sched_dump = 0;
-#endif
-int flag_print_asm_name = 0;
-#ifdef STACK_REGS
-int stack_reg_dump = 0;
-#endif
-#ifdef MACHINE_DEPENDENT_REORG
-int mach_dep_reorg_dump = 0;
-#endif
-static int flag_print_mem = 0;
-static int version_flag = 0;
-static char * filename = 0;
+/* Describes a dump file. */
+
+struct dump_file_info
+{
+ /* The unique extension to apply, e.g. ".jump". */
+ const char * const extension;
+
+ /* The -d<c> character that enables this dump file. */
+ char const debug_switch;
+
+ /* True if there is a corresponding graph dump file. */
+ char const graph_dump_p;
+
+ /* True if the user selected this dump. */
+ char enabled;
+
+ /* True if the files have been initialized (ie truncated). */
+ char initialized;
+};
+
+/* Enumerate the extant dump files. */
+
+enum dump_file_index
+{
+ DFI_rtl,
+ DFI_sibling,
+ DFI_jump,
+ DFI_cse,
+ DFI_addressof,
+ DFI_ssa,
+ DFI_ussa,
+ DFI_gcse,
+ DFI_loop,
+ DFI_cse2,
+ DFI_bp,
+ DFI_flow,
+ DFI_combine,
+ DFI_ce,
+ DFI_regmove,
+ DFI_sched,
+ DFI_lreg,
+ DFI_greg,
+ DFI_flow2,
+ DFI_ce2,
+ DFI_peephole2,
+ DFI_sched2,
+ DFI_bbro,
+ DFI_rnreg,
+ DFI_jump2,
+ DFI_mach,
+ DFI_dbr,
+ DFI_stack,
+ DFI_MAX
+};
+
+/* Describes all the dump files. Should be kept in order of the
+ pass and in sync with dump_file_index above.
+
+ Remaining -d letters:
+
+ " h o q u "
+ " H K OPQ TUVWXYZ"
+*/
+
+struct dump_file_info dump_file[DFI_MAX] =
+{
+ { "rtl", 'r', 0, 0, 0 },
+ { "sibling", 'i', 0, 0, 0 },
+ { "jump", 'j', 0, 0, 0 },
+ { "cse", 's', 0, 0, 0 },
+ { "addressof", 'F', 0, 0, 0 },
+ { "ssa", 'e', 1, 0, 0 },
+ { "ussa", 'e', 1, 0, 0 }, /* Yes, duplicate enable switch. */
+ { "gcse", 'G', 1, 0, 0 },
+ { "loop", 'L', 1, 0, 0 },
+ { "cse2", 't', 1, 0, 0 },
+ { "bp", 'b', 1, 0, 0 },
+ { "flow", 'f', 1, 0, 0 },
+ { "combine", 'c', 1, 0, 0 },
+ { "ce", 'C', 1, 0, 0 },
+ { "regmove", 'N', 1, 0, 0 },
+ { "sched", 'S', 1, 0, 0 },
+ { "lreg", 'l', 1, 0, 0 },
+ { "greg", 'g', 1, 0, 0 },
+ { "flow2", 'w', 1, 0, 0 },
+ { "ce2", 'E', 1, 0, 0 },
+ { "peephole2", 'z', 1, 0, 0 },
+ { "sched2", 'R', 1, 0, 0 },
+ { "bbro", 'B', 1, 0, 0 },
+ { "rnreg", 'n', 1, 0, 0 },
+ { "jump2", 'J', 1, 0, 0 },
+ { "mach", 'M', 1, 0, 0 },
+ { "dbr", 'd', 0, 0, 0 },
+ { "stack", 'k', 1, 0, 0 },
+};
+
+static int open_dump_file PARAMS ((enum dump_file_index, tree));
+static void close_dump_file PARAMS ((enum dump_file_index,
+ void (*) (FILE *, rtx), rtx));
+
+/* Other flags saying which kinds of debugging dump have been requested. */
+
+int rtl_dump_and_exit;
+int flag_print_asm_name;
+static int flag_print_mem;
+static int version_flag;
+static char * filename;
enum graph_dump_types graph_dump_format;
/* Name for output file of assembly code, specified with -o. */
int warningcount = 0;
int sorrycount = 0;
+/* The FUNCTION_DECL for the function currently being compiled,
+ or 0 if between functions. */
+tree current_function_decl;
+
+/* Set to the FUNC_BEGIN label of the current function, or NULL_TREE
+ if none. */
+tree current_function_func_begin_label;
+
/* Pointer to function to compute the name to use to print a declaration.
DECL is the declaration in question.
VERBOSITY determines what information will be printed:
2: and any other information that might be interesting, such as function
parameter types in C++. */
-const char *(*decl_printable_name) PROTO ((tree, int));
+const char *(*decl_printable_name) PARAMS ((tree, int));
/* Pointer to function to compute rtl for a language-specific tree code. */
typedef rtx (*lang_expand_expr_t)
- PROTO ((union tree_node *, rtx, enum machine_mode,
+ PARAMS ((union tree_node *, rtx, enum machine_mode,
enum expand_modifier modifier));
lang_expand_expr_t lang_expand_expr = 0;
-tree (*lang_expand_constant) PROTO((tree)) = 0;
+tree (*lang_expand_constant) PARAMS ((tree)) = 0;
/* Pointer to function to finish handling an incomplete decl at the
end of compilation. */
-void (*incomplete_decl_finalize_hook) PROTO((tree)) = 0;
+void (*incomplete_decl_finalize_hook) PARAMS ((tree)) = 0;
/* Nonzero if generating code to do profiling. */
int flag_branch_probabilities = 0;
+/* Nonzero if basic blocks should be reordered. */
+
+int flag_reorder_blocks = 0;
+
+/* Nonzero if registers should be renamed */
+
+int flag_rename_registers = 0;
+
/* Nonzero for -pedantic switch: warn about anything
that standard spec forbids. */
int in_system_header = 0;
-/* Nonzero means do stupid register allocation.
- Currently, this is 1 if `optimize' is 0. */
-
-int obey_regdecls = 0;
-
/* Don't print functions as they are compiled and don't print
times taken by the various passes. -quiet. */
int flag_fast_math = 0;
+/* Nonzero allows GCC to optimize sibling and tail recursive calls. */
+
+int flag_optimize_sibling_calls = 0;
+
/* Nonzero means the front end generally wants `errno' maintained by math
operations, like built-in SQRT, unless overridden by flag_fast_math. */
int flag_gnu_linker = 1;
#endif
+/* Enable SSA. */
+int flag_ssa = 0;
+
/* Tag all structures with __attribute__(packed) */
int flag_pack_struct = 0;
"Defer popping functions args from stack until later" },
{"omit-frame-pointer", &flag_omit_frame_pointer, 1,
"When possible do not generate stack frames"},
+ {"optimize-sibling-calls", &flag_optimize_sibling_calls, 1,
+ "Optimize sibling and tail recursive calls" },
{"cse-follow-jumps", &flag_cse_follow_jumps, 1,
"When running CSE, follow jumps to their targets" },
{"cse-skip-blocks", &flag_cse_skip_blocks, 1,
"Create data files needed by gcov" },
{"branch-probabilities", &flag_branch_probabilities, 1,
"Use profiling information for branch probabilities" },
+ {"reorder-blocks", &flag_reorder_blocks, 1,
+ "Reorder basic blocks to improve code placement" },
+ {"rename-registers", &flag_rename_registers, 1,
+ "Do the register renaming optimization pass"},
{"fast-math", &flag_fast_math, 1,
"Improve FP speed by violating ANSI & IEEE rules" },
{"common", &flag_no_common, 0,
"Suppress output of instruction numbers and line number notes in debugging dumps"},
{"instrument-functions", &flag_instrument_function_entry_exit, 1,
"Instrument function entry/exit with profiling calls"},
+ {"ssa", &flag_ssa, 1,
+ "Enable SSA optimizations" },
{"leading-underscore", &flag_leading_underscore, 1,
"External symbols have a leading underscore" },
{"ident", &flag_no_ident, 0,
{ "-Wno-sign-compare", "" },
{ "-Wfloat-equal", "Warn about testing equality of floating point numbers" },
{ "-Wno-float-equal", "" },
- { "-Wunknown-pragmas", "Warn about unrecognised pragmas" },
+ { "-Wunknown-pragmas", "Warn about unrecognized pragmas" },
{ "-Wno-unknown-pragmas", "" },
{ "-Wstrict-prototypes", "Warn about non-prototyped function decls" },
{ "-Wno-strict-prototypes", "" },
characters. The value N is in `id_clash_len'. */
int warn_id_clash;
-unsigned id_clash_len;
+int id_clash_len;
/* Nonzero means warn about any objects definitions whose size is larger
than N bytes. Also want about function definitions whose returned
values are larger than N bytes. The value N is in `larger_than_size'. */
int warn_larger_than;
-unsigned larger_than_size;
+HOST_WIDE_INT larger_than_size;
/* Nonzero means warn if inline function is too large. */
return atoi (p);
}
-
-/* Time accumulators, to count the total time spent in various passes. */
-
-int parse_time;
-int varconst_time;
-int integration_time;
-int jump_time;
-int cse_time;
-int gcse_time;
-int loop_time;
-int cse2_time;
-int branch_prob_time;
-int flow_time;
-int combine_time;
-int regmove_time;
-int sched_time;
-int local_alloc_time;
-int global_alloc_time;
-int flow2_time;
-int peephole2_time;
-int sched2_time;
-int dbr_sched_time;
-int shorten_branch_time;
-int stack_reg_time;
-int final_time;
-int symout_time;
-int dump_time;
-int gc_time;
-int all_time;
\f
-/* Return time used so far, in microseconds. */
-
-long
-get_run_time ()
-{
- if (quiet_flag)
- return 0;
-
-#ifdef __BEOS__
- return 0;
-#else /* not BeOS */
-#if defined (_WIN32) && !defined (__CYGWIN__)
- if (clock() < 0)
- return 0;
- else
- return (clock() * 1000);
-#else /* not _WIN32 */
-#ifdef _SC_CLK_TCK
- {
- static int tick;
- struct tms tms;
- if (tick == 0)
- tick = 1000000 / sysconf(_SC_CLK_TCK);
- times (&tms);
- return (tms.tms_utime + tms.tms_stime) * tick;
- }
-#else
-#ifdef USG
- {
- struct tms tms;
-# if HAVE_SYSCONF && defined _SC_CLK_TCK
-# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
-# else
-# ifdef CLK_TCK
-# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
-# else
-# define TICKS_PER_SECOND HZ /* traditional UNIX */
-# endif
-# endif
- times (&tms);
- return (tms.tms_utime + tms.tms_stime) * (1000000 / TICKS_PER_SECOND);
- }
-#else
-#ifndef VMS
- {
- struct rusage rusage;
- getrusage (0, &rusage);
- return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
- + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
- }
-#else /* VMS */
- {
- struct
- {
- int proc_user_time;
- int proc_system_time;
- int child_user_time;
- int child_system_time;
- } vms_times;
- times ((void *) &vms_times);
- return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000;
- }
-#endif /* VMS */
-#endif /* USG */
-#endif /* _SC_CLK_TCK */
-#endif /* _WIN32 */
-#endif /* __BEOS__ */
-}
-
-#define TIMEVAR(VAR, BODY) \
-do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
-
-void
-print_time (str, total)
- const char *str;
- int total;
-{
- fprintf (stderr,
- "time in %s: %d.%06d (%.0f%%)\n",
- str, total / 1000000, total % 1000000,
- (double)total / (double)all_time * 100.0);
-}
-
/* This is the default decl_printable_name function. */
static const char *
}
\f
/* Mark P for GC. Also mark main_input_filename and input_filename. */
+
static void
mark_file_stack (p)
void *p;
int
do_float_handler (fn, data)
- void (*fn) PROTO ((PTR));
+ void (*fn) PARAMS ((PTR));
PTR data;
{
jmp_buf buf;
}
#endif
-/* Routine to open a dump file. */
-static void
-open_dump_file (suffix, function_name)
- const char *suffix;
- const char *function_name;
+/* Routine to open a dump file. Return true if the dump file is enabled. */
+
+static int
+open_dump_file (index, decl)
+ enum dump_file_index index;
+ tree decl;
{
- char *dumpname;
+ char *dump_name;
+ const char *open_arg;
+ char seq[16];
- TIMEVAR
- (dump_time,
- {
- dumpname = concat (dump_base_name, suffix, NULL);
+ if (! dump_file[index].enabled)
+ return 0;
- if (rtl_dump_file != NULL)
- fclose (rtl_dump_file);
+ timevar_push (TV_DUMP);
+ if (rtl_dump_file != NULL)
+ fclose (rtl_dump_file);
- rtl_dump_file = fopen (dumpname, "a");
-
- if (rtl_dump_file == NULL)
- pfatal_with_name (dumpname);
-
- free (dumpname);
+ sprintf (seq, ".%02d.", index);
- if (function_name)
- fprintf (rtl_dump_file, "\n;; Function %s\n\n", function_name);
- });
-
- return;
-}
+ if (! dump_file[index].initialized)
+ {
+ /* If we've not initialized the files, do so now. */
+ if (graph_dump_format != no_graph
+ && dump_file[index].graph_dump_p)
+ {
+ dump_name = concat (seq, dump_file[index].extension, NULL);
+ clean_graph_dump_file (dump_base_name, dump_name);
+ free (dump_name);
+ }
+ dump_file[index].initialized = 1;
+ open_arg = "w";
+ }
+ else
+ open_arg = "a";
-/* Routine to close a dump file. */
-static void
-close_dump_file (func, insns)
- void (*func) PROTO ((FILE *, rtx));
- rtx insns;
-{
- TIMEVAR
- (dump_time,
- {
- if (func)
- func (rtl_dump_file, insns);
-
- fflush (rtl_dump_file);
- fclose (rtl_dump_file);
+ dump_name = concat (dump_base_name, seq,
+ dump_file[index].extension, NULL);
+
+ rtl_dump_file = fopen (dump_name, open_arg);
+ if (rtl_dump_file == NULL)
+ pfatal_with_name (dump_name);
- rtl_dump_file = NULL;
- });
+ free (dump_name);
- return;
-}
+ if (decl)
+ fprintf (rtl_dump_file, "\n;; Function %s\n\n",
+ decl_printable_name (decl, 2));
-/* Routine to dump rtl into a file. */
-static void
-dump_rtl (suffix, decl, func, insns)
- const char *suffix;
- tree decl;
- void (*func) PROTO ((FILE *, rtx));
- rtx insns;
-{
- open_dump_file (suffix, decl_printable_name (decl, 2));
- close_dump_file (func, insns);
+ timevar_pop (TV_DUMP);
+ return 1;
}
-/* Routine to empty a dump file. */
+/* Routine to close a dump file. */
+
static void
-clean_dump_file (suffix)
- const char *suffix;
+close_dump_file (index, func, insns)
+ enum dump_file_index index;
+ void (*func) PARAMS ((FILE *, rtx));
+ rtx insns;
{
- char * const dumpname = concat (dump_base_name, suffix, NULL);
-
- rtl_dump_file = fopen (dumpname, "w");
+ if (! rtl_dump_file)
+ return;
- if (rtl_dump_file == NULL)
- pfatal_with_name (dumpname);
+ timevar_push (TV_DUMP);
+ if (insns
+ && graph_dump_format != no_graph
+ && dump_file[index].graph_dump_p)
+ {
+ char seq[16];
+ char *suffix;
- free (dumpname);
+ sprintf (seq, ".%02d.", index);
+ suffix = concat (seq, dump_file[index].extension, NULL);
+ print_rtl_graph_with_bb (dump_base_name, suffix, insns);
+ free (suffix);
+ }
+ if (func && insns)
+ func (rtl_dump_file, insns);
+
+ fflush (rtl_dump_file);
fclose (rtl_dump_file);
+
rtl_dump_file = NULL;
-
- return;
+ timevar_pop (TV_DUMP);
}
/* Do any final processing required for the declarations in VEC, of
&& ! TREE_USED (DECL_NAME (decl)))
warning_with_decl (decl, "`%s' defined but not used");
+ timevar_push (TV_SYMOUT);
#ifdef SDB_DEBUGGING_INFO
/* The COFF linker can move initialized global vars to the end.
And that can screw up the symbol ordering.
&& TREE_PUBLIC (decl) && DECL_INITIAL (decl)
&& ! DECL_EXTERNAL (decl)
&& DECL_RTL (decl) != 0)
- TIMEVAR (symout_time, sdbout_symbol (decl, 0));
+ sdbout_symbol (decl, 0);
/* Output COFF information for non-global
file-scope initialized variables. */
&& ! DECL_EXTERNAL (decl)
&& DECL_RTL (decl) != 0
&& GET_CODE (DECL_RTL (decl)) == MEM)
- TIMEVAR (symout_time, sdbout_toplevel_data (decl));
+ sdbout_toplevel_data (decl);
#endif /* SDB_DEBUGGING_INFO */
#ifdef DWARF_DEBUGGING_INFO
/* Output DWARF information for file-scope tentative data object
if (write_symbols == DWARF_DEBUG
&& (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 1));
+ dwarfout_file_scope_decl (decl, 1);
#endif
#ifdef DWARF2_DEBUGGING_INFO
/* Output DWARF2 information for file-scope tentative data object
if (write_symbols == DWARF2_DEBUG
&& (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- TIMEVAR (symout_time, dwarf2out_decl (decl));
+ dwarf2out_decl (decl);
#endif
+ timevar_pop (TV_SYMOUT);
}
}
+/* Save the current INPUT_FILENAME and LINENO on the top entry in the
+ INPUT_FILE_STACK. Push a new entry for FILE and LINE, and set the
+ INPUT_FILENAME and LINENO accordingly. */
+
+void
+push_srcloc (file, line)
+ char *file;
+ int line;
+{
+ struct file_stack *fs;
+
+ if (input_file_stack)
+ {
+ input_file_stack->name = input_filename;
+ input_file_stack->line = lineno;
+ }
+
+ fs = (struct file_stack *) xmalloc (sizeof (struct file_stack));
+ fs->name = input_filename = file;
+ fs->line = lineno = line;
+ fs->indent_level = 0;
+ fs->next = input_file_stack;
+ input_file_stack = fs;
+ input_file_stack_tick++;
+}
+
+/* Pop the top entry off the stack of presently open source files.
+ Restore the INPUT_FILENAME and LINENO from the new topmost entry on
+ the stack. */
+
+void
+pop_srcloc ()
+{
+ struct file_stack *fs;
+
+ fs = input_file_stack;
+ input_file_stack = fs->next;
+ free (fs);
+ input_file_stack_tick++;
+ /* The initial souce file is never popped. */
+ if (!input_file_stack)
+ abort ();
+ input_filename = input_file_stack->name;
+ lineno = input_file_stack->line;
+}
+
/* Compile an entire file of output from cpp, named NAME.
Write a file of assembly output and various debugging dumps. */
char *name;
{
tree globals;
- int start_time;
int name_specified = name != 0;
if (dump_base_name == 0)
dump_base_name = name ? name : "gccdump";
- parse_time = 0;
- varconst_time = 0;
- integration_time = 0;
- jump_time = 0;
- cse_time = 0;
- gcse_time = 0;
- loop_time = 0;
- cse2_time = 0;
- branch_prob_time = 0;
- flow_time = 0;
- combine_time = 0;
- regmove_time = 0;
- sched_time = 0;
- local_alloc_time = 0;
- global_alloc_time = 0;
- flow2_time = 0;
- peephole2_time = 0;
- sched2_time = 0;
- dbr_sched_time = 0;
- shorten_branch_time = 0;
- stack_reg_time = 0;
- final_time = 0;
- symout_time = 0;
- dump_time = 0;
+ /* Start timing total execution time. */
+ init_timevar ();
+ timevar_start (TV_TOTAL);
+
/* Initialize data in various passes. */
init_obstacks ();
pfatal_with_name (aux_info_file_name);
}
- /* Clear the dump files. */
- if (rtl_dump)
- clean_dump_file (".00.rtl");
- if (jump_opt_dump)
- {
- clean_dump_file (".01.jump");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".01.jump");
- }
- if (cse_dump)
- {
- clean_dump_file (".02.cse");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".02.cse");
- }
- if (addressof_dump)
- {
- clean_dump_file (".03.addressof");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".03.addressof");
- }
- if (gcse_dump)
- {
- clean_dump_file (".04.gcse");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".04.gcse");
- }
- if (loop_dump)
- {
- clean_dump_file (".05.loop");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".05.loop");
- }
- if (cse2_dump)
- {
- clean_dump_file (".06.cse2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".06.cse2");
- }
- if (branch_prob_dump)
- {
- clean_dump_file (".07.bp");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".07.bp");
- }
- if (flow_dump)
- {
- clean_dump_file (".08.flow");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".08.flow");
- }
- if (combine_dump)
- {
- clean_dump_file (".09.combine");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".09.combine");
- }
- if (regmove_dump)
- {
- clean_dump_file (".10.regmove");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".10.regmove");
- }
-#ifdef INSN_SCHEDULING
- if (sched_dump)
- {
- clean_dump_file (".11.sched");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".11.sched");
- }
-#endif
- if (local_reg_dump)
- {
- clean_dump_file (".12.lreg");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".12.lreg");
- }
- if (global_reg_dump)
- {
- clean_dump_file (".13.greg");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".13.greg");
- }
- if (flow2_dump)
- {
- clean_dump_file (".14.flow2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".14.flow2");
- }
-#ifdef HAVE_peephole2
- if (peephole2_dump)
- {
- clean_dump_file (".15.peephole2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".15.peephole2");
- }
-#endif
-#ifdef INSN_SCHEDULING
- if (sched2_dump)
- {
- clean_dump_file (".16.sched2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".16.sched2");
- }
-#endif
- if (jump2_opt_dump)
- {
- clean_dump_file (".17.jump2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".17.jump2");
- }
-#ifdef MACHINE_DEPENDENT_REORG
- if (mach_dep_reorg_dump)
- {
- clean_dump_file (".18.mach");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".18.mach");
- }
-#endif
-#ifdef DELAY_SLOTS
- if (dbr_sched_dump)
- {
- clean_dump_file (".19.dbr");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".19.dbr");
- }
-#endif
-#ifdef STACK_REGS
- if (stack_reg_dump)
- {
- clean_dump_file (".20.stack");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".20.stack");
- }
-#endif
-
/* Open assembler code output file. */
if (flag_syntax_only)
input_filename = name;
/* Put an entry on the input file stack for the main input file. */
- input_file_stack
- = (struct file_stack *) xmalloc (sizeof (struct file_stack));
- input_file_stack->next = 0;
- input_file_stack->name = input_filename;
+ push_srcloc (input_filename, 0);
/* Perform language-specific initialization.
This may set main_input_filename. */
/* If dbx symbol table desired, initialize writing it
and output the predefined types. */
+ timevar_push (TV_SYMOUT);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- TIMEVAR (symout_time, dbxout_init (asm_out_file, main_input_filename,
- getdecls ()));
+ dbxout_init (asm_out_file, main_input_filename, getdecls ());
#endif
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
- TIMEVAR (symout_time, sdbout_init (asm_out_file, main_input_filename,
- getdecls ()));
+ sdbout_init (asm_out_file, main_input_filename, getdecls ());
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
- TIMEVAR (symout_time, dwarfout_init (asm_out_file, main_input_filename));
+ dwarfout_init (asm_out_file, main_input_filename);
#endif
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
- TIMEVAR (symout_time, dwarf2out_init (asm_out_file, main_input_filename));
+ dwarf2out_init (asm_out_file, main_input_filename);
#endif
+ timevar_pop (TV_SYMOUT);
/* Initialize yet another pass. */
init_final (main_input_filename);
init_branch_prob (dump_base_name);
- start_time = get_run_time ();
+ timevar_push (TV_PARSE);
/* Call the parser, which parses the entire file
(calling rest_of_compilation for each function). */
/* Compilation is now finished except for writing
what's left of the symbol table output. */
- parse_time += get_run_time () - start_time;
-
- parse_time -= integration_time;
- parse_time -= varconst_time;
+ timevar_pop (TV_PARSE);
if (flag_syntax_only)
goto finish_syntax;
weak_finish ();
/* Do dbx symbols */
+ timevar_push (TV_SYMOUT);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- TIMEVAR (symout_time,
- {
- dbxout_finish (asm_out_file, main_input_filename);
- });
+ dbxout_finish (asm_out_file, main_input_filename);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
- TIMEVAR (symout_time,
- {
- dwarfout_finish ();
- });
+ dwarfout_finish ();
#endif
#ifdef DWARF2_UNWIND_INFO
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
- TIMEVAR (symout_time,
- {
- dwarf2out_finish ();
- });
+ dwarf2out_finish ();
#endif
+ timevar_pop (TV_SYMOUT);
/* Output some stuff at end of file if nec. */
end_final (dump_base_name);
- if (branch_prob_dump)
- open_dump_file (".07.bp", NULL);
-
- TIMEVAR (dump_time, end_branch_prob (rtl_dump_file));
-
- if (branch_prob_dump)
- close_dump_file (NULL, NULL_RTX);
+ if (flag_test_coverage || flag_branch_probabilities)
+ {
+ timevar_push (TV_DUMP);
+ open_dump_file (DFI_bp, NULL);
+ end_branch_prob (rtl_dump_file);
+ close_dump_file (DFI_bp, NULL, NULL_RTX);
+ timevar_pop (TV_DUMP);
+ }
#ifdef ASM_FILE_END
ASM_FILE_END (asm_out_file);
#endif
-
/* Language-specific end of compilation actions. */
finish_syntax:
lang_finish ();
unlink (aux_info_file_name);
}
- if (combine_dump)
+ if (optimize > 0 && open_dump_file (DFI_combine, NULL))
{
- open_dump_file (".09.combine", NULL);
- TIMEVAR (dump_time, dump_combine_total_stats (rtl_dump_file));
- close_dump_file (NULL, NULL_RTX);
+ timevar_push (TV_DUMP);
+ dump_combine_total_stats (rtl_dump_file);
+ close_dump_file (DFI_combine, NULL, NULL_RTX);
+ timevar_pop (TV_DUMP);
}
/* Close non-debugging input and output files. Take special care to note
/* Do whatever is necessary to finish printing the graphs. */
if (graph_dump_format != no_graph)
{
- if (jump_opt_dump)
- finish_graph_dump_file (dump_base_name, ".01.jump");
- if (cse_dump)
- finish_graph_dump_file (dump_base_name, ".02.cse");
- if (addressof_dump)
- finish_graph_dump_file (dump_base_name, ".03.addressof");
- if (gcse_dump)
- finish_graph_dump_file (dump_base_name, ".04.gcse");
- if (loop_dump)
- finish_graph_dump_file (dump_base_name, ".05.loop");
- if (cse2_dump)
- finish_graph_dump_file (dump_base_name, ".06.cse2");
- if (branch_prob_dump)
- finish_graph_dump_file (dump_base_name, ".07.bp");
- if (flow_dump)
- finish_graph_dump_file (dump_base_name, ".08.flow");
- if (combine_dump)
- finish_graph_dump_file (dump_base_name, ".09.combine");
- if (regmove_dump)
- finish_graph_dump_file (dump_base_name, ".10.regmove");
-#ifdef INSN_SCHEDULING
- if (sched_dump)
- finish_graph_dump_file (dump_base_name, ".11.sched");
-#endif
- if (local_reg_dump)
- finish_graph_dump_file (dump_base_name, ".12.lreg");
- if (global_reg_dump)
- finish_graph_dump_file (dump_base_name, ".13.greg");
- if (flow2_dump)
- finish_graph_dump_file (dump_base_name, ".14.flow2");
-#ifdef HAVE_peephole2
- if (flow2_dump)
- finish_graph_dump_file (dump_base_name, ".15.peephole2");
-#endif
-#ifdef INSN_SCHEDULING
- if (sched2_dump)
- finish_graph_dump_file (dump_base_name, ".16.sched2");
-#endif
- if (jump2_opt_dump)
- finish_graph_dump_file (dump_base_name, ".17.jump2");
-#ifdef MACHINE_DEPENDENT_REORG
- if (mach_dep_reorg_dump)
- finish_graph_dump_file (dump_base_name, ".18.mach");
-#endif
-#ifdef DELAY_SLOTS
- if (dbr_sched_dump)
- finish_graph_dump_file (dump_base_name, ".19.dbr");
-#endif
-#ifdef STACK_REGS
- if (stack_reg_dump)
- finish_graph_dump_file (dump_base_name, ".20.stack");
-#endif
+ int i;
+
+ for (i = 0; i < DFI_MAX; ++i)
+ if (dump_file[i].initialized && dump_file[i].graph_dump_p)
+ {
+ char seq[16];
+ char *suffix;
+
+ sprintf (seq, ".%02d.", i);
+ suffix = concat (seq, dump_file[i].extension, NULL);
+ finish_graph_dump_file (dump_base_name, suffix);
+ free (suffix);
+ }
}
/* Free up memory for the benefit of leak detectors. */
free_reg_info ();
+ /* Stop timing total execution time. */
+ timevar_stop (TV_TOTAL);
+
/* Print the times. */
if (! quiet_flag)
- {
- all_time = get_run_time ();
-
- fprintf (stderr,"\n");
-
- print_time ("parse", parse_time);
- print_time ("integration", integration_time);
- print_time ("jump", jump_time);
- print_time ("cse", cse_time);
- print_time ("gcse", gcse_time);
- print_time ("loop", loop_time);
- print_time ("cse2", cse2_time);
- print_time ("branch-prob", branch_prob_time);
- print_time ("flow", flow_time);
- print_time ("combine", combine_time);
- print_time ("regmove", regmove_time);
-#ifdef INSN_SCHEDULING
- print_time ("sched", sched_time);
-#endif
- print_time ("local-alloc", local_alloc_time);
- print_time ("global-alloc", global_alloc_time);
- print_time ("flow2", flow2_time);
-#ifdef HAVE_peephole2
- print_time ("peephole2", peephole2_time);
-#endif
-#ifdef INSN_SCHEDULING
- print_time ("sched2", sched2_time);
-#endif
-#ifdef DELAY_SLOTS
- print_time ("dbranch", dbr_sched_time);
-#endif
- print_time ("shorten-branch", shorten_branch_time);
-#ifdef STACK_REGS
- print_time ("stack-reg", stack_reg_time);
-#endif
- print_time ("final", final_time);
- print_time ("varconst", varconst_time);
- print_time ("symout", symout_time);
- print_time ("dump", dump_time);
- if (ggc_p)
- print_time ("gc", gc_time);
- }
+ timevar_print (stderr);
}
\f
/* This is called from various places for FUNCTION_DECL, VAR_DECL,
but we need to treat them as if they were. */
if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
|| TREE_CODE (decl) == FUNCTION_DECL)
- TIMEVAR (varconst_time,
- {
- make_decl_rtl (decl, asmspec, top_level);
- /* Initialized extern variable exists to be replaced
- with its value, or represents something that will be
- output in another file. */
- if (! (TREE_CODE (decl) == VAR_DECL
- && DECL_EXTERNAL (decl) && TREE_READONLY (decl)
- && DECL_INITIAL (decl) != 0
- && DECL_INITIAL (decl) != error_mark_node))
- /* Don't output anything
- when a tentative file-scope definition is seen.
- But at end of compilation, do output code for them. */
- if (! (! at_end && top_level
- && (DECL_INITIAL (decl) == 0
- || DECL_INITIAL (decl) == error_mark_node)))
- assemble_variable (decl, top_level, at_end, 0);
- if (decl == last_assemble_variable_decl)
- {
- ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
- top_level, at_end);
- }
- });
+ {
+ timevar_push (TV_VARCONST);
+ make_decl_rtl (decl, asmspec, top_level);
+ /* Initialized extern variable exists to be replaced
+ with its value, or represents something that will be
+ output in another file. */
+ if (! (TREE_CODE (decl) == VAR_DECL
+ && DECL_EXTERNAL (decl) && TREE_READONLY (decl)
+ && DECL_INITIAL (decl) != 0
+ && DECL_INITIAL (decl) != error_mark_node))
+ /* Don't output anything
+ when a tentative file-scope definition is seen.
+ But at end of compilation, do output code for them. */
+ if (! (! at_end && top_level
+ && (DECL_INITIAL (decl) == 0
+ || DECL_INITIAL (decl) == error_mark_node)))
+ assemble_variable (decl, top_level, at_end, 0);
+ if (decl == last_assemble_variable_decl)
+ {
+ ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
+ top_level, at_end);
+ }
+ timevar_pop (TV_VARCONST);
+ }
else if (DECL_REGISTER (decl) && asmspec != 0)
{
if (decode_reg_name (asmspec) >= 0)
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
&& TREE_CODE (decl) == TYPE_DECL)
- TIMEVAR (symout_time, dbxout_symbol (decl, 0));
+ {
+ timevar_push (TV_SYMOUT);
+ dbxout_symbol (decl, 0);
+ timevar_pop (TV_SYMOUT);
+ }
#endif
#ifdef SDB_DEBUGGING_INFO
else if (write_symbols == SDB_DEBUG && top_level
&& TREE_CODE (decl) == TYPE_DECL)
- TIMEVAR (symout_time, sdbout_symbol (decl, 0));
+ {
+ timevar_push (TV_SYMOUT);
+ sdbout_symbol (decl, 0);
+ timevar_pop (TV_SYMOUT);
+ }
#endif
}
int toplev ATTRIBUTE_UNUSED;
#endif
{
+ timevar_push (TV_SYMOUT);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- TIMEVAR (symout_time, dbxout_symbol (TYPE_STUB_DECL (type), !toplev));
+ dbxout_symbol (TYPE_STUB_DECL (type), !toplev);
#endif
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
- TIMEVAR (symout_time, sdbout_symbol (TYPE_STUB_DECL (type), !toplev));
+ sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
#endif
+ timevar_pop (TV_SYMOUT);
}
/* DECL is an inline function, whose body is present, but which is not
void
note_deferral_of_defined_inline_function (decl)
- tree decl;
+ tree decl ATTRIBUTE_UNUSED;
{
#ifdef DWARF_DEBUGGING_INFO
/* Generate the DWARF info for the "abstract" instance of a function
which we may later generate inlined and/or out-of-line instances
of. */
- if (write_symbols == DWARF_DEBUG)
+ if (write_symbols == DWARF_DEBUG && DECL_INLINE (decl))
{
/* The front-end may not have set CURRENT_FUNCTION_DECL, but the
DWARF code expects it to be set in this case. Intuitively,
tree decl;
{
register rtx insns;
- int start_time = get_run_time ();
int tem;
int failure = 0;
int rebuild_label_notes_after_reload;
+ timevar_push (TV_REST_OF_COMPILATION);
+
/* When processing delayed functions, prepare_function_start() won't
have been run to re-initialize it. */
cse_not_expected = ! optimize;
- /* First, remove any notes we don't need. That will make iterating
+ /* First, make sure that NOTE_BLOCK is set correctly for each
+ NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note. */
+ if (!cfun->x_whole_function_mode_p)
+ identify_blocks ();
+
+ /* Then remove any notes we don't need. That will make iterating
over the instruction sequence faster, and allow the garbage
collector to reclaim the memory used by the notes. */
- remove_unncessary_notes ();
+ remove_unnecessary_notes ();
/* In function-at-a-time mode, we do not attempt to keep the BLOCK
tree in sensible shape. So, we just recalculate it here. */
if (cfun->x_whole_function_mode_p)
- {
- find_loop_tree_blocks ();
- unroll_block_trees ();
- }
+ reorder_blocks ();
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
/* If requested, consider whether to make this function inline. */
if (DECL_INLINE (decl) || flag_inline_functions)
- TIMEVAR (integration_time,
- {
- lose = function_cannot_inline_p (decl);
- if (lose || ! optimize)
- {
- if (warn_inline && DECL_INLINE (decl))
- warning_with_decl (decl, lose);
- DECL_ABSTRACT_ORIGIN (decl) = 0;
- /* Don't really compile an extern inline function.
- If we can't make it inline, pretend
- it was only declared. */
- if (DECL_EXTERNAL (decl))
- {
- DECL_INITIAL (decl) = 0;
- goto exit_rest_of_compilation;
- }
- }
- else
- /* ??? Note that this has the effect of making it look
- like "inline" was specified for a function if we choose
- to inline it. This isn't quite right, but it's
- probably not worth the trouble to fix. */
- inlinable = DECL_INLINE (decl) = 1;
- });
+ {
+ timevar_push (TV_INTEGRATION);
+ lose = function_cannot_inline_p (decl);
+ timevar_pop (TV_INTEGRATION);
+ if (lose || ! optimize)
+ {
+ if (warn_inline && DECL_INLINE (decl))
+ warning_with_decl (decl, lose);
+ DECL_ABSTRACT_ORIGIN (decl) = 0;
+ /* Don't really compile an extern inline function.
+ If we can't make it inline, pretend
+ it was only declared. */
+ if (DECL_EXTERNAL (decl))
+ {
+ DECL_INITIAL (decl) = 0;
+ goto exit_rest_of_compilation;
+ }
+ }
+ else
+ /* ??? Note that this has the effect of making it look
+ like "inline" was specified for a function if we choose
+ to inline it. This isn't quite right, but it's
+ probably not worth the trouble to fix. */
+ inlinable = DECL_INLINE (decl) = 1;
+ }
insns = get_insns ();
/* Dump the rtl code if we are dumping rtl. */
- if (rtl_dump)
+ if (open_dump_file (DFI_rtl, decl))
{
- open_dump_file (".00.rtl", decl_printable_name (decl, 2));
-
if (DECL_SAVED_INSNS (decl))
fprintf (rtl_dump_file, ";; (integrable)\n\n");
-
- close_dump_file (print_rtl, insns);
+ close_dump_file (DFI_rtl, print_rtl, insns);
}
/* If function is inline, and we don't yet know whether to
for those functions that need to be output. Also defer those
functions that we are supposed to defer. */
- if (inlinable)
- DECL_DEFER_OUTPUT (decl) = 1;
-
- if (DECL_DEFER_OUTPUT (decl)
+ if (inlinable
|| (DECL_INLINE (decl)
&& ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
&& ! flag_keep_inline_functions)
|| DECL_EXTERNAL (decl))))
- {
- DECL_DEFER_OUTPUT (decl) = 1;
+ DECL_DEFER_OUTPUT (decl) = 1;
+ if (DECL_INLINE (decl))
+ /* DWARF wants seperate debugging info for abstract and
+ concrete instances of all inline functions, including those
+ declared inline but not inlined, and those inlined even
+ though they weren't declared inline. Conveniently, that's
+ what DECL_INLINE means at this point. */
+ note_deferral_of_defined_inline_function (decl);
+
+ if (DECL_DEFER_OUTPUT (decl))
+ {
/* If -Wreturn-type, we have to do a bit of compilation.
However, if we just fall through we will call
save_for_inline_copying() which results in excessive
int saved_optimize = optimize;
optimize = 0;
find_exception_handler_labels ();
- jump_optimize (get_insns(), !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
!JUMP_AFTER_REGSCAN);
optimize = saved_optimize;
}
- note_deferral_of_defined_inline_function (decl);
- TIMEVAR (integration_time, save_for_inline_nocopy (decl));
+ current_function_nothrow = nothrow_function_p ();
+ if (current_function_nothrow)
+ /* Now we know that this can't throw; set the flag for the benefit
+ of other functions later in this translation unit. */
+ TREE_NOTHROW (current_function_decl) = 1;
+
+ timevar_push (TV_INTEGRATION);
+ save_for_inline_nocopy (decl);
+ timevar_pop (TV_INTEGRATION);
DECL_SAVED_INSNS (decl)->inlinable = inlinable;
goto exit_rest_of_compilation;
}
goto exit_rest_of_compilation;
}
+ init_EXPR_INSN_LIST_cache ();
+
+ if (ggc_p)
+ ggc_collect ();
+
/* Initialize some variables used by the optimizers. */
init_function_for_compilation ();
/* Don't return yet if -Wreturn-type; we need to do jump_optimize. */
if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
- {
- goto exit_rest_of_compilation;
- }
+ goto exit_rest_of_compilation;
/* Emit code to get eh context, if needed. */
emit_eh_context ();
+ /* We may have potential sibling or tail recursion sites. Select one
+ (of possibly multiple) methods of performing the call. */
+ if (flag_optimize_sibling_calls)
+ {
+ timevar_push (TV_JUMP);
+ open_dump_file (DFI_sibling, decl);
+
+ optimize_sibling_and_tail_recursive_calls ();
+
+ close_dump_file (DFI_sibling, print_rtl, get_insns ());
+ timevar_pop (TV_JUMP);
+ }
+
#ifdef FINALIZE_PIC
/* If we are doing position-independent code generation, now
is the time to output special prologues and epilogues.
insns = get_insns ();
/* Copy any shared structure that should not be shared. */
-
- unshare_all_rtl (insns);
-
- init_EXPR_INSN_LIST_cache ();
+ unshare_all_rtl (current_function_decl, insns);
#ifdef SETJMP_VIA_SAVE_AREA
/* This must be performed before virutal register instantiation. */
#endif
/* Instantiate all virtual registers. */
-
- instantiate_virtual_regs (current_function_decl, get_insns ());
-
- /* See if we have allocated stack slots that are not directly addressable.
- If so, scan all the insns and create explicit address computation
- for all references to such slots. */
- /* fixup_stack_slots (); */
+ instantiate_virtual_regs (current_function_decl, insns);
/* Find all the EH handlers. */
find_exception_handler_labels ();
- if (jump_opt_dump)
- open_dump_file (".01.jump", decl_printable_name (decl, 2));
+ open_dump_file (DFI_jump, decl);
/* Always do one jump optimization pass to ensure that JUMP_LABEL fields
are initialized and to compute whether control can drop off the end
of the function. */
- TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
- JUMP_AFTER_REGSCAN));
- /* Jump optimization, and the removal of NULL pointer checks, may
- have reduced the number of instructions substantially. CSE, and
- future passes, allocate arrays whose dimensions involve the maximum
- instruction UID, so if we can reduce the maximum UID we'll save big on
- memory. */
- renumber_insns (rtl_dump_file);
+ timevar_push (TV_JUMP);
+ /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this
+ before jump optimization switches branch directions. */
+ expected_value_to_br_prob ();
- /* Dump rtl code after jump, if we are doing that. */
- if (jump_opt_dump)
- close_dump_file (print_rtl, insns);
+ reg_scan (insns, max_reg_num (), 0);
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ JUMP_AFTER_REGSCAN);
+
+ timevar_pop (TV_JUMP);
/* Now is when we stop if -fsyntax-only and -Wreturn-type. */
if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
- goto exit_rest_of_compilation;
+ {
+ close_dump_file (DFI_jump, print_rtl, insns);
+ goto exit_rest_of_compilation;
+ }
+
+ timevar_push (TV_JUMP);
- /* Try to identify useless null pointer tests and delete them. */
- if (flag_delete_null_pointer_checks)
- TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
+ if (optimize > 0)
+ {
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+
+ /* ??? Run if-conversion before delete_null_pointer_checks,
+ since the later does not preserve the CFG. This should
+ be changed -- no since converting if's that are going to
+ be deleted. */
+ timevar_push (TV_IFCVT);
+ if_convert (0);
+ timevar_pop (TV_IFCVT);
+
+ /* Try to identify useless null pointer tests and delete them. */
+ if (flag_delete_null_pointer_checks)
+ delete_null_pointer_checks (insns);
+ }
+
+ /* Jump optimization, and the removal of NULL pointer checks, may
+ have reduced the number of instructions substantially. CSE, and
+ future passes, allocate arrays whose dimensions involve the
+ maximum instruction UID, so if we can reduce the maximum UID
+ we'll save big on memory. */
+ renumber_insns (rtl_dump_file);
+ timevar_pop (TV_JUMP);
+
+ close_dump_file (DFI_jump, print_rtl, insns);
if (ggc_p)
ggc_collect ();
if (optimize > 0)
{
- if (cse_dump)
- open_dump_file (".02.cse", decl_printable_name (decl, 2));
+ open_dump_file (DFI_cse, decl);
+ timevar_push (TV_CSE);
- TIMEVAR (cse_time, reg_scan (insns, max_reg_num (), 1));
+ reg_scan (insns, max_reg_num (), 1);
if (flag_thread_jumps)
- TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 1));
+ {
+ timevar_push (TV_JUMP);
+ thread_jumps (insns, max_reg_num (), 1);
+ timevar_pop (TV_JUMP);
+ }
+
+ tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
- TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num (),
- 0, rtl_dump_file));
/* If we are not running the second CSE pass, then we are no longer
expecting CSE to be run. */
cse_not_expected = !flag_rerun_cse_after_loop;
if (tem || optimize > 1)
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ {
+ timevar_push (TV_JUMP);
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN);
+ timevar_pop (TV_JUMP);
+ }
/* Run this after jump optmizations remove all the unreachable code
so that unreachable code will not keep values live. */
- TIMEVAR (cse_time, delete_trivially_dead_insns (insns, max_reg_num ()));
+ delete_trivially_dead_insns (insns, max_reg_num ());
/* Try to identify useless null pointer tests and delete them. */
if (flag_delete_null_pointer_checks)
- TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
+ {
+ timevar_push (TV_JUMP);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+ cleanup_cfg (insns);
+
+ delete_null_pointer_checks (insns);
+ timevar_pop (TV_JUMP);
+ }
/* The second pass of jump optimization is likely to have
removed a bunch more instructions. */
renumber_insns (rtl_dump_file);
- /* Dump rtl code after cse, if we are doing that. */
- if (cse_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".02.cse", insns);
- }
+ timevar_pop (TV_CSE);
+ close_dump_file (DFI_cse, print_rtl, insns);
}
+ open_dump_file (DFI_addressof, decl);
+
purge_addressof (insns);
reg_scan (insns, max_reg_num (), 1);
- if (addressof_dump)
- {
- dump_rtl (".03.addressof", decl, print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".03.addressof", insns);
- }
+ close_dump_file (DFI_addressof, print_rtl, insns);
if (ggc_p)
ggc_collect ();
+ if (optimize > 0 && flag_ssa)
+ {
+ /* Convert to SSA form. */
+
+ timevar_push (TV_TO_SSA);
+ open_dump_file (DFI_ssa, decl);
+
+ find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
+ cleanup_cfg (insns);
+ convert_to_ssa ();
+
+ close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
+ timevar_pop (TV_TO_SSA);
+
+ /* Currently, there's nothing to do in SSA form. */
+
+ /* Convert from SSA form. */
+
+ timevar_push (TV_FROM_SSA);
+ open_dump_file (DFI_ussa, decl);
+
+ convert_from_ssa ();
+ /* New registers have been created. Rescan their usage. */
+ reg_scan (insns, max_reg_num (), 1);
+ /* Life analysis used in SSA adds log_links but these
+ shouldn't be there until the flow stage, so clear
+ them away. */
+ clear_log_links (insns);
+
+ close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
+ timevar_pop (TV_FROM_SSA);
+
+ if (ggc_p)
+ ggc_collect ();
+ }
+
/* Perform global cse. */
if (optimize > 0 && flag_gcse)
{
- if (gcse_dump)
- open_dump_file (".04.gcse", decl_printable_name (decl, 2));
+ timevar_push (TV_GCSE);
+ open_dump_file (DFI_gcse, decl);
- TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file));
+ find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
+ cleanup_cfg (insns);
+ tem = gcse_main (insns, rtl_dump_file);
/* If gcse altered any jumps, rerun jump optimizations to clean
things up. */
if (tem)
{
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ timevar_push (TV_JUMP);
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN);
+ timevar_pop (TV_JUMP);
}
- if (gcse_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".04.gcse", insns);
- }
+ close_dump_file (DFI_gcse, print_rtl, insns);
+ timevar_pop (TV_GCSE);
if (ggc_p)
ggc_collect ();
}
+
/* Move constant computations out of loops. */
if (optimize > 0)
{
- if (loop_dump)
- open_dump_file (".05.loop", decl_printable_name (decl, 2));
-
- TIMEVAR
- (loop_time,
- {
- if (flag_rerun_loop_opt)
- {
- /* We only want to perform unrolling once. */
-
- loop_optimize (insns, rtl_dump_file, 0, 0);
+ timevar_push (TV_LOOP);
+ open_dump_file (DFI_loop, decl);
+
+ if (flag_rerun_loop_opt)
+ {
+ /* We only want to perform unrolling once. */
-
- /* The first call to loop_optimize makes some instructions
- trivially dead. We delete those instructions now in the
- hope that doing so will make the heuristics in loop work
- better and possibly speed up compilation. */
- delete_trivially_dead_insns (insns, max_reg_num ());
-
- /* The regscan pass is currently necessary as the alias
- analysis code depends on this information. */
- reg_scan (insns, max_reg_num (), 1);
- }
- loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1);
- });
+ loop_optimize (insns, rtl_dump_file, 0, 0);
- /* Dump rtl code after loop opt, if we are doing that. */
+ /* The first call to loop_optimize makes some instructions
+ trivially dead. We delete those instructions now in the
+ hope that doing so will make the heuristics in loop work
+ better and possibly speed up compilation. */
+ delete_trivially_dead_insns (insns, max_reg_num ());
- if (loop_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".05.loop", insns);
+ /* The regscan pass is currently necessary as the alias
+ analysis code depends on this information. */
+ reg_scan (insns, max_reg_num (), 1);
}
+ loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1);
+
+ close_dump_file (DFI_loop, print_rtl, insns);
+ timevar_pop (TV_LOOP);
if (ggc_p)
ggc_collect ();
}
- /* ??? Well, nearly. If HAVE_conditional_arithmetic, jump_optimize
- has put off all if-conversion until "after CSE". If we put this
- off any longer we may miss out doing if-conversion entirely. */
- cse_not_expected = 1;
-
if (optimize > 0)
{
- if (cse2_dump)
- open_dump_file (".06.cse2", decl_printable_name (decl, 2));
+ timevar_push (TV_CSE2);
+ open_dump_file (DFI_cse2, decl);
if (flag_rerun_cse_after_loop)
{
the second CSE pass to do a better job. Jump_optimize can change
max_reg_num so we must rerun reg_scan afterwards.
??? Rework to not call reg_scan so often. */
- TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- JUMP_AFTER_REGSCAN));
+ timevar_push (TV_JUMP);
+
+ reg_scan (insns, max_reg_num (), 0);
+ jump_optimize (insns, !JUMP_CROSS_JUMP,
+ !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
+
+ timevar_push (TV_IFCVT);
+
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+ if_convert (0);
+
+ timevar_pop(TV_IFCVT);
+
+ timevar_pop (TV_JUMP);
- TIMEVAR (cse2_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (cse2_time, tem = cse_main (insns, max_reg_num (),
- 1, rtl_dump_file));
+ reg_scan (insns, max_reg_num (), 0);
+ tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
+
if (tem)
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ {
+ timevar_push (TV_JUMP);
+ jump_optimize (insns, !JUMP_CROSS_JUMP,
+ !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ timevar_pop (TV_JUMP);
+ }
}
if (flag_thread_jumps)
{
/* This pass of jump threading straightens out code
that was kinked by loop optimization. */
- TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 0));
+ timevar_push (TV_JUMP);
+ reg_scan (insns, max_reg_num (), 0);
+ thread_jumps (insns, max_reg_num (), 0);
+ timevar_pop (TV_JUMP);
}
- /* Dump rtl code after cse, if we are doing that. */
- if (cse2_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".06.cse2", insns);
- }
+ close_dump_file (DFI_cse2, print_rtl, insns);
+ timevar_pop (TV_CSE2);
if (ggc_p)
ggc_collect ();
}
+ cse_not_expected = 1;
+
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
{
- if (branch_prob_dump)
- open_dump_file (".07.bp", decl_printable_name (decl, 2));
+ timevar_push (TV_BRANCH_PROB);
+ open_dump_file (DFI_bp, decl);
- TIMEVAR
- (branch_prob_time,
- {
- branch_prob (insns, rtl_dump_file);
- });
+ branch_prob (insns, rtl_dump_file);
- if (branch_prob_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".07.bp", insns);
- }
+ close_dump_file (DFI_bp, print_rtl, insns);
+ timevar_pop (TV_BRANCH_PROB);
if (ggc_p)
ggc_collect ();
}
- /* Now we choose between stupid (pcc-like) register allocation
- (if we got the -noreg switch and not -opt)
- and smart register allocation. */
-
- if (optimize > 0) /* Stupid allocation probably won't work */
- obey_regdecls = 0; /* if optimizations being done. */
-
regclass_init ();
/* Print function header into flow dump now
because doing the flow analysis makes some of the dump. */
- if (flow_dump)
- open_dump_file (".08.flow", decl_printable_name (decl, 2));
+ open_dump_file (DFI_flow, decl);
- if (obey_regdecls)
- {
- TIMEVAR (flow_time,
- {
- regclass (insns, max_reg_num (), NULL);
- stupid_life_analysis (insns, max_reg_num (),
- rtl_dump_file);
- });
- }
- else
+ /* Do control and data flow analysis; wrote some of the results to
+ the dump file. */
+
+ timevar_push (TV_FLOW);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+ if (optimize)
{
- /* Do control and data flow analysis,
- and write some of the results to dump file. */
+ struct loops loops;
- TIMEVAR
- (flow_time,
- {
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
- calculate_loop_depth (rtl_dump_file);
- life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
- });
+ /* Discover and record the loop depth at the head of each basic
+ block. The loop infrastructure does the real job for us. */
+ flow_loops_find (&loops);
- if (warn_uninitialized || extra_warnings)
- {
- uninitialized_vars_warning (DECL_INITIAL (decl));
- if (extra_warnings)
- setjmp_args_warning ();
- }
- }
+ /* Estimate using heuristics if no profiling info is available. */
+ if (! flag_branch_probabilities)
+ estimate_probability (&loops);
- /* Dump rtl after flow analysis. */
+ if (rtl_dump_file)
+ flow_loops_dump (&loops, rtl_dump_file, 0);
+
+ flow_loops_free (&loops);
+ }
+ life_analysis (insns, rtl_dump_file, PROP_FINAL);
+ mark_constant_function ();
+ timevar_pop (TV_FLOW);
- if (flow_dump)
+ if (warn_uninitialized || extra_warnings)
{
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".08.flow", insns);
+ uninitialized_vars_warning (DECL_INITIAL (decl));
+ if (extra_warnings)
+ setjmp_args_warning ();
}
+ close_dump_file (DFI_flow, print_rtl_with_bb, insns);
+
if (ggc_p)
ggc_collect ();
- /* The first life analysis pass has finished. From now on we can not
- generate any new pseudos. */
- no_new_pseudos = 1;
-
/* If -opt, try combining insns through substitution. */
if (optimize > 0)
{
- TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ()));
+ int rebuild_jump_labels_after_combine = 0;
- /* Dump rtl code after insn combination. */
+ timevar_push (TV_COMBINE);
+ open_dump_file (DFI_combine, decl);
- if (combine_dump)
+ rebuild_jump_labels_after_combine
+ = combine_instructions (insns, max_reg_num ());
+
+ /* Combining insns may have turned an indirect jump into a
+ direct jump. Rebuid the JUMP_LABEL fields of jumping
+ instructions. */
+ if (rebuild_jump_labels_after_combine)
{
- dump_rtl (".09.combine", decl, print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".09.combine", insns);
+ timevar_push (TV_JUMP);
+ rebuild_jump_labels (insns);
+ timevar_pop (TV_JUMP);
+
+ timevar_push (TV_FLOW);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+
+ /* Blimey. We've got to have the CFG up to date for the call to
+ if_convert below. However, the random deletion of blocks
+ without updating life info can wind up with Wierd Stuff in
+ global_live_at_end. We then run sched1, which updates things
+ properly, discovers the wierdness and aborts. */
+ update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_DEATH_NOTES);
+
+ timevar_pop (TV_FLOW);
}
+ close_dump_file (DFI_combine, print_rtl_with_bb, insns);
+ timevar_pop (TV_COMBINE);
+
if (ggc_p)
ggc_collect ();
}
+ /* Rerun if-conversion, as combine may have simplified things enough to
+ now meet sequence length restrictions. */
+ if (optimize > 0)
+ {
+ timevar_push (TV_IFCVT);
+ open_dump_file (DFI_ce, decl);
+
+ if_convert (1);
+
+ close_dump_file (DFI_ce, print_rtl_with_bb, insns);
+ timevar_pop (TV_IFCVT);
+ }
+
/* Register allocation pre-pass, to reduce number of moves
necessary for two-address machines. */
if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
{
- if (regmove_dump)
- open_dump_file (".10.regmove", decl_printable_name (decl, 2));
+ timevar_push (TV_REGMOVE);
+ open_dump_file (DFI_regmove, decl);
- TIMEVAR (regmove_time, regmove_optimize (insns, max_reg_num (),
- rtl_dump_file));
+ regmove_optimize (insns, max_reg_num (), rtl_dump_file);
- if (regmove_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".10.regmove", insns);
- }
+ close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
+ timevar_pop (TV_REGMOVE);
if (ggc_p)
ggc_collect ();
}
- /* Print function header into sched dump now
- because doing the sched analysis makes some of the dump. */
+ if (optimize && n_basic_blocks)
+ {
+ timevar_push (TV_GCSE);
+ optimize_mode_switching (NULL_PTR);
+ timevar_pop (TV_GCSE);
+ }
#ifdef INSN_SCHEDULING
+
+ /* Print function header into sched dump now
+ because doing the sched analysis makes some of the dump. */
if (optimize > 0 && flag_schedule_insns)
{
- if (sched_dump)
- open_dump_file (".11.sched", decl_printable_name (decl, 2));
+ timevar_push (TV_SCHED);
+ open_dump_file (DFI_sched, decl);
/* Do control and data sched analysis,
and write some of the results to dump file. */
- TIMEVAR (sched_time, schedule_insns (rtl_dump_file));
-
- /* Dump rtl after instruction scheduling. */
+ schedule_insns (rtl_dump_file);
- if (sched_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".11.sched", insns);
- }
+ close_dump_file (DFI_sched, print_rtl_with_bb, insns);
+ timevar_pop (TV_SCHED);
if (ggc_p)
ggc_collect ();
+
+ /* Register lifetime information is up to date. From now on
+ we can not generate any new pseudos. */
+ no_new_pseudos = 1;
}
#endif
epilogue thus changing register elimination offsets. */
current_function_is_leaf = leaf_function_p ();
- if (local_reg_dump)
- open_dump_file (".12.lreg", decl_printable_name (decl, 2));
+ timevar_push (TV_LOCAL_ALLOC);
+ open_dump_file (DFI_lreg, decl);
- /* Unless we did stupid register allocation,
- allocate pseudo-regs that are used only within 1 basic block.
+ /* Allocate pseudo-regs that are used only within 1 basic block.
RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
jump optimizer after register allocation and reloading are finished. */
- if (!obey_regdecls)
- TIMEVAR (local_alloc_time,
- {
- /* We recomputed reg usage as part of updating the rest
- of life info during sched. */
- if (! flag_schedule_insns)
- recompute_reg_usage (insns, ! optimize_size);
- regclass (insns, max_reg_num (), rtl_dump_file);
- rebuild_label_notes_after_reload = local_alloc ();
- });
- else
- rebuild_label_notes_after_reload = 0;
+ /* We recomputed reg usage as part of updating the rest
+ of life info during sched. */
+ if (! flag_schedule_insns)
+ {
+ recompute_reg_usage (insns, ! optimize_size);
+
+ /* Register lifetime information is up to date. From now on
+ we can not generate any new pseudos. */
+ no_new_pseudos = 1;
+ }
+ regclass (insns, max_reg_num (), rtl_dump_file);
+ rebuild_label_notes_after_reload = local_alloc ();
- /* Dump rtl code after allocating regs within basic blocks. */
+ timevar_pop (TV_LOCAL_ALLOC);
- if (local_reg_dump)
+ if (dump_file[DFI_lreg].enabled)
{
- TIMEVAR (dump_time, dump_flow_info (rtl_dump_file));
- TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
+ timevar_push (TV_DUMP);
+
+ dump_flow_info (rtl_dump_file);
+ dump_local_alloc (rtl_dump_file);
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".12.lreg", insns);
+ close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
}
if (ggc_p)
ggc_collect ();
- if (global_reg_dump)
- open_dump_file (".13.greg", decl_printable_name (decl, 2));
+ timevar_push (TV_GLOBAL_ALLOC);
+ open_dump_file (DFI_greg, decl);
- /* Unless we did stupid register allocation,
- allocate remaining pseudo-regs, then do the reload pass
- fixing up any insns that are invalid. */
+ /* If optimizing, allocate remaining pseudo-regs. Do the reload
+ pass fixing up any insns that are invalid. */
- TIMEVAR (global_alloc_time,
- {
- if (!obey_regdecls)
- failure = global_alloc (rtl_dump_file);
- else
- failure = reload (insns, 0, rtl_dump_file);
- });
+ if (optimize)
+ failure = global_alloc (rtl_dump_file);
+ else
+ {
+ build_insn_chain (insns);
+ failure = reload (insns, 0, rtl_dump_file);
+ }
+ timevar_pop (TV_GLOBAL_ALLOC);
if (failure)
goto exit_rest_of_compilation;
/* Do a very simple CSE pass over just the hard registers. */
if (optimize > 0)
- reload_cse_regs (insns);
+ {
+ timevar_push (TV_RELOAD_CSE_REGS);
+ reload_cse_regs (insns);
+ timevar_pop (TV_RELOAD_CSE_REGS);
+ }
+
+ /* If optimizing, then go ahead and split insns now since we are about
+ to recompute flow information anyway. */
+ if (optimize > 0)
+ split_all_insns (0);
/* Register allocation and reloading may have turned an indirect jump into
a direct jump. If so, we must rebuild the JUMP_LABEL fields of
jumping instructions. */
if (rebuild_label_notes_after_reload)
- TIMEVAR (jump_time, rebuild_jump_labels (insns));
+ {
+ timevar_push (TV_JUMP);
- /* On some machines, the prologue and epilogue code, or parts thereof,
- can be represented as RTL. Doing so lets us schedule insns between
- it and the rest of the code and also allows delayed branch
- scheduling to operate in the epilogue. */
+ rebuild_jump_labels (insns);
- thread_prologue_and_epilogue_insns (insns);
+ timevar_pop (TV_JUMP);
+ }
- /* If optimizing and we are performing instruction scheduling after
- reload, then go ahead and split insns now since we are about to
- recompute flow information anyway.
+ if (dump_file[DFI_greg].enabled)
+ {
+ timevar_push (TV_DUMP);
- reload_cse_regs may expose more splitting opportunities, expecially
- for double-word operations. */
- if (optimize > 0 && flag_schedule_insns_after_reload)
- split_all_insns (0);
+ dump_global_regs (rtl_dump_file);
- if (global_reg_dump)
- {
- TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".13.greg", insns);
+ close_dump_file (DFI_greg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
}
/* Re-create the death notes which were deleted during reload. */
- if (flow2_dump)
- open_dump_file (".14.flow2", decl_printable_name (decl, 2));
-
+ timevar_push (TV_FLOW2);
+ open_dump_file (DFI_flow2, decl);
+
+ jump_optimize_minimal (insns);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+ /* On some machines, the prologue and epilogue code, or parts thereof,
+ can be represented as RTL. Doing so lets us schedule insns between
+ it and the rest of the code and also allows delayed branch
+ scheduling to operate in the epilogue. */
+ thread_prologue_and_epilogue_insns (insns);
+
if (optimize)
{
- TIMEVAR
- (flow2_time,
- {
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
- life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
- });
+ cleanup_cfg (insns);
+ life_analysis (insns, rtl_dump_file, PROP_FINAL);
+
+ /* This is kind of heruistics. We need to run combine_stack_adjustments
+ even for machines with possibly nonzero RETURN_POPS_ARGS
+ and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having
+ push instructions will have popping returns. */
+#ifndef PUSH_ROUNDING
+ if (!ACCUMULATE_OUTGOING_ARGS)
+#endif
+ combine_stack_adjustments ();
if (ggc_p)
ggc_collect ();
flow2_completed = 1;
- if (flow2_dump)
+ close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
+ timevar_pop (TV_FLOW2);
+
+ if (optimize > 0)
{
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".14.flow2", insns);
+ timevar_push (TV_IFCVT2);
+ open_dump_file (DFI_ce2, decl);
+
+ if_convert (1);
+
+ close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
+ timevar_pop (TV_IFCVT2);
}
#ifdef HAVE_peephole2
if (optimize > 0 && flag_peephole2)
{
- if (peephole2_dump)
- open_dump_file (".15.peephole2", decl_printable_name (decl, 2));
+ timevar_push (TV_PEEPHOLE2);
+ open_dump_file (DFI_peephole2, decl);
- TIMEVAR (peephole2_time, peephole2_optimize (rtl_dump_file));
+ peephole2_optimize (rtl_dump_file);
- if (peephole2_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".15.peephole2", insns);
- }
+ close_dump_file (DFI_peephole2, print_rtl_with_bb, insns);
+ timevar_pop (TV_PEEPHOLE2);
}
#endif
#ifdef INSN_SCHEDULING
if (optimize > 0 && flag_schedule_insns_after_reload)
{
- if (sched2_dump)
- open_dump_file (".16.sched2", decl_printable_name (decl, 2));
+ timevar_push (TV_SCHED2);
+ open_dump_file (DFI_sched2, decl);
/* Do control and data sched analysis again,
and write some more of the results to dump file. */
- TIMEVAR (sched2_time, schedule_insns (rtl_dump_file));
-
- /* Dump rtl after post-reorder instruction scheduling. */
+ schedule_insns (rtl_dump_file);
- if (sched2_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".16.sched2", insns);
- }
+ close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
+ timevar_pop (TV_SCHED2);
if (ggc_p)
ggc_collect ();
= optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
#endif
- /* One more attempt to remove jumps to .+1
- left by dead-store-elimination.
- Also do cross-jumping this time
- and delete no-op move insns. */
+ if (optimize > 0 && flag_reorder_blocks)
+ {
+ timevar_push (TV_REORDER_BLOCKS);
+ open_dump_file (DFI_bbro, decl);
+
+ reorder_basic_blocks ();
+
+ close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
+ timevar_pop (TV_REORDER_BLOCKS);
+ }
+
+ if (optimize > 0 && flag_rename_registers)
+ {
+ timevar_push (TV_RENAME_REGISTERS);
+ open_dump_file (DFI_rnreg, decl);
+
+ regrename_optimize ();
+
+ close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
+ timevar_pop (TV_RENAME_REGISTERS);
+ }
+
+ /* One more attempt to remove jumps to .+1 left by dead-store elimination.
+ Also do cross-jumping this time and delete no-op move insns. */
if (optimize > 0)
{
- TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP,
- JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ timevar_push (TV_JUMP);
+ open_dump_file (DFI_jump2, decl);
- /* Dump rtl code after jump, if we are doing that. */
+ jump_optimize (insns, JUMP_CROSS_JUMP, JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN);
- if (jump2_opt_dump)
- {
- dump_rtl (".17.jump2", decl, print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".17.jump2", insns);
- }
+ /* CFG no longer kept up to date. */
+
+ close_dump_file (DFI_jump2, print_rtl_with_bb, insns);
+ timevar_pop (TV_JUMP);
}
/* If a machine dependent reorganization is needed, call it. */
#ifdef MACHINE_DEPENDENT_REORG
- if (mach_dep_reorg_dump)
- open_dump_file (".18.mach", decl_printable_name (decl, 2));
+ open_dump_file (DFI_mach, decl);
- MACHINE_DEPENDENT_REORG (insns);
+ MACHINE_DEPENDENT_REORG (insns);
- if (mach_dep_reorg_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".18.mach", insns);
- }
+ close_dump_file (DFI_mach, print_rtl_with_bb, insns);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
#endif
/* If a scheduling pass for delayed branches is to be done,
#ifdef DELAY_SLOTS
if (optimize > 0 && flag_delayed_branch)
{
- if (dbr_sched_dump)
- open_dump_file (".19.dbr", decl_printable_name (decl, 2));
+ timevar_push (TV_DBR_SCHED);
+ open_dump_file (DFI_dbr, decl);
- TIMEVAR
- (dbr_sched_time,
- {
- dbr_schedule (insns, rtl_dump_file);
- });
+ dbr_schedule (insns, rtl_dump_file);
- if (dbr_sched_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".19.dbr", insns);
- }
- }
+ close_dump_file (DFI_dbr, print_rtl_with_bb, insns);
+ timevar_pop (TV_DBR_SCHED);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
+ }
#endif
/* Shorten branches.
Note this must run before reg-stack because of death note (ab)use
in the ia32 backend. */
- TIMEVAR (shorten_branch_time,
- {
- shorten_branches (get_insns ());
- });
+ timevar_push (TV_SHORTEN_BRANCH);
+ shorten_branches (get_insns ());
+ timevar_pop (TV_SHORTEN_BRANCH);
#ifdef STACK_REGS
- if (stack_reg_dump)
- open_dump_file (".20.stack", decl_printable_name (decl, 2));
+ timevar_push (TV_REG_STACK);
+ open_dump_file (DFI_stack, decl);
- TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file));
+ reg_to_stack (insns, rtl_dump_file);
- if (stack_reg_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".20.stack", insns);
- }
+ close_dump_file (DFI_stack, print_rtl_with_bb, insns);
+ timevar_pop (TV_REG_STACK);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
#endif
+ current_function_nothrow = nothrow_function_p ();
+ if (current_function_nothrow)
+ /* Now we know that this can't throw; set the flag for the benefit
+ of other functions later in this translation unit. */
+ TREE_NOTHROW (current_function_decl) = 1;
+
/* Now turn the rtl into assembler code. */
- TIMEVAR (final_time,
- {
- rtx x;
- char *fnname;
+ timevar_push (TV_FINAL);
+ {
+ rtx x;
+ const char *fnname;
- /* Get the function's name, as described by its RTL.
+ /* Get the function's name, as described by its RTL.
This may be different from the DECL_NAME name used
in the source file. */
- x = DECL_RTL (decl);
- if (GET_CODE (x) != MEM)
- abort ();
- x = XEXP (x, 0);
- if (GET_CODE (x) != SYMBOL_REF)
- abort ();
- fnname = XSTR (x, 0);
-
- assemble_start_function (decl, fnname);
- final_start_function (insns, asm_out_file, optimize);
- final (insns, asm_out_file, optimize, 0);
- final_end_function (insns, asm_out_file, optimize);
- assemble_end_function (decl, fnname);
- if (! quiet_flag)
- fflush (asm_out_file);
+ x = DECL_RTL (decl);
+ if (GET_CODE (x) != MEM)
+ abort ();
+ x = XEXP (x, 0);
+ if (GET_CODE (x) != SYMBOL_REF)
+ abort ();
+ fnname = XSTR (x, 0);
+
+ assemble_start_function (decl, fnname);
+ final_start_function (insns, asm_out_file, optimize);
+ final (insns, asm_out_file, optimize, 0);
+ final_end_function (insns, asm_out_file, optimize);
+ assemble_end_function (decl, fnname);
+ if (! quiet_flag)
+ fflush (asm_out_file);
/* Release all memory allocated by flow. */
- free_basic_block_vars (0);
+ free_basic_block_vars (0);
- /* Release all memory held by regsets now */
- regset_release_memory ();
- });
+ /* Release all memory held by regsets now */
+ regset_release_memory ();
+ }
+ timevar_pop (TV_FINAL);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
/* Write DBX symbols if requested */
for those inline functions that need to have out-of-line copies
generated. During that call, we *will* be routed past here. */
+ timevar_push (TV_SYMOUT);
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
- TIMEVAR (symout_time, dbxout_function (decl));
+ dbxout_function (decl);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
- TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0));
+ dwarfout_file_scope_decl (decl, 0);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
- TIMEVAR (symout_time, dwarf2out_decl (decl));
+ dwarf2out_decl (decl);
#endif
+ timevar_pop (TV_SYMOUT);
exit_rest_of_compilation:
flow2_completed = 0;
no_new_pseudos = 0;
- TIMEVAR (final_time,
- {
- /* Clear out the insn_length contents now that they are no
- longer valid. */
- init_insn_lengths ();
+ timevar_push (TV_FINAL);
+
+ /* Clear out the insn_length contents now that they are no
+ longer valid. */
+ init_insn_lengths ();
- /* Clear out the real_constant_chain before some of the rtx's
+ /* Clear out the real_constant_chain before some of the rtx's
it runs through become garbage. */
- clear_const_double_mem ();
+ clear_const_double_mem ();
- /* Cancel the effect of rtl_in_current_obstack. */
- resume_temporary_allocation ();
+ /* Cancel the effect of rtl_in_current_obstack. */
+ resume_temporary_allocation ();
- /* Show no temporary slots allocated. */
- init_temp_slots ();
+ /* Show no temporary slots allocated. */
+ init_temp_slots ();
- free_basic_block_vars (0);
- });
+ free_basic_block_vars (0);
+
+ timevar_pop (TV_FINAL);
/* Make sure volatile mem refs aren't considered valid operands for
arithmetic insns. We must call this here if this is a nested inline
if (ggc_p)
ggc_collect ();
- /* The parsing time is all the time spent in yyparse
- *except* what is spent in this function. */
-
- parse_time -= get_run_time () - start_time;
+ timevar_pop (TV_REST_OF_COMPILATION);
}
\f
static void
printf (" -d[letters] Enable dumps from specific passes of the compiler\n");
printf (" -dumpbase <file> Base name to be used for dumps from specific passes\n");
#if defined INSN_SCHEDULING
- printf (" -sched-verbose=<number> Set the verbosity level of the scheduler\n");
+ printf (" -fsched-verbose=<number> Set the verbosity level of the scheduler\n");
#endif
printf (" --help Display this information\n");
decode_d_option (arg)
const char * arg;
{
- while (* arg)
- switch (* arg ++)
+ int i, c, matched;
+
+ while (*arg)
+ switch (c = *arg++)
{
case 'a':
- branch_prob_dump = 1;
- combine_dump = 1;
-#ifdef DELAY_SLOTS
- dbr_sched_dump = 1;
-#endif
- flow_dump = 1;
- flow2_dump = 1;
- global_reg_dump = 1;
- jump_opt_dump = 1;
- addressof_dump = 1;
- jump2_opt_dump = 1;
- local_reg_dump = 1;
- loop_dump = 1;
- regmove_dump = 1;
- rtl_dump = 1;
- cse_dump = 1;
- cse2_dump = 1;
- gcse_dump = 1;
- sched_dump = 1;
- sched2_dump = 1;
-#ifdef STACK_REGS
- stack_reg_dump = 1;
-#endif
-#ifdef MACHINE_DEPENDENT_REORG
- mach_dep_reorg_dump = 1;
-#endif
- peephole2_dump = 1;
+ for (i = 0; i < DFI_MAX; ++i)
+ dump_file[i].enabled = 1;
break;
case 'A':
flag_debug_asm = 1;
break;
- case 'b':
- branch_prob_dump = 1;
- break;
- case 'c':
- combine_dump = 1;
- break;
-#ifdef DELAY_SLOTS
- case 'd':
- dbr_sched_dump = 1;
- break;
-#endif
- case 'f':
- flow_dump = 1;
- break;
- case 'F':
- addressof_dump = 1;
- break;
- case 'g':
- global_reg_dump = 1;
- break;
- case 'G':
- gcse_dump = 1;
- break;
- case 'j':
- jump_opt_dump = 1;
- break;
- case 'J':
- jump2_opt_dump = 1;
- break;
-#ifdef STACK_REGS
- case 'k':
- stack_reg_dump = 1;
- break;
-#endif
- case 'l':
- local_reg_dump = 1;
- break;
- case 'L':
- loop_dump = 1;
- break;
case 'm':
flag_print_mem = 1;
break;
-#ifdef MACHINE_DEPENDENT_REORG
- case 'M':
- mach_dep_reorg_dump = 1;
- break;
-#endif
case 'p':
flag_print_asm_name = 1;
break;
- case 'r':
- rtl_dump = 1;
- break;
- case 'R':
- sched2_dump = 1;
- break;
- case 's':
- cse_dump = 1;
- break;
- case 'S':
- sched_dump = 1;
- break;
- case 't':
- cse2_dump = 1;
- break;
- case 'N':
- regmove_dump = 1;
- break;
case 'v':
graph_dump_format = vcg;
break;
- case 'w':
- flow2_dump = 1;
- break;
case 'x':
rtl_dump_and_exit = 1;
break;
case 'y':
set_yydebug (1);
break;
- case 'z':
- peephole2_dump = 1;
- break;
case 'D': /* These are handled by the preprocessor. */
case 'I':
break;
+
default:
- warning ("unrecognised gcc debugging option: %c", arg[-1]);
+ matched = 0;
+ for (i = 0; i < DFI_MAX; ++i)
+ if (c == dump_file[i].debug_switch)
+ {
+ dump_file[i].enabled = 1;
+ matched = 1;
+ }
+
+ if (! matched)
+ warning ("unrecognized gcc debugging option: %c", c);
break;
}
}
else if (!strncmp (arg, "align-loops=", 12))
align_loops = read_integral_parameter (arg + 12, arg - 2, align_loops);
else if (!strncmp (arg, "align-functions=", 16))
- align_functions =
- read_integral_parameter (arg + 16, arg - 2, align_functions);
+ align_functions
+ = read_integral_parameter (arg + 16, arg - 2, align_functions);
else if (!strncmp (arg, "align-jumps=", 12))
align_jumps = read_integral_parameter (arg + 12, arg - 2, align_jumps);
else if (!strncmp (arg, "align-labels=", 13))
stack_limit_rtx = NULL_RTX;
else if (!strcmp (arg, "preprocessed"))
/* Recognise this switch but do nothing. This prevents warnings
- about an unrecognised switch if cpplib has not been linked in. */
+ about an unrecognized switch if cpplib has not been linked in. */
;
else
return 0;
/* Parse a -W... comand line switch. ARG is the value after the -W.
It is safe to access 'ARG - 2' to generate the full switch name.
Return the number of strings consumed. */
+
static int
decode_W_option (arg)
const char * arg;
if (!strncmp (arg, "id-clash-", 9))
{
- const int id_clash_val = read_integral_parameter (arg + 9, arg - 2, -1);
+ id_clash_len = read_integral_parameter (arg + 9, arg - 2, -1);
- if (id_clash_val != -1)
- {
- id_clash_len = id_clash_val;
- warn_id_clash = 1;
- }
+ if (id_clash_len != -1)
+ warn_id_clash = 1;
}
else if (!strncmp (arg, "larger-than-", 12))
{
- const int larger_than_val =
- read_integral_parameter (arg + 12, arg - 2, -1);
- if (larger_than_val != -1)
- {
- larger_than_size = larger_than_val;
- warn_larger_than = 1;
- }
+ larger_than_size = read_integral_parameter (arg + 12, arg - 2, -1);
+
+ if (larger_than_size != -1)
+ warn_larger_than = 1;
}
else
return 0;
number of strings that have already been decoded in a language
specific fashion before this function was invoked. */
-static unsigned
+static unsigned int
independent_decode_option (argc, argv, strings_processed)
int argc;
- char ** argv;
- unsigned strings_processed ATTRIBUTE_UNUSED;
+ char **argv;
+ unsigned int strings_processed;
{
- char * arg = argv[0];
+ char *arg = argv[0];
if (arg[0] != '-' || arg[1] == 0)
{
if (* arg == 'Y')
arg ++;
- switch (* arg)
+ switch (*arg)
{
default:
return 0;
return decode_f_option (arg + 1);
case 'g':
- return decode_g_option (arg + 1);
+ if (strings_processed == 0)
+ return decode_g_option (arg + 1);
+ else
+ return strings_processed;
case 'd':
if (!strcmp (arg, "dumpbase"))
Exit code is 35 if can't open files, 34 if fatal error,
33 if had nonfatal errors, else success. */
-extern int main PROTO ((int, char **));
+extern int main PARAMS ((int, char **));
int
main (argc, argv)
ggc_add_root (&input_file_stack, 1, sizeof input_file_stack,
mark_file_stack);
ggc_add_rtx_root (&stack_limit_rtx, 1);
+ ggc_add_tree_root (¤t_function_decl, 1);
+ ggc_add_tree_root (¤t_function_func_begin_label, 1);
/* Perform language-specific options intialization. */
lang_init_options ();
}
}
- obey_regdecls = (optimize == 0);
-
if (optimize >= 1)
{
flag_defer_pop = 1;
if (optimize >= 2)
{
+ flag_optimize_sibling_calls = 1;
flag_cse_follow_jumps = 1;
flag_cse_skip_blocks = 1;
flag_gcse = 1;
/* Perform normal command line switch decoding. */
for (i = 1; i < argc;)
{
- unsigned lang_processed;
- unsigned indep_processed;
+ unsigned int lang_processed;
+ unsigned int indep_processed;
/* Give the language a chance to decode the option for itself. */
lang_processed = lang_decode_option (argc - i, argv + i);
/* Now see if the option also has a language independent meaning.
Some options are both language specific and language independent,
eg --help. It is possible that there might be options that should
- only be decoded in a language independent way if the were not
+ only be decoded in a language independent way if they were not
decoded in a langauge specific way, which is why 'lang_processed'
is passed in. */
indep_processed = independent_decode_option (argc - i, argv + i,
}
}
else
- error ("Unrecognised option `%s'", argv[i]);
+ error ("Unrecognized option `%s'", argv[i]);
i++;
}
dwarf2out_undef (lineno, buffer);
#endif /* DWARF2_DEBUGGING_INFO */
}
+
+/* Returns nonzero if it is appropriate not to emit any debugging
+ information for BLOCK, because it doesn't contain any instructions.
+ This may not be the case for blocks containing nested functions, since
+ we may actually call such a function even though the BLOCK information
+ is messed up. */
+
+int
+debug_ignore_block (block)
+ tree block ATTRIBUTE_UNUSED;
+{
+ /* Never delete the BLOCK for the outermost scope
+ of the function; we can refer to names from
+ that scope even if the block notes are messed up. */
+ if (is_body_block (block))
+ return 0;
+
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ return dwarf2out_ignore_block (block);
+#endif
+
+ return 1;
+}