Hi:

This patch is about to support User Interrupt (UINTR) instructions.

This feature defines user interrupts as new events in the architecture.
They are delivered to software operating in 64-bit mode with CPL = 3
without any change to segmentation state.

For more details, please refer to
https://software.intel.com/content/dam/develop/external/us/en/documents/architecture-instruction-set-extensions-programming-reference.pdf

Bootstrap ok, regression test on i386/x86 backend is ok.

OK for master?

gcc/
* common/config/i386/cpuinfo.h (get_available_features):
Detect UINTR.
* common/config/i386/i386-common.c (OPTION_MASK_ISA2_UINTR_SET
OPTION_MASK_ISA2_UINTR_UNSET): New.
(ix86_handle_option): Handle -muintr.
* common/config/i386/i386-cpuinfo.h (enum processor_features):
Add FEATURE_UINTR.
* common/config/i386/i386-isas.h: Add ISA_NAMES_TABLE_ENTRY
for uintr.
* config.gcc: Add uintrintrin.h to extra_headers.
* config/i386/uintrintrin.h: New.
* config/i386/cpuid.h (bit_UINTR): New.
* config/i386/driver-i386.c (host_detect_local_cpu): Detect UINTR.
* config/i386/i386-builtin-types.def: Add new types.
* config/i386/i386-builtin.def: Add new builtins.
* config/i386/i386-builtins.c (ix86_init_mmx_sse_builtins): Add
__builtin_ia32_testui.
* config/i386/i386-builtins.h (ix86_builtins): Add
IX86_BUILTIN_TESTUI.
* config/i386/i386-c.c (ix86_target_macros_internal): Define
__UINTR__.
* config/i386/i386-expand.c (ix86_expand_special_args_builtin):
Handle UINT8_FTYPE_VOID.
(ix86_expand_builtin): Handle IX86_BUILTIN_TESTUI.
* config/i386/i386-options.c (isa2_opts): Add -muintr.
(ix86_valid_target_attribute_inner_p): Handle UINTR.
(ix86_option_override_internal): Add TARGET_64BIT check for UINTR.
* config/i386/i386.h (TARGET_UINTR, TARGET_UINTR_P, PTA_UINTR): New.
(PTA_SAPPHIRRAPIDS): Add PTA_UINTR.
* config/i386/i386.opt: Add -muintr.
* config/i386/i386.md
(define_int_iterator UINTR_UNSPECV): New.
(define_int_attr uintr_unspecv): New.
(uintr_<uintr_unspecv>, uintr_senduipi, testui):
New define_insn patterns.
* config/i386/x86gprintrin.h: Include uintrintrin.h
* doc/invoke.texi: Document -muintr.
* doc/extend.texi: Document uintr.

gcc/testsuite/

* gcc.target/i386/funcspec-56.inc: Add new target attribute.
* gcc.target/i386/uintr-1.c: New test.
* gcc.target/i386/uintr-2.c: Ditto.
* gcc.target/i386/uintr-3.c: Ditto.
* gcc.target/i386/uintr-4.c: Ditto.
* gcc.target/i386/uintr-5.c: Ditto.

-- 
Regards,

Hongyu, Wang
From 9f15ec4498eb7ff03ba9757592871d03fb05d222 Mon Sep 17 00:00:00 2001
From: liuhongt <hongtao....@intel.com>
Date: Mon, 20 May 2019 17:56:41 +0800
Subject: [PATCH] Enable gcc support for UINTR

2020-0X-XX  Hongtao Liu  <hongtao....@intel.com>

