[flang-commits] [flang] [flang][evaluate] Fold SIND() by rewriting to SIN(x * pi/180) (PR #194527)

Eugene Epshteyn via flang-commits flang-commits at lists.llvm.org
Mon Apr 27 20:55:53 PDT 2026


https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/194527

>From 4b7fea7073c9d55a098780cda82728dfc9ff3f7e Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 27 Apr 2026 23:52:39 -0400
Subject: [PATCH 1/2] [flang][evaluate] Fold SIND() by rewriting to SIN(x *
 pi/180)

Add constant folding for the SIND intrinsic. When SIND is called on a
constant argument, rewrite it to SIN(x * pi/180) and recurse through
FoldIntrinsicFunction, letting the existing SIN host-runtime folding
finish the work. This mirrors the rewrite already performed by lowering
in IntrinsicLibrary::genSind.
---
 flang/lib/Evaluate/fold-real.cpp  | 18 ++++++++++++++++++
 flang/test/Evaluate/fold-sind.f90 | 29 +++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)
 create mode 100644 flang/test/Evaluate/fold-sind.f90

diff --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp
index 9c591e2ef36ec..49f624e80963e 100644
--- a/flang/lib/Evaluate/fold-real.cpp
+++ b/flang/lib/Evaluate/fold-real.cpp
@@ -408,6 +408,24 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
   } else if (name == "sign") {
     return FoldElementalIntrinsic<T, T, T>(
         context, std::move(funcRef), &Scalar<T>::SIGN);
+  } else if (name == "sind") {
+    // Rewrite SIND(x) -> SIN(x * pi/180); the SIN call then folds when x is
+    // constant.  pi and 180 are first rounded to the target precision so that
+    // folded results match the lowering of SIND, which uses the same sequence
+    // (see IntrinsicLibrary::genSind).
+    CHECK(args.size() == 1);
+    if (auto *xExpr{UnwrapExpr<Expr<T>>(args[0])}) {
+      const char *piStr{
+          "3.141592653589793238462643383279502884"}; // llvm::numbers::pis
+      const char *oneEightyStr{"180.0"};
+      Scalar<T> pi{Scalar<T>::Read(piStr).value};
+      Scalar<T> oneEighty{Scalar<T>::Read(oneEightyStr).value};
+      Scalar<T> piOver180{pi.Divide(oneEighty).value};
+      *xExpr = std::move(*xExpr) *
+          Expr<T>{Constant<T>{std::move(piOver180)}};
+      intrinsic->name = "sin";
+      return FoldIntrinsicFunction<KIND>(context, std::move(funcRef));
+    }
   } else if (name == "spacing") {
     return FoldElementalIntrinsic<T, T>(context, std::move(funcRef),
         ScalarFunc<T, T>(
diff --git a/flang/test/Evaluate/fold-sind.f90 b/flang/test/Evaluate/fold-sind.f90
new file mode 100644
index 0000000000000..3f4c876555f39
--- /dev/null
+++ b/flang/test/Evaluate/fold-sind.f90
@@ -0,0 +1,29 @@
+! RUN: %python %S/test_folding.py %s %flang_fc1
+! Tests folding of SIND() via rewrite to SIN(x * pi/180).
+module m
+  ! Kind preservation.
+  logical, parameter :: test_kind4 = kind(sind(1.0_4)) == 4
+  logical, parameter :: test_kind8 = kind(sind(1.0_8)) == 8
+
+  ! sin(0) is exactly 0 in any reasonable libm.
+  logical, parameter :: test_zero4 = sind(0.0_4) == 0.0_4
+  logical, parameter :: test_zero8 = sind(0.0_8) == 0.0_8
+
+  ! Tolerance-based checks tolerate small host libm differences.
+  real(4), parameter :: res_30_4 = sind(30.0_4)
+  real(8), parameter :: res_30_8 = sind(30.0_8)
+  logical, parameter :: test_30_4 = abs(res_30_4 - 0.5_4) <= 1.0e-6_4
+  logical, parameter :: test_30_8 = abs(res_30_8 - 0.5_8) <= 1.0e-12_8
+
+  real(4), parameter :: res_90_4 = sind(90.0_4)
+  real(8), parameter :: res_90_8 = sind(90.0_8)
+  logical, parameter :: test_90_4 = abs(res_90_4 - 1.0_4) <= 1.0e-6_4
+  logical, parameter :: test_90_8 = abs(res_90_8 - 1.0_8) <= 1.0e-12_8
+
+  real(4), parameter :: res_neg90_4 = sind(-90.0_4)
+  logical, parameter :: test_neg90_4 = abs(res_neg90_4 + 1.0_4) <= 1.0e-6_4
+
+  ! Elemental application over an array argument also folds.
+  logical, parameter :: test_array = &
+      all(abs(sind([0.0_4, 90.0_4]) - [0.0_4, 1.0_4]) <= 1.0e-6_4)
+end

>From 635dbfd10f237bf4e82ab9188d5a60392a6fd806 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 27 Apr 2026 23:55:42 -0400
Subject: [PATCH 2/2] clang-format

---
 flang/lib/Evaluate/fold-real.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp
index 49f624e80963e..9826fe0f5cb26 100644
--- a/flang/lib/Evaluate/fold-real.cpp
+++ b/flang/lib/Evaluate/fold-real.cpp
@@ -421,8 +421,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
       Scalar<T> pi{Scalar<T>::Read(piStr).value};
       Scalar<T> oneEighty{Scalar<T>::Read(oneEightyStr).value};
       Scalar<T> piOver180{pi.Divide(oneEighty).value};
-      *xExpr = std::move(*xExpr) *
-          Expr<T>{Constant<T>{std::move(piOver180)}};
+      *xExpr = std::move(*xExpr) * Expr<T>{Constant<T>{std::move(piOver180)}};
       intrinsic->name = "sin";
       return FoldIntrinsicFunction<KIND>(context, std::move(funcRef));
     }



More information about the flang-commits mailing list