Skip to content

Conversation

@arsenm
Copy link
Contributor

@arsenm arsenm commented Nov 10, 2025

This defends against regressions in future patches. This excludes
the target intrinsic case for now; I'm worried introducing an intermediate
AssertNoFPClass is likely to break combines.

Copy link
Contributor Author

arsenm commented Nov 10, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@arsenm arsenm added floating-point Floating-point math llvm:SelectionDAG SelectionDAGISel as well labels Nov 10, 2025 — with Graphite App
@arsenm arsenm marked this pull request as ready for review November 10, 2025 05:06
@llvmbot
Copy link
Member

llvmbot commented Nov 10, 2025

@llvm/pr-subscribers-backend-amdgpu

@llvm/pr-subscribers-llvm-selectiondag

Author: Matt Arsenault (arsenm)

Changes

This defends against regressions in future patches. This excludes
the target intrinsic case for now; I'm worried introducing an intermediate
AssertNoFPClass is likely to break combines.


Full diff: https://github.com/llvm/llvm-project/pull/167264.diff

3 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+17)
  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h (+4)
  • (modified) llvm/test/CodeGen/AMDGPU/nofpclass-call.ll (+4-12)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 88b0809b767b5..6a9022dff41ad 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4638,6 +4638,12 @@ static std::optional<ConstantRange> getRange(const Instruction &I) {
   return std::nullopt;
 }
 
+static FPClassTest getNoFPClass(const Instruction &I) {
+  if (const auto *CB = dyn_cast<CallBase>(&I))
+    return CB->getRetNoFPClass();
+  return fcNone;
+}
+
 void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
   if (I.isAtomic())
     return visitAtomicLoad(I);
