[llvm] [SDAG] Honor signed arguments in floating point libcalls (PR #109134)
Timothy Pearson via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 18 11:09:29 PDT 2024
https://github.com/tpearson-ssc updated https://github.com/llvm/llvm-project/pull/109134
>From 961d4383f8c73e0639799308c0b0e6d3bdaa1ef4 Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson at solidsilicon.com>
Date: Wed, 18 Sep 2024 07:49:58 -0500
Subject: [PATCH] [SDAG] Honor signed arguments in floating point libcalls
In ExpandFPLibCall, an assumption is made that all floating point libcalls
that take integer arguments use unsigned integers. In the case of ldexp
and frexp, this assumption is incorrect, leading to miscompilation and
subsequent target-dependent incorrect operation.
Indicate that ldexp and frexp utilize signed arguments in ExpandFPLibCall.
Fixes #108904
Signed-off-by: Timothy Pearson <tpearson at solidsilicon.com>
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 19 +++++++++-
llvm/test/CodeGen/Generic/negintfplibcall.ll | 37 +++++++++++++++++++
2 files changed, 55 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/Generic/negintfplibcall.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index f5fbc01cd95e96..a4fad1e2eb1a16 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2205,7 +2205,24 @@ void SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node,
Results.push_back(Tmp.first);
Results.push_back(Tmp.second);
} else {
- SDValue Tmp = ExpandLibCall(LC, Node, false).first;
+ bool isSignedArgument = false;
+ switch (LC) {
+ case RTLIB::LDEXP_F32:
+ case RTLIB::LDEXP_F64:
+ case RTLIB::LDEXP_F80:
+ case RTLIB::LDEXP_F128:
+ case RTLIB::LDEXP_PPCF128:
+ isSignedArgument = true;
+ break;
+ case RTLIB::FREXP_F32:
+ case RTLIB::FREXP_F64:
+ case RTLIB::FREXP_F80:
+ case RTLIB::FREXP_F128:
+ case RTLIB::FREXP_PPCF128:
+ isSignedArgument = true;
+ break;
+ }
+ SDValue Tmp = ExpandLibCall(LC, Node, isSignedArgument).first;
Results.push_back(Tmp);
}
}
diff --git a/llvm/test/CodeGen/Generic/negintfplibcall.ll b/llvm/test/CodeGen/Generic/negintfplibcall.ll
new file mode 100644
index 00000000000000..efb3442f1b134f
--- /dev/null
+++ b/llvm/test/CodeGen/Generic/negintfplibcall.ll
@@ -0,0 +1,37 @@
+; RUN: llc -O1 -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s
+; REQUIRES: powerpc-registered-target
+
+; Test that a negative parameter smaller than 64 bits (e.g., int)
+; is correctly implemented with sign-extension when passed to
+; a floating point libcall.
+
+define double @ldexp_test(ptr %a, ptr %b) {
+; CHECK-LABEL: ldexp_test: # @ldexp_test
+; CHECK: # %bb.0:
+; CHECK: lfd 1, 0(3)
+; CHECK-NEXT: lwa 4, 0(4)
+; CHECK-NEXT: bl ldexp
+; CHECK-NEXT: nop
+ %base = load double, ptr %a
+ %exp = load i32, ptr %b
+ %call = call double @llvm.ldexp.f64.i32(double %base, i32 signext %exp)
+ ret double %call
+}
+
+define i64 @frexp_test(ptr %a) {
+; CHECK-LABEL: frexp_test: # @frexp_test
+; CHECK: # %bb.0:
+; CHECK: bl frexp
+; CHECK-NEXT: nop
+; CHECK-NEXT: lwa 3, 124(1)
+; CHECK-NEXT: addi 1, 1, 128
+; CHECK-NEXT: ld 0, 16(1)
+; CHECK-NEXT: mtlr 0
+; CHECK-NEXT: blr
+
+ %input = load double, ptr %a
+ %call = call { double, i32 } @llvm.frexp.f64.i32(double %input)
+ %exp_result = extractvalue { double, i32 } %call, 1
+ %exp_extended = sext i32 %exp_result to i64
+ ret i64 %exp_extended
+}
More information about the llvm-commits
mailing list