[flang-commits] [flang] [flang] Added lowering and runtime for COMPLEX(16) intrinsics. (PR #83874)

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Tue Mar 5 11:18:08 PST 2024


https://github.com/vzakhari updated https://github.com/llvm/llvm-project/pull/83874

>From 6f43b74b5813e7cd83b01f77b6ec4926e2aefd35 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Sun, 3 Mar 2024 17:46:09 -0800
Subject: [PATCH 1/2] [flang] Added lowering and runtime for COMPLEX(16)
 intrinsics.

For `LDBL_MANT_DIG == 113` targets the FortranFloat128Math library
is just an interface library that provides sources and compilation
options to be used for building FortranRuntime - there are not extra
dependencies on other libraries, so it can be a part of FortranRuntime,
which helps to avoid extra linking steps in the compiler driver.
Targets with __float128 support in libc will also use this path.
Other targets, where the math support comes from FLANG_RUNTIME_F128_MATH_LIB,
FortranFloat128Math is built as a standalone static library,
and the compiler driver needs to conduct the linking.

Flang APIs for COMPLEX(16) are just thin C wrappers around
the C math functions. Flang uses C _Complex ABI for passing/returning
COMPLEX values, so the runtime is aligned to this.
---
 flang/lib/Optimizer/Builder/IntrinsicCall.cpp |  56 ++++++--
 flang/runtime/CMakeLists.txt                  |  43 +++++--
 flang/runtime/Float128Math/CMakeLists.txt     | 100 +++++++++------
 flang/runtime/Float128Math/cabs.cpp           |  24 ----
 flang/runtime/Float128Math/complex-math.c     |  55 ++++++++
 flang/runtime/Float128Math/complex-math.h     |  62 +++++++++
 flang/runtime/Float128Math/exponent.cpp       |   2 +-
 flang/runtime/Float128Math/fraction.cpp       |   2 +-
 flang/runtime/Float128Math/math-entries.h     | 120 ++++++++----------
 flang/runtime/Float128Math/mod-real.cpp       |   2 +-
 flang/runtime/Float128Math/modulo-real.cpp    |   2 +-
 flang/runtime/Float128Math/nearest.cpp        |   2 +-
 flang/runtime/Float128Math/rrspacing.cpp      |   2 +-
 flang/runtime/Float128Math/scale.cpp          |   2 +-
 flang/runtime/Float128Math/set-exponent.cpp   |   2 +-
 flang/runtime/Float128Math/spacing.cpp        |   2 +-
 flang/runtime/numeric.cpp                     |  60 ---------
 .../test/Lower/Intrinsics/acos_complex16.f90  |   8 ++
 .../test/Lower/Intrinsics/acosh_complex16.f90 |   8 ++
 .../test/Lower/Intrinsics/asin_complex16.f90  |   8 ++
 .../test/Lower/Intrinsics/asinh_complex16.f90 |   8 ++
 .../test/Lower/Intrinsics/atan_complex16.f90  |   8 ++
 .../test/Lower/Intrinsics/atanh_complex16.f90 |   8 ++
 flang/test/Lower/Intrinsics/cos_complex16.f90 |   8 ++
 .../test/Lower/Intrinsics/cosh_complex16.f90  |   8 ++
 flang/test/Lower/Intrinsics/exp_complex16.f90 |   8 ++
 flang/test/Lower/Intrinsics/log_complex16.f90 |   8 ++
 .../Lower/Intrinsics/missing-math-runtime.f90 |  12 --
 flang/test/Lower/Intrinsics/pow_complex16.f90 |   8 ++
 flang/test/Lower/Intrinsics/sin_complex16.f90 |   8 ++
 .../test/Lower/Intrinsics/sinh_complex16.f90  |   8 ++
 .../test/Lower/Intrinsics/sqrt_complex16.f90  |   8 ++
 flang/test/Lower/Intrinsics/tan_complex16.f90 |   8 ++
 .../test/Lower/Intrinsics/tanh_complex16.f90  |   8 ++
 34 files changed, 445 insertions(+), 233 deletions(-)
 delete mode 100644 flang/runtime/Float128Math/cabs.cpp
 create mode 100644 flang/runtime/Float128Math/complex-math.c
 create mode 100644 flang/runtime/Float128Math/complex-math.h
 create mode 100644 flang/test/Lower/Intrinsics/acos_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/acosh_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/asin_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/asinh_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/atan_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/atanh_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/cos_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/cosh_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/exp_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/log_complex16.f90
 delete mode 100644 flang/test/Lower/Intrinsics/missing-math-runtime.f90
 create mode 100644 flang/test/Lower/Intrinsics/pow_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/sin_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/sinh_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/sqrt_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/tan_complex16.f90
 create mode 100644 flang/test/Lower/Intrinsics/tanh_complex16.f90

diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index fb9b58ef69c6ae..25598ed1683162 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -689,22 +689,22 @@ prettyPrintIntrinsicName(fir::FirOpBuilder &builder, mlir::Location loc,
 }
 
 // Generate a call to the Fortran runtime library providing
-// support for 128-bit float math via a third-party library.
-// If the compiler is built without FLANG_RUNTIME_F128_MATH_LIB,
-// this function will report an error.
+// support for 128-bit float math.
+// On 'LDBL_MANT_DIG == 113' targets the implementation
+// is provided by FortranRuntime, otherwise, it is done via
+// FortranFloat128Math library. In the latter case the compiler
+// has to be built with FLANG_RUNTIME_F128_MATH_LIB to guarantee
+// proper linking actions in the driver.
 static mlir::Value genLibF128Call(fir::FirOpBuilder &builder,
                                   mlir::Location loc,
                                   const MathOperation &mathOp,
                                   mlir::FunctionType libFuncType,
                                   llvm::ArrayRef<mlir::Value> args) {
-#ifndef FLANG_RUNTIME_F128_MATH_LIB
-  std::string message = prettyPrintIntrinsicName(
-      builder, loc, "compiler is built without support for '", mathOp.key, "'",
-      libFuncType);
-  fir::emitFatalError(loc, message, /*genCrashDiag=*/false);
-#else  // FLANG_RUNTIME_F128_MATH_LIB
+  // TODO: if we knew that the C 'long double' does not have 113-bit mantissa
+  // on the target, we could have asserted that FLANG_RUNTIME_F128_MATH_LIB
+  // must be specified. For now just always generate the call even
+  // if it will be unresolved.
   return genLibCall(builder, loc, mathOp, libFuncType, args);
-#endif // FLANG_RUNTIME_F128_MATH_LIB
 }
 
 mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
@@ -926,6 +926,10 @@ constexpr auto FuncTypeInteger8Real16 =
     genFuncType<Ty::Integer<8>, Ty::Real<16>>;
 constexpr auto FuncTypeReal16Complex16 =
     genFuncType<Ty::Real<16>, Ty::Complex<16>>;
+constexpr auto FuncTypeComplex16Complex16 =
+    genFuncType<Ty::Complex<16>, Ty::Complex<16>>;
+constexpr auto FuncTypeComplex16Complex16Complex16 =
+    genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Complex<16>>;
 
 static constexpr MathOperation mathOperations[] = {
     {"abs", "fabsf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
@@ -944,6 +948,8 @@ static constexpr MathOperation mathOperations[] = {
     {"acos", RTNAME_STRING(AcosF128), FuncTypeReal16Real16, genLibF128Call},
     {"acos", "cacosf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
     {"acos", "cacos", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
+    {"acos", RTNAME_STRING(CAcosF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"acosh", "acoshf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
     {"acosh", "acosh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
     {"acosh", RTNAME_STRING(AcoshF128), FuncTypeReal16Real16, genLibF128Call},
@@ -951,6 +957,8 @@ static constexpr MathOperation mathOperations[] = {
      genLibCall},
     {"acosh", "cacosh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genLibCall},
+    {"acosh", RTNAME_STRING(CAcoshF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     // llvm.trunc behaves the same way as libm's trunc.
     {"aint", "llvm.trunc.f32", genFuncType<Ty::Real<4>, Ty::Real<4>>,
      genLibCall},
@@ -972,6 +980,8 @@ static constexpr MathOperation mathOperations[] = {
     {"asin", RTNAME_STRING(AsinF128), FuncTypeReal16Real16, genLibF128Call},
     {"asin", "casinf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
     {"asin", "casin", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
+    {"asin", RTNAME_STRING(CAsinF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"asinh", "asinhf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
     {"asinh", "asinh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
     {"asinh", RTNAME_STRING(AsinhF128), FuncTypeReal16Real16, genLibF128Call},
@@ -979,6 +989,8 @@ static constexpr MathOperation mathOperations[] = {
      genLibCall},
     {"asinh", "casinh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genLibCall},
+    {"asinh", RTNAME_STRING(CAsinhF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"atan", "atanf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
      genMathOp<mlir::math::AtanOp>},
     {"atan", "atan", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -986,6 +998,8 @@ static constexpr MathOperation mathOperations[] = {
     {"atan", RTNAME_STRING(AtanF128), FuncTypeReal16Real16, genLibF128Call},
     {"atan", "catanf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
     {"atan", "catan", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
+    {"atan", RTNAME_STRING(CAtanF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"atan2", "atan2f", genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Real<4>>,
      genMathOp<mlir::math::Atan2Op>},
     {"atan2", "atan2", genFuncType<Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>,
@@ -999,6 +1013,8 @@ static constexpr MathOperation mathOperations[] = {
      genLibCall},
     {"atanh", "catanh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genLibCall},
+    {"atanh", RTNAME_STRING(CAtanhF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"bessel_j0", "j0f", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
     {"bessel_j0", "j0", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
     {"bessel_j0", RTNAME_STRING(J0F128), FuncTypeReal16Real16, genLibF128Call},
@@ -1038,11 +1054,15 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::CosOp>},
     {"cos", "ccos", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::CosOp>},
+    {"cos", RTNAME_STRING(CCosF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"cosh", "coshf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
     {"cosh", "cosh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
     {"cosh", RTNAME_STRING(CoshF128), FuncTypeReal16Real16, genLibF128Call},
     {"cosh", "ccoshf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
     {"cosh", "ccosh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
+    {"cosh", RTNAME_STRING(CCoshF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"divc",
      {},
      genFuncType<Ty::Complex<2>, Ty::Complex<2>, Ty::Complex<2>>,
@@ -1080,6 +1100,8 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::ExpOp>},
     {"exp", "cexp", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::ExpOp>},
+    {"exp", RTNAME_STRING(CExpF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"feclearexcept", "feclearexcept",
      genFuncType<Ty::Integer<4>, Ty::Integer<4>>, genLibCall},
     {"fedisableexcept", "fedisableexcept",
@@ -1131,6 +1153,8 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::LogOp>},
     {"log", "clog", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::LogOp>},
+    {"log", RTNAME_STRING(CLogF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"log10", "log10f", genFuncType<Ty::Real<4>, Ty::Real<4>>,
      genMathOp<mlir::math::Log10Op>},
     {"log10", "log10", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1178,6 +1202,8 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::PowOp>},
     {"pow", "cpow", genFuncType<Ty::Complex<8>, Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::PowOp>},
+    {"pow", RTNAME_STRING(CPowF128), FuncTypeComplex16Complex16Complex16,
+     genLibF128Call},
     {"pow", RTNAME_STRING(FPow4i),
      genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Integer<4>>,
      genMathOp<mlir::math::FPowIOp>},
@@ -1222,11 +1248,15 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::SinOp>},
     {"sin", "csin", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::SinOp>},
+    {"sin", RTNAME_STRING(CSinF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"sinh", "sinhf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
     {"sinh", "sinh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
     {"sinh", RTNAME_STRING(SinhF128), FuncTypeReal16Real16, genLibF128Call},
     {"sinh", "csinhf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
     {"sinh", "csinh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
+    {"sinh", RTNAME_STRING(CSinhF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"sqrt", "sqrtf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
      genMathOp<mlir::math::SqrtOp>},
     {"sqrt", "sqrt", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1236,6 +1266,8 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::SqrtOp>},
     {"sqrt", "csqrt", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::SqrtOp>},
+    {"sqrt", RTNAME_STRING(CSqrtF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"tan", "tanf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
      genMathOp<mlir::math::TanOp>},
     {"tan", "tan", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1245,6 +1277,8 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::TanOp>},
     {"tan", "ctan", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::TanOp>},
+    {"tan", RTNAME_STRING(CTanF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
     {"tanh", "tanhf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
      genMathOp<mlir::math::TanhOp>},
     {"tanh", "tanh", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1254,6 +1288,8 @@ static constexpr MathOperation mathOperations[] = {
      genComplexMathOp<mlir::complex::TanhOp>},
     {"tanh", "ctanh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
      genComplexMathOp<mlir::complex::TanhOp>},
+    {"tanh", RTNAME_STRING(CTanhF128), FuncTypeComplex16Complex16,
+     genLibF128Call},
 };
 
 // This helper class computes a "distance" between two function types.
diff --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt
index ac89184a7cbffc..7dd60b5edcd5fb 100644
--- a/flang/runtime/CMakeLists.txt
+++ b/flang/runtime/CMakeLists.txt
@@ -57,12 +57,6 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
     REAL(16) is mapped to __float128, or libm for targets where REAL(16) \
     is mapped to long double, etc."
     )
-
-  if (NOT FLANG_RUNTIME_F128_MATH_LIB STREQUAL "")
-    add_compile_definitions(
-      -DFLANG_RUNTIME_F128_MATH_LIB="${FLANG_RUNTIME_F128_MATH_LIB}"
-      )
-  endif()
 endif()
 
 include(CheckCXXSymbolExists)
@@ -78,6 +72,16 @@ check_cxx_source_compiles(
   "
   HAVE_DECL_STRERROR_S)
 
+# Check if 128-bit float computations can be done via long double.
+check_cxx_source_compiles(
+  "#include <cfloat>
+   #if LDBL_MANT_DIG != 113
+   #error LDBL_MANT_DIG != 113
+   #endif
+   int main() { return 0; }
+  "
+  HAVE_LDBL_MANT_DIG_113)
+
 check_cxx_compiler_flag(-fno-lto FLANG_RUNTIME_HAS_FNO_LTO_FLAG)
 if (FLANG_RUNTIME_HAS_FNO_LTO_FLAG)
   set(NO_LTO_FLAGS "-fno-lto")
@@ -100,9 +104,7 @@ add_definitions(-U_GLIBCXX_ASSERTIONS)
 add_definitions(-U_LIBCPP_ENABLE_ASSERTIONS)
 
 add_subdirectory(FortranMain)
-if (NOT ${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "")
-  add_subdirectory(Float128Math)
-endif()
+add_subdirectory(Float128Math)
 
 set(sources
   ISO_Fortran_binding.cpp
@@ -319,6 +321,29 @@ if (NOT FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD STREQUAL "off")
   endif()
 endif()
 
+if (NOT TARGET FortranFloat128Math)
+  # If FortranFloat128Math is not defined, then we are not building
+  # standalone FortranFloat128Math library. Instead, include
+  # the relevant sources into FortranRuntime itself.
+  # The information is provided via FortranFloat128MathILib
+  # interface library.
+  get_target_property(f128_sources
+    FortranFloat128MathILib INTERFACE_SOURCES
+    )
+  if (f128_sources)
+    # The interface may define special macros for Float128Math files,
+    # so we need to propagate them.
+    get_target_property(f128_defs
+      FortranFloat128MathILib INTERFACE_COMPILE_DEFINITIONS
+      )
+    set_property(SOURCE ${f128_sources}
+      APPEND PROPERTY COMPILE_DEFINITIONS
+      ${f128_defs}
+      )
+    list(APPEND sources ${f128_sources})
+  endif()
+endif()
+
 if (NOT DEFINED MSVC)
   add_flang_library(FortranRuntime
     ${sources}
diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt
index 60d44c78be0faf..b84f9251a8a485 100644
--- a/flang/runtime/Float128Math/CMakeLists.txt
+++ b/flang/runtime/Float128Math/CMakeLists.txt
@@ -16,34 +16,6 @@
 
 include(CheckLibraryExists)
 
-if (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libquadmath")
-  check_include_file(quadmath.h FOUND_QUADMATH_HEADER)
-  if(FOUND_QUADMATH_HEADER)
-    add_compile_definitions(HAS_QUADMATHLIB)
-  else()
-    message(FATAL_ERROR
-      "FLANG_RUNTIME_F128_MATH_LIB setting requires quadmath.h "
-      "to be available: ${FLANG_RUNTIME_F128_MATH_LIB}"
-      )
-  endif()
-elseif (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libm")
-  check_library_exists(m sinl "" FOUND_LIBM)
-  check_library_exists(m sinf128 "" FOUND_LIBMF128)
-  if (FOUND_LIBM)
-    add_compile_definitions(HAS_LIBM)
-  endif()
-  if (FOUND_LIBMF128)
-    add_compile_definitions(HAS_LIBMF128)
-  endif()
-endif()
-
-if (NOT FOUND_QUADMATH_HEADER AND NOT FOUND_LIBM)
-  message(FATAL_ERROR
-    "Unsupported third-party library for Fortran F128 math runtime: "
-    "${FLANG_RUNTIME_F128_MATH_LIB}"
-    )
-endif()
-
 set(sources
   acos.cpp
   acosh.cpp
@@ -52,8 +24,8 @@ set(sources
   atan.cpp
   atan2.cpp
   atanh.cpp
-  cabs.cpp
   ceil.cpp
+  complex-math.c
   cos.cpp
   cosh.cpp
   erf.cpp
@@ -94,18 +66,62 @@ set(sources
   )
 
 include_directories(AFTER "${CMAKE_CURRENT_SOURCE_DIR}/..")
-add_flang_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN ${sources})
+add_library(FortranFloat128MathILib INTERFACE)
 
-if (DEFINED MSVC)
-  set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
-  add_flang_library(FortranFloat128Math.static STATIC INSTALL_WITH_TOOLCHAIN
-    ${sources}
-    )
-  set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
-  add_flang_library(FortranFloat128Math.static_dbg STATIC INSTALL_WITH_TOOLCHAIN
-    ${sources}
-    )
-  add_dependencies(FortranFloat128Math FortranFloat128Math.static
-    FortranFloat128Math.static_dbg
-    )
+if (FLANG_RUNTIME_F128_MATH_LIB)
+  if (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libquadmath")
+    check_include_file(quadmath.h FOUND_QUADMATH_HEADER)
+    if(FOUND_QUADMATH_HEADER)
+      add_compile_definitions(HAS_QUADMATHLIB)
+    else()
+      message(FATAL_ERROR
+        "FLANG_RUNTIME_F128_MATH_LIB setting requires quadmath.h "
+        "to be available: ${FLANG_RUNTIME_F128_MATH_LIB}"
+        )
+    endif()
+  else()
+    message(FATAL_ERROR
+      "Unsupported third-party library for Fortran F128 math runtime: "
+      "${FLANG_RUNTIME_F128_MATH_LIB}"
+      )
+  endif()
+
+  add_flang_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN
+    ${sources})
+
+  if (DEFINED MSVC)
+    set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
+    add_flang_library(FortranFloat128Math.static STATIC INSTALL_WITH_TOOLCHAIN
+      ${sources}
+      )
+    set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
+    add_flang_library(FortranFloat128Math.static_dbg STATIC INSTALL_WITH_TOOLCHAIN
+      ${sources}
+      )
+    add_dependencies(FortranFloat128Math FortranFloat128Math.static
+      FortranFloat128Math.static_dbg
+      )
+  endif()
+elseif (HAVE_LDBL_MANT_DIG_113)
+  # We can use 'long double' versions from libc.
+  check_library_exists(m sinl "" FOUND_LIBM)
+  if (NOT FOUND_LIBM)
+    message(FATAL_ERROR "FortranRuntime cannot build without libm")
+  endif()
+  if (FOUND_LIBM)
+    target_compile_definitions(FortranFloat128MathILib INTERFACE
+      HAS_LIBM
+      )
+    target_sources(FortranFloat128MathILib INTERFACE ${sources})
+  endif()
+else()
+  # We can use '__float128' version from libc, if it has them.
+  check_library_exists(m sinf128 "" FOUND_LIBMF128)
+  if (FOUND_LIBMF128)
+    target_compile_definitions(FortranFloat128MathILib INTERFACE
+      HAS_LIBMF128
+      )
+    # Enable this, when math-entries.h and complex-math.h is ready.
+    # target_sources(FortranFloat128MathILib INTERFACE ${sources})
+  endif()
 endif()
diff --git a/flang/runtime/Float128Math/cabs.cpp b/flang/runtime/Float128Math/cabs.cpp
deleted file mode 100644
index 3b8c9d17003c6e..00000000000000
--- a/flang/runtime/Float128Math/cabs.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===-- runtime/Float128Math/cabs.cpp -------------------------------------===//
-//
-// 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 "math-entries.h"
-
-namespace Fortran::runtime {
-extern "C" {
-#if 0
-// FIXME: temporarily disabled. Need to add pure C entry point
-// using C _Complex ABI.
-#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
-// NOTE: Flang calls the runtime APIs using C _Complex ABI
-CppTypeFor<TypeCategory::Real, 16> RTDEF(CAbsF128)(CFloat128ComplexType x) {
-  return CAbs<true>::invoke(x);
-}
-#endif
-#endif
-} // extern "C"
-} // namespace Fortran::runtime
diff --git a/flang/runtime/Float128Math/complex-math.c b/flang/runtime/Float128Math/complex-math.c
new file mode 100644
index 00000000000000..d0180c63a0d7bf
--- /dev/null
+++ b/flang/runtime/Float128Math/complex-math.c
@@ -0,0 +1,55 @@
+/*===-- runtime/Float128Math/complex-math.c -------------------------*- 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
+ *
+ * ===-----------------------------------------------------------------------===
+ */
+
+#include "complex-math.h"
+
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
+
+CFloat128Type RTDEF(CAbsF128)(CFloat128ComplexType x) { return CAbs(x); }
+CFloat128ComplexType RTDEF(CAcosF128)(CFloat128ComplexType x) {
+  return CAcos(x);
+}
+CFloat128ComplexType RTDEF(CAcoshF128)(CFloat128ComplexType x) {
+  return CAcosh(x);
+}
+CFloat128ComplexType RTDEF(CAsinF128)(CFloat128ComplexType x) {
+  return CAsin(x);
+}
+CFloat128ComplexType RTDEF(CAsinhF128)(CFloat128ComplexType x) {
+  return CAsinh(x);
+}
+CFloat128ComplexType RTDEF(CAtanF128)(CFloat128ComplexType x) {
+  return CAtan(x);
+}
+CFloat128ComplexType RTDEF(CAtanhF128)(CFloat128ComplexType x) {
+  return CAtanh(x);
+}
+CFloat128ComplexType RTDEF(CCosF128)(CFloat128ComplexType x) { return CCos(x); }
+CFloat128ComplexType RTDEF(CCoshF128)(CFloat128ComplexType x) {
+  return CCosh(x);
+}
+CFloat128ComplexType RTDEF(CExpF128)(CFloat128ComplexType x) { return CExp(x); }
+CFloat128ComplexType RTDEF(CLogF128)(CFloat128ComplexType x) { return CLog(x); }
+CFloat128ComplexType RTDEF(CPowF128)(
+    CFloat128ComplexType x, CFloat128ComplexType p) {
+  return CPow(x, p);
+}
+CFloat128ComplexType RTDEF(CSinF128)(CFloat128ComplexType x) { return CSin(x); }
+CFloat128ComplexType RTDEF(CSinhF128)(CFloat128ComplexType x) {
+  return CSinh(x);
+}
+CFloat128ComplexType RTDEF(CSqrtF128)(CFloat128ComplexType x) {
+  return CSqrt(x);
+}
+CFloat128ComplexType RTDEF(CTanF128)(CFloat128ComplexType x) { return CTan(x); }
+CFloat128ComplexType RTDEF(CTanhF128)(CFloat128ComplexType x) {
+  return CTanh(x);
+}
+
+#endif // LDBL_MANT_DIG == 113 || HAS_FLOAT128
diff --git a/flang/runtime/Float128Math/complex-math.h b/flang/runtime/Float128Math/complex-math.h
new file mode 100644
index 00000000000000..81dd53a175d1aa
--- /dev/null
+++ b/flang/runtime/Float128Math/complex-math.h
@@ -0,0 +1,62 @@
+/*===-- runtime/Float128Math/complex-math.h -------------------------*- 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 FORTRAN_RUNTIME_FLOAT128MATH_COMPLEX_MATH_H_
+#define FORTRAN_RUNTIME_FLOAT128MATH_COMPLEX_MATH_H_
+
+#include "flang/Common/float128.h"
+#include "flang/Runtime/entry-names.h"
+
+#if HAS_QUADMATHLIB
+#include "quadmath.h"
+#define CAbs(x) cabsq(x)
+#define CAcos(x) cacosq(x)
+#define CAcosh(x) cacoshq(x)
+#define CAsin(x) casinq(x)
+#define CAsinh(x) casinhq(x)
+#define CAtan(x) catanq(x)
+#define CAtanh(x) catanhq(x)
+#define CCos(x) ccosq(x)
+#define CCosh(x) ccoshq(x)
+#define CExp(x) cexpq(x)
+#define CLog(x) clogq(x)
+#define CPow(x, p) cpowq(x, p)
+#define CSin(x) csinq(x)
+#define CSinh(x) csinhq(x)
+#define CSqrt(x) csqrtq(x)
+#define CTan(x) ctanq(x)
+#define CTanh(x) ctanhq(x)
+#elif LDBL_MANT_DIG == 113
+/* Use 'long double' versions of libm functions. */
+#include <complex.h>
+
+#define CAbs(x) cabsl(x)
+#define CAcos(x) cacosl(x)
+#define CAcosh(x) cacoshl(x)
+#define CAsin(x) casinl(x)
+#define CAsinh(x) casinhl(x)
+#define CAtan(x) catanl(x)
+#define CAtanh(x) catanhl(x)
+#define CCos(x) ccosl(x)
+#define CCosh(x) ccoshl(x)
+#define CExp(x) cexpl(x)
+#define CLog(x) clogl(x)
+#define CPow(x, p) cpowl(x, p)
+#define CSin(x) csinl(x)
+#define CSinh(x) csinhl(x)
+#define CSqrt(x) csqrtl(x)
+#define CTan(x) ctanl(x)
+#define CTanh(x) ctanhl(x)
+#elif HAS_LIBMF128
+/* We can use __float128 versions of libm functions.
+ * __STDC_WANT_IEC_60559_TYPES_EXT__ needs to be defined
+ * before including math.h to enable the *f128 prototypes. */
+#error "Float128Math build with glibc>=2.26 is unsupported yet"
+#endif
+
+#endif /* FORTRAN_RUNTIME_FLOAT128MATH_COMPLEX_MATH_H_ */
diff --git a/flang/runtime/Float128Math/exponent.cpp b/flang/runtime/Float128Math/exponent.cpp
index c0e43c0ee8d36e..1be1dd0d0ac8b8 100644
--- a/flang/runtime/Float128Math/exponent.cpp
+++ b/flang/runtime/Float128Math/exponent.cpp
@@ -12,7 +12,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 // EXPONENT (16.9.75)
 CppTypeFor<TypeCategory::Integer, 4> RTDEF(Exponent16_4)(F128Type x) {
   return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
diff --git a/flang/runtime/Float128Math/fraction.cpp b/flang/runtime/Float128Math/fraction.cpp
index 8de6d3c7ff6c07..8c9889b7f6871e 100644
--- a/flang/runtime/Float128Math/fraction.cpp
+++ b/flang/runtime/Float128Math/fraction.cpp
@@ -12,7 +12,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 // FRACTION (16.9.80)
 F128Type RTDEF(Fraction16)(F128Type x) { return Fraction(x); }
 #endif
diff --git a/flang/runtime/Float128Math/math-entries.h b/flang/runtime/Float128Math/math-entries.h
index ad3f6aa18aa9a1..1eab7c86f2ed76 100644
--- a/flang/runtime/Float128Math/math-entries.h
+++ b/flang/runtime/Float128Math/math-entries.h
@@ -106,11 +106,59 @@ DEFINE_FALLBACK_F128(Y0)
 DEFINE_FALLBACK_F128(Y1)
 DEFINE_FALLBACK_F128(Yn)
 
-#if HAS_LIBM
-#include <limits>
+#if HAS_QUADMATHLIB
+// Define wrapper callers for libquadmath.
+#include "quadmath.h"
+DEFINE_SIMPLE_ALIAS(Abs, fabsq)
+DEFINE_SIMPLE_ALIAS(Acos, acosq)
+DEFINE_SIMPLE_ALIAS(Acosh, acoshq)
+DEFINE_SIMPLE_ALIAS(Asin, asinq)
+DEFINE_SIMPLE_ALIAS(Asinh, asinhq)
+DEFINE_SIMPLE_ALIAS(Atan, atanq)
+DEFINE_SIMPLE_ALIAS(Atan2, atan2q)
+DEFINE_SIMPLE_ALIAS(Atanh, atanhq)
+DEFINE_SIMPLE_ALIAS(Ceil, ceilq)
+DEFINE_SIMPLE_ALIAS(Cos, cosq)
+DEFINE_SIMPLE_ALIAS(Cosh, coshq)
+DEFINE_SIMPLE_ALIAS(Erf, erfq)
+DEFINE_SIMPLE_ALIAS(Erfc, erfcq)
+DEFINE_SIMPLE_ALIAS(Exp, expq)
+DEFINE_SIMPLE_ALIAS(Floor, floorq)
+DEFINE_SIMPLE_ALIAS(Frexp, frexpq)
+DEFINE_SIMPLE_ALIAS(Hypot, hypotq)
+DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq)
+DEFINE_SIMPLE_ALIAS(Isinf, isinfq)
+DEFINE_SIMPLE_ALIAS(Isnan, isnanq)
+DEFINE_SIMPLE_ALIAS(J0, j0q)
+DEFINE_SIMPLE_ALIAS(J1, j1q)
+DEFINE_SIMPLE_ALIAS(Jn, jnq)
+DEFINE_SIMPLE_ALIAS(Ldexp, ldexpq)
+DEFINE_SIMPLE_ALIAS(Lgamma, lgammaq)
+DEFINE_SIMPLE_ALIAS(Llround, llroundq)
+DEFINE_SIMPLE_ALIAS(Log, logq)
+DEFINE_SIMPLE_ALIAS(Log10, log10q)
+DEFINE_SIMPLE_ALIAS(Lround, lroundq)
+DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq)
+DEFINE_SIMPLE_ALIAS(Pow, powq)
+DEFINE_SIMPLE_ALIAS(Round, roundq)
+DEFINE_SIMPLE_ALIAS(Sin, sinq)
+DEFINE_SIMPLE_ALIAS(Sinh, sinhq)
+DEFINE_SIMPLE_ALIAS(Sqrt, sqrtq)
+DEFINE_SIMPLE_ALIAS(Tan, tanq)
+DEFINE_SIMPLE_ALIAS(Tanh, tanhq)
+DEFINE_SIMPLE_ALIAS(Tgamma, tgammaq)
+DEFINE_SIMPLE_ALIAS(Trunc, truncq)
+DEFINE_SIMPLE_ALIAS(Y0, y0q)
+DEFINE_SIMPLE_ALIAS(Y1, y1q)
+DEFINE_SIMPLE_ALIAS(Yn, ynq)
 
+// Use cmath INFINITY/NAN definition. Rely on C implicit conversions.
+#define F128_RT_INFINITY (INFINITY)
+#define F128_RT_QNAN (NAN)
+#elif LDBL_MANT_DIG == 113
 // Define wrapper callers for libm.
-#if LDBL_MANT_DIG == 113
+#include <limits>
+
 // Use STD math functions. They provide IEEE-754 128-bit float
 // support either via 'long double' or __float128.
 // The Bessel's functions are not present in STD namespace.
@@ -122,9 +170,6 @@ DEFINE_SIMPLE_ALIAS(Asinh, std::asinh)
 DEFINE_SIMPLE_ALIAS(Atan, std::atan)
 DEFINE_SIMPLE_ALIAS(Atan2, std::atan2)
 DEFINE_SIMPLE_ALIAS(Atanh, std::atanh)
-// TODO: enable complex abs, when ABI adjustment for complex
-// data type is resolved.
-// DEFINE_SIMPLE_ALIAS(CAbs, std::abs)
 DEFINE_SIMPLE_ALIAS(Ceil, std::ceil)
 DEFINE_SIMPLE_ALIAS(Cos, std::cos)
 DEFINE_SIMPLE_ALIAS(Cosh, std::cosh)
@@ -165,70 +210,11 @@ DEFINE_SIMPLE_ALIAS(Yn, ynl)
   (std::numeric_limits<CppTypeFor<TypeCategory::Real, 16>>::infinity())
 #define F128_RT_QNAN \
   (std::numeric_limits<CppTypeFor<TypeCategory::Real, 16>>::quiet_NaN())
-#else // LDBL_MANT_DIG != 113
-#if !HAS_LIBMF128
-// glibc >=2.26 seems to have complete support for __float128
-// versions of the math functions.
-#error "FLANG_RUNTIME_F128_MATH_LIB=libm build requires libm >=2.26"
-#endif
-
+#elif HAS_LIBMF128
 // We can use __float128 versions of libm functions.
 // __STDC_WANT_IEC_60559_TYPES_EXT__ needs to be defined
 // before including cmath to enable the *f128 prototypes.
-// TODO: this needs to be enabled separately, especially
-// for complex data types that require C++ complex to C complex
-// adjustment to match the ABIs.
-#error "Unsupported FLANG_RUNTIME_F128_MATH_LIB=libm build"
-#endif // LDBL_MANT_DIG != 113
-#elif HAS_QUADMATHLIB
-// Define wrapper callers for libquadmath.
-#include "quadmath.h"
-DEFINE_SIMPLE_ALIAS(Abs, fabsq)
-DEFINE_SIMPLE_ALIAS(Acos, acosq)
-DEFINE_SIMPLE_ALIAS(Acosh, acoshq)
-DEFINE_SIMPLE_ALIAS(Asin, asinq)
-DEFINE_SIMPLE_ALIAS(Asinh, asinhq)
-DEFINE_SIMPLE_ALIAS(Atan, atanq)
-DEFINE_SIMPLE_ALIAS(Atan2, atan2q)
-DEFINE_SIMPLE_ALIAS(Atanh, atanhq)
-DEFINE_SIMPLE_ALIAS(Ceil, ceilq)
-DEFINE_SIMPLE_ALIAS(Cos, cosq)
-DEFINE_SIMPLE_ALIAS(Cosh, coshq)
-DEFINE_SIMPLE_ALIAS(Erf, erfq)
-DEFINE_SIMPLE_ALIAS(Erfc, erfcq)
-DEFINE_SIMPLE_ALIAS(Exp, expq)
-DEFINE_SIMPLE_ALIAS(Floor, floorq)
-DEFINE_SIMPLE_ALIAS(Frexp, frexpq)
-DEFINE_SIMPLE_ALIAS(Hypot, hypotq)
-DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq)
-DEFINE_SIMPLE_ALIAS(Isinf, isinfq)
-DEFINE_SIMPLE_ALIAS(Isnan, isnanq)
-DEFINE_SIMPLE_ALIAS(J0, j0q)
-DEFINE_SIMPLE_ALIAS(J1, j1q)
-DEFINE_SIMPLE_ALIAS(Jn, jnq)
-DEFINE_SIMPLE_ALIAS(Ldexp, ldexpq)
-DEFINE_SIMPLE_ALIAS(Lgamma, lgammaq)
-DEFINE_SIMPLE_ALIAS(Llround, llroundq)
-DEFINE_SIMPLE_ALIAS(Log, logq)
-DEFINE_SIMPLE_ALIAS(Log10, log10q)
-DEFINE_SIMPLE_ALIAS(Lround, lroundq)
-DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq)
-DEFINE_SIMPLE_ALIAS(Pow, powq)
-DEFINE_SIMPLE_ALIAS(Round, roundq)
-DEFINE_SIMPLE_ALIAS(Sin, sinq)
-DEFINE_SIMPLE_ALIAS(Sinh, sinhq)
-DEFINE_SIMPLE_ALIAS(Sqrt, sqrtq)
-DEFINE_SIMPLE_ALIAS(Tan, tanq)
-DEFINE_SIMPLE_ALIAS(Tanh, tanhq)
-DEFINE_SIMPLE_ALIAS(Tgamma, tgammaq)
-DEFINE_SIMPLE_ALIAS(Trunc, truncq)
-DEFINE_SIMPLE_ALIAS(Y0, y0q)
-DEFINE_SIMPLE_ALIAS(Y1, y1q)
-DEFINE_SIMPLE_ALIAS(Yn, ynq)
-
-// Use cmath INFINITY/NAN definition. Rely on C implicit conversions.
-#define F128_RT_INFINITY (INFINITY)
-#define F128_RT_QNAN (NAN)
+#error "Float128Math build with glibc>=2.26 is unsupported yet"
 #endif
 
 } // namespace Fortran::runtime
diff --git a/flang/runtime/Float128Math/mod-real.cpp b/flang/runtime/Float128Math/mod-real.cpp
index 9cc2926e45d51a..42e6ce76e2fa1b 100644
--- a/flang/runtime/Float128Math/mod-real.cpp
+++ b/flang/runtime/Float128Math/mod-real.cpp
@@ -12,7 +12,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 // MOD (16.9.135)
 F128Type RTDEF(ModReal16)(
     F128Type x, F128Type p, const char *sourceFile, int sourceLine) {
diff --git a/flang/runtime/Float128Math/modulo-real.cpp b/flang/runtime/Float128Math/modulo-real.cpp
index b25797fd8f4128..13000aba8c8323 100644
--- a/flang/runtime/Float128Math/modulo-real.cpp
+++ b/flang/runtime/Float128Math/modulo-real.cpp
@@ -12,7 +12,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 // MODULO (16.9.136)
 F128Type RTDEF(ModuloReal16)(
     F128Type x, F128Type p, const char *sourceFile, int sourceLine) {
diff --git a/flang/runtime/Float128Math/nearest.cpp b/flang/runtime/Float128Math/nearest.cpp
index fd990532e52293..148ac4ef839160 100644
--- a/flang/runtime/Float128Math/nearest.cpp
+++ b/flang/runtime/Float128Math/nearest.cpp
@@ -11,7 +11,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 CppTypeFor<TypeCategory::Real, 16> RTDEF(Nearest16)(
     CppTypeFor<TypeCategory::Real, 16> x, bool positive) {
   return Nextafter<true>::invoke(
diff --git a/flang/runtime/Float128Math/rrspacing.cpp b/flang/runtime/Float128Math/rrspacing.cpp
index f2187f42313ae5..feddac418eec39 100644
--- a/flang/runtime/Float128Math/rrspacing.cpp
+++ b/flang/runtime/Float128Math/rrspacing.cpp
@@ -12,7 +12,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 // FRACTION (16.9.80)
 F128Type RTDEF(RRSpacing16)(F128Type x) { return RRSpacing<113>(x); }
 #endif
diff --git a/flang/runtime/Float128Math/scale.cpp b/flang/runtime/Float128Math/scale.cpp
index d6b843150e726f..0be958bd9f2a72 100644
--- a/flang/runtime/Float128Math/scale.cpp
+++ b/flang/runtime/Float128Math/scale.cpp
@@ -13,7 +13,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 F128Type RTDEF(Scale16)(F128Type x, std::int64_t p) {
   auto ip{static_cast<int>(p)};
   if (ip != p) {
diff --git a/flang/runtime/Float128Math/set-exponent.cpp b/flang/runtime/Float128Math/set-exponent.cpp
index 0f942d238b8f35..99c34af7962b9a 100644
--- a/flang/runtime/Float128Math/set-exponent.cpp
+++ b/flang/runtime/Float128Math/set-exponent.cpp
@@ -12,7 +12,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 // SET_EXPONENT (16.9.171)
 F128Type RTDEF(SetExponent16)(F128Type x, std::int64_t p) {
   return SetExponent(x, p);
diff --git a/flang/runtime/Float128Math/spacing.cpp b/flang/runtime/Float128Math/spacing.cpp
index d00e74644f8a86..a86c0b30e567ab 100644
--- a/flang/runtime/Float128Math/spacing.cpp
+++ b/flang/runtime/Float128Math/spacing.cpp
@@ -12,7 +12,7 @@
 namespace Fortran::runtime {
 extern "C" {
 
-#if LDBL_MANT_DIG != 113 && HAS_FLOAT128
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
 // SPACING (16.9.180)
 F128Type RTDEF(Spacing16)(F128Type x) { return Spacing<113>(x); }
 #endif
diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp
index d61f32e1d5b866..abd3e500029fe4 100644
--- a/flang/runtime/numeric.cpp
+++ b/flang/runtime/numeric.cpp
@@ -324,16 +324,6 @@ CppTypeFor<TypeCategory::Integer, 8> RTDEF(Exponent10_8)(
     CppTypeFor<TypeCategory::Real, 10> x) {
   return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Integer, 4> RTDEF(Exponent16_4)(
-    CppTypeFor<TypeCategory::Real, 16> x) {
-  return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
-}
-CppTypeFor<TypeCategory::Integer, 8> RTDEF(Exponent16_8)(
-    CppTypeFor<TypeCategory::Real, 16> x) {
-  return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
-}
 #endif
 
 CppTypeFor<TypeCategory::Integer, 1> RTDEF(Floor4_1)(
@@ -441,12 +431,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(Fraction10)(
     CppTypeFor<TypeCategory::Real, 10> x) {
   return Fraction(x);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(Fraction16)(
-    CppTypeFor<TypeCategory::Real, 16> x) {
-  return Fraction(x);
-}
 #endif
 
 bool RTDEF(IsFinite4)(CppTypeFor<TypeCategory::Real, 4> x) {
@@ -529,13 +513,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(ModReal10)(
     const char *sourceFile, int sourceLine) {
   return RealMod<false>(x, p, sourceFile, sourceLine);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(ModReal16)(
-    CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
-    const char *sourceFile, int sourceLine) {
-  return RealMod<false>(x, p, sourceFile, sourceLine);
-}
 #endif
 
 CppTypeFor<TypeCategory::Integer, 1> RTDEF(ModuloInteger1)(
@@ -586,13 +563,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(ModuloReal10)(
     const char *sourceFile, int sourceLine) {
   return RealMod<true>(x, p, sourceFile, sourceLine);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(ModuloReal16)(
-    CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
-    const char *sourceFile, int sourceLine) {
-  return RealMod<true>(x, p, sourceFile, sourceLine);
-}
 #endif
 
 CppTypeFor<TypeCategory::Real, 4> RTDEF(Nearest4)(
@@ -608,12 +578,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(Nearest10)(
     CppTypeFor<TypeCategory::Real, 10> x, bool positive) {
   return Nearest<64>(x, positive);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(Nearest16)(
-    CppTypeFor<TypeCategory::Real, 16> x, bool positive) {
-  return Nearest<113>(x, positive);
-}
 #endif
 
 CppTypeFor<TypeCategory::Integer, 1> RTDEF(Nint4_1)(
@@ -721,12 +685,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(RRSpacing10)(
     CppTypeFor<TypeCategory::Real, 10> x) {
   return RRSpacing<64>(x);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(RRSpacing16)(
-    CppTypeFor<TypeCategory::Real, 16> x) {
-  return RRSpacing<113>(x);
-}
 #endif
 
 CppTypeFor<TypeCategory::Real, 4> RTDEF(SetExponent4)(
@@ -742,12 +700,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(SetExponent10)(
     CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
   return SetExponent(x, p);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(SetExponent16)(
-    CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
-  return SetExponent(x, p);
-}
 #endif
 
 CppTypeFor<TypeCategory::Real, 4> RTDEF(Scale4)(
@@ -763,12 +715,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(Scale10)(
     CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
   return Scale(x, p);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(Scale16)(
-    CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
-  return Scale(x, p);
-}
 #endif
 
 // SELECTED_INT_KIND
@@ -823,12 +769,6 @@ CppTypeFor<TypeCategory::Real, 10> RTDEF(Spacing10)(
     CppTypeFor<TypeCategory::Real, 10> x) {
   return Spacing<64>(x);
 }
-#elif LDBL_MANT_DIG == 113
-// The __float128 implementation resides in FortranFloat128Math library.
-CppTypeFor<TypeCategory::Real, 16> RTDEF(Spacing16)(
-    CppTypeFor<TypeCategory::Real, 16> x) {
-  return Spacing<113>(x);
-}
 #endif
 
 CppTypeFor<TypeCategory::Real, 4> RTDEF(FPow4i)(
diff --git a/flang/test/Lower/Intrinsics/acos_complex16.f90 b/flang/test/Lower/Intrinsics/acos_complex16.f90
new file mode 100644
index 00000000000000..5b3545e472e043
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/acos_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACAcosF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = acos(a)
+end
diff --git a/flang/test/Lower/Intrinsics/acosh_complex16.f90 b/flang/test/Lower/Intrinsics/acosh_complex16.f90
new file mode 100644
index 00000000000000..a80238d72e4517
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/acosh_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACAcoshF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = acosh(a)
+end
diff --git a/flang/test/Lower/Intrinsics/asin_complex16.f90 b/flang/test/Lower/Intrinsics/asin_complex16.f90
new file mode 100644
index 00000000000000..982bf6f21b16ff
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/asin_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACAsinF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = asin(a)
+end
diff --git a/flang/test/Lower/Intrinsics/asinh_complex16.f90 b/flang/test/Lower/Intrinsics/asinh_complex16.f90
new file mode 100644
index 00000000000000..2d658a68f8a2b4
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/asinh_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACAsinhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = asinh(a)
+end
diff --git a/flang/test/Lower/Intrinsics/atan_complex16.f90 b/flang/test/Lower/Intrinsics/atan_complex16.f90
new file mode 100644
index 00000000000000..315928d8856831
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/atan_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACAtanF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = atan(a)
+end
diff --git a/flang/test/Lower/Intrinsics/atanh_complex16.f90 b/flang/test/Lower/Intrinsics/atanh_complex16.f90
new file mode 100644
index 00000000000000..0d9f798ea4a2b1
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/atanh_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACAtanhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = atanh(a)
+end
diff --git a/flang/test/Lower/Intrinsics/cos_complex16.f90 b/flang/test/Lower/Intrinsics/cos_complex16.f90
new file mode 100644
index 00000000000000..79b89ce057e12b
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/cos_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACCosF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = cos(a)
+end
diff --git a/flang/test/Lower/Intrinsics/cosh_complex16.f90 b/flang/test/Lower/Intrinsics/cosh_complex16.f90
new file mode 100644
index 00000000000000..dc1723b4582049
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/cosh_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACCoshF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = cosh(a)
+end
diff --git a/flang/test/Lower/Intrinsics/exp_complex16.f90 b/flang/test/Lower/Intrinsics/exp_complex16.f90
new file mode 100644
index 00000000000000..972285c654bfe4
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/exp_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACExpF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = exp(a)
+end
diff --git a/flang/test/Lower/Intrinsics/log_complex16.f90 b/flang/test/Lower/Intrinsics/log_complex16.f90
new file mode 100644
index 00000000000000..d5d0eb388ca2fe
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/log_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACLogF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = log(a)
+end
diff --git a/flang/test/Lower/Intrinsics/missing-math-runtime.f90 b/flang/test/Lower/Intrinsics/missing-math-runtime.f90
deleted file mode 100644
index 699678fcf2bcec..00000000000000
--- a/flang/test/Lower/Intrinsics/missing-math-runtime.f90
+++ /dev/null
@@ -1,12 +0,0 @@
-! If the compiler is built without 128-bit float math
-! support, an appropriate error message is emitted.
-! UNSUPPORTED: flang-supports-f128-math
-! RUN: bbc -emit-fir %s -o /dev/null >%t 2>&1 || echo
-! RUN: FileCheck %s --input-file=%t
-
- complex(16) :: a
- real(16) :: b
-! CHECK: compiler is built without support for 'ABS(COMPLEX(KIND=16))'
- b = abs(a)
-end
-
diff --git a/flang/test/Lower/Intrinsics/pow_complex16.f90 b/flang/test/Lower/Intrinsics/pow_complex16.f90
new file mode 100644
index 00000000000000..db6b207aea9073
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/pow_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACPowF128({{.*}}){{.*}}: (!fir.complex<16>, !fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = a ** b
+end
diff --git a/flang/test/Lower/Intrinsics/sin_complex16.f90 b/flang/test/Lower/Intrinsics/sin_complex16.f90
new file mode 100644
index 00000000000000..5114501e48dac7
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/sin_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACSinF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = sin(a)
+end
diff --git a/flang/test/Lower/Intrinsics/sinh_complex16.f90 b/flang/test/Lower/Intrinsics/sinh_complex16.f90
new file mode 100644
index 00000000000000..5baf9ea8052a2a
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/sinh_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACSinhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = sinh(a)
+end
diff --git a/flang/test/Lower/Intrinsics/sqrt_complex16.f90 b/flang/test/Lower/Intrinsics/sqrt_complex16.f90
new file mode 100644
index 00000000000000..75ffa22a6e2ed1
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/sqrt_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACSqrtF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = sqrt(a)
+end
diff --git a/flang/test/Lower/Intrinsics/tan_complex16.f90 b/flang/test/Lower/Intrinsics/tan_complex16.f90
new file mode 100644
index 00000000000000..7217145f81b006
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/tan_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACTanF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = tan(a)
+end
diff --git a/flang/test/Lower/Intrinsics/tanh_complex16.f90 b/flang/test/Lower/Intrinsics/tanh_complex16.f90
new file mode 100644
index 00000000000000..1965094c5bce0e
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/tanh_complex16.f90
@@ -0,0 +1,8 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK: fir.call @_FortranACTanhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16>
+  complex(16) :: a, b
+  b = tanh(a)
+end

>From 603bcd0707e6bb21f30652bec04d87f199aff6d9 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Tue, 5 Mar 2024 11:17:36 -0800
Subject: [PATCH 2/2] Addressed Jean's comment.

---
 flang/runtime/Float128Math/CMakeLists.txt | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt
index b84f9251a8a485..980356131b680e 100644
--- a/flang/runtime/Float128Math/CMakeLists.txt
+++ b/flang/runtime/Float128Math/CMakeLists.txt
@@ -105,14 +105,13 @@ if (FLANG_RUNTIME_F128_MATH_LIB)
 elseif (HAVE_LDBL_MANT_DIG_113)
   # We can use 'long double' versions from libc.
   check_library_exists(m sinl "" FOUND_LIBM)
-  if (NOT FOUND_LIBM)
-    message(FATAL_ERROR "FortranRuntime cannot build without libm")
-  endif()
   if (FOUND_LIBM)
     target_compile_definitions(FortranFloat128MathILib INTERFACE
       HAS_LIBM
       )
     target_sources(FortranFloat128MathILib INTERFACE ${sources})
+  else()
+    message(FATAL_ERROR "FortranRuntime cannot build without libm")
   endif()
 else()
   # We can use '__float128' version from libc, if it has them.



More information about the flang-commits mailing list