diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
index b592134..9dd9a8d 100644
--- a/gcc/config/arm/arm-c.c
+++ b/gcc/config/arm/arm-c.c
@@ -243,6 +243,8 @@ arm_pragma_target_parse (tree args, tree pop_target)
       /* handle_pragma_pop_options and handle_pragma_reset_options will set
        target_option_current_node, but not handle_pragma_target.  */
       target_option_current_node = cur_tree;
+      arm_configure_build_target (&arm_active_target, &global_options,
+				  &global_options_set, false);
     }
 
   /* Update macros if target_node changes. The global state will be restored
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 659959b..da3484f 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -24,6 +24,7 @@
 
 #include "arm-flags.h"
 #include "arm-isa.h"
+#include "sbitmap.h"
 
 extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
 extern int use_return_insn (int, rtx);
@@ -223,6 +224,9 @@ extern bool arm_change_mode_p (tree);
 
 extern tree arm_valid_target_attribute_tree (tree, struct gcc_options *,
 					     struct gcc_options *);
+extern void arm_configure_build_target (struct arm_build_target *,
+					struct gcc_options *,
+					struct gcc_options *, bool);
 extern void arm_pr_long_calls (struct cpp_reader *);
 extern void arm_pr_no_long_calls (struct cpp_reader *);
 extern void arm_pr_long_calls_off (struct cpp_reader *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index bc246c9..437ee2d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -231,6 +231,8 @@ static tree arm_build_builtin_va_list (void);
 static void arm_expand_builtin_va_start (tree, rtx);
 static tree arm_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
 static void arm_option_override (void);
+static void arm_option_restore (struct gcc_options *,
+				struct cl_target_option *);
 static void arm_override_options_after_change (void);
 static void arm_option_print (FILE *, int, struct cl_target_option *);
 static void arm_set_current_function (tree);
@@ -408,6 +410,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
 #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE arm_override_options_after_change
 
+#undef TARGET_OPTION_RESTORE
+#define TARGET_OPTION_RESTORE arm_option_restore
+
 #undef TARGET_OPTION_PRINT
 #define TARGET_OPTION_PRINT arm_option_print
 
@@ -2932,9 +2937,19 @@ arm_override_options_after_change_1 (struct gcc_options *opts)
 static void
 arm_override_options_after_change (void)
 {
+  arm_configure_build_target (&arm_active_target, &global_options,
+			      &global_options_set, false);
+
   arm_override_options_after_change_1 (&global_options);
 }
 
+static void
+arm_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)
+{
+  arm_configure_build_target (&arm_active_target, opts, &global_options_set,
+			      false);
+}
+
 /* Reset options between modes that the user has specified.  */
 static void
 arm_option_override_internal (struct gcc_options *opts,
@@ -3048,13 +3063,13 @@ arm_initialize_isa (sbitmap isa, const enum isa_feature *isa_bits)
     bitmap_set_bit (isa, *(isa_bits++));
 }
 
-static sbitmap isa_fpubits;
+static sbitmap isa_all_fpubits;
 static sbitmap isa_quirkbits;
 
 /* Configure a build target TARGET from the user-specified options OPTS and
    OPTS_SET.  If WARN_COMPATIBLE, emit a diagnostic if both the CPU and
    architecture have been specified, but the two are not identical.  */