gcc/
	* common/config/i386/cpuinfo.h (get_available_features):
	Detect UINTR.
	* common/config/i386/i386-common.c (OPTION_MASK_ISA2_UINTR_SET
	OPTION_MASK_ISA2_UINTR_UNSET): New.
	(ix86_handle_option): Handle -muintr.
	* common/config/i386/i386-cpuinfo.h (enum processor_features):
	Add FEATURE_UINTR.
	* common/config/i386/i386-isas.h: Add ISA_NAMES_TABLE_ENTRY
	for uintr.
	* config.gcc: Add uintrintrin.h to extra_headers.
	* config/i386/uintrintrin.h: New.
	* config/i386/cpuid.h (bit_UINTR): New.
	* config/i386/driver-i386.c (host_detect_local_cpu): Detect UINTR.
	* config/i386/i386-builtin-types.def: Add new types.
	* config/i386/i386-builtin.def: Add new builtins.
	* config/i386/i386-builtins.c (ix86_init_mmx_sse_builtins): Add
	__builtin_ia32_testui.
	* config/i386/i386-builtins.h (ix86_builtins): Add
	IX86_BUILTIN_TESTUI.
	* config/i386/i386-c.c (ix86_target_macros_internal): Define
	__UINTR__.
	* config/i386/i386-expand.c (ix86_expand_special_args_builtin):
	Handle UINT8_FTYPE_VOID.
	(ix86_expand_builtin): Handle IX86_BUILTIN_TESTUI.
	* config/i386/i386-options.c (isa2_opts): Add -muintr.
	(ix86_valid_target_attribute_inner_p): Handle UINTR.
	(ix86_option_override_internal): Add TARGET_64BIT check for UINTR.
	* config/i386/i386.h (TARGET_UINTR, TARGET_UINTR_P, PTA_UINTR): New.
	(PTA_SAPPHIRRAPIDS): Add PTA_UINTR.
	* config/i386/i386.opt: Add -muintr.
	* config/i386/i386.md
	(define_int_iterator UINTR_UNSPECV): New.
	(define_int_attr uintr_unspecv): New.
	(uintr_<uintr_unspecv>, uintr_senduipi, testui):
	New define_insn patterns.
	* config/i386/x86gprintrin.h: Include uintrintrin.h
	* doc/invoke.texi: Document -muintr.
	* doc/extend.texi: Document uintr.

gcc/testsuite/

	* gcc.target/i386/funcspec-56.inc: Add new target attribute.
	* gcc.target/i386/uintr-1.c: New test.
	* gcc.target/i386/uintr-2.c: Ditto.
	* gcc.target/i386/uintr-3.c: Ditto.
	* gcc.target/i386/uintr-4.c: Ditto.
	* gcc.target/i386/uintr-5.c: Ditto.
---
 gcc/common/config/i386/cpuinfo.h              |  2 +
 gcc/common/config/i386/i386-common.c          | 15 ++++
 gcc/common/config/i386/i386-cpuinfo.h         |  1 +
 gcc/common/config/i386/i386-isas.h            |  1 +
 gcc/config.gcc                                |  4 +-
 gcc/config/i386/cpuid.h                       |  1 +
 gcc/config/i386/i386-builtin-types.def        |  1 +
 gcc/config/i386/i386-builtin.def              |  5 ++
 gcc/config/i386/i386-builtins.c               |  5 ++
 gcc/config/i386/i386-builtins.h               |  1 +
 gcc/config/i386/i386-c.c                      |  2 +
 gcc/config/i386/i386-expand.c                 | 14 +++
 gcc/config/i386/i386-options.c                |  7 +-
 gcc/config/i386/i386.h                        |  6 +-
 gcc/config/i386/i386.md                       | 36 +++++++-
 gcc/config/i386/i386.opt                      |  4 +
 gcc/config/i386/uintrintrin.h                 | 87 +++++++++++++++++++
 gcc/config/i386/x86gprintrin.h                |  2 +
 gcc/doc/extend.texi                           |  5 ++
 gcc/doc/invoke.texi                           |  8 +-
 gcc/testsuite/gcc.target/i386/funcspec-56.inc |  2 +
 gcc/testsuite/gcc.target/i386/uintr-1.c       | 21 +++++
 gcc/testsuite/gcc.target/i386/uintr-2.c       | 17 ++++
 gcc/testsuite/gcc.target/i386/uintr-3.c       |  9 ++
 gcc/testsuite/gcc.target/i386/uintr-4.c       |  9 ++
 gcc/testsuite/gcc.target/i386/uintr-5.c       | 10 +++
 26 files changed, 267 insertions(+), 8 deletions(-)
 create mode 100644 gcc/config/i386/uintrintrin.h
 create mode 100644 gcc/testsuite/gcc.target/i386/uintr-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/uintr-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/uintr-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/uintr-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/uintr-5.c

diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
index c96455ce64f..0e63db271f6 100644
--- a/gcc/common/config/i386/cpuinfo.h
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -701,6 +701,8 @@ get_available_features (struct __processor_model *cpu_model,
 	    set_feature (FEATURE_AVX5124FMAPS);
 	  if (edx & bit_AVX512VP2INTERSECT)
 	    set_feature (FEATURE_AVX512VP2INTERSECT);
+	  if (edx & bit_UINTR)
+	    set_feature (FEATURE_UINTR);
 
 	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
 	  if (eax & bit_AVX512BF16)
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 62a620b4430..6a06383ef0d 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -163,6 +163,7 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTION_MASK_ISA2_ENQCMD_SET OPTION_MASK_ISA2_ENQCMD
 #define OPTION_MASK_ISA2_SERIALIZE_SET OPTION_MASK_ISA2_SERIALIZE
 #define OPTION_MASK_ISA2_TSXLDTRK_SET OPTION_MASK_ISA2_TSXLDTRK
+#define OPTION_MASK_ISA2_UINTR_SET OPTION_MASK_ISA2_UINTR
 
 /* Define a set of ISAs which aren't available when a given ISA is
    disabled.  MMX and SSE ISAs are handled separately.  */
@@ -254,6 +255,7 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTION_MASK_ISA2_AMX_TILE_UNSET OPTION_MASK_ISA2_AMX_TILE
 #define OPTION_MASK_ISA2_AMX_INT8_UNSET OPTION_MASK_ISA2_AMX_INT8
 #define OPTION_MASK_ISA2_AMX_BF16_UNSET OPTION_MASK_ISA2_AMX_BF16
+#define OPTION_MASK_ISA2_UINTR_UNSET OPTION_MASK_ISA2_UINTR
 
 /* SSE4 includes both SSE4.1 and SSE4.2.  -mno-sse4 should the same
    as -mno-sse4.1. */
@@ -702,6 +704,19 @@ ix86_handle_option (struct gcc_options *opts,
 	}
       return true;
 
+    case OPT_muintr:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_UINTR_SET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_UINTR_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_UINTR_UNSET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_UINTR_UNSET;
+	}
+      return true;
+
     case OPT_mavx5124fmaps:
       if (value)
 	{
diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
index 5b94b1f1df7..3fc2af5c3b1 100644
--- a/gcc/common/config/i386/i386-cpuinfo.h
+++ b/gcc/common/config/i386/i386-cpuinfo.h
@@ -219,6 +219,7 @@ enum processor_features
   FEATURE_AMX_TILE,
   FEATURE_AMX_INT8,
   FEATURE_AMX_BF16,
+  FEATURE_UINTR,
   CPU_FEATURE_MAX
 };
 
diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
index 3c830ea08ff..c2dc74171bf 100644
--- a/gcc/common/config/i386/i386-isas.h
+++ b/gcc/common/config/i386/i386-isas.h
@@ -163,4 +163,5 @@ ISA_NAMES_TABLE_START
   ISA_NAMES_TABLE_ENTRY("amx-tile", FEATURE_AMX_TILE, P_NONE, "-mamx-tile")
   ISA_NAMES_TABLE_ENTRY("amx-int8", FEATURE_AMX_INT8, P_NONE, "-mamx-int8")
   ISA_NAMES_TABLE_ENTRY("amx-bf16", FEATURE_AMX_BF16, P_NONE, "-mamx-bf16")
+  ISA_NAMES_TABLE_ENTRY("uintr", FEATURE_UINTR, P_NONE, "-muintr")
 ISA_NAMES_TABLE_END
diff --git a/gcc/config.gcc b/gcc/config.gcc
index d5634b043e2..c02bdddab69 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -413,7 +413,7 @@ i[34567]86-*-*)
 		       avx512bf16intrin.h enqcmdintrin.h serializeintrin.h
 		       avx512vp2intersectintrin.h avx512vp2intersectvlintrin.h
 		       tsxldtrkintrin.h amxtileintrin.h amxint8intrin.h
-		       amxbf16intrin.h x86gprintrin.h"
+		       amxbf16intrin.h x86gprintrin.h uintrintrin.h"
 	;;
 x86_64-*-*)
 	cpu_type=i386
@@ -449,7 +449,7 @@ x86_64-*-*)
 		       avx512bf16intrin.h enqcmdintrin.h serializeintrin.h
 		       avx512vp2intersectintrin.h avx512vp2intersectvlintrin.h
 		       tsxldtrkintrin.h amxtileintrin.h amxint8intrin.h
