[llvm] [SimplifyLibCalls] Preserve !fpmath when replacing libcalls. (PR #227886)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 15:02:22 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

<details>
<summary>Changes</summary>

As pointed out in https://github.com/llvm/llvm-project/pull/227697, replaceUnaryCall and replaceBinaryCall drop !fpmath. 

Transfer it to the created intrinsics.

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


2 Files Affected:

- (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+9) 
- (added) llvm/test/Transforms/InstCombine/libcall-fpmath.ll (+43) 


``````````diff
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
new file mode 100644
index 0000000000000..7c09c482b620b
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/libcall-fpmath.ll
@@ -0,0 +1,43 @@
+; 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]]), !fpmath [[META0:![0-9]+]]
+; 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]]), !fpmath [[META0]]
+; 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]]), !fpmath [[META0]]
+; 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}
+;.
+; CHECK: [[META0]] = !{float 2.500000e+00}
+;.

``````````

</details>


https://github.com/llvm/llvm-project/pull/227886


More information about the llvm-commits mailing list