diff mbox

Remove __isinf uses that rely on signed return value

Message ID 001301d09d57$c0bfdf60$423f9e20$@com
State New
Headers show

Commit Message

Wilco June 2, 2015, 5:15 p.m. UTC
The printf code contains a few uses of __isinf where the sign is used - replace these with separate
isinf and signbit. Also change __isnan into isnan.

OK for commit?

Wilco

2015-06-02  Wilco Dijkstra  <wdijkstr@arm.com>

	* stdio-common/printf_fp.c (___printf_fp):
	Use signbit to get the sign. Use isinf/isnan macros.
	* stdio-common/printf_fphex.c (__printf_fphex): Likewise.
	* stdio-common/printf_size.c (__printf_size): Likewise.

---
 stdio-common/printf_fp.c    | 17 +++++++----------
 stdio-common/printf_fphex.c | 14 +++++---------
 stdio-common/printf_size.c  | 23 +++++++++++------------
 3 files changed, 23 insertions(+), 31 deletions(-)

Comments

Joseph Myers June 2, 2015, 5:42 p.m. UTC | #1
On Tue, 2 Jun 2015, Wilco Dijkstra wrote:

> The printf code contains a few uses of __isinf where the sign is used - 
> replace these with separate isinf and signbit.

Why?  Isn't the point of glibc's isinf returning a signed value that you 
can do such combined operations?

I'd also really recommend separating safe cleanups that don't change the 
stripped installed shared libraries at all (other than assertion line 
numbers), such as moving to use the type-generic macros internally, from 
any other changes that might affect the installed binaries.  And when 
something shouldn't change the (stripped) installed binaries, verify that 
it doesn't, and state the platform on which you did such verification.
Szabolcs Nagy June 2, 2015, 6 p.m. UTC | #2
On 02/06/15 18:15, Wilco Dijkstra wrote:
> The printf code contains a few uses of __isinf where the sign is used - replace these with separate
> isinf and signbit. Also change __isnan into isnan.
> 

i suspect it slightly changes semantics on x86 (for the better).

i386 __isnanl does not seem to handle invalid ld80 representations.

if exponent != 0 and significand>>63 == 0 then it's a "pseudo normal"
or "pseudo infinite" value that the fpu would categorize as nan, but
not __isnanl.

(passing around long doubles with invalid representation is ub,
but probably __isnanl should be consistent with fcom instruction
to be safe when it is used on random bytes).

