From: Richard Biener <richard.guenther@gmail.com>
To: Alan Modra <amodra@gmail.com>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>
Subject: Re: [RFC] PR70117, ppc long double isinf
Date: Tue, 05 Apr 2016 09:29:00 -0000 [thread overview]
Message-ID: <CAFiYyc0EJp-2QhEd0JL4fEE1F0ZnD65-Vpn+Vb0eeBnVS_WbcA@mail.gmail.com> (raw)
In-Reply-To: <20160405083340.GD18129@bubble.grove.modra.org>
On Tue, Apr 5, 2016 at 10:33 AM, Alan Modra <amodra@gmail.com> wrote:
> This patch fixes the incompatibility between GNUlib's 107 bit
> precision LDBL_MAX for IBM extended precision and gcc's 106 bit
> LDBL_MAX used to test for Inf, by just testing the high double for inf
> and nan. This agrees with the ABI which has stated for many years
> that IBM extended precision "does not fully support the IEEE special
> numbers NaN and INF. These values are encoded in the high-order
> double value only. The low-order value is not significant".
>
> I've also changed the test for nan, and both the inf test and the
> subnormal test in isnormal, to just use the high double. Changing the
> subnormal test *does* allow a small range of values to be seen as
> normal that previously would be rejected in a test of the whole long
> double against 2**-969. Which is why I'm making this an RFC rather
> than a patch submission.
>
> What is "subnormal" for an IBM extended precision number, anyway? I
> think the only definition that makes sense is in terms of precision.
> We can't say a long double is subnormal if the low double is
> subnormal, because numbers like (1.0 + 0x1p-1074) are representable
> with the high double properly rounded and are clearly not close to
> zero or losing precision. So "subnormal" for IBM extended precision
> is a number that has less than 106 bits of precision. That would be
> at a magnitude of less than 2**-969. You can see that
> (0x1p-969 + 0x1p-1074) = 0x1.000000000000000000000000008p-969
> still has 106 bits of precision. (0x1p-1074 is the smallest double
> distinct from zero, and of course is subnormal.) However,
> (0x1p-969 + -0x1p-1074) = 0x1.ffffffffffffffffffffffffffp-970
> has only 105 bits of precision, if I'm counting correctly.
>
> So testing just the high double in isnormal() returns true for a range
> of 105 bit precision values, from (0x1p-969 - 0x1p-1023) to
> (0x1p-969 - 0x1p-1074). The question is whether I should make the
> isnormal() code quite nasty in order to give the right answer.
> Probably yes, in which case this post becomes an explanation for why
> the lower bound test in isnormal() needs to be a long double test.
> Or probably better in terms of emitted code, can I get at both of the
> component doubles of an IBM long double at the tree level?
> VEIW_CONVERT_EXPR to a complex double perhaps?
Yes, that would work I think, the other variant would be a
BIT_FIELD_REF (but watch out for endianess?).
In general the patch looks like a good approach to me but can we
hide that
> + const struct real_format *fmt = FLOAT_MODE_FORMAT (mode);
> + bool is_ibm_extended = fmt->pnan < fmt->p;
in a function somewhere in real.[ch]?
Thanks,
Richard.
> PR target/70117
> * builtins.c (fold_builtin_classify): For IBM extended precision,
> look at just the high-order double to test for NaN.
> (fold_builtin_interclass_mathfn): Similarly for Inf, and range
> test for IBM extended precision isnormal.
>
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index 9368ed0..ed27d57 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -7529,6 +7529,9 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
>
> mode = TYPE_MODE (TREE_TYPE (arg));
>
> + const struct real_format *fmt = FLOAT_MODE_FORMAT (mode);
> + bool is_ibm_extended = fmt->pnan < fmt->p;
> +
> /* If there is no optab, try generic code. */
> switch (DECL_FUNCTION_CODE (fndecl))
> {
> @@ -7538,10 +7541,18 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
> {
> /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
> tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
> - tree const type = TREE_TYPE (arg);
> + tree type = TREE_TYPE (arg);
> REAL_VALUE_TYPE r;
> char buf[128];
>
> + if (is_ibm_extended)
> + {
> + /* NaN and INF are encoded in the high-order double value
> + only. The low-order value is not significant. */
> + type = double_type_node;
> + mode = DFmode;
> + arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
> + }
> get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
> real_from_string (&r, buf);
> result = build_call_expr (isgr_fn, 2,
> @@ -7554,10 +7565,18 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
> {
> /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
> tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
> - tree const type = TREE_TYPE (arg);
> + tree type = TREE_TYPE (arg);
> REAL_VALUE_TYPE r;
> char buf[128];
>
> + if (is_ibm_extended)
> + {
> + /* NaN and INF are encoded in the high-order double value
> + only. The low-order value is not significant. */
> + type = double_type_node;
> + mode = DFmode;
> + arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
> + }
> get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
> real_from_string (&r, buf);
> result = build_call_expr (isle_fn, 2,
> @@ -7578,15 +7597,28 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
> islessequal(fabs(x),DBL_MAX). */
> tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
> tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
> - tree const type = TREE_TYPE (arg);
> + tree type = TREE_TYPE (arg);
> + machine_mode orig_mode = mode;
> REAL_VALUE_TYPE rmax, rmin;
> char buf[128];
>
> + if (is_ibm_extended)
> + {
> + /* Use double to test the normal range of IBM extended
> + precision. Emin for IBM extended precision is
> + different to emin for IEEE double, being 53 higher
> + since the low double exponent is at least 53 lower
> + than the high double exponent. */
> + type = double_type_node;
> + mode = DFmode;
> + arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
> + }
> + arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
> +
> get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
> real_from_string (&rmax, buf);
> - sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
> + sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
> real_from_string (&rmin, buf);
> - arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
> result = build_call_expr (isle_fn, 2, arg,
> build_real (type, rmax));
> result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
> @@ -7664,6 +7696,17 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
> if (!HONOR_NANS (arg))
> return omit_one_operand_loc (loc, type, integer_zero_node, arg);
>
> + {
> + const struct real_format *fmt
> + = FLOAT_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)));
> + bool is_ibm_extended = fmt->pnan < fmt->p;
> + if (is_ibm_extended)
> + {
> + /* NaN and INF are encoded in the high-order double value
> + only. The low-order value is not significant. */
> + arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
> + }
> + }
> arg = builtin_save_expr (arg);
> return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
>
>
> --
> Alan Modra
> Australia Development Lab, IBM
next prev parent reply other threads:[~2016-04-05 9:29 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-04-05 8:33 Alan Modra
2016-04-05 9:29 ` Richard Biener [this message]
2016-04-06 8:32 ` [PATCH] " Alan Modra
2016-04-06 8:46 ` Richard Biener
2016-04-06 9:19 ` Alan Modra
2016-04-07 8:04 ` Alan Modra
2016-04-07 9:33 ` Richard Biener
2016-04-07 14:17 ` Alan Modra
2016-04-07 14:43 ` David Edelsohn
2016-04-08 3:03 ` Alan Modra
2016-04-08 5:41 ` Richard Biener
2016-04-06 10:27 ` Andreas Schwab
2016-04-06 12:43 ` Alan Modra
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=CAFiYyc0EJp-2QhEd0JL4fEE1F0ZnD65-Vpn+Vb0eeBnVS_WbcA@mail.gmail.com \
--to=richard.guenther@gmail.com \
--cc=amodra@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
/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).