aarch64: Implement math acceleration via builtins

This patch converts asm statements into builtins for AArch64.  As an
example for the file sysdeps/aarch64/fpu/s_ceil.c, we convert the
function from

double
__ceil (double x)
{
  double result;
  asm ("frintp\t%d0, %d1" :
       "=w" (result) : "w" (x) );
  return result;
}

into

double
__ceil (double x)
{
  return __builtin_ceil (x);
}

Tested on aarch64-linux-gnu with gcc-4.9.4 and gcc-6.

	* sysdeps/aarch64/fpu/e_sqrt.c (ieee754_sqrt): Replace asm statements
	with __builtin_sqrt.
	* sysdeps/aarch64/fpu/e_sqrtf.c (ieee754_sqrtf): Replace asm statements
	with __builtin_sqrtf.
	* sysdeps/aarch64/fpu/s_ceil.c (__ceil): Replace asm statements
	with __builtin_ceil.
	* sysdeps/aarch64/fpu/s_ceilf.c (__ceilf): Replace asm statements
	with __builtin_ceilf.
	* sysdeps/aarch64/fpu/s_floor.c (__floor): Replace asm statements
	with __builtin_floor.
	* sysdeps/aarch64/fpu/s_floorf.c (__floorf): Replace asm statements
	with __builtin_floorf.
	* sysdeps/aarch64/fpu/s_fma.c (__fma): Replace asm statements
	with __builtin_fma.
	* sysdeps/aarch64/fpu/s_fmaf.c (__fmaf): Replace asm statements
	with __builtin_fmaf.
	* sysdeps/aarch64/fpu/s_fmax.c (__fmax): Replace asm statements
	with __builtin_fmax.
	* sysdeps/aarch64/fpu/s_fmaxf.c (__fmaxf): Replace asm statements
	with __builtin_fmaxf.
	* sysdeps/aarch64/fpu/s_fmin.c (__fmin): Replace asm statements
	with __builtin_fmin.
	* sysdeps/aarch64/fpu/s_fminf.c (__fminf): Replace asm statements
	with __builtin_fminf.
	* sysdeps/aarch64/fpu/s_frint.c: Delete file.
	* sysdeps/aarch64/fpu/s_frintf.c: Delete file.
	* sysdeps/aarch64/fpu/s_llrint.c (__llrint): Replace asm statements
	with builtin_rint and conversion to int.
	* sysdeps/aarch64/fpu/s_llrintf.c (__llrintf): Likewise.
	* sysdeps/aarch64/fpu/s_llround.c (__llround): Replace asm statements
	with builtin_llround.
	* sysdeps/aarch64/fpu/s_llroundf.c (__llroundf): Likewise.
	* sysdeps/aarch64/fpu/s_lrint.c (__lrint): Replace asm statements
	with builtin_rint and conversion to long int.
	* sysdeps/aarch64/fpu/s_lrintf.c (__lrintf): Likewise.
	* sysdeps/aarch64/fpu/s_lround.c (__lround): Replace asm statements
	with builtin_lround.
	* sysdeps/aarch64/fpu/s_lroundf.c (__lroundf): Replace asm statements
	with builtin_lroundf.
	* sysdeps/aarch64/fpu/s_nearbyint.c (__nearbyint): Replace asm
	statements with __builtin_nearbyint.
	* sysdeps/aarch64/fpu/s_nearbyintf.c (__nearbyintf): Replace asm
	statements with __builtin_nearbyintf.
	* sysdeps/aarch64/fpu/s_rint.c (__rint): Replace asm statements
	with __builtin_rint.
	* sysdeps/aarch64/fpu/s_rintf.c (__rintf): Replace asm statements
	with __builtin_rintf.
	* sysdeps/aarch64/fpu/s_round.c (__round): Replace asm statements
	with __builtin_round.
	* sysdeps/aarch64/fpu/s_roundf.c (__roundf): Replace asm statements
	with __builtin_roundf.
	* sysdeps/aarch64/fpu/s_trunc.c (__trunc): Replace asm statements
	with __builtin_trunc.
	* sysdeps/aarch64/fpu/s_truncf.c (__truncf): Replace asm statements
	with __builtin_truncf.
	* sysdeps/aarch64/fpu/Makefile: Build e_sqrt[f].c with -fno-math-errno.
