[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