[llvm] [Mips] Fix wrong qNaN encoding when -mnan=legacy (PR #153777)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 21 02:37:34 PDT 2025


https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/153777

>From 3b70160c18887c89ea50e26aac250e06e401547f Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Fri, 15 Aug 2025 05:57:33 -0400
Subject: [PATCH] [Mips] Fix wrong qNaN encoding when -mnan=legacy

The correct value is:
Single floating-point 0x7fbf ffff(legacy) 0x7fc0 0000(nan2008)
Double floating-point 0x7ff7 ffff ffff ffff(legacy) 0x7ff8 0000 0000 0000(nan2008)

Fix #100495.
---
 llvm/include/llvm/CodeGen/TargetLowering.h     |  5 ++++-
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp  |  2 +-
 .../CodeGen/SelectionDAG/LegalizeVectorOps.cpp |  2 +-
 .../CodeGen/SelectionDAG/TargetLowering.cpp    | 12 ++++++++----
 llvm/lib/Target/Mips/MipsISelLowering.cpp      | 14 ++++++++++++++
 llvm/lib/Target/Mips/MipsISelLowering.h        |  2 ++
 llvm/test/CodeGen/Mips/fminimum-fmaximum.ll    | 18 ++++++++++++++++++
 7 files changed, 48 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/CodeGen/Mips/fminimum-fmaximum.ll

diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index ed7495694cc70..19865fbed1cab 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -4433,6 +4433,8 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
   ///
   virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
 
+  virtual APFloat getNaNValue(EVT VT) const;
+
   /// Return true if it is profitable to move this shift by a constant amount
   /// through its operand, adjusting any immediate operands as necessary to
   /// preserve semantics. This transformation may not be desirable if it
@@ -5436,7 +5438,8 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
   SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const;
 
   /// Expand fminimum/fmaximum into multiple comparison with selects.
-  SDValue expandFMINIMUM_FMAXIMUM(SDNode *N, SelectionDAG &DAG) const;
+  SDValue expandFMINIMUM_FMAXIMUM(SDNode *N, SelectionDAG &DAG,
+                                  const TargetLowering &TLI) const;
 
   /// Expand fminimumnum/fmaximumnum into multiple comparison with selects.
   SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const;
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index ba0ab2383d87a..719dbc8dafc7e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3756,7 +3756,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
   }
   case ISD::FMINIMUM:
   case ISD::FMAXIMUM: {
-    if (SDValue Expanded = TLI.expandFMINIMUM_FMAXIMUM(Node, DAG))
+    if (SDValue Expanded = TLI.expandFMINIMUM_FMAXIMUM(Node, DAG, TLI))
       Results.push_back(Expanded);
     break;
   }
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index d2ecc13331e02..57be9aa960bbc 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -1141,7 +1141,7 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
     break;
   case ISD::FMINIMUM:
   case ISD::FMAXIMUM:
-    Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(Node, DAG));
+    Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(Node, DAG, TLI));
     return;
   case ISD::FMINIMUMNUM:
   case ISD::FMAXIMUMNUM:
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 911bbabc42aa3..6d815cbb6d570 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8731,8 +8731,13 @@ SDValue TargetLowering::expandFMINNUM_FMAXNUM(SDNode *Node,
   return SDValue();
 }
 
-SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
-                                                SelectionDAG &DAG) const {
+APFloat TargetLowering::getNaNValue(EVT VT) const {
+  return APFloat::getNaN(VT.getFltSemantics());
+}
+
+SDValue
+TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N, SelectionDAG &DAG,
+                                        const TargetLowering &TLI) const {
   if (SDValue Expanded = expandVectorNaryOpBySplitting(N, DAG))
     return Expanded;
 
@@ -8773,8 +8778,7 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
   // Propagate any NaN of both operands
   if (!N->getFlags().hasNoNaNs() &&
       (!DAG.isKnownNeverNaN(RHS) || !DAG.isKnownNeverNaN(LHS))) {
-    ConstantFP *FPNaN = ConstantFP::get(*DAG.getContext(),
-                                        APFloat::getNaN(VT.getFltSemantics()));
+    ConstantFP *FPNaN = ConstantFP::get(*DAG.getContext(), TLI.getNaNValue(VT));
     MinMax = DAG.getSelect(DL, VT, DAG.getSetCC(DL, CCVT, LHS, RHS, ISD::SETUO),
                            DAG.getConstantFP(*FPNaN, DL, VT), MinMax, Flags);
   }
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 9fbbdb2ecb264..7a27c0b9c9316 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -1255,6 +1255,20 @@ static SDValue performSignExtendCombine(SDNode *N, SelectionDAG &DAG,
   return SDValue();
 }
 
+APFloat MipsTargetLowering::getNaNValue(EVT VT) const {
+  if (!Subtarget.isNaN2008()) {
+    if (&VT.getFltSemantics() == &APFloat::IEEEsingle()) {
+      APInt intPayload(64, 0xbfffff);
+      return APFloat::getSNaN(VT.getFltSemantics(), false, &intPayload);
+    } else if (&VT.getFltSemantics() == &APFloat::IEEEdouble()) {
+      APInt intPayload(64, 0x7ffffffffffff);
+      return APFloat::getSNaN(VT.getFltSemantics(), false, &intPayload);
+    }
+  }
+
+  return APFloat::getNaN(VT.getFltSemantics());
+}
+
 SDValue  MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
   const {
   SelectionDAG &DAG = DCI.DAG;
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index c65c76ccffc75..870306529de8f 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -341,6 +341,8 @@ class TargetRegisterClass;
 
     SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
 
+    APFloat getNaNValue(EVT VT) const override;
+
     MachineBasicBlock *
     EmitInstrWithCustomInserter(MachineInstr &MI,
                                 MachineBasicBlock *MBB) const override;
diff --git a/llvm/test/CodeGen/Mips/fminimum-fmaximum.ll b/llvm/test/CodeGen/Mips/fminimum-fmaximum.ll
new file mode 100644
index 0000000000000..0121e8905303f
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/fminimum-fmaximum.ll
@@ -0,0 +1,18 @@
+; RUN: llc -mtriple=mips64el-unknown-linux-gnuabi64 -mcpu=mips64r2 -mattr=+nan2008 < %s | FileCheck -check-prefixes=NAN2008 %s
+; RUN: llc -mtriple=mips64el-unknown-linux-gnuabi64 -mcpu=mips64r2 -mattr=-nan2008 < %s | FileCheck -check-prefixes=LEGACY %s
+
+define float @test_fminimum_f32(float %a, float %b) {
+; NAN2008:    .4byte 0x7fc00000    # float NaN
+;
+; LEGACY:    .4byte 0x7fbfffff    # float NaN
+  %val = tail call float @llvm.minimum.f32(float %a, float %b)
+  ret float %val
+}
+
+define double @test_fminimum_f64(double %a, double %b) {
+; NAN2008:    .8byte 0x7ff8000000000000    # double NaN
+;
+; LEGACY:    .8byte 0x7ff7ffffffffffff    # double NaN
+  %val = tail call double @llvm.minimum.f64(double %a, double %b)
+  ret double %val
+}



More information about the llvm-commits mailing list