aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYvan Roux <yvan.roux@linaro.org>2015-11-18 09:27:06 +0100
committerLinaro Code Review <review@review.linaro.org>2015-11-18 13:57:09 +0000
commit1f677480a31529f9afc53dbb4aaa088b91de8840 (patch)
tree9b6b06a7606ea9a20dbb8d867acb27f39cbfb68a
parent0a82844286c0fe515ba88458f969ffd87b4c6d58 (diff)
gcc/
Backport from trunk r226987. 2015-08-18 Richard Sandiford <richard.sandiford@arm.com> PR rtl-optimization/67218 * simplify-rtx.c (exact_int_to_float_conversion_p): New function. (simplify_unary_operation_1): Use it. gcc/testsuite/ Backport from trunk r226987. 2015-08-18 Richard Sandiford <richard.sandiford@arm.com> PR rtl-optimization/67218 * gcc.c-torture/execute/ieee/pr67218.c, gcc.target/aarch64/fcvt_int_float_double1.c, gcc.target/aarch64/fcvt_int_float_double2.c, gcc.target/aarch64/fcvt_int_float_double3.c, gcc.target/aarch64/fcvt_int_float_double4.c, gcc.target/aarch64/fcvt_uint_float_double1.c, gcc.target/aarch64/fcvt_uint_float_double2.c, gcc.target/aarch64/fcvt_uint_float_double3.c, gcc.target/aarch64/fcvt_uint_float_double4.c: New tests. Change-Id: I8acc70855d5a6bfbb0df4d3fd531e5b911329914
-rw-r--r--gcc/simplify-rtx.c38
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/pr67218.c15
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double1.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double2.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double3.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double4.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double1.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double2.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double3.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double4.c11
10 files changed, 127 insertions, 10 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index a8e4b48aa25..a5f3100062c 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -847,6 +847,32 @@ simplify_unary_operation (enum rtx_code code, machine_mode mode,
return simplify_unary_operation_1 (code, mode, op);
}
+/* Return true if FLOAT or UNSIGNED_FLOAT operation OP is known
+ to be exact. */
+
+static bool
+exact_int_to_float_conversion_p (const_rtx op)
+{
+ int out_bits = significand_size (GET_MODE_INNER (GET_MODE (op)));
+ machine_mode op0_mode = GET_MODE (XEXP (op, 0));
+ /* Constants shouldn't reach here. */
+ gcc_assert (op0_mode != VOIDmode);
+ int in_prec = GET_MODE_UNIT_PRECISION (op0_mode);
+ int in_bits = in_prec;
+ if (HWI_COMPUTABLE_MODE_P (op0_mode))
+ {
+ unsigned HOST_WIDE_INT nonzero = nonzero_bits (XEXP (op, 0), op0_mode);
+ if (GET_CODE (op) == FLOAT)
+ in_bits -= num_sign_bit_copies (XEXP (op, 0), op0_mode);
+ else if (GET_CODE (op) == UNSIGNED_FLOAT)
+ in_bits = wi::min_precision (wi::uhwi (nonzero, in_prec), UNSIGNED);
+ else
+ gcc_unreachable ();
+ in_bits -= wi::ctz (wi::uhwi (nonzero, in_prec));
+ }
+ return in_bits <= out_bits;
+}
+
/* Perform some simplifications we can do even if the operands
aren't constant. */
static rtx
@@ -1211,11 +1237,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
/* (float_truncate (float x)) is (float x) */
if ((GET_CODE (op) == FLOAT || GET_CODE (op) == UNSIGNED_FLOAT)
&& (flag_unsafe_math_optimizations
- || (SCALAR_FLOAT_MODE_P (GET_MODE (op))
- && ((unsigned)significand_size (GET_MODE (op))
- >= (GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))
- - num_sign_bit_copies (XEXP (op, 0),
- GET_MODE (XEXP (op, 0))))))))
+ || exact_int_to_float_conversion_p (op)))
return simplify_gen_unary (GET_CODE (op), mode,
XEXP (op, 0),
GET_MODE (XEXP (op, 0)));
@@ -1248,11 +1270,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
*/
if (GET_CODE (op) == FLOAT_EXTEND
|| ((GET_CODE (op) == FLOAT || GET_CODE (op) == UNSIGNED_FLOAT)
- && SCALAR_FLOAT_MODE_P (GET_MODE (op))
- && ((unsigned)significand_size (GET_MODE (op))
- >= (GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))
- - num_sign_bit_copies (XEXP (op, 0),
- GET_MODE (XEXP (op, 0)))))))
+ && exact_int_to_float_conversion_p (op)))
return simplify_gen_unary (GET_CODE (op), mode,
XEXP (op, 0),
GET_MODE (XEXP (op, 0)));
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/pr67218.c b/gcc/testsuite/gcc.c-torture/execute/ieee/pr67218.c
new file mode 100644
index 00000000000..2a1260a7aa0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/pr67218.c
@@ -0,0 +1,15 @@
+extern void abort (void) __attribute__ ((noreturn));
+
+double __attribute__ ((noinline, noclone))
+foo (unsigned int x)
+{
+ return (double) (float) (x | 0xffff0000);
+}
+
+int
+main ()
+{
+ if (foo (1) != 0x1.fffep31)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double1.c b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double1.c
new file mode 100644
index 00000000000..e555b2ce2ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (int x)
+{
+ return (double) (float) (x | (int) 0xff000000);
+}
+
+/* { dg-final { scan-assembler {\tscvtf\td0, w[0-9]*} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double2.c b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double2.c
new file mode 100644
index 00000000000..7791b2213fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (int x)
+{
+ return (double) (float) (x | (int) 0xfe000000);
+}
+
+/* { dg-final { scan-assembler {\tscvtf\ts[0-9]*, w[0-9]*} } } */
+/* { dg-final { scan-assembler {\tfcvt\td0, s[0-9]*} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double3.c b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double3.c
new file mode 100644
index 00000000000..c647742637e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (int x)
+{
+ return (double) (float) ((x & -16) | (int) 0xf0000000);
+}
+
+/* { dg-final { scan-assembler {\tscvtf\td0, w[0-9]*} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double4.c b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double4.c
new file mode 100644
index 00000000000..88a5242503e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (int x)
+{
+ return (double) (float) ((x & -16) | (int) 0xfe00000);
+}
+
+/* { dg-final { scan-assembler {\tscvtf\ts[0-9]*, w[0-9]*} } } */
+/* { dg-final { scan-assembler {\tfcvt\td0, s[0-9]*} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double1.c b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double1.c
new file mode 100644
index 00000000000..c1c492093ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (unsigned int x)
+{
+ return (double) (float) (x & 0xffffff);
+}
+
+/* { dg-final { scan-assembler {\t[su]cvtf\td0, w[0-9]*} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double2.c b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double2.c
new file mode 100644
index 00000000000..334aae8035f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (unsigned int x)
+{
+ return (double) (float) (x & 0x1ffffff);
+}
+
+/* { dg-final { scan-assembler {\t[su]cvtf\ts[0-9]*, w[0-9]*} } } */
+/* { dg-final { scan-assembler {\tfcvt\td0, s[0-9]*} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double3.c b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double3.c
new file mode 100644
index 00000000000..deb45783ff8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (unsigned int x)
+{
+ return (double) (float) (x & 0xffffff00);
+}
+
+/* { dg-final { scan-assembler {\tucvtf\td0, w[0-9]*} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double4.c b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double4.c
new file mode 100644
index 00000000000..8f0955c1e3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+foo (unsigned int x)
+{
+ return (double) (float) (x & 0xffffff80);
+}
+
+/* { dg-final { scan-assembler {\tucvtf\ts[0-9]*, w[0-9]*} } } */
+/* { dg-final { scan-assembler {\tfcvt\td0, s[0-9]*} } } */