alpha: Remove s_ceil{f} and s_floor{f} implementation (BZ#22665)

As discussed in libc-alpha [1], alpha ceil{f} and floor{f}
implementation uses cvttq/svm and although the Alpha Architecture
Handbook version 3 states that that CVTfi OUTPUT Exceptions
(B.3 Mapping to IEEE Standard) should not generate Inexact if INE
bit is set on fpcr, the Alpha 21264 [1] chip manual (A.8 IEEE
Floating-Point Conformance) states that CVTfi and CVTif OUTPUT
does generate inexact exception for inexact result regardless.

As Joseph noted [2] to correctly fix it on alpha we need to either
avoid the instruction or avoid any inexact bit from it being set
on return from the function (while preserving the inexact bit that
might be set on the entry to the function).  The later will result
mf_fpcr followed by a mt_fpcr to get and set the fpcr which will
defeat the optimization itself.

So the patch just remove the alpha optimized and rely on generic
implementation.  It fixes the math/test-*-{ceil,floor} on alpha.

	[BZ #15479]
	[BZ #22665]
	* sysdeps/alpha/fpu/s_ceil.c: Remove file.
	* sysdeps/alpha/fpu/s_ceilf.c: Likewise.
	* sysdeps/alpha/fpu/s_floor.c: Likewise.
	* sysdeps/alpha/fpu/s_floorf.c: Likewise.

[1] https://www.star.bnl.gov/public/daq/HARDWARE/21264_data_sheet.pdf
[2] https://sourceware.org/ml/libc-alpha/2018-01/msg00086.html

Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
Adhemerval Zanella 2018-01-03 15:36:53 -02:00
parent 8a5df95ffa
commit 4854ddd874
5 changed files with 9 additions and 210 deletions

View File

@ -1,3 +1,12 @@
2018-01-03 Adhemerval Zanella <adhemerval.zanella@linaro.org>
[BZ #15479]
[BZ #22665]
* sysdeps/alpha/fpu/s_ceil.c: Remove file.
* sysdeps/alpha/fpu/s_ceilf.c: Likewise.
* sysdeps/alpha/fpu/s_floor.c: Likewise.
* sysdeps/alpha/fpu/s_floorf.c: Likewise.
2018-01-04 Florian Weimer <fweimer@redhat.com>
[BZ #22667]

View File

@ -1,50 +0,0 @@
/* Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <math_ldbl_opt.h>
#include <libm-alias-double.h>
/* Use the -inf rounding mode conversion instructions to implement
ceil, via something akin to -floor(-x). This is much faster than
playing with the fpcr to achieve +inf rounding mode. */
double
__ceil (double x)
{
if (isnan (x))
return x + x;
if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */
{
double tmp1, new_x;
new_x = -x;
__asm (
"cvttq/svm %2,%1\n\t"
"cvtqt/m %1,%0\n\t"
: "=f"(new_x), "=&f"(tmp1)
: "f"(new_x));
/* Fix up the negation we did above, as well as handling -0 properly. */
x = copysign(new_x, x);
}
return x;
}
libm_alias_double (__ceil, ceil)

View File

@ -1,54 +0,0 @@
/* Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <libm-alias-float.h>
/* Use the -inf rounding mode conversion instructions to implement
ceil, via something akin to -floor(-x). This is much faster than
playing with the fpcr to achieve +inf rounding mode. */
float
__ceilf (float x)
{
if (isnanf (x))
return x + x;
if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */
{
/* Note that Alpha S_Floating is stored in registers in a
restricted T_Floating format, so we don't even need to
convert back to S_Floating in the end. The initial
conversion to T_Floating is needed to handle denormals. */
float tmp1, tmp2, new_x;
new_x = -x;
__asm ("cvtst/s %3,%2\n\t"
"cvttq/svm %2,%1\n\t"
"cvtqt/m %1,%0\n\t"
: "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2)
: "f"(new_x));
/* Fix up the negation we did above, as well as handling -0 properly. */
x = copysignf(new_x, x);
}
return x;
}
libm_alias_float (__ceil, ceil)

View File

@ -1,51 +0,0 @@
/* Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <math_ldbl_opt.h>
#include <libm-alias-double.h>
/* Use the -inf rounding mode conversion instructions to implement
floor. We note when the exponent is large enough that the value
must be integral, as this avoids unpleasant integer overflows. */
double
__floor (double x)
{
if (isnan (x))
return x + x;
if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */
{
double tmp1, new_x;
__asm (
"cvttq/svm %2,%1\n\t"
"cvtqt/m %1,%0\n\t"
: "=f"(new_x), "=&f"(tmp1)
: "f"(x));
/* floor(-0) == -0, and in general we'll always have the same
sign as our input. */
x = copysign(new_x, x);
}
return x;
}
libm_alias_double (__floor, floor)

View File

@ -1,55 +0,0 @@
/* Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <libm-alias-float.h>
/* Use the -inf rounding mode conversion instructions to implement
floor. We note when the exponent is large enough that the value
must be integral, as this avoids unpleasant integer overflows. */
float
__floorf (float x)
{
if (isnanf (x))
return x + x;
if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */
{
/* Note that Alpha S_Floating is stored in registers in a
restricted T_Floating format, so we don't even need to
convert back to S_Floating in the end. The initial
conversion to T_Floating is needed to handle denormals. */
float tmp1, tmp2, new_x;
__asm ("cvtst/s %3,%2\n\t"
"cvttq/svm %2,%1\n\t"
"cvtqt/m %1,%0\n\t"
: "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2)
: "f"(x));
/* floor(-0) == -0, and in general we'll always have the same
sign as our input. */
x = copysignf(new_x, x);
}
return x;
}
libm_alias_float (__floor, floor)