| #pragma once | |
| // Apple clang was fixed in 8.1 | |
| #if defined(__apple_build_version__) && \ | |
| ((__clang_major__ < 8) || \ | |
| ((__clang_major__ == 8) && (__clang_minor__ < 1))) | |
| #define CAFFE2_INTERNAL_APPLE_NEED_FIX 1 | |
| #endif | |
| // Regular clang was fixed in 3.9 | |
| #if defined(__clang__) && (__clang_major__ < 4) && (__clang_minor__ < 9) | |
| #define CAFFE2_INTERNAL_CLANG_NEED_FIX 1 | |
| #endif | |
| #if defined(CAFFE2_INTERNAL_APPLE_NEED_FIX) || \ | |
| defined(CAFFE2_INTERNAL_CLANG_NEED_FIX) | |
| #include <c10/util/Half.h> | |
| #include <emmintrin.h> | |
| // This version of clang has a bug that _cvtsh_ss is not defined, see | |
| // https://reviews.llvm.org/D16177 | |
| static __inline float | |
| __attribute__((__always_inline__, __nodebug__, __target__("f16c"))) | |
| _cvtsh_ss(unsigned short a) { | |
| __v8hi v = {(short)a, 0, 0, 0, 0, 0, 0, 0}; | |
| __v4sf r = __builtin_ia32_vcvtph2ps(v); | |
| return r[0]; | |
| } | |
| static __inline unsigned short | |
| __attribute__((__always_inline__, __nodebug__, __target__("f16c"))) | |
| _cvtss_sh(float a, int imm8) { | |
| unsigned short ret; | |
| *reinterpret_cast<at::Half*>(&ret) = a; | |
| return ret; | |
| } | |
| #endif // __APPLE_NEED_FIX || __CLANG_NEED_FIX | |
| #undef __APPLE_NEED_FIX | |
| #undef __CLANG_NEED_FIX | |
| #if defined(_MSC_VER) && !defined(__clang__) | |
| #include <c10/util/Half.h> | |
| #include <cstdint> | |
| // It seems that microsoft msvc does not have a _cvtsh_ss implementation so | |
| // we will add a dummy version to it. | |
| static inline float _cvtsh_ss(unsigned short x) { | |
| union { | |
| std::uint32_t intval; | |
| float floatval; | |
| } t1; | |
| std::uint32_t t2, t3; | |
| t1.intval = x & 0x7fff; // Non-sign bits | |
| t2 = x & 0x8000; // Sign bit | |
| t3 = x & 0x7c00; // Exponent | |
| t1.intval <<= 13; // Align mantissa on MSB | |
| t2 <<= 16; // Shift sign bit into position | |
| t1.intval += 0x38000000; // Adjust bias | |
| t1.intval = (t3 == 0 ? 0 : t1.intval); // Denormals-as-zero | |
| t1.intval |= t2; // Re-insert sign bit | |
| return t1.floatval; | |
| } | |
| static inline unsigned short _cvtss_sh(float x, int imm8) { | |
| unsigned short ret; | |
| *reinterpret_cast<at::Half*>(&ret) = x; | |
| return ret; | |
| } | |
| #endif // _MSC_VER |