Index: gcc/doc/options.texi
===================================================================
--- gcc/doc/options.texi	(revision 166795)
+++ gcc/doc/options.texi	(working copy)
@@ -201,6 +201,12 @@ If the option takes an argument and has 
 @var{var} is an integer variable that stores the value of the argument.
 
 @item
+If the option has the @code{Defer} property, @var{var} is a pointer to
+a @code{VEC(cl_deferred_option,heap)} that stores the option for later
+processing.  (@var{var} is declared with type @code{void *} and needs
+to be cast to @code{VEC(cl_deferred_option,heap)} before use.)
+
+@item
 Otherwise, if the option takes an argument, @var{var} is a pointer to
 the argument string.  The pointer will be null if the argument is optional
 and wasn't given.
@@ -255,6 +261,10 @@ The main purpose of this property is to 
 The first option should use @samp{Mask(@var{name})} and the others
 should use @samp{Mask(@var{name}) MaskExists}.
 
+@item Defer
+The option should be stored in a vector, specified with @code{Var},
+for later processing.
+
 @item Alias(@var{opt})
 @itemx Alias(@var{opt}, @var{arg})
 @itemx Alias(@var{opt}, @var{posarg}, @var{negarg})
Index: gcc/opts-common.c
===================================================================
--- gcc/opts-common.c	(revision 166795)
+++ gcc/opts-common.c	(working copy)
@@ -958,6 +958,22 @@ set_option (struct gcc_options *opts, st
 	if (set_flag_var)
 	  *(const char **) set_flag_var = "";
 	break;
+
+    case CLVC_DEFER:
+	{
+	  VEC(cl_deferred_option,heap) *vec
+	    = (VEC(cl_deferred_option,heap) *) *(void **) flag_var;
+	  cl_deferred_option *p;
+
+	  p = VEC_safe_push (cl_deferred_option, heap, vec, NULL);
+	  p->opt_index = opt_index;
+	  p->arg = arg;
+	  p->value = value;
+	  *(void **) flag_var = vec;
+	  if (set_flag_var)
+	    *(void **) set_flag_var = vec;
+	}
+	break;
     }
 
   if ((diagnostic_t) kind != DK_UNSPECIFIED
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 166795)
+++ gcc/toplev.c	(working copy)
@@ -2365,6 +2365,8 @@ toplev_main (int argc, char **argv)
 		  save_decoded_options, save_decoded_options_count,
 		  UNKNOWN_LOCATION, global_dc);
 
+  handle_common_deferred_options ();
+
   init_local_tick ();
 
   initialize_plugins ();
Index: gcc/opts.c
===================================================================
--- gcc/opts.c	(revision 166795)
+++ gcc/opts.c	(working copy)
@@ -25,10 +25,7 @@ along with GCC; see the file COPYING3.  
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "expr.h"
-#include "ggc.h"
-#include "output.h"
 #include "langhooks.h"
 #include "opts.h"
 #include "options.h"
@@ -39,10 +36,8 @@ along with GCC; see the file COPYING3.  
 #include "opts-diagnostic.h"
 #include "insn-attr.h"		/* For INSN_SCHEDULING.  */
 #include "target.h"
-#include "tree-pass.h"
 #include "dbgcnt.h"
 #include "debug.h"
-#include "plugin.h"
 #include "except.h"
 #include "lto-streamer.h"
 
