llvm.org GIT mirror llvm / 7dcaeaf
ADT: add <bit> header, implement C++20 bit_cast, use Summary: I saw a few places that were punning through a union of FP and integer, and that made me sad. Luckily, C++20 adds bit_cast for exactly that purpose. Implement our own version in ADT (without constexpr, leaving us a bit sad), and use it in the few places my grep-fu found silly union punning. This was originally committed as r341728 and reverted in r341730. Reviewers: javed.absar, steven_wu, srhines Subscribers: dexonsmith, llvm-commits Differential Revision: https://reviews.llvm.org/D51693 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@341741 91177308-0d34-0410-b5e6-96231b3b80d8 JF Bastien 1 year, 11 months ago
4 changed file(s) with 59 addition(s) and 39 deletion(s). Raw diff Collapse all Expand all
0 //===-- llvm/ADT/bit.h - C++20 ----------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the C++20 header.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_ADT_BIT_H
14 #define LLVM_ADT_BIT_H
15
16 #include "llvm/Support/type_traits.h"
17 #include
18
19 namespace llvm {
20
21 template
22 typename = typename std::enable_if::type,
23 typename = typename std::enable_if::value>::type,
24 typename = typename std::enable_if::value>::type>
25 inline To bit_cast(const From &from) noexcept {
26 alignas(To) unsigned char storage[sizeof(To)];
27 std::memcpy(&storage, &from, sizeof(To));
28 return reinterpret_cast(storage);
29 }
30
31 } // namespace llvm
32
33 #endif
1818 #include "llvm/ADT/Optional.h"
1919 #include "llvm/ADT/SmallString.h"
2020 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/bit.h"
2122 #include "llvm/Config/llvm-config.h"
2223 #include "llvm/Support/Debug.h"
2324 #include "llvm/Support/ErrorHandling.h"
711712 }
712713
713714 APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
714 union {
715 double D;
716 uint64_t I;
717 } T;
718 T.D = Double;
715 uint64_t I = bit_cast(Double);
719716
720717 // Get the sign bit from the highest order bit
721 bool isNeg = T.I >> 63;
718 bool isNeg = I >> 63;
722719
723720 // Get the 11-bit exponent and adjust for the 1023 bit bias
724 int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
721 int64_t exp = ((I >> 52) & 0x7ff) - 1023;
725722
726723 // If the exponent is negative, the value is < 0 so just return 0.
727724 if (exp < 0)
728725 return APInt(width, 0u);
729726
730727 // Extract the mantissa by clearing the top 12 bits (sign + exponent).
731 uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52;
728 uint64_t mantissa = (I & (~0ULL >> 12)) | 1ULL << 52;
732729
733730 // If the exponent doesn't shift all bits out of the mantissa
734731 if (exp < 52)
805802
806803 // The leading bit of mantissa is implicit, so get rid of it.
807804 uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0;
808 union {
809 double D;
810 uint64_t I;
811 } T;
812 T.I = sign | (exp << 52) | mantissa;
813 return T.D;
805 uint64_t I = sign | (exp << 52) | mantissa;
806 return bit_cast(I);
814807 }
815808
816809 // Truncate to new width.
1515
1616 #include "llvm/ADT/APFloat.h"
1717 #include "llvm/ADT/APInt.h"
18 #include "llvm/ADT/bit.h"
1819 #include "llvm/Support/ErrorHandling.h"
1920 #include "llvm/Support/MathExtras.h"
2021 #include
341342 //
342343 static inline float getFPImmFloat(unsigned Imm) {
343344 // We expect an 8-bit binary encoding of a floating-point number here.
344 union {
345 uint32_t I;
346 float F;
347 } FPUnion;
348345
349346 uint8_t Sign = (Imm >> 7) & 0x1;
350347 uint8_t Exp = (Imm >> 4) & 0x7;
351348 uint8_t Mantissa = Imm & 0xf;
352349
353 // 8-bit FP iEEEE Float Encoding
350 // 8-bit FP IEEE Float Encoding
354351 // abcd efgh aBbbbbbc defgh000 00000000 00000000
355352 //
356353 // where B = NOT(b);
357354
358 FPUnion.I = 0;
359 FPUnion.I |= Sign << 31;
360 FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
361 FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
362 FPUnion.I |= (Exp & 0x3) << 23;
363 FPUnion.I |= Mantissa << 19;
364 return FPUnion.F;
355 uint32_t I = 0;
356 I |= Sign << 31;
357 I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
358 I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
359 I |= (Exp & 0x3) << 23;
360 I |= Mantissa << 19;
361 return bit_cast(I);
365362 }
366363
367364 /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
1515
1616 #include "llvm/ADT/APFloat.h"
1717 #include "llvm/ADT/APInt.h"
18 #include "llvm/ADT/bit.h"
1819 #include "llvm/Support/ErrorHandling.h"
1920 #include "llvm/Support/MathExtras.h"
2021 #include
626627 //
627628 inline float getFPImmFloat(unsigned Imm) {
628629 // We expect an 8-bit binary encoding of a floating-point number here.
629 union {
630 uint32_t I;
631 float F;
632 } FPUnion;
633630
634631 uint8_t Sign = (Imm >> 7) & 0x1;
635632 uint8_t Exp = (Imm >> 4) & 0x7;
636633 uint8_t Mantissa = Imm & 0xf;
637634
638 // 8-bit FP iEEEE Float Encoding
635 // 8-bit FP IEEE Float Encoding
639636 // abcd efgh aBbbbbbc defgh000 00000000 00000000
640637 //
641638 // where B = NOT(b);
642
643 FPUnion.I = 0;
644 FPUnion.I |= Sign << 31;
645 FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
646 FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
647 FPUnion.I |= (Exp & 0x3) << 23;
648 FPUnion.I |= Mantissa << 19;
649 return FPUnion.F;
639 uint32_t I = 0;
640 I |= Sign << 31;
641 I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
642 I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
643 I |= (Exp & 0x3) << 23;
644 I |= Mantissa << 19;
645 return bit_cast(F);
650646 }
651647
652648 /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit