[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:53:14 PDT 2026
https://github.com/eugeneepshteyn created https://github.com/llvm/llvm-project/pull/194527
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.
>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] [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
More information about the flang-commits
mailing list