[llvm] DAG: Gracefully diagnose missing FMA and ppcf128 expansion libcalls (PR #228094)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 03:30:11 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/228094
>From 1ce5fb0a739cf9b362d8ffa5d35ad7dd541708cd Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 11 Aug 2026 21:00:33 +0200
Subject: [PATCH 1/2] DAG: Gracefully diagnose missing FMA and ppcf128
expansion libcalls
Previously this would hit a fatal error. Legalize to poison and report
a proper context error.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
.../SelectionDAG/LegalizeFloatTypes.cpp | 73 +++++++++++++----
llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 1 +
.../CodeGen/NVPTX/f128-no-libcall-error.ll | 12 +++
.../X86/ppcf128-expand-no-libcall-error.ll | 82 +++++++++++++++++++
4 files changed, 154 insertions(+), 14 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index b7efd80d93fd4..bf9efd027e491 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -521,9 +521,12 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FMA(SDNode *N) {
N->getOperand(1 + Offset).getValueType(),
N->getOperand(2 + Offset).getValueType() };
CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
+ RTLIB::Libcall LC = RTLIB::getFMA(N->getValueType(0));
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+ if (LCImpl == RTLIB::Unsupported)
+ return SoftenFloatRes_NoLibcall(N, NVT);
std::pair<SDValue, SDValue> Tmp =
- TLI.makeLibCall(DAG, RTLIB::getFMA(N->getValueType(0)), NVT, Ops,
- CallOptions, SDLoc(N), Chain);
+ TLI.makeLibCall(DAG, LCImpl, NVT, Ops, CallOptions, SDLoc(N), Chain);
if (IsStrict)
ReplaceValueWith(SDValue(N, 1), Tmp.second);
return Tmp.first;
@@ -1646,16 +1649,29 @@ void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo,
Hi = DAG.getConstantFP(APFloat(Sem, C.extractBits(64, 0)), dl, NVT);
}
+// Diagnose a missing libcall and produce a poison expanded pair.
+void DAGTypeLegalizer::ExpandFloatRes_NoLibcall(SDNode *N, SDValue &Lo,
+ SDValue &Hi) {
+ DAG.getContext()->emitError(Twine("no libcall available for ") +
+ N->getOperationName(&DAG));
+ if (N->isStrictFPOpcode())
+ ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
+ EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
+ Lo = Hi = DAG.getPOISON(NVT);
+}
+
void DAGTypeLegalizer::ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC,
SDValue &Lo, SDValue &Hi) {
bool IsStrict = N->isStrictFPOpcode();
unsigned Offset = IsStrict ? 1 : 0;
SDValue Op = N->getOperand(0 + Offset);
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+ if (LCImpl == RTLIB::Unsupported)
+ return ExpandFloatRes_NoLibcall(N, Lo, Hi);
TargetLowering::MakeLibCallOptions CallOptions;
- std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
- Op, CallOptions, SDLoc(N),
- Chain);
+ std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(
+ DAG, LCImpl, N->getValueType(0), Op, CallOptions, SDLoc(N), Chain);
if (IsStrict)
ReplaceValueWith(SDValue(N, 1), Tmp.second);
GetPairElements(Tmp.first, Lo, Hi);
@@ -1667,10 +1683,12 @@ void DAGTypeLegalizer::ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC,
unsigned Offset = IsStrict ? 1 : 0;
SDValue Ops[] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset) };
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+ if (LCImpl == RTLIB::Unsupported)
+ return ExpandFloatRes_NoLibcall(N, Lo, Hi);
TargetLowering::MakeLibCallOptions CallOptions;
- std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
- Ops, CallOptions, SDLoc(N),
- Chain);
+ std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(
+ DAG, LCImpl, N->getValueType(0), Ops, CallOptions, SDLoc(N), Chain);
if (IsStrict)
ReplaceValueWith(SDValue(N, 1), Tmp.second);
GetPairElements(Tmp.first, Lo, Hi);
@@ -1694,7 +1712,15 @@ void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
assert(!N->isStrictFPOpcode() && "strictfp not implemented");
SmallVector<SDValue> Results;
- TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo);
+ if (!TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo)) {
+ DAG.getContext()->emitError(Twine("no libcall available for ") +
+ N->getOperationName(&DAG));
+ EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
+ SDValue Poison = DAG.getPOISON(NVT);
+ for (unsigned ResNo = 0, E = N->getNumValues(); ResNo != E; ++ResNo)
+ SetExpandedFloat(SDValue(N, ResNo), Poison, Poison);
+ return;
+ }
for (auto [ResNo, Res] : enumerate(Results)) {
SDValue Lo, Hi;
GetPairElements(Res, Lo, Hi);
@@ -1841,10 +1867,13 @@ void DAGTypeLegalizer::ExpandFloatRes_FMA(SDNode *N, SDValue &Lo,
SDValue Ops[3] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset),
N->getOperand(2 + Offset) };
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
+ RTLIB::Libcall LC = RTLIB::getFMA(N->getValueType(0));
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+ if (LCImpl == RTLIB::Unsupported)
+ return ExpandFloatRes_NoLibcall(N, Lo, Hi);
TargetLowering::MakeLibCallOptions CallOptions;
- std::pair<SDValue, SDValue> Tmp =
- TLI.makeLibCall(DAG, RTLIB::getFMA(N->getValueType(0)),
- N->getValueType(0), Ops, CallOptions, SDLoc(N), Chain);
+ std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(
+ DAG, LCImpl, N->getValueType(0), Ops, CallOptions, SDLoc(N), Chain);
if (IsStrict)
ReplaceValueWith(SDValue(N, 1), Tmp.second);
GetPairElements(Tmp.first, Lo, Hi);
@@ -2066,10 +2095,14 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
}
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+ if (LCImpl == RTLIB::Unsupported)
+ return ExpandFloatRes_NoLibcall(N, Lo, Hi);
+
TargetLowering::MakeLibCallOptions CallOptions;
CallOptions.setIsSigned(true);
std::pair<SDValue, SDValue> Tmp =
- TLI.makeLibCall(DAG, LC, VT, Src, CallOptions, dl, Chain);
+ TLI.makeLibCall(DAG, LCImpl, VT, Src, CallOptions, dl, Chain);
if (Strict)
Chain = Tmp.second;
GetPairElements(Tmp.first, Lo, Hi);
@@ -2301,9 +2334,21 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_XINT(SDNode *N) {
RTLIB::Libcall LC = findFPToIntLibcall(Op.getValueType(), RVT, NVT, Signed);
assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
"Unsupported FP_TO_XINT!");
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+ if (LCImpl == RTLIB::Unsupported) {
+ DAG.getContext()->emitError(Twine("no libcall available for ") +
+ N->getOperationName(&DAG));
+ SDValue Poison = DAG.getPOISON(RVT);
+ if (IsStrict) {
+ ReplaceValueWith(SDValue(N, 1), Chain);
+ ReplaceValueWith(SDValue(N, 0), Poison);
+ return SDValue();
+ }
+ return Poison;
+ }
TargetLowering::MakeLibCallOptions CallOptions;
std::pair<SDValue, SDValue> Tmp =
- TLI.makeLibCall(DAG, LC, NVT, Op, CallOptions, dl, Chain);
+ TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, dl, Chain);
if (!IsStrict)
return Tmp.first;
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 187f7ecb806b2..7dfc4c1330eca 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -670,6 +670,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
// Float Result Expansion.
void ExpandFloatResult(SDNode *N, unsigned ResNo);
void ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, SDValue &Hi);
+ void ExpandFloatRes_NoLibcall(SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC,
SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC,
diff --git a/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll b/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll
index d3286a0bf0391..c68fec089d51a 100644
--- a/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll
+++ b/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll
@@ -16,6 +16,18 @@ define fp128 @test_maximum(fp128 %x, fp128 %y) nounwind {
ret fp128 %r
}
+; CHECK: error: no libcall available for fma
+define fp128 @test_fma(fp128 %x, fp128 %y, fp128 %z) nounwind {
+ %r = call fp128 @llvm.fma.f128(fp128 %x, fp128 %y, fp128 %z)
+ ret fp128 %r
+}
+
+; CHECK: error: no libcall available for strict_fma
+define fp128 @test_strict_fma(fp128 %x, fp128 %y, fp128 %z) nounwind strictfp {
+ %r = call fp128 @llvm.experimental.constrained.fma.f128(fp128 %x, fp128 %y, fp128 %z, metadata !"round.tonearest", metadata !"fpexcept.strict")
+ ret fp128 %r
+}
+
; CHECK: error: no libcall available for ffrexp
define { fp128, i32 } @test_frexp(fp128 %x) nounwind {
%r = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %x)
diff --git a/llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll b/llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll
new file mode 100644
index 0000000000000..672b94b59e254
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll
@@ -0,0 +1,82 @@
+; RUN: not llc -mtriple=x86_64-unknown-unknown -filetype=null %s 2>&1 | FileCheck %s
+
+; x86 expands ppc_fp128 but has no ppc_fp128 runtime library, so these
+; operations should diagnose a missing libcall rather than crash.
+
+; CHECK: error: no libcall available for fsqrt
+define ppc_fp128 @test_sqrt(ppc_fp128 %x) nounwind {
+ %r = call ppc_fp128 @llvm.sqrt.ppcf128(ppc_fp128 %x)
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for fpow
+define ppc_fp128 @test_pow(ppc_fp128 %x, ppc_fp128 %y) nounwind {
+ %r = call ppc_fp128 @llvm.pow.ppcf128(ppc_fp128 %x, ppc_fp128 %y)
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for fma
+define ppc_fp128 @test_fma(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z) nounwind {
+ %r = call ppc_fp128 @llvm.fma.ppcf128(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z)
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for frem
+define ppc_fp128 @test_frem(ppc_fp128 %x, ppc_fp128 %y) nounwind {
+ %r = frem ppc_fp128 %x, %y
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for sint_to_fp
+define ppc_fp128 @test_sitofp(i64 %x) nounwind {
+ %r = sitofp i64 %x to ppc_fp128
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for fp_to_sint
+define i64 @test_fptosi(ppc_fp128 %x) nounwind {
+ %r = fptosi ppc_fp128 %x to i64
+ ret i64 %r
+}
+
+; CHECK: error: no libcall available for fsincos
+define { ppc_fp128, ppc_fp128 } @test_sincos(ppc_fp128 %x) nounwind {
+ %r = call { ppc_fp128, ppc_fp128 } @llvm.sincos.ppcf128(ppc_fp128 %x)
+ ret { ppc_fp128, ppc_fp128 } %r
+}
+
+; CHECK: error: no libcall available for fmodf
+define { ppc_fp128, ppc_fp128 } @test_modf(ppc_fp128 %x) nounwind {
+ %r = call { ppc_fp128, ppc_fp128 } @llvm.modf.ppcf128(ppc_fp128 %x)
+ ret { ppc_fp128, ppc_fp128 } %r
+}
+
+; CHECK: error: no libcall available for strict_fsqrt
+define ppc_fp128 @test_strict_sqrt(ppc_fp128 %x) nounwind strictfp {
+ %r = call ppc_fp128 @llvm.experimental.constrained.sqrt.ppcf128(ppc_fp128 %x, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for strict_fadd
+define ppc_fp128 @test_strict_fadd(ppc_fp128 %x, ppc_fp128 %y) nounwind strictfp {
+ %r = call ppc_fp128 @llvm.experimental.constrained.fadd.ppcf128(ppc_fp128 %x, ppc_fp128 %y, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for strict_fma
+define ppc_fp128 @test_strict_fma(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z) nounwind strictfp {
+ %r = call ppc_fp128 @llvm.experimental.constrained.fma.ppcf128(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for strict_sint_to_fp
+define ppc_fp128 @test_strict_sitofp(i64 %x) nounwind strictfp {
+ %r = call ppc_fp128 @llvm.experimental.constrained.sitofp.ppcf128.i64(i64 %x, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for strict_fp_to_sint
+define i64 @test_strict_fptosi(ppc_fp128 %x) nounwind strictfp {
+ %r = call i64 @llvm.experimental.constrained.fptosi.i64.ppcf128(ppc_fp128 %x, metadata !"fpexcept.strict")
+ ret i64 %r
+}
>From b951f9a587e5d1941207f5a3e6bd40428e7a64c3 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 2 Oct 2026 11:48:21 +0200
Subject: [PATCH 2/2] Include the type in missing-libcall diagnostics
---
.../SelectionDAG/LegalizeFloatTypes.cpp | 33 +++++++-------
.../CodeGen/NVPTX/f128-no-libcall-error.ll | 14 +++---
.../X86/ppcf128-expand-no-libcall-error.ll | 44 +++++++++++++------
3 files changed, 53 insertions(+), 38 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index bf9efd027e491..8c974e461b80c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -26,6 +26,12 @@ using namespace llvm;
#define DEBUG_TYPE "legalize-types"
+static void reportNoLibcall(SelectionDAG &DAG, SDNode *N, EVT VT) {
+ DAG.getContext()->emitError(Twine("no libcall available for ") +
+ N->getOperationName(&DAG) + " with type " +
+ VT.getEVTString());
+}
+
/// GetFPLibCall - Return the right libcall for the given floating point type.
/// FIXME: This is a local version of RTLIB::getFPLibCall that should be
/// refactored away (see RTLIB::getPOWI for an example).
@@ -194,8 +200,7 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
// No libcall is available to soften this operation. Emit a diagnostic and
// produce a poison result of the softened type \p NVT.
SDValue DAGTypeLegalizer::SoftenFloatRes_NoLibcall(SDNode *N, EVT NVT) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, N->getValueType(0));
if (N->isStrictFPOpcode())
ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
return DAG.getPOISON(NVT);
@@ -715,8 +720,7 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FFREXP(SDNode *N) {
SDLoc DL(N);
if (LCImpl == RTLIB::Unsupported) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, VT0);
SDValue PoisonExp = DAG.getPOISON(VT1);
ReplaceValueWith(SDValue(N, 1), PoisonExp);
return DAG.getMergeValues({DAG.getPOISON(NVT0), PoisonExp}, DL);
@@ -1160,8 +1164,7 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) {
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
if (LCImpl == RTLIB::Unsupported) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, SVT);
SDValue Poison = DAG.getPOISON(RVT);
if (IsStrict) {
ReplaceValueWith(SDValue(N, 1), Chain);
@@ -1247,8 +1250,7 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT(SDNode *N) {
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
if (LCImpl == RTLIB::Unsupported) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, SVT);
SDValue Poison = DAG.getPOISON(RVT);
if (IsStrict) {
ReplaceValueWith(SDValue(N, 1), Chain);
@@ -1419,8 +1421,7 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_Unary(SDNode *N, RTLIB::Libcall LC) {
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
if (LCImpl == RTLIB::Unsupported) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, N->getOperand(0 + Offset).getValueType());
SDValue Poison = DAG.getPOISON(N->getValueType(0));
if (IsStrict) {
ReplaceValueWith(SDValue(N, 1), Chain);
@@ -1652,8 +1653,7 @@ void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo,
// Diagnose a missing libcall and produce a poison expanded pair.
void DAGTypeLegalizer::ExpandFloatRes_NoLibcall(SDNode *N, SDValue &Lo,
SDValue &Hi) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, N->getValueType(0));
if (N->isStrictFPOpcode())
ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
@@ -1713,8 +1713,7 @@ void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
assert(!N->isStrictFPOpcode() && "strictfp not implemented");
SmallVector<SDValue> Results;
if (!TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo)) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, N->getValueType(0));
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
SDValue Poison = DAG.getPOISON(NVT);
for (unsigned ResNo = 0, E = N->getNumValues(); ResNo != E; ++ResNo)
@@ -2336,8 +2335,7 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_XINT(SDNode *N) {
"Unsupported FP_TO_XINT!");
RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
if (LCImpl == RTLIB::Unsupported) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, Op.getValueType());
SDValue Poison = DAG.getPOISON(RVT);
if (IsStrict) {
ReplaceValueWith(SDValue(N, 1), Chain);
@@ -2427,8 +2425,7 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_XRINT_XROUND(SDNode *N,
EVT RVT = N->getValueType(0);
RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
if (LCImpl == RTLIB::Unsupported) {
- DAG.getContext()->emitError(Twine("no libcall available for ") +
- N->getOperationName(&DAG));
+ reportNoLibcall(DAG, N, N->getOperand(0).getValueType());
return DAG.getPOISON(RVT);
}
diff --git a/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll b/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll
index c68fec089d51a..506056536aca5 100644
--- a/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll
+++ b/llvm/test/CodeGen/NVPTX/f128-no-libcall-error.ll
@@ -4,43 +4,43 @@
; available. Make sure they emit a proper diagnostic rather than fatal erroring
; in makeLibCall.
-; CHECK: error: no libcall available for fexp10
+; CHECK: error: no libcall available for fexp10 with type f128
define fp128 @test_exp10(fp128 %x) nounwind {
%r = call fp128 @llvm.exp10.f128(fp128 %x)
ret fp128 %r
}
-; CHECK: error: no libcall available for fmaximum
+; CHECK: error: no libcall available for fmaximum with type f128
define fp128 @test_maximum(fp128 %x, fp128 %y) nounwind {
%r = call fp128 @llvm.maximum.f128(fp128 %x, fp128 %y)
ret fp128 %r
}
-; CHECK: error: no libcall available for fma
+; CHECK: error: no libcall available for fma with type f128
define fp128 @test_fma(fp128 %x, fp128 %y, fp128 %z) nounwind {
%r = call fp128 @llvm.fma.f128(fp128 %x, fp128 %y, fp128 %z)
ret fp128 %r
}
-; CHECK: error: no libcall available for strict_fma
+; CHECK: error: no libcall available for strict_fma with type f128
define fp128 @test_strict_fma(fp128 %x, fp128 %y, fp128 %z) nounwind strictfp {
%r = call fp128 @llvm.experimental.constrained.fma.f128(fp128 %x, fp128 %y, fp128 %z, metadata !"round.tonearest", metadata !"fpexcept.strict")
ret fp128 %r
}
-; CHECK: error: no libcall available for ffrexp
+; CHECK: error: no libcall available for ffrexp with type f128
define { fp128, i32 } @test_frexp(fp128 %x) nounwind {
%r = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %x)
ret { fp128, i32 } %r
}
-; CHECK: error: no libcall available for lrint
+; CHECK: error: no libcall available for lrint with type f128
define i32 @test_lrint(fp128 %x) nounwind {
%r = call i32 @llvm.lrint.i32.f128(fp128 %x)
ret i32 %r
}
-; CHECK: error: no libcall available for strict_fadd
+; CHECK: error: no libcall available for strict_fadd with type f128
define fp128 @test_strict_fadd(fp128 %x, fp128 %y) nounwind strictfp {
%r = call fp128 @llvm.experimental.constrained.fadd.f128(fp128 %x, fp128 %y, metadata !"round.tonearest", metadata !"fpexcept.strict")
ret fp128 %r
diff --git a/llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll b/llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll
index 672b94b59e254..f94b8737692f7 100644
--- a/llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll
+++ b/llvm/test/CodeGen/X86/ppcf128-expand-no-libcall-error.ll
@@ -3,79 +3,97 @@
; x86 expands ppc_fp128 but has no ppc_fp128 runtime library, so these
; operations should diagnose a missing libcall rather than crash.
-; CHECK: error: no libcall available for fsqrt
+; CHECK: error: no libcall available for fsqrt with type ppcf128
define ppc_fp128 @test_sqrt(ppc_fp128 %x) nounwind {
%r = call ppc_fp128 @llvm.sqrt.ppcf128(ppc_fp128 %x)
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for fpow
+; CHECK: error: no libcall available for fpow with type ppcf128
define ppc_fp128 @test_pow(ppc_fp128 %x, ppc_fp128 %y) nounwind {
%r = call ppc_fp128 @llvm.pow.ppcf128(ppc_fp128 %x, ppc_fp128 %y)
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for fma
+; CHECK: error: no libcall available for fma with type ppcf128
define ppc_fp128 @test_fma(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z) nounwind {
%r = call ppc_fp128 @llvm.fma.ppcf128(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z)
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for frem
+; CHECK: error: no libcall available for fldexp with type ppcf128
+define ppc_fp128 @test_ldexp(ppc_fp128 %x, i32 %y) nounwind {
+ %r = call ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 %x, i32 %y)
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for fpowi with type ppcf128
+define ppc_fp128 @test_powi(ppc_fp128 %x, i32 %y) nounwind {
+ %r = call ppc_fp128 @llvm.powi.ppcf128.i32(ppc_fp128 %x, i32 %y)
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for strict_fldexp with type ppcf128
+define ppc_fp128 @test_strict_ldexp(ppc_fp128 %x, i32 %y) nounwind strictfp {
+ %r = call ppc_fp128 @llvm.experimental.constrained.ldexp.ppcf128.i32(ppc_fp128 %x, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret ppc_fp128 %r
+}
+
+; CHECK: error: no libcall available for frem with type ppcf128
define ppc_fp128 @test_frem(ppc_fp128 %x, ppc_fp128 %y) nounwind {
%r = frem ppc_fp128 %x, %y
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for sint_to_fp
+; CHECK: error: no libcall available for sint_to_fp with type ppcf128
define ppc_fp128 @test_sitofp(i64 %x) nounwind {
%r = sitofp i64 %x to ppc_fp128
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for fp_to_sint
+; CHECK: error: no libcall available for fp_to_sint with type ppcf128
define i64 @test_fptosi(ppc_fp128 %x) nounwind {
%r = fptosi ppc_fp128 %x to i64
ret i64 %r
}
-; CHECK: error: no libcall available for fsincos
+; CHECK: error: no libcall available for fsincos with type ppcf128
define { ppc_fp128, ppc_fp128 } @test_sincos(ppc_fp128 %x) nounwind {
%r = call { ppc_fp128, ppc_fp128 } @llvm.sincos.ppcf128(ppc_fp128 %x)
ret { ppc_fp128, ppc_fp128 } %r
}
-; CHECK: error: no libcall available for fmodf
+; CHECK: error: no libcall available for fmodf with type ppcf128
define { ppc_fp128, ppc_fp128 } @test_modf(ppc_fp128 %x) nounwind {
%r = call { ppc_fp128, ppc_fp128 } @llvm.modf.ppcf128(ppc_fp128 %x)
ret { ppc_fp128, ppc_fp128 } %r
}
-; CHECK: error: no libcall available for strict_fsqrt
+; CHECK: error: no libcall available for strict_fsqrt with type ppcf128
define ppc_fp128 @test_strict_sqrt(ppc_fp128 %x) nounwind strictfp {
%r = call ppc_fp128 @llvm.experimental.constrained.sqrt.ppcf128(ppc_fp128 %x, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for strict_fadd
+; CHECK: error: no libcall available for strict_fadd with type ppcf128
define ppc_fp128 @test_strict_fadd(ppc_fp128 %x, ppc_fp128 %y) nounwind strictfp {
%r = call ppc_fp128 @llvm.experimental.constrained.fadd.ppcf128(ppc_fp128 %x, ppc_fp128 %y, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for strict_fma
+; CHECK: error: no libcall available for strict_fma with type ppcf128
define ppc_fp128 @test_strict_fma(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z) nounwind strictfp {
%r = call ppc_fp128 @llvm.experimental.constrained.fma.ppcf128(ppc_fp128 %x, ppc_fp128 %y, ppc_fp128 %z, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for strict_sint_to_fp
+; CHECK: error: no libcall available for strict_sint_to_fp with type ppcf128
define ppc_fp128 @test_strict_sitofp(i64 %x) nounwind strictfp {
%r = call ppc_fp128 @llvm.experimental.constrained.sitofp.ppcf128.i64(i64 %x, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret ppc_fp128 %r
}
-; CHECK: error: no libcall available for strict_fp_to_sint
+; CHECK: error: no libcall available for strict_fp_to_sint with type ppcf128
define i64 @test_strict_fptosi(ppc_fp128 %x) nounwind strictfp {
%r = call i64 @llvm.experimental.constrained.fptosi.i64.ppcf128(ppc_fp128 %x, metadata !"fpexcept.strict")
ret i64 %r
More information about the llvm-commits
mailing list