[llvm] 5b8ea2d - [PowerPC] Lower IS_FPCLASS by test data class instruction

Qiu Chaofan via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 2 20:44:06 PDT 2023


Author: Qiu Chaofan
Date: 2023-04-03T11:37:17+08:00
New Revision: 5b8ea2d0e160ff4a30b9bc058e386bd89c1743d2

URL: https://github.com/llvm/llvm-project/commit/5b8ea2d0e160ff4a30b9bc058e386bd89c1743d2
DIFF: https://github.com/llvm/llvm-project/commit/5b8ea2d0e160ff4a30b9bc058e386bd89c1743d2.diff

LOG: [PowerPC] Lower IS_FPCLASS by test data class instruction

Power ISA 3.0 introduced new 'test data class' instructions, which
accept flags for: NaN/Infinity/Zero/Denormal. This instruction can be
used to implement custom lowering for llvm.is.fpclass, but some extra
bits provided by the intrinsic are missing (normal and QNaN/SNaN).

For those categories not natively supported, this patch uses a two-way
or three-way combination to implement correct behavior.

Reviewed By: sepavloff, shchenz

Differential Revision: https://reviews.llvm.org/D140381

Added: 
    

Modified: 
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/lib/Target/PowerPC/PPCISelLowering.h
    llvm/test/CodeGen/PowerPC/is_fpclass.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 2b10e0512dc1f..a16c77a857292 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -1185,6 +1185,13 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i32, Custom);
       setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Custom);
 
+      // Test data class instructions store results in CR bits.
+      if (Subtarget.useCRBits()) {
+        setOperationAction(ISD::IS_FPCLASS, MVT::f32, Custom);
+        setOperationAction(ISD::IS_FPCLASS, MVT::f64, Custom);
+        setOperationAction(ISD::IS_FPCLASS, MVT::f128, Custom);
+      }
+
       // 128 bit shifts can be accomplished via 3 instructions for SHL and
       // SRL, but not for SRA because of the instructions available:
       // VS{RL} and VS{RL}O.
@@ -10999,6 +11006,153 @@ SDValue PPCTargetLowering::LowerATOMIC_LOAD_STORE(SDValue Op,
   }
 }
 
