From e6f146d226b225b1aa2fdcd0a868cb24e88321fd Mon Sep 17 00:00:00 2001 From: Sebastian Peryt Date: Wed, 15 Nov 2017 13:27:31 +0100 Subject: [PATCH] Fix PR82941 and PR82942 by adding proper vzeroupper generation on SKX. 2017-11-15 Sebastian Peryt 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 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 | 22 ++++++++++ gcc/config/i386/i386.c | 53 ++++++++++++----------- gcc/config/i386/i386.h | 3 ++ gcc/testsuite/ChangeLog | 9 ++++ gcc/testsuite/gcc.target/i386/pr82941-1.c | 14 ++++++ gcc/testsuite/gcc.target/i386/pr82941-2.c | 6 +++ gcc/testsuite/gcc.target/i386/pr82942-1.c | 6 +++ gcc/testsuite/gcc.target/i386/pr82942-2.c | 6 +++ 8 files changed, 93 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr82941-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr82941-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr82942-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr82942-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 63e904ce4a7..4bae57c7d3a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2017-11-15 Sebastian Peryt + + 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 * config/arm/xgene1.md (xgene1): Split into automatons diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 769f1898b22..c5e84a09954 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 837906b5169..e3e55da4232 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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 \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 74d35abbc0a..28cfd3cbe59 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2017-11-15 Sebastian Peryt + + 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 * 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 index 00000000000..d7e530d5116 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr82941-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=skylake-avx512" } */ + +#include + +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 index 00000000000..db2f8589ab6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr82941-2.c @@ -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 index 00000000000..9cdf81a9d60 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr82942-1.c @@ -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 index 00000000000..cb0e337113e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr82942-2.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512f -mavx512er -O2" } */ + +#include "pr82941-1.c" + +/* { dg-final { scan-assembler-not "vzeroupper" } } */ -- 2.30.2