[flang-commits] [flang] [Flang] Fold complex ** (1, 0) to identity in constant folding (PR #213256)

via flang-commits flang-commits at lists.llvm.org
Fri Jul 31 04:59:49 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-semantics

Author: ejose02

<details>
<summary>Changes</summary>

Fixes #<!-- -->192418 

Treat a constant exponent exactly equal to (1,0) as the identity in FoldOperation for complex Power, returning the base instead of calling libm cpow*. This avoids rounding error for cases like z**(1,0) where the result should be exactly z. Added folding tests for kind=8, kind=16, and a named complex parameter base.

---
Full diff: https://github.com/llvm/llvm-project/pull/213256.diff


2 Files Affected:

- (modified) flang/lib/Evaluate/fold-implementation.h (+20) 
- (added) flang/test/Evaluate/folding-cpow-unity.f90 (+21) 


``````````diff
diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h
index 918d20da8b880..7c1761ef33601 100644
--- a/flang/lib/Evaluate/fold-implementation.h
+++ b/flang/lib/Evaluate/fold-implementation.h
@@ -2222,6 +2222,14 @@ Expr<T> FoldOperation(FoldingContext &context, Divide<T> &&x) {
   return Expr<T>{std::move(x)};
 }
 
+template <typename T>
+bool IsComplexUnity(const typename T::Scalar &z) {
+  static_assert(T::category == TypeCategory::Complex);
+  using Part = typename T::Part::Scalar;
+  auto one{Part::FromInteger(value::Integer<8>{1}).value};
+  return z.AIMAG().IsZero() && z.REAL().Compare(one) == Relation::Equal;
+}
+
 template <typename T>
 Expr<T> FoldOperation(FoldingContext &context, Power<T> &&x) {
   if (auto array{ApplyElementwise(context, x)}) {
@@ -2242,6 +2250,11 @@ Expr<T> FoldOperation(FoldingContext &context, Power<T> &&x) {
       }
       return Expr<T>{Constant<T>{power.power}};
     } else {
+      if constexpr (T::category == TypeCategory::Complex) {
+        if (IsComplexUnity<T>(folded->second)) {
+          return Expr<T>{Constant<T>{folded->first}};
+        }
+      }
       if (folded->first.IsZero()) {
         if (folded->second.IsZero()) {
           context.Warn(common::UsageWarning::FoldingException,
@@ -2259,6 +2272,13 @@ Expr<T> FoldOperation(FoldingContext &context, Power<T> &&x) {
       }
     }
   }
+  if constexpr (T::category == TypeCategory::Complex) {
+    if (auto exp{GetScalarConstantValue<T>(x.right())}) {
+      if (IsComplexUnity<T>(*exp)) {
+        return Fold(context, std::move(x.left()));
+      }
+    }
+  }
   return Expr<T>{std::move(x)};
 }
 
diff --git a/flang/test/Evaluate/folding-cpow-unity.f90 b/flang/test/Evaluate/folding-cpow-unity.f90
new file mode 100644
index 0000000000000..c19b6d9161958
--- /dev/null
+++ b/flang/test/Evaluate/folding-cpow-unity.f90
@@ -0,0 +1,21 @@
+! RUN: %python %S/test_folding.py %s %flang_fc1
+
+! z**(1,0) must fold to z exactly.
+
+real(8), parameter :: &
+  r_cplx = real((3.0_8, 0.0_8) ** (1.0_8, 0.0_8), kind=8)
+logical, parameter :: test_cpow_unity_cplx = r_cplx == 3.0_8
+
+real(8), parameter :: &
+  r_real = real(3.0_8 ** (1.0_8, 0.0_8), kind=8)
+logical, parameter :: test_cpow_unity_real = r_real == 3.0_8
+
+real(16), parameter :: &
+  r_cplx16 = real((3.0_16, 0.0_16) ** (1.0_16, 0.0_16), kind=16)
+logical, parameter :: test_cpow_unity_cplx16 = r_cplx16 == 3.0_16
+
+complex(8), parameter :: z = (3.0_8, 0.0_8)
+real(8), parameter :: r_var = real(z ** (1.0_8, 0.0_8), kind=8)
+logical, parameter :: test_cpow_unity_var = r_var == 3.0_8
+
+end

``````````

</details>


https://github.com/llvm/llvm-project/pull/213256


More information about the flang-commits mailing list