//===--- Float16bits.cpp - supports 2-byte floats ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements f16 and bf16 to support the compilation and execution // of programs using these types. // //===----------------------------------------------------------------------===// #include "mlir/ExecutionEngine/Float16bits.h" #ifdef MLIR_FLOAT16_DEFINE_FUNCTIONS // We are building this library #include <cmath> #include <cstring> namespace { // Union used to make the int/float aliasing explicit so we can access the raw // bits. Float32Bits; const uint32_t kF32MantiBits = …; const uint32_t kF32HalfMantiBitDiff = …; const uint32_t kF32HalfBitDiff = …; const Float32Bits kF32Magic = …; const uint32_t kF32HalfExpAdjust = …; // Constructs the 16 bit representation for a half precision value from a float // value. This implementation is adapted from Eigen. uint16_t float2half(float floatValue) { … } // Converts the 16 bit representation of a half precision value to a float // value. This implementation is adapted from Eigen. float half2float(uint16_t halfValue) { … } const uint32_t kF32BfMantiBitDiff = …; // Constructs the 16 bit representation for a bfloat value from a float value. // This implementation is adapted from Eigen. uint16_t float2bfloat(float floatValue) { … } // Converts the 16 bit representation of a bfloat value to a float value. This // implementation is adapted from Eigen. float bfloat2float(uint16_t bfloatBits) { … } } // namespace f16::f16(float f) : … { … } bf16::bf16(float f) : … { … } std::ostream &operator<<(std::ostream &os, const f16 &f) { … } std::ostream &operator<<(std::ostream &os, const bf16 &d) { … } bool operator==(const f16 &f1, const f16 &f2) { … } bool operator==(const bf16 &f1, const bf16 &f2) { … } // Mark these symbols as weak so they don't conflict when compiler-rt also // defines them. #define ATTR_WEAK #ifdef __has_attribute #if __has_attribute(weak) && !defined(__MINGW32__) && !defined(__CYGWIN__) && \ !defined(_WIN32) #undef ATTR_WEAK #define ATTR_WEAK … #endif #endif #if defined(__x86_64__) || defined(_M_X64) // On x86 bfloat16 is passed in SSE registers. Since both float and __bf16 // are passed in the same register we can use the wider type and careful casting // to conform to x86_64 psABI. This only works with the assumption that we're // dealing with little-endian values passed in wider registers. // Ideally this would directly use __bf16, but that type isn't supported by all // compilers. BF16ABIType; #else // Default to uint16_t if we have nothing else. using BF16ABIType = uint16_t; #endif // Provide a float->bfloat conversion routine in case the runtime doesn't have // one. extern "C" BF16ABIType ATTR_WEAK __truncsfbf2(float f) { … } // Provide a double->bfloat conversion routine in case the runtime doesn't have // one. extern "C" BF16ABIType ATTR_WEAK __truncdfbf2(double d) { … } // Provide these to the CRunner with the local float16 knowledge. extern "C" void printF16(uint16_t bits) { … } extern "C" void printBF16(uint16_t bits) { … } #endif // MLIR_FLOAT16_DEFINE_FUNCTIONS