Hi!

If the backend doesn't have floating point EQ or NE comparison, dojump.c
splits it into ORDERED && UNEQ or UNORDERED || LTGT.  If both comparison
operands are the same, we know the result of the second comparison though,
a == b is equivalent to a ord b and a != b is equivalent to a unord b,
and thus can just use ORDERED or UNORDERED.

On the testcase, this changes f1:
-       ucomiss %xmm0, %xmm0
-       movl    $1, %eax
-       jp      .L3
-       jne     .L3
-       ret
-       .p2align 4,,10
-       .p2align 3
-.L3:
        xorl    %eax, %eax
+       ucomiss %xmm0, %xmm0
+       setnp   %al
and f3:
-       ucomisd %xmm0, %xmm0
-       movl    $1, %eax
-       jp      .L8
-       jne     .L8
-       ret
-       .p2align 4,,10
-       .p2align 3
-.L8:
        xorl    %eax, %eax
+       ucomisd %xmm0, %xmm0
+       setnp   %al
while keeping the same code for f2 and f4.

Bootstrapped/regtested on {x86_64,i686,powerpc64le,aarch64,armv7hl}-linux,
ok for trunk?

2020-12-10  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/98169
        * dojump.c (do_compare_rtx_and_jump): Don't split self-EQ/NE
        comparisons, just use ORDERED or UNORDERED.

        * gcc.target/i386/pr98169.c: New test.

--- gcc/dojump.c.jj     2020-01-27 13:20:40.000000000 +0100
+++ gcc/dojump.c        2020-12-09 11:56:12.484150856 +0100
@@ -1114,7 +1114,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
                   /* ... or if there is no libcall for it.  */
                   || code_to_optab (code) == unknown_optab))
         {
-         enum rtx_code first_code;
+         enum rtx_code first_code, orig_code = code;
          bool and_them = split_comparison (code, mode, &first_code, &code);
 
          /* If there are no NaNs, the first comparison should always fall
@@ -1122,6 +1122,12 @@ do_compare_rtx_and_jump (rtx op0, rtx op
          if (!HONOR_NANS (mode))
            gcc_assert (first_code == (and_them ? ORDERED : UNORDERED));
 
+         else if ((orig_code == EQ || orig_code == NE)
+                  && rtx_equal_p (op0, op1))
+           /* Self-comparisons x == x or x != x can be optimized into
+              just x ord x or x nord x.  */
+           code = orig_code == EQ ? ORDERED : UNORDERED;
+
          else
            {
              profile_probability cprob
--- gcc/testsuite/gcc.target/i386/pr98169.c.jj  2020-12-09 12:01:23.055686732 
+0100
+++ gcc/testsuite/gcc.target/i386/pr98169.c     2020-12-09 12:02:00.450269645 
+0100
@@ -0,0 +1,29 @@
+/* PR tree-optimization/98169 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-finite-math-only" } */
+/* { dg-final { scan-assembler-times "\tsetn\?p\t" 4 } } */
+/* { dg-final { scan-assembler-not "\tjn\?\[ep]\t" } } */
+
+int
+f1 (float a)
+{
+  return a == a;
+}
+
+int
+f2 (float a)
+{
+  return !__builtin_isnanf (a);
+}
+
+int
+f3 (double a)
+{
+  return a == a;
+}
+
+int
+f4 (double a)
+{
+  return !__builtin_isnan (a);
+}

        Jakub

Reply via email to