This commit is contained in:
Michael Collison 2017-10-23 10:28:01 +01:00 committed by Szabolcs Nagy
parent 174935af03
commit 5062680c60
31 changed files with 309 additions and 288 deletions

View File

@ -1,3 +1,62 @@
2017-10-23 Michael Collison <michael.collison@arm.com>
* sysdeps/aarch64/fpu/e_sqrt.c (ieee754_sqrt): Replace asm statements
with __builtin_sqrt.
* sysdeps/aarch64/fpu/e_sqrtf.c (ieee754_sqrtf): Replace asm statements
with __builtin_sqrtf.
* sysdeps/aarch64/fpu/s_ceil.c (__ceil): Replace asm statements
with __builtin_ceil.
* sysdeps/aarch64/fpu/s_ceilf.c (__ceilf): Replace asm statements
with __builtin_ceilf.
* sysdeps/aarch64/fpu/s_floor.c (__floor): Replace asm statements
with __builtin_floor.
* sysdeps/aarch64/fpu/s_floorf.c (__floorf): Replace asm statements
with __builtin_floorf.
* sysdeps/aarch64/fpu/s_fma.c (__fma): Replace asm statements
with __builtin_fma.
* sysdeps/aarch64/fpu/s_fmaf.c (__fmaf): Replace asm statements
with __builtin_fmaf.
* sysdeps/aarch64/fpu/s_fmax.c (__fmax): Replace asm statements
with __builtin_fmax.
* sysdeps/aarch64/fpu/s_fmaxf.c (__fmaxf): Replace asm statements
with __builtin_fmaxf.
* sysdeps/aarch64/fpu/s_fmin.c (__fmin): Replace asm statements
with __builtin_fmin.
* sysdeps/aarch64/fpu/s_fminf.c (__fminf): Replace asm statements
with __builtin_fminf.
* sysdeps/aarch64/fpu/s_frint.c: Delete file.
* sysdeps/aarch64/fpu/s_frintf.c: Delete file.
* sysdeps/aarch64/fpu/s_llrint.c (__llrint): Replace asm statements
with builtin_rint and conversion to int.
* sysdeps/aarch64/fpu/s_llrintf.c (__llrintf): Likewise.
* sysdeps/aarch64/fpu/s_llround.c (__llround): Replace asm statements
with builtin_llround.
* sysdeps/aarch64/fpu/s_llroundf.c (__llroundf): Likewise.
* sysdeps/aarch64/fpu/s_lrint.c (__lrint): Replace asm statements
with builtin_rint and conversion to long int.
* sysdeps/aarch64/fpu/s_lrintf.c (__lrintf): Likewise.
* sysdeps/aarch64/fpu/s_lround.c (__lround): Replace asm statements
with builtin_lround.
* sysdeps/aarch64/fpu/s_lroundf.c (__lroundf): Replace asm statements
with builtin_lroundf.
* sysdeps/aarch64/fpu/s_nearbyint.c (__nearbyint): Replace asm
statements with __builtin_nearbyint.
* sysdeps/aarch64/fpu/s_nearbyintf.c (__nearbyintf): Replace asm
statements with __builtin_nearbyintf.
* sysdeps/aarch64/fpu/s_rint.c (__rint): Replace asm statements
with __builtin_rint.
* sysdeps/aarch64/fpu/s_rintf.c (__rintf): Replace asm statements
with __builtin_rintf.
* sysdeps/aarch64/fpu/s_round.c (__round): Replace asm statements
with __builtin_round.
* sysdeps/aarch64/fpu/s_roundf.c (__roundf): Replace asm statements
with __builtin_roundf.
* sysdeps/aarch64/fpu/s_trunc.c (__trunc): Replace asm statements
with __builtin_trunc.
* sysdeps/aarch64/fpu/s_truncf.c (__truncf): Replace asm statements
with __builtin_truncf.
* sysdeps/aarch64/fpu/Makefile: Build e_sqrt[f].c with -fno-math-errno.
2017-10-23 Alan Modra <amodra@gmail.com>
* sysdeps/powerpc/powerpc64/power8/strncpy.S: Move LR cfi.

