mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-10 14:27:26 +08:00
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
This commit is contained in:
parent
36875565eb
commit
9ddae796cd
@ -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.
|
||||
|
107
gcc/fold-const.c
107
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
|
||||
|
@ -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
|
||||
|
31
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-6.c
Normal file
31
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-6.c
Normal file
@ -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);
|
||||
}
|
||||
|
14
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.c
Normal file
14
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.c
Normal file
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user