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
