diff mbox series

[1/3] Add PTWRITE builtins for x86

Message ID 20181104063235.6914-1-andi@firstfloor.org
State New
Headers show
Series [1/3] Add PTWRITE builtins for x86 | expand

Commit Message

Andi Kleen Nov. 4, 2018, 6:32 a.m. UTC
From: Andi Kleen <ak@linux.intel.com>

Add builtins/intrinsics for PTWRITE. PTWRITE is a new instruction on Intel Gemini Lake/
Goldmont Plus that allows to write values into the Processor Trace log. This allows
very light weight instrumentation of programs.

The intrinsics are compatible to icc. Automatically enabled for Goldmont Plus.

gcc/:

2018-11-03  Andi Kleen  <ak@linux.intel.com>

	* common/config/i386/i386-common.c (OPTION_MASK_ISA_PTWRITE_SET): New.
	(OPTION_MASK_ISA_PTWRITE_UNSET): New.
	(ix86_handle_option): Handle OPT_mptwrite.
	* config/i386/cpuid.h (bit_PTWRITE): Add.
	* config/i386/driver-i386.c (host_detect_local_cpu): Detect ptwrite.
	* config/i386/i386-builtin.def (BDESC): Add ptwrite32/64.
	* config/i386/i386-c.c (ix86_target_macros_internal): Define __PTWRITE__.
	* config/i386/i386.c (ix86_target_string): Handle ptwrite.
	(ix86_option_override_internal): Handle PTA_PTWRITE.
	(ix86_valid_target_attribute_inner_p): Define ptwrite.
	(def_builtin2): Force UINT64 to be 64bit only.
	* config/i386/i386.h (TARGET_PTWRITE): Add.
	(TARGET_PTWRITE_P): Add.
	(PTA_PTWRITE): Add.
	* config/i386/i386.md: Define ptwrite.
	* config/i386/i386.opt: Add -mptwrite.
	* config/i386/immintrin.h (_ptwrite64): Add.
	(_ptwrite32): Add
	* doc/extend.texi: Document __builtin_ia32_ptwrite*.
	* doc/invoke.texi: Document -mptwrite.

gcc/testsuite/ChangeLog:

2018-11-03  Andi Kleen  <ak@linux.intel.com>

	* gcc.target/i386/ptwrite1.c: New test.
	* gcc.target/i386/ptwrite2.c: New test.
---
 gcc/common/config/i386/i386-common.c     | 15 ++++++++++++
 gcc/config/i386/cpuid.h                  |  4 ++++
 gcc/config/i386/driver-i386.c            | 12 ++++++++++
 gcc/config/i386/i386-builtin.def         |  4 ++++
 gcc/config/i386/i386-c.c                 |  2 ++
 gcc/config/i386/i386.c                   |  9 ++++++-
 gcc/config/i386/i386.h                   |  5 +++-
 gcc/config/i386/i386.md                  | 10 ++++++++
 gcc/config/i386/i386.opt                 |  4 ++++
 gcc/config/i386/immintrin.h              | 26 ++++++++++++++++++++
 gcc/doc/extend.texi                      |  9 +++++++
 gcc/doc/invoke.texi                      |  7 ++++--
 gcc/testsuite/gcc.target/i386/ptwrite1.c | 30 ++++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/ptwrite2.c | 14 +++++++++++
 14 files changed, 147 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/ptwrite1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/ptwrite2.c

Comments

Andi Kleen Nov. 8, 2018, 5:10 p.m. UTC | #1
Andi Kleen <andi@firstfloor.org> writes:

Ping!

