From ee8db92b391a602cb93f4ba227b152bcf81cb054 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Sat, 19 Jun 2004 00:17:33 +0000 Subject: [PATCH] fold-const.c (fold): Add constant folding for unordered comparison tree nodes. * fold-const.c (fold) : Add constant folding for unordered comparison tree nodes. If both operands are real constants, call fold_relational_const. If either operand is a NaN, evaluate the other for side-effects and return a constant. Optimize (double)float1 CMP (double)float2 into the equivalent float1 CMP float2. (nondestructive_fold_binary_to_constant) : Call fold_relational_const for constant operands. (fold_relational_const): Add support for unordered comparison tree nodes. Don't constant fold "ordered" floating point comparisons against NaN if when flag_trapping_math is set. * gcc.dg/unordered-2.c: New test case. * gcc.dg/unordered-3.c: New test case. From-SVN: r83379 --- gcc/ChangeLog | 16 +++ gcc/fold-const.c | 155 ++++++++++++++++++++++++++--- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/unordered-2.c | 51 ++++++++++ gcc/testsuite/gcc.dg/unordered-3.c | 79 +++++++++++++++ 5 files changed, 292 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/unordered-2.c create mode 100644 gcc/testsuite/gcc.dg/unordered-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 069c48e0f9b..7694596d8b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2004-06-18 Roger Sayle + + * fold-const.c (fold) : Add + constant folding for unordered comparison tree nodes. If both + operands are real constants, call fold_relational_const. If either + operand is a NaN, evaluate the other for side-effects and return a + constant. Optimize (double)float1 CMP (double)float2 into the + equivalent float1 CMP float2. + (nondestructive_fold_binary_to_constant) : Call fold_relational_const for constant operands. + (fold_relational_const): Add support for unordered comparison tree + nodes. Don't constant fold "ordered" floating point comparisons + against NaN if when flag_trapping_math is set. + 2004-06-19 Jakub Jelinek * fold-const.c (build_range_check): If !in_p and recursive call diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 00fd1346e2c..5266b000bee 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8252,6 +8252,59 @@ fold (tree expr) t1 = fold_relational_const (code, type, arg0, arg1); return (t1 == NULL_TREE ? t : t1); + case UNORDERED_EXPR: + case ORDERED_EXPR: + case UNLT_EXPR: + case UNLE_EXPR: + case UNGT_EXPR: + case UNGE_EXPR: + case UNEQ_EXPR: + case LTGT_EXPR: + if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST) + { + t1 = fold_relational_const (code, type, arg0, arg1); + if (t1 != NULL_TREE) + return t1; + } + + /* If the first operand is NaN, the result is constant. */ + if (TREE_CODE (arg0) == REAL_CST + && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0)) + && (code != LTGT_EXPR || ! flag_trapping_math)) + { + t1 = (code == ORDERED_EXPR || code == LTGT_EXPR) + ? integer_zero_node + : integer_one_node; + return omit_one_operand (type, t1, arg1); + } + + /* If the second operand is NaN, the result is constant. */ + if (TREE_CODE (arg1) == REAL_CST + && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)) + && (code != LTGT_EXPR || ! flag_trapping_math)) + { + t1 = (code == ORDERED_EXPR || code == LTGT_EXPR) + ? integer_zero_node + : integer_one_node; + return omit_one_operand (type, t1, arg0); + } + + /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */ + { + tree targ0 = strip_float_extensions (arg0); + tree targ1 = strip_float_extensions (arg1); + tree newtype = TREE_TYPE (targ0); + + if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (targ1); + + if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0))) + return fold (build2 (code, type, fold_convert (newtype, targ0), + fold_convert (newtype, targ1))); + } + + return t; + case COND_EXPR: /* Pedantic ANSI C says that a conditional expression is never an lvalue, so all simple results must be passed through pedantic_non_lvalue. */ @@ -9770,6 +9823,16 @@ nondestructive_fold_binary_to_constant (enum tree_code code, tree type, if (tem) return tem; + /* Fall through. */ + + case ORDERED_EXPR: + case UNORDERED_EXPR: + case UNLT_EXPR: + case UNLE_EXPR: + case UNGT_EXPR: + case UNGE_EXPR: + case UNEQ_EXPR: + case LTGT_EXPR: if (!wins) return NULL_TREE; @@ -10075,7 +10138,82 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) int result, invert; /* From here on, the only cases we handle are when the result is - known to be a constant. + known to be a constant. */ + + if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST) + { + /* Handle the cases where either operand is a NaN. */ + if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0)) + || REAL_VALUE_ISNAN (TREE_REAL_CST (op1))) + { + switch (code) + { + case EQ_EXPR: + case ORDERED_EXPR: + result = 0; + break; + + case NE_EXPR: + case UNORDERED_EXPR: + case UNLT_EXPR: + case UNLE_EXPR: + case UNGT_EXPR: + case UNGE_EXPR: + case UNEQ_EXPR: + result = 1; + break; + + case LT_EXPR: + case LE_EXPR: + case GT_EXPR: + case GE_EXPR: + case LTGT_EXPR: + if (flag_trapping_math) + return NULL_TREE; + result = 0; + break; + + default: + abort (); + } + + return constant_boolean_node (result, type); + } + + /* From here on we're sure there are no NaNs. */ + switch (code) + { + case ORDERED_EXPR: + return constant_boolean_node (true, type); + + case UNORDERED_EXPR: + return constant_boolean_node (false, type); + + case UNLT_EXPR: + code = LT_EXPR; + break; + case UNLE_EXPR: + code = LE_EXPR; + break; + case UNGT_EXPR: + code = GT_EXPR; + break; + case UNGE_EXPR: + code = GE_EXPR; + break; + case UNEQ_EXPR: + code = EQ_EXPR; + break; + case LTGT_EXPR: + code = NE_EXPR; + break; + + default: + break; + } + } + + /* From here on we only handle LT, LE, GT, GE, EQ and NE. To compute GT, swap the arguments and do LT. To compute GE, do LT and invert the result. @@ -10093,7 +10231,7 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) } /* Note that it is safe to invert for real values here because we - will check below in the one case that it matters. */ + have already handled the one case that it matters. */ invert = 0; if (code == NE_EXPR || code == GE_EXPR) @@ -10121,18 +10259,7 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) /* Two real constants can be compared explicitly. */ else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST) { - /* If either operand is a NaN, the result is false with two - exceptions: First, an NE_EXPR is true on NaNs, but that case - is already handled correctly since we will be inverting the - result for NE_EXPR. Second, if we had inverted a LE_EXPR - or a GE_EXPR into a LT_EXPR, we must return true so that it - will be inverted into false. */ - - if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0)) - || REAL_VALUE_ISNAN (TREE_REAL_CST (op1))) - result = invert && code == LT_EXPR; - - else if (code == EQ_EXPR) + if (code == EQ_EXPR) result = REAL_VALUES_EQUAL (TREE_REAL_CST (op0), TREE_REAL_CST (op1)); else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 856b789fe6c..362d4f92e14 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-06-18 Roger Sayle + + * gcc.dg/unordered-2.c: New test case. + * gcc.dg/unordered-3.c: New test case. + 2004-06-19 David Billinghurst (David.Billinghurst@riotinto.com) PR other/16043 diff --git a/gcc/testsuite/gcc.dg/unordered-2.c b/gcc/testsuite/gcc.dg/unordered-2.c new file mode 100644 index 00000000000..0696d37cfb4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/unordered-2.c @@ -0,0 +1,51 @@ +/* { dg-do link } */ + +void link_error (); + +int main() +{ + if (__builtin_isgreater(1.0,2.0) != 0) + link_error (); + if (__builtin_isgreater(3.0,3.0) != 0) + link_error (); + if (__builtin_isgreater(5.0,4.0) == 0) + link_error (); + + if (__builtin_isgreaterequal(1.0,2.0) != 0) + link_error (); + if (__builtin_isgreaterequal(3.0,3.0) == 0) + link_error (); + if (__builtin_isgreaterequal(5.0,4.0) == 0) + link_error (); + + if (__builtin_isless(1.0,2.0) == 0) + link_error (); + if (__builtin_isless(3.0,3.0) != 0) + link_error (); + if (__builtin_isless(5.0,4.0) != 0) + link_error (); + + if (__builtin_islessequal(1.0,2.0) == 0) + link_error (); + if (__builtin_islessequal(3.0,3.0) == 0) + link_error (); + if (__builtin_islessequal(5.0,4.0) != 0) + link_error (); + + if (__builtin_islessgreater(1.0,2.0) == 0) + link_error (); + if (__builtin_islessgreater(3.0,3.0) != 0) + link_error (); + if (__builtin_islessgreater(5.0,4.0) == 0) + link_error (); + + if (__builtin_isunordered(1.0,2.0) != 0) + link_error (); + if (__builtin_isunordered(3.0,3.0) != 0) + link_error (); + if (__builtin_isunordered(5.0,4.0) != 0) + link_error (); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/unordered-3.c b/gcc/testsuite/gcc.dg/unordered-3.c new file mode 100644 index 00000000000..4a11a6d48d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/unordered-3.c @@ -0,0 +1,79 @@ +/* { dg-do link } */ + +void link_error (); + +void test1() +{ + if (__builtin_isgreater(1.0,__builtin_nan("")) != 0) + link_error (); + if (__builtin_isgreater(__builtin_nan(""),1.0) != 0) + link_error (); + + if (__builtin_isgreaterequal(1.0,__builtin_nan("")) != 0) + link_error (); + if (__builtin_isgreaterequal(__builtin_nan(""),1.0) != 0) + link_error (); + + if (__builtin_isless(1.0,__builtin_nan("")) != 0) + link_error (); + if (__builtin_isless(__builtin_nan(""),1.0) != 0) + link_error (); + + if (__builtin_islessequal(1.0,__builtin_nan("")) != 0) + link_error (); + if (__builtin_islessequal(__builtin_nan(""),1.0) != 0) + link_error (); + + if (__builtin_islessgreater(1.0,__builtin_nan("")) != 0) + link_error (); + if (__builtin_islessgreater(__builtin_nan(""),1.0) != 0) + link_error (); + + if (__builtin_isunordered(1.0,__builtin_nan("")) == 0) + link_error (); + if (__builtin_isunordered(__builtin_nan(""),1.0) == 0) + link_error (); +} + + +void test2(double x) +{ + if (__builtin_isgreater(x,__builtin_nan("")) != 0) + link_error (); + if (__builtin_isgreater(__builtin_nan(""),x) != 0) + link_error (); + + if (__builtin_isgreaterequal(x,__builtin_nan("")) != 0) + link_error (); + if (__builtin_isgreaterequal(__builtin_nan(""),x) != 0) + link_error (); + + if (__builtin_isless(x,__builtin_nan("")) != 0) + link_error (); + if (__builtin_isless(__builtin_nan(""),x) != 0) + link_error (); + + if (__builtin_islessequal(x,__builtin_nan("")) != 0) + link_error (); + if (__builtin_islessequal(__builtin_nan(""),x) != 0) + link_error (); + + if (__builtin_islessgreater(x,__builtin_nan("")) != 0) + link_error (); + if (__builtin_islessgreater(__builtin_nan(""),x) != 0) + link_error (); + + if (__builtin_isunordered(x,__builtin_nan("")) == 0) + link_error (); + if (__builtin_isunordered(__builtin_nan(""),x) == 0) + link_error (); +} + + +int main() +{ + test1 (); + test2 (1.0); + return 0; +} + -- 2.30.2