[llvm] [SDAG] Don't handle non-canonical libcalls in SDAG lowering (PR #171114)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 8 03:46:21 PST 2025


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/171114

SDAG currently tries to lower certain libcalls to ISD opcodes. However, many of these are already canonicalized from libcalls to intrinsic in the middle-end (and often already emitted as intrinsics in the front-end).

I believe that SDAG should not be doing anything for such libcalls. This PR just drops a single libcall to get consensus on the direction, as these changes need a non-trivial amount of test updates.

A lot of the remaining libcalls *should* probably also be canonicalized to intrinsics in the middle-end when annotated with `memory(none)`, but that would require additional work in SimplifyLibCalls.

>From 4068497a9f6c736eccda8fde54a3adfafecb0de2 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 8 Dec 2025 12:31:40 +0100
Subject: [PATCH] [SDAG] Don't handle non-canonical libcalls in SDAG lowering

SDAG currently tries to lower certain libcalls to ISD opcodes.
However, many of these are already canonicalized from libcalls
to intrinsic in the middle-end (and often already emitted as
intrinsics in the front-end).

I believe that SDAG should not be doing anything for such libcalls.
This PR just drops a single libcall to get consensus on the direction,
as these changes need a non-trivial amount of test updates.

A lot of the remaining libcalls *should* probably also be
canonicalized to intrinsics in the middle-end when annotated with
`memory(none)`, but that would require additional work in
SimplifyLibCalls.
---
 .../SelectionDAG/SelectionDAGBuilder.cpp       | 18 ++++++++++++------
 llvm/test/CodeGen/AArch64/arm64-rounding.ll    |  8 ++------
 llvm/test/CodeGen/AArch64/floatdp_1source.ll   |  7 ++-----
 llvm/test/CodeGen/ARM/arm32-rounding.ll        |  6 ++----
 llvm/test/CodeGen/Mips/mips64-f128.ll          |  4 +---
 llvm/test/CodeGen/RISCV/double-zfa.ll          |  4 +---
 llvm/test/CodeGen/RISCV/float-zfa.ll           |  4 +---
 llvm/test/CodeGen/X86/rounding-ops.ll          |  8 ++------
 8 files changed, 23 insertions(+), 36 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 09a0673bfe1bb..71345509ea429 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9559,6 +9559,8 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
     // Check for well-known libc/libm calls.  If the function is internal, it
     // can't be a library call.  Don't do the check if marked as nobuiltin for
     // some reason.
+    // This code should not handle libcalls that are already canonicalized to
+    // intrinsics by the middle-end.
     LibFunc Func;
     if (!I.isNoBuiltin() && !F->hasLocalLinkage() && F->hasName() &&
         LibInfo->getLibFunc(*F, Func) && LibInfo->hasOptimizedCodeGen(Func)) {
@@ -9584,30 +9586,35 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
       case LibFunc_fabs:
       case LibFunc_fabsf:
       case LibFunc_fabsl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitUnaryFloatCall(I, ISD::FABS))
           return;
         break;
       case LibFunc_fmin:
       case LibFunc_fminf:
       case LibFunc_fminl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitBinaryFloatCall(I, ISD::FMINNUM))
           return;
         break;
       case LibFunc_fmax:
       case LibFunc_fmaxf:
       case LibFunc_fmaxl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitBinaryFloatCall(I, ISD::FMAXNUM))
           return;
         break;
       case LibFunc_fminimum_num:
       case LibFunc_fminimum_numf:
       case LibFunc_fminimum_numl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitBinaryFloatCall(I, ISD::FMINIMUMNUM))
           return;
         break;
       case LibFunc_fmaximum_num:
       case LibFunc_fmaximum_numf:
       case LibFunc_fmaximum_numl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitBinaryFloatCall(I, ISD::FMAXIMUMNUM))
           return;
         break;
@@ -9683,36 +9690,35 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
       case LibFunc_floor:
       case LibFunc_floorf:
       case LibFunc_floorl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitUnaryFloatCall(I, ISD::FFLOOR))
           return;
         break;
-      case LibFunc_nearbyint:
-      case LibFunc_nearbyintf:
-      case LibFunc_nearbyintl:
-        if (visitUnaryFloatCall(I, ISD::FNEARBYINT))
-          return;
-        break;
       case LibFunc_ceil:
       case LibFunc_ceilf:
       case LibFunc_ceill:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitUnaryFloatCall(I, ISD::FCEIL))
           return;
         break;
       case LibFunc_rint:
       case LibFunc_rintf:
       case LibFunc_rintl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitUnaryFloatCall(I, ISD::FRINT))
           return;
         break;
       case LibFunc_round:
       case LibFunc_roundf:
       case LibFunc_roundl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitUnaryFloatCall(I, ISD::FROUND))
           return;
         break;
       case LibFunc_trunc:
       case LibFunc_truncf:
       case LibFunc_truncl:
