[llvm] [SelectionDAG] Use `KnownFPClass` to infer `isKnownNeverZeroFloat` (PR #190621)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 6 12:35:11 PDT 2026
https://github.com/zGoldthorpe updated https://github.com/llvm/llvm-project/pull/190621
>From 676c76ced4474161ce21cd075e2f9dc9e295d0d7 Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Wed, 1 Apr 2026 15:48:41 -0500
Subject: [PATCH 1/5] [SelectionDAG] Use `KnownFPClass` to infer
`isKnownNeverZeroFloat`
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 11 ++++++++---
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 15 +++++++++------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index c1012c940ed5b..e0778e5730eb8 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2442,9 +2442,14 @@ class SelectionDAG {
return isKnownNeverNaN(Op, true, Depth);
}
- /// Test whether the given floating point SDValue is known to never be
- /// positive or negative zero.
- LLVM_ABI bool isKnownNeverZeroFloat(SDValue Op) const;
+ /// Test whether the given SDValue (or all elements of it, if it is a vector)
+ /// is known to never be positive or negative zero in \p DemandedElts.
+ LLVM_ABI bool isKnownNeverZeroFloat(SDValue Op, const APInt &DemandedElts,
+ unsigned Depth = 0) const;
+
+ /// Test whether the given floating point SDValue (or all elements of it, if
+ /// it is a vector) is known to never be positive or negative zero.
+ LLVM_ABI bool isKnownNeverZeroFloat(SDValue Op, unsigned Depth = 0) const;
/// Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth = 0) const;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 137922aa62557..4c89195a0e17d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6317,13 +6317,16 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
return Known.isKnownNever(NanMask);
}
-bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op) const {
- assert(Op.getValueType().isFloatingPoint() &&
- "Floating point type expected");
+bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op, unsigned Depth) const {
+ APInt DemandedElts = getDemandAllEltsMask(Op);
+ return isKnownNeverZeroFloat(Op, DemandedElts, Depth);
+}
- // If the value is a constant, we can obviously see if it is a zero or not.
- return ISD::matchUnaryFpPredicate(
- Op, [](ConstantFPSDNode *C) { return !C->isZero(); });
+bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op, const APInt &DemandedElts,
+ unsigned Depth) const {
+ assert(!DemandedElts.isZero() && "No demanded elements");
+ KnownFPClass Known = computeKnownFPClass(Op, DemandedElts, fcZero, Depth);
+ return Known.isKnownNeverZero();
}
bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
>From 49a0a2b1eeada02f4983de16443e69d3e7311bdb Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Mon, 6 Apr 2026 12:26:42 -0500
Subject: [PATCH 2/5] Use `isKnownNeverLogicalZero`
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 4c89195a0e17d..9e15be4fa3d45 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6325,8 +6325,10 @@ bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op, unsigned Depth) const {
bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op, const APInt &DemandedElts,
unsigned Depth) const {
assert(!DemandedElts.isZero() && "No demanded elements");
- KnownFPClass Known = computeKnownFPClass(Op, DemandedElts, fcZero, Depth);
- return Known.isKnownNeverZero();
+ EVT VT = Op.getValueType();
+ KnownFPClass Known =
+ computeKnownFPClass(Op, DemandedElts, fcZero | fcSubnormal, Depth);
+ return Known.isKnownNeverLogicalZero(getDenormalMode(VT));
}
bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
>From b18ad1170bad22fa83ee72e9bc0bdd1990931b37 Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Mon, 6 Apr 2026 12:28:38 -0500
Subject: [PATCH 3/5] Added DAZ tests.
---
.../AArch64/AArch64SelectionDAGTest.cpp | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index b144060afe925..1e4fad63e481b 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -6,6 +6,7 @@
//===----------------------------------------------------------------------===//
#include "AArch64SelectionDAGInfo.h"
+#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/AsmParser/Parser.h"
@@ -1576,6 +1577,53 @@ TEST_F(AArch64SelectionDAGTest, KnownNeverZero_Select) {
EXPECT_TRUE(DAG->isKnownNeverZero(VSelect4444, DemandAll));
}
+TEST_F(AArch64SelectionDAGTest, KnownNeverZeroFloat_DAZ) {
+ // Set function attribute to establish that denormals are zero (DAZ)
+ AttrBuilder AB(Context);
+ AB.addDenormalFPEnvAttr(DenormalFPEnv(DenormalMode::getPreserveSign()));
+ F->addFnAttrs(AB);
+ EXPECT_TRUE(DAG->getDenormalMode(MVT::f32).inputsAreZero());
+
+ SDLoc Loc;
+ const fltSemantics &FltSemantics = EVT(MVT::f32).getFltSemantics();
+
+ SDValue PosZeroF32 =
+ DAG->getConstantFP(APFloat::getZero(FltSemantics), Loc, MVT::f32);
+ EXPECT_FALSE(DAG->isKnownNeverZeroFloat(PosZeroF32));
+ SDValue NegZeroF32 = DAG->getConstantFP(
+ APFloat::getZero(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
+ EXPECT_FALSE(DAG->isKnownNeverZeroFloat(NegZeroF32));
+
+ SDValue PosDenormalF32 =
+ DAG->getConstantFP(APFloat::getSmallest(FltSemantics), Loc, MVT::f32);
+ EXPECT_FALSE(DAG->isKnownNeverZeroFloat(PosDenormalF32));
+ SDValue NegDenormalF32 = DAG->getConstantFP(
+ APFloat::getSmallest(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
+ EXPECT_FALSE(DAG->isKnownNeverZeroFloat(NegDenormalF32));
+
+ SDValue PosNormalF32 = DAG->getConstantFP(
+ APFloat::getSmallestNormalized(FltSemantics), Loc, MVT::f32);
+ EXPECT_TRUE(DAG->isKnownNeverZeroFloat(PosNormalF32));
+ SDValue NegNormalF32 = DAG->getConstantFP(
+ APFloat::getSmallestNormalized(FltSemantics, /*Negative=*/true), Loc,
+ MVT::f32);
+ EXPECT_TRUE(DAG->isKnownNeverZeroFloat(NegNormalF32));
+
+ SDValue PosInfF32 =
+ DAG->getConstantFP(APFloat::getInf(FltSemantics), Loc, MVT::f32);
+ EXPECT_TRUE(DAG->isKnownNeverZeroFloat(PosInfF32));
+ SDValue NegInfF32 = DAG->getConstantFP(
+ APFloat::getInf(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
+ EXPECT_TRUE(DAG->isKnownNeverZeroFloat(NegInfF32));
+
+ SDValue PosNaNF32 =
+ DAG->getConstantFP(APFloat::getNaN(FltSemantics), Loc, MVT::f32);
+ EXPECT_TRUE(DAG->isKnownNeverZeroFloat(PosNaNF32));
+ SDValue NegNaNF32 = DAG->getConstantFP(
+ APFloat::getNaN(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
+ EXPECT_TRUE(DAG->isKnownNeverZeroFloat(NegNaNF32));
+}
+
TEST_F(AArch64SelectionDAGTest, KnownFPClass_Bitcast) {
SDLoc Loc;
SDValue Cond = DAG->getRegister(1, MVT::i1);
>From 2accdfe5f6bf2a2228bce84b1ec63a0726c90741 Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Mon, 6 Apr 2026 12:52:29 -0500
Subject: [PATCH 4/5] Rename `isKnownNeverZeroFloat` ~~>
`isKnownNeverLogicalZero`
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 13 ++++++------
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 13 ++++++------
.../CodeGen/SelectionDAG/TargetLowering.cpp | 10 +++++-----
.../WebAssembly/WebAssemblyISelLowering.cpp | 4 ++--
.../WebAssembly/WebAssemblyInstrSIMD.td | 8 ++++----
llvm/lib/Target/X86/X86ISelLowering.cpp | 12 +++++------
.../AArch64/AArch64SelectionDAGTest.cpp | 20 +++++++++----------
7 files changed, 41 insertions(+), 39 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index e0778e5730eb8..df4cac1caf7fd 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2442,14 +2442,15 @@ class SelectionDAG {
return isKnownNeverNaN(Op, true, Depth);
}
- /// Test whether the given SDValue (or all elements of it, if it is a vector)
- /// is known to never be positive or negative zero in \p DemandedElts.
- LLVM_ABI bool isKnownNeverZeroFloat(SDValue Op, const APInt &DemandedElts,
- unsigned Depth = 0) const;
+ /// Test whether the given floating point SDValue (or all elements of it, if
+ /// it is a vector) is known to never be interpretable as zero in \p
+ /// DemandedElts.
+ LLVM_ABI bool isKnownNeverLogicalZero(SDValue Op, const APInt &DemandedElts,
+ unsigned Depth = 0) const;
/// Test whether the given floating point SDValue (or all elements of it, if
- /// it is a vector) is known to never be positive or negative zero.
- LLVM_ABI bool isKnownNeverZeroFloat(SDValue Op, unsigned Depth = 0) const;
+ /// it is a vector) is known to never be interpretable as zero.
+ LLVM_ABI bool isKnownNeverLogicalZero(SDValue Op, unsigned Depth = 0) const;
/// Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth = 0) const;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 9e15be4fa3d45..8822807b11502 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6317,13 +6317,14 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
return Known.isKnownNever(NanMask);
}
-bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op, unsigned Depth) const {
+bool SelectionDAG::isKnownNeverLogicalZero(SDValue Op, unsigned Depth) const {
APInt DemandedElts = getDemandAllEltsMask(Op);
- return isKnownNeverZeroFloat(Op, DemandedElts, Depth);
+ return isKnownNeverLogicalZero(Op, DemandedElts, Depth);
}
-bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op, const APInt &DemandedElts,
- unsigned Depth) const {
+bool SelectionDAG::isKnownNeverLogicalZero(SDValue Op,
+ const APInt &DemandedElts,
+ unsigned Depth) const {
assert(!DemandedElts.isZero() && "No demanded elements");
EVT VT = Op.getValueType();
KnownFPClass Known =
@@ -6345,7 +6346,7 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, const APInt &DemandedElts,
unsigned BitWidth = OpVT.getScalarSizeInBits();
assert(!Op.getValueType().isFloatingPoint() &&
- "Floating point types unsupported - use isKnownNeverZeroFloat");
+ "Floating point types unsupported - use isKnownNeverLogicalZero");
// If the value is a constant, we can obviously see if it is a zero or not.
auto IsNeverZero = [BitWidth](const ConstantSDNode *C) {
@@ -6603,7 +6604,7 @@ bool SelectionDAG::canIgnoreSignBitOfZero(const SDUse &Use) const {
// Arithmetic with non-zero constants fixes the uncertainty around the
// sign bit.
SDValue Other = User->getOperand(1 - OperandNo);
- return isKnownNeverZeroFloat(Other);
+ return isKnownNeverLogicalZero(Other);
}
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT:
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 092bc283c84dc..7564b89a2ad8f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9182,7 +9182,7 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
// fminimum/fmaximum requires -0.0 less than +0.0
if (!MinMaxMustRespectOrderedZero && !N->getFlags().hasNoSignedZeros() &&
- !DAG.isKnownNeverZeroFloat(RHS) && !DAG.isKnownNeverZeroFloat(LHS)) {
+ !DAG.isKnownNeverLogicalZero(RHS) && !DAG.isKnownNeverLogicalZero(LHS)) {
SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
DAG.getConstantFP(0.0, DL, VT), ISD::SETOEQ);
SDValue TestZero =
@@ -9242,8 +9242,8 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
// either one for +0.0 vs -0.0.
if ((Flags.hasNoNaNs() ||
(DAG.isKnownNeverSNaN(LHS) && DAG.isKnownNeverSNaN(RHS))) &&
- (Flags.hasNoSignedZeros() || DAG.isKnownNeverZeroFloat(LHS) ||
- DAG.isKnownNeverZeroFloat(RHS))) {
+ (Flags.hasNoSignedZeros() || DAG.isKnownNeverLogicalZero(LHS) ||
+ DAG.isKnownNeverLogicalZero(RHS))) {
unsigned IEEE2008Op = Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM : ISD::FMAXNUM;
if (isOperationLegalOrCustom(IEEE2008Op, VT))
return DAG.getNode(IEEE2008Op, DL, VT, LHS, RHS, Flags);
@@ -9269,8 +9269,8 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
// TODO: We need quiet sNaN if strictfp.
// Fixup signed zero behavior.
- if (Flags.hasNoSignedZeros() || DAG.isKnownNeverZeroFloat(LHS) ||
- DAG.isKnownNeverZeroFloat(RHS)) {
+ if (Flags.hasNoSignedZeros() || DAG.isKnownNeverLogicalZero(LHS) ||
+ DAG.isKnownNeverLogicalZero(RHS)) {
return MinMax;
}
SDValue TestZero =
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 47de46a6f7070..4e5d7083fd7ea 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -2907,8 +2907,8 @@ static bool HasNoSignedZerosOrNaNs(SDValue Op, SelectionDAG &DAG) {
(DAG.isKnownNeverNaN(Op->getOperand(0)) &&
DAG.isKnownNeverNaN(Op->getOperand(1)))) &&
(Op->getFlags().hasNoSignedZeros() ||
- DAG.isKnownNeverZeroFloat(Op->getOperand(0)) ||
- DAG.isKnownNeverZeroFloat(Op->getOperand(1)));
+ DAG.isKnownNeverLogicalZero(Op->getOperand(0)) ||
+ DAG.isKnownNeverLogicalZero(Op->getOperand(1)));
}
SDValue WebAssemblyTargetLowering::LowerFMIN(SDValue Op,
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index ac810893999cf..a8e3a4e648dac 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1845,8 +1845,8 @@ def relaxed_pmin :
(CurDAG->isKnownNeverNaN(N->getOperand(1)) &&
CurDAG->isKnownNeverNaN(N->getOperand(2)))) &&
(N->getFlags().hasNoSignedZeros() ||
- CurDAG->isKnownNeverZeroFloat(N->getOperand(1)) ||
- CurDAG->isKnownNeverZeroFloat(N->getOperand(2)));
+ CurDAG->isKnownNeverLogicalZero(N->getOperand(1)) ||
+ CurDAG->isKnownNeverLogicalZero(N->getOperand(2)));
}]>;
def relaxed_pmax :
@@ -1855,8 +1855,8 @@ def relaxed_pmax :
((CurDAG->isKnownNeverNaN(N->getOperand(1))) &&
CurDAG->isKnownNeverNaN(N->getOperand(2)))) &&
(N->getFlags().hasNoSignedZeros() ||
- CurDAG->isKnownNeverZeroFloat(N->getOperand(1)) ||
- CurDAG->isKnownNeverZeroFloat(N->getOperand(2)));
+ CurDAG->isKnownNeverLogicalZero(N->getOperand(1)) ||
+ CurDAG->isKnownNeverLogicalZero(N->getOperand(2)));
}]>;
let Predicates = [HasRelaxedSIMD] in {
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 67d25e4eabbac..0f8ef24efbafe 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -29922,8 +29922,8 @@ static SDValue LowerFMINIMUM_FMAXIMUM(SDValue Op, const X86Subtarget &Subtarget,
bool IsXNeverNaN = DAG.isKnownNeverNaN(X);
bool IsYNeverNaN = DAG.isKnownNeverNaN(Y);
bool IgnoreSignedZero = Op->getFlags().hasNoSignedZeros() ||
- DAG.isKnownNeverZeroFloat(X) ||
- DAG.isKnownNeverZeroFloat(Y);
+ DAG.isKnownNeverLogicalZero(X) ||
+ DAG.isKnownNeverLogicalZero(Y);
bool ShouldHandleZeros = true;
SDValue NewX = X;
SDValue NewY = Y;
@@ -48393,8 +48393,8 @@ static SDValue combineSelectToMinMax(SelectionDAG &DAG,
case ISD::SETOLE:
// Converting this to a min would handle comparisons between positive
// and negative zero incorrectly.
- if (!N->getFlags().hasNoSignedZeros() && !DAG.isKnownNeverZeroFloat(LHS) &&
- !DAG.isKnownNeverZeroFloat(RHS))
+ if (!N->getFlags().hasNoSignedZeros() &&
+ !DAG.isKnownNeverLogicalZero(LHS) && !DAG.isKnownNeverLogicalZero(RHS))
break;
Opcode = X86ISD::FMIN;
break;
@@ -48410,8 +48410,8 @@ static SDValue combineSelectToMinMax(SelectionDAG &DAG,
case ISD::SETOGE:
// Converting this to a max would handle comparisons between positive
// and negative zero incorrectly.
- if (!N->getFlags().hasNoSignedZeros() && !DAG.isKnownNeverZeroFloat(LHS) &&
- !DAG.isKnownNeverZeroFloat(RHS))
+ if (!N->getFlags().hasNoSignedZeros() &&
+ !DAG.isKnownNeverLogicalZero(LHS) && !DAG.isKnownNeverLogicalZero(RHS))
break;
Opcode = X86ISD::FMAX;
break;
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index 1e4fad63e481b..3598aa30d5c68 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -1589,39 +1589,39 @@ TEST_F(AArch64SelectionDAGTest, KnownNeverZeroFloat_DAZ) {
SDValue PosZeroF32 =
DAG->getConstantFP(APFloat::getZero(FltSemantics), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverZeroFloat(PosZeroF32));
+ EXPECT_FALSE(DAG->isKnownNeverLogicalZero(PosZeroF32));
SDValue NegZeroF32 = DAG->getConstantFP(
APFloat::getZero(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverZeroFloat(NegZeroF32));
+ EXPECT_FALSE(DAG->isKnownNeverLogicalZero(NegZeroF32));
SDValue PosDenormalF32 =
DAG->getConstantFP(APFloat::getSmallest(FltSemantics), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverZeroFloat(PosDenormalF32));
+ EXPECT_FALSE(DAG->isKnownNeverLogicalZero(PosDenormalF32));
SDValue NegDenormalF32 = DAG->getConstantFP(
APFloat::getSmallest(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverZeroFloat(NegDenormalF32));
+ EXPECT_FALSE(DAG->isKnownNeverLogicalZero(NegDenormalF32));
SDValue PosNormalF32 = DAG->getConstantFP(
APFloat::getSmallestNormalized(FltSemantics), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverZeroFloat(PosNormalF32));
+ EXPECT_TRUE(DAG->isKnownNeverLogicalZero(PosNormalF32));
SDValue NegNormalF32 = DAG->getConstantFP(
APFloat::getSmallestNormalized(FltSemantics, /*Negative=*/true), Loc,
MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverZeroFloat(NegNormalF32));
+ EXPECT_TRUE(DAG->isKnownNeverLogicalZero(NegNormalF32));
SDValue PosInfF32 =
DAG->getConstantFP(APFloat::getInf(FltSemantics), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverZeroFloat(PosInfF32));
+ EXPECT_TRUE(DAG->isKnownNeverLogicalZero(PosInfF32));
SDValue NegInfF32 = DAG->getConstantFP(
APFloat::getInf(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverZeroFloat(NegInfF32));
+ EXPECT_TRUE(DAG->isKnownNeverLogicalZero(NegInfF32));
SDValue PosNaNF32 =
DAG->getConstantFP(APFloat::getNaN(FltSemantics), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverZeroFloat(PosNaNF32));
+ EXPECT_TRUE(DAG->isKnownNeverLogicalZero(PosNaNF32));
SDValue NegNaNF32 = DAG->getConstantFP(
APFloat::getNaN(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverZeroFloat(NegNaNF32));
+ EXPECT_TRUE(DAG->isKnownNeverLogicalZero(NegNaNF32));
}
TEST_F(AArch64SelectionDAGTest, KnownFPClass_Bitcast) {
>From d1850c5f4a8d5f7c49fa98d264b93fc6234f2819 Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Mon, 6 Apr 2026 14:32:20 -0500
Subject: [PATCH 5/5] Use lit test instead of unit test
---
llvm/test/CodeGen/X86/fminimum-fmaximum.ll | 194 ++++++++++++++++++
.../AArch64/AArch64SelectionDAGTest.cpp | 48 -----
2 files changed, 194 insertions(+), 48 deletions(-)
diff --git a/llvm/test/CodeGen/X86/fminimum-fmaximum.ll b/llvm/test/CodeGen/X86/fminimum-fmaximum.ll
index a56758d73165e..dcaa8cde94dd2 100644
--- a/llvm/test/CodeGen/X86/fminimum-fmaximum.ll
+++ b/llvm/test/CodeGen/X86/fminimum-fmaximum.ll
@@ -3171,3 +3171,197 @@ define float @test_fminimum_snan(float %x) {
%1 = tail call float @llvm.minimum.f32(float 0x7ff4000000000000, float %x)
ret float %1
}
+
+define float @test_fmaximum_dnz(float %x) {
+; SSE2-LABEL: test_fmaximum_dnz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: maxss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: test_fmaximum_dnz:
+; AVX: # %bb.0:
+; AVX-NEXT: vmaxss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX-NEXT: retq
+;
+; AVX10_2-LABEL: test_fmaximum_dnz:
+; AVX10_2: # %bb.0:
+; AVX10_2-NEXT: vminmaxss $5, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; AVX10_2-NEXT: retq
+;
+; X86-LABEL: test_fmaximum_dnz:
+; X86: # %bb.0:
+; X86-NEXT: pushl %eax
+; X86-NEXT: .cfi_def_cfa_offset 8
+; X86-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86-NEXT: vmaxss {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm0
+; X86-NEXT: vmovss %xmm0, (%esp)
+; X86-NEXT: flds (%esp)
+; X86-NEXT: popl %eax
+; X86-NEXT: .cfi_def_cfa_offset 4
+; X86-NEXT: retl
+ %denorm = bitcast i32 1 to float
+ %1 = tail call nnan float @llvm.maximum.f32(float %denorm, float %x)
+ ret float %1
+}
+
+define float @test_fmaximum_daz(float %x) #0 {
+; SSE2-LABEL: test_fmaximum_daz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: movaps %xmm0, %xmm1
+; SSE2-NEXT: maxss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SSE2-NEXT: orps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE2-NEXT: andps %xmm1, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX1-LABEL: test_fmaximum_daz:
+; AVX1: # %bb.0:
+; AVX1-NEXT: vmaxss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX1-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX1-NEXT: vandps %xmm1, %xmm0, %xmm0
+; AVX1-NEXT: retq
+;
+; AVX512F-LABEL: test_fmaximum_daz:
+; AVX512F: # %bb.0:
+; AVX512F-NEXT: vbroadcastss {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
+; AVX512F-NEXT: vorps %xmm1, %xmm0, %xmm1
+; AVX512F-NEXT: vmaxss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX512F-NEXT: vandps %xmm0, %xmm1, %xmm0
+; AVX512F-NEXT: retq
+;
+; AVX512DQ-LABEL: test_fmaximum_daz:
+; AVX512DQ: # %bb.0:
+; AVX512DQ-NEXT: vfpclassss $3, %xmm0, %k0 # k0 = isQuietNaN(xmm0) | isPositiveZero(xmm0)
+; AVX512DQ-NEXT: kmovw %k0, %k1
+; AVX512DQ-NEXT: vmovss {{.*#+}} xmm1 = [1.40129846E-45,0.0E+0,0.0E+0,0.0E+0]
+; AVX512DQ-NEXT: vmovaps %xmm1, %xmm2
+; AVX512DQ-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512DQ-NEXT: vmovss %xmm1, %xmm0, %xmm0 {%k1}
+; AVX512DQ-NEXT: vmaxss %xmm2, %xmm0, %xmm0
+; AVX512DQ-NEXT: retq
+;
+; AVX512BF16-LABEL: test_fmaximum_daz:
+; AVX512BF16: # %bb.0:
+; AVX512BF16-NEXT: vmaxss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX512BF16-NEXT: vpternlogd {{.*#+}} xmm0 = xmm1 & (xmm0 | m32bcst)
+; AVX512BF16-NEXT: retq
+;
+; AVX10_2-LABEL: test_fmaximum_daz:
+; AVX10_2: # %bb.0:
+; AVX10_2-NEXT: vminmaxss $5, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; AVX10_2-NEXT: retq
+;
+; X86-LABEL: test_fmaximum_daz:
+; X86: # %bb.0:
+; X86-NEXT: pushl %eax
+; X86-NEXT: .cfi_def_cfa_offset 8
+; X86-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86-NEXT: vmaxss {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm1
+; X86-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm0
+; X86-NEXT: vandps %xmm1, %xmm0, %xmm0
+; X86-NEXT: vmovss %xmm0, (%esp)
+; X86-NEXT: flds (%esp)
+; X86-NEXT: popl %eax
+; X86-NEXT: .cfi_def_cfa_offset 4
+; X86-NEXT: retl
+ %denorm = bitcast i32 1 to float
+ %1 = tail call nnan float @llvm.maximum.f32(float %denorm, float %x)
+ ret float %1
+}
+
+define float @test_fminimum_dnz(float %x) {
+; SSE2-LABEL: test_fminimum_dnz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: minss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: test_fminimum_dnz:
+; AVX: # %bb.0:
+; AVX-NEXT: vminss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX-NEXT: retq
+;
+; AVX10_2-LABEL: test_fminimum_dnz:
+; AVX10_2: # %bb.0:
+; AVX10_2-NEXT: vminmaxss $4, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; AVX10_2-NEXT: retq
+;
+; X86-LABEL: test_fminimum_dnz:
+; X86: # %bb.0:
+; X86-NEXT: pushl %eax
+; X86-NEXT: .cfi_def_cfa_offset 8
+; X86-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86-NEXT: vminss {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm0
+; X86-NEXT: vmovss %xmm0, (%esp)
+; X86-NEXT: flds (%esp)
+; X86-NEXT: popl %eax
+; X86-NEXT: .cfi_def_cfa_offset 4
+; X86-NEXT: retl
+ %denorm = bitcast i32 1 to float
+ %1 = tail call nnan float @llvm.minimum.f32(float %denorm, float %x)
+ ret float %1
+}
+
+define float @test_fminimum_daz(float %x) #0 {
+; SSE2-LABEL: test_fminimum_daz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: movaps %xmm0, %xmm1
+; SSE2-NEXT: minss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SSE2-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SSE2-NEXT: orps %xmm1, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX1-LABEL: test_fminimum_daz:
+; AVX1: # %bb.0:
+; AVX1-NEXT: vminss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0
+; AVX1-NEXT: retq
+;
+; AVX512F-LABEL: test_fminimum_daz:
+; AVX512F: # %bb.0:
+; AVX512F-NEXT: vbroadcastss {{.*#+}} xmm1 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
+; AVX512F-NEXT: vandps %xmm1, %xmm0, %xmm1
+; AVX512F-NEXT: vminss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX512F-NEXT: vorps %xmm0, %xmm1, %xmm0
+; AVX512F-NEXT: retq
+;
+; AVX512DQ-LABEL: test_fminimum_daz:
+; AVX512DQ: # %bb.0:
+; AVX512DQ-NEXT: vfpclassss $5, %xmm0, %k0 # k0 = isQuietNaN(xmm0) | isNegativeZero(xmm0)
+; AVX512DQ-NEXT: kmovw %k0, %k1
+; AVX512DQ-NEXT: vmovss {{.*#+}} xmm1 = [1.40129846E-45,0.0E+0,0.0E+0,0.0E+0]
+; AVX512DQ-NEXT: vmovaps %xmm1, %xmm2
+; AVX512DQ-NEXT: vmovss %xmm0, %xmm2, %xmm2 {%k1}
+; AVX512DQ-NEXT: vmovss %xmm1, %xmm0, %xmm0 {%k1}
+; AVX512DQ-NEXT: vminss %xmm2, %xmm0, %xmm0
+; AVX512DQ-NEXT: retq
+;
+; AVX512BF16-LABEL: test_fminimum_daz:
+; AVX512BF16: # %bb.0:
+; AVX512BF16-NEXT: vminss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX512BF16-NEXT: vpternlogd {{.*#+}} xmm0 = (xmm0 & m32bcst) | xmm1
+; AVX512BF16-NEXT: retq
+;
+; AVX10_2-LABEL: test_fminimum_daz:
+; AVX10_2: # %bb.0:
+; AVX10_2-NEXT: vminmaxss $4, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; AVX10_2-NEXT: retq
+;
+; X86-LABEL: test_fminimum_daz:
+; X86: # %bb.0:
+; X86-NEXT: pushl %eax
+; X86-NEXT: .cfi_def_cfa_offset 8
+; X86-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86-NEXT: vminss {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm1
+; X86-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm0
+; X86-NEXT: vorps %xmm1, %xmm0, %xmm0
+; X86-NEXT: vmovss %xmm0, (%esp)
+; X86-NEXT: flds (%esp)
+; X86-NEXT: popl %eax
+; X86-NEXT: .cfi_def_cfa_offset 4
+; X86-NEXT: retl
+ %denorm = bitcast i32 1 to float
+ %1 = tail call nnan float @llvm.minimum.f32(float %denorm, float %x)
+ ret float %1
+}
+
+attributes #0 = { denormal_fpenv(preservesign|preservesign) }
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index 3598aa30d5c68..b144060afe925 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -6,7 +6,6 @@
//===----------------------------------------------------------------------===//
#include "AArch64SelectionDAGInfo.h"
-#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/AsmParser/Parser.h"
@@ -1577,53 +1576,6 @@ TEST_F(AArch64SelectionDAGTest, KnownNeverZero_Select) {
EXPECT_TRUE(DAG->isKnownNeverZero(VSelect4444, DemandAll));
}
-TEST_F(AArch64SelectionDAGTest, KnownNeverZeroFloat_DAZ) {
- // Set function attribute to establish that denormals are zero (DAZ)
- AttrBuilder AB(Context);
- AB.addDenormalFPEnvAttr(DenormalFPEnv(DenormalMode::getPreserveSign()));
- F->addFnAttrs(AB);
- EXPECT_TRUE(DAG->getDenormalMode(MVT::f32).inputsAreZero());
-
- SDLoc Loc;
- const fltSemantics &FltSemantics = EVT(MVT::f32).getFltSemantics();
-
- SDValue PosZeroF32 =
- DAG->getConstantFP(APFloat::getZero(FltSemantics), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverLogicalZero(PosZeroF32));
- SDValue NegZeroF32 = DAG->getConstantFP(
- APFloat::getZero(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverLogicalZero(NegZeroF32));
-
- SDValue PosDenormalF32 =
- DAG->getConstantFP(APFloat::getSmallest(FltSemantics), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverLogicalZero(PosDenormalF32));
- SDValue NegDenormalF32 = DAG->getConstantFP(
- APFloat::getSmallest(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_FALSE(DAG->isKnownNeverLogicalZero(NegDenormalF32));
-
- SDValue PosNormalF32 = DAG->getConstantFP(
- APFloat::getSmallestNormalized(FltSemantics), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverLogicalZero(PosNormalF32));
- SDValue NegNormalF32 = DAG->getConstantFP(
- APFloat::getSmallestNormalized(FltSemantics, /*Negative=*/true), Loc,
- MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverLogicalZero(NegNormalF32));
-
- SDValue PosInfF32 =
- DAG->getConstantFP(APFloat::getInf(FltSemantics), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverLogicalZero(PosInfF32));
- SDValue NegInfF32 = DAG->getConstantFP(
- APFloat::getInf(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverLogicalZero(NegInfF32));
-
- SDValue PosNaNF32 =
- DAG->getConstantFP(APFloat::getNaN(FltSemantics), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverLogicalZero(PosNaNF32));
- SDValue NegNaNF32 = DAG->getConstantFP(
- APFloat::getNaN(FltSemantics, /*Negative=*/true), Loc, MVT::f32);
- EXPECT_TRUE(DAG->isKnownNeverLogicalZero(NegNaNF32));
-}
-
TEST_F(AArch64SelectionDAGTest, KnownFPClass_Bitcast) {
SDLoc Loc;
SDValue Cond = DAG->getRegister(1, MVT::i1);
More information about the llvm-commits
mailing list