Message ID | alpine.DEB.2.21.1809262114210.17757@digraph.polyomino.org.uk |
---|---|
State | New |
Headers | show |
Series | Support excess precision for integer / floating-point comparisons (PR c/87390) | expand |
Hi Joseph, On Wed, 26 Sep 2018 at 23:15, Joseph Myers <joseph@codesourcery.com> wrote: > > 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. Applied to > mainline. > > gcc/c: > 2018-09-26 Joseph Myers <joseph@codesourcery.com> > > 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: > 2018-09-26 Joseph Myers <joseph@codesourcery.com> > > PR c/87390 > * gcc.target/i386/excess-precision-9.c, > gcc.target/i386/excess-precision-10.c: New tests. > After this patch I've noticed regressions on fp-int-convert-float16-timode.c gcc.dg/torture/fp-int-convert-float16.c on aarch64 and arm (at execution time) Christophe > Index: gcc/c/c-typeck.c > =================================================================== > --- gcc/c/c-typeck.c (revision 264650) > +++ gcc/c/c-typeck.c (working copy) > @@ -11249,6 +11249,20 @@ build_binary_op (location_t location, enum tree_co > 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; > Index: gcc/testsuite/gcc.target/i386/excess-precision-10.c > =================================================================== > --- gcc/testsuite/gcc.target/i386/excess-precision-10.c (nonexistent) > +++ gcc/testsuite/gcc.target/i386/excess-precision-10.c (working copy) > @@ -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); > +} > Index: gcc/testsuite/gcc.target/i386/excess-precision-9.c > =================================================================== > --- gcc/testsuite/gcc.target/i386/excess-precision-9.c (nonexistent) > +++ gcc/testsuite/gcc.target/i386/excess-precision-9.c (working copy) > @@ -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); > +} > > -- > Joseph S. Myers > joseph@codesourcery.com
On Thu, 27 Sep 2018, Christophe Lyon wrote: > After this patch I've noticed regressions on > fp-int-convert-float16-timode.c > gcc.dg/torture/fp-int-convert-float16.c > on aarch64 and arm (at execution time) Does this patch help? Index: gcc/testsuite/gcc.dg/torture/fp-int-convert.h =================================================================== --- gcc/testsuite/gcc.dg/torture/fp-int-convert.h (revision 264666) +++ gcc/testsuite/gcc.dg/torture/fp-int-convert.h (working copy) @@ -90,6 +90,7 @@ if (ivin != (VAL) \ || ((PREC_OK) && ivout != ivin) \ || ((PREC_OK) && ivout != (VAL)) \ - || fv1 != (VAL) || fv2 != (VAL) || fv1 != fv2) \ + || fv1 != (FT) (VAL) || fv2 != (FT) (VAL) \ + || fv1 != fv2) \ abort (); \ } while (0)
On Thu, 27 Sep 2018 at 21:29, Joseph Myers <joseph@codesourcery.com> wrote: > > On Thu, 27 Sep 2018, Christophe Lyon wrote: > > > After this patch I've noticed regressions on > > fp-int-convert-float16-timode.c > > gcc.dg/torture/fp-int-convert-float16.c > > on aarch64 and arm (at execution time) > > Does this patch help? > > Index: gcc/testsuite/gcc.dg/torture/fp-int-convert.h > =================================================================== > --- gcc/testsuite/gcc.dg/torture/fp-int-convert.h (revision 264666) > +++ gcc/testsuite/gcc.dg/torture/fp-int-convert.h (working copy) > @@ -90,6 +90,7 @@ > if (ivin != (VAL) \ > || ((PREC_OK) && ivout != ivin) \ > || ((PREC_OK) && ivout != (VAL)) \ > - || fv1 != (VAL) || fv2 != (VAL) || fv1 != fv2) \ > + || fv1 != (FT) (VAL) || fv2 != (FT) (VAL) \ > + || fv1 != fv2) \ > abort (); \ > } while (0) > Yes, it works, thanks! > -- > Joseph S. Myers > joseph@codesourcery.com
On Fri, 28 Sep 2018, Christophe Lyon wrote:
> Yes, it works, thanks!
Thanks, committed as r264696.
Index: gcc/c/c-typeck.c =================================================================== --- gcc/c/c-typeck.c (revision 264650) +++ gcc/c/c-typeck.c (working copy) @@ -11249,6 +11249,20 @@ build_binary_op (location_t location, enum tree_co 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; Index: gcc/testsuite/gcc.target/i386/excess-precision-10.c =================================================================== --- gcc/testsuite/gcc.target/i386/excess-precision-10.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/excess-precision-10.c (working copy) @@ -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); +} Index: gcc/testsuite/gcc.target/i386/excess-precision-9.c =================================================================== --- gcc/testsuite/gcc.target/i386/excess-precision-9.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/excess-precision-9.c (working copy) @@ -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); +}