[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