• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

修订版4c57e57b370333ae30feba624ab9caa69a33e15c (tree)
时间2022-11-12 19:18:40
作者Aldy Hernandez <aldyh@redh...>
CommiterAldy Hernandez

Log Message

[range-ops] Add ability to represent open intervals in frange.

Currently we represent < and > with a closed interval. So < 3.0 is
represented as [-INF, +3.0]. This means 3.0 is included in the range,
and though not ideal, is conservatively correct. Jakub has found a
couple cases where properly representing < and > would help
optimizations and tests, and this patch allows representing open
intervals with real_nextafter.

There are a few caveats.

First, we leave MODE_COMPOSITE_P types pessimistically as a closed interval.

Second, for -ffinite-math-only, real_nextafter will saturate the
maximum representable number into +INF. However, this will still do
the right thing, as frange::set() will crop things appropriately.

Finally, and most frustratingly, representing < and > -+0.0 is
problematic because we flush denormals to zero. Let me explain...

real_nextafter(+0.0, +INF) gives 0x0.8p-148 as expected, but setting a
range to this value yields [+0.0, 0x0.8p-148] because of the flushing.

On the other hand, real_nextafter(+0.0, -INF) (surprisingly) gives
-0.0.8p-148, but setting a range to that value yields [-0.0x8p-148,
-0.0]. I say surprising, because according to cppreference.com,
std::nextafter(+0.0, -INF) should give -0.0. But that's neither here
nor there because our flushing denormals to zero prevents us from even
representing ranges involving small values around 0.0. We ultimately
end up with ranges looking like this:

> +0.0 => [+0.0, INF]
> -0.0 => [+0.0, INF]
< +0.0 => [-INF, -0.0]
< -0.0 => [-INF, -0.0]

I suppose this is no worse off that what we had before with closed
intervals. One could even argue that we're better because we at least
have the right sign now ;-).

gcc/ChangeLog:

* range-op-float.cc (build_lt): Adjust with frange_nextafter
instead of default to a closed range.
(build_gt): Same.

更改概述

差异

--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -381,9 +381,17 @@ build_lt (frange &r, tree type, const frange &val)
381381 r.set_undefined ();
382382 return false;
383383 }
384- // We only support closed intervals.
384+
385385 REAL_VALUE_TYPE ninf = frange_val_min (type);
386- r.set (type, ninf, val.upper_bound ());
386+ REAL_VALUE_TYPE prev = val.upper_bound ();
387+ machine_mode mode = TYPE_MODE (type);
388+ // Default to the conservatively correct closed ranges for
389+ // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
390+ // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
391+ // will crop the range appropriately.
392+ if (!MODE_COMPOSITE_P (mode))
393+ frange_nextafter (mode, prev, ninf);
394+ r.set (type, ninf, prev);
387395 return true;
388396 }
389397
@@ -424,9 +432,16 @@ build_gt (frange &r, tree type, const frange &val)
424432 return false;
425433 }
426434
427- // We only support closed intervals.
428435 REAL_VALUE_TYPE inf = frange_val_max (type);
429- r.set (type, val.lower_bound (), inf);
436+ REAL_VALUE_TYPE next = val.lower_bound ();
437+ machine_mode mode = TYPE_MODE (type);
438+ // Default to the conservatively correct closed ranges for
439+ // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
440+ // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
441+ // will crop the range appropriately.
442+ if (!MODE_COMPOSITE_P (mode))
443+ frange_nextafter (mode, next, inf);
444+ r.set (type, next, inf);
430445 return true;
431446 }
432447