From 8313a7643a2cf5f0037e08f4e6a6d7002aeef8a0 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Wed, 26 Sep 2018 22:14:16 +0100 Subject: [PATCH] Support excess precision for integer / floating-point comparisons (PR c/87390). In C11, implicit conversions from integer to floating-point types produce results with the range and precision of the corresponding evaluation format rather than only those of the type implicitly converted to. This patch implements that case of C11 excess precision semantics in the case of a comparison between integer and floating-point types, previously missed when implementing other cases of excess precision for such implicit conversions. As with other such fixes, this patch conservatively follows the reading of C99 where conversions from integer to floating-point do not produce results with excess precision and so the change is made for C11 mode only. Bootstrapped with no regressions on x86_64-pc-linux-gnu. gcc/c: PR c/87390 * c-typeck.c (build_binary_op): Use excess precision for comparisons of integers and floating-point for C11 and later. gcc/testsuite: PR c/87390 * gcc.target/i386/excess-precision-9.c, gcc.target/i386/excess-precision-10.c: New tests. From-SVN: r264656 --- gcc/c/ChangeLog | 6 +++ gcc/c/c-typeck.c | 14 +++++ gcc/testsuite/ChangeLog | 6 +++ .../gcc.target/i386/excess-precision-10.c | 52 +++++++++++++++++++ .../gcc.target/i386/excess-precision-9.c | 52 +++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/excess-precision-10.c create mode 100644 gcc/testsuite/gcc.target/i386/excess-precision-9.c diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 1ea87b95a52..a8e235c9f9b 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2018-09-26 Joseph Myers + + PR c/87390 + * c-typeck.c (build_binary_op): Use excess precision for + comparisons of integers and floating-point for C11 and later. + 2018-09-26 Martin Jambor PR c/87347 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index a5a7da0084c..9d09b8d65fd 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -11249,6 +11249,20 @@ build_binary_op (location_t location, enum tree_code code, case EXACT_DIV_EXPR: may_need_excess_precision = true; break; + + case EQ_EXPR: + case NE_EXPR: + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + /* Excess precision for implicit conversions of integers to + floating point in C11 and later. */ + may_need_excess_precision = (flag_isoc11 + && (ANY_INTEGRAL_TYPE_P (type0) + || ANY_INTEGRAL_TYPE_P (type1))); + break; + default: may_need_excess_precision = false; break; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aa005e71441..16407e5244c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-09-26 Joseph Myers + + PR c/87390 + * gcc.target/i386/excess-precision-9.c, + gcc.target/i386/excess-precision-10.c: New tests. + 2018-09-26 Richard Biener PR debug/87443 diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-10.c b/gcc/testsuite/gcc.target/i386/excess-precision-10.c new file mode 100644 index 00000000000..f1b9b7e1980 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/excess-precision-10.c @@ -0,0 +1,52 @@ +/* Excess precision tests. Test implicit conversions in comparisons: + excess precision in C11 mode. */ +/* { dg-do run } */ +/* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */ + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + float f = 0x1p63f; + unsigned long long int u = (1ULL << 63) + 1; + + if ((f == u) != 0) + abort (); + + if ((u == f) != 0) + abort (); + + if ((f != u) != 1) + abort (); + + if ((u != f) != 1) + abort (); + + if ((f < u) != 1) + abort (); + + if ((u < f) != 0) + abort (); + + if ((f <= u) != 1) + abort (); + + if ((u <= f) != 0) + abort (); + + if ((f > u) != 0) + abort (); + + if ((u > f) != 1) + abort (); + + if ((f >= u) != 0) + abort (); + + if ((u >= f) != 1) + abort (); + + exit (0); +} diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-9.c b/gcc/testsuite/gcc.target/i386/excess-precision-9.c new file mode 100644 index 00000000000..61e5fc104ad --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/excess-precision-9.c @@ -0,0 +1,52 @@ +/* Excess precision tests. Test implicit conversions in comparisons: + no excess precision in C99 mode. */ +/* { dg-do run } */ +/* { dg-options "-std=c99 -mfpmath=387 -fexcess-precision=standard" } */ + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + float f = 0x1p63f; + unsigned long long int u = (1ULL << 63) + 1; + + if ((f == u) != 1) + abort (); + + if ((u == f) != 1) + abort (); + + if ((f != u) != 0) + abort (); + + if ((u != f) != 0) + abort (); + + if ((f < u) != 0) + abort (); + + if ((u < f) != 0) + abort (); + + if ((f <= u) != 1) + abort (); + + if ((u <= f) != 1) + abort (); + + if ((f > u) != 0) + abort (); + + if ((u > f) != 0) + abort (); + + if ((f >= u) != 1) + abort (); + + if ((u >= f) != 1) + abort (); + + exit (0); +} -- 2.30.2