Message ID | Y5C2HQOXFT+RTCId@tucnak |
---|---|
State | New |
Headers | show |
Series | range-op-float, v2: Fix up frange_arithmetic [PR107967] | expand |
OK, thanks. Aldy On 12/7/22 16:49, Jakub Jelinek wrote: > On Wed, Dec 07, 2022 at 04:26:14PM +0100, Aldy Hernandez wrote: >> This chunk... >> >> ...is quite similar to this one. Could you abstract this? > > It differs in various small details, plus comment content. > Anyway, here it is reworked such that those various small details > are based on whether inf is negative or positive in a single piece > of code. > Is this ok if it passes bootstrap/regtest? > > 2022-12-07 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/107967 > * range-op-float.cc (frange_arithmetic): Fix a thinko - if > inf is negative, use nextafter if !real_less (&result, &value) > rather than if real_less (&result, &value). If result is +-INF > while value is finite and -fno-rounding-math, don't do rounding > if !inexact or if result is significantly above max representable > value or below min representable value. > > * gcc.dg/pr107967-1.c: New test. > * gcc.dg/pr107967-2.c: New test. > * gcc.dg/pr107967-3.c: New test. > > --- gcc/range-op-float.cc.jj 2022-12-07 16:37:05.285143250 +0100 > +++ gcc/range-op-float.cc 2022-12-07 16:41:58.500928517 +0100 > @@ -287,9 +287,42 @@ frange_arithmetic (enum tree_code code, > > // Be extra careful if there may be discrepancies between the > // compile and runtime results. > - if ((mode_composite || (real_isneg (&inf) ? real_less (&result, &value) > - : !real_less (&value, &result))) > - && (inexact || !real_identical (&result, &value))) > + bool round = false; > + if (mode_composite) > + round = true; > + else > + { > + bool low = real_isneg (&inf); > + round = (low ? !real_less (&result, &value) > + : !real_less (&value, &result)); > + if (real_isinf (&result, !low) > + && !real_isinf (&value) > + && !flag_rounding_math) > + { > + // Use just [+INF, +INF] rather than [MAX, +INF] > + // even if value is larger than MAX and rounds to > + // nearest to +INF. Similarly just [-INF, -INF] > + // rather than [-INF, +MAX] even if value is smaller > + // than -MAX and rounds to nearest to -INF. > + // Unless INEXACT is true, in that case we need some > + // extra buffer. > + if (!inexact) > + round = false; > + else > + { > + REAL_VALUE_TYPE tmp = result, tmp2; > + frange_nextafter (mode, tmp, inf); > + // TMP is at this point the maximum representable > + // number. > + real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp); > + if (real_isneg (&tmp2) != low > + && (REAL_EXP (&tmp2) - REAL_EXP (&tmp) > + >= 2 - REAL_MODE_FORMAT (mode)->p)) > + round = false; > + } > + } > + } > + if (round && (inexact || !real_identical (&result, &value))) > { > if (mode_composite) > { > --- gcc/testsuite/gcc.dg/pr107967-1.c.jj 2022-12-07 16:38:07.519248686 +0100 > +++ gcc/testsuite/gcc.dg/pr107967-1.c 2022-12-07 16:38:07.519248686 +0100 > @@ -0,0 +1,35 @@ > +/* PR tree-optimization/107967 */ > +/* { dg-do compile { target float64 } } */ > +/* { dg-options "-O2 -frounding-math -fno-trapping-math -fdump-tree-optimized" } */ > +/* { dg-add-options float64 } */ > +/* { dg-final { scan-tree-dump-not "return\[ \t]\*-?Inf;" "optimized" } } */ > + > +_Float64 > +foo (void) > +{ > + const _Float64 huge = 1.0e+300f64; > + return huge * huge; > +} > + > +_Float64 > +bar (void) > +{ > + const _Float64 huge = 1.0e+300f64; > + return huge * -huge; > +} > + > +_Float64 > +baz (void) > +{ > + const _Float64 a = 0x1.fffffffffffffp+1023f64; > + const _Float64 b = 0x1.fffffffffffffp+970f64; > + return a + b; > +} > + > +_Float64 > +qux (void) > +{ > + const _Float64 a = 0x1.fffffffffffffp+1023f64; > + const _Float64 b = 0x1.fffffffffffffp+969f64; > + return a + b; > +} > --- gcc/testsuite/gcc.dg/pr107967-2.c.jj 2022-12-07 16:38:07.519248686 +0100 > +++ gcc/testsuite/gcc.dg/pr107967-2.c 2022-12-07 16:38:07.519248686 +0100 > @@ -0,0 +1,35 @@ > +/* PR tree-optimization/107967 */ > +/* { dg-do compile { target float64 } } */ > +/* { dg-options "-O2 -fno-rounding-math -fno-trapping-math -fdump-tree-optimized" } */ > +/* { dg-add-options float64 } */ > +/* { dg-final { scan-tree-dump-times "return\[ \t]\*-?Inf;" 3 "optimized" } } */ > + > +_Float64 > +foo (void) > +{ > + const _Float64 huge = 1.0e+300f64; > + return huge * huge; > +} > + > +_Float64 > +bar (void) > +{ > + const _Float64 huge = 1.0e+300f64; > + return huge * -huge; > +} > + > +_Float64 > +baz (void) > +{ > + const _Float64 a = 0x1.fffffffffffffp+1023f64; > + const _Float64 b = 0x1.fffffffffffffp+970f64; > + return a + b; > +} > + > +_Float64 > +qux (void) > +{ > + const _Float64 a = 0x1.fffffffffffffp+1023f64; > + const _Float64 b = 0x1.fffffffffffffp+969f64; > + return a + b; > +} > --- gcc/testsuite/gcc.dg/pr107967-3.c.jj 2022-12-07 16:38:07.519248686 +0100 > +++ gcc/testsuite/gcc.dg/pr107967-3.c 2022-12-07 16:38:07.519248686 +0100 > @@ -0,0 +1,53 @@ > +/* PR tree-optimization/107967 */ > +/* { dg-do compile { target float64 } } */ > +/* { dg-options "-O2 -fno-rounding-math -fno-trapping-math -fdump-tree-optimized" } */ > +/* { dg-add-options float64 } */ > +/* { dg-final { scan-tree-dump-times "return\[ \t]\*-?Inf;" 3 "optimized" } } */ > + > +_Float64 > +foo (_Float64 x) > +{ > + if (x >= 1.0e+300f64) > + ; > + else > + __builtin_unreachable (); > + return x * x; > +} > + > +_Float64 > +bar (_Float64 x) > +{ > + if (x >= 1.0e+300f64) > + ; > + else > + __builtin_unreachable (); > + return x * -x; > +} > + > +_Float64 > +baz (_Float64 a, _Float64 b) > +{ > + if (a >= 0x1.fffffffffffffp+1023f64) > + ; > + else > + __builtin_unreachable (); > + if (b >= 0x1.p+972f64) > + ; > + else > + __builtin_unreachable (); > + return a + b; > +} > + > +_Float64 > +qux (_Float64 a, _Float64 b) > +{ > + if (a >= 0x1.fffffffffffffp+1023f64) > + ; > + else > + __builtin_unreachable (); > + if (b >= 0x1.fffffffffffffp+969f64) > + ; > + else > + __builtin_unreachable (); > + return a + b; > +} > > > Jakub >
--- gcc/range-op-float.cc.jj 2022-12-07 16:37:05.285143250 +0100 +++ gcc/range-op-float.cc 2022-12-07 16:41:58.500928517 +0100 @@ -287,9 +287,42 @@ frange_arithmetic (enum tree_code code, // Be extra careful if there may be discrepancies between the // compile and runtime results. - if ((mode_composite || (real_isneg (&inf) ? real_less (&result, &value) - : !real_less (&value, &result))) - && (inexact || !real_identical (&result, &value))) + bool round = false; + if (mode_composite) + round = true; + else + { + bool low = real_isneg (&inf); + round = (low ? !real_less (&result, &value) + : !real_less (&value, &result)); + if (real_isinf (&result, !low) + && !real_isinf (&value) + && !flag_rounding_math) + { + // Use just [+INF, +INF] rather than [MAX, +INF] + // even if value is larger than MAX and rounds to + // nearest to +INF. Similarly just [-INF, -INF] + // rather than [-INF, +MAX] even if value is smaller + // than -MAX and rounds to nearest to -INF. + // Unless INEXACT is true, in that case we need some + // extra buffer. + if (!inexact) + round = false; + else + { + REAL_VALUE_TYPE tmp = result, tmp2; + frange_nextafter (mode, tmp, inf); + // TMP is at this point the maximum representable + // number. + real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp); + if (real_isneg (&tmp2) != low + && (REAL_EXP (&tmp2) - REAL_EXP (&tmp) + >= 2 - REAL_MODE_FORMAT (mode)->p)) + round = false; + } + } + } + if (round && (inexact || !real_identical (&result, &value))) { if (mode_composite) { --- gcc/testsuite/gcc.dg/pr107967-1.c.jj 2022-12-07 16:38:07.519248686 +0100 +++ gcc/testsuite/gcc.dg/pr107967-1.c 2022-12-07 16:38:07.519248686 +0100 @@ -0,0 +1,35 @@ +/* PR tree-optimization/107967 */ +/* { dg-do compile { target float64 } } */ +/* { dg-options "-O2 -frounding-math -fno-trapping-math -fdump-tree-optimized" } */ +/* { dg-add-options float64 } */ +/* { dg-final { scan-tree-dump-not "return\[ \t]\*-?Inf;" "optimized" } } */ + +_Float64 +foo (void) +{ + const _Float64 huge = 1.0e+300f64; + return huge * huge; +} + +_Float64 +bar (void) +{ + const _Float64 huge = 1.0e+300f64; + return huge * -huge; +} + +_Float64 +baz (void) +{ + const _Float64 a = 0x1.fffffffffffffp+1023f64; + const _Float64 b = 0x1.fffffffffffffp+970f64; + return a + b; +} + +_Float64 +qux (void) +{ + const _Float64 a = 0x1.fffffffffffffp+1023f64; + const _Float64 b = 0x1.fffffffffffffp+969f64; + return a + b; +} --- gcc/testsuite/gcc.dg/pr107967-2.c.jj 2022-12-07 16:38:07.519248686 +0100 +++ gcc/testsuite/gcc.dg/pr107967-2.c 2022-12-07 16:38:07.519248686 +0100 @@ -0,0 +1,35 @@ +/* PR tree-optimization/107967 */ +/* { dg-do compile { target float64 } } */ +/* { dg-options "-O2 -fno-rounding-math -fno-trapping-math -fdump-tree-optimized" } */ +/* { dg-add-options float64 } */ +/* { dg-final { scan-tree-dump-times "return\[ \t]\*-?Inf;" 3 "optimized" } } */ + +_Float64 +foo (void) +{ + const _Float64 huge = 1.0e+300f64; + return huge * huge; +} + +_Float64 +bar (void) +{ + const _Float64 huge = 1.0e+300f64; + return huge * -huge; +} + +_Float64 +baz (void) +{ + const _Float64 a = 0x1.fffffffffffffp+1023f64; + const _Float64 b = 0x1.fffffffffffffp+970f64; + return a + b; +} + +_Float64 +qux (void) +{ + const _Float64 a = 0x1.fffffffffffffp+1023f64; + const _Float64 b = 0x1.fffffffffffffp+969f64; + return a + b; +} --- gcc/testsuite/gcc.dg/pr107967-3.c.jj 2022-12-07 16:38:07.519248686 +0100 +++ gcc/testsuite/gcc.dg/pr107967-3.c 2022-12-07 16:38:07.519248686 +0100 @@ -0,0 +1,53 @@ +/* PR tree-optimization/107967 */ +/* { dg-do compile { target float64 } } */ +/* { dg-options "-O2 -fno-rounding-math -fno-trapping-math -fdump-tree-optimized" } */ +/* { dg-add-options float64 } */ +/* { dg-final { scan-tree-dump-times "return\[ \t]\*-?Inf;" 3 "optimized" } } */ + +_Float64 +foo (_Float64 x) +{ + if (x >= 1.0e+300f64) + ; + else + __builtin_unreachable (); + return x * x; +} + +_Float64 +bar (_Float64 x) +{ + if (x >= 1.0e+300f64) + ; + else + __builtin_unreachable (); + return x * -x; +} + +_Float64 +baz (_Float64 a, _Float64 b) +{ + if (a >= 0x1.fffffffffffffp+1023f64) + ; + else + __builtin_unreachable (); + if (b >= 0x1.p+972f64) + ; + else + __builtin_unreachable (); + return a + b; +} + +_Float64 +qux (_Float64 a, _Float64 b) +{ + if (a >= 0x1.fffffffffffffp+1023f64) + ; + else + __builtin_unreachable (); + if (b >= 0x1.fffffffffffffp+969f64) + ; + else + __builtin_unreachable (); + return a + b; +}