diff --git a/gcc/common.opt b/gcc/common.opt
index c16d1faff8898ff27223085223cf6609431b3e8a..084e28ee6172c3ecf2e05ed7d9e38e7da63b054e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2884,7 +2884,7 @@ Common Report Var(flag_unroll_all_loops) Optimization
 Perform loop unrolling for all loops.
 
 funroll-completely-grow-size
-Undocumented Var(flag_cunroll_grow_size) Init(2) Optimization
+Undocumented Var(flag_cunroll_grow_size) Optimization
 ; Internal undocumented flag, allow size growth during complete unrolling
 
 ; Nonzero means that loop optimizer may assume that the induction variables
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 40ee0a695f10b92de4ef077728eace81de6fd327..fe93cf6ff2b2fb46e3f6f49f9f657fc8f8bdb646 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1493,6 +1493,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #undef TARGET_PROMOTE_FUNCTION_MODE
 #define TARGET_PROMOTE_FUNCTION_MODE rs6000_promote_function_mode
 
+#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
+#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE rs6000_override_options_after_change
+
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory
 
@@ -3420,6 +3423,34 @@ rs6000_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
   return NULL;
 }
 
+/* This target function is similar to the hook TARGET_OPTION_OVERRIDE
+   but is called when the optimize level is changed via an attribute or
+   pragma or when it is reset at the end of the code affected by the
+   attribute or pragma.  It is not called at the beginning of compilation
+   when TARGET_OPTION_OVERRIDE is called so if you want to perform these
+   actions then, you should have TARGET_OPTION_OVERRIDE call
+   TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
+
+static void
+rs6000_override_options_after_change (void)
+{
+  /* Explicit -funroll-loops turns -munroll-only-small-loops off, and
+     turns -frename-registers on.  */
+  if ((global_options_set.x_flag_unroll_loops && flag_unroll_loops)
+       || (global_options_set.x_flag_unroll_all_loops
+	   && flag_unroll_all_loops))
+    {
+      if (!global_options_set.x_unroll_only_small_loops)
+	unroll_only_small_loops = 0;
+      if (!global_options_set.x_flag_rename_registers)
+	flag_rename_registers = 1;
+      if (!global_options_set.x_flag_cunroll_grow_size)
+	flag_cunroll_grow_size = 1;
+    }
+  else if (!global_options_set.x_flag_cunroll_grow_size)
+    flag_cunroll_grow_size = flag_peel_loops || optimize >= 3;
+}
+
 /* Override command line options.
 
    Combine build-specific configuration information with options
@@ -4647,23 +4678,6 @@ rs6000_option_override_internal (bool global_init_p)
 			   param_sched_pressure_algorithm,
 			   SCHED_PRESSURE_MODEL);
 
-      /* Explicit -funroll-loops turns -munroll-only-small-loops off, and
-	 turns -frename-registers on.  */
-      if ((global_options_set.x_flag_unroll_loops && flag_unroll_loops)
-	   || (global_options_set.x_flag_unroll_all_loops
-	       && flag_unroll_all_loops))
-	{
-	  if (!global_options_set.x_unroll_only_small_loops)
-	    unroll_only_small_loops = 0;
-	  if (!global_options_set.x_flag_rename_registers)
-	    flag_rename_registers = 1;
-	  if (!global_options_set.x_flag_cunroll_grow_size)
-	    flag_cunroll_grow_size = 1;
-	}
-      else
-	if (!global_options_set.x_flag_cunroll_grow_size)
-	  flag_cunroll_grow_size = flag_peel_loops || optimize >= 3;
-
       /* If using typedef char *va_list, signal that
 	 __builtin_va_start (&ap, 0) can be optimized to
 	 ap = __builtin_next_arg (0).  */
@@ -4671,6 +4685,8 @@ rs6000_option_override_internal (bool global_init_p)
 	targetm.expand_builtin_va_start = NULL;
     }
 
+  rs6000_override_options_after_change ();
+
   /* If not explicitly specified via option, decide whether to generate indexed
      load/store instructions.  A value of -1 indicates that the
      initial value of this variable has not been overwritten. During
diff --git a/gcc/opts.c b/gcc/opts.c
index 63c995ddde9035d0ce41bdf17f42a4f3983df565..c5c60581f70220a89289a59e5f4a6b1a282fd8b9 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1142,11 +1142,21 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 
   /* Control IPA optimizations based on different -flive-patching level.  */
   if (opts->x_flag_live_patching)
-    {
-      control_options_for_live_patching (opts, opts_set,
-					 opts->x_flag_live_patching,
-					 loc);
-    }
+    control_options_for_live_patching (opts, opts_set,
+				       opts->x_flag_live_patching,
+				       loc);
+
+  /* Unrolling all loops implies that standard loop unrolling must also
+     be done.  */
+  if (opts->x_flag_unroll_all_loops)
+    opts->x_flag_unroll_loops = 1;
+
+  /* Allow cunroll to grow size accordingly.  */
+  if (!opts_set->x_flag_cunroll_grow_size)
+    opts->x_flag_cunroll_grow_size
+      = (opts->x_flag_unroll_loops
+         || opts->x_flag_peel_loops
+         || opts->x_optimize >= 3);
 }
 
 #define LEFT_COLUMN	27
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 9a78af1e1cf3e48f6ed706f8a070ff67310dc599..07457d08c3aa6f50fb5b14c60541cfe623a1fdf4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1474,16 +1474,6 @@ process_options (void)
       flag_abi_version = 2;
     }
 
-  /* Unrolling all loops implies that standard loop unrolling must also
-     be done.  */
-  if (flag_unroll_all_loops)
-    flag_unroll_loops = 1;
-
-  /* Allow cunroll to grow size accordingly.  */
-  if (flag_cunroll_grow_size == AUTODETECT_VALUE)
-    flag_cunroll_grow_size
-      = flag_unroll_loops || flag_peel_loops || optimize >= 3;
-
   /* web and rename-registers help when run after loop unrolling.  */
   if (flag_web == AUTODETECT_VALUE)
     flag_web = flag_unroll_loops;