diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-03-28 02:41:14 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-03-28 02:41:14 +0000 |
commit | 9ddae796cd67ef5c256206a83fa47cb37ac953c2 (patch) | |
tree | b0c28630163f7f911309e25022ada80efb24b629 /gcc | |
parent | 36875565ebc10f5c19ea9303551077618d52b35f (diff) | |
download | gcc-9ddae796cd67ef5c256206a83fa47cb37ac953c2.zip gcc-9ddae796cd67ef5c256206a83fa47cb37ac953c2.tar.gz gcc-9ddae796cd67ef5c256206a83fa47cb37ac953c2.tar.bz2 |
fold-const.c (fold_inf_compare): New function to simplify FP comparisons against +Infinity or -Infinity.
* fold-const.c (fold_inf_compare): New function to simplify FP
comparisons against +Infinity or -Infinity.
(fold): Optimize floating point comparisons against Infs and NaNs.
* gcc.c-torture/execute/ieee/fp-cmp-6.c: New test case.
* gcc.c-torture/execute/ieee/fp-cmp-7.c: New test case.
From-SVN: r64945
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/fold-const.c | 107 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-6.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.c | 14 |
5 files changed, 149 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 93c1921..80acf51 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2003-03-27 Roger Sayle <roger@eyesopen.com> + + * fold-const.c (fold_inf_compare): New function to simplify FP + comparisons against +Infinity or -Infinity. + (fold): Optimize floating point comparisons against Infs and NaNs. + 2003-03-27 Janis Johnson <janis187@us.ibm.com> * libgcov.c: Provide only dummy functions if libc is not available. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0f9f3d4..6e17e00 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -114,6 +114,7 @@ static tree fold_binary_op_with_conditional_arg static bool fold_real_zero_addition_p PARAMS ((tree, tree, int)); static tree fold_mathfn_compare PARAMS ((enum built_in_function, enum tree_code, tree, tree, tree)); +static tree fold_inf_compare PARAMS ((enum tree_code, tree, tree, tree)); /* The following constants represent a bit based encoding of GCC's comparison operators. This encoding simplifies transformations @@ -4798,6 +4799,62 @@ fold_mathfn_compare (fcode, code, type, arg0, arg1) return NULL_TREE; } +/* Subroutine of fold() that optimizes comparisons against Infinities, + either +Inf or -Inf. + + CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR, + GE_EXPR or LE_EXPR. TYPE is the type of the result and ARG0 and ARG1 + are the operands of the comparison. ARG1 must be a TREE_REAL_CST. + + The function returns the constant folded tree if a simplification + can be made, and NULL_TREE otherwise. */ + +static tree +fold_inf_compare (code, type, arg0, arg1) + enum tree_code code; + tree type, arg0, arg1; +{ + /* For negative infinity swap the sense of the comparison. */ + if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))) + code = swap_tree_comparison (code); + + switch (code) + { + case GT_EXPR: + /* x > +Inf is always false, if with ignore sNANs. */ + if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))) + return NULL_TREE; + return omit_one_operand (type, + convert (type, integer_zero_node), + arg0); + + case LE_EXPR: + /* x <= +Inf is always true, if we don't case about NaNs. */ + if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))) + return omit_one_operand (type, + convert (type, integer_one_node), + arg0); + + /* x <= +Inf is the same as x == x, i.e. isfinite(x). */ + if ((*lang_hooks.decls.global_bindings_p) () == 0 + && ! contains_placeholder_p (arg0)) + { + arg0 = save_expr (arg0); + return fold (build (EQ_EXPR, type, arg0, arg0)); + } + break; + + case EQ_EXPR: /* ??? x == +Inf is x > DBL_MAX */ + case GE_EXPR: /* ??? x >= +Inf is x > DBL_MAX */ + case LT_EXPR: /* ??? x < +Inf is x <= DBL_MAX */ + case NE_EXPR: /* ??? x != +Inf is !(x > DBL_MAX) */ + + default: + break; + } + + return NULL_TREE; +} /* Perform constant folding and related simplification of EXPR. The related simplifications include x*1 => x, x*0 => 0, etc., @@ -6317,20 +6374,42 @@ fold (expr) && TREE_CODE (arg1) == NEGATE_EXPR) return fold (build (code, type, TREE_OPERAND (arg1, 0), TREE_OPERAND (arg0, 0))); - /* (-a) CMP CST -> a swap(CMP) (-CST) */ - if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST) - return - fold (build - (swap_tree_comparison (code), type, - TREE_OPERAND (arg0, 0), - build_real (TREE_TYPE (arg1), - REAL_VALUE_NEGATE (TREE_REAL_CST (arg1))))); - /* IEEE doesn't distinguish +0 and -0 in comparisons. */ - /* a CMP (-0) -> a CMP 0 */ - if (TREE_CODE (arg1) == REAL_CST - && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1))) - return fold (build (code, type, arg0, - build_real (TREE_TYPE (arg1), dconst0))); + + if (TREE_CODE (arg1) == REAL_CST) + { + REAL_VALUE_TYPE cst; + cst = TREE_REAL_CST (arg1); + + /* (-a) CMP CST -> a swap(CMP) (-CST) */ + if (TREE_CODE (arg0) == NEGATE_EXPR) + return + fold (build (swap_tree_comparison (code), type, + TREE_OPERAND (arg0, 0), + build_real (TREE_TYPE (arg1), + REAL_VALUE_NEGATE (cst)))); + + /* IEEE doesn't distinguish +0 and -0 in comparisons. */ + /* a CMP (-0) -> a CMP 0 */ + if (REAL_VALUE_MINUS_ZERO (cst)) + return fold (build (code, type, arg0, + build_real (TREE_TYPE (arg1), dconst0))); + + /* x != NaN is always true, other ops are always false. */ + if (REAL_VALUE_ISNAN (cst) + && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))) + { + t = (code == NE_EXPR) ? integer_one_node : integer_zero_node; + return omit_one_operand (type, convert (type, t), arg0); + } + + /* Fold comparisons against infinity. */ + if (REAL_VALUE_ISINF (cst)) + { + tem = fold_inf_compare (code, type, arg0, arg1); + if (tem != NULL_TREE) + return tem; + } + } /* If this is a comparison of a real constant with a PLUS_EXPR or a MINUS_EXPR of a real constant, we can convert it into a diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c438ad3..f9d63b2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-03-27 Roger Sayle <roger@eyesopen.com> + + * gcc.c-torture/execute/ieee/fp-cmp-6.c: New test case. + * gcc.c-torture/execute/ieee/fp-cmp-7.c: New test case. + 2003-03-27 Mark Mitchell <mark@codesourcery.com> * lib/gcov.exp (run-gcov): Add branches and calls options, rather diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-6.c b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-6.c new file mode 100644 index 0000000..9111d6e --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-6.c @@ -0,0 +1,31 @@ + +const double dnan = 1.0/0.0 - 1.0/0.0; +double x = 1.0; + +extern void link_error (); + +main () +{ +#if ! defined (__vax__) && ! defined (_CRAY) + /* NaN is an IEEE unordered operand. All these test should be false. */ + if (dnan == dnan) + link_error (); + if (dnan != x) + x = 1.0; + else + link_error (); + + if (dnan < x) + link_error (); + if (dnan > x) + link_error (); + if (dnan <= x) + link_error (); + if (dnan >= x) + link_error (); + if (dnan == x) + link_error (); +#endif + exit (0); +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.c b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.c new file mode 100644 index 0000000..385acaf --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.c @@ -0,0 +1,14 @@ +extern void link_error (); + +void foo(double x) +{ + if (x > __builtin_inf()) + link_error (); +} + +int main () +{ + foo (1.0); + return 0; +} + |