diff mbox series

[committed] d: Add float and double overloads for all core.math intrinsics

Message ID 20201127202852.46858-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Add float and double overloads for all core.math intrinsics | expand

Commit Message

Iain Buclaw Nov. 27, 2020, 8:28 p.m. UTC
Hi,

For the math intrinsics: cos, fabs, ldexp, rint, rndtol, and sin, new
overloads have been added to the core.math module for matching float and
double types.  These have been implemented in the compiler.

A recent change to dump_function_to_file started triggering some
scan-tree-dump tests to FAIL, these have been adjusted as well when
updating the test.

Bootstrapped and regression tested on x86_64-linux-gnu with -mx32/-m32,
committed to mainline.

Regards
Iain.

---
gcc/d/ChangeLog:

	* intrinsics.cc (maybe_expand_intrinsic): Handle new intrinsics.
	* intrinsics.def (INTRINSIC_COS): Add float and double overloads.
	(INTRINSIC_FABS): Likewise.
	(INTRINSIC_LDEXP): Likewise.
	(INTRINSIC_RINT): Likewise.
	(INTRINSIC_RNDTOL): Likewise.
	(INTRINSIC_SIN): Likewise.
	(INTRINSIC_TOPREC): Adjust signature.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime 5e4492c4.

gcc/testsuite/ChangeLog:

	* gdc.dg/intrinsics.d: Adjust patterns in scan-tree-dump.
---
 gcc/d/intrinsics.cc               |  12 ++++
 gcc/d/intrinsics.def              |  20 ++++--
 gcc/testsuite/gdc.dg/intrinsics.d |  92 +++++++++++++++---------
 libphobos/libdruntime/MERGE       |   2 +-
 libphobos/libdruntime/core/math.d | 113 +++++++++++++++++-------------
 5 files changed, 151 insertions(+), 88 deletions(-)
diff mbox series

Patch

diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc
index a7de91019a4..4196ed3c552 100644
--- a/gcc/d/intrinsics.cc
+++ b/gcc/d/intrinsics.cc
@@ -814,10 +814,14 @@  maybe_expand_intrinsic (tree callexp)
     case INTRINSIC_CEIL:
     case INTRINSIC_CEILF:
     case INTRINSIC_CEILL:
+    case INTRINSIC_COS:
+    case INTRINSIC_COSF:
     case INTRINSIC_COSL:
     case INTRINSIC_EXP:
     case INTRINSIC_EXP2:
     case INTRINSIC_EXPM1:
+    case INTRINSIC_FABS:
+    case INTRINSIC_FABSF:
     case INTRINSIC_FABSL:
     case INTRINSIC_FLOOR:
     case INTRINSIC_FLOORF:
@@ -828,9 +832,15 @@  maybe_expand_intrinsic (tree callexp)
     case INTRINSIC_LOG:
     case INTRINSIC_LOG10:
     case INTRINSIC_LOG2:
+    case INTRINSIC_RINT:
+    case INTRINSIC_RINTF:
     case INTRINSIC_RINTL:
+    case INTRINSIC_RNDTOL:
+    case INTRINSIC_RNDTOLF:
     case INTRINSIC_RNDTOLL:
     case INTRINSIC_ROUND:
+    case INTRINSIC_SIN:
+    case INTRINSIC_SINF:
     case INTRINSIC_SINL:
     case INTRINSIC_SQRT:
     case INTRINSIC_SQRTF:
@@ -844,6 +854,8 @@  maybe_expand_intrinsic (tree callexp)
 
     case INTRINSIC_FMAX:
     case INTRINSIC_FMIN:
+    case INTRINSIC_LDEXP:
+    case INTRINSIC_LDEXPF:
     case INTRINSIC_LDEXPL:
       code = intrinsic_decls[intrinsic].built_in;
       gcc_assert (code != BUILT_IN_NONE);