@@ -9132,6 +9138,7 @@ void SelectionDAGBuilder::LowerCallTo(const CallBase &CB, SDValue Callee,
 
   if (Result.first.getNode()) {
     Result.first = lowerRangeToAssertZExt(DAG, CB, Result.first);
+    Result.first = lowerNoFPClassToAssertNoFPClass(DAG, CB, Result.first);
     setValue(&CB, Result.first);
   }
 
@@ -10718,6 +10725,16 @@ SDValue SelectionDAGBuilder::lowerRangeToAssertZExt(SelectionDAG &DAG,
   return DAG.getMergeValues(Ops, SL);
 }
 
+SDValue SelectionDAGBuilder::lowerNoFPClassToAssertNoFPClass(
+    SelectionDAG &DAG, const Instruction &I, SDValue Op) {
+  FPClassTest Classes = getNoFPClass(I);
+  if (Classes == fcNone)
+    return Op;
+
+  return DAG.getNode(ISD::AssertNoFPClass, SDLoc(Op), Op.getValueType(), Op,
+                     DAG.getTargetConstant(Classes, SDLoc(), MVT::i32));
+}
+
 /// Populate a CallLowerinInfo (into \p CLI) based on the properties of
 /// the call being lowered.
 ///
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index ed63bee58c957..13e2daa783147 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -429,6 +429,10 @@ class SelectionDAGBuilder {
   SDValue lowerRangeToAssertZExt(SelectionDAG &DAG, const Instruction &I,
                                  SDValue Op);
 
+  // Lower nofpclass attributes to AssertNoFPClass
+  SDValue lowerNoFPClassToAssertNoFPClass(SelectionDAG &DAG,
+                                          const Instruction &I, SDValue Op);
+
   void populateCallLoweringInfo(TargetLowering::CallLoweringInfo &CLI,
                                 const CallBase *Call, unsigned ArgIdx,
                                 unsigned NumArgs, SDValue Callee,
diff --git a/llvm/test/CodeGen/AMDGPU/nofpclass-call.ll b/llvm/test/CodeGen/AMDGPU/nofpclass-call.ll
index 1861f02ec8b1c..5f303cc2a1eef 100644
--- a/llvm/test/CodeGen/AMDGPU/nofpclass-call.ll
+++ b/llvm/test/CodeGen/AMDGPU/nofpclass-call.ll
@@ -35,9 +35,7 @@ define float @call_nofpclass_funcs_f32(ptr addrspace(1) %ptr) {
 ; CHECK-NEXT:    v_mov_b32_e32 v3, v0
 ; CHECK-NEXT:    v_mov_b32_e32 v0, v2
 ; CHECK-NEXT:    s_swappc_b64 s[30:31], s[16:17]
-; CHECK-NEXT:    v_max_f32_e32 v1, v3, v3
-; CHECK-NEXT:    v_max_f32_e32 v0, v0, v0
-; CHECK-NEXT:    v_min_f32_e32 v0, v1, v0
+; CHECK-NEXT:    v_min_f32_e32 v0, v3, v0
 ; CHECK-NEXT:    v_readlane_b32 s31, v4, 1
 ; CHECK-NEXT:    v_readlane_b32 s30, v4, 0
 ; CHECK-NEXT:    s_mov_b32 s32, s33
@@ -87,12 +85,8 @@ define <2 x float> @call_nofpclass_funcs_v2f32(ptr addrspace(1) %ptr) {
 ; CHECK-NEXT:    v_mov_b32_e32 v0, v3
 ; CHECK-NEXT:    v_mov_b32_e32 v1, v2
 ; CHECK-NEXT:    s_swappc_b64 s[30:31], s[16:17]
-; CHECK-NEXT:    v_max_f32_e32 v2, v4, v4
-; CHECK-NEXT:    v_max_f32_e32 v0, v0, v0
-; CHECK-NEXT:    v_min_f32_e32 v0, v2, v0
-; CHECK-NEXT:    v_max_f32_e32 v2, v5, v5
-; CHECK-NEXT:    v_max_f32_e32 v1, v1, v1
-; CHECK-NEXT:    v_min_f32_e32 v1, v2, v1
+; CHECK-NEXT:    v_min_f32_e32 v0, v4, v0
+; CHECK-NEXT:    v_min_f32_e32 v1, v5, v1
 ; CHECK-NEXT:    v_readlane_b32 s31, v6, 1
 ; CHECK-NEXT:    v_readlane_b32 s30, v6, 0
 ; CHECK-NEXT:    s_mov_b32 s32, s33
@@ -142,12 +136,10 @@ define double @call_nofpclass_funcs_f64(ptr addrspace(1) %ptr) {
 ; CHECK-NEXT:    v_mov_b32_e32 v0, v5
 ; CHECK-NEXT:    v_mov_b32_e32 v1, v4
 ; CHECK-NEXT:    s_swappc_b64 s[30:31], s[16:17]
-; CHECK-NEXT:    v_max_f64 v[2:3], v[2:3], v[2:3]
-; CHECK-NEXT:    v_max_f64 v[0:1], v[0:1], v[0:1]
+; CHECK-NEXT:    v_min_f64 v[0:1], v[2:3], v[0:1]
 ; CHECK-NEXT:    v_readlane_b32 s31, v6, 1
 ; CHECK-NEXT:    v_readlane_b32 s30, v6, 0
 ; CHECK-NEXT:    s_mov_b32 s32, s33
-; CHECK-NEXT:    v_min_f64 v[0:1], v[2:3], v[0:1]
 ; CHECK-NEXT:    s_xor_saveexec_b64 s[4:5], -1
 ; CHECK-NEXT:    buffer_load_dword v6, off, s[0:3], s33 ; 4-byte Folded Reload
 ; CHECK-NEXT:    s_mov_b64 exec, s[4:5]

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG

Base automatically changed from users/arsenm/amdgpu/add-baseline-test-nofpclass-attr-call to main November 10, 2025 16:04
This defends against regressions in future patches. This excludes
the target intrinsic case for now; I'm worried introducing an intermediate
AssertNoFPClass is likely to break combines.
@arsenm arsenm force-pushed the users/arsenm/dag/add-assert-nofpclass-from-call-returns branch from 669fbce to b86a3c5 Compare November 10, 2025 16:11
@arsenm arsenm enabled auto-merge (squash) November 10, 2025 16:12
@arsenm arsenm merged commit b4f1994 into main Nov 10, 2025
9 of 10 checks passed
@arsenm arsenm deleted the users/arsenm/dag/add-assert-nofpclass-from-call-returns branch November 10, 2025 16:42
@mikaelholmen
Copy link
Collaborator

Hi @arsenm,

The following starts crashing with this patch:
clang -O0 -ffast-math bbi-112647.c
Result:

clang-22: ../include/llvm/CodeGen/SelectionDAGNodes.h:1263: llvm::SDValue::SDValue(SDNode *, unsigned int): Assertion `(!Node || !ResNo || ResNo < Node->getNumValues()) && "Invalid result number for the given node!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /repo/uabelho/main-github/llvm/build-all/bin/clang-22 -cc1 -triple x86_64-unknown-linux-gnu -O0 -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name bbi-112647.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -menable-no-infs -menable-no-nans -fapprox-func -funsafe-math-optimizations -fno-signed-zeros -mreassociate -freciprocal-math -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -complex-range=basic -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/repo/uabelho/main-github/llvm -fcoverage-compilation-dir=/repo/uabelho/main-github/llvm -resource-dir /repo/uabelho/main-github/llvm/build-all/lib/clang/22 -internal-isystem /repo/uabelho/main-github/llvm/build-all/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fmessage-length=111 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -faddrsig -fdwarf2-cfi-asm -o /tmp/bbi-112647-476309.o -x c bbi-112647.c
1.	<eof> parser at end of file
2.	Code generation
3.	Running pass 'Function Pass Manager' on module 'bbi-112647.c'.
4.	Running pass 'X86 DAG->DAG Instruction Selection' on function '@f747'
 #0 0x000055f6e5224686 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x917c686)
 #1 0x000055f6e5221dd5 llvm::sys::RunSignalHandlers() (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x9179dd5)
 #2 0x000055f6e5225499 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007f284e2e7990 __restore_rt (/lib64/libpthread.so.0+0x12990)
 #4 0x00007f284bc8752f raise (/lib64/libc.so.6+0x4e52f)
 #5 0x00007f284bc5ae65 abort (/lib64/libc.so.6+0x21e65)
 #6 0x00007f284bc5ad39 _nl_load_domain.cold.0 (/lib64/libc.so.6+0x21d39)
 #7 0x00007f284bc7fe86 (/lib64/libc.so.6+0x46e86)
 #8 0x000055f6e6cfd3f0 llvm::SelectionDAGBuilder::visitExtractValue(llvm::ExtractValueInst const&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0xac553f0)
 #9 0x000055f6e6ceb211 llvm::SelectionDAGBuilder::visit(llvm::Instruction const&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0xac43211)
#10 0x000055f6e6dbd3f4 llvm::SelectionDAGISel::SelectBasicBlock(llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void, true, llvm::BasicBlock>, false, true>, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void, true, llvm::BasicBlock>, false, true>, bool&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0xad153f4)
#11 0x000055f6e6dbc76d llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0xad1476d)
#12 0x000055f6e6db9bb1 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0xad11bb1)
#13 0x000055f6e6db7449 llvm::SelectionDAGISelLegacy::runOnMachineFunction(llvm::MachineFunction&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0xad0f449)
#14 0x000055f6e45f8677 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x8550677)
#15 0x000055f6e4b99efc llvm::FPPassManager::runOnFunction(llvm::Function&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x8af1efc)
#16 0x000055f6e4ba2142 llvm::FPPassManager::runOnModule(llvm::Module&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x8afa142)
#17 0x000055f6e4b9a9c8 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x8af29c8)
#18 0x000055f6e59ff927 clang::emitBackendOutput(clang::CompilerInstance&, clang::CodeGenOptions&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x9957927)
#19 0x000055f6e5a16434 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x996e434)
#20 0x000055f6e75352a9 clang::ParseAST(clang::Sema&, bool, bool) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0xb48d2a9)
#21 0x000055f6e5f5b954 clang::FrontendAction::Execute() (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x9eb3954)
#22 0x000055f6e5ebf5cd clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x9e175cd)
#23 0x000055f6e6070ce4 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x9fc8ce4)
#24 0x000055f6e250af88 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x6462f88)
#25 0x000055f6e2507083 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) driver.cpp:0:0
#26 0x000055f6e2506036 clang_main(int, char**, llvm::ToolContext const&) (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x645e036)
#27 0x000055f6e2516e36 main (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x646ee36)
#28 0x00007f284bc737e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#29 0x000055f6e2504a2e _start (/repo/uabelho/main-github/llvm/build-all/bin/clang-22+0x645ca2e)
clang: error: unable to execute command: Aborted (core dumped)
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 22.0.0git
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /repo/uabelho/main-github/llvm/build-all/bin
Build config: +assertions

bbi-112647.c.gz

@arsenm
Copy link
Contributor Author

arsenm commented Nov 12, 2025

Reduced:

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

define nofpclass(nan inf) { double, double } @f747() {
entry:
  %call.i.i = call { double, double } @f747()
  ret { double, double } %call.i.i
}

@arsenm
Copy link
Contributor Author

arsenm commented Nov 12, 2025

Fixed by #167725

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:AMDGPU floating-point Floating-point math llvm:SelectionDAG SelectionDAGISel as well

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants