diff options
author | kan <kan@FreeBSD.org> | 2003-07-11 04:48:05 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2003-07-11 04:48:05 +0000 |
commit | 3af246c7f23c2d1ef9c0c5835c056f851436974c (patch) | |
tree | f305190c3b4906aca8e163d7b5ce6389bd2dacdf /contrib | |
parent | 62d33c6b58a463e3e4d6e54a926d415894eb0222 (diff) | |
download | FreeBSD-src-3af246c7f23c2d1ef9c0c5835c056f851436974c.zip FreeBSD-src-3af246c7f23c2d1ef9c0c5835c056f851436974c.tar.gz |
Merge FreeBSD modifications into gcc 3.3.1-prerelease:
1.2 -fformat-extensions.
1.7 FORCE_OPTIMIZATION_DOWNGRADE knob for Alpha.
1.14 -O0 -O1 optimize alignment for time, not size.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/gcc/toplev.c | 1430 |
1 files changed, 797 insertions, 633 deletions
diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c index 8b60d9e..a763eed 100644 --- a/contrib/gcc/toplev.c +++ b/contrib/gcc/toplev.c @@ -1,6 +1,6 @@ /* Top level of GNU C compiler Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -31,7 +31,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #undef FFS /* Some systems define this in param.h. */ #include "system.h" #include <signal.h> -#include <setjmp.h> #ifdef HAVE_SYS_RESOURCE_H # include <sys/resource.h> @@ -69,9 +68,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "reload.h" #include "dwarf2asm.h" #include "integrate.h" +#include "real.h" #include "debug.h" #include "target.h" #include "langhooks.h" +#include "cfglayout.h" #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) #include "dwarf2out.h" @@ -89,10 +90,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "xcoffout.h" /* Needed for external data declarations for e.g. AIX 4.x. */ #endif - -#ifdef HALF_PIC_DEBUG -#include "halfpic.h" -#endif /* Carry information from ASM_DECLARE_OBJECT_NAME to ASM_FINISH_DECLARE_OBJECT. */ @@ -100,21 +97,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA extern int size_directive_output; extern tree last_assemble_variable_decl; +extern void reg_alloc PARAMS ((void)); + static void general_init PARAMS ((char *)); static void parse_options_and_default_flags PARAMS ((int, char **)); static void do_compile PARAMS ((void)); static void process_options PARAMS ((void)); -static void lang_independent_init PARAMS ((void)); +static void backend_init PARAMS ((void)); static int lang_dependent_init PARAMS ((const char *)); static void init_asm_output PARAMS ((const char *)); static void finalize PARAMS ((void)); static void set_target_switch PARAMS ((const char *)); -static const char *decl_name PARAMS ((tree, int)); -static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN; static void crash_signal PARAMS ((int)) ATTRIBUTE_NORETURN; -static void set_float_handler PARAMS ((jmp_buf)); static void compile_file PARAMS ((void)); static void display_help PARAMS ((void)); static void display_target_options PARAMS ((void)); @@ -132,6 +128,9 @@ static int print_single_switch PARAMS ((FILE *, int, int, const char *, static void print_switch_values PARAMS ((FILE *, int, int, const char *, const char *, const char *)); +/* Nonzero to dump debug info whilst parsing (-dy option). */ +static int set_yydebug; + /* Length of line when printing switch values. */ #define MAX_LINE 75 @@ -172,6 +171,10 @@ int input_file_stack_tick; const char *dump_base_name; +/* Name to use as a base for auxiliary output files. */ + +const char *aux_base_name; + /* Format to use to print dumpfile index value */ #ifndef DUMPFILE_FORMAT #define DUMPFILE_FORMAT ".%02d." @@ -183,9 +186,14 @@ const char *dump_base_name; extern int target_flags; +/* A mask of target_flags that includes bit X if X was set or cleared + on the command line. */ + +int target_flags_explicit; + /* Debug hooks - dependent upon command line options. */ -struct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks; +const struct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks; /* Describes a dump file. */ @@ -219,16 +227,19 @@ enum dump_file_index DFI_ssa_ccp, DFI_ssa_dce, DFI_ussa, + DFI_null, DFI_cse, DFI_addressof, DFI_gcse, DFI_loop, - DFI_cse2, DFI_cfg, DFI_bp, + DFI_ce1, + DFI_tracer, + DFI_cse2, DFI_life, DFI_combine, - DFI_ce, + DFI_ce2, DFI_regmove, DFI_sched, DFI_lreg, @@ -237,7 +248,7 @@ enum dump_file_index DFI_flow2, DFI_peephole2, DFI_rnreg, - DFI_ce2, + DFI_ce3, DFI_sched2, DFI_stack, DFI_bbro, @@ -251,7 +262,7 @@ enum dump_file_index Remaining -d letters: - " o q u " + " o q " " H JK OPQ TUV YZ" */ @@ -265,16 +276,19 @@ static struct dump_file_info dump_file[DFI_MAX] = { "ssaccp", 'W', 1, 0, 0 }, { "ssadce", 'X', 1, 0, 0 }, { "ussa", 'e', 1, 0, 0 }, /* Yes, duplicate enable switch. */ + { "null", 'u', 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 }, + { "ce1", 'C', 1, 0, 0 }, + { "tracer", 'T', 1, 0, 0 }, + { "cse2", 't', 1, 0, 0 }, { "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "combine", 'c', 1, 0, 0 }, - { "ce", 'C', 1, 0, 0 }, + { "ce2", 'C', 1, 0, 0 }, { "regmove", 'N', 1, 0, 0 }, { "sched", 'S', 1, 0, 0 }, { "lreg", 'l', 1, 0, 0 }, @@ -283,7 +297,7 @@ static struct dump_file_info dump_file[DFI_MAX] = { "flow2", 'w', 1, 0, 0 }, { "peephole2", 'z', 1, 0, 0 }, { "rnreg", 'n', 1, 0, 0 }, - { "ce2", 'E', 1, 0, 0 }, + { "ce3", 'E', 1, 0, 0 }, { "sched2", 'R', 1, 0, 0 }, { "stack", 'k', 1, 0, 0 }, { "bbro", 'B', 1, 0, 0 }, @@ -336,8 +350,8 @@ int use_gnu_debug_info_extensions = 0; int optimize = 0; /* Nonzero means optimize for size. -Os. - The only valid values are zero and non-zero. When optimize_size is - non-zero, optimize defaults to 2, but certain individual code + The only valid values are zero and nonzero. When optimize_size is + nonzero, optimize defaults to 2, but certain individual code bloating optimizations are disabled. */ int optimize_size = 0; @@ -353,29 +367,6 @@ tree current_function_decl; 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: - 0: DECL_NAME, demangled as necessary. - 1: and scope information. - 2: and any other information that might be interesting, such as function - parameter types in C++. */ - -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) - PARAMS ((union tree_node *, rtx, enum machine_mode, - enum expand_modifier modifier)); - -lang_expand_expr_t lang_expand_expr = 0; - -/* Pointer to function to finish handling an incomplete decl at the - end of compilation. */ - -void (*incomplete_decl_finalize_hook) PARAMS ((tree)) = 0; - /* Nonzero if doing dwarf2 duplicate elimination. */ int flag_eliminate_dwarf2_dups = 0; @@ -400,6 +391,10 @@ int flag_branch_probabilities = 0; int flag_reorder_blocks = 0; +/* Nonzero if functions should be reordered. */ + +int flag_reorder_functions = 0; + /* Nonzero if registers should be renamed. */ int flag_rename_registers = 0; @@ -584,12 +579,24 @@ int flag_errno_math = 1; int flag_unsafe_math_optimizations = 0; +/* Nonzero means that no NaNs or +-Infs are expected. */ + +int flag_finite_math_only = 0; + /* Zero means that floating-point math operations cannot generate a (user-visible) trap. This is the case, for example, in nonstop - IEEE 754 arithmetic. */ + IEEE 754 arithmetic. Trapping conditions include division by zero, + overflow, underflow, invalid and inexact, but does not include + operations on signaling NaNs (see below). */ int flag_trapping_math = 1; +/* Nonzero means disable transformations observable by signaling NaNs. + This option implies that any operation on a IEEE signaling NaN can + generate a (user-visible) trap. */ + +int flag_signaling_nans = 0; + /* 0 means straightforward implementation of complex divide acceptable. 1 means wide ranges of inputs must work for complex divide. 2 means C99-like requirements for complex divide (not yet implemented). */ @@ -616,6 +623,22 @@ int flag_syntax_only = 0; static int flag_gcse; +/* Nonzero means perform loop optimizer. */ + +static int flag_loop_optimize; + +/* Nonzero means perform crossjumping. */ + +static int flag_crossjumping; + +/* Nonzero means perform if conversion. */ + +static int flag_if_conversion; + +/* Nonzero means perform if conversion after reload. */ + +static int flag_if_conversion2; + /* Nonzero means to use global dataflow analysis to eliminate useless null pointer tests. */ @@ -684,12 +707,15 @@ int flag_shared_data; int flag_delayed_branch; /* Nonzero if we are compiling pure (sharable) code. - Value is 1 if we are doing reasonable (i.e. simple - offset into offset table) pic. Value is 2 if we can - only perform register offsets. */ + Value is 1 if we are doing "small" pic; value is 2 if we're doing + "large" pic. */ int flag_pic; +/* Set to the default thread-local storage (tls) model to use. */ + +enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC; + /* Nonzero means generate extra code for exception handling and enable exception handling. */ @@ -708,12 +734,6 @@ int flag_asynchronous_unwind_tables = 0; int flag_no_common; -/* Nonzero means pretend it is OK to examine bits of target floats, - even if that isn't true. The resulting code will have incorrect constants, - but the same series of instructions that the native compiler would make. */ - -int flag_pretend_float; - /* Nonzero means change certain warnings into errors. Usually these are warnings about failure to conform to some standard. */ @@ -785,6 +805,9 @@ int flag_gnu_linker = 0; int flag_gnu_linker = 1; #endif +/* Nonzero means put zero initialized data in the bss section. */ +int flag_zero_initialized_in_bss = 1; + /* Enable SSA. */ int flag_ssa = 0; @@ -842,19 +865,10 @@ int flag_peephole2 = 0; /* This will try to guess branch probabilities. */ int flag_guess_branch_prob = 0; -/* -fbounded-pointers causes gcc to compile pointers as composite - objects occupying three words: the pointer value, the base address - of the referent object, and the address immediately beyond the end - of the referent object. The base and extent allow us to perform - runtime bounds checking. -fbounded-pointers implies -fcheck-bounds. */ -int flag_bounded_pointers = 0; - /* -fcheck-bounds causes gcc to generate array bounds checks. - For C, C++: defaults to value of flag_bounded_pointers. - For ObjC: defaults to off. + For C, C++, ObjC: defaults to off. For Java: defaults to on. - For Fortran: defaults to off. - For CHILL: defaults to off. */ + For Fortran: defaults to off. */ int flag_bounds_check = 0; /* This will attempt to merge constant section constants, if 1 only @@ -867,6 +881,13 @@ int flag_merge_constants = 1; one, unconditionally renumber instruction UIDs. */ int flag_renumber_insns = 1; +/* If nonzero, use the graph coloring register allocator. */ +int flag_new_regalloc = 0; + +/* Nonzero if we perform superblock formation. */ + +int flag_tracer = 0; + /* Values of the -falign-* flags: how much to align labels in code. 0 means `use default', 1 means `don't align'. For each variable, there is an _log variant which is the power @@ -953,11 +974,6 @@ static const param_info lang_independent_params[] = { { NULL, 0, NULL } }; -/* A default for same. */ -#ifndef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "" -#endif - /* Table of language-independent -f options. STRING is the option name. VARIABLE is the address of the variable. ON_VALUE is the value to store in VARIABLE @@ -984,6 +1000,8 @@ static const lang_independent_options f_options[] = N_("When possible do not generate stack frames") }, {"optimize-sibling-calls", &flag_optimize_sibling_calls, 1, N_("Optimize sibling and tail recursive calls") }, + {"tracer", &flag_tracer, 1, + N_("Perform superblock formation via tail duplication") }, {"cse-follow-jumps", &flag_cse_follow_jumps, 1, N_("When running CSE, follow jumps to their targets") }, {"cse-skip-blocks", &flag_cse_skip_blocks, 1, @@ -1040,14 +1058,20 @@ static const lang_independent_options f_options[] = N_("Perform enhanced load motion during global subexpression elimination") }, {"gcse-sm", &flag_gcse_sm, 1, N_("Perform store motion after global subexpression elimination") }, + {"loop-optimize", &flag_loop_optimize, 1, + N_("Perform the loop optimizations") }, + {"crossjumping", &flag_crossjumping, 1, + N_("Perform cross-jumping optimization") }, + {"if-conversion", &flag_if_conversion, 1, + N_("Perform conversion of conditional jumps to branchless equivalents") }, + {"if-conversion2", &flag_if_conversion2, 1, + N_("Perform conversion of conditional jumps to conditional execution") }, {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1, N_("Run CSE pass after loop optimizations") }, {"rerun-loop-opt", &flag_rerun_loop_opt, 1, N_("Run the loop optimizer twice") }, {"delete-null-pointer-checks", &flag_delete_null_pointer_checks, 1, N_("Delete useless null pointer checks") }, - {"pretend-float", &flag_pretend_float, 1, - N_("Pretend that host and target use the same FP format") }, {"schedule-insns", &flag_schedule_insns, 1, N_("Reschedule instructions before register allocation") }, {"schedule-insns2", &flag_schedule_insns_after_reload, 1, @@ -1079,8 +1103,12 @@ static const lang_independent_options f_options[] = N_("Create data files needed by gcov") }, {"branch-probabilities", &flag_branch_probabilities, 1, N_("Use profiling information for branch probabilities") }, + {"profile", &profile_flag, 1, + N_("Enable basic program profiling code") }, {"reorder-blocks", &flag_reorder_blocks, 1, N_("Reorder basic blocks to improve code placement") }, + {"reorder-functions", &flag_reorder_functions, 1, + N_("Reorder functions to improve code placement") }, {"rename-registers", &flag_rename_registers, 1, N_("Do the register renaming optimization pass") }, {"cprop-registers", &flag_cprop_registers, 1, @@ -1094,7 +1122,7 @@ static const lang_independent_options f_options[] = {"data-sections", &flag_data_sections, 1, N_("place data items into their own section") }, {"verbose-asm", &flag_verbose_asm, 1, - N_("Add extra commentry to assembler output") }, + N_("Add extra commentary to assembler output") }, {"gnu-linker", &flag_gnu_linker, 1, N_("Output GNU ld formatted global initializers") }, {"regmove", &flag_regmove, 1, @@ -1122,13 +1150,15 @@ static const lang_independent_options f_options[] = {"align-functions", &align_functions, 0, N_("Align the start of functions") }, {"merge-constants", &flag_merge_constants, 1, - N_("Attempt to merge identical constants accross compilation units") }, + N_("Attempt to merge identical constants across compilation units") }, {"merge-all-constants", &flag_merge_constants, 2, N_("Attempt to merge identical constants and constant variables") }, {"dump-unnumbered", &flag_dump_unnumbered, 1, N_("Suppress output of instruction numbers and line number notes in debugging dumps") }, {"instrument-functions", &flag_instrument_function_entry_exit, 1, N_("Instrument function entry/exit with profiling calls") }, + {"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1, + N_("Put zero initialized data in the bss section") }, {"ssa", &flag_ssa, 1, N_("Enable SSA optimizations") }, {"ssa-ccp", &flag_ssa_ccp, 1, @@ -1141,6 +1171,8 @@ static const lang_independent_options f_options[] = N_("Process #ident directives") }, { "peephole2", &flag_peephole2, 1, N_("Enables an rtl peephole pass run before sched2") }, + {"finite-math-only", &flag_finite_math_only, 1, + N_("Assume no NaNs or +-Infs are generated") }, { "guess-branch-probability", &flag_guess_branch_prob, 1, N_("Enables guessing of branch probabilities") }, {"math-errno", &flag_errno_math, 1, @@ -1149,10 +1181,10 @@ static const lang_independent_options f_options[] = N_("Floating-point operations can trap") }, {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1, N_("Allow math optimizations that may violate IEEE or ANSI standards") }, - {"bounded-pointers", &flag_bounded_pointers, 1, - N_("Compile pointers as triples: value, base & end") }, + {"signaling-nans", &flag_signaling_nans, 1, + N_("Disable optimizations observable by IEEE signaling NaNs") }, {"bounds-check", &flag_bounds_check, 1, - N_("Generate code to check bounds before dereferencing pointers and arrays") }, + N_("Generate code to check bounds before indexing arrays") }, {"single-precision-constant", &flag_single_precision_constant, 1, N_("Convert floating point constant to single precision constant") }, {"time-report", &time_report, 1, @@ -1161,6 +1193,8 @@ static const lang_independent_options f_options[] = N_("Report on permanent memory allocation at end of run") }, { "trapv", &flag_trapv, 1, N_("Trap for signed overflow in addition / subtraction / multiplication") }, + { "new-ra", &flag_new_regalloc, 1, + N_("Use graph coloring register allocation.") }, }; /* Table of language-specific options. */ @@ -1176,11 +1210,9 @@ documented_lang_options[] = used here is to only describe those options which are not enabled by default. */ - { "-ansi", - N_("Compile just for ISO C89") }, - { "-fallow-single-precision", - N_("Do not promote floats to double if using -traditional") }, - { "-std= ", + { "-ansi", + N_("Compile just for ISO C90") }, + { "-std= ", N_("Determine language standard") }, { "-fsigned-bitfields", "" }, @@ -1188,104 +1220,103 @@ documented_lang_options[] = N_("Make bit-fields by unsigned by default") }, { "-fno-signed-bitfields", "" }, { "-fno-unsigned-bitfields","" }, - { "-fsigned-char", + { "-fsigned-char", N_("Make 'char' be signed by default") }, - { "-funsigned-char", + { "-funsigned-char", N_("Make 'char' be unsigned by default") }, { "-fno-signed-char", "" }, { "-fno-unsigned-char", "" }, - { "-ftraditional", "" }, - { "-traditional", - N_("Attempt to support traditional K&R style C") }, - { "-fnotraditional", "" }, - { "-fno-traditional", "" }, - { "-fasm", "" }, - { "-fno-asm", + { "-fno-asm", N_("Do not recognize the 'asm' keyword") }, { "-fbuiltin", "" }, - { "-fno-builtin", + { "-fno-builtin", N_("Do not recognize any built in functions") }, - { "-fhosted", + { "-fhosted", N_("Assume normal C execution environment") }, { "-fno-hosted", "" }, { "-ffreestanding", N_("Assume that standard libraries & main might not exist") }, { "-fno-freestanding", "" }, - { "-fcond-mismatch", + { "-fcond-mismatch", N_("Allow different types as args of ? operator") }, { "-fno-cond-mismatch", "" }, - { "-fdollars-in-identifiers", + { "-fdollars-in-identifiers", N_("Allow the use of $ inside identifiers") }, { "-fno-dollars-in-identifiers", "" }, { "-fpreprocessed", "" }, { "-fno-preprocessed", "" }, - { "-fshort-double", + { "-fshort-double", N_("Use the same size for double as for float") }, { "-fno-short-double", "" }, - { "-fshort-enums", + { "-fshort-enums", N_("Use the smallest fitting integer to hold enums") }, { "-fno-short-enums", "" }, - { "-fshort-wchar", + { "-fshort-wchar", N_("Override the underlying type for wchar_t to `unsigned short'") }, { "-fno-short-wchar", "" }, - { "-Wall", + { "-Wall", N_("Enable most warning messages") }, { "-Wbad-function-cast", N_("Warn about casting functions to incompatible types") }, { "-Wno-bad-function-cast", "" }, - { "-Wno-missing-noreturn", "" }, { "-Wmissing-format-attribute", N_("Warn about functions which might be candidates for format attributes") }, { "-Wno-missing-format-attribute", "" }, - { "-Wcast-qual", + { "-Wcast-qual", N_("Warn about casts which discard qualifiers") }, { "-Wno-cast-qual", "" }, - { "-Wchar-subscripts", + { "-Wchar-subscripts", N_("Warn about subscripts whose type is 'char'") }, { "-Wno-char-subscripts", "" }, - { "-Wcomment", + { "-Wcomment", N_("Warn if nested comments are detected") }, { "-Wno-comment", "" }, - { "-Wcomments", + { "-Wcomments", N_("Warn if nested comments are detected") }, { "-Wno-comments", "" }, - { "-Wconversion", + { "-Wconversion", N_("Warn about possibly confusing type conversions") }, { "-Wno-conversion", "" }, - { "-Wformat", + { "-Wdiv-by-zero", "" }, + { "-Wno-div-by-zero", + N_("Do not warn about compile-time integer division by zero") }, + { "-Wfloat-equal", + N_("Warn about testing equality of floating point numbers") }, + { "-Wno-float-equal", "" }, + { "-Wformat", N_("Warn about printf/scanf/strftime/strfmon format anomalies") }, { "-Wno-format", "" }, - { "-Wformat-y2k", "" }, - { "-Wno-format-y2k", - N_("Don't warn about strftime formats yielding 2 digit years") }, { "-Wformat-extra-args", "" }, { "-Wno-format-extra-args", N_("Don't warn about too many arguments to format functions") }, - { "-Wformat-nonliteral", + { "-Wformat-nonliteral", N_("Warn about non-string-literal format strings") }, { "-Wno-format-nonliteral", "" }, { "-Wformat-security", N_("Warn about possible security problems with format functions") }, { "-Wno-format-security", "" }, + { "-Wformat-y2k", "" }, + { "-Wno-format-y2k", + N_("Don't warn about strftime formats yielding 2 digit years") }, { "-Wimplicit-function-declaration", N_("Warn about implicit function declarations") }, { "-Wno-implicit-function-declaration", "" }, { "-Werror-implicit-function-declaration", "" }, - { "-Wimplicit-int", + { "-Wimplicit-int", N_("Warn when a declaration does not specify a type") }, { "-Wno-implicit-int", "" }, { "-Wimplicit", "" }, { "-Wno-implicit", "" }, - { "-Wimport", + { "-Wimport", N_("Warn about the use of the #import directive") }, { "-Wno-import", "" }, { "-Wlong-long","" }, - { "-Wno-long-long", + { "-Wno-long-long", N_("Do not warn about using 'long long' when -pedantic") }, - { "-Wmain", + { "-Wmain", N_("Warn about suspicious declarations of main") }, { "-Wno-main", "" }, { "-Wmissing-braces", @@ -1294,48 +1325,48 @@ documented_lang_options[] = { "-Wmissing-declarations", N_("Warn about global funcs without previous declarations") }, { "-Wno-missing-declarations", "" }, - { "-Wmissing-prototypes", + { "-Wmissing-prototypes", N_("Warn about global funcs without prototypes") }, { "-Wno-missing-prototypes", "" }, - { "-Wmultichar", + { "-Wmultichar", N_("Warn about use of multicharacter literals") }, { "-Wno-multichar", "" }, - { "-Wnested-externs", + { "-Wnested-externs", N_("Warn about externs not at file scope level") }, { "-Wno-nested-externs", "" }, - { "-Wparentheses", + { "-Wparentheses", N_("Warn about possible missing parentheses") }, { "-Wno-parentheses", "" }, - { "-Wsequence-point", - N_("Warn about possible violations of sequence point rules") }, - { "-Wno-sequence-point", "" }, - { "-Wpointer-arith", + { "-Wpointer-arith", N_("Warn about function pointer arithmetic") }, { "-Wno-pointer-arith", "" }, { "-Wredundant-decls", N_("Warn about multiple declarations of the same object") }, { "-Wno-redundant-decls", "" }, - { "-Wsign-compare", + { "-Wreturn-type", + N_("Warn whenever a function's return-type defaults to int") }, + { "-Wno-return-type", "" }, + { "-Wsequence-point", + N_("Warn about possible violations of sequence point rules") }, + { "-Wno-sequence-point", "" }, + { "-Wsign-compare", N_("Warn about signed/unsigned comparisons") }, { "-Wno-sign-compare", "" }, - { "-Wfloat-equal", - N_("Warn about testing equality of floating point numbers") }, - { "-Wno-float-equal", "" }, - { "-Wunknown-pragmas", - N_("Warn about unrecognized pragmas") }, - { "-Wno-unknown-pragmas", "" }, - { "-Wstrict-prototypes", + { "-Wstrict-prototypes", N_("Warn about non-prototyped function decls") }, { "-Wno-strict-prototypes", "" }, - { "-Wtraditional", - N_("Warn about constructs whose meaning change in ISO C") }, + { "-Wtraditional", + N_("Warn about constructs whose meanings change in ISO C") }, { "-Wno-traditional", "" }, - { "-Wtrigraphs", + { "-Wtrigraphs", N_("Warn when trigraphs are encountered") }, { "-Wno-trigraphs", "" }, { "-Wundef", "" }, { "-Wno-undef", "" }, - { "-Wwrite-strings", + { "-Wunknown-pragmas", + N_("Warn about unrecognized pragmas") }, + { "-Wno-unknown-pragmas", "" }, + { "-Wwrite-strings", N_("Mark strings as 'const char *'") }, { "-Wno-write-strings", "" }, @@ -1357,7 +1388,7 @@ static const struct const int value; const char *const description; } -target_switches [] = TARGET_SWITCHES; +target_switches[] = TARGET_SWITCHES; /* This table is similar, but allows the switch to have a value. */ @@ -1368,7 +1399,7 @@ static const struct const char **const variable; const char *const description; } -target_options [] = TARGET_OPTIONS; +target_options[] = TARGET_OPTIONS; #endif /* Options controlling warnings. */ @@ -1409,10 +1440,20 @@ int warn_uninitialized; int warn_shadow; -/* Warn if a switch on an enum fails to have a case for every enum value. */ +/* Warn if a switch on an enum, that does not have a default case, + fails to have a case for every enum value. */ int warn_switch; +/* Warn if a switch does not have a default case. */ + +int warn_switch_default; + +/* Warn if a switch on an enum fails to have a case for every enum + value (regardless of the presence or otherwise of a default case). */ + +int warn_switch_enum; + /* Nonzero means warn about function definitions that default the return type or that use a null return and have a return-type other than void. */ @@ -1456,11 +1497,16 @@ int warn_disabled_optimization; int warn_missing_noreturn; -/* Nonzero means warn about uses of __attribute__((deprecated)) +/* Nonzero means warn about uses of __attribute__((deprecated)) declarations. */ int warn_deprecated_decl = 1; +/* Nonzero means warn about constructs which might not be + strict-aliasing safe. */ + +int warn_strict_aliasing; + /* Likewise for -W. */ static const lang_independent_options W_options[] = @@ -1482,7 +1528,11 @@ static const lang_independent_options W_options[] = {"shadow", &warn_shadow, 1, N_("Warn when one local variable shadows another") }, {"switch", &warn_switch, 1, - N_("Warn about enumerated switches missing a specific case") }, + N_("Warn about enumerated switches, with no default, missing a case") }, + {"switch-default", &warn_switch_default, 1, + N_("Warn about enumerated switches missing a default case") }, + {"switch-enum", &warn_switch_enum, 1, + N_("Warn about all enumerated switches missing a specific case") }, {"aggregate-return", &warn_aggregate_return, 1, N_("Warn about returning structures, unions or arrays") }, {"cast-align", &warn_cast_align, 1, @@ -1502,7 +1552,9 @@ static const lang_independent_options W_options[] = {"deprecated-declarations", &warn_deprecated_decl, 1, N_("Warn about uses of __attribute__((deprecated)) declarations") }, {"missing-noreturn", &warn_missing_noreturn, 1, - N_("Warn about functions which might be candidates for attribute noreturn") } + N_("Warn about functions which might be candidates for attribute noreturn") }, + {"strict-aliasing", &warn_strict_aliasing, 1, + N_ ("Warn about code which might break the strict aliasing rules") } }; void @@ -1526,19 +1578,25 @@ set_Wunused (setting) -ffast-math and -fno-fast-math imply. */ void -set_fast_math_flags () +set_fast_math_flags (set) + int set; { - flag_trapping_math = 0; - flag_unsafe_math_optimizations = 1; - flag_errno_math = 0; + flag_trapping_math = !set; + flag_unsafe_math_optimizations = set; + flag_finite_math_only = set; + flag_errno_math = !set; + if (set) + flag_signaling_nans = 0; } -void -set_no_fast_math_flags () +/* Return true iff flags are set as if -ffast-math. */ +bool +fast_math_flags_set_p () { - flag_trapping_math = 1; - flag_unsafe_math_optimizations = 0; - flag_errno_math = 1; + return (!flag_trapping_math + && flag_unsafe_math_optimizations + && flag_finite_math_only + && !flag_errno_math); } @@ -1579,20 +1637,8 @@ read_integral_parameter (p, pname, defval) return atoi (p); } - - -/* This is the default decl_printable_name function. */ - -static const char * -decl_name (decl, verbosity) - tree decl; - int verbosity ATTRIBUTE_UNUSED; -{ - return IDENTIFIER_POINTER (DECL_NAME (decl)); -} - -/* This calls abort and is used to avoid problems when abort if a macro. +/* This calls abort and is used to avoid problems when abort is a macro. It is used when we need to pass the address of abort. */ void @@ -1645,73 +1691,6 @@ floor_log2_wide (x) return log; } -static int float_handler_set; -int float_handled; -jmp_buf float_handler; - -/* Signals actually come here. */ - -static void -float_signal (signo) - /* If this is missing, some compilers complain. */ - int signo ATTRIBUTE_UNUSED; -{ - if (float_handled == 0) - crash_signal (signo); - float_handled = 0; - - /* On System-V derived systems, we must reinstall the signal handler. - This is harmless on BSD-derived systems. */ - signal (SIGFPE, float_signal); - longjmp (float_handler, 1); -} - -/* Specify where to longjmp to when a floating arithmetic error happens. - If HANDLER is 0, it means don't handle the errors any more. */ - -static void -set_float_handler (handler) - jmp_buf handler; -{ - float_handled = (handler != 0); - if (handler) - memcpy (float_handler, handler, sizeof (float_handler)); - - if (float_handled && ! float_handler_set) - { - signal (SIGFPE, float_signal); - float_handler_set = 1; - } -} - -/* This is a wrapper function for code which might elicit an - arithmetic exception. That code should be passed in as a function - pointer FN, and one argument DATA. DATA is usually a struct which - contains the real input and output for function FN. This function - returns 0 (failure) if longjmp was called (i.e. an exception - occurred.) It returns 1 (success) otherwise. */ - -int -do_float_handler (fn, data) - void (*fn) PARAMS ((PTR)); - PTR data; -{ - jmp_buf buf; - - if (setjmp (buf)) - { - /* We got here via longjmp () caused by an exception in function - fn (). */ - set_float_handler (NULL); - return 0; - } - - set_float_handler (buf); - (*fn)(data); - set_float_handler (NULL); - return 1; -} - /* Handler for fatal signals, such as SIGSEGV. These are transformed into ICE messages, which is much more user friendly. */ @@ -1719,7 +1698,7 @@ static void crash_signal (signo) int signo; { - internal_error ("internal error: %s", strsignal (signo)); + internal_error ("%s", strsignal (signo)); } /* Strip off a legitimate source ending from the input string NAME of @@ -1733,7 +1712,7 @@ strip_off_ending (name, len) int len; { int i; - for (i = 2; i < 6 && len > i; i++) + for (i = 2; i < 6 && len > i; i++) { if (name[len - i] == '.') { @@ -1765,12 +1744,30 @@ output_quoted_string (asm_file, string) putc (c, asm_file); } else - fprintf (asm_file, "\\%03o", c); + fprintf (asm_file, "\\%03o", (unsigned char) c); } putc ('\"', asm_file); #endif } +/* Output NAME into FILE after having turned it into something + usable as an identifier in a target's assembly file. */ +void +output_clean_symbol_name (file, name) + FILE *file; + const char *name; +{ + /* Make a copy of NAME. */ + char *id = xstrdup (name); + + /* Make it look like a valid identifier for an assembler. */ + clean_symbol_name (id); + + fputs (id, file); + free (id); +} + + /* Output a file name in the form wanted by System V. */ void @@ -1785,7 +1782,7 @@ output_file_directive (asm_file, input_name) while (na > input_name) { if (IS_DIR_SEPARATOR (na[-1])) - break; + break; na--; } @@ -1848,8 +1845,13 @@ open_dump_file (index, decl) free (dump_name); if (decl) - fprintf (rtl_dump_file, "\n;; Function %s\n\n", - decl_printable_name (decl, 2)); + fprintf (rtl_dump_file, "\n;; Function %s%s\n\n", + (*lang_hooks.decl_printable_name) (decl, 2), + cfun->function_frequency == FUNCTION_FREQUENCY_HOT + ? " (hot)" + : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED + ? " (unlikely executed)" + : ""); timevar_pop (TV_DUMP); return 1; @@ -1893,7 +1895,7 @@ close_dump_file (index, func, insns) /* Do any final processing required for the declarations in VEC, of which there are LEN. We write out inline functions and variables that have been deferred until this point, but which are required. - Returns non-zero if anything was put out. */ + Returns nonzero if anything was put out. */ int wrapup_global_declarations (vec, len) @@ -1909,12 +1911,13 @@ wrapup_global_declarations (vec, len) { decl = vec[i]; - /* We're not deferring this any longer. */ - DECL_DEFER_OUTPUT (decl) = 0; + /* We're not deferring this any longer. Assignment is + conditional to avoid needlessly dirtying PCH pages. */ + if (DECL_DEFER_OUTPUT (decl) != 0) + DECL_DEFER_OUTPUT (decl) = 0; - if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0 - && incomplete_decl_finalize_hook != 0) - (*incomplete_decl_finalize_hook) (decl); + if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0) + (*lang_hooks.finish_incomplete_decl) (decl); } /* Now emit any global variables or functions that we have been @@ -2041,27 +2044,33 @@ check_global_declarations (vec, len) assemble_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_function - && TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl)) + /* Warn about static fns or vars defined but not used. */ + if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL) + /* We don't warn about "static const" variables because the + "rcs_id" idiom uses that construction. */ || (warn_unused_variable && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl))) && ! DECL_IN_SYSTEM_HEADER (decl) + && ! TREE_USED (decl) + /* The TREE_USED bit for file-scope decls is kept in the identifier, + to handle multiple external decls in different scopes. */ + && ! TREE_USED (DECL_NAME (decl)) && ! DECL_EXTERNAL (decl) && ! TREE_PUBLIC (decl) - && ! TREE_USED (decl) - && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl)) - /* The TREE_USED bit for file-scope decls - is kept in the identifier, to handle multiple - external decls in different scopes. */ - && ! TREE_USED (DECL_NAME (decl))) + /* Global register variables must be declared to reserve them. */ + && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)) + /* Otherwise, ask the language. */ + && (*lang_hooks.decls.warn_unused_global) (decl)) warning_with_decl (decl, "`%s' defined but not used"); - timevar_push (TV_SYMOUT); - (*debug_hooks->global_decl) (decl); - timevar_pop (TV_SYMOUT); + /* Avoid confusing the debug information machinery when there are + errors. */ + if (errorcount == 0 && sorrycount == 0) + { + timevar_push (TV_SYMOUT); + (*debug_hooks->global_decl) (decl); + timevar_pop (TV_SYMOUT); + } } } @@ -2085,7 +2094,6 @@ push_srcloc (file, line) 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++; @@ -2117,18 +2125,16 @@ pop_srcloc () static void compile_file () { - tree globals; - /* Initialize yet another pass. */ init_final (main_input_filename); - init_branch_prob (dump_base_name); + init_branch_prob (aux_base_name); timevar_push (TV_PARSE); - /* Call the parser, which parses the entire file - (calling rest_of_compilation for each function). */ - yyparse (); + /* Call the parser, which parses the entire file (calling + rest_of_compilation for each function). */ + (*lang_hooks.parse_file) (set_yydebug); /* In case there were missing block closers, get us back to the global binding level. */ @@ -2136,31 +2142,12 @@ compile_file () /* Compilation is now finished except for writing what's left of the symbol table output. */ - timevar_pop (TV_PARSE); if (flag_syntax_only) return; - globals = getdecls (); - - /* Really define vars that have had only a tentative definition. - Really output inline functions that must actually be callable - and have not been output so far. */ - - { - int len = list_length (globals); - tree *vec = (tree *) xmalloc (sizeof (tree) * len); - int i; - tree decl; - - /* Process the decls in reverse order--earliest first. - Put them into VEC from back to front, then take out from front. */ - - for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) - vec[len - i - 1] = decl; - - wrapup_global_declarations (vec, len); + (*lang_hooks.decls.final_write_globals)(); /* This must occur after the loop to output deferred functions. Else the profiler initializer would not be emitted if all the functions @@ -2171,12 +2158,6 @@ compile_file () loop above. */ output_func_start_profiler (); - check_global_declarations (vec, len); - - /* Clean up. */ - free (vec); - } - /* Write out any pending weak symbol declarations. */ weak_finish (); @@ -2196,7 +2177,7 @@ compile_file () dw2_output_indirect_constants (); - end_final (dump_base_name); + end_final (aux_base_name); if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) { @@ -2268,7 +2249,7 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end) { alias = TREE_VALUE (TREE_VALUE (alias)); alias = get_identifier (TREE_STRING_POINTER (alias)); - assemble_alias (decl, alias); + assemble_alias (decl, alias); } } @@ -2278,11 +2259,12 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end) || TREE_CODE (decl) == FUNCTION_DECL) { timevar_push (TV_VARCONST); + if (asmspec) make_decl_rtl (decl, asmspec); - /* Don't output anything - when a tentative file-scope definition is seen. - But at end of compilation, do output code for them. */ + + /* 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 || !DECL_DEFER_OUTPUT (decl)) assemble_variable (decl, top_level, at_end, 0); if (decl == last_assemble_variable_decl) @@ -2290,6 +2272,7 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end) ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl, top_level, at_end); } + timevar_pop (TV_VARCONST); } else if (DECL_REGISTER (decl) && asmspec != 0) @@ -2325,6 +2308,17 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end) timevar_pop (TV_SYMOUT); } #endif +#ifdef DWARF2_DEBUGGING_INFO + else if ((write_symbols == DWARF2_DEBUG + || write_symbols == VMS_AND_DWARF2_DEBUG) + && top_level + && TREE_CODE (decl) == TYPE_DECL) + { + timevar_push (TV_SYMOUT); + dwarf2out_decl (decl); + timevar_pop (TV_SYMOUT); + } +#endif } /* Called after finishing a record, union or enumeral type. */ @@ -2339,6 +2333,11 @@ rest_of_type_compilation (type, toplev) int toplev ATTRIBUTE_UNUSED; #endif { + /* Avoid confusing the debug information machinery when there are + errors. */ + if (errorcount != 0 || sorrycount != 0) + return; + timevar_push (TV_SYMOUT); #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) @@ -2357,7 +2356,7 @@ rest_of_type_compilation (type, toplev) timevar_pop (TV_SYMOUT); } -/* This is called from finish_function (within yyparse) +/* This is called from finish_function (within langhooks.parse_file) after each top-level definition is parsed. It is supposed to compile that function or variable and output the assembler code for it. @@ -2372,7 +2371,6 @@ rest_of_compilation (decl) int failure = 0; int rebuild_label_notes_after_reload; int register_life_up_to_date; - int cleanup_crossjump; timevar_push (TV_REST_OF_COMPILATION); @@ -2443,12 +2441,17 @@ rest_of_compilation (decl) 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; + else + { + /* ??? Note that we used to just make it look like if + the "inline" keyword was specified when we decide + to inline it (because of -finline-functions). + garloff at suse dot de, 2002-04-24: Add another flag to + actually record this piece of information. */ + if (!DECL_INLINE (decl)) + DID_INLINE_FUNC (decl) = 1; + inlinable = DECL_INLINE (decl) = 1; + } } insns = get_insns (); @@ -2468,10 +2471,11 @@ rest_of_compilation (decl) convert_from_eh_region_ranges (); /* If function is inline, and we don't yet know whether to - compile it by itself, defer decision till end of compilation. - finish_compilation will call rest_of_compilation again - for those functions that need to be output. Also defer those - functions that we are supposed to defer. */ + compile it by itself, defer decision till end of compilation. + wrapup_global_declarations will (indirectly) call + rest_of_compilation again for those functions that need to + be output. Also defer those functions that we are supposed + to defer. */ if (inlinable || (DECL_INLINE (decl) @@ -2510,7 +2514,7 @@ rest_of_compilation (decl) free_bb_for_insn (); } - current_function_nothrow = nothrow_function_p (); + set_nothrow_function_flags (); 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. */ @@ -2565,7 +2569,7 @@ rest_of_compilation (decl) distinguish between the return value of this function and the return value of called functions. Also, we can remove all SETs of subregs of hard registers; they are only here because of - integrate. Also, we can now initialize pseudos intended to + integrate. Also, we can now initialize pseudos intended to carry magic hard reg data throughout the function. */ rtx_equal_function_value_matters = 0; purge_hard_subreg_sets (get_insns ()); @@ -2577,21 +2581,56 @@ rest_of_compilation (decl) || errorcount || sorrycount) goto exit_rest_of_compilation; + timevar_push (TV_JUMP); + open_dump_file (DFI_sibling, decl); + insns = get_insns (); + rebuild_jump_labels (insns); + find_exception_handler_labels (); + find_basic_blocks (insns, max_reg_num (), rtl_dump_file); + + delete_unreachable_blocks (); + + /* We have to issue these warnings now already, because CFG cleanups + further down may destroy the required information. */ + check_function_return_warnings (); + + /* Turn NOTE_INSN_PREDICTIONs into branch predictions. */ + if (flag_guess_branch_prob) + { + timevar_push (TV_BRANCH_PROB); + note_prediction_to_br_prob (); + timevar_pop (TV_BRANCH_PROB); + } + /* 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); - + rtx insn; optimize_sibling_and_tail_recursive_calls (); - close_dump_file (DFI_sibling, print_rtl, get_insns ()); - timevar_pop (TV_JUMP); + /* Recompute the CFG as sibling optimization clobbers it randomly. */ + free_bb_for_insn (); + find_exception_handler_labels (); + rebuild_jump_labels (insns); + find_basic_blocks (insns, max_reg_num (), rtl_dump_file); + + /* There is pass ordering problem - we must lower NOTE_INSN_PREDICTION + notes before simplifying cfg and we must do lowering after sibcall + that unhides parts of RTL chain and cleans up the CFG. + + Until sibcall is replaced by tree-level optimizer, lets just + sweep away the NOTE_INSN_PREDICTION notes that leaked out. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION) + delete_insn (insn); } + close_dump_file (DFI_sibling, print_rtl, get_insns ()); + timevar_pop (TV_JUMP); + scope_to_insns_initialize (); /* Complete generation of exception handling code. */ - find_exception_handler_labels (); if (doing_eh (0)) { timevar_push (TV_JUMP); @@ -2622,7 +2661,10 @@ rest_of_compilation (decl) unshare_all_rtl (current_function_decl, insns); #ifdef SETJMP_VIA_SAVE_AREA - /* This must be performed before virtual register instantiation. */ + /* This must be performed before virtual register instantiation. + Please be aware the everything in the compiler that can look + at the RTL up to this point must understand that REG_SAVE_AREA + is just like a use of the REG contained inside. */ if (current_function_calls_alloca) optimize_save_area_alloca (insns); #endif @@ -2639,24 +2681,33 @@ rest_of_compilation (decl) 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 (); + if (flag_guess_branch_prob) + expected_value_to_br_prob (); reg_scan (insns, max_reg_num (), 0); rebuild_jump_labels (insns); find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP); + delete_trivially_dead_insns (insns, max_reg_num ()); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); + cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - copy_loop_headers (insns); + if (optimize) + { + free_bb_for_insn (); + copy_loop_headers (insns); + find_basic_blocks (insns, max_reg_num (), rtl_dump_file); + } purge_line_number_notes (insns); timevar_pop (TV_JUMP); + close_dump_file (DFI_jump, print_rtl, insns); /* Now is when we stop if -fsyntax-only and -Wreturn-type. */ if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl)) { - close_dump_file (DFI_jump, print_rtl, insns); goto exit_rest_of_compilation; } @@ -2670,7 +2721,6 @@ rest_of_compilation (decl) timevar_push (TV_TO_SSA); open_dump_file (DFI_ssa, decl); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); convert_to_ssa (); @@ -2706,7 +2756,7 @@ rest_of_compilation (decl) open_dump_file (DFI_ssa_dce, decl); insns = get_insns (); - ssa_eliminate_dead_code(); + ssa_eliminate_dead_code (); close_dump_file (DFI_ssa_dce, print_rtl_with_bb, insns); timevar_pop (TV_SSA_DCE); @@ -2725,31 +2775,23 @@ rest_of_compilation (decl) timevar_pop (TV_FROM_SSA); ggc_collect (); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); } timevar_push (TV_JUMP); + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - if (optimize > 0) + /* Try to identify useless null pointer tests and delete them. */ + if (flag_delete_null_pointer_checks) { - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP - | (flag_thread_jumps ? CLEANUP_THREADING : 0)); + open_dump_file (DFI_null, decl); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); - /* ??? 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); + if (delete_null_pointer_checks (insns)) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - /* Try to identify useless null pointer tests and delete them. */ - if (flag_delete_null_pointer_checks) - delete_null_pointer_checks (insns); + close_dump_file (DFI_null, print_rtl_with_bb, insns); } /* Jump optimization, and the removal of NULL pointer checks, may @@ -2760,7 +2802,7 @@ rest_of_compilation (decl) renumber_insns (rtl_dump_file); timevar_pop (TV_JUMP); - close_dump_file (DFI_jump, print_rtl, insns); + close_dump_file (DFI_jump, print_rtl_with_bb, insns); ggc_collect (); @@ -2772,44 +2814,32 @@ rest_of_compilation (decl) if (optimize > 0) { open_dump_file (DFI_cse, decl); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); timevar_push (TV_CSE); reg_scan (insns, max_reg_num (), 1); tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file); + if (tem) + rebuild_jump_labels (insns); + purge_all_dead_edges (0); + + delete_trivially_dead_insns (insns, max_reg_num ()); /* If we are not running more CSE passes, then we are no longer expecting CSE to be run. But always rerun it in a cheap mode. */ cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse; if (tem || optimize > 1) - { - timevar_push (TV_JUMP); - rebuild_jump_labels (insns); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - timevar_pop (TV_JUMP); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - } - - /* Run this after jump optmizations remove all the unreachable code - so that unreachable code will not keep values live. */ - delete_trivially_dead_insns (insns, max_reg_num (), 0); - + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); /* Try to identify useless null pointer tests and delete them. */ - if (flag_delete_null_pointer_checks || flag_thread_jumps) + if (flag_delete_null_pointer_checks) { timevar_push (TV_JUMP); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP - | (flag_thread_jumps ? CLEANUP_THREADING : 0)); - - if (flag_delete_null_pointer_checks) - delete_null_pointer_checks (insns); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); + if (delete_null_pointer_checks (insns)) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); timevar_pop (TV_JUMP); } @@ -2818,12 +2848,14 @@ rest_of_compilation (decl) renumber_insns (rtl_dump_file); timevar_pop (TV_CSE); - close_dump_file (DFI_cse, print_rtl, insns); + close_dump_file (DFI_cse, print_rtl_with_bb, insns); } open_dump_file (DFI_addressof, decl); purge_addressof (insns); + if (optimize) + purge_all_dead_edges (0); reg_scan (insns, max_reg_num (), 1); close_dump_file (DFI_addressof, print_rtl, insns); @@ -2840,17 +2872,14 @@ rest_of_compilation (decl) timevar_push (TV_GCSE); open_dump_file (DFI_gcse, decl); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); tem = gcse_main (insns, rtl_dump_file); rebuild_jump_labels (insns); + delete_trivially_dead_insns (insns, max_reg_num ()); save_csb = flag_cse_skip_blocks; save_cfj = flag_cse_follow_jumps; flag_cse_skip_blocks = flag_cse_follow_jumps = 0; - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); /* If -fexpensive-optimizations, re-run CSE to clean up things done by gcse. */ if (flag_expensive_optimizations) @@ -2858,6 +2887,8 @@ rest_of_compilation (decl) timevar_push (TV_CSE); reg_scan (insns, max_reg_num (), 1); tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file); + purge_all_dead_edges (0); + delete_trivially_dead_insns (insns, max_reg_num ()); timevar_pop (TV_CSE); cse_not_expected = !flag_rerun_cse_after_loop; } @@ -2869,11 +2900,7 @@ rest_of_compilation (decl) tem = tem2 = 0; timevar_push (TV_JUMP); rebuild_jump_labels (insns); - delete_trivially_dead_insns (insns, max_reg_num (), 0); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); timevar_pop (TV_JUMP); if (flag_expensive_optimizations) @@ -2881,123 +2908,78 @@ rest_of_compilation (decl) timevar_push (TV_CSE); reg_scan (insns, max_reg_num (), 1); tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file); + purge_all_dead_edges (0); + delete_trivially_dead_insns (insns, max_reg_num ()); timevar_pop (TV_CSE); } } - close_dump_file (DFI_gcse, print_rtl, insns); + close_dump_file (DFI_gcse, print_rtl_with_bb, insns); timevar_pop (TV_GCSE); ggc_collect (); flag_cse_skip_blocks = save_csb; flag_cse_follow_jumps = save_cfj; +#ifdef ENABLE_CHECKING + verify_flow_info (); +#endif } /* Move constant computations out of loops. */ - if (optimize > 0) + if (optimize > 0 && flag_loop_optimize) { + int do_unroll, do_prefetch; + timevar_push (TV_LOOP); + delete_dead_jumptables (); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); open_dump_file (DFI_loop, decl); + /* CFG is no longer maintained up-to-date. */ free_bb_for_insn (); + do_unroll = flag_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL; + do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0; if (flag_rerun_loop_opt) { cleanup_barriers (); /* We only want to perform unrolling once. */ - loop_optimize (insns, rtl_dump_file, LOOP_FIRST_PASS); + loop_optimize (insns, rtl_dump_file, do_unroll); + do_unroll = 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 (), 0); + 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); } cleanup_barriers (); - loop_optimize (insns, rtl_dump_file, - (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT - | (flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0)); + loop_optimize (insns, rtl_dump_file, do_unroll | LOOP_BCT | do_prefetch); + /* Loop can create trivially dead instructions. */ + delete_trivially_dead_insns (insns, max_reg_num ()); close_dump_file (DFI_loop, print_rtl, insns); timevar_pop (TV_LOOP); + find_basic_blocks (insns, max_reg_num (), rtl_dump_file); ggc_collect (); } - if (optimize > 0) - { - timevar_push (TV_CSE2); - open_dump_file (DFI_cse2, decl); - - if (flag_rerun_cse_after_loop) - { - /* Running another jump optimization pass before the second - cse pass sometimes simplifies the RTL enough to allow - 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_push (TV_JUMP); - - /* The previous 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 jump work - better and possibly speed up compilation. */ - delete_trivially_dead_insns (insns, max_reg_num (), 0); - - reg_scan (insns, max_reg_num (), 0); - - timevar_push (TV_IFCVT); - - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE); - if_convert (0); - - timevar_pop(TV_IFCVT); - - timevar_pop (TV_JUMP); - - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - reg_scan (insns, max_reg_num (), 0); - tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file); - - if (tem) - { - timevar_push (TV_JUMP); - rebuild_jump_labels (insns); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - timevar_pop (TV_JUMP); - } - } - - close_dump_file (DFI_cse2, print_rtl, insns); - timevar_pop (TV_CSE2); - - 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 ((optimize ? CLEANUP_EXPENSIVE : 0) - | (flag_thread_jumps ? CLEANUP_THREADING : 0)); - check_function_return_warnings (); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); /* It may make more sense to mark constant functions after dead code is eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs @@ -3006,25 +2988,20 @@ rest_of_compilation (decl) life_analyzis rarely eliminates modification of external memory. */ - mark_constant_function (); + if (optimize) + mark_constant_function (); close_dump_file (DFI_cfg, print_rtl_with_bb, insns); - if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) + /* Do branch profiling and static profile estimation passes. */ + if (optimize > 0 || cfun->arc_profile || flag_branch_probabilities) { + struct loops loops; + timevar_push (TV_BRANCH_PROB); open_dump_file (DFI_bp, decl); - - branch_prob (); - - close_dump_file (DFI_bp, print_rtl_with_bb, insns); - timevar_pop (TV_BRANCH_PROB); - } - - open_dump_file (DFI_life, decl); - if (optimize) - { - struct loops loops; + if (cfun->arc_profile || flag_branch_probabilities) + branch_prob (); /* Discover and record the loop depth at the head of each basic block. The loop infrastructure does the real job for us. */ @@ -3038,12 +3015,79 @@ rest_of_compilation (decl) estimate_probability (&loops); flow_loops_free (&loops); + close_dump_file (DFI_bp, print_rtl_with_bb, insns); + timevar_pop (TV_BRANCH_PROB); } + if (optimize > 0) + { + open_dump_file (DFI_ce1, decl); + if (flag_if_conversion) + { + timevar_push (TV_IFCVT); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (insns, max_reg_num (), 0); + if_convert (0); + timevar_pop (TV_IFCVT); + } + timevar_push (TV_JUMP); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (insns, max_reg_num (), 0); + timevar_pop (TV_JUMP); + close_dump_file (DFI_ce1, print_rtl_with_bb, get_insns ()); + } + if (flag_tracer) + { + timevar_push (TV_TRACER); + open_dump_file (DFI_tracer, decl); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); + tracer (); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (insns, max_reg_num (), 0); + close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ()); + timevar_pop (TV_TRACER); + } + + if (flag_rerun_cse_after_loop) + { + timevar_push (TV_CSE2); + open_dump_file (DFI_cse2, decl); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); + /* CFG is no longer maintained up-to-date. */ + tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file); + purge_all_dead_edges (0); + delete_trivially_dead_insns (insns, max_reg_num ()); + + if (tem) + { + timevar_push (TV_JUMP); + rebuild_jump_labels (insns); + cleanup_cfg (CLEANUP_EXPENSIVE); + timevar_pop (TV_JUMP); + } + reg_scan (insns, max_reg_num (), 0); + close_dump_file (DFI_cse2, print_rtl_with_bb, insns); + ggc_collect (); + timevar_pop (TV_CSE2); + } + + cse_not_expected = 1; + + open_dump_file (DFI_life, decl); + regclass_init (); + +#ifdef ENABLE_CHECKING + verify_flow_info (); +#endif life_analysis (insns, rtl_dump_file, PROP_FINAL); + if (optimize) + cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_UPDATE_LIFE + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); timevar_pop (TV_FLOW); - no_new_pseudos = 1; - if (warn_uninitialized || extra_warnings) { uninitialized_vars_warning (DECL_INITIAL (decl)); @@ -3053,15 +3097,19 @@ rest_of_compilation (decl) if (optimize) { - if (initialize_uninitialized_subregs ()) + if (!flag_new_regalloc && initialize_uninitialized_subregs ()) { - /* Insns were inserted, so things might look a bit different. */ + /* Insns were inserted, and possibly pseudos created, so + things might look a bit different. */ insns = get_insns (); - life_analysis (insns, rtl_dump_file, - (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES)); + allocate_reg_life_data (); + update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES); } } + no_new_pseudos = 1; + close_dump_file (DFI_life, print_rtl_with_bb, insns); ggc_collect (); @@ -3078,10 +3126,6 @@ rest_of_compilation (decl) rebuild_jump_labels_after_combine = combine_instructions (insns, max_reg_num ()); - /* Always purge dead edges, as we may eliminate an insn throwing - exception. */ - rebuild_jump_labels_after_combine |= purge_all_dead_edges (true); - /* Combining insns may have turned an indirect jump into a direct jump. Rebuid the JUMP_LABEL fields of jumping instructions. */ @@ -3102,16 +3146,16 @@ rest_of_compilation (decl) /* Rerun if-conversion, as combine may have simplified things enough to now meet sequence length restrictions. */ - if (optimize > 0) + if (flag_if_conversion) { timevar_push (TV_IFCVT); - open_dump_file (DFI_ce, decl); + open_dump_file (DFI_ce2, decl); no_new_pseudos = 0; if_convert (1); no_new_pseudos = 1; - close_dump_file (DFI_ce, print_rtl_with_bb, insns); + close_dump_file (DFI_ce2, print_rtl_with_bb, insns); timevar_pop (TV_IFCVT); } @@ -3124,6 +3168,7 @@ rest_of_compilation (decl) regmove_optimize (insns, max_reg_num (), rtl_dump_file); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); close_dump_file (DFI_regmove, print_rtl_with_bb, insns); timevar_pop (TV_REGMOVE); @@ -3142,13 +3187,7 @@ rest_of_compilation (decl) timevar_push (TV_MODE_SWITCH); no_new_pseudos = 0; - if (optimize_mode_switching (NULL)) - { - /* We did work, and so had to regenerate global life information. - Take advantage of this and don't re-recompute register life - information below. */ - register_life_up_to_date = 1; - } + optimize_mode_switching (NULL); no_new_pseudos = 1; timevar_pop (TV_MODE_SWITCH); @@ -3196,60 +3235,101 @@ rest_of_compilation (decl) if (! register_life_up_to_date) recompute_reg_usage (insns, ! optimize_size); - /* Allocate the reg_renumber array. */ - allocate_reg_info (max_regno, FALSE, TRUE); + if (flag_new_regalloc) + { + delete_trivially_dead_insns (insns, max_reg_num ()); + reg_alloc (); + + timevar_pop (TV_LOCAL_ALLOC); + if (dump_file[DFI_lreg].enabled) + { + timevar_push (TV_DUMP); - /* And the reg_equiv_memory_loc array. */ - reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx)); + close_dump_file (DFI_lreg, NULL, NULL); + timevar_pop (TV_DUMP); + } - allocate_initial_values (reg_equiv_memory_loc); + /* XXX clean up the whole mess to bring live info in shape again. */ + timevar_push (TV_GLOBAL_ALLOC); + open_dump_file (DFI_greg, decl); - regclass (insns, max_reg_num (), rtl_dump_file); - rebuild_label_notes_after_reload = local_alloc (); + build_insn_chain (insns); + failure = reload (insns, 0); - timevar_pop (TV_LOCAL_ALLOC); + timevar_pop (TV_GLOBAL_ALLOC); - if (dump_file[DFI_lreg].enabled) - { - timevar_push (TV_DUMP); + if (dump_file[DFI_greg].enabled) + { + timevar_push (TV_DUMP); - dump_flow_info (rtl_dump_file); - dump_local_alloc (rtl_dump_file); + dump_global_regs (rtl_dump_file); - close_dump_file (DFI_lreg, print_rtl_with_bb, insns); - timevar_pop (TV_DUMP); + close_dump_file (DFI_greg, print_rtl_with_bb, insns); + timevar_pop (TV_DUMP); + } + + if (failure) + goto exit_rest_of_compilation; + reload_completed = 1; + rebuild_label_notes_after_reload = 0; } + else + { + /* Allocate the reg_renumber array. */ + allocate_reg_info (max_regno, FALSE, TRUE); - ggc_collect (); + /* And the reg_equiv_memory_loc array. */ + reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx)); - timevar_push (TV_GLOBAL_ALLOC); - open_dump_file (DFI_greg, decl); + allocate_initial_values (reg_equiv_memory_loc); - /* If optimizing, allocate remaining pseudo-regs. Do the reload - pass fixing up any insns that are invalid. */ + regclass (insns, max_reg_num (), rtl_dump_file); + rebuild_label_notes_after_reload = local_alloc (); - if (optimize) - failure = global_alloc (rtl_dump_file); - else - { - build_insn_chain (insns); - failure = reload (insns, 0); - } + timevar_pop (TV_LOCAL_ALLOC); - timevar_pop (TV_GLOBAL_ALLOC); + if (dump_file[DFI_lreg].enabled) + { + timevar_push (TV_DUMP); - if (dump_file[DFI_greg].enabled) - { - timevar_push (TV_DUMP); + dump_flow_info (rtl_dump_file); + dump_local_alloc (rtl_dump_file); - dump_global_regs (rtl_dump_file); + close_dump_file (DFI_lreg, print_rtl_with_bb, insns); + timevar_pop (TV_DUMP); + } - close_dump_file (DFI_greg, print_rtl_with_bb, insns); - timevar_pop (TV_DUMP); - } + ggc_collect (); - if (failure) - goto exit_rest_of_compilation; + 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. */ + + if (optimize) + failure = global_alloc (rtl_dump_file); + else + { + build_insn_chain (insns); + failure = reload (insns, 0); + } + + timevar_pop (TV_GLOBAL_ALLOC); + + if (dump_file[DFI_greg].enabled) + { + timevar_push (TV_DUMP); + + dump_global_regs (rtl_dump_file); + + close_dump_file (DFI_greg, print_rtl_with_bb, insns); + timevar_pop (TV_DUMP); + } + + if (failure) + goto exit_rest_of_compilation; + } ggc_collect (); @@ -3271,6 +3351,7 @@ rest_of_compilation (decl) timevar_push (TV_JUMP); rebuild_jump_labels (insns); + purge_all_dead_edges (0); timevar_pop (TV_JUMP); } @@ -3286,10 +3367,13 @@ rest_of_compilation (decl) #endif /* If optimizing, then go ahead and split insns now. */ +#ifndef STACK_REGS if (optimize > 0) +#endif split_all_insns (0); - cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0); + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE); /* On some machines, the prologue and epilogue code, or parts thereof, can be represented as RTL. Doing so lets us schedule insns between @@ -3297,22 +3381,11 @@ rest_of_compilation (decl) scheduling to operate in the epilogue. */ thread_prologue_and_epilogue_insns (insns); - /* Cross-jumping is O(N^3) on the number of edges, thus trying to - perform cross-jumping on flow graphs which have a high connectivity - will take a long time. This is similar to the test to disable GCSE. */ - cleanup_crossjump = CLEANUP_CROSSJUMP; - if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20) - { - if (optimize && warn_disabled_optimization) - warning ("crossjump disabled: %d > 1000 basic blocks and %d >= 20 edges/basic block", - n_basic_blocks, n_edges / n_basic_blocks); - cleanup_crossjump = 0; - } - if (optimize) { - cleanup_cfg (CLEANUP_EXPENSIVE | cleanup_crossjump); life_analysis (insns, rtl_dump_file, PROP_FINAL); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE + | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); /* This is kind of a heuristic. We need to run combine_stack_adjustments even for machines with possibly nonzero RETURN_POPS_ARGS @@ -3350,28 +3423,24 @@ rest_of_compilation (decl) open_dump_file (DFI_rnreg, decl); if (flag_rename_registers) - regrename_optimize (); + regrename_optimize (); if (flag_cprop_registers) - copyprop_hardreg_forward (); + copyprop_hardreg_forward (); close_dump_file (DFI_rnreg, print_rtl_with_bb, insns); timevar_pop (TV_RENAME_REGISTERS); } - if (optimize > 0) + if (flag_if_conversion2) { timevar_push (TV_IFCVT2); - open_dump_file (DFI_ce2, decl); + open_dump_file (DFI_ce3, decl); if_convert (1); - close_dump_file (DFI_ce2, print_rtl_with_bb, insns); + close_dump_file (DFI_ce3, print_rtl_with_bb, insns); timevar_pop (TV_IFCVT2); } -#ifdef STACK_REGS - if (optimize) - split_all_insns (1); -#endif #ifdef INSN_SCHEDULING if (optimize > 0 && flag_schedule_insns_after_reload) @@ -3414,12 +3483,12 @@ rest_of_compilation (decl) timevar_push (TV_REORDER_BLOCKS); open_dump_file (DFI_bbro, decl); - /* Last attempt to optimize CFG, as life analysis possibly removed - some instructions. Note that we can't rerun crossjump at this - point, because it can turn a switch into a direct branch, which - can leave the tablejump address calculation in the code, which - can lead to referencing an undefined label. */ - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK); + /* Last attempt to optimize CFG, as scheduling, peepholing and insn + splitting possibly introduced more crossjumping oppurtuntities. + Except that we can't actually run crossjumping without running + another DCE pass, which we can't do after reg-stack. */ + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK + | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); if (flag_reorder_blocks) { reorder_basic_blocks (); @@ -3481,7 +3550,7 @@ rest_of_compilation (decl) shorten_branches (get_insns ()); timevar_pop (TV_SHORTEN_BRANCH); - current_function_nothrow = nothrow_function_p (); + set_nothrow_function_flags (); 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. */ @@ -3542,9 +3611,10 @@ rest_of_compilation (decl) know for certain that we will be generating an out-of-line copy, the first invocation of this routine (rest_of_compilation) will skip over this code by doing a `goto exit_rest_of_compilation;'. - Later on, finish_compilation will call rest_of_compilation again - for those inline functions that need to have out-of-line copies - generated. During that call, we *will* be routed past here. */ + Later on, wrapup_global_declarations will (indirectly) call + rest_of_compilation again 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); (*debug_hooks->function_decl) (decl); @@ -3570,10 +3640,6 @@ rest_of_compilation (decl) longer valid. */ init_insn_lengths (); - /* Clear out the real_constant_chain before some of the rtx's - it runs through become garbage. */ - clear_const_double_mem (); - /* Show no temporary slots allocated. */ init_temp_slots (); @@ -3623,12 +3689,17 @@ display_help () printf (_(" -finline-limit=<number> Limits the size of inlined functions to <number>\n")); printf (_(" -fmessage-length=<number> Limits diagnostics messages lengths to <number> characters per line. 0 suppresses line-wrapping\n")); printf (_(" -fdiagnostics-show-location=[once | every-line] Indicates how often source location information should be emitted, as prefix, at the beginning of diagnostics when line-wrapping\n")); + printf (_(" -ftls-model=[global-dynamic | local-dynamic | initial-exec | local-exec] Indicates the default thread-local storage code generation model\n")); + printf (_(" -fstack-limit-register=<register> Trap if the stack goes past <register>\n")); + printf (_(" -fstack-limit-symbol=<name> Trap if the stack goes past symbol <name>\n")); + printf (_(" -frandom-seed=<string> Make compile reproducible using <string>\n")); + for (i = ARRAY_SIZE (f_options); i--;) { const char *description = f_options[i].description; - if (description != NULL && * description != 0) + if (description != NULL && *description != 0) printf (" -f%-21s %s\n", f_options[i].string, _(description)); } @@ -3638,9 +3709,9 @@ display_help () for (i = LAST_PARAM; i--;) { const char *description = compiler_params[i].help; - const int length = 21-strlen(compiler_params[i].option); + const int length = 21 - strlen (compiler_params[i].option); - if (description != NULL && * description != 0) + if (description != NULL && *description != 0) printf (" --param %s=<value>%.*s%s\n", compiler_params[i].option, length > 0 ? length : 1, " ", @@ -3655,7 +3726,7 @@ display_help () { const char *description = W_options[i].description; - if (description != NULL && * description != 0) + if (description != NULL && *description != 0) printf (" -W%-21s %s\n", W_options[i].string, _(description)); } @@ -3775,7 +3846,7 @@ display_target_options () if (extra_warnings) printf (_(" -m%-23.23s [undocumented]\n"), option); } - else if (* description != 0) + else if (*description != 0) doc += printf (" -m%-23.23s %s\n", option, _(description)); } @@ -3794,7 +3865,7 @@ display_target_options () if (extra_warnings) printf (_(" -m%-23.23s [undocumented]\n"), option); } - else if (* description != 0) + else if (*description != 0) doc += printf (" -m%-23.23s %s\n", option, _(description)); } #endif @@ -3830,9 +3901,9 @@ decode_d_option (arg) flag_print_asm_name = 1; break; case 'P': - flag_dump_rtl_in_asm = 1; - flag_print_asm_name = 1; - break; + flag_dump_rtl_in_asm = 1; + flag_print_asm_name = 1; + break; case 'v': graph_dump_format = vcg; break; @@ -3840,7 +3911,7 @@ decode_d_option (arg) rtl_dump_and_exit = 1; break; case 'y': - (*lang_hooks.set_yydebug) (1); + set_yydebug = 1; break; case 'D': /* These are handled by the preprocessor. */ case 'I': @@ -3890,9 +3961,9 @@ decode_f_option (arg) } if (!strcmp (arg, "fast-math")) - set_fast_math_flags (); + set_fast_math_flags (1); else if (!strcmp (arg, "no-fast-math")) - set_no_fast_math_flags (); + set_fast_math_flags (0); else if ((option_value = skip_leading_substring (arg, "inline-limit-")) || (option_value = skip_leading_substring (arg, "inline-limit="))) { @@ -3900,6 +3971,29 @@ decode_f_option (arg) read_integral_parameter (option_value, arg - 2, MAX_INLINE_INSNS); set_param_value ("max-inline-insns", val); + set_param_value ("max-inline-insns-single", val/2); + set_param_value ("max-inline-insns-auto", val/2); + set_param_value ("max-inline-insns-rtl", val); + if (val/4 < MIN_INLINE_INSNS) + { + if (val/4 > 10) + set_param_value ("min-inline-insns", val/4); + else + set_param_value ("min-inline-insns", 10); + } + } + else if ((option_value = skip_leading_substring (arg, "tls-model="))) + { + if (strcmp (option_value, "global-dynamic") == 0) + flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC; + else if (strcmp (option_value, "local-dynamic") == 0) + flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC; + else if (strcmp (option_value, "initial-exec") == 0) + flag_tls_default = TLS_MODEL_INITIAL_EXEC; + else if (strcmp (option_value, "local-exec") == 0) + flag_tls_default = TLS_MODEL_LOCAL_EXEC; + else + warning ("`%s': unknown tls-model option", arg - 2); } #ifdef INSN_SCHEDULING else if ((option_value = skip_leading_substring (arg, "sched-verbose="))) @@ -3938,7 +4032,7 @@ decode_f_option (arg) stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, nm); } else if ((option_value - = skip_leading_substring (arg, "message-length="))) + = skip_leading_substring (arg, "message-length="))) output_set_maximum_length (&global_dc->buffer, read_integral_parameter (option_value, arg - 2, diagnostic_line_cutoff (global_dc))); @@ -3946,17 +4040,21 @@ decode_f_option (arg) = skip_leading_substring (arg, "diagnostics-show-location="))) { if (!strcmp (option_value, "once")) - diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE; + diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE; else if (!strcmp (option_value, "every-line")) - diagnostic_prefixing_rule (global_dc) - = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE; + diagnostic_prefixing_rule (global_dc) + = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE; else error ("unrecognized option `%s'", arg - 2); } else if (!strcmp (arg, "no-stack-limit")) stack_limit_rtx = NULL_RTX; + else if ((option_value = skip_leading_substring (arg, "random-seed="))) + flag_random_seed = option_value; + else if (!strcmp (arg, "no-random-seed")) + flag_random_seed = NULL; else if (!strcmp (arg, "preprocessed")) - /* Recognise this switch but do nothing. This prevents warnings + /* Recognize this switch but do nothing. This prevents warnings about an unrecognized switch if cpplib has not been linked in. */ ; else @@ -4024,7 +4122,7 @@ static int decode_g_option (arg) const char *arg; { - static unsigned level=0; + static unsigned level = 0; /* A lot of code assumes write_symbols == NO_DEBUG if the debugging level is 0 (thus -gstabs1 -gstabs0 would lose track of what debugging type has been selected). This records the @@ -4168,18 +4266,21 @@ independent_decode_option (argc, argv) { display_help (); exit_after_options = 1; + return 1; } if (!strcmp (arg, "-target-help")) { display_target_options (); exit_after_options = 1; + return 1; } if (!strcmp (arg, "-version")) { print_version (stderr, ""); exit_after_options = 1; + return 1; } /* Handle '--param <name>=<value>'. */ @@ -4244,7 +4345,9 @@ independent_decode_option (argc, argv) if (argc == 1) return 0; - dump_base_name = argv[1]; + if (argv[1][0]) + dump_base_name = argv[1]; + return 2; } else @@ -4317,6 +4420,30 @@ independent_decode_option (argc, argv) else return 0; } + else if (!strcmp (arg, "auxbase")) + { + if (argc == 1) + return 0; + + if (argv[1][0]) + aux_base_name = argv[1]; + + return 2; + } + else if (!strcmp (arg, "auxbase-strip")) + { + if (argc == 1) + return 0; + + if (argv[1][0]) + { + strip_off_ending (argv[1], strlen (argv[1])); + if (argv[1][0]) + aux_base_name = argv[1]; + } + + return 2; + } else return 0; break; @@ -4383,6 +4510,13 @@ set_target_switch (name) target_flags &= ~-target_switches[j].value; else target_flags |= target_switches[j].value; + if (name[0] != 0) + { + if (target_switches[j].value < 0) + target_flags_explicit |= -target_switches[j].value; + else + target_flags_explicit |= target_switches[j].value; + } valid_target_option = 1; } @@ -4424,6 +4558,9 @@ print_version (file, indent) , indent, *indent != 0 ? " " : "", lang_hooks.name, version_string, TARGET_NAME, indent, __VERSION__); + fnotice (file, "%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n", + indent, *indent != 0 ? " " : "", + PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE)); } /* Print an option value and return the adjusted position in the line. @@ -4470,6 +4607,12 @@ print_switch_values (file, pos, max, indent, sep, term) size_t j; char **p; + /* Fill in the -frandom-seed option, if the user didn't pass it, so + that it can be printed below. This helps reproducibility. Of + course, the string may never be used, but we can't tell that at + this point in the compile. */ + default_flag_random_seed (); + /* Print the options as passed. */ pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term, @@ -4548,25 +4691,25 @@ init_asm_output (name) else { if (asm_file_name == 0) - { - int len = strlen (dump_base_name); - char *dumpname = (char *) xmalloc (len + 6); - memcpy (dumpname, dump_base_name, len + 1); - strip_off_ending (dumpname, len); - strcat (dumpname, ".s"); - asm_file_name = dumpname; - } + { + int len = strlen (dump_base_name); + char *dumpname = (char *) xmalloc (len + 6); + memcpy (dumpname, dump_base_name, len + 1); + strip_off_ending (dumpname, len); + strcat (dumpname, ".s"); + asm_file_name = dumpname; + } if (!strcmp (asm_file_name, "-")) - asm_out_file = stdout; + asm_out_file = stdout; else - asm_out_file = fopen (asm_file_name, "w"); + asm_out_file = fopen (asm_file_name, "w"); if (asm_out_file == 0) fatal_io_error ("can't open %s for writing", asm_file_name); } #ifdef IO_BUFFER_SIZE setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE), - _IOFBF, IO_BUFFER_SIZE); + _IOFBF, IO_BUFFER_SIZE); #endif if (!flag_syntax_only) @@ -4606,11 +4749,9 @@ general_init (argv0) xmalloc_set_program_name (progname); - gcc_init_libintl (); + hex_init (); - /* Install handler for SIGFPE, which may be received while we do - compile-time floating point arithmetic. */ - signal (SIGFPE, float_signal); + gcc_init_libintl (); /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */ #ifdef SIGSEGV @@ -4628,16 +4769,27 @@ general_init (argv0) #if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT) signal (SIGIOT, crash_signal); #endif +#ifdef SIGFPE + signal (SIGFPE, crash_signal); +#endif /* Initialize the diagnostics reporting machinery, so option parsing can give warnings and errors. */ diagnostic_initialize (global_dc); + + /* Initialize the garbage-collector, string pools and tree type hash + table. */ + init_ggc (); + init_stringpool (); + init_ttree (); } /* Parse command line options and set default flag values, called after language-independent option-independent initialization. Do minimal options processing. Outputting diagnostics is OK, but GC - and identifier hashtables etc. are not initialized yet. */ + and identifier hashtables etc. are not initialized yet. + + Return nonzero to suppress compiler back end initialization. */ static void parse_options_and_default_flags (argc, argv) int argc; @@ -4655,6 +4807,9 @@ parse_options_and_default_flags (argc, argv) /* Register the language-independent parameters. */ add_params (lang_independent_params, LAST_PARAM); + /* This must be done after add_params but before argument processing. */ + init_ggc_heuristics(); + /* Perform language-specific options initialization. */ (*lang_hooks.init_options) (); @@ -4729,6 +4884,10 @@ parse_options_and_default_flags (argc, argv) #endif flag_guess_branch_prob = 1; flag_cprop_registers = 1; + flag_loop_optimize = 1; + flag_crossjumping = 1; + flag_if_conversion = 1; + flag_if_conversion2 = 1; } if (optimize >= 2) @@ -4752,6 +4911,7 @@ parse_options_and_default_flags (argc, argv) flag_strict_aliasing = 1; flag_delete_null_pointer_checks = 1; flag_reorder_blocks = 1; + flag_reorder_functions = 1; } if (optimize >= 3) @@ -4766,6 +4926,15 @@ parse_options_and_default_flags (argc, argv) align_jumps = 1; align_labels = 1; align_functions = 1; + + /* Don't reorder blocks when optimizing for size because extra + jump insns may be created; also barrier may create extra padding. + + More correctly we should have a block reordering mode that tried + to minimize the combined size of all the jumps. This would more + or less automatically remove extra jumps, but would also try to + use more short jumps instead of long jumps. */ + flag_reorder_blocks = 0; } /* Initialize whether `char' is signed. */ @@ -4882,10 +5051,6 @@ parse_options_and_default_flags (argc, argv) if (flag_really_no_inline == 2) flag_really_no_inline = flag_no_inline; - - /* All command line options have been parsed; allow the front end to - perform consistency checks, etc. */ - (*lang_hooks.post_options) (); } /* Process the options that have been parsed. */ @@ -4943,16 +5108,6 @@ process_options () warning ("this target machine does not have delayed branches"); #endif - /* Some operating systems do not allow profiling without a frame - pointer. */ - if (!TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER - && profile_flag - && flag_omit_frame_pointer) - { - error ("profiling does not work without a frame pointer"); - flag_omit_frame_pointer = 0; - } - user_label_prefix = USER_LABEL_PREFIX; if (flag_leading_underscore != -1) { @@ -4977,7 +5132,7 @@ process_options () print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n"); } - if (! quiet_flag) + if (! quiet_flag || flag_detailed_statistics) time_report = 1; if (flag_syntax_only) @@ -5069,30 +5224,19 @@ process_options () if (flag_function_sections && write_symbols != NO_DEBUG) warning ("-ffunction-sections may affect debugging on some targets"); #endif + + /* The presence of IEEE signaling NaNs, implies all math can trap. */ + if (flag_signaling_nans) + flag_trapping_math = 1; } -/* Language-independent initialization, before language-dependent - initialization. */ +/* Initialize the compiler back end. */ static void -lang_independent_init () +backend_init () { - decl_printable_name = decl_name; - lang_expand_expr = (lang_expand_expr_t) do_abort; - - /* Set the language-dependent identifier size. */ - tree_code_length[(int) IDENTIFIER_NODE] - = ((lang_hooks.identifier_size - sizeof (struct tree_common) - + sizeof (tree) - 1) / sizeof (tree)); - - /* Initialize the garbage-collector, and string pools. */ - init_ggc (); - 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); - - init_stringpool (); - init_obstacks (); - + /* init_emit_once uses reg_raw_mode and therefore must be called + after init_regs which initialized reg_raw_mode. */ + init_regs (); init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL || debug_info_level == DINFO_LEVEL_VERBOSE #ifdef VMS_DEBUGGING_INFO @@ -5101,34 +5245,30 @@ lang_independent_init () #endif || flag_test_coverage || warn_notreached); - init_regs (); + init_fake_stack_mems (); init_alias_once (); - init_stmt (); init_loop (); init_reload (); init_function_once (); - init_stor_layout_once (); init_varasm_once (); - init_EXPR_INSN_LIST_cache (); /* The following initialization functions need to generate rtl, so provide a dummy function context for them. */ init_dummy_function_start (); init_expmed (); - init_expr_once (); if (flag_caller_saves) init_caller_save (); expand_dummy_function_end (); } -/* Language-dependent initialization. Returns non-zero on success. */ +/* Language-dependent initialization. Returns nonzero on success. */ static int lang_dependent_init (name) const char *name; { if (dump_base_name == 0) dump_base_name = name ? name : "gccdump"; - + /* Front-end initialization. This hook can assume that GC, identifier hashes etc. are set up, but debug initialization is not done yet. This routine must return the original filename @@ -5147,6 +5287,12 @@ lang_dependent_init (name) init_eh (); init_optabs (); + /* The following initialization functions need to generate rtl, so + provide a dummy function context for them. */ + init_dummy_function_start (); + init_expr_once (); + expand_dummy_function_end (); + /* Put an entry on the input file stack for the main input file. */ push_srcloc (input_filename, 0); @@ -5229,17 +5375,37 @@ finalize () static void do_compile () { + /* All command line options have been parsed; allow the front end to + perform consistency checks, etc. */ + bool no_backend = (*lang_hooks.post_options) (); + /* The bulk of command line switch processing. */ process_options (); + /* If an error has already occurred, give up. */ + if (errorcount) + return; + + if (aux_base_name) + /*NOP*/; + else if (filename) + { + char *name = xstrdup (lbasename (filename)); + + aux_base_name = name; + strip_off_ending (name, strlen (name)); + } + else + aux_base_name = "gccaux"; + /* We cannot start timing until after options are processed since that says if we run timers or not. */ init_timevar (); timevar_start (TV_TOTAL); - /* Language-independent initialization. Also sets up GC, identifier - hashes etc. */ - lang_independent_init (); + /* Set up the back-end if requested. */ + if (!no_backend) + backend_init (); /* Language-dependent initialization. Returns true on success. */ if (lang_dependent_init (filename)) @@ -5264,17 +5430,15 @@ toplev_main (argc, argv) int argc; char **argv; { - hex_init (); - /* Initialization of GCC's environment, and diagnostics. */ - general_init (argv [0]); + general_init (argv[0]); /* Parse the options and do minimal processing; basically just enough to default flags appropriately. */ parse_options_and_default_flags (argc, argv); /* Exit early if we can (e.g. -help). */ - if (!errorcount && !exit_after_options) + if (!exit_after_options) do_compile (); if (errorcount || sorrycount) |