diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2015-08-18 19:04:41 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2015-08-18 19:04:41 +0000 |
commit | a1c045caab2c1b31ce7b8e9c28ccd9f8106c4e58 (patch) | |
tree | f459282bbf47a1c01f68bd41fd20bb0ca6c6e953 /gcc | |
parent | f641b2d6bbe4702f1374d12c773d1f2027040524 (diff) | |
download | gcc-a1c045caab2c1b31ce7b8e9c28ccd9f8106c4e58.zip gcc-a1c045caab2c1b31ce7b8e9c28ccd9f8106c4e58.tar.gz gcc-a1c045caab2c1b31ce7b8e9c28ccd9f8106c4e58.tar.bz2 |
re PR rtl-optimization/67218 (Combine incorrectly folds (double) (float) (unsigned))
gcc/
PR rtl-optimization/67218
* simplify-rtx.c (exact_int_to_float_conversion_p): New function.
(simplify_unary_operation_1): Use it.
gcc/testsuite/
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.
From-SVN: r226987
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/ieee/pr67218.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double1.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double2.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double3.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_int_float_double4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double1.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double2.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double3.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/fcvt_uint_float_double4.c | 11 |
12 files changed, 146 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 90b7893..bd0435e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +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. + 2015-08-18 Marek Polacek <polacek@redhat.com> PR middle-end/67222 diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index f9352a1..8d86e57 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -829,6 +829,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 @@ -1190,11 +1216,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))); @@ -1227,11 +1249,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/ChangeLog b/gcc/testsuite/ChangeLog index 7cb29d3..af91c7d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +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. + 2015-08-18 Matthew Wahab <matthew.wahab@arm.com> * gcc.target/aarch64/atomic-comp-swap-release-acquire.c: Adjust 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 0000000..2a1260a --- /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 0000000..e555b2c --- /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 0000000..7791b22 --- /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 0000000..c647742 --- /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 0000000..88a5242 --- /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 0000000..c1c4920 --- /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 0000000..334aae8 --- /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 0000000..deb4578 --- /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 0000000..8f0955c --- /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]*} } } */ |