diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 9a0a50ee7003f1..97a9e508d37a32 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -104,6 +104,7 @@ set(GENERIC_SOURCES divti3.c extendsfdf2.c extendhfsf2.c + extendhfxf2.c ffsdi2.c ffssi2.c ffsti2.c diff --git a/compiler-rt/lib/builtins/extendhfxf2.c b/compiler-rt/lib/builtins/extendhfxf2.c new file mode 100644 index 00000000000000..7425859f79f763 --- /dev/null +++ b/compiler-rt/lib/builtins/extendhfxf2.c @@ -0,0 +1,18 @@ +//===-- lib/extendhfxf2.c - half -> long double conversion --------*- C -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#define SRC_HALF +#define DST_DOUBLE +#include "fp_extend_impl.inc" + +// 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. +// Long double are expected to be as precise as double. +COMPILER_RT_ABI NOINLINE long double __extendhfxf2(src_t a) { + return (long double)__extendXfYf2__(a); +} diff --git a/compiler-rt/lib/builtins/macho_embedded/common.txt b/compiler-rt/lib/builtins/macho_embedded/common.txt index 819109768f5298..fa99bc239e68f2 100644 --- a/compiler-rt/lib/builtins/macho_embedded/common.txt +++ b/compiler-rt/lib/builtins/macho_embedded/common.txt @@ -60,6 +60,7 @@ divsf3 divsi3 extendsfdf2 extendhfsf2 +extendhfxf2 ffssi2 fixdfsi fixsfsi diff --git a/compiler-rt/test/builtins/Unit/extendhfxf2_test.c b/compiler-rt/test/builtins/Unit/extendhfxf2_test.c new file mode 100644 index 00000000000000..9972b024ab415e --- /dev/null +++ b/compiler-rt/test/builtins/Unit/extendhfxf2_test.c @@ -0,0 +1,71 @@ +// RUN: %clang_builtins %s %librt -o %t && %run %t +// REQUIRES: librt_has_extendhfxf2 + +#include +#include // for isnan, isinf +#include + +#if __LDBL_MANT_DIG__ >= 64 && defined(COMPILER_RT_HAS_FLOAT16) + +long double __extendhfxf2(_Float16 f); + +int test_extendhfxf2(_Float16 a, long double expected) { + long double x = __extendhfxf2(a); + __uint16_t *b = (void *)&a; + int ret = !((isnan(x) && isnan(expected)) || x == expected); + if (ret) { + printf("error in test__extendhfxf2(%#.4x) = %.20Lf, " + "expected %.20Lf\n", + *b, x, expected); + } + return ret; +} + +char assumption_1[sizeof(_Float16) * CHAR_BIT == 16] = {0}; + +int main() { + // Small positive value + if (test_extendhfxf2(0.09997558593750000000f, 0.09997558593750000000L)) + return 1; + + // Small negative value + if (test_extendhfxf2(-0.09997558593750000000f, -0.09997558593750000000L)) + return 1; + + // Zero + if (test_extendhfxf2(0.0f, 0.0L)) + return 1; + + // Smallest positive non-zero value + if (test_extendhfxf2(0x1p-16f, 0x1p-16L)) + return 1; + + // Smallest negative non-zero value + if (test_extendhfxf2(-0x1p-16f, -0x1p-16L)) + return 1; + + // Positive infinity + if (test_extendhfxf2(__builtin_huge_valf16(), __builtin_huge_valf64x())) + return 1; + + // Negative infinity + if (test_extendhfxf2(-__builtin_huge_valf16(), + (long double)-__builtin_huge_valf64x())) + return 1; + + // NaN + if (test_extendhfxf2(__builtin_nanf16(""), + (long double)__builtin_nanf64x(""))) + return 1; + + return 0; +} + +#else + +int main() { + printf("skipped\n"); + return 0; +} + +#endif diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/builtins/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/lib/builtins/BUILD.gn index 8904aed28229f1..efbf01960bf907 100644 --- a/llvm/utils/gn/secondary/compiler-rt/lib/builtins/BUILD.gn +++ b/llvm/utils/gn/secondary/compiler-rt/lib/builtins/BUILD.gn @@ -126,6 +126,7 @@ static_library("builtins") { "divsi3.c", "divti3.c", "extendhfsf2.c", + "extendhfxf2.c" "extendsfdf2.c", "ffsdi2.c", "ffssi2.c",