[PATCH v2] x86: Allow minus ones for Kn and standard constants for XMMn

"H.J. Lu" <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CAMe9rOr8Gn5DGpqOx3ZFQPA8_ix9WqxBcHFg3GR7ZVKDUgYhWQ@mail.gmail.com>
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.
v2-0001-x86-Allow-minus-ones-for-Kn-and-standard-constant.patch (application/x-patch, 5.9 KB)
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.