View File

@ -21,8 +21,6 @@
double
__ieee754_sqrt (double d)
{
double res;
asm ("fsqrt %d0, %d1" : "=w" (res) : "w" (d));
return res;
return __builtin_sqrt (d);
}
strong_alias (__ieee754_sqrt, __sqrt_finite)

View File

@ -21,8 +21,6 @@
float
__ieee754_sqrtf (float s)
{
float res;
asm ("fsqrt %s0, %s1" : "=w" (res) : "w" (s));
return res;
return __builtin_sqrtf (s);
}
strong_alias (__ieee754_sqrtf, __sqrtf_finite)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC ceil
#define INSN "frintp"
#include <s_frint.c>
#include <math.h>
double
__ceil (double x)
{
return __builtin_ceil (x);
}
weak_alias (__ceil, ceil)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC ceilf
#define INSN "frintp"
#include <s_frintf.c>
#include <math.h>
float
__ceilf (float x)
{
return __builtin_ceilf (x);
}
weak_alias (__ceilf, ceilf)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC floor
#define INSN "frintm"
#include <s_frint.c>
#include <math.h>
double
__floor (double x)
{
return __builtin_floor (x);
}
weak_alias (__floor, floor)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC floorf
#define INSN "frintm"
#include <s_frintf.c>
#include <math.h>
float
__floorf (float x)
{
return __builtin_floorf (x);
}
weak_alias (__floorf, floorf)

View File

@ -18,28 +18,10 @@
#include <math.h>
#ifndef FUNC
# define FUNC fma
#endif
#ifndef TYPE
# define TYPE double
# define REGS "d"
#else
# ifndef REGS
# error REGS not defined
# endif
#endif
#define __CONCATX(a,b) __CONCAT(a,b)
TYPE
__CONCATX(__,FUNC) (TYPE x, TYPE y, TYPE z)
double
__fma (double x, double y, double z)
{
TYPE result;
asm ( "fmadd" "\t%" REGS "0, %" REGS "1, %" REGS "2, %" REGS "3"
: "=w" (result) : "w" (x), "w" (y), "w" (z) );
return result;
return __builtin_fma (x, y, z);
}
weak_alias (__CONCATX(__,FUNC), FUNC)
weak_alias (__fma, fma)

View File

@ -16,7 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC fmaf
#define TYPE float
#define REGS "s"
#include <s_fma.c>
#include <math.h>
float
__fmaf (float x, float y, float z)
{
return __builtin_fmaf (x, y, z);
}
weak_alias (__fmaf, fmaf)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC fmax
#define INSN "fmaxnm"
#include <fpu/s_fmin.c>
#include <math.h>
double
__fmax (double x, double y)
{
return __builtin_fmax (x, y);
}
weak_alias (__fmax, fmax)

View File

@ -16,8 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC fmaxf
#define INSN "fmaxnm"
#define TYPE float
#define REGS "s"
#include <fpu/s_fmin.c>
#include <math.h>
float
__fmaxf (float x, float y)
{
return __builtin_fmaxf (x, y);
}
weak_alias (__fmaxf, fmaxf)

View File

@ -18,32 +18,10 @@
#include <math.h>
#ifndef FUNC
# define FUNC fmin
#endif
#ifndef INSN
# define INSN "fminnm"
#endif
#ifndef TYPE
# define TYPE double
# define REGS "d"
#else
# ifndef REGS
# error REGS not defined
# endif
#endif
#define __CONCATX(a,b) __CONCAT(a,b)
TYPE
__CONCATX(__,FUNC) (TYPE x, TYPE y)
double
__fmin (double x, double y)
{
TYPE result;
asm ( INSN "\t%" REGS "0, %" REGS "1, %" REGS "2"
: "=w" (result) : "w" (x), "w" (y) );
return result;
return __builtin_fmin (x, y);
}
weak_alias (__CONCATX(__,FUNC), FUNC)
weak_alias (__fmin, fmin)

View File

