The ccmp expansion code allowed DFmode, SFmode and HFmode comparisons
without verifying that the corresponding floating-point instruction
set was available. This could result in attempts to generate ccmp
sequences for comparisons that cannot be emitted as a single instruction
under the selected target options.
Restrict XFmode support to x87 targets, DFmode/SFmode support to
targets with either x87 or SSE with SSE math enabled, and HFmode
support to targets with AVX512FP16 enabled.
PR target/126148
gcc/ChangeLog:
* config/i386/i386-expand.cc (ix86_gen_ccmp_first): Restrict
floating-point modes accepted for ccmp according to the
available floating-point instruction set.
gcc/testsuite/ChangeLog:
* gcc.target/i386/pr126148.c: New test.
Bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32}.
Uros.
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index fd25b93a566..a448e470f73 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -27294,12 +27294,15 @@ ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn
**gen_seq,
op_mode = GET_MODE (op1);
/* We only supports following scalar comparisons that use just 1
- instruction: DI/SI/QI/HI/DF/SF/HF.
+ instruction: DI/SI/HI/QI/XF/DF/SF/HF.
Unordered/Ordered compare cannot be correctly identified by
ccmp so they are not supported. */
- if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
- || op_mode == QImode || op_mode == DFmode || op_mode == SFmode
- || op_mode == HFmode)
+ if (!(op_mode == DImode || op_mode == SImode
+ || op_mode == HImode || op_mode == QImode
+ || ((op_mode == XFmode || op_mode == DFmode || op_mode == SFmode)
+ && (TARGET_80387
+ || (SSE_FLOAT_MODE_P (op_mode) && TARGET_SSE_MATH)))
+ || (op_mode == HFmode && TARGET_AVX512FP16))
|| code == ORDERED
|| code == UNORDERED)
{
diff --git a/gcc/testsuite/gcc.target/i386/pr126148.c
b/gcc/testsuite/gcc.target/i386/pr126148.c
new file mode 100644
index 00000000000..f706d303c4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126148.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -ffast-math -mapxf -mno-80387 -mfpmath=387" } */
+
+int foo (int a, double b) {
+ if (a || b)
+ return 1;
+ return 0;
+}