On Tue, Aug 25, 2020 at 5:27 AM Uros Bizjak <ubiz...@gmail.com> wrote:
>
> On Tue, Aug 25, 2020 at 2:13 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> >
> > On Mon, Aug 24, 2020 at 12:40 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> > >
> > > On Mon, Aug 24, 2020 at 12:25 PM Uros Bizjak <ubiz...@gmail.com> wrote:
> > > >
> > > > On Mon, Aug 24, 2020 at 6:17 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> > > > >
> > > > > On Mon, Aug 24, 2020 at 7:55 AM Uros Bizjak <ubiz...@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, Aug 24, 2020 at 3:23 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> > > > > >
> > > > > > > > Speaking of pragmas, these should be added outside cpuid.h, 
> > > > > > > > like:
> > > > > > > >
> > > > > > > > #pragma GCC push_options
> > > > > > > > #pragma GCC target("general-regs-only")
> > > > > > > >
> > > > > > > > #include <cpuid.h>
> > > > > > > >
> > > > > > > > void cpuid_check ()
> > > > > > > > ...
> > > > > > > >
> > > > > > > > #pragma GCC pop_options
> > > > > > > >
> > > > > > > > >footnote
> > > > > > > >
> > > > > > > > Nowadays, -march=native is mostly used outside generic target
> > > > > > > > compilations, so for relevant avx512 targets, we still generate 
> > > > > > > > spills
> > > > > > > > to mask regs. In future, we can review the setting of the 
> > > > > > > > tuning flag
> > > > > > > > for a generic target in the same way as with SSE2 inter-reg 
> > > > > > > > moves.
> > > > > > > >
> > > > > > >
> > > > > > > Florian raised an issue that we need to limit <cpuid.h> to the 
> > > > > > > basic ISAs.
> > > > > > > <cpuid.h> should be handled similarly to other intrinsic header 
> > > > > > > files.
> > > > > > > That is <cpuid.h> should use
> > > > > > >
> > > > > > > #pragma GCC push_options
> > > > > > > #ifdef __x86_64__
> > > > > > > #pragma GCC target("arch=x86-64")
> > > > > > > #else
> > > > > > > #pragma GCC target("arch=i386")
> > > > > > > ...
> > > > > > > #pragma GCC pop_options
> > > > > > >
> > > > > > > Here is a patch.  OK for master?
> > > > > >
> > > > > > -ENOPATCH
> > > > > >
> > > > > > However, how will this affect inlining? Every single function in
> > > > > > cpuid.h is defined as static __inline, and due to target flags
> > > > > > mismatch, it won't be inlined anymore. These inline functions are 
> > > > > > used
> > > > > > in some bit testing functions, and to keep them inlined, these 
> > > > > > should
> > > > > > also use the same options to avoid non-basic ISAs. This is the 
> > > > > > reason
> > > > > > cpuid.h should be #included after pragma, together with bit testing
> > > > > > functions, as shown above.
> > > > > >
> > > > >
> > > > > How about target("baseline-isas-only")? All CPUID functions are
> > > > > inlined.
> > > >
> > > > No, I don't think this is a good idea. Now consider the situation that
> > > > caller functions are compiled with e.g. -mgeneral-regs-only. Due to
> > > > #pragmas, CPUID functions are compiled with a superset ISAs, so they
> > > > again won't be inlined. ISAs of caller functions and CPUID should
> > > > match, the best way is to include <cpuid.h> after the #pragma. And
> > > > IMO, general-regs-only target #pragma is an excellent setting for
> > > > both: cpuid.h and caller bit testing functions.
> > > >
> > > > So, if we care about inlining, decorating cpuid.h with target pragmas
> > > > is a bad idea.
> > >
> > > This can be done with #pragma in <cpuid.h>.
> > >
> >
> > We just need to update ix86_can_inline_p to allow inline functions
> > with baseline-isas-only and general-regs-only attributes if caller
> > supports the same set of ISAs.
> >
> > Here is the updated patch.
>
> I'm not against it, but I don't plan to approve the attached patch.
>