-		       amxbf16intrin.h x86gprintrin.h"
+		       amxbf16intrin.h x86gprintrin.h uintrintrin.h"
 	;;
 ia64-*-*)
 	extra_headers=ia64intrin.h
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 4598434fd02..fbc8ca245bd 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -124,6 +124,7 @@
 #define bit_AVX5124FMAPS (1 << 3)
 #define bit_AVX512VP2INTERSECT	(1 << 8)
 #define bit_IBT	(1 << 20)
+#define bit_UINTR (1 << 5)
 #define bit_PCONFIG	(1 << 18)
 #define bit_SERIALIZE	(1 << 14)
 #define bit_TSXLDTRK    (1 << 16)
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 1adf7c44f4a..6d585f2280c 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -194,6 +194,7 @@ DEF_FUNCTION_TYPE (UNSIGNED)
 DEF_FUNCTION_TYPE (UINT)
 DEF_FUNCTION_TYPE (USHORT)
 DEF_FUNCTION_TYPE (INT)
+DEF_FUNCTION_TYPE (UINT8)
 DEF_FUNCTION_TYPE (VOID)
 DEF_FUNCTION_TYPE (PVOID)
 
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index fec5cef0b55..9f2d4cc0406 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -452,6 +452,11 @@ BDESC (0, OPTION_MASK_ISA2_SERIALIZE, CODE_FOR_serialize, "__builtin_ia32_serial
 BDESC (0, OPTION_MASK_ISA2_TSXLDTRK, CODE_FOR_xsusldtrk, "__builtin_ia32_xsusldtrk", IX86_BUILTIN_XSUSLDTRK, UNKNOWN, (int) VOID_FTYPE_VOID)
 BDESC (0, OPTION_MASK_ISA2_TSXLDTRK, CODE_FOR_xresldtrk, "__builtin_ia32_xresldtrk", IX86_BUILTIN_XRESLDTRK, UNKNOWN, (int) VOID_FTYPE_VOID)
 
+/* UINTR.  */
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_UINTR, CODE_FOR_clui, "__builtin_ia32_clui", IX86_BUILTIN_CLUI, UNKNOWN, (int) VOID_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_UINTR, CODE_FOR_stui, "__builtin_ia32_stui", IX86_BUILTIN_STUI, UNKNOWN, (int) VOID_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_UINTR, CODE_FOR_senduipi, "__builtin_ia32_senduipi", IX86_BUILTIN_SENDUIPI, UNKNOWN, (int) VOID_FTYPE_UINT64)
+
 BDESC_END (SPECIAL_ARGS, ARGS)
 
 /* Builtins with variable number of arguments.  */
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index ca7a870896b..504987a5410 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -1194,6 +1194,11 @@ ix86_init_mmx_sse_builtins (void)
   def_builtin (0, OPTION_MASK_ISA2_WAITPKG, "__builtin_ia32_tpause",
 	       UINT8_FTYPE_UNSIGNED_UINT64, IX86_BUILTIN_TPAUSE);
 
+  /* UINTR.  */
+  def_builtin (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_UINTR,
+	       "__builtin_ia32_testui",
+	       UINT8_FTYPE_VOID, IX86_BUILTIN_TESTUI);
+
   /* CLDEMOTE.  */
   def_builtin (0, OPTION_MASK_ISA2_CLDEMOTE, "__builtin_ia32_cldemote",
 	       VOID_FTYPE_PCVOID, IX86_BUILTIN_CLDEMOTE);
diff --git a/gcc/config/i386/i386-builtins.h b/gcc/config/i386/i386-builtins.h
index cc6a8ce9966..a88cc0c387e 100644
--- a/gcc/config/i386/i386-builtins.h
+++ b/gcc/config/i386/i386-builtins.h
@@ -40,6 +40,7 @@ enum ix86_builtins
   IX86_BUILTIN_UMONITOR,
   IX86_BUILTIN_UMWAIT,
   IX86_BUILTIN_TPAUSE,
+  IX86_BUILTIN_TESTUI,
   IX86_BUILTIN_CLZERO,
   IX86_BUILTIN_CLDEMOTE,
   IX86_BUILTIN_VEC_INIT_V2SI,
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index e647fce9ad4..219e1be23e6 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -598,6 +598,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
     def_or_undef (parse_in, "__LAHF_SAHF__");
   if (isa_flag2 & OPTION_MASK_ISA2_MOVBE)
     def_or_undef (parse_in, "__MOVBE__");
