From: Aldy Hernandez <aldyh@redhat.com>
To: Jakub Jelinek <jakub@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] range-op: Implement floating point multiplication fold_range [PR107569]
Date: Fri, 11 Nov 2022 11:01:38 +0100 [thread overview]
Message-ID: <91a2e8c2-c846-6e8a-952e-d497db2fed50@redhat.com> (raw)
In-Reply-To: <Y21O5iOYd2VxxSQE@tucnak>
On 11/10/22 20:20, Jakub Jelinek wrote:
> On Thu, Nov 10, 2022 at 03:50:47PM +0100, Aldy Hernandez wrote:
>>> @@ -1908,6 +1910,123 @@ class foperator_minus : public range_ope
>>> }
>>> } fop_minus;
>>> +/* Wrapper around frange_arithmetics, that computes the result
>>> + if inexact rounded to both directions. Also, if one of the
>>> + operands is +-0.0 and another +-INF, return +-0.0 rather than
>>> + NAN. */
>>
>> s/frange_arithmetics/frange_arithmetic/
>>
>> Also, would you mind written a little blurb about why it's necessary not to
>> compute INF*0.0 as NAN. I assume it's because you're using it for the cross
>> product and you'll set maybe_nan separately, but it's nice to spell it out.
>
> This made me think about it some more and I'll need to play around with it
> some more, perhaps the right thing is similarly to what I've attached for
> division to handle special cases upfront and call frange_arithmetic only
> for the safe cases.
> E.g. one case which the posted foperator_mult handles pessimistically is
> [0.0, 10.0] * [INF, INF]. This should be just [INF, INF] +-NAN IMHO,
> because the 0.0 * INF case will result in NAN, while
> nextafter (0.0, 1.0) * INF
> will be already INF and everything larger as well.
> I could in frange_mult be very conservative and for the 0 * INF cases
> set result_lb and result_ub to [0.0, INF] range (corresponding signs
> depending on the xor of sign of ops), but that would be quite pessimistic as
> well. If one has:
> [0.0, 0.0] * [10.0, INF], the result should be just [0.0, 0.0] +-NAN,
> because again 0.0 * INF is NAN, but 0.0 * nextafter (INF, 0.0) is already 0.0.
>
> Note, the is_square case doesn't suffer from all of this mess, the result
> is never NAN (unless operand is NAN).
>
>> It'd be nice to have some testcases. For example, from what I can see, the
>> original integer multiplication code came with some tests in
>> gcc.dg/tree-ssa/vrp13.c (commit 9983270bec0a18). It'd be nice to have some
>> sanity checks, especially because so many things can go wrong with floats.
>>
>> I'll leave it to you to decide what tests to include.
>
> I've tried following, but it suffers from various issues:
> 1) we don't handle __builtin_signbit (whatever) == 0 (or != 0) as guarantee
> that in the guarded code whatever has signbit 0 or 1
We have a range-op entry for __builtin_signbit in cfn_signbit. Is this
a shortcoming of this code, or something else?
> 2) __builtin_isinf (x) > 0 is lowered to x > DBL_MAX, but unfortunately we don't
> infer from that [INF,INF] range, but [DBL_MAX, INF] range
> 3) what I wrote above, I think we don't handle [0, 2] * [INF, INF] right but
> due to 2) we can't see it
Doesn't this boil down to a representation issue? I wonder if we should
bite the bullet and tweak build_gt() and build_lt() to represent open
ranges. In theory it should be one more/less ULP, while adjusting for
HONOR_INFINITIES.
If the signbit issue were resolved and we could represent > and <
properly, would that allow us to write proper testcases without having
to writing a plug-in (which I assume is a lot harder)?
Aldy
>
> So, maybe for now a selftest will be better than a testcase, or
> alternatively a plugin test which acts like a selftest.
>
> /* { dg-do compile { target { ! { vax-*-* powerpc-*-*spe pdp11-*-* } } } } */
> /* { dg-options "-O2 -fno-trapping-math -fno-signaling-nans -fsigned-zeros -fno-tree-fre -fno-tree-dominator-opts -fno-thread-jumps -fdump-tree-optimized" } */
> /* { dg-add-options ieee } */
>
> void
> foo (double x, double y)
> {
> const double inf = __builtin_inf ();
> const double minf = -inf;
> if (__builtin_isnan (x) || __builtin_isnan (y))
> return;
> #define TEST(n, xl, xu, yl, yu, rl, ru, nan) \
> if ((__builtin_isinf (xl) > 0 \
> ? x > 0.0 && __builtin_isinf (x) \
> : __builtin_isinf (xu) < 0 \
> ? x < 0.0 && __builtin_isinf (x) \
> : x >= xl && x <= xu \
> && (xl != 0.0 \
> || __builtin_signbit (xl) \
> || !__builtin_signbit (x)) \
> && (xu != 0.0 \
> || !__builtin_signbit (xu) \
> || __builtin_signbit (x))) \
> && (__builtin_isinf (yl) > 0 \
> ? y > 0.0 && __builtin_isinf (y) \
> : __builtin_isinf (yu) < 0 \
> ? y < 0.0 && __builtin_isinf (y) \
> : y >= yl && y <= yu \
> && (yl != 0.0 \
> || __builtin_signbit (yl) \
> || !__builtin_signbit (y)) \
> && (yu != 0.0 \
> || !__builtin_signbit (yu) \
> || __builtin_signbit (y)))) \
> { \
> double r##n = x * y; \
> if (nan == 2) \
> { \
> if (!__builtin_isnan (r##n)) \
> __builtin_abort (); \
> } \
> else if (nan == 1) \
> { \
> if (!__builtin_isnan (r##n)) \
> { \
> if (r##n < rl || r##n > ru) \
> __builtin_abort (); \
> } \
> } \
> else \
> { \
> if (__builtin_isnan (r##n)) \
> __builtin_abort (); \
> if (r##n < rl || r##n > ru) \
> __builtin_abort (); \
> } \
> }
> #define TEST2(n, xl, xu, rl, ru) \
> if (__builtin_isinf (xl) > 0 \
> ? x > 0.0 && __builtin_isinf (x) \
> : __builtin_isinf (xu) < 0 \
> ? x < 0.0 && __builtin_isinf (x) \
> : x >= xl && x <= xu \
> && (xl != 0.0 \
> || __builtin_signbit (xl) \
> || !__builtin_signbit (x)) \
> && (xu != 0.0 \
> || !__builtin_signbit (xu) \
> || __builtin_signbit (x))) \
> { \
> double s##n = x * x; \
> if (__builtin_isnan (s##n)) \
> __builtin_abort (); \
> if (s##n < rl || s##n > ru) \
> __builtin_abort (); \
> }
> TEST (1, 2.0, 4.0, 6.0, 8.0, 12.0, 32.0, 0);
> TEST (2, -2.0, 3.0, -7.0, 4.0, -21.0, 14.0, 0);
> TEST (3, -9.0, 5.0, 8.0, 10.0, -90.0, 50.0, 0);
> TEST (4, -0.0, 0.0, 16.0, 32.0, -0.0, 0.0, 0);
> TEST (5, -0.0, 0.0, 16.0, 32.0, -0.0, 0.0, 0);
> TEST (6, 0.0, 0.0, 16.0, 32.0, 0.0, 0.0, 0);
> TEST (7, 0.0, 0.0, 16.0, 32.0, 0.0, 0.0, 0);
> TEST (8, -0.0, -0.0, 16.0, 32.0, -0.0, -0.0, 0);
> TEST (9, -0.0, -0.0, 16.0, 32.0, -0.0, -0.0, 0);
> TEST (10, minf, inf, minf, inf, minf, inf, 1);
> TEST (11, -0.0, 0.0, 128.0, inf, -0.0, 0.0, 1);
> TEST (12, -0.0, 0.0, inf, inf, 0.0, 0.0, 2);
> TEST (13, minf, minf, 0.0, 0.0, 0.0, 0.0, 2);
> TEST (14, 0.0, 2.0, inf, inf, inf, inf, 1);
> TEST (15, 0.0, 2.0, minf, minf, minf, minf, 1);
> TEST (16, inf, inf, -0.0, 2.0, minf, inf, 1);
> TEST (17, minf, minf, -0.0, 3.0, minf, inf, 1);
>
> TEST2 (1, 2.0, 4.0, 4.0, 16.0);
> TEST2 (2, -0.0, 0.0, -0.0, 0.0);
> TEST2 (3, 0.0, inf, 0.0, inf);
> TEST2 (4, inf, inf, inf, inf);
> }
>
>
> Jakub
>
next prev parent reply other threads:[~2022-11-11 10:01 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-10 13:44 Jakub Jelinek
2022-11-10 14:50 ` Aldy Hernandez
2022-11-10 19:20 ` Jakub Jelinek
2022-11-11 2:06 ` Jakub Jelinek
2022-11-11 8:52 ` [PATCH] range-op, v2: " Jakub Jelinek
2022-11-11 10:01 ` [PATCH] range-op: Cleanup floating point multiplication and division " Jakub Jelinek
2022-11-11 10:12 ` Aldy Hernandez
2022-11-11 10:56 ` Jakub Jelinek
2022-11-11 14:27 ` Aldy Hernandez
2022-11-11 10:01 ` Aldy Hernandez [this message]
2022-11-11 10:47 ` [PATCH] range-op: Implement floating point multiplication " Jakub Jelinek
2022-11-11 10:59 ` Aldy Hernandez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=91a2e8c2-c846-6e8a-952e-d497db2fed50@redhat.com \
--to=aldyh@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).