How about this one?

-- 
H.J.
From a6ffd2914535d23eb916b4684d5edef132912f72 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.to...@gmail.com>
Date: Fri, 21 Aug 2020 09:42:49 -0700
Subject: [PATCH] x86: Add -mbaseline-isas-only/target("baseline-isas-only")

Add -mbaseline-isas-only and target("baseline-isas-only") attribute to
support baseline ISAs, which include FXSR, MMX, SSE and SSE2 in 64-bit
mode.  Use only general registers and baseline ISAs to perform CPUID
check.  We can inline functions with general registers and baseline
ISAs attributes if caller supports the same set of ISAs.

gcc/

	PR target/96744
	* common/config/i386/i386-common.c (ix86_handle_option): Support
	-mbaseline-isas-only.
	* config/i386/i386-options.c (ix86_valid_target_attribute_inner_p):
	Handle baseline-isas-only.
	* config/i386/i386.c (ix86_can_inline_p): Allow inline functions
	with baseline-isas-only and general-regs-only attributes if caller
	supports the same set of ISAs.
	* config/i386/i386.h (TARGET_64BIT_BASELINE_ISAS): New.
	* config/i386/i386.opt: Add -mbaseline-isas-only.
	* doc/extend.texi: Document target("baseline-isas-only") function
	attribute.
	* doc/invoke.texi: Document -mbaseline-isas-only.