+  if (isa_flag2 & OPTION_MASK_ISA2_UINTR)
+    def_or_undef (parse_in, "__UINTR__");
 
   if (TARGET_IAMCU)
     {
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index e6f8b314f18..5a9955bf8c4 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -10413,6 +10413,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
     case USHORT_FTYPE_VOID:
     case UINT64_FTYPE_VOID:
     case UINT_FTYPE_VOID:
+    case UINT8_FTYPE_VOID:
     case UNSIGNED_FTYPE_VOID:
       nargs = 0;
       klass = load;
@@ -11203,6 +11204,19 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
       return target;
 
+    case IX86_BUILTIN_TESTUI:
+      emit_insn (gen_testui ());
+
+      if (target == 0
+	  || !register_operand (target, QImode))
+	target = gen_reg_rtx (QImode);
+
+      pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
+			 const0_rtx);
+      emit_insn (gen_rtx_SET (target, pat));
+
+      return target;
+
     case IX86_BUILTIN_CLZERO:
       arg0 = CALL_EXPR_ARG (exp, 0);
       op0 = expand_normal (arg0);
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index a59bd703880..1edc1c8a7b9 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -212,7 +212,8 @@ static struct ix86_target_opts isa2_opts[] =
   { "-mtsxldtrk",	OPTION_MASK_ISA2_TSXLDTRK },
   { "-mamx-tile",	OPTION_MASK_ISA2_AMX_TILE },
   { "-mamx-int8",	OPTION_MASK_ISA2_AMX_INT8 },
-  { "-mamx-bf16",	OPTION_MASK_ISA2_AMX_BF16 }
+  { "-mamx-bf16",	OPTION_MASK_ISA2_AMX_BF16 },
+  { "-muintr",		OPTION_MASK_ISA2_UINTR }
 };
 static struct ix86_target_opts isa_opts[] =
 {
@@ -1031,6 +1032,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, 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 ("uintr", OPT_muintr),
     IX86_ATTR_ISA ("ptwrite",   OPT_mptwrite),
     IX86_ATTR_ISA ("avx512bf16",   OPT_mavx512bf16),
     IX86_ATTR_ISA ("enqcmd", OPT_menqcmd),
@@ -1899,6 +1901,9 @@ ix86_option_override_internal (bool main_args_p,
       opts->x_ix86_stringop_alg = no_stringop;
     }
 
+  if (TARGET_UINTR && !TARGET_64BIT)
+    error ("%<-muintr%> not supported for 32-bit code");
+
   if (!opts->x_ix86_arch_string)
     opts->x_ix86_arch_string
       = TARGET_64BIT_P (opts->x_ix86_isa_flags)
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 9a5de6a0e9c..e933b3588c2 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -209,6 +209,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_AMX_INT8_P(x) TARGET_ISA2_AMX_INT8(x)
 #define TARGET_AMX_BF16 TARGET_ISA2_AMX_BF16
 #define TARGET_AMX_BF16_P(x) TARGET_ISA2_AMX_BF16(x)
+#define TARGET_UINTR	TARGET_ISA2_UINTR
+#define TARGET_UINTR_P(x) TARGET_ISA2_UINTR_P(x)
 
 #define TARGET_LP64	TARGET_ABI_64
 #define TARGET_LP64_P(x)	TARGET_ABI_64_P(x)
@@ -2475,6 +2477,7 @@ const wide_int_bitmask PTA_TSXLDTRK (0, HOST_WIDE_INT_1U << 18);
 const wide_int_bitmask PTA_AMX_TILE(0, HOST_WIDE_INT_1U << 19);
 const wide_int_bitmask PTA_AMX_INT8(0, HOST_WIDE_INT_1U << 20);
 const wide_int_bitmask PTA_AMX_BF16(0, HOST_WIDE_INT_1U << 21);
+const wide_int_bitmask PTA_UINTR (0, HOST_WIDE_INT_1U << 22);
 
 const wide_int_bitmask PTA_X86_64_BASELINE = PTA_64BIT | PTA_MMX | PTA_SSE
   | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR;
@@ -2485,6 +2488,7 @@ const wide_int_bitmask PTA_X86_64_V3 = PTA_X86_64_V2
   | PTA_MOVBE | PTA_XSAVE;
 const wide_int_bitmask PTA_X86_64_V4 = PTA_X86_64_V3
   | PTA_AVX512F | PTA_AVX512BW | PTA_AVX512CD | PTA_AVX512DQ | PTA_AVX512VL;
+
 const wide_int_bitmask PTA_CORE2 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
   | PTA_SSE3 | PTA_SSSE3 | PTA_CX16 | PTA_FXSR;
 const wide_int_bitmask PTA_NEHALEM = PTA_CORE2 | PTA_SSE4_1 | PTA_SSE4_2
@@ -2518,7 +2522,7 @@ const wide_int_bitmask PTA_TIGERLAKE = PTA_ICELAKE_CLIENT | PTA_MOVDIRI
 const wide_int_bitmask PTA_SAPPHIRERAPIDS = PTA_COOPERLAKE | PTA_MOVDIRI
   | PTA_MOVDIR64B | PTA_AVX512VP2INTERSECT | PTA_ENQCMD | PTA_CLDEMOTE
   | PTA_PTWRITE | PTA_WAITPKG | PTA_SERIALIZE | PTA_TSXLDTRK | PTA_AMX_TILE
-  | PTA_AMX_INT8 | PTA_AMX_BF16;
+  | PTA_AMX_INT8 | PTA_AMX_BF16 | PTA_UINTR;
 const wide_int_bitmask PTA_ALDERLAKE = PTA_SKYLAKE | PTA_CLDEMOTE | PTA_PTWRITE
   | PTA_WAITPKG | PTA_SERIALIZE;
 const wide_int_bitmask PTA_KNL = PTA_BROADWELL | PTA_AVX512PF | PTA_AVX512ER
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 9dd12cf8643..b27cf53ed97 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -293,6 +293,12 @@
   UNSPECV_UMONITOR
   UNSPECV_TPAUSE
 
+  ;; For UINTR support
+  UNSPECV_CLUI
+  UNSPECV_STUI
+  UNSPECV_TESTUI
+  UNSPECV_SENDUIPI
+
   ;; For CLDEMOTE support
   UNSPECV_CLDEMOTE
 
@@ -13666,7 +13672,7 @@
    (unspec [(const_int 0)] UNSPEC_INTERRUPT_RETURN)]
   "reload_completed"
 {
-  return TARGET_64BIT ? "iretq" : "iret";
+  return TARGET_64BIT ? (TARGET_UINTR ? "uiret" : "iretq") : "iret";
 })
 
 ;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
