Add pattern to remove useless float casts in comparisons.
authorYury Gribov <tetra2005@gmail.com>
Fri, 12 Oct 2018 20:35:20 +0000 (20:35 +0000)
committerYury Gribov <ygribov@gcc.gnu.org>
Fri, 12 Oct 2018 20:35:20 +0000 (20:35 +0000)
PR middle-end/81376

gcc/
* real.c (format_helper::can_represent_integral_type_p): New function
* real.h (format_helper::can_represent_integral_type_p): Ditto.
* match.pd: New pattern.

gcc/testsuite/
* c-c++-common/pr81376.c: New test.
* gcc.target/i386/387-ficom-2.c: Update test.
* gcc.target/i386/387-ficom-2.c: Ditto.

From-SVN: r265131

gcc/ChangeLog
gcc/match.pd
gcc/real.c
gcc/real.h
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr81376.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/387-ficom-1.c
gcc/testsuite/gcc.target/i386/387-ficom-2.c

index 1cc85d8f23e53a6b1c2076d7893bd3440f3c881b..465de40d61e9da81154826c526a16867aeb04383 100644 (file)
@@ -1,3 +1,10 @@
+2018-10-12  Yury Gribov  <tetra2005@gmail.com>
+
+       PR middle-end/81376
+       * real.c (format_helper::can_represent_integral_type_p): New function
+       * real.h (format_helper::can_represent_integral_type_p): Ditto.
+       * match.pd: New pattern.
+
 2018-10-12  Alexandre Oliva <oliva@adacore.com>
 
        * configure.ac: Introduce --enable-large-address-aware
index 94fbab841f5e36bd33fda849a686fd80886ee1ff..b36d7ccb5dc30b56ce65ecd274ac98f46a78136c 100644 (file)
@@ -3400,6 +3400,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       (if (! HONOR_NANS (@0))
        (cmp @0 @1))))))
 
+/* Optimize various special cases of (FTYPE) N CMP (FTYPE) M.  */
+(for cmp (tcc_comparison)
+ (simplify
+  (cmp (float@0 @1) (float @2))
+   (if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@0))
+       && ! DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@0)))
+    (with
+     {
+       format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@0))));
+       tree type1 = TREE_TYPE (@1);
+       bool type1_signed_p = TYPE_SIGN (type1) == SIGNED;
+       tree type2 = TREE_TYPE (@2);
+       bool type2_signed_p = TYPE_SIGN (type2) == SIGNED;
+     }
+     (if (fmt.can_represent_integral_type_p (type1)
+         && fmt.can_represent_integral_type_p (type2))
+      (if (TYPE_PRECISION (type1) > TYPE_PRECISION (type2)
+           && type1_signed_p >= type2_signed_p)
+       (cmp @1 (convert @2))
+       (if (TYPE_PRECISION (type1) < TYPE_PRECISION (type2)
+            && type1_signed_p <= type2_signed_p)
+        (cmp (convert:type2 @1) @2)
+        (if (TYPE_PRECISION (type1) == TYPE_PRECISION (type2)
+             && type1_signed_p == type2_signed_p)
+        (cmp @1 @2)))))))))
+
 /* Optimize various special cases of (FTYPE) N CMP CST.  */
 (for cmp  (lt le eq ne ge gt)
      icmp (le le eq ne ge ge)
@@ -3410,7 +3436,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (with
      {
        tree itype = TREE_TYPE (@0);
-       signop isign = TYPE_SIGN (itype);
        format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1))));
        const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1);
        /* Be careful to preserve any potential exceptions due to
@@ -3420,17 +3445,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        bool exception_p
          = real_isnan (cst) && (cst->signalling
                                || (cmp != EQ_EXPR && cmp != NE_EXPR));
-       /* INT?_MIN is power-of-two so it takes
-         only one mantissa bit.  */
-       bool signed_p = isign == SIGNED;
-       bool itype_fits_ftype_p
-        = TYPE_PRECISION (itype) - signed_p <= significand_size (fmt);
      }
      /* TODO: allow non-fitting itype and SNaNs when
        -fno-trapping-math.  */
