diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 0d643b1..33c6e45 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -168,6 +168,7 @@ extern bool ix86_secondary_memory_needed (enum reg_class, enum reg_class,
 extern bool ix86_cannot_change_mode_class (enum machine_mode,
 					   enum machine_mode, enum reg_class);
 
+extern void ix86_avx256_optimize_mode_switching(int (*f)(void));
 extern int ix86_mode_needed (int, rtx);
 extern int ix86_mode_after (int, int, rtx);
 extern int ix86_mode_entry (int);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2386017..b5a495e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -23395,11 +23395,28 @@ ix86_init_machine_status (void)
   f = ggc_alloc_cleared_machine_function ();
   f->use_fast_prologue_epilogue_nregs = -1;
   f->call_abi = ix86_abi;
-  f->optimize_mode_switching[AVX_U128] = TARGET_VZEROUPPER;
 
   return f;
 }
 
+void ix86_avx256_optimize_mode_switching(int (*f)(void))
+{
+  int oms[MAX_386_ENTITIES];
+  int i;
+
+  for (i = 0; i < MAX_386_ENTITIES - 1; i++)
+    {
+      oms [i] = OPTIMIZE_MODE_SWITCHING(i);
+      OPTIMIZE_MODE_SWITCHING(i) = 0;
+    }
+
+  OPTIMIZE_MODE_SWITCHING(AVX_U128) = 1;
+  f ();
+
+  for (i = 0; i < MAX_386_ENTITIES - 1; i++)
+    OPTIMIZE_MODE_SWITCHING(i) = oms [i];
+}
+
 /* Return a MEM corresponding to a stack slot with mode MODE.
    Allocate a new slot if necessary.
 
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 18d476d..b87c903 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2176,6 +2176,10 @@ enum avx_u128_state
 #define OPTIMIZE_MODE_SWITCHING(ENTITY) \
    ix86_optimize_mode_switching[(ENTITY)]
 
+#define OPTIMIZE_MODE_SWITCHING1 \
+  if (TARGET_VZEROUPPER) \
+    ix86_avx256_optimize_mode_switching (optimize_mode_switching);
+
 /* If you define `OPTIMIZE_MODE_SWITCHING', you have to define this as
    initializer for an array of integers.  Each initializer element N
    refers to an entity that needs mode switching, and specifies the
diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c
index 2072628..f6da395 100644
--- a/gcc/mode-switching.c
+++ b/gcc/mode-switching.c
@@ -798,3 +798,45 @@ struct rtl_opt_pass pass_mode_switching =
   0                                     /* todo_flags_finish */
  }
 };
+
+
+static bool
+gate_mode_switching1 (void)
+{
+#ifdef OPTIMIZE_MODE_SWITCHING1
+  return true;
+#else
+  return false;
+#endif
+}
+
+static unsigned int
+rest_of_handle_mode_switching1 (void)
+{
+#ifdef OPTIMIZE_MODE_SWITCHING1
+  OPTIMIZE_MODE_SWITCHING1;
+#endif /* OPTIMIZE_MODE_SWITCHING1 */
+  return 0;
+}
+
+
+struct rtl_opt_pass pass_mode_switching1 =
+{
+ {
+  RTL_PASS,
+  "mode_sw1",                            /* name */
+  OPTGROUP_NONE,                        /* optinfo_flags */
+  gate_mode_switching1,                  /* gate */
+  rest_of_handle_mode_switching1,        /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_MODE_SWITCH,                       /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_df_finish | TODO_verify_rtl_sharing |
+  0                                     /* todo_flags_finish */
+ }
+};
diff --git a/gcc/passes.c b/gcc/passes.c
index 67aae52..97d16ef 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1659,6 +1659,7 @@ init_optimization_passes (void)
 	  NEXT_PASS (pass_variable_tracking);
 	  NEXT_PASS (pass_free_cfg);
 	  NEXT_PASS (pass_machine_reorg);
+	  NEXT_PASS (pass_mode_switching1);
 	  NEXT_PASS (pass_cleanup_barriers);
 	  NEXT_PASS (pass_delay_slots);
 	  NEXT_PASS (pass_split_for_shorten_branches);
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 09ec531..198f888 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -439,6 +439,7 @@ extern struct rtl_opt_pass pass_split_all_insns;
 extern struct rtl_opt_pass pass_fast_rtl_byte_dce;
 extern struct rtl_opt_pass pass_lower_subreg2;
 extern struct rtl_opt_pass pass_mode_switching;
+extern struct rtl_opt_pass pass_mode_switching1;
 extern struct rtl_opt_pass pass_sms;
 extern struct rtl_opt_pass pass_sched;
 extern struct rtl_opt_pass pass_ira;
