aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaksit Ashok <raksit@google.com>2009-08-18 05:43:57 +0000
committerRaksit Ashok <raksit@google.com>2009-08-18 05:43:57 +0000
commitc00d5de9e4743e95c75cf7c76af3367e66162afd (patch)
tree2f33fed5dcb877bfbaba709f07b2fecba9aac551
parent905da5babc29f4498951834b97f5180ae2a6e414 (diff)
(1) Record relevant GCC command line options in the gcda file (-O*, -f*,
-W*, --param). (2) At profile-use time, if foo.cc imports bar.cc, compare the command line options that were used at profile-generate time for these two modules (these options are recorded in the gcda file), and decide if bar.cc would be compatible with foo.cc. (3) New warning option -Wripa-opt-mismatch emits a warning whenever we encounter auxiliary modules with mismatching options from the primary module (this warning is turned on by -Wall). (4) New option -fripa-disallow-opt-mismatch skips auxiliary modules with mismatching options from the primary module. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lw-ipo@150867 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/c-opts.c1
-rw-r--r--gcc/common.opt8
-rw-r--r--gcc/coverage.c183
-rw-r--r--gcc/doc/invoke.texi24
-rw-r--r--gcc/dyn-ipa.c5
-rw-r--r--gcc/gcov-io.c5
-rw-r--r--gcc/gcov-io.h1
-rw-r--r--gcc/opts.c33
-rw-r--r--gcc/opts.h9
9 files changed, 225 insertions, 44 deletions
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index b1343fef53e..1859534c9b3 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -388,6 +388,7 @@ c_common_handle_option (size_t scode, const char *arg, int value)
warn_missing_braces = value;
warn_parentheses = value;
warn_return_type = value;
+ warn_ripa_opt_mismatch = value;
warn_sequence_point = value; /* Was C only. */
warn_switch = value;
if (warn_strict_aliasing == -1)
diff --git a/gcc/common.opt b/gcc/common.opt
index d0ecea8a1aa..947eeb7b8ef 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -152,6 +152,10 @@ Wpadded
Common Var(warn_padded) Warning
Warn when padding is required to align structure members
+Wripa-opt-mismatch
+Common Var(warn_ripa_opt_mismatch) Warning
+Warn if primary and auxiliary modules have mismatched command line options
+
Wshadow
Common Var(warn_shadow) Warning
Warn when one local variable shadows another
@@ -482,6 +486,10 @@ fdump-unnumbered-links
Common Report Var(flag_dump_unnumbered_links) VarExists
Suppress output of previous and next insn numbers in debugging dumps
+fripa-disallow-opt-mismatch
+Common Report Var(flag_ripa_disallow_opt_mismatch)
+Don't import an auxiliary module if the command line options mismatch with the primary module
+
fearly-inlining
Common Report Var(flag_early_inlining) Init(1) Optimization
Perform early inlining
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 914e48691f4..4d22ca8d3a3 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -149,7 +149,7 @@ static tree build_ctr_info_type (void);
static tree build_ctr_info_value (unsigned, tree);
static tree build_gcov_info (void);
static void create_coverage (void);
-static void get_da_file_name (const char *);
+static char * get_da_file_name (const char *);
/* Return the type node for gcov_type. */
@@ -205,6 +205,70 @@ is_last_module (unsigned mod_id)
return (mod_id == module_infos[num_in_fnames - 1]->ident);
}
+/* Returns true if the command-line arguments stored in the given module-infos
+ are incompatible. */
+static bool
+incompatible_cl_args (struct gcov_module_info* mod_info1,
+ struct gcov_module_info* mod_info2)
+{
+ char **warning_opts1 = XNEWVEC (char *, mod_info1->num_cl_args);
+ char **warning_opts2 = XNEWVEC (char *, mod_info2->num_cl_args);
+ char **non_warning_opts1 = XNEWVEC (char *, mod_info1->num_cl_args);
+ char **non_warning_opts2 = XNEWVEC (char *, mod_info2->num_cl_args);
+ unsigned int i, num_warning_opts1 = 0, num_warning_opts2 = 0;
+ unsigned int num_non_warning_opts1 = 0, num_non_warning_opts2 = 0;
+ bool warning_mismatch = false;
+ bool non_warning_mismatch = false;
+ unsigned int start_index1 = mod_info1->num_quote_paths +
+ mod_info1->num_bracket_paths + mod_info1->num_cpp_defines;
+ unsigned int start_index2 = mod_info2->num_quote_paths +
+ mod_info2->num_bracket_paths + mod_info2->num_cpp_defines;
+
+ /* First, separate the warning and non-warning options. */
+ for (i = 0; i < mod_info1->num_cl_args; i++)
+ if (mod_info1->string_array[start_index1 + i][1] == 'W')
+ warning_opts1[num_warning_opts1++] =
+ mod_info1->string_array[start_index1 + i];
+ else
+ non_warning_opts1[num_non_warning_opts1++] =
+ mod_info1->string_array[start_index1 + i];
+
+ for (i = 0; i < mod_info2->num_cl_args; i++)
+ if (mod_info2->string_array[start_index2 + i][1] == 'W')
+ warning_opts2[num_warning_opts2++] =
+ mod_info2->string_array[start_index2 + i];
+ else
+ non_warning_opts2[num_non_warning_opts2++] =
+ mod_info2->string_array[start_index2 + i];
+
+ /* Compare warning options. If these mismatch, we emit a warning. */
+ if (num_warning_opts1 != num_warning_opts2)
+ warning_mismatch = true;
+ else
+ for (i = 0; i < num_warning_opts1 && !warning_mismatch; i++)
+ warning_mismatch = strcmp (warning_opts1[i], warning_opts2[i]) != 0;
+
+ /* Compare non-warning options. If these mismatch, we emit a warning, and if
+ -fripa-disallow-opt-mismatch is supplied, the two modules are also
+ incompatible. */
+ if (num_non_warning_opts1 != num_non_warning_opts2)
+ non_warning_mismatch = true;
+ else
+ for (i = 0; i < num_non_warning_opts1 && !non_warning_mismatch; i++)
+ non_warning_mismatch =
+ strcmp (non_warning_opts1[i], non_warning_opts2[i]) != 0;
+
+ if (warn_ripa_opt_mismatch && (warning_mismatch || non_warning_mismatch))
+ warning (OPT_Wripa_opt_mismatch, "command line arguments mismatch for %s "
+ "and %s", mod_info1->source_filename, mod_info2->source_filename);
+
+ XDELETEVEC (warning_opts1);
+ XDELETEVEC (warning_opts2);
+ XDELETEVEC (non_warning_opts1);
+ XDELETEVEC (non_warning_opts2);
+ return flag_ripa_disallow_opt_mismatch && non_warning_mismatch;
+}
+
/* Read in the counts file, if available. DA_FILE_NAME is the
name of the gcda file, and MODULE_ID is the module id of the
associated source module. */
@@ -377,16 +441,16 @@ read_counts_file (const char *da_file_name, unsigned module_id)
= (struct gcov_module_info *) alloca ((length + 2)
* sizeof (gcov_unsigned_t));
gcov_read_module_info (mod_info, length);
- module_infos_read++;
-
info_sz = (sizeof (struct gcov_module_info) +
sizeof (void *) * (mod_info->num_quote_paths +
mod_info->num_bracket_paths +
- mod_info->num_cpp_defines));
+ mod_info->num_cpp_defines +
+ mod_info->num_cl_args));
/* The first MODULE_INFO record must be for the primary module. */
- if (module_infos_read == 1)
+ if (module_infos_read == 0)
{
gcc_assert (mod_info->is_primary && !modset);
+ module_infos_read++;
modset = pointer_set_create ();
pointer_set_insert (modset, (void *)(size_t)mod_info->ident);
primary_module_id = mod_info->ident;
@@ -396,33 +460,49 @@ read_counts_file (const char *da_file_name, unsigned module_id)
}
else
{
+ int fd;
+ char *aux_da_filename = get_da_file_name (mod_info->da_filename);
gcc_assert (!mod_info->is_primary);
- if (!pointer_set_insert (modset, (void *)(size_t)mod_info->ident)
- /* Forbid mixed language LIPO for now. */
- && module_infos[0]->lang == mod_info->lang
- /* Debugging support. */
- && module_infos_read <= max_group)
+ if (pointer_set_insert (modset, (void *)(size_t)mod_info->ident))
+ inform (input_location, "Not importing %s: already imported",
+ mod_info->source_filename);
+ else if (module_infos[0]->lang != mod_info->lang)
+ inform (input_location, "Not importing %s: source language"
+ " different from primary module's source language",
+ mod_info->source_filename);
+ else if (module_infos_read == max_group)
+ inform (input_location, "Not importing %s: maximum group size"
+ " reached", mod_info->source_filename);
+ else if (incompatible_cl_args (module_infos[0], mod_info))
+ inform (input_location, "Not importing %s: command-line"
+ " arguments not compatible with primary module",
+ mod_info->source_filename);
+ else if ((fd = open (aux_da_filename, O_RDONLY)) < 0)
+ inform (input_location, "Not importing %s: couldn't open %s",
+ mod_info->source_filename, aux_da_filename);
+ else
{
+ close (fd);
+ module_infos_read++;
add_input_filename (mod_info->source_filename);
- module_infos = XRESIZEVEC (struct gcov_module_info *, module_infos,
- num_in_fnames);
- gcc_assert (num_in_fnames == module_infos_read);
- module_infos[module_infos_read - 1]
- = XCNEWVAR (struct gcov_module_info, info_sz);
- memcpy (module_infos[module_infos_read - 1], mod_info, info_sz);
+ module_infos = XRESIZEVEC (struct gcov_module_info *,
+ module_infos, num_in_fnames);
+ gcc_assert (num_in_fnames == module_infos_read);
+ module_infos[module_infos_read - 1]
+ = XCNEWVAR (struct gcov_module_info, info_sz);
+ memcpy (module_infos[module_infos_read - 1], mod_info,
+ info_sz);
}
- else
- module_infos_read--;
}
/* Debugging */
{
- fprintf (stderr,
- "MODULE Id=%d, Is_Primary=%s,"
- " Is_Exported=%s, Name=%s (%s)\n",
- mod_info->ident, mod_info->is_primary?"yes":"no",
- mod_info->is_exported?"yes":"no", mod_info->source_filename,
- mod_info->da_filename);
+ inform (input_location,
+ "MODULE Id=%d, Is_Primary=%s,"
+ " Is_Exported=%s, Name=%s (%s)",
+ mod_info->ident, mod_info->is_primary?"yes":"no",
+ mod_info->is_exported?"yes":"no", mod_info->source_filename,
+ mod_info->da_filename);
}
}
gcov_sync (offset, length);
@@ -1129,6 +1209,29 @@ build_cpp_def_array_value (tree string_type, tree cpp_def_value,
return cpp_def_value;
}
+/* Returns an array (tree) of command-line argument strings. STRING_TYPE is
+ the string type, CL_ARGS_VALUE is the initial value of the command-line
+ args array. */
+
+static tree
+build_cl_args_array_value (tree string_type, tree cl_args_value)
+{
+ unsigned int i;
+ for (i = 0; i < num_lipo_cl_args; i++)
+ {
+ int arg_length = strlen (lipo_cl_args[i]);
+ tree arg_string = build_string (arg_length + 1, lipo_cl_args[i]);
+ TREE_TYPE (arg_string) =
+ build_array_type (char_type_node,
+ build_index_type (build_int_cst (NULL_TREE,
+ arg_length)));
+ cl_args_value = tree_cons (NULL_TREE,
+ build1 (ADDR_EXPR, string_type, arg_string),
+ cl_args_value);
+ }
+ return cl_args_value;
+}
+
/* Returns the value of the module info associated with the
current source module being compiled. */
@@ -1254,11 +1357,20 @@ build_gcov_module_info_value (void)
value = tree_cons (field, build_int_cstu (get_gcov_unsigned_t (),
num_cpp_defines), value);
+ /* Num command-line args. */
+ field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
+ NULL_TREE, get_gcov_unsigned_t ());
+ TREE_CHAIN (field) = fields;
+ fields = field;
+ value = tree_cons (field, build_int_cstu (get_gcov_unsigned_t (),
+ num_lipo_cl_args), value);
+
/* string array */
index_type = build_index_type (build_int_cst (NULL_TREE,
num_quote_paths +
num_bracket_paths +
- num_cpp_defines));
+ num_cpp_defines +
+ num_lipo_cl_args));
string_array_type = build_array_type (string_type, index_type);
string_array = build_inc_path_array_value (string_type, string_array,
quote_paths, num_quote_paths);
@@ -1266,6 +1378,7 @@ build_gcov_module_info_value (void)
bracket_paths, num_bracket_paths);
string_array = build_cpp_def_array_value (string_type, string_array,
cpp_defines_head);
+ string_array = build_cl_args_array_value (string_type, string_array);
string_array = build_constructor_from_list (string_array_type,
nreverse (string_array));
field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
@@ -1500,9 +1613,10 @@ create_coverage (void)
/* Get the da file name, given base file name. */
-void
+static char *
get_da_file_name (const char *base_file_name)
{
+ char *da_file_name;
int len = strlen (base_file_name);
const char *prefix = profile_data_prefix;
/* + 1 for extra '/', in case prefix doesn't end with /. */
@@ -1516,7 +1630,6 @@ get_da_file_name (const char *base_file_name)
/* Name of da file. */
da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
+ prefix_len + 1);
- da_base_file_name = XNEWVEC (char, len + 1);
if (prefix)
{
@@ -1528,7 +1641,7 @@ get_da_file_name (const char *base_file_name)
da_file_name[0] = 0;
strcat (da_file_name, base_file_name);
strcat (da_file_name, GCOV_DATA_SUFFIX);
- strcpy (da_base_file_name, base_file_name);
+ return da_file_name;
}
/* Rebuild counts_hash already built the primary module. This hashtable
@@ -1640,7 +1753,9 @@ coverage_init (const char *filename, const char* source_name)
int src_name_prefix_len = 0;
int len = strlen (filename);
- get_da_file_name (filename);
+ da_file_name = get_da_file_name (filename);
+ da_base_file_name = XNEWVEC (char, strlen (filename) + 1);
+ strcpy (da_base_file_name, filename);
/* Name of bbg file. */
bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
@@ -1670,17 +1785,11 @@ coverage_init (const char *filename, const char* source_name)
if (flag_profile_use && L_IPO_COMP_MODE)
{
unsigned i;
- char *da_file_name_p = da_file_name;
- char *da_base_file_name_p = da_base_file_name;
gcc_assert (flag_dyn_ipa);
rebuild_counts_hash ();
for (i = 1; i < num_in_fnames; i++)
- {
- get_da_file_name (module_infos[i]->da_filename);
- read_counts_file (da_file_name, module_infos[i]->ident);
- }
- da_file_name = da_file_name_p;
- da_base_file_name = da_base_file_name_p;
+ read_counts_file (get_da_file_name (module_infos[i]->da_filename),
+ module_infos[i]->ident);
}
}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 77568998a44..84018510b46 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -253,7 +253,7 @@ Objective-C and Objective-C++ Dialects}.
-Wparentheses -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
-Wpointer-arith -Wno-pointer-to-int-cast @gol
-Wredundant-decls @gol
--Wreturn-type -Wsequence-point -Wshadow @gol
+-Wreturn-type -Wripa-opt-mismatch -Wsequence-point -Wshadow @gol
-Wsign-compare -Wsign-conversion -Wstack-protector @gol
-Wstrict-aliasing -Wstrict-aliasing=n @gol
-Wstrict-overflow -Wstrict-overflow=@var{n} @gol
@@ -333,7 +333,7 @@ Objective-C and Objective-C++ Dialects}.
-fcheck-data-deps -fconserve-stack -fcprop-registers -fcrossjumping @gol
-fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules -fcx-limited-range @gol
-fdata-sections -fdce -fdce @gol
--fdelayed-branch -fdelete-null-pointer-checks -fdse -fdse -fripa @gol
+-fdelayed-branch -fdelete-null-pointer-checks -fdse -fdse @gol
-fearly-inlining -fexpensive-optimizations -ffast-math @gol
-ffinite-math-only -ffloat-store -fexcess-precision=@var{style} @gol
-fforward-propagate -ffunction-sections @gol
@@ -363,7 +363,7 @@ Objective-C and Objective-C++ Dialects}.
-freciprocal-math -fregmove -frename-registers -freorder-blocks @gol
-freorder-blocks-and-partition -freorder-functions @gol
-frerun-cse-after-loop -freschedule-modulo-scheduled-loops @gol
--frounding-math -fsched2-use-superblocks @gol
+-fripa -fripa-disallow-opt-mismatch -frounding-math -fsched2-use-superblocks @gol
-fsched2-use-traces -fsched-spec-load -fsched-spec-load-dangerous @gol
-fsched-stalled-insns-dep[=@var{n}] -fsched-stalled-insns[=@var{n}] @gol
-fsched-group-heuristic -fsched-critical-path-heuristic @gol
@@ -2803,6 +2803,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-Wpointer-sign @gol
-Wreorder @gol
-Wreturn-type @gol
+-Wripa-opt-mismatch @gol
-Wsequence-point @gol
-Wsign-compare @r{(only in C++)} @gol
-Wstrict-aliasing @gol
@@ -3207,6 +3208,16 @@ exceptions are @samp{main} and functions defined in system headers.
This warning is enabled by @option{-Wall}.
+@item -Wripa-opt-mismatch
+@opindex Wripa-opt-mismatch
+@opindex Wno-ripa-opt-mismatch
+When doing an FDO build with @option{-fprofile-use} and @option{-fripa},
+warn if importing an axuiliary module that was built with a different
+GCC command line during the profile-generate phase than the primary
+module.
+
+This warning is enabled by @option{-Wall}.
+
@item -Wswitch
@opindex Wswitch
@opindex Wno-switch
@@ -7103,6 +7114,13 @@ During the @option{-fprofile-generate} phase, this flag turns on some additional
instrumentation code that enables dynamic call-graph analysis.
During the @option{-fprofile-use} phase, this flag enables cross-module
optimizations such as inlining.
+
+@item -fripa-disallow-opt-mismatch
+@opindex fripa-disallow-opt-mismatch
+Don't import an auxiliary module, if the GCC command line options used for this
+auxiliary module during the profile-generate stage were different from those used
+for the primary module. Note that any mismatches in warning-related options are
+ignored for this comparison.
@end table
The following options control compiler behavior regarding floating
diff --git a/gcc/dyn-ipa.c b/gcc/dyn-ipa.c
index 99b7fd25adb..9353535f780 100644
--- a/gcc/dyn-ipa.c
+++ b/gcc/dyn-ipa.c
@@ -1011,7 +1011,7 @@ gcov_write_module_info (const struct gcov_info *mod_info,
len += 2; /* each name string is led by a length. */
num_strings = module_info->num_quote_paths + module_info->num_bracket_paths +
- module_info->num_cpp_defines;
+ module_info->num_cpp_defines + module_info->num_cl_args;
for (i = 0; i < num_strings; i++)
{
gcov_unsigned_t string_len
@@ -1021,7 +1021,7 @@ gcov_write_module_info (const struct gcov_info *mod_info,
len += 1; /* Each string is lead by a length. */
}
- len += 7; /* 7 more fields */
+ len += 8; /* 8 more fields */
gcov_write_tag_length (GCOV_TAG_MODULE_INFO, len);
gcov_write_unsigned (module_info->ident);
@@ -1031,6 +1031,7 @@ gcov_write_module_info (const struct gcov_info *mod_info,
gcov_write_unsigned (module_info->num_quote_paths);
gcov_write_unsigned (module_info->num_bracket_paths);
gcov_write_unsigned (module_info->num_cpp_defines);
+ gcov_write_unsigned (module_info->num_cl_args);
/* Now write the filenames */
aligned_fname = (gcov_unsigned_t *) alloca ((filename_len + src_filename_len + 2) *
diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c
index 1e351f1cb3b..833f7ae1215 100644
--- a/gcc/gcov-io.c
+++ b/gcc/gcov-io.c
@@ -511,7 +511,8 @@ gcov_read_module_info (struct gcov_module_info *mod_info,
mod_info->num_quote_paths = gcov_read_unsigned ();
mod_info->num_bracket_paths = gcov_read_unsigned ();
mod_info->num_cpp_defines = gcov_read_unsigned ();
- len -= 7;
+ mod_info->num_cl_args = gcov_read_unsigned ();
+ len -= 8;
filename_len = gcov_read_unsigned ();
mod_info->da_filename = (char *) xmalloc (filename_len *
@@ -528,7 +529,7 @@ gcov_read_module_info (struct gcov_module_info *mod_info,
len -= (src_filename_len + 1);
num_strings = mod_info->num_quote_paths + mod_info->num_bracket_paths +
- mod_info->num_cpp_defines;
+ mod_info->num_cpp_defines + mod_info->num_cl_args;
for (j = 0; j < num_strings; j++)
{
gcov_unsigned_t string_len = gcov_read_unsigned ();
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index e88db363069..4fccc63e0a3 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -470,6 +470,7 @@ struct gcov_module_info
gcov_unsigned_t num_quote_paths;
gcov_unsigned_t num_bracket_paths;
gcov_unsigned_t num_cpp_defines;
+ gcov_unsigned_t num_cl_args;
char *string_array[1];
};
diff --git a/gcc/opts.c b/gcc/opts.c
index cb43729edac..cc0bff14ac9 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -731,6 +731,37 @@ flag_instrument_functions_exclude_p (tree fndecl)
return false;
}
+/* GCC command-line options saved to the LIPO profile data file.
+ See detailed comment in opts.h. */
+const char **lipo_cl_args;
+unsigned num_lipo_cl_args;
+
+/* Inspect the given GCC command-line arguments, which are part of one GCC
+ switch, and decide whether or not to store these to the LIPO profile data
+ file. */
+static void
+lipo_save_cl_args (unsigned int argc, const char **argv)
+{
+ unsigned int i;
+ const char *opt = argv[0];
+ /* Store the following command-line flags to the lipo profile data file:
+ (1) -f... (except -frandom-seed...)
+ (2) -m...
+ (3) -W...
+ (4) -O...
+ (5) --param...
+ */
+ if (opt[0] == '-'
+ && (opt[1] == 'f' || opt[1] == 'm' || opt[1] == 'W' || opt[1] == 'O'
+ || (strstr (opt, "--param") == opt))
+ && !strstr(opt, "-frandom-seed"))
+ {
+ num_lipo_cl_args += argc;
+ lipo_cl_args = XRESIZEVEC (const char *, lipo_cl_args, num_lipo_cl_args);
+ for (i = 0; i < argc; i++)
+ lipo_cl_args[num_lipo_cl_args - argc + i] = argv[i];
+ }
+}
/* Decode and handle the vector of command line options. LANG_MASK
contains has a single bit set representing the current
@@ -766,6 +797,8 @@ handle_options (unsigned int argc, const char **argv, unsigned int lang_mask)
n = handle_option (argv + i, lang_mask);
+ lipo_save_cl_args (n, argv + i);
+
if (!n)
{
n = 1;
diff --git a/gcc/opts.h b/gcc/opts.h
index 7a13fb705cf..590f6c14a71 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -98,6 +98,15 @@ extern const char **in_fnames;
extern unsigned num_in_fnames;
+/* GCC command-line arguments used during profile-gen, that are saved to the
+ profile data file. During profile-use, these can be compared to make sure
+ only those auxiliary modules are actually imported that use a compatible
+ set of GCC flags as the primary module. */
+extern const char **lipo_cl_args;
+
+/* The size of the above mentioned mentioned array. */
+extern unsigned num_lipo_cl_args;
+
size_t find_opt (const char *input, int lang_mask);
extern void prune_options (int *argcp, char ***argvp);
extern void decode_options (unsigned int argc, const char **argv);