[compiler-rt] r204999 - Add instrastructure for IEEE quad precision.

Joerg Sonnenberger joerg at bec.de
Fri Mar 28 03:29:32 PDT 2014


Author: joerg
Date: Fri Mar 28 05:29:31 2014
New Revision: 204999

URL: http://llvm.org/viewvc/llvm-project?rev=204999&view=rev
Log:
Add instrastructure for IEEE quad precision.
Based on patch from GuanHong Liu.

Differential Revision: http://llvm-reviews.chandlerc.com/D2796

Modified:
    compiler-rt/trunk/lib/builtins/fp_lib.h

Modified: compiler-rt/trunk/lib/builtins/fp_lib.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/fp_lib.h?rev=204999&r1=204998&r2=204999&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/fp_lib.h (original)
+++ compiler-rt/trunk/lib/builtins/fp_lib.h Fri Mar 28 05:29:31 2014
@@ -12,9 +12,9 @@
 // many useful constants and utility routines that are used in the
 // implementation of the soft-float routines in compiler-rt.
 //
-// Assumes that float and double correspond to the IEEE-754 binary32 and
-// binary64 types, respectively, and that integer endianness matches floating
-// point endianness on the target platform.
+// Assumes that float, double and long double correspond to the IEEE-754
+// binary32, binary64 and binary 128 types, respectively, and that integer
+// endianness matches floating point endianness on the target platform.
 //
 //===----------------------------------------------------------------------===//
 
@@ -59,7 +59,7 @@ static inline int rep_clz(rep_t a) {
 #else
     if (a & REP_C(0xffffffff00000000))
         return __builtin_clz(a >> 32);
-    else 
+    else
         return 32 + __builtin_clz(a & REP_C(0xffffffff));
 #endif
 }
@@ -86,10 +86,118 @@ static inline void wideMultiply(rep_t a,
 #undef loWord
 #undef hiWord
 
+#elif defined QUAD_PRECISION
+#if __LDBL_MANT_DIG__ == 113
+#define CRT_LDBL_128BIT
+typedef __uint128_t rep_t;
+typedef __int128_t srep_t;
+typedef long double fp_t;
+#define REP_C (__uint128_t)
+// Note: Since there is no explicit way to tell compiler the constant is a
+// 128-bit integer, we let the constant be casted to 128-bit integer
+#define significandBits 112
+
+static inline int rep_clz(rep_t a) {
+    const union
+        {
+             __uint128_t ll;
+#if _YUGA_BIG_ENDIAN
+             struct { uint64_t high, low; } s;
 #else
-#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
+             struct { uint64_t low, high; } s;
 #endif
+        } uu = { .ll = a };
+
+    uint64_t word;
+    uint64_t add;
 
+    if (uu.s.high){
+        word = uu.s.high;
+        add = 0;
+    }
+    else{
+        word = uu.s.low;
+        add = 64;
+    }
+    return __builtin_clzll(word) + add;
+}
+
+#define Word_LoMask   UINT64_C(0x00000000ffffffff)
+#define Word_HiMask   UINT64_C(0xffffffff00000000)
+#define Word_FullMask UINT64_C(0xffffffffffffffff)
+#define Word_1(a) (uint64_t)((a >> 96) & Word_LoMask)
+#define Word_2(a) (uint64_t)((a >> 64) & Word_LoMask)
+#define Word_3(a) (uint64_t)((a >> 32) & Word_LoMask)
+#define Word_4(a) (uint64_t)(a & Word_LoMask)
+
+// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
+// many 64-bit platforms have this operation, but they tend to have hardware
+// floating-point, so we don't bother with a special case for them here.
+static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
+
+    const uint64_t product11 = Word_1(a) * Word_1(b);
+    const uint64_t product12 = Word_1(a) * Word_2(b);
+    const uint64_t product13 = Word_1(a) * Word_3(b);
+    const uint64_t product14 = Word_1(a) * Word_4(b);
+    const uint64_t product21 = Word_2(a) * Word_1(b);
+    const uint64_t product22 = Word_2(a) * Word_2(b);
+    const uint64_t product23 = Word_2(a) * Word_3(b);
+    const uint64_t product24 = Word_2(a) * Word_4(b);
+    const uint64_t product31 = Word_3(a) * Word_1(b);
+    const uint64_t product32 = Word_3(a) * Word_2(b);
+    const uint64_t product33 = Word_3(a) * Word_3(b);
+    const uint64_t product34 = Word_3(a) * Word_4(b);
+    const uint64_t product41 = Word_4(a) * Word_1(b);
+    const uint64_t product42 = Word_4(a) * Word_2(b);
+    const uint64_t product43 = Word_4(a) * Word_3(b);
+    const uint64_t product44 = Word_4(a) * Word_4(b);
+
+    const __uint128_t sum0 = (__uint128_t)product44;
+    const __uint128_t sum1 = (__uint128_t)product34 +
+                             (__uint128_t)product43;
+    const __uint128_t sum2 = (__uint128_t)product24 +
+                             (__uint128_t)product33 +
+                             (__uint128_t)product42;
+    const __uint128_t sum3 = (__uint128_t)product14 +
+                             (__uint128_t)product23 +
+                             (__uint128_t)product32 +
+                             (__uint128_t)product41;
+    const __uint128_t sum4 = (__uint128_t)product13 +
+                             (__uint128_t)product22 +
+                             (__uint128_t)product31;
+    const __uint128_t sum5 = (__uint128_t)product12 +
+                             (__uint128_t)product21;
+    const __uint128_t sum6 = (__uint128_t)product11;
+
+    const __uint128_t r0 = (sum0 & Word_FullMask) +
+                           ((sum1 & Word_LoMask) << 32);
+    const __uint128_t r1 = (sum0 >> 64) +
+                           ((sum1 >> 32) & Word_FullMask) +
+                           (sum2 & Word_FullMask) +
+                           ((sum3 << 32) & Word_HiMask);
+
+    *lo = r0 + (r1 << 64);
+    *hi = (r1 >> 64) +
+          (sum1 >> 96) +
+          (sum2 >> 64) +
+          (sum3 >> 32) +
+          sum4 +
+          (sum5 << 32) +
+          (sum6 << 64);
+}
+#undef Word_1
+#undef Word_2
+#undef Word_3
+#undef Word_4
+#undef Word_HiMask
+#undef Word_LoMask
+#undef Word_FullMask
+#endif // __LDBL_MANT_DIG__ == 113
+#else
+#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
+#endif
+
+#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || defined(CRT_LDBL_128BIT)
 #define typeWidth       (sizeof(rep_t)*CHAR_BIT)
 #define exponentBits    (typeWidth - significandBits - 1)
 #define maxExponent     ((1 << exponentBits) - 1)
@@ -142,7 +250,7 @@ static inline void wideRightShiftWithSti
         *hi = 0;
     }
 }
-
+#endif
 COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
 COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b);
 





More information about the llvm-commits mailing list