From 7a948298813c913841a36ed0b460db0856fe7082 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Wed, 18 Nov 2020 19:08:43 +0000 Subject: [PATCH] [compiler-rt] [builtins] Use _Float16 on extendhfsf2, truncdfhf2 __truncsfhf2 if available On AArch64 it allows use the native FP16 ABI (although libcalls are not emitted for fptrunc/fpext lowering), while on other architectures the expected current semantic is preserved (arm for instance). Differential Revision: https://reviews.llvm.org/D91733 --- compiler-rt/lib/builtins/extendhfsf2.c | 6 +- compiler-rt/lib/builtins/fp_extend.h | 4 + compiler-rt/lib/builtins/fp_trunc.h | 4 + compiler-rt/lib/builtins/truncdfhf2.c | 4 +- compiler-rt/lib/builtins/truncsfhf2.c | 6 +- compiler-rt/test/builtins/CMakeLists.txt | 1 + compiler-rt/test/builtins/Unit/extendhfsf2_test.c | 98 ++++++++++------------- compiler-rt/test/builtins/Unit/truncdfhf2_test.c | 8 +- compiler-rt/test/builtins/Unit/truncsfhf2_test.c | 6 +- 9 files changed, 65 insertions(+), 72 deletions(-) diff --git a/compiler-rt/lib/builtins/extendhfsf2.c b/compiler-rt/lib/builtins/extendhfsf2.c index 7c1a76e..0159ab0 100644 --- a/compiler-rt/lib/builtins/extendhfsf2.c +++ b/compiler-rt/lib/builtins/extendhfsf2.c @@ -12,15 +12,15 @@ // Use a forwarding definition and noinline to implement a poor man's alias, // as there isn't a good cross-platform way of defining one. -COMPILER_RT_ABI NOINLINE float __extendhfsf2(uint16_t a) { +COMPILER_RT_ABI NOINLINE float __extendhfsf2(src_t a) { return __extendXfYf2__(a); } -COMPILER_RT_ABI float __gnu_h2f_ieee(uint16_t a) { return __extendhfsf2(a); } +COMPILER_RT_ABI float __gnu_h2f_ieee(src_t a) { return __extendhfsf2(a); } #if defined(__ARM_EABI__) #if defined(COMPILER_RT_ARMHF_TARGET) -AEABI_RTABI float __aeabi_h2f(uint16_t a) { return __extendhfsf2(a); } +AEABI_RTABI float __aeabi_h2f(src_t a) { return __extendhfsf2(a); } #else COMPILER_RT_ALIAS(__extendhfsf2, __aeabi_h2f) #endif diff --git a/compiler-rt/lib/builtins/fp_extend.h b/compiler-rt/lib/builtins/fp_extend.h index fb51267..aad4436 100644 --- a/compiler-rt/lib/builtins/fp_extend.h +++ b/compiler-rt/lib/builtins/fp_extend.h @@ -40,7 +40,11 @@ static __inline int src_rep_t_clz(src_rep_t a) { } #elif defined SRC_HALF +#ifdef COMPILER_RT_HAS_FLOAT16 +typedef _Float16 src_t; +#else typedef uint16_t src_t; +#endif typedef uint16_t src_rep_t; #define SRC_REP_C UINT16_C static const int srcSigBits = 10; diff --git a/compiler-rt/lib/builtins/fp_trunc.h b/compiler-rt/lib/builtins/fp_trunc.h index aca4c9b..00595ed 100644 --- a/compiler-rt/lib/builtins/fp_trunc.h +++ b/compiler-rt/lib/builtins/fp_trunc.h @@ -50,7 +50,11 @@ typedef uint32_t dst_rep_t; static const int dstSigBits = 23; #elif defined DST_HALF +#ifdef COMPILER_RT_HAS_FLOAT16 +typedef _Float16 dst_t; +#else typedef uint16_t dst_t; +#endif typedef uint16_t dst_rep_t; #define DST_REP_C UINT16_C static const int dstSigBits = 10; diff --git a/compiler-rt/lib/builtins/truncdfhf2.c b/compiler-rt/lib/builtins/truncdfhf2.c index 90c418a..24c6e62 100644 --- a/compiler-rt/lib/builtins/truncdfhf2.c +++ b/compiler-rt/lib/builtins/truncdfhf2.c @@ -10,11 +10,11 @@ #define DST_HALF #include "fp_trunc_impl.inc" -COMPILER_RT_ABI uint16_t __truncdfhf2(double a) { return __truncXfYf2__(a); } +COMPILER_RT_ABI dst_t __truncdfhf2(double a) { return __truncXfYf2__(a); } #if defined(__ARM_EABI__) #if defined(COMPILER_RT_ARMHF_TARGET) -AEABI_RTABI uint16_t __aeabi_d2h(double a) { return __truncdfhf2(a); } +AEABI_RTABI dst_t __aeabi_d2h(double a) { return __truncdfhf2(a); } #else COMPILER_RT_ALIAS(__truncdfhf2, __aeabi_d2h) #endif diff --git a/compiler-rt/lib/builtins/truncsfhf2.c b/compiler-rt/lib/builtins/truncsfhf2.c index 1f17194..379e7cb 100644 --- a/compiler-rt/lib/builtins/truncsfhf2.c +++ b/compiler-rt/lib/builtins/truncsfhf2.c @@ -12,15 +12,15 @@ // Use a forwarding definition and noinline to implement a poor man's alias, // as there isn't a good cross-platform way of defining one. -COMPILER_RT_ABI NOINLINE uint16_t __truncsfhf2(float a) { +COMPILER_RT_ABI NOINLINE dst_t __truncsfhf2(float a) { return __truncXfYf2__(a); } -COMPILER_RT_ABI uint16_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); } +COMPILER_RT_ABI dst_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); } #if defined(__ARM_EABI__) #if defined(COMPILER_RT_ARMHF_TARGET) -AEABI_RTABI uint16_t __aeabi_f2h(float a) { return __truncsfhf2(a); } +AEABI_RTABI dst_t __aeabi_f2h(float a) { return __truncsfhf2(a); } #else COMPILER_RT_ALIAS(__truncsfhf2, __aeabi_f2h) #endif diff --git a/compiler-rt/test/builtins/CMakeLists.txt b/compiler-rt/test/builtins/CMakeLists.txt index 68ff285..a20a22c 100644 --- a/compiler-rt/test/builtins/CMakeLists.txt +++ b/compiler-rt/test/builtins/CMakeLists.txt @@ -45,6 +45,7 @@ foreach(arch ${BUILTIN_TEST_ARCH}) endif() append_list_if(COMPILER_RT_HAS_FLOAT16 -DCOMPILER_RT_HAS_FLOAT16 BUILTINS_TEST_TARGET_CFLAGS) + string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}") # Compute builtins available in library and add them as lit features. if(APPLE) diff --git a/compiler-rt/test/builtins/Unit/extendhfsf2_test.c b/compiler-rt/test/builtins/Unit/extendhfsf2_test.c index 9a5258b..86150e8 100644 --- a/compiler-rt/test/builtins/Unit/extendhfsf2_test.c +++ b/compiler-rt/test/builtins/Unit/extendhfsf2_test.c @@ -5,99 +5,83 @@ #include "fp_test.h" -float __extendhfsf2(uint16_t a); +float __extendhfsf2(TYPE_FP16 a); -int test__extendhfsf2(uint16_t a, float expected) +int test__extendhfsf2(TYPE_FP16 a, uint32_t expected) { float x = __extendhfsf2(a); - int ret = compareResultH(x, expected); + int ret = compareResultF(x, expected); if (ret){ printf("error in test__extendhfsf2(%#.4x) = %f, " - "expected %f\n", a, x, expected); + "expected %f\n", toRep16(a), x, fromRep32(expected)); } return ret; } -char assumption_1[sizeof(__fp16) * CHAR_BIT == 16] = {0}; +char assumption_1[sizeof(TYPE_FP16) * CHAR_BIT == 16] = {0}; int main() { // qNaN - if (test__extendhfsf2(UINT16_C(0x7e00), - makeQNaN32())) + if (test__extendhfsf2(fromRep16(0x7e00), + UINT32_C(0x7fc00000))) return 1; // NaN - if (test__extendhfsf2(UINT16_C(0x7e00), - makeNaN32(UINT32_C(0x8000)))) + if (test__extendhfsf2(fromRep16(0x7f80), + UINT32_C(0x7ff00000))) return 1; // inf - if (test__extendhfsf2(UINT16_C(0x7c00), - makeInf32())) + if (test__extendhfsf2(fromRep16(0x7c00), + UINT32_C(0x7f800000))) return 1; - if (test__extendhfsf2(UINT16_C(0xfc00), - -makeInf32())) + // -inf + if (test__extendhfsf2(fromRep16(0xfc00), + UINT32_C(0xff800000))) return 1; // zero - if (test__extendhfsf2(UINT16_C(0x0), - 0.0f)) + if (test__extendhfsf2(fromRep16(0x0), + UINT32_C(0x00000000))) return 1; - if (test__extendhfsf2(UINT16_C(0x8000), - -0.0f)) + // -zero + if (test__extendhfsf2(fromRep16(0x8000), + UINT32_C(0x80000000))) return 1; - - if (test__extendhfsf2(UINT16_C(0x4248), - 3.1415926535f)) - return 1; - if (test__extendhfsf2(UINT16_C(0xc248), - -3.1415926535f)) + if (test__extendhfsf2(fromRep16(0x4248), + UINT32_C(0x40490000))) return 1; - if (test__extendhfsf2(UINT16_C(0x7c00), - 0x1.987124876876324p+100f)) + if (test__extendhfsf2(fromRep16(0xc248), + UINT32_C(0xc0490000))) return 1; - if (test__extendhfsf2(UINT16_C(0x6e62), - 0x1.988p+12f)) + if (test__extendhfsf2(fromRep16(0x6e62), + UINT32_C(0x45cc4000))) return 1; - if (test__extendhfsf2(UINT16_C(0x3c00), - 0x1.0p+0f)) + if (test__extendhfsf2(fromRep16(0x3c00), + UINT32_C(0x3f800000))) return 1; - if (test__extendhfsf2(UINT16_C(0x0400), - 0x1.0p-14f)) + if (test__extendhfsf2(fromRep16(0x0400), + UINT32_C(0x38800000))) return 1; // denormal - if (test__extendhfsf2(UINT16_C(0x0010), - 0x1.0p-20f)) - return 1; - if (test__extendhfsf2(UINT16_C(0x0001), - 0x1.0p-24f)) + if (test__extendhfsf2(fromRep16(0x0010), + UINT32_C(0x35800000))) return 1; - if (test__extendhfsf2(UINT16_C(0x8001), - -0x1.0p-24f)) + if (test__extendhfsf2(fromRep16(0x0001), + UINT32_C(0x33800000))) return 1; - if (test__extendhfsf2(UINT16_C(0x0001), - 0x1.5p-25f)) + if (test__extendhfsf2(fromRep16(0x8001), + UINT32_C(0xb3800000))) return 1; - // and back to zero - if (test__extendhfsf2(UINT16_C(0x0000), - 0x1.0p-25f)) - return 1; - if (test__extendhfsf2(UINT16_C(0x8000), - -0x1.0p-25f)) + if (test__extendhfsf2(fromRep16(0x0001), + UINT32_C(0x33800000))) return 1; // max (precise) - if (test__extendhfsf2(UINT16_C(0x7bff), - 65504.0f)) + if (test__extendhfsf2(fromRep16(0x7bff), + UINT32_C(0x477fe000))) return 1; // max (rounded) - if (test__extendhfsf2(UINT16_C(0x7bff), - 65504.0f)) - return 1; - // max (to +inf) - if (test__extendhfsf2(UINT16_C(0x7c00), - makeInf32())) - return 1; - if (test__extendhfsf2(UINT16_C(0xfc00), - -makeInf32())) + if (test__extendhfsf2(fromRep16(0x7bff), + UINT32_C(0x477fe000))) return 1; return 0; } diff --git a/compiler-rt/test/builtins/Unit/truncdfhf2_test.c b/compiler-rt/test/builtins/Unit/truncdfhf2_test.c index 74e975e..1990ec9 100644 --- a/compiler-rt/test/builtins/Unit/truncdfhf2_test.c +++ b/compiler-rt/test/builtins/Unit/truncdfhf2_test.c @@ -5,16 +5,16 @@ #include "fp_test.h" -uint16_t __truncdfhf2(double a); +TYPE_FP16 __truncdfhf2(double a); int test__truncdfhf2(double a, uint16_t expected) { - uint16_t x = __truncdfhf2(a); + TYPE_FP16 x = __truncdfhf2(a); int ret = compareResultH(x, expected); if (ret){ - printf("error in test__truncdfhf2(%f) = %#.4x, " - "expected %#.4x\n", a, x, fromRep16(expected)); + printf("error in test__truncdfhf2(%lf) = %#.4x, " + "expected %#.4x\n", a, toRep16(x), expected); } return ret; } diff --git a/compiler-rt/test/builtins/Unit/truncsfhf2_test.c b/compiler-rt/test/builtins/Unit/truncsfhf2_test.c index 7fcccf1..c7c8063 100644 --- a/compiler-rt/test/builtins/Unit/truncsfhf2_test.c +++ b/compiler-rt/test/builtins/Unit/truncsfhf2_test.c @@ -5,16 +5,16 @@ #include "fp_test.h" -uint16_t __truncsfhf2(float a); +TYPE_FP16 __truncsfhf2(float a); int test__truncsfhf2(float a, uint16_t expected) { - uint16_t x = __truncsfhf2(a); + TYPE_FP16 x = __truncsfhf2(a); int ret = compareResultH(x, expected); if (ret){ printf("error in test__truncsfhf2(%f) = %#.4x, " - "expected %#.4x\n", a, x, fromRep16(expected)); + "expected %#.4x\n", a, toRep16(x), expected); } return ret; } -- 2.7.4