On Fri, Aug 21, 2026 at 10:06 AM Hongtao Liu <[email protected]> wrote:
>
> On Fri, Aug 21, 2026 at 9:08 AM H.J. Lu <[email protected]> wrote:
> >
> > Since we can load minus ones into an SSE or MASK register, allow minus
> > ones for SSE and MASK registers so that
> >
>
> I think we should use standard_sse_constant_p (x, mode) for
> MAYBE_SSE_CLASS_P since there's no direct instruction to move -1 to
> sse register for scalar floating mode, pcmpeq is only used for vector
> mode.
> So how about
>
> if (CONSTANT_P (x))
>   {
>     if (MAYBE_MAAX_CLASS_P (regclass))
>       return NO_REGS;
>     if (MAYBE_MASK_CLASS_P (regclass))
>       return x == constm1_rtx ? regclass : NO_REG;
>     if (MAYBE_SSE_CLASS_P (regclass))
>       return (mode != VOIDmode && stardard_sse_constant_p (x, mode)) ?
> regclass : NO_REGS;
> }

Like this?

-- 
H.J.
---
Since we can load minus ones into a MASK register and standard SSE
constants into a SSE register, allow them for MASK and SSE registers
so that

kxnor %k0, %k0, %k0

is used to load -1 into mask register, instead of loading from memory.

PR target/126959
* config/i386/i386.cc (ix86_preferred_reload_class): Allow
minus ones for MASK register and standard SSE constants for
SSE register.
* gcc.target/i386/pr126959-1a.c: New test.
* gcc.target/i386/pr126959-1b.c: Likewise.
* gcc.target/i386/pr126959-2a.c: Likewise.
* gcc.target/i386/pr126959-2b.c: Likewise.
From a33f52cc84b0334cf0ba5eb6c0b37021da04fee4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Thu, 20 Aug 2026 12:17:41 +0800
Subject: [PATCH v2] x86: Allow minus ones for Kn and standard constants for
 XMMn

Since we can load minus ones into a MASK register and standard SSE
constants into a SSE register, allow them for MASK and SSE registers
so that

	kxnor	%k0, %k0, %k0

is used to load -1 into mask register, instead of loading from memory.

	PR target/126959
	* config/i386/i386.cc (ix86_preferred_reload_class): Allow
	minus ones for MASK register and standard SSE constants for
	SSE register.
	* gcc.target/i386/pr126959-1a.c: New test.
	* gcc.target/i386/pr126959-1b.c: Likewise.
	* gcc.target/i386/pr126959-2a.c: Likewise.
	* gcc.target/i386/pr126959-2b.c: Likewise.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/config/i386/i386.cc                     | 23 ++++++---
 gcc/testsuite/gcc.target/i386/pr126959-1a.c | 55 +++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr126959-1b.c | 36 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr126959-2a.c | 21 ++++++++
 gcc/testsuite/gcc.target/i386/pr126959-2b.c | 16 ++++++
 5 files changed, 143 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126959-1a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126959-1b.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126959-2a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126959-2b.c

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index dcfe4531f11..4b5380f0b05 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -21077,14 +21077,21 @@ ix86_preferred_reload_class (rtx x, reg_class_t regclass)
   if (x == CONST0_RTX (mode))
     return regclass;
 
-  /* Force constants into memory if we are loading a (nonzero) constant into
-     an MMX, SSE or MASK register.  This is because there are no MMX/SSE/MASK
-     instructions to load from a constant.  */
-  if (CONSTANT_P (x)
-      && (MAYBE_MMX_CLASS_P (regclass)
-	  || MAYBE_SSE_CLASS_P (regclass)
-	  || MAYBE_MASK_CLASS_P (regclass)))
-    return NO_REGS;
+  /* Force constants into memory if we are loading a non-zero constant
+     into an MMX, SSE or MASK register.  This is because there are no
+     MMX/SSE/MASK instructions to load from a constant.  Exceptions are
+     minus ones for MASK register and standard SSE constants for SSE
+     register.  */
+  if (CONSTANT_P (x))
+    {
+      if (MAYBE_MMX_CLASS_P (regclass))
+	return NO_REGS;
+       if (MAYBE_MASK_CLASS_P (regclass))
+	 return x == constm1_rtx ? regclass : NO_REGS;
+       if (MAYBE_SSE_CLASS_P (regclass))
+	 return (mode != VOIDmode && standard_sse_constant_p (x, mode)
+		 ? regclass : NO_REGS);
+    }
 
   /* Floating-point constants need more complex checks.  */
   if (CONST_DOUBLE_P (x))
diff --git a/gcc/testsuite/gcc.target/i386/pr126959-1a.c b/gcc/testsuite/gcc.target/i386/pr126959-1a.c
new file mode 100644
index 00000000000..a0c7b409cd6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126959-1a.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target *-*-* } {^\t?\.} } } */
+
+/*
+**func1:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnorb	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+void
+func1 (void)
+{
+  unsigned char k = -1;
+  __asm volatile ("" : : "k" (k));
+}
+
+/*
+**func2:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnorw	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+void
+func2 (void)
+{
+  unsigned short k = -1;
+  __asm volatile ("" : : "k" (k));
+}
+
+/*
+**func3:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnord	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+void
+func3 (void)
+{
+  unsigned int k = -1;
+  __asm volatile ("" : : "k" (k));
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126959-1b.c b/gcc/testsuite/gcc.target/i386/pr126959-1b.c
new file mode 100644
index 00000000000..12b86f98e79
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126959-1b.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4 -mtune=znver4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target *-*-* } {^\t?\.} } } */
+
+/*
+**func1:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnorb	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+/*
+**func2:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnorw	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+/*
+**func3:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnord	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+#include "pr126959-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126959-2a.c b/gcc/testsuite/gcc.target/i386/pr126959-2a.c
new file mode 100644
index 00000000000..3d350c85389
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126959-2a.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target *-*-* } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnorq	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+void
+func (void)
+{
+  unsigned long long k = -1;
+  __asm volatile ("" : : "k" (k));
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126959-2b.c b/gcc/testsuite/gcc.target/i386/pr126959-2b.c
new file mode 100644
index 00000000000..f4bd15bfbf8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126959-2b.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -march=x86-64-v4 -mtune=znver4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target *-*-* } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB[0-9]+:
+**	.cfi_startproc
+**	kxnorq	%k0, %k0, %k0
+**	ret
+**	.cfi_endproc
+**...
+*/
+
+#include "pr126959-2a.c"
-- 
2.55.0

Reply via email to