[llvm] 5c38ca1 - DAG: Gracefully diagnose missing floating-point state libcalls (#228426)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 2 09:45:53 PDT 2026


Author: Matt Arsenault
Date: 2026-10-02T16:45:46Z
New Revision: 5c38ca153312ea29871fcdd89a0a9ec678c9fb72

URL: https://github.com/llvm/llvm-project/commit/5c38ca153312ea29871fcdd89a0a9ec678c9fb72
DIFF: https://github.com/llvm/llvm-project/commit/5c38ca153312ea29871fcdd89a0a9ec678c9fb72.diff

LOG: DAG: Gracefully diagnose missing floating-point state libcalls (#228426)

Previously makeStateFunctionCall would hit a fatal error if the target has no 
fegetenv/fesetenv/fegetmode/fesetmode implementation. Report a proper
context error and emit nothing.

Co-authored-by: Claude Opus 5 <noreply at anthropic.com>

Added: 
    llvm/test/CodeGen/NVPTX/fenv-no-libcall-error.ll

Modified: 
    llvm/include/llvm/CodeGen/SelectionDAG.h
    llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 764858702b732..a345c90ae9c0a 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2757,7 +2757,7 @@ class SelectionDAG {
   }
 
   LLVM_ABI SDValue makeStateFunctionCall(unsigned LibFunc, SDValue Ptr,
-                                         SDValue InChain, const SDLoc &DLoc);
+                                         SDValue InChain, SDNode *Node);
 
   /// Returns the maximum runtime number of elements in VT if known, or 0
   /// otherwise.

diff  --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 15d82359e8682..d8e5e23e21337 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -5350,21 +5350,21 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
     SDValue Ptr = DAG.getAllOnesConstant(dl, PtrTy);
     SDValue Chain = Node->getOperand(0);
     Results.push_back(
-        DAG.makeStateFunctionCall(RTLIB::FESETENV, Ptr, Chain, dl));
+        DAG.makeStateFunctionCall(RTLIB::FESETENV, Ptr, Chain, Node));
     break;
   }
   case ISD::GET_FPENV_MEM: {
     SDValue Chain = Node->getOperand(0);
     SDValue EnvPtr = Node->getOperand(1);
     Results.push_back(
-        DAG.makeStateFunctionCall(RTLIB::FEGETENV, EnvPtr, Chain, dl));
+        DAG.makeStateFunctionCall(RTLIB::FEGETENV, EnvPtr, Chain, Node));
     break;
   }
   case ISD::SET_FPENV_MEM: {
     SDValue Chain = Node->getOperand(0);
     SDValue EnvPtr = Node->getOperand(1);
     Results.push_back(
-        DAG.makeStateFunctionCall(RTLIB::FESETENV, EnvPtr, Chain, dl));
+        DAG.makeStateFunctionCall(RTLIB::FESETENV, EnvPtr, Chain, Node));
     break;
   }
   case ISD::GET_FPMODE: {
@@ -5374,7 +5374,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
     SDValue StackPtr = DAG.CreateStackTemporary(ModeVT);
     int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
     SDValue Chain = DAG.makeStateFunctionCall(RTLIB::FEGETMODE, StackPtr,
-                                              Node->getOperand(0), dl);
+                                              Node->getOperand(0), Node);
     SDValue LdInst = DAG.getLoad(
         ModeVT, dl, Chain, StackPtr,
         MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI));
