diff options
author | Reed Kotler <rkotler@mips.com> | 2014-09-30 16:30:13 +0000 |
---|---|---|
committer | Reed Kotler <rkotler@mips.com> | 2014-09-30 16:30:13 +0000 |
commit | 3ebdcc9ea791033d40b757ce4ad7668279502131 (patch) | |
tree | 614ce8ced6fd8acfc87dcc27c7b7aef486121e19 /llvm/lib/Target/Mips/MipsFastISel.cpp | |
parent | 2c13e71728200cd40aaa0fde3987c45949375433 (diff) | |
download | bcm5719-llvm-3ebdcc9ea791033d40b757ce4ad7668279502131.tar.gz bcm5719-llvm-3ebdcc9ea791033d40b757ce4ad7668279502131.zip |
Add numeric extend, trunctate to mips fast-isel
Summary:
Add numeric extend, trunctate to mips fast-isel
Reactivates D4827
Test Plan:
fpext.ll
loadstoreconv.ll
Reviewers: dsanders
Subscribers: mcrosier
Differential Revision: http://reviews.llvm.org/D5251
llvm-svn: 218681
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, |