-     (if (itype_fits_ftype_p && ! exception_p)
+     (if (fmt.can_represent_integral_type_p (itype) && ! exception_p)
       (with
        {
+        signop isign = TYPE_SIGN (itype);
         REAL_VALUE_TYPE imin, imax;
         real_from_integer (&imin, fmt, wi::min_value (itype), isign);
         real_from_integer (&imax, fmt, wi::max_value (itype), isign);
index 51f8fd5b3aeb02ce2a996ce730721f9402031c84..0e2da25c2d1cef68bcfe73f004360229a2940035 100644 (file)
@@ -5176,6 +5176,19 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len)
   gcc_assert (strlen (buf) < len);
 }
 
+/* True if all values of integral type can be represented
+   by this floating-point type exactly.  */
+
+bool format_helper::can_represent_integral_type_p (tree type) const
+{
+  gcc_assert (! decimal_p () && INTEGRAL_TYPE_P (type));
+
+  /* INT?_MIN is power-of-two so it takes
+     only one mantissa bit.  */
+  bool signed_p = TYPE_SIGN (type) == SIGNED;
+  return TYPE_PRECISION (type) - signed_p <= significand_size (*this);
+}
+
 /* True if mode M has a NaN representation and
    the treatment of NaN operands is important.  */
 
index 561d0fda129d01db9c64b2c2d8af4f882227cab8..cd557b31c23303f5be0dde715553106ed303702c 100644 (file)
@@ -216,6 +216,7 @@ public:
   operator const real_format *() const { return m_format; }
 
   bool decimal_p () const { return m_format && m_format->b == 10; }
+  bool can_represent_integral_type_p (tree type) const;
 
 private:
   const real_format *m_format;
index 3604fe631374bd551fd69925ed3548d2953d17c4..d5bdf787a38adbe22e21c5ff189721cab1b67c00 100644 (file)
@@ -1,3 +1,10 @@
+2018-10-12  Yury Gribov  <tetra2005@gmail.com>
+
+       PR middle-end/81376
+       * c-c++-common/pr81376.c: New test.
+       * gcc.target/i386/387-ficom-2.c: Update test.
+       * gcc.target/i386/387-ficom-2.c: Ditto.
+
 2018-10-12  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/87597
diff --git a/gcc/testsuite/c-c++-common/pr81376.c b/gcc/testsuite/c-c++-common/pr81376.c
new file mode 100644 (file)
index 0000000..e67f41e
--- /dev/null
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+typedef double c_t;
+typedef int a_t;
+int f(a_t a1, a_t a2) {
+  return (c_t) a1 < (c_t) a2;
+  /* { dg-final { scan-tree-dump "return (<retval> = )?a1 < a2" "original" } } */
+}
+
+void f1(short a, short b)
+{
+  volatile int s_s;
+  s_s = (float) a < (float) b;
+  /* { dg-final { scan-tree-dump "s_s = a < b" "original" } } */
+}
+
+void f2(unsigned short a, unsigned short b)
+{
+  volatile int us_us;
+  us_us = (float) a < (float) b;
+  /* { dg-final { scan-tree-dump "us_us = a < b" "original" } } */
+}
+
+/* We don't optimize here because neither of integral types is
+   subset of the other.  */
+void f3(unsigned short a, short b)
+{
+  volatile int us_s;
+  us_s = (float) a < (float) b;
+  /* { dg-final { scan-tree-dump "us_s = \\(float\\) a < \\(float\\) b" "original" } } */
+}
+
+void f4(unsigned short a, int b)
+{
+  volatile int us_i;
+  us_i = (double) a < (double) b;
+  /* { dg-final { scan-tree-dump "us_i = \\(int\\) a < b" "original" } } */
+}
+
+/* We don't optimize here because neither of integral types is
+   subset of the other.  */
+void f5(short a, unsigned int b)
+{
+  volatile int s_ui;
+  s_ui = (double) a < (double) b;
+  /* { dg-final { scan-tree-dump "s_ui = \\(double\\) a < \\(double\\) b" "original" } } */
+}
index 325698854a94beb313dd1a856d0f071f182ca1fb..8cef82df6a01b4034594e74d741c78937a80552a 100644 (file)
@@ -37,5 +37,6 @@ int test_ld_i (int x)
   return (long double)i != x;
 }
 
-/* { dg-final { scan-assembler-times "ficomp\[s\t\]" 3 } } */
-/* { dg-final { scan-assembler-times "ficompl" 3 } } */
+/* { dg-final { scan-assembler-times "cmpw\[s\t\]" 3 } } */
+/* { dg-final { scan-assembler-times "ficompl" 1 } } */
+/* { dg-final { scan-assembler-times "cmpl" 2 } } */
index d5283684f8ea4f4d3e77a987cf94c7f72827bb53..46c4b558d8ceb32ae841141f4ce7e63cd603ea90 100644 (file)
@@ -5,5 +5,6 @@
 
 #include "387-ficom-1.c"
 
-/* { dg-final { scan-assembler-times "ficomp\[s\t\]" 3 } } */
-/* { dg-final { scan-assembler-times "ficompl" 3 } } */
+/* { dg-final { scan-assembler-times "cmpw\[s\t\]" 3 } } */
+/* { dg-final { scan-assembler-times "ficompl" 1 } } */
+/* { dg-final { scan-assembler-times "cmpl" 2 } } */