diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 8e5cff798f9..4e74b2c639d 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -1060,6 +1060,20 @@ void PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { getI32Imm(0)), 0); return; } + + case PPCISD::MFCR: { + SDOperand InFlag; + Select(InFlag, N->getOperand(1)); + // Use MFOCRF if supported. + if (TLI.getTargetMachine().getSubtarget().isGigaProcessor()) + Result = SDOperand(CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, + N->getOperand(0), InFlag), 0); + else + Result = SDOperand(CurDAG->getTargetNode(PPC::MFCR, MVT::i32, InFlag), 0); + CodeGenMap[Op] = Result; + return; + } + case ISD::SDIV: { // FIXME: since this depends on the setting of the carry flag from the srawi // we should really be making notes about that for the scheduler. diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 01cb343a12f..21c16443b0b 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -22,6 +22,7 @@ #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Constants.h" #include "llvm/Function.h" +#include "llvm/Intrinsics.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -136,6 +137,9 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand); + // We want to custom lower some of our intrinsics. + setOperationAction(ISD::INTRINSIC , MVT::Other, Custom); + if (TM.getSubtarget().is64Bit()) { // They also have instructions for converting between i64 and fp. setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); @@ -230,6 +234,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::STD_32: return "PPCISD::STD_32"; case PPCISD::CALL: return "PPCISD::CALL"; case PPCISD::RET_FLAG: return "PPCISD::RET_FLAG"; + case PPCISD::MFCR: return "PPCISD::MFCR"; + case PPCISD::VCMPo: return "PPCISD::VCMPo"; } } @@ -746,6 +752,80 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { SDOperand VPermMask =DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, ResultMask); return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask); } + case ISD::INTRINSIC: { + bool HasChain = Op.getOperand(0).getValueType() == MVT::Other; + unsigned IntNo=cast(Op.getOperand(HasChain))->getValue(); + + // If this is a lowered altivec predicate compare, CompareOpc is set to the + // opcode number of the comparison. + int CompareOpc = -1; + switch (IntNo) { + default: return SDOperand(); // Don't custom lower most intrinsics. + case Intrinsic::ppc_altivec_vcmpbfp_p: CompareOpc = 966; break; + case Intrinsic::ppc_altivec_vcmpeqfp_p: CompareOpc = 198; break; + case Intrinsic::ppc_altivec_vcmpequb_p: CompareOpc = 6; break; + case Intrinsic::ppc_altivec_vcmpequh_p: CompareOpc = 70; break; + case Intrinsic::ppc_altivec_vcmpequw_p: CompareOpc = 134; break; + case Intrinsic::ppc_altivec_vcmpgefp_p: CompareOpc = 454; break; + case Intrinsic::ppc_altivec_vcmpgtfp_p: CompareOpc = 710; break; + case Intrinsic::ppc_altivec_vcmpgtsb_p: CompareOpc = 774; break; + case Intrinsic::ppc_altivec_vcmpgtsh_p: CompareOpc = 838; break; + case Intrinsic::ppc_altivec_vcmpgtsw_p: CompareOpc = 902; break; + case Intrinsic::ppc_altivec_vcmpgtub_p: CompareOpc = 518; break; + case Intrinsic::ppc_altivec_vcmpgtuh_p: CompareOpc = 582; break; + case Intrinsic::ppc_altivec_vcmpgtuw_p: CompareOpc = 646; break; + } + + assert(CompareOpc>0 && "We only lower altivec predicate compares so far!"); + + // Create the PPCISD altivec 'dot' comparison node. + std::vector Ops; + std::vector VTs; + Ops.push_back(Op.getOperand(2)); // LHS + Ops.push_back(Op.getOperand(3)); // RHS + Ops.push_back(DAG.getConstant(CompareOpc, MVT::i32)); + VTs.push_back(Op.getOperand(2).getValueType()); + VTs.push_back(MVT::Flag); + SDOperand CompNode = DAG.getNode(PPCISD::VCMPo, VTs, Ops); + + // Now that we have the comparison, emit a copy from the CR to a GPR. + // This is flagged to the above dot comparison. + SDOperand Flags = DAG.getNode(PPCISD::MFCR, MVT::i32, + DAG.getRegister(PPC::CR6, MVT::i32), + CompNode.getValue(1)); + + // Unpack the result based on how the target uses it. + unsigned BitNo; // Bit # of CR6. + bool InvertBit; // Invert result? + switch (cast(Op.getOperand(1))->getValue()) { + default: // Can't happen, don't crash on invalid number though. + case 0: // Return the value of the EQ bit of CR6. + BitNo = 0; InvertBit = false; + break; + case 1: // Return the inverted value of the EQ bit of CR6. + BitNo = 0; InvertBit = true; + break; + case 2: // Return the value of the LT bit of CR6. + BitNo = 2; InvertBit = false; + break; + case 3: // Return the inverted value of the LT bit of CR6. + BitNo = 2; InvertBit = true; + break; + } + + // Shift the bit into the low position. + Flags = DAG.getNode(ISD::SRL, MVT::i32, Flags, + DAG.getConstant(8-(3-BitNo), MVT::i32)); + // Isolate the bit. + Flags = DAG.getNode(ISD::AND, MVT::i32, Flags, + DAG.getConstant(1, MVT::i32)); + + // If we are supposed to, toggle the bit. + if (InvertBit) + Flags = DAG.getNode(ISD::XOR, MVT::i32, Flags, + DAG.getConstant(1, MVT::i32)); + return Flags; + } } return SDOperand(); } diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index e131217f94e..cad4ea84d96 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -88,6 +88,17 @@ namespace llvm { /// Return with a flag operand, matched by 'blr' RET_FLAG, + + /// R32 = MFCR(CRREG, INFLAG) - Represents the MFCR/MFOCRF instructions. + /// This copies the bits corresponding to the specified CRREG into the + /// resultant GPR. Bits corresponding to other CR regs are undefined. + MFCR, + + /// RESVEC, OUTFLAG = VCMPo(LHS, RHS, OPC) - Represents one of the + /// altivec VCMP*o instructions. For lack of better number, we use the + /// opcode number encoding for the OPC field to identify the compare. For + /// example, 838 is VCMPGTSH. + VCMPo }; } diff --git a/lib/Target/PowerPC/PPCInstrAltivec.td b/lib/Target/PowerPC/PPCInstrAltivec.td index 1c3057d884e..bc7221b88cf 100644 --- a/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/lib/Target/PowerPC/PPCInstrAltivec.td @@ -306,28 +306,32 @@ def VCMPBFP : VXRForm_1<966, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), (int_ppc_altivec_vcmpbfp VRRC:$vA, VRRC:$vB))]>; def VCMPBFPo : VXRForm_1<966, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpbfp. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v4f32 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 966)))]>, isVDOT; def VCMPEQFP : VXRForm_1<198, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpeqfp $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpeqfp VRRC:$vA, VRRC:$vB))]>; def VCMPEQFPo : VXRForm_1<198, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpeqfp. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v4f32 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 198)))]>, isVDOT; def VCMPGEFP : VXRForm_1<454, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgefp $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgefp VRRC:$vA, VRRC:$vB))]>; def VCMPGEFPo : VXRForm_1<454, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgefp. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v4f32 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 454)))]>, isVDOT; def VCMPGTFP : VXRForm_1<710, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtfp $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgtfp VRRC:$vA, VRRC:$vB))]>; def VCMPGTFPo : VXRForm_1<710, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtfp. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v4f32 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 710)))]>, isVDOT; // i8 element comparisons. def VCMPEQUB : VXRForm_1<6, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), @@ -336,21 +340,24 @@ def VCMPEQUB : VXRForm_1<6, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), (int_ppc_altivec_vcmpequb VRRC:$vA, VRRC:$vB))]>; def VCMPEQUBo : VXRForm_1<6, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpequb. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v16i8 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 6)))]>, isVDOT; def VCMPGTSB : VXRForm_1<774, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtsb $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgtsb VRRC:$vA, VRRC:$vB))]>; def VCMPGTSBo : VXRForm_1<774, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtsb. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v16i8 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 774)))]>, isVDOT; def VCMPGTUB : VXRForm_1<518, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtub $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgtub VRRC:$vA, VRRC:$vB))]>; def VCMPGTUBo : VXRForm_1<518, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtub. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v16i8 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 518)))]>, isVDOT; // i16 element comparisons. def VCMPEQUH : VXRForm_1<70, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), @@ -359,21 +366,24 @@ def VCMPEQUH : VXRForm_1<70, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), (int_ppc_altivec_vcmpequh VRRC:$vA, VRRC:$vB))]>; def VCMPEQUHo : VXRForm_1<70, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpequh. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v8i16 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 70)))]>, isVDOT; def VCMPGTSH : VXRForm_1<838, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtsh $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgtsh VRRC:$vA, VRRC:$vB))]>; def VCMPGTSHo : VXRForm_1<838, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtsh. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v8i16 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 838)))]>, isVDOT; def VCMPGTUH : VXRForm_1<582, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtuh $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgtuh VRRC:$vA, VRRC:$vB))]>; def VCMPGTUHo : VXRForm_1<582, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtuh. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v8i16 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 582)))]>, isVDOT; // i32 element comparisons. def VCMPEQUW : VXRForm_1<134, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), @@ -382,21 +392,24 @@ def VCMPEQUW : VXRForm_1<134, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), (int_ppc_altivec_vcmpequw VRRC:$vA, VRRC:$vB))]>; def VCMPEQUWo : VXRForm_1<134, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpequw. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v4i32 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 134)))]>, isVDOT; def VCMPGTSW : VXRForm_1<902, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtsw $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgtsw VRRC:$vA, VRRC:$vB))]>; def VCMPGTSWo : VXRForm_1<902, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtsw. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v4i32 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 902)))]>, isVDOT; def VCMPGTUW : VXRForm_1<646, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtuw $vD, $vA, $vB", VecFPCompare, [(set VRRC:$vD, (int_ppc_altivec_vcmpgtuw VRRC:$vA, VRRC:$vB))]>; def VCMPGTUWo : VXRForm_1<646, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vcmpgtuw. $vD, $vA, $vB", VecFPCompare, - []>, isVDOT; + [(set VRRC:$vD, (v4i32 + (PPCvcmp_o VRRC:$vA, VRRC:$vB, 646)))]>, isVDOT; def V_SET0 : VXForm_setzero<1220, (ops VRRC:$vD), "vxor $vD, $vD, $vD", VecFP, diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 90573881f06..518d266bdd6 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -30,6 +30,10 @@ def SDT_PPCvperm : SDTypeProfile<1, 3, [ SDTCisVT<3, v16i8>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2> ]>; +def SDT_PPCvcmp_o : SDTypeProfile<1, 3, [ + SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32> +]>; + //===----------------------------------------------------------------------===// // PowerPC specific DAG Nodes. // @@ -68,6 +72,8 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeq,[SDNPHasChain]>; def retflag : SDNode<"PPCISD::RET_FLAG", SDT_PPCRetFlag, [SDNPHasChain, SDNPOptInFlag]>; +def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp_o, [SDNPOutFlag]>; + //===----------------------------------------------------------------------===// // PowerPC specific transformation functions and pattern fragments. // @@ -701,11 +707,11 @@ def MFVRSAVE : XFXForm_1_ext<31, 339, 256, (ops GPRC:$rT), "mfspr $rT, 256", IntGeneral>, PPC970_DGroup_First, PPC970_Unit_FXU; -def MFCR : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>, - PPC970_MicroCode, PPC970_Unit_CRU; def MTCRF : XFXForm_5<31, 144, (ops crbitm:$FXM, GPRC:$rS), "mtcrf $FXM, $rS", BrMCRX>, PPC970_MicroCode, PPC970_Unit_CRU; +def MFCR : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>, + PPC970_MicroCode, PPC970_Unit_CRU; def MFOCRF: XFXForm_5a<31, 19, (ops GPRC:$rT, crbitm:$FXM), "mfcr $rT, $FXM", SprMFCR>, PPC970_DGroup_First, PPC970_Unit_CRU;