[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