[llvm] DAG: Gracefully diagnose missing fp-compare libcall when softening (PR #228416)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 05:28:05 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/228416
Avoid fatal errors, and legalize to poison with a proper context
error.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
>From cbbd94d47b1c614d2a009d017e91873821ed0a4b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 12 Aug 2026 03:37:35 +0200
Subject: [PATCH] DAG: Gracefully diagnose missing fp-compare libcall when
softening
Avoid fatal errors, and legalize to poison with a proper context
error.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
llvm/include/llvm/CodeGen/ISDOpcodes.h | 5 ++
.../SelectionDAG/SelectionDAGDumper.cpp | 89 ++++++++++++-------
.../CodeGen/SelectionDAG/TargetLowering.cpp | 35 +++++---
.../NVPTX/fp128-compare-no-libcall-error.ll | 23 +++++
4 files changed, 112 insertions(+), 40 deletions(-)
create mode 100644 llvm/test/CodeGen/NVPTX/fp128-compare-no-libcall-error.ll
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 953201a26a3e71..cbc9902968a132 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -18,6 +18,8 @@
namespace llvm {
+class StringRef;
+
/// ISD namespace - This namespace contains an enum which represents all of the
/// SelectionDAG node types and value types.
///
@@ -1893,6 +1895,9 @@ inline unsigned getUnorderedFlavor(CondCode Cond) {
/// SetCC operation.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type);
+/// Return the name of the given condition code, e.g. "setoeq".
+LLVM_ABI StringRef getCondCodeName(CondCode Operation);
+
inline bool isExtOpcode(unsigned Opcode) {
return Opcode == ISD::ANY_EXTEND || Opcode == ISD::ZERO_EXTEND ||
Opcode == ISD::SIGN_EXTEND;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 0017e35ab371e3..7e3a6520e11427 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -59,6 +59,64 @@ static cl::opt<bool>
PrintSDNodeAddrs("print-sdnode-addrs", cl::Hidden,
cl::desc("Print addresses of SDNodes when dumping"));
+StringRef ISD::getCondCodeName(ISD::CondCode Operation) {
+ switch (Operation) {
+ default:
+ llvm_unreachable("Unknown setcc condition!");
+ case ISD::SETOEQ:
+ return "setoeq";
+ case ISD::SETOGT:
+ return "setogt";
+ case ISD::SETOGE:
+ return "setoge";
+ case ISD::SETOLT:
+ return "setolt";
+ case ISD::SETOLE:
+ return "setole";
+ case ISD::SETONE:
+ return "setone";
+
+ case ISD::SETO:
+ return "seto";
+ case ISD::SETUO:
+ return "setuo";
+ case ISD::SETUEQ:
+ return "setueq";
+ case ISD::SETUGT:
+ return "setugt";
+ case ISD::SETUGE:
+ return "setuge";
+ case ISD::SETULT:
+ return "setult";
+ case ISD::SETULE:
+ return "setule";
+ case ISD::SETUNE:
+ return "setune";
+
+ case ISD::SETEQ:
+ return "seteq";
+ case ISD::SETGT:
+ return "setgt";
+ case ISD::SETGE:
+ return "setge";
+ case ISD::SETLT:
+ return "setlt";
+ case ISD::SETLE:
+ return "setle";
+ case ISD::SETNE:
+ return "setne";
+
+ case ISD::SETTRUE:
+ return "settrue";
+ case ISD::SETTRUE2:
+ return "settrue2";
+ case ISD::SETFALSE:
+ return "setfalse";
+ case ISD::SETFALSE2:
+ return "setfalse2";
+ }
+}
+
std::string SDNode::getOperationName(const SelectionDAG *G) const {
switch (getOpcode()) {
default:
@@ -544,36 +602,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
// clang-format on
case ISD::CONDCODE:
- switch (cast<CondCodeSDNode>(this)->get()) {
- default: llvm_unreachable("Unknown setcc condition!");
- case ISD::SETOEQ: return "setoeq";
- case ISD::SETOGT: return "setogt";
- case ISD::SETOGE: return "setoge";
- case ISD::SETOLT: return "setolt";
- case ISD::SETOLE: return "setole";
- case ISD::SETONE: return "setone";
-
- case ISD::SETO: return "seto";
- case ISD::SETUO: return "setuo";
- case ISD::SETUEQ: return "setueq";
- case ISD::SETUGT: return "setugt";
- case ISD::SETUGE: return "setuge";
- case ISD::SETULT: return "setult";
- case ISD::SETULE: return "setule";
- case ISD::SETUNE: return "setune";
-
- case ISD::SETEQ: return "seteq";
- case ISD::SETGT: return "setgt";
- case ISD::SETGE: return "setge";
- case ISD::SETLT: return "setlt";
- case ISD::SETLE: return "setle";
- case ISD::SETNE: return "setne";
-
- case ISD::SETTRUE: return "settrue";
- case ISD::SETTRUE2: return "settrue2";
- case ISD::SETFALSE: return "setfalse";
- case ISD::SETFALSE2: return "setfalse2";
- }
+ return ISD::getCondCodeName(cast<CondCodeSDNode>(this)->get()).str();
case ISD::VECREDUCE_FADD: return "vecreduce_fadd";
case ISD::VECREDUCE_SEQ_FADD: return "vecreduce_seq_fadd";
case ISD::VECREDUCE_FMUL: return "vecreduce_fmul";
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 1eeab43bd480e1..e89be8b69929f8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -412,6 +412,7 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
&& "Unsupported setcc type!");
// Expand into one or more soft-fp libcall(s).
+ ISD::CondCode OrigCCCode = CCCode;
RTLIB::Libcall LC1 = RTLIB::UNKNOWN_LIBCALL, LC2 = RTLIB::UNKNOWN_LIBCALL;
ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID;
bool ShouldInvertCC = false;
@@ -525,15 +526,28 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
EVT OpsVT[2] = { OldLHS.getValueType(),
OldRHS.getValueType() };
CallOptions.setTypeListBeforeSoften(OpsVT, RetVT);
- auto Call = makeLibCall(DAG, LC1, RetVT, Ops, CallOptions, dl, Chain);
- NewLHS = Call.first;
- NewRHS = DAG.getConstant(0, dl, RetVT);
- if (DAG.getLibcalls().getLibcallImpl(LC1) == RTLIB::Unsupported) {
- reportFatalUsageError(
- "no libcall available to soften floating-point compare");
+ auto ReportNoLibcall = [&]() {
+ DAG.getContext()->emitError(
+ Twine("no libcall available to soften floating-point ") +
+ ISD::getCondCodeName(OrigCCCode) + " compare with type " +
+ VT.getEVTString());
+ NewLHS = DAG.getPOISON(RetVT);
+ NewRHS = DAG.getConstant(0, dl, RetVT);
+ CCCode = ISD::SETNE;
+ };
+
+ // Check availability before makeLibCall, which fatally errors otherwise.
+ RTLIB::LibcallImpl LC1Impl = DAG.getLibcalls().getLibcallImpl(LC1);
+ if (LC1Impl == RTLIB::Unsupported) {
+ ReportNoLibcall();
+ return;
}
+ auto Call = makeLibCall(DAG, LC1Impl, RetVT, Ops, CallOptions, dl, Chain);
+ NewLHS = Call.first;
+ NewRHS = DAG.getConstant(0, dl, RetVT);
+
CCCode = CC1;
if (ShouldInvertCC) {
assert(RetVT.isInteger());
@@ -544,9 +558,10 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
// Update Chain.
Chain = Call.second;
} else {
- if (DAG.getLibcalls().getLibcallImpl(LC2) == RTLIB::Unsupported) {
- reportFatalUsageError(
- "no libcall available to soften floating-point compare");
+ RTLIB::LibcallImpl LC2Impl = DAG.getLibcalls().getLibcallImpl(LC2);
+ if (LC2Impl == RTLIB::Unsupported) {
+ ReportNoLibcall();
+ return;
}
assert(CCCode == (ShouldInvertCC ? ISD::SETEQ : ISD::SETNE) &&
@@ -560,7 +575,7 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
}
SDValue Tmp = DAG.getSetCC(dl, SetCCVT, NewLHS, NewRHS, CCCode);
- auto Call2 = makeLibCall(DAG, LC2, RetVT, Ops, CallOptions, dl, Chain);
+ auto Call2 = makeLibCall(DAG, LC2Impl, RetVT, Ops, CallOptions, dl, Chain);
CCCode = CC2;
if (ShouldInvertCC)
CCCode = getSetCCInverse(CCCode, RetVT);
diff --git a/llvm/test/CodeGen/NVPTX/fp128-compare-no-libcall-error.ll b/llvm/test/CodeGen/NVPTX/fp128-compare-no-libcall-error.ll
new file mode 100644
index 00000000000000..e05dc591584e6c
--- /dev/null
+++ b/llvm/test/CodeGen/NVPTX/fp128-compare-no-libcall-error.ll
@@ -0,0 +1,23 @@
+; RUN: not llc -mtriple=nvptx64 -filetype=null %s 2>&1 | FileCheck %s
+
+; NVPTX has no fp128 compare libcall, so this should diagnose a missing libcall
+; rather than crash. The reported compare kind is the original one, not the
+; inverted or rewritten form used to select the libcall.
+
+; CHECK: error: no libcall available to soften floating-point setoeq compare with type f128
+define i1 @test_fcmp_oeq_f128(fp128 %a, fp128 %b) {
+ %r = fcmp oeq fp128 %a, %b
+ ret i1 %r
+}
+
+; CHECK: error: no libcall available to soften floating-point setult compare with type f128
+define i1 @test_fcmp_ult_f128(fp128 %a, fp128 %b) {
+ %r = fcmp ult fp128 %a, %b
+ ret i1 %r
+}
+
+; CHECK: error: no libcall available to soften floating-point setone compare with type f128
+define i1 @test_fcmp_one_f128(fp128 %a, fp128 %b) {
+ %r = fcmp one fp128 %a, %b
+ ret i1 %r
+}
More information about the llvm-commits
mailing list