summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorJF Bastien <jfbastien@apple.com>2018-09-08 03:55:25 +0000
committerJF Bastien <jfbastien@apple.com>2018-09-08 03:55:25 +0000
commitc4986cef12cd3d6f2256a938e50007695ddd9673 (patch)
treef67238fbb9d21ebb47df51eb9909b566ece819a2 /llvm
parent58963e4396d6557aa8509c90ef753a3f41e5f662 (diff)
downloadbcm5719-llvm-c4986cef12cd3d6f2256a938e50007695ddd9673.tar.gz
bcm5719-llvm-c4986cef12cd3d6f2256a938e50007695ddd9673.zip
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 llvm-svn: 341741
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/ADT/bit.h34
-rw-r--r--llvm/lib/Support/APInt.cpp21
-rw-r--r--llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h21
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h22
4 files changed, 59 insertions, 39 deletions
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h
new file mode 100644
index 00000000000..8ea4746bf6e
--- /dev/null
+++ b/llvm/include/llvm/ADT/bit.h
@@ -0,0 +1,34 @@
+//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++20 <bit> header.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_BIT_H
+#define LLVM_ADT_BIT_H
+
+#include "llvm/Support/type_traits.h"
+#include <cstring>
+
+namespace llvm {
+
+template <typename To, typename From,
+ typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type,
+ typename = typename std::enable_if<isPodLike<To>::value>::type,
+ typename = typename std::enable_if<isPodLike<From>::value>::type>
+inline To bit_cast(const From &from) noexcept {
+ alignas(To) unsigned char storage[sizeof(To)];
+ std::memcpy(&storage, &from, sizeof(To));
+ return reinterpret_cast<To &>(storage);
+}
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index f3c2ca5dab9..f2f5cca946f 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/bit.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -712,24 +713,20 @@ APInt llvm::APIntOps::GreatestCommonDivisor(APInt A, APInt B) {
}
APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
- union {
- double D;
- uint64_t I;
- } T;
- T.D = Double;
+ uint64_t I = bit_cast<uint64_t>(Double);
// Get the sign bit from the highest order bit
- bool isNeg = T.I >> 63;
+ bool isNeg = I >> 63;
// Get the 11-bit exponent and adjust for the 1023 bit bias
- int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
+ int64_t exp = ((I >> 52) & 0x7ff) - 1023;
// If the exponent is negative, the value is < 0 so just return 0.
if (exp < 0)
return APInt(width, 0u);
// Extract the mantissa by clearing the top 12 bits (sign + exponent).
- uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52;
+ uint64_t mantissa = (I & (~0ULL >> 12)) | 1ULL << 52;
// If the exponent doesn't shift all bits out of the mantissa
if (exp < 52)
@@ -806,12 +803,8 @@ double APInt::roundToDouble(bool isSigned) const {
// The leading bit of mantissa is implicit, so get rid of it.
uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0;
- union {
- double D;
- uint64_t I;
- } T;
- T.I = sign | (exp << 52) | mantissa;
- return T.D;
+ uint64_t I = sign | (exp << 52) | mantissa;
+ return bit_cast<double>(I);
}
// Truncate to new width.
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
index 62644ab2f45..34b732a1ff4 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/bit.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
@@ -342,27 +343,23 @@ static inline bool isValidDecodeLogicalImmediate(uint64_t val,
//
static inline float getFPImmFloat(unsigned Imm) {
// We expect an 8-bit binary encoding of a floating-point number here.
- union {
- uint32_t I;
- float F;
- } FPUnion;
uint8_t Sign = (Imm >> 7) & 0x1;
uint8_t Exp = (Imm >> 4) & 0x7;
uint8_t Mantissa = Imm & 0xf;
- // 8-bit FP iEEEE Float Encoding
+ // 8-bit FP IEEE Float Encoding
// abcd efgh aBbbbbbc defgh000 00000000 00000000
//
// where B = NOT(b);
- FPUnion.I = 0;
- FPUnion.I |= Sign << 31;
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
- FPUnion.I |= (Exp & 0x3) << 23;
- FPUnion.I |= Mantissa << 19;
- return FPUnion.F;
+ uint32_t I = 0;
+ I |= Sign << 31;
+ I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
+ I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
+ I |= (Exp & 0x3) << 23;
+ I |= Mantissa << 19;
+ return bit_cast<float>(I);
}
/// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h
index f472b215431..f8ee96026ba 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/bit.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
@@ -627,27 +628,22 @@ namespace ARM_AM {
//
inline float getFPImmFloat(unsigned Imm) {
// We expect an 8-bit binary encoding of a floating-point number here.
- union {
- uint32_t I;
- float F;
- } FPUnion;
uint8_t Sign = (Imm >> 7) & 0x1;
uint8_t Exp = (Imm >> 4) & 0x7;
uint8_t Mantissa = Imm & 0xf;
- // 8-bit FP iEEEE Float Encoding
+ // 8-bit FP IEEE Float Encoding
// abcd efgh aBbbbbbc defgh000 00000000 00000000
//
// where B = NOT(b);
-
- FPUnion.I = 0;
- FPUnion.I |= Sign << 31;
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
- FPUnion.I |= (Exp & 0x3) << 23;
- FPUnion.I |= Mantissa << 19;
- return FPUnion.F;
+ uint32_t I = 0;
+ I |= Sign << 31;
+ I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
+ I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
+ I |= (Exp & 0x3) << 23;
+ I |= Mantissa << 19;
+ return bit_cast<float>(F);
}
/// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
OpenPOWER on IntegriCloud