@@ -1440,7 +1435,8 @@ print_filtered_help (unsigned int includ
 	  else
 	    strcpy (new_help, "\t");
 
-	  if (flag_var != NULL)
+	  if (flag_var != NULL
+	      && option->var_type != CLVC_DEFER)
 	    {
 	      if (option->flags & CL_JOINED)
 		{
@@ -1839,11 +1835,8 @@ common_handle_option (struct gcc_options
       break;
 
     case OPT_fcall_used_:
-      fix_register (arg, 0, 1);
-      break;
-
     case OPT_fcall_saved_:
-      fix_register (arg, 0, 0);
+      /* Deferred.  */
       break;
 
     case OPT_fcompare_debug_second:
@@ -1877,8 +1870,7 @@ common_handle_option (struct gcc_options
       break;
 
     case OPT_fdump_:
-      if (!dump_switch_p (arg))
-	return false;
+      /* Deferred.  */
       break;
 
     case OPT_ffp_contract_:
@@ -1911,7 +1903,7 @@ common_handle_option (struct gcc_options
       break;
 
     case OPT_ffixed_:
-      fix_register (arg, 1, 1);
+      /* Deferred.  */
       break;
 
     case OPT_finline_limit_:
@@ -1946,19 +1938,8 @@ common_handle_option (struct gcc_options
       break;
 
     case OPT_fplugin_:
-#ifdef ENABLE_PLUGIN
-      add_new_plugin (arg);
-#else
-      error ("plugin support is disabled; configure with --enable-plugin");
-#endif
-      break;
-
     case OPT_fplugin_arg_:
-#ifdef ENABLE_PLUGIN
-      parse_plugin_arg_opt (arg);
-#else
-      error ("plugin support is disabled; configure with --enable-plugin");
-#endif
+      /* Deferred.  */
       break;
 
     case OPT_fprofile_dir_:
@@ -2084,21 +2065,12 @@ common_handle_option (struct gcc_options
       /* The real switch is -fno-stack-limit.  */
       if (value)
 	return false;
-      stack_limit_rtx = NULL_RTX;
+      /* Deferred.  */
       break;
 
     case OPT_fstack_limit_register_:
-      {
-	int reg = decode_reg_name (arg);
-	if (reg < 0)
-	  error ("unrecognized register name \"%s\"", arg);
-	else
-	  stack_limit_rtx = gen_rtx_REG (Pmode, reg);
-      }
-      break;
-
     case OPT_fstack_limit_symbol_:
-      stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (arg));
+      /* Deferred.  */
       break;
 
     case OPT_ftree_vectorizer_verbose_:
@@ -2380,6 +2352,7 @@ option_enabled (int opt_idx, void *opts)
 	return (*(int *) flag_var & option->var_value) != 0;
 
       case CLVC_STRING:
+      case CLVC_DEFER:
 	break;
       }
   return -1;
@@ -2418,6 +2391,9 @@ get_option_state (struct gcc_options *op
 	state->data = "";
       state->size = strlen ((const char *) state->data) + 1;
       break;
+
+    case CLVC_DEFER:
+      return false;
     }
   return true;
 }
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 166795)
+++ gcc/opts.h	(working copy)
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  
 #define GCC_OPTS_H
 
 #include "input.h"
+#include "vec.h"
 
 /* Specifies how a switch's VAR_VALUE relates to its FLAG_VAR.  */
 enum cl_var_type {
@@ -39,7 +40,11 @@ enum cl_var_type {
 
   /* The switch takes a string argument and FLAG_VAR points to that
      argument.  */
-  CLVC_STRING
+  CLVC_STRING,
+
+  /* The switch should be stored in the VEC pointed to by FLAG_VAR for
+     later processing.  */
+  CLVC_DEFER
 };
 
 struct cl_option
@@ -158,6 +163,20 @@ struct cl_decoded_option
   int errors;
 };
 
+/* Structure describing an option deferred for handling after the main
+   option handlers.  */
+
+typedef struct
+{
+  /* Elements from struct cl_decoded_option used for deferred
+     options.  */
+  size_t opt_index;
+  const char *arg;
+  int value;
+} cl_deferred_option;
+DEF_VEC_O(cl_deferred_option);
+DEF_VEC_ALLOC_O(cl_deferred_option,heap);
+
 /* Structure describing a single option-handling callback.  */
 
 struct cl_option_handler_func
@@ -264,4 +283,5 @@ extern void control_warning_option (unsi
 				    struct gcc_options *opts_set,
 				    diagnostic_context *dc);
 extern void print_ignored_options (void);
+extern void handle_common_deferred_options (void);
 #endif
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 166795)
+++ gcc/common.opt	(working copy)
@@ -710,11 +710,11 @@ Common Report Var(flag_btr_bb_exclusive)
 Restrict target load migration not to re-use registers in any basic block
 
 fcall-saved-
-Common Joined RejectNegative
+Common Joined RejectNegative Var(common_deferred_options) Defer
 -fcall-saved-<register>	Mark <register> as being preserved across functions
 
 fcall-used-
-Common Joined RejectNegative
+Common Joined RejectNegative Var(common_deferred_options) Defer
 -fcall-used-<register>	Mark <register> as being corrupted by function calls
 
 ; Nonzero for -fcaller-saves: allocate values in regs that need to
@@ -815,7 +815,7 @@ Common Var(flag_diagnostics_show_option)
 Amend appropriate diagnostic messages with the command line option that controls them
 
 fdump-
-Common Joined RejectNegative
+Common Joined RejectNegative Var(common_deferred_options) Defer
 -fdump-<type>	Dump various compiler internals to a file
 
 fdump-final-insns
@@ -893,7 +893,7 @@ Common Report Var(flag_finite_math_only)
 Assume no NaNs or infinities are generated
 
 ffixed-
-Common Joined RejectNegative
+Common Joined RejectNegative Var(common_deferred_options) Defer
 -ffixed-<register>	Mark <register> as being unavailable to the compiler
 
 ffloat-store
@@ -1306,11 +1306,11 @@ Common Report Var(flag_pie,1)
 Generate position-independent code for executables if possible (small mode)
 
 fplugin=
-Common Joined RejectNegative
+Common Joined RejectNegative Var(common_deferred_options) Defer
 Specify a plugin to load
 
 fplugin-arg-
-Common Joined RejectNegative
+Common Joined RejectNegative Var(common_deferred_options) Defer
 -fplugin-arg-<name>-<key>[=<value>]	Specify argument <key>=<value> for plugin <name>
 
 fpredictive-commoning
@@ -1573,14 +1573,14 @@ Common Alias(fstack-check=, specific, no
 Insert stack checking code into the program.  Same as -fstack-check=specific
 
 fstack-limit
-Common
+Common Var(common_deferred_options) Defer
 
 fstack-limit-register=
-Common RejectNegative Joined
+Common RejectNegative Joined Var(common_deferred_options) Defer
 -fstack-limit-register=<register>	Trap if the stack goes past <register>
 
 fstack-limit-symbol=
-Common RejectNegative Joined
+Common RejectNegative Joined Var(common_deferred_options) Defer
 -fstack-limit-symbol=<name>	Trap if the stack goes past symbol <name>
 
 fstack-protector
Index: gcc/opt-functions.awk
===================================================================
--- gcc/opt-functions.awk	(revision 166795)
+++ gcc/opt-functions.awk	(working copy)
@@ -148,7 +148,9 @@ function static_var(name, flags)
 # Return the type of variable that should be associated with the given flags.
 function var_type(flags)
 {
-	if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags))
+	if (flag_set_p("Defer", flags))
+		return "void *"
+	else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags))
 		return "int "
 	else if (flag_set_p("UInteger", flags))
 		return "int "
@@ -177,6 +179,8 @@ function var_type_struct(flags)
 # "var_cond" and "var_value" fields of its cl_options[] entry.
 function var_set(flags)
 {
+	if (flag_set_p("Defer", flags))
+		return "CLVC_DEFER, 0"
 	s = nth_arg(1, opt_args("Var", flags))
 	if (s != "")
 		return "CLVC_EQUAL, " s
Index: gcc/opts-global.c
===================================================================
--- gcc/opts-global.c	(revision 0)
+++ gcc/opts-global.c	(revision 0)
@@ -0,0 +1,105 @@
+/* Command line option handling.  Code involving global state that
+   should not be shared with the driver.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
+
+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 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+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 COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic-core.h"
+#include "opts.h"
+#include "flags.h"
+#include "ggc.h"
+#include "tm.h" /* Required by rtl.h.  */
+#include "rtl.h"
+#include "output.h"
+#include "plugin.h"
+#include "tree-pass.h"
+
+void
+handle_common_deferred_options (void)
+{
+  unsigned int i;
+  cl_deferred_option *opt;
+  VEC(cl_deferred_option,heap) *vec
+    = (VEC(cl_deferred_option,heap) *) common_deferred_options;
+
+  FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
+    {
+      switch (opt->opt_index)
+	{
+	case OPT_fcall_used_:
+	  fix_register (opt->arg, 0, 1);
+	  break;
+
+	case OPT_fcall_saved_:
+	  fix_register (opt->arg, 0, 0);
+	  break;
+
+	case OPT_fdump_:
+	  if (!dump_switch_p (opt->arg))
+	    error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
+	  break;
+
+	case OPT_ffixed_:
+	  /* Deferred.  */
+	  fix_register (opt->arg, 1, 1);
+	  break;
+
+	case OPT_fplugin_:
+#ifdef ENABLE_PLUGIN
+	  add_new_plugin (opt->arg);
+#else
+	  error ("plugin support is disabled; configure with --enable-plugin");
+#endif
+	  break;
+
+	case OPT_fplugin_arg_:
+#ifdef ENABLE_PLUGIN
+	  parse_plugin_arg_opt (opt->arg);
+#else
+	  error ("plugin support is disabled; configure with --enable-plugin");
+#endif
+	  break;
+
+	case OPT_fstack_limit:
+	  /* The real switch is -fno-stack-limit.  */
+	  gcc_assert (!opt->value);
+	  stack_limit_rtx = NULL_RTX;
+	  break;
+
+	case OPT_fstack_limit_register_:
+	  {
+	    int reg = decode_reg_name (opt->arg);
+	    if (reg < 0)
+	      error ("unrecognized register name %qs", opt->arg);
+	    else
+	      stack_limit_rtx = gen_rtx_REG (Pmode, reg);
+	  }
+	  break;
+
+	case OPT_fstack_limit_symbol_:
+	  stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (opt->arg));
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+}
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 166795)
+++ gcc/Makefile.in	(working copy)
@@ -932,7 +932,7 @@ PREDICT_H = predict.h predict.def
 CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
 	$(srcdir)/../libcpp/include/cpplib.h
 INPUT_H = $(srcdir)/../libcpp/include/line-map.h input.h
-OPTS_H = $(INPUT_H) opts.h
+OPTS_H = $(INPUT_H) $(VEC_H) opts.h
 DECNUM_H = $(DECNUM)/decContext.h $(DECNUM)/decDPD.h $(DECNUM)/decNumber.h \
 	$(DECNUMFMT)/decimal32.h $(DECNUMFMT)/decimal64.h \
 	$(DECNUMFMT)/decimal128.h $(DECNUMFMT)/decimal128Local.h
@@ -1295,6 +1295,7 @@ OBJS-common = \
 	optabs.o \
 	options.o \
 	opts-common.o \
+	opts-global.o \
 	opts.o \
 	params.o \
 	passes.o \
@@ -2810,10 +2811,13 @@ fold-const.o : fold-const.c $(CONFIG_H) 
 diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    version.h $(INPUT_H) intl.h $(DIAGNOSTIC_H) diagnostic.def
 opts.o : opts.c $(OPTS_H) $(OPTIONS_H) $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) $(CONFIG_H) $(SYSTEM_H) \
-   coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(EXPR_H) $(RTL_H) \
-   output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
-   $(FLAGS_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H) debug.h \
-   $(PLUGIN_H) $(EXCEPT_H) $(LTO_STREAMER_H) opts-diagnostic.h
+   coretypes.h $(TREE_H) $(TM_H) langhooks.h $(EXPR_H) \
+   $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
+   $(FLAGS_H) $(PARAMS_H) $(DBGCNT_H) debug.h \
+   $(EXCEPT_H) $(LTO_STREAMER_H) opts-diagnostic.h
+opts-global.o : opts-global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+   $(DIAGNOSTIC_CORE_H) $(OPTS_H) $(FLAGS_H) $(GGC_H) $(TM_H) $(RTL_H) \
+   output.h $(PLUGIN_H) $(TREE_PASS_H)
 opts-common.o : opts-common.c $(OPTS_H) $(FLAGS_H) $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h intl.h $(DIAGNOSTIC_H) $(TM_H)
 targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
