aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-05-23 03:46:53 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-05-23 03:46:53 +0000
commit18c2511ccbc14dc2899b0fb6ec60935ac87087c2 (patch)
tree5b38df8d0da0fa5e04c432815e2f600b41d5f2e5
parenta8e097d6db75fdb7fb530bd571647a656376fe97 (diff)
downloadgcc-18c2511ccbc14dc2899b0fb6ec60935ac87087c2.zip
gcc-18c2511ccbc14dc2899b0fb6ec60935ac87087c2.tar.gz
gcc-18c2511ccbc14dc2899b0fb6ec60935ac87087c2.tar.bz2
real.c (real_maxval): New function to return the largest finite value representable in a given mode (i.e.
* real.c (real_maxval): New function to return the largest finite value representable in a given mode (i.e. FLT_MAX and DBL_MAX). * real.h (real_maxval): Prototype here. * fold-const.c (fold_inf_compare): Transform comparisons against +-Infinity into comparisons against DBL_MAX (or equivalent). * gcc.c-torture/execute/ieee/inf-2.c: New test case. From-SVN: r67112
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c40
-rw-r--r--gcc/real.c27
-rw-r--r--gcc/real.h3
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c79
6 files changed, 154 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 453fea8..fa4639e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2003-05-22 Roger Sayle <roger@eyesopen.com>
+
+ * real.c (real_maxval): New function to return the largest finite
+ value representable in a given mode (i.e. FLT_MAX and DBL_MAX).
+ * real.h (real_maxval): Prototype here.
+ * fold-const.c (fold_inf_compare): Transform comparisons against
+ +-Infinity into comparisons against DBL_MAX (or equivalent).
+
2003-05-22 Mike Stump <mrs@apple.com>
* config.gcc (*-*-darwin*): Remove use_collect2=no, as it is the
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index eb65795..6a4e229 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -4820,15 +4820,23 @@ fold_inf_compare (code, type, arg0, arg1)
enum tree_code code;
tree type, arg0, arg1;
{
+ enum machine_mode mode;
+ REAL_VALUE_TYPE max;
+ tree temp;
+ bool neg;
+
+ mode = TYPE_MODE (TREE_TYPE (arg0));
+
/* For negative infinity swap the sense of the comparison. */
- if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
+ neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1));
+ if (neg)
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))))
+ if (HONOR_SNANS (mode))
return NULL_TREE;
return omit_one_operand (type,
convert (type, integer_zero_node),
@@ -4836,7 +4844,7 @@ fold_inf_compare (code, type, arg0, arg1)
case LE_EXPR:
/* x <= +Inf is always true, if we don't case about NaNs. */
- if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ if (! HONOR_NANS (mode))
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
@@ -4850,10 +4858,28 @@ fold_inf_compare (code, type, arg0, arg1)
}
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) */
+ case EQ_EXPR:
+ case GE_EXPR:
+ /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */
+ real_maxval (&max, neg, mode);
+ return fold (build (neg ? LT_EXPR : GT_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+
+ case LT_EXPR:
+ /* x < +Inf is always equal to x <= DBL_MAX. */
+ real_maxval (&max, neg, mode);
+ return fold (build (neg ? GE_EXPR : LE_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+
+ case NE_EXPR:
+ /* x != +Inf is always equal to !(x > DBL_MAX). */
+ real_maxval (&max, neg, mode);
+ if (! HONOR_NANS (mode))
+ return fold (build (neg ? GE_EXPR : LE_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+ temp = fold (build (neg ? LT_EXPR : GT_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+ return fold (build1 (TRUTH_NOT_EXPR, type, temp));
default:
break;
diff --git a/gcc/real.c b/gcc/real.c
index 16cd02a..4a4b040 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -2280,6 +2280,33 @@ real_nan (r, str, quiet, mode)
return true;
}
+/* Fills R with the largest finite value representable in mode MODE.
+ If SIGN is non-zero, R is set to the most negative finite value. */
+
+void
+real_maxval (r, sign, mode)
+ REAL_VALUE_TYPE *r;
+ int sign;
+ enum machine_mode mode;
+{
+ const struct real_format *fmt;
+ int np2;
+
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
+
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->signalling = 0;
+ r->canonical = 0;
+ r->exp = fmt->emax * fmt->log2_b;
+
+ np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
+ memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
+ clear_significand_below (r, np2);
+}
+
/* Fills R with 2**N. */
void
diff --git a/gcc/real.h b/gcc/real.h
index 1611392..15a5d93 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -219,6 +219,9 @@ extern void real_inf PARAMS ((REAL_VALUE_TYPE *));
extern bool real_nan PARAMS ((REAL_VALUE_TYPE *, const char *,
int, enum machine_mode));
+extern void real_maxval PARAMS ((REAL_VALUE_TYPE *, int,
+ enum machine_mode));
+
extern void real_2expN PARAMS ((REAL_VALUE_TYPE *, int));
extern unsigned int real_hash PARAMS ((const REAL_VALUE_TYPE *));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c3b456e..6774aea 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-05-22 Roger Sayle <roger@eyesopen.com>
+
+ * gcc.c-torture/execute/ieee/inf-2.c: New test case.
+
2003-05-21 Janis Johnson <janis187@us.ibm.com>
* gcc.dg/compat/scalar-return-1_main.c: New file.
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c b/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c
new file mode 100644
index 0000000..40270c0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c
@@ -0,0 +1,79 @@
+extern void abort (void);
+
+void test(double f, double i)
+{
+ if (f == __builtin_inf())
+ abort ();
+ if (f == -__builtin_inf())
+ abort ();
+ if (i == -__builtin_inf())
+ abort ();
+ if (i != __builtin_inf())
+ abort ();
+
+ if (f >= __builtin_inf())
+ abort ();
+ if (f > __builtin_inf())
+ abort ();
+ if (i > __builtin_inf())
+ abort ();
+ if (f <= -__builtin_inf())
+ abort ();
+ if (f < -__builtin_inf())
+ abort ();
+}
+
+void testf(float f, float i)
+{
+ if (f == __builtin_inff())
+ abort ();
+ if (f == -__builtin_inff())
+ abort ();
+ if (i == -__builtin_inff())
+ abort ();
+ if (i != __builtin_inff())
+ abort ();
+
+ if (f >= __builtin_inff())
+ abort ();
+ if (f > __builtin_inff())
+ abort ();
+ if (i > __builtin_inff())
+ abort ();
+ if (f <= -__builtin_inff())
+ abort ();
+ if (f < -__builtin_inff())
+ abort ();
+}
+
+void testl(long double f, long double i)
+{
+ if (f == __builtin_infl())
+ abort ();
+ if (f == -__builtin_infl())
+ abort ();
+ if (i == -__builtin_infl())
+ abort ();
+ if (i != __builtin_infl())
+ abort ();
+
+ if (f >= __builtin_infl())
+ abort ();
+ if (f > __builtin_infl())
+ abort ();
+ if (i > __builtin_infl())
+ abort ();
+ if (f <= -__builtin_infl())
+ abort ();
+ if (f < -__builtin_infl())
+ abort ();
+}
+
+int main()
+{
+ test (34.0, __builtin_inf());
+ testf (34.0f, __builtin_inff());
+ testf (34.0l, __builtin_infl());
+ return 0;
+}
+