[llvm-branch-commits] [llvm] ADT: Add utility functions for comparing FPClassTest (PR #175380)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 13 10:41:05 PST 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/175380

>From 1b55651332811f2670b39509cd78426e1964ded5 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 9 Jan 2026 08:39:23 +0100
Subject: [PATCH] ADT: Add utility functions for comparing FPClassTest

Add utility functions for checking if less and greater queries
are known to not evaluate to true. This will permit more precise
folding of min/max intrinsics. The test is kind of a mess.
---
 llvm/include/llvm/ADT/FloatingPointMode.h |  34 ++
 llvm/lib/Support/FloatingPointMode.cpp    |  51 ++
 llvm/unittests/ADT/FloatingPointMode.cpp  | 560 ++++++++++++++++++++++
 3 files changed, 645 insertions(+)

diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h b/llvm/include/llvm/ADT/FloatingPointMode.h
index 1ab14d119fcd3..36e20d8f25c98 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -302,6 +302,40 @@ LLVM_ABI FPClassTest unknown_sign(FPClassTest Mask);
 /// Write a human readable form of \p Mask to \p OS
 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, FPClassTest Mask);
 
+/// Returns true if all values in \p LHS must be less than or equal to those in
+/// \p RHS. That is, the comparison `fcmp ogt LHS, RHS` will always return
+/// false.
+///
+/// If \p OrderedZeroSign is true, -0 will be treated as ordered less than +0,
+/// unlike fcmp.
+LLVM_ABI bool cannotOrderStrictlyGreater(FPClassTest LHS, FPClassTest RHS,
+                                         bool OrderedZeroSign = false);
+
+/// Returns true if all values in \p LHS must be less than those in \p RHS. That
+/// is, the comparison `fcmp oge LHS, RHS` will always return false.
+//
+// If \p OrderedZeroSign is true, -0 will be treated as ordered less than +0,
+// unlike fcmp.
+LLVM_ABI bool cannotOrderStrictlyGreaterEq(FPClassTest LHS, FPClassTest RHS,
+                                           bool OrderedZeroSign = false);
+
+/// Returns true if all values in \p LHS must be greater than or equal to those
+/// in \p RHS. That is, the comparison `fcmp olt LHS, RHS` will always return
+/// false.
+///
+/// If \p OrderedZeroSign is true, -0 will be treated as ordered less than +0,
+/// unlike fcmp.
+LLVM_ABI bool cannotOrderStrictlyLess(FPClassTest LHS, FPClassTest RHS,
+                                      bool OrderedZeroSign = false);
+
+/// Returns true if all values in \p LHS must be greater than to those in \p
+/// RHS. That is, the comparison `fcmp ole LHS, RHS` will always return false.
+///
+/// If \p OrderedZeroSign is true, -0 will be treated as ordered less than +0,
+/// unlike fcmp.
+LLVM_ABI bool cannotOrderStrictlyLessEq(FPClassTest LHS, FPClassTest RHS,
+                                        bool OrderedZeroSign = false);
+
 } // namespace llvm
 
 #endif // LLVM_ADT_FLOATINGPOINTMODE_H
diff --git a/llvm/lib/Support/FloatingPointMode.cpp b/llvm/lib/Support/FloatingPointMode.cpp
index 5a2836eb82434..f2cd008277236 100644
--- a/llvm/lib/Support/FloatingPointMode.cpp
+++ b/llvm/lib/Support/FloatingPointMode.cpp
@@ -106,3 +106,54 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, FPClassTest Mask) {
   OS << ')';
   return OS;
 }
