[llvm] [SimplifyLibCalls] Fold more FP libcalls to intrinsics. (PR #227697)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 15:02:31 PDT 2026
================
@@ -0,0 +1,483 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine -mtriple=x86_64-unknown-linux-gnu %s | FileCheck %s
+
+; Rounding functions, sqrt and copysign libcalls are replaced by the
+; corresponding intrinsics. sqrt may set errno, so it is only replaced if the
+; call does not access memory.
+
+define float @ceilf_libcall(float %x) {
+; CHECK-LABEL: define float @ceilf_libcall(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.ceil.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @ceilf(float %x)
+ ret float %r
+}
+
+define double @ceil_libcall(double %x) {
+; CHECK-LABEL: define double @ceil_libcall(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.ceil.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @ceil(double %x)
+ ret double %r
+}
+
+define x86_fp80 @ceill_libcall(x86_fp80 %x) {
+; CHECK-LABEL: define x86_fp80 @ceill_libcall(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 [[X]])
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @ceill(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define float @floorf_libcall(float %x) {
+; CHECK-LABEL: define float @floorf_libcall(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @floorf(float %x)
+ ret float %r
+}
+
+define double @floor_libcall(double %x) {
+; CHECK-LABEL: define double @floor_libcall(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.floor.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @floor(double %x)
+ ret double %r
+}
+
+define x86_fp80 @floorl_libcall(x86_fp80 %x) {
+; CHECK-LABEL: define x86_fp80 @floorl_libcall(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 [[X]])
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @floorl(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define float @roundf_libcall(float %x) {
+; CHECK-LABEL: define float @roundf_libcall(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.round.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @roundf(float %x)
+ ret float %r
+}
+
+define double @round_libcall(double %x) {
+; CHECK-LABEL: define double @round_libcall(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.round.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @round(double %x)
+ ret double %r
+}
+
+define x86_fp80 @roundl_libcall(x86_fp80 %x) {
+; CHECK-LABEL: define x86_fp80 @roundl_libcall(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 [[X]])
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @roundl(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define float @roundevenf_libcall(float %x) {
+; CHECK-LABEL: define float @roundevenf_libcall(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.roundeven.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @roundevenf(float %x)
+ ret float %r
+}
+
+define double @roundeven_libcall(double %x) {
+; CHECK-LABEL: define double @roundeven_libcall(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.roundeven.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @roundeven(double %x)
+ ret double %r
+}
+
+define x86_fp80 @roundevenl_libcall(x86_fp80 %x) {
+; CHECK-LABEL: define x86_fp80 @roundevenl_libcall(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.roundeven.f80(x86_fp80 [[X]])
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @roundevenl(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define float @nearbyintf_libcall(float %x) {
+; CHECK-LABEL: define float @nearbyintf_libcall(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.nearbyint.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @nearbyintf(float %x)
+ ret float %r
+}
+
+define double @nearbyint_libcall(double %x) {
+; CHECK-LABEL: define double @nearbyint_libcall(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.nearbyint.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @nearbyint(double %x)
+ ret double %r
+}
+
+define x86_fp80 @nearbyintl_libcall(x86_fp80 %x) {
+; CHECK-LABEL: define x86_fp80 @nearbyintl_libcall(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 [[X]])
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @nearbyintl(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define float @rintf_libcall(float %x) {
+; CHECK-LABEL: define float @rintf_libcall(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.rint.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @rintf(float %x)
+ ret float %r
+}
+
+define double @rint_libcall(double %x) {
+; CHECK-LABEL: define double @rint_libcall(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.rint.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @rint(double %x)
+ ret double %r
+}
+
+define x86_fp80 @rintl_libcall(x86_fp80 %x) {
+; CHECK-LABEL: define x86_fp80 @rintl_libcall(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 [[X]])
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @rintl(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define float @truncf_libcall(float %x) {
+; CHECK-LABEL: define float @truncf_libcall(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.trunc.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @truncf(float %x)
+ ret float %r
+}
+
+define double @trunc_libcall(double %x) {
+; CHECK-LABEL: define double @trunc_libcall(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.trunc.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @trunc(double %x)
+ ret double %r
+}
+
+define x86_fp80 @truncl_libcall(x86_fp80 %x) {
+; CHECK-LABEL: define x86_fp80 @truncl_libcall(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 [[X]])
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @truncl(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define float @floorf_libcall_fmf_tail(float %x) {
+; CHECK-LABEL: define float @floorf_libcall_fmf_tail(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = tail call nnan ninf float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = tail call nnan ninf float @floorf(float %x)
+ ret float %r
+}
+
+define float @floorf_libcall_strictfp(float %x) strictfp {
+; CHECK-LABEL: define float @floorf_libcall_strictfp(
+; CHECK-SAME: float [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[R:%.*]] = call float @floorf(float [[X]]) #[[ATTR0]]
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @floorf(float %x) strictfp
+ ret float %r
+}
+
+define float @floorf_libcall_nobuiltin(float %x) {
+; CHECK-LABEL: define float @floorf_libcall_nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @floorf(float [[X]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @floorf(float %x) nobuiltin
+ ret float %r
+}
+
+define x86_fp80 @rintl_libcall_strictfp(x86_fp80 %x) strictfp {
+; CHECK-LABEL: define x86_fp80 @rintl_libcall_strictfp(
+; CHECK-SAME: x86_fp80 [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @rintl(x86_fp80 [[X]]) #[[ATTR0]]
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+ %r = call x86_fp80 @rintl(x86_fp80 %x) strictfp
+ ret x86_fp80 %r
+}
+
+define float @sqrtf_libcall_readnone(float %x) {
+; CHECK-LABEL: define float @sqrtf_libcall_readnone(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @sqrtf(float %x) memory(none)
----------------
fhahn wrote:
It looks like we currently do not preserve it for any replaced intrinsic.
Put up https://github.com/llvm/llvm-project/pull/227886
https://github.com/llvm/llvm-project/pull/227697
More information about the llvm-commits
mailing list