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)