Skip to content

Commit 71d4f34

Browse files
authored
[flang] Use libm routine for compile-time folding on AIX (#114106)
On AIX, the implementation of `std::sqrt` is different from that of `csqrtf`, it leads to different results in compile-time folding and runtime evaluation. This patch is to make the routine calls using the same implementation.
1 parent 12e3ed8 commit 71d4f34

File tree

1 file changed

+73
-2
lines changed

1 file changed

+73
-2
lines changed

flang/lib/Evaluate/intrinsics-library.cpp

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "fold-implementation.h"
1616
#include "host.h"
1717
#include "flang/Common/erfc-scaled.h"
18+
#include "flang/Common/idioms.h"
1819
#include "flang/Common/static-multimap-view.h"
1920
#include "flang/Evaluate/expression.h"
2021
#include <cfloat>
@@ -277,6 +278,76 @@ static std::complex<HostT> StdPowF2B(
277278
return std::pow(x, y);
278279
}
279280

281+
#ifdef _AIX
282+
#ifdef __clang_major__
283+
#pragma clang diagnostic ignored "-Wc99-extensions"
284+
#endif
285+
286+
extern "C" {
287+
float _Complex cacosf(float _Complex);
288+
double _Complex cacos(double _Complex);
289+
float _Complex csqrtf(float _Complex);
290+
double _Complex csqrt(double _Complex);
291+
}
292+
293+
enum CRI { Real, Imag };
294+
template <typename TR, typename TA> static TR &reIm(TA &x, CRI n) {
295+
return reinterpret_cast<TR(&)[2]>(x)[n];
296+
}
297+
template <typename TR, typename T> static TR CppToC(const std::complex<T> &x) {
298+
TR r;
299+
reIm<T, TR>(r, CRI::Real) = x.real();
300+
reIm<T, TR>(r, CRI::Imag) = x.imag();
301+
return r;
302+
}
303+
template <typename T, typename TA> static std::complex<T> CToCpp(const TA &x) {
304+
TA &z{const_cast<TA &>(x)};
305+
return std::complex<T>(reIm<T, TA>(z, CRI::Real), reIm<T, TA>(z, CRI::Imag));
306+
}
307+
#endif
308+
309+
template <typename HostT>
310+
static std::complex<HostT> CSqrt(const std::complex<HostT> &x) {
311+
std::complex<HostT> res;
312+
#ifdef _AIX
313+
// On AIX, the implementation of csqrt[f] and std::sqrt is different,
314+
// use csqrt[f] in folding.
315+
if constexpr (std::is_same_v<HostT, float>) {
316+
float _Complex r{csqrtf(CppToC<float _Complex, float>(x))};
317+
res = CToCpp<float, float _Complex>(r);
318+
} else if constexpr (std::is_same_v<HostT, double>) {
319+
double _Complex r{csqrt(CppToC<double _Complex, double>(x))};
320+
res = CToCpp<double, double _Complex>(r);
321+
} else {
322+
DIE("bad complex component type");
323+
}
324+
#else
325+
res = std::sqrt(x);
326+
#endif
327+
return res;
328+
}
329+
330+
template <typename HostT>
331+
static std::complex<HostT> CAcos(const std::complex<HostT> &x) {
332+
std::complex<HostT> res;
333+
#ifdef _AIX
334+
// On AIX, the implementation of cacos[f] and std::acos is different,
335+
// use cacos[f] in folding.
336+
if constexpr (std::is_same_v<HostT, float>) {
337+
float _Complex r{cacosf(CppToC<float _Complex, float>(x))};
338+
res = CToCpp<float, float _Complex>(r);
339+
} else if constexpr (std::is_same_v<HostT, double>) {
340+
double _Complex r{cacos(CppToC<double _Complex, double>(x))};
341+
res = CToCpp<double, double _Complex>(r);
342+
} else {
343+
DIE("bad complex component type");
344+
}
345+
#else
346+
res = std::acos(x);
347+
#endif
348+
return res;
349+
}
350+
280351
template <typename HostT>
281352
struct HostRuntimeLibrary<std::complex<HostT>, LibraryVersion::Libm> {
282353
using F = FuncPointer<std::complex<HostT>, const std::complex<HostT> &>;
@@ -287,7 +358,7 @@ struct HostRuntimeLibrary<std::complex<HostT>, LibraryVersion::Libm> {
287358
using F2B = FuncPointer<std::complex<HostT>, const std::complex<HostT> &,
288359
const HostT &>;
289360
static constexpr HostRuntimeFunction table[]{
290-
FolderFactory<F, F{std::acos}>::Create("acos"),
361+
FolderFactory<F, F{CAcos}>::Create("acos"),
291362
FolderFactory<F, F{std::acosh}>::Create("acosh"),
292363
FolderFactory<F, F{std::asin}>::Create("asin"),
293364
FolderFactory<F, F{std::asinh}>::Create("asinh"),
@@ -302,7 +373,7 @@ struct HostRuntimeLibrary<std::complex<HostT>, LibraryVersion::Libm> {
302373
FolderFactory<F2B, F2B{StdPowF2B}>::Create("pow"),
303374
FolderFactory<F, F{std::sin}>::Create("sin"),
304375
FolderFactory<F, F{std::sinh}>::Create("sinh"),
305-
FolderFactory<F, F{std::sqrt}>::Create("sqrt"),
376+
FolderFactory<F, F{CSqrt}>::Create("sqrt"),
306377
FolderFactory<F, F{std::tan}>::Create("tan"),
307378
FolderFactory<F, F{std::tanh}>::Create("tanh"),
308379
};

0 commit comments

Comments
 (0)