From 39647dcba53dcaa2e18984b86f5546589e92738a Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Wed, 23 Oct 1996 10:20:45 -0400 Subject: [PATCH] (exact_real_inverse): Likewise, if no REAL_ARITHMETIC. (fold, case RDIV_EXPR): Turn divide by constant into multiplication by the reciprocal, if optimizing and result is exact. From-SVN: r13004 --- gcc/fold-const.c | 111 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 5 deletions(-) diff --git a/gcc/fold-const.c b/gcc/fold-const.c index d1c25c3039a..2af2f8b2cc3 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -867,6 +867,94 @@ target_negative (x) return x < 0; } #endif /* Target not IEEE */ + +/* Try to change R into its exact multiplicative inverse in machine mode + MODE. Return nonzero function value if successful. */ + +int +exact_real_inverse (mode, r) + enum machine_mode mode; + REAL_VALUE_TYPE *r; +{ + union + { + double d; + unsigned short i[4]; + }x, t, y; + int i; + + /* Usually disable if bounds checks are not reliable. */ + if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float) + return 0; + + /* Set array index to the less significant bits in the unions, depending + on the endian-ness of the host doubles. + Disable if insufficient information on the data structure. */ +#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT + return 0; +#else +#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT +#define K 2 +#else +#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT +#define K 2 +#else +#define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN) +#endif +#endif +#endif + + if (setjmp (float_error)) + { + /* Don't do the optimization if there was an arithmetic error. */ +fail: + set_float_handler (NULL_PTR); + return 0; + } + set_float_handler (float_error); + + /* Domain check the argument. */ + x.d = *r; + if (x.d == 0.0) + goto fail; + +#ifdef REAL_INFINITY + if (REAL_VALUE_ISINF (x.d) || REAL_VALUE_ISNAN (x.d)) + goto fail; +#endif + + /* Compute the reciprocal and check for numerical exactness. + It is unnecessary to check all the significand bits to determine + whether X is a power of 2. If X is not, then it is impossible for + the bottom half significand of both X and 1/X to be all zero bits. + Hence we ignore the data structure of the top half and examine only + the low order bits of the two significands. */ + t.d = 1.0 / x.d; + if (x.i[K] != 0 || x.i[K + 1] != 0 || t.i[K] != 0 || t.i[K + 1] != 0) + goto fail; + + /* Truncate to the required mode and range-check the result. */ + y.d = REAL_VALUE_TRUNCATE (mode, t.d); +#ifdef CHECK_FLOAT_VALUE + i = 0; + if (CHECK_FLOAT_VALUE (mode, y.d, i)) + goto fail; +#endif + + /* Fail if truncation changed the value. */ + if (y.d != t.d || y.d == 0.0) + goto fail; + +#ifdef REAL_INFINITY + if (REAL_VALUE_ISINF (y.d) || REAL_VALUE_ISNAN (y.d)) + goto fail; +#endif + + /* Output the reciprocal and return success flag. */ + set_float_handler (NULL_PTR); + *r = y.d; + return 1; +} #endif /* no REAL_ARITHMETIC */ /* Split a tree IN into a constant and a variable part @@ -4343,11 +4431,24 @@ fold (expr) so only do this if -ffast-math. We can actually always safely do it if ARG1 is a power of two, but it's hard to tell if it is or not in a portable manner. */ - if (TREE_CODE (arg1) == REAL_CST && flag_fast_math - && 0 != (tem = const_binop (code, build_real (type, dconst1), - arg1, 0))) - return fold (build (MULT_EXPR, type, arg0, tem)); - + if (TREE_CODE (arg1) == REAL_CST) + { + if (flag_fast_math + && 0 != (tem = const_binop (code, build_real (type, dconst1), + arg1, 0))) + return fold (build (MULT_EXPR, type, arg0, tem)); + /* Find the reciprocal if optimizing and the result is exact. */ + else if (optimize) + { + REAL_VALUE_TYPE r; + r = TREE_REAL_CST (arg1); + if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r)) + { + tem = build_real (type, r); + return fold (build (MULT_EXPR, type, arg0, tem)); + } + } + } goto binary; case TRUNC_DIV_EXPR: -- 2.30.2