Skip to content

Commit 50d848d

Browse files
authored
[flang] Added lowering and runtime for COMPLEX(16) intrinsics. (#83874)
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.
1 parent 5a52662 commit 50d848d

34 files changed

+444
-233
lines changed

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

+46-10
Original file line numberDiff line numberDiff line change
@@ -689,22 +689,22 @@ prettyPrintIntrinsicName(fir::FirOpBuilder &builder, mlir::Location loc,
689689
}
690690

691691
// Generate a call to the Fortran runtime library providing
692-
// support for 128-bit float math via a third-party library.
693-
// If the compiler is built without FLANG_RUNTIME_F128_MATH_LIB,
694-
// this function will report an error.
692+
// support for 128-bit float math.
693+
// On 'LDBL_MANT_DIG == 113' targets the implementation
694+
// is provided by FortranRuntime, otherwise, it is done via
695+
// FortranFloat128Math library. In the latter case the compiler
696+
// has to be built with FLANG_RUNTIME_F128_MATH_LIB to guarantee
697+
// proper linking actions in the driver.
695698
static mlir::Value genLibF128Call(fir::FirOpBuilder &builder,
696699
mlir::Location loc,
697700
const MathOperation &mathOp,
698701
mlir::FunctionType libFuncType,
699702
llvm::ArrayRef<mlir::Value> args) {
700-
#ifndef FLANG_RUNTIME_F128_MATH_LIB
701-
std::string message = prettyPrintIntrinsicName(
702-
builder, loc, "compiler is built without support for '", mathOp.key, "'",
703-
libFuncType);
704-
fir::emitFatalError(loc, message, /*genCrashDiag=*/false);
705-
#else // FLANG_RUNTIME_F128_MATH_LIB
703+
// TODO: if we knew that the C 'long double' does not have 113-bit mantissa
704+
// on the target, we could have asserted that FLANG_RUNTIME_F128_MATH_LIB
705+
// must be specified. For now just always generate the call even
706+
// if it will be unresolved.
706707
return genLibCall(builder, loc, mathOp, libFuncType, args);
707-
#endif // FLANG_RUNTIME_F128_MATH_LIB
708708
}
709709

710710
mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
@@ -926,6 +926,10 @@ constexpr auto FuncTypeInteger8Real16 =
926926
genFuncType<Ty::Integer<8>, Ty::Real<16>>;
927927
constexpr auto FuncTypeReal16Complex16 =
928928
genFuncType<Ty::Real<16>, Ty::Complex<16>>;
929+
constexpr auto FuncTypeComplex16Complex16 =
930+
genFuncType<Ty::Complex<16>, Ty::Complex<16>>;
931+
constexpr auto FuncTypeComplex16Complex16Complex16 =
932+
genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Complex<16>>;
929933

930934
static constexpr MathOperation mathOperations[] = {
931935
{"abs", "fabsf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
@@ -944,13 +948,17 @@ static constexpr MathOperation mathOperations[] = {
944948
{"acos", RTNAME_STRING(AcosF128), FuncTypeReal16Real16, genLibF128Call},
945949
{"acos", "cacosf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
946950
{"acos", "cacos", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
951+
{"acos", RTNAME_STRING(CAcosF128), FuncTypeComplex16Complex16,
952+
genLibF128Call},
947953
{"acosh", "acoshf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
948954
{"acosh", "acosh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
949955
{"acosh", RTNAME_STRING(AcoshF128), FuncTypeReal16Real16, genLibF128Call},
950956
{"acosh", "cacoshf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>,
951957
genLibCall},
952958
{"acosh", "cacosh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
953959
genLibCall},
960+
{"acosh", RTNAME_STRING(CAcoshF128), FuncTypeComplex16Complex16,
961+
genLibF128Call},
954962
// llvm.trunc behaves the same way as libm's trunc.
955963
{"aint", "llvm.trunc.f32", genFuncType<Ty::Real<4>, Ty::Real<4>>,
956964
genLibCall},
@@ -972,20 +980,26 @@ static constexpr MathOperation mathOperations[] = {
972980
{"asin", RTNAME_STRING(AsinF128), FuncTypeReal16Real16, genLibF128Call},
973981
{"asin", "casinf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
974982
{"asin", "casin", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
983+
{"asin", RTNAME_STRING(CAsinF128), FuncTypeComplex16Complex16,
984+
genLibF128Call},
975985
{"asinh", "asinhf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
976986
{"asinh", "asinh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
977987
{"asinh", RTNAME_STRING(AsinhF128), FuncTypeReal16Real16, genLibF128Call},
978988
{"asinh", "casinhf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>,
979989
genLibCall},
980990
{"asinh", "casinh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
981991
genLibCall},
992+
{"asinh", RTNAME_STRING(CAsinhF128), FuncTypeComplex16Complex16,
993+
genLibF128Call},
982994
{"atan", "atanf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
983995
genMathOp<mlir::math::AtanOp>},
984996
{"atan", "atan", genFuncType<Ty::Real<8>, Ty::Real<8>>,
985997
genMathOp<mlir::math::AtanOp>},
986998
{"atan", RTNAME_STRING(AtanF128), FuncTypeReal16Real16, genLibF128Call},
987999
{"atan", "catanf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
9881000
{"atan", "catan", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
1001+
{"atan", RTNAME_STRING(CAtanF128), FuncTypeComplex16Complex16,
1002+
genLibF128Call},
9891003
{"atan2", "atan2f", genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Real<4>>,
9901004
genMathOp<mlir::math::Atan2Op>},
9911005
{"atan2", "atan2", genFuncType<Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>,
@@ -999,6 +1013,8 @@ static constexpr MathOperation mathOperations[] = {
9991013
genLibCall},
10001014
{"atanh", "catanh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
10011015
genLibCall},
1016+
{"atanh", RTNAME_STRING(CAtanhF128), FuncTypeComplex16Complex16,
1017+
genLibF128Call},
10021018
{"bessel_j0", "j0f", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
10031019
{"bessel_j0", "j0", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
10041020
{"bessel_j0", RTNAME_STRING(J0F128), FuncTypeReal16Real16, genLibF128Call},
@@ -1038,11 +1054,15 @@ static constexpr MathOperation mathOperations[] = {
10381054
genComplexMathOp<mlir::complex::CosOp>},
10391055
{"cos", "ccos", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
10401056
genComplexMathOp<mlir::complex::CosOp>},
1057+
{"cos", RTNAME_STRING(CCosF128), FuncTypeComplex16Complex16,
1058+
genLibF128Call},
10411059
{"cosh", "coshf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
10421060
{"cosh", "cosh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
10431061
{"cosh", RTNAME_STRING(CoshF128), FuncTypeReal16Real16, genLibF128Call},
10441062
{"cosh", "ccoshf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
10451063
{"cosh", "ccosh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
1064+
{"cosh", RTNAME_STRING(CCoshF128), FuncTypeComplex16Complex16,
1065+
genLibF128Call},
10461066
{"divc",
10471067
{},
10481068
genFuncType<Ty::Complex<2>, Ty::Complex<2>, Ty::Complex<2>>,
@@ -1080,6 +1100,8 @@ static constexpr MathOperation mathOperations[] = {
10801100
genComplexMathOp<mlir::complex::ExpOp>},
10811101
{"exp", "cexp", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
10821102
genComplexMathOp<mlir::complex::ExpOp>},
1103+
{"exp", RTNAME_STRING(CExpF128), FuncTypeComplex16Complex16,
1104+
genLibF128Call},
10831105
{"feclearexcept", "feclearexcept",
10841106
genFuncType<Ty::Integer<4>, Ty::Integer<4>>, genLibCall},
10851107
{"fedisableexcept", "fedisableexcept",
@@ -1131,6 +1153,8 @@ static constexpr MathOperation mathOperations[] = {
11311153
genComplexMathOp<mlir::complex::LogOp>},
11321154
{"log", "clog", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
11331155
genComplexMathOp<mlir::complex::LogOp>},
1156+
{"log", RTNAME_STRING(CLogF128), FuncTypeComplex16Complex16,
1157+
genLibF128Call},
11341158
{"log10", "log10f", genFuncType<Ty::Real<4>, Ty::Real<4>>,
11351159
genMathOp<mlir::math::Log10Op>},
11361160
{"log10", "log10", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1178,6 +1202,8 @@ static constexpr MathOperation mathOperations[] = {
11781202
genComplexMathOp<mlir::complex::PowOp>},
11791203
{"pow", "cpow", genFuncType<Ty::Complex<8>, Ty::Complex<8>, Ty::Complex<8>>,
11801204
genComplexMathOp<mlir::complex::PowOp>},
1205+
{"pow", RTNAME_STRING(CPowF128), FuncTypeComplex16Complex16Complex16,
1206+
genLibF128Call},
11811207
{"pow", RTNAME_STRING(FPow4i),
11821208
genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Integer<4>>,
11831209
genMathOp<mlir::math::FPowIOp>},
@@ -1222,11 +1248,15 @@ static constexpr MathOperation mathOperations[] = {
12221248
genComplexMathOp<mlir::complex::SinOp>},
12231249
{"sin", "csin", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
12241250
genComplexMathOp<mlir::complex::SinOp>},
1251+
{"sin", RTNAME_STRING(CSinF128), FuncTypeComplex16Complex16,
1252+
genLibF128Call},
12251253
{"sinh", "sinhf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall},
12261254
{"sinh", "sinh", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
12271255
{"sinh", RTNAME_STRING(SinhF128), FuncTypeReal16Real16, genLibF128Call},
12281256
{"sinh", "csinhf", genFuncType<Ty::Complex<4>, Ty::Complex<4>>, genLibCall},
12291257
{"sinh", "csinh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
1258+
{"sinh", RTNAME_STRING(CSinhF128), FuncTypeComplex16Complex16,
1259+
genLibF128Call},
12301260
{"sqrt", "sqrtf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
12311261
genMathOp<mlir::math::SqrtOp>},
12321262
{"sqrt", "sqrt", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1236,6 +1266,8 @@ static constexpr MathOperation mathOperations[] = {
12361266
genComplexMathOp<mlir::complex::SqrtOp>},
12371267
{"sqrt", "csqrt", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
12381268
genComplexMathOp<mlir::complex::SqrtOp>},
1269+
{"sqrt", RTNAME_STRING(CSqrtF128), FuncTypeComplex16Complex16,
1270+
genLibF128Call},
12391271
{"tan", "tanf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
12401272
genMathOp<mlir::math::TanOp>},
12411273
{"tan", "tan", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1245,6 +1277,8 @@ static constexpr MathOperation mathOperations[] = {
12451277
genComplexMathOp<mlir::complex::TanOp>},
12461278
{"tan", "ctan", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
12471279
genComplexMathOp<mlir::complex::TanOp>},
1280+
{"tan", RTNAME_STRING(CTanF128), FuncTypeComplex16Complex16,
1281+
genLibF128Call},
12481282
{"tanh", "tanhf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
12491283
genMathOp<mlir::math::TanhOp>},
12501284
{"tanh", "tanh", genFuncType<Ty::Real<8>, Ty::Real<8>>,
@@ -1254,6 +1288,8 @@ static constexpr MathOperation mathOperations[] = {
12541288
genComplexMathOp<mlir::complex::TanhOp>},
12551289
{"tanh", "ctanh", genFuncType<Ty::Complex<8>, Ty::Complex<8>>,
12561290
genComplexMathOp<mlir::complex::TanhOp>},
1291+
{"tanh", RTNAME_STRING(CTanhF128), FuncTypeComplex16Complex16,
1292+
genLibF128Call},
12571293
};
12581294

12591295
// This helper class computes a "distance" between two function types.

flang/runtime/CMakeLists.txt

+34-9
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,6 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
5757
REAL(16) is mapped to __float128, or libm for targets where REAL(16) \
5858
is mapped to long double, etc."
5959
)
60-
61-
if (NOT FLANG_RUNTIME_F128_MATH_LIB STREQUAL "")
62-
add_compile_definitions(
63-
-DFLANG_RUNTIME_F128_MATH_LIB="${FLANG_RUNTIME_F128_MATH_LIB}"
64-
)
65-
endif()
6660
endif()
6761

6862
include(CheckCXXSymbolExists)
@@ -78,6 +72,16 @@ check_cxx_source_compiles(
7872
"
7973
HAVE_DECL_STRERROR_S)
8074

75+
# Check if 128-bit float computations can be done via long double.
76+
check_cxx_source_compiles(
77+
"#include <cfloat>
78+
#if LDBL_MANT_DIG != 113
79+
#error LDBL_MANT_DIG != 113
80+
#endif
81+
int main() { return 0; }
82+
"
83+
HAVE_LDBL_MANT_DIG_113)
84+
8185
check_cxx_compiler_flag(-fno-lto FLANG_RUNTIME_HAS_FNO_LTO_FLAG)
8286
if (FLANG_RUNTIME_HAS_FNO_LTO_FLAG)
8387
set(NO_LTO_FLAGS "-fno-lto")
@@ -100,9 +104,7 @@ add_definitions(-U_GLIBCXX_ASSERTIONS)
100104
add_definitions(-U_LIBCPP_ENABLE_ASSERTIONS)
101105

102106
add_subdirectory(FortranMain)
103-
if (NOT ${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "")
104-
add_subdirectory(Float128Math)
105-
endif()
107+
add_subdirectory(Float128Math)
106108

107109
set(sources
108110
ISO_Fortran_binding.cpp
@@ -319,6 +321,29 @@ if (NOT FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD STREQUAL "off")
319321
endif()
320322
endif()
321323

324+
if (NOT TARGET FortranFloat128Math)
325+
# If FortranFloat128Math is not defined, then we are not building
326+
# standalone FortranFloat128Math library. Instead, include
327+
# the relevant sources into FortranRuntime itself.
328+
# The information is provided via FortranFloat128MathILib
329+
# interface library.
330+
get_target_property(f128_sources
331+
FortranFloat128MathILib INTERFACE_SOURCES
332+
)
333+
if (f128_sources)
334+
# The interface may define special macros for Float128Math files,
335+
# so we need to propagate them.
336+
get_target_property(f128_defs
337+
FortranFloat128MathILib INTERFACE_COMPILE_DEFINITIONS
338+
)
339+
set_property(SOURCE ${f128_sources}
340+
APPEND PROPERTY COMPILE_DEFINITIONS
341+
${f128_defs}
342+
)
343+
list(APPEND sources ${f128_sources})
344+
endif()
345+
endif()
346+
322347
if (NOT DEFINED MSVC)
323348
add_flang_library(FortranRuntime
324349
${sources}

flang/runtime/Float128Math/CMakeLists.txt

+57-42
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,6 @@
1616

1717
include(CheckLibraryExists)
1818

19-
if (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libquadmath")
20-
check_include_file(quadmath.h FOUND_QUADMATH_HEADER)
21-
if(FOUND_QUADMATH_HEADER)
22-
add_compile_definitions(HAS_QUADMATHLIB)
23-
else()
24-
message(FATAL_ERROR
25-
"FLANG_RUNTIME_F128_MATH_LIB setting requires quadmath.h "
26-
"to be available: ${FLANG_RUNTIME_F128_MATH_LIB}"
27-
)
28-
endif()
29-
elseif (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libm")
30-
check_library_exists(m sinl "" FOUND_LIBM)
31-
check_library_exists(m sinf128 "" FOUND_LIBMF128)
32-
if (FOUND_LIBM)
33-
add_compile_definitions(HAS_LIBM)
34-
endif()
35-
if (FOUND_LIBMF128)
36-
add_compile_definitions(HAS_LIBMF128)
37-
endif()
38-
endif()
39-
40-
if (NOT FOUND_QUADMATH_HEADER AND NOT FOUND_LIBM)
41-
message(FATAL_ERROR
42-
"Unsupported third-party library for Fortran F128 math runtime: "
43-
"${FLANG_RUNTIME_F128_MATH_LIB}"
44-
)
45-
endif()
46-
4719
set(sources
4820
acos.cpp
4921
acosh.cpp
@@ -52,8 +24,8 @@ set(sources
5224
atan.cpp
5325
atan2.cpp
5426
atanh.cpp
55-
cabs.cpp
5627
ceil.cpp
28+
complex-math.c
5729
cos.cpp
5830
cosh.cpp
5931
erf.cpp
@@ -94,18 +66,61 @@ set(sources
9466
)
9567

9668
include_directories(AFTER "${CMAKE_CURRENT_SOURCE_DIR}/..")
97-
add_flang_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN ${sources})
69+
add_library(FortranFloat128MathILib INTERFACE)
9870

99-
if (DEFINED MSVC)
100-
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
101-
add_flang_library(FortranFloat128Math.static STATIC INSTALL_WITH_TOOLCHAIN
102-
${sources}
103-
)
104-
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
105-
add_flang_library(FortranFloat128Math.static_dbg STATIC INSTALL_WITH_TOOLCHAIN
106-
${sources}
107-
)
108-
add_dependencies(FortranFloat128Math FortranFloat128Math.static
109-
FortranFloat128Math.static_dbg
110-
)
71+
if (FLANG_RUNTIME_F128_MATH_LIB)
72+
if (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libquadmath")
73+
check_include_file(quadmath.h FOUND_QUADMATH_HEADER)
74+
if(FOUND_QUADMATH_HEADER)
75+
add_compile_definitions(HAS_QUADMATHLIB)
76+
else()
77+
message(FATAL_ERROR
78+
"FLANG_RUNTIME_F128_MATH_LIB setting requires quadmath.h "
79+
"to be available: ${FLANG_RUNTIME_F128_MATH_LIB}"
80+
)
81+
endif()
82+
else()
83+
message(FATAL_ERROR
84+
"Unsupported third-party library for Fortran F128 math runtime: "
85+
"${FLANG_RUNTIME_F128_MATH_LIB}"
86+
)
87+
endif()
88+
89+
add_flang_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN
90+
${sources})
91+
92+
if (DEFINED MSVC)
93+
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
94+
add_flang_library(FortranFloat128Math.static STATIC INSTALL_WITH_TOOLCHAIN
95+
${sources}
96+
)
97+
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
98+
add_flang_library(FortranFloat128Math.static_dbg STATIC INSTALL_WITH_TOOLCHAIN
99+
${sources}
100+
)
101+
add_dependencies(FortranFloat128Math FortranFloat128Math.static
102+
FortranFloat128Math.static_dbg
103+
)
104+
endif()
105+
elseif (HAVE_LDBL_MANT_DIG_113)
106+
# We can use 'long double' versions from libc.
107+
check_library_exists(m sinl "" FOUND_LIBM)
108+
if (FOUND_LIBM)
109+
target_compile_definitions(FortranFloat128MathILib INTERFACE
110+
HAS_LIBM
111+
)
112+
target_sources(FortranFloat128MathILib INTERFACE ${sources})
113+
else()
114+
message(FATAL_ERROR "FortranRuntime cannot build without libm")
115+
endif()
116+
else()
117+
# We can use '__float128' version from libc, if it has them.
118+
check_library_exists(m sinf128 "" FOUND_LIBMF128)
119+
if (FOUND_LIBMF128)
120+
target_compile_definitions(FortranFloat128MathILib INTERFACE
121+
HAS_LIBMF128
122+
)
123+
# Enable this, when math-entries.h and complex-math.h is ready.
124+
# target_sources(FortranFloat128MathILib INTERFACE ${sources})
125+
endif()
111126
endif()

flang/runtime/Float128Math/cabs.cpp

-24
This file was deleted.

0 commit comments

Comments
 (0)