@@ -8556,11 +8556,12 @@ static std::optional<bool> isFCmpEqualZero(FPClassTest Test,
8556
8556
}
8557
8557
8558
8558
SDValue TargetLowering::expandIS_FPCLASS(EVT ResultVT, SDValue Op,
8559
- FPClassTest Test, SDNodeFlags Flags ,
8560
- const SDLoc &DL,
8559
+ const FPClassTest OrigTestMask ,
8560
+ SDNodeFlags Flags, const SDLoc &DL,
8561
8561
SelectionDAG &DAG) const {
8562
8562
EVT OperandVT = Op.getValueType();
8563
8563
assert(OperandVT.isFloatingPoint());
8564
+ FPClassTest Test = OrigTestMask;
8564
8565
8565
8566
// Degenerated cases.
8566
8567
if (Test == fcNone)
@@ -8594,9 +8595,21 @@ SDValue TargetLowering::expandIS_FPCLASS(EVT ResultVT, SDValue Op,
8594
8595
// exceptions are ignored.
8595
8596
if (Flags.hasNoFPExcept() &&
8596
8597
isOperationLegalOrCustom(ISD::SETCC, OperandVT.getScalarType())) {
8598
+ FPClassTest FPTestMask = Test;
8599
+
8597
8600
ISD::CondCode OrderedCmpOpcode = IsInverted ? ISD::SETUNE : ISD::SETOEQ;
8598
8601
ISD::CondCode UnorderedCmpOpcode = IsInverted ? ISD::SETONE : ISD::SETUEQ;
8599
8602
8603
+ // See if we can fold an | fcNan into an unordered compare.
8604
+ FPClassTest OrderedFPTestMask = FPTestMask & ~fcNan;
8605
+
8606
+ // Can't fold the ordered check if we're only testing for snan or qnan
8607
+ // individually.
8608
+ if ((FPTestMask & fcNan) != fcNan)
8609
+ OrderedFPTestMask = FPTestMask;
8610
+
8611
+ const bool IsOrdered = FPTestMask == OrderedFPTestMask;
8612
+
8600
8613
if (std::optional<bool> IsCmp0 =
8601
8614
isFCmpEqualZero(Test, Semantics, DAG.getMachineFunction());
8602
8615
IsCmp0 && (isCondCodeLegalOrCustom(
@@ -8628,6 +8641,27 @@ SDValue TargetLowering::expandIS_FPCLASS(EVT ResultVT, SDValue Op,
8628
8641
return DAG.getSetCC(DL, ResultVT, Abs, Inf,
8629
8642
IsInverted ? ISD::SETUNE : ISD::SETOEQ);
8630
8643
}
8644
+
8645
+ if (OrderedFPTestMask == (fcSubnormal | fcZero) && !IsOrdered) {
8646
+ // TODO: Could handle ordered case, but it produces worse code for
8647
+ // x86. Maybe handle ordered if fabs is free?
8648
+
8649
+ ISD::CondCode OrderedOp = IsInverted ? ISD::SETUGE : ISD::SETOLT;
8650
+ ISD::CondCode UnorderedOp = IsInverted ? ISD::SETOGE : ISD::SETULT;
8651
+
8652
+ if (isCondCodeLegalOrCustom(IsOrdered ? OrderedOp : UnorderedOp,
8653
+ OperandVT.getScalarType().getSimpleVT())) {
8654
+ // (issubnormal(x) || iszero(x)) --> fabs(x) < smallest_normal
8655
+
8656
+ // TODO: Maybe only makes sense if fabs is free. Integer test of
8657
+ // exponent bits seems better for x86.
8658
+ SDValue Abs = DAG.getNode(ISD::FABS, DL, OperandVT, Op);
8659
+ SDValue SmallestNormal = DAG.getConstantFP(
8660
+ APFloat::getSmallestNormalized(Semantics), DL, OperandVT);
8661
+ return DAG.getSetCC(DL, ResultVT, Abs, SmallestNormal,
8662
+ IsOrdered ? OrderedOp : UnorderedOp);
8663
+ }
8664
+ }
8631
8665
}
8632
8666
8633
8667
// In the general case use integer operations.
0 commit comments