-static void
+void
 arm_configure_build_target (struct arm_build_target *target,
 			    struct gcc_options *opts,
 			    struct gcc_options *opts_set,
@@ -3063,6 +3078,7 @@ arm_configure_build_target (struct arm_build_target *target,
   const struct processors *arm_selected_tune = NULL;
   const struct processors *arm_selected_arch = NULL;
   const struct processors *arm_selected_cpu = NULL;
+  const struct arm_fpu_desc *arm_selected_fpu = NULL;
 
   bitmap_clear (target->isa);
   target->core_name = NULL;
@@ -3093,7 +3109,7 @@ arm_configure_build_target (struct arm_build_target *target,
 	  /* Ignore any bits that are quirk bits.  */
 	  bitmap_and_compl (cpu_isa, cpu_isa, isa_quirkbits);
 	  /* Ignore (for now) any bits that might be set by -mfpu.  */
-	  bitmap_and_compl (cpu_isa, cpu_isa, isa_fpubits);
+	  bitmap_and_compl (cpu_isa, cpu_isa, isa_all_fpubits);
 
 	  if (!bitmap_empty_p (cpu_isa))
 	    {
@@ -3239,6 +3255,13 @@ arm_configure_build_target (struct arm_build_target *target,
 
   gcc_assert (arm_selected_cpu);
 
+  arm_selected_fpu = &all_fpus[opts->x_arm_fpu_index];
+  auto_sbitmap fpu_bits(isa_num_bits);
+
+  arm_initialize_isa (fpu_bits, arm_selected_fpu->isa_bits);
+  bitmap_and_compl (target->isa, target->isa, isa_all_fpubits);
+  bitmap_ior (target->isa, target->isa, fpu_bits);
+
   /* The selected cpu may be an architecture, so lookup tuning by core ID.  */
   if (!arm_selected_tune)
     arm_selected_tune = &all_cores[arm_selected_cpu->core];
@@ -3263,11 +3286,27 @@ arm_option_override (void)
   isa_quirkbits = sbitmap_alloc (isa_num_bits);
   arm_initialize_isa (isa_quirkbits, quirk_bitlist);
 
-  isa_fpubits = sbitmap_alloc (isa_num_bits);
-  arm_initialize_isa (isa_fpubits, fpu_bitlist);
+  isa_all_fpubits = sbitmap_alloc (isa_num_bits);
+  arm_initialize_isa (isa_all_fpubits, fpu_bitlist);
 
   arm_active_target.isa = sbitmap_alloc (isa_num_bits);
 
+  if (!global_options_set.x_arm_fpu_index)
+    {
+      const char *target_fpu_name;
+      bool ok;
+
+#ifdef FPUTYPE_DEFAULT
+      target_fpu_name = FPUTYPE_DEFAULT;
+#else
+      target_fpu_name = "vfp";
+#endif
+
+      ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &arm_fpu_index,
+				  CL_TARGET);
+      gcc_assert (ok);
+    }
+
   arm_configure_build_target (&arm_active_target, &global_options,
 			      &global_options_set, true);
 
@@ -3378,22 +3417,6 @@ arm_option_override (void)
   if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT)
     error ("iwmmxt abi requires an iwmmxt capable cpu");
 
-  if (!global_options_set.x_arm_fpu_index)
-    {
-      const char *target_fpu_name;
-      bool ok;
-
-#ifdef FPUTYPE_DEFAULT
-      target_fpu_name = FPUTYPE_DEFAULT;
-#else
-      target_fpu_name = "vfp";
-#endif
-
-      ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &arm_fpu_index,
-				  CL_TARGET);
-      gcc_assert (ok);
-    }
-
   /* If soft-float is specified then don't use FPU.  */
   if (TARGET_SOFT_FLOAT)
     arm_fpu_attr = FPU_NONE;
@@ -30293,8 +30316,6 @@ arm_valid_target_attribute_rec (tree args, struct gcc_options *opts)
 	  error ("attribute(target(\"%s\")) is unknown", q);
 	  return false;
 	}
-
-      arm_option_check_internal (opts);
     }
 
   return true;
@@ -30309,6 +30330,8 @@ arm_valid_target_attribute_tree (tree args, struct gcc_options *opts,
   if (!arm_valid_target_attribute_rec (args, opts))
     return NULL_TREE;
 
+  arm_configure_build_target (&arm_active_target, opts, opts_set, false);
+  arm_option_check_internal (opts);
   /* Do any overrides, such as global options arch=xxx.  */
   arm_option_override_internal (opts, opts_set);
 
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index a37facc..934144d 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -73,7 +73,7 @@ mapcs-stack-check
 Target Report Mask(APCS_STACK) Undocumented
 
 march=
-Target RejectNegative ToLower Joined Enum(arm_arch) Var(arm_arch_option)
+Target RejectNegative ToLower Joined Enum(arm_arch) Var(arm_arch_option) Save
 Specify the name of the target architecture.
 
 ; Other arm_arch values are loaded from arm-tables.opt
@@ -98,7 +98,7 @@ Target Report Mask(CALLER_INTERWORKING)
 Thumb: Assume function pointers may go to non-Thumb aware code.
 
 mcpu=
-Target RejectNegative ToLower Joined Enum(processor_type) Var(arm_cpu_option) Init(TARGET_CPU_arm_none)
+Target RejectNegative ToLower Joined Enum(processor_type) Var(arm_cpu_option) Init(TARGET_CPU_arm_none) Save
 Specify the name of the target CPU.
 
 mfloat-abi=
@@ -223,7 +223,7 @@ Target Report Mask(TPCS_LEAF_FRAME)
 Thumb: Generate (leaf) stack frames even if not needed.
 
 mtune=
-Target RejectNegative ToLower Joined Enum(processor_type) Var(arm_tune_option) Init(TARGET_CPU_arm_none)
+Target RejectNegative ToLower Joined Enum(processor_type) Var(arm_tune_option) Init(TARGET_CPU_arm_none) Save
 Tune code for the given processor.
 
 mprint-tune-info

