1//===-- MipsastISel.cpp - Mips FastISel implementation
2//---------------------===//
3
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"
16
17using namespace llvm;
18
19namespace {
20
21// 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
36class MipsFastISel final : public FastISel {
37
38  /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
39  /// make the right decision when generating code for different targets.
40  Module &M;
41  const TargetMachine &TM;
42  const TargetInstrInfo &TII;
43  const TargetLowering &TLI;
44  const MipsSubtarget *Subtarget;
45  MipsFunctionInfo *MFI;
46
47  // Convenience variables to avoid some queries.
48  LLVMContext *Context;
49
50  bool TargetSupported;
51
52public:
53  explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
54                        const TargetLibraryInfo *libInfo)
55      : FastISel(funcInfo, libInfo),
56        M(const_cast<Module &>(*funcInfo.Fn->getParent())),
57        TM(funcInfo.MF->getTarget()), TII(*TM.getInstrInfo()),
58        TLI(*TM.getTargetLowering()),
59        Subtarget(&TM.getSubtarget<MipsSubtarget>()) {
60    MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
61    Context = &funcInfo.Fn->getContext();
62    TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
63                       (Subtarget->hasMips32r2() && (Subtarget->isABI_O32())));
64  }
65
66  bool TargetSelectInstruction(const Instruction *I) override;
67  unsigned TargetMaterializeConstant(const Constant *C) override;
68
69  bool ComputeAddress(const Value *Obj, Address &Addr);
70
71private:
72  bool EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
73                unsigned Alignment = 0);
74  bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
75                 unsigned Alignment = 0);
76  bool SelectLoad(const Instruction *I);
77  bool SelectRet(const Instruction *I);
78  bool SelectStore(const Instruction *I);
79
80  bool isTypeLegal(Type *Ty, MVT &VT);
81  bool isLoadTypeLegal(Type *Ty, MVT &VT);
82
83  unsigned MaterializeFP(const ConstantFP *CFP, MVT VT);
84  unsigned MaterializeGV(const GlobalValue *GV, MVT VT);
85  unsigned MaterializeInt(const Constant *C, MVT VT);
86  unsigned Materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC);
87
88  // for some reason, this default is not generated by tablegen
89  // so we explicitly generate it here.
90  //
91  unsigned FastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC,
92                             unsigned Op0, bool Op0IsKill, uint64_t imm1,
93                             uint64_t imm2, unsigned Op3, bool Op3IsKill) {
94    return 0;
95  }
96
97  MachineInstrBuilder EmitInst(unsigned Opc) {
98    return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
99  }
100
101  MachineInstrBuilder EmitInst(unsigned Opc, unsigned DstReg) {
102    return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
103                   DstReg);
104  }
105
106  MachineInstrBuilder EmitInstStore(unsigned Opc, unsigned SrcReg,
107                                    unsigned MemReg, int64_t MemOffset) {
108    return EmitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
109  }
110
111  MachineInstrBuilder EmitInstLoad(unsigned Opc, unsigned DstReg,
112                                      unsigned MemReg, int64_t MemOffset) {
113    return EmitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
114  }
115
116#include "MipsGenFastISel.inc"
117};
118
119bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
120  EVT evt = TLI.getValueType(Ty, true);
121  // Only handle simple types.
122  if (evt == MVT::Other || !evt.isSimple())
123    return false;
124  VT = evt.getSimpleVT();
125
126  // Handle all legal types, i.e. a register that will directly hold this
127  // value.
128  return TLI.isTypeLegal(VT);
129}
130
131bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
132  if (isTypeLegal(Ty, VT))
133    return true;
134  // We will extend this in a later patch:
135  //   If this is a type than can be sign or zero-extended to a basic operation
136  //   go ahead and accept it now.
137  if (VT == MVT::i8 || VT == MVT::i16)
138    return true;
139  return false;
140}
141
142bool MipsFastISel::ComputeAddress(const Value *Obj, Address &Addr) {
143  // This construct looks a big awkward but it is how other ports handle this
144  // and as this function is more fully completed, these cases which
145  // return false will have additional code in them.
146  //
147  if (isa<Instruction>(Obj))
148    return false;
149  else if (isa<ConstantExpr>(Obj))
150    return false;
151  Addr.Base.Reg = getRegForValue(Obj);
152  return Addr.Base.Reg != 0;
153}
154
155bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
156                            unsigned Alignment) {
157  //
158  // more cases will be handled here in following patches.
159  //
160  unsigned Opc;
161  switch (VT.SimpleTy) {
162  case MVT::i32: {
163    ResultReg = createResultReg(&Mips::GPR32RegClass);
164    Opc = Mips::LW;
165    break;
166  }
167  case MVT::i16: {
168    ResultReg = createResultReg(&Mips::GPR32RegClass);
169    Opc = Mips::LHu;
170    break;
171  }
172  case MVT::i8: {
173    ResultReg = createResultReg(&Mips::GPR32RegClass);
174    Opc = Mips::LBu;
175    break;
176  }
177  case MVT::f32: {
178    ResultReg = createResultReg(&Mips::FGR32RegClass);
179    Opc = Mips::LWC1;
180    break;
181  }
182  case MVT::f64: {
183    ResultReg = createResultReg(&Mips::AFGR64RegClass);
184    Opc = Mips::LDC1;
185    break;
186  }
187  default:
188    return false;
189  }
190  EmitInstLoad(Opc, ResultReg, Addr.Base.Reg, Addr.Offset);
191  return true;
192}
193
194// Materialize a constant into a register, and return the register
195// number (or zero if we failed to handle it).
196unsigned MipsFastISel::TargetMaterializeConstant(const Constant *C) {
197  EVT CEVT = TLI.getValueType(C->getType(), true);
198
199  // Only handle simple types.
200  if (!CEVT.isSimple())
201    return 0;
202  MVT VT = CEVT.getSimpleVT();
203
204  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
205    return MaterializeFP(CFP, VT);
206  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
207    return MaterializeGV(GV, VT);
208  else if (isa<ConstantInt>(C))
209    return MaterializeInt(C, VT);
210
211  return 0;
212}
213
214bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
215                             unsigned Alignment) {
216  //
217  // more cases will be handled here in following patches.
218  //
219  unsigned Opc;
220  switch (VT.SimpleTy) {
221  case MVT::i8:
222    Opc = Mips::SB;
223    break;
224  case MVT::i16:
225    Opc = Mips::SH;
226    break;
227  case MVT::i32:
228    Opc = Mips::SW;
229    break;
230  case MVT::f32:
231    Opc = Mips::SWC1;
232    break;
233  case MVT::f64:
234    Opc = Mips::SDC1;
235    break;
236  default:
237    return false;
238  }
239  EmitInstStore(Opc, SrcReg, Addr.Base.Reg, Addr.Offset);
240  return true;
241}
242
243bool MipsFastISel::SelectLoad(const Instruction *I) {
244  // Atomic loads need special handling.
245  if (cast<LoadInst>(I)->isAtomic())
246    return false;
247
248  // Verify we have a legal type before going any further.
249  MVT VT;
250  if (!isLoadTypeLegal(I->getType(), VT))
251    return false;
252
253  // See if we can handle this address.
254  Address Addr;
255  if (!ComputeAddress(I->getOperand(0), Addr))
256    return false;
257
258  unsigned ResultReg;
259  if (!EmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
260    return false;
261  UpdateValueMap(I, ResultReg);
262  return true;
263}
264
265bool MipsFastISel::SelectStore(const Instruction *I) {
266  Value *Op0 = I->getOperand(0);
267  unsigned SrcReg = 0;
268
269  // Atomic stores need special handling.
270  if (cast<StoreInst>(I)->isAtomic())
271    return false;
272
273  // Verify we have a legal type before going any further.
274  MVT VT;
275  if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
276    return false;
277
278  // Get the value to be stored into a register.
279  SrcReg = getRegForValue(Op0);
280  if (SrcReg == 0)
281    return false;
282
283  // See if we can handle this address.
284  Address Addr;
285  if (!ComputeAddress(I->getOperand(1), Addr))
286    return false;
287
288  if (!EmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
289    return false;
290  return true;
291}
292
293bool MipsFastISel::SelectRet(const Instruction *I) {
294  const ReturnInst *Ret = cast<ReturnInst>(I);
295
296  if (!FuncInfo.CanLowerReturn)
297    return false;
298  if (Ret->getNumOperands() > 0) {
299    return false;
300  }
301  EmitInst(Mips::RetRA);
302  return true;
303}
304
305bool MipsFastISel::TargetSelectInstruction(const Instruction *I) {
306  if (!TargetSupported)
307    return false;
308  switch (I->getOpcode()) {
309  default:
310    break;
311  case Instruction::Load:
312    return SelectLoad(I);
313  case Instruction::Store:
314    return SelectStore(I);
315  case Instruction::Ret:
316    return SelectRet(I);
317  }
318  return false;
319}
320}
321
322unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) {
323  int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
324  if (VT == MVT::f32) {
325    const TargetRegisterClass *RC = &Mips::FGR32RegClass;
326    unsigned DestReg = createResultReg(RC);
327    unsigned TempReg = Materialize32BitInt(Imm, &Mips::GPR32RegClass);
328    EmitInst(Mips::MTC1, DestReg).addReg(TempReg);
329    return DestReg;
330  } else if (VT == MVT::f64) {
331    const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
332    unsigned DestReg = createResultReg(RC);
333    unsigned TempReg1 = Materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
334    unsigned TempReg2 =
335        Materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
336    EmitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
337    return DestReg;
338  }
339  return 0;
340}
341
342unsigned MipsFastISel::MaterializeGV(const GlobalValue *GV, MVT VT) {
343  // For now 32-bit only.
344  if (VT != MVT::i32)
345    return 0;
346  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
347  unsigned DestReg = createResultReg(RC);
348  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
349  bool IsThreadLocal = GVar && GVar->isThreadLocal();
350  // TLS not supported at this time.
351  if (IsThreadLocal)
352    return 0;
353  EmitInst(Mips::LW, DestReg).addReg(MFI->getGlobalBaseReg()).addGlobalAddress(
354      GV, 0, MipsII::MO_GOT);
355  return DestReg;
356}
357unsigned MipsFastISel::MaterializeInt(const Constant *C, MVT VT) {
358  if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
359    return 0;
360  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
361  const ConstantInt *CI = cast<ConstantInt>(C);
362  int64_t Imm;
363  if (CI->isNegative())
364    Imm = CI->getSExtValue();
365  else
366    Imm = CI->getZExtValue();
367  return Materialize32BitInt(Imm, RC);
368}
369
370unsigned MipsFastISel::Materialize32BitInt(int64_t Imm,
371                                           const TargetRegisterClass *RC) {
372  unsigned ResultReg = createResultReg(RC);
373
374  if (isInt<16>(Imm)) {
375    unsigned Opc = Mips::ADDiu;
376    EmitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
377    return ResultReg;
378  } else if (isUInt<16>(Imm)) {
379    EmitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
380    return ResultReg;
381  }
382  unsigned Lo = Imm & 0xFFFF;
383  unsigned Hi = (Imm >> 16) & 0xFFFF;
384  if (Lo) {
385    // Both Lo and Hi have nonzero bits.
386    unsigned TmpReg = createResultReg(RC);
387    EmitInst(Mips::LUi, TmpReg).addImm(Hi);
388    EmitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
389  } else {
390    EmitInst(Mips::LUi, ResultReg).addImm(Hi);
391  }
392  return ResultReg;
393}
394
395namespace llvm {
396FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
397                               const TargetLibraryInfo *libInfo) {
398  return new MipsFastISel(funcInfo, libInfo);
399}
400}
401