public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work078)] Don't do int cmoves for IEEE comparisons.
@ 2022-02-17 17:47 Michael Meissner
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Meissner @ 2022-02-17 17:47 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:8946d7f6e2239ad5c2c91da3d50bc0250e7e0162

commit 8946d7f6e2239ad5c2c91da3d50bc0250e7e0162
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Thu Feb 17 12:40:15 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.
    
    The code used to generate the condition, and possibly reverse the condition if
    ISEL could not handle it by rewriting the OP in the comparison rtx.
    Unfortunately there are some conditions like UNLE that can't easily be reversed
    due to NaNs.
    
    The patch changes this so that it does the reversal before generating the
    comparison.  If the comparison cannot be reversed, it just returns false,
    saying that we can't do an int conditional move in this case.
    
    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 needs to be reversed and
            there isn't a direct reverse comparison.
    
    gcc/testsuite/
            PR target/104256
            * gcc.target/powerpc/ppc-fortran/pr104254.f90: New test.

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

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index f56cf66313a..15d324d13aa 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -16174,18 +16174,35 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
 {
   rtx condition_rtx, cr;
   machine_mode mode = GET_MODE (dest);
-  enum rtx_code cond_code;
   rtx (*isel_func) (rtx, rtx, rtx, rtx, rtx);
   bool signedp;
 
   if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode))
     return false;
 
+  /* Swap the comparison if isel can't handle it directly.  Don't generate int
+     cmoves if we can't swap the condition code due to NaNs.  */
+  enum rtx_code op_code = GET_CODE (op);
+  if (op_code != LT && op_code != GT && op_code != LTU && op_code != GTU
+      && op_code != EQ)
+    {
+      if (!COMPARISON_P (op))
+	return false;
+
+      enum rtx_code rev_code = reverse_condition (op_code);
+      if (rev_code == UNKNOWN)
+	return false;
+
+      std::swap (false_cond, true_cond);
+      op = gen_rtx_fmt_ee (rev_code, GET_MODE (op),
+			   XEXP (op, 0),
+			   XEXP (op, 1));
+    }
+
   /* 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.  */
   condition_rtx = rs6000_generate_compare (op, mode);
-  cond_code = GET_CODE (condition_rtx);
   cr = XEXP (condition_rtx, 0);
   signedp = GET_MODE (cr) == CCmode;
 
@@ -16193,21 +16210,6 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
 	       ? (signedp ? gen_isel_signed_si : gen_isel_unsigned_si)
 	       : (signedp ? gen_isel_signed_di : gen_isel_unsigned_di));
 
-  switch (cond_code)
-    {
-    case LT: case GT: case LTU: case GTU: case EQ:
-      /* isel handles these directly.  */
-      break;
-
-    default:
-      /* We need to swap the sense of the comparison.  */
-      {
-	std::swap (false_cond, true_cond);
-	PUT_CODE (condition_rtx, reverse_condition (cond_code));
-      }
-      break;
-    }
-
   false_cond = force_reg (mode, false_cond);
   if (true_cond != const0_rtx)
     true_cond = force_reg (mode, true_cond);
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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [gcc(refs/users/meissner/heads/work078)] Don't do int cmoves for IEEE comparisons.
@ 2022-02-17 16:36 Michael Meissner
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Meissner @ 2022-02-17 16:36 UTC (permalink / raw)
  To: gcc-cvs

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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [gcc(refs/users/meissner/heads/work078)] Don't do int cmoves for IEEE comparisons.
@ 2022-02-17  5:53 Michael Meissner
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Meissner @ 2022-02-17  5:53 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7f7055147cfde9158d33f790bba8cb85cc8b7581

commit 7f7055147cfde9158d33f790bba8cb85cc8b7581
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Thu Feb 17 00:53:38 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 IEEE comparisons that must be
    done with a CCFPmode instead of the CCmode normally used for int cmoves.
    
    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 IEEE comparisons.
    
    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..10af34fca69 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 do int cmoves for IEEE comparisons.  The rs6000_generate_compare
+     function will eventually raise an exception because the mode used is
+     CCmode (due to this being an int cmove), but you can only do these
+     comparsions with CCFP mode.  */
+  enum rtx_code op_code = GET_CODE (op);
+  if (op_code == ORDERED || op_code == UNORDERED || op_code == UNEQ || op_code == LTGT
+      || op_code == UNGT || op_code == UNLT || op_code == UNGE || op_code == UNLE)
+    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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [gcc(refs/users/meissner/heads/work078)] Don't do int cmoves for IEEE comparisons.
@ 2022-02-17  3:52 Michael Meissner
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Meissner @ 2022-02-17  3:52 UTC (permalink / raw)
  To: gcc-cvs

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

commit c4eee68ab4248600dcfdf23dffdeffcfc2ae5e0a
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Wed Feb 16 22:52:07 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 IEEE comparisons that must be
    done with a CCFPmode instead of the CCmode normally used for int cmoves.
    
    2022-02-16  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 IEEE comparisons.

Diff:
---
 gcc/config/rs6000/rs6000.cc | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index f56cf66313a..10af34fca69 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 do int cmoves for IEEE comparisons.  The rs6000_generate_compare
+     function will eventually raise an exception because the mode used is
+     CCmode (due to this being an int cmove), but you can only do these
+     comparsions with CCFP mode.  */
+  enum rtx_code op_code = GET_CODE (op);
+  if (op_code == ORDERED || op_code == UNORDERED || op_code == UNEQ || op_code == LTGT
+      || op_code == UNGT || op_code == UNLT || op_code == UNGE || op_code == UNLE)
+    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.  */


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-02-17 17:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-17 17:47 [gcc(refs/users/meissner/heads/work078)] Don't do int cmoves for IEEE comparisons Michael Meissner
  -- strict thread matches above, loose matches on Subject: below --
2022-02-17 16:36 Michael Meissner
2022-02-17  5:53 Michael Meissner
2022-02-17  3:52 Michael Meissner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).