[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