[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