Skip to content

[SelectionDAG] Fix NaN regression in fma dag-combine. #146592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 1, 2025

Conversation

jyknight
Copy link
Member

@jyknight jyknight commented Jul 1, 2025

After 901e139 (#127770), the DAG combine would transform fma(x, 0.0, 1.0) into 1.0 if -fp-contract=fast was enabled, in addition to when 'x' is marked nnan/ninf.

It's only valid in the latter case, not the former, so delete the extra condition.

After 901e139 (llvm#127770), the DAG
combine would transform `fma(x, 0.0, 1.0)` into `1.0` if
`-fp-contract=fast` was enabled, in addition to when 'x' is marked
nnan/ninf. It's only valid in the latter case, not the former, so
delete the extra condition.
@llvmbot
Copy link
Member

llvmbot commented Jul 1, 2025

@llvm/pr-subscribers-llvm-selectiondag

@llvm/pr-subscribers-backend-x86

Author: James Y Knight (jyknight)

Changes

After 901e139 (#127770), the DAG combine would transform fma(x, 0.0, 1.0) into 1.0 if -fp-contract=fast was enabled, in addition to when 'x' is marked nnan/ninf.

It's only valid in the latter case, not the former, so delete the extra condition.


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+1-2)
  • (modified) llvm/test/CodeGen/X86/dag-combiner-fma-folding.ll (+12)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c43677f8b925c..bfc061b404560 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18087,8 +18087,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitFMA(SDNode *N) {
 
   // FIXME: use fast math flags instead of Options.UnsafeFPMath
   // TODO: Finally migrate away from global TargetOptions.
-  if (Options.AllowFPOpFusion == FPOpFusion::Fast ||
-      (Options.NoNaNsFPMath && Options.NoInfsFPMath) ||
+  if ((Options.NoNaNsFPMath && Options.NoInfsFPMath) ||
       (N->getFlags().hasNoNaNs() && N->getFlags().hasNoInfs())) {
     if (Options.NoSignedZerosFPMath || N->getFlags().hasNoSignedZeros() ||
         (N2CFP && !N2CFP->isExactlyValue(-0.0))) {
diff --git a/llvm/test/CodeGen/X86/dag-combiner-fma-folding.ll b/llvm/test/CodeGen/X86/dag-combiner-fma-folding.ll
index 2bd7dc445a02b..6291100f42c3d 100644
--- a/llvm/test/CodeGen/X86/dag-combiner-fma-folding.ll
+++ b/llvm/test/CodeGen/X86/dag-combiner-fma-folding.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc -mtriple=x86_64-- --start-before=x86-isel -mattr=+avx,+fma %s -o - | FileCheck %s
+; RUN: llc -mtriple=x86_64-- --start-before=x86-isel -mattr=+avx,+fma %s -o - -fp-contract=fast | FileCheck %s
 
 define double @fma_folding(double %x) {
 ; CHECK-LABEL: fma_folding:
@@ -20,3 +21,14 @@ define double @fma_no_folding(double %x) {
   %fused = call contract nnan ninf double @llvm.fma.f64(double %x, double 0.0, double -0.0)
   ret double %fused
 }
+
+define double @fma_no_fold_potential_nan(double %x) {
+; CHECK-LABEL: fma_no_fold_potential_nan:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vxorpd %xmm1, %xmm1, %xmm1
+; CHECK-NEXT:    vfmadd213sd {{.*#+}} xmm0 = (xmm1 * xmm0) + mem
+; CHECK-NEXT:    retq
+ %fused = call contract double @llvm.fma.f64(double %x, double 0.0, double 1.0)
+ ret double %fused
+}
+

@pranavk
Copy link
Contributor

pranavk commented Jul 1, 2025

I have verified and it fixes the bug in jax-ml/jax#4780

@pranavk
Copy link
Contributor

pranavk commented Jul 1, 2025

we are also blocked on it internally. So would appreciate if we can get a quick a review here sooner.

@jyknight
Copy link
Member Author

jyknight commented Jul 1, 2025

we are also blocked on it internally. So would appreciate if we can get a quick a review here sooner.

I mean...do you want to review the change?

@pranavk pranavk self-requested a review July 1, 2025 22:01
Copy link
Contributor

@pranavk pranavk left a comment

Choose a reason for hiding this comment

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

LGTM.

@jyknight jyknight merged commit ae21048 into llvm:main Jul 1, 2025
10 checks passed
@jyknight jyknight deleted the nan-dagcombine branch July 1, 2025 22:10
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 2, 2025

LLVM Buildbot has detected a new failure on builder premerge-monolithic-linux running on premerge-linux-1 while building llvm at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/153/builds/36665

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'SanitizerCommon-ubsan-x86_64-Linux :: Posix/create_thread_loop.cpp' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/build/buildbot/premerge-monolithic-linux/build/./bin/clang  --driver-mode=g++ -gline-tables-only -fsanitize=undefined  -m64 -funwind-tables  -I/build/buildbot/premerge-monolithic-linux/llvm-project/compiler-rt/test -ldl -O3 -pthread /build/buildbot/premerge-monolithic-linux/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/create_thread_loop.cpp -o /build/buildbot/premerge-monolithic-linux/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/ubsan-x86_64-Linux/Posix/Output/create_thread_loop.cpp.tmp &&  /build/buildbot/premerge-monolithic-linux/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/ubsan-x86_64-Linux/Posix/Output/create_thread_loop.cpp.tmp 1000 # RUN: at line 3
+ /build/buildbot/premerge-monolithic-linux/build/./bin/clang --driver-mode=g++ -gline-tables-only -fsanitize=undefined -m64 -funwind-tables -I/build/buildbot/premerge-monolithic-linux/llvm-project/compiler-rt/test -ldl -O3 -pthread /build/buildbot/premerge-monolithic-linux/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/create_thread_loop.cpp -o /build/buildbot/premerge-monolithic-linux/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/ubsan-x86_64-Linux/Posix/Output/create_thread_loop.cpp.tmp
+ /build/buildbot/premerge-monolithic-linux/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/ubsan-x86_64-Linux/Posix/Output/create_thread_loop.cpp.tmp 1000
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==3459505==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x7ddfba6f1948 (pc 0x7ddfc1b87c30 bp 0x000000000002 sp 0x7ffc56966e38 T3459505)
==3459505==The signal is caused by a READ memory access.
    #0 0x7ddfc1b87c30 in pthread_detach (/lib/x86_64-linux-gnu/libc.so.6+0x95c30) (BuildId: a43bfc8428df6623cd498c9c0caeb91aec9be4f9)
    #1 0x59543cedeee0 in main /build/buildbot/premerge-monolithic-linux/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/create_thread_loop.cpp:23:7
    #2 0x7ddfc1b1bd8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: a43bfc8428df6623cd498c9c0caeb91aec9be4f9)
    #3 0x7ddfc1b1be3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: a43bfc8428df6623cd498c9c0caeb91aec9be4f9)
    #4 0x59543ceb2404 in _start (/build/buildbot/premerge-monolithic-linux/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/ubsan-x86_64-Linux/Posix/Output/create_thread_loop.cpp.tmp+0x5404)

==3459505==Register values:
rax = 0x0000000000000000  rbx = 0x00000000000002d2  rcx = 0x00007ddfc1b87219  rdx = 0x0000000000000000  
rdi = 0x00007ddfba6f1640  rsi = 0x00007ffc56966d60  rbp = 0x0000000000000002  rsp = 0x00007ffc56966e38  
 r8 = 0x00007ddfba6f1640   r9 = 0x00007ffc56966d1f  r10 = 0x0000000000000008  r11 = 0x0000000000000246  
r12 = 0x00007ffc56966f78  r13 = 0x000059543cedee58  r14 = 0x000059543cedef28  r15 = 0x00007ffc56966e48  
UndefinedBehaviorSanitizer can not provide additional info.
SUMMARY: UndefinedBehaviorSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0x95c30) (BuildId: a43bfc8428df6623cd498c9c0caeb91aec9be4f9) in pthread_detach
==3459505==ABORTING

--

********************


; CHECK-NEXT: vxorpd %xmm1, %xmm1, %xmm1
; CHECK-NEXT: vfmadd213sd {{.*#+}} xmm0 = (xmm1 * xmm0) + mem
; CHECK-NEXT: retq
%fused = call contract double @llvm.fma.f64(double %x, double 0.0, double 1.0)
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't need contract flag?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:X86 llvm:SelectionDAG SelectionDAGISel as well
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants