[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