diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-05-23 03:46:53 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-05-23 03:46:53 +0000 |
commit | ac4bd9a0eed8a2ccbbaee8480dba1e3a646458cc (patch) | |
tree | 5b38df8d0da0fa5e04c432815e2f600b41d5f2e5 /gcc | |
parent | 07fea4789bd395e94460b94cceac2e1f925dd607 (diff) | |
download | gcc-ac4bd9a0eed8a2ccbbaee8480dba1e3a646458cc.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@67112 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fold-const.c | 40 | ||||
-rw-r--r-- | gcc/real.c | 27 | ||||
-rw-r--r-- | gcc/real.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c | 79 |
6 files changed, 154 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 453fea87ae4..fa4639ecacd 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 eb65795e913..6a4e2290e39 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 16cd02acb7f..4a4b04012ce 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 16113924ae5..15a5d93e444 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 c3b456ecee1..6774aeac0a6 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 00000000000..40270c0f6ab --- /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; +} + |