diff options
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 14 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 80 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.h | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrAltivec.td | 39 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.td | 10 | 
5 files changed, 139 insertions, 15 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 8e5cff798f9..4e74b2c639d 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/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<PPCSubtarget>().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/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 01cb343a12f..21c16443b0b 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/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<PPCSubtarget>().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<ConstantSDNode>(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<SDOperand> Ops; +    std::vector<MVT::ValueType> 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<ConstantSDNode>(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/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index e131217f94e..cad4ea84d96 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/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/llvm/lib/Target/PowerPC/PPCInstrAltivec.td b/llvm/lib/Target/PowerPC/PPCInstrAltivec.td index 1c3057d884e..bc7221b88cf 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/llvm/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/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 90573881f06..518d266bdd6 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/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;  | 

