[llvm] [KnownFPClass] Refactor NaN sign encoding for KnownFPClass (PR #220606)

Tim Gymnich via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 04:25:24 PDT 2026


================
@@ -24,41 +24,213 @@ class APInt;
 struct fltSemantics;
 struct KnownBits;
 
-struct KnownFPClass {
-  FPClassTest KnownFPClassesValue = fcAllFlags;
-  std::optional<bool> SignBitValue;
+enum FPClassMask : unsigned {
+  kfcNone = 0,
+
+  kfcNegQNan = 0x0001,
+  kfcNegSNan = 0x0002,
+  kfcNegInf = 0x0004,
+  kfcNegNormal = 0x0008,
+  kfcNegSubnormal = 0x0010,
+  kfcNegZero = 0x0020,
+  kfcPosZero = 0x0040,
+  kfcPosSubnormal = 0x0080,
+  kfcPosNormal = 0x0100,
+  kfcPosInf = 0x0200,
+  kfcPosSNan = 0x0400,
+  kfcPosQNan = 0x0800,
+
+  kfcSNan = kfcPosSNan | kfcNegSNan,
+  kfcQNan = kfcPosQNan | kfcNegQNan,
+  kfcPosNan = kfcPosSNan | kfcPosQNan,
+  kfcNegNan = kfcNegSNan | kfcNegQNan,
+  kfcNan = kfcSNan | kfcQNan,
+  kfcInf = kfcPosInf | kfcNegInf,
+  kfcNormal = kfcPosNormal | kfcNegNormal,
+  kfcSubnormal = kfcPosSubnormal | kfcNegSubnormal,
+  kfcZero = kfcPosZero | kfcNegZero,
+  kfcPosFinite = kfcPosNormal | kfcPosSubnormal | kfcPosZero,
+  kfcNegFinite = kfcNegNormal | kfcNegSubnormal | kfcNegZero,
+  kfcFinite = kfcPosFinite | kfcNegFinite,
+  kfcPositive = kfcPosFinite | kfcPosInf,
+  kfcNegative = kfcNegFinite | kfcNegInf,
+  kfcPosSignBit = kfcPositive | kfcPosNan,
+  kfcNegSignBit = kfcNegative | kfcNegNan,
+
+  kfcAllFlags = kfcNan | kfcInf | kfcFinite,
+};
+
+LLVM_DECLARE_ENUM_AS_BITMASK(FPClassMask, /* LargestValue */ kfcPosQNan);
+
+constexpr FPClassMask toFPClassMask(FPClassTest Classes) {
+  FPClassMask Mask = kfcNone;
+
+  if (Classes & fcQNan)
+    Mask |= kfcQNan;
+  if (Classes & fcSNan)
+    Mask |= kfcSNan;
+  if (Classes & fcNegInf)
+    Mask |= kfcNegInf;
+  if (Classes & fcNegNormal)
+    Mask |= kfcNegNormal;
+  if (Classes & fcNegSubnormal)
+    Mask |= kfcNegSubnormal;
+  if (Classes & fcNegZero)
+    Mask |= kfcNegZero;
+  if (Classes & fcPosZero)
+    Mask |= kfcPosZero;
+  if (Classes & fcPosSubnormal)
+    Mask |= kfcPosSubnormal;
+  if (Classes & fcPosNormal)
+    Mask |= kfcPosNormal;
+  if (Classes & fcPosInf)
+    Mask |= kfcPosInf;
+
+  return Mask;
+}
+
+constexpr FPClassMask toFPClassMask(FPClassTest Classes, bool SignBit) {
+  FPClassMask Mask = toFPClassMask(Classes);
+
+  // This is the only way to generate a NaN with a specific sign from
+  // FPClassTest. SignBit must agree with the input classes.
+  if (!SignBit) {
+    Mask &= ~kfcNegNan;
+    // If the SignBit is false, then we should not have any negative classes.
+    if (!(Mask & kfcNegSignBit))
+      return Mask;
+  } else {
+    Mask &= ~kfcPosNan;
+    // If the SignBit is true, then we should not have any positive classes.
+    if (!(Mask & kfcPosSignBit))
+      return Mask;
+  }
+
+  // SignBit is unknown or inconsistent with the input classes. Expand the
+  // possible set to its opposite sign pair.
+  if (Classes & fcQNan)
+    Mask |= kfcQNan;
+  if (Classes & fcSNan)
+    Mask |= kfcSNan;
+  if (Classes & fcInf)
+    Mask |= kfcInf;
+  if (Classes & fcNormal)
+    Mask |= kfcNormal;
+  if (Classes & fcSubnormal)
+    Mask |= kfcSubnormal;
+  if (Classes & fcZero)
+    Mask |= kfcZero;
+
+  return Mask;
+}
+
+constexpr FPClassTest toFPClassTest(FPClassMask Mask) {
----------------
tgymnich wrote:

We should keep `toFPClassMask` private e.g. make it `inline` for now or move it to the `.cpp`.

https://github.com/llvm/llvm-project/pull/220606


More information about the llvm-commits mailing list