[llvm] [SimplifyLibCalls] Constant fold scalbxx (PR #114417)

via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 2 08:55:50 PDT 2024


https://github.com/fawdlstty updated https://github.com/llvm/llvm-project/pull/114417

>From 16ff8929b0dd53cda1f22d2a00ff36737a5d03d4 Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Thu, 31 Oct 2024 23:36:51 +0800
Subject: [PATCH 1/3] add optimize method & test

---
 .../llvm/Transforms/Utils/SimplifyLibCalls.h  |  1 +
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 43 ++++++++++
 llvm/test/Transforms/InstCombine/scalbn.ll    | 85 +++++++++++++++++++
 3 files changed, 129 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/scalbn.ll

diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 128502b99d9a37..93ab5f5974c189 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -213,6 +213,7 @@ class LibCallSimplifier {
   Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
   Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
   Value *optimizeFdim(CallInst *CI, IRBuilderBase &B);
+  Value *optimizeScalbn(CallInst *CI, IRBuilderBase &B);
   // Wrapper for all floating point library call optimizations
   Value *optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func,
                                       IRBuilderBase &B);
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d85e0d99466022..afa2196243b538 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3157,6 +3157,42 @@ Value *LibCallSimplifier::optimizeFdim(CallInst *CI, IRBuilderBase &B) {
   return ConstantFP::get(CI->getType(), MaxVal);
 }
 
+Value *LibCallSimplifier::optimizeScalbn(CallInst *CI, IRBuilderBase &B) {
+  Value *Base = CI->getArgOperand(0);
+  Value *Expo = CI->getArgOperand(1);
+  // Function *Callee = CI->getCalledFunction();
+  // StringRef Name = Callee->getName();
+  Type *Ty = CI->getType();
+  Module *M = CI->getModule();
+  // bool AllowApprox = CI->hasApproxFunc();
+  // bool Ignored;
+
+  // Propagate the math semantics from the call to any created instructions.
+  IRBuilderBase::FastMathFlagGuard Guard(B);
+  B.setFastMathFlags(CI->getFastMathFlags());
+  // Evaluate special cases related to the base.
+
+  // Scalbn(0.0, exp) -> 0.0
+  if (match(Base, m_SpecificFP(0.0)))
+    return Base;
+
+  // Scalbn(arg, 0) -> arg
+  if (match(Expo, m_Zero()))
+    return Base;
+
+  // Scalbn(arg, 1) -> arg * 2.0
+  if (match(Expo, m_SpecificInt(1)))
+    return B.CreateFMul(Base, ConstantFP::get(Ty, 2.0), "mul");
+
+  // Scalbn(1.0, exp) -> FLT_RADIX ^ exp
+  auto pow = createPowWithIntegerExponent(ConstantFP::get(Ty, 2.0), Expo, M, B);
+  if (match(Base, m_SpecificFP(1.0)))
+    return pow;
+
+  // otherwise
+  return B.CreateFMul(Base, pow, "mul");
+}
+
 //===----------------------------------------------------------------------===//
 // Integer Library Call Optimizations
 //===----------------------------------------------------------------------===//
@@ -4105,6 +4141,13 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_remquof:
   case LibFunc_remquol:
     return optimizeRemquo(CI, Builder);
+  case LibFunc_scalbln:
+  case LibFunc_scalblnf:
+  case LibFunc_scalblnl:
+  case LibFunc_scalbn:
+  case LibFunc_scalbnf:
+  case LibFunc_scalbnl:
+    return optimizeScalbn(CI, Builder);
   case LibFunc_nan:
   case LibFunc_nanf:
   case LibFunc_nanl:
diff --git a/llvm/test/Transforms/InstCombine/scalbn.ll b/llvm/test/Transforms/InstCombine/scalbn.ll
new file mode 100644
index 00000000000000..4dccef967973cf
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/scalbn.ll
@@ -0,0 +1,85 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare double @scalbln(double, i64)
+declare float @scalblnf(float, i64)
+declare x86_fp80 @scalblnl(x86_fp80, i64)
+declare double @scalbn(double, i32)
+declare float @scalbnf(float, i32)
+declare x86_fp80 @scalbnl(x86_fp80, i32)
+
+;---------------------------------------------------------------------
+; scalbn(scalbn(x, a), b) -> scalbn(x, a + b)
+;---------------------------------------------------------------------
+
+define double @scalbln_scalbln(double %x, i64 %a, i64 %b) {
+; CHECK-LABEL: define double @scalbln
+; CHECK-SAME: (double [[X:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
+; CHECK-NEXT:    [[SCALBXX0:%.*]] = call double @scalbln(double [[X]], i64 [[A]])
+; CHECK-NEXT:    [[SCALBXX1:%.*]] = call double @scalbln(double [[SCALBXX0]], i64 [[B]])
+; CHECK-NEXT:    ret double [[SCALBXX1]]
+;
+  %scalbxx0 = call double @scalbln(double %x, i64 %a)
+  %scalbxx1 = call double @scalbln(double %scalbxx0, i64 %b)
+  ret double %scalbxx1
+}
+
+define float @scalblnf_scalblnf(float %x, i64 %a, i64 %b) {
+; CHECK-LABEL: define float @scalblnf
+; CHECK-SAME: (float [[X:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
+; CHECK-NEXT:    [[SCALBXX0:%.*]] = call float @scalblnf(float [[X]], i64 [[A]])
+; CHECK-NEXT:    [[SCALBXX1:%.*]] = call float @scalblnf(float [[SCALBXX0]], i64 [[B]])
+; CHECK-NEXT:    ret float [[SCALBXX1]]
+;
+  %scalbxx0 = call float @scalblnf(float %x, i64 %a)
+  %scalbxx1 = call float @scalblnf(float %scalbxx0, i64 %b)
+  ret float %scalbxx1
+}
+
+define x86_fp80 @scalblnl_scalblnl(x86_fp80 %x, i64 %a, i64 %b) {
+; CHECK-LABEL: define x86_fp80 @scalblnl
+; CHECK-SAME: (x86_fp80 [[X:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
+; CHECK-NEXT:    [[SCALBXX0:%.*]] = call x86_fp80 @scalblnl(x86_fp80 [[X]], i64 [[A]])
+; CHECK-NEXT:    [[SCALBXX1:%.*]] = call x86_fp80 @scalblnl(x86_fp80 [[SCALBXX0]], i64 [[B]])
+; CHECK-NEXT:    ret x86_fp80 [[SCALBXX1]]
+;
+  %scalbxx0 = call x86_fp80 @scalblnl(x86_fp80 %x, i64 %a)
+  %scalbxx1 = call x86_fp80 @scalblnl(x86_fp80 %scalbxx0, i64 %b)
+  ret x86_fp80 %scalbxx1
+}
+
+define double @scalbn_scalbn(double %x, i32 %a, i32 %b) {
+; CHECK-LABEL: define double @scalbn
+; CHECK-SAME: (double [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[SCALBXX0:%.*]] = call double @scalbn(double [[X]], i32 [[A]])
+; CHECK-NEXT:    [[SCALBXX1:%.*]] = call double @scalbn(double [[SCALBXX0]], i32 [[B]])
+; CHECK-NEXT:    ret double [[SCALBXX1]]
+;
+  %scalbxx0 = call double @scalbn(double %x, i32 %a)
+  %scalbxx1 = call double @scalbn(double %scalbxx0, i32 %b)
+  ret double %scalbxx1
+}
+
+define float @scalbnf_scalbnf(float %x, i32 %a, i32 %b) {
+; CHECK-LABEL: define float @scalbnf
+; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[SCALBXX0:%.*]] = call float @scalbnf(float [[X]], i32 [[A]])
+; CHECK-NEXT:    [[SCALBXX1:%.*]] = call float @scalbnf(float [[SCALBXX0]], i32 [[B]])
+; CHECK-NEXT:    ret float [[SCALBXX1]]
+;
+  %scalbxx0 = call float @scalbnf(float %x, i32 %a)
+  %scalbxx1 = call float @scalbnf(float %scalbxx0, i32 %b)
+  ret float %scalbxx1
+}
+
+define x86_fp80 @scalbnl_scalbnl(x86_fp80 %x, i32 %a, i32 %b) {
+; CHECK-LABEL: define x86_fp80 @scalbnl
+; CHECK-SAME: (x86_fp80 [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[SCALBXX0:%.*]] = call x86_fp80 @scalbnl(x86_fp80 [[X]], i32 [[A]])
+; CHECK-NEXT:    [[SCALBXX1:%.*]] = call x86_fp80 @scalbnl(x86_fp80 [[SCALBXX0]], i32 [[B]])
+; CHECK-NEXT:    ret x86_fp80 [[SCALBXX1]]
+;
+  %scalbxx0 = call x86_fp80 @scalbnl(x86_fp80 %x, i32 %a)
+  %scalbxx1 = call x86_fp80 @scalbnl(x86_fp80 %scalbxx0, i32 %b)
+  ret x86_fp80 %scalbxx1
+}

>From 11b33db7f51162a6caba02a1a9e98a5441bc810a Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Sat, 2 Nov 2024 23:53:03 +0800
Subject: [PATCH 2/3] impl in Analysis/ConstantFolding.cpp

---
 llvm/include/llvm/IR/Intrinsics.td            |  1 +
 .../llvm/Transforms/Utils/SimplifyLibCalls.h  |  1 -
 llvm/lib/Analysis/ConstantFolding.cpp         | 19 ++++++++--
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 36 -------------------
 4 files changed, 18 insertions(+), 39 deletions(-)

diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 8ed57f818d6006..a9a015a51e2286 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -1034,6 +1034,7 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
   def int_tanh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_pow  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
                            [LLVMMatchType<0>, LLVMMatchType<0>]>;
+  def int_ldexp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>;
   def int_log  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_log10: DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_log2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 93ab5f5974c189..128502b99d9a37 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -213,7 +213,6 @@ class LibCallSimplifier {
   Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
   Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
   Value *optimizeFdim(CallInst *CI, IRBuilderBase &B);
-  Value *optimizeScalbn(CallInst *CI, IRBuilderBase &B);
   // Wrapper for all floating point library call optimizations
   Value *optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func,
                                       IRBuilderBase &B);
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index c5a2c2f52f8dc2..dbbd3621d5e34e 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1681,7 +1681,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
   case 'i':
     return Name == "ilogb" || Name == "ilogbf";
   case 'l':
-    return Name == "log" || Name == "logf" || Name == "logl" ||
+    return Name == "ldexp" || Name == "ldexpf" || Name == "ldexpl" ||
+           Name == "log" || Name == "logf" || Name == "logl" ||
            Name == "log2" || Name == "log2f" || Name == "log10" ||
            Name == "log10f" || Name == "logb" || Name == "logbf" ||
            Name == "log1p" || Name == "log1pf";
@@ -1694,7 +1695,9 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
            Name == "rint" || Name == "rintf" ||
            Name == "round" || Name == "roundf";
   case 's':
-    return Name == "sin" || Name == "sinf" ||
+    return Name == "scalbn" || Name == "scalbnf" || Name == "scalbnl" ||
+           Name == "scalbln" || Name == "scalblnf" || Name == "scalblnl" ||
+           Name == "sin" || Name == "sinf" ||
            Name == "sinh" || Name == "sinhf" ||
            Name == "sqrt" || Name == "sqrtf";
   case 't':
@@ -2372,6 +2375,18 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
         return ConstantFP::get(Ty->getContext(), U);
       }
       break;
+    case LibFunc_ldexp:
+    case LibFunc_ldexpf:
+    case LibFunc_ldexpl:
+    case LibFunc_scalbn:
+    case LibFunc_scalbnf:
+    case LibFunc_scalbnl:
+    case LibFunc_scalbln:
+    case LibFunc_scalblnf:
+    case LibFunc_scalblnl:
+      if (TLI->has(Func))
+        return ConstantFoldFP(ldexp, APF, Ty);
+      break;
     case LibFunc_log:
     case LibFunc_logf:
     case LibFunc_log_finite:
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index afa2196243b538..d333242762eb9e 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3157,42 +3157,6 @@ Value *LibCallSimplifier::optimizeFdim(CallInst *CI, IRBuilderBase &B) {
   return ConstantFP::get(CI->getType(), MaxVal);
 }
 
-Value *LibCallSimplifier::optimizeScalbn(CallInst *CI, IRBuilderBase &B) {
-  Value *Base = CI->getArgOperand(0);
-  Value *Expo = CI->getArgOperand(1);
-  // Function *Callee = CI->getCalledFunction();
-  // StringRef Name = Callee->getName();
-  Type *Ty = CI->getType();
-  Module *M = CI->getModule();
-  // bool AllowApprox = CI->hasApproxFunc();
-  // bool Ignored;
-
-  // Propagate the math semantics from the call to any created instructions.
-  IRBuilderBase::FastMathFlagGuard Guard(B);
-  B.setFastMathFlags(CI->getFastMathFlags());
-  // Evaluate special cases related to the base.
-
-  // Scalbn(0.0, exp) -> 0.0
-  if (match(Base, m_SpecificFP(0.0)))
-    return Base;
-
-  // Scalbn(arg, 0) -> arg
-  if (match(Expo, m_Zero()))
-    return Base;
-
-  // Scalbn(arg, 1) -> arg * 2.0
-  if (match(Expo, m_SpecificInt(1)))
-    return B.CreateFMul(Base, ConstantFP::get(Ty, 2.0), "mul");
-
-  // Scalbn(1.0, exp) -> FLT_RADIX ^ exp
-  auto pow = createPowWithIntegerExponent(ConstantFP::get(Ty, 2.0), Expo, M, B);
-  if (match(Base, m_SpecificFP(1.0)))
-    return pow;
-
-  // otherwise
-  return B.CreateFMul(Base, pow, "mul");
-}
-
 //===----------------------------------------------------------------------===//
 // Integer Library Call Optimizations
 //===----------------------------------------------------------------------===//

>From 0d7c62cf833fec6d5e3205a4403c75623d03586e Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Sat, 2 Nov 2024 23:55:35 +0800
Subject: [PATCH 3/3] remove unused codes

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d333242762eb9e..d85e0d99466022 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -4105,13 +4105,6 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_remquof:
   case LibFunc_remquol:
     return optimizeRemquo(CI, Builder);
-  case LibFunc_scalbln:
-  case LibFunc_scalblnf:
-  case LibFunc_scalblnl:
-  case LibFunc_scalbn:
-  case LibFunc_scalbnf:
-  case LibFunc_scalbnl:
-    return optimizeScalbn(CI, Builder);
   case LibFunc_nan:
   case LibFunc_nanf:
   case LibFunc_nanl:



More information about the llvm-commits mailing list