[llvm] r341728 - ADT: add <bit> header, implement C++20 bit_cast, use

Richard Smith via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 7 16:28:10 PDT 2018


On Fri, 7 Sep 2018 at 16:08, JF Bastien via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: jfb
> Date: Fri Sep  7 16:08:26 2018
> New Revision: 341728
>
> URL: http://llvm.org/viewvc/llvm-project?rev=341728&view=rev
> Log:
> 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.
>
> Reviewers: javed.absar
>
> Subscribers: dexonsmith, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D51693
>
> Added:
>     llvm/trunk/include/llvm/ADT/bit.h
> Modified:
>     llvm/trunk/lib/Support/APInt.cpp
>     llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
>     llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h
>
> Added: llvm/trunk/include/llvm/ADT/bit.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/bit.h?rev=341728&view=auto
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/bit.h (added)
> +++ llvm/trunk/include/llvm/ADT/bit.h Fri Sep  7 16:08:26 2018
> @@ -0,0 +1,37 @@
> +//===-- 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 <cstring>
> +#include <type_traits>
> +
> +namespace llvm {
> +
> +template <
> +    typename To, typename From,
> +    typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type,
> +    typename =
> +        typename
> std::enable_if<std::is_trivially_copyable<To>::value>::type,
> +    typename =
> +        typename
> std::enable_if<std::is_trivially_copyable<From>::value>::type>
> +inline To bit_cast(const From &from) noexcept {
> +  typename std::aligned_storage<sizeof(To), alignof(To)>::type storage;
>

std::aligned_storage should never be used for anything, ever. Use

alignas(To) unsigned char storage[sizeof(To)];

+  std::memcpy(&storage, &from, sizeof(To));
> +  return reinterpret_cast<To &>(storage);
> +}
> +
> +} // namespace llvm
> +
> +#endif
>
> Modified: llvm/trunk/lib/Support/APInt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=341728&r1=341727&r2=341728&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Support/APInt.cpp (original)
> +++ llvm/trunk/lib/Support/APInt.cpp Fri Sep  7 16:08:26 2018
> @@ -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::GreatestCommonDivi
>  }
>
>  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 isSigne
>
>    // 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.
>
> Modified:
> llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h?rev=341728&r1=341727&r2=341728&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
> (original)
> +++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
> Fri Sep  7 16:08:26 2018
> @@ -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 isValidDecodeLogicalI
>  //
>  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
>
> Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h?rev=341728&r1=341727&r2=341728&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h (original)
> +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h Fri Sep  7
> 16:08:26 2018
> @@ -627,27 +627,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
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180907/416b92f0/attachment-0001.html>


More information about the llvm-commits mailing list