<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Fri, 7 Sep 2018 at 16:08, JF Bastien via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: jfb<br>
Date: Fri Sep 7 16:08:26 2018<br>
New Revision: 341728<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=341728&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=341728&view=rev</a><br>
Log:<br>
ADT: add <bit> header, implement C++20 bit_cast, use<br>
<br>
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.<br>
<br>
Reviewers: javed.absar<br>
<br>
Subscribers: dexonsmith, llvm-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D51693" rel="noreferrer" target="_blank">https://reviews.llvm.org/D51693</a><br>
<br>
Added:<br>
llvm/trunk/include/llvm/ADT/bit.h<br>
Modified:<br>
llvm/trunk/lib/Support/APInt.cpp<br>
llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h<br>
llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h<br>
<br>
Added: llvm/trunk/include/llvm/ADT/bit.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/bit.h?rev=341728&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/bit.h?rev=341728&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ADT/bit.h (added)<br>
+++ llvm/trunk/include/llvm/ADT/bit.h Fri Sep 7 16:08:26 2018<br>
@@ -0,0 +1,37 @@<br>
+//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file implements the C++20 <bit> header.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_ADT_BIT_H<br>
+#define LLVM_ADT_BIT_H<br>
+<br>
+#include <cstring><br>
+#include <type_traits><br>
+<br>
+namespace llvm {<br>
+<br>
+template <<br>
+ typename To, typename From,<br>
+ typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type,<br>
+ typename =<br>
+ typename std::enable_if<std::is_trivially_copyable<To>::value>::type,<br>
+ typename =<br>
+ typename std::enable_if<std::is_trivially_copyable<From>::value>::type><br>
+inline To bit_cast(const From &from) noexcept {<br>
+ typename std::aligned_storage<sizeof(To), alignof(To)>::type storage;<br></blockquote><div><br></div><div>std::aligned_storage should never be used for anything, ever. Use</div><div><br></div><div>alignas(To) unsigned char storage[sizeof(To)];</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ std::memcpy(&storage, &from, sizeof(To));<br>
+ return reinterpret_cast<To &>(storage);<br>
+}<br>
+<br>
+} // namespace llvm<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/lib/Support/APInt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=341728&r1=341727&r2=341728&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=341728&r1=341727&r2=341728&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/APInt.cpp (original)<br>
+++ llvm/trunk/lib/Support/APInt.cpp Fri Sep 7 16:08:26 2018<br>
@@ -19,6 +19,7 @@<br>
#include "llvm/ADT/Optional.h"<br>
#include "llvm/ADT/SmallString.h"<br>
#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/ADT/bit.h"<br>
#include "llvm/Config/llvm-config.h"<br>
#include "llvm/Support/Debug.h"<br>
#include "llvm/Support/ErrorHandling.h"<br>
@@ -712,24 +713,20 @@ APInt llvm::APIntOps::GreatestCommonDivi<br>
}<br>
<br>
APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {<br>
- union {<br>
- double D;<br>
- uint64_t I;<br>
- } T;<br>
- T.D = Double;<br>
+ uint64_t I = bit_cast<uint64_t>(Double);<br>
<br>
// Get the sign bit from the highest order bit<br>
- bool isNeg = T.I >> 63;<br>
+ bool isNeg = I >> 63;<br>
<br>
// Get the 11-bit exponent and adjust for the 1023 bit bias<br>
- int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;<br>
+ int64_t exp = ((I >> 52) & 0x7ff) - 1023;<br>
<br>
// If the exponent is negative, the value is < 0 so just return 0.<br>
if (exp < 0)<br>
return APInt(width, 0u);<br>
<br>
// Extract the mantissa by clearing the top 12 bits (sign + exponent).<br>
- uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52;<br>
+ uint64_t mantissa = (I & (~0ULL >> 12)) | 1ULL << 52;<br>
<br>
// If the exponent doesn't shift all bits out of the mantissa<br>
if (exp < 52)<br>
@@ -806,12 +803,8 @@ double APInt::roundToDouble(bool isSigne<br>
<br>
// The leading bit of mantissa is implicit, so get rid of it.<br>
uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0;<br>
- union {<br>
- double D;<br>
- uint64_t I;<br>
- } T;<br>
- T.I = sign | (exp << 52) | mantissa;<br>
- return T.D;<br>
+ uint64_t I = sign | (exp << 52) | mantissa;<br>
+ return bit_cast<double>(I);<br>
}<br>
<br>
// Truncate to new width.<br>
<br>
Modified: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h?rev=341728&r1=341727&r2=341728&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h?rev=341728&r1=341727&r2=341728&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h (original)<br>
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h Fri Sep 7 16:08:26 2018<br>
@@ -16,6 +16,7 @@<br>
<br>
#include "llvm/ADT/APFloat.h"<br>
#include "llvm/ADT/APInt.h"<br>
+#include "llvm/ADT/bit.h"<br>
#include "llvm/Support/ErrorHandling.h"<br>
#include "llvm/Support/MathExtras.h"<br>
#include <cassert><br>
@@ -342,27 +343,23 @@ static inline bool isValidDecodeLogicalI<br>
//<br>
static inline float getFPImmFloat(unsigned Imm) {<br>
// We expect an 8-bit binary encoding of a floating-point number here.<br>
- union {<br>
- uint32_t I;<br>
- float F;<br>
- } FPUnion;<br>
<br>
uint8_t Sign = (Imm >> 7) & 0x1;<br>
uint8_t Exp = (Imm >> 4) & 0x7;<br>
uint8_t Mantissa = Imm & 0xf;<br>
<br>
- // 8-bit FP iEEEE Float Encoding<br>
+ // 8-bit FP IEEE Float Encoding<br>
// abcd efgh aBbbbbbc defgh000 00000000 00000000<br>
//<br>
// where B = NOT(b);<br>
<br>
- FPUnion.I = 0;<br>
- FPUnion.I |= Sign << 31;<br>
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;<br>
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;<br>
- FPUnion.I |= (Exp & 0x3) << 23;<br>
- FPUnion.I |= Mantissa << 19;<br>
- return FPUnion.F;<br>
+ uint32_t I = 0;<br>
+ I |= Sign << 31;<br>
+ I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;<br>
+ I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;<br>
+ I |= (Exp & 0x3) << 23;<br>
+ I |= Mantissa << 19;<br>
+ return bit_cast<float>(I);<br>
}<br>
<br>
/// getFP16Imm - Return an 8-bit floating-point version of the 16-bit<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h?rev=341728&r1=341727&r2=341728&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h?rev=341728&r1=341727&r2=341728&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h (original)<br>
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h Fri Sep 7 16:08:26 2018<br>
@@ -627,27 +627,22 @@ namespace ARM_AM {<br>
//<br>
inline float getFPImmFloat(unsigned Imm) {<br>
// We expect an 8-bit binary encoding of a floating-point number here.<br>
- union {<br>
- uint32_t I;<br>
- float F;<br>
- } FPUnion;<br>
<br>
uint8_t Sign = (Imm >> 7) & 0x1;<br>
uint8_t Exp = (Imm >> 4) & 0x7;<br>
uint8_t Mantissa = Imm & 0xf;<br>
<br>
- // 8-bit FP iEEEE Float Encoding<br>
+ // 8-bit FP IEEE Float Encoding<br>
// abcd efgh aBbbbbbc defgh000 00000000 00000000<br>
//<br>
// where B = NOT(b);<br>
-<br>
- FPUnion.I = 0;<br>
- FPUnion.I |= Sign << 31;<br>
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;<br>
- FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;<br>
- FPUnion.I |= (Exp & 0x3) << 23;<br>
- FPUnion.I |= Mantissa << 19;<br>
- return FPUnion.F;<br>
+ uint32_t I = 0;<br>
+ I |= Sign << 31;<br>
+ I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;<br>
+ I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;<br>
+ I |= (Exp & 0x3) << 23;<br>
+ I |= Mantissa << 19;<br>
+ return bit_cast<float>(F);<br>
}<br>
<br>
/// getFP16Imm - Return an 8-bit floating-point version of the 16-bit<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>