llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

[LLVM] Add constant folding for llrint, llrintf, llrintl

Open pratheekhassan21 opened this issue 4 months ago • 13 comments

Fixes issue :#113914

pratheekhassan21 avatar Aug 21 '25 17:08 pratheekhassan21

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

github-actions[bot] avatar Aug 21 '25 17:08 github-actions[bot]

@llvm/pr-subscribers-github-workflow @llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: None (pratheekhassan21)

Changes

Fixes issue :#113914


Full diff: https://github.com/llvm/llvm-project/pull/154799.diff

11 Files Affected:

  • (modified) llvm/include/llvm/Analysis/TargetLibraryInfo.def (+19)
  • (modified) llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h (+1)
  • (modified) llvm/lib/Analysis/TargetLibraryInfo.cpp (+2)
  • (modified) llvm/lib/Transforms/Utils/BuildLibCalls.cpp (+7)
  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+27)
  • (modified) llvm/test/Transforms/InferFunctionAttrs/annotate.ll (+10)
  • (added) llvm/test/Transforms/InstCombine/llrint_fold.ll (+87)
  • (added) llvm/test/Transforms/InstCombine/llrintf_fold.ll (+33)
  • (added) llvm/test/Transforms/InstCombine/llrintl_fp80.ll (+65)
  • (modified) llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml (+20-4)
  • (modified) llvm/unittests/Analysis/TargetLibraryInfoTest.cpp (+3)
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index db566b8ee610e..c9529b64ad77d 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -2117,6 +2117,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 e2fd2aa13cce7..d871e4194ac55 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -307,6 +307,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);
@@ -340,6 +341,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 a5f6047b0b7ae..68887f5becdf0 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1383,6 +1383,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 941e787f91eff..2e8ca90215455 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3109,6 +3109,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)
@@ -4076,6 +4099,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 9e56b01c6b315..3c85b8f64755d 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -975,6 +975,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 2d23b15d74b17..4bc3adf7094a9 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 523 symbols, 289 available
-# AVAIL-COUNT-289: {{^}} available
+# AVAIL: TLI knows 526 symbols, 292 available
+# AVAIL-COUNT-292: {{^}} available
 # AVAIL-NOT:       {{^}} available
 # UNAVAIL-COUNT-234: 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 97722483aefe0..190467f5bed21 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -327,6 +327,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"

llvmbot avatar Aug 21 '25 17:08 llvmbot

Please rebase to resolve the merge conflict and format the code using git-clang-format.

nikic avatar Aug 21 '25 19:08 nikic

:white_check_mark: With the latest revision this PR passed the C/C++ code formatter.

github-actions[bot] avatar Aug 21 '25 21:08 github-actions[bot]

@nikic i rebased and ran clang formatter on the code forgive my ignorance since this is my first contribution to llvm

pratheekhassan21 avatar Aug 22 '25 05:08 pratheekhassan21

Why do you need to directly constant fold the libcalls? We have intrinsics for these, which we arguably should just always replace libcalls with

This is a great question. I assumed this is because of the usual issue where the libcall may set errno and intrinsics don't. But these particular functions are specified to not set errno. (Edit: Well, at least that's what the man page says. It seems like the C standard does not specify this.)

The intrinsic is emitted if you use -fno-math-errno though. So I think these builtins may have just been misclassified in clang codegen and should be switched to emit the intrinsic unconditionally (not inside the GenerateIntrinsics conditional).

nikic avatar Aug 22 '25 16:08 nikic

@arsenm do u suggest me to take back the pr and emit llrint intrinsics instead

pratheekhassan21 avatar Aug 22 '25 17:08 pratheekhassan21

@nikic i fixed the issues can u review it once

pratheekhassan21 avatar Aug 24 '25 21:08 pratheekhassan21

@arsenm i moved to constant folding.cpp and clang formatted it

pratheekhassan21 avatar Dec 08 '25 11:12 pratheekhassan21

:penguin: Linux x64 Test Results

  • 187560 tests passed
  • 4972 tests skipped

:white_check_mark: The build succeeded and all tests passed.

github-actions[bot] avatar Dec 08 '25 12:12 github-actions[bot]

@nikic hey can u review?

pratheekhassan21 avatar Dec 09 '25 14:12 pratheekhassan21

@arsenm hey can u review if everything is right?

pratheekhassan21 avatar Dec 10 '25 03:12 pratheekhassan21

:window: Windows x64 Test Results

  • 128712 tests passed
  • 2824 tests skipped

:white_check_mark: The build succeeded and all tests passed.

github-actions[bot] avatar Dec 10 '25 07:12 github-actions[bot]