@@ -21571,6 +21577,34 @@
   "enqcmd<enqcmd_sfx>\t{%1, %0|%0, %1}"
   [(set_attr "type" "other")])
 
+;; UINTR
+(define_int_iterator UINTR [UNSPECV_CLUI UNSPECV_STUI])
+(define_int_attr uintr [(UNSPECV_CLUI "clui") (UNSPECV_STUI "stui")])
+
+(define_insn "<uintr>"
+  [(unspec_volatile [(const_int 0)] UINTR)]
+  "TARGET_UINTR && TARGET_64BIT"
+  "<uintr>"
+  [(set_attr "type" "other")
+   (set_attr "length" "4")])
+
+(define_insn "testui"
+  [(set (reg:CCC FLAGS_REG)
+	(unspec_volatile:CCC [(const_int 0)] UNSPECV_TESTUI))]
+  "TARGET_UINTR && TARGET_64BIT"
+  "testui"
+  [(set_attr "type" "other")
+   (set_attr "length" "4")])
+
+(define_insn "senduipi"
+  [(unspec_volatile
+    [(match_operand:DI 0 "register_operand" "r")]
+    UNSPECV_SENDUIPI)]
+  "TARGET_UINTR && TARGET_64BIT"
+  "senduipi\t%0"
+  [(set_attr "type" "other")
+   (set_attr "length" "4")])
+
 ;; WAITPKG
 
 (define_insn "umwait"
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 9389dc24948..68f49f53d47 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -788,6 +788,10 @@ mptwrite
 Target Report Mask(ISA2_PTWRITE) Var(ix86_isa_flags2) Save
 Support PTWRITE built-in functions and code generation.
 
+muintr
+Target Report Mask(ISA2_UINTR) Var(ix86_isa_flags2) Save
+Support UINTR built-in functions and code generation.
+
 msgx
 Target Report Mask(ISA2_SGX) Var(ix86_isa_flags2) Save
 Support SGX built-in functions and code generation.
diff --git a/gcc/config/i386/uintrintrin.h b/gcc/config/i386/uintrintrin.h
new file mode 100644
index 00000000000..991f6427971
--- /dev/null
+++ b/gcc/config/i386/uintrintrin.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2020 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/>.  */
+
+#ifndef _X86GPRINTRIN_H_INCLUDED
+# error "Never use <uintrintrin.h> directly; include <x86gprintrin.h> instead."
+#endif
+
+#ifndef _UINTRNTRIN_H_INCLUDED
+#define _UINTRNTRIN_H_INCLUDED
+
+#ifdef __x86_64__
+
+#ifndef __UINTR__
+#pragma GCC push_options
+#pragma GCC target ("uintr")
+#define __DISABLE_UINTR__
+#endif /* __UINTR__ */
+
+struct __uintr_frame
+{
+  /* The position of the most significant bit set in user-interrupt
+     request register.  */
+  unsigned long long uirrv;
+  /* RIP of the interrupted user process.  */
+  unsigned long long rip;
+  /* RFLAGS of the interrupted user process.  */
+  unsigned long long rflags;
+  /* RSP of the interrupted user process.  */
+  unsigned long long rsp;
+};
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_clui (void)
+{
+  __builtin_ia32_clui ();
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_stui (void)
+{
+  __builtin_ia32_stui ();
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_senduipi (unsigned long long __R)
+{
+  __builtin_ia32_senduipi (__R);
+}
+
+extern __inline unsigned char
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_testui (void)
+{
+  return __builtin_ia32_testui ();
+}
+
+#ifdef __DISABLE_UINTR__
+#undef __DISABLE_UINTR__
+#pragma GCC pop_options
+#endif /* __DISABLE_UINTR__ */
+
+#endif
+
+#endif /* _UINTRNTRIN_H_INCLUDED.  */
diff --git a/gcc/config/i386/x86gprintrin.h b/gcc/config/i386/x86gprintrin.h
index ecfb1c0e67f..e35f4b65c9c 100644
--- a/gcc/config/i386/x86gprintrin.h
+++ b/gcc/config/i386/x86gprintrin.h
@@ -76,6 +76,8 @@
 
 #include <tsxldtrkintrin.h>
 
+#include <uintrintrin.h>
+
 #include <waitpkgintrin.h>
 
 #include <wbnoinvdintrin.h>
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index b9684dc7a06..bd46ebc83cc 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -6638,6 +6638,11 @@ Enable/disable the generation of the AMX-INT8 instructions.
 @cindex @code{target("amx-bf16")} function attribute, x86
 Enable/disable the generation of the AMX-BF16 instructions.
 
+@item uintr
+@itemx no-uintr
+@cindex @code{target("uintr")} function attribute, x86
+Enable/disable the generation of the UINTR instructions.
+
 @item cld
 @itemx no-cld
 @cindex @code{target("cld")} function attribute, x86
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b8c807e631c..595c113fbe1 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1362,7 +1362,7 @@ See RS/6000 and PowerPC Options.
 -mvpclmulqdq  -mavx512bitalg  -mmovdiri  -mmovdir64b  -mavx512vpopcntdq @gol
 -mavx5124fmaps  -mavx512vnni  -mavx5124vnniw  -mprfchw  -mrdpid @gol
 -mrdseed  -msgx -mavx512vp2intersect -mserialize -mtsxldtrk@gol
--mamx-tile  -mamx-int8  -mamx-bf16@gol
+-mamx-tile  -mamx-int8  -mamx-bf16 -muintr@gol
 -mcldemote  -mms-bitfields  -mno-align-stringops  -minline-all-stringops @gol
 -minline-stringops-dynamically  -mstringop-strategy=@var{alg} @gol
 -mmemcpy-strategy=@var{strategy}  -mmemset-strategy=@var{strategy} @gol
@@ -30228,6 +30228,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
 @need 200
 @itemx -menqcmd
 @opindex menqcmd
+@itemx -muintr
+@opindex muintr
 @need 200
 @itemx -mtsxldtrk
 @opindex mtsxldtrk
@@ -30269,8 +30271,8 @@ WBNOINVD, FMA4, PREFETCHW, RDPID, PREFETCHWT1, RDSEED, SGX, XOP, LWP,
 3DNow!@:, enhanced 3DNow!@:, POPCNT, ABM, ADX, BMI, BMI2, LZCNT, FXSR, XSAVE,
 XSAVEOPT, XSAVEC, XSAVES, RTM, HLE, TBM, MWAITX, CLZERO, PKU, AVX512VBMI2,
 GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16,
-ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, SERIALIZE
-or CLDEMOTE extended instruction sets.  Each has a corresponding
+ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, SERIALIZE,
+UINTR or CLDEMOTE extended instruction sets.  Each has a corresponding
 @option{-mno-} option to disable use of these instructions.
 
 These extensions are also available as built-in functions: see
diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
index 8e669f12215..d6a2e8d2305 100644
--- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
@@ -74,6 +74,7 @@ extern void test_avx512vp2intersect (void)	__attribute__((__target__("avx512vp2i
 extern void test_amx_tile (void)		__attribute__((__target__("amx-tile")));
 extern void test_amx_int8 (void)		__attribute__((__target__("amx-int8")));
 extern void test_amx_bf16 (void)		__attribute__((__target__("amx-bf16")));
+extern void test_uintr (void)			__attribute__((__target__("uintr")));
 
 extern void test_no_sgx (void)			__attribute__((__target__("no-sgx")));
 extern void test_no_avx5124fmaps(void)		__attribute__((__target__("no-avx5124fmaps")));
@@ -149,6 +150,7 @@ extern void test_no_avx512vp2intersect (void)	__attribute__((__target__("no-avx5
 extern void test_no_amx_tile (void)		__attribute__((__target__("no-amx-tile")));
 extern void test_no_amx_int8 (void)		__attribute__((__target__("no-amx-int8")));
 extern void test_no_amx_bf16 (void)		__attribute__((__target__("no-amx-bf16")));
+extern void test_no_uintr (void)		__attribute__((__target__("no-uintr")));
 
 extern void test_arch_nocona (void)		__attribute__((__target__("arch=nocona")));
 extern void test_arch_core2 (void)		__attribute__((__target__("arch=core2")));
diff --git a/gcc/testsuite/gcc.target/i386/uintr-1.c b/gcc/testsuite/gcc.target/i386/uintr-1.c
new file mode 100644
index 00000000000..f30f755a139
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/uintr-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -muintr" } */
+/* { dg-final { scan-assembler-times "clui" "1" } } */
+/* { dg-final { scan-assembler-times "stui" "2" } } */
+/* { dg-final { scan-assembler-times "senduipi" "1" } } */
+/* { dg-final { scan-assembler-times "setc" "1" } } */
+/* { dg-final { scan-assembler-times "testui" "1" } } */
+
+#include <x86gprintrin.h>
+
+extern volatile unsigned char c;
+extern volatile unsigned long long l;
+
+void
+foo (void)
+{
+  _clui ();
+  _stui ();
+  _senduipi (l);
+  c = _testui ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-2.c b/gcc/testsuite/gcc.target/i386/uintr-2.c
new file mode 100644
index 00000000000..e705732c1bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/uintr-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -muintr -mgeneral-regs-only" } */
+/* { dg-final { scan-assembler-times "uiret" "2" } } */
+
+#include <x86gprintrin.h>
+
+void
+__attribute__((interrupt))
+foo (void *frame)
+{
+}
+
+void
+__attribute__((interrupt))
+UINTR_hanlder (struct __uintr_frame *frame)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-3.c b/gcc/testsuite/gcc.target/i386/uintr-3.c
new file mode 100644
index 00000000000..d2843495158
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/uintr-3.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -muintr" } */
+/* { dg-final { scan-assembler "uiret" } } */
+#include <x86gprintrin.h>
+
+void __attribute__ ((target("general-regs-only"), interrupt))
+UINTR_handler (struct __uintr_frame *p)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-4.c b/gcc/testsuite/gcc.target/i386/uintr-4.c
new file mode 100644
index 00000000000..f3b371b4231
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/uintr-4.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -muintr" } */
+
+#include <x86gprintrin.h>
+
+void __attribute__ ((interrupt))
+UINTR_handler (struct __uintr_frame *p)
+{ /* { dg-message "SSE instructions aren't allowed in an interrupt service routine" }  */
+}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-5.c b/gcc/testsuite/gcc.target/i386/uintr-5.c
new file mode 100644
index 00000000000..ac44be0a706
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/uintr-5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -muintr" } */
+/* { dg-error "'-muintr' not supported for 32-bit code" "" { target ia32 } 0 } */
+
+#include <x86gprintrin.h>
+
+void
+UINTR_hanlder (struct __uintr_frame *frame)
+{
+}
-- 
2.25.1

Reply via email to