X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftoplev.c;h=425f94ea6af7f2230d26d62488e5a67b6e1c784c;hp=92ef8358d8afb4ee3ba1c8af2cce823e52936440;hb=08d163a9f560aba0131e1ec71cc5de397c8579fb;hpb=c0c4adc61b1b611f2cb7933a65769ae2e203d025 diff --git a/gcc/toplev.c b/gcc/toplev.c index 92ef8358d8a..425f94ea6af 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1,6 +1,6 @@ /* Top level of GCC compilers (cc1, cc1plus, etc.) Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -63,7 +63,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "regs.h" #include "timevar.h" #include "diagnostic.h" -#include "ssa.h" #include "params.h" #include "reload.h" #include "dwarf2asm.h" @@ -78,6 +77,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "cgraph.h" #include "opts.h" #include "coverage.h" +#include "value-prof.h" #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) #include "dwarf2out.h" @@ -96,6 +96,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA declarations for e.g. AIX 4.x. */ #endif +#ifndef HAVE_conditional_execution +#define HAVE_conditional_execution 0 +#endif + /* Carry information from ASM_DECLARE_OBJECT_NAME to ASM_FINISH_DECLARE_OBJECT. */ @@ -124,7 +128,6 @@ static void print_switch_values (FILE *, int, int, const char *, /* Rest of compilation helper functions. */ static bool rest_of_handle_inlining (tree); -static rtx rest_of_handle_ssa (tree, rtx); static void rest_of_handle_cse (tree, rtx); static void rest_of_handle_cse2 (tree, rtx); static void rest_of_handle_gcse (tree, rtx); @@ -137,6 +140,7 @@ static void rest_of_handle_null_pointer (tree, rtx); static void rest_of_handle_addressof (tree, rtx); static void rest_of_handle_cfg (tree, rtx); static void rest_of_handle_branch_prob (tree, rtx); +static void rest_of_handle_value_profile_transformations (tree, rtx); static void rest_of_handle_if_conversion (tree, rtx); static void rest_of_handle_if_after_combine (tree, rtx); static void rest_of_handle_tracer (tree, rtx); @@ -146,8 +150,8 @@ static void rest_of_handle_regmove (tree, rtx); static void rest_of_handle_sched (tree, rtx); static void rest_of_handle_sched2 (tree, rtx); #endif -static bool rest_of_handle_new_regalloc (tree, rtx, int *); -static bool rest_of_handle_old_regalloc (tree, rtx, int *); +static bool rest_of_handle_new_regalloc (tree, rtx); +static bool rest_of_handle_old_regalloc (tree, rtx); static void rest_of_handle_regrename (tree, rtx); static void rest_of_handle_reorder_blocks (tree, rtx); #ifdef STACK_REGS @@ -185,6 +189,8 @@ const char *main_input_filename; location_t input_location; +struct line_maps line_table; + /* Nonzero if it is unsafe to create any new pseudo registers. */ int no_new_pseudos; @@ -252,10 +258,6 @@ enum dump_file_index DFI_sibling, DFI_eh, DFI_jump, - DFI_ssa, - DFI_ssa_ccp, - DFI_ssa_dce, - DFI_ussa, DFI_null, DFI_cse, DFI_addressof, @@ -264,9 +266,11 @@ enum dump_file_index DFI_bypass, DFI_cfg, DFI_bp, + DFI_vpt, DFI_ce1, DFI_tracer, DFI_loop2, + DFI_web, DFI_cse2, DFI_life, DFI_combine, @@ -279,8 +283,8 @@ enum dump_file_index DFI_flow2, DFI_peephole2, DFI_rnreg, - DFI_bbro, DFI_ce3, + DFI_bbro, DFI_branch_target_load, DFI_sched2, DFI_stack, @@ -294,8 +298,8 @@ enum dump_file_index Remaining -d letters: - " m q " - " JK O Q V YZ" + " e m q " + " JK O Q WXY " */ static struct dump_file_info dump_file[DFI_MAX] = @@ -305,10 +309,6 @@ static struct dump_file_info dump_file[DFI_MAX] = { "sibling", 'i', 0, 0, 0 }, { "eh", 'h', 0, 0, 0 }, { "jump", 'j', 0, 0, 0 }, - { "ssa", 'e', 1, 0, 0 }, - { "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 }, @@ -317,9 +317,11 @@ static struct dump_file_info dump_file[DFI_MAX] = { "bypass", 'G', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "cfg", 'f', 1, 0, 0 }, { "bp", 'b', 1, 0, 0 }, + { "vpt", 'V', 1, 0, 0 }, { "ce1", 'C', 1, 0, 0 }, { "tracer", 'T', 1, 0, 0 }, { "loop2", 'L', 1, 0, 0 }, + { "web", 'Z', 0, 0, 0 }, { "cse2", 't', 1, 0, 0 }, { "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "combine", 'c', 1, 0, 0 }, @@ -332,8 +334,8 @@ static struct dump_file_info dump_file[DFI_MAX] = { "flow2", 'w', 1, 0, 0 }, { "peephole2", 'z', 1, 0, 0 }, { "rnreg", 'n', 1, 0, 0 }, - { "bbro", 'B', 1, 0, 0 }, { "ce3", 'E', 1, 0, 0 }, + { "bbro", 'B', 1, 0, 0 }, { "btl", 'd', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "sched2", 'R', 1, 0, 0 }, { "stack", 'k', 1, 0, 0 }, @@ -402,6 +404,9 @@ int profile_arc_flag = 0; int flag_profile_values = 0; +/* Nonzero if value histograms should be used to optimize code. */ +int flag_value_profile_transformations = 0; + /* Nonzero if generating info for gcov to calculate line test coverage. */ int flag_test_coverage = 0; @@ -472,11 +477,7 @@ int flag_short_enums; be saved across function calls, if that produces overall better code. Optional now, so people can test it. */ -#ifdef DEFAULT_CALLER_SAVES -int flag_caller_saves = 1; -#else int flag_caller_saves = 0; -#endif /* Nonzero if structures and unions should be returned in memory. @@ -654,6 +655,10 @@ int flag_complex_divide_method = 0; int flag_syntax_only = 0; +/* Nonzero means performs web construction pass. */ + +int flag_web; + /* Nonzero means perform loop optimizer. */ int flag_loop_optimize; @@ -691,6 +696,11 @@ int flag_gcse_lm = 1; int flag_gcse_sm = 1; +/* Nonzero if we want to perfrom redundant load after store elimination + in gcse. */ + +int flag_gcse_las = 1; + /* Perform target register optimization before prologue / epilogue threading. */ @@ -701,6 +711,11 @@ int flag_branch_target_load_optimize = 0; int flag_branch_target_load_optimize2 = 0; +/* For the bt-load pass, nonzero means don't re-use branch target registers + in any basic block. */ + +int flag_btr_bb_exclusive; + /* Nonzero means to rerun cse after loop optimization. This increases compilation time about 20% and picks up a few more common expressions. */ @@ -826,6 +841,20 @@ int flag_schedule_speculative = 1; int flag_schedule_speculative_load = 0; int flag_schedule_speculative_load_dangerous = 0; +/* The following flags have an effect during scheduling after register + allocation: + + flag_sched_stalled_insns means that insns can be moved prematurely from the queue + of stalled insns into the ready list. + + flag_sched_stalled_insns_dep controls how many insn groups will be examined + for a dependency on a stalled insn that is candidate for premature removal + from the queue of stalled insns into the ready list (has an effect only if + the flag 'sched_stalled_insns' is set). */ + +int flag_sched_stalled_insns = 0; +int flag_sched_stalled_insns_dep = 1; + int flag_single_precision_constant; /* flag_branch_on_count_reg means try to replace add-1,compare,branch tupple @@ -860,27 +889,9 @@ int flag_debug_asm = 0; int flag_dump_rtl_in_asm = 0; -/* -fgnu-linker specifies use of the GNU linker for initializations. - (Or, more generally, a linker that handles initializations.) - -fno-gnu-linker says that collect2 will be used. */ -#ifdef USE_COLLECT2 -int flag_gnu_linker = 0; -#else -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; - -/* Enable ssa conditional constant propagation. */ -int flag_ssa_ccp = 0; - -/* Enable ssa aggressive dead code elimination. */ -int flag_ssa_dce = 0; - /* Tag all structures with __attribute__(packed). */ int flag_pack_struct = 0; @@ -988,6 +999,9 @@ int flag_trapv = 0; /* Nonzero if signed arithmetic overflow should wrap around. */ int flag_wrapv = 0; +/* Nonzero if subexpressions must be evaluated from left-to-right. */ +int flag_evaluation_order = 0; + /* Add or remove a leading underscore from user symbols. */ int flag_leading_underscore = -1; @@ -1048,11 +1062,14 @@ static const lang_independent_options f_options[] = {"pcc-struct-return", &flag_pcc_struct_return, 1 }, {"reg-struct-return", &flag_pcc_struct_return, 0 }, {"delayed-branch", &flag_delayed_branch, 1 }, + {"web", &flag_web, 1}, {"gcse", &flag_gcse, 1 }, {"gcse-lm", &flag_gcse_lm, 1 }, {"gcse-sm", &flag_gcse_sm, 1 }, + {"gcse-las", &flag_gcse_las, 1 }, {"branch-target-load-optimize", &flag_branch_target_load_optimize, 1 }, {"branch-target-load-optimize2", &flag_branch_target_load_optimize2, 1 }, + {"btr-bb-exclusive", &flag_btr_bb_exclusive, 1 }, {"loop-optimize", &flag_loop_optimize, 1 }, {"crossjumping", &flag_crossjumping, 1 }, {"if-conversion", &flag_if_conversion, 1 }, @@ -1066,6 +1083,8 @@ static const lang_independent_options f_options[] = {"sched-spec",&flag_schedule_speculative, 1 }, {"sched-spec-load",&flag_schedule_speculative_load, 1 }, {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1 }, + {"sched-stalled-insns", &flag_sched_stalled_insns, 0 }, + {"sched-stalled-insns-dep", &flag_sched_stalled_insns_dep, 1 }, {"sched2-use-superblocks", &flag_sched2_use_superblocks, 1 }, {"sched2-use-traces", &flag_sched2_use_traces, 1 }, {"branch-count-reg",&flag_branch_on_count_reg, 1 }, @@ -1078,6 +1097,8 @@ static const lang_independent_options f_options[] = {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1 }, {"non-call-exceptions", &flag_non_call_exceptions, 1 }, {"profile-arcs", &profile_arc_flag, 1 }, + {"profile-values", &flag_profile_values, 1 }, + {"vpt", &flag_value_profile_transformations, 1 }, {"test-coverage", &flag_test_coverage, 1 }, {"branch-probabilities", &flag_branch_probabilities, 1 }, {"profile", &profile_flag, 1 }, @@ -1090,7 +1111,6 @@ static const lang_independent_options f_options[] = {"function-sections", &flag_function_sections, 1 }, {"data-sections", &flag_data_sections, 1 }, {"verbose-asm", &flag_verbose_asm, 1 }, - {"gnu-linker", &flag_gnu_linker, 1 }, {"regmove", &flag_regmove, 1 }, {"optimize-register-move", &flag_regmove, 1 }, {"pack-struct", &flag_pack_struct, 1 }, @@ -1108,9 +1128,6 @@ static const lang_independent_options f_options[] = {"dump-unnumbered", &flag_dump_unnumbered, 1 }, {"instrument-functions", &flag_instrument_function_entry_exit, 1 }, {"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1 }, - {"ssa", &flag_ssa, 1 }, - {"ssa-ccp", &flag_ssa_ccp, 1 }, - {"ssa-dce", &flag_ssa_dce, 1 }, {"leading-underscore", &flag_leading_underscore, 1 }, {"ident", &flag_no_ident, 0 }, { "peephole2", &flag_peephole2, 1 }, @@ -1232,12 +1249,12 @@ randomize (void) { unsigned HOST_WIDE_INT value; static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3]; - + /* Get some more or less random data. */ #ifdef HAVE_GETTIMEOFDAY { struct timeval tv; - + gettimeofday (&tv, NULL); local_tick = tv.tv_sec * 1000 + tv.tv_usec / 1000; } @@ -1250,7 +1267,7 @@ randomize (void) } #endif value = local_tick ^ getpid (); - + sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value); flag_random_seed = random_seed; } @@ -1403,8 +1420,14 @@ output_quoted_string (FILE *asm_file, const char *string) void output_file_directive (FILE *asm_file, const char *input_name) { - int len = strlen (input_name); - const char *na = input_name + len; + int len; + const char *na; + + if (input_name == NULL) + input_name = ""; + + len = strlen (input_name); + na = input_name + len; /* NA gets INPUT_NAME sans directory names. */ while (na > input_name) @@ -1414,9 +1437,6 @@ output_file_directive (FILE *asm_file, const char *input_name) na--; } -#ifdef ASM_OUTPUT_MAIN_SOURCE_FILENAME - ASM_OUTPUT_MAIN_SOURCE_FILENAME (asm_file, na); -#else #ifdef ASM_OUTPUT_SOURCE_FILENAME ASM_OUTPUT_SOURCE_FILENAME (asm_file, na); #else @@ -1424,7 +1444,6 @@ output_file_directive (FILE *asm_file, const char *input_name) output_quoted_string (asm_file, na); fputc ('\n', asm_file); #endif -#endif } /* Routine to open a dump file. Return true if the dump file is enabled. */ @@ -1663,11 +1682,9 @@ check_global_declarations (tree *vec, int len) && ! TREE_PUBLIC (decl)) { if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) - pedwarn ("%H'%F' used but never defined", - &DECL_SOURCE_LOCATION (decl), decl); + pedwarn ("%J'%F' used but never defined", decl, decl); else - warning ("%H'%F' declared `static' but never defined", - &DECL_SOURCE_LOCATION (decl), decl); + warning ("%J'%F' declared `static' but never defined", decl, decl); /* This symbol is effectively an "extern" declaration now. */ TREE_PUBLIC (decl) = 1; assemble_external (decl); @@ -1675,7 +1692,11 @@ check_global_declarations (tree *vec, int len) /* Warn about static fns or vars defined but not used. */ if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL) - || (warn_unused_variable && TREE_CODE (decl) == VAR_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. */ @@ -1688,8 +1709,7 @@ check_global_declarations (tree *vec, int len) && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)) /* Otherwise, ask the language. */ && (*lang_hooks.decls.warn_unused_global) (decl)) - warning ("%H'%D' defined but not used", - &DECL_SOURCE_LOCATION (decl), decl); + warning ("%J'%D' defined but not used", decl, decl); /* Avoid confusing the debug information machinery when there are errors. */ @@ -1702,6 +1722,44 @@ check_global_declarations (tree *vec, int len) } } +/* Warn about a use of an identifier which was marked deprecated. */ +void +warn_deprecated_use (tree node) +{ + if (node == 0 || !warn_deprecated_decl) + return; + + if (DECL_P (node)) + warning ("`%s' is deprecated (declared at %s:%d)", + IDENTIFIER_POINTER (DECL_NAME (node)), + DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node)); + else if (TYPE_P (node)) + { + const char *what = NULL; + tree decl = TYPE_STUB_DECL (node); + + if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE) + what = IDENTIFIER_POINTER (TYPE_NAME (node)); + else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (node))) + what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))); + + if (what) + { + if (decl) + warning ("`%s' is deprecated (declared at %s:%d)", what, + DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + else + warning ("`%s' is deprecated", what); + } + else if (decl) + warning ("type is deprecated (declared at %s:%d)", + DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + else + warning ("type is deprecated"); + } +} + /* Save the current INPUT_LOCATION on the top entry in the INPUT_FILE_STACK. Push a new entry for FILE and LINE, and set the INPUT_LOCATION accordingly. */ @@ -1866,8 +1924,15 @@ rest_of_decl_compilation (tree decl, 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. */ - if ((at_end || !DECL_DEFER_OUTPUT (decl)) && !DECL_EXTERNAL (decl)) + is seen. But at end of compilation, do output code for them. + + We do output all variables when unit-at-a-time is active and rely on + callgraph code to defer them except for forward declarations + (see gcc.c-torture/compile/920624-1.c) */ + if ((at_end + || !DECL_DEFER_OUTPUT (decl) + || (flag_unit_at_a_time && DECL_INITIAL (decl))) + && !DECL_EXTERNAL (decl)) { if (flag_unit_at_a_time && !cgraph_global_info_ready && TREE_CODE (decl) != FUNCTION_DECL && top_level) @@ -2044,6 +2109,23 @@ rest_of_handle_delay_slots (tree decl, rtx insns) static void rest_of_handle_stack_regs (tree decl, rtx insns) { +#if defined (HAVE_ATTR_length) + /* If flow2 creates new instructions which need splitting + and scheduling after reload is not done, they might not be + split until final which doesn't allow splitting + if HAVE_ATTR_length. */ +#ifdef INSN_SCHEDULING + if (optimize && !flag_schedule_insns_after_reload) +#else + if (optimize) +#endif + { + timevar_push (TV_SHORTEN_BRANCH); + split_all_insns (1); + timevar_pop (TV_SHORTEN_BRANCH); + } +#endif + timevar_push (TV_REG_STACK); open_dump_file (DFI_stack, decl); @@ -2085,7 +2167,7 @@ rest_of_handle_machine_reorg (tree decl, rtx insns) /* Run new register allocator. Return TRUE if we must exit rest_of_compilation upon return. */ static bool -rest_of_handle_new_regalloc (tree decl, rtx insns, int *rebuild_notes) +rest_of_handle_new_regalloc (tree decl, rtx insns) { int failure; @@ -2124,7 +2206,6 @@ rest_of_handle_new_regalloc (tree decl, rtx insns, int *rebuild_notes) return true; reload_completed = 1; - *rebuild_notes = 0; return false; } @@ -2132,9 +2213,10 @@ rest_of_handle_new_regalloc (tree decl, rtx insns, int *rebuild_notes) /* Run old register allocator. Return TRUE if we must exit rest_of_compilation upon return. */ static bool -rest_of_handle_old_regalloc (tree decl, rtx insns, int *rebuild_notes) +rest_of_handle_old_regalloc (tree decl, rtx insns) { int failure; + int rebuild_notes; /* Allocate the reg_renumber array. */ allocate_reg_info (max_regno, FALSE, TRUE); @@ -2145,10 +2227,23 @@ rest_of_handle_old_regalloc (tree decl, rtx insns, int *rebuild_notes) allocate_initial_values (reg_equiv_memory_loc); regclass (insns, max_reg_num (), rtl_dump_file); - *rebuild_notes = local_alloc (); + rebuild_notes = local_alloc (); timevar_pop (TV_LOCAL_ALLOC); + /* Local allocation may have turned an indirect jump into a direct + jump. If so, we must rebuild the JUMP_LABEL fields of jumping + instructions. */ + if (rebuild_notes) + { + timevar_push (TV_JUMP); + + rebuild_jump_labels (insns); + purge_all_dead_edges (0); + + timevar_pop (TV_JUMP); + } + if (dump_file[DFI_lreg].enabled) { timevar_push (TV_DUMP); @@ -2211,13 +2306,14 @@ rest_of_handle_regrename (tree decl, rtx insns) static void rest_of_handle_reorder_blocks (tree decl, rtx insns) { - timevar_push (TV_REORDER_BLOCKS); + bool changed; open_dump_file (DFI_bbro, decl); /* Last attempt to optimize CFG, as scheduling, peepholing and insn splitting possibly introduced more crossjumping opportunities. */ - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE - | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); + changed = cleanup_cfg (CLEANUP_EXPENSIVE + | (!HAVE_conditional_execution + ? CLEANUP_UPDATE_LIFE : 0)); if (flag_sched2_use_traces && flag_schedule_insns_after_reload) tracer (); @@ -2225,10 +2321,17 @@ rest_of_handle_reorder_blocks (tree decl, rtx insns) reorder_basic_blocks (); if (flag_reorder_blocks || (flag_sched2_use_traces && flag_schedule_insns_after_reload)) - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); - + changed |= cleanup_cfg (CLEANUP_EXPENSIVE + | (!HAVE_conditional_execution + ? CLEANUP_UPDATE_LIFE : 0)); + + /* On conditional execution targets we can not update the life cheaply, so + we deffer the updating to after both cleanups. This may lose some cases + but should not be terribly bad. */ + if (changed && HAVE_conditional_execution) + update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_DEATH_NOTES | PROP_REG_INFO); close_dump_file (DFI_bbro, print_rtl_with_bb, insns); - timevar_pop (TV_REORDER_BLOCKS); } #ifdef INSN_SCHEDULING @@ -2307,7 +2410,6 @@ rest_of_handle_regmove (tree decl, rtx insns) static void rest_of_handle_tracer (tree decl, rtx insns) { - timevar_push (TV_TRACER); open_dump_file (DFI_tracer, decl); if (rtl_dump_file) dump_flow_info (rtl_dump_file); @@ -2315,7 +2417,6 @@ rest_of_handle_tracer (tree decl, rtx insns) 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-conversion and CFG cleanup. */ @@ -2356,6 +2457,20 @@ rest_of_handle_if_after_combine (tree decl, rtx insns) timevar_pop (TV_IFCVT); } +static void +rest_of_handle_web (tree decl, rtx insns) +{ + open_dump_file (DFI_web, decl); + timevar_push (TV_WEB); + web_main (); + delete_trivially_dead_insns (insns, max_reg_num ()); + cleanup_cfg (CLEANUP_EXPENSIVE); + + timevar_pop (TV_WEB); + close_dump_file (DFI_web, print_rtl_with_bb, insns); + reg_scan (get_insns (), max_reg_num (), 0); +} + /* Do branch profiling and static profile estimation passes. */ static void rest_of_handle_branch_prob (tree decl, rtx insns) @@ -2364,6 +2479,7 @@ rest_of_handle_branch_prob (tree decl, rtx insns) timevar_push (TV_BRANCH_PROB); open_dump_file (DFI_bp, decl); + if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) branch_prob (); @@ -2379,10 +2495,25 @@ rest_of_handle_branch_prob (tree decl, rtx insns) estimate_probability (&loops); flow_loops_free (&loops); + free_dominance_info (CDI_DOMINATORS); close_dump_file (DFI_bp, print_rtl_with_bb, insns); timevar_pop (TV_BRANCH_PROB); } +/* Do optimizations based on expression value profiles. */ +static void +rest_of_handle_value_profile_transformations (tree decl, rtx insns) +{ + open_dump_file (DFI_vpt, decl); + timevar_push (TV_VPT); + + if (value_profile_transformations ()) + cleanup_cfg (CLEANUP_EXPENSIVE); + + timevar_pop (TV_VPT); + close_dump_file (DFI_vpt, print_rtl_with_bb, insns); +} + /* Do control and data flow analysis; write some of the results to the dump file. */ static void @@ -2403,7 +2534,12 @@ rest_of_handle_cfg (tree decl, rtx insns) life_analysis rarely eliminates modification of external memory. */ if (optimize) - mark_constant_function (); + { + /* Alias analysis depends on this information and mark_constant_function + depends on alias analysis. */ + reg_scan (insns, max_reg_num (), 1); + mark_constant_function (); + } close_dump_file (DFI_cfg, print_rtl_with_bb, insns); } @@ -2458,6 +2594,7 @@ rest_of_handle_jump_bypass (tree decl, rtx insns) open_dump_file (DFI_bypass, decl); cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (insns, max_reg_num (), 1); if (bypass_jumps (rtl_dump_file)) { @@ -2520,11 +2657,8 @@ rest_of_handle_inlining (tree decl) { if (warn_inline && lose && DECL_INLINE (decl)) { - char *msg = xmalloc (2 + strlen (lose) + 1); - msg[0] = '%'; - msg[1] = 'H'; - strcpy(msg + 2, lose); - warning (msg, &DECL_SOURCE_LOCATION (decl)); + char *msg = concat ("%J", lose, NULL); + warning (msg, decl); free (msg); } DECL_ABSTRACT_ORIGIN (decl) = 0; @@ -2566,7 +2700,13 @@ rest_of_handle_inlining (tree decl) if (inlinable || (DECL_INLINE (decl) - && flag_inline_functions + /* Egad. This RTL deferral test conflicts with Fortran assumptions + for unreferenced symbols. See g77.f-torture/execute/980520-1.f. + But removing this line from the check breaks all languages that + use the call graph to output symbols. This hard-coded check is + the least invasive work-around. */ + && (flag_inline_functions + || strcmp (lang_hooks.name, "GNU F77") == 0) && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl) && ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) && ! flag_keep_inline_functions) @@ -2621,71 +2761,6 @@ rest_of_handle_inlining (tree decl) return (bool) DECL_EXTERNAL (decl); } -/* Rest of compilation helper to convert the rtl to SSA form. */ -static rtx -rest_of_handle_ssa (tree decl, rtx insns) -{ - timevar_push (TV_TO_SSA); - open_dump_file (DFI_ssa, decl); - - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - convert_to_ssa (); - - close_dump_file (DFI_ssa, print_rtl_with_bb, insns); - timevar_pop (TV_TO_SSA); - - /* Perform sparse conditional constant propagation, if requested. */ - if (flag_ssa_ccp) - { - timevar_push (TV_SSA_CCP); - open_dump_file (DFI_ssa_ccp, decl); - - ssa_const_prop (); - - close_dump_file (DFI_ssa_ccp, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_SSA_CCP); - } - - /* It would be useful to cleanup the CFG at this point, but block - merging and possibly other transformations might leave a PHI - node in the middle of a basic block, which is a strict no-no. */ - - /* The SSA implementation uses basic block numbers in its phi - nodes. Thus, changing the control-flow graph or the basic - blocks, e.g., calling find_basic_blocks () or cleanup_cfg (), - may cause problems. */ - - if (flag_ssa_dce) - { - /* Remove dead code. */ - - timevar_push (TV_SSA_DCE); - open_dump_file (DFI_ssa_dce, decl); - - insns = get_insns (); - ssa_eliminate_dead_code (); - - close_dump_file (DFI_ssa_dce, print_rtl_with_bb, insns); - timevar_pop (TV_SSA_DCE); - } - - /* 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); - timevar_pop (TV_FROM_SSA); - - ggc_collect (); - - return insns; -} - /* Try to identify useless null pointer tests and delete them. */ static void rest_of_handle_null_pointer (tree decl, rtx insns) @@ -2743,6 +2818,7 @@ rest_of_handle_life (tree decl, rtx insns) life_analysis (insns, rtl_dump_file, PROP_FINAL); if (optimize) cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_UPDATE_LIFE + | CLEANUP_LOG_LINKS | (flag_thread_jumps ? CLEANUP_THREADING : 0)); timevar_pop (TV_FLOW); @@ -2791,7 +2867,8 @@ rest_of_handle_cse (tree decl, rtx insns) tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file); if (tem) rebuild_jump_labels (insns); - purge_all_dead_edges (0); + if (purge_all_dead_edges (0)) + delete_unreachable_blocks (); delete_trivially_dead_insns (insns, max_reg_num ()); @@ -2831,6 +2908,13 @@ rest_of_handle_cse2 (tree decl, rtx insns) 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); + + /* Run a pass to eliminate duplicated assignments to condition code + registers. We have to run this after bypass_jumps, because it + makes it harder for that pass to determine whether a jump can be + bypassed safely. */ + cse_condition_code_reg (); + purge_all_dead_edges (0); delete_trivially_dead_insns (insns, max_reg_num ()); @@ -2929,7 +3013,7 @@ rest_of_handle_loop_optimize (tree decl, rtx insns) free_bb_for_insn (); if (flag_unroll_loops) - do_unroll = 0; /* Having two unrollers is useless. */ + do_unroll = LOOP_AUTO_UNROLL; /* Having two unrollers is useless. */ else do_unroll = flag_old_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL; do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0; @@ -3013,13 +3097,12 @@ void rest_of_compilation (tree decl) { rtx insns; - int rebuild_label_notes_after_reload; timevar_push (TV_REST_OF_COMPILATION); /* Register rtl specific functions for cfg. */ rtl_register_cfg_hooks (); - + /* Now that we're out of the frontend, we shouldn't have any more CONCATs anywhere. */ generating_concat_p = 0; @@ -3057,7 +3140,7 @@ rest_of_compilation (tree decl) /* We are now committed to emitting code for this function. Do any preparation, such as emitting abstract debug info for the inline before it gets mangled by optimization. */ - if (DECL_INLINE (decl)) + if (cgraph_function_possibly_inlined_p (decl)) (*debug_hooks->outlining_inline_function) (decl); /* Remove any notes we don't need. That will make iterating @@ -3099,10 +3182,6 @@ rest_of_compilation (tree decl) 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) { @@ -3114,6 +3193,14 @@ rest_of_compilation (tree decl) if (flag_optimize_sibling_calls) rest_of_handle_sibling_calls (insns); + /* We have to issue these warnings now already, because CFG cleanups + further down may destroy the required information. However, this + must be done after the sibcall optimization pass because the barrier + emitted for noreturn calls that are candidate for the optimization + is folded into the CALL_PLACEHOLDER until after this pass, so the + CFG is inaccurate. */ + check_function_return_warnings (); + timevar_pop (TV_JUMP); insn_locators_initialize (); @@ -3195,12 +3282,6 @@ rest_of_compilation (tree decl) if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl)) goto exit_rest_of_compilation; - /* Long term, this should probably move before the jump optimizer too, - but I didn't want to disturb the rtl_dump_and_exit and related - stuff at this time. */ - if (optimize > 0 && flag_ssa) - insns = rest_of_handle_ssa (decl, insns); - timevar_push (TV_JUMP); if (optimize) @@ -3235,9 +3316,6 @@ rest_of_compilation (tree decl) if (flag_loop_optimize) rest_of_handle_loop_optimize (decl, insns); - - if (flag_gcse) - rest_of_handle_jump_bypass (decl, insns); } timevar_push (TV_FLOW); @@ -3246,7 +3324,18 @@ rest_of_compilation (tree decl) if (optimize > 0 || profile_arc_flag || flag_test_coverage || flag_branch_probabilities) - rest_of_handle_branch_prob (decl, insns); + { + rest_of_handle_branch_prob (decl, insns); + + if (flag_branch_probabilities + && flag_profile_values + && flag_value_profile_transformations) + rest_of_handle_value_profile_transformations (decl, insns); + + /* Remove the death notes created for vpt. */ + if (flag_profile_values) + count_or_remove_death_notes (NULL, 1); + } if (optimize > 0) rest_of_handle_if_conversion (decl, insns); @@ -3254,11 +3343,19 @@ rest_of_compilation (tree decl) if (flag_tracer) rest_of_handle_tracer (decl, insns); - if (optimize > 0 - && (flag_unswitch_loops + if (optimize > 0) + { + if (flag_unswitch_loops || flag_peel_loops - || flag_unroll_loops)) - rest_of_handle_loop2 (decl, insns); + || flag_unroll_loops) + rest_of_handle_loop2 (decl, insns); + + if (flag_gcse) + rest_of_handle_jump_bypass (decl, insns); + } + + if (flag_web) + rest_of_handle_web (decl, insns); if (flag_rerun_cse_after_loop) rest_of_handle_cse2 (decl, insns); @@ -3309,14 +3406,12 @@ rest_of_compilation (tree decl) if (flag_new_regalloc) { - if (rest_of_handle_new_regalloc (decl, insns, - &rebuild_label_notes_after_reload)) + if (rest_of_handle_new_regalloc (decl, insns)) goto exit_rest_of_compilation; } else { - if (rest_of_handle_old_regalloc (decl, insns, - &rebuild_label_notes_after_reload)) + if (rest_of_handle_old_regalloc (decl, insns)) goto exit_rest_of_compilation; } @@ -3329,22 +3424,13 @@ rest_of_compilation (tree decl) { timevar_push (TV_RELOAD_CSE_REGS); reload_cse_regs (insns); + /* reload_cse_regs can eliminate potentially-trapping MEMs. + Remove any EH edges associated with them. */ + if (flag_non_call_exceptions) + purge_all_dead_edges (0); timevar_pop (TV_RELOAD_CSE_REGS); } - /* 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_push (TV_JUMP); - - rebuild_jump_labels (insns); - purge_all_dead_edges (0); - - timevar_pop (TV_JUMP); - } - close_dump_file (DFI_postreload, print_rtl_with_bb, insns); /* Re-create the death notes which were deleted during reload. */ @@ -3384,7 +3470,7 @@ rest_of_compilation (tree decl) if (optimize) { - life_analysis (insns, rtl_dump_file, PROP_FINAL); + life_analysis (insns, rtl_dump_file, PROP_POSTRELOAD); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); @@ -3418,42 +3504,48 @@ rest_of_compilation (tree decl) } #endif - if (optimize > 0) - { - if (flag_rename_registers || flag_cprop_registers) - rest_of_handle_regrename (decl, insns); - - rest_of_handle_reorder_blocks (decl, insns); - } - + open_dump_file (DFI_ce3, decl); + if (optimize) + /* Last attempt to optimize CFG, as scheduling, peepholing and insn + splitting possibly introduced more crossjumping opportunities. */ + cleanup_cfg (CLEANUP_EXPENSIVE + | CLEANUP_UPDATE_LIFE + | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); if (flag_if_conversion2) { timevar_push (TV_IFCVT2); - open_dump_file (DFI_ce3, decl); if_convert (1); - close_dump_file (DFI_ce3, print_rtl_with_bb, insns); timevar_pop (TV_IFCVT2); } + close_dump_file (DFI_ce3, print_rtl_with_bb, insns); - if (flag_branch_target_load_optimize2) - { - /* Leave this a warning for now so that it is possible to experiment - with running this pass twice. In 3.6, we should either make this - an error, or use separate dump files. */ - if (flag_branch_target_load_optimize) - warning ("branch target register load optimization is not intended " - "to be run twice"); + if (optimize > 0) + { + if (flag_rename_registers || flag_cprop_registers) + rest_of_handle_regrename (decl, insns); - open_dump_file (DFI_branch_target_load, decl); + rest_of_handle_reorder_blocks (decl, insns); + } - branch_target_load_optimize (insns, true); + if (flag_branch_target_load_optimize2) + { + /* Leave this a warning for now so that it is possible to experiment + with running this pass twice. In 3.6, we should either make this + an error, or use separate dump files. */ + if (flag_branch_target_load_optimize) + warning ("branch target register load optimization is not intended " + "to be run twice"); - close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns); + open_dump_file (DFI_branch_target_load, decl); - ggc_collect (); - } + branch_target_load_optimize (insns, true); + + close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns); + + ggc_collect (); + } #ifdef INSN_SCHEDULING if (optimize > 0 && flag_schedule_insns_after_reload) @@ -3588,7 +3680,7 @@ rest_of_compilation (tree decl) } /* Display help for target options. */ -void +void display_target_options (void) { int undoc, i; @@ -3959,6 +4051,123 @@ init_asm_output (const char *name) } } +/* Default version of get_pch_validity. + By default, every flag difference is fatal; that will be mostly right for + most targets, but completely right for very few. */ + +void * +default_get_pch_validity (size_t *len) +{ +#ifdef TARGET_OPTIONS + size_t i; +#endif + char *result, *r; + + *len = sizeof (target_flags) + 2; +#ifdef TARGET_OPTIONS + for (i = 0; i < ARRAY_SIZE (target_options); i++) + { + *len += 1; + if (*target_options[i].variable) + *len += strlen (*target_options[i].variable); + } +#endif + + result = r = xmalloc (*len); + r[0] = flag_pic; + r[1] = flag_pie; + r += 2; + memcpy (r, &target_flags, sizeof (target_flags)); + r += sizeof (target_flags); + +#ifdef TARGET_OPTIONS + for (i = 0; i < ARRAY_SIZE (target_options); i++) + { + const char *str = *target_options[i].variable; + size_t l; + if (! str) + str = ""; + l = strlen (str) + 1; + memcpy (r, str, l); + r += l; + } +#endif + + return result; +} + +/* Default version of pch_valid_p. */ + +const char * +default_pch_valid_p (const void *data_p, size_t len) +{ + const char *data = (const char *)data_p; + const char *flag_that_differs = NULL; + size_t i; + + /* -fpic and -fpie also usually make a PCH invalid. */ + if (data[0] != flag_pic) + return _("created and used with different settings of -fpic"); + if (data[1] != flag_pie) + return _("created and used with different settings of -fpie"); + data += 2; + + /* Check target_flags. */ + if (memcmp (data, &target_flags, sizeof (target_flags)) != 0) + { + for (i = 0; i < ARRAY_SIZE (target_switches); i++) + { + int bits; + int tf; + + memcpy (&tf, data, sizeof (target_flags)); + + bits = target_switches[i].value; + if (bits < 0) + bits = -bits; + if ((target_flags & bits) != (tf & bits)) + { + flag_that_differs = target_switches[i].name; + goto make_message; + } + } + abort (); + } + data += sizeof (target_flags); + len -= sizeof (target_flags); + + /* Check string options. */ +#ifdef TARGET_OPTIONS + for (i = 0; i < ARRAY_SIZE (target_options); i++) + { + const char *str = *target_options[i].variable; + size_t l; + if (! str) + str = ""; + l = strlen (str) + 1; + if (len < l || memcmp (data, str, l) != 0) + { + flag_that_differs = target_options[i].prefix; + goto make_message; + } + data += l; + len -= l; + } +#endif + + return NULL; + + make_message: + { + char *r; + asprintf (&r, _("created and used with differing settings of `-m%s'"), + flag_that_differs); + if (r == NULL) + return _("out of memory"); + return r; + } +} + /* Default tree printer. Handles declarations only. */ static bool default_tree_printer (pretty_printer * pp, text_info *text) @@ -4035,6 +4244,7 @@ general_init (const char *argv0) table. */ init_ggc (); init_stringpool (); + linemap_init (&line_table); init_ttree (); /* Initialize register usage now so switches may override. */ @@ -4129,6 +4339,9 @@ process_options (void) if (flag_unit_at_a_time && ! lang_hooks.callgraph.expand_function) flag_unit_at_a_time = 0; + if (flag_value_profile_transformations) + flag_profile_values = 1; + /* Warn about options that are not supported on this machine. */ #ifndef INSN_SCHEDULING if (flag_schedule_insns || flag_schedule_insns_after_reload) @@ -4190,10 +4403,6 @@ process_options (void) else if (write_symbols == SDB_DEBUG) debug_hooks = &sdb_debug_hooks; #endif -#ifdef DWARF_DEBUGGING_INFO - else if (write_symbols == DWARF_DEBUG) - debug_hooks = &dwarf_debug_hooks; -#endif #ifdef DWARF2_DEBUGGING_INFO else if (write_symbols == DWARF2_DEBUG) debug_hooks = &dwarf2_debug_hooks; @@ -4272,6 +4481,8 @@ process_options (void) static void backend_init (void) { + init_adjust_machine_modes (); + init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL || debug_info_level == DINFO_LEVEL_VERBOSE #ifdef VMS_DEBUGGING_INFO @@ -4388,6 +4599,8 @@ finalize (void) ggc_print_statistics (); stringpool_statistics (); dump_tree_statistics (); + dump_rtx_statistics (); + dump_varray_statistics (); } /* Free up memory for the benefit of leak detectors. */