@@ -5393,7 +5393,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
         Node->getOperand(0), dl, Mode, StackPtr,
         MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI));
     Results.push_back(
-        DAG.makeStateFunctionCall(RTLIB::FESETMODE, StackPtr, StInst, dl));
+        DAG.makeStateFunctionCall(RTLIB::FESETMODE, StackPtr, StInst, Node));
     break;
   }
   case ISD::RESET_FPMODE: {
@@ -5404,7 +5404,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
     EVT PtrTy = TLI.getPointerTy(DL);
     SDValue Mode = DAG.getAllOnesConstant(dl, PtrTy);
     Results.push_back(DAG.makeStateFunctionCall(RTLIB::FESETMODE, Mode,
-                                                Node->getOperand(0), dl));
+                                                Node->getOperand(0), Node));
     break;
   }
   }

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index abc8172fb67b5..48aaeca8e80a8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -15232,24 +15232,28 @@ SDValue SelectionDAG::getPartialReduceMLS(unsigned Opc, const SDLoc &DL,
 /// \param LibFunc Reference to library function (value of RTLIB::Libcall).
 /// \param Ptr Pointer used to save/load state.
 /// \param InChain Ingoing token chain.
+/// \param Node Node being legalized
 /// \returns Outgoing chain token.
 SDValue SelectionDAG::makeStateFunctionCall(unsigned LibFunc, SDValue Ptr,
-                                            SDValue InChain,
-                                            const SDLoc &DLoc) {
+                                            SDValue InChain, SDNode *Node) {
   assert(InChain.getValueType() == MVT::Other && "Expected token chain");
-  TargetLowering::ArgListTy Args;
-  Args.emplace_back(Ptr, Ptr.getValueType().getTypeForEVT(*getContext()));
   RTLIB::LibcallImpl LibcallImpl =
       Libcalls->getLibcallImpl(static_cast<RTLIB::Libcall>(LibFunc));
-  if (LibcallImpl == RTLIB::Unsupported)
-    reportFatalUsageError("emitting call to unsupported libcall");
+  if (LibcallImpl == RTLIB::Unsupported) {
+    getContext()->emitError(Twine("no libcall available for ") +
+                            Node->getOperationName(this));
+    return InChain;
+  }
 
+  TargetLowering::ArgListTy Args;
+  Args.emplace_back(Ptr, Ptr.getValueType().getTypeForEVT(*getContext()));
   SDValue Callee =
       getExternalSymbol(LibcallImpl, TLI->getPointerTy(getDataLayout()));
   TargetLowering::CallLoweringInfo CLI(*this);
-  CLI.setDebugLoc(DLoc).setChain(InChain).setLibCallee(
-      Libcalls->getLibcallImplCallingConv(LibcallImpl),
-      Type::getVoidTy(*getContext()), Callee, std::move(Args));
+  CLI.setDebugLoc(SDLoc(Node))
+      .setChain(InChain)
+      .setLibCallee(Libcalls->getLibcallImplCallingConv(LibcallImpl),
+                    Type::getVoidTy(*getContext()), Callee, std::move(Args));
   return TLI->LowerCallTo(CLI).second;
 }
 

diff  --git a/llvm/test/CodeGen/NVPTX/fenv-no-libcall-error.ll b/llvm/test/CodeGen/NVPTX/fenv-no-libcall-error.ll
new file mode 100644
index 0000000000000..163926b03d56d
--- /dev/null
+++ b/llvm/test/CodeGen/NVPTX/fenv-no-libcall-error.ll
@@ -0,0 +1,41 @@
+; RUN: not llc -mtriple=nvptx64 -filetype=null %s 2>&1 | FileCheck %s
+
+; NVPTX has no fenv library, so these operations have no libcall
+; available. Make sure they emit a diagnostic and do not fatally
+; error.
+
+; CHECK: error: no libcall available for reset_fpenv
+define void @test_reset_fpenv() nounwind {
+  call void @llvm.reset.fpenv()
+  ret void
+}
+
+; CHECK: error: no libcall available for get_fpenv_mem
+define i256 @test_get_fpenv() nounwind {
+  %e = call i256 @llvm.get.fpenv.i256()
+  ret i256 %e
+}
+
+; CHECK: error: no libcall available for set_fpenv_mem
+define void @test_set_fpenv(i256 %e) nounwind {
+  call void @llvm.set.fpenv.i256(i256 %e)
+  ret void
+}
+
+; CHECK: error: no libcall available for get_fpmode
+define i32 @test_get_fpmode() nounwind {
+  %m = call i32 @llvm.get.fpmode.i32()
+  ret i32 %m
+}
+
+; CHECK: error: no libcall available for set_fpmode
+define void @test_set_fpmode(i32 %m) nounwind {
+  call void @llvm.set.fpmode.i32(i32 %m)
+  ret void
+}
+
+; CHECK: error: no libcall available for reset_fpmode
+define void @test_reset_fpmode() nounwind {
+  call void @llvm.reset.fpmode()
+  ret void
+}


        


More information about the llvm-commits mailing list