Since we can load minus ones into an SSE or MASK register, allow minus ones for SSE and MASK 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 SSE and MASK registers. * 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. -- H.J.
From 95adb02f16b5984e278fad9ed45b2c25cfaa4921 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Thu, 20 Aug 2026 12:17:41 +0800 Subject: [PATCH] x86: Allow minus ones for SSE and MASK registers Since we can load minus ones into an SSE or MASK register, allow minus ones for SSE and MASK 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 SSE and MASK registers. * 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 | 20 +++++--- 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, 140 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..b4e2ea65915 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -21077,14 +21077,18 @@ 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. One exception + is minus ones for SSE and MASK registers. */ + if (CONSTANT_P (x)) + { + if (MAYBE_MMX_CLASS_P (regclass)) + return NO_REGS; + if (MAYBE_SSE_CLASS_P (regclass) + || MAYBE_MASK_CLASS_P (regclass)) + return x == CONSTM1_RTX (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
