diff options
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 32 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp | 222 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrFormats.td | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrInfo.td | 55 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb.td | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb2.td | 118 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrVFP.td | 20 | 
7 files changed, 137 insertions, 326 deletions
| diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index beb843ca9aa..cedfc6d4495 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -727,7 +727,6 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,        MI.eraseFromParent();        return true;      } -      case ARM::MOVCCsr: {        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsr),                (MI.getOperand(1).getReg())) @@ -743,13 +742,14 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,        MI.eraseFromParent();        return true;      } +    case ARM::t2MOVCCi16:      case ARM::MOVCCi16: { -      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi16), +      unsigned NewOpc = AFI->isThumbFunction() ? ARM::t2MOVi16 : ARM::MOVi16; +      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),                MI.getOperand(1).getReg())          .addImm(MI.getOperand(2).getImm())          .addImm(MI.getOperand(3).getImm()) // 'pred'          .addReg(MI.getOperand(4).getReg()); -        MI.eraseFromParent();        return true;      } @@ -766,8 +766,10 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,        MI.eraseFromParent();        return true;      } +    case ARM::t2MVNCCi:      case ARM::MVNCCi: { -      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MVNi), +      unsigned Opc = AFI->isThumbFunction() ? ARM::t2MVNi : ARM::MVNi; +      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),                MI.getOperand(1).getReg())          .addImm(MI.getOperand(2).getImm())          .addImm(MI.getOperand(3).getImm()) // 'pred' @@ -777,6 +779,28 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,        MI.eraseFromParent();        return true;      } +    case ARM::t2MOVCClsl: +    case ARM::t2MOVCClsr: +    case ARM::t2MOVCCasr: +    case ARM::t2MOVCCror: { +      unsigned NewOpc; +      switch (Opcode) { +      case ARM::t2MOVCClsl: NewOpc = ARM::t2LSLri; break; +      case ARM::t2MOVCClsr: NewOpc = ARM::t2LSRri; break; +      case ARM::t2MOVCCasr: NewOpc = ARM::t2ASRri; break; +      case ARM::t2MOVCCror: NewOpc = ARM::t2RORri; break; +      default: llvm_unreachable("unexpeced conditional move"); +      } +      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc), +              MI.getOperand(1).getReg()) +        .addReg(MI.getOperand(2).getReg()) +        .addImm(MI.getOperand(3).getImm()) +        .addImm(MI.getOperand(4).getImm()) // 'pred' +        .addReg(MI.getOperand(5).getReg()) +        .addReg(0); // 's' bit +      MI.eraseFromParent(); +      return true; +    }      case ARM::Int_eh_sjlj_dispatchsetup: {        MachineFunction &MF = *MI.getParent()->getParent();        const ARMBaseInstrInfo *AII = diff --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp index 3298b73dad2..c2dbcb9750c 100644 --- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -130,6 +130,13 @@ public:      return true;    } +  bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) { +    const ConstantSDNode *CN = cast<ConstantSDNode>(N); +    Pred = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); +    Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32); +    return true; +  } +    bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,                               SDValue &Offset, SDValue &Opc);    bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, @@ -239,21 +246,6 @@ private:    /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.    SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned); -  /// SelectCMOVOp - Select CMOV instructions for ARM. -  SDNode *SelectCMOVOp(SDNode *N); -  SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                              ARMCC::CondCodes CCVal, SDValue CCR, -                              SDValue InFlag); -  SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                               ARMCC::CondCodes CCVal, SDValue CCR, -                               SDValue InFlag); -  SDNode *SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                              ARMCC::CondCodes CCVal, SDValue CCR, -                              SDValue InFlag); -  SDNode *SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                               ARMCC::CondCodes CCVal, SDValue CCR, -                               SDValue InFlag); -    // Select special operations if node forms integer ABS pattern    SDNode *SelectABSOp(SDNode *N); @@ -2321,204 +2313,6 @@ SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,    return NULL;  } -SDNode *ARMDAGToDAGISel:: -SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                    ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { -  SDValue CPTmp0; -  SDValue CPTmp1; -  if (SelectT2ShifterOperandReg(TrueVal, CPTmp0, CPTmp1)) { -    unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue(); -    unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); -    unsigned Opc = 0; -    switch (SOShOp) { -    case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; -    case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; -    case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; -    case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; -    default: -      llvm_unreachable("Unknown so_reg opcode!"); -    } -    SDValue SOShImm = -      CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); -    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); -    SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; -    return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6); -  } -  return 0; -} - -SDNode *ARMDAGToDAGISel:: -SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                     ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { -  SDValue CPTmp0; -  SDValue CPTmp1; -  SDValue CPTmp2; -  if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp2)) { -    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); -    SDValue Ops[] = { FalseVal, CPTmp0, CPTmp2, CC, CCR, InFlag }; -    return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 6); -  } - -  if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) { -    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); -    SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; -    return CurDAG->SelectNodeTo(N, ARM::MOVCCsr, MVT::i32, Ops, 7); -  } -  return 0; -} - -SDNode *ARMDAGToDAGISel:: -SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                  ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { -  ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); -  if (!T) -    return 0; - -  unsigned Opc = 0; -  unsigned TrueImm = T->getZExtValue(); -  if (is_t2_so_imm(TrueImm)) { -    Opc = ARM::t2MOVCCi; -  } else if (TrueImm <= 0xffff) { -    Opc = ARM::t2MOVCCi16; -  } else if (is_t2_so_imm_not(TrueImm)) { -    TrueImm = ~TrueImm; -    Opc = ARM::t2MVNCCi; -  } else if (TrueVal.getNode()->hasOneUse() && Subtarget->hasV6T2Ops()) { -    // Large immediate. -    Opc = ARM::t2MOVCCi32imm; -  } - -  if (Opc) { -    SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32); -    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); -    SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; -    return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); -  } - -  return 0; -} - -SDNode *ARMDAGToDAGISel:: -SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, -                   ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { -  ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); -  if (!T) -    return 0; - -  unsigned Opc = 0; -  unsigned TrueImm = T->getZExtValue(); -  bool isSoImm = is_so_imm(TrueImm); -  if (isSoImm) { -    Opc = ARM::MOVCCi; -  } else if (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff) { -    Opc = ARM::MOVCCi16; -  } else if (is_so_imm_not(TrueImm)) { -    TrueImm = ~TrueImm; -    Opc = ARM::MVNCCi; -  } else if (TrueVal.getNode()->hasOneUse() && -             (Subtarget->hasV6T2Ops() || ARM_AM::isSOImmTwoPartVal(TrueImm))) { -    // Large immediate. -    Opc = ARM::MOVCCi32imm; -  } - -  if (Opc) { -    SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32); -    SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); -    SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; -    return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); -  } - -  return 0; -} - -SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { -  EVT VT = N->getValueType(0); -  SDValue FalseVal = N->getOperand(0); -  SDValue TrueVal  = N->getOperand(1); -  SDValue CC = N->getOperand(2); -  SDValue CCR = N->getOperand(3); -  SDValue InFlag = N->getOperand(4); -  assert(CC.getOpcode() == ISD::Constant); -  assert(CCR.getOpcode() == ISD::Register); -  ARMCC::CondCodes CCVal = -    (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue(); - -  if (!Subtarget->isThumb1Only() && VT == MVT::i32) { -    // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) -    // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) -    // Pattern complexity = 18  cost = 1  size = 0 -    if (Subtarget->isThumb()) { -      SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal, -                                        CCVal, CCR, InFlag); -      if (!Res) -        Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal, -                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag); -      if (Res) -        return Res; -    } else { -      SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal, -                                         CCVal, CCR, InFlag); -      if (!Res) -        Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal, -                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag); -      if (Res) -        return Res; -    } - -    // Pattern: (ARMcmov:i32 GPR:i32:$false, -    //             (imm:i32)<<P:Pred_so_imm>>:$true, -    //             (imm:i32):$cc) -    // Emits: (MOVCCi:i32 GPR:i32:$false, -    //           (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) -    // Pattern complexity = 10  cost = 1  size = 0 -    if (Subtarget->isThumb()) { -      SDNode *Res = SelectT2CMOVImmOp(N, FalseVal, TrueVal, -                                        CCVal, CCR, InFlag); -      if (!Res) -        Res = SelectT2CMOVImmOp(N, TrueVal, FalseVal, -                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag); -      if (Res) -        return Res; -    } else { -      SDNode *Res = SelectARMCMOVImmOp(N, FalseVal, TrueVal, -                                         CCVal, CCR, InFlag); -      if (!Res) -        Res = SelectARMCMOVImmOp(N, TrueVal, FalseVal, -                               ARMCC::getOppositeCondition(CCVal), CCR, InFlag); -      if (Res) -        return Res; -    } -  } - -  // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) -  // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) -  // Pattern complexity = 6  cost = 1  size = 0 -  // -  // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) -  // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) -  // Pattern complexity = 6  cost = 11  size = 0 -  // -  // Also VMOVScc and VMOVDcc. -  SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); -  SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; -  unsigned Opc = 0; -  switch (VT.getSimpleVT().SimpleTy) { -  default: llvm_unreachable("Illegal conditional move type!"); -  case MVT::i32: -    Opc = Subtarget->isThumb() -      ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) -      : ARM::MOVCCr; -    break; -  case MVT::f32: -    Opc = ARM::VMOVScc; -    break; -  case MVT::f64: -    Opc = ARM::VMOVDcc; -    break; -  } -  return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); -} -  /// Target-specific DAG combining for ISD::XOR.  /// Target-independent combining lowers SELECT_CC nodes of the form  /// select_cc setg[ge] X,  0,  X, -X @@ -2882,8 +2676,6 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {                  SDValue(Chain.getNode(), Chain.getResNo()));      return NULL;    } -  case ARMISD::CMOV: -    return SelectCMOVOp(N);    case ARMISD::VZIP: {      unsigned Opc = 0;      EVT VT = N->getValueType(0); diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 1349476d7c7..6d4de3dd99b 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -155,6 +155,16 @@ def pred : PredicateOperand<OtherVT, (ops i32imm, i32imm),    let DecoderMethod = "DecodePredicateOperand";  } +// Selectable predicate operand for CMOV instructions. We can't use a normal +// predicate because the default values interfere with instruction selection. In +// all other respects it is identical though: pseudo-instruction expansion +// relies on the MachineOperands being compatible. +def cmovpred : Operand<i32>, PredicateOp, +               ComplexPattern<i32, 2, "SelectCMOVPred"> { +  let MIOperandInfo = (ops i32imm, i32imm); +  let PrintMethod = "printPredicateOperand"; +} +  // Conditional code result for instructions whose 's' bit is set, e.g. subs.  def CCOutOperand : AsmOperandClass { let Name = "CCOut"; }  def cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 zero_reg))> { diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index 3b836671ce3..a4ea69f7a8b 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -4146,56 +4146,65 @@ def BCCZi64 : PseudoInst<(outs),  // Conditional moves -// FIXME: should be able to write a pattern for ARMcmov, but can't use -// a two-value operand where a dag node expects two operands. :(  let neverHasSideEffects = 1 in {  let isCommutable = 1, isSelect = 1 in -def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p), +def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), +                           (ins GPR:$false, GPR:$Rm, cmovpred:$p),                             4, IIC_iCMOVr, -  [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, -      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; +                           [(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, +                                                   cmovpred:$p))]>, +             RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;  def MOVCCsi : ARMPseudoInst<(outs GPR:$Rd), -                           (ins GPR:$false, so_reg_imm:$shift, pred:$p), -                           4, IIC_iCMOVsr, -  [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_imm:$shift, -                            imm:$cc, CCR:$ccr))*/]>, +                            (ins GPR:$false, so_reg_imm:$shift, cmovpred:$p), +                            4, IIC_iCMOVsr, +                            [(set GPR:$Rd, +                                  (ARMcmov GPR:$false, so_reg_imm:$shift, +                                           cmovpred:$p))]>,        RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;  def MOVCCsr : ARMPseudoInst<(outs GPR:$Rd), -                           (ins GPR:$false, so_reg_reg:$shift, pred:$p), +                            (ins GPR:$false, so_reg_reg:$shift, cmovpred:$p),                             4, IIC_iCMOVsr, -  [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_reg:$shift, -                            imm:$cc, CCR:$ccr))*/]>, +  [(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_reg:$shift, +                            cmovpred:$p))]>,        RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;  let isMoveImm = 1 in -def MOVCCi16 : ARMPseudoInst<(outs GPR:$Rd), -                             (ins GPR:$false, imm0_65535_expr:$imm, pred:$p), -                             4, IIC_iMOVi, -                             []>, +def MOVCCi16 +    : ARMPseudoInst<(outs GPR:$Rd), +                    (ins GPR:$false, imm0_65535_expr:$imm, cmovpred:$p), +                    4, IIC_iMOVi, +                    [(set GPR:$Rd, (ARMcmov GPR:$false, imm0_65535:$imm, +                                            cmovpred:$p))]>,        RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>,        Sched<[WriteALU]>;  let isMoveImm = 1 in  def MOVCCi : ARMPseudoInst<(outs GPR:$Rd), -                           (ins GPR:$false, so_imm:$imm, pred:$p), +                           (ins GPR:$false, so_imm:$imm, cmovpred:$p),                             4, IIC_iCMOVi, -   [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, +                           [(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, +                                                   cmovpred:$p))]>,        RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;  // Two instruction predicate mov immediate.  let isMoveImm = 1 in -def MOVCCi32imm : ARMPseudoInst<(outs GPR:$Rd), -                                (ins GPR:$false, i32imm:$src, pred:$p), -                  8, IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">; +def MOVCCi32imm +    : ARMPseudoInst<(outs GPR:$Rd), +                    (ins GPR:$false, i32imm:$src, cmovpred:$p), +                    8, IIC_iCMOVix2, +                    [(set GPR:$Rd, (ARMcmov GPR:$false, imm:$src, +                                            cmovpred:$p))]>, +      RegConstraint<"$false = $Rd">, Requires<[HasV6T2]>;  let isMoveImm = 1 in  def MVNCCi : ARMPseudoInst<(outs GPR:$Rd), -                           (ins GPR:$false, so_imm:$imm, pred:$p), +                           (ins GPR:$false, so_imm:$imm, cmovpred:$p),                             4, IIC_iCMOVi, - [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm, imm:$cc, CCR:$ccr))*/]>, +                           [(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm, +                                                   cmovpred:$p))]>,                  RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;  } // neverHasSideEffects diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index 7e383d2b0d1..291b98abd70 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -1204,9 +1204,9 @@ def tUXTH :                     // A8.6.264  // Expanded after instruction selection into a branch sequence.  let usesCustomInserter = 1 in  // Expanded after instruction selection.    def tMOVCCr_pseudo : -  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), -              NoItinerary, -             [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; +  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, cmovpred:$p), +             NoItinerary, +             [(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, cmovpred:$p))]>;  // tLEApcrel - Load a pc-relative address into a register without offending the  // assembler. diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index 3498e41ba1b..f3464cc2773 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -3032,93 +3032,67 @@ defm t2TEQ  : T2I_cmp_irs<0b0100, "teq",                           BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>>;  // Conditional moves -// FIXME: should be able to write a pattern for ARMcmov, but can't use -// a two-value operand where a dag node expects two operands. :(  let neverHasSideEffects = 1 in {  let isCommutable = 1, isSelect = 1 in  def t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd), -                            (ins rGPR:$false, rGPR:$Rm, pred:$p), +                            (ins rGPR:$false, rGPR:$Rm, cmovpred:$p),                              4, IIC_iCMOVr, -   [/*(set rGPR:$Rd, (ARMcmov rGPR:$false, rGPR:$Rm, imm:$cc, CCR:$ccr))*/]>, -                RegConstraint<"$false = $Rd">, -                Sched<[WriteALU]>; +                            [(set rGPR:$Rd, (ARMcmov rGPR:$false, rGPR:$Rm, +                                                     cmovpred:$p))]>, +               RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;  let isMoveImm = 1 in -def t2MOVCCi : t2PseudoInst<(outs rGPR:$Rd), -                            (ins rGPR:$false, t2_so_imm:$imm, pred:$p), +def t2MOVCCi +    : t2PseudoInst<(outs rGPR:$Rd), +                   (ins rGPR:$false, t2_so_imm:$imm, cmovpred:$p),                     4, IIC_iCMOVi, -[/*(set rGPR:$Rd,(ARMcmov rGPR:$false,t2_so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, -                   RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; +                   [(set rGPR:$Rd, (ARMcmov rGPR:$false,t2_so_imm:$imm, +                                            cmovpred:$p))]>, +      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; -// FIXME: Pseudo-ize these. For now, just mark codegen only.  let isCodeGenOnly = 1 in {  let isMoveImm = 1 in -def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, imm0_65535_expr:$imm), -                      IIC_iCMOVi, -                      "movw", "\t$Rd, $imm", []>, -                      RegConstraint<"$false = $Rd">, Sched<[WriteALU]> { -  let Inst{31-27} = 0b11110; -  let Inst{25} = 1; -  let Inst{24-21} = 0b0010; -  let Inst{20} = 0; // The S bit. -  let Inst{15} = 0; - -  bits<4> Rd; -  bits<16> imm; - -  let Inst{11-8}  = Rd; -  let Inst{19-16} = imm{15-12}; -  let Inst{26}    = imm{11}; -  let Inst{14-12} = imm{10-8}; -  let Inst{7-0}   = imm{7-0}; -} +def t2MOVCCi16 +    : t2PseudoInst<(outs rGPR:$Rd), +                   (ins  rGPR:$false, imm0_65535_expr:$imm, cmovpred:$p), +                   4, IIC_iCMOVi, +                   [(set rGPR:$Rd, (ARMcmov rGPR:$false, imm0_65535:$imm, +                                            cmovpred:$p))]>, +      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;  let isMoveImm = 1 in -def t2MOVCCi32imm : PseudoInst<(outs rGPR:$dst), -                               (ins rGPR:$false, i32imm:$src, pred:$p), -                    IIC_iCMOVix2, []>, RegConstraint<"$false = $dst">; +def t2MVNCCi +    : t2PseudoInst<(outs rGPR:$Rd), +                   (ins rGPR:$false, t2_so_imm:$imm, cmovpred:$p), +                   4, IIC_iCMOVi, +                   [(set rGPR:$Rd, +                         (ARMcmov rGPR:$false, t2_so_imm_not:$imm, +                                  cmovpred:$p))]>, +      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; + +class MOVCCShPseudo<SDPatternOperator opnode, Operand ty> +    : t2PseudoInst<(outs rGPR:$Rd), +                   (ins rGPR:$false, rGPR:$Rm, i32imm:$imm, cmovpred:$p), +                   4, IIC_iCMOVsi, +                   [(set rGPR:$Rd, (ARMcmov rGPR:$false, +                                            (opnode rGPR:$Rm, (i32 ty:$imm)), +                                            cmovpred:$p))]>, +      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; + +def t2MOVCClsl : MOVCCShPseudo<shl,  imm0_31>; +def t2MOVCClsr : MOVCCShPseudo<srl,  imm_sr>; +def t2MOVCCasr : MOVCCShPseudo<sra,  imm_sr>; +def t2MOVCCror : MOVCCShPseudo<rotr, imm0_31>;  let isMoveImm = 1 in -def t2MVNCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm), -                   IIC_iCMOVi, "mvn", "\t$Rd, $imm", -[/*(set rGPR:$Rd,(ARMcmov rGPR:$false,t2_so_imm_not:$imm, -                   imm:$cc, CCR:$ccr))*/]>, -                   RegConstraint<"$false = $Rd">, Sched<[WriteALU]> { -  let Inst{31-27} = 0b11110; -  let Inst{25} = 0; -  let Inst{24-21} = 0b0011; -  let Inst{20} = 0; // The S bit. -  let Inst{19-16} = 0b1111; // Rn -  let Inst{15} = 0; -} - -class T2I_movcc_sh<bits<2> opcod, dag oops, dag iops, InstrItinClass itin, -                   string opc, string asm, list<dag> pattern> -  : T2TwoRegShiftImm<oops, iops, itin, opc, asm, pattern>, Sched<[WriteALU]> { -  let Inst{31-27} = 0b11101; -  let Inst{26-25} = 0b01; -  let Inst{24-21} = 0b0010; -  let Inst{20} = 0; // The S bit. -  let Inst{19-16} = 0b1111; // Rn -  let Inst{5-4} = opcod; // Shift type. -} -def t2MOVCClsl : T2I_movcc_sh<0b00, (outs rGPR:$Rd), -                             (ins rGPR:$false, rGPR:$Rm, i32imm:$imm), -                             IIC_iCMOVsi, "lsl", ".w\t$Rd, $Rm, $imm", []>, -                 RegConstraint<"$false = $Rd">; -def t2MOVCClsr : T2I_movcc_sh<0b01, (outs rGPR:$Rd), -                             (ins rGPR:$false, rGPR:$Rm, i32imm:$imm), -                             IIC_iCMOVsi, "lsr", ".w\t$Rd, $Rm, $imm", []>, -                 RegConstraint<"$false = $Rd">; -def t2MOVCCasr : T2I_movcc_sh<0b10, (outs rGPR:$Rd), -                             (ins rGPR:$false, rGPR:$Rm, i32imm:$imm), -                             IIC_iCMOVsi, "asr", ".w\t$Rd, $Rm, $imm", []>, -                 RegConstraint<"$false = $Rd">; -def t2MOVCCror : T2I_movcc_sh<0b11, (outs rGPR:$Rd), -                             (ins rGPR:$false, rGPR:$Rm, i32imm:$imm), -                             IIC_iCMOVsi, "ror", ".w\t$Rd, $Rm, $imm", []>, -                 RegConstraint<"$false = $Rd">; +def t2MOVCCi32imm +    : t2PseudoInst<(outs rGPR:$dst), +                   (ins rGPR:$false, i32imm:$src, cmovpred:$p), +                   8, IIC_iCMOVix2, +                   [(set rGPR:$dst, (ARMcmov rGPR:$false, imm:$src, +                                             cmovpred:$p))]>, +      RegConstraint<"$false = $dst">;  } // isCodeGenOnly = 1  } // neverHasSideEffects diff --git a/llvm/lib/Target/ARM/ARMInstrVFP.td b/llvm/lib/Target/ARM/ARMInstrVFP.td index f9cfa15a731..c6b8bc3f929 100644 --- a/llvm/lib/Target/ARM/ARMInstrVFP.td +++ b/llvm/lib/Target/ARM/ARMInstrVFP.td @@ -1466,15 +1466,17 @@ def : Pat<(fneg (f32 (fma SPR:$Sn, (fneg SPR:$Sm), SPR:$Sdin))),  //  let neverHasSideEffects = 1 in { -def VMOVDcc  : ARMPseudoInst<(outs DPR:$Dd), (ins DPR:$Dn, DPR:$Dm, pred:$p), -                    4, IIC_fpUNA64, -                    [/*(set DPR:$Dd, (ARMcmov DPR:$Dn, DPR:$Dm, imm:$cc))*/]>, -                 RegConstraint<"$Dn = $Dd">; - -def VMOVScc  : ARMPseudoInst<(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm, pred:$p), -                    4, IIC_fpUNA32, -                    [/*(set SPR:$Sd, (ARMcmov SPR:$Sn, SPR:$Sm, imm:$cc))*/]>, -                 RegConstraint<"$Sn = $Sd">; +def VMOVDcc  : PseudoInst<(outs DPR:$Dd), (ins DPR:$Dn, DPR:$Dm, cmovpred:$p), +                    IIC_fpUNA64, +                    [(set (f64 DPR:$Dd), +                          (ARMcmov DPR:$Dn, DPR:$Dm, cmovpred:$p))]>, +               RegConstraint<"$Dn = $Dd">, Requires<[HasVFP2]>; + +def VMOVScc  : PseudoInst<(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm, cmovpred:$p), +                    IIC_fpUNA32, +                    [(set (f32 SPR:$Sd), +                          (ARMcmov SPR:$Sn, SPR:$Sm, cmovpred:$p))]>, +               RegConstraint<"$Sn = $Sd">, Requires<[HasVFP2]>;  } // neverHasSideEffects  //===----------------------------------------------------------------------===// | 

