blob: c7ba4add3e508cc8a1a2960b428c1ab1e188af48 [file] [log] [blame]
Reed Kotler720c5ca2014-04-17 22:15:34 +00001//===-- MipsastISel.cpp - Mips FastISel implementation
2//---------------------===//
3
4#include "llvm/CodeGen/FunctionLoweringInfo.h"
5#include "llvm/CodeGen/FastISel.h"
Reed Kotler67077b32014-04-29 17:57:50 +00006#include "llvm/CodeGen/MachineInstrBuilder.h"
Reed Kotlerbab3f232014-05-01 20:39:21 +00007#include "llvm/IR/GlobalAlias.h"
8#include "llvm/IR/GlobalVariable.h"
Reed Kotler67077b32014-04-29 17:57:50 +00009#include "llvm/Target/TargetInstrInfo.h"
Reed Kotler720c5ca2014-04-17 22:15:34 +000010#include "llvm/Target/TargetLibraryInfo.h"
Reed Kotlerbab3f232014-05-01 20:39:21 +000011#include "MipsRegisterInfo.h"
Reed Kotler720c5ca2014-04-17 22:15:34 +000012#include "MipsISelLowering.h"
Reed Kotler67077b32014-04-29 17:57:50 +000013#include "MipsMachineFunction.h"
14#include "MipsSubtarget.h"
Reed Kotler9fe25f32014-06-08 02:08:43 +000015#include "MipsTargetMachine.h"
Reed Kotler720c5ca2014-04-17 22:15:34 +000016
17using namespace llvm;
18
19namespace {
20
Reed Kotlerbab3f232014-05-01 20:39:21 +000021// All possible address modes.
22typedef struct Address {
23 enum { RegBase, FrameIndexBase } BaseType;
24
25 union {
26 unsigned Reg;
27 int FI;
28 } Base;
29
30 int64_t Offset;
31
32 // Innocuous defaults for our address.
33 Address() : BaseType(RegBase), Offset(0) { Base.Reg = 0; }
34} Address;
35
Reed Kotler720c5ca2014-04-17 22:15:34 +000036class MipsFastISel final : public FastISel {
37
Reed Kotler67077b32014-04-29 17:57:50 +000038 /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
39 /// make the right decision when generating code for different targets.
Reed Kotler67077b32014-04-29 17:57:50 +000040 Module &M;
41 const TargetMachine &TM;
42 const TargetInstrInfo &TII;
43 const TargetLowering &TLI;
Eric Christopher22405e42014-07-10 17:26:51 +000044 const MipsSubtarget *Subtarget;
Reed Kotler67077b32014-04-29 17:57:50 +000045 MipsFunctionInfo *MFI;
46
47 // Convenience variables to avoid some queries.
48 LLVMContext *Context;
49
50 bool TargetSupported;
Reed Kotler12f94882014-10-10 17:00:46 +000051 bool UnsupportedFPMode;
Reed Kotler67077b32014-04-29 17:57:50 +000052
Reed Kotler720c5ca2014-04-17 22:15:34 +000053public:
54 explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
55 const TargetLibraryInfo *libInfo)
Reed Kotler67077b32014-04-29 17:57:50 +000056 : FastISel(funcInfo, libInfo),
57 M(const_cast<Module &>(*funcInfo.Fn->getParent())),
Eric Christopherd9134482014-08-04 21:25:23 +000058 TM(funcInfo.MF->getTarget()),
59 TII(*TM.getSubtargetImpl()->getInstrInfo()),
60 TLI(*TM.getSubtargetImpl()->getTargetLowering()),
Eric Christopher22405e42014-07-10 17:26:51 +000061 Subtarget(&TM.getSubtarget<MipsSubtarget>()) {
Reed Kotler67077b32014-04-29 17:57:50 +000062 MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
63 Context = &funcInfo.Fn->getContext();
Eric Christopher22405e42014-07-10 17:26:51 +000064 TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
Reed Kotler32be74b2014-09-15 20:30:25 +000065 ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) &&
66 (Subtarget->isABI_O32())));
Reed Kotler12f94882014-10-10 17:00:46 +000067 UnsupportedFPMode = Subtarget->isFP64bit();
Reed Kotler67077b32014-04-29 17:57:50 +000068 }
69
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +000070 bool fastSelectInstruction(const Instruction *I) override;
71 unsigned fastMaterializeConstant(const Constant *C) override;
Reed Kotler67077b32014-04-29 17:57:50 +000072
Reed Kotlerbab3f232014-05-01 20:39:21 +000073 bool ComputeAddress(const Value *Obj, Address &Addr);
74
75private:
Reed Kotler9fe3bfd2014-06-16 22:05:47 +000076 bool EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
77 unsigned Alignment = 0);
Reed Kotlerbab3f232014-05-01 20:39:21 +000078 bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
79 unsigned Alignment = 0);
Reed Kotler9fe3bfd2014-06-16 22:05:47 +000080 bool SelectLoad(const Instruction *I);
Reed Kotler67077b32014-04-29 17:57:50 +000081 bool SelectRet(const Instruction *I);
Reed Kotlerbab3f232014-05-01 20:39:21 +000082 bool SelectStore(const Instruction *I);
Reed Kotler3ebdcc92014-09-30 16:30:13 +000083 bool SelectIntExt(const Instruction *I);
84 bool SelectTrunc(const Instruction *I);
85 bool SelectFPExt(const Instruction *I);
Reed Kotlerb9dc2482014-10-01 18:47:02 +000086 bool SelectFPTrunc(const Instruction *I);
Reed Kotler12f94882014-10-10 17:00:46 +000087 bool SelectFPToI(const Instruction *I, bool IsSigned);
Reed Kotler497311a2014-10-10 17:39:51 +000088 bool SelectCmp(const Instruction *I);
Reed Kotlerbab3f232014-05-01 20:39:21 +000089
90 bool isTypeLegal(Type *Ty, MVT &VT);
91 bool isLoadTypeLegal(Type *Ty, MVT &VT);
92
Reed Kotler497311a2014-10-10 17:39:51 +000093 unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned);
94
Reed Kotlerbab3f232014-05-01 20:39:21 +000095 unsigned MaterializeFP(const ConstantFP *CFP, MVT VT);
96 unsigned MaterializeGV(const GlobalValue *GV, MVT VT);
97 unsigned MaterializeInt(const Constant *C, MVT VT);
Reed Kotler6280d972014-05-15 21:54:15 +000098 unsigned Materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC);
Reed Kotler9fe25f32014-06-08 02:08:43 +000099
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000100 bool EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg,
101 bool IsZExt);
102
103 bool EmitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
104
105 bool EmitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
106 bool EmitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
107 unsigned DestReg);
108 bool EmitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
109 unsigned DestReg);
Reed Kotler9fe25f32014-06-08 02:08:43 +0000110 // for some reason, this default is not generated by tablegen
Reed Kotlerfb77bc92014-06-08 03:04:42 +0000111 // so we explicitly generate it here.
Reed Kotler9fe25f32014-06-08 02:08:43 +0000112 //
Juergen Ributzka88e32512014-09-03 20:56:59 +0000113 unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC,
Reed Kotler9fe25f32014-06-08 02:08:43 +0000114 unsigned Op0, bool Op0IsKill, uint64_t imm1,
115 uint64_t imm2, unsigned Op3, bool Op3IsKill) {
116 return 0;
117 }
118
Reed Kotlerfb77bc92014-06-08 03:04:42 +0000119 MachineInstrBuilder EmitInst(unsigned Opc) {
120 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
121 }
122
123 MachineInstrBuilder EmitInst(unsigned Opc, unsigned DstReg) {
124 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
125 DstReg);
126 }
127
128 MachineInstrBuilder EmitInstStore(unsigned Opc, unsigned SrcReg,
129 unsigned MemReg, int64_t MemOffset) {
130 return EmitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
131 }
132
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000133 MachineInstrBuilder EmitInstLoad(unsigned Opc, unsigned DstReg,
Reed Kotler87048a42014-08-07 22:09:01 +0000134 unsigned MemReg, int64_t MemOffset) {
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000135 return EmitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
136 }
137
Reed Kotler9fe25f32014-06-08 02:08:43 +0000138#include "MipsGenFastISel.inc"
Reed Kotler720c5ca2014-04-17 22:15:34 +0000139};
Reed Kotler67077b32014-04-29 17:57:50 +0000140
Reed Kotlerbab3f232014-05-01 20:39:21 +0000141bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
142 EVT evt = TLI.getValueType(Ty, true);
143 // Only handle simple types.
144 if (evt == MVT::Other || !evt.isSimple())
145 return false;
146 VT = evt.getSimpleVT();
147
148 // Handle all legal types, i.e. a register that will directly hold this
149 // value.
150 return TLI.isTypeLegal(VT);
151}
152
153bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
154 if (isTypeLegal(Ty, VT))
155 return true;
156 // We will extend this in a later patch:
157 // If this is a type than can be sign or zero-extended to a basic operation
158 // go ahead and accept it now.
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000159 if (VT == MVT::i8 || VT == MVT::i16)
160 return true;
Reed Kotlerbab3f232014-05-01 20:39:21 +0000161 return false;
162}
163
164bool MipsFastISel::ComputeAddress(const Value *Obj, Address &Addr) {
165 // This construct looks a big awkward but it is how other ports handle this
166 // and as this function is more fully completed, these cases which
167 // return false will have additional code in them.
168 //
169 if (isa<Instruction>(Obj))
170 return false;
171 else if (isa<ConstantExpr>(Obj))
172 return false;
173 Addr.Base.Reg = getRegForValue(Obj);
174 return Addr.Base.Reg != 0;
175}
176
Reed Kotler497311a2014-10-10 17:39:51 +0000177unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V,
178 bool IsUnsigned) {
179 unsigned VReg = getRegForValue(V);
180 if (VReg == 0)
181 return 0;
182 MVT VMVT = TLI.getValueType(V->getType(), true).getSimpleVT();
183 if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) {
184 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
185 if (!EmitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned))
186 return 0;
187 VReg = TempReg;
188 }
189 return VReg;
190}
191
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000192bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
193 unsigned Alignment) {
194 //
195 // more cases will be handled here in following patches.
196 //
197 unsigned Opc;
198 switch (VT.SimpleTy) {
199 case MVT::i32: {
200 ResultReg = createResultReg(&Mips::GPR32RegClass);
201 Opc = Mips::LW;
202 break;
203 }
204 case MVT::i16: {
205 ResultReg = createResultReg(&Mips::GPR32RegClass);
206 Opc = Mips::LHu;
207 break;
208 }
209 case MVT::i8: {
210 ResultReg = createResultReg(&Mips::GPR32RegClass);
211 Opc = Mips::LBu;
212 break;
213 }
214 case MVT::f32: {
Reed Kotler12f94882014-10-10 17:00:46 +0000215 if (UnsupportedFPMode)
216 return false;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000217 ResultReg = createResultReg(&Mips::FGR32RegClass);
218 Opc = Mips::LWC1;
219 break;
220 }
221 case MVT::f64: {
Reed Kotler12f94882014-10-10 17:00:46 +0000222 if (UnsupportedFPMode)
223 return false;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000224 ResultReg = createResultReg(&Mips::AFGR64RegClass);
225 Opc = Mips::LDC1;
226 break;
227 }
228 default:
229 return false;
230 }
231 EmitInstLoad(Opc, ResultReg, Addr.Base.Reg, Addr.Offset);
232 return true;
233}
234
Reed Kotlerbab3f232014-05-01 20:39:21 +0000235// Materialize a constant into a register, and return the register
236// number (or zero if we failed to handle it).
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000237unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
Reed Kotlerbab3f232014-05-01 20:39:21 +0000238 EVT CEVT = TLI.getValueType(C->getType(), true);
239
240 // Only handle simple types.
241 if (!CEVT.isSimple())
242 return 0;
243 MVT VT = CEVT.getSimpleVT();
244
245 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
Reed Kotler12f94882014-10-10 17:00:46 +0000246 return (UnsupportedFPMode) ? 0 : MaterializeFP(CFP, VT);
Reed Kotlerbab3f232014-05-01 20:39:21 +0000247 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
248 return MaterializeGV(GV, VT);
249 else if (isa<ConstantInt>(C))
250 return MaterializeInt(C, VT);
251
252 return 0;
253}
254
255bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
256 unsigned Alignment) {
257 //
258 // more cases will be handled here in following patches.
259 //
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000260 unsigned Opc;
261 switch (VT.SimpleTy) {
262 case MVT::i8:
263 Opc = Mips::SB;
264 break;
265 case MVT::i16:
266 Opc = Mips::SH;
267 break;
268 case MVT::i32:
269 Opc = Mips::SW;
270 break;
271 case MVT::f32:
Reed Kotler12f94882014-10-10 17:00:46 +0000272 if (UnsupportedFPMode)
273 return false;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000274 Opc = Mips::SWC1;
275 break;
276 case MVT::f64:
Reed Kotler12f94882014-10-10 17:00:46 +0000277 if (UnsupportedFPMode)
278 return false;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000279 Opc = Mips::SDC1;
280 break;
281 default:
Reed Kotlerbab3f232014-05-01 20:39:21 +0000282 return false;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000283 }
284 EmitInstStore(Opc, SrcReg, Addr.Base.Reg, Addr.Offset);
285 return true;
286}
287
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000288bool MipsFastISel::EmitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
289 unsigned DestReg) {
290 unsigned ShiftAmt;
291 switch (SrcVT.SimpleTy) {
292 default:
293 return false;
294 case MVT::i8:
295 ShiftAmt = 24;
296 break;
297 case MVT::i16:
298 ShiftAmt = 16;
299 break;
300 }
301 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
302 EmitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt);
303 EmitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt);
304 return true;
305}
306
307bool MipsFastISel::EmitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
308 unsigned DestReg) {
309 switch (SrcVT.SimpleTy) {
310 default:
311 return false;
312 case MVT::i8:
313 EmitInst(Mips::SEB, DestReg).addReg(SrcReg);
314 break;
315 case MVT::i16:
316 EmitInst(Mips::SEH, DestReg).addReg(SrcReg);
317 break;
318 }
319 return true;
320}
321
322bool MipsFastISel::EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
323 unsigned DestReg, bool IsZExt) {
324 if (IsZExt)
325 return EmitIntZExt(SrcVT, SrcReg, DestVT, DestReg);
326 return EmitIntSExt(SrcVT, SrcReg, DestVT, DestReg);
327}
328
329bool MipsFastISel::EmitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
330 unsigned DestReg) {
331 if ((DestVT != MVT::i32) && (DestVT != MVT::i16))
332 return false;
333 if (Subtarget->hasMips32r2())
334 return EmitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg);
335 return EmitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg);
336}
337
338bool MipsFastISel::EmitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
339 unsigned DestReg) {
340 switch (SrcVT.SimpleTy) {
341 default:
342 return false;
343 case MVT::i1:
344 EmitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1);
345 break;
346 case MVT::i8:
347 EmitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff);
348 break;
349 case MVT::i16:
350 EmitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff);
351 break;
352 }
353 return true;
354}
355
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000356bool MipsFastISel::SelectLoad(const Instruction *I) {
357 // Atomic loads need special handling.
358 if (cast<LoadInst>(I)->isAtomic())
359 return false;
360
361 // Verify we have a legal type before going any further.
362 MVT VT;
363 if (!isLoadTypeLegal(I->getType(), VT))
364 return false;
365
366 // See if we can handle this address.
367 Address Addr;
368 if (!ComputeAddress(I->getOperand(0), Addr))
369 return false;
370
371 unsigned ResultReg;
372 if (!EmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
373 return false;
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000374 updateValueMap(I, ResultReg);
Reed Kotlerbab3f232014-05-01 20:39:21 +0000375 return true;
376}
377
378bool MipsFastISel::SelectStore(const Instruction *I) {
379 Value *Op0 = I->getOperand(0);
380 unsigned SrcReg = 0;
381
382 // Atomic stores need special handling.
383 if (cast<StoreInst>(I)->isAtomic())
384 return false;
385
386 // Verify we have a legal type before going any further.
387 MVT VT;
388 if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
389 return false;
390
391 // Get the value to be stored into a register.
392 SrcReg = getRegForValue(Op0);
393 if (SrcReg == 0)
394 return false;
395
396 // See if we can handle this address.
397 Address Addr;
398 if (!ComputeAddress(I->getOperand(1), Addr))
399 return false;
400
401 if (!EmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
402 return false;
403 return true;
404}
405
Reed Kotler67077b32014-04-29 17:57:50 +0000406bool MipsFastISel::SelectRet(const Instruction *I) {
407 const ReturnInst *Ret = cast<ReturnInst>(I);
408
409 if (!FuncInfo.CanLowerReturn)
410 return false;
411 if (Ret->getNumOperands() > 0) {
412 return false;
413 }
Reed Kotlerfb77bc92014-06-08 03:04:42 +0000414 EmitInst(Mips::RetRA);
Reed Kotler67077b32014-04-29 17:57:50 +0000415 return true;
416}
417
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000418// Attempt to fast-select a floating-point extend instruction.
419bool MipsFastISel::SelectFPExt(const Instruction *I) {
Reed Kotler12f94882014-10-10 17:00:46 +0000420 if (UnsupportedFPMode)
421 return false;
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000422 Value *Src = I->getOperand(0);
423 EVT SrcVT = TLI.getValueType(Src->getType(), true);
424 EVT DestVT = TLI.getValueType(I->getType(), true);
425
426 if (SrcVT != MVT::f32 || DestVT != MVT::f64)
427 return false;
428
429 unsigned SrcReg =
430 getRegForValue(Src); // his must be a 32 bit floating point register class
431 // maybe we should handle this differently
432 if (!SrcReg)
433 return false;
434
435 unsigned DestReg = createResultReg(&Mips::AFGR64RegClass);
436 EmitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg);
437 updateValueMap(I, DestReg);
438 return true;
439}
440
Reed Kotlerb9dc2482014-10-01 18:47:02 +0000441// Attempt to fast-select a floating-point truncate instruction.
442bool MipsFastISel::SelectFPTrunc(const Instruction *I) {
Reed Kotler12f94882014-10-10 17:00:46 +0000443 if (UnsupportedFPMode)
444 return false;
Reed Kotlerb9dc2482014-10-01 18:47:02 +0000445 Value *Src = I->getOperand(0);
446 EVT SrcVT = TLI.getValueType(Src->getType(), true);
447 EVT DestVT = TLI.getValueType(I->getType(), true);
448
449 if (SrcVT != MVT::f64 || DestVT != MVT::f32)
450 return false;
451
452 unsigned SrcReg = getRegForValue(Src);
453 if (!SrcReg)
454 return false;
455
456 unsigned DestReg = createResultReg(&Mips::FGR32RegClass);
457 if (!DestReg)
458 return false;
459
460 EmitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg);
461 updateValueMap(I, DestReg);
462 return true;
463}
464
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000465bool MipsFastISel::SelectIntExt(const Instruction *I) {
466 Type *DestTy = I->getType();
467 Value *Src = I->getOperand(0);
468 Type *SrcTy = Src->getType();
469
470 bool isZExt = isa<ZExtInst>(I);
471 unsigned SrcReg = getRegForValue(Src);
472 if (!SrcReg)
473 return false;
474
475 EVT SrcEVT, DestEVT;
476 SrcEVT = TLI.getValueType(SrcTy, true);
477 DestEVT = TLI.getValueType(DestTy, true);
478 if (!SrcEVT.isSimple())
479 return false;
480 if (!DestEVT.isSimple())
481 return false;
482
483 MVT SrcVT = SrcEVT.getSimpleVT();
484 MVT DestVT = DestEVT.getSimpleVT();
485 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
486
487 if (!EmitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt))
488 return false;
489 updateValueMap(I, ResultReg);
490 return true;
491}
492
493bool MipsFastISel::SelectTrunc(const Instruction *I) {
494 // The high bits for a type smaller than the register size are assumed to be
495 // undefined.
496 Value *Op = I->getOperand(0);
497
498 EVT SrcVT, DestVT;
499 SrcVT = TLI.getValueType(Op->getType(), true);
500 DestVT = TLI.getValueType(I->getType(), true);
501
502 if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
503 return false;
504 if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
505 return false;
506
507 unsigned SrcReg = getRegForValue(Op);
508 if (!SrcReg)
509 return false;
510
511 // Because the high bits are undefined, a truncate doesn't generate
512 // any code.
513 updateValueMap(I, SrcReg);
514 return true;
515}
516
Reed Kotler12f94882014-10-10 17:00:46 +0000517// Attempt to fast-select a floating-point-to-integer conversion.
518bool MipsFastISel::SelectFPToI(const Instruction *I, bool IsSigned) {
519 if (UnsupportedFPMode)
520 return false;
521 MVT DstVT, SrcVT;
522 if (!IsSigned)
523 return false; // We don't handle this case yet. There is no native
524 // instruction for this but it can be synthesized.
525 Type *DstTy = I->getType();
526 if (!isTypeLegal(DstTy, DstVT))
527 return false;
528
529 if (DstVT != MVT::i32)
530 return false;
531
532 Value *Src = I->getOperand(0);
533 Type *SrcTy = Src->getType();
534 if (!isTypeLegal(SrcTy, SrcVT))
535 return false;
536
537 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
538 return false;
539
540 unsigned SrcReg = getRegForValue(Src);
541 if (SrcReg == 0)
542 return false;
543
544 // Determine the opcode for the conversion, which takes place
545 // entirely within FPRs.
546 unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
547 unsigned TempReg = createResultReg(&Mips::FGR32RegClass);
548 unsigned Opc;
549
550 if (SrcVT == MVT::f32)
551 Opc = Mips::TRUNC_W_S;
552 else
553 Opc = Mips::TRUNC_W_D32;
554
555 // Generate the convert.
556 EmitInst(Opc, TempReg).addReg(SrcReg);
557
558 EmitInst(Mips::MFC1, DestReg).addReg(TempReg);
559
560 updateValueMap(I, DestReg);
561 return true;
562}
563
Reed Kotler497311a2014-10-10 17:39:51 +0000564//
565// Because of how SelectCmp is called with fast-isel, you can
566// end up with redundant "andi" instructions after the sequences emitted below.
567// We should try and solve this issue in the future.
568//
569bool MipsFastISel::SelectCmp(const Instruction *I) {
570 const CmpInst *CI = cast<CmpInst>(I);
571 bool IsUnsigned = CI->isUnsigned();
572 const Value *Left = I->getOperand(0), *Right = I->getOperand(1);
573
574 unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned);
575 if (LeftReg == 0)
576 return false;
577 unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned);
578 if (RightReg == 0)
579 return false;
580 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotler1f64eca2014-10-10 20:46:28 +0000581 CmpInst::Predicate P = CI->getPredicate();
582 switch (P) {
Reed Kotler497311a2014-10-10 17:39:51 +0000583 default:
584 return false;
585 case CmpInst::ICMP_EQ: {
586 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
587 EmitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
588 EmitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1);
589 break;
590 }
591 case CmpInst::ICMP_NE: {
592 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
593 EmitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
594 EmitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
595 break;
596 }
597 case CmpInst::ICMP_UGT: {
598 EmitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
599 break;
600 }
601 case CmpInst::ICMP_ULT: {
602 EmitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
603 break;
604 }
605 case CmpInst::ICMP_UGE: {
606 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
607 EmitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
608 EmitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
609 break;
610 }
611 case CmpInst::ICMP_ULE: {
612 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
613 EmitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg);
614 EmitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
615 break;
616 }
617 case CmpInst::ICMP_SGT: {
618 EmitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
619 break;
620 }
621 case CmpInst::ICMP_SLT: {
622 EmitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
623 break;
624 }
625 case CmpInst::ICMP_SGE: {
626 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
627 EmitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
628 EmitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
629 break;
630 }
631 case CmpInst::ICMP_SLE: {
632 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
633 EmitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg);
634 EmitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
635 break;
636 }
Reed Kotler1f64eca2014-10-10 20:46:28 +0000637 case CmpInst::FCMP_OEQ:
638 case CmpInst::FCMP_UNE:
639 case CmpInst::FCMP_OLT:
640 case CmpInst::FCMP_OLE:
641 case CmpInst::FCMP_OGT:
642 case CmpInst::FCMP_OGE: {
643 if (UnsupportedFPMode)
644 return false;
645 bool IsFloat = Left->getType()->isFloatTy();
646 bool IsDouble = Left->getType()->isDoubleTy();
647 if (!IsFloat && !IsDouble)
648 return false;
649 unsigned Opc, CondMovOpc;
650 switch (P) {
651 case CmpInst::FCMP_OEQ:
652 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
653 CondMovOpc = Mips::MOVT_I;
654 break;
655 case CmpInst::FCMP_UNE:
656 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
657 CondMovOpc = Mips::MOVF_I;
658 break;
659 case CmpInst::FCMP_OLT:
660 Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32;
661 CondMovOpc = Mips::MOVT_I;
662 break;
663 case CmpInst::FCMP_OLE:
664 Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32;
665 CondMovOpc = Mips::MOVT_I;
666 break;
667 case CmpInst::FCMP_OGT:
668 Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32;
669 CondMovOpc = Mips::MOVF_I;
670 break;
671 case CmpInst::FCMP_OGE:
672 Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32;
673 CondMovOpc = Mips::MOVF_I;
674 break;
675 default:
Chandler Carruth38811cc2014-10-10 21:07:03 +0000676 llvm_unreachable("Only switching of a subset of CCs.");
Reed Kotler1f64eca2014-10-10 20:46:28 +0000677 }
678 unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass);
679 unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
680 EmitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
681 EmitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
682 EmitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
683 Mips::FCC0, RegState::ImplicitDefine);
684 MachineInstrBuilder MI = EmitInst(CondMovOpc, ResultReg)
685 .addReg(RegWithOne)
686 .addReg(Mips::FCC0)
687 .addReg(RegWithZero, RegState::Implicit);
688 MI->tieOperands(0, 3);
689 break;
690 }
Reed Kotler497311a2014-10-10 17:39:51 +0000691 }
692 updateValueMap(I, ResultReg);
693 return true;
694}
695
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000696bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
Reed Kotler67077b32014-04-29 17:57:50 +0000697 if (!TargetSupported)
698 return false;
699 switch (I->getOpcode()) {
700 default:
701 break;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000702 case Instruction::Load:
703 return SelectLoad(I);
Reed Kotlerbab3f232014-05-01 20:39:21 +0000704 case Instruction::Store:
705 return SelectStore(I);
Reed Kotler67077b32014-04-29 17:57:50 +0000706 case Instruction::Ret:
707 return SelectRet(I);
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000708 case Instruction::Trunc:
709 return SelectTrunc(I);
710 case Instruction::ZExt:
711 case Instruction::SExt:
712 return SelectIntExt(I);
Reed Kotlerb9dc2482014-10-01 18:47:02 +0000713 case Instruction::FPTrunc:
714 return SelectFPTrunc(I);
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000715 case Instruction::FPExt:
716 return SelectFPExt(I);
Reed Kotler12f94882014-10-10 17:00:46 +0000717 case Instruction::FPToSI:
718 return SelectFPToI(I, /*isSigned*/ true);
719 case Instruction::FPToUI:
720 return SelectFPToI(I, /*isSigned*/ false);
Reed Kotler497311a2014-10-10 17:39:51 +0000721 case Instruction::ICmp:
722 case Instruction::FCmp:
723 return SelectCmp(I);
Reed Kotler67077b32014-04-29 17:57:50 +0000724 }
725 return false;
726}
Reed Kotler720c5ca2014-04-17 22:15:34 +0000727
Reed Kotlerbab3f232014-05-01 20:39:21 +0000728unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) {
Reed Kotler12f94882014-10-10 17:00:46 +0000729 if (UnsupportedFPMode)
730 return 0;
Reed Kotler063d4fb2014-06-10 16:45:44 +0000731 int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
732 if (VT == MVT::f32) {
733 const TargetRegisterClass *RC = &Mips::FGR32RegClass;
734 unsigned DestReg = createResultReg(RC);
735 unsigned TempReg = Materialize32BitInt(Imm, &Mips::GPR32RegClass);
736 EmitInst(Mips::MTC1, DestReg).addReg(TempReg);
737 return DestReg;
738 } else if (VT == MVT::f64) {
739 const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
740 unsigned DestReg = createResultReg(RC);
741 unsigned TempReg1 = Materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
742 unsigned TempReg2 =
743 Materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
744 EmitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
745 return DestReg;
746 }
Reed Kotlerbab3f232014-05-01 20:39:21 +0000747 return 0;
748}
749
750unsigned MipsFastISel::MaterializeGV(const GlobalValue *GV, MVT VT) {
751 // For now 32-bit only.
752 if (VT != MVT::i32)
753 return 0;
754 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
755 unsigned DestReg = createResultReg(RC);
756 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
757 bool IsThreadLocal = GVar && GVar->isThreadLocal();
758 // TLS not supported at this time.
759 if (IsThreadLocal)
760 return 0;
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000761 EmitInst(Mips::LW, DestReg)
762 .addReg(MFI->getGlobalBaseReg())
763 .addGlobalAddress(GV, 0, MipsII::MO_GOT);
Reed Kotler87048a42014-08-07 22:09:01 +0000764 if ((GV->hasInternalLinkage() ||
765 (GV->hasLocalLinkage() && !isa<Function>(GV)))) {
766 unsigned TempReg = createResultReg(RC);
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000767 EmitInst(Mips::ADDiu, TempReg)
768 .addReg(DestReg)
769 .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO);
Reed Kotler87048a42014-08-07 22:09:01 +0000770 DestReg = TempReg;
771 }
Reed Kotlerbab3f232014-05-01 20:39:21 +0000772 return DestReg;
773}
Reed Kotler87048a42014-08-07 22:09:01 +0000774
Reed Kotlerbab3f232014-05-01 20:39:21 +0000775unsigned MipsFastISel::MaterializeInt(const Constant *C, MVT VT) {
Reed Kotler6280d972014-05-15 21:54:15 +0000776 if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
Reed Kotlerbab3f232014-05-01 20:39:21 +0000777 return 0;
778 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
Reed Kotlerbab3f232014-05-01 20:39:21 +0000779 const ConstantInt *CI = cast<ConstantInt>(C);
Reed Kotler6280d972014-05-15 21:54:15 +0000780 int64_t Imm;
Reed Kotler87048a42014-08-07 22:09:01 +0000781 if ((VT != MVT::i1) && CI->isNegative())
Reed Kotler6280d972014-05-15 21:54:15 +0000782 Imm = CI->getSExtValue();
783 else
784 Imm = CI->getZExtValue();
785 return Materialize32BitInt(Imm, RC);
786}
787
788unsigned MipsFastISel::Materialize32BitInt(int64_t Imm,
789 const TargetRegisterClass *RC) {
790 unsigned ResultReg = createResultReg(RC);
791
792 if (isInt<16>(Imm)) {
Reed Kotlerbab3f232014-05-01 20:39:21 +0000793 unsigned Opc = Mips::ADDiu;
Reed Kotlerfb77bc92014-06-08 03:04:42 +0000794 EmitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
Reed Kotler6280d972014-05-15 21:54:15 +0000795 return ResultReg;
796 } else if (isUInt<16>(Imm)) {
Reed Kotlerfb77bc92014-06-08 03:04:42 +0000797 EmitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
Reed Kotler6280d972014-05-15 21:54:15 +0000798 return ResultReg;
Reed Kotlerbab3f232014-05-01 20:39:21 +0000799 }
Reed Kotler6280d972014-05-15 21:54:15 +0000800 unsigned Lo = Imm & 0xFFFF;
801 unsigned Hi = (Imm >> 16) & 0xFFFF;
802 if (Lo) {
803 // Both Lo and Hi have nonzero bits.
804 unsigned TmpReg = createResultReg(RC);
Reed Kotlerfb77bc92014-06-08 03:04:42 +0000805 EmitInst(Mips::LUi, TmpReg).addImm(Hi);
806 EmitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
Reed Kotler6280d972014-05-15 21:54:15 +0000807 } else {
Reed Kotlerfb77bc92014-06-08 03:04:42 +0000808 EmitInst(Mips::LUi, ResultReg).addImm(Hi);
Reed Kotler6280d972014-05-15 21:54:15 +0000809 }
810 return ResultReg;
Reed Kotlerbab3f232014-05-01 20:39:21 +0000811}
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000812}
Reed Kotlerbab3f232014-05-01 20:39:21 +0000813
Reed Kotler720c5ca2014-04-17 22:15:34 +0000814namespace llvm {
815FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
816 const TargetLibraryInfo *libInfo) {
817 return new MipsFastISel(funcInfo, libInfo);
818}
819}