+static SDValue getDataClassTest(SDValue Op, FPClassTest Mask, const SDLoc &Dl,
+                                SelectionDAG &DAG,
+                                const PPCSubtarget &Subtarget) {
+  assert(Mask <= fcAllFlags && "Invalid fp_class flags!");
+
+  enum DataClassMask {
+    DC_NAN = 1 << 6,
+    DC_NEG_INF = 1 << 4,
+    DC_POS_INF = 1 << 5,
+    DC_NEG_ZERO = 1 << 2,
+    DC_POS_ZERO = 1 << 3,
+    DC_NEG_SUBNORM = 1,
+    DC_POS_SUBNORM = 1 << 1,
+  };
+
+  EVT VT = Op.getValueType();
+
+  unsigned TestOp = VT == MVT::f128  ? PPC::XSTSTDCQP
+                    : VT == MVT::f64 ? PPC::XSTSTDCDP
+                                     : PPC::XSTSTDCSP;
+
+  if (Mask == fcAllFlags)
+    return DAG.getBoolConstant(true, Dl, MVT::i1, VT);
+  if (Mask == 0)
+    return DAG.getBoolConstant(false, Dl, MVT::i1, VT);
+
+  // When it's cheaper or necessary to test reverse flags.
+  if ((Mask & fcNormal) == fcNormal || Mask == ~fcQNan || Mask == ~fcSNan) {
+    SDValue Rev = getDataClassTest(Op, ~Mask, Dl, DAG, Subtarget);
+    return DAG.getNOT(Dl, Rev, MVT::i1);
+  }
+
+  // Power doesn't support testing whether a value is 'normal'. Test the rest
+  // first, and test if it's 'not not-normal' with expected sign.
+  if (Mask & fcNormal) {
+    SDValue Rev(DAG.getMachineNode(
+                    TestOp, Dl, MVT::i32,
+                    DAG.getTargetConstant(DC_NAN | DC_NEG_INF | DC_POS_INF |
+                                              DC_NEG_ZERO | DC_POS_ZERO |
+                                              DC_NEG_SUBNORM | DC_POS_SUBNORM,
+                                          Dl, MVT::i32),
+                    Op),
+                0);
+    // Sign are stored in CR bit 0, result are in CR bit 2.
+    SDValue Sign(
+        DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
+                           DAG.getTargetConstant(PPC::sub_lt, Dl, MVT::i32)),
+        0);
+    SDValue Normal(DAG.getNOT(
+        Dl,
+        SDValue(DAG.getMachineNode(
+                    TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
+                    DAG.getTargetConstant(PPC::sub_eq, Dl, MVT::i32)),
+                0),
+        MVT::i1));
+    if (Mask & fcPosNormal)
+      Sign = DAG.getNOT(Dl, Sign, MVT::i1);
+    SDValue Result = DAG.getNode(ISD::AND, Dl, MVT::i1, Sign, Normal);
+    if (Mask == fcPosNormal || Mask == fcNegNormal)
+      return Result;
+
+    return DAG.getNode(
+        ISD::OR, Dl, MVT::i1,
+        getDataClassTest(Op, Mask & ~fcNormal, Dl, DAG, Subtarget), Result);
+  }
+
+  // The instruction doesn't 
diff erentiate between signaling or quiet NaN. Test
+  // the rest first, and test if it 'is NaN and is signaling/quiet'.
+  if ((Mask & fcNan) == fcQNan || (Mask & fcNan) == fcSNan) {
+    bool IsQuiet = Mask & fcQNan;
+    SDValue NanCheck = getDataClassTest(Op, fcNan, Dl, DAG, Subtarget);
+
+    // Quietness is determined by the first bit in fraction field.
+    uint64_t QuietMask = 0;
+    SDValue HighWord;
+    if (VT == MVT::f128) {
+      HighWord = DAG.getNode(
+          ISD::EXTRACT_VECTOR_ELT, Dl, MVT::i32, DAG.getBitcast(MVT::v4i32, Op),
+          DAG.getVectorIdxConstant(Subtarget.isLittleEndian() ? 3 : 0, Dl));
+      QuietMask = 0x8000;
+    } else if (VT == MVT::f64) {
+      if (Subtarget.isPPC64()) {
+        HighWord = DAG.getNode(ISD::EXTRACT_ELEMENT, Dl, MVT::i32,
+                               DAG.getBitcast(MVT::i64, Op),
+                               DAG.getConstant(1, Dl, MVT::i32));
+      } else {
+        SDValue Vec = DAG.getBitcast(
+            MVT::v4i32, DAG.getNode(ISD::SCALAR_TO_VECTOR, Dl, MVT::v2f64, Op));
+        HighWord = DAG.getNode(
+            ISD::EXTRACT_VECTOR_ELT, Dl, MVT::i32, Vec,
+            DAG.getVectorIdxConstant(Subtarget.isLittleEndian() ? 1 : 0, Dl));
+      }
+      QuietMask = 0x80000;
+    } else if (VT == MVT::f32) {
+      HighWord = DAG.getBitcast(MVT::i32, Op);
+      QuietMask = 0x400000;
+    }
+    SDValue NanRes = DAG.getSetCC(
+        Dl, MVT::i1,
+        DAG.getNode(ISD::AND, Dl, MVT::i32, HighWord,
+                    DAG.getConstant(QuietMask, Dl, MVT::i32)),
+        DAG.getConstant(0, Dl, MVT::i32), IsQuiet ? ISD::SETNE : ISD::SETEQ);
+    NanRes = DAG.getNode(ISD::AND, Dl, MVT::i1, NanCheck, NanRes);
+    if (Mask == fcQNan || Mask == fcSNan)
+      return NanRes;
+
+    return DAG.getNode(ISD::OR, Dl, MVT::i1,
+                       getDataClassTest(Op, Mask & ~fcNan, Dl, DAG, Subtarget),
+                       NanRes);
+  }
+
+  unsigned NativeMask = 0;
+  if ((Mask & fcNan) == fcNan)
+    NativeMask |= DC_NAN;
+  if (Mask & fcNegInf)
+    NativeMask |= DC_NEG_INF;
+  if (Mask & fcPosInf)
+    NativeMask |= DC_POS_INF;
+  if (Mask & fcNegZero)
+    NativeMask |= DC_NEG_ZERO;
+  if (Mask & fcPosZero)
+    NativeMask |= DC_POS_ZERO;
+  if (Mask & fcNegSubnormal)
+    NativeMask |= DC_NEG_SUBNORM;
+  if (Mask & fcPosSubnormal)
+    NativeMask |= DC_POS_SUBNORM;
+  return SDValue(
+      DAG.getMachineNode(
+          TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1,
+          SDValue(DAG.getMachineNode(
+                      TestOp, Dl, MVT::i32,
+                      DAG.getTargetConstant(NativeMask, Dl, MVT::i32), Op),
+                  0),
+          DAG.getTargetConstant(PPC::sub_eq, Dl, MVT::i32)),
+      0);
+}
+
+SDValue PPCTargetLowering::LowerIS_FPCLASS(SDValue Op,
+                                           SelectionDAG &DAG) const {
+  assert(Subtarget.hasP9Vector() && "Test data class requires Power9");
+  SDValue LHS = Op.getOperand(0);
+  const auto *RHS = cast<ConstantSDNode>(Op.getOperand(1));
+  SDLoc Dl(Op);
+  FPClassTest Category = static_cast<FPClassTest>(RHS->getZExtValue());
+  return getDataClassTest(LHS, Category, Dl, DAG, Subtarget);
+}
+
 SDValue PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDValue Op,
                                                  SelectionDAG &DAG) const {
   SDLoc dl(Op);
@@ -11426,6 +11580,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
     return LowerATOMIC_CMP_SWAP(Op, DAG);
   case ISD::ATOMIC_STORE:
     return LowerATOMIC_LOAD_STORE(Op, DAG);
+  case ISD::IS_FPCLASS:
+    return LowerIS_FPCLASS(Op, DAG);
   }
 }
 

diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 2c3ae03a08167..da5c548782f3a 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -1293,6 +1293,7 @@ namespace llvm {
     SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerBSWAP(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerATOMIC_CMP_SWAP(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerToLibCall(const char *LibCallName, SDValue Op,
                            SelectionDAG &DAG) const;
     SDValue lowerLibCallBasedOnType(const char *LibCallFloatName,

diff  --git a/llvm/test/CodeGen/PowerPC/is_fpclass.ll b/llvm/test/CodeGen/PowerPC/is_fpclass.ll
index e7e02d2163032..a4368a1dca26e 100644
--- a/llvm/test/CodeGen/PowerPC/is_fpclass.ll
+++ b/llvm/test/CodeGen/PowerPC/is_fpclass.ll
@@ -5,10 +5,10 @@
 define i1 @isnan_float(float %x) nounwind {
 ; CHECK-LABEL: isnan_float:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    fcmpu 0, 1, 1
+; CHECK-NEXT:    xststdcsp 0, 1, 64
 ; CHECK-NEXT:    li 3, 0
 ; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    isel 3, 4, 3, 3
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3)  ; nan
   ret i1 %1
@@ -17,10 +17,10 @@ define i1 @isnan_float(float %x) nounwind {
 define i1 @isnan_double(double %x) nounwind {
 ; CHECK-LABEL: isnan_double:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    fcmpu 0, 1, 1
+; CHECK-NEXT:    xststdcdp 0, 1, 64
 ; CHECK-NEXT:    li 3, 0
 ; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    isel 3, 4, 3, 3
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3)  ; nan
   ret i1 %1
@@ -41,10 +41,10 @@ define i1 @isnan_ppc_fp128(ppc_fp128 %x) nounwind {
 define i1 @isnan_f128(fp128 %x) nounwind {
 ; CHECK-LABEL: isnan_f128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xscmpuqp 0, 2, 2
+; CHECK-NEXT:    xststdcqp 0, 2, 64
 ; CHECK-NEXT:    li 3, 0
 ; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    isel 3, 4, 3, 3
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3)  ; nan
   ret i1 %1
@@ -53,14 +53,10 @@ define i1 @isnan_f128(fp128 %x) nounwind {
 define i1 @isnan_float_strictfp(float %x) strictfp nounwind {
 ; CHECK-LABEL: isnan_float_strictfp:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    lis 4, 32640
-; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    clrlwi 3, 3, 1
-; CHECK-NEXT:    cmpw 3, 4
+; CHECK-NEXT:    xststdcsp 0, 1, 64
 ; CHECK-NEXT:    li 3, 0
 ; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    iselgt 3, 4, 3
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3)  ; nan
   ret i1 %1
@@ -69,14 +65,10 @@ define i1 @isnan_float_strictfp(float %x) strictfp nounwind {
 define i1 @isnan_double_strictfp(double %x) strictfp nounwind {
 ; CHECK-LABEL: isnan_double_strictfp:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    li 4, 2047
-; CHECK-NEXT:    clrldi 3, 3, 1
-; CHECK-NEXT:    rldic 4, 4, 52, 1
-; CHECK-NEXT:    cmpd 3, 4
+; CHECK-NEXT:    xststdcdp 0, 1, 64
 ; CHECK-NEXT:    li 3, 0
 ; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    iselgt 3, 4, 3
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3)  ; nan
   ret i1 %1
@@ -101,20 +93,10 @@ define i1 @isnan_ppc_fp128_strictfp(ppc_fp128 %x) strictfp nounwind {
 define i1 @isnan_f128_strictfp(fp128 %x) strictfp nounwind {
 ; CHECK-LABEL: isnan_f128_strictfp:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stxv 34, -16(1)
-; CHECK-NEXT:    li 5, 32767
-; CHECK-NEXT:    ld 4, -8(1)
-; CHECK-NEXT:    ld 3, -16(1)
-; CHECK-NEXT:    rldic 5, 5, 48, 1
-; CHECK-NEXT:    clrldi 4, 4, 1
-; CHECK-NEXT:    cmpld 4, 5
-; CHECK-NEXT:    cmpd 1, 4, 5
-; CHECK-NEXT:    crandc 20, 5, 2
-; CHECK-NEXT:    cmpdi 1, 3, 0
-; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    crandc 21, 2, 6
-; CHECK-NEXT:    crnor 20, 21, 20
-; CHECK-NEXT:    isel 3, 0, 3, 20
+; CHECK-NEXT:    xststdcqp 0, 2, 64
+; CHECK-NEXT:    li 3, 0
+; CHECK-NEXT:    li 4, 1
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3)  ; nan
   ret i1 %1
@@ -123,13 +105,9 @@ define i1 @isnan_f128_strictfp(fp128 %x) strictfp nounwind {
 define i1 @isinf_float(float %x) nounwind {
 ; CHECK-LABEL: isinf_float:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    clrlwi 3, 3, 1
-; CHECK-NEXT:    xoris 3, 3, 32640
-; CHECK-NEXT:    cmplwi 3, 0
+; CHECK-NEXT:    xststdcsp 0, 1, 48
 ; CHECK-NEXT:    li 3, 0
+; CHECK-NEXT:    li 4, 1
 ; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 516)  ; 0x204 = "inf"
@@ -155,16 +133,10 @@ define i1 @isinf_ppc_fp128(ppc_fp128 %x) nounwind {
 define i1 @isinf_f128(fp128 %x) nounwind {
 ; CHECK-LABEL: isinf_f128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stxv 34, -16(1)
-; CHECK-NEXT:    li 5, 32767
-; CHECK-NEXT:    ld 4, -8(1)
-; CHECK-NEXT:    ld 3, -16(1)
-; CHECK-NEXT:    rldic 5, 5, 48, 1
-; CHECK-NEXT:    clrldi 4, 4, 1
-; CHECK-NEXT:    xor 4, 4, 5
-; CHECK-NEXT:    or 3, 3, 4
-; CHECK-NEXT:    cntlzd 3, 3
-; CHECK-NEXT:    rldicl 3, 3, 58, 63
+; CHECK-NEXT:    xststdcqp 0, 2, 48
+; CHECK-NEXT:    li 3, 0
+; CHECK-NEXT:    li 4, 1
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 516)  ; 0x204 = "inf"
   ret i1 %1
@@ -173,14 +145,9 @@ define i1 @isinf_f128(fp128 %x) nounwind {
 define i1 @isfinite_float(float %x) nounwind {
 ; CHECK-LABEL: isfinite_float:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    lis 4, 32640
-; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    clrlwi 3, 3, 1
-; CHECK-NEXT:    cmpw 3, 4
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    xststdcsp 0, 1, 112
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    iseleq 3, 0, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 504)  ; 0x1f8 = "finite"
   ret i1 %1
@@ -189,15 +156,9 @@ define i1 @isfinite_float(float %x) nounwind {
 define i1 @isfinite_f128(fp128 %x) nounwind {
 ; CHECK-LABEL: isfinite_f128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stxv 34, -16(1)
-; CHECK-NEXT:    li 4, 32767
-; CHECK-NEXT:    ld 3, -8(1)
-; CHECK-NEXT:    rldic 4, 4, 48, 1
-; CHECK-NEXT:    clrldi 3, 3, 1
-; CHECK-NEXT:    cmpd 3, 4
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    xststdcqp 0, 2, 112
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    iseleq 3, 0, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 504)  ; 0x1f8 = "finite"
   ret i1 %1
@@ -206,15 +167,9 @@ define i1 @isfinite_f128(fp128 %x) nounwind {
 define i1 @isnormal_float(float %x) nounwind {
 ; CHECK-LABEL: isnormal_float:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    clrlwi 3, 3, 1
-; CHECK-NEXT:    addis 3, 3, -128
-; CHECK-NEXT:    srwi 3, 3, 24
-; CHECK-NEXT:    cmplwi 3, 127
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    xststdcsp 0, 1, 127
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    iseleq 3, 0, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 264)  ; 0x108 = "normal"
   ret i1 %1
@@ -223,17 +178,9 @@ define i1 @isnormal_float(float %x) nounwind {
 define i1 @isnormal_f128(fp128 %x) nounwind {
 ; CHECK-LABEL: isnormal_f128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stxv 34, -16(1)
-; CHECK-NEXT:    li 4, -1
-; CHECK-NEXT:    ld 3, -8(1)
-; CHECK-NEXT:    rldic 4, 4, 48, 0
-; CHECK-NEXT:    clrldi 3, 3, 1
-; CHECK-NEXT:    add 3, 3, 4
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    rldicl 3, 3, 15, 49
-; CHECK-NEXT:    cmpldi 3, 16383
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    xststdcqp 0, 2, 127
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    iseleq 3, 0, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 264)  ; 0x108 = "normal"
   ret i1 %1
@@ -242,16 +189,10 @@ define i1 @isnormal_f128(fp128 %x) nounwind {
 define i1 @issubnormal_float(float %x) nounwind {
 ; CHECK-LABEL: issubnormal_float:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    lis 4, 127
-; CHECK-NEXT:    ori 4, 4, 65535
-; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    clrlwi 3, 3, 1
-; CHECK-NEXT:    addi 3, 3, -1
-; CHECK-NEXT:    cmplw 3, 4
+; CHECK-NEXT:    xststdcsp 0, 1, 3
 ; CHECK-NEXT:    li 3, 0
 ; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 144)  ; 0x90 = "subnormal"
   ret i1 %1
@@ -260,21 +201,10 @@ define i1 @issubnormal_float(float %x) nounwind {
 define i1 @issubnormal_f128(fp128 %x) nounwind {
 ; CHECK-LABEL: issubnormal_f128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stxv 34, -16(1)
-; CHECK-NEXT:    li 5, -1
-; CHECK-NEXT:    ld 4, -8(1)
-; CHECK-NEXT:    ld 3, -16(1)
-; CHECK-NEXT:    rldic 5, 5, 0, 16
-; CHECK-NEXT:    clrldi 4, 4, 1
-; CHECK-NEXT:    addic 3, 3, -1
-; CHECK-NEXT:    addme 4, 4
-; CHECK-NEXT:    cmpdi 1, 3, -1
-; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    cmpld 4, 5
-; CHECK-NEXT:    crandc 20, 0, 2
-; CHECK-NEXT:    crandc 21, 2, 6
-; CHECK-NEXT:    crnor 20, 21, 20
-; CHECK-NEXT:    isel 3, 0, 3, 20
+; CHECK-NEXT:    xststdcqp 0, 2, 3
+; CHECK-NEXT:    li 3, 0
+; CHECK-NEXT:    li 4, 1
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 144)  ; 0x90 = "subnormal"
   ret i1 %1
@@ -283,10 +213,9 @@ define i1 @issubnormal_f128(fp128 %x) nounwind {
 define i1 @iszero_float(float %x) nounwind {
 ; CHECK-LABEL: iszero_float:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xxlxor 0, 0, 0
+; CHECK-NEXT:    xststdcsp 0, 1, 12
 ; CHECK-NEXT:    li 3, 0
 ; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    fcmpu 0, 1, 0
 ; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 96)  ; 0x60 = "zero"
@@ -296,12 +225,9 @@ define i1 @iszero_float(float %x) nounwind {
 define i1 @iszero_f128(fp128 %x) nounwind {
 ; CHECK-LABEL: iszero_f128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    addis 3, 2, .LCPI18_0 at toc@ha
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    addi 3, 3, .LCPI18_0 at toc@l
-; CHECK-NEXT:    lxv 35, 0(3)
+; CHECK-NEXT:    xststdcqp 0, 2, 12
 ; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    xscmpuqp 0, 2, 3
+; CHECK-NEXT:    li 4, 1
 ; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 96)  ; 0x60 = "zero"
@@ -312,14 +238,11 @@ define i1 @issnan_float(float %x) nounwind {
 ; CHECK-LABEL: issnan_float:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    lis 4, 32704
+; CHECK-NEXT:    xststdcsp 1, 1, 64
 ; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    clrlwi 3, 3, 1
-; CHECK-NEXT:    cmpw 3, 4
-; CHECK-NEXT:    lis 4, 32640
-; CHECK-NEXT:    cmpw 1, 3, 4
+; CHECK-NEXT:    andis. 3, 3, 64
 ; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    crnand 20, 5, 0
+; CHECK-NEXT:    crnand 20, 6, 2
 ; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 1)
@@ -330,15 +253,11 @@ define i1 @issnan_double(double %x) nounwind {
 ; CHECK-LABEL: issnan_double:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    li 4, 4095
-; CHECK-NEXT:    clrldi 3, 3, 1
-; CHECK-NEXT:    rldic 4, 4, 51, 1
-; CHECK-NEXT:    cmpd 3, 4
-; CHECK-NEXT:    li 4, 2047
-; CHECK-NEXT:    rldic 4, 4, 52, 1
-; CHECK-NEXT:    cmpd 1, 3, 4
+; CHECK-NEXT:    xststdcdp 1, 1, 64
+; CHECK-NEXT:    rldicl 3, 3, 32, 32
+; CHECK-NEXT:    andis. 3, 3, 8
 ; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    crnand 20, 5, 0
+; CHECK-NEXT:    crnand 20, 6, 2
 ; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 1)
@@ -348,23 +267,12 @@ define i1 @issnan_double(double %x) nounwind {
 define i1 @issnan_fp128(fp128 %x) nounwind {
 ; CHECK-LABEL: issnan_fp128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stxv 34, -16(1)
-; CHECK-NEXT:    li 5, 32767
-; CHECK-NEXT:    ld 4, -8(1)
-; CHECK-NEXT:    ld 3, -16(1)
-; CHECK-NEXT:    rldic 5, 5, 48, 1
-; CHECK-NEXT:    clrldi 4, 4, 1
-; CHECK-NEXT:    cmpld 4, 5
-; CHECK-NEXT:    cmpd 1, 4, 5
-; CHECK-NEXT:    crandc 20, 5, 2
-; CHECK-NEXT:    cmpdi 1, 3, 0
-; CHECK-NEXT:    li 3, -1
-; CHECK-NEXT:    crandc 21, 2, 6
-; CHECK-NEXT:    rldic 3, 3, 47, 1
-; CHECK-NEXT:    cror 20, 21, 20
-; CHECK-NEXT:    cmpd 4, 3
+; CHECK-NEXT:    li 3, 12
+; CHECK-NEXT:    xststdcqp 1, 2, 64
+; CHECK-NEXT:    vextuwrx 3, 3, 2
+; CHECK-NEXT:    andi. 3, 3, 32768
 ; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    crnand 20, 20, 0
+; CHECK-NEXT:    crnand 20, 6, 2
 ; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 1)
@@ -394,14 +302,13 @@ define i1 @isqnan_float(float %x) nounwind {
 ; CHECK-LABEL: isqnan_float:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    lis 4, 32703
-; CHECK-NEXT:    ori 4, 4, 65535
+; CHECK-NEXT:    xststdcsp 1, 1, 64
 ; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    clrlwi 3, 3, 1
-; CHECK-NEXT:    cmpw 3, 4
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    iselgt 3, 4, 3
+; CHECK-NEXT:    srwi 3, 3, 22
+; CHECK-NEXT:    andi. 3, 3, 1
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    crnand 20, 6, 1
+; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 2)
   ret i1 %1
@@ -411,13 +318,12 @@ define i1 @isqnan_double(double %x) nounwind {
 ; CHECK-LABEL: isqnan_double:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    li 4, -17
-; CHECK-NEXT:    clrldi 3, 3, 1
-; CHECK-NEXT:    rldicl 4, 4, 47, 1
-; CHECK-NEXT:    cmpd 3, 4
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    iselgt 3, 4, 3
+; CHECK-NEXT:    xststdcdp 1, 1, 64
+; CHECK-NEXT:    rldicl 3, 3, 13, 51
+; CHECK-NEXT:    andi. 3, 3, 1
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    crnand 20, 6, 1
+; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 2)
   ret i1 %1
@@ -426,15 +332,14 @@ define i1 @isqnan_double(double %x) nounwind {
 define i1 @isqnan_fp128(fp128 %x) nounwind {
 ; CHECK-LABEL: isqnan_fp128:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stxv 34, -16(1)
-; CHECK-NEXT:    li 4, -2
-; CHECK-NEXT:    ld 3, -8(1)
-; CHECK-NEXT:    rldicl 4, 4, 47, 1
-; CHECK-NEXT:    clrldi 3, 3, 1
-; CHECK-NEXT:    cmpd 3, 4
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    iselgt 3, 4, 3
+; CHECK-NEXT:    li 3, 12
+; CHECK-NEXT:    xststdcqp 1, 2, 64
+; CHECK-NEXT:    vextuwrx 3, 3, 2
+; CHECK-NEXT:    srwi 3, 3, 15
+; CHECK-NEXT:    andi. 3, 3, 1
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    crnand 20, 6, 1
+; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 2)
   ret i1 %1
@@ -459,9 +364,10 @@ define i1 @isqnan_ppc_fp128(ppc_fp128 %x) nounwind {
 define i1 @isposzero_double(double %x) nounwind {
 ; CHECK-LABEL: isposzero_double:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    cntlzd 3, 3
-; CHECK-NEXT:    rldicl 3, 3, 58, 63
+; CHECK-NEXT:    xststdcdp 0, 1, 8
+; CHECK-NEXT:    li 3, 0
+; CHECK-NEXT:    li 4, 1
+; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 64)
   ret i1 %1
@@ -470,11 +376,9 @@ define i1 @isposzero_double(double %x) nounwind {
 define i1 @isnegzero_double(double %x) nounwind {
 ; CHECK-LABEL: isnegzero_double:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    rldic 5, 4, 63, 0
-; CHECK-NEXT:    cmpd 3, 5
+; CHECK-NEXT:    xststdcdp 0, 1, 4
 ; CHECK-NEXT:    li 3, 0
+; CHECK-NEXT:    li 4, 1
 ; CHECK-NEXT:    iseleq 3, 4, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 32)
@@ -484,16 +388,9 @@ define i1 @isnegzero_double(double %x) nounwind {
 define i1 @isposnormal_double(double %x) nounwind {
 ; CHECK-LABEL: isposnormal_double:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    li 5, 4095
-; CHECK-NEXT:    clrldi 4, 3, 1
-; CHECK-NEXT:    rldic 5, 5, 52, 0
-; CHECK-NEXT:    cmpdi 1, 3, -1
+; CHECK-NEXT:    xststdcdp 0, 1, 127
 ; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    add 4, 4, 5
-; CHECK-NEXT:    rldicl 4, 4, 11, 53
-; CHECK-NEXT:    cmpldi 4, 1023
-; CHECK-NEXT:    crnand 20, 0, 5
+; CHECK-NEXT:    cror 20, 0, 2
 ; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 256)
@@ -503,16 +400,9 @@ define i1 @isposnormal_double(double %x) nounwind {
 define i1 @isnegnormal_double(double %x) nounwind {
 ; CHECK-LABEL: isnegnormal_double:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    li 5, 4095
-; CHECK-NEXT:    clrldi 4, 3, 1
-; CHECK-NEXT:    rldic 5, 5, 52, 0
-; CHECK-NEXT:    cmpdi 1, 3, 0
+; CHECK-NEXT:    xststdcdp 0, 1, 127
 ; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    add 4, 4, 5
-; CHECK-NEXT:    rldicl 4, 4, 11, 53
-; CHECK-NEXT:    cmpldi 4, 1023
-; CHECK-NEXT:    crnand 20, 0, 4
+; CHECK-NEXT:    crorc 20, 2, 0
 ; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 8)
@@ -522,16 +412,9 @@ define i1 @isnegnormal_double(double %x) nounwind {
 define i1 @isnormal_double(double %x) nounwind {
 ; CHECK-LABEL: isnormal_double:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    li 4, 4095
-; CHECK-NEXT:    clrldi 3, 3, 1
-; CHECK-NEXT:    rldic 4, 4, 52, 0
-; CHECK-NEXT:    add 3, 3, 4
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    rldicl 3, 3, 11, 53
-; CHECK-NEXT:    cmpldi 3, 1023
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    xststdcdp 0, 1, 127
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    iseleq 3, 0, 3
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 264)
   ret i1 %1
@@ -541,24 +424,16 @@ define i1 @isclass_00d_double(double %x) nounwind {
 ; CHECK-LABEL: isclass_00d_double:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mffprd 3, 1
-; CHECK-NEXT:    li 5, 4095
-; CHECK-NEXT:    clrldi 4, 3, 1
-; CHECK-NEXT:    rldic 6, 5, 51, 1
-; CHECK-NEXT:    rldic 5, 5, 52, 0
-; CHECK-NEXT:    cmpd 4, 6
-; CHECK-NEXT:    li 6, 2047
-; CHECK-NEXT:    rldic 6, 6, 52, 1
-; CHECK-NEXT:    cmpd 1, 4, 6
-; CHECK-NEXT:    add 4, 4, 5
-; CHECK-NEXT:    crand 20, 5, 0
-; CHECK-NEXT:    cmpd 3, 5
-; CHECK-NEXT:    rldicl 4, 4, 11, 53
-; CHECK-NEXT:    cmpdi 1, 3, 0
+; CHECK-NEXT:    xststdcdp 0, 1, 127
+; CHECK-NEXT:    xststdcdp 1, 1, 64
+; CHECK-NEXT:    rldicl 3, 3, 32, 32
+; CHECK-NEXT:    crandc 20, 0, 2
+; CHECK-NEXT:    andis. 3, 3, 8
 ; CHECK-NEXT:    li 3, 1
-; CHECK-NEXT:    cror 20, 2, 20
-; CHECK-NEXT:    cmpldi 4, 1023
-; CHECK-NEXT:    crand 21, 0, 4
-; CHECK-NEXT:    crnor 20, 20, 21
+; CHECK-NEXT:    crand 21, 6, 2
+; CHECK-NEXT:    xststdcdp 0, 1, 16
+; CHECK-NEXT:    cror 21, 2, 21
+; CHECK-NEXT:    crnor 20, 21, 20
 ; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 13)
@@ -568,13 +443,12 @@ define i1 @isclass_00d_double(double %x) nounwind {
 define i1 @isclass_1c0_float(float %x) nounwind {
 ; CHECK-LABEL: isclass_1c0_float:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xscvdpspn 0, 1
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    mffprwz 3, 0
-; CHECK-NEXT:    srwi 3, 3, 23
-; CHECK-NEXT:    cmplwi 3, 255
-; CHECK-NEXT:    li 3, 0
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    xststdcsp 0, 1, 127
+; CHECK-NEXT:    li 3, 1
+; CHECK-NEXT:    crnor 20, 0, 2
+; CHECK-NEXT:    xststdcsp 0, 1, 10
+; CHECK-NEXT:    crnor 20, 2, 20
+; CHECK-NEXT:    isel 3, 0, 3, 20
 ; CHECK-NEXT:    blr
   %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 448)
   ret i1 %1


        


More information about the llvm-commits mailing list