@ -16,7 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC fminf
#define TYPE float
#define REGS "s"
#include <fpu/s_fmin.c>
#include <math.h>
float
__fminf (float x, float y)
{
return __builtin_fminf (x, y);
}
weak_alias (__fminf, fminf)

View File

@ -1,49 +0,0 @@
/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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>
#ifndef FUNC
# error FUNC not defined
#endif
#ifndef TYPE
# define TYPE double
# define REGS "d"
#else
# ifndef REGS
# error REGS not defined
# endif
#endif
#ifndef INSN
# error INSN not defined
#endif
#define __CONCATX(a,b) __CONCAT(a,b)
TYPE
__CONCATX(__,FUNC) (TYPE x)
{
TYPE result;
asm ( INSN "\t%" REGS "0, %" REGS "1" :
"=w" (result) : "w" (x) );
return result;
}
weak_alias (__CONCATX(__,FUNC), FUNC)

View File

@ -1,24 +0,0 @@
/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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/>. */
#ifndef FUNC
# error FUNC not defined
#endif
#define TYPE float
#define REGS "s"
#include <s_frint.c>

View File

@ -16,7 +16,19 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC llrint
#define OTYPE long long int
#define OREG_SIZE 64
#include <s_lrint.c>
#include <math.h>
#include <math_private.h>
long long int
__llrint (double x)
{
double r = __builtin_rint (x);
/* Prevent gcc from calling llrint directly when compiled with
-fno-math-errno by inserting a barrier. */
math_opt_barrier (r);
return r;
}
weak_alias (__llrint, llrint)

View File

@ -16,9 +16,20 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC llrintf
#define ITYPE float
#define IREG_SIZE 32
#define OTYPE long long int
#define OREG_SIZE 64
#include <s_lrint.c>
#include <math.h>
#include <math_private.h>
long long int
__llrintf (float x)
{
float r = __builtin_rintf (x);
/* Prevent gcc from calling llrintf directly when compiled with
-fno-math-errno by inserting a barrier. */
math_opt_barrier (r);
return r;
}
weak_alias (__llrintf, llrintf)

View File

@ -16,7 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC llround
#define OTYPE long long int
#define OREG_SIZE 64
#include <s_lround.c>
#include <math.h>
long long int
__llround (double x)
{
return __builtin_llround (x);
}
weak_alias (__llround, llround)

View File

@ -16,9 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC llroundf
#define ITYPE float
#define IREG_SIZE 32
#define OTYPE long long int
#define OREG_SIZE 64
#include <s_lround.c>
#include <math.h>
long long int
__llroundf (float x)
{
return __builtin_llroundf (x);
}
weak_alias (__llroundf, llroundf)

View File

