#include "insn-attr.h"
#include "insn-codes.h"
#include "insn-config.h"
+#include "hard-reg-set.h"
#include "recog.h"
#include "defaults.h"
#include "output.h"
#include "graph.h"
#include "loop.h"
#include "regs.h"
+#include "timevar.h"
#ifndef ACCUMULATE_OUTGOING_ARGS
#define ACCUMULATE_OUTGOING_ARGS 0
#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
#endif
-#ifdef NEED_DECLARATION_ENVIRON
+#if defined (HAVE_DECL_ENVIRON) && !HAVE_DECL_ENVIRON
extern char **environ;
#endif
/* This might or might not be used in ASM_IDENTIFY_LANGUAGE. */
static void output_lang_identify PARAMS ((FILE *)) ATTRIBUTE_UNUSED;
#endif
-static void compile_file PARAMS ((char *));
+static void compile_file PARAMS ((const char *));
static void display_help PARAMS ((void));
static void mark_file_stack PARAMS ((void *));
/* Name of current original source file (what was input to cpp).
This comes from each #-command in the actual input. */
-char *input_filename;
+const char *input_filename;
/* Name of top-level original source file (what was input to cpp).
This comes from the #-command at the beginning of the actual input.
If there isn't any there, then this is the cc1 input file name. */
-char *main_input_filename;
+const char *main_input_filename;
/* Current line number in real source file. */
enum dump_file_index
{
DFI_rtl,
+ DFI_sibling,
DFI_jump,
DFI_cse,
DFI_addressof,
DFI_gcse,
DFI_loop,
DFI_cse2,
+ DFI_cfg,
DFI_bp,
- DFI_flow,
+ DFI_life,
DFI_combine,
+ DFI_ce,
DFI_regmove,
DFI_sched,
DFI_lreg,
DFI_greg,
DFI_flow2,
+ DFI_ce2,
DFI_peephole2,
+ DFI_rnreg,
DFI_sched2,
DFI_bbro,
DFI_jump2,
};
/* Describes all the dump files. Should be kept in order of the
- pass and in sync with dump_file_index above. */
+ 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 },
{ "gcse", 'G', 1, 0, 0 },
{ "loop", 'L', 1, 0, 0 },
{ "cse2", 't', 1, 0, 0 },
+ { "cfg", 'f', 1, 0, 0 },
{ "bp", 'b', 1, 0, 0 },
- { "flow", 'f', 1, 0, 0 },
+ { "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */
{ "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 },
+ { "rnreg", 'n', 1, 0, 0 },
{ "sched2", 'R', 1, 0, 0 },
{ "bbro", 'B', 1, 0, 0 },
{ "jump2", 'J', 1, 0, 0 },
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. */
"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,
int warnings_are_errors = 0;
-/* Nonzero to warn about unused local variables. */
+/* Nonzero to warn about unused variables, functions et.al. */
-int warn_unused;
+int warn_unused_function;
+int warn_unused_label;
+int warn_unused_parameter;
+int warn_unused_variable;
+int warn_unused_value;
+
+void
+set_Wunused (setting)
+ int setting;
+{
+ warn_unused_function = setting;
+ warn_unused_label = setting;
+ /* Unused function parameter warnings are reported when either ``-W
+ -Wunused'' or ``-Wunused-parameter'' is specified. Differentiate
+ -Wunused by setting WARN_UNUSED_PARAMETER to -1 */
+ if (!setting)
+ warn_unused_parameter = 0;
+ else if (!warn_unused_parameter)
+ warn_unused_parameter = -1;
+ warn_unused_variable = setting;
+ warn_unused_value = setting;
+}
/* Nonzero to warn about code which is never reached. */
lang_independent_options W_options[] =
{
- {"unused", &warn_unused, 1, "Warn when a variable is unused" },
+ {"unused-function", &warn_unused_function, 1, "Warn when a function is unused" },
+ {"unused-label", &warn_unused_label, 1, "Warn when a label is unused" },
+ {"unused-parameter", &warn_unused_parameter, 1, "Warn when a function parameter is unused" },
+ {"unused-variable", &warn_unused_variable, 1, "Warn when a variable is unused" },
+ {"unused-value", &warn_unused_value, 1, "Warn when an expression value is unused" },
{"error", &warnings_are_errors, 1, ""},
{"shadow", &warn_shadow, 1, "Warn when one local variable shadows another" },
{"switch", &warn_switch, 1,
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 reorder_blocks_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,
- all_time == 0 ? 0.00 : (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;
/* NA gets INPUT_NAME sans directory names. */
while (na > input_name)
{
- if (na[-1] == '/')
- break;
-#ifdef DIR_SEPARATOR
- if (na[-1] == DIR_SEPARATOR)
- break;
-#endif
+ if (IS_DIR_SEPARATOR (na[-1]))
+ break;
na--;
}
if (! dump_file[index].enabled)
return 0;
- TIMEVAR
- (dump_time,
- {
- if (rtl_dump_file != NULL)
- fclose (rtl_dump_file);
+ timevar_push (TV_DUMP);
+ if (rtl_dump_file != NULL)
+ fclose (rtl_dump_file);
- sprintf (seq, ".%02d.", index);
+ sprintf (seq, ".%02d.", index);
- 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";
+ 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";
- dump_name = concat (dump_base_name, seq,
- dump_file[index].extension, NULL);
+ 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 = fopen (dump_name, open_arg);
+ if (rtl_dump_file == NULL)
+ pfatal_with_name (dump_name);
- free (dump_name);
+ free (dump_name);
- if (decl)
- fprintf (rtl_dump_file, "\n;; Function %s\n\n",
- decl_printable_name (decl, 2));
- });
-
+ if (decl)
+ fprintf (rtl_dump_file, "\n;; Function %s\n\n",
+ decl_printable_name (decl, 2));
+
+ timevar_pop (TV_DUMP);
return 1;
}
if (! rtl_dump_file)
return;
- TIMEVAR
- (dump_time,
- {
- if (insns
- && graph_dump_format != no_graph
- && dump_file[index].graph_dump_p)
- {
- char seq[16];
- char *suffix;
+ timevar_push (TV_DUMP);
+ if (insns
+ && graph_dump_format != no_graph
+ && dump_file[index].graph_dump_p)
+ {
+ char seq[16];
+ char *suffix;
- sprintf (seq, ".%02d.", index);
- suffix = concat (seq, dump_file[index].extension, NULL);
- print_rtl_graph_with_bb (dump_base_name, suffix, insns);
- free (suffix);
- }
+ 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);
+ if (func && insns)
+ func (rtl_dump_file, insns);
- fflush (rtl_dump_file);
- fclose (rtl_dump_file);
+ fflush (rtl_dump_file);
+ fclose (rtl_dump_file);
- rtl_dump_file = NULL;
- });
+ rtl_dump_file = NULL;
+ timevar_pop (TV_DUMP);
}
/* Do any final processing required for the declarations in VEC, of
because many programs have static variables
that exist only to get some text into the object file. */
if (TREE_CODE (decl) == FUNCTION_DECL
- && (warn_unused
+ && (warn_unused_function
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
&& DECL_INITIAL (decl) == 0
&& DECL_EXTERNAL (decl)
/* Warn about static fns or vars defined but not used,
but not about inline functions or static consts
since defining those in header files is normal practice. */
- if (warn_unused
- && ((TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
- || (TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
+ if (((warn_unused_function
+ && TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
+ || (warn_unused_variable
+ && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& ! DECL_EXTERNAL (decl)
&& ! TREE_PUBLIC (decl)
&& ! 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);
}
}
void
push_srcloc (file, line)
- char *file;
+ const char *file;
int line;
{
struct file_stack *fs;
static void
compile_file (name)
- char *name;
+ const 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;
- reorder_blocks_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 ();
#endif
}
- if (ggc_p)
+ if (ggc_p && name != 0)
name = ggc_alloc_string (name, strlen (name));
+
input_filename = name;
/* Put an entry on the input file stack for the main input file. */
/* 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;
/* Now that all possible functions have been output, we can dump
the exception table. */
+#ifndef IA64_UNWIND_INFO
output_exception_table ();
-
+#endif
+ free_exception_table ();
+
check_global_declarations (vec, len);
/* Clean up. */
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 (flag_test_coverage || flag_branch_probabilities)
+ if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
{
+ timevar_push (TV_DUMP);
open_dump_file (DFI_bp, NULL);
-
- TIMEVAR (dump_time, end_branch_prob (rtl_dump_file));
-
+
+ end_branch_prob ();
+
close_dump_file (DFI_bp, NULL, NULL_RTX);
+ timevar_pop (TV_DUMP);
}
#ifdef ASM_FILE_END
if (optimize > 0 && open_dump_file (DFI_combine, NULL))
{
- TIMEVAR (dump_time, dump_combine_total_stats (rtl_dump_file));
+ 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
/* 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 ("bbro", reorder_blocks_time);
- 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
/* 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;
/* 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 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 ();
|| DECL_EXTERNAL (decl))))
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.
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;
}
of other functions later in this translation unit. */
TREE_NOTHROW (current_function_decl) = 1;
- note_deferral_of_defined_inline_function (decl);
- TIMEVAR (integration_time, save_for_inline_nocopy (decl));
+ 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;
}
- /* We may have potential sibling or tail recursion sites. Select one
- (of possibly multiple) methods of performing the call. */
init_EXPR_INSN_LIST_cache ();
- if (flag_optimize_sibling_calls)
- optimize_sibling_and_tail_recursive_calls ();
-
+
if (ggc_p)
ggc_collect ();
/* 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 (current_function_decl, insns);
#ifdef SETJMP_VIA_SAVE_AREA
#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 ();
/* 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 ();
- close_dump_file (DFI_jump, 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);
+
+ if (optimize > 0)
+ {
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
- /* 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 ()));
+ /* ??? 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)
{
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);
+ timevar_pop (TV_CSE);
close_dump_file (DFI_cse, print_rtl, insns);
}
if (ggc_p)
ggc_collect ();
- if (flag_ssa)
+ 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);
- close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
-
- /* Life analysis used in SSA adds log_links but these shouldn't
- be there until the flow stage, so clear them away. */
+ /* 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 ();
}
if (optimize > 0 && flag_gcse)
{
+ 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);
}
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)
{
+ timevar_push (TV_LOOP);
open_dump_file (DFI_loop, decl);
-
- TIMEVAR
- (loop_time,
- {
- if (flag_rerun_loop_opt)
- {
- /* We only want to perform unrolling once. */
-
- loop_optimize (insns, rtl_dump_file, 0, 0);
+
+ 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
+ loop_optimize (insns, rtl_dump_file, 0);
+
+ /* 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);
- });
+ reg_scan (insns, max_reg_num (), 1);
+ }
+ loop_optimize (insns, rtl_dump_file, (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT);
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)
{
+ 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);
}
close_dump_file (DFI_cse2, print_rtl, insns);
+ timevar_pop (TV_CSE2);
if (ggc_p)
ggc_collect ();
}
+ cse_not_expected = 1;
+
+ regclass_init ();
+
+
+ /* Do control and data flow analysis; wrote some of the results to
+ the dump file. */
+
+ timevar_push (TV_FLOW);
+ open_dump_file (DFI_cfg, decl);
+
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+
+ close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
+
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
{
+ timevar_push (TV_BRANCH_PROB);
open_dump_file (DFI_bp, decl);
- TIMEVAR
- (branch_prob_time,
- {
- branch_prob (insns, rtl_dump_file);
- });
+ branch_prob ();
- close_dump_file (DFI_bp, print_rtl, insns);
-
- if (ggc_p)
- ggc_collect ();
+ close_dump_file (DFI_bp, print_rtl_with_bb, insns);
+ timevar_pop (TV_BRANCH_PROB);
}
- regclass_init ();
+ open_dump_file (DFI_life, decl);
+ if (optimize)
+ {
+ struct loops loops;
- /* Print function header into flow dump now
- because doing the flow analysis makes some of the dump. */
+ /* 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);
- open_dump_file (DFI_flow, decl);
-
- /* Do control and data flow analysis; wrote some of the results to
- the dump file. */
+ /* Estimate using heuristics if no profiling info is available. */
+ estimate_probability (&loops);
+
+ if (rtl_dump_file)
+ flow_loops_dump (&loops, rtl_dump_file, 0);
- TIMEVAR
- (flow_time,
- {
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (insns);
- if (optimize)
- calculate_loop_depth (rtl_dump_file);
- life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
- mark_constant_function ();
- });
+ flow_loops_free (&loops);
+ }
+ life_analysis (insns, rtl_dump_file, PROP_FINAL);
+ mark_constant_function ();
+ timevar_pop (TV_FLOW);
if (warn_uninitialized || extra_warnings)
{
setjmp_args_warning ();
}
- close_dump_file (DFI_flow, print_rtl_with_bb, insns);
+ close_dump_file (DFI_life, 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)
{
int rebuild_jump_labels_after_combine = 0;
+ timevar_push (TV_COMBINE);
open_dump_file (DFI_combine, decl);
- TIMEVAR (combine_time,
- {
- rebuild_jump_labels_after_combine
- = combine_instructions (insns, max_reg_num ());
- });
+ 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)
{
- TIMEVAR (jump_time, rebuild_jump_labels (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 | PROP_KILL_DEAD_CODE
+ | PROP_SCAN_DEAD_CODE);
+
+ 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))
{
+ 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);
close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
+ timevar_pop (TV_REGMOVE);
if (ggc_p)
ggc_collect ();
}
- if (optimize && n_basic_blocks)
+#ifdef OPTIMIZE_MODE_SWITCHING
+ if (optimize)
{
- TIMEVAR (gcse_time, optimize_mode_switching (NULL_PTR));
+ timevar_push (TV_GCSE);
+
+ if (optimize_mode_switching (NULL_PTR))
+ {
+ /* We did work, and so had to regenerate global life information.
+ Take advantage of this and don't re-recompute register life
+ information below. */
+ no_new_pseudos = 1;
+ }
+
+ timevar_pop (TV_GCSE);
}
+#endif
#ifdef INSN_SCHEDULING
because doing the sched analysis makes some of the dump. */
if (optimize > 0 && flag_schedule_insns)
{
+ 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));
+ schedule_insns (rtl_dump_file);
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 ();
+ timevar_push (TV_LOCAL_ALLOC);
open_dump_file (DFI_lreg, decl);
/* 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. */
- 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 ();
- });
+ if (! no_new_pseudos)
+ {
+ 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 ();
+
+ timevar_pop (TV_LOCAL_ALLOC);
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 (DFI_lreg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
}
if (ggc_p)
ggc_collect ();
+ timevar_push (TV_GLOBAL_ALLOC);
open_dump_file (DFI_greg, decl);
/* If optimizing, allocate remaining pseudo-regs. Do the reload
pass fixing up any insns that are invalid. */
- TIMEVAR (global_alloc_time,
- {
- if (optimize)
- failure = global_alloc (rtl_dump_file);
- else
- {
- build_insn_chain (insns);
- 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);
-
- /* 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.
+ {
+ timevar_push (TV_RELOAD_CSE_REGS);
+ reload_cse_regs (insns);
+ timevar_pop (TV_RELOAD_CSE_REGS);
+ }
- reload_cse_regs may expose more splitting opportunities, expecially
- for double-word operations. */
- if (optimize > 0 && flag_schedule_insns_after_reload)
+ /* 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);
+
+ rebuild_jump_labels (insns);
+
+ timevar_pop (TV_JUMP);
+ }
if (dump_file[DFI_greg].enabled)
{
- TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
+ timevar_push (TV_DUMP);
+
+ dump_global_regs (rtl_dump_file);
+
close_dump_file (DFI_greg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
}
/* Re-create the death notes which were deleted during reload. */
+ timevar_push (TV_FLOW2);
open_dump_file (DFI_flow2, decl);
-
- TIMEVAR (flow2_time,
- {
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- });
+
+ jump_optimize (insns, !JUMP_CROSS_JUMP,
+ !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ 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
if (optimize)
{
- TIMEVAR (flow2_time,
- {
- cleanup_cfg (insns);
- 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
+ /* This is kind of a heuristic. 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
- TIMEVAR (flow2_time, { combine_stack_adjustments (); });
+ combine_stack_adjustments ();
if (ggc_p)
ggc_collect ();
flow2_completed = 1;
close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
+ timevar_pop (TV_FLOW2);
+
+ if (optimize > 0)
+ {
+ 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)
{
+ timevar_push (TV_PEEPHOLE2);
open_dump_file (DFI_peephole2, decl);
- TIMEVAR (peephole2_time, peephole2_optimize (rtl_dump_file));
+ peephole2_optimize (rtl_dump_file);
close_dump_file (DFI_peephole2, print_rtl_with_bb, insns);
+ timevar_pop (TV_PEEPHOLE2);
}
#endif
+ 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);
+ }
+
#ifdef INSN_SCHEDULING
if (optimize > 0 && flag_schedule_insns_after_reload)
{
+ 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));
+ schedule_insns (rtl_dump_file);
close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
+ timevar_pop (TV_SCHED2);
if (ggc_p)
ggc_collect ();
if (optimize > 0 && flag_reorder_blocks)
{
+ timevar_push (TV_REORDER_BLOCKS);
open_dump_file (DFI_bbro, decl);
- TIMEVAR (reorder_blocks_time, reorder_basic_blocks ());
+ reorder_basic_blocks ();
close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
+ timevar_pop (TV_REORDER_BLOCKS);
}
/* One more attempt to remove jumps to .+1 left by dead-store elimination.
if (optimize > 0)
{
+ timevar_push (TV_JUMP);
open_dump_file (DFI_jump2, decl);
- TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP,
- JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ jump_optimize (insns, JUMP_CROSS_JUMP, JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN);
+
+ /* 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 DELAY_SLOTS
if (optimize > 0 && flag_delayed_branch)
{
+ 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);
close_dump_file (DFI_dbr, print_rtl_with_bb, insns);
+ timevar_pop (TV_DBR_SCHED);
if (ggc_p)
ggc_collect ();
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
+ 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);
close_dump_file (DFI_stack, print_rtl_with_bb, insns);
+ timevar_pop (TV_REG_STACK);
if (ggc_p)
ggc_collect ();
/* Now turn the rtl into assembler code. */
- TIMEVAR (final_time,
- {
- rtx x;
- const char *fnname;
-
- /* 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);
+ timevar_push (TV_FINAL);
+ {
+ rtx x;
+ const char *fnname;
+
+ /* 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);
/* 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 ();
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
W_options[i].string, description);
}
+ printf (" -Wunused Enable unused warnings\n");
printf (" -Wid-clash-<num> Warn if 2 identifiers have the same first <num> chars\n");
printf (" -Wlarger-than-<number> Warn if an object is larger than <number> bytes\n");
printf (" -p Enable function profiling\n");
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");
if (larger_than_size != -1)
warn_larger_than = 1;
}
+ else if (!strcmp (arg, "unused"))
+ {
+ set_Wunused (1);
+ }
+ else if (!strcmp (arg, "no-unused"))
+ {
+ set_Wunused (0);
+ }
else
return 0;
save_argv = argv;
p = argv[0] + strlen (argv[0]);
- while (p != argv[0] && p[-1] != '/'
-#ifdef DIR_SEPARATOR
- && p[-1] != DIR_SEPARATOR
-#endif
- )
+ while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
--p;
progname = p;
#ifdef DWARF2_UNWIND_INFO
exceptions_via_longjmp = ! DWARF2_UNWIND_INFO;
#else
+#ifdef IA64_UNWIND_INFO
+ exceptions_via_longjmp = ! IA64_UNWIND_INFO;
+#else
exceptions_via_longjmp = 1;
#endif
+#endif
}
+ /* Since each function gets its own handler data, we can't support the
+ new model currently, since it depend on a specific rethrow label
+ which is declared at the front of the table, and we can only
+ have one such symbol in a file. */
+#ifdef IA64_UNWIND_INFO
+ flag_new_exceptions = 0;
+#endif
+
/* Set up the align_*_log variables, defaulting them to 1 if they
were still unset. */
if (align_loops <= 0) align_loops = 1;
void
debug_start_source_file (filename)
- register char *filename ATTRIBUTE_UNUSED;
+ register const char *filename ATTRIBUTE_UNUSED;
{
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
#endif /* DWARF2_DEBUGGING_INFO */
}
-/* Tell the debugging backend that we've decided not to emit any
- debugging information for BLOCK, so it can clean up after any local
- classes or nested functions. */
+/* 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. */
-void
+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)
- dwarf2out_ignore_block (block);
+ return dwarf2out_ignore_block (block);
#endif
+
+ return 1;
}