Skip to content

Commit

Permalink
[flang] Added COMPLEX(16) ** INTEGER(4/8) lowering and runtime. (#84115)
Browse files Browse the repository at this point in the history
  • Loading branch information
vzakhari committed Mar 6, 2024
1 parent 28e30b4 commit 1c6e09c
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
8 changes: 8 additions & 0 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,10 @@ constexpr auto FuncTypeComplex16Complex16 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>>;
constexpr auto FuncTypeComplex16Complex16Complex16 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Complex<16>>;
constexpr auto FuncTypeComplex16Complex16Integer4 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Integer<4>>;
constexpr auto FuncTypeComplex16Complex16Integer8 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Integer<8>>;

static constexpr MathOperation mathOperations[] = {
{"abs", "fabsf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
Expand Down Expand Up @@ -1226,10 +1230,14 @@ static constexpr MathOperation mathOperations[] = {
genFuncType<Ty::Complex<4>, Ty::Complex<4>, Ty::Integer<4>>, genLibCall},
{"pow", RTNAME_STRING(zpowi),
genFuncType<Ty::Complex<8>, Ty::Complex<8>, Ty::Integer<4>>, genLibCall},
{"pow", RTNAME_STRING(cqpowi), FuncTypeComplex16Complex16Integer4,
genLibF128Call},
{"pow", RTNAME_STRING(cpowk),
genFuncType<Ty::Complex<4>, Ty::Complex<4>, Ty::Integer<8>>, genLibCall},
{"pow", RTNAME_STRING(zpowk),
genFuncType<Ty::Complex<8>, Ty::Complex<8>, Ty::Integer<8>>, genLibCall},
{"pow", RTNAME_STRING(cqpowk), FuncTypeComplex16Complex16Integer8,
genLibF128Call},
{"sign", "copysignf", genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Real<4>>,
genMathOp<mlir::math::CopySignOp>},
{"sign", "copysign", genFuncType<Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>,
Expand Down
45 changes: 44 additions & 1 deletion flang/runtime/complex-powi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*
* ===-----------------------------------------------------------------------===
*/
#include "flang/Common/float128.h"
#include "flang/Runtime/entry-names.h"
#include <cstdint>
#include <cstdio>
Expand Down Expand Up @@ -79,6 +80,30 @@ extern "C" double _Complex RTNAME(zpowk)(
double _Complex base, std::int64_t exp) {
return tgpowi(base, exp);
}

#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
// Duplicate CFloat128ComplexType definition from flang/Common/float128.h.
// float128.h does not define it for C++, because _Complex triggers
// c99-extension warnings. We decided to disable warnings for this
// particular file, so we can use _Complex here.
#if LDBL_MANT_DIG == 113
typedef long double _Complex Qcomplex;
#elif HAS_FLOAT128
#if !defined(_ARCH_PPC) || defined(__LONG_DOUBLE_IEEE128__)
typedef _Complex float __attribute__((mode(TC))) Qcomplex;
#else
typedef _Complex float __attribute__((mode(KC))) Qcomplex;
#endif
#endif

extern "C" Qcomplex RTNAME(cqpowi)(Qcomplex base, std::int32_t exp) {
return tgpowi(base, exp);
}
extern "C" Qcomplex RTNAME(cqpowk)(Qcomplex base, std::int64_t exp) {
return tgpowi(base, exp);
}
#endif

#else
// on MSVC, C complex is always just a struct of two members as it is not
// supported as a builtin type. So we use C++ complex here as that has the
Expand Down Expand Up @@ -116,10 +141,28 @@ extern "C" Fcomplex RTNAME(cpowk)(Fcomplex base, std::int64_t exp) {
return *(Fcomplex *)(&cppres);
}

extern "C" Dcomplex RTNAME(zpowk)(Dcomplex base, std::int32_t exp) {
extern "C" Dcomplex RTNAME(zpowk)(Dcomplex base, std::int64_t exp) {
auto cppbase = *(std::complex<double> *)(&base);
auto cppres = tgpowi(cppbase, exp);
return *(Dcomplex *)(&cppres);
}

#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
struct Qcomplex {
CFloat128Type re;
CFloat128Type im;
};

extern "C" Dcomplex RTNAME(cqpowi)(Qcomplex base, std::int32_t exp) {
auto cppbase = *(std::complex<CFloat128Type> *)(&base);
auto cppres = tgpowi(cppbase, exp);
return *(Qcomplex *)(&cppres);
}

extern "C" Dcomplex RTNAME(cqpowk)(Qcomplex base, std::int64_t exp) {
auto cppbase = *(std::complex<CFloat128Type> *)(&base);
auto cppres = tgpowi(cppbase, exp);
return *(Qcomplex *)(&cppres);
}
#endif
#endif
9 changes: 9 additions & 0 deletions flang/test/Lower/Intrinsics/pow_complex16i.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
! 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 @_FortranAcqpowi({{.*}}){{.*}}: (!fir.complex<16>, i32) -> !fir.complex<16>
complex(16) :: a
integer(4) :: b
b = a ** b
end
9 changes: 9 additions & 0 deletions flang/test/Lower/Intrinsics/pow_complex16k.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
! 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 @_FortranAcqpowk({{.*}}){{.*}}: (!fir.complex<16>, i64) -> !fir.complex<16>
complex(16) :: a
integer(8) :: b
b = a ** b
end

0 comments on commit 1c6e09c

Please sign in to comment.