> OK for commit?
> 
> Wilco
> 
> 2015-06-02  Wilco Dijkstra  <wdijkstr@arm.com>
> 
> 	* stdio-common/printf_fp.c (___printf_fp):
> 	Use signbit to get the sign. Use isinf/isnan macros.
> 	* stdio-common/printf_fphex.c (__printf_fphex): Likewise.
> 	* stdio-common/printf_size.c (__printf_size): Likewise.
> 
> ---
>  stdio-common/printf_fp.c    | 17 +++++++----------
>  stdio-common/printf_fphex.c | 14 +++++---------
>  stdio-common/printf_size.c  | 23 +++++++++++------------
>  3 files changed, 23 insertions(+), 31 deletions(-)
> 
> diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
> index 575842b..11f3145 100644
> --- a/stdio-common/printf_fp.c
> +++ b/stdio-common/printf_fp.c
> @@ -332,8 +332,7 @@ ___printf_fp (FILE *fp,
>        fpnum.ldbl = *(const long double *) args[0];
>  
>        /* Check for special values: not a number or infinity.  */
> -      int res;
> -      if (__isnanl (fpnum.ldbl))
> +      if (isnan (fpnum.ldbl))
>  	{
>  	  is_neg = signbit (fpnum.ldbl);
>  	  if (isupper (info->spec))
> @@ -347,9 +346,9 @@ ___printf_fp (FILE *fp,
>  		wspecial = L"nan";
>  	      }
>  	}
> -      else if ((res = __isinfl (fpnum.ldbl)))
> +      else if (isinf (fpnum.ldbl))
>  	{
> -	  is_neg = res < 0;
> +	  is_neg = signbit (fpnum.ldbl);
>  	  if (isupper (info->spec))
>  	    {
>  	      special = "INF";
> @@ -377,11 +376,9 @@ ___printf_fp (FILE *fp,
>        fpnum.dbl = *(const double *) args[0];
>  
>        /* Check for special values: not a number or infinity.  */
> -      int res;
> -      if (__isnan (fpnum.dbl))
> +      if (isnan (fpnum.dbl))
>  	{
> -	  union ieee754_double u = { .d = fpnum.dbl };
> -	  is_neg = u.ieee.negative != 0;
> +	  is_neg = signbit (fpnum.dbl);
>  	  if (isupper (info->spec))
>  	    {
>  	      special = "NAN";
> @@ -393,9 +390,9 @@ ___printf_fp (FILE *fp,
>  	      wspecial = L"nan";
>  	    }
>  	}
> -      else if ((res = __isinf (fpnum.dbl)))
> +      else if (isinf (fpnum.dbl))
>  	{
> -	  is_neg = res < 0;
> +	  is_neg = signbit (fpnum.dbl);
>  	  if (isupper (info->spec))
>  	    {
>  	      special = "INF";
> diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c
> index ba0639f..0627bea 100644
> --- a/stdio-common/printf_fphex.c
> +++ b/stdio-common/printf_fphex.c
> @@ -165,7 +165,7 @@ __printf_fphex (FILE *fp,
>        fpnum.ldbl = *(const long double *) args[0];
>  
>        /* Check for special values: not a number or infinity.  */
> -      if (__isnanl (fpnum.ldbl))
> +      if (isnan (fpnum.ldbl))
>  	{
>  	  if (isupper (info->spec))
>  	    {
> @@ -180,7 +180,7 @@ __printf_fphex (FILE *fp,
>  	}
>        else
>  	{
> -	  if (__isinfl (fpnum.ldbl))
> +	  if (isinf (fpnum.ldbl))
>  	    {
>  	      if (isupper (info->spec))
>  		{
> @@ -202,9 +202,8 @@ __printf_fphex (FILE *fp,
>        fpnum.dbl.d = *(const double *) args[0];
>  
>        /* Check for special values: not a number or infinity.  */
> -      if (__isnan (fpnum.dbl.d))
> +      if (isnan (fpnum.dbl.d))
>  	{
> -	  negative = fpnum.dbl.ieee.negative != 0;
>  	  if (isupper (info->spec))
>  	    {
>  	      special = "NAN";
> @@ -218,8 +217,7 @@ __printf_fphex (FILE *fp,
>  	}
>        else
>  	{
> -	  int res = __isinf (fpnum.dbl.d);
> -	  if (res)
> +	  if (isinf (fpnum.dbl.d))
>  	    {
>  	      if (isupper (info->spec))
>  		{
> @@ -231,11 +229,9 @@ __printf_fphex (FILE *fp,
>  		  special = "inf";
>  		  wspecial = L"inf";
>  		}
> -	      negative = res < 0;
>  	    }
> -	  else
> -	    negative = signbit (fpnum.dbl.d);
>  	}
> +      negative = signbit (fpnum.dbl.d);
>      }
>  
>    if (special)
> diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c
> index 6ee753f..216f170 100644
> --- a/stdio-common/printf_size.c
> +++ b/stdio-common/printf_size.c
> @@ -108,7 +108,7 @@ __printf_size (FILE *fp, const struct printf_info *info,
>    fpnum;
>    const void *ptr = &fpnum;
>  
> -  int fpnum_sign = 0;
> +  int is_neg = 0;
>  
>    /* "NaN" or "Inf" for the special cases.  */
>    const char *special = NULL;
> @@ -117,7 +117,6 @@ __printf_size (FILE *fp, const struct printf_info *info,
>    struct printf_info fp_info;
>    int done = 0;
>    int wide = info->wide;
> -  int res;
>  
>    /* Fetch the argument value.	*/
>  #ifndef __NO_LONG_DOUBLE_MATH
> @@ -126,15 +125,15 @@ __printf_size (FILE *fp, const struct printf_info *info,
>        fpnum.ldbl = *(const long double *) args[0];
>  
>        /* Check for special values: not a number or infinity.  */
> -      if (__isnanl (fpnum.ldbl))
> +      if (isnan (fpnum.ldbl))
>  	{
>  	  special = "nan";
>  	  wspecial = L"nan";
> -	  // fpnum_sign = 0;	Already zero
> +	  // is_neg = 0;	Already zero
>  	}
> -      else if ((res = __isinfl (fpnum.ldbl)))
> +      else if (isinf (fpnum.ldbl))
>  	{
> -	  fpnum_sign = res;
> +	  is_neg = signbit (fpnum.ldbl);
>  	  special = "inf";
>  	  wspecial = L"inf";
>  	}
> @@ -151,15 +150,15 @@ __printf_size (FILE *fp, const struct printf_info *info,
>        fpnum.dbl.d = *(const double *) args[0];
>  
>        /* Check for special values: not a number or infinity.  */
> -      if (__isnan (fpnum.dbl.d))
> +      if (isnan (fpnum.dbl.d))
>  	{
>  	  special = "nan";
>  	  wspecial = L"nan";
> -	  // fpnum_sign = 0;	Already zero
> +	  // is_neg = 0;	Already zero
>  	}
> -      else if ((res = __isinf (fpnum.dbl.d)))
> +      else if (isinf (fpnum.dbl.d))
>  	{
> -	  fpnum_sign = res;
> +	  is_neg = signbit (fpnum.dbl.d);
>  	  special = "inf";
>  	  wspecial = L"inf";
>  	}
> @@ -175,14 +174,14 @@ __printf_size (FILE *fp, const struct printf_info *info,
>      {
>        int width = info->prec > info->width ? info->prec : info->width;
>  
> -      if (fpnum_sign < 0 || info->showsign || info->space)
> +      if (is_neg || info->showsign || info->space)
>  	--width;
>        width -= 3;
>  
>        if (!info->left && width > 0)
>  	PADN (' ', width);
>  
> -      if (fpnum_sign < 0)
> +      if (is_neg)
>  	outchar ('-');
>        else if (info->showsign)
>  	outchar ('+');
>
Joseph Myers June 2, 2015, 8:20 p.m. UTC | #3
On Tue, 2 Jun 2015, Szabolcs Nagy wrote:

> On 02/06/15 18:15, Wilco Dijkstra wrote:
> > The printf code contains a few uses of __isinf where the sign is used - replace these with separate
> > isinf and signbit. Also change __isnan into isnan.
> 
> i suspect it slightly changes semantics on x86 (for the better).

It shouldn't.  isnan, the type-generic macro, just calls __isnanf / 
__isnan / __isnanl depending on the type of the argument.

> i386 __isnanl does not seem to handle invalid ld80 representations.
> 
> if exponent != 0 and significand>>63 == 0 then it's a "pseudo normal"
> or "pseudo infinite" value that the fpu would categorize as nan, but
> not __isnanl.
> 
> (passing around long doubles with invalid representation is ub,
> but probably __isnanl should be consistent with fcom instruction
> to be safe when it is used on random bytes).

glibc policy on invalid long double values (both ldbl-96 and I think 
ldbl-128ibm) is bounded undefined behavior (unspecified result, 
unspecified exceptions, no expectation of any consistency, but should 
avoid crashing the program / out-of-bounds stores).
Wilco June 3, 2015, 11:35 a.m. UTC | #4
> Joseph Myers wrote:
> On Tue, 2 Jun 2015, Wilco Dijkstra wrote:
> 
> > The printf code contains a few uses of __isinf where the sign is used -
> > replace these with separate isinf and signbit.
> 
> Why?  Isn't the point of glibc's isinf returning a signed value that you
> can do such combined operations?

We discussed this a while back (and I thought it was agreed on going forward 
like this) - to recap, it is not required by any standard (so no standard
compliant software may rely on this GLIBC specific behaviour), and is
actually incompatible with C++ which requires a boolean to be returned. 
So the idea is to only support the old behaviour in GNUC mode for backwards 
compatibility, but not in C99/C++.

It would be possible to introduce a new macro isinf_sign if someone can make
the argument it is a good interface. I don't see how it could be as getting 
the sign is just a single compare or shift once you've transferred the FP 
value to the integer side - in other words isinf_sign (x) will be slower than
using isinf (x) plus signbit (x)...

> I'd also really recommend separating safe cleanups that don't change the
> stripped installed shared libraries at all (other than assertion line
> numbers), such as moving to use the type-generic macros internally, from
> any other changes that might affect the installed binaries.  And when
> something shouldn't change the (stripped) installed binaries, verify that
> it doesn't, and state the platform on which you did such verification.

I have a separate patch with all the __isxxx macros renamed across GLIBC, so
I'll add the __isnan cases in printf too. I'll check in when I've confirmed
there are no diffs.

Wilco
Joseph Myers June 3, 2015, 11:49 a.m. UTC | #5
On Wed, 3 Jun 2015, Wilco Dijkstra wrote:

> > Joseph Myers wrote:
> > On Tue, 2 Jun 2015, Wilco Dijkstra wrote:
> > 
> > > The printf code contains a few uses of __isinf where the sign is used -
> > > replace these with separate isinf and signbit.
> > 
> > Why?  Isn't the point of glibc's isinf returning a signed value that you
> > can do such combined operations?
> 
> We discussed this a while back (and I thought it was agreed on going forward 
> like this) - to recap, it is not required by any standard (so no standard

I don't recall any such discussion or agreement.  The discussion in bug 
15367 is on the basis of using __builtin_isinf_sign to implement the 
header macro, not of changing the requirements and sometimes using 
__builtin_isinf.

> compliant software may rely on this GLIBC specific behaviour), and is
> actually incompatible with C++ which requires a boolean to be returned. 

C++ is the responsibility of libstdc++ (and defines overloaded functions, 
not type-generic macros; libstdc++ needs to override things done in the C 
header anyway).

> So the idea is to only support the old behaviour in GNUC mode for backwards 
> compatibility, but not in C99/C++.

glibc is built with _GNU_SOURCE and can freely use all GNU features 
(subject to link-time namespace issues).  I see no need to change the 
interface to this macro in glibc.  Presumably the aim should be to make 
the GCC __builtin_isinf / __builtin_isinf_sign at least as efficient as 
the out-of-line functions, and safe for all inputs, make the isinf macro 
use __builtin_isinf_sign, and make GCC optimize __builtin_isinf_sign calls 
so it's as efficient as __builtin_isinf if the sign isn't used, and as 
efficient as __builtin_isinf + __builtin_signbit if the sign is used.
Wilco June 3, 2015, 1:21 p.m. UTC | #6
> Joseph Myers wrote: 
> On Wed, 3 Jun 2015, Wilco Dijkstra wrote:
> 
> > > Joseph Myers wrote:
> > > On Tue, 2 Jun 2015, Wilco Dijkstra wrote:
> > >
> > > > The printf code contains a few uses of __isinf where the sign is used -
> > > > replace these with separate isinf and signbit.
> > >
> > > Why?  Isn't the point of glibc's isinf returning a signed value that you
> > > can do such combined operations?
> >
> > We discussed this a while back (and I thought it was agreed on going forward
> > like this) - to recap, it is not required by any standard (so no standard
> 
> I don't recall any such discussion or agreement.  The discussion in bug
> 15367 is on the basis of using __builtin_isinf_sign to implement the
> header macro, not of changing the requirements and sometimes using
> __builtin_isinf.

Well it was a while back. However the GCC built-ins need further optimization
and fixes so just using the builtins is not a good fix either...

> > compliant software may rely on this GLIBC specific behaviour), and is
> > actually incompatible with C++ which requires a boolean to be returned.
> 
> C++ is the responsibility of libstdc++ (and defines overloaded functions,
> not type-generic macros; libstdc++ needs to override things done in the C
> header anyway).
> 
> > So the idea is to only support the old behaviour in GNUC mode for backwards
> > compatibility, but not in C99/C++.
> 
> glibc is built with _GNU_SOURCE and can freely use all GNU features
> (subject to link-time namespace issues).  I see no need to change the
> interface to this macro in glibc.  Presumably the aim should be to make
> the GCC __builtin_isinf / __builtin_isinf_sign at least as efficient as
> the out-of-line functions, and safe for all inputs, make the isinf macro
> use __builtin_isinf_sign, and make GCC optimize __builtin_isinf_sign calls
> so it's as efficient as __builtin_isinf if the sign isn't used, and as
> efficient as __builtin_isinf + __builtin_signbit if the sign is used.

In principle GLIBC could continue to use this feature internally, but do 
you have any objections to removing all internal uses like my patch does?

In terms of interface, why do you think it is useful to continue a non-standard
interface indefinitely rather than making it GNUC specific? Other than backwards
compatibility there seems to be no compelling reason to keep it.

Note I am also planning to remove all internal uses of __isinf_ns and replace
them with isinf - no reason to keep using this non-standard interface either!

Yes it would be possible to expand isinf as:

(__isinf_ns (x) ? (signbit (x) ? -1 : 1) : 0)

This should make if (isinf (x)) as efficient as if (__isinf_ns (x)), however if 
the result is assigned to a variable then it would always have additional overhead.
This is obvious if the sign is not used, but if the sign is used it would still
not be as efficient as separate isinf and signbit calls.

Wilco
Joseph Myers June 3, 2015, 2:23 p.m. UTC | #7
On Wed, 3 Jun 2015, Wilco Dijkstra wrote:

> > > We discussed this a while back (and I thought it was agreed on going forward
> > > like this) - to recap, it is not required by any standard (so no standard
> > 
> > I don't recall any such discussion or agreement.  The discussion in bug
> > 15367 is on the basis of using __builtin_isinf_sign to implement the
> > header macro, not of changing the requirements and sometimes using
> > __builtin_isinf.
> 
> Well it was a while back. However the GCC built-ins need further optimization
> and fixes so just using the builtins is not a good fix either...

I've grepped my libc-alpha mailboxes for the past 15 years without finding 
anything obvious in this area.

> > glibc is built with _GNU_SOURCE and can freely use all GNU features
> > (subject to link-time namespace issues).  I see no need to change the
> > interface to this macro in glibc.  Presumably the aim should be to make
> > the GCC __builtin_isinf / __builtin_isinf_sign at least as efficient as
> > the out-of-line functions, and safe for all inputs, make the isinf macro
> > use __builtin_isinf_sign, and make GCC optimize __builtin_isinf_sign calls
> > so it's as efficient as __builtin_isinf if the sign isn't used, and as
> > efficient as __builtin_isinf + __builtin_signbit if the sign is used.
> 
> In principle GLIBC could continue to use this feature internally, but do 
> you have any objections to removing all internal uses like my patch does?

Yes, in the absence of evidence that the two produce equivalent code or 
the new one produces better code than the old one (at least for current 
GCC).  I'd expect that to most likely be the case once the GCC built-in 
functions have been appropriately optimized, made to use integer 
arithmetic and are in use when building with current GCC.  It might well 
be the case with appropriate inline integer expansions in glibc headers, 
but I think the GCC inline improvements should take priority with any 
glibc inline expansions being added afterwards as fallbacks for older GCC 
versions.

> In terms of interface, why do you think it is useful to continue a 
> non-standard interface indefinitely rather than making it GNUC specific? 
> Other than backwards compatibility there seems to be no compelling 
> reason to keep it.

It's pretty much universally the case in glibc that feature test macros 
only protect the definitions of identifiers, rather than affecting the 
semantics of those identifiers.  The exceptions are cases where extensions 
actually conflict with supported standards (e.g. basename, or scanf %a).  
The glibc extension does not conflict with the supported standards and 
doesn't seem otherwise problematic - and there's a clear route through GCC 
work for making it not pessimize code for programs that only care about 
the boolean return value of isinf.

> Yes it would be possible to expand isinf as:
> 
> (__isinf_ns (x) ? (signbit (x) ? -1 : 1) : 0)
> 
> This should make if (isinf (x)) as efficient as if (__isinf_ns (x)), 
> however if the result is assigned to a variable then it would always 
> have additional overhead. This is obvious if the sign is not used, but 
> if the sign is used it would still not be as efficient as separate isinf 
> and signbit calls.

I'd expect it to be just as efficient, given that the relevant functions 
have the const attribute so calls to them can be optimized out if the 
results are not used.  It's rather less obvious how the efficiency would 
compare with a direct call to __isinf producing both bits of information, 
until everything is expanded inline.

However, I don't think we really want to add __isinf_ns (an internal 
function at present, not exported from any shared library) to the public 
ABI, given the preferred direction involves compiler support for expanding 
all these calls efficiently inline.
diff mbox

Patch

diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index 575842b..11f3145 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -332,8 +332,7 @@  ___printf_fp (FILE *fp,
       fpnum.ldbl = *(const long double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      int res;
-      if (__isnanl (fpnum.ldbl))
+      if (isnan (fpnum.ldbl))
 	{
 	  is_neg = signbit (fpnum.ldbl);
 	  if (isupper (info->spec))
@@ -347,9 +346,9 @@  ___printf_fp (FILE *fp,
 		wspecial = L"nan";
 	      }
 	}
-      else if ((res = __isinfl (fpnum.ldbl)))
+      else if (isinf (fpnum.ldbl))
 	{
-	  is_neg = res < 0;
+	  is_neg = signbit (fpnum.ldbl);
 	  if (isupper (info->spec))
 	    {
 	      special = "INF";
@@ -377,11 +376,9 @@  ___printf_fp (FILE *fp,
       fpnum.dbl = *(const double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      int res;
-      if (__isnan (fpnum.dbl))
+      if (isnan (fpnum.dbl))
 	{
-	  union ieee754_double u = { .d = fpnum.dbl };
-	  is_neg = u.ieee.negative != 0;
+	  is_neg = signbit (fpnum.dbl);
 	  if (isupper (info->spec))
 	    {
 	      special = "NAN";
@@ -393,9 +390,9 @@  ___printf_fp (FILE *fp,
 	      wspecial = L"nan";
 	    }
 	}
-      else if ((res = __isinf (fpnum.dbl)))
+      else if (isinf (fpnum.dbl))
 	{
-	  is_neg = res < 0;
+	  is_neg = signbit (fpnum.dbl);
 	  if (isupper (info->spec))
 	    {
 	      special = "INF";
diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c
index ba0639f..0627bea 100644
--- a/stdio-common/printf_fphex.c
+++ b/stdio-common/printf_fphex.c
@@ -165,7 +165,7 @@  __printf_fphex (FILE *fp,
       fpnum.ldbl = *(const long double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      if (__isnanl (fpnum.ldbl))
+      if (isnan (fpnum.ldbl))
 	{
 	  if (isupper (info->spec))
 	    {
@@ -180,7 +180,7 @@  __printf_fphex (FILE *fp,
 	}
       else
 	{
-	  if (__isinfl (fpnum.ldbl))
+	  if (isinf (fpnum.ldbl))
 	    {
 	      if (isupper (info->spec))
 		{
@@ -202,9 +202,8 @@  __printf_fphex (FILE *fp,
       fpnum.dbl.d = *(const double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      if (__isnan (fpnum.dbl.d))
+      if (isnan (fpnum.dbl.d))
 	{
-	  negative = fpnum.dbl.ieee.negative != 0;
 	  if (isupper (info->spec))
 	    {
 	      special = "NAN";
@@ -218,8 +217,7 @@  __printf_fphex (FILE *fp,
 	}
       else
 	{
-	  int res = __isinf (fpnum.dbl.d);
-	  if (res)
+	  if (isinf (fpnum.dbl.d))
 	    {
 	      if (isupper (info->spec))
 		{
@@ -231,11 +229,9 @@  __printf_fphex (FILE *fp,
 		  special = "inf";
 		  wspecial = L"inf";
 		}
-	      negative = res < 0;
 	    }
-	  else
-	    negative = signbit (fpnum.dbl.d);
 	}
+      negative = signbit (fpnum.dbl.d);
     }
 
   if (special)
diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c
index 6ee753f..216f170 100644
--- a/stdio-common/printf_size.c
+++ b/stdio-common/printf_size.c
@@ -108,7 +108,7 @@  __printf_size (FILE *fp, const struct printf_info *info,
   fpnum;
   const void *ptr = &fpnum;
 
-  int fpnum_sign = 0;
+  int is_neg = 0;
 
   /* "NaN" or "Inf" for the special cases.  */
   const char *special = NULL;
@@ -117,7 +117,6 @@  __printf_size (FILE *fp, const struct printf_info *info,
   struct printf_info fp_info;
   int done = 0;
   int wide = info->wide;
-  int res;
 
   /* Fetch the argument value.	*/
 #ifndef __NO_LONG_DOUBLE_MATH
@@ -126,15 +125,15 @@  __printf_size (FILE *fp, const struct printf_info *info,
       fpnum.ldbl = *(const long double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      if (__isnanl (fpnum.ldbl))
+      if (isnan (fpnum.ldbl))
 	{
 	  special = "nan";
 	  wspecial = L"nan";
-	  // fpnum_sign = 0;	Already zero
+	  // is_neg = 0;	Already zero
 	}
-      else if ((res = __isinfl (fpnum.ldbl)))
+      else if (isinf (fpnum.ldbl))
 	{
-	  fpnum_sign = res;
+	  is_neg = signbit (fpnum.ldbl);
 	  special = "inf";
 	  wspecial = L"inf";
 	}
@@ -151,15 +150,15 @@  __printf_size (FILE *fp, const struct printf_info *info,
       fpnum.dbl.d = *(const double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      if (__isnan (fpnum.dbl.d))
+      if (isnan (fpnum.dbl.d))
 	{
 	  special = "nan";
 	  wspecial = L"nan";
-	  // fpnum_sign = 0;	Already zero
+	  // is_neg = 0;	Already zero
 	}
-      else if ((res = __isinf (fpnum.dbl.d)))
+      else if (isinf (fpnum.dbl.d))
 	{
-	  fpnum_sign = res;
+	  is_neg = signbit (fpnum.dbl.d);
 	  special = "inf";
 	  wspecial = L"inf";
 	}
@@ -175,14 +174,14 @@  __printf_size (FILE *fp, const struct printf_info *info,
     {
       int width = info->prec > info->width ? info->prec : info->width;
 
-      if (fpnum_sign < 0 || info->showsign || info->space)
+      if (is_neg || info->showsign || info->space)
 	--width;
       width -= 3;
 
       if (!info->left && width > 0)
 	PADN (' ', width);
 
-      if (fpnum_sign < 0)
+      if (is_neg)
 	outchar ('-');
       else if (info->showsign)
 	outchar ('+');