+        // TODO: Remove this, already canonicalized by the middle-end.
         if (visitUnaryFloatCall(I, ISD::FTRUNC))
           return;
         break;
diff --git a/llvm/test/CodeGen/AArch64/arm64-rounding.ll b/llvm/test/CodeGen/AArch64/arm64-rounding.ll
index 3ce35bfc4537c..618731fb001ca 100644
--- a/llvm/test/CodeGen/AArch64/arm64-rounding.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-rounding.ll
@@ -26,22 +26,18 @@ declare double @floor(double) nounwind readnone
 ; CHECK: frinti
 define float @test3(float %a) #0 {
 entry:
-  %call = tail call float @nearbyintf(float %a) nounwind readnone
+  %call = tail call float @llvm.nearbyint.f32(float %a) nounwind readnone
   ret float %call
 }
 
-declare float @nearbyintf(float) nounwind readnone
-
 ; CHECK-LABEL: test4:
 ; CHECK: frinti
 define double @test4(double %a) #0 {
 entry:
-  %call = tail call double @nearbyint(double %a) nounwind readnone
+  %call = tail call double @llvm.nearbyint.f64(double %a) nounwind readnone
   ret double %call
 }
 
-declare double @nearbyint(double) nounwind readnone
-
 ; CHECK-LABEL: test5:
 ; CHECK: frintp
 ; CHECK-NOT: frintx
diff --git a/llvm/test/CodeGen/AArch64/floatdp_1source.ll b/llvm/test/CodeGen/AArch64/floatdp_1source.ll
index 1c37f7045342f..8d1620d62ab01 100644
--- a/llvm/test/CodeGen/AArch64/floatdp_1source.ll
+++ b/llvm/test/CodeGen/AArch64/floatdp_1source.ll
@@ -19,9 +19,6 @@ declare double @trunc(double) readonly
 declare float @rintf(float) readonly
 declare double @rint(double) readonly
 
