[flang-commits] [flang] [flang] Added COMPLEX(16) ** INTEGER(4/8) lowering and runtime. (PR #84115)

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Tue Mar 5 20:36:02 PST 2024


https://github.com/vzakhari created https://github.com/llvm/llvm-project/pull/84115

None

>From eb9a97f530065cbd9bd54d88fb90691eec36a6d4 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Tue, 5 Mar 2024 18:11:44 -0800
Subject: [PATCH] [flang] Added COMPLEX(16) ** INTEGER(4/8) lowering and
 runtime.

---
 flang/lib/Optimizer/Builder/IntrinsicCall.cpp |  8 ++++
 flang/runtime/complex-powi.cpp                | 45 ++++++++++++++++++-
 .../test/Lower/Intrinsics/pow_complex16i.f90  |  9 ++++
 .../test/Lower/Intrinsics/pow_complex16k.f90  |  9 ++++
 4 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/Lower/Intrinsics/pow_complex16i.f90
 create mode 100644 flang/test/Lower/Intrinsics/pow_complex16k.f90

diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 25598ed1683162..2f7ace658e4752 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -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>>,
@@ -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>>,
diff --git a/flang/runtime/complex-powi.cpp b/flang/runtime/complex-powi.cpp
index 18723bb93cbf17..77031e40242791 100644
--- a/flang/runtime/complex-powi.cpp
+++ b/flang/runtime/complex-powi.cpp
@@ -6,6 +6,7 @@
  *
  * ===-----------------------------------------------------------------------===
  */
+#include "flang/Common/float128.h"
 #include "flang/Runtime/entry-names.h"
 #include <cstdint>
 #include <cstdio>
@@ -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
@@ -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
diff --git a/flang/test/Lower/Intrinsics/pow_complex16i.f90 b/flang/test/Lower/Intrinsics/pow_complex16i.f90
new file mode 100644
index 00000000000000..1cabaf94f8a605
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/pow_complex16i.f90
@@ -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
diff --git a/flang/test/Lower/Intrinsics/pow_complex16k.f90 b/flang/test/Lower/Intrinsics/pow_complex16k.f90
new file mode 100644
index 00000000000000..e3b1b4d31afa72
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/pow_complex16k.f90
@@ -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



More information about the flang-commits mailing list