[PATCH] [COMPILER_RT] add long double setting in fp_lib.h

GuanHong Liu koviankevin at hotmail.com
Tue Feb 25 19:25:13 PST 2014


  introduce CRT_LDBL_128BIT

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

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2796?vs=7105&id=7362#toc

Files:
  lib/builtins/fp_lib.h

Index: lib/builtins/fp_lib.h
===================================================================
--- lib/builtins/fp_lib.h
+++ lib/builtins/fp_lib.h
@@ -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 @@
 #else
     if (a & REP_C(0xffffffff00000000))
         return __builtin_clz(a >> 32);
-    else 
+    else
         return 32 + __builtin_clz(a & REP_C(0xffffffff));
 #endif
 }
@@ -84,10 +84,108 @@
     *hi = hiWord(plohi) + hiWord(philo) + hiWord(r1) + phihi;
 }
 
+#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
+             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_1(a) (uint64_t)((a >> 96) & 0xffffffffU)
+#define Word_2(a) (uint64_t)((a >> 64) & 0xffffffffU)
+#define Word_3(a) (uint64_t)((a >> 32) & 0xffffffffU)
+#define Word_4(a) (uint64_t)(a & 0xffffffffU)
+
+// 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 & 0xffffffffffffffff) +
+                           ((sum1 & 0xffffffff) << 32);
+    const __uint128_t r1 = (sum0 >> 64) +
+                           ((sum1 << 32) >> 64) +
+                           (sum2 & 0xffffffffffffffff) +
+                           ((sum3 & 0xffffffff) << 32);
+
+    *lo = r0 + (r1 << 64);
+    *hi = (r1 >> 64) +
+          (sum1 >> 96) +
+          (sum2 >> 64) +
+          (sum3 >> 32) +
+          sum4 +
+          (sum5 << 32) +
+          (sum6 << 64);
+}
+#endif // __LDBL_MANT_DIG__ == 113
 #else
-#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
+#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)
@@ -140,5 +238,5 @@
         *hi = 0;
     }
 }
-
+#endif
 #endif // FP_LIB_HEADER
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2796.2.patch
Type: text/x-patch
Size: 5293 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140225/7c31755b/attachment.bin>


More information about the llvm-commits mailing list