diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp index bb439a6bb3a74..c1b270f518c0e 100644 --- a/flang/lib/Evaluate/intrinsics-library.cpp +++ b/flang/lib/Evaluate/intrinsics-library.cpp @@ -15,6 +15,7 @@ #include "fold-implementation.h" #include "host.h" #include "flang/Common/erfc-scaled.h" +#include "flang/Common/idioms.h" #include "flang/Common/static-multimap-view.h" #include "flang/Evaluate/expression.h" #include @@ -277,6 +278,76 @@ static std::complex StdPowF2B( return std::pow(x, y); } +#ifdef _AIX +#ifdef __clang_major__ +#pragma clang diagnostic ignored "-Wc99-extensions" +#endif + +extern "C" { +float _Complex cacosf(float _Complex); +double _Complex cacos(double _Complex); +float _Complex csqrtf(float _Complex); +double _Complex csqrt(double _Complex); +} + +enum CRI { Real, Imag }; +template static TR &reIm(TA &x, CRI n) { + return reinterpret_cast(x)[n]; +} +template static TR CppToC(const std::complex &x) { + TR r; + reIm(r, CRI::Real) = x.real(); + reIm(r, CRI::Imag) = x.imag(); + return r; +} +template static std::complex CToCpp(const TA &x) { + TA &z{const_cast(x)}; + return std::complex(reIm(z, CRI::Real), reIm(z, CRI::Imag)); +} +#endif + +template +static std::complex CSqrt(const std::complex &x) { + std::complex res; +#ifdef _AIX + // On AIX, the implementation of csqrt[f] and std::sqrt is different, + // use csqrt[f] in folding. + if constexpr (std::is_same_v) { + float _Complex r{csqrtf(CppToC(x))}; + res = CToCpp(r); + } else if constexpr (std::is_same_v) { + double _Complex r{csqrt(CppToC(x))}; + res = CToCpp(r); + } else { + DIE("bad complex component type"); + } +#else + res = std::sqrt(x); +#endif + return res; +} + +template +static std::complex CAcos(const std::complex &x) { + std::complex res; +#ifdef _AIX + // On AIX, the implementation of cacos[f] and std::acos is different, + // use cacos[f] in folding. + if constexpr (std::is_same_v) { + float _Complex r{cacosf(CppToC(x))}; + res = CToCpp(r); + } else if constexpr (std::is_same_v) { + double _Complex r{cacos(CppToC(x))}; + res = CToCpp(r); + } else { + DIE("bad complex component type"); + } +#else + res = std::acos(x); +#endif + return res; +} + template struct HostRuntimeLibrary, LibraryVersion::Libm> { using F = FuncPointer, const std::complex &>; @@ -287,7 +358,7 @@ struct HostRuntimeLibrary, LibraryVersion::Libm> { using F2B = FuncPointer, const std::complex &, const HostT &>; static constexpr HostRuntimeFunction table[]{ - FolderFactory::Create("acos"), + FolderFactory::Create("acos"), FolderFactory::Create("acosh"), FolderFactory::Create("asin"), FolderFactory::Create("asinh"), @@ -302,7 +373,7 @@ struct HostRuntimeLibrary, LibraryVersion::Libm> { FolderFactory::Create("pow"), FolderFactory::Create("sin"), FolderFactory::Create("sinh"), - FolderFactory::Create("sqrt"), + FolderFactory::Create("sqrt"), FolderFactory::Create("tan"), FolderFactory::Create("tanh"), };