[llvm] [LLVM] Add constant folding for llrint, llrintf, llrintl (PR #154799)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 21 14:03:11 PDT 2025
https://github.com/pratheekhassan21 updated https://github.com/llvm/llvm-project/pull/154799
>From adbfbaecc65014189e2240a301c25c50fba150ff Mon Sep 17 00:00:00 2001
From: Pratheek Gowda BS <pratheekgowdabs at Pratheeks-MacBook-Air.local>
Date: Thu, 21 Aug 2025 18:52:33 +0530
Subject: [PATCH] FIX:std::llrint,std::llrintf,std::llrintl compile time
folding
---
.../llvm/Analysis/TargetLibraryInfo.def | 19 ++++
.../llvm/Transforms/Utils/SimplifyLibCalls.h | 1 +
llvm/lib/Analysis/TargetLibraryInfo.cpp | 2 +
llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 7 ++
.../lib/Transforms/Utils/SimplifyLibCalls.cpp | 27 ++++++
.../Transforms/InferFunctionAttrs/annotate.ll | 10 +++
.../Transforms/InstCombine/llrint_fold.ll | 87 +++++++++++++++++++
.../Transforms/InstCombine/llrintf_fold.ll | 33 +++++++
.../Transforms/InstCombine/llrintl_fp80.ll | 65 ++++++++++++++
.../tools/llvm-tli-checker/ps4-tli-check.yaml | 24 ++++-
.../Analysis/TargetLibraryInfoTest.cpp | 3 +
11 files changed, 274 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/Transforms/InstCombine/llrint_fold.ll
create mode 100644 llvm/test/Transforms/InstCombine/llrintf_fold.ll
create mode 100644 llvm/test/Transforms/InstCombine/llrintl_fp80.ll
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index 014988299d37f..3f84a005c1b42 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -2122,6 +2122,25 @@ TLI_DEFINE_ENUM_INTERNAL(remquol)
TLI_DEFINE_STRING_INTERNAL("remquol")
TLI_DEFINE_SIG_INTERNAL(LDbl, LDbl, LDbl, Ptr)
+
+//long long llrint ( double num );
+TLI_DEFINE_ENUM_INTERNAL(llrint)
+TLI_DEFINE_STRING_INTERNAL("llrint")
+TLI_DEFINE_SIG_INTERNAL(LLong,Dbl)
+
+
+//long long llrintf( float arg );
+TLI_DEFINE_ENUM_INTERNAL(llrintf)
+TLI_DEFINE_STRING_INTERNAL("llrintf")
+TLI_DEFINE_SIG_INTERNAL(LLong,Flt)
+
+//long long llrintl( long double arg );
+TLI_DEFINE_ENUM_INTERNAL(llrintl)
+TLI_DEFINE_STRING_INTERNAL("llrintl")
+TLI_DEFINE_SIG_INTERNAL(LLong,LDbl)
+
+
+
/// double fdim(double x, double y);
TLI_DEFINE_ENUM_INTERNAL(fdim)
TLI_DEFINE_STRING_INTERNAL("fdim")
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 128502b99d9a3..c4b04acf33daa 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -212,6 +212,7 @@ class LibCallSimplifier {
Value *optimizeTrigInversionPairs(CallInst *CI, IRBuilderBase &B);
Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
+ Value *optimizellrint(CallInst *CI,IRBuilderBase &B);
Value *optimizeFdim(CallInst *CI, IRBuilderBase &B);
// Wrapper for all floating point library call optimizations
Value *optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func,
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index 6e9276669eb70..58867c8e58d82 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -315,6 +315,7 @@ static void initializeLibCalls(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_powf);
TLI.setUnavailable(LibFunc_remainderf);
TLI.setUnavailable(LibFunc_remquof);
+ TLI.setUnavailable(LibFunc_llrintf);
TLI.setUnavailable(LibFunc_fdimf);
TLI.setUnavailable(LibFunc_sinf);
TLI.setUnavailable(LibFunc_sinhf);
@@ -348,6 +349,7 @@ static void initializeLibCalls(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_powl);
TLI.setUnavailable(LibFunc_remainderl);
TLI.setUnavailable(LibFunc_remquol);
+ TLI.setUnavailable(LibFunc_llrintl);
TLI.setUnavailable(LibFunc_fdiml);
TLI.setUnavailable(LibFunc_sinl);
TLI.setUnavailable(LibFunc_sinhl);
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 573a78150ff3d..10d9603168a55 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1385,6 +1385,13 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setWillReturn(F);
Changed |= setOnlyWritesArgMemOrErrnoMem(F);
break;
+ case LibFunc_llrintf:
+ case LibFunc_llrintl:
+ case LibFunc_llrint:
+ Changed|=setDoesNotThrow(F);
+ Changed|=setDoesNotAccessMemory(F);
+ Changed|=setWillReturn(F);
+ break;
default:
// FIXME: It'd be really nice to cover all the library functions we're
// aware of here.
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 2d6a748f45079..4e449764e0cfb 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3111,6 +3111,29 @@ Value *LibCallSimplifier::optimizeRemquo(CallInst *CI, IRBuilderBase &B) {
return ConstantFP::get(CI->getType(), Rem);
}
+
+Value *LibCallSimplifier::optimizellrint(CallInst *CI,IRBuilderBase &B){
+ const APFloat *X;
+ if(!match(CI->getOperand(0),m_APFloat(X))){
+ return nullptr;
+ }
+ Type *type=CI->getType();
+
+ unsigned width=type->getIntegerBitWidth();
+
+ APSInt Result(width,false);
+ bool Isexact;
+
+ APFloat::opStatus Status=X->convertToInteger(Result,APFloat::rmNearestTiesToEven,&Isexact);
+
+ if(Status==APFloat::opOK || Status==APFloat::opInexact){
+ return ConstantInt::get(type,Result);
+ }
+
+ return nullptr;
+
+}
+
/// Constant folds fdim
Value *LibCallSimplifier::optimizeFdim(CallInst *CI, IRBuilderBase &B) {
// Cannot perform the fold unless the call has attribute memory(none)
@@ -4078,6 +4101,10 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
case LibFunc_remquof:
case LibFunc_remquol:
return optimizeRemquo(CI, Builder);
+ case LibFunc_llrint:
+ case LibFunc_llrintf:
+ case LibFunc_llrintl:
+ return optimizellrint(CI,Builder);
case LibFunc_nan:
case LibFunc_nanf:
case LibFunc_nanl:
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index 51e22bb86f331..464f664b045d7 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -978,6 +978,16 @@ declare i32 @statvfs(ptr, ptr)
; CHECK-LINUX: declare noundef i32 @statvfs64(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
declare i32 @statvfs64(ptr, ptr)
+; CHECK: declare noundef i64 @llrint(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare i64 @llrint(double)
+
+; CHECK: declare noundef i64 @llrintf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare i64 @llrintf(float)
+
+; CHECK: declare noundef i64 @llrintl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare i64 @llrintl(x86_fp80)
+
+
; CHECK: declare ptr @stpcpy(ptr noalias writeonly, ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
declare ptr @stpcpy(ptr, ptr)
diff --git a/llvm/test/Transforms/InstCombine/llrint_fold.ll b/llvm/test/Transforms/InstCombine/llrint_fold.ll
new file mode 100644
index 0000000000000..08cd4f66543a3
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/llrint_fold.ll
@@ -0,0 +1,87 @@
+; RUN: opt -S -passes=instcombine %s -o - | FileCheck %s
+
+
+declare i64 @llrint(double)
+
+; Positive number test
+; CHECK-LABEL: define i64 @test_llrint_pos()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 4
+define i64 @test_llrint_pos() {
+entry:
+ %val = call i64 @llrint(double 3.5)
+ ret i64 %val
+}
+
+; Negative number test
+; CHECK-LABEL: define i64 @test_llrint_neg()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 -2
+define i64 @test_llrint_neg() {
+entry:
+ %val = call i64 @llrint(double -2.5)
+ ret i64 %val
+}
+
+; Zero test
+; CHECK-LABEL: define i64 @test_llrint_zero()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 0
+define i64 @test_llrint_zero() {
+entry:
+ %val = call i64 @llrint(double 0.0)
+ ret i64 %val
+}
+
+; Large value test
+; CHECK-LABEL: define i64 @test_llrint_large()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 1000000
+define i64 @test_llrint_large() {
+entry:
+ %val = call i64 @llrint(double 1.0e6)
+ ret i64 %val
+}
+
+; Rounding test (check ties-to-even)
+; CHECK-LABEL: define i64 @test_llrint_round_even()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 2
+define i64 @test_llrint_round_even() {
+entry:
+ %val = call i64 @llrint(double 2.5)
+ ret i64 %val
+}
+
+; NaN test
+; CHECK-LABEL: define i64 @test_llrint_nan()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %val = call i64 @llrint(double 0x7FF8000000000000)
+; CHECK-NEXT: ret i64 %val
+define i64 @test_llrint_nan() {
+entry:
+ %val = call i64 @llrint(double 0x7FF8000000000000) ; NaN
+ ret i64 %val
+}
+
+; +Inf test
+; CHECK-LABEL: define i64 @test_llrint_posinf()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %val = call i64 @llrint(double 0x7FF0000000000000)
+; CHECK-NEXT: ret i64 %val
+define i64 @test_llrint_posinf() {
+entry:
+ %val = call i64 @llrint(double 0x7FF0000000000000) ; +Inf
+ ret i64 %val
+}
+
+; -Inf test
+; CHECK-LABEL: define i64 @test_llrint_neginf()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %val = call i64 @llrint(double 0xFFF0000000000000)
+; CHECK-NEXT: ret i64 %val
+define i64 @test_llrint_neginf() {
+entry:
+ %val = call i64 @llrint(double 0xFFF0000000000000) ; -Inf
+ ret i64 %val
+}
diff --git a/llvm/test/Transforms/InstCombine/llrintf_fold.ll b/llvm/test/Transforms/InstCombine/llrintf_fold.ll
new file mode 100644
index 0000000000000..40cc265c1666c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/llrintf_fold.ll
@@ -0,0 +1,33 @@
+; RUN: opt -S -passes=instcombine %s -o - | FileCheck %s
+
+declare i64 @llrintf(float)
+
+; Positive number test
+; CHECK-LABEL: define i64 @test_llrintf_pos()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 4
+define i64 @test_llrintf_pos() {
+entry:
+ %val = call i64 @llrintf(float 3.5)
+ ret i64 %val
+}
+
+; Negative number test
+; CHECK-LABEL: define i64 @test_llrintf_neg()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 -2
+define i64 @test_llrintf_neg() {
+entry:
+ %val = call i64 @llrintf(float -2.5)
+ ret i64 %val
+}
+
+; Zero test
+; CHECK-LABEL: define i64 @test_llrintf_zero()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 0
+define i64 @test_llrintf_zero() {
+entry:
+ %val = call i64 @llrintf(float 0.0)
+ ret i64 %val
+}
\ No newline at end of file
diff --git a/llvm/test/Transforms/InstCombine/llrintl_fp80.ll b/llvm/test/Transforms/InstCombine/llrintl_fp80.ll
new file mode 100644
index 0000000000000..a3e162ba5dac1
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/llrintl_fp80.ll
@@ -0,0 +1,65 @@
+; RUN: opt -S -passes=instcombine %s -o - | FileCheck %s
+declare i64 @llrintl(x86_fp80)
+
+; Positive number
+; CHECK-LABEL: define i64 @test_llrintl_pos()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 4
+define i64 @test_llrintl_pos() {
+entry:
+ %val = call i64 @llrintl(x86_fp80 0xK4000E000000000000000)
+ ret i64 %val
+}
+
+; Negative number
+; CHECK-LABEL: define i64 @test_llrintl_neg()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 -2
+define i64 @test_llrintl_neg() {
+entry:
+ %val = call i64 @llrintl(x86_fp80 0xKC000A000000000000000)
+ ret i64 %val
+}
+
+; Zero
+; CHECK-LABEL: define i64 @test_llrintl_zero()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i64 0
+define i64 @test_llrintl_zero() {
+entry:
+ %val = call i64 @llrintl(x86_fp80 0xK00000000000000000000)
+ ret i64 %val
+}
+
+; NaN
+; CHECK-LABEL: define i64 @test_llrintl_nan()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %val = call i64 @llrintl(x86_fp80 0xK7FFF8000000000000000)
+; CHECK-NEXT: ret i64 %val
+define i64 @test_llrintl_nan() {
+entry:
+ %val = call i64 @llrintl(x86_fp80 0xK7FFF8000000000000000)
+ ret i64 %val
+}
+
+; +Inf
+; CHECK-LABEL: define i64 @test_llrintl_posinf()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %val = call i64 @llrintl(x86_fp80 0xK7FFF0000000000000000)
+; CHECK-NEXT: ret i64 %val
+define i64 @test_llrintl_posinf() {
+entry:
+ %val = call i64 @llrintl(x86_fp80 0xK7FFF0000000000000000)
+ ret i64 %val
+}
+
+; -Inf
+; CHECK-LABEL: define i64 @test_llrintl_neginf()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %val = call i64 @llrintl(x86_fp80 0xKFFFF0000000000000000)
+; CHECK-NEXT: ret i64 %val
+define i64 @test_llrintl_neginf() {
+entry:
+ %val = call i64 @llrintl(x86_fp80 0xKFFFF0000000000000000)
+ ret i64 %val
+}
diff --git a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
index 51a5a63ba370c..2df49cc68bc43 100644
--- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
+++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
@@ -34,7 +34,7 @@
#
# CHECK: << Total TLI yes SDK no: 18
# CHECK: >> Total TLI no SDK yes: 0
-# CHECK: == Total TLI yes SDK yes: 271
+# CHECK: == Total TLI yes SDK yes: 274
#
# WRONG_DETAIL: << TLI yes SDK no : '_ZdaPv' aka operator delete[](void*)
# WRONG_DETAIL: >> TLI no SDK yes: '_ZdaPvj' aka operator delete[](void*, unsigned int)
@@ -48,14 +48,14 @@
# WRONG_DETAIL: << TLI yes SDK no : 'fminimum_numl'
# WRONG_SUMMARY: << Total TLI yes SDK no: 19{{$}}
# WRONG_SUMMARY: >> Total TLI no SDK yes: 1{{$}}
-# WRONG_SUMMARY: == Total TLI yes SDK yes: 270
+# WRONG_SUMMARY: == Total TLI yes SDK yes: 273
#
## The -COUNT suffix doesn't care if there are too many matches, so check
## the exact count first; the two directives should add up to that.
## Yes, this means additions to TLI will fail this test, but the argument
## to -COUNT can't be an expression.
-# AVAIL: TLI knows 524 symbols, 289 available
-# AVAIL-COUNT-289: {{^}} available
+# AVAIL: TLI knows 526 symbols, 292 available
+# AVAIL-COUNT-292: {{^}} available
# AVAIL-NOT: {{^}} available
# UNAVAIL-COUNT-235: not available
# UNAVAIL-NOT: not available
@@ -842,6 +842,10 @@ DynamicSymbols:
Type: STT_FUNC
Section: .text
Binding: STB_GLOBAL
+ - Name: llrint
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
- Name: remquof
Type: STT_FUNC
Section: .text
@@ -850,6 +854,18 @@ DynamicSymbols:
Type: STT_FUNC
Section: .text
Binding: STB_GLOBAL
+ - Name: llrint
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ - Name: llrintf
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ - Name: llrintl
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
- Name: fdim
Type: STT_FUNC
Section: .text
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index b33419545efa8..e40f1e6bbcd71 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -328,6 +328,9 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare double @remquo(double, double, ptr)\n"
"declare float @remquof(float, float, ptr)\n"
"declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr)\n"
+ "declare i64 @llrint(double)\n"
+ "declare i64 @llrintf(float)\n"
+ "declare i64 @llrintl(x86_fp80)\n"
"declare double @fdim(double, double)\n"
"declare float @fdimf(float, float)\n"
"declare x86_fp80 @fdiml(x86_fp80, x86_fp80)\n"
More information about the llvm-commits
mailing list