diff options
Diffstat (limited to 'llvm/lib/Target/Mips/MipsFastISel.cpp')
| -rw-r--r-- | llvm/lib/Target/Mips/MipsFastISel.cpp | 173 | 
1 files changed, 168 insertions, 5 deletions
| diff --git a/llvm/lib/Target/Mips/MipsFastISel.cpp b/llvm/lib/Target/Mips/MipsFastISel.cpp index e5857a0100e..bd3d08527b7 100644 --- a/llvm/lib/Target/Mips/MipsFastISel.cpp +++ b/llvm/lib/Target/Mips/MipsFastISel.cpp @@ -78,6 +78,9 @@ private:    bool SelectLoad(const Instruction *I);    bool SelectRet(const Instruction *I);    bool SelectStore(const Instruction *I); +  bool SelectIntExt(const Instruction *I); +  bool SelectTrunc(const Instruction *I); +  bool SelectFPExt(const Instruction *I);    bool isTypeLegal(Type *Ty, MVT &VT);    bool isLoadTypeLegal(Type *Ty, MVT &VT); @@ -87,6 +90,16 @@ private:    unsigned MaterializeInt(const Constant *C, MVT VT);    unsigned Materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC); +  bool EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, +                  bool IsZExt); + +  bool EmitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); + +  bool EmitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); +  bool EmitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, +                       unsigned DestReg); +  bool EmitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, +                       unsigned DestReg);    // for some reason, this default is not generated by tablegen    // so we explicitly generate it here.    // @@ -242,6 +255,74 @@ bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,    return true;  } +bool MipsFastISel::EmitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, +                                   unsigned DestReg) { +  unsigned ShiftAmt; +  switch (SrcVT.SimpleTy) { +  default: +    return false; +  case MVT::i8: +    ShiftAmt = 24; +    break; +  case MVT::i16: +    ShiftAmt = 16; +    break; +  } +  unsigned TempReg = createResultReg(&Mips::GPR32RegClass); +  EmitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt); +  EmitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt); +  return true; +} + +bool MipsFastISel::EmitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, +                                   unsigned DestReg) { +  switch (SrcVT.SimpleTy) { +  default: +    return false; +  case MVT::i8: +    EmitInst(Mips::SEB, DestReg).addReg(SrcReg); +    break; +  case MVT::i16: +    EmitInst(Mips::SEH, DestReg).addReg(SrcReg); +    break; +  } +  return true; +} + +bool MipsFastISel::EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, +                              unsigned DestReg, bool IsZExt) { +  if (IsZExt) +    return EmitIntZExt(SrcVT, SrcReg, DestVT, DestReg); +  return EmitIntSExt(SrcVT, SrcReg, DestVT, DestReg); +} + +bool MipsFastISel::EmitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, +                               unsigned DestReg) { +  if ((DestVT != MVT::i32) && (DestVT != MVT::i16)) +    return false; +  if (Subtarget->hasMips32r2()) +    return EmitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg); +  return EmitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg); +} + +bool MipsFastISel::EmitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, +                               unsigned DestReg) { +  switch (SrcVT.SimpleTy) { +  default: +    return false; +  case MVT::i1: +    EmitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1); +    break; +  case MVT::i8: +    EmitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff); +    break; +  case MVT::i16: +    EmitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff); +    break; +  } +  return true; +} +  bool MipsFastISel::SelectLoad(const Instruction *I) {    // Atomic loads need special handling.    if (cast<LoadInst>(I)->isAtomic()) @@ -304,6 +385,79 @@ bool MipsFastISel::SelectRet(const Instruction *I) {    return true;  } +// Attempt to fast-select a floating-point extend instruction. +bool MipsFastISel::SelectFPExt(const Instruction *I) { +  Value *Src = I->getOperand(0); +  EVT SrcVT = TLI.getValueType(Src->getType(), true); +  EVT DestVT = TLI.getValueType(I->getType(), true); + +  if (SrcVT != MVT::f32 || DestVT != MVT::f64) +    return false; + +  unsigned SrcReg = +      getRegForValue(Src); // his must be a 32 bit floating point register class +                           // maybe we should handle this differently +  if (!SrcReg) +    return false; + +  unsigned DestReg = createResultReg(&Mips::AFGR64RegClass); +  EmitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg); +  updateValueMap(I, DestReg); +  return true; +} + +bool MipsFastISel::SelectIntExt(const Instruction *I) { +  Type *DestTy = I->getType(); +  Value *Src = I->getOperand(0); +  Type *SrcTy = Src->getType(); + +  bool isZExt = isa<ZExtInst>(I); +  unsigned SrcReg = getRegForValue(Src); +  if (!SrcReg) +    return false; + +  EVT SrcEVT, DestEVT; +  SrcEVT = TLI.getValueType(SrcTy, true); +  DestEVT = TLI.getValueType(DestTy, true); +  if (!SrcEVT.isSimple()) +    return false; +  if (!DestEVT.isSimple()) +    return false; + +  MVT SrcVT = SrcEVT.getSimpleVT(); +  MVT DestVT = DestEVT.getSimpleVT(); +  unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + +  if (!EmitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt)) +    return false; +  updateValueMap(I, ResultReg); +  return true; +} + +bool MipsFastISel::SelectTrunc(const Instruction *I) { +  // The high bits for a type smaller than the register size are assumed to be +  // undefined. +  Value *Op = I->getOperand(0); + +  EVT SrcVT, DestVT; +  SrcVT = TLI.getValueType(Op->getType(), true); +  DestVT = TLI.getValueType(I->getType(), true); + +  if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8) +    return false; +  if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1) +    return false; + +  unsigned SrcReg = getRegForValue(Op); +  if (!SrcReg) +    return false; + +  // Because the high bits are undefined, a truncate doesn't generate +  // any code. +  updateValueMap(I, SrcReg); +  return true; +} +  bool MipsFastISel::fastSelectInstruction(const Instruction *I) {    if (!TargetSupported)      return false; @@ -316,10 +470,16 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) {      return SelectStore(I);    case Instruction::Ret:      return SelectRet(I); +  case Instruction::Trunc: +    return SelectTrunc(I); +  case Instruction::ZExt: +  case Instruction::SExt: +    return SelectIntExt(I); +  case Instruction::FPExt: +    return SelectFPExt(I);    }    return false;  } -}  unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) {    int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); @@ -352,13 +512,15 @@ unsigned MipsFastISel::MaterializeGV(const GlobalValue *GV, MVT VT) {    // TLS not supported at this time.    if (IsThreadLocal)      return 0; -  EmitInst(Mips::LW, DestReg).addReg(MFI->getGlobalBaseReg()).addGlobalAddress( -      GV, 0, MipsII::MO_GOT); +  EmitInst(Mips::LW, DestReg) +      .addReg(MFI->getGlobalBaseReg()) +      .addGlobalAddress(GV, 0, MipsII::MO_GOT);    if ((GV->hasInternalLinkage() ||         (GV->hasLocalLinkage() && !isa<Function>(GV)))) {      unsigned TempReg = createResultReg(RC); -    EmitInst(Mips::ADDiu, TempReg).addReg(DestReg).addGlobalAddress( -        GV, 0, MipsII::MO_ABS_LO); +    EmitInst(Mips::ADDiu, TempReg) +        .addReg(DestReg) +        .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO);      DestReg = TempReg;    }    return DestReg; @@ -401,6 +563,7 @@ unsigned MipsFastISel::Materialize32BitInt(int64_t Imm,    }    return ResultReg;  } +}  namespace llvm {  FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo, | 

