Commit e41ec71b by Yury Gribov Committed by Yury Gribov

Add pattern to remove useless float casts in comparisons.

	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
parent 67aeaded
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> 2018-10-12 Alexandre Oliva <oliva@adacore.com>
* configure.ac: Introduce --enable-large-address-aware * configure.ac: Introduce --enable-large-address-aware
...@@ -3400,6 +3400,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -3400,6 +3400,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (! HONOR_NANS (@0)) (if (! HONOR_NANS (@0))
(cmp @0 @1)))))) (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. */ /* Optimize various special cases of (FTYPE) N CMP CST. */
(for cmp (lt le eq ne ge gt) (for cmp (lt le eq ne ge gt)
icmp (le le eq ne ge ge) icmp (le le eq ne ge ge)
...@@ -3410,7 +3436,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -3410,7 +3436,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(with (with
{ {
tree itype = TREE_TYPE (@0); tree itype = TREE_TYPE (@0);
signop isign = TYPE_SIGN (itype);
format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1)))); format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1))));
const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1); const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1);
/* Be careful to preserve any potential exceptions due to /* Be careful to preserve any potential exceptions due to
...@@ -3420,17 +3445,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -3420,17 +3445,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
bool exception_p bool exception_p
= real_isnan (cst) && (cst->signalling = real_isnan (cst) && (cst->signalling
|| (cmp != EQ_EXPR && cmp != NE_EXPR)); || (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 /* TODO: allow non-fitting itype and SNaNs when
-fno-trapping-math. */ -fno-trapping-math. */
(if (itype_fits_ftype_p && ! exception_p) (if (fmt.can_represent_integral_type_p (itype) && ! exception_p)
(with (with
{ {
signop isign = TYPE_SIGN (itype);
REAL_VALUE_TYPE imin, imax; REAL_VALUE_TYPE imin, imax;
real_from_integer (&imin, fmt, wi::min_value (itype), isign); real_from_integer (&imin, fmt, wi::min_value (itype), isign);
real_from_integer (&imax, fmt, wi::max_value (itype), isign); real_from_integer (&imax, fmt, wi::max_value (itype), isign);
......
...@@ -5176,6 +5176,19 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len) ...@@ -5176,6 +5176,19 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len)
gcc_assert (strlen (buf) < 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 /* True if mode M has a NaN representation and
the treatment of NaN operands is important. */ the treatment of NaN operands is important. */
......
...@@ -216,6 +216,7 @@ public: ...@@ -216,6 +216,7 @@ public:
operator const real_format *() const { return m_format; } operator const real_format *() const { return m_format; }
bool decimal_p () const { return m_format && m_format->b == 10; } bool decimal_p () const { return m_format && m_format->b == 10; }
bool can_represent_integral_type_p (tree type) const;
private: private:
const real_format *m_format; const real_format *m_format;
......
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> 2018-10-12 Tobias Burnus <burnus@net-b.de>
PR fortran/87597 PR fortran/87597
......
/* { 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" } } */
}
...@@ -37,5 +37,6 @@ int test_ld_i (int x) ...@@ -37,5 +37,6 @@ int test_ld_i (int x)
return (long double)i != x; return (long double)i != x;
} }
/* { dg-final { scan-assembler-times "ficomp\[s\t\]" 3 } } */ /* { dg-final { scan-assembler-times "cmpw\[s\t\]" 3 } } */
/* { dg-final { scan-assembler-times "ficompl" 3 } } */ /* { dg-final { scan-assembler-times "ficompl" 1 } } */
/* { dg-final { scan-assembler-times "cmpl" 2 } } */
...@@ -5,5 +5,6 @@ ...@@ -5,5 +5,6 @@
#include "387-ficom-1.c" #include "387-ficom-1.c"
/* { dg-final { scan-assembler-times "ficomp\[s\t\]" 3 } } */ /* { dg-final { scan-assembler-times "cmpw\[s\t\]" 3 } } */
/* { dg-final { scan-assembler-times "ficompl" 3 } } */ /* { dg-final { scan-assembler-times "ficompl" 1 } } */
/* { dg-final { scan-assembler-times "cmpl" 2 } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment