Index: llvm/trunk/include/llvm/ADT/bit.h =================================================================== --- llvm/trunk/include/llvm/ADT/bit.h +++ llvm/trunk/include/llvm/ADT/bit.h @@ -0,0 +1,34 @@ +//===-- llvm/ADT/bit.h - C++20 ----------------------------*- 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 header. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BIT_H +#define LLVM_ADT_BIT_H + +#include "llvm/Support/type_traits.h" +#include + +namespace llvm { + +template ::type, + typename = typename std::enable_if::value>::type, + typename = typename std::enable_if::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(storage); +} + +} // namespace llvm + +#endif Index: llvm/trunk/lib/Support/APInt.cpp =================================================================== --- llvm/trunk/lib/Support/APInt.cpp +++ llvm/trunk/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::RoundDoubleToAPInt(double Double, unsigned width) { - union { - double D; - uint64_t I; - } T; - T.D = Double; + uint64_t I = bit_cast(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 @@ // 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(I); } // Truncate to new width. Index: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h =================================================================== --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h +++ llvm/trunk/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 @@ -342,27 +343,23 @@ // 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(I); } /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit Index: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h =================================================================== --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h +++ llvm/trunk/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 @@ -627,27 +628,22 @@ // 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(F); } /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit