Fix PR82941 and PR82942 by adding proper vzeroupper generation on SKX.
authorSebastian Peryt <sebastian.peryt@intel.com>
Wed, 15 Nov 2017 12:27:31 +0000 (13:27 +0100)
committerSebastian Peryt <speryt@gcc.gnu.org>
Wed, 15 Nov 2017 12:27:31 +0000 (13:27 +0100)
2017-11-15  Sebastian Peryt  <sebastian.peryt@intel.com>

gcc/

PR target/82941
PR target/82942
* config/i386/i386.c (pass_insert_vzeroupper): Modify gate condition
to return true on Xeon and not on Xeon Phi.
(ix86_check_avx256_register): Changed to ...
(ix86_check_avx_upper_register): ... this. Add extra check for
VALID_AVX512F_REG_OR_XI_MODE.
(ix86_avx_u128_mode_needed): Changed
ix86_check_avx256_register to ix86_check_avx_upper_register.
(ix86_check_avx256_stores): Changed to ...
(ix86_check_avx_upper_stores): ... this. Changed
ix86_check_avx256_register to ix86_check_avx_upper_register.
(ix86_avx_u128_mode_after): Changed
avx_reg256_found to avx_upper_reg_found. Changed
ix86_check_avx256_stores to ix86_check_avx_upper_stores.
(ix86_avx_u128_mode_entry): Changed
ix86_check_avx256_register to ix86_check_avx_upper_register.
(ix86_avx_u128_mode_exit): Ditto.
* config/i386/i386.h: (host_detect_local_cpu): New define.

2017-11-15  Sebastian Peryt  <sebastian.peryt@intel.com>

gcc/testsuite/

PR target/82941
PR target/82942
* gcc.target/i386/pr82941-1.c: New test.
* gcc.target/i386/pr82941-2.c: New test.
* gcc.target/i386/pr82942-1.c: New test.
* gcc.target/i386/pr82942-2.c: New test.

From-SVN: r254763

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr82941-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr82941-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr82942-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr82942-2.c [new file with mode: 0644]

index 63e904c..4bae57c 100644 (file)
@@ -1,3 +1,25 @@
+2017-11-15  Sebastian Peryt  <sebastian.peryt@intel.com>
+
+       PR target/82941
+       PR target/82942
+       * config/i386/i386.c (pass_insert_vzeroupper): Modify gate condition
+       to return true on Xeon and not on Xeon Phi.
+       (ix86_check_avx256_register): Changed to ...
+       (ix86_check_avx_upper_register): ... this. Add extra check for
+       VALID_AVX512F_REG_OR_XI_MODE.
+       (ix86_avx_u128_mode_needed): Changed
+       ix86_check_avx256_register to ix86_check_avx_upper_register.
+       (ix86_check_avx256_stores): Changed to ...
+       (ix86_check_avx_upper_stores): ... this. Changed
+       ix86_check_avx256_register to ix86_check_avx_upper_register.
+       (ix86_avx_u128_mode_after): Changed
+       avx_reg256_found to avx_upper_reg_found. Changed
+       ix86_check_avx256_stores to ix86_check_avx_upper_stores.
+       (ix86_avx_u128_mode_entry): Changed
+       ix86_check_avx256_register to ix86_check_avx_upper_register.
+       (ix86_avx_u128_mode_exit): Ditto.
+       * config/i386/i386.h: (host_detect_local_cpu): New define.
+
 2017-11-15  Dominik Infuehr  <dominik.infuehr@theobroma-systems.com>
 
        * config/arm/xgene1.md (xgene1): Split into automatons
index 769f189..c5e84a0 100644 (file)
@@ -875,7 +875,7 @@ 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
+     account for possible spills from 256bit or 512bit 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++)
@@ -2497,7 +2497,7 @@ public:
   /* opt_pass methods: */
   virtual bool gate (function *)
     {
-      return TARGET_AVX && !TARGET_AVX512F
+      return TARGET_AVX && !TARGET_AVX512ER
             && TARGET_VZEROUPPER && flag_expensive_optimizations
             && !optimize_size;
     }
@@ -18640,16 +18640,17 @@ ix86_dirflag_mode_needed (rtx_insn *insn)
   return X86_DIRFLAG_ANY;
 }
 
-/* Check if a 256bit AVX register is referenced inside of EXP.   */
+/* Check if a 256bit or 512 bit AVX register is referenced inside of EXP.   */
 
 static bool
-ix86_check_avx256_register (const_rtx exp)
+ix86_check_avx_upper_register (const_rtx exp)
 {
   if (SUBREG_P (exp))
     exp = SUBREG_REG (exp);
 
   return (REG_P (exp)
-         && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (exp)));
+       && (VALID_AVX256_REG_OR_OI_MODE (GET_MODE (exp))
+       || VALID_AVX512F_REG_OR_XI_MODE (GET_MODE (exp))));
 }
 
 /* Return needed mode for entity in optimize_mode_switching pass.  */
@@ -18662,7 +18663,7 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
       rtx link;
 
       /* Needed mode is set to AVX_U128_CLEAN if there are
-        no 256bit modes used in function arguments.  */
+        no 256bit or 512bit modes used in function arguments. */
       for (link = CALL_INSN_FUNCTION_USAGE (insn);
           link;
           link = XEXP (link, 1))
@@ -18671,7 +18672,7 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
            {
              rtx arg = XEXP (XEXP (link, 0), 0);
 
-             if (ix86_check_avx256_register (arg))
+             if (ix86_check_avx_upper_register (arg))
                return AVX_U128_DIRTY;
            }
        }
@@ -18679,13 +18680,13 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
       return AVX_U128_CLEAN;
     }
 
-  /* Require DIRTY mode if a 256bit AVX register is referenced.  Hardware
-     changes state only when a 256bit register is written to, but we need
-     to prevent the compiler from moving optimal insertion point above
-     eventual read from 256bit register.  */
+  /* Require DIRTY mode if a 256bit or 512bit AVX register is referenced.
+     Hardware changes state only when a 256bit register is written to,
+     but we need to prevent the compiler from moving optimal insertion
+     point above eventual read from 256bit or 512 bit register.  */
   subrtx_iterator::array_type array;
   FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
-    if (ix86_check_avx256_register (*iter))
+    if (ix86_check_avx_upper_register (*iter))
       return AVX_U128_DIRTY;
 
   return AVX_U128_ANY;
@@ -18767,12 +18768,12 @@ ix86_mode_needed (int entity, rtx_insn *insn)
   return 0;
 }
 
-/* Check if a 256bit AVX register is referenced in stores.   */
+/* Check if a 256bit or 512bit AVX register is referenced in stores.   */
  
 static void