@ -19,38 +19,17 @@
#include <math.h>
#include <get-rounding-mode.h>
#include <stdint.h>
#include <math_private.h>
#ifndef FUNC
# define FUNC lrint
#endif
#ifndef ITYPE
# define ITYPE double
# define IREG_SIZE 64
#else
# ifndef IREG_SIZE
# error IREG_SIZE not defined
# endif
#endif
#ifndef OTYPE
# define OTYPE long int
# ifdef __ILP32__
# define OREG_SIZE 32
# else
# define OREG_SIZE 64
# endif
#else
# ifndef OREG_SIZE
# error OREG_SIZE not defined
# endif
#endif
#if IREG_SIZE == 32
# define IREGS "s"
#else
# define IREGS "d"
#endif
#if OREG_SIZE == 32
# define OREGS "w"
@ -58,15 +37,14 @@
# define OREGS "x"
#endif
#define __CONCATX(a,b) __CONCAT(a,b)
OTYPE
__CONCATX(__,FUNC) (ITYPE x)
long int
__lrint (double x)
{
OTYPE result;
ITYPE temp;
#if IREG_SIZE == 64 && OREG_SIZE == 32
long int result;
if (__builtin_fabs (x) > INT32_MAX)
{
/* Converting large values to a 32 bit int may cause the frintx/fcvtza
@ -96,10 +74,14 @@ __CONCATX(__,FUNC) (ITYPE x)
return result;
}
#endif
asm ( "frintx" "\t%" IREGS "1, %" IREGS "2\n\t"
"fcvtzs" "\t%" OREGS "0, %" IREGS "1"
: "=r" (result), "=w" (temp) : "w" (x) );
return result;
double r = __builtin_rint (x);
/* Prevent gcc from calling lrint directly when compiled with
-fno-math-errno by inserting a barrier. */
math_opt_barrier (r);
return r;
}
weak_alias (__CONCATX(__,FUNC), FUNC)
weak_alias (__lrint, lrint)

View File

@ -16,7 +16,19 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC lrintf
#define ITYPE float
#define IREG_SIZE 32
#include <s_lrint.c>
#include <math.h>
#include <math_private.h>
long int
__lrintf (float x)
{
float r = __builtin_rintf (x);
/* Prevent gcc from calling lrintf directly when compiled with
-fno-math-errno by inserting a barrier. */
math_opt_barrier (r);
return r;
}
weak_alias (__lrintf, lrintf)

View File

@ -18,53 +18,10 @@
#include <math.h>
#ifndef FUNC
# define FUNC lround
#endif
long int
__lround (double x)
{
return __builtin_lround (x);
}
#ifndef ITYPE
# define ITYPE double
# define IREG_SIZE 64
#else
# ifndef IREG_SIZE
# error IREG_SIZE not defined
# endif
#endif
#ifndef OTYPE
# define OTYPE long int
# ifdef __ILP32__
# define OREG_SIZE 32
# else
# define OREG_SIZE 64
# endif
#else
# ifndef OREG_SIZE
# error OREG_SIZE not defined
# endif
#endif
#if IREG_SIZE == 32
# define IREGS "s"
#else
# define IREGS "d"
#endif
#if OREG_SIZE == 32
# define OREGS "w"
#else
# define OREGS "x"
#endif
#define __CONCATX(a,b) __CONCAT(a,b)
OTYPE
__CONCATX(__,FUNC) (ITYPE x)
{
OTYPE result;
asm ( "fcvtas" "\t%" OREGS "0, %" IREGS "1"
: "=r" (result) : "w" (x) );
return result;
}
weak_alias (__CONCATX(__,FUNC), FUNC)
weak_alias (__lround, lround)

View File

@ -16,7 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC lroundf
#define ITYPE float
#define IREG_SIZE 32
#include <s_lround.c>
#include <math.h>
long int
__lroundf (float x)
{
return __builtin_lroundf (x);
}
weak_alias (__lroundf, lroundf)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC nearbyint
#define INSN "frinti"
#include <s_frint.c>
#include <math.h>
double
__nearbyint (double x)
{
return __builtin_nearbyint (x);
}
weak_alias (__nearbyint, nearbyint)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC nearbyintf
#define INSN "frinti"
#include <s_frintf.c>
#include <math.h>
float
__nearbyintf (float x)
{
return __builtin_nearbyintf (x);
}
weak_alias (__nearbyintf, nearbyintf)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC rint
#define INSN "frintx"
#include <s_frint.c>
#include <math.h>
double
__rint (double x)
{
return __builtin_rint (x);
}
weak_alias (__rint, rint)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC rintf
#define INSN "frintx"
#include <s_frintf.c>
#include <math.h>
float
__rintf (float x)
{
return __builtin_rintf (x);
}
weak_alias (__rintf, rintf)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC round
#define INSN "frinta"
#include <s_frint.c>
#include <math.h>
double
__round (double x)
{
return __builtin_round (x);
}
weak_alias (__round, round)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC roundf
#define INSN "frinta"
#include <s_frintf.c>
#include <math.h>
float
__roundf (float x)
{
return __builtin_roundf (x);
}
weak_alias (__roundf, roundf)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC trunc
#define INSN "frintz"
#include <s_frint.c>
#include <math.h>
double
__trunc (double x)
{
return __builtin_trunc (x);
}
weak_alias (__trunc, trunc)

View File

@ -16,6 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define FUNC truncf
#define INSN "frintz"
#include <s_frintf.c>
#include <math.h>
float
__truncf (float x)
{
return __builtin_truncf (x);
}
weak_alias (__truncf, truncf)