[llvm] [ConstantFold] Fold `tgamma` and `tgammaf` when the input parameter is a constant value. (PR #114065)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 31 07:06:43 PDT 2024


https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/114065

>From 1d6cce1b74b85d05bc668e07e6cd5c795c338461 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 29 Oct 2024 22:32:13 +0800
Subject: [PATCH 1/5] fold tgamma

---
 llvm/lib/Analysis/ConstantFolding.cpp      |  19 +-
 llvm/test/Transforms/InstCombine/tgamma.ll | 237 +++++++++++++++++++++
 2 files changed, 253 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/tgamma.ll

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index c5a2c2f52f8dc2..b84193acafdc40 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1698,9 +1698,9 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
            Name == "sinh" || Name == "sinhf" ||
            Name == "sqrt" || Name == "sqrtf";
   case 't':
-    return Name == "tan" || Name == "tanf" ||
-           Name == "tanh" || Name == "tanhf" ||
-           Name == "trunc" || Name == "truncf";
+    return Name == "tan" || Name == "tanf" || Name == "tanh" ||
+           Name == "tanhf" || Name == "trunc" || Name == "truncf" ||
+           Name == "tgamma" || Name == "tgammaf";
   case '_':
     // Check for various function names that get used for the math functions
     // when the header files are preprocessed with the macro
@@ -2417,6 +2417,15 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       if (TLI->has(Func))
         return ConstantFoldFP(erf, APF, Ty);
       break;
+    case LibFunc_tgamma:
+    case LibFunc_tgammaf:
+      // NOTE: These boundaries are somewhat conservative.
+      if (TLI->has(Func) && (Ty->isDoubleTy() && (APF > APFloat(1 / DBL_MAX) &&
+                                                  APF < APFloat(171.0)) ||
+                             Ty->isFloatTy() && (APF > APFloat(1 / FLT_MAX) &&
+                                                 APF < APFloat(35.0f))))
+        return ConstantFoldFP(tgamma, APF, Ty);
+      break;
     case LibFunc_nearbyint:
     case LibFunc_nearbyintf:
     case LibFunc_rint:
@@ -3629,6 +3638,10 @@ bool llvm::isMathLibCallNoop(const CallBase *Call,
       case LibFunc_sqrtf:
         return Op.isNaN() || Op.isZero() || !Op.isNegative();
 
+      case LibFunc_tgamma:
+      case LibFunc_tgammaf:
+        return true;
+
       // FIXME: Add more functions: sqrt_finite, atanh, expm1, log1p,
       // maybe others?
       default:
diff --git a/llvm/test/Transforms/InstCombine/tgamma.ll b/llvm/test/Transforms/InstCombine/tgamma.ll
new file mode 100644
index 00000000000000..d81eb6c8a15720
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/tgamma.ll
@@ -0,0 +1,237 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define float @tgammaf_const() {
+; CHECK-LABEL: define float @tgammaf_const() {
+; CHECK-NEXT:    ret float 0x479A216280000000
+;
+  %r = call float @tgammaf(float 34.0)
+  ret float %r
+}
+
+define double @tgamma_const() {
+; CHECK-LABEL: define double @tgamma_const() {
+; CHECK-NEXT:    ret double 0x7F2F2054EB4D96EB
+;
+  %r = call double @tgamma(double 170.0)
+  ret double %r
+}
+
+define float @tgammaf_const_overflow() {
+; CHECK-LABEL: define float @tgammaf_const_overflow() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 3.600000e+01)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 36.0)
+  ret float %r
+}
+
+define double @tgamma_const_overflow() {
+; CHECK-LABEL: define double @tgamma_const_overflow() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 1.720000e+02)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 172.0)
+  ret double %r
+}
+
+define float @tgammaf_minus_one() {
+; CHECK-LABEL: define float @tgammaf_minus_one() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float -1.000000e+00)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float -1.000000e+00)
+  ret float %r
+}
+
+define double @tgamma_minus_one() {
+; CHECK-LABEL: define double @tgamma_minus_one() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double -1.000000e+00)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double -1.000000e+00)
+  ret double %r
+}
+
+define float @tgammaf_minus_one_memory_none() {
+; CHECK-LABEL: define float @tgammaf_minus_one_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float -1.000000e+00) #[[ATTR1:[0-9]+]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float -1.000000e+00) readnone
+  ret float %r
+}
+
+define double @tgamma_minus_one_memory_none() {
+; CHECK-LABEL: define double @tgamma_minus_one_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double -1.000000e+00) #[[ATTR1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double -1.000000e+00) readnone
+  ret double %r
+}
+
+define float @tgammaf_zero() {
+; CHECK-LABEL: define float @tgammaf_zero() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0.000000e+00)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0.000000e+00)
+  ret float %r
+}
+
+define double @tgamma_zero() {
+; CHECK-LABEL: define double @tgamma_zero() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0.000000e+00)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0.000000e+00)
+  ret double %r
+}
+
+define float @tgammaf_neg_zero() {
+; CHECK-LABEL: define float @tgammaf_neg_zero() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float -0.000000e+00)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float -0.000000e+00)
+  ret float %r
+}
+
+define double @tgamma_neg_zero() {
+; CHECK-LABEL: define double @tgamma_neg_zero() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double -0.000000e+00)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double -0.000000e+00)
+  ret double %r
+}
+
+define float @tgammaf_inf() {
+; CHECK-LABEL: define float @tgammaf_inf() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0x7FF0000000000000)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0x7FF0000000000000)
+  ret float %r
+}
+
+define double @tgamma_inf() {
+; CHECK-LABEL: define double @tgamma_inf() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0x7FF0000000000000)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0x7FF0000000000000)
+  ret double %r
+}
+
+define float @tgammaf_inf_memory_none() {
+; CHECK-LABEL: define float @tgammaf_inf_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0x7FF0000000000000) #[[ATTR1]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0x7FF0000000000000) readnone
+  ret float %r
+}
+
+define double @tgamma_inf_memory_none() {
+; CHECK-LABEL: define double @tgamma_inf_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0x7FF0000000000000) #[[ATTR1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0x7FF0000000000000) readnone
+  ret double %r
+}
+
+define float @tgammaf_neg_inf() {
+; CHECK-LABEL: define float @tgammaf_neg_inf() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0xFFF0000000000000)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0xFFF0000000000000)
+  ret float %r
+}
+
+define double @tgamma_neg_inf() {
+; CHECK-LABEL: define double @tgamma_neg_inf() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0xFFF0000000000000)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0xFFF0000000000000)
+  ret double %r
+}
+
+define float @tgammaf_neg_inf_memory_none() {
+; CHECK-LABEL: define float @tgammaf_neg_inf_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0xFFF0000000000000) #[[ATTR1]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0xFFF0000000000000) readnone
+  ret float %r
+}
+
+define double @tgamma_neg_inf_memory_none() {
+; CHECK-LABEL: define double @tgamma_neg_inf_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0xFFF0000000000000) #[[ATTR1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0xFFF0000000000000) readnone
+  ret double %r
+}
+
+define float @tgammaf_nan() {
+; CHECK-LABEL: define float @tgammaf_nan() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0x7FF8000000000000)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0x7FF8000000000000)
+  ret float %r
+}
+
+define double @tgamma_nan() {
+; CHECK-LABEL: define double @tgamma_nan() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0x7FF8000000000000)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0x7FF8000000000000)
+  ret double %r
+}
+
+define float @tgammaf_nan_memory_none() {
+; CHECK-LABEL: define float @tgammaf_nan_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0x7FF8000000000000) #[[ATTR1]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0x7FF8000000000000) readnone
+  ret float %r
+}
+
+define double @tgamma_nan_memory_none() {
+; CHECK-LABEL: define double @tgamma_nan_memory_none() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0x7FF8000000000000) #[[ATTR1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0x7FF8000000000000) readnone
+  ret double %r
+}
+
+define float @tgammaf_poison() {
+; CHECK-LABEL: define float @tgammaf_poison() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float poison)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float poison)
+  ret float %r
+}
+
+define double @tgamma_poison() {
+; CHECK-LABEL: define double @tgamma_poison() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double poison)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double poison)
+  ret double %r
+}
+
+declare float @tgammaf(float) willreturn
+declare double @tgamma(double) willreturn

