[llvm] [LLVM] Add constant folding for llrint, llrintf, llrintl (PR #154799)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 24 03:38:45 PDT 2025
https://github.com/pratheekhassan21 updated https://github.com/llvm/llvm-project/pull/154799
>From 98e7f6ee9364b772564f7659de256346a48e9cde Mon Sep 17 00:00:00 2001
From: Pratheek Gowda BS <pratheekgowdabs at example.com>
Date: Sun, 24 Aug 2025 16:07:03 +0530
Subject: [PATCH] errors were fixed
---
.../llvm/Analysis/TargetLibraryInfo.def | 16 +++
.../llvm/Transforms/Utils/SimplifyLibCalls.h | 1 +
llvm/lib/Analysis/TargetLibraryInfo.cpp | 2 +
llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 7 ++
.../lib/Transforms/Utils/SimplifyLibCalls.cpp | 22 ++++
.../Transforms/InferFunctionAttrs/annotate.ll | 10 ++
.../Transforms/InstCombine/llrint_fold.ll | 87 +++++++++++++++
.../Transforms/InstCombine/llrintf_fold.ll | 102 ++++++++++++++++++
.../Transforms/InstCombine/llrintl_fp80.ll | 65 +++++++++++
.../tools/llvm-tli-checker/ps4-tli-check.yaml | 12 +++
.../Analysis/TargetLibraryInfoTest.cpp | 3 +
11 files changed, 327 insertions(+)
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..01290698da9df 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -1731,6 +1731,22 @@ TLI_DEFINE_ENUM_INTERNAL(llabs)
TLI_DEFINE_STRING_INTERNAL("llabs")
TLI_DEFINE_SIG_INTERNAL(LLong, LLong)
+//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 log(double x);
TLI_DEFINE_ENUM_INTERNAL(log)
TLI_DEFINE_STRING_INTERNAL("log")
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 128502b99d9a3..1c630783c029d 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -207,6 +207,7 @@ class LibCallSimplifier {
Value *optimizeLog(CallInst *CI, IRBuilderBase &B);
Value *optimizeSqrt(CallInst *CI, IRBuilderBase &B);
Value *optimizeFMod(CallInst *CI, IRBuilderBase &B);
+ Value *optimizellrint(CallInst *CI,IRBuilderBase &B);
Value *mergeSqrtToExp(CallInst *CI, IRBuilderBase &B);
Value *optimizeSinCosPi(CallInst *CI, bool IsSin, IRBuilderBase &B);
Value *optimizeTrigInversionPairs(CallInst *CI, IRBuilderBase &B);
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index 6e9276669eb70..431e91f2584ea 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -309,6 +309,7 @@ static void initializeLibCalls(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_floorf);
TLI.setUnavailable(LibFunc_fmodf);
TLI.setUnavailable(LibFunc_hypotf);
+ TLI.setAvailable(LibFunc_llrintf);
TLI.setUnavailable(LibFunc_log10f);
TLI.setUnavailable(LibFunc_logf);
TLI.setUnavailable(LibFunc_modff);
@@ -342,6 +343,7 @@ static void initializeLibCalls(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_frexpl);
TLI.setUnavailable(LibFunc_hypotl);
TLI.setUnavailable(LibFunc_ldexpl);
+ TLI.setUnavailable(LibFunc_llrintl);
TLI.setUnavailable(LibFunc_log10l);
TLI.setUnavailable(LibFunc_logl);
TLI.setUnavailable(LibFunc_modfl);
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 573a78150ff3d..737d59081fd43 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1368,6 +1368,13 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotFreeMemory(F);
Changed |= setWillReturn(F);
break;
+ case LibFunc_llrintf:
+ case LibFunc_llrintl:
+ case LibFunc_llrint:
+ Changed|=setDoesNotThrow(F);
+ Changed|=setDoesNotAccessMemory(F);
+ Changed|=setWillReturn(F);
+ break;
case LibFunc_sincos:
case LibFunc_sincosf:
case LibFunc_sincosl:
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 2d6a748f45079..f40a771453790 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3111,6 +3111,28 @@ 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)
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index 51e22bb86f331..4c8cf6b747602 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -661,6 +661,15 @@ declare i32 @ilogbf(float)
; CHECK: declare i32 @ilogbl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare i32 @ilogbl(x86_fp80)
+; CHECK: declare noundef i64 @llrint(double) [[MATH_NOACCESS:#[0-9]+]]
+declare i64 @llrint(double)
+
+; CHECK: declare noundef i64 @llrintf(float) [[MATH_NOACCESS:#[0-9]+]]
+declare i64 @llrintf(float)
+
+; CHECK: declare noundef i64 @llrintl(x86_fp80) [[MATH_NOACCESS:#[0-9]+]]
+declare i64 @llrintl(x86_fp80)
+
; CHECK: declare double @logb(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare double @logb(double)
@@ -1196,6 +1205,7 @@ declare void @memset_pattern16(ptr, ptr, i64)
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn memory(read) }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind memory(read) }
+; CHECK-DAG: attributes [[MATH_NOACCESS]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_FREE_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
diff --git a/llvm/test/Transforms/InstCombine/llrint_fold.ll b/llvm/test/Transforms/InstCombine/llrint_fold.ll
new file mode 100644
index 0000000000000..1e8b71d60f495
--- /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
+}
\ No newline at end of file
diff --git a/llvm/test/Transforms/InstCombine/llrintf_fold.ll b/llvm/test/Transforms/InstCombine/llrintf_fold.ll
new file mode 100644
index 0000000000000..e611f666fd646
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/llrintf_fold.ll
@@ -0,0 +1,102 @@
+; 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
+}
+ 65 changes: 65 additions & 0 deletions65
+llvm/test/Transforms/InstCombine/llrintl_fp80.ll
+Original file line number Diff line number Diff line change
+@@ -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
+}
\ 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..04d54d95163ef
--- /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
+}
\ No newline at end of file
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..9f52c5a3a5b02 100644
--- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
+++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
@@ -690,6 +690,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: logb
Type: STT_FUNC
Section: .text
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index b33419545efa8..86eae5da2baa4 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -258,6 +258,9 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare double @ldexp(double, i32)\n"
"declare float @ldexpf(float, i32)\n"
"declare x86_fp80 @ldexpl(x86_fp80, i32)\n"
+ "declare i64 @llrint(double)\n"
+ "declare i64 @llrintf(float)\n"
+ "declare i64 @llrintl(x86_fp80)\n"
"declare i64 @llabs(i64)\n"
"declare double @log(double)\n"
"declare double @log10(double)\n"
More information about the llvm-commits
mailing list