blob: 97682d8ae9ead0963e70406fbe7ef6733e642c6d [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
21class MipsFastISel final : public FastISel {
22
Reed Kotlera562b462014-10-13 21:46:41 +000023 // All possible address modes.
24 class Address {
25 public:
26 typedef enum { RegBase, FrameIndexBase } BaseKind;
27
28 private:
29 BaseKind Kind;
30 union {
31 unsigned Reg;
32 int FI;
33 } Base;
34
35 int64_t Offset;
36
37 const GlobalValue *GV;
38
39 public:
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!");
47 Base.Reg = Reg;
48 }
49 unsigned getReg() const {
50 assert(isRegBase() && "Invalid base register access!");
51 return Base.Reg;
52 }
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; }
57 };
58
Reed Kotler67077b32014-04-29 17:57:50 +000059 /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
60 /// make the right decision when generating code for different targets.
Reed Kotler67077b32014-04-29 17:57:50 +000061 Module &M;
62 const TargetMachine &TM;
63 const TargetInstrInfo &TII;
64 const TargetLowering &TLI;
Eric Christopher22405e42014-07-10 17:26:51 +000065 const MipsSubtarget *Subtarget;
Reed Kotler67077b32014-04-29 17:57:50 +000066 MipsFunctionInfo *MFI;
67
68 // Convenience variables to avoid some queries.
69 LLVMContext *Context;
70
71 bool TargetSupported;
Reed Kotlera562b462014-10-13 21:46:41 +000072 bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle
73 // floating point but not reject doing fast-isel in other
74 // situations
75
76private:
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);
88
89 // Utility helper routines.
90
91 bool isTypeLegal(Type *Ty, MVT &VT);
92 bool isLoadTypeLegal(Type *Ty, MVT &VT);
93 bool computeAddress(const Value *Obj, Address &Addr);
94
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,
102
103 bool IsZExt);
104 bool emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
105
106 bool emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
107 bool emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
108 unsigned DestReg);
109 bool emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
110 unsigned DestReg);
111
112 unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned);
113
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);
118
119 MachineInstrBuilder emitInst(unsigned Opc) {
120 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
121 }
122 MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) {
123 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
124 DstReg);
125 }
126 MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg,
127 unsigned MemReg, int64_t MemOffset) {
128 return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
129 }
130 MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg,
131 unsigned MemReg, int64_t MemOffset) {
132 return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
133 }
134 // for some reason, this default is not generated by tablegen
135 // so we explicitly generate it here.
136 //
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) {
140 return 0;
141 }
Reed Kotler67077b32014-04-29 17:57:50 +0000142
Reed Kotler720c5ca2014-04-17 22:15:34 +0000143public:
Reed Kotlera562b462014-10-13 21:46:41 +0000144 // Backend specific FastISel code.
145
Reed Kotler720c5ca2014-04-17 22:15:34 +0000146 explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
147 const TargetLibraryInfo *libInfo)
Reed Kotler67077b32014-04-29 17:57:50 +0000148 : FastISel(funcInfo, libInfo),
149 M(const_cast<Module &>(*funcInfo.Fn->getParent())),
Eric Christopherd9134482014-08-04 21:25:23 +0000150 TM(funcInfo.MF->getTarget()),
151 TII(*TM.getSubtargetImpl()->getInstrInfo()),
152 TLI(*TM.getSubtargetImpl()->getTargetLowering()),
Eric Christopher22405e42014-07-10 17:26:51 +0000153 Subtarget(&TM.getSubtarget<MipsSubtarget>()) {
Reed Kotler67077b32014-04-29 17:57:50 +0000154 MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
155 Context = &funcInfo.Fn->getContext();
Eric Christopher22405e42014-07-10 17:26:51 +0000156 TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
Reed Kotler32be74b2014-09-15 20:30:25 +0000157 ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) &&
158 (Subtarget->isABI_O32())));
Reed Kotler12f94882014-10-10 17:00:46 +0000159 UnsupportedFPMode = Subtarget->isFP64bit();
Reed Kotler67077b32014-04-29 17:57:50 +0000160 }
161
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000162 unsigned fastMaterializeConstant(const Constant *C) override;
Reed Kotlera562b462014-10-13 21:46:41 +0000163 bool fastSelectInstruction(const Instruction *I) override;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000164
Reed Kotler9fe25f32014-06-08 02:08:43 +0000165#include "MipsGenFastISel.inc"
Reed Kotler720c5ca2014-04-17 22:15:34 +0000166};
Reed Kotlera562b462014-10-13 21:46:41 +0000167} // end anonymous namespace.
Reed Kotler67077b32014-04-29 17:57:50 +0000168
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000169unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) {
170 if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
Reed Kotler497311a2014-10-10 17:39:51 +0000171 return 0;
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000172 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
173 const ConstantInt *CI = cast<ConstantInt>(C);
174 int64_t Imm;
175 if ((VT != MVT::i1) && CI->isNegative())
176 Imm = CI->getSExtValue();
177 else
178 Imm = CI->getZExtValue();
179 return materialize32BitInt(Imm, RC);
Reed Kotler497311a2014-10-10 17:39:51 +0000180}
181
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000182unsigned MipsFastISel::materialize32BitInt(int64_t Imm,
183 const TargetRegisterClass *RC) {
184 unsigned ResultReg = createResultReg(RC);
185
186 if (isInt<16>(Imm)) {
187 unsigned Opc = Mips::ADDiu;
188 emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
189 return ResultReg;
190 } else if (isUInt<16>(Imm)) {
191 emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
192 return ResultReg;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000193 }
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000194 unsigned Lo = Imm & 0xFFFF;
195 unsigned Hi = (Imm >> 16) & 0xFFFF;
196 if (Lo) {
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);
201 } else {
202 emitInst(Mips::LUi, ResultReg).addImm(Hi);
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000203 }
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000204 return ResultReg;
205}
206
207unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
208 if (UnsupportedFPMode)
209 return 0;
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);
216 return DestReg;
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);
221 unsigned TempReg2 =
222 materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
223 emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
224 return DestReg;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000225 }
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000226 return 0;
227}
228
229unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) {
230 // For now 32-bit only.
231 if (VT != MVT::i32)
232 return 0;
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.
238 if (IsThreadLocal)
239 return 0;
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)
247 .addReg(DestReg)
248 .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO);
249 DestReg = TempReg;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000250 }
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000251 return DestReg;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000252}
253
Reed Kotlerbab3f232014-05-01 20:39:21 +0000254// Materialize a constant into a register, and return the register
255// number (or zero if we failed to handle it).
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000256unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
Reed Kotlerbab3f232014-05-01 20:39:21 +0000257 EVT CEVT = TLI.getValueType(C->getType(), true);
258
259 // Only handle simple types.
260 if (!CEVT.isSimple())
261 return 0;
262 MVT VT = CEVT.getSimpleVT();
263
264 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
Reed Kotlera562b462014-10-13 21:46:41 +0000265 return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT);
Reed Kotlerbab3f232014-05-01 20:39:21 +0000266 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
Reed Kotlera562b462014-10-13 21:46:41 +0000267 return materializeGV(GV, VT);
Reed Kotlerbab3f232014-05-01 20:39:21 +0000268 else if (isa<ConstantInt>(C))
Reed Kotlera562b462014-10-13 21:46:41 +0000269 return materializeInt(C, VT);
Reed Kotlerbab3f232014-05-01 20:39:21 +0000270
271 return 0;
272}
273
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000274bool 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.
Reed Kotlerbab3f232014-05-01 20:39:21 +0000278 //
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000279 if (isa<Instruction>(Obj))
Reed Kotlerbab3f232014-05-01 20:39:21 +0000280 return false;
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000281 else if (isa<ConstantExpr>(Obj))
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000282 return false;
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000283 Addr.setReg(getRegForValue(Obj));
284 return Addr.getReg() != 0;
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000285}
286
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000287bool 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())
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000291 return false;
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000292 VT = evt.getSimpleVT();
293
294 // Handle all legal types, i.e. a register that will directly hold this
295 // value.
296 return TLI.isTypeLegal(VT);
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000297}
298
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000299bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
300 if (isTypeLegal(Ty, VT))
Reed Kotler62de6b92014-10-11 00:55:18 +0000301 return true;
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000302 // 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)
306 return true;
Reed Kotler62de6b92014-10-11 00:55:18 +0000307 return false;
308}
Reed Kotler62de6b92014-10-11 00:55:18 +0000309// Because of how EmitCmp is called with fast-isel, you can
Reed Kotler497311a2014-10-10 17:39:51 +0000310// end up with redundant "andi" instructions after the sequences emitted below.
311// We should try and solve this issue in the future.
312//
Reed Kotlera562b462014-10-13 21:46:41 +0000313bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
Reed Kotler62de6b92014-10-11 00:55:18 +0000314 const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1);
Reed Kotler497311a2014-10-10 17:39:51 +0000315 bool IsUnsigned = CI->isUnsigned();
Reed Kotler497311a2014-10-10 17:39:51 +0000316 unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned);
317 if (LeftReg == 0)
318 return false;
319 unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned);
320 if (RightReg == 0)
321 return false;
Reed Kotler1f64eca2014-10-10 20:46:28 +0000322 CmpInst::Predicate P = CI->getPredicate();
Reed Kotler62de6b92014-10-11 00:55:18 +0000323
Reed Kotler1f64eca2014-10-10 20:46:28 +0000324 switch (P) {
Reed Kotler497311a2014-10-10 17:39:51 +0000325 default:
326 return false;
327 case CmpInst::ICMP_EQ: {
328 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000329 emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
330 emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1);
Reed Kotler497311a2014-10-10 17:39:51 +0000331 break;
332 }
333 case CmpInst::ICMP_NE: {
334 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000335 emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
336 emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
Reed Kotler497311a2014-10-10 17:39:51 +0000337 break;
338 }
339 case CmpInst::ICMP_UGT: {
Reed Kotlera562b462014-10-13 21:46:41 +0000340 emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
Reed Kotler497311a2014-10-10 17:39:51 +0000341 break;
342 }
343 case CmpInst::ICMP_ULT: {
Reed Kotlera562b462014-10-13 21:46:41 +0000344 emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
Reed Kotler497311a2014-10-10 17:39:51 +0000345 break;
346 }
347 case CmpInst::ICMP_UGE: {
348 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000349 emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
350 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
Reed Kotler497311a2014-10-10 17:39:51 +0000351 break;
352 }
353 case CmpInst::ICMP_ULE: {
354 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000355 emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg);
356 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
Reed Kotler497311a2014-10-10 17:39:51 +0000357 break;
358 }
359 case CmpInst::ICMP_SGT: {
Reed Kotlera562b462014-10-13 21:46:41 +0000360 emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
Reed Kotler497311a2014-10-10 17:39:51 +0000361 break;
362 }
363 case CmpInst::ICMP_SLT: {
Reed Kotlera562b462014-10-13 21:46:41 +0000364 emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
Reed Kotler497311a2014-10-10 17:39:51 +0000365 break;
366 }
367 case CmpInst::ICMP_SGE: {
368 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000369 emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
370 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
Reed Kotler497311a2014-10-10 17:39:51 +0000371 break;
372 }
373 case CmpInst::ICMP_SLE: {
374 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000375 emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg);
376 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
Reed Kotler497311a2014-10-10 17:39:51 +0000377 break;
378 }
Reed Kotler1f64eca2014-10-10 20:46:28 +0000379 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)
386 return false;
387 bool IsFloat = Left->getType()->isFloatTy();
388 bool IsDouble = Left->getType()->isDoubleTy();
389 if (!IsFloat && !IsDouble)
390 return false;
391 unsigned Opc, CondMovOpc;
392 switch (P) {
393 case CmpInst::FCMP_OEQ:
394 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
395 CondMovOpc = Mips::MOVT_I;
396 break;
397 case CmpInst::FCMP_UNE:
398 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
399 CondMovOpc = Mips::MOVF_I;
400 break;
401 case CmpInst::FCMP_OLT:
402 Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32;
403 CondMovOpc = Mips::MOVT_I;
404 break;
405 case CmpInst::FCMP_OLE:
406 Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32;
407 CondMovOpc = Mips::MOVT_I;
408 break;
409 case CmpInst::FCMP_OGT:
410 Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32;
411 CondMovOpc = Mips::MOVF_I;
412 break;
413 case CmpInst::FCMP_OGE:
414 Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32;
415 CondMovOpc = Mips::MOVF_I;
416 break;
417 default:
Chandler Carruth38811cc2014-10-10 21:07:03 +0000418 llvm_unreachable("Only switching of a subset of CCs.");
Reed Kotler1f64eca2014-10-10 20:46:28 +0000419 }
420 unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass);
421 unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000422 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(
Reed Kotler1f64eca2014-10-10 20:46:28 +0000425 Mips::FCC0, RegState::ImplicitDefine);
Reed Kotlera562b462014-10-13 21:46:41 +0000426 MachineInstrBuilder MI = emitInst(CondMovOpc, ResultReg)
Reed Kotler1f64eca2014-10-10 20:46:28 +0000427 .addReg(RegWithOne)
428 .addReg(Mips::FCC0)
429 .addReg(RegWithZero, RegState::Implicit);
430 MI->tieOperands(0, 3);
431 break;
432 }
Reed Kotler497311a2014-10-10 17:39:51 +0000433 }
Reed Kotler62de6b92014-10-11 00:55:18 +0000434 return true;
435}
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000436bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
437 unsigned Alignment) {
438 //
439 // more cases will be handled here in following patches.
440 //
441 unsigned Opc;
442 switch (VT.SimpleTy) {
443 case MVT::i32: {
444 ResultReg = createResultReg(&Mips::GPR32RegClass);
445 Opc = Mips::LW;
446 break;
447 }
448 case MVT::i16: {
449 ResultReg = createResultReg(&Mips::GPR32RegClass);
450 Opc = Mips::LHu;
451 break;
452 }
453 case MVT::i8: {
454 ResultReg = createResultReg(&Mips::GPR32RegClass);
455 Opc = Mips::LBu;
456 break;
457 }
458 case MVT::f32: {
459 if (UnsupportedFPMode)
460 return false;
461 ResultReg = createResultReg(&Mips::FGR32RegClass);
462 Opc = Mips::LWC1;
463 break;
464 }
465 case MVT::f64: {
466 if (UnsupportedFPMode)
467 return false;
468 ResultReg = createResultReg(&Mips::AFGR64RegClass);
469 Opc = Mips::LDC1;
470 break;
471 }
472 default:
473 return false;
474 }
475 emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
476 return true;
477}
478
479bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr,
480 unsigned Alignment) {
481 //
482 // more cases will be handled here in following patches.
483 //
484 unsigned Opc;
485 switch (VT.SimpleTy) {
486 case MVT::i8:
487 Opc = Mips::SB;
488 break;
489 case MVT::i16:
490 Opc = Mips::SH;
491 break;
492 case MVT::i32:
493 Opc = Mips::SW;
494 break;
495 case MVT::f32:
496 if (UnsupportedFPMode)
497 return false;
498 Opc = Mips::SWC1;
499 break;
500 case MVT::f64:
501 if (UnsupportedFPMode)
502 return false;
503 Opc = Mips::SDC1;
504 break;
505 default:
506 return false;
507 }
508 emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
509 return true;
510}
511
512bool MipsFastISel::selectLoad(const Instruction *I) {
513 // Atomic loads need special handling.
514 if (cast<LoadInst>(I)->isAtomic())
515 return false;
516
517 // Verify we have a legal type before going any further.
518 MVT VT;
519 if (!isLoadTypeLegal(I->getType(), VT))
520 return false;
521
522 // See if we can handle this address.
523 Address Addr;
524 if (!computeAddress(I->getOperand(0), Addr))
525 return false;
526
527 unsigned ResultReg;
528 if (!emitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
529 return false;
530 updateValueMap(I, ResultReg);
531 return true;
532}
533
534bool MipsFastISel::selectStore(const Instruction *I) {
535 Value *Op0 = I->getOperand(0);
536 unsigned SrcReg = 0;
537
538 // Atomic stores need special handling.
539 if (cast<StoreInst>(I)->isAtomic())
540 return false;
541
542 // Verify we have a legal type before going any further.
543 MVT VT;
544 if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
545 return false;
546
547 // Get the value to be stored into a register.
548 SrcReg = getRegForValue(Op0);
549 if (SrcReg == 0)
550 return false;
551
552 // See if we can handle this address.
553 Address Addr;
554 if (!computeAddress(I->getOperand(1), Addr))
555 return false;
556
557 if (!emitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
558 return false;
559 return true;
560}
561
562//
563// This can cause a redundant sltiu to be generated.
564// FIXME: try and eliminate this in a future patch.
565//
566bool MipsFastISel::selectBranch(const Instruction *I) {
567 const BranchInst *BI = cast<BranchInst>(I);
568 MachineBasicBlock *BrBB = FuncInfo.MBB;
569 //
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
573 // goto FBB
574 // TBB:
575 //
576 MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
577 MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
578 BI->getCondition();
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))
583 return false;
584 BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ))
585 .addReg(CondReg)
586 .addMBB(TBB);
587 fastEmitBranch(FBB, DbgLoc);
588 FuncInfo.MBB->addSuccessor(TBB);
589 return true;
590 }
591 return false;
592}
Reed Kotler62de6b92014-10-11 00:55:18 +0000593
Reed Kotlera562b462014-10-13 21:46:41 +0000594bool MipsFastISel::selectCmp(const Instruction *I) {
Reed Kotler62de6b92014-10-11 00:55:18 +0000595 const CmpInst *CI = cast<CmpInst>(I);
596 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
Reed Kotlera562b462014-10-13 21:46:41 +0000597 if (!emitCmp(ResultReg, CI))
Reed Kotler62de6b92014-10-11 00:55:18 +0000598 return false;
Reed Kotler497311a2014-10-10 17:39:51 +0000599 updateValueMap(I, ResultReg);
600 return true;
601}
602
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000603// Attempt to fast-select a floating-point extend instruction.
604bool MipsFastISel::selectFPExt(const Instruction *I) {
605 if (UnsupportedFPMode)
606 return false;
607 Value *Src = I->getOperand(0);
608 EVT SrcVT = TLI.getValueType(Src->getType(), true);
609 EVT DestVT = TLI.getValueType(I->getType(), true);
610
611 if (SrcVT != MVT::f32 || DestVT != MVT::f64)
612 return false;
613
614 unsigned SrcReg =
615 getRegForValue(Src); // his must be a 32 bit floating point register class
616 // maybe we should handle this differently
617 if (!SrcReg)
618 return false;
619
620 unsigned DestReg = createResultReg(&Mips::AFGR64RegClass);
621 emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg);
622 updateValueMap(I, DestReg);
623 return true;
624}
625
626// Attempt to fast-select a floating-point truncate instruction.
627bool MipsFastISel::selectFPTrunc(const Instruction *I) {
628 if (UnsupportedFPMode)
629 return false;
630 Value *Src = I->getOperand(0);
631 EVT SrcVT = TLI.getValueType(Src->getType(), true);
632 EVT DestVT = TLI.getValueType(I->getType(), true);
633
634 if (SrcVT != MVT::f64 || DestVT != MVT::f32)
635 return false;
636
637 unsigned SrcReg = getRegForValue(Src);
638 if (!SrcReg)
639 return false;
640
641 unsigned DestReg = createResultReg(&Mips::FGR32RegClass);
642 if (!DestReg)
643 return false;
644
645 emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg);
646 updateValueMap(I, DestReg);
647 return true;
648}
649
650// Attempt to fast-select a floating-point-to-integer conversion.
651bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) {
652 if (UnsupportedFPMode)
653 return false;
654 MVT DstVT, SrcVT;
655 if (!IsSigned)
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))
660 return false;
661
662 if (DstVT != MVT::i32)
663 return false;
664
665 Value *Src = I->getOperand(0);
666 Type *SrcTy = Src->getType();
667 if (!isTypeLegal(SrcTy, SrcVT))
668 return false;
669
670 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
671 return false;
672
673 unsigned SrcReg = getRegForValue(Src);
674 if (SrcReg == 0)
675 return false;
676
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);
681 unsigned Opc;
682
683 if (SrcVT == MVT::f32)
684 Opc = Mips::TRUNC_W_S;
685 else
686 Opc = Mips::TRUNC_W_D32;
687
688 // Generate the convert.
689 emitInst(Opc, TempReg).addReg(SrcReg);
690
691 emitInst(Mips::MFC1, DestReg).addReg(TempReg);
692
693 updateValueMap(I, DestReg);
694 return true;
695}
696//
697bool MipsFastISel::selectRet(const Instruction *I) {
698 const ReturnInst *Ret = cast<ReturnInst>(I);
699
700 if (!FuncInfo.CanLowerReturn)
701 return false;
702 if (Ret->getNumOperands() > 0) {
703 return false;
704 }
705 emitInst(Mips::RetRA);
706 return true;
707}
708
709bool MipsFastISel::selectTrunc(const Instruction *I) {
710 // The high bits for a type smaller than the register size are assumed to be
711 // undefined.
712 Value *Op = I->getOperand(0);
713
714 EVT SrcVT, DestVT;
715 SrcVT = TLI.getValueType(Op->getType(), true);
716 DestVT = TLI.getValueType(I->getType(), true);
717
718 if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
719 return false;
720 if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
721 return false;
722
723 unsigned SrcReg = getRegForValue(Op);
724 if (!SrcReg)
725 return false;
726
727 // Because the high bits are undefined, a truncate doesn't generate
728 // any code.
729 updateValueMap(I, SrcReg);
730 return true;
731}
732bool MipsFastISel::selectIntExt(const Instruction *I) {
733 Type *DestTy = I->getType();
734 Value *Src = I->getOperand(0);
735 Type *SrcTy = Src->getType();
736
737 bool isZExt = isa<ZExtInst>(I);
738 unsigned SrcReg = getRegForValue(Src);
739 if (!SrcReg)
740 return false;
741
742 EVT SrcEVT, DestEVT;
743 SrcEVT = TLI.getValueType(SrcTy, true);
744 DestEVT = TLI.getValueType(DestTy, true);
745 if (!SrcEVT.isSimple())
746 return false;
747 if (!DestEVT.isSimple())
748 return false;
749
750 MVT SrcVT = SrcEVT.getSimpleVT();
751 MVT DestVT = DestEVT.getSimpleVT();
752 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
753
754 if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt))
755 return false;
756 updateValueMap(I, ResultReg);
757 return true;
758}
759bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
760 unsigned DestReg) {
761 unsigned ShiftAmt;
762 switch (SrcVT.SimpleTy) {
763 default:
764 return false;
765 case MVT::i8:
766 ShiftAmt = 24;
767 break;
768 case MVT::i16:
769 ShiftAmt = 16;
770 break;
771 }
772 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
773 emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt);
774 emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt);
775 return true;
776}
777
778bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
779 unsigned DestReg) {
780 switch (SrcVT.SimpleTy) {
781 default:
782 return false;
783 case MVT::i8:
784 emitInst(Mips::SEB, DestReg).addReg(SrcReg);
785 break;
786 case MVT::i16:
787 emitInst(Mips::SEH, DestReg).addReg(SrcReg);
788 break;
789 }
790 return true;
791}
792
793bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
794 unsigned DestReg) {
795 if ((DestVT != MVT::i32) && (DestVT != MVT::i16))
796 return false;
797 if (Subtarget->hasMips32r2())
798 return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg);
799 return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg);
800}
801
802bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
803 unsigned DestReg) {
804 switch (SrcVT.SimpleTy) {
805 default:
806 return false;
807 case MVT::i1:
808 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1);
809 break;
810 case MVT::i8:
811 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff);
812 break;
813 case MVT::i16:
814 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff);
815 }
816 return true;
817}
818
819bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
820 unsigned DestReg, bool IsZExt) {
821 if (IsZExt)
822 return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg);
823 return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg);
824}
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000825bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
Reed Kotler67077b32014-04-29 17:57:50 +0000826 if (!TargetSupported)
827 return false;
828 switch (I->getOpcode()) {
829 default:
830 break;
Reed Kotler9fe3bfd2014-06-16 22:05:47 +0000831 case Instruction::Load:
Reed Kotlera562b462014-10-13 21:46:41 +0000832 return selectLoad(I);
Reed Kotlerbab3f232014-05-01 20:39:21 +0000833 case Instruction::Store:
Reed Kotlera562b462014-10-13 21:46:41 +0000834 return selectStore(I);
Reed Kotler62de6b92014-10-11 00:55:18 +0000835 case Instruction::Br:
Reed Kotlera562b462014-10-13 21:46:41 +0000836 return selectBranch(I);
Reed Kotler67077b32014-04-29 17:57:50 +0000837 case Instruction::Ret:
Reed Kotlera562b462014-10-13 21:46:41 +0000838 return selectRet(I);
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000839 case Instruction::Trunc:
Reed Kotlera562b462014-10-13 21:46:41 +0000840 return selectTrunc(I);
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000841 case Instruction::ZExt:
842 case Instruction::SExt:
Reed Kotlera562b462014-10-13 21:46:41 +0000843 return selectIntExt(I);
Reed Kotlerb9dc2482014-10-01 18:47:02 +0000844 case Instruction::FPTrunc:
Reed Kotlera562b462014-10-13 21:46:41 +0000845 return selectFPTrunc(I);
Reed Kotler3ebdcc92014-09-30 16:30:13 +0000846 case Instruction::FPExt:
Reed Kotlera562b462014-10-13 21:46:41 +0000847 return selectFPExt(I);
Reed Kotler12f94882014-10-10 17:00:46 +0000848 case Instruction::FPToSI:
Reed Kotlera562b462014-10-13 21:46:41 +0000849 return selectFPToInt(I, /*isSigned*/ true);
Reed Kotler12f94882014-10-10 17:00:46 +0000850 case Instruction::FPToUI:
Reed Kotlera562b462014-10-13 21:46:41 +0000851 return selectFPToInt(I, /*isSigned*/ false);
Reed Kotler497311a2014-10-10 17:39:51 +0000852 case Instruction::ICmp:
853 case Instruction::FCmp:
Reed Kotlera562b462014-10-13 21:46:41 +0000854 return selectCmp(I);
Reed Kotler67077b32014-04-29 17:57:50 +0000855 }
856 return false;
857}
Reed Kotler720c5ca2014-04-17 22:15:34 +0000858
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000859unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V,
860 bool IsUnsigned) {
861 unsigned VReg = getRegForValue(V);
862 if (VReg == 0)
Reed Kotler12f94882014-10-10 17:00:46 +0000863 return 0;
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000864 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))
868 return 0;
869 VReg = TempReg;
Reed Kotler063d4fb2014-06-10 16:45:44 +0000870 }
Reed Kotlerd4ea29e2014-10-14 18:27:58 +0000871 return VReg;
Reed Kotlerbab3f232014-05-01 20:39:21 +0000872}
873
Reed Kotler720c5ca2014-04-17 22:15:34 +0000874namespace llvm {
875FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
876 const TargetLibraryInfo *libInfo) {
877 return new MipsFastISel(funcInfo, libInfo);
878}
879}