-declare float @nearbyintf(float) readonly
-declare double @nearbyint(double) readonly
-
 define float @fabs_f(float %v) {
 ; CHECK-LABEL: fabs_f:
 ; CHECK:       ; %bb.0:
@@ -90,7 +87,7 @@ define float @nearbyint_f(float %v) {
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    frinti s0, s0
 ; CHECK-NEXT:    ret
-  %r = call float @nearbyintf(float %v)
+  %r = call float @llvm.nearbyint.f32(float %v)
   ret float %r
 }
 
@@ -162,7 +159,7 @@ define double @nearbyint_d(double %v) {
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    frinti d0, d0
 ; CHECK-NEXT:    ret
-  %r = call double @nearbyint(double %v)
+  %r = call double @llvm.nearbyint.f64(double %v)
   ret double %r
 }
 
diff --git a/llvm/test/CodeGen/ARM/arm32-rounding.ll b/llvm/test/CodeGen/ARM/arm32-rounding.ll
index cc5b5612f49bb..5363f0fd6f081 100644
--- a/llvm/test/CodeGen/ARM/arm32-rounding.ll
+++ b/llvm/test/CodeGen/ARM/arm32-rounding.ll
@@ -74,7 +74,7 @@ entry:
 ; CHECK: vrintr.f32
 define float @test9(float %a) {
 entry:
-  %call = call float @nearbyintf(float %a) nounwind readnone
+  %call = call float @llvm.nearbyint.f32(float %a) nounwind readnone
   ret float %call
 }
 
@@ -83,7 +83,7 @@ entry:
 ; DP: vrintr.f64
 define double @test10(double %a) {
 entry:
-  %call = call double @nearbyint(double %a) nounwind readnone
+  %call = call double @llvm.nearbyint.f64(double %a) nounwind readnone
   ret double %call
 }
 
@@ -128,8 +128,6 @@ declare float @roundf(float) nounwind readnone
 declare double @round(double) nounwind readnone
 declare float @truncf(float) nounwind readnone
 declare double @trunc(double) nounwind readnone
-declare float @nearbyintf(float) nounwind readnone
-declare double @nearbyint(double) nounwind readnone
 declare float @rintf(float) nounwind readnone
 declare double @rint(double) nounwind readnone
 declare float @llvm.roundeven.f32(float)
diff --git a/llvm/test/CodeGen/Mips/mips64-f128.ll b/llvm/test/CodeGen/Mips/mips64-f128.ll
index 04bed7d42bf96..026caa90ef575 100644
--- a/llvm/test/CodeGen/Mips/mips64-f128.ll
+++ b/llvm/test/CodeGen/Mips/mips64-f128.ll
@@ -1736,12 +1736,10 @@ define fp128 @libcall1_nearbyintl() {
 ; CMP_CC_FMT-NEXT:    jrc $ra
 entry:
   %0 = load fp128, ptr @gld0, align 16
-  %call = tail call fp128 @nearbyintl(fp128 %0) nounwind readnone
+  %call = tail call fp128 @llvm.nearbyint.f128(fp128 %0) nounwind readnone
   ret fp128 %call
 }
 
-declare fp128 @nearbyintl(fp128) #1
-
 define fp128 @libcall1_floorl() {
 ; C_CC_FMT-LABEL: libcall1_floorl:
 ; C_CC_FMT:       # %bb.0: # %entry
diff --git a/llvm/test/CodeGen/RISCV/double-zfa.ll b/llvm/test/CodeGen/RISCV/double-zfa.ll
index a93ec86e363fc..dec56d2b79e33 100644
--- a/llvm/test/CodeGen/RISCV/double-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/double-zfa.ll
@@ -250,12 +250,10 @@ define double @fround_d_5(double %a) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fround.d fa0, fa0
 ; CHECK-NEXT:    ret
-  %call = tail call double @nearbyint(double %a) nounwind readnone
+  %call = tail call double @llvm.nearbyint.f64(double %a) nounwind readnone
   ret double %call
 }
 
-declare double @nearbyint(double) nounwind readnone
-
 define double @fround_d_6(double %a) nounwind {
 ; CHECK-LABEL: fround_d_6:
 ; CHECK:       # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/float-zfa.ll b/llvm/test/CodeGen/RISCV/float-zfa.ll
index 7be0d998f38c3..dd9eedfa4cb35 100644
--- a/llvm/test/CodeGen/RISCV/float-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/float-zfa.ll
@@ -183,12 +183,10 @@ define float @fround_s_5(float %a) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fround.s fa0, fa0
 ; CHECK-NEXT:    ret
-  %call = tail call float @nearbyintf(float %a) nounwind readnone
+  %call = tail call float @llvm.nearbyint.f32(float %a) nounwind readnone
   ret float %call
 }
 
-declare float @nearbyintf(float) nounwind readnone
-
 define float @fround_s_6(float %a) nounwind {
 ; CHECK-LABEL: fround_s_6:
 ; CHECK:       # %bb.0:
diff --git a/llvm/test/CodeGen/X86/rounding-ops.ll b/llvm/test/CodeGen/X86/rounding-ops.ll
index 948449c68b3f0..147663a84d2e0 100644
--- a/llvm/test/CodeGen/X86/rounding-ops.ll
+++ b/llvm/test/CodeGen/X86/rounding-ops.ll
@@ -60,12 +60,10 @@ define float @test3(float %x) nounwind  {
 ; CHECK-AVX512:       ## %bb.0:
 ; CHECK-AVX512-NEXT:    vroundss $12, %xmm0, %xmm0, %xmm0
 ; CHECK-AVX512-NEXT:    retq
-  %call = tail call float @nearbyintf(float %x) nounwind readnone
+  %call = tail call float @llvm.nearbyint.f32(float %x) nounwind readnone
   ret float %call
 }
 
-declare float @nearbyintf(float) nounwind readnone
-
 define double @test4(double %x) nounwind  {
 ; CHECK-SSE-LABEL: test4:
 ; CHECK-SSE:       ## %bb.0:
@@ -81,12 +79,10 @@ define double @test4(double %x) nounwind  {
 ; CHECK-AVX512:       ## %bb.0:
 ; CHECK-AVX512-NEXT:    vroundsd $12, %xmm0, %xmm0, %xmm0
 ; CHECK-AVX512-NEXT:    retq
-  %call = tail call double @nearbyint(double %x) nounwind readnone
+  %call = tail call double @llvm.nearbyint.f64(double %x) nounwind readnone
   ret double %call
 }
 
-declare double @nearbyint(double) nounwind readnone
-
 define float @test5(float %x) nounwind  {
 ; CHECK-SSE-LABEL: test5:
 ; CHECK-SSE:       ## %bb.0:



More information about the llvm-commits mailing list