[PATCH] Fold comparisons against Inf and NaN
Roger Sayle
roger@www.eyesopen.com
Thu Mar 27 06:10:00 GMT 2003
The following patch performs constant folding of comparisons against
+Inf, -Inf and NaN.
This patch has been tested on i686-pc-linux-gnu by a full bootstrap,
all languages except Ada and treelang, and regression tested with a
top-level "make -k check" with no new failures [except for libjava
due to timeouts].
Ok for mainline?
2003-03-26 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.
* gcc.c-torture/execute/ieee/fp-cmp-6.c: New test case.
* gcc.c-torture/execute/ieee/fp-cmp-7.c: New test case.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.241
diff -c -3 -p -r1.241 fold-const.c
*** fold-const.c 21 Mar 2003 00:03:24 -0000 1.241
--- fold-const.c 26 Mar 2003 16:59:47 -0000
*************** static tree fold_binary_op_with_conditio
*** 114,119 ****
--- 114,120 ----
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
*************** fold_mathfn_compare (fcode, code, type,
*** 4793,4798 ****
--- 4794,4855 ----
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.,
*************** fold (expr)
*** 6312,6331 ****
&& 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 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
--- 6369,6410 ----
&& TREE_CODE (arg1) == NEGATE_EXPR)
return fold (build (code, type, TREE_OPERAND (arg1, 0),
TREE_OPERAND (arg0, 0)));
!
! 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
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);
}
extern void link_error ();
void foo(double x)
{
if (x > __builtin_inf())
link_error ();
}
int main ()
{
foo (1.0);
return 0;
}
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833
More information about the Gcc-patches
mailing list