Index: gcc/gcc/gcc.c =================================================================== --- gcc/gcc/gcc.c (revision 140444) +++ gcc/gcc/gcc.c (working copy) @@ -232,12 +232,9 @@ static int combine_flag = 0; static int use_pipes; -/* Nonzero means we are running in lto-single mode, and each object file - resulting from a compilation should be immediately recompiled using - the LTO back end. This makes it easy to exercise the LTO by adding - a single switch to existing makefiles. */ +/* A string describing the mode in which we run the LTO back-end. */ -static int lto_single; +static char *lto_mode; /* The compiler version. */ @@ -384,6 +381,9 @@ static const char *version_compare_spec_ static const char *include_spec_function (int, const char **); static const char *print_asm_header_spec_function (int, const char **); static const char *lto_single_spec_function (int, const char **); +static const char *lto_mode_spec_function (int, const char **); +static const char *lto_linker_options_spec_function (int, const char **); +static const char *lto1_options_spec_function (int, const char **); /* The Specs Language @@ -748,7 +748,7 @@ proper position among the other output f #ifndef LINK_COMMAND_SPEC #define LINK_COMMAND_SPEC "\ %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ - %(linker) %{flto} %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ + %(linker) %:linker-lto-mode() %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\ @@ -847,7 +847,7 @@ static const char *cpp_debug_options = " /* NB: This is shared amongst all front-ends. */ /* FIXME lto: -O2 is needed as a temporary workaround. Remove. */ -static const char *cc1_options = +static const char *cc1_non_lto_options = "%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\ %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\ @@ -859,19 +859,25 @@ static const char *cc1_options = %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ %{fsyntax-only:-o %j} %{-param*}\ %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\ - %{coverage:-fprofile-arcs -ftest-coverage}\ - %{flto:-O2} %{?lto-single():-O2} %{?lto-single():-flto}"; + %{coverage:-fprofile-arcs -ftest-coverage} "; + +/* This is the front-end optiob shared by all front-end except lto1. */ +static const char *cc1_options = +"%(cc1_non_lto_options)\ + %{?lto-mode():-O2 -flto-mode=lgen} "; /* Do we need to preserve any assembler options here? Note that we are going to ignore the object code, as we are only interested in the .lto_info sections. */ static const char *invoke_lto_single = #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT -"%{?lto-single(): -o %|.lto.s |\n as %(asm_options) %|.lto.s -o %g.lto.o \n\ - lto1 %(cc1_options) %g.lto.o }"; +"%{?lto-single(): -o %|.lto.s |\n\ + as %(asm_options) %|.lto.s -o %g.lto.o \n\ + lto1 %(cc1_non_lto_options) -flto-mode=normal %g.lto.o }"; #else -"%{?lto-single(): -o %|.lto.s |\n as %(asm_options) %m.lto.s -o %g.lto.o \n\ - lto1 %(cc1_options) %g.lto.o }"; +"%{?lto-single(): -o %|.lto.s |\n\ + as %(asm_options) %m.lto.s -o %g.lto.o \n\ + lto1 %(cc1_non_lto_options) -flto-mode=normal %g.lto.o }"; #endif static const char *asm_options = @@ -1625,6 +1631,7 @@ static struct spec_list static_specs[] = INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options), INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp), INIT_STATIC_SPEC ("cc1", &cc1_spec), + INIT_STATIC_SPEC ("cc1_non_lto_options", &cc1_non_lto_options), INIT_STATIC_SPEC ("cc1_options", &cc1_options), INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec), @@ -1686,6 +1693,9 @@ static const struct spec_function static { "include", include_spec_function }, { "print-asm-header", print_asm_header_spec_function }, { "lto-single", lto_single_spec_function }, + { "lto-mode", lto_mode_spec_function }, + { "linker-lto-mode", lto_linker_options_spec_function }, + { "lto1-options", lto1_options_spec_function }, #ifdef EXTRA_SPEC_FUNCTIONS EXTRA_SPEC_FUNCTIONS #endif @@ -3367,6 +3377,25 @@ add_linker_option (const char *option, i linker_options [n_linker_options - 1] = save_string (option, len); } + +/* Single is not a real LTO FE mode. */ +static void +set_lto_mode (const char *mode) +{ + if (!strcmp (mode, "lgen") + || !strcmp (mode, "normal") + || !strcmp (mode, "wpa") + || !strcmp (mode, "ltran") + || !strcmp (mode, "single")) + { + if (lto_mode) + free (lto_mode); + lto_mode = xstrdup (mode); + } + else + error ("Unrecognized LTO mode '%s'.", mode); +} + /* Create the vector `switches' and its contents. Store its length in `n_switches'. */ @@ -3864,8 +3893,12 @@ warranty; not even for MERCHANTABILITY o n_switches++; n_switches++; } + else if (strcmp (argv[i], "-flto") == 0) + set_lto_mode ("lgen"); else if (strcmp (argv[i], "-flto-single") == 0) - lto_single = 1; + set_lto_mode ("single"); + else if (strncmp (argv[i], "-flto-mode=", 11) == 0) + set_lto_mode (argv[i] + 11); else if (strcmp (argv[i], "-###") == 0) { /* This is similar to -v except that there is no execution @@ -4241,6 +4274,10 @@ warranty; not even for MERCHANTABILITY o ; else if (strcmp (argv[i], "-time") == 0) ; + else if (strcmp (argv[i], "-flto") == 0) + ; + else if (strncmp (argv[i], "-flto-mode=", 11) == 0) + ; else if (strcmp (argv[i], "-flto-single") == 0) ; else if (strcmp (argv[i], "-###") == 0) @@ -8198,5 +8235,61 @@ lto_single_spec_function (int argc, if (argc != 0) abort (); - return ((lto_single) ? "lto-single" : NULL); + return ((lto_mode && !strcmp (lto_mode, "single")) ? "lto-single" : NULL); +} + +/* Return the last set value of lto_mode or NULL if it is not set. */ + +static const char * +lto_mode_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED) +{ + if (argc != 0) + abort (); + + return lto_mode; +} + +/* Expand to appropriate linker LTO option. ARGV is an array of ARGC + strings. */ + +static const char * +lto_linker_options_spec_function (int argc, + const char **argv ATTRIBUTE_UNUSED) +{ + if (argc != 0) + abort (); + + if (!lto_mode) + return NULL; + else if (!strcmp (lto_mode, "single")) + return NULL; + else if (!strcmp (lto_mode, "lgen") || !strcmp (lto_mode, "normal")) + return "-flto-mode=normal"; + else if (!strcmp (lto_mode, "wpa")) + return "-flto-mode=wpa"; + else + gcc_unreachable (); +} + +/* Expand to appropriate front-end LTO option. ARGV is an array of input + ARGC file names. */ + +static const char * +lto1_options_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED) +{ + if (argc != 0) + abort (); + + gcc_assert (lto_mode); + + /* Single mode is handle specially. */ + if (!strcmp (lto_mode, "single")) + return NULL; + + if (!strcmp (lto_mode, "wpa")) + return "-flto-mode=wpa"; + else if (!strcmp (lto_mode, "ltran")) + return "-flto-mode=ltran"; + else + return "-flto-mode=normal"; } Index: gcc/gcc/lto-function-out.c =================================================================== --- gcc/gcc/lto-function-out.c (revision 140444) +++ gcc/gcc/lto-function-out.c (working copy) @@ -50,6 +50,7 @@ Boston, MA 02110-1301, USA. */ #include "lto-section-in.h" #include "lto-section-out.h" #include "lto-tree-out.h" +#include "langhooks.h" sbitmap lto_flags_needed_for; sbitmap lto_types_needed_for; @@ -2399,7 +2400,7 @@ lto_output (cgraph_node_set set) { decl_state = lto_new_out_decl_state (); lto_push_out_decl_state (decl_state); - if (!flag_wpa) + if (lang_hooks.lto.get_mode () != LTO_MODE_WPA) output_function (node); else copy_function (node); Index: gcc/gcc/toplev.c =================================================================== --- gcc/gcc/toplev.c (revision 140444) +++ gcc/gcc/toplev.c (working copy) @@ -1029,7 +1029,7 @@ compile_file (void) process_pending_assemble_externals (); /* Emit LTO marker if LTO info has been previously emitted. */ - if (flag_generate_lto) + if (lto_mode_generate_lto_p (lang_hooks.lto.get_mode ())) fprintf (asm_out_file,".globl\tgnu_lto_v1\n"); /* Attach a special .ident directive to the end of the file to identify Index: gcc/gcc/cp/cp-lang.c =================================================================== --- gcc/gcc/cp/cp-lang.c (revision 140444) +++ gcc/gcc/cp/cp-lang.c (working copy) @@ -37,6 +37,8 @@ enum c_language_kind c_language = clk_cx static void cp_init_ts (void); static const char * cxx_dwarf_name (tree t, int verbosity); static enum classify_record cp_classify_record (tree type); +static int cp_get_lto_mode (void); +static void cp_set_lto_mode (int); /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h; consequently, there should be very few hooks below. */ @@ -57,6 +59,10 @@ static enum classify_record cp_classify_ #define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref #undef LANG_HOOKS_INIT_TS #define LANG_HOOKS_INIT_TS cp_init_ts +#undef LANG_HOOKS_GET_MODE +#define LANG_HOOKS_GET_MODE cp_get_lto_mode +#undef LANG_HOOKS_SET_MODE +#define LANG_HOOKS_SET_MODE cp_set_lto_mode /* Each front end provides its own lang hook initializer. */ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; @@ -129,4 +135,23 @@ finish_file (void) { } +/* Hooks to handle LTO modes */ + +static int lto_mode = LTO_MODE_NOT_LTO; + +static int +cp_get_lto_mode (void) +{ + return lto_mode; +} + +static void +cp_set_lto_mode (int mode) +{ + if (mode == LTO_MODE_LGEN || mode == LTO_MODE_NOT_LTO) + lto_mode = mode; + else + error ("Unsupported LTO mode."); +} + #include "gtype-cp.h" Index: gcc/gcc/lto-cgraph.c =================================================================== --- gcc/gcc/lto-cgraph.c (revision 140444) +++ gcc/gcc/lto-cgraph.c (working copy) @@ -81,7 +81,8 @@ output_edge (struct lto_simple_output_bl LTO_DEBUG_FN_NAME (edge->callee->decl); LTO_DEBUG_TOKEN ("stmt"); - uid = flag_wpa ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt); + uid = (lang_hooks.lto.get_mode () == LTO_MODE_WPA + ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt)); lto_output_uleb128_stream (ob->main_stream, uid); LTO_DEBUG_TOKEN ("count"); lto_output_uleb128_stream (ob->main_stream, edge->count); Index: gcc/gcc/ipa-inline.c =================================================================== --- gcc/gcc/ipa-inline.c (revision 140444) +++ gcc/gcc/ipa-inline.c (working copy) @@ -425,7 +425,7 @@ cgraph_default_inline_p (struct cgraph_n } if (!DECL_STRUCT_FUNCTION (decl)->cfg - && !flag_wpa) + && lang_hooks.lto.get_mode () != LTO_MODE_WPA) { if (reason) *reason = CIF_BODY_NOT_AVAILABLE; Index: gcc/gcc/opts.c =================================================================== --- gcc/gcc/opts.c (revision 140444) +++ gcc/gcc/opts.c (working copy) @@ -1048,7 +1048,8 @@ decode_options (unsigned int argc, const /* FIXME lto: With -flto, debug information will be incomplete or inaccurate, or worse, may be sufficiently corrupt as to crash the debug info writer. */ - if (flag_generate_lto && debug_info_level != DINFO_LEVEL_NONE) + if (lto_mode_generate_lto_p (lang_hooks.lto.get_mode ()) + && debug_info_level != DINFO_LEVEL_NONE) inform (input_location, "-g is presently unsupported with -flto"); /* Set flag_no_inline before the post_options () hook. The C front @@ -1779,6 +1780,19 @@ common_handle_option (size_t scode, cons (&flag_instrument_functions_exclude_files, arg); break; + case OPT_flto_mode_: + if (!strcmp(arg, "lgen")) + lang_hooks.lto.set_mode (LTO_MODE_LGEN); + else if (!strcmp(arg, "normal")) + lang_hooks.lto.set_mode (LTO_MODE_NORMAL); + else if (!strcmp(arg, "wpa")) + lang_hooks.lto.set_mode (LTO_MODE_WPA); + else if (!strcmp(arg, "ltran")) + lang_hooks.lto.set_mode (LTO_MODE_LTRAN); + else + error ("unrecognized LTO mode \"%s\"", arg); + break; + case OPT_fmessage_length_: pp_set_line_maximum_length (global_dc->printer, value); break; Index: gcc/gcc/langhooks.c =================================================================== --- gcc/gcc/langhooks.c (revision 140444) +++ gcc/gcc/langhooks.c (working copy) @@ -647,3 +647,22 @@ lhd_end_section (void) saved_section = NULL; } } + +/* Get the current mode of the LTO FE. The default implementation is + to return LTO_MODE_NOT_LTO. */ + +int +lhd_get_mode (void) +{ + return LTO_MODE_NOT_LTO; +} + +/* Set the current mode of the LTO FE. The default implementation is + reports error for any value other than LTO_MODE_NOT_LTO. */ + +void +lhd_set_mode (int mode) +{ + if (mode != LTO_MODE_NOT_LTO) + error ("Unsupported LTO mode."); +} Index: gcc/gcc/langhooks.h =================================================================== --- gcc/gcc/langhooks.h (revision 140444) +++ gcc/gcc/langhooks.h (working copy) @@ -220,6 +220,36 @@ struct lang_hooks_for_decls void (*omp_finish_clause) (tree clause); }; +/* Different modes of LTO operations. The modes are: + + NOT_LTO: FE is not doing any LTO operations. This is the default + return value of the get_mode hook. + + LGEN: FE is generating local informatio. The is used by + all FE supporting LTO. + + The following are only used by lto1. + + NORMAL: lto1 reads LGEN output file(s) and produce a .S file. + WPA: lto1 reads LGEN output file(s) and produce a Makefile fragment + and a number of WPA object files. + LTRAN: lto1 reads an WPA output file and produce a .S file. +*/ + +#define LTO_MODE_NOT_LTO 0 +#define LTO_MODE_LGEN 1 +#define LTO_MODE_NORMAL 2 +#define LTO_MODE_WPA 3 +#define LTO_MODE_LTRAN 4 + +/* Return true if we output LTO IR information. */ + +static inline bool +lto_mode_generate_lto_p (int mode) +{ + return mode == LTO_MODE_LGEN || mode == LTO_MODE_WPA; +} + /* Language hooks related to LTO serialization. */ struct lang_hooks_for_lto @@ -235,6 +265,13 @@ struct lang_hooks_for_lto /* End the previously begun LTO section. */ void (*end_section) (void); + + /* Get current mode of FE. Returns LTO_MODE_NOT_LTO if FE does not + support LTO. */ + int (*get_mode) (void); + + /* Set current mode of FE. NOP if FE does not support LTO. */ + void (*set_mode) (int); }; /* Language-specific hooks. See langhooks-def.h for defaults. */ Index: gcc/gcc/lto/lto.c =================================================================== --- gcc/gcc/lto/lto.c (revision 140444) +++ gcc/gcc/lto/lto.c (working copy) @@ -84,7 +84,7 @@ lto_materialize_function (struct cgraph_ DECL_EXTERNAL (decl) = 0; allocate_struct_function (decl, false); - if (!flag_wpa) + if (lang_hooks.lto.get_mode () != LTO_MODE_WPA) lto_input_function_body (file_data, decl, data); fn = DECL_STRUCT_FUNCTION (decl); lto_free_section_data (file_data, LTO_section_function_body, name, @@ -608,7 +608,7 @@ lto_main (int debug_p ATTRIBUTE_UNUSED) ipa_read_summaries (); - if (flag_wpa) + if (lto_get_mode () == LTO_MODE_WPA) lto_1_to_1_map (); /* Now that we have input the cgraph, we need to clear all of the aux @@ -645,23 +645,10 @@ lto_main (int debug_p ATTRIBUTE_UNUSED) /*top_level=*/1, /*at_end=*/0); - /* This is some bogus wrapper code for development testing. It will be - replaced once some basic WPA partitioning logic is implemented. To use - this pass "-flto -fsyntax-only" to the lto1 invocation. */ - if (flag_generate_lto) - { - lto_file *file; - - file = lto_elf_file_open ("bogus.lto.o", /*writable=*/true); - if (!file) - fatal_error ("lto_elf_file_open() failed"); - lto_set_current_out_file (file); - } - /* Let the middle end know that we have read and merged all of the input files. */ /*cgraph_finalize_compilation_unit ();*/ - if (!flag_wpa) + if (lang_hooks.lto.get_mode () != LTO_MODE_WPA) cgraph_optimize (); else { @@ -686,17 +673,7 @@ lto_main (int debug_p ATTRIBUTE_UNUSED) bitmap_obstack_release (NULL); } - /* This is the continuation of the previous bogus wrapper code. It will be - replaced once some basic WPA partitioning logic is implemented. */ - if (flag_generate_lto) - { - lto_file *file; - - file = lto_set_current_out_file (NULL); - lto_elf_file_close (file); - } - - if (flag_wpa) + if (lto_get_mode () == LTO_MODE_WPA) { lto_wpa_write_files (); } Index: gcc/gcc/lto/lang-specs.h =================================================================== --- gcc/gcc/lto/lang-specs.h (revision 140444) +++ gcc/gcc/lto/lang-specs.h (working copy) @@ -23,5 +23,5 @@ Boston, MA 02110-1301, USA. */ {".lto", "@lto", /*cpp_spec=*/NULL, /*combinable=*/1, /*needs_preprocessing=*/0}, - {"@lto", "lto1 %(cc1_options) %i %{!fsyntax-only:%(invoke_as)}", + {"@lto", "lto1 %(cc1_non_lto_options) %:lto1-options() %i %{!fsyntax-only:%(invoke_as)}", /*cpp_spec=*/NULL, /*combinable=*/1, /*needs_preprocessing=*/0}, Index: gcc/gcc/lto/lto.h =================================================================== --- gcc/gcc/lto/lto.h (revision 140444) +++ gcc/gcc/lto/lto.h (working copy) @@ -68,6 +68,8 @@ extern htab_t lto_elf_build_section_tabl extern void lto_elf_begin_section (const char *name); extern void lto_elf_append_data (const void *data, size_t len, void *block); extern void lto_elf_end_section (void); +extern int lto_get_mode (void); +extern void lto_set_mode (int); /* Routines for setting/getting the current output file. */ extern lto_file *lto_set_current_out_file (lto_file *file); Index: gcc/gcc/lto/lto-lang.c =================================================================== --- gcc/gcc/lto/lto-lang.c (revision 140444) +++ gcc/gcc/lto/lto-lang.c (working copy) @@ -947,10 +947,6 @@ lto_init_eh (void) static bool lto_init (void) { - /* FIXME lto, collect2 is calling lto1 with -flto. This is useless, - we don't need to emit LTO again from lto1. */ - flag_generate_lto = 0; - /* Initialize libcpp line maps for gcc_assert to work. */ linemap_add (line_table, LC_RENAME, 0, NULL, 0); @@ -1057,6 +1053,10 @@ static void lto_init_ts (void) #define LANG_HOOKS_APPEND_DATA lto_elf_append_data #undef LANG_HOOKS_END_SECTION #define LANG_HOOKS_END_SECTION lto_elf_end_section +#undef LANG_HOOKS_GET_MODE +#define LANG_HOOKS_GET_MODE lto_get_mode +#undef LANG_HOOKS_SET_MODE +#define LANG_HOOKS_SET_MODE lto_set_mode #undef LANG_HOOKS_INIT_TS #define LANG_HOOKS_INIT_TS lto_init_ts @@ -1079,6 +1079,32 @@ lto_tree_node_structure (union lang_tree return TS_LTO_GENERIC; } +/* Language hooks for handling LTO modes. */ + +static int lto_current_mode; + +int +lto_get_mode (void) +{ + return lto_current_mode; +} + +void +lto_set_mode (int mode) +{ + switch (mode) + { + case LTO_MODE_LGEN: + case LTO_MODE_NORMAL: + case LTO_MODE_WPA: + case LTO_MODE_LTRAN: + lto_current_mode = mode; + break; + default: + gcc_unreachable (); + } +} + #include "ggc.h" #include "gtype-lto.h" #include "gt-lto-lto-lang.h" Index: gcc/gcc/common.opt =================================================================== --- gcc/gcc/common.opt (revision 140444) +++ gcc/gcc/common.opt (working copy) @@ -717,9 +717,10 @@ floop-optimize Common Does nothing. Preserved for backward compatibility. -flto -Common Var(flag_generate_lto) -Causes Link Time Optimization to be written into the object file. +flto-mode= +Common Joined RejectNegative +-flto-mode=[lgen|normal|wpa|ltran] Run FE in LTO mode. + fmath-errno Common Report Var(flag_errno_math) Init(1) Optimization @@ -1356,10 +1357,6 @@ fwhole-program Common Report Var(flag_whole_program) Init(0) Optimization Perform whole program optimizations -fwpa -Common Report Var(flag_wpa) Init(0) Optimization -Run LTO in WPA mode - fwrapv Common Report Var(flag_wrapv) Optimization Assume signed arithmetic overflow wraps around Index: gcc/gcc/Makefile.in =================================================================== --- gcc/gcc/Makefile.in (revision 140444) +++ gcc/gcc/Makefile.in (working copy) @@ -2076,7 +2076,7 @@ lto-function-out.o : lto-function-out.c tree-pass.h tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) \ except.h debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def \ lto-tree-tags.def lto-tags.h lto-header.h $(LTO_SECTION_OUT_H) output.h \ - dwarf2asm.h dwarf2out.h $(LTO_SECTION_IN_H) + dwarf2asm.h dwarf2out.h $(LTO_SECTION_IN_H) langhooks.h lto-section-in.o: lto-section-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TOPLEV_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h $(VARRAY_H) \ $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h tree-pass.h \ Index: gcc/gcc/passes.c =================================================================== --- gcc/gcc/passes.c (revision 140444) +++ gcc/gcc/passes.c (working copy) @@ -1379,7 +1379,8 @@ ipa_write_summaries (void) cgraph_node_set set; struct cgraph_node *node; - if (flag_generate_lto && !(errorcount || sorrycount)) + if (lto_mode_generate_lto_p (lang_hooks.lto.get_mode ()) + && !(errorcount || sorrycount)) { set = cgraph_node_set_new (); for (node = cgraph_nodes; node; node = node->next) @@ -1392,7 +1393,8 @@ ipa_write_summaries (void) void ipa_write_summaries_of_cgraph_node_set (cgraph_node_set set) { - if (flag_generate_lto && !(errorcount || sorrycount)) + if (lto_mode_generate_lto_p (lang_hooks.lto.get_mode ()) + && !(errorcount || sorrycount)) ipa_write_summaries_1 (all_ipa_passes, set); } Index: gcc/gcc/c-lang.c =================================================================== --- gcc/gcc/c-lang.c (revision 140444) +++ gcc/gcc/c-lang.c (working copy) @@ -35,6 +35,10 @@ along with GCC; see the file COPYING3. #include "c-pragma.h" enum c_language_kind c_language = clk_c; +static int lto_mode = LTO_MODE_NOT_LTO; + +static int c_get_lto_mode (void); +static void c_set_lto_mode (int); /* Lang hooks common to C and ObjC are declared in c-objc-common.h; consequently, there should be very few hooks below. */ @@ -43,6 +47,10 @@ enum c_language_kind c_language = clk_c; #define LANG_HOOKS_NAME "GNU C" #undef LANG_HOOKS_INIT #define LANG_HOOKS_INIT c_objc_common_init +#undef LANG_HOOKS_GET_MODE +#define LANG_HOOKS_GET_MODE c_get_lto_mode +#undef LANG_HOOKS_SET_MODE +#define LANG_HOOKS_SET_MODE c_set_lto_mode /* Each front end provides its own lang hook initializer. */ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; @@ -54,4 +62,24 @@ finish_file (void) { } + +/* Return current LTO mode. */ + +static int +c_get_lto_mode (void) +{ + return lto_mode; +} + +/* Set current LTO mode to MODE. Only LTO_MODE_LGEN is allowed. */ + +static void +c_set_lto_mode (int mode) +{ + if (mode == LTO_MODE_LGEN || mode == LTO_MODE_NOT_LTO) + lto_mode = mode; + else + error ("Unsupported LTO mode."); +} + #include "gtype-c.h" Index: gcc/gcc/lto-section-out.c =================================================================== --- gcc/gcc/lto-section-out.c (revision 140444) +++ gcc/gcc/lto-section-out.c (working copy) @@ -1307,7 +1307,7 @@ produce_asm_for_decls (cgraph_node_set s bool gate_lto_out (void) { - return (flag_generate_lto + return (lto_mode_generate_lto_p (lang_hooks.lto.get_mode ()) /* Don't bother doing anything if the program has errors. */ && !(errorcount || sorrycount)); } Index: gcc/gcc/collect2.c =================================================================== --- gcc/gcc/collect2.c (revision 140444) +++ gcc/gcc/collect2.c (working copy) @@ -178,7 +178,7 @@ static int export_flag; static int aix64_flag; /* true if -b64 */ static int aixrtl_flag; /* true if -brtl */ #endif -static bool lto_flag; /* true if -flto */ +static const char *lto_mode; /* Last specified LTO mode. */ int debug; /* true if -debug */ @@ -893,7 +893,7 @@ maybe_run_lto_and_relink (char **lto_ld_ /* Increment the argument count by the number of initial arguments added below. */ - num_lto_c_args += 8; + num_lto_c_args += 9; lto_c_argv = (char **) xcalloc (sizeof (char *), num_lto_c_args); lto_c_ptr = (const char **) lto_c_argv; @@ -907,6 +907,8 @@ maybe_run_lto_and_relink (char **lto_ld_ *lto_c_ptr++ = "-O2"; *lto_c_ptr++ = "-o"; *lto_c_ptr++ = lto_o_file; + if (lto_mode) + *lto_c_ptr++ = lto_mode; /* Add inherited GCC options to the LTO back end command line. Filter out some obviously inappropriate options that will @@ -914,8 +916,8 @@ maybe_run_lto_and_relink (char **lto_ld_ all of the remaining options on to LTO, and let it complain about any it doesn't like. Note that we invoke LTO via the `gcc' driver, so the usual option processing takes place. - Except for `-flto', we should only filter options that are - meaningful to `ld', lest an option go silently unclaimed. */ + Except for `-flto-mode=', we should only filter options that + are meaningful to `ld', lest an option go silently unclaimed. */ cp = opts; @@ -923,8 +925,8 @@ maybe_run_lto_and_relink (char **lto_ld_ { const char *s = extract_string (&cp); - if (strcmp (s, "-flto") == 0) - /* We've handled the `-flto' option, don't pass it on. */ + if (strncmp (s, "-flto-mode=", 11) == 0) + /* We've handled the `-flto-mode=' option, don't pass it on. */ ; else if (strcmp (s, "-o") == 0) { @@ -1122,8 +1124,8 @@ main (int argc, char **argv) { if (! strcmp (argv[i], "-debug")) debug = 1; - else if (! strcmp (argv[i], "-flto")) - lto_flag = true; + else if (! strncmp (argv[i], "-flto-mode=", 11)) + lto_mode = argv[i]; } vflag = debug; } @@ -1372,7 +1374,7 @@ main (int argc, char **argv) break; case 'f': - if (strcmp (arg, "-flto") == 0) + if (strncmp (arg, "-flto-mode=",11) == 0) { /* Do not pass -flto to the linker. */ ld1--; @@ -1623,7 +1625,7 @@ main (int argc, char **argv) if (export_file != 0 && export_file[0]) maybe_unlink (export_file); #endif - if (lto_flag) + if (lto_mode) maybe_run_lto_and_relink (ld1_argv, object_lst, object, false); maybe_unlink (c_file); @@ -1666,7 +1668,7 @@ main (int argc, char **argv) do_tlink (ld1_argv, object_lst); #endif - if (lto_flag) + if (lto_mode) maybe_run_lto_and_relink (ld1_argv, object_lst, object, false); /* Strip now if it was requested on the command line. */ @@ -1762,11 +1764,11 @@ main (int argc, char **argv) /* On AIX we must call tlink because of possible templates resolution. */ do_tlink (ld2_argv, object_lst); - if (lto_flag) + if (lto_mode) maybe_run_lto_and_relink (ld2_argv, object_lst, object, false); #else /* Otherwise, simply call ld because tlink is already done. */ - if (lto_flag) + if (lto_mode) maybe_run_lto_and_relink (ld2_argv, object_lst, object, true); else fork_execute ("ld", ld2_argv); Index: gcc/gcc/langhooks-def.h =================================================================== --- gcc/gcc/langhooks-def.h (revision 140444) +++ gcc/gcc/langhooks-def.h (working copy) @@ -228,15 +228,21 @@ extern tree lhd_make_node (enum tree_cod extern void lhd_begin_section (const char *); extern void lhd_append_data (const void *, size_t, void *); extern void lhd_end_section (void); +extern int lhd_get_mode (void); +extern void lhd_set_mode (int); #define LANG_HOOKS_BEGIN_SECTION lhd_begin_section #define LANG_HOOKS_APPEND_DATA lhd_append_data #define LANG_HOOKS_END_SECTION lhd_end_section +#define LANG_HOOKS_GET_MODE lhd_get_mode +#define LANG_HOOKS_SET_MODE lhd_set_mode #define LANG_HOOKS_LTO { \ LANG_HOOKS_BEGIN_SECTION, \ LANG_HOOKS_APPEND_DATA, \ - LANG_HOOKS_END_SECTION \ + LANG_HOOKS_END_SECTION, \ + LANG_HOOKS_GET_MODE, \ + LANG_HOOKS_SET_MODE \ } /* The whole thing. The structure is defined in langhooks.h. */