Patchwork [i386] : Implement post-reload vzeroupper insertion pass

login
register
mail settings
Submitter Uros Bizjak
Date Nov. 14, 2012, 4:53 p.m.
Message ID <CAFULd4ZXAHHEAopZvCyQBmGgKbvY4hFQ-Mgf4-yPx=F+rSrckg@mail.gmail.com>
Download mbox | patch
Permalink /patch/198963/
State New
Headers show

Comments

Uros Bizjak - Nov. 14, 2012, 4:53 p.m.
On Sun, Nov 11, 2012 at 9:45 PM, Uros Bizjak <ubizjak@gmail.com> wrote:
>
>> Regarding vzeroupper insertion pass - we will use gcc pass manager to
>> insert a target-dependant pass directly after reload ...
>
> ... like attached patch. The patch inserts vzeroupper pass directly
> after reload, so spills from 256bit registers are considered when
> processing AVX_U128 entity. The patched gcc reruns mode-switching
> pass, so an export of entry function from mode-switching is needed.

2012-11-14  Uros Bizjak  <ubizjak@gmail.com>
            Vladimir Yakovlev  <vladimir.b.yakovlev@intel.com>

        PR target/47440
        * config/i386/i386.c (gate_insert_vzeroupper): New function.
        (rest_of_handle_insert_vzeroupper): Ditto.
        (struct rtl_opt_pass pass_insert_vzeroupper): New.
        (ix86_option_override): Register vzeroupper insertion pass here.
        (ix86_check_avx256_register): Handle SUBREGs properly.
        (ix86_init_machine_status): Remove optimize_mode_switching[AVX_U128]
        initialization.

Bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32} AVX
target and committed to mainline SVN.

Uros.

Patch

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 193502)
+++ config/i386/i386.c	(working copy)
@@ -2301,6 +2301,52 @@  static const char *const cpu_names[TARGET_CPU_DEFA
   "btver2"
 };
 
+static bool
+gate_insert_vzeroupper (void)
+{
+  return TARGET_VZEROUPPER;
+}
+
+static unsigned int
+rest_of_handle_insert_vzeroupper (void)
+{
+  int i;
+
+  /* vzeroupper instructions are inserted immediately after reload to
+     account for possible spills from 256bit registers.  The pass
+     reuses mode switching infrastructure by re-running mode insertion
+     pass, so disable entities that have already been processed.  */
+  for (i = 0; i < MAX_386_ENTITIES; i++)
+    ix86_optimize_mode_switching[i] = 0;
+
+  ix86_optimize_mode_switching[AVX_U128] = 1;
+
+  /* Call optimize_mode_switching.  */
+  pass_mode_switching.pass.execute ();
+  return 0;
+}
+
+struct rtl_opt_pass pass_insert_vzeroupper =
+{
+ {
+  RTL_PASS,
+  "vzeroupper",				/* name */
+  OPTGROUP_NONE,			/* optinfo_flags */
+  gate_insert_vzeroupper,		/* gate */
+  rest_of_handle_insert_vzeroupper,	/* execute */
+  NULL,					/* sub */
+  NULL,					/* next */
+  0,					/* static_pass_number */
+  TV_NONE,				/* 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 */
+ }
+};
+
 /* Return true if a red-zone is in use.  */
 
 static inline bool
@@ -3705,7 +3751,16 @@  ix86_option_override_internal (bool main_args_p)
 static void
 ix86_option_override (void)
 {
+  static struct register_pass_info insert_vzeroupper_info
+    = { &pass_insert_vzeroupper.pass, "reload",
+	1, PASS_POS_INSERT_AFTER
+      };
+
   ix86_option_override_internal (true);
+
+
+  /* This needs to be done at start up.  It's convenient to do it here.  */
+  register_pass (&insert_vzeroupper_info);
 }
 
 /* Update register usage after having seen the compiler flags.  */
@@ -14988,10 +15043,15 @@  output_387_binary_op (rtx insn, rtx *operands)
 /* Check if a 256bit AVX register is referenced inside of EXP.   */
 
 static int
-ix86_check_avx256_register (rtx *exp, void *data ATTRIBUTE_UNUSED)
+ix86_check_avx256_register (rtx *pexp, void *data ATTRIBUTE_UNUSED)
 {
-  if (REG_P (*exp)
-      && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (*exp)))
+  rtx exp = *pexp;
+
+  if (GET_CODE (exp) == SUBREG)
+    exp = SUBREG_REG (exp);
+
+  if (REG_P (exp)
+      && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (exp)))
     return 1;
 
   return 0;
@@ -23449,7 +23509,6 @@  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;
 }