>From eb1e1cfd498a90671048db90889b6e278e55aaf5 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 29 Oct 2024 23:12:37 +0800
Subject: [PATCH 2/5] add header

---
 llvm/lib/Analysis/ConstantFolding.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index b84193acafdc40..1d95937003a6e7 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -57,6 +57,7 @@
 #include <cassert>
 #include <cerrno>
 #include <cfenv>
+#include <climits>
 #include <cmath>
 #include <cstdint>
 

>From 43a069b1ae3806ce19b0a84bcb6e1d06bc1e7e3f Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Wed, 30 Oct 2024 00:35:41 +0800
Subject: [PATCH 3/5] Update ConstantFolding.cpp

---
 llvm/lib/Analysis/ConstantFolding.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 1d95937003a6e7..19327c5c5afb7b 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -57,7 +57,7 @@
 #include <cassert>
 #include <cerrno>
 #include <cfenv>
-#include <climits>
+#include <cfloat>
 #include <cmath>
 #include <cstdint>
 

>From 8c345ecd7c33df5802224e9b97e76f0f48ee9b57 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Wed, 30 Oct 2024 08:51:48 +0800
Subject: [PATCH 4/5] test

---
 llvm/test/Transforms/InstCombine/tgamma.ll | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/tgamma.ll b/llvm/test/Transforms/InstCombine/tgamma.ll
