| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| ! Test for correct forwarding of integer overflow flags from the compiler driver | ||
| ! to the frontend driver | ||
|
|
||
| ! RUN: %flang -### -fno-strict-overflow %s 2>&1 | FileCheck %s --check-prefix=INDUCED | ||
| ! RUN: %flang -### -fstrict-overflow %s 2>&1 | FileCheck %s | ||
| ! RUN: %flang -### -fno-wrapv %s 2>&1 | FileCheck %s | ||
| ! RUN: %flang -### -fno-wrapv -fno-strict-overflow %s 2>&1 | FileCheck %s | ||
|
|
||
| ! CHECK-NOT: "-fno-wrapv" | ||
| ! INDUCED: "-fwrapv" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| !===----------------------------------------------------------------------===! | ||
| ! This directory can be used to add Integration tests involving multiple | ||
| ! stages of the compiler (for eg. from Fortran to LLVM IR). It should not | ||
| ! contain executable tests. We should only add tests here sparingly and only | ||
| ! if there is no other way to test. Repeat this message in each test that is | ||
| ! added to this directory and sub-directories. | ||
| !===----------------------------------------------------------------------===! | ||
|
|
||
| !RUN: %if x86-registered-target %{ %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fopenmp %s -o - | FileCheck --check-prefixes=CHECK,X86 %s %} | ||
| !RUN: %if aarch64-registerd-target %{ %flang_fc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fopenmp %s -o - | FileCheck --check-prefixes=CHECK,AARCH64 %s %} | ||
|
|
||
| !CHECK: %[[X_NEW_VAL:.*]] = alloca { float, float }, align 8 | ||
| !CHECK: %[[VAL_1:.*]] = alloca { float, float }, i64 1, align 8 | ||
| !CHECK: %[[ORIG_VAL:.*]] = alloca { float, float }, i64 1, align 8 | ||
| !CHECK: store { float, float } { float 2.000000e+00, float 2.000000e+00 }, ptr %[[ORIG_VAL]], align 4 | ||
| !CHECK: br label %entry | ||
|
|
||
| !CHECK: entry: | ||
| !CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 8 | ||
| !CHECK: call void @__atomic_load(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0) | ||
| !CHECK: %[[PHI_NODE_ENTRY_1:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 8 | ||
| !CHECK: br label %.atomic.cont | ||
|
|
||
| !CHECK: .atomic.cont | ||
| !CHECK: %[[VAL_4:.*]] = phi { float, float } [ %[[PHI_NODE_ENTRY_1]], %entry ], [ %{{.*}}, %.atomic.cont ] | ||
| !CHECK: %[[VAL_5:.*]] = extractvalue { float, float } %[[VAL_4]], 0 | ||
| !CHECK: %[[VAL_6:.*]] = extractvalue { float, float } %[[VAL_4]], 1 | ||
| !CHECK: %[[VAL_7:.*]] = fadd contract float %[[VAL_5]], 1.000000e+00 | ||
| !CHECK: %[[VAL_8:.*]] = fadd contract float %[[VAL_6]], 1.000000e+00 | ||
| !CHECK: %[[VAL_9:.*]] = insertvalue { float, float } undef, float %[[VAL_7]], 0 | ||
| !CHECK: %[[VAL_10:.*]] = insertvalue { float, float } %[[VAL_9]], float %[[VAL_8]], 1 | ||
| !CHECK: store { float, float } %[[VAL_10]], ptr %[[X_NEW_VAL]], align 4 | ||
| !CHECK: %[[VAL_11:.*]] = call i1 @__atomic_compare_exchange(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], ptr %[[X_NEW_VAL]], | ||
| !i32 2, i32 2) | ||
| !CHECK: %[[VAL_12:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 4 | ||
| !CHECK: br i1 %[[VAL_11]], label %.atomic.exit, label %.atomic.cont | ||
|
|
||
| !CHECK: .atomic.exit | ||
| !AARCH64: %[[LCSSA:.*]] = phi { float, float } [ %[[VAL_10]], %.atomic.cont ] | ||
| !AARCH64: store { float, float } %[[LCSSA]], ptr %[[VAL_1]], align 4 | ||
| !X86: store { float, float } %[[VAL_10]], ptr %[[VAL_1]], align 4 | ||
|
|
||
| program main | ||
| complex*8 ia, ib | ||
| ia = (2, 2) | ||
| !$omp atomic capture | ||
| ia = ia + (1, 1) | ||
| ib = ia | ||
| !$omp end atomic | ||
| end program |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| //===-- Definition of cfloat128 type --------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_TYPES_CFLOAT128_H | ||
| #define LLVM_LIBC_TYPES_CFLOAT128_H | ||
|
|
||
| #include "../llvm-libc-macros/float-macros.h" // LDBL_MANT_DIG | ||
|
|
||
| // Currently, the complex variant of C23 `_Float128` type is only defined as a | ||
| // built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For | ||
| // clang, the complex variant of `__float128` is defined instead, and only on | ||
| // x86-64 targets for clang 11 or later. | ||
| // | ||
| // TODO: Update the complex variant of C23 `_Float128` type detection again when | ||
| // clang supports it. | ||
| #if defined(__STDC_IEC_60559_COMPLEX__) && !defined(__clang__) | ||
| #if !defined(__cplusplus) | ||
| #define LIBC_TYPES_HAS_CFLOAT128 | ||
| typedef _Complex _Float128 cfloat128; | ||
| #elif defined(__GNUC__) && __GNUC__ >= 13 | ||
| #define LIBC_TYPES_HAS_CFLOAT128 | ||
| typedef _Complex _Float128 cfloat128; | ||
| #endif | ||
| #elif __clang_major__ >= 11 && \ | ||
| (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) | ||
| // Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__ | ||
| // macro to notify the availability of __float128 type: | ||
| // https://reviews.llvm.org/D15120 | ||
| #define LIBC_TYPES_HAS_CFLOAT128 | ||
| typedef _Complex __float128 cfloat128; | ||
| #elif (LDBL_MANT_DIG == 113) | ||
| #define LIBC_TYPES_HAS_CFLOAT128 | ||
| typedef _Complex long double cfloat128; | ||
| #endif | ||
|
|
||
| #endif // LLVM_LIBC_TYPES_CFLOAT128_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| //===-- Definition of cfloat16 type ---------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_TYPES_CFLOAT16_H | ||
| #define LLVM_LIBC_TYPES_CFLOAT16_H | ||
|
|
||
| #if defined(__FLT16_MANT_DIG__) && \ | ||
| (!defined(__GNUC__) || __GNUC__ >= 13 || \ | ||
| (defined(__clang__) && __clang_major__ >= 14)) && \ | ||
| !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ | ||
| !defined(_WIN32) | ||
| #define LIBC_TYPES_HAS_CFLOAT16 | ||
| typedef _Complex _Float16 cfloat16; | ||
| #endif | ||
|
|
||
| #endif // LLVM_LIBC_TYPES_CFLOAT16_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| //===-- Complex Types support -----------------------------------*- 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // Complex Types detection and support. | ||
|
|
||
| #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H | ||
| #define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H | ||
|
|
||
| #include "include/llvm-libc-types/cfloat128.h" | ||
| #include "include/llvm-libc-types/cfloat16.h" | ||
| #include "types.h" | ||
|
|
||
| // -- cfloat16 support -------------------------------------------------------- | ||
| // LIBC_TYPES_HAS_CFLOAT16 and 'cfloat16' type is provided by | ||
| // "include/llvm-libc-types/cfloat16.h" | ||
|
|
||
| // -- cfloat128 support ------------------------------------------------------- | ||
| // LIBC_TYPES_HAS_CFLOAT128 and 'cfloat128' type are provided by | ||
| // "include/llvm-libc-types/cfloat128.h" | ||
|
|
||
| #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| //===-- Half-precision tanh(x) function -----------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/math/tanhf16.h" | ||
| #include "expxf16.h" | ||
| #include "hdr/fenv_macros.h" | ||
| #include "src/__support/CPP/array.h" | ||
| #include "src/__support/FPUtil/FEnvImpl.h" | ||
| #include "src/__support/FPUtil/FPBits.h" | ||
| #include "src/__support/FPUtil/PolyEval.h" | ||
| #include "src/__support/FPUtil/cast.h" | ||
| #include "src/__support/FPUtil/except_value_utils.h" | ||
| #include "src/__support/FPUtil/multiply_add.h" | ||
| #include "src/__support/FPUtil/nearest_integer.h" | ||
| #include "src/__support/FPUtil/rounding_mode.h" | ||
| #include "src/__support/common.h" | ||
| #include "src/__support/macros/config.h" | ||
| #include "src/__support/macros/optimization.h" | ||
|
|
||
| namespace LIBC_NAMESPACE_DECL { | ||
|
|
||
| static constexpr fputil::ExceptValues<float16, 2> TANHF16_EXCEPTS = {{ | ||
| // x = 0x1.f54p+0, tanhf16(x) = 0x1.ecp-1 (RZ) | ||
| {0x3fd5U, 0x3bb0U, 1U, 0U, 0U}, | ||
| // x = -0x1.f54p+0, tanhf16(x) = -0x1.ecp-1 (RZ) | ||
| {0xbfd5U, 0xbbb0U, 0U, 1U, 0U}, | ||
| }}; | ||
|
|
||
| LLVM_LIBC_FUNCTION(float16, tanhf16, (float16 x)) { | ||
| using FPBits = fputil::FPBits<float16>; | ||
| FPBits x_bits(x); | ||
|
|
||
| uint16_t x_u = x_bits.uintval(); | ||
| uint16_t x_abs = x_u & 0x7fffU; | ||
|
|
||
| // When -2^(-14) <= x <= -2^(-9), or |x| <= 0x1.d2p-4, | ||
| // or |x| >= atanh(1 - 2^(-11)), or x is NaN. | ||
| if (LIBC_UNLIKELY(x_abs <= 0x2f48U || x_abs >= 0x4429U)) { | ||
| // tanh(NaN) = NaN | ||
| if (x_bits.is_nan()) { | ||
| if (x_bits.is_signaling_nan()) { | ||
| fputil::raise_except_if_required(FE_INVALID); | ||
| return FPBits::quiet_nan().get_val(); | ||
| } | ||
|
|
||
| return x; | ||
| } | ||
|
|
||
| // When -2^(-14) <= x <= -2^(-9). | ||
| if (x_u >= 0x8400U && x_u <= 0x9800U) { | ||
| switch (fputil::quick_get_round()) { | ||
| case FE_TONEAREST: | ||
| case FE_DOWNWARD: | ||
| return x; | ||
| default: | ||
| return FPBits(static_cast<uint16_t>(x_u - 1U)).get_val(); | ||
| } | ||
| } | ||
|
|
||
| // When |x| <= 0x1.d2p-4. | ||
| if (x_abs <= 0x2f48U) { | ||
| float xf = x; | ||
| float xf_sq = xf * xf; | ||
| // Degree-7 Taylor expansion generated by Sollya with the following | ||
| // commands: | ||
| // > taylor(tanh(x), 7, 0); | ||
| // > display = hexadecimal; | ||
| // > // For each coefficient: | ||
| // > round(/* put coefficient here */, SG, RN); | ||
| return fputil::cast<float16>( | ||
| xf * fputil::polyeval(xf_sq, 0x1p+0f, -0x1.555556p-2f, 0x1.111112p-3f, | ||
| -0x1.ba1ba2p-5f)); | ||
| } | ||
|
|
||
| // tanh(+/-inf) = +/-1 | ||
| if (x_bits.is_inf()) | ||
| return FPBits::one(x_bits.sign()).get_val(); | ||
|
|
||
| // When |x| >= atanh(1 - 2^(-11)). | ||
| fputil::raise_except_if_required(FE_INEXACT); | ||
|
|
||
| int rounding_mode = fputil::quick_get_round(); | ||
| if ((rounding_mode == FE_TONEAREST && x_abs >= 0x4482U) || | ||
| (rounding_mode == FE_UPWARD && x_bits.is_pos()) || | ||
| (rounding_mode == FE_DOWNWARD && x_bits.is_neg())) { | ||
| return FPBits::one(x_bits.sign()).get_val(); | ||
| } | ||
| if (x_bits.is_pos()) | ||
| return fputil::cast<float16>(0x1.ffcp-1); | ||
| return fputil::cast<float16>(-0x1.ffcp-1); | ||
| } | ||
|
|
||
| if (auto r = TANHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) | ||
| return r.value(); | ||
|
|
||
| // For atanh(-1 + 2^(-11)) < x < atanh(1 - 2^(-11)), to compute tanh(x), we | ||
| // perform the following range reduction: find hi, mid, lo, such that: | ||
| // x = (hi + mid) * log(2) * 0.5 + lo, in which | ||
| // hi is an integer, | ||
| // mid * 2^5 is an integer, | ||
| // -2^(-5) <= lo < 2^(-5). | ||
| // In particular, | ||
| // hi + mid = round(x * log2(e) * 2 * 2^5) * 2^(-5). | ||
| // Then, | ||
| // tanh(x) = sinh(x)/cosh(x) | ||
| // = (e^x - e^(-x)) / (e^x + e^(-x)) | ||
| // = (e^(2x) - 1) / (e^(2x) + 1) | ||
| // = (2^(hi + mid) * e^(2*lo) - 1) / (2^(hi + mid) * e^(2*lo) + 1) | ||
| // = (e^(2*lo) - 2^(-hi - mid)) / (e^(2*lo) + 2^(-hi - mid)) | ||
| // We store 2^(-mid) in the lookup table EXP2_MID_5_BITS, and compute | ||
| // 2^(-hi - mid) by adding -hi to the exponent field of 2^(-mid). | ||
| // e^lo is computed using a degree-3 minimax polynomial generated by Sollya. | ||
|
|
||
| float xf = x; | ||
| float kf = fputil::nearest_integer(xf * (LOG2F_E * 2.0f * 0x1.0p+5f)); | ||
| int x_hi_mid = -static_cast<int>(kf); | ||
| unsigned x_hi = static_cast<unsigned>(x_hi_mid) >> 5; | ||
| unsigned x_mid = static_cast<unsigned>(x_hi_mid) & 0x1f; | ||
| // lo = x - (hi + mid) | ||
| // = round(x * log2(e) * 2 * 2^5) * log(2) * 0.5 * (-2^(-5)) + x | ||
| float lo = fputil::multiply_add(kf, LOGF_2 * 0.5f * -0x1.0p-5f, xf); | ||
|
|
||
| uint32_t exp2_hi_mid_bits = | ||
| EXP2_MID_5_BITS[x_mid] + | ||
| static_cast<uint32_t>(x_hi << fputil::FPBits<float>::FRACTION_LEN); | ||
| // exp2_hi_mid = 2^(-hi - mid) | ||
| float exp2_hi_mid = fputil::FPBits<float>(exp2_hi_mid_bits).get_val(); | ||
| // Degree-3 minimax polynomial generated by Sollya with the following | ||
| // commands: | ||
| // > display = hexadecimal; | ||
| // > P = fpminimax(expm1(2*x)/x, 2, [|SG...|], [-2^-5, 2^-5]); | ||
| // > 1 + x * P; | ||
| float exp_2lo = | ||
| fputil::polyeval(lo, 0x1p+0f, 0x1p+1f, 0x1.001p+1f, 0x1.555ddep+0f); | ||
| return fputil::cast<float16>((exp_2lo - exp2_hi_mid) / | ||
| (exp_2lo + exp2_hi_mid)); | ||
| } | ||
|
|
||
| } // namespace LIBC_NAMESPACE_DECL |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| //===-- Implementation header for tanhf16 -----------------------*- 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_SRC_MATH_TANHF16_H | ||
| #define LLVM_LIBC_SRC_MATH_TANHF16_H | ||
|
|
||
| #include "src/__support/macros/config.h" | ||
| #include "src/__support/macros/properties/types.h" | ||
|
|
||
| namespace LIBC_NAMESPACE_DECL { | ||
|
|
||
| float16 tanhf16(float16 x); | ||
|
|
||
| } // namespace LIBC_NAMESPACE_DECL | ||
|
|
||
| #endif // LLVM_LIBC_SRC_MATH_TANHF16_H |