-ix86_check_avx256_stores (rtx dest, const_rtx, void *data)
+ix86_check_avx_upper_stores (rtx dest, const_rtx, void *data)
  {
-   if (ix86_check_avx256_register (dest))
+   if (ix86_check_avx_upper_register (dest))
     {
       bool *used = (bool *) data;
       *used = true;
@@ -18791,18 +18792,18 @@ ix86_avx_u128_mode_after (int mode, rtx_insn *insn)
     return AVX_U128_CLEAN;
 
   /* We know that state is clean after CALL insn if there are no
-     256bit registers used in the function return register.  */
+     256bit or 512bit registers used in the function return register. */
   if (CALL_P (insn))
     {
-      bool avx_reg256_found = false;
-      note_stores (pat, ix86_check_avx256_stores, &avx_reg256_found);
+      bool avx_upper_reg_found = false;
+      note_stores (pat, ix86_check_avx_upper_stores, &avx_upper_reg_found);
 
-      return avx_reg256_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
+      return avx_upper_reg_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
     }
 
   /* Otherwise, return current mode.  Remember that if insn
-     references AVX 256bit registers, the mode was already changed
-     to DIRTY from MODE_NEEDED.  */
+     references AVX 256bit or 512bit registers, the mode was already
+     changed to DIRTY from MODE_NEEDED.  */
   return mode;
 }
 
@@ -18845,13 +18846,13 @@ ix86_avx_u128_mode_entry (void)
   tree arg;
 
   /* Entry mode is set to AVX_U128_DIRTY if there are
-     256bit modes used in function arguments.  */
+     256bit or 512bit modes used in function arguments.  */
   for (arg = DECL_ARGUMENTS (current_function_decl); arg;
        arg = TREE_CHAIN (arg))
     {
       rtx incoming = DECL_INCOMING_RTL (arg);
 
-      if (incoming && ix86_check_avx256_register (incoming))
+      if (incoming && ix86_check_avx_upper_register (incoming))
        return AVX_U128_DIRTY;
     }
 
@@ -18885,9 +18886,9 @@ ix86_avx_u128_mode_exit (void)
 {
   rtx reg = crtl->return_rtx;
 
-  /* Exit mode is set to AVX_U128_DIRTY if there are
-     256bit modes used in the function return register.  */
-  if (reg && ix86_check_avx256_register (reg))
+  /* Exit mode is set to AVX_U128_DIRTY if there are 256bit
+     or 512 bit modes used in the function return register. */
+  if (reg && ix86_check_avx_upper_register (reg))
     return AVX_U128_DIRTY;
 
   return AVX_U128_CLEAN;
index 837906b..e3e55da 100644 (file)
@@ -1097,6 +1097,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
    || (MODE) == V16SImode || (MODE) == V16SFmode || (MODE) == V32HImode \
    || (MODE) == V4TImode)
 
+#define VALID_AVX512F_REG_OR_XI_MODE(MODE)                             \
+  (VALID_AVX512F_REG_MODE (MODE) || (MODE) == XImode)
+
 #define VALID_AVX512VL_128_REG_MODE(MODE)                              \
   ((MODE) == V2DImode || (MODE) == V2DFmode || (MODE) == V16QImode     \
    || (MODE) == V4SImode || (MODE) == V4SFmode || (MODE) == V8HImode   \
index 74d35ab..28cfd3c 100644 (file)
@@ -1,3 +1,12 @@
+2017-11-15  Sebastian Peryt  <sebastian.peryt@intel.com>
+       
+       PR target/82941
+       PR target/82942
+       * gcc.target/i386/pr82941-1.c: New test.
+       * gcc.target/i386/pr82941-2.c: New test.
+       * gcc.target/i386/pr82942-1.c: New test.
+       * gcc.target/i386/pr82942-2.c: New test.
+
 2017-11-15  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * g++.dg/cpp0x/rv-trivial-bug.C (test2): Return a value.
diff --git a/gcc/testsuite/gcc.target/i386/pr82941-1.c b/gcc/testsuite/gcc.target/i386/pr82941-1.c
new file mode 100644 (file)
index 0000000..d7e530d
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake-avx512" } */
+
+#include <immintrin.h>
+
+extern __m512d y, z;
+
+void
+pr82941 ()
+{
+  z = y;
+}
+
+/* { dg-final { scan-assembler-times "vzeroupper" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82941-2.c b/gcc/testsuite/gcc.target/i386/pr82941-2.c
new file mode 100644 (file)
index 0000000..db2f858
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=knl" } */
+
+#include "pr82941-1.c"
+
+/* { dg-final { scan-assembler-not "vzeroupper" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82942-1.c b/gcc/testsuite/gcc.target/i386/pr82942-1.c
new file mode 100644 (file)
index 0000000..9cdf81a
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -mno-avx512er -O2" } */
+
+#include "pr82941-1.c"
+
+/* { dg-final { scan-assembler-times "vzeroupper" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82942-2.c b/gcc/testsuite/gcc.target/i386/pr82942-2.c
new file mode 100644 (file)
index 0000000..cb0e337
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -mavx512er -O2" } */
+
+#include "pr82941-1.c"
+
+/* { dg-final { scan-assembler-not "vzeroupper" } } */