diff --git a/gcc/d/intrinsics.def b/gcc/d/intrinsics.def
index 5b8cb712264..c05a6662865 100644
--- a/gcc/d/intrinsics.def
+++ b/gcc/d/intrinsics.def
@@ -93,22 +93,34 @@  DEF_D_BUILTIN (NEGSL, NONE, "negs", "core.checkedint", "FNaNbNiNflKbZl")
 
 /* core.math intrinsics.  */
 
+DEF_D_BUILTIN (COSF, COSF, "cos", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (COS, COS, "cos", "core.math", "FNaNbNiNfdZd")
 DEF_D_BUILTIN (COSL, COSL, "cos", "core.math", "FNaNbNiNfeZe")
+DEF_D_BUILTIN (FABSF, FABSL, "fabs", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (FABS, FABS, "fabs", "core.math", "FNaNbNiNfdZd")
 DEF_D_BUILTIN (FABSL, FABSL, "fabs", "core.math", "FNaNbNiNfeZe")
+DEF_D_BUILTIN (LDEXPF, LDEXPF, "ldexp", "core.math", "FNaNbNiNffiZf")
+DEF_D_BUILTIN (LDEXP, LDEXP, "ldexp", "core.math", "FNaNbNiNfdiZd")
 DEF_D_BUILTIN (LDEXPL, LDEXPL, "ldexp", "core.math", "FNaNbNiNfeiZe")
+DEF_D_BUILTIN (RINTF, RINTF, "rint", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (RINT, RINT, "rint", "core.math", "FNaNbNiNfdZd")
 DEF_D_BUILTIN (RINTL, RINTL, "rint", "core.math", "FNaNbNiNfeZe")
 
-/* Not sure if `llroundl' stands as a good replacement for the expected
+/* Not sure if `llround{f,l}' stands as a good replacement for the expected
    behavior of `rndtol()'.  */
+DEF_D_BUILTIN (RNDTOLF, LLROUNDF, "rndtol", "core.math", "FNaNbNiNffZl")
+DEF_D_BUILTIN (RNDTOL, LLROUND, "rndtol", "core.math", "FNaNbNiNfdZl")
 DEF_D_BUILTIN (RNDTOLL, LLROUNDL, "rndtol", "core.math", "FNaNbNiNfeZl")
 
+DEF_D_BUILTIN (SINF, SINF, "sin", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (SIN, SIN, "sin", "core.math", "FNaNbNiNfdZd")
 DEF_D_BUILTIN (SINL, SINL, "sin", "core.math", "FNaNbNiNfeZe")
 DEF_D_BUILTIN (SQRTF, SQRTF, "sqrt", "core.math", "FNaNbNiNffZf")
 DEF_D_BUILTIN (SQRT, SQRT, "sqrt", "core.math", "FNaNbNiNfdZd")
 DEF_D_BUILTIN (SQRTL, SQRTL, "sqrt", "core.math", "FNaNbNiNfeZe")
-DEF_D_BUILTIN (TOPRECF, NONE, "toPrec", "core.math", "FNaNbNffZI1T")
-DEF_D_BUILTIN (TOPREC, NONE, "toPrec", "core.math", "FNaNbNfdZI1T")
-DEF_D_BUILTIN (TOPRECL, NONE, "toPrec", "core.math", "FNaNbNfeZI1T")
+DEF_D_BUILTIN (TOPRECF, NONE, "toPrec", "core.math", "FfZI1T")
+DEF_D_BUILTIN (TOPREC, NONE, "toPrec", "core.math", "FdZI1T")
+DEF_D_BUILTIN (TOPRECL, NONE, "toPrec", "core.math", "FeZI1T")
 
 /* std.math intrinsics.  */
 
diff --git a/gcc/testsuite/gdc.dg/intrinsics.d b/gcc/testsuite/gdc.dg/intrinsics.d
index 5888361a438..a7752370582 100644
--- a/gcc/testsuite/gdc.dg/intrinsics.d
+++ b/gcc/testsuite/gdc.dg/intrinsics.d
@@ -8,65 +8,77 @@  import core.stdc.stdarg;
 //////////////////////////////////////////////////////
 // core.bitop
 
-// { dg-final { scan-tree-dump-not " bsf " "original" } }
+// { dg-final { scan-tree-dump " __builtin_ctz " "original" } }
 int test_bsf(uint a) { return bsf(a); }
+// { dg-final { scan-tree-dump " __builtin_ctz(l|ll) " "original" } }
 int test_bsf(ulong a) { return bsf(a); }
-// { dg-final { scan-tree-dump-not " bsr " "original" } }
+// { dg-final { scan-tree-dump " __builtin_clz " "original" } }
 int test_bsr(uint a) { return bsr(a); }
+// { dg-final { scan-tree-dump " __builtin_clz(l|ll) " "original" } }
 int test_bsr(ulong a) { return bsr(a); }
-// { dg-final { scan-tree-dump-not " bt " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = bt " "original" } }
 int test_bt(size_t *a, size_t b) { return bt(a, b); }
-// { dg-final { scan-tree-dump-not " btc " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = btc " "original" } }
 int test_btc(size_t *a, size_t b) { return btc(a, b); }
-// { dg-final { scan-tree-dump-not " btr " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = btr " "original" } }
 int test_btr(size_t *a, size_t b) { return btr(a, b); }
-// { dg-final { scan-tree-dump-not " bts " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = bts " "original" } }
 int test_bts(size_t *a, size_t b) { return bts(a, b); }
-// { dg-final { scan-tree-dump-not " bswap " "original" } }
+// { dg-final { scan-tree-dump " __builtin_bswap32 " "original" } }
 uint test_bswap(uint a) { return bswap(a); }
+// { dg-final { scan-tree-dump " __builtin_bswap64 " "original" } }
 ulong test_bswap(ulong a) { return bswap(a); }
-// { dg-final { scan-tree-dump-not " popcnt " "original" } }
+// { dg-final { scan-tree-dump " __builtin_popcount " "original" } }
 int test_popcnt(uint a) { return popcnt(a); }
+// { dg-final { scan-tree-dump " __builtin_popcount(l|ll) " "original" } }
 int test_popcnt(ulong a) { return popcnt(a); }
-// { dg-final { scan-tree-dump-not " volatileLoad " "original" } }
+// { dg-final { scan-tree-dump "\\(volatile ubyte \\*\\) a;" "original" } }
 ubyte test_volatileLoad(ubyte *a) { return volatileLoad(a); }
+// { dg-final { scan-tree-dump "\\(volatile ushort \\*\\) a;" "original" } }
 ushort test_volatileLoad(ushort *a) { return volatileLoad(a); }
+// { dg-final { scan-tree-dump "\\(volatile uint \\*\\) a;" "original" } }
 uint test_volatileLoad(uint *a) { return volatileLoad(a); }
+// { dg-final { scan-tree-dump "\\(volatile ulong \\*\\) a;" "original" } }
 ulong test_volatileLoad(ulong *a) { return volatileLoad(a); }
-// { dg-final { scan-tree-dump-not " volatileStore " "original" } }
+// { dg-final { scan-tree-dump "\\(volatile ubyte \\*\\) a = b" "original" } }
 void test_volatileStore(ubyte *a, ubyte b) { return volatileStore(a, b); }
+// { dg-final { scan-tree-dump "\\(volatile ushort \\*\\) a = b" "original" } }
 void test_volatileStore(ushort *a, ushort b) { return volatileStore(a, b); }
+// { dg-final { scan-tree-dump "\\(volatile uint \\*\\) a = b" "original" } }
 void test_volatileStore(uint *a, uint b) { return volatileStore(a, b); }
+// { dg-final { scan-tree-dump "\\(volatile ulong \\*\\) a = b" "original" } }
 void test_volatileStore(ulong *a, ulong b) { return volatileStore(a, b); }
-// { dg-final { scan-tree-dump-not " rol " "original" } }
+// { dg-final { scan-tree-dump " a r<< b;" "original" } }
 ubyte test_rol(ubyte a, uint b) { return rol!ubyte(a, b); }
+// { dg-final { scan-tree-dump " a r>> 31;" "original" } }
 uint test_rol(uint a) { return rol!(1, uint)(a); }
-// { dg-final { scan-tree-dump-not " ror " "original" } }
+// { dg-final { scan-tree-dump " a r>> b;" "original" } }
 ushort test_ror(ushort a, uint b) { return ror!ushort(a, b); }
+// { dg-final { scan-tree-dump " a r>> 1;" "original" } }
 ulong test_ror(ulong a) { return ror!(1, ulong)(a); }
 
 //////////////////////////////////////////////////////
 // core.checkedint
 
-// { dg-final { scan-tree-dump-not " adds " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = adds " "original" } }
 int test_adds(int a, int b, ref bool c) { return adds(a, b, c); }
 long test_adds(long a, long b, ref bool c) { return adds(a, b, c); }
-// { dg-final { scan-tree-dump-not " addu " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = addu " "original" } }
 uint test_addu(uint a, uint b, ref bool c) { return addu(a, b, c); }
 ulong test_addu(ulong a, ulong b, ref bool c) { return addu(a, b, c); }
-// { dg-final { scan-tree-dump-not " subs " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = subs " "original" } }
 int test_subs(int a, int b, ref bool c) { return subs(a, b, c); }
 long test_subs(long a, long b, ref bool c) { return subs(a, b, c); }
-// { dg-final { scan-tree-dump-not " subu " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = subu " "original" } }
 uint test_subu(uint a, uint b, ref bool c) { return subu(a, b, c); }
 ulong test_subu(ulong a, ulong b, ref bool c) { return subu(a, b, c); }
-// { dg-final { scan-tree-dump-not " negs " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = negs " "original" } }
 int test_negs(int a, ref bool b) { return negs(a, b); }
 long test_negs(long a, ref bool b) { return negs(a, b); }
-// { dg-final { scan-tree-dump-not " muls " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = muls " "original" } }
 int test_muls(int a, int b, ref bool c) { return muls(a, b, c); }
 long test_muls(long a, long b, ref bool c) { return muls(a, b, c); }
-// { dg-final { scan-tree-dump-not " mulu " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = mulu " "original" } }
 uint test_mulu(uint a, uint b, ref bool c) { return mulu(a, b, c); }
 ulong test_mulu(ulong a, uint b, ref bool c) { return mulu(a, b, c); }
 ulong test_mulu(ulong a, ulong b, ref bool c) { return mulu(a, b, c); }
@@ -74,50 +86,62 @@  ulong test_mulu(ulong a, ulong b, ref bool c) { return mulu(a, b, c); }
 //////////////////////////////////////////////////////
 // core.math
 
-// { dg-final { scan-tree-dump-not " cos " "original" } }
+// { dg-final { scan-tree-dump " __builtin_cosf " "original" } }
 float test_cos(float a) { return cos(a); }
+// { dg-final { scan-tree-dump " __builtin_cos " "original" } }
 double test_cos(double a) { return cos(a); }
+// { dg-final { scan-tree-dump " __builtin_cosl " "original" } }
 real test_cos(real a) { return cos(a); }
-// { dg-final { scan-tree-dump-not " sin " "original" } }
+// { dg-final { scan-tree-dump " __builtin_sinf " "original" } }
 float test_sin(float a) { return sin(a); }
+// { dg-final { scan-tree-dump " __builtin_sin " "original" } }
 double test_sin(double a) { return sin(a); }
+// { dg-final { scan-tree-dump " __builtin_sinl " "original" } }
 real test_sin(real a) { return sin(a); }
-// { dg-final { scan-tree-dump-not " rndtol " "original" } }
+// { dg-final { scan-tree-dump " __builtin_llroundf " "original" } }
 long test_rndtol(float a) { return rndtol(a); }
+// { dg-final { scan-tree-dump " __builtin_llround " "original" } }
 long test_rndtol(double a) { return rndtol(a); }
+// { dg-final { scan-tree-dump " __builtin_llroundl " "original" } }
 long test_rndtol(real a) { return rndtol(a); }
-// { dg-final { scan-tree-dump-not " sqrt " "original" } }
+// { dg-final { scan-tree-dump " __builtin_sqrtf " "original" } }
 float test_sqrt(float a) { return sqrt(a); }
+// { dg-final { scan-tree-dump " __builtin_sqrt " "original" } }
 double test_sqrt(double a) { return sqrt(a); }
+// { dg-final { scan-tree-dump " __builtin_sqrtl " "original" } }
 real test_sqrt(real a) { return sqrt(a); }
-// { dg-final { scan-tree-dump-not " ldexp " "original" } }
+// { dg-final { scan-tree-dump " __builtin_ldexpf " "original" } }
 float test_ldexp(float a, int b) { return ldexp(a, b); }
+// { dg-final { scan-tree-dump " __builtin_ldexp " "original" } }
 double test_ldexp(double a, int b) { return ldexp(a, b); }
+// { dg-final { scan-tree-dump " __builtin_ldexpl " "original" } }
 real test_ldexp(real a, int b) { return ldexp(a, b); }
-// { dg-final { scan-tree-dump-not " fabs " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = fabs " "original" } }
 float test_fabs(float a) { return fabs(a); }
 double test_fabs(double a) { return fabs(a); }
 real test_fabs(real a) { return fabs(a); }
-// { dg-final { scan-tree-dump-not " rint " "original" } }
+// { dg-final { scan-tree-dump " __builtin_rintf " "original" } }
 float test_rint(float a) { return rint(a); }
+// { dg-final { scan-tree-dump " __builtin_rint " "original" } }
 double test_rint(double a) { return rint(a); }
+// { dg-final { scan-tree-dump " __builtin_rintl " "original" } }
 real test_rint(real a) { return rint(a); }
-// { dg-final { scan-tree-dump-not " toPrec " "original" } }
-float test_toPrec(float a) { return toPrec!float(a); }
-float test_toPrec(double a) { return toPrec!float(a); }
-float test_toPrec(real a) { return toPrec!float(a); }
+// { dg-final { scan-tree-dump-not " <retval> = toPrec " "original" } }
+float test_toPrecf(float a) { return toPrec!float(a); }
+float test_toPrecf(double a) { return toPrec!float(a); }
+float test_toPrecf(real a) { return toPrec!float(a); }
 double test_toPrec(float a) { return toPrec!double(a); }
 double test_toPrec(double a) { return toPrec!double(a); }
 double test_toPrec(real a) { return toPrec!double(a); }
-real test_toPrec(float a) { return toPrec!real(a); }
-real test_toPrec(double a) { return toPrec!real(a); }
-real test_toPrec(real a) { return toPrec!real(a); }
+real test_toPrecl(float a) { return toPrec!real(a); }
+real test_toPrecl(double a) { return toPrec!real(a); }
+real test_toPrecl(real a) { return toPrec!real(a); }
 
 //////////////////////////////////////////////////////
 // core.stdc.stdarg
 
 // { dg-final { scan-tree-dump-not " va_arg " "original" } }
-void test_va_arg(...) { int a; return va_arg!int(_argptr, a); }
+void test_va_argc(...) { int a; return va_arg!int(_argptr, a); }
 int test_va_arg(...) { return va_arg!int(_argptr); }
 // { dg-final { scan-tree-dump-not " va_start " "original" } }
 void test_va_start(int a, ...) { return va_start(_argptr, a); }
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 485f8e999d6..91154eebdc9 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-58560d5163381b0f1c893bd0d035b7a0a1631f92
+5e4492c45172110b035591f5961b9f9f5adf6f13
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/core/math.d b/libphobos/libdruntime/core/math.d
index 219b4263ff2..4d46b67d2a3 100644
--- a/libphobos/libdruntime/core/math.d
+++ b/libphobos/libdruntime/core/math.d
@@ -1,4 +1,4 @@ 
-// Written in the D programming language.
+// Written in the D programming language.
 
 /**
  * Builtin mathematical intrinsics
@@ -19,15 +19,26 @@ 
  *      GT = &gt;
  *
  * Copyright: Copyright Digital Mars 2000 - 2011.
- * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors:   $(WEB digitalmars.com, Walter Bright),
+ * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ * Authors:   $(HTTP digitalmars.com, Walter Bright),
  *                        Don Clugston
  */
 module core.math;
 
 public:
 @nogc:
+nothrow:
+@safe:
 
+/*****************************************
+ * Returns x rounded to a long value using the FE_TONEAREST rounding mode.
+ * If the integer value of x is
+ * greater than long.max, the result is
+ * indeterminate.
+ */
+extern (C) real rndtonl(real x);
+
+pure:
 /***********************************
  * Returns cosine of x. x is in radians.
  *
@@ -40,7 +51,9 @@  public:
  *      Results are undefined if |x| >= $(POWER 2,64).
  */
 
-real cos(real x) @safe pure nothrow;       /* intrinsic */
+float cos(float x);     /* intrinsic */
+double cos(double x);   /* intrinsic */ /// ditto
+real cos(real x);       /* intrinsic */ /// ditto
 
 /***********************************
  * Returns sine of x. x is in radians.
@@ -55,7 +68,9 @@  real cos(real x) @safe pure nothrow;       /* intrinsic */
  *      Results are undefined if |x| >= $(POWER 2,64).
  */
 
-real sin(real x) @safe pure nothrow;       /* intrinsic */
+float sin(float x);     /* intrinsic */
+double sin(double x);   /* intrinsic */ /// ditto
+real sin(real x);       /* intrinsic */ /// ditto
 
 /*****************************************
  * Returns x rounded to a long value using the current rounding mode.
@@ -63,16 +78,10 @@  real sin(real x) @safe pure nothrow;       /* intrinsic */
  * greater than long.max, the result is
  * indeterminate.
  */
-long rndtol(real x) @safe pure nothrow;    /* intrinsic */
 
-
-/*****************************************
- * Returns x rounded to a long value using the FE_TONEAREST rounding mode.
- * If the integer value of x is
- * greater than long.max, the result is
- * indeterminate.
- */
-extern (C) real rndtonl(real x);
+long rndtol(float x);   /* intrinsic */
+long rndtol(double x);  /* intrinsic */ /// ditto
+long rndtol(real x);    /* intrinsic */ /// ditto
 
 /***************************************
  * Compute square root of x.
@@ -85,57 +94,65 @@  extern (C) real rndtonl(real x);
  *      )
  */
 
-@safe pure nothrow
-{
-    float sqrt(float x);    /* intrinsic */
-    double sqrt(double x);  /* intrinsic */ /// ditto
-    real sqrt(real x);      /* intrinsic */ /// ditto
-}
+float sqrt(float x);    /* intrinsic */
+double sqrt(double x);  /* intrinsic */ /// ditto
+real sqrt(real x);      /* intrinsic */ /// ditto
 
 /*******************************************
  * Compute n * 2$(SUPERSCRIPT exp)
  * References: frexp
  */
 
-real ldexp(real n, int exp) @safe pure nothrow;    /* intrinsic */
+float ldexp(float n, int exp);   /* intrinsic */
+double ldexp(double n, int exp); /* intrinsic */ /// ditto
+real ldexp(real n, int exp);     /* intrinsic */ /// ditto
 
 unittest {
     static if (real.mant_dig == 113)
     {
-        assert(ldexp(1, -16384) == 0x1p-16384L);
-        assert(ldexp(1, -16382) == 0x1p-16382L);
+        assert(ldexp(1.0L, -16384) == 0x1p-16384L);
+        assert(ldexp(1.0L, -16382) == 0x1p-16382L);
     }
     else static if (real.mant_dig == 106)
     {
-        assert(ldexp(1,  1023) == 0x1p1023L);
-        assert(ldexp(1, -1022) == 0x1p-1022L);
-        assert(ldexp(1, -1021) == 0x1p-1021L);
+        assert(ldexp(1.0L,  1023) == 0x1p1023L);
+        assert(ldexp(1.0L, -1022) == 0x1p-1022L);
+        assert(ldexp(1.0L, -1021) == 0x1p-1021L);
     }
     else static if (real.mant_dig == 64)
     {
-        assert(ldexp(1, -16384) == 0x1p-16384L);
-        assert(ldexp(1, -16382) == 0x1p-16382L);
+        assert(ldexp(1.0L, -16384) == 0x1p-16384L);
+        assert(ldexp(1.0L, -16382) == 0x1p-16382L);
     }
     else static if (real.mant_dig == 53)
     {
-        assert(ldexp(1,  1023) == 0x1p1023L);
-        assert(ldexp(1, -1022) == 0x1p-1022L);
-        assert(ldexp(1, -1021) == 0x1p-1021L);
+        assert(ldexp(1.0L,  1023) == 0x1p1023L);
+        assert(ldexp(1.0L, -1022) == 0x1p-1022L);
+        assert(ldexp(1.0L, -1021) == 0x1p-1021L);
     }
     else
         assert(false, "Only 128bit, 80bit and 64bit reals expected here");
 }
 
 /*******************************
- * Returns |x|
- *
+ * Compute the absolute value.
  *      $(TABLE_SV
  *      $(TR $(TH x)                 $(TH fabs(x)))
  *      $(TR $(TD $(PLUSMN)0.0)      $(TD +0.0) )
  *      $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) )
  *      )
+ * It is implemented as a compiler intrinsic.
+ * Params:
+ *      x = floating point value
+ * Returns: |x|
+ * References: equivalent to `std.math.fabs`
  */
-real fabs(real x) @safe pure nothrow;      /* intrinsic */
+@safe pure nothrow @nogc
+{
+    float  fabs(float  x);
+    double fabs(double x); /// ditto
+    real   fabs(real   x); /// ditto
+}
 
 /**********************************
  * Rounds x to the nearest integer value, using the current rounding
@@ -145,22 +162,29 @@  real fabs(real x) @safe pure nothrow;      /* intrinsic */
  * $(B nearbyint) performs
  * the same operation, but does not set the FE_INEXACT exception.
  */
-real rint(real x) @safe pure nothrow;      /* intrinsic */
+float rint(float x);    /* intrinsic */
+double rint(double x);  /* intrinsic */ /// ditto
+real rint(real x);      /* intrinsic */ /// ditto
 
 /***********************************
  * Building block functions, they
  * translate to a single x87 instruction.
  */
-
-real yl2x(real x, real y)   @safe pure nothrow;       // y * log2(x)
-real yl2xp1(real x, real y) @safe pure nothrow;       // y * log2(x + 1)
+// y * log2(x)
+float yl2x(float x, float y);    /* intrinsic */
+double yl2x(double x, double y);  /* intrinsic */ /// ditto
+real yl2x(real x, real y);      /* intrinsic */ /// ditto
+// y * log2(x +1)
+float yl2xp1(float x, float y);    /* intrinsic */
+double yl2xp1(double x, double y);  /* intrinsic */ /// ditto
+real yl2xp1(real x, real y);      /* intrinsic */ /// ditto
 
 unittest
 {
     version (INLINE_YL2X)
     {
-        assert(yl2x(1024, 1) == 10);
-        assert(yl2xp1(1023, 1) == 10);
+        assert(yl2x(1024.0L, 1) == 10);
+        assert(yl2xp1(1023.0L, 1) == 10);
     }
 }
 
@@ -179,31 +203,22 @@  unittest
  * Returns:
  *      f in precision of type `T`
  */
-@safe pure nothrow
 T toPrec(T:float)(float f) { pragma(inline, false); return f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:float)(double f) { pragma(inline, false); return cast(T) f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:float)(real f)  { pragma(inline, false); return cast(T) f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:double)(float f) { pragma(inline, false); return f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:double)(double f) { pragma(inline, false); return f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:double)(real f)  { pragma(inline, false); return cast(T) f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:real)(float f) { pragma(inline, false); return f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:real)(double f) { pragma(inline, false); return f; }
 /// ditto
-@safe pure nothrow
 T toPrec(T:real)(real f)  { pragma(inline, false); return f; }
 
 @safe unittest