+2004-06-18 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (fold) <UNORDERED_EXPR, ORDERED_EXPR, UNLT_EXPR,
+ UNLE_EXPR, UNGT_EXPR, UNGE_EXPR, UNEQ_EXPR, LTGT_EXPR>: 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) <UNORDERED_EXPR,
+ ORDERED_EXPR, UNLT_EXPR, UNLE_EXPR, UNGT_EXPR, UNGE_EXPR, UNEQ_EXPR,
+ LTGT_EXPR>: 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 <jakub@redhat.com>
* fold-const.c (build_range_check): If !in_p and recursive call
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. */
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;
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.
}
/* 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)
/* 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
+2004-06-18 Roger Sayle <roger@eyesopen.com>
+
+ * 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
--- /dev/null
+/* { 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;
+}
+
--- /dev/null
+/* { 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;
+}
+