1 //===-- MipsastISel.cpp - Mips FastISel implementation
2 //---------------------===//
4 #include "llvm/CodeGen/FunctionLoweringInfo.h"
5 #include "llvm/CodeGen/FastISel.h"
6 #include "llvm/CodeGen/MachineInstrBuilder.h"
7 #include "llvm/IR/GlobalAlias.h"
8 #include "llvm/IR/GlobalVariable.h"
9 #include "llvm/Target/TargetInstrInfo.h"
10 #include "llvm/Target/TargetLibraryInfo.h"
11 #include "MipsRegisterInfo.h"
12 #include "MipsISelLowering.h"
13 #include "MipsMachineFunction.h"
14 #include "MipsSubtarget.h"
15 #include "MipsTargetMachine.h"
21 class MipsFastISel final : public FastISel {
23 // All possible address modes.
26 typedef enum { RegBase, FrameIndexBase } BaseKind;
37 const GlobalValue *GV;
40 // Innocuous defaults for our address.
41 Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
42 void setKind(BaseKind K) { Kind = K; }
43 BaseKind getKind() const { return Kind; }
44 bool isRegBase() const { return Kind == RegBase; }
45 void setReg(unsigned Reg) {
46 assert(isRegBase() && "Invalid base register access!");
49 unsigned getReg() const {
50 assert(isRegBase() && "Invalid base register access!");
53 void setOffset(int64_t Offset_) { Offset = Offset_; }
54 int64_t getOffset() const { return Offset; }
55 void setGlobalValue(const GlobalValue *G) { GV = G; }
56 const GlobalValue *getGlobalValue() { return GV; }
59 /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
60 /// make the right decision when generating code for different targets.
62 const TargetMachine &TM;
63 const TargetInstrInfo &TII;
64 const TargetLowering &TLI;
65 const MipsSubtarget *Subtarget;
66 MipsFunctionInfo *MFI;
68 // Convenience variables to avoid some queries.
72 bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle
73 // floating point but not reject doing fast-isel in other
77 // Selection routines.
78 bool selectLoad(const Instruction *I);
79 bool selectStore(const Instruction *I);
80 bool selectBranch(const Instruction *I);
81 bool selectCmp(const Instruction *I);
82 bool selectFPExt(const Instruction *I);
83 bool selectFPTrunc(const Instruction *I);
84 bool selectFPToInt(const Instruction *I, bool IsSigned);
85 bool selectRet(const Instruction *I);
86 bool selectTrunc(const Instruction *I);
87 bool selectIntExt(const Instruction *I);
89 // Utility helper routines.
91 bool isTypeLegal(Type *Ty, MVT &VT);
92 bool isLoadTypeLegal(Type *Ty, MVT &VT);
93 bool computeAddress(const Value *Obj, Address &Addr);
95 // Emit helper routines.
96 bool emitCmp(unsigned DestReg, const CmpInst *CI);
97 bool emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
98 unsigned Alignment = 0);
99 bool emitStore(MVT VT, unsigned SrcReg, Address &Addr,
100 unsigned Alignment = 0);
101 bool emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg,
104 bool emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
106 bool emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
107 bool emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
109 bool emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
112 unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned);
114 unsigned materializeFP(const ConstantFP *CFP, MVT VT);
115 unsigned materializeGV(const GlobalValue *GV, MVT VT);
116 unsigned materializeInt(const Constant *C, MVT VT);
117 unsigned materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC);
119 MachineInstrBuilder emitInst(unsigned Opc) {
120 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
122 MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) {
123 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
126 MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg,
127 unsigned MemReg, int64_t MemOffset) {
128 return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
130 MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg,
131 unsigned MemReg, int64_t MemOffset) {
132 return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
134 // for some reason, this default is not generated by tablegen
135 // so we explicitly generate it here.
137 unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC,
138 unsigned Op0, bool Op0IsKill, uint64_t imm1,
139 uint64_t imm2, unsigned Op3, bool Op3IsKill) {
144 // Backend specific FastISel code.
146 explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
147 const TargetLibraryInfo *libInfo)
148 : FastISel(funcInfo, libInfo),
149 M(const_cast<Module &>(*funcInfo.Fn->getParent())),
150 TM(funcInfo.MF->getTarget()),
151 TII(*TM.getSubtargetImpl()->getInstrInfo()),
152 TLI(*TM.getSubtargetImpl()->getTargetLowering()),
153 Subtarget(&TM.getSubtarget<MipsSubtarget>()) {
154 MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
155 Context = &funcInfo.Fn->getContext();
156 TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
157 ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) &&
158 (Subtarget->isABI_O32())));
159 UnsupportedFPMode = Subtarget->isFP64bit();
162 unsigned fastMaterializeConstant(const Constant *C) override;
163 bool fastSelectInstruction(const Instruction *I) override;
165 #include "MipsGenFastISel.inc"
167 } // end anonymous namespace.
169 unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) {
170 if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
172 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
173 const ConstantInt *CI = cast<ConstantInt>(C);
175 if ((VT != MVT::i1) && CI->isNegative())
176 Imm = CI->getSExtValue();
178 Imm = CI->getZExtValue();
179 return materialize32BitInt(Imm, RC);
182 unsigned MipsFastISel::materialize32BitInt(int64_t Imm,
183 const TargetRegisterClass *RC) {
184 unsigned ResultReg = createResultReg(RC);
186 if (isInt<16>(Imm)) {
187 unsigned Opc = Mips::ADDiu;
188 emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
190 } else if (isUInt<16>(Imm)) {
191 emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
194 unsigned Lo = Imm & 0xFFFF;
195 unsigned Hi = (Imm >> 16) & 0xFFFF;
197 // Both Lo and Hi have nonzero bits.
198 unsigned TmpReg = createResultReg(RC);
199 emitInst(Mips::LUi, TmpReg).addImm(Hi);
200 emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
202 emitInst(Mips::LUi, ResultReg).addImm(Hi);
207 unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
208 if (UnsupportedFPMode)
210 int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
211 if (VT == MVT::f32) {
212 const TargetRegisterClass *RC = &Mips::FGR32RegClass;
213 unsigned DestReg = createResultReg(RC);
214 unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass);
215 emitInst(Mips::MTC1, DestReg).addReg(TempReg);
217 } else if (VT == MVT::f64) {
218 const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
219 unsigned DestReg = createResultReg(RC);
220 unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
222 materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
223 emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
229 unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) {
230 // For now 32-bit only.
233 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
234 unsigned DestReg = createResultReg(RC);
235 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
236 bool IsThreadLocal = GVar && GVar->isThreadLocal();
237 // TLS not supported at this time.
240 emitInst(Mips::LW, DestReg)
241 .addReg(MFI->getGlobalBaseReg())
242 .addGlobalAddress(GV, 0, MipsII::MO_GOT);
243 if ((GV->hasInternalLinkage() ||
244 (GV->hasLocalLinkage() && !isa<Function>(GV)))) {
245 unsigned TempReg = createResultReg(RC);
246 emitInst(Mips::ADDiu, TempReg)
248 .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO);
254 // Materialize a constant into a register, and return the register
255 // number (or zero if we failed to handle it).
256 unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
257 EVT CEVT = TLI.getValueType(C->getType(), true);
259 // Only handle simple types.
260 if (!CEVT.isSimple())
262 MVT VT = CEVT.getSimpleVT();
264 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
265 return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT);
266 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
267 return materializeGV(GV, VT);
268 else if (isa<ConstantInt>(C))
269 return materializeInt(C, VT);
274 bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
275 // This construct looks a big awkward but it is how other ports handle this
276 // and as this function is more fully completed, these cases which
277 // return false will have additional code in them.
279 if (isa<Instruction>(Obj))
281 else if (isa<ConstantExpr>(Obj))
283 Addr.setReg(getRegForValue(Obj));
284 return Addr.getReg() != 0;
287 bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
288 EVT evt = TLI.getValueType(Ty, true);
289 // Only handle simple types.
290 if (evt == MVT::Other || !evt.isSimple())
292 VT = evt.getSimpleVT();
294 // Handle all legal types, i.e. a register that will directly hold this
296 return TLI.isTypeLegal(VT);
299 bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
300 if (isTypeLegal(Ty, VT))
302 // We will extend this in a later patch:
303 // If this is a type than can be sign or zero-extended to a basic operation
304 // go ahead and accept it now.
305 if (VT == MVT::i8 || VT == MVT::i16)
309 // Because of how EmitCmp is called with fast-isel, you can
310 // end up with redundant "andi" instructions after the sequences emitted below.
311 // We should try and solve this issue in the future.
313 bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
314 const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1);
315 bool IsUnsigned = CI->isUnsigned();
316 unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned);
319 unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned);
322 CmpInst::Predicate P = CI->getPredicate();
327 case CmpInst::ICMP_EQ: {
328 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
329 emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
330 emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1);
333 case CmpInst::ICMP_NE: {
334 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
335 emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
336 emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
339 case CmpInst::ICMP_UGT: {
340 emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
343 case CmpInst::ICMP_ULT: {
344 emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
347 case CmpInst::ICMP_UGE: {
348 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
349 emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
350 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
353 case CmpInst::ICMP_ULE: {
354 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
355 emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg);
356 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
359 case CmpInst::ICMP_SGT: {
360 emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
363 case CmpInst::ICMP_SLT: {
364 emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
367 case CmpInst::ICMP_SGE: {
368 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
369 emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
370 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
373 case CmpInst::ICMP_SLE: {
374 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
375 emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg);
376 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
379 case CmpInst::FCMP_OEQ:
380 case CmpInst::FCMP_UNE:
381 case CmpInst::FCMP_OLT:
382 case CmpInst::FCMP_OLE:
383 case CmpInst::FCMP_OGT:
384 case CmpInst::FCMP_OGE: {
385 if (UnsupportedFPMode)
387 bool IsFloat = Left->getType()->isFloatTy();
388 bool IsDouble = Left->getType()->isDoubleTy();
389 if (!IsFloat && !IsDouble)
391 unsigned Opc, CondMovOpc;
393 case CmpInst::FCMP_OEQ:
394 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
395 CondMovOpc = Mips::MOVT_I;
397 case CmpInst::FCMP_UNE:
398 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
399 CondMovOpc = Mips::MOVF_I;
401 case CmpInst::FCMP_OLT:
402 Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32;
403 CondMovOpc = Mips::MOVT_I;
405 case CmpInst::FCMP_OLE:
406 Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32;
407 CondMovOpc = Mips::MOVT_I;
409 case CmpInst::FCMP_OGT:
410 Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32;
411 CondMovOpc = Mips::MOVF_I;
413 case CmpInst::FCMP_OGE:
414 Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32;
415 CondMovOpc = Mips::MOVF_I;
418 llvm_unreachable("Only switching of a subset of CCs.");
420 unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass);
421 unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
422 emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
423 emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
424 emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
425 Mips::FCC0, RegState::ImplicitDefine);
426 MachineInstrBuilder MI = emitInst(CondMovOpc, ResultReg)
429 .addReg(RegWithZero, RegState::Implicit);
430 MI->tieOperands(0, 3);
436 bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
437 unsigned Alignment) {
439 // more cases will be handled here in following patches.
442 switch (VT.SimpleTy) {
444 ResultReg = createResultReg(&Mips::GPR32RegClass);
449 ResultReg = createResultReg(&Mips::GPR32RegClass);
454 ResultReg = createResultReg(&Mips::GPR32RegClass);
459 if (UnsupportedFPMode)
461 ResultReg = createResultReg(&Mips::FGR32RegClass);
466 if (UnsupportedFPMode)
468 ResultReg = createResultReg(&Mips::AFGR64RegClass);
475 emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
479 bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr,
480 unsigned Alignment) {
482 // more cases will be handled here in following patches.
485 switch (VT.SimpleTy) {
496 if (UnsupportedFPMode)
501 if (UnsupportedFPMode)
508 emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
512 bool MipsFastISel::selectLoad(const Instruction *I) {
513 // Atomic loads need special handling.
514 if (cast<LoadInst>(I)->isAtomic())
517 // Verify we have a legal type before going any further.
519 if (!isLoadTypeLegal(I->getType(), VT))
522 // See if we can handle this address.
524 if (!computeAddress(I->getOperand(0), Addr))
528 if (!emitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
530 updateValueMap(I, ResultReg);
534 bool MipsFastISel::selectStore(const Instruction *I) {
535 Value *Op0 = I->getOperand(0);
538 // Atomic stores need special handling.
539 if (cast<StoreInst>(I)->isAtomic())
542 // Verify we have a legal type before going any further.
544 if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
547 // Get the value to be stored into a register.
548 SrcReg = getRegForValue(Op0);
552 // See if we can handle this address.
554 if (!computeAddress(I->getOperand(1), Addr))
557 if (!emitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
563 // This can cause a redundant sltiu to be generated.
564 // FIXME: try and eliminate this in a future patch.
566 bool MipsFastISel::selectBranch(const Instruction *I) {
567 const BranchInst *BI = cast<BranchInst>(I);
568 MachineBasicBlock *BrBB = FuncInfo.MBB;
570 // TBB is the basic block for the case where the comparison is true.
571 // FBB is the basic block for the case where the comparison is false.
572 // if (cond) goto TBB
576 MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
577 MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
579 // For now, just try the simplest case where it's fed by a compare.
580 if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
581 unsigned CondReg = createResultReg(&Mips::GPR32RegClass);
582 if (!emitCmp(CondReg, CI))
584 BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ))
587 fastEmitBranch(FBB, DbgLoc);
588 FuncInfo.MBB->addSuccessor(TBB);
594 bool MipsFastISel::selectCmp(const Instruction *I) {
595 const CmpInst *CI = cast<CmpInst>(I);
596 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
597 if (!emitCmp(ResultReg, CI))
599 updateValueMap(I, ResultReg);
603 // Attempt to fast-select a floating-point extend instruction.
604 bool MipsFastISel::selectFPExt(const Instruction *I) {
605 if (UnsupportedFPMode)
607 Value *Src = I->getOperand(0);
608 EVT SrcVT = TLI.getValueType(Src->getType(), true);
609 EVT DestVT = TLI.getValueType(I->getType(), true);
611 if (SrcVT != MVT::f32 || DestVT != MVT::f64)
615 getRegForValue(Src); // his must be a 32 bit floating point register class
616 // maybe we should handle this differently
620 unsigned DestReg = createResultReg(&Mips::AFGR64RegClass);
621 emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg);
622 updateValueMap(I, DestReg);
626 // Attempt to fast-select a floating-point truncate instruction.
627 bool MipsFastISel::selectFPTrunc(const Instruction *I) {
628 if (UnsupportedFPMode)
630 Value *Src = I->getOperand(0);
631 EVT SrcVT = TLI.getValueType(Src->getType(), true);
632 EVT DestVT = TLI.getValueType(I->getType(), true);
634 if (SrcVT != MVT::f64 || DestVT != MVT::f32)
637 unsigned SrcReg = getRegForValue(Src);
641 unsigned DestReg = createResultReg(&Mips::FGR32RegClass);
645 emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg);
646 updateValueMap(I, DestReg);
650 // Attempt to fast-select a floating-point-to-integer conversion.
651 bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) {
652 if (UnsupportedFPMode)
656 return false; // We don't handle this case yet. There is no native
657 // instruction for this but it can be synthesized.
658 Type *DstTy = I->getType();
659 if (!isTypeLegal(DstTy, DstVT))
662 if (DstVT != MVT::i32)
665 Value *Src = I->getOperand(0);
666 Type *SrcTy = Src->getType();
667 if (!isTypeLegal(SrcTy, SrcVT))
670 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
673 unsigned SrcReg = getRegForValue(Src);
677 // Determine the opcode for the conversion, which takes place
678 // entirely within FPRs.
679 unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
680 unsigned TempReg = createResultReg(&Mips::FGR32RegClass);
683 if (SrcVT == MVT::f32)
684 Opc = Mips::TRUNC_W_S;
686 Opc = Mips::TRUNC_W_D32;
688 // Generate the convert.
689 emitInst(Opc, TempReg).addReg(SrcReg);
691 emitInst(Mips::MFC1, DestReg).addReg(TempReg);
693 updateValueMap(I, DestReg);
697 bool MipsFastISel::selectRet(const Instruction *I) {
698 const ReturnInst *Ret = cast<ReturnInst>(I);
700 if (!FuncInfo.CanLowerReturn)
702 if (Ret->getNumOperands() > 0) {
705 emitInst(Mips::RetRA);
709 bool MipsFastISel::selectTrunc(const Instruction *I) {
710 // The high bits for a type smaller than the register size are assumed to be
712 Value *Op = I->getOperand(0);
715 SrcVT = TLI.getValueType(Op->getType(), true);
716 DestVT = TLI.getValueType(I->getType(), true);
718 if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
720 if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
723 unsigned SrcReg = getRegForValue(Op);
727 // Because the high bits are undefined, a truncate doesn't generate
729 updateValueMap(I, SrcReg);
732 bool MipsFastISel::selectIntExt(const Instruction *I) {
733 Type *DestTy = I->getType();
734 Value *Src = I->getOperand(0);
735 Type *SrcTy = Src->getType();
737 bool isZExt = isa<ZExtInst>(I);
738 unsigned SrcReg = getRegForValue(Src);
743 SrcEVT = TLI.getValueType(SrcTy, true);
744 DestEVT = TLI.getValueType(DestTy, true);
745 if (!SrcEVT.isSimple())
747 if (!DestEVT.isSimple())
750 MVT SrcVT = SrcEVT.getSimpleVT();
751 MVT DestVT = DestEVT.getSimpleVT();
752 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
754 if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt))
756 updateValueMap(I, ResultReg);
759 bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
762 switch (SrcVT.SimpleTy) {
772 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
773 emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt);
774 emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt);
778 bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
780 switch (SrcVT.SimpleTy) {
784 emitInst(Mips::SEB, DestReg).addReg(SrcReg);
787 emitInst(Mips::SEH, DestReg).addReg(SrcReg);
793 bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
795 if ((DestVT != MVT::i32) && (DestVT != MVT::i16))
797 if (Subtarget->hasMips32r2())
798 return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg);
799 return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg);
802 bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
804 switch (SrcVT.SimpleTy) {
808 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1);
811 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff);
814 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff);
819 bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
820 unsigned DestReg, bool IsZExt) {
822 return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg);
823 return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg);
825 bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
826 if (!TargetSupported)
828 switch (I->getOpcode()) {
831 case Instruction::Load:
832 return selectLoad(I);
833 case Instruction::Store:
834 return selectStore(I);
835 case Instruction::Br:
836 return selectBranch(I);
837 case Instruction::Ret:
839 case Instruction::Trunc:
840 return selectTrunc(I);
841 case Instruction::ZExt:
842 case Instruction::SExt:
843 return selectIntExt(I);
844 case Instruction::FPTrunc:
845 return selectFPTrunc(I);
846 case Instruction::FPExt:
847 return selectFPExt(I);
848 case Instruction::FPToSI:
849 return selectFPToInt(I, /*isSigned*/ true);
850 case Instruction::FPToUI:
851 return selectFPToInt(I, /*isSigned*/ false);
852 case Instruction::ICmp:
853 case Instruction::FCmp:
859 unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V,
861 unsigned VReg = getRegForValue(V);
864 MVT VMVT = TLI.getValueType(V->getType(), true).getSimpleVT();
865 if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) {
866 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
867 if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned))
875 FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
876 const TargetLibraryInfo *libInfo) {
877 return new MipsFastISel(funcInfo, libInfo);