X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fopts.c;h=e935fd9509c10db3d64d4af50e7e521d6b4cf1a9;hb=fbbc6fdbe73dde1b85b992579ce30f6d90ea62e8;hp=f8eeb1a7db9c3140c9f6e3b8313ece264a44be09;hpb=b6c1bd727a489a6b86c231d03211065cf877e01d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/opts.c b/gcc/opts.c index f8eeb1a7db9..e935fd9509c 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -7,7 +7,7 @@ This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -40,6 +39,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "insn-attr.h" /* For INSN_SCHEDULING. */ #include "target.h" #include "tree-pass.h" +#include "dbgcnt.h" +#include "debug.h" /* Value of the -G xx switch, and whether it was passed or not. */ unsigned HOST_WIDE_INT g_switch_value; @@ -77,6 +78,256 @@ enum debug_info_type write_symbols = NO_DEBUG; the definitions of the different possible levels. */ enum debug_info_level debug_info_level = DINFO_LEVEL_NONE; +/* A major contribution to object and executable size is debug + information size. A major contribution to debug information size + is struct descriptions replicated in several object files. The + following flags attempt to reduce this information. The basic + idea is to not emit struct debugging information in the current + compilation unit when that information will be generated by + another compilation unit. + + Debug information for a struct defined in the current source + file should be generated in the object file. Likewise the + debug information for a struct defined in a header should be + generated in the object file of the corresponding source file. + Both of these case are handled when the base name of the file of + the struct definition matches the base name of the source file + of the current compilation unit. This matching emits minimal + struct debugging information. + + The base file name matching rule above will fail to emit debug + information for structs defined in system headers. So a second + category of files includes system headers in addition to files + with matching bases. + + The remaining types of files are library headers and application + headers. We cannot currently distinguish these two types. */ + +enum debug_struct_file +{ + DINFO_STRUCT_FILE_NONE, /* Debug no structs. */ + DINFO_STRUCT_FILE_BASE, /* Debug structs defined in files with the + same base name as the compilation unit. */ + DINFO_STRUCT_FILE_SYS, /* Also debug structs defined in system + header files. */ + DINFO_STRUCT_FILE_ANY /* Debug structs defined in all files. */ +}; + +/* Generic structs (e.g. templates not explicitly specialized) + may not have a compilation unit associated with them, and so + may need to be treated differently from ordinary structs. + + Structs only handled by reference (indirectly), will also usually + not need as much debugging information. */ + +static enum debug_struct_file debug_struct_ordinary[DINFO_USAGE_NUM_ENUMS] + = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }; +static enum debug_struct_file debug_struct_generic[DINFO_USAGE_NUM_ENUMS] + = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }; + +/* Parse the -femit-struct-debug-detailed option value + and set the flag variables. */ + +#define MATCH( prefix, string ) \ + ((strncmp (prefix, string, sizeof prefix - 1) == 0) \ + ? ((string += sizeof prefix - 1), 1) : 0) + +void +set_struct_debug_option (const char *spec) +{ + /* various labels for comparison */ + static char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:"; + static char ord_lbl[] = "ord:", gen_lbl[] = "gen:"; + static char none_lbl[] = "none", any_lbl[] = "any"; + static char base_lbl[] = "base", sys_lbl[] = "sys"; + + enum debug_struct_file files = DINFO_STRUCT_FILE_ANY; + /* Default is to apply to as much as possible. */ + enum debug_info_usage usage = DINFO_USAGE_NUM_ENUMS; + int ord = 1, gen = 1; + + /* What usage? */ + if (MATCH (dfn_lbl, spec)) + usage = DINFO_USAGE_DFN; + else if (MATCH (dir_lbl, spec)) + usage = DINFO_USAGE_DIR_USE; + else if (MATCH (ind_lbl, spec)) + usage = DINFO_USAGE_IND_USE; + + /* Generics or not? */ + if (MATCH (ord_lbl, spec)) + gen = 0; + else if (MATCH (gen_lbl, spec)) + ord = 0; + + /* What allowable environment? */ + if (MATCH (none_lbl, spec)) + files = DINFO_STRUCT_FILE_NONE; + else if (MATCH (any_lbl, spec)) + files = DINFO_STRUCT_FILE_ANY; + else if (MATCH (sys_lbl, spec)) + files = DINFO_STRUCT_FILE_SYS; + else if (MATCH (base_lbl, spec)) + files = DINFO_STRUCT_FILE_BASE; + else + error ("argument %qs to %<-femit-struct-debug-detailed%> not recognized", + spec); + + /* Effect the specification. */ + if (usage == DINFO_USAGE_NUM_ENUMS) + { + if (ord) + { + debug_struct_ordinary[DINFO_USAGE_DFN] = files; + debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files; + debug_struct_ordinary[DINFO_USAGE_IND_USE] = files; + } + if (gen) + { + debug_struct_generic[DINFO_USAGE_DFN] = files; + debug_struct_generic[DINFO_USAGE_DIR_USE] = files; + debug_struct_generic[DINFO_USAGE_IND_USE] = files; + } + } + else + { + if (ord) + debug_struct_ordinary[usage] = files; + if (gen) + debug_struct_generic[usage] = files; + } + + if (*spec == ',') + set_struct_debug_option (spec+1); + else + { + /* No more -femit-struct-debug-detailed specifications. + Do final checks. */ + if (*spec != '\0') + error ("argument %qs to %<-femit-struct-debug-detailed%> unknown", + spec); + if (debug_struct_ordinary[DINFO_USAGE_DIR_USE] + < debug_struct_ordinary[DINFO_USAGE_IND_USE] + || debug_struct_generic[DINFO_USAGE_DIR_USE] + < debug_struct_generic[DINFO_USAGE_IND_USE]) + error ("%<-femit-struct-debug-detailed=dir:...%> must allow at least" + " as much as %<-femit-struct-debug-detailed=ind:...%>"); + } +} + +/* Find the base name of a path, stripping off both directories and + a single final extension. */ +static int +base_of_path (const char *path, const char **base_out) +{ + const char *base = path; + const char *dot = 0; + const char *p = path; + char c = *p; + while (c) + { + if (IS_DIR_SEPARATOR(c)) + { + base = p + 1; + dot = 0; + } + else if (c == '.') + dot = p; + c = *++p; + } + if (!dot) + dot = p; + *base_out = base; + return dot - base; +} + +/* Match the base name of a file to the base name of a compilation unit. */ + +static const char *main_input_basename; +static int main_input_baselength; + +static int +matches_main_base (const char *path) +{ + /* Cache the last query. */ + static const char *last_path = NULL; + static int last_match = 0; + if (path != last_path) + { + const char *base; + int length = base_of_path (path, &base); + last_path = path; + last_match = (length == main_input_baselength + && memcmp (base, main_input_basename, length) == 0); + } + return last_match; +} + +#ifdef DEBUG_DEBUG_STRUCT + +static int +dump_struct_debug (tree type, enum debug_info_usage usage, + enum debug_struct_file criterion, int generic, + int matches, int result) +{ + /* Find the type name. */ + tree type_decl = TYPE_STUB_DECL (type); + tree t = type_decl; + const char *name = 0; + if (TREE_CODE (t) == TYPE_DECL) + t = DECL_NAME (t); + if (t) + name = IDENTIFIER_POINTER (t); + + fprintf (stderr, " struct %d %s %s %s %s %d %p %s\n", + criterion, + DECL_IN_SYSTEM_HEADER (type_decl) ? "sys" : "usr", + matches ? "bas" : "hdr", + generic ? "gen" : "ord", + usage == DINFO_USAGE_DFN ? ";" : + usage == DINFO_USAGE_DIR_USE ? "." : "*", + result, + (void*) type_decl, name); + return result; +} +#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ + dump_struct_debug (type, usage, criterion, generic, matches, result) + +#else + +#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ + (result) + +#endif + + +bool +should_emit_struct_debug (tree type, enum debug_info_usage usage) +{ + enum debug_struct_file criterion; + tree type_decl; + bool generic = lang_hooks.types.generic_p (type); + + if (generic) + criterion = debug_struct_generic[usage]; + else + criterion = debug_struct_ordinary[usage]; + + if (criterion == DINFO_STRUCT_FILE_NONE) + return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); + if (criterion == DINFO_STRUCT_FILE_ANY) + return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); + + type_decl = TYPE_STUB_DECL (type); + + if (criterion == DINFO_STRUCT_FILE_SYS && DECL_IN_SYSTEM_HEADER (type_decl)) + return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); + + if (matches_main_base (DECL_SOURCE_FILE (type_decl))) + return DUMP_GSTRUCT (type, usage, criterion, generic, true, true); + return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); +} + /* Nonzero means use GNU-only extensions in the generated symbolic debugging information. Currently, this only has an effect when write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG. */ @@ -102,6 +353,16 @@ static bool profile_arc_flag_set, flag_profile_values_set; static bool flag_unroll_loops_set, flag_tracer_set; static bool flag_value_profile_transformations_set; static bool flag_peel_loops_set, flag_branch_probabilities_set; +static bool flag_inline_functions_set; + +/* Functions excluded from profiling. */ + +typedef char *char_p; /* For DEF_VEC_P. */ +DEF_VEC_P(char_p); +DEF_VEC_ALLOC_P(char_p,heap); + +static VEC(char_p,heap) *flag_instrument_functions_exclude_functions; +static VEC(char_p,heap) *flag_instrument_functions_exclude_files; /* Input file names. */ const char **in_fnames; @@ -352,6 +613,87 @@ add_input_filename (const char *filename) in_fnames[num_in_fnames - 1] = filename; } +/* Add functions or file names to a vector of names to exclude from + instrumentation. */ + +static void +add_instrument_functions_exclude_list (VEC(char_p,heap) **pvec, + const char* arg) +{ + char *tmp; + char *r; + char *w; + char *token_start; + + /* We never free this string. */ + tmp = xstrdup (arg); + + r = tmp; + w = tmp; + token_start = tmp; + + while (*r != '\0') + { + if (*r == ',') + { + *w++ = '\0'; + ++r; + VEC_safe_push (char_p, heap, *pvec, token_start); + token_start = w; + } + if (*r == '\\' && r[1] == ',') + { + *w++ = ','; + r += 2; + } + else + *w++ = *r++; + } + if (*token_start != '\0') + VEC_safe_push (char_p, heap, *pvec, token_start); +} + +/* Return whether we should exclude FNDECL from instrumentation. */ + +bool +flag_instrument_functions_exclude_p (tree fndecl) +{ + if (VEC_length (char_p, flag_instrument_functions_exclude_functions) > 0) + { + const char *name; + int i; + char *s; + + name = lang_hooks.decl_printable_name (fndecl, 0); + for (i = 0; + VEC_iterate (char_p, flag_instrument_functions_exclude_functions, + i, s); + ++i) + { + if (strstr (name, s) != NULL) + return true; + } + } + + if (VEC_length (char_p, flag_instrument_functions_exclude_files) > 0) + { + const char *name; + int i; + char *s; + + name = DECL_SOURCE_FILE (fndecl); + for (i = 0; + VEC_iterate (char_p, flag_instrument_functions_exclude_files, i, s); + ++i) + { + if (strstr (name, s) != NULL) + return true; + } + } + + return false; +} + /* Decode and handle the vector of command line options. LANG_MASK contains has a single bit set representing the current language. */ @@ -368,7 +710,11 @@ handle_options (unsigned int argc, const char **argv, unsigned int lang_mask) if (opt[0] != '-' || opt[1] == '\0') { if (main_input_filename == NULL) + { main_input_filename = opt; + main_input_baselength + = base_of_path (main_input_filename, &main_input_basename); + } add_input_filename (opt); n = 1; continue; @@ -476,6 +822,7 @@ decode_options (unsigned int argc, const char **argv) if (optimize >= 2) { + flag_inline_small_functions = 1; flag_thread_jumps = 1; flag_crossjumping = 1; flag_optimize_sibling_calls = 1; @@ -506,13 +853,21 @@ decode_options (unsigned int argc, const char **argv) /* PRE tends to generate bigger code. */ flag_tree_pre = 1; } + + /* Allow more virtual operators to increase alias precision. */ + set_param_value ("max-aliased-vops", 500); } if (optimize >= 3) { + flag_predictive_commoning = 1; flag_inline_functions = 1; flag_unswitch_loops = 1; flag_gcse_after_reload = 1; + + /* Allow even more virtual operators. */ + set_param_value ("max-aliased-vops", 1000); + set_param_value ("avg-aliased-vops", 3); } if (optimize < 2 || optimize_size) @@ -535,9 +890,8 @@ decode_options (unsigned int argc, const char **argv) if (optimize_size) { - /* Inlining of very small functions usually reduces total size. */ - set_param_value ("max-inline-insns-single", 5); - set_param_value ("max-inline-insns-auto", 5); + /* Inlining of functions reducing size is a good idea regardless + of them being declared inline. */ flag_inline_functions = 1; /* We want to crossjump as much as possible. */ @@ -893,7 +1247,8 @@ print_specific_help (unsigned int include_flags, descrip_extra = lang_names [i]; } else - description = _("The following options are supported by, amoung others, the language "); + description = _("The following options are supported by the language "); + descrip_extra = lang_names [i]; break; } } @@ -966,6 +1321,10 @@ common_handle_option (size_t scode, const char *arg, int value, case OPT__target_help: print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0); exit_after_options = true; + + /* Allow the target a chance to give the user some additional information. */ + if (targetm.target_help) + targetm.target_help (); break; case OPT_fhelp_: @@ -983,7 +1342,8 @@ common_handle_option (size_t scode, const char *arg, int value, /* Walk along the argument string, parsing each word in turn. The format is: arg = [^]{word}[,{arg}] - word = {optimizers|target|warnings|undocumented|params} */ + word = {optimizers|target|warnings|undocumented| + params|common|} */ while (* a != 0) { static struct @@ -1000,6 +1360,7 @@ common_handle_option (size_t scode, const char *arg, int value, { "params", CL_PARAMS }, { "joined", CL_JOINED }, { "separate", CL_SEPARATE }, + { "common", CL_COMMON }, { NULL, 0 } }; unsigned int * pflags; @@ -1089,6 +1450,9 @@ common_handle_option (size_t scode, const char *arg, int value, break; case OPT_Wstrict_aliasing: + set_Wstrict_aliasing (value); + break; + case OPT_Wstrict_aliasing_: warn_strict_aliasing = value; break; @@ -1162,6 +1526,18 @@ common_handle_option (size_t scode, const char *arg, int value, fix_register (arg, 0, 0); break; + case OPT_fdbg_cnt_: + dbg_cnt_process_opt (arg); + break; + + case OPT_fdbg_cnt_list: + dbg_cnt_list_all_counters (); + break; + + case OPT_fdebug_prefix_map_: + add_debug_prefix_map (arg); + break; + case OPT_fdiagnostics_show_location_: if (!strcmp (arg, "once")) diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE; @@ -1185,6 +1561,10 @@ common_handle_option (size_t scode, const char *arg, int value, set_fast_math_flags (value); break; + case OPT_funsafe_math_optimizations: + set_unsafe_math_optimizations_flags (value); + break; + case OPT_ffixed_: fix_register (arg, 1, 1); break; @@ -1195,6 +1575,16 @@ common_handle_option (size_t scode, const char *arg, int value, set_param_value ("max-inline-insns-auto", value / 2); break; + case OPT_finstrument_functions_exclude_function_list_: + add_instrument_functions_exclude_list + (&flag_instrument_functions_exclude_functions, arg); + break; + + case OPT_finstrument_functions_exclude_file_list_: + add_instrument_functions_exclude_list + (&flag_instrument_functions_exclude_files, arg); + break; + case OPT_fmessage_length_: pp_set_line_maximum_length (global_dc->printer, value); break; @@ -1217,6 +1607,10 @@ common_handle_option (size_t scode, const char *arg, int value, profile_arc_flag_set = true; break; + case OPT_finline_functions: + flag_inline_functions_set = true; + break; + case OPT_fprofile_use: if (!flag_branch_probabilities_set) flag_branch_probabilities = value; @@ -1230,6 +1624,8 @@ common_handle_option (size_t scode, const char *arg, int value, flag_tracer = value; if (!flag_value_profile_transformations_set) flag_value_profile_transformations = value; + if (!flag_inline_functions_set) + flag_inline_functions = value; break; case OPT_fprofile_generate: @@ -1239,6 +1635,8 @@ common_handle_option (size_t scode, const char *arg, int value, flag_profile_values = value; if (!flag_value_profile_transformations_set) flag_value_profile_transformations = value; + if (!flag_inline_functions_set) + flag_inline_functions = value; break; case OPT_fprofile_values: @@ -1452,6 +1850,20 @@ set_Wunused (int setting) warn_unused_value = setting; } +/* Used to set the level of strict aliasing warnings, + when no level is specified (i.e., when -Wstrict-aliasing, and not + -Wstrict-aliasing=level was given). + ONOFF is assumed to take value 1 when -Wstrict-aliasing is specified, + and 0 otherwise. After calling this function, wstrict_aliasing will be + set to the default value of -Wstrict_aliasing=level, currently 3. */ +void +set_Wstrict_aliasing (int onoff) +{ + gcc_assert (onoff == 0 || onoff == 1); + if (onoff != 0) + warn_strict_aliasing = 3; +} + /* The following routines are useful in setting all the flags that -ffast-math and -fno-fast-math imply. */ void @@ -1459,6 +1871,8 @@ set_fast_math_flags (int set) { flag_trapping_math = !set; flag_unsafe_math_optimizations = set; + flag_associative_math = set; + flag_reciprocal_math = set; flag_finite_math_only = set; flag_signed_zeros = !set; flag_errno_math = !set; @@ -1470,6 +1884,15 @@ set_fast_math_flags (int set) } } +/* When -funsafe-math-optimizations is set the following + flags are set as well. */ +void +set_unsafe_math_optimizations_flags (int set) +{ + flag_reciprocal_math = set; + flag_associative_math = set; +} + /* Return true iff flags are set as if -ffast-math. */ bool fast_math_flags_set_p (void)