https://gcc.gnu.org/g:30bdb83cf272c702487a72a715890994056319fe
commit r17-5211-g30bdb83cf272c702487a72a715890994056319fe Author: Hongyu Wang <[email protected]> Date: Mon Oct 12 17:14:56 2026 +0800 i386: Raise FE_INVALID for vector LTGT compares [PR127649] LTGT is a signaling compare and must raise FE_INVALID on a quiet NaN, like the scalar comiss it expands to. The vector expansion used quiet compares instead: NEQ_OQ for AVX and AVX512, and ORDERED & NE for SSE. Use the signaling NEQ_OS predicate for AVX and AVX512. Legacy SSE has no ordered not-equal predicate, so expand LTGT as LT | GT, which uses the signaling cmpltps and needs no extra instruction. gcc/ChangeLog: PR target/127649 * config/i386/i386-expand.cc (ix86_fp_cmp_code_to_pcmp_immediate): Use NEQ_OS for LTGT. (ix86_expand_fp_vec_cmp): Expand LTGT as LT | GT. * config/i386/i386.cc (ix86_print_operand): Print neq_os for LTGT. gcc/testsuite/ChangeLog: PR target/127649 * gcc.target/i386/pr127649-1.c: New test. * gcc.target/i386/pr127649-2.c: Likewise. Diff: --- gcc/config/i386/i386-expand.cc | 10 +++---- gcc/config/i386/i386.cc | 2 +- gcc/testsuite/gcc.target/i386/pr127649-1.c | 37 ++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr127649-2.c | 46 ++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index a9654e9a8354..deae439814b6 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -4818,7 +4818,7 @@ ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code) case UNEQ: return 0x08; case LTGT: - return 0x0c; + return 0x1c; case ORDERED: return 0x07; case UNORDERED: @@ -4886,11 +4886,11 @@ ix86_expand_fp_vec_cmp (rtx operands[]) switch (GET_CODE (operands[1])) { case LTGT: - temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2], + temp = ix86_expand_sse_cmp (operands[0], LT, operands[2], operands[3], NULL, NULL); - cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2], - operands[3], NULL, NULL); - code = AND; + cmp = ix86_expand_sse_cmp (operands[0], LT, operands[3], + operands[2], NULL, NULL); + code = IOR; break; case UNEQ: temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2], diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 4dba04774e86..8dc89f2dcde3 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -14545,7 +14545,7 @@ ix86_print_operand (FILE *file, rtx x, int code) case LTGT: if (TARGET_AVX) { - fputs ("neq_oq", file); + fputs ("neq_os", file); break; } /* FALLTHRU */ diff --git a/gcc/testsuite/gcc.target/i386/pr127649-1.c b/gcc/testsuite/gcc.target/i386/pr127649-1.c new file mode 100644 index 000000000000..e1b1cb981dc8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr127649-1.c @@ -0,0 +1,37 @@ +/* PR target/127649 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2 -mno-avx" } */ + +/* LTGT is a signaling compare. Use LT | GT for SSE and the NEQ_OS + predicate for AVX. */ + +void +ltgt_sse (int *r, float *a, float *b) +{ + for (int i = 0; i < 1024; i++) + r[i] = (a[i] < b[i]) | (a[i] > b[i]); +} + +__attribute__((target ("avx,no-avx512f"))) +void +ltgt_avx (int *r, float *a, float *b) +{ + for (int i = 0; i < 1024; i++) + r[i] = (a[i] < b[i]) | (a[i] > b[i]); +} + +__attribute__((target ("avx512vl"))) +void +ltgt_avx512 (int *r, float *a, float *b) +{ + for (int i = 0; i < 1024; i++) + r[i] = (a[i] < b[i]) | (a[i] > b[i]); +} + +/* { dg-final { scan-assembler-times "\[ \t\]cmpltps" 2 } } */ +/* { dg-final { scan-assembler-not "\[ \t\]cmpordps" } } */ +/* { dg-final { scan-assembler-not "\[ \t\]cmpneqps" } } */ +/* { dg-final { scan-assembler-times "vcmpneq_osps" 1 } } */ +/* { dg-final { scan-assembler-times "vcmpps\[ \t\]*\\\$28," 1 } } */ +/* { dg-final { scan-assembler-not "vcmpneq_oqps" } } */ +/* { dg-final { scan-assembler-not "vcmpps\[ \t\]*\\\$12," } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr127649-2.c b/gcc/testsuite/gcc.target/i386/pr127649-2.c new file mode 100644 index 000000000000..04d74a229363 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr127649-2.c @@ -0,0 +1,46 @@ +/* PR target/127649 */ +/* { dg-do run } */ +/* { dg-options "-O2 -msse2 -mno-avx" } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-additional-options "-mfpmath=sse" { target ia32 } } */ + +#include <fenv.h> +#include "pr127649-1.c" + +#define N 1024 + +static float a[N], b[N]; +static int r[N]; + +static void +check (void (*fn) (int *, float *, float *)) +{ + for (int i = 0; i < N; i++) + r[i] = -1; + feclearexcept (FE_ALL_EXCEPT); + fn (r, a, b); + if (!fetestexcept (FE_INVALID)) + __builtin_abort (); + for (int i = 0; i < N; i++) + if (r[i] != 0) + __builtin_abort (); +} + +int +main (void) +{ + __builtin_cpu_init (); + + for (int i = 0; i < N; i++) + { + a[i] = __builtin_nanf (""); + b[i] = 1.0f; + } + + check (ltgt_sse); + if (__builtin_cpu_supports ("avx")) + check (ltgt_avx); + if (__builtin_cpu_supports ("avx512vl")) + check (ltgt_avx512); + return 0; +}
