public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Intrinsics for fxsave[,64], xsave[,64], xsaveopt[,64]
@ 2012-10-18 10:22 Alexander Ivchenko
  2012-10-18 16:00 ` Uros Bizjak
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Alexander Ivchenko @ 2012-10-18 10:22 UTC (permalink / raw)
  To: ubizjak, hjl.tools, kirill.yukhin, izamyatin, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2292 bytes --]

Hi,

this patch adds new intrinsics for fxsave, fxsave64, xsave, xsave64,
xsaveopt and xsaveopt64 instructions

Bootstrapped on x86-64

Is it ok for trunk?

Changelog entry:
2012-10-16  Alexander Ivchenko  <alexander.ivchenko@intel.com>

        * gcc/common/config/i386/i386-common.c
        (OPTION_MASK_ISA_FXSAVE_SET): New.
        (OPTION_MASK_ISA_XSAVE_SET): Likewise.
        (ix86_handle_option): Handle mfxsave and mxsave options.
        * gcc/config.gcc (i[34567]86-*-*): Add fxsaveintrin.h and xsaveintrin.h.
        (x86_64-*-*): Likewise.
        * config/i386/xsaveintrin.h: New header.
        * config/i386/fxsaveintrin.h: Likewise.
        * gcc/config/i386/driver-i386.c (host_detect_local_cpu): Detect
        FXSAVE/XSAVE support.
        * gcc/config/i386/i386-builtin-types.def
        (VOID_FTYPE_PVOID_INT64): New function type.
        * gcc/config/i386/i386-c.c: Define __FXSAVE__ and __XSAVE__ if needed.
        * gcc/config/i386/i386.c (ix86_target_string): Define -mfxsave
        and -mxsave options.
        (PTA_FXSAVE): New.
        (PTA_XSAVE): Likewise.
        (ix86_option_override_internal): Handle new option.
        (ix86_valid_target_attribute_inner_p): Add OPT_mfxsave, OPT_mxsave.
        (ix86_builtins): Add IX86_BUILTIN_FXSAVE32, IX86_BUILTIN_FXSAVE64,
        IX86_BUILTIN_XSAVE32, IX86_BUILTIN_XSAVE64,
        IX86_BUILTIN_XSAVEOPT32, IX86_BUILTIN_XSAVEOPT64.
        (ix86_expand_builtin): Handle these built-ins.
        * gcc/config/i386/i386.h (TARGET_FXSAVE): New.
        (TARGET_XSAVE): Likewise.
        * gcc/config/i386/i386.md (fxsave32): New.
        (fxsave64): Likewise.
        (xsave32): Likewise.
        (xsave64): Likewise.
        (xsaveopt32): Likewise.
        (xsaveopt64): Likewise.
        * gcc/config/i386/i386.opt (mfxsave): New.
        (mxsave): Likewise.
        * gcc/config/i386/x86intrin.h: Include
        xsaveintrin.h, fxsaveintrin.h.

testsuite/Changelog entry:
2012-10-16  Alexander Ivchenko  <alexander.ivchenko@intel.com>

        * gcc.target/i386/fxsave-1.c: New.
        * gcc.target/i386/fxsave64-1.c: Ditto.
        * gcc.target/i386/xsave-1.c: Ditto.
        * gcc.target/i386/xsave64-1.c: Ditto.
        * gcc.target/i386/xsaveopt-1.c: Ditto.
        * gcc.target/i386/xsaveopt64-1.c: Ditto.

[-- Attachment #2: fxsave_xsave_intrin.patch --]
[-- Type: application/octet-stream, Size: 27624 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 227a60f..9c3f08f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,41 @@
+2012-10-16  Alexander Ivchenko  <alexander.ivchenko@intel.com>
+
+	* gcc/common/config/i386/i386-common.c
+	(OPTION_MASK_ISA_FXSAVE_SET): New.
+	(OPTION_MASK_ISA_XSAVE_SET): Likewise.
+	(ix86_handle_option): Handle mfxsave and mxsave options.
+	* gcc/config.gcc (i[34567]86-*-*): Add fxsaveintrin.h and xsaveintrin.h.
+	(x86_64-*-*): Likewise.
+	* config/i386/xsaveintrin.h: New header.
+	* config/i386/fxsaveintrin.h: Likewise.
+	* gcc/config/i386/driver-i386.c (host_detect_local_cpu): Detect
+	FXSAVE/XSAVE support.
+	* gcc/config/i386/i386-builtin-types.def
+	(VOID_FTYPE_PVOID_INT64): New function type.
+	* gcc/config/i386/i386-c.c: Define __FXSAVE__ and __XSAVE__ if needed.
+	* gcc/config/i386/i386.c (ix86_target_string): Define -mfxsave
+	and -mxsave options.
+	(PTA_FXSAVE): New.
+	(PTA_XSAVE): Likewise.
+	(ix86_option_override_internal): Handle new option.
+	(ix86_valid_target_attribute_inner_p): Add OPT_mfxsave, OPT_mxsave.
+	(ix86_builtins): Add IX86_BUILTIN_FXSAVE32, IX86_BUILTIN_FXSAVE64,
+	IX86_BUILTIN_XSAVE32, IX86_BUILTIN_XSAVE64,
+	IX86_BUILTIN_XSAVEOPT32, IX86_BUILTIN_XSAVEOPT64.
+	(ix86_expand_builtin): Handle these built-ins.
+	* gcc/config/i386/i386.h (TARGET_FXSAVE): New.
+	(TARGET_XSAVE): Likewise.
+	* gcc/config/i386/i386.md (fxsave32): New.
+	(fxsave64): Likewise.
+	(xsave32): Likewise.
+	(xsave64): Likewise.
+	(xsaveopt32): Likewise.
+	(xsaveopt64): Likewise.
+	* gcc/config/i386/i386.opt (mfxsave): New.
+	(mxsave): Likewise.
+	* gcc/config/i386/x86intrin.h: Include
+	xsaveintrin.h, fxsaveintrin.h.
+
 2012-10-15  Marc Glisse  <marc.glisse@inria.fr>
 
 	PR tree-optimization/54915
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index e05cd56..62dc71f 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -54,6 +54,8 @@ along with GCC; see the file COPYING3.  If not see
   (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_AVX_SET)
 #define OPTION_MASK_ISA_AVX2_SET \
   (OPTION_MASK_ISA_AVX2 | OPTION_MASK_ISA_AVX_SET)
+#define OPTION_MASK_ISA_FXSAVE_SET OPTION_MASK_ISA_FXSAVE
+#define OPTION_MASK_ISA_XSAVE_SET OPTION_MASK_ISA_XSAVE
 #define OPTION_MASK_ISA_RTM_SET OPTION_MASK_ISA_RTM
 #define OPTION_MASK_ISA_PRFCHW_SET OPTION_MASK_ISA_PRFCHW
 #define OPTION_MASK_ISA_RDSEED_SET OPTION_MASK_ISA_RDSEED
@@ -125,6 +127,8 @@ along with GCC; see the file COPYING3.  If not see
    | OPTION_MASK_ISA_AVX2_UNSET)
 #define OPTION_MASK_ISA_FMA_UNSET OPTION_MASK_ISA_FMA
 #define OPTION_MASK_ISA_AVX2_UNSET OPTION_MASK_ISA_AVX2
+#define OPTION_MASK_ISA_FXSAVE_UNSET OPTION_MASK_ISA_FXSAVE
+#define OPTION_MASK_ISA_XSAVE_UNSET OPTION_MASK_ISA_XSAVE
 #define OPTION_MASK_ISA_RTM_UNSET OPTION_MASK_ISA_RTM
 #define OPTION_MASK_ISA_PRFCHW_UNSET OPTION_MASK_ISA_PRFCHW
 #define OPTION_MASK_ISA_RDSEED_UNSET OPTION_MASK_ISA_RDSEED
@@ -574,6 +578,32 @@ ix86_handle_option (struct gcc_options *opts,
 	}
       return true;
 
+    case OPT_mfxsave:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FXSAVE_SET;
+	  opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FXSAVE_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_FXSAVE_UNSET;
+	  opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FXSAVE_UNSET;
+	}
+      return true;
+
+    case OPT_mxsave:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVE_SET;
+	  opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XSAVE_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_XSAVE_UNSET;
+	  opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XSAVE_UNSET;
+	}
+      return true;
+
     case OPT_mrdseed:
       if (value)
 	{
diff --git a/gcc/config.gcc b/gcc/config.gcc
index ed7474a..8aaacb0 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -362,7 +362,8 @@ i[34567]86-*-*)
 		       ia32intrin.h cross-stdarg.h lwpintrin.h popcntintrin.h
 		       lzcntintrin.h bmiintrin.h bmi2intrin.h tbmintrin.h
 		       avx2intrin.h fmaintrin.h f16cintrin.h rtmintrin.h
-		       xtestintrin.h rdseedintrin.h prfchwintrin.h adxintrin.h"
+		       xtestintrin.h rdseedintrin.h prfchwintrin.h adxintrin.h
+		       fxsaveintrin.h xsaveintrin.h"
 	;;
 x86_64-*-*)
 	cpu_type=i386
@@ -376,7 +377,8 @@ x86_64-*-*)
 		       ia32intrin.h cross-stdarg.h lwpintrin.h popcntintrin.h
 		       lzcntintrin.h bmiintrin.h tbmintrin.h bmi2intrin.h
 		       avx2intrin.h fmaintrin.h f16cintrin.h rtmintrin.h
-		       xtestintrin.h rdseedintrin.h prfchwintrin.h adxintrin.h"
+		       xtestintrin.h rdseedintrin.h prfchwintrin.h adxintrin.h
+		       fxsaveintrin.h xsaveintrin.h"
 	need_64bit_hwint=yes
 	;;
 ia64-*-*)
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 36d80b1..6e6774f 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -390,7 +390,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
   unsigned int has_hle = 0, has_rtm = 0;
   unsigned int has_rdrnd = 0, has_f16c = 0, has_fsgsbase = 0;
   unsigned int has_rdseed = 0, has_prfchw = 0, has_adx = 0;
-  unsigned int has_osxsave = 0;
+  unsigned int has_osxsave = 0, has_fxsave = 0, has_xsave = 0;
 
   bool arch;
 
@@ -441,10 +441,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
   has_fma = ecx & bit_FMA;
   has_f16c = ecx & bit_F16C;
   has_rdrnd = ecx & bit_RDRND;
+  has_xsave = ecx & bit_XSAVE;
 
   has_cmpxchg8b = edx & bit_CMPXCHG8B;
   has_cmov = edx & bit_CMOV;
   has_mmx = edx & bit_MMX;
+  has_fxsave = edx & bit_FXSAVE;
   has_sse = edx & bit_SSE;
   has_sse2 = edx & bit_SSE2;
 
@@ -763,11 +765,14 @@ const char *host_detect_local_cpu (int argc, const char **argv)
       const char *rdseed = has_rdseed ? " -mrdseed" : " -mno-rdseed";
       const char *prfchw = has_prfchw ? " -mprfchw" : " -mno-prfchw";
       const char *adx = has_adx ? " -madx" : " -mno-adx";
+      const char *fxsave = has_fxsave ? " -mfxsave" : " -mno-fxsave";
+      const char *xsave = has_xsave ? " -mxsave" : " -mno-xsave";
 
       options = concat (options, cx16, sahf, movbe, ase, pclmul,
 			popcnt, abm, lwp, fma, fma4, xop, bmi, bmi2,
 			tbm, avx, avx2, sse4_2, sse4_1, lzcnt, rtm,
-			hle, rdrnd, f16c, fsgsbase, rdseed, prfchw, adx, NULL);
+			hle, rdrnd, f16c, fsgsbase, rdseed, prfchw, adx,
+			fxsave, xsave, NULL);
     }
 
 done:
diff --git a/gcc/config/i386/fxsaveintrin.h b/gcc/config/i386/fxsaveintrin.h
new file mode 100644
index 0000000..6e5b566
--- /dev/null
+++ b/gcc/config/i386/fxsaveintrin.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* #if !defined _X86INTRIN_H_INCLUDED && !defined _IMMINTRIN_H_INCLUDED */
+/* # error "Never use <fxsaveintrin.h> directly; include <x86intrin.h> instead." */
+/* #endif */
+
+#ifndef _FXSAVEINTRIN_H_INCLUDED
+#define _FXSAVEINTRIN_H_INCLUDED
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_fxsave (void *mem)
+{
+    return __builtin_ia32_fxsave32 (mem);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_fxsave64 (void *mem)
+{
+    return __builtin_ia32_fxsave64 (mem);
+}
+#endif
+
+#endif /* _FXSAVEINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 8a199c0..f0ad9ff 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -225,6 +225,7 @@ DEF_FUNCTION_TYPE (V16HI, V8HI)
 DEF_FUNCTION_TYPE (V8SI, V8SI)
 DEF_FUNCTION_TYPE (VOID, PCVOID)
 DEF_FUNCTION_TYPE (VOID, PVOID)
+DEF_FUNCTION_TYPE (VOID, PVOID, INT64)
 DEF_FUNCTION_TYPE (VOID, UINT64)
 DEF_FUNCTION_TYPE (VOID, UNSIGNED)
 DEF_FUNCTION_TYPE (INT, PUSHORT)
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index edd64ff..31fa890 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -302,6 +302,10 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
     def_or_undef (parse_in, "__PRFCHW__");
   if (isa_flag & OPTION_MASK_ISA_ADX)
     def_or_undef (parse_in, "__ADX__");
+  if (isa_flag & OPTION_MASK_ISA_FXSAVE)
+    def_or_undef (parse_in, "__FXSAVE__");
+  if (isa_flag & OPTION_MASK_ISA_XSAVE)
+    def_or_undef (parse_in, "__XSAVE__");
   if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE))
     def_or_undef (parse_in, "__SSE_MATH__");
   if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2))
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index c10e49458..8560d41 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2748,7 +2748,7 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
      preceding options while match those first.  */
   static struct ix86_target_opts isa_opts[] =
   {
-    { "-mfma4",	OPTION_MASK_ISA_FMA4 },
+    { "-mfma4",		OPTION_MASK_ISA_FMA4 },
     { "-mfma",		OPTION_MASK_ISA_FMA },
     { "-mxop",		OPTION_MASK_ISA_XOP },
     { "-mlwp",		OPTION_MASK_ISA_LWP },
@@ -2756,17 +2756,18 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
     { "-msse4.2",	OPTION_MASK_ISA_SSE4_2 },
     { "-msse4.1",	OPTION_MASK_ISA_SSE4_1 },
     { "-mssse3",	OPTION_MASK_ISA_SSSE3 },
-    { "-msse3",	OPTION_MASK_ISA_SSE3 },
-    { "-msse2",	OPTION_MASK_ISA_SSE2 },
+    { "-msse3",		OPTION_MASK_ISA_SSE3 },
+    { "-msse2",		OPTION_MASK_ISA_SSE2 },
     { "-msse",		OPTION_MASK_ISA_SSE },
     { "-m3dnow",	OPTION_MASK_ISA_3DNOW },
     { "-m3dnowa",	OPTION_MASK_ISA_3DNOW_A },
     { "-mmmx",		OPTION_MASK_ISA_MMX },
     { "-mabm",		OPTION_MASK_ISA_ABM },
     { "-mbmi",		OPTION_MASK_ISA_BMI },
-    { "-mbmi2",	OPTION_MASK_ISA_BMI2 },
+    { "-mbmi2",		OPTION_MASK_ISA_BMI2 },
     { "-mlzcnt",	OPTION_MASK_ISA_LZCNT },
     { "-mhle",		OPTION_MASK_ISA_HLE },
+    { "-mfxsave",	OPTION_MASK_ISA_FXSAVE },
     { "-mrdseed",	OPTION_MASK_ISA_RDSEED },
     { "-mprfchw",	OPTION_MASK_ISA_PRFCHW },
     { "-madx",		OPTION_MASK_ISA_ADX },
@@ -2778,8 +2779,9 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
     { "-mpclmul",	OPTION_MASK_ISA_PCLMUL },
     { "-mfsgsbase",	OPTION_MASK_ISA_FSGSBASE },
     { "-mrdrnd",	OPTION_MASK_ISA_RDRND },
-    { "-mf16c",	OPTION_MASK_ISA_F16C },
+    { "-mf16c",		OPTION_MASK_ISA_F16C },
     { "-mrtm",		OPTION_MASK_ISA_RTM },
+    { "-mxsave",	OPTION_MASK_ISA_XSAVE },
   };
 
   /* Flag options.  */
@@ -3050,6 +3052,9 @@ ix86_option_override_internal (bool main_args_p)
 #define PTA_PRFCHW		(HOST_WIDE_INT_1 << 34)
 #define PTA_RDSEED		(HOST_WIDE_INT_1 << 35)
 #define PTA_ADX			(HOST_WIDE_INT_1 << 36)
+#define PTA_FXSAVE		(HOST_WIDE_INT_1 << 37)
+#define PTA_XSAVE		(HOST_WIDE_INT_1 << 38)
+
 /* if this reaches 64, need to widen struct pta flags below */
 
   static struct pta
@@ -3545,6 +3550,12 @@ ix86_option_override_internal (bool main_args_p)
 	if (processor_alias_table[i].flags & PTA_ADX
 	    && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ADX))
 	  ix86_isa_flags |= OPTION_MASK_ISA_ADX;
+	if (processor_alias_table[i].flags & PTA_FXSAVE
+	    && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FXSAVE))
+	  ix86_isa_flags |= OPTION_MASK_ISA_FXSAVE;
+	if (processor_alias_table[i].flags & PTA_XSAVE
+	    && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVE))
+	  ix86_isa_flags |= OPTION_MASK_ISA_XSAVE;
 	if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE))
 	  x86_prefetch_sse = true;
 
@@ -4364,6 +4375,8 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
     IX86_ATTR_ISA ("prfchw",	OPT_mprfchw),
     IX86_ATTR_ISA ("rdseed",	OPT_mrdseed),
     IX86_ATTR_ISA ("adx",	OPT_madx),
+    IX86_ATTR_ISA ("fxsave",	OPT_mfxsave),
+    IX86_ATTR_ISA ("xsave",	OPT_mxsave),
 
     /* enum options */
     IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
@@ -25558,6 +25571,14 @@ enum ix86_builtins
   IX86_BUILTIN_STMXCSR,
   IX86_BUILTIN_SFENCE,
 
+  IX86_BUILTIN_FXSAVE32,
+  IX86_BUILTIN_FXSAVE64,
+
+  IX86_BUILTIN_XSAVE32,
+  IX86_BUILTIN_XSAVE64,
+  IX86_BUILTIN_XSAVEOPT32,
+  IX86_BUILTIN_XSAVEOPT64,
+
   /* 3DNow! Original */
   IX86_BUILTIN_FEMMS,
   IX86_BUILTIN_PAVGUSB,
@@ -26764,6 +26785,14 @@ static const struct builtin_description bdesc_special_args[] =
   /* 3DNow! */
   { OPTION_MASK_ISA_3DNOW, CODE_FOR_mmx_femms, "__builtin_ia32_femms", IX86_BUILTIN_FEMMS, UNKNOWN, (int) VOID_FTYPE_VOID },
 
+  /* FXSAVE and XSAVE*/
+  { OPTION_MASK_ISA_FXSAVE, CODE_FOR_fxsave32, "__builtin_ia32_fxsave32", IX86_BUILTIN_FXSAVE32, UNKNOWN, (int) VOID_FTYPE_PVOID },
+  { OPTION_MASK_ISA_FXSAVE, CODE_FOR_fxsave64, "__builtin_ia32_fxsave64", IX86_BUILTIN_FXSAVE64, UNKNOWN, (int) VOID_FTYPE_PVOID },
+  { OPTION_MASK_ISA_XSAVE, CODE_FOR_xsave32, "__builtin_ia32_xsave32", IX86_BUILTIN_XSAVE32, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+  { OPTION_MASK_ISA_XSAVE, CODE_FOR_xsave64, "__builtin_ia32_xsave64", IX86_BUILTIN_XSAVE64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+  { OPTION_MASK_ISA_XSAVE, CODE_FOR_xsaveopt32, "__builtin_ia32_xsaveopt32", IX86_BUILTIN_XSAVEOPT32, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+  { OPTION_MASK_ISA_XSAVE, CODE_FOR_xsaveopt64, "__builtin_ia32_xsaveopt64", IX86_BUILTIN_XSAVEOPT64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+
   /* SSE */
   { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movups, "__builtin_ia32_storeups", IX86_BUILTIN_STOREUPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
   { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movntv4sf, "__builtin_ia32_movntps", IX86_BUILTIN_MOVNTPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
@@ -30619,6 +30648,66 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
 	return target;
       }
 
+    case IX86_BUILTIN_XSAVE32:
+    case IX86_BUILTIN_XSAVE64:
+    case IX86_BUILTIN_XSAVEOPT32:
+    case IX86_BUILTIN_XSAVEOPT64:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      arg1 = CALL_EXPR_ARG (exp, 1);
+      op0 = expand_normal (arg0);
+      op1 = expand_normal (arg1);
+
+      if (GET_MODE (op0) != Pmode)
+	op0 = convert_to_mode (Pmode, op0, 1);
+      op0 = gen_rtx_MEM (Pmode, force_reg (Pmode, op0));
+
+      op1 = force_reg (DImode, op1);
+
+      rtx op1_lo;
+      rtx op1_hi;
+
+      if (TARGET_64BIT)
+	{
+	  op1_lo = gen_reg_rtx (SImode);
+	  emit_move_insn (op1_lo, gen_lowpart (SImode, op1));
+	  emit_insn (gen_lshrdi3 (op1, op1, GEN_INT (32)));
+	  op1_hi = gen_lowpart (SImode, op1);
+	}
+      else
+	split_double_mode (DImode, &op1, 1, &op1_lo, &op1_hi);
+
+      icode = fcode == IX86_BUILTIN_XSAVE32 ? CODE_FOR_xsave32
+	       : fcode == IX86_BUILTIN_XSAVE64 ? CODE_FOR_xsave64
+	       : fcode == IX86_BUILTIN_XSAVEOPT32 ? CODE_FOR_xsaveopt32
+	       : CODE_FOR_xsaveopt64;
+
+      pat = GEN_FCN (icode) (op0, op1_hi, op1_lo);
+      if (pat)
+	emit_insn (pat);
+      return 0;
+
+    case IX86_BUILTIN_FXSAVE32:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = expand_normal (arg0);
+
+      if (GET_MODE (op0) != Pmode)
+	op0 = convert_to_mode (Pmode, op0, 1);
+      op0 = gen_rtx_MEM (Pmode, force_reg (Pmode, op0));
+
+      emit_insn (gen_fxsave32 (op0));
+      return 0;
+
+    case IX86_BUILTIN_FXSAVE64:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = expand_normal (arg0);
+
+      if (GET_MODE (op0) != Pmode)
+	op0 = convert_to_mode (Pmode, op0, 1);
+      op0 = gen_rtx_MEM (Pmode, force_reg (Pmode, op0));
+
+      emit_insn (gen_fxsave64 (op0));
+      return 0;
+
     case IX86_BUILTIN_LLWPCB:
       arg0 = CALL_EXPR_ARG (exp, 0);
       op0 = expand_normal (arg0);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 2e70952..379d92f 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -79,6 +79,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_RDSEED	OPTION_ISA_RDSEED
 #define TARGET_PRFCHW	OPTION_ISA_PRFCHW
 #define TARGET_ADX	OPTION_ISA_ADX
+#define TARGET_FXSAVE	OPTION_ISA_FXSAVE
+#define TARGET_XSAVE	OPTION_ISA_XSAVE
 
 #define TARGET_LP64	OPTION_ABI_64
 #define TARGET_X32	OPTION_ABI_X32
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index fa10cb4..c27a47b 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -202,6 +202,12 @@
   UNSPECV_RDGSBASE
   UNSPECV_WRFSBASE
   UNSPECV_WRGSBASE
+  UNSPECV_FXSAVE32
+  UNSPECV_FXSAVE64
+  UNSPECV_XSAVE32
+  UNSPECV_XSAVE64
+  UNSPECV_XSAVEOPT32
+  UNSPECV_XSAVEOPT64
 
   ;; For RDRAND support
   UNSPECV_RDRAND
@@ -18137,6 +18143,100 @@
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
+;; FXSAVE and XSAVE instructions
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "fxsave32"
+  [(unspec_volatile [(match_operand 0 "memory_operand" "=m")]
+		    UNSPECV_FXSAVE32)]
+  "TARGET_FXSAVE")
+
+(define_insn "*fxsave32"
+  [(unspec_volatile [(match_operand:P 0 "memory_operand" "=m")]
+		    UNSPECV_FXSAVE32)]
+  "TARGET_FXSAVE"
+  "fxsave\t%0"
+  [(set_attr "mode" "<MODE>")])
+
+(define_expand "fxsave64"
+  [(unspec_volatile [(match_operand 0 "memory_operand")]
+		    UNSPECV_FXSAVE64)]
+  "TARGET_FXSAVE && TARGET_64BIT")
+
+(define_insn "*fxsave64"
+  [(unspec_volatile [(match_operand:P 0 "memory_operand" "=m")]
+		    UNSPECV_FXSAVE64)]
+  "TARGET_FXSAVE && TARGET_64BIT"
+  "fxsave64\t%0"
+  [(set_attr "mode" "<MODE>")])
+
+(define_expand "xsave32"
+  [(unspec_volatile [(match_operand 0 "memory_operand")
+		     (match_operand 1 "register_operand")
+		     (match_operand 2 "register_operand")]
+		    UNSPECV_XSAVE32)]
+  "TARGET_XSAVE")
+
+(define_insn "*xsave32"
+  [(unspec_volatile [(match_operand:P 0 "memory_operand" "=m")
+		     (match_operand:SI 1 "register_operand" "d")
+		     (match_operand:SI 2 "register_operand" "a")]
+		    UNSPECV_XSAVE32)]
+  "TARGET_XSAVE"
+  "xsave\t%0"
+  [(set_attr "mode" "<MODE>")])
+
+(define_expand "xsave64"
+  [(unspec_volatile [(match_operand 0 "memory_operand" "=m")
+		     (match_operand 1 "register_operand")
+		     (match_operand 2 "register_operand")]
+		    UNSPECV_XSAVE64)]
+  "TARGET_XSAVE && TARGET_64BIT")
+
+(define_insn "*xsave64"
+  [(unspec_volatile [(match_operand:P 0 "memory_operand" "=m")
+		     (match_operand:SI 1 "register_operand" "d")
+		     (match_operand:SI 2 "register_operand" "a")]
+		    UNSPECV_XSAVE64)]
+  "TARGET_XSAVE && TARGET_64BIT"
+  "xsave64\t%0"
+  [(set_attr "mode" "<MODE>")])
+
+(define_expand "xsaveopt32"
+  [(unspec_volatile [(match_operand 0 "memory_operand")
+		     (match_operand 1 "register_operand")
+		     (match_operand 2 "register_operand")]
+		    UNSPECV_XSAVEOPT32)]
+  "TARGET_XSAVE")
+
+(define_insn "*xsaveopt32"
+  [(unspec_volatile [(match_operand:P 0 "memory_operand" "=m")
+		     (match_operand:SI 1 "register_operand" "d")
+		     (match_operand:SI 2 "register_operand" "a")]
+		    UNSPECV_XSAVEOPT32)]
+  "TARGET_XSAVE"
+  "xsaveopt\t%0"
+  [(set_attr "mode" "<MODE>")])
+
+(define_expand "xsaveopt64"
+  [(unspec_volatile [(match_operand 0 "memory_operand" "=m")
+		     (match_operand 1 "register_operand")
+		     (match_operand 2 "register_operand")]
+		    UNSPECV_XSAVEOPT64)]
+  "TARGET_XSAVE && TARGET_64BIT")
+
+(define_insn "*xsaveopt64"
+  [(unspec_volatile [(match_operand:P 0 "memory_operand" "=m")
+		     (match_operand:SI 1 "register_operand" "d")
+		     (match_operand:SI 2 "register_operand" "a")]
+		    UNSPECV_XSAVEOPT64)]
+  "TARGET_XSAVE && TARGET_64BIT"
+  "xsaveopt64\t%0"
+  [(set_attr "mode" "<MODE>")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
 ;; LWP instructions
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 6a38994..3ab5735 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -552,6 +552,14 @@ madx
 Target Report Mask(ISA_ADX) Var(ix86_isa_flags) Save
 Support flag-preserving add-carry instructions
 
+mfxsave
+Target Report Mask(ISA_FXSAVE) Var(ix86_isa_flags) Save
+Support FXSAVE and FXRSTOR instructions
+
+mxsave
+Target Report Mask(ISA_XSAVE) Var(ix86_isa_flags) Save
+Support XSAVE and FXRSTOR instructions
+
 mtbm
 Target Report Mask(ISA_TBM) Var(ix86_isa_flags) Save
 Support TBM built-in functions and code generation
diff --git a/gcc/config/i386/x86intrin.h b/gcc/config/i386/x86intrin.h
index fae6491..90914c7 100644
--- a/gcc/config/i386/x86intrin.h
+++ b/gcc/config/i386/x86intrin.h
@@ -105,6 +105,14 @@
 #include <prfchwintrin.h>
 #endif
 
+#ifdef __FXSAVE__
+#include <fxsaveintrin.h>
+#endif
+
+#ifdef __XSAVE__
+#include <xsaveintrin.h>
+#endif
+
 #include <adxintrin.h>
 
 #endif /* _X86INTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/xsaveintrin.h b/gcc/config/i386/xsaveintrin.h
new file mode 100644
index 0000000..9fc2dc5
--- /dev/null
+++ b/gcc/config/i386/xsaveintrin.h
@@ -0,0 +1,63 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* #if !defined _X86INTRIN_H_INCLUDED && !defined _IMMINTRIN_H_INCLUDED */
+/* # error "Never use <xsaveintrin.h> directly; include <x86intrin.h> instead." */
+/* #endif */
+
+#ifndef _XSAVEINTRIN_H_INCLUDED
+#define _XSAVEINTRIN_H_INCLUDED
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsave (void *mem, long long msk)
+{
+  return __builtin_ia32_xsave32 (mem, msk);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsave64 (void *mem, long long msk)
+{
+  return __builtin_ia32_xsave64 (mem, msk);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsaveopt (void *mem, long long msk)
+{
+  return __builtin_ia32_xsaveopt32 (mem, msk);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsaveopt64 (void *mem, long long msk)
+{
+  return __builtin_ia32_xsaveopt64 (mem, msk);
+}
+#endif
+
+#endif /* _XSAVEINTRIN_H_INCLUDED */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 74e7b1c..08e1312 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2012-10-16  Alexander Ivchenko  <alexander.ivchenko@intel.com>
+
+	* gcc.target/i386/fxsave-1.c: New.
+	* gcc.target/i386/fxsave64-1.c: Ditto.
+	* gcc.target/i386/xsave-1.c: Ditto.
+	* gcc.target/i386/xsave64-1.c: Ditto.
+	* gcc.target/i386/xsaveopt-1.c: Ditto.
+	* gcc.target/i386/xsaveopt64-1.c: Ditto.
+
 2012-10-15  Marc Glisse  <marc.glisse@inria.fr>
 
 	PR tree-optimization/54915
diff --git a/gcc/testsuite/gcc.target/i386/fxsave-1.c b/gcc/testsuite/gcc.target/i386/fxsave-1.c
new file mode 100644
index 0000000..940b54e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fxsave-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mfxsave -O2" } */
+/* { dg-final { scan-assembler "fxsave\[ \\t\]" } } */
+
+#include <x86intrin.h>
+
+void extern
+fxsave_test (void)
+{
+  char fxsave_region [512] __attribute__((aligned(16)));
+  _fxsave (fxsave_region);
+}
diff --git a/gcc/testsuite/gcc.target/i386/fxsave64-1.c b/gcc/testsuite/gcc.target/i386/fxsave64-1.c
new file mode 100644
index 0000000..b7dd2fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fxsave64-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mfxsave -O2" } */
+/* { dg-final { scan-assembler "fxsave64\[ \\t\]" } } */
+
+#include <x86intrin.h>
+
+void extern
+fxsave_test (void)
+{
+  char fxsave_region [512] __attribute__((aligned(16)));
+  _fxsave64 (fxsave_region);
+}
diff --git a/gcc/testsuite/gcc.target/i386/xsave-1.c b/gcc/testsuite/gcc.target/i386/xsave-1.c
new file mode 100644
index 0000000..9eee597
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsave-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mxsave -O2" } */
+/* { dg-final { scan-assembler "xsave\[ \\t\]" } } */
+
+#include <x86intrin.h>
+
+void extern
+xsave_test (void)
+{
+  char xsave_region [512] __attribute__((aligned(64)));
+  _xsave (xsave_region, ((long long) 0xA0000000F));
+}
diff --git a/gcc/testsuite/gcc.target/i386/xsave64-1.c b/gcc/testsuite/gcc.target/i386/xsave64-1.c
new file mode 100644
index 0000000..661da91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsave64-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mxsave -O2" } */
+/* { dg-final { scan-assembler "xsave64\[ \\t\]" } } */
+
+#include <x86intrin.h>
+
+void extern
+xsave_test (void)
+{
+  char xsave_region [512] __attribute__((aligned(64)));
+  _xsave64 (xsave_region, ((long long) 0xA0000000F));
+}
diff --git a/gcc/testsuite/gcc.target/i386/xsaveopt-1.c b/gcc/testsuite/gcc.target/i386/xsaveopt-1.c
new file mode 100644
index 0000000..68c510e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsaveopt-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mxsave -O2" } */
+/* { dg-final { scan-assembler "xsaveopt\[ \\t\]" } } */
+
+#include <x86intrin.h>
+
+void extern
+xsave_test (void)
+{
+  char xsaveopt_region [512] __attribute__((aligned(64)));
+  _xsaveopt (xsaveopt_region, ((long long) 0xA0000000F));
+}
diff --git a/gcc/testsuite/gcc.target/i386/xsaveopt64-1.c b/gcc/testsuite/gcc.target/i386/xsaveopt64-1.c
new file mode 100644
index 0000000..c5068a2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsaveopt64-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mxsave -O2" } */
+/* { dg-final { scan-assembler "xsaveopt64\[ \\t\]" } } */
+
+#include <x86intrin.h>
+
+void extern
+xsave_test (void)
+{
+  char xsaveopt_region [512] __attribute__((aligned(64)));
+  _xsaveopt64 (xsaveopt_region, ((long long) 0xA0000000F));
+}

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2013-08-26 12:08 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-18 10:22 [PATCH] Intrinsics for fxsave[,64], xsave[,64], xsaveopt[,64] Alexander Ivchenko
2012-10-18 16:00 ` Uros Bizjak
2012-10-18 16:44   ` Uros Bizjak
2012-10-19  9:33 ` H.J. Lu
     [not found]   ` <CACysShjhcionZNHw9jsrCZPQhsC1rjLN5Y0EW4cJt11JaqCHvQ@mail.gmail.com>
2012-10-22 19:20     ` Uros Bizjak
     [not found]       ` <CACysShivffw32UNR-vJXJ=e8zm_89kwTW2ch-GSiz_NuoEjnrQ@mail.gmail.com>
2012-10-23 11:39         ` Uros Bizjak
2012-10-24 11:23         ` H.J. Lu
2012-10-24 12:18           ` Uros Bizjak
2012-10-24 12:24             ` Uros Bizjak
2012-10-26  8:40             ` Uros Bizjak
2012-10-26  9:55               ` Kirill Yukhin
     [not found] ` <alpine.LNX.2.00.1308172209510.2133@trevally.site>
     [not found]   ` <CACysShhBg6yTcsPT4fx9WxnO3xt0nc+PoSk2S4Hg7fg_JApkFQ@mail.gmail.com>
2013-08-26 12:10     ` Alexander Ivchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).