[llvm] [SimplifyLibCalls] Preserve !fpmath when replacing libcalls. (PR #227886)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 01:36:13 PDT 2026
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/227886
>From 9ab2c5107053e0364db1f6692bb0299621b078ae Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 30 Sep 2026 21:30:50 +0100
Subject: [PATCH 1/2] [InstCombine] Add tests for !fpmath on libcalls replaced
by intrinsics.
---
.../Transforms/InstCombine/libcall-fpmath.ll | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/libcall-fpmath.ll
diff --git a/llvm/test/Transforms/InstCombine/libcall-fpmath.ll b/llvm/test/Transforms/InstCombine/libcall-fpmath.ll
new file mode 100644
index 0000000000000..611fd2a7b5bfa
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/libcall-fpmath.ll
@@ -0,0 +1,40 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=instcombine -S %s | FileCheck %s
+
+; !fpmath must be preserved when a libcall is replaced by an intrinsic.
+
+define double @floor_fpmath(double %x) {
+; CHECK-LABEL: define double @floor_fpmath(
+; 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), !fpmath !0
+ ret double %r
+}
+
+define double @fabs_fpmath(double %x) {
+; CHECK-LABEL: define double @fabs_fpmath(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.fabs.f64(double [[X]])
+; CHECK-NEXT: ret double [[R]]
+;
+ %r = call double @fabs(double %x), !fpmath !0
+ ret double %r
+}
+
+define float @sinf_fpmath(float %x) {
+; CHECK-LABEL: define float @sinf_fpmath(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.sin.f32(float [[X]])
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @sinf(float %x) memory(none), !fpmath !0
+ ret float %r
+}
+
+declare double @floor(double)
+declare double @fabs(double)
+declare float @sinf(float)
+
+!0 = !{float 2.5}
>From 2f8492cf722c461c3619d5ce8cd4bf311eb16c21 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 30 Sep 2026 21:31:09 +0100
Subject: [PATCH 2/2] [SimplifyLibCalls] Preserve !fpmath when replacing
libcalls with intrinsics.
---
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 9 +++++++++
llvm/test/Transforms/InstCombine/libcall-fpmath.ll | 9 ++++++---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index f6235b5b98fcb..2ca27db66d490 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2022,11 +2022,19 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
// Math Library Optimizations
//===----------------------------------------------------------------------===//
+/// Preserve the accuracy requirement of \p Old on the replacement \p New.
+static void copyFPMath(const CallInst &Old, Value *New) {
+ if (auto *NewI = dyn_cast<Instruction>(New))
+ if (MDNode *MD = Old.getMetadata(LLVMContext::MD_fpmath))
+ NewI->setMetadata(LLVMContext::MD_fpmath, MD);
+}
+
// Replace a libcall \p CI with a call to intrinsic \p IID
static Value *replaceUnaryCall(CallInst *CI, IRBuilderBase &B,
Intrinsic::ID IID) {
Value *NewCall = B.CreateUnaryIntrinsic(IID, CI->getArgOperand(0), CI);
NewCall->takeName(CI);
+ copyFPMath(*CI, NewCall);
return copyFlags(*CI, NewCall);
}
@@ -2035,6 +2043,7 @@ static Value *replaceBinaryCall(CallInst *CI, IRBuilderBase &B,
Value *NewCall = B.CreateBinaryIntrinsic(IID, CI->getArgOperand(0),
CI->getArgOperand(1), CI);
NewCall->takeName(CI);
+ copyFPMath(*CI, NewCall);
return copyFlags(*CI, NewCall);
}
diff --git a/llvm/test/Transforms/InstCombine/libcall-fpmath.ll b/llvm/test/Transforms/InstCombine/libcall-fpmath.ll
index 611fd2a7b5bfa..7c09c482b620b 100644
--- a/llvm/test/Transforms/InstCombine/libcall-fpmath.ll
+++ b/llvm/test/Transforms/InstCombine/libcall-fpmath.ll
@@ -6,7 +6,7 @@
define double @floor_fpmath(double %x) {
; CHECK-LABEL: define double @floor_fpmath(
; CHECK-SAME: double [[X:%.*]]) {
-; CHECK-NEXT: [[R:%.*]] = call double @llvm.floor.f64(double [[X]])
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.floor.f64(double [[X]]), !fpmath [[META0:![0-9]+]]
; CHECK-NEXT: ret double [[R]]
;
%r = call double @floor(double %x), !fpmath !0
@@ -16,7 +16,7 @@ define double @floor_fpmath(double %x) {
define double @fabs_fpmath(double %x) {
; CHECK-LABEL: define double @fabs_fpmath(
; CHECK-SAME: double [[X:%.*]]) {
-; CHECK-NEXT: [[R:%.*]] = call double @llvm.fabs.f64(double [[X]])
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.fabs.f64(double [[X]]), !fpmath [[META0]]
; CHECK-NEXT: ret double [[R]]
;
%r = call double @fabs(double %x), !fpmath !0
@@ -26,7 +26,7 @@ define double @fabs_fpmath(double %x) {
define float @sinf_fpmath(float %x) {
; CHECK-LABEL: define float @sinf_fpmath(
; CHECK-SAME: float [[X:%.*]]) {
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.sin.f32(float [[X]])
+; CHECK-NEXT: [[R:%.*]] = call float @llvm.sin.f32(float [[X]]), !fpmath [[META0]]
; CHECK-NEXT: ret float [[R]]
;
%r = call float @sinf(float %x) memory(none), !fpmath !0
@@ -38,3 +38,6 @@ declare double @fabs(double)
declare float @sinf(float)
!0 = !{float 2.5}
+;.
+; CHECK: [[META0]] = !{float 2.500000e+00}
+;.
More information about the llvm-commits
mailing list