gcc/testsuite/

	PR target/96744
	* gcc.target/i386/avx512-check.h: Add #pragma GCC
	target(""general-regs-only,baseline-isas-only") for CPUID check.
	* gcc.target/i386/pr96744-10.c: New test.
	* gcc.target/i386/pr96744-11.c: Likewise.
	* gcc.target/i386/pr96744-12.c: Likewise.
	* gcc.target/i386/pr96744-13.c: Likewise.
	* gcc.target/i386/pr96744-14.c: Likewise.
	* gcc.target/i386/pr96744-15.c: Likewise.
	* gcc.target/i386/pr96744-16.c: Likewise.
	* gcc.target/i386/pr96744-17.c: Likewise.
---
 gcc/common/config/i386/i386-common.c         | 28 ++++++++++++
 gcc/config/i386/i386-options.c               |  7 ++-
 gcc/config/i386/i386.c                       | 34 +++++++-------
 gcc/config/i386/i386.h                       |  4 ++
 gcc/config/i386/i386.opt                     |  6 ++-
 gcc/doc/extend.texi                          |  4 ++
 gcc/doc/invoke.texi                          |  5 +++
 gcc/testsuite/gcc.target/i386/avx512-check.h | 10 +++++
 gcc/testsuite/gcc.target/i386/pr96744-10.c   | 27 +++++++++++
 gcc/testsuite/gcc.target/i386/pr96744-11.c   | 27 +++++++++++
 gcc/testsuite/gcc.target/i386/pr96744-12.c   | 27 +++++++++++
 gcc/testsuite/gcc.target/i386/pr96744-13.c   | 35 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr96744-14.c   | 47 ++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr96744-15.c   | 47 ++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr96744-16.c   | 12 +++++
 gcc/testsuite/gcc.target/i386/pr96744-17.c   | 16 +++++++
 16 files changed, 319 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-10.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-11.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-12.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-13.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-14.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-15.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-16.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr96744-17.c

diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index bb14305ad7b..46ee70e1e47 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -338,6 +338,34 @@ ix86_handle_option (struct gcc_options *opts,
 	gcc_unreachable ();
       return true;
 
+    case OPT_mbaseline_isas_only:
+      if (value)
+	{
+	  /* Only enable baseline ISAs.  */
+	  if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
+	    {
+	      HOST_WIDE_INT x_ix86_isa_flags;
+	      if (TARGET_LP64_P (opts->x_ix86_isa_flags))
+		x_ix86_isa_flags = (OPTION_MASK_ISA_64BIT
+				    | OPTION_MASK_ABI_64);
+	      else
+		x_ix86_isa_flags = (OPTION_MASK_ISA_64BIT
+				    | OPTION_MASK_ABI_X32);
+	      if (!TARGET_GENERAL_REGS_ONLY_P (opts->x_ix86_target_flags))
+		x_ix86_isa_flags |= TARGET_64BIT_BASELINE_ISAS;
+	      opts->x_ix86_isa_flags = x_ix86_isa_flags;
+	    }
+	  else
+	    {
+	      opts->x_ix86_isa_flags = 0;
+	      opts->x_ix86_fpmath = FPMATH_387;
+	    }
+	  opts->x_ix86_isa_flags2 = 0;
+	}
+      else
+	gcc_unreachable ();
+      return true;
+
     case OPT_mmmx:
       if (value)
 	{
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index b93c338346f..199cf20e9da 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -1072,6 +1072,10 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
     IX86_ATTR_IX86_YES ("general-regs-only",
 			OPT_mgeneral_regs_only,
 			OPTION_MASK_GENERAL_REGS_ONLY),
+
+    IX86_ATTR_IX86_YES ("baseline-isas-only",
+			OPT_mbaseline_isas_only,
+			OPTION_MASK_BASELINE_ISAS_ONLY),
   };
 
   location_t loc
@@ -1187,7 +1191,8 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
 
       else if (type == ix86_opt_ix86_yes || type == ix86_opt_ix86_no)
 	{
-	  if (mask == OPTION_MASK_GENERAL_REGS_ONLY)
+	  if (mask == OPTION_MASK_GENERAL_REGS_ONLY
+	      || mask == OPTION_MASK_BASELINE_ISAS_ONLY)
 	    {
 	      if (!opt_set_p)
 		{
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 37e77ea9fdd..91b535f1a95 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -551,18 +551,6 @@ ix86_can_inline_p (tree caller, tree callee)
   tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller);
   tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee);
 
-  /* Changes of those flags can be tolerated for always inlines. Lets hope
-     user knows what he is doing.  */
-  const unsigned HOST_WIDE_INT always_inline_safe_mask
-	 = (MASK_USE_8BIT_IDIV | MASK_ACCUMULATE_OUTGOING_ARGS
-	    | MASK_NO_ALIGN_STRINGOPS | MASK_AVX256_SPLIT_UNALIGNED_LOAD
-	    | MASK_AVX256_SPLIT_UNALIGNED_STORE | MASK_CLD
-	    | MASK_NO_FANCY_MATH_387 | MASK_IEEE_FP | MASK_INLINE_ALL_STRINGOPS
-	    | MASK_INLINE_STRINGOPS_DYNAMICALLY | MASK_RECIP | MASK_STACK_PROBE
-	    | MASK_STV | MASK_TLS_DIRECT_SEG_REFS | MASK_VZEROUPPER
-	    | MASK_NO_PUSH_ARGS | MASK_OMIT_LEAF_FRAME_POINTER);
-
-
   if (!callee_tree)
     callee_tree = target_option_default_node;
   if (!caller_tree)
@@ -573,10 +561,26 @@ ix86_can_inline_p (tree caller, tree callee)
   struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree);
   struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
   bool ret = false;
+  /* NB: Also tolerate those flags like always inlines for target
+    ("general-regs-only") attribute.  */
   bool always_inline
-    = (DECL_DISREGARD_INLINE_LIMITS (callee)
-       && lookup_attribute ("always_inline",
-			    DECL_ATTRIBUTES (callee)));
+    = ((DECL_DISREGARD_INLINE_LIMITS (callee)
+	&& lookup_attribute ("always_inline",
+			     DECL_ATTRIBUTES (callee)))
+       || TARGET_BASELINE_ISAS_ONLY_P (callee_opts->x_ix86_target_flags));
+
+  /* Changes of those flags can be tolerated for always inlines. Lets hope
+     user knows what he is doing.  */
+  const unsigned HOST_WIDE_INT always_inline_safe_mask
+	 = (MASK_USE_8BIT_IDIV | MASK_ACCUMULATE_OUTGOING_ARGS
+	    | MASK_NO_ALIGN_STRINGOPS | MASK_AVX256_SPLIT_UNALIGNED_LOAD
+	    | MASK_AVX256_SPLIT_UNALIGNED_STORE | MASK_CLD
+	    | MASK_NO_FANCY_MATH_387 | MASK_IEEE_FP | MASK_INLINE_ALL_STRINGOPS
+	    | MASK_INLINE_STRINGOPS_DYNAMICALLY | MASK_RECIP | MASK_STACK_PROBE
+	    | MASK_STV | MASK_TLS_DIRECT_SEG_REFS | MASK_VZEROUPPER
+	    | MASK_NO_PUSH_ARGS | MASK_OMIT_LEAF_FRAME_POINTER
+	    | (TARGET_GENERAL_REGS_ONLY_P (callee_opts->x_ix86_target_flags)
+	       ? MASK_80387 : 0));
 
   cgraph_node *callee_node = cgraph_node::get (callee);
   /* Callee's isa options should be a subset of the caller's, i.e. a SSE4
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 92b7475a7bf..334ff966e6f 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -211,6 +211,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_16BIT	TARGET_CODE16
 #define TARGET_16BIT_P(x)	TARGET_CODE16_P(x)
 
+#define TARGET_64BIT_BASELINE_ISAS \
+  (OPTION_MASK_ISA_FXSR | OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE \
+   | OPTION_MASK_ISA_SSE2)
+
 #define TARGET_MMX_WITH_SSE	(TARGET_64BIT && TARGET_SSE2)
 
 #include "config/vxworks-dummy.h"
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index c9f7195d423..f3a088aaa28 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1015,6 +1015,10 @@ mgeneral-regs-only
 Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
 Generate code which uses only the general registers.
 
+mbaseline-isas-only
+Target Report RejectNegative Mask(BASELINE_ISAS_ONLY) Var(ix86_target_flags) Save
+Generate code which uses only the baseline ISAs.
+
 mshstk
 Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags) Save
 Enable shadow stack built-in functions from Control-flow Enforcement
@@ -1114,4 +1118,4 @@ Support SERIALIZE built-in functions and code generation.
 
 mtsxldtrk
 Target Report Mask(ISA2_TSXLDTRK) Var(ix86_isa_flags2) Save
-Support TSXLDTRK built-in functions and code generation.
\ No newline at end of file
+Support TSXLDTRK built-in functions and code generation.
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 3b37aba5795..cd8ceaa25c6 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -6666,6 +6666,10 @@ doing a floating-point division.
 @cindex @code{target("general-regs-only")} function attribute, x86
 Generate code which uses only the general registers.
 
+@item baseline-isas-only
+@cindex @code{target("baseline-isas-only")} function attribute, x86
+Generate code which uses only the baseline ISAs.
+
 @item arch=@var{ARCH}
 @cindex @code{target("arch=@var{ARCH}")} function attribute, x86
 Specify the architecture to generate code for in compiling the function.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c99924214a7..c28448dd946 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -30603,6 +30603,11 @@ Generate code that uses only the general-purpose registers.  This
 prevents the compiler from using floating-point, vector, mask and bound
 registers.
 
+@item -mbaseline-isas-only
+@opindex mbaseline-isas-only
+Generate code that uses only the baseline ISAs which include FXSR, MMX,
+SSE and SSE2 in 64-bit mode.
+
 @item -mindirect-branch=@var{choice}
 @opindex mindirect-branch
 Convert indirect call and jump with @var{choice}.  The default is
diff --git a/gcc/testsuite/gcc.target/i386/avx512-check.h b/gcc/testsuite/gcc.target/i386/avx512-check.h
index 0a377dba1d5..1f1f59a37a3 100644
--- a/gcc/testsuite/gcc.target/i386/avx512-check.h
+++ b/gcc/testsuite/gcc.target/i386/avx512-check.h
@@ -1,5 +1,10 @@
 #include <stdlib.h>
+
+#pragma GCC push_options
+#pragma GCC target("general-regs-only,baseline-isas-only")
 #include "cpuid.h"
+#pragma GCC pop_options
+
 #include "m512-check.h"
 #include "avx512f-os-support.h"
 
@@ -25,6 +30,9 @@ do_test (void)
 }
 #endif
 
+#pragma GCC push_options
+#pragma GCC target("baseline-isas-only")
+
 static int
 check_osxsave (void)
 {
@@ -110,3 +118,5 @@ main ()
 #endif
   return 0;
 }
+
+#pragma GCC pop_options
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-10.c b/gcc/testsuite/gcc.target/i386/pr96744-10.c
new file mode 100644
index 00000000000..14bcc06f121
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-10.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <cpuid.h>
+
+int
+main ()
+{
+  unsigned int eax, ebx, ecx, edx;
+  int cpuid_info[4];
+
+  if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  __cpuidex (cpuid_info, 7, 0);
+
+  if (cpuid_info[0] != eax
+      || cpuid_info[1] != ebx
+      || cpuid_info[2] != ecx
+      || cpuid_info[3] != edx)
+    __builtin_abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not {call[ \t]+_?__get_cpuid_count} } } */
+/* { dg-final { scan-assembler-not {call[ \t]+_?__cpuidex} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-11.c b/gcc/testsuite/gcc.target/i386/pr96744-11.c
new file mode 100644
index 00000000000..7fec1a8612b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-11.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mgeneral-regs-only" } */
+
+#include <cpuid.h>
+
+int
+main ()
+{
+  unsigned int eax, ebx, ecx, edx;
+  int cpuid_info[4];
+
+  if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  __cpuidex (cpuid_info, 7, 0);
+
+  if (cpuid_info[0] != eax
+      || cpuid_info[1] != ebx
+      || cpuid_info[2] != ecx
+      || cpuid_info[3] != edx)
+    __builtin_abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not {call[ \t]+_?__get_cpuid_count} } } */
+/* { dg-final { scan-assembler-not {call[ \t]+_?__cpuidex} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-12.c b/gcc/testsuite/gcc.target/i386/pr96744-12.c
new file mode 100644
index 00000000000..54ca127e75a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-12.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse" } */
+
+#include <cpuid.h>
+
+int
+main ()
+{
+  unsigned int eax, ebx, ecx, edx;
+  int cpuid_info[4];
+
+  if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  __cpuidex (cpuid_info, 7, 0);
+
+  if (cpuid_info[0] != eax
+      || cpuid_info[1] != ebx
+      || cpuid_info[2] != ecx
+      || cpuid_info[3] != edx)
+    __builtin_abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not {call[ \t]+_?__get_cpuid_count} } } */
+/* { dg-final { scan-assembler-not {call[ \t]+_?__cpuidex} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-13.c b/gcc/testsuite/gcc.target/i386/pr96744-13.c
new file mode 100644
index 00000000000..e38ed3ccabb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-13.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse" } */
+
+#pragma GCC push_options
+#pragma GCC target("general-regs-only,baseline-isas-only")
+#include <cpuid.h>
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target("general-regs-only,baseline-isas-only")
+
+int
+main ()
+{
+  unsigned int eax, ebx, ecx, edx;
+  int cpuid_info[4];
+
+  if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  __cpuidex (cpuid_info, 7, 0);
+
+  if (cpuid_info[0] != eax
+      || cpuid_info[1] != ebx
+      || cpuid_info[2] != ecx
+      || cpuid_info[3] != edx)
+    __builtin_abort ();
+
+  return 0;
+}
+
+#pragma GCC pop_options
+
+/* { dg-final { scan-assembler-not {call[ \t]+_?__get_cpuid_count} } } */
+/* { dg-final { scan-assembler-not {call[ \t]+_?__cpuidex} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-14.c b/gcc/testsuite/gcc.target/i386/pr96744-14.c
new file mode 100644
index 00000000000..577ffc76d1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-14.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake" } */
+
+#pragma GCC push_options
+#pragma GCC target("general-regs-only,baseline-isas-only")
+#include <cpuid.h>
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target("baseline-isas-only")
+
+static __inline void
+foo (int __cpuid_info[4], int __leaf, int __subleaf)
+{
+  __cpuid_count (__leaf, __subleaf, __cpuid_info[0], __cpuid_info[1],
+		 __cpuid_info[2], __cpuid_info[3]);
+}
+
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target("general-regs-only")
+
+int
+bar (void)
+{
+  unsigned int eax, ebx, ecx, edx;
+  int cpuid_info[4];
+
+  if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  foo (cpuid_info, 7, 0);
+
+  if (cpuid_info[0] != eax
+      || cpuid_info[1] != ebx
+      || cpuid_info[2] != ecx
+      || cpuid_info[3] != edx)
+    __builtin_abort ();
+
+  return 0;
+}
+
+#pragma GCC pop_options
+
+/* { dg-final { scan-assembler-not {call[ \t]+_?__get_cpuid_count} } } */
+/* { dg-final { scan-assembler {call[ \t]+_?foo} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-15.c b/gcc/testsuite/gcc.target/i386/pr96744-15.c
new file mode 100644
index 00000000000..3a6fb9d0124
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-15.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake" } */
+
+#pragma GCC push_options
+#pragma GCC target("general-regs-only,baseline-isas-only")
+#include <cpuid.h>
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target("general-regs-only")
+
+static __inline void
+foo (int __cpuid_info[4], int __leaf, int __subleaf)
+{
+  __cpuid_count (__leaf, __subleaf, __cpuid_info[0], __cpuid_info[1],
+		 __cpuid_info[2], __cpuid_info[3]);
+}
+
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target("baseline-isas-only")
+
+int
+bar (void)
+{
+  unsigned int eax, ebx, ecx, edx;
+  int cpuid_info[4];
+
+  if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  foo (cpuid_info, 7, 0);
+
+  if (cpuid_info[0] != eax
+      || cpuid_info[1] != ebx
+      || cpuid_info[2] != ecx
+      || cpuid_info[3] != edx)
+    __builtin_abort ();
+
+  return 0;
+}
+
+#pragma GCC pop_options
+
+/* { dg-final { scan-assembler-not {call[ \t]+_?__get_cpuid_count} } } */
+/* { dg-final { scan-assembler {call[ \t]+_?foo} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-16.c b/gcc/testsuite/gcc.target/i386/pr96744-16.c
new file mode 100644
index 00000000000..06064a74a46
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-16.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+/* Reject the negated form of non-negatable attributes.  */
+
+__attribute__ ((target ("no-baseline-isas-only")))
+int
+foo (int a)
+{
+  return a + 1;
+}
+
+/* { dg-error "does not allow a negated form" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96744-17.c b/gcc/testsuite/gcc.target/i386/pr96744-17.c
new file mode 100644
index 00000000000..65be5a2951b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96744-17.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+/* Reject the negated form of non-negatable pragma target.  */
+
+#pragma GCC push_options
+#pragma GCC target("no-baseline-isas-only")
+
+int
+foo (int a)
+{
+  return a + 1;
+}
+
+#pragma GCC pop_options
+
+/* { dg-error "does not allow a negated form" "" { target *-*-* } 0 } */
-- 
2.26.2

Reply via email to