> From: Andi Kleen <ak@linux.intel.com>
>
> Add builtins/intrinsics for PTWRITE. PTWRITE is a new instruction on Intel Gemini Lake/
> Goldmont Plus that allows to write values into the Processor Trace log. This allows
> very light weight instrumentation of programs.
>
> The intrinsics are compatible to icc. Automatically enabled for Goldmont Plus.
>
> gcc/:
>
> 2018-11-03  Andi Kleen  <ak@linux.intel.com>
>
> 	* common/config/i386/i386-common.c (OPTION_MASK_ISA_PTWRITE_SET): New.
> 	(OPTION_MASK_ISA_PTWRITE_UNSET): New.
> 	(ix86_handle_option): Handle OPT_mptwrite.
> 	* config/i386/cpuid.h (bit_PTWRITE): Add.
> 	* config/i386/driver-i386.c (host_detect_local_cpu): Detect ptwrite.
> 	* config/i386/i386-builtin.def (BDESC): Add ptwrite32/64.
> 	* config/i386/i386-c.c (ix86_target_macros_internal): Define __PTWRITE__.
> 	* config/i386/i386.c (ix86_target_string): Handle ptwrite.
> 	(ix86_option_override_internal): Handle PTA_PTWRITE.
> 	(ix86_valid_target_attribute_inner_p): Define ptwrite.
> 	(def_builtin2): Force UINT64 to be 64bit only.
> 	* config/i386/i386.h (TARGET_PTWRITE): Add.
> 	(TARGET_PTWRITE_P): Add.
> 	(PTA_PTWRITE): Add.
> 	* config/i386/i386.md: Define ptwrite.
> 	* config/i386/i386.opt: Add -mptwrite.
> 	* config/i386/immintrin.h (_ptwrite64): Add.
> 	(_ptwrite32): Add
> 	* doc/extend.texi: Document __builtin_ia32_ptwrite*.
> 	* doc/invoke.texi: Document -mptwrite.
>
> gcc/testsuite/ChangeLog:
>
> 2018-11-03  Andi Kleen  <ak@linux.intel.com>
>
> 	* gcc.target/i386/ptwrite1.c: New test.
> 	* gcc.target/i386/ptwrite2.c: New test.
> ---
>  gcc/common/config/i386/i386-common.c     | 15 ++++++++++++
>  gcc/config/i386/cpuid.h                  |  4 ++++
>  gcc/config/i386/driver-i386.c            | 12 ++++++++++
>  gcc/config/i386/i386-builtin.def         |  4 ++++
>  gcc/config/i386/i386-c.c                 |  2 ++
>  gcc/config/i386/i386.c                   |  9 ++++++-
>  gcc/config/i386/i386.h                   |  5 +++-
>  gcc/config/i386/i386.md                  | 10 ++++++++
>  gcc/config/i386/i386.opt                 |  4 ++++
>  gcc/config/i386/immintrin.h              | 26 ++++++++++++++++++++
>  gcc/doc/extend.texi                      |  9 +++++++
>  gcc/doc/invoke.texi                      |  7 ++++--
>  gcc/testsuite/gcc.target/i386/ptwrite1.c | 30 ++++++++++++++++++++++++
>  gcc/testsuite/gcc.target/i386/ptwrite2.c | 14 +++++++++++
>  14 files changed, 147 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/ptwrite1.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/ptwrite2.c
>
> diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
> index f12806ef3a9..f740995c1e4 100644
> --- a/gcc/common/config/i386/i386-common.c
> +++ b/gcc/common/config/i386/i386-common.c
> @@ -140,6 +140,7 @@ along with GCC; see the file COPYING3.  If not see
>  
>  #define OPTION_MASK_ISA_FSGSBASE_SET OPTION_MASK_ISA_FSGSBASE
>  #define OPTION_MASK_ISA_RDRND_SET OPTION_MASK_ISA_RDRND
> +#define OPTION_MASK_ISA_PTWRITE_SET OPTION_MASK_ISA_PTWRITE
>  #define OPTION_MASK_ISA_F16C_SET \
>    (OPTION_MASK_ISA_F16C | OPTION_MASK_ISA_AVX_SET)
>  #define OPTION_MASK_ISA_MWAITX_SET OPTION_MASK_ISA_MWAITX
> @@ -267,6 +268,7 @@ along with GCC; see the file COPYING3.  If not see
>  
>  #define OPTION_MASK_ISA_FSGSBASE_UNSET OPTION_MASK_ISA_FSGSBASE
>  #define OPTION_MASK_ISA_RDRND_UNSET OPTION_MASK_ISA_RDRND
> +#define OPTION_MASK_ISA_PTWRITE_UNSET OPTION_MASK_ISA_PTWRITE
>  #define OPTION_MASK_ISA_F16C_UNSET OPTION_MASK_ISA_F16C
>  
>  #define OPTION_MASK_ISA_GENERAL_REGS_ONLY_UNSET \
> @@ -1125,6 +1127,19 @@ ix86_handle_option (struct gcc_options *opts,
>  	}
>        return true;
>  
> +    case OPT_mptwrite:
> +      if (value)
> +	{
> +	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_PTWRITE_SET;
> +	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_PTWRITE_SET;
> +	}
> +      else
> +	{
> +	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_PTWRITE_UNSET;
> +	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_PTWRITE_UNSET;
> +	}
> +      return true;
> +
>      case OPT_mf16c:
>        if (value)
>  	{
> diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
> index 7e9e2d153dc..2e6d4a55602 100644
> --- a/gcc/config/i386/cpuid.h
> +++ b/gcc/config/i386/cpuid.h
> @@ -126,6 +126,10 @@
>  #define bit_XSAVEC	(1 << 1)
>  #define bit_XSAVES	(1 << 3)
>  
> +/* PT sub leaf (%eax == 14, %ecx == 0) */
> +/* %ebx */
> +#define bit_PTWRITE	(1 << 4)
> +
>  /* Signatures for different CPU implementations as returned in uses
>     of cpuid with level 0.  */
>  #define signature_AMD_ebx	0x68747541
> diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
> index 8c830bde1dd..423b1c3827f 100644
> --- a/gcc/config/i386/driver-i386.c
> +++ b/gcc/config/i386/driver-i386.c
> @@ -427,6 +427,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>    unsigned int has_waitpkg = 0;
>    unsigned int has_cldemote = 0;
>  
> +  unsigned int has_ptwrite = 0;
> +
>    bool arch;
>  
>    unsigned int l2sizekb = 0;
> @@ -542,6 +544,13 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>        has_xsaves = eax & bit_XSAVES;
>      }
>  
> +  if (max_level >= 0x14)
> +    {
> +      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
> +
> +      has_ptwrite = ebx & bit_PTWRITE;
> +    }
> +
>    /* Check cpuid level of extended features.  */
>    __cpuid (0x80000000, ext_level, ebx, ecx, edx);
>  
> @@ -1124,6 +1133,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>        const char *movdir64b = has_movdir64b ? " -mmovdir64b" : " -mno-movdir64b";
>        const char *waitpkg = has_waitpkg ? " -mwaitpkg" : " -mno-waitpkg";
>        const char *cldemote = has_cldemote ? " -mcldemote" : " -mno-cldemote";
> +      const char *ptwrite = has_ptwrite ? " -mptwrite" : " -mno-ptwrite";
> +
>        options = concat (options, mmx, mmx3dnow, sse, sse2, sse3, ssse3,
>  			sse4a, cx16, sahf, movbe, aes, sha, pclmul,
>  			popcnt, abm, lwp, fma, fma4, xop, bmi, sgx, bmi2,
> @@ -1137,6 +1148,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>  			clwb, mwaitx, clzero, pku, rdpid, gfni, shstk,
>  			avx512vbmi2, avx512vnni, vaes, vpclmulqdq,
>  			avx512bitalg, movdiri, movdir64b, waitpkg, cldemote,
> +			ptwrite,
>  			NULL);
>      }
>  
> diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
> index df0f7e975ac..ca3f357228f 100644
> --- a/gcc/config/i386/i386-builtin.def
> +++ b/gcc/config/i386/i386-builtin.def
> @@ -2879,6 +2879,10 @@ BDESC_FIRST (special_args2, SPECIAL_ARGS2,
>  	OPTION_MASK_ISA_WBNOINVD, CODE_FOR_wbnoinvd, "__builtin_ia32_wbnoinvd", IX86_BUILTIN_WBNOINVD, UNKNOWN, (int) VOID_FTYPE_VOID)
>  BDESC (OPTION_MASK_ISA_MOVDIR64B, CODE_FOR_nothing, "__builtin_ia32_movdir64b", IX86_BUILTIN_MOVDIR64B, UNKNOWN, (int) VOID_FTYPE_PVOID_PCVOID)
>  
> +/* PTWRITE */
> +BDESC (OPTION_MASK_ISA_PTWRITE, CODE_FOR_ptwritesi, "__builtin_ia32_ptwrite32", IX86_BUILTIN_PTWRITE32, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
> +BDESC (OPTION_MASK_ISA_PTWRITE, CODE_FOR_ptwritedi, "__builtin_ia32_ptwrite64", IX86_BUILTIN_PTWRITE64, UNKNOWN, (int) VOID_FTYPE_UINT64)
> +
>  BDESC_END (SPECIAL_ARGS2, MULTI_ARG)
>  
>  /* FMA4 and XOP.  */
> diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
> index 005e1a5b308..4661d00f85d 100644
> --- a/gcc/config/i386/i386-c.c
> +++ b/gcc/config/i386/i386-c.c
> @@ -532,6 +532,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
>      def_or_undef (parse_in, "__WAITPKG__");
>    if (isa_flag2 & OPTION_MASK_ISA_CLDEMOTE)
>      def_or_undef (parse_in, "__CLDEMOTE__");
> +  if (isa_flag2 & OPTION_MASK_ISA_PTWRITE)
> +    def_or_undef (parse_in, "__PTWRITE__");
>    if (TARGET_IAMCU)
>      {
>        def_or_undef (parse_in, "__iamcu");
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 963c7fcbb34..490bb6292a8 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -2793,7 +2793,8 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
>      { "-mmwaitx",	OPTION_MASK_ISA_MWAITX },
>      { "-mmovdir64b",	OPTION_MASK_ISA_MOVDIR64B },
>      { "-mwaitpkg",	OPTION_MASK_ISA_WAITPKG },
> -    { "-mcldemote",	OPTION_MASK_ISA_CLDEMOTE }
> +    { "-mcldemote",	OPTION_MASK_ISA_CLDEMOTE },
> +    { "-mptwrite",	OPTION_MASK_ISA_PTWRITE }
>    };
>    static struct ix86_target_opts isa_opts[] =
>    {
> @@ -3875,6 +3876,9 @@ ix86_option_override_internal (bool main_args_p,
>  	if (((processor_alias_table[i].flags & PTA_WBNOINVD) != 0)
>  	    && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA_WBNOINVD))
>  	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_WBNOINVD;
> +	if (((processor_alias_table[i].flags & PTA_PTWRITE) != 0)
> +	    && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA_PTWRITE))
> +	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_PTWRITE;
>  
>  	if ((processor_alias_table[i].flags
>  	   & (PTA_PREFETCH_SSE | PTA_SSE)) != 0)
> @@ -5077,6 +5081,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
>      IX86_ATTR_ISA ("movdir64b", OPT_mmovdir64b),
>      IX86_ATTR_ISA ("waitpkg", OPT_mwaitpkg),
>      IX86_ATTR_ISA ("cldemote", OPT_mcldemote),
> +    IX86_ATTR_ISA ("ptwrite",   OPT_mptwrite),
>  
>      /* enum options */
>      IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
> @@ -30180,6 +30185,8 @@ def_builtin2 (HOST_WIDE_INT mask, const char *name,
>    tree decl = NULL_TREE;
>  
>    ix86_builtins_isa[(int) code].isa2 = mask;
> +  if (tcode == VOID_FTYPE_UINT64)
> +    ix86_builtins_isa[(int) code].isa = OPTION_MASK_ISA_64BIT;
>  
>    if (mask == 0
>        || (mask & ix86_isa_flags2) != 0
> diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
> index 01d49a7263b..39d3e59c8dd 100644
> --- a/gcc/config/i386/i386.h
> +++ b/gcc/config/i386/i386.h
> @@ -191,6 +191,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>  #define TARGET_WAITPKG_P(x)	TARGET_ISA_WAITPKG_P(x)
>  #define TARGET_CLDEMOTE	TARGET_ISA_CLDEMOTE
>  #define TARGET_CLDEMOTE_P(x) TARGET_ISA_CLDEMOTE_P(x)
> +#define TARGET_PTWRITE	TARGET_ISA_PTWRITE
> +#define TARGET_PTWRITE_P(x)	TARGET_ISA_PTWRITE_P(x)
>  
>  #define TARGET_LP64	TARGET_ABI_64
>  #define TARGET_LP64_P(x)	TARGET_ABI_64_P(x)
> @@ -2354,6 +2356,7 @@ const wide_int_bitmask PTA_RDPID (0, HOST_WIDE_INT_1U << 6);
>  const wide_int_bitmask PTA_PCONFIG (0, HOST_WIDE_INT_1U << 7);
>  const wide_int_bitmask PTA_WBNOINVD (0, HOST_WIDE_INT_1U << 8);
>  const wide_int_bitmask PTA_WAITPKG (0, HOST_WIDE_INT_1U << 9);
> +const wide_int_bitmask PTA_PTWRITE (0, HOST_WIDE_INT_1U << 10);
>  
>  const wide_int_bitmask PTA_CORE2 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
>    | PTA_SSE3 | PTA_SSSE3 | PTA_CX16 | PTA_FXSR;
> @@ -2389,7 +2392,7 @@ const wide_int_bitmask PTA_GOLDMONT = PTA_SILVERMONT | PTA_SHA | PTA_XSAVE
>    | PTA_RDSEED | PTA_XSAVEC | PTA_XSAVES | PTA_CLFLUSHOPT | PTA_XSAVEOPT
>    | PTA_FSGSBASE;
>  const wide_int_bitmask PTA_GOLDMONT_PLUS = PTA_GOLDMONT | PTA_RDPID
> -  | PTA_SGX;
> +  | PTA_SGX | PTA_PTWRITE;
>  const wide_int_bitmask PTA_TREMONT = PTA_GOLDMONT_PLUS | PTA_CLWB
>    | PTA_GFNI;
>  const wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index 7fb2b144f47..bdc39456106 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -292,6 +292,8 @@
>  
>    ;; For Speculation Barrier support
>    UNSPECV_SPECULATION_BARRIER
> +
> +  UNSPECV_PTWRITE
>  ])
>  
>  ;; Constants to represent rounding modes in the ROUND instruction
> @@ -19498,6 +19500,14 @@
>    [(set_attr "type" "other")
>     (set_attr "prefix_extra" "2")])
>  
> +(define_insn "ptwrite<mode>"
> +  [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")]
> +		    UNSPECV_PTWRITE)]
> +  "TARGET_PTWRITE"
> +  "ptwrite\t%0"
> +  [(set_attr "type" "other")
> +   (set_attr "prefix_extra" "2")])
> +
>  (define_insn "rdrand<mode>_1"
>    [(set (match_operand:SWI248 0 "register_operand" "=r")
>  	(unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))
> diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> index e7fbf9b6f99..1705815a2ec 100644
> --- a/gcc/config/i386/i386.opt
> +++ b/gcc/config/i386/i386.opt
> @@ -785,6 +785,10 @@ mwbnoinvd
>  Target Report Mask(ISA_WBNOINVD) Var(ix86_isa_flags2) Save
>  Support WBNOINVD built-in functions and code generation.
>  
> +mptwrite
> +Target Report Mask(ISA_PTWRITE) Var(ix86_isa_flags2) Save
> +Support PTWRITE built-in functions and code generation.
> +
>  msgx
>  Target Report Mask(ISA_SGX) Var(ix86_isa_flags2) Save
>  Support SGX built-in functions and code generation.
> diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
> index 344e92c745a..b52ab91b4d5 100644
> --- a/gcc/config/i386/immintrin.h
> +++ b/gcc/config/i386/immintrin.h
> @@ -251,4 +251,30 @@ _rdrand64_step (unsigned long long *__P)
>  
>  #endif /* __x86_64__  */
>  
> +#ifndef __PTWRITE__
> +#pragma GCC push_options
> +#pragma GCC target("ptwrite")
> +#define __DISABLE_PTWRITE__
> +#endif
> +
> +#ifdef __x86_64__
> +extern __inline void
> +__attribute__((__gnu_inline__, __always_inline__, __artificial__))
> +_ptwrite64 (unsigned long long __B)
> +{
> +  __builtin_ia32_ptwrite64 (__B);
> +}
> +#endif /* __x86_64__ */
> +
> +extern __inline void
> +__attribute__((__gnu_inline__, __always_inline__, __artificial__))
> +_ptwrite32 (unsigned __B)
> +{
> +  __builtin_ia32_ptwrite32 (__B);
> +}
> +#ifdef __DISABLE_PTWRITE__
> +#undef __DISABLE_PTWRITE__
> +#pragma GCC pop_options
> +#endif /* __DISABLE_PTWRITE__ */
> +
>  #endif /* _IMMINTRIN_H_INCLUDED */
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index e2b9ee11a54..1eca009e255 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -21331,6 +21331,15 @@ unsigned int __builtin_ia32_rdrand32_step (unsigned int *)
>  unsigned int __builtin_ia32_rdrand64_step (unsigned long long *)
>  @end smallexample
>  
> +The following built-in function is available when @option{-mptwrite} is
> +used.  All of them generate the machine instruction that is part of the
> +name.
> +
> +@smallexample
> +void __builtin_ia32_ptwrite32 (unsigned)
> +void __builtin_ia32_ptwrite64 (unsigned long long)
> +@end smallexample
> +
>  The following built-in functions are available when @option{-msse4a} is used.
>  All of them generate the machine instruction that is part of the name.
>  
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index e290128f535..cb5bc7bafc5 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1281,7 +1281,7 @@ See RS/6000 and PowerPC Options.
>  -mmmx  -msse  -msse2  -msse3  -mssse3  -msse4.1  -msse4.2  -msse4  -mavx @gol
>  -mavx2  -mavx512f  -mavx512pf  -mavx512er  -mavx512cd  -mavx512vl @gol
>  -mavx512bw  -mavx512dq  -mavx512ifma  -mavx512vbmi  -msha  -maes @gol
> --mpclmul  -mfsgsbase  -mrdrnd  -mf16c  -mfma -mpconfig -mwbnoinvd @gol
> +-mpclmul  -mfsgsbase  -mrdrnd  -mf16c  -mfma -mpconfig -mwbnoinvd -mptwrite @gol
>  -mprefetchwt1  -mclflushopt  -mxsavec  -mxsaves @gol
>  -msse4a  -m3dnow  -m3dnowa  -mpopcnt  -mabm  -mbmi  -mtbm  -mfma4  -mxop @gol
>  -mlzcnt  -mbmi2  -mfxsr  -mxsave  -mxsaveopt  -mrtm  -mlwp @gol
> @@ -27815,6 +27815,9 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
>  @itemx -mfsgsbase
>  @opindex mfsgsbase
>  @need 200
> +@itemx -mptwrite
> +@opindex mptwrite
> +@need 200
>  @itemx -mrdrnd
>  @opindex mrdrnd
>  @need 200
> @@ -27923,7 +27926,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
>  @opindex mcldemote
>  These switches enable the use of instructions in the MMX, SSE,
>  SSE2, SSE3, SSSE3, SSE4.1, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD,
> -SHA, AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM,
> +SHA, AES, PCLMUL, FSGSBASE, PTWRITE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM,
>  AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, BMI, BMI2, VAES, WAITPKG,
>  FXSR, XSAVE, XSAVEOPT, LZCNT, RTM, MWAITX, PKU, IBT, SHSTK, AVX512VBMI2,
>  GFNI, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B,
> diff --git a/gcc/testsuite/gcc.target/i386/ptwrite1.c b/gcc/testsuite/gcc.target/i386/ptwrite1.c
> new file mode 100644
> index 00000000000..e09028ed428
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ptwrite1.c
> @@ -0,0 +1,30 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mptwrite" } */
> +/* { dg-final { scan-assembler "ptwrite" } } */
> +
> +void ptwrite1(int a)
> +{
> +  __builtin_ia32_ptwrite32 (a);
> +}
> +
> +#ifdef __x86_64__
> +void ptwrite2(unsigned long b)
> +{
> +  __builtin_ia32_ptwrite64 (b);
> +}
> +
> +void ptwrite3(unsigned char b)
> +{
> +  __builtin_ia32_ptwrite64 (b);
> +}
> +
> +void ptwrite4(unsigned short b)
> +{
> +  __builtin_ia32_ptwrite64 (b);
> +}
> +#endif
> +
> +void ptwrite5(unsigned short b)
> +{
> +  __builtin_ia32_ptwrite32 (b);
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/ptwrite2.c b/gcc/testsuite/gcc.target/i386/ptwrite2.c
> new file mode 100644
> index 00000000000..299c6511ef4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ptwrite2.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mptwrite " } */
> +/* { dg-final { scan-assembler "ptwrite.*r" } } */
> +/* { dg-final { scan-assembler "ptwrite.*e" } } */
> +
> +#include <x86intrin.h>
> +
> +void ptwrite1(void)
> +{
> +  _ptwrite32 (1);
> +#ifdef __x86_64__
> +  _ptwrite64 (2);
> +#endif
> +}
diff mbox series

Patch

diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index f12806ef3a9..f740995c1e4 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -140,6 +140,7 @@  along with GCC; see the file COPYING3.  If not see
 
 #define OPTION_MASK_ISA_FSGSBASE_SET OPTION_MASK_ISA_FSGSBASE
 #define OPTION_MASK_ISA_RDRND_SET OPTION_MASK_ISA_RDRND
+#define OPTION_MASK_ISA_PTWRITE_SET OPTION_MASK_ISA_PTWRITE
 #define OPTION_MASK_ISA_F16C_SET \
   (OPTION_MASK_ISA_F16C | OPTION_MASK_ISA_AVX_SET)
 #define OPTION_MASK_ISA_MWAITX_SET OPTION_MASK_ISA_MWAITX
@@ -267,6 +268,7 @@  along with GCC; see the file COPYING3.  If not see
 
 #define OPTION_MASK_ISA_FSGSBASE_UNSET OPTION_MASK_ISA_FSGSBASE
 #define OPTION_MASK_ISA_RDRND_UNSET OPTION_MASK_ISA_RDRND
+#define OPTION_MASK_ISA_PTWRITE_UNSET OPTION_MASK_ISA_PTWRITE
 #define OPTION_MASK_ISA_F16C_UNSET OPTION_MASK_ISA_F16C
 
 #define OPTION_MASK_ISA_GENERAL_REGS_ONLY_UNSET \
@@ -1125,6 +1127,19 @@  ix86_handle_option (struct gcc_options *opts,
 	}
       return true;
 
+    case OPT_mptwrite:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_PTWRITE_SET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_PTWRITE_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_PTWRITE_UNSET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_PTWRITE_UNSET;
+	}
+      return true;
+
     case OPT_mf16c:
       if (value)
 	{
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 7e9e2d153dc..2e6d4a55602 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -126,6 +126,10 @@ 
 #define bit_XSAVEC	(1 << 1)
 #define bit_XSAVES	(1 << 3)
 
+/* PT sub leaf (%eax == 14, %ecx == 0) */
+/* %ebx */
+#define bit_PTWRITE	(1 << 4)
+
 /* Signatures for different CPU implementations as returned in uses
    of cpuid with level 0.  */
 #define signature_AMD_ebx	0x68747541
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 8c830bde1dd..423b1c3827f 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -427,6 +427,8 @@  const char *host_detect_local_cpu (int argc, const char **argv)
   unsigned int has_waitpkg = 0;
   unsigned int has_cldemote = 0;
 
+  unsigned int has_ptwrite = 0;
+
   bool arch;
 
   unsigned int l2sizekb = 0;
@@ -542,6 +544,13 @@  const char *host_detect_local_cpu (int argc, const char **argv)
       has_xsaves = eax & bit_XSAVES;
     }
 
+  if (max_level >= 0x14)
+    {
+      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
+
+      has_ptwrite = ebx & bit_PTWRITE;
+    }
+
   /* Check cpuid level of extended features.  */
   __cpuid (0x80000000, ext_level, ebx, ecx, edx);
 
@@ -1124,6 +1133,8 @@  const char *host_detect_local_cpu (int argc, const char **argv)
       const char *movdir64b = has_movdir64b ? " -mmovdir64b" : " -mno-movdir64b";
       const char *waitpkg = has_waitpkg ? " -mwaitpkg" : " -mno-waitpkg";
       const char *cldemote = has_cldemote ? " -mcldemote" : " -mno-cldemote";
+      const char *ptwrite = has_ptwrite ? " -mptwrite" : " -mno-ptwrite";
+
       options = concat (options, mmx, mmx3dnow, sse, sse2, sse3, ssse3,
 			sse4a, cx16, sahf, movbe, aes, sha, pclmul,
 			popcnt, abm, lwp, fma, fma4, xop, bmi, sgx, bmi2,
@@ -1137,6 +1148,7 @@  const char *host_detect_local_cpu (int argc, const char **argv)
 			clwb, mwaitx, clzero, pku, rdpid, gfni, shstk,
 			avx512vbmi2, avx512vnni, vaes, vpclmulqdq,
 			avx512bitalg, movdiri, movdir64b, waitpkg, cldemote,
+			ptwrite,
 			NULL);
     }
 
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index df0f7e975ac..ca3f357228f 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -2879,6 +2879,10 @@  BDESC_FIRST (special_args2, SPECIAL_ARGS2,
 	OPTION_MASK_ISA_WBNOINVD, CODE_FOR_wbnoinvd, "__builtin_ia32_wbnoinvd", IX86_BUILTIN_WBNOINVD, UNKNOWN, (int) VOID_FTYPE_VOID)
 BDESC (OPTION_MASK_ISA_MOVDIR64B, CODE_FOR_nothing, "__builtin_ia32_movdir64b", IX86_BUILTIN_MOVDIR64B, UNKNOWN, (int) VOID_FTYPE_PVOID_PCVOID)
 
+/* PTWRITE */
+BDESC (OPTION_MASK_ISA_PTWRITE, CODE_FOR_ptwritesi, "__builtin_ia32_ptwrite32", IX86_BUILTIN_PTWRITE32, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
+BDESC (OPTION_MASK_ISA_PTWRITE, CODE_FOR_ptwritedi, "__builtin_ia32_ptwrite64", IX86_BUILTIN_PTWRITE64, UNKNOWN, (int) VOID_FTYPE_UINT64)
+
 BDESC_END (SPECIAL_ARGS2, MULTI_ARG)
 
 /* FMA4 and XOP.  */
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 005e1a5b308..4661d00f85d 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -532,6 +532,8 @@  ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
     def_or_undef (parse_in, "__WAITPKG__");
   if (isa_flag2 & OPTION_MASK_ISA_CLDEMOTE)
     def_or_undef (parse_in, "__CLDEMOTE__");
+  if (isa_flag2 & OPTION_MASK_ISA_PTWRITE)
+    def_or_undef (parse_in, "__PTWRITE__");
   if (TARGET_IAMCU)
     {
       def_or_undef (parse_in, "__iamcu");
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 963c7fcbb34..490bb6292a8 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2793,7 +2793,8 @@  ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
     { "-mmwaitx",	OPTION_MASK_ISA_MWAITX },
     { "-mmovdir64b",	OPTION_MASK_ISA_MOVDIR64B },
     { "-mwaitpkg",	OPTION_MASK_ISA_WAITPKG },
-    { "-mcldemote",	OPTION_MASK_ISA_CLDEMOTE }
+    { "-mcldemote",	OPTION_MASK_ISA_CLDEMOTE },
+    { "-mptwrite",	OPTION_MASK_ISA_PTWRITE }
   };
   static struct ix86_target_opts isa_opts[] =
   {
@@ -3875,6 +3876,9 @@  ix86_option_override_internal (bool main_args_p,
 	if (((processor_alias_table[i].flags & PTA_WBNOINVD) != 0)
 	    && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA_WBNOINVD))
 	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_WBNOINVD;
+	if (((processor_alias_table[i].flags & PTA_PTWRITE) != 0)
+	    && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA_PTWRITE))
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_PTWRITE;
 
 	if ((processor_alias_table[i].flags
 	   & (PTA_PREFETCH_SSE | PTA_SSE)) != 0)
@@ -5077,6 +5081,7 @@  ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
     IX86_ATTR_ISA ("movdir64b", OPT_mmovdir64b),
     IX86_ATTR_ISA ("waitpkg", OPT_mwaitpkg),
     IX86_ATTR_ISA ("cldemote", OPT_mcldemote),
+    IX86_ATTR_ISA ("ptwrite",   OPT_mptwrite),
 
     /* enum options */
     IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
@@ -30180,6 +30185,8 @@  def_builtin2 (HOST_WIDE_INT mask, const char *name,
   tree decl = NULL_TREE;
 
   ix86_builtins_isa[(int) code].isa2 = mask;
+  if (tcode == VOID_FTYPE_UINT64)
+    ix86_builtins_isa[(int) code].isa = OPTION_MASK_ISA_64BIT;
 
   if (mask == 0
       || (mask & ix86_isa_flags2) != 0
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 01d49a7263b..39d3e59c8dd 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -191,6 +191,8 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_WAITPKG_P(x)	TARGET_ISA_WAITPKG_P(x)
 #define TARGET_CLDEMOTE	TARGET_ISA_CLDEMOTE
 #define TARGET_CLDEMOTE_P(x) TARGET_ISA_CLDEMOTE_P(x)
+#define TARGET_PTWRITE	TARGET_ISA_PTWRITE
+#define TARGET_PTWRITE_P(x)	TARGET_ISA_PTWRITE_P(x)
 
 #define TARGET_LP64	TARGET_ABI_64
 #define TARGET_LP64_P(x)	TARGET_ABI_64_P(x)
@@ -2354,6 +2356,7 @@  const wide_int_bitmask PTA_RDPID (0, HOST_WIDE_INT_1U << 6);
 const wide_int_bitmask PTA_PCONFIG (0, HOST_WIDE_INT_1U << 7);
 const wide_int_bitmask PTA_WBNOINVD (0, HOST_WIDE_INT_1U << 8);
 const wide_int_bitmask PTA_WAITPKG (0, HOST_WIDE_INT_1U << 9);
+const wide_int_bitmask PTA_PTWRITE (0, HOST_WIDE_INT_1U << 10);
 
 const wide_int_bitmask PTA_CORE2 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
   | PTA_SSE3 | PTA_SSSE3 | PTA_CX16 | PTA_FXSR;
@@ -2389,7 +2392,7 @@  const wide_int_bitmask PTA_GOLDMONT = PTA_SILVERMONT | PTA_SHA | PTA_XSAVE
   | PTA_RDSEED | PTA_XSAVEC | PTA_XSAVES | PTA_CLFLUSHOPT | PTA_XSAVEOPT
   | PTA_FSGSBASE;
 const wide_int_bitmask PTA_GOLDMONT_PLUS = PTA_GOLDMONT | PTA_RDPID
-  | PTA_SGX;
+  | PTA_SGX | PTA_PTWRITE;
 const wide_int_bitmask PTA_TREMONT = PTA_GOLDMONT_PLUS | PTA_CLWB
   | PTA_GFNI;
 const wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 7fb2b144f47..bdc39456106 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -292,6 +292,8 @@ 
 
   ;; For Speculation Barrier support
   UNSPECV_SPECULATION_BARRIER
+
+  UNSPECV_PTWRITE
 ])
 
 ;; Constants to represent rounding modes in the ROUND instruction
@@ -19498,6 +19500,14 @@ 
   [(set_attr "type" "other")
    (set_attr "prefix_extra" "2")])
 
+(define_insn "ptwrite<mode>"
+  [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")]
+		    UNSPECV_PTWRITE)]
+  "TARGET_PTWRITE"
+  "ptwrite\t%0"
+  [(set_attr "type" "other")
+   (set_attr "prefix_extra" "2")])
+
 (define_insn "rdrand<mode>_1"
   [(set (match_operand:SWI248 0 "register_operand" "=r")
 	(unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index e7fbf9b6f99..1705815a2ec 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -785,6 +785,10 @@  mwbnoinvd
 Target Report Mask(ISA_WBNOINVD) Var(ix86_isa_flags2) Save
 Support WBNOINVD built-in functions and code generation.
 
+mptwrite
+Target Report Mask(ISA_PTWRITE) Var(ix86_isa_flags2) Save
+Support PTWRITE built-in functions and code generation.
+
 msgx
 Target Report Mask(ISA_SGX) Var(ix86_isa_flags2) Save
 Support SGX built-in functions and code generation.
diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
index 344e92c745a..b52ab91b4d5 100644
--- a/gcc/config/i386/immintrin.h
+++ b/gcc/config/i386/immintrin.h
@@ -251,4 +251,30 @@  _rdrand64_step (unsigned long long *__P)
 
 #endif /* __x86_64__  */
 
+#ifndef __PTWRITE__
+#pragma GCC push_options
+#pragma GCC target("ptwrite")
+#define __DISABLE_PTWRITE__
+#endif
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_ptwrite64 (unsigned long long __B)
+{
+  __builtin_ia32_ptwrite64 (__B);
+}
+#endif /* __x86_64__ */
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_ptwrite32 (unsigned __B)
+{
+  __builtin_ia32_ptwrite32 (__B);
+}
+#ifdef __DISABLE_PTWRITE__
+#undef __DISABLE_PTWRITE__
+#pragma GCC pop_options
+#endif /* __DISABLE_PTWRITE__ */
+
 #endif /* _IMMINTRIN_H_INCLUDED */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e2b9ee11a54..1eca009e255 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -21331,6 +21331,15 @@  unsigned int __builtin_ia32_rdrand32_step (unsigned int *)
 unsigned int __builtin_ia32_rdrand64_step (unsigned long long *)
 @end smallexample
 
+The following built-in function is available when @option{-mptwrite} is
+used.  All of them generate the machine instruction that is part of the
+name.
+
+@smallexample
+void __builtin_ia32_ptwrite32 (unsigned)
+void __builtin_ia32_ptwrite64 (unsigned long long)
+@end smallexample
+
 The following built-in functions are available when @option{-msse4a} is used.
 All of them generate the machine instruction that is part of the name.
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e290128f535..cb5bc7bafc5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1281,7 +1281,7 @@  See RS/6000 and PowerPC Options.
 -mmmx  -msse  -msse2  -msse3  -mssse3  -msse4.1  -msse4.2  -msse4  -mavx @gol
 -mavx2  -mavx512f  -mavx512pf  -mavx512er  -mavx512cd  -mavx512vl @gol
 -mavx512bw  -mavx512dq  -mavx512ifma  -mavx512vbmi  -msha  -maes @gol
--mpclmul  -mfsgsbase  -mrdrnd  -mf16c  -mfma -mpconfig -mwbnoinvd @gol
+-mpclmul  -mfsgsbase  -mrdrnd  -mf16c  -mfma -mpconfig -mwbnoinvd -mptwrite @gol
 -mprefetchwt1  -mclflushopt  -mxsavec  -mxsaves @gol
 -msse4a  -m3dnow  -m3dnowa  -mpopcnt  -mabm  -mbmi  -mtbm  -mfma4  -mxop @gol
 -mlzcnt  -mbmi2  -mfxsr  -mxsave  -mxsaveopt  -mrtm  -mlwp @gol
@@ -27815,6 +27815,9 @@  preferred alignment to @option{-mpreferred-stack-boundary=2}.
 @itemx -mfsgsbase
 @opindex mfsgsbase
 @need 200
+@itemx -mptwrite
+@opindex mptwrite
+@need 200
 @itemx -mrdrnd
 @opindex mrdrnd
 @need 200
@@ -27923,7 +27926,7 @@  preferred alignment to @option{-mpreferred-stack-boundary=2}.
 @opindex mcldemote
 These switches enable the use of instructions in the MMX, SSE,
 SSE2, SSE3, SSSE3, SSE4.1, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD,
-SHA, AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM,
+SHA, AES, PCLMUL, FSGSBASE, PTWRITE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM,
 AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, BMI, BMI2, VAES, WAITPKG,
 FXSR, XSAVE, XSAVEOPT, LZCNT, RTM, MWAITX, PKU, IBT, SHSTK, AVX512VBMI2,
 GFNI, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B,
diff --git a/gcc/testsuite/gcc.target/i386/ptwrite1.c b/gcc/testsuite/gcc.target/i386/ptwrite1.c
new file mode 100644
index 00000000000..e09028ed428
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ptwrite1.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -mptwrite" } */
+/* { dg-final { scan-assembler "ptwrite" } } */
+
+void ptwrite1(int a)
+{
+  __builtin_ia32_ptwrite32 (a);
+}
+
+#ifdef __x86_64__
+void ptwrite2(unsigned long b)
+{
+  __builtin_ia32_ptwrite64 (b);
+}
+
+void ptwrite3(unsigned char b)
+{
+  __builtin_ia32_ptwrite64 (b);
+}
+
+void ptwrite4(unsigned short b)
+{
+  __builtin_ia32_ptwrite64 (b);
+}
+#endif
+
+void ptwrite5(unsigned short b)
+{
+  __builtin_ia32_ptwrite32 (b);
+}
diff --git a/gcc/testsuite/gcc.target/i386/ptwrite2.c b/gcc/testsuite/gcc.target/i386/ptwrite2.c
new file mode 100644
index 00000000000..299c6511ef4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ptwrite2.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -mptwrite " } */
+/* { dg-final { scan-assembler "ptwrite.*r" } } */
+/* { dg-final { scan-assembler "ptwrite.*e" } } */
+
+#include <x86intrin.h>
+
+void ptwrite1(void)
+{
+  _ptwrite32 (1);
+#ifdef __x86_64__
+  _ptwrite64 (2);
+#endif
+}