[llvm] expandIS_FPCLASS: Support fcNegative and fcPositive (PR #184788)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 29 02:12:48 PDT 2026


================
@@ -10524,6 +10568,49 @@ SDValue TargetLowering::expandIS_FPCLASS(EVT ResultVT, SDValue Op,
   // Tests that involve more than one class should be processed first.
   SDValue PartialRes;
 
+  // Handle sign bit tests first (fcPositive/fcNegative).
+  // These test only the sign bit, if not NaN.
+  // On 32-bit platforms with 64-bit floats, we need to be careful about
+  // integer comparisons. We use FP_ROUND to convert to a smaller float type
+  // that matches ResultVT's size, then compare with 0.
+  FPClassTest FPTestSign = Test & (~fcNan);
+  FPClassTest FPTestNaN = Test & fcNan;
+  // FPTestSign must be exactly fcNegative or fcPositive; combined flags are
+  // not supported.
+  bool testNegative = FPTestSign == fcNegative;
+  bool testPositive = FPTestSign == fcPositive;
+  // FPTestNaN must be fcNan or fcNone; testing sNan or qNan individually is
+  // not supported.
+  bool testNaN = FPTestNaN == fcNan;
+  bool testNotNaN = FPTestNaN == fcNone;
+  if ((testPositive || testNegative) && (testNaN || testNotNaN)) {
+    bool NeedFPTrunc = false;
+
+    SDValue SignBitResult =
+        getFloatSign(ResultVT, NeedFPTrunc, Op, DAG, DL, *this);
+    // This logic is not needed if we are sure that Op is not NaN,
+    // while combiner will help us to remove it: maybe in future.
+    if (testNaN) {
+      SDValue IsNaN = DAG.getSetCC(DL, ResultVT, Op, Op, ISD::SETUO);
+      SignBitResult = DAG.getNode(ISD::OR, DL, ResultVT, IsNaN, SignBitResult);
+    } else {
+      SDValue NotNaN = DAG.getSetCC(DL, ResultVT, Op, Op, ISD::SETO);
+      SignBitResult =
+          DAG.getNode(ISD::AND, DL, ResultVT, NotNaN, SignBitResult);
+    }
+
+    bool IsICmpImmLegal =
+        isLegalICmpImmediate(APInt::getAllOnes(BitSize).getSExtValue());
+    if (NeedFPTrunc || DAG.isKnownNeverNaN(Op) ||
+        (OperandVT.isVector() && isTypeLegal(OperandVT)) || testNegative ||
+        !IsICmpImmLegal) {
+      if (!testNegative)
+        SignBitResult = DAG.getNode(ISD::XOR, DL, ResultVT, SignBitResult,
+                                    ResultInversionMask);
----------------
nikic wrote:

Doesn't this incorrectly also revert the NaN result, rather than just the sign result?

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


More information about the llvm-commits mailing list