[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