+
+static bool cannotOrderStrictlyGreaterImpl(FPClassTest LHS, FPClassTest RHS,
+                                           bool OrEqual, bool OrderedZero) {
+  LHS &= ~fcNan;
+  RHS &= ~fcNan;
+
+  if (LHS == fcNone || RHS == fcNone)
+    return true;
+
+  FPClassTest LowestBitRHS = static_cast<FPClassTest>(RHS & -RHS);
+  FPClassTest HighestBitLHS = static_cast<FPClassTest>(1 << Log2_32(LHS));
+
+  if (!OrderedZero) {
+    // Introduce conflict in zero bits if we're treating them as equal.
+    if (LowestBitRHS == fcNegZero)
+      LowestBitRHS = fcPosZero;
+    if (HighestBitLHS == fcNegZero)
+      HighestBitLHS = fcPosZero;
+  }
+
+  if (LowestBitRHS > HighestBitLHS) {
+    assert((LHS & RHS) == fcNone && "no bits should intersect");
+    return true;
+  }
+
+  if (LowestBitRHS < HighestBitLHS)
+    return false;
+
+  constexpr FPClassTest ExactValuesMask = fcZero | fcInf;
+  return !OrEqual && (LowestBitRHS & ExactValuesMask) != fcNone;
+}
+
+bool llvm::cannotOrderStrictlyGreater(FPClassTest LHS, FPClassTest RHS,
+                                      bool OrderedZeroSign) {
+  return cannotOrderStrictlyGreaterImpl(LHS, RHS, false, OrderedZeroSign);
+}
+
+bool llvm::cannotOrderStrictlyGreaterEq(FPClassTest LHS, FPClassTest RHS,
+                                        bool OrderedZeroSign) {
+  return cannotOrderStrictlyGreaterImpl(LHS, RHS, true, OrderedZeroSign);
+}
+
+bool llvm::cannotOrderStrictlyLess(FPClassTest LHS, FPClassTest RHS,
+                                   bool OrderedZeroSign) {
+  return cannotOrderStrictlyGreaterImpl(RHS, LHS, false, OrderedZeroSign);
+}
+
+bool llvm::cannotOrderStrictlyLessEq(FPClassTest LHS, FPClassTest RHS,
+                                     bool OrderedZeroSign) {
+  return cannotOrderStrictlyGreaterImpl(RHS, LHS, true, OrderedZeroSign);
+}
diff --git a/llvm/unittests/ADT/FloatingPointMode.cpp b/llvm/unittests/ADT/FloatingPointMode.cpp
index b87507625542e..cbdd64aeb00cd 100644
--- a/llvm/unittests/ADT/FloatingPointMode.cpp
+++ b/llvm/unittests/ADT/FloatingPointMode.cpp
@@ -13,6 +13,11 @@ using namespace llvm;
 
 namespace {
 
+static constexpr FPClassTest OrderedLessThanZeroMask =
+    fcNegSubnormal | fcNegNormal | fcNegInf;
+static constexpr FPClassTest OrderedGreaterThanZeroMask =
+    fcPosSubnormal | fcPosNormal | fcPosInf;
+
 TEST(FloatingPointModeTest, ParseDenormalFPAttributeComponent) {
   EXPECT_EQ(DenormalMode::IEEE, parseDenormalFPAttributeComponent("ieee"));
   EXPECT_EQ(DenormalMode::IEEE, parseDenormalFPAttributeComponent(""));
@@ -226,4 +231,559 @@ TEST(FloatingPointModeTest, DenormalModePredicates) {
   EXPECT_FALSE(DenormalMode::getIEEE().inputsAreZero());
   EXPECT_FALSE(DenormalMode::getDynamic().inputsAreZero());
 }
+
+#define TEST_ORDERED_LT(a, b)                                                  \
+  EXPECT_TRUE(cannotOrderStrictlyGreater(a, b));                               \
+  EXPECT_FALSE(cannotOrderStrictlyGreater(b, a));
+
+TEST(FloatingPointModeTest, cannotOrderStrictlyGreater) {
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNone, fcNone));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcAllFlags, fcAllFlags));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcQNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcSNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcSNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcQNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcQNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcSNan, fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcSNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcQNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcPosZero, true));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcPosZero, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosZero, fcNegZero, true));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcPosZero, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcPosZero, fcPosZero, true));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcNegZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcNegZero, true));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegSubnormal, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcNegZero, fcNegSubnormal));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcPosSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosSubnormal, fcNegZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcNegZero, fcSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcSubnormal, fcNegZero));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcPosZero, fcPosSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosSubnormal, fcPosZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosZero, fcNegSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosZero, fcNegSubnormal, true));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcZero, fcSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcZero, fcSubnormal, true));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcZero, fcNegSubnormal));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcZero, fcPosSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosSubnormal, fcZero));
+
+  TEST_ORDERED_LT(fcNegInf, fcNegNormal);
+  TEST_ORDERED_LT(fcNegInf, fcNegSubnormal);
+  TEST_ORDERED_LT(fcNegInf, fcNegZero);
+  TEST_ORDERED_LT(fcNegInf, fcPosZero);
+  TEST_ORDERED_LT(fcNegInf, fcPosSubnormal);
+  TEST_ORDERED_LT(fcNegInf, fcPosNormal);
+  TEST_ORDERED_LT(fcNegInf, fcPosInf);
+
+  TEST_ORDERED_LT(fcNegNormal, fcPosNormal);
+  TEST_ORDERED_LT(fcNegNormal, fcPositive);
+  TEST_ORDERED_LT(fcNegNormal, fcPositive | fcNan);
+  TEST_ORDERED_LT(fcNegNormal | fcNan, fcPositive | fcNan);
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegNormal, fcPosNormal | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosNormal | fcNan, fcNegNormal));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreater(fcPosNormal | fcNan, fcNegNormal | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcNegNormal | fcNan, fcNegNormal));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreater(fcNegNormal | fcNan, fcNegNormal | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, ~fcNegInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(~fcNegInf, fcNegInf));
+
+  TEST_ORDERED_LT(fcNegInf, ~(fcNegInf | fcNan));
+  TEST_ORDERED_LT(fcNegative, fcPositive);
+  TEST_ORDERED_LT(fcNegFinite, fcPosFinite);
+  TEST_ORDERED_LT(fcNegZero, fcPosInf);
+  TEST_ORDERED_LT(fcPosZero, fcPosInf);
+  TEST_ORDERED_LT(fcZero, fcPosInf);
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcNegZero, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, fcNegZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcZero, fcInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcInf, fcZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcZero, fcInf | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcInf | fcNan, fcZero));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf | fcNan, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosInf | fcNan, fcZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcZero | fcNan, fcInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcInf, fcZero | fcNan));
+
+  TEST_ORDERED_LT(OrderedLessThanZeroMask, OrderedGreaterThanZeroMask);
+  TEST_ORDERED_LT(OrderedLessThanZeroMask, OrderedGreaterThanZeroMask | fcNan);
+
+  TEST_ORDERED_LT(OrderedLessThanZeroMask | fcNegZero,
+                  OrderedGreaterThanZeroMask);
+  TEST_ORDERED_LT(OrderedLessThanZeroMask | fcPosZero,
+                  OrderedGreaterThanZeroMask);
+  TEST_ORDERED_LT(OrderedLessThanZeroMask | fcZero, OrderedGreaterThanZeroMask);
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcPosZero, true));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcPosZero, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosZero, fcNegZero, true));
+
+  TEST_ORDERED_LT(fcNegZero, fcPosSubnormal);
+  TEST_ORDERED_LT(fcNegZero, fcPosZero | fcPosSubnormal);
+  TEST_ORDERED_LT(fcNegZero, OrderedGreaterThanZeroMask);
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(OrderedLessThanZeroMask,
+                                          OrderedLessThanZeroMask | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(OrderedLessThanZeroMask | fcNan,
+                                          OrderedLessThanZeroMask | fcNan));
+
+  TEST_ORDERED_LT(fcZero, fcPosInf);
+  TEST_ORDERED_LT(fcZero, fcPosInf | fcNan);
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcZero | fcNan, fcPosInf));
+
+  TEST_ORDERED_LT(fcPosNormal, fcPosInf);
+  TEST_ORDERED_LT(fcPosNormal, fcPosInf | fcNan);
+
+  TEST_ORDERED_LT(fcNegInf, fcPosInf);
+  TEST_ORDERED_LT(fcNegInf | fcNegZero, fcPosInf);
+
+  EXPECT_TRUE(
+      cannotOrderStrictlyGreater(fcNegInf | fcNegZero, fcZero | fcPosInf));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreater(fcZero | fcPosInf, fcNegInf | fcNegZero));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf | fcNegZero,
+                                         fcZero | fcPosInf, true));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcZero | fcPosInf,
+                                          fcNegInf | fcNegZero, true));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf | fcNegZero,
+                                         fcZero | fcPosInf | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf | fcNegZero,
+                                         fcPosZero | fcPosInf | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcPosInf, fcPosInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcPosZero, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegZero, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcNegSubnormal, fcNegSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosSubnormal, fcPosSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcNegNormal, fcNegNormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosNormal, fcPosNormal));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcFinite, fcFinite));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcFinite, fcInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcInf, fcInf));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreater(fcPosInf, ~fcPosInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreater(~fcPosInf, fcPosInf));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreater(fcNegInf, ~fcNegInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreater(~fcNegInf, fcNegInf));
+}
+
+TEST(FloatingPointModeTest, cannotOrderStrictlyGreaterEq) {
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNone, fcNone));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcAllFlags, fcAllFlags));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcQNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcSNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcSNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcQNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcQNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcSNan, fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegInf, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegInf, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegInf, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcSNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcQNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNan, fcNegInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegInf, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegZero, fcPosZero,
+                                           /*OrderedZeroSign=*/true));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero, fcPosZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosZero, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosZero, fcNegZero,
+                                            /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosZero, fcPosZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosZero, fcPosZero,
+                                            /*OrderedZeroSign=*/true));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero, fcNegZero,
+                                            /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(OrderedLessThanZeroMask,
+                                            OrderedLessThanZeroMask));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(OrderedLessThanZeroMask,
+                                            OrderedLessThanZeroMask | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(OrderedLessThanZeroMask,
+                                           OrderedGreaterThanZeroMask));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(OrderedLessThanZeroMask,
+                                           OrderedGreaterThanZeroMask | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(OrderedLessThanZeroMask | fcNan,
+                                           OrderedGreaterThanZeroMask));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero, fcNegZero | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero | fcNan, fcNegZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegZero, fcPosZero,
+                                           /*OrderedZeroSign=*/true));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosZero, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero | fcNan, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegZero | fcNan, fcPosZero,
+                                           /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosZero | fcNan, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero, fcPosZero | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegZero, fcPosZero | fcNan,
+                                           /*OrderedZeroSign=*/true));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosZero, fcNegZero | fcNan));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegZero, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero, fcNegZero,
+                                            /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero, fcPosZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero, fcPosZero,
+                                            /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosInf, fcPosInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosInf, fcPosInf | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosInf | fcNan, fcPosInf));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPosInf | fcNan, fcPosInf | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegSubnormal, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegSubnormal, fcNegZero));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcNegSubnormal | fcNegZero, fcNegZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosSubnormal, fcZero));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegSubnormal, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcSubnormal, fcZero));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcZero, fcPosInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcZero, fcPosInf | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcZero | fcNan, fcPosInf));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosNormal, fcPosNormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosSubnormal, fcPosSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegNormal, fcNegNormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegSubnormal, fcNegSubnormal));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosNormal | fcPosSubnormal,
+                                            fcPosNormal | fcPosSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegNormal | fcNegSubnormal,
+                                            fcNegNormal | fcNegSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNormal, fcNormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcSubnormal, fcSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcSubnormal | fcNormal,
+                                            fcSubnormal | fcNormal));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegInf, fcNegInf | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegInf | fcNan, fcNegInf));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegSubnormal, fcNegNormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosSubnormal, fcNegNormal));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcPosSubnormal, fcPosNormal));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegSubnormal, fcPosNormal));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegSubnormal, fcNegInf));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcNegInf | fcNegZero, fcZero | fcPosInf));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcZero | fcPosInf, fcNegInf | fcNegZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegInf | fcNegZero,
+                                            fcZero | fcPosInf | fcNan));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegInf | fcNegZero,
+                                            fcPosZero | fcPosInf | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegInf | fcNegZero,
+                                           fcPosZero | fcPosInf | fcNan,
+                                           /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPosInf | fcPosNormal, fcPosNormal));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPosNormal, fcPosInf | fcPosNormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(
+      fcPosInf | fcPosNormal | fcSubnormal, fcPosNormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(
+      fcPosNormal, fcPosInf | fcPosNormal | fcSubnormal));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPosSubnormal | fcPosZero, fcPosZero));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPosZero, fcPosSubnormal | fcPosZero));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcSubnormal | fcPosZero, fcPosZero));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPosZero, fcSubnormal | fcPosZero));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcSubnormal | fcPosZero, fcNegZero));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcNegZero, fcSubnormal | fcPosZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegative, fcPositive));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegative, fcPositive,
+                                           /*OrderedZeroSign=*/true));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPositive, fcNegative));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcNegative | fcNan, fcPositive | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(
+      fcNegative | fcNan, fcPositive | fcNan, /*OrderedZeroSign=*/true));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPositive | fcNan, fcNegative | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcZero, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNan, fcZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero, fcSubnormal));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcSubnormal, fcZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcFinite, fcFinite));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcFinite, fcInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcInf, fcInf));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcNegFinite, fcPosFinite));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegFinite, fcPosFinite,
+                                           /*OrderedZeroSign=*/true));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosFinite, fcNegFinite));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcNegFinite, fcPosFinite | fcNegZero));
+  EXPECT_FALSE(
+      cannotOrderStrictlyGreaterEq(fcPosFinite | fcNegZero, fcNegFinite));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero | fcInf, fcZero | fcInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero, fcZero | fcInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero | fcInf, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcZero | fcInf | fcNormal, fcZero));
+
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(fcPosInf, ~fcPosInf));
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(~fcPosInf, fcPosInf));
+
+  EXPECT_TRUE(cannotOrderStrictlyGreaterEq(fcNegInf, ~fcNegInf));
+  EXPECT_FALSE(cannotOrderStrictlyGreaterEq(~fcNegInf, fcNegInf));
+}
+
+TEST(FloatingPointModeTest, cannotOrderStrictlyLess) {
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNone, fcNone));
+  EXPECT_FALSE(cannotOrderStrictlyLess(fcAllFlags, fcAllFlags));
+
+  EXPECT_FALSE(cannotOrderStrictlyLess(OrderedLessThanZeroMask,
+                                       OrderedLessThanZeroMask));
+  EXPECT_FALSE(cannotOrderStrictlyLess(OrderedLessThanZeroMask,
+                                       OrderedGreaterThanZeroMask));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(OrderedGreaterThanZeroMask,
+                                      OrderedLessThanZeroMask));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPositive, fcNegative));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPositive, fcNegative,
+                                      /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyLess(fcNegative, fcPositive));
+  EXPECT_FALSE(cannotOrderStrictlyLess(fcNegative, fcPositive,
+                                       /*OrderedZeroSign=*/true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPositive | fcNan, fcNegative));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPositive | fcNan, fcNegative,
+                                      /*OrderedZeroSign=*/true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPositive, fcNegative | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPositive, fcNegative | fcNan,
+                                      /*OrderedZeroSign=*/true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(OrderedGreaterThanZeroMask | fcNan,
+                                      OrderedLessThanZeroMask));
+  EXPECT_TRUE(cannotOrderStrictlyLess(OrderedGreaterThanZeroMask,
+                                      OrderedLessThanZeroMask | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(OrderedGreaterThanZeroMask | fcNan,
+                                      OrderedLessThanZeroMask | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcQNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcSNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcSNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcQNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcQNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcSNan, fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNegInf, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNegInf, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNegInf, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcSNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcQNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNegInf, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNegZero, fcPosZero));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPosZero, fcNegZero));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPosZero, fcPosZero));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcPosZero, fcPosZero));
+
+  EXPECT_TRUE(
+      cannotOrderStrictlyLess(fcPosZero, fcNegZero, /*OrderedZeroSign=*/true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcZero, fcPosZero));
+  EXPECT_FALSE(cannotOrderStrictlyLess(fcZero, fcPosZero, true));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPosZero, fcZero));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPosZero, fcZero, true));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcZero, fcNegZero));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcZero, fcNegZero, true));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNegZero, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyLess(fcNegZero, fcZero, true));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcZero, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyLess(fcZero, fcZero, true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcInf, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcNan, fcInf));
+
+  EXPECT_TRUE(
+      cannotOrderStrictlyLess(fcPosInf | fcPosZero, fcNegZero | fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLess(
+      fcPosInf | fcPosZero, fcNegZero | fcNegInf, /*OrderedZeroSign=*/true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPosInf | fcPosZero, fcZero | fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPosInf | fcPosZero, fcZero | fcNegInf,
+                                      /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyLess(fcZero | fcNegInf, fcPosInf | fcPosZero));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyLess(fcNegInf | fcNegZero, fcZero | fcPosInf));
+  EXPECT_FALSE(
+      cannotOrderStrictlyLess(fcNegInf | fcNegZero, fcZero | fcPosInf, true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcZero | fcPosInf, fcNegInf | fcNegZero));
+  EXPECT_TRUE(
+      cannotOrderStrictlyLess(fcZero | fcPosInf, fcNegInf | fcNegZero, true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLess(fcPosInf, ~fcPosInf));
+  EXPECT_FALSE(cannotOrderStrictlyLess(~fcPosInf, fcPosInf));
+
+  EXPECT_FALSE(cannotOrderStrictlyLess(fcNegInf, ~fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLess(~fcNegInf, fcNegInf));
+}
+
+TEST(FloatingPointModeTest, cannotOrderStrictlyLessEq) {
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcNone, fcNone));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcAllFlags, fcAllFlags));
+
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(OrderedLessThanZeroMask,
+                                         OrderedLessThanZeroMask));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(OrderedLessThanZeroMask,
+                                         OrderedGreaterThanZeroMask));
+
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(OrderedGreaterThanZeroMask,
+                                        OrderedLessThanZeroMask));
+
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcPositive, fcNegative));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcPositive, fcNegative,
+                                        /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcNegative, fcPositive));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcNegative, fcPositive,
+                                         /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcPositive | fcNan, fcNegative));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcPositive | fcNan, fcNegative,
+                                        /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcPositive, fcNegative | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcPositive, fcNegative | fcNan,
+                                        /*OrderedZeroSign=*/true));
+
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(OrderedGreaterThanZeroMask | fcNan,
+                                        OrderedLessThanZeroMask));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(OrderedGreaterThanZeroMask,
+                                        OrderedLessThanZeroMask | fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(OrderedGreaterThanZeroMask | fcNan,
+                                        OrderedLessThanZeroMask | fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcQNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcSNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcSNan, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcQNan, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcQNan, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcSNan, fcNan));
+
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcNegInf, fcSNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcNegInf, fcQNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcNegInf, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcSNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcQNan, fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcNan, fcNegInf));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcNegInf, fcNegInf));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcNegZero, fcPosZero));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcPosZero, fcNegZero));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcPosZero, fcNegZero,
+                                        /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcZero, fcPosZero));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcPosZero, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcZero, fcNegZero));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcNegZero, fcZero));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcZero, fcZero));
+
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcInf, fcNan));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcNan, fcInf));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyLessEq(fcPosInf | fcPosZero, fcNegZero | fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(
+      fcPosInf | fcPosZero, fcNegZero | fcNegInf, /*OrderedZeroSign=*/true));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyLessEq(fcPosInf | fcPosZero, fcZero | fcNegInf));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyLessEq(fcZero | fcNegInf, fcPosInf | fcPosZero));
+
+  EXPECT_FALSE(
+      cannotOrderStrictlyLessEq(fcNegInf | fcNegZero, fcZero | fcPosInf));
+  EXPECT_FALSE(
+      cannotOrderStrictlyLessEq(fcZero | fcPosInf, fcNegInf | fcNegZero));
+
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(fcPosInf, ~fcPosInf));
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(~fcPosInf, fcPosInf));
+
+  EXPECT_FALSE(cannotOrderStrictlyLessEq(fcNegInf, ~fcNegInf));
+  EXPECT_TRUE(cannotOrderStrictlyLessEq(~fcNegInf, fcNegInf));
+}
 }



More information about the llvm-branch-commits mailing list