[llvm] DAG: Gracefully diagnose missing fp-compare libcall when softening (PR #228416)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 05:29:06 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-selectiondag
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
Avoid fatal errors, and legalize to poison with a proper context
error.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply@<!-- -->anthropic.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/228416.diff
4 Files Affected:
- (modified) llvm/include/llvm/CodeGen/ISDOpcodes.h (+5)
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp (+59-30)
- (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+25-10)
- (added) llvm/test/CodeGen/NVPTX/fp128-compare-no-libcall-error.ll (+23)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 953201a26a3e7..cbc9902968a13 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 0017e35ab371e..7e3a6520e1142 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 1eeab43bd480e..e89be8b69929f 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 0000000000000..e05dc591584e6
--- /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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/228416
More information about the llvm-commits
mailing list