<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>