1 // Copyright 2018 Ulf Adams
2 //
3 // The contents of this file may be used under the terms of the Apache License,
4 // Version 2.0.
5 //
6 //    (See accompanying file LICENSE-Apache or copy at
7 //     http://www.apache.org/licenses/LICENSE-2.0)
8 //
9 // Alternatively, the contents of this file may be used under the terms of
10 // the Boost Software License, Version 1.0.
11 //    (See accompanying file LICENSE-Boost or copy at
12 //     https://www.boost.org/LICENSE_1_0.txt)
13 //
14 // Unless required by applicable law or agreed to in writing, this software
15 // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 // KIND, either express or implied.
17 #ifndef RYU_D2S_INTRINSICS_H
18 #define RYU_D2S_INTRINSICS_H
19 
20 
21 // Defines RYU_32_BIT_PLATFORM if applicable.
22 
23 // ABSL avoids uint128_t on Win32 even if __SIZEOF_INT128__ is defined.
24 // Let's do the same for now.
25 #if defined(__SIZEOF_INT128__) && !defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS)
26 #define HAS_UINT128
27 #elif defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
28 #define HAS_64_BIT_INTRINSICS
29 #endif
30 
31 #if defined(HAS_64_BIT_INTRINSICS)
32 
33 
umul128(const uint64_t a,const uint64_t b,uint64_t * const productHi)34 static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
35   return _umul128(a, b, productHi);
36 }
37 
38 // Returns the lower 64 bits of (hi*2^64 + lo) >> dist, with 0 < dist < 64.
shiftright128(const uint64_t lo,const uint64_t hi,const uint32_t dist)39 static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
40   // For the __shiftright128 intrinsic, the shift value is always
41   // modulo 64.
42   // In the current implementation of the double-precision version
43   // of Ryu, the shift value is always < 64. (In the case
44   // RYU_OPTIMIZE_SIZE == 0, the shift value is in the range [49, 58].
45   // Otherwise in the range [2, 59].)
46   // However, this function is now also called by s2d, which requires supporting
47   // the larger shift range (TODO: what is the actual range?).
48   // Check this here in case a future change requires larger shift
49   // values. In this case this function needs to be adjusted.
50   assert(dist < 64);
51   return __shiftright128(lo, hi, (unsigned char) dist);
52 }
53 
54 #else // defined(HAS_64_BIT_INTRINSICS)
55 
umul128(const uint64_t a,const uint64_t b,uint64_t * const productHi)56 static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
57   // The casts here help MSVC to avoid calls to the __allmul library function.
58   const uint32_t aLo = (uint32_t)a;
59   const uint32_t aHi = (uint32_t)(a >> 32);
60   const uint32_t bLo = (uint32_t)b;
61   const uint32_t bHi = (uint32_t)(b >> 32);
62 
63   const uint64_t b00 = (uint64_t)aLo * bLo;
64   const uint64_t b01 = (uint64_t)aLo * bHi;
65   const uint64_t b10 = (uint64_t)aHi * bLo;
66   const uint64_t b11 = (uint64_t)aHi * bHi;
67 
68   const uint32_t b00Lo = (uint32_t)b00;
69   const uint32_t b00Hi = (uint32_t)(b00 >> 32);
70 
71   const uint64_t mid1 = b10 + b00Hi;
72   const uint32_t mid1Lo = (uint32_t)(mid1);
73   const uint32_t mid1Hi = (uint32_t)(mid1 >> 32);
74 
75   const uint64_t mid2 = b01 + mid1Lo;
76   const uint32_t mid2Lo = (uint32_t)(mid2);
77   const uint32_t mid2Hi = (uint32_t)(mid2 >> 32);
78 
79   const uint64_t pHi = b11 + mid1Hi + mid2Hi;
80   const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo;
81 
82   *productHi = pHi;
83   return pLo;
84 }
85 
shiftright128(const uint64_t lo,const uint64_t hi,const uint32_t dist)86 static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
87   // We don't need to handle the case dist >= 64 here (see above).
88   assert(dist < 64);
89   assert(dist > 0);
90   return (hi << (64 - dist)) | (lo >> dist);
91 }
92 
93 #endif // defined(HAS_64_BIT_INTRINSICS)
94 
95 #if defined(RYU_32_BIT_PLATFORM)
96 
97 // Returns the high 64 bits of the 128-bit product of a and b.
umulh(const uint64_t a,const uint64_t b)98 static inline uint64_t umulh(const uint64_t a, const uint64_t b) {
99   // Reuse the umul128 implementation.
100   // Optimizers will likely eliminate the instructions used to compute the
101   // low part of the product.
102   uint64_t hi;
103   umul128(a, b, &hi);
104   return hi;
105 }
106 
107 // On 32-bit platforms, compilers typically generate calls to library
108 // functions for 64-bit divisions, even if the divisor is a constant.
109 //
110 // E.g.:
111 // https://bugs.llvm.org/show_bug.cgi?id=37932
112 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17958
113 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37443
114 //
115 // The functions here perform division-by-constant using multiplications
116 // in the same way as 64-bit compilers would do.
117 //
118 // NB:
119 // The multipliers and shift values are the ones generated by clang x64
120 // for expressions like x/5, x/10, etc.
121 
div5(const uint64_t x)122 static inline uint64_t div5(const uint64_t x) {
123   return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2;
124 }
125 
div10(const uint64_t x)126 static inline uint64_t div10(const uint64_t x) {
127   return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3;
128 }
129 
div100(const uint64_t x)130 static inline uint64_t div100(const uint64_t x) {
131   return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2;
132 }
133 
div1e8(const uint64_t x)134 static inline uint64_t div1e8(const uint64_t x) {
135   return umulh(x, 0xABCC77118461CEFDu) >> 26;
136 }
137 
div1e9(const uint64_t x)138 static inline uint64_t div1e9(const uint64_t x) {
139   return umulh(x >> 9, 0x44B82FA09B5A53u) >> 11;
140 }
141 
mod1e9(const uint64_t x)142 static inline uint32_t mod1e9(const uint64_t x) {
143   // Avoid 64-bit math as much as possible.
144   // Returning (uint32_t) (x - 1000000000 * div1e9(x)) would
145   // perform 32x64-bit multiplication and 64-bit subtraction.
146   // x and 1000000000 * div1e9(x) are guaranteed to differ by
147   // less than 10^9, so their highest 32 bits must be identical,
148   // so we can truncate both sides to uint32_t before subtracting.
149   // We can also simplify (uint32_t) (1000000000 * div1e9(x)).
150   // We can truncate before multiplying instead of after, as multiplying
151   // the highest 32 bits of div1e9(x) can't affect the lowest 32 bits.
152   return ((uint32_t) x) - 1000000000 * ((uint32_t) div1e9(x));
153 }
154 
155 #else // defined(RYU_32_BIT_PLATFORM)
156 
div5(const uint64_t x)157 static inline uint64_t div5(const uint64_t x) {
158   return x / 5;
159 }
160 
div10(const uint64_t x)161 static inline uint64_t div10(const uint64_t x) {
162   return x / 10;
163 }
164 
div100(const uint64_t x)165 static inline uint64_t div100(const uint64_t x) {
166   return x / 100;
167 }
168 
div1e8(const uint64_t x)169 static inline uint64_t div1e8(const uint64_t x) {
170   return x / 100000000;
171 }
172 
div1e9(const uint64_t x)173 static inline uint64_t div1e9(const uint64_t x) {
174   return x / 1000000000;
175 }
176 
mod1e9(const uint64_t x)177 static inline uint32_t mod1e9(const uint64_t x) {
178   return (uint32_t) (x - 1000000000 * div1e9(x));
179 }
180 
181 #endif // defined(RYU_32_BIT_PLATFORM)
182 
pow5Factor(uint64_t value)183 static inline uint32_t pow5Factor(uint64_t value) {
184   uint32_t count = 0;
185   for (;;) {
186     assert(value != 0);
187     const uint64_t q = div5(value);
188     const uint32_t r = ((uint32_t) value) - 5 * ((uint32_t) q);
189     if (r != 0) {
190       break;
191     }
192     value = q;
193     ++count;
194   }
195   return count;
196 }
197 
198 // Returns true if value is divisible by 5^p.
multipleOfPowerOf5(const uint64_t value,const uint32_t p)199 static inline bool multipleOfPowerOf5(const uint64_t value, const uint32_t p) {
200   // I tried a case distinction on p, but there was no performance difference.
201   return pow5Factor(value) >= p;
202 }
203 
204 // Returns true if value is divisible by 2^p.
multipleOfPowerOf2(const uint64_t value,const uint32_t p)205 static inline bool multipleOfPowerOf2(const uint64_t value, const uint32_t p) {
206   assert(value != 0);
207   assert(p < 64);
208   // __builtin_ctzll doesn't appear to be faster here.
209   return (value & ((1ull << p) - 1)) == 0;
210 }
211 
212 // We need a 64x128-bit multiplication and a subsequent 128-bit shift.
213 // Multiplication:
214 //   The 64-bit factor is variable and passed in, the 128-bit factor comes
215 //   from a lookup table. We know that the 64-bit factor only has 55
216 //   significant bits (i.e., the 9 topmost bits are zeros). The 128-bit
217 //   factor only has 124 significant bits (i.e., the 4 topmost bits are
218 //   zeros).
219 // Shift:
220 //   In principle, the multiplication result requires 55 + 124 = 179 bits to
221 //   represent. However, we then shift this value to the right by j, which is
222 //   at least j >= 115, so the result is guaranteed to fit into 179 - 115 = 64
223 //   bits. This means that we only need the topmost 64 significant bits of
224 //   the 64x128-bit multiplication.
225 //
226 // There are several ways to do this:
227 // 1. Best case: the compiler exposes a 128-bit type.
228 //    We perform two 64x64-bit multiplications, add the higher 64 bits of the
229 //    lower result to the higher result, and shift by j - 64 bits.
230 //
231 //    We explicitly cast from 64-bit to 128-bit, so the compiler can tell
232 //    that these are only 64-bit inputs, and can map these to the best
233 //    possible sequence of assembly instructions.
234 //    x64 machines happen to have matching assembly instructions for
235 //    64x64-bit multiplications and 128-bit shifts.
236 //
237 // 2. Second best case: the compiler exposes intrinsics for the x64 assembly
238 //    instructions mentioned in 1.
239 //
240 // 3. We only have 64x64 bit instructions that return the lower 64 bits of
241 //    the result, i.e., we have to use plain C.
242 //    Our inputs are less than the full width, so we have three options:
243 //    a. Ignore this fact and just implement the intrinsics manually.
244 //    b. Split both into 31-bit pieces, which guarantees no internal overflow,
245 //       but requires extra work upfront (unless we change the lookup table).
246 //    c. Split only the first factor into 31-bit pieces, which also guarantees
247 //       no internal overflow, but requires extra work since the intermediate
248 //       results are not perfectly aligned.
249 #if defined(HAS_UINT128)
250 
251 // Best case: use 128-bit type.
mulShift64(const uint64_t m,const uint64_t * const mul,const int32_t j)252 static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
253   const uint128_t b0 = ((uint128_t) m) * mul[0];
254   const uint128_t b2 = ((uint128_t) m) * mul[1];
255   return (uint64_t) (((b0 >> 64) + b2) >> (j - 64));
256 }
257 
mulShiftAll64(const uint64_t m,const uint64_t * const mul,const int32_t j,uint64_t * const vp,uint64_t * const vm,const uint32_t mmShift)258 static inline uint64_t mulShiftAll64(const uint64_t m, const uint64_t* const mul, const int32_t j,
259   uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
260 //  m <<= 2;
261 //  uint128_t b0 = ((uint128_t) m) * mul[0]; // 0
262 //  uint128_t b2 = ((uint128_t) m) * mul[1]; // 64
263 //
264 //  uint128_t hi = (b0 >> 64) + b2;
265 //  uint128_t lo = b0 & 0xffffffffffffffffull;
266 //  uint128_t factor = (((uint128_t) mul[1]) << 64) + mul[0];
267 //  uint128_t vpLo = lo + (factor << 1);
268 //  *vp = (uint64_t) ((hi + (vpLo >> 64)) >> (j - 64));
269 //  uint128_t vmLo = lo - (factor << mmShift);
270 //  *vm = (uint64_t) ((hi + (vmLo >> 64) - (((uint128_t) 1ull) << 64)) >> (j - 64));
271 //  return (uint64_t) (hi >> (j - 64));
272   *vp = mulShift64(4 * m + 2, mul, j);
273   *vm = mulShift64(4 * m - 1 - mmShift, mul, j);
274   return mulShift64(4 * m, mul, j);
275 }
276 
277 #elif defined(HAS_64_BIT_INTRINSICS)
278 
mulShift64(const uint64_t m,const uint64_t * const mul,const int32_t j)279 static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
280   // m is maximum 55 bits
281   uint64_t high1;                                   // 128
282   const uint64_t low1 = umul128(m, mul[1], &high1); // 64
283   uint64_t high0;                                   // 64
284   umul128(m, mul[0], &high0);                       // 0
285   const uint64_t sum = high0 + low1;
286   if (sum < high0) {
287     ++high1; // overflow into high1
288   }
289   return shiftright128(sum, high1, j - 64);
290 }
291 
mulShiftAll64(const uint64_t m,const uint64_t * const mul,const int32_t j,uint64_t * const vp,uint64_t * const vm,const uint32_t mmShift)292 static inline uint64_t mulShiftAll64(const uint64_t m, const uint64_t* const mul, const int32_t j,
293   uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
294   *vp = mulShift64(4 * m + 2, mul, j);
295   *vm = mulShift64(4 * m - 1 - mmShift, mul, j);
296   return mulShift64(4 * m, mul, j);
297 }
298 
299 #else // !defined(HAS_UINT128) && !defined(HAS_64_BIT_INTRINSICS)
300 
mulShift64(const uint64_t m,const uint64_t * const mul,const int32_t j)301 static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
302   // m is maximum 55 bits
303   uint64_t high1;                                   // 128
304   const uint64_t low1 = umul128(m, mul[1], &high1); // 64
305   uint64_t high0;                                   // 64
306   umul128(m, mul[0], &high0);                       // 0
307   const uint64_t sum = high0 + low1;
308   if (sum < high0) {
309     ++high1; // overflow into high1
310   }
311   return shiftright128(sum, high1, j - 64);
312 }
313 
314 // This is faster if we don't have a 64x64->128-bit multiplication.
mulShiftAll64(uint64_t m,const uint64_t * const mul,const int32_t j,uint64_t * const vp,uint64_t * const vm,const uint32_t mmShift)315 static inline uint64_t mulShiftAll64(uint64_t m, const uint64_t* const mul, const int32_t j,
316   uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
317   m <<= 1;
318   // m is maximum 55 bits
319   uint64_t tmp;
320   const uint64_t lo = umul128(m, mul[0], &tmp);
321   uint64_t hi;
322   const uint64_t mid = tmp + umul128(m, mul[1], &hi);
323   hi += mid < tmp; // overflow into hi
324 
325   const uint64_t lo2 = lo + mul[0];
326   const uint64_t mid2 = mid + mul[1] + (lo2 < lo);
327   const uint64_t hi2 = hi + (mid2 < mid);
328   *vp = shiftright128(mid2, hi2, (uint32_t) (j - 64 - 1));
329 
330   if (mmShift == 1) {
331     const uint64_t lo3 = lo - mul[0];
332     const uint64_t mid3 = mid - mul[1] - (lo3 > lo);
333     const uint64_t hi3 = hi - (mid3 > mid);
334     *vm = shiftright128(mid3, hi3, (uint32_t) (j - 64 - 1));
335   } else {
336     const uint64_t lo3 = lo + lo;
337     const uint64_t mid3 = mid + mid + (lo3 < lo);
338     const uint64_t hi3 = hi + hi + (mid3 < mid);
339     const uint64_t lo4 = lo3 - mul[0];
340     const uint64_t mid4 = mid3 - mul[1] - (lo4 > lo3);
341     const uint64_t hi4 = hi3 - (mid4 > mid3);
342     *vm = shiftright128(mid4, hi4, (uint32_t) (j - 64));
343   }
344 
345   return shiftright128(mid, hi, (uint32_t) (j - 64 - 1));
346 }
347 
348 #endif // HAS_64_BIT_INTRINSICS
349 
350 #endif // RYU_D2S_INTRINSICS_H
351