Skip to content

Conversation

@nikic
Copy link
Contributor

@nikic nikic commented Dec 8, 2025

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.

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.
@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2025

@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-backend-arm

@llvm/pr-subscribers-backend-aarch64

Author: Nikita Popov (nikic)

Changes

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.


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

8 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+12-6)
  • (modified) llvm/test/CodeGen/AArch64/arm64-rounding.ll (+2-6)
  • (modified) llvm/test/CodeGen/AArch64/floatdp_1source.ll (+2-5)
  • (modified) llvm/test/CodeGen/ARM/arm32-rounding.ll (+2-4)
  • (modified) llvm/test/CodeGen/Mips/mips64-f128.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/double-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/float-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/X86/rounding-ops.ll (+2-6)
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:

@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2025

@llvm/pr-subscribers-backend-mips

Author: Nikita Popov (nikic)

Changes

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.


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

8 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+12-6)
  • (modified) llvm/test/CodeGen/AArch64/arm64-rounding.ll (+2-6)
  • (modified) llvm/test/CodeGen/AArch64/floatdp_1source.ll (+2-5)
  • (modified) llvm/test/CodeGen/ARM/arm32-rounding.ll (+2-4)
  • (modified) llvm/test/CodeGen/Mips/mips64-f128.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/double-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/float-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/X86/rounding-ops.ll (+2-6)
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:

@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2025

@llvm/pr-subscribers-backend-x86

Author: Nikita Popov (nikic)

Changes

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.


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

8 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+12-6)
  • (modified) llvm/test/CodeGen/AArch64/arm64-rounding.ll (+2-6)
  • (modified) llvm/test/CodeGen/AArch64/floatdp_1source.ll (+2-5)
  • (modified) llvm/test/CodeGen/ARM/arm32-rounding.ll (+2-4)
  • (modified) llvm/test/CodeGen/Mips/mips64-f128.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/double-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/float-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/X86/rounding-ops.ll (+2-6)
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:

@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2025

@llvm/pr-subscribers-llvm-selectiondag

Author: Nikita Popov (nikic)

Changes

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.


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

8 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+12-6)
  • (modified) llvm/test/CodeGen/AArch64/arm64-rounding.ll (+2-6)
  • (modified) llvm/test/CodeGen/AArch64/floatdp_1source.ll (+2-5)
  • (modified) llvm/test/CodeGen/ARM/arm32-rounding.ll (+2-4)
  • (modified) llvm/test/CodeGen/Mips/mips64-f128.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/double-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/RISCV/float-zfa.ll (+1-3)
  • (modified) llvm/test/CodeGen/X86/rounding-ops.ll (+2-6)
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:

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always found this behavior surprising

@nikic nikic merged commit d5b3ba6 into llvm:main Dec 9, 2025
17 checks passed
@nikic nikic deleted the sdag-libcalls-remove branch December 9, 2025 07:07
nikic added a commit that referenced this pull request Dec 10, 2025
This is a followup to #171114,
removing the handling for most libcalls that are already canonicalized
to intrinsics in the middle-end. The only remaining one is fabs, which
has more test coverage than the others.
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Dec 10, 2025
This is a followup to llvm/llvm-project#171114,
removing the handling for most libcalls that are already canonicalized
to intrinsics in the middle-end. The only remaining one is fabs, which
has more test coverage than the others.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants