[gcc(refs/users/meissner/heads/work078)] Don't do int cmoves for IEEE comparisons.

Michael Meissner meissner@gcc.gnu.org
Thu Feb 17 16:36:35 GMT 2022


https://gcc.gnu.org/g:eb40af84b538b127a7b1a7733ac77b90d777b6bb

commit eb40af84b538b127a7b1a7733ac77b90d777b6bb
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Thu Feb 17 11:34:54 2022 -0500

    Don't do int cmoves for IEEE comparisons.
    
    Protect int cmove from raising an assertion if it is trying to do an int
    conditional move where the test involves floating point comparisons that
    can't easily be reversed due to NaNs.
    
    2022-02-17  Michael Meissner  <meissner@the-meissners.org>
    
    gcc/
            PR target/104256
            * config/rs6000/rs6000.cc (rs6000_emit_int_cmove): Don't do
            integer conditional moves if the test involves floating point
            comparisons that can't easily be reversed.
    
    gcc/testsuite/
            PR target/104256
            * gcc.target/powerpc/ppc-fortran/pr104254.f90: New test.

Diff:
---
 gcc/config/rs6000/rs6000.cc                        |  9 ++++++++
 .../gcc.target/powerpc/ppc-fortran/pr104254.f90    | 25 ++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index f56cf66313a..820a6ed77b8 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -16181,6 +16181,15 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
   if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode))
     return false;
 
+  /* Don't generate int cmoves for floating point comparisons that might
+     involve NaNs and generate conditions that can't be reversed.  */
+  enum rtx_code op_code = GET_CODE (op);
+  if (GET_MODE (XEXP (op, 0)) == CCFPmode
+      && (!flag_finite_math_only
+	  || op_code == UNLT || op_code == UNLE || op_code == UNGT
+	  || op_code == UNGE || op_code == UNEQ || op_code == LTGT))
+    return false;
+
   /* We still have to do the compare, because isel doesn't do a
      compare, it just looks at the CRx bits set by a previous compare
      instruction.  */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr104254.f90 b/gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr104254.f90
new file mode 100644
index 00000000000..d1bfab23482
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr104254.f90
@@ -0,0 +1,25 @@
+! { dg-do compile }
+! { dg-require-effective-target powerpc_p9vector_ok }
+! { dg-options "-mdejagnu-cpu=power9 -O1 -fnon-call-exceptions" }
+
+! PR target/104254.  GCC would raise an assertion error if this program was
+! compiled with -O1 and -fnon-call-exceptions on a power9 or higher.  The issue
+! occurs because at this optimization level, the compiler is trying to make
+! a conditional move to store integers using a 32-bit floating point compare.
+! It wants to use UNLE, which is not supported for integer modes.
+  
+  real :: a(2), nan
+  real, allocatable :: c(:)
+  integer :: ia(1)
+
+  nan = 0.0
+  nan = 0.0/nan
+
+  a(:) = nan
+  ia = maxloc (a)
+  if (ia(1).ne.1) STOP 1
+
+  allocate (c(1))
+  c(:) = nan
+  deallocate (c)
+end


More information about the Gcc-cvs mailing list