index d81eb6c8a15720..e79687e41d8af5 100644
--- a/llvm/test/Transforms/InstCombine/tgamma.ll
+++ b/llvm/test/Transforms/InstCombine/tgamma.ll
@@ -11,9 +11,9 @@ define float @tgammaf_const() {
 
 define double @tgamma_const() {
 ; CHECK-LABEL: define double @tgamma_const() {
-; CHECK-NEXT:    ret double 0x7F2F2054EB4D96EB
+; CHECK-NEXT:    ret double 0x605166C698CF183B
 ;
-  %r = call double @tgamma(double 170.0)
+  %r = call double @tgamma(double 100.0)
   ret double %r
 }
 

>From bb91f9af6e8482be93dd2f4c2d8d2e8b68927a7e Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Thu, 31 Oct 2024 22:06:24 +0800
Subject: [PATCH 5/5] update

---
 llvm/lib/Analysis/ConstantFolding.cpp      |  7 ++---
 llvm/test/Transforms/InstCombine/tgamma.ll | 34 +++++++++++++++++-----
 2 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 19327c5c5afb7b..a96c3bebba790e 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -2421,10 +2421,9 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
     case LibFunc_tgamma:
     case LibFunc_tgammaf:
       // NOTE: These boundaries are somewhat conservative.
-      if (TLI->has(Func) && (Ty->isDoubleTy() && (APF > APFloat(1 / DBL_MAX) &&
-                                                  APF < APFloat(171.0)) ||
-                             Ty->isFloatTy() && (APF > APFloat(1 / FLT_MAX) &&
-                                                 APF < APFloat(35.0f))))
+      if (TLI->has(Func) &&
+          (Ty->isDoubleTy() && APF > APFloat(DBL_MIN) && APF < APFloat(171.0) ||
+           Ty->isFloatTy() && APF > APFloat(FLT_MIN) && APF < APFloat(35.0f)))
         return ConstantFoldFP(tgamma, APF, Ty);
       break;
     case LibFunc_nearbyint:
diff --git a/llvm/test/Transforms/InstCombine/tgamma.ll b/llvm/test/Transforms/InstCombine/tgamma.ll
index e79687e41d8af5..dd74617fee83e5 100644
--- a/llvm/test/Transforms/InstCombine/tgamma.ll
+++ b/llvm/test/Transforms/InstCombine/tgamma.ll
@@ -1,24 +1,42 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
-define float @tgammaf_const() {
-; CHECK-LABEL: define float @tgammaf_const() {
+define float @tgammaf_in_range() {
+; CHECK-LABEL: define float @tgammaf_in_range() {
 ; CHECK-NEXT:    ret float 0x479A216280000000
 ;
   %r = call float @tgammaf(float 34.0)
   ret float %r
 }
 
-define double @tgamma_const() {
-; CHECK-LABEL: define double @tgamma_const() {
+define double @tgamma_in_range() {
+; CHECK-LABEL: define double @tgamma_in_range() {
 ; CHECK-NEXT:    ret double 0x605166C698CF183B
 ;
   %r = call double @tgamma(double 100.0)
   ret double %r
 }
 
-define float @tgammaf_const_overflow() {
-; CHECK-LABEL: define float @tgammaf_const_overflow() {
+define float @tgammaf_const_left_range() {
+; CHECK-LABEL: define float @tgammaf_const_left_range() {
+; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 0x3810000000000000)
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = call float @tgammaf(float 0x3810000000000000)
+  ret float %r
+}
+
+define double @tgamma_const_left_range() {
+; CHECK-LABEL: define double @tgamma_const_left_range() {
+; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 0x10000000000000)
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @tgamma(double 0x0010000000000000)
+  ret double %r
+}
+
+define float @tgammaf_const_right_range() {
+; CHECK-LABEL: define float @tgammaf_const_right_range() {
 ; CHECK-NEXT:    [[R:%.*]] = call float @tgammaf(float 3.600000e+01)
 ; CHECK-NEXT:    ret float [[R]]
 ;
@@ -26,8 +44,8 @@ define float @tgammaf_const_overflow() {
   ret float %r
 }
 
-define double @tgamma_const_overflow() {
-; CHECK-LABEL: define double @tgamma_const_overflow() {
+define double @tgamma_const_right_range() {
+; CHECK-LABEL: define double @tgamma_const_right_range() {
 ; CHECK-NEXT:    [[R:%.*]] = call double @tgamma(double 1.720000e+02)
 ; CHECK-NEXT:    ret double [[R]]
 ;



More information about the llvm-commits mailing list