1 //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements the targeting of the InstructionSelector class for
10 /// Mips.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13 
14 #include "MCTargetDesc/MipsInstPrinter.h"
15 #include "MipsMachineFunction.h"
16 #include "MipsRegisterBankInfo.h"
17 #include "MipsTargetMachine.h"
18 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
19 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20 #include "llvm/CodeGen/MachineJumpTableInfo.h"
21 #include "llvm/IR/IntrinsicsMips.h"
22 
23 #define DEBUG_TYPE "mips-isel"
24 
25 using namespace llvm;
26 
27 namespace {
28 
29 #define GET_GLOBALISEL_PREDICATE_BITSET
30 #include "MipsGenGlobalISel.inc"
31 #undef GET_GLOBALISEL_PREDICATE_BITSET
32 
33 class MipsInstructionSelector : public InstructionSelector {
34 public:
35   MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
36                           const MipsRegisterBankInfo &RBI);
37 
38   bool select(MachineInstr &I) override;
39   static const char *getName() { return DEBUG_TYPE; }
40 
41 private:
42   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
43   bool isRegInGprb(Register Reg, MachineRegisterInfo &MRI) const;
44   bool isRegInFprb(Register Reg, MachineRegisterInfo &MRI) const;
45   bool materialize32BitImm(Register DestReg, APInt Imm,
46                            MachineIRBuilder &B) const;
47   bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
48   const TargetRegisterClass *
49   getRegClassForTypeOnBank(Register Reg, MachineRegisterInfo &MRI) const;
50   unsigned selectLoadStoreOpCode(MachineInstr &I,
51                                  MachineRegisterInfo &MRI) const;
52 
53   const MipsTargetMachine &TM;
54   const MipsSubtarget &STI;
55   const MipsInstrInfo &TII;
56   const MipsRegisterInfo &TRI;
57   const MipsRegisterBankInfo &RBI;
58 
59 #define GET_GLOBALISEL_PREDICATES_DECL
60 #include "MipsGenGlobalISel.inc"
61 #undef GET_GLOBALISEL_PREDICATES_DECL
62 
63 #define GET_GLOBALISEL_TEMPORARIES_DECL
64 #include "MipsGenGlobalISel.inc"
65 #undef GET_GLOBALISEL_TEMPORARIES_DECL
66 };
67 
68 } // end anonymous namespace
69 
70 #define GET_GLOBALISEL_IMPL
71 #include "MipsGenGlobalISel.inc"
72 #undef GET_GLOBALISEL_IMPL
73 
74 MipsInstructionSelector::MipsInstructionSelector(
75     const MipsTargetMachine &TM, const MipsSubtarget &STI,
76     const MipsRegisterBankInfo &RBI)
77     : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
78       TRI(*STI.getRegisterInfo()), RBI(RBI),
79 
80 #define GET_GLOBALISEL_PREDICATES_INIT
81 #include "MipsGenGlobalISel.inc"
82 #undef GET_GLOBALISEL_PREDICATES_INIT
83 #define GET_GLOBALISEL_TEMPORARIES_INIT
84 #include "MipsGenGlobalISel.inc"
85 #undef GET_GLOBALISEL_TEMPORARIES_INIT
86 {
87 }
88 
89 bool MipsInstructionSelector::isRegInGprb(Register Reg,
90                                           MachineRegisterInfo &MRI) const {
91   return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::GPRBRegBankID;
92 }
93 
94 bool MipsInstructionSelector::isRegInFprb(Register Reg,
95                                           MachineRegisterInfo &MRI) const {
96   return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::FPRBRegBankID;
97 }
98 
99 bool MipsInstructionSelector::selectCopy(MachineInstr &I,
100                                          MachineRegisterInfo &MRI) const {
101   Register DstReg = I.getOperand(0).getReg();
102   if (Register::isPhysicalRegister(DstReg))
103     return true;
104 
105   const TargetRegisterClass *RC = getRegClassForTypeOnBank(DstReg, MRI);
106   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
107     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
108                       << " operand\n");
109     return false;
110   }
111   return true;
112 }
113 
114 const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
115     Register Reg, MachineRegisterInfo &MRI) const {
116   const LLT Ty = MRI.getType(Reg);
117   const unsigned TySize = Ty.getSizeInBits();
118 
119   if (isRegInGprb(Reg, MRI)) {
120     assert((Ty.isScalar() || Ty.isPointer()) && TySize == 32 &&
121            "Register class not available for LLT, register bank combination");
122     return &Mips::GPR32RegClass;
123   }
124 
125   if (isRegInFprb(Reg, MRI)) {
126     if (Ty.isScalar()) {
127       assert((TySize == 32 || TySize == 64) &&
128              "Register class not available for LLT, register bank combination");
129       if (TySize == 32)
130         return &Mips::FGR32RegClass;
131       return STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
132     }
133   }
134 
135   llvm_unreachable("Unsupported register bank.");
136 }
137 
138 bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
139                                                   MachineIRBuilder &B) const {
140   assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
141   // Ori zero extends immediate. Used for values with zeros in high 16 bits.
142   if (Imm.getHiBits(16).isNullValue()) {
143     MachineInstr *Inst =
144         B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
145             .addImm(Imm.getLoBits(16).getLimitedValue());
146     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
147   }
148   // Lui places immediate in high 16 bits and sets low 16 bits to zero.
149   if (Imm.getLoBits(16).isNullValue()) {
150     MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
151                              .addImm(Imm.getHiBits(16).getLimitedValue());
152     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
153   }
154   // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
155   if (Imm.isSignedIntN(16)) {
156     MachineInstr *Inst =
157         B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
158             .addImm(Imm.getLoBits(16).getLimitedValue());
159     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
160   }
161   // Values that cannot be materialized with single immediate instruction.
162   Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
163   MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
164                           .addImm(Imm.getHiBits(16).getLimitedValue());
165   MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
166                           .addImm(Imm.getLoBits(16).getLimitedValue());
167   if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
168     return false;
169   if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
170     return false;
171   return true;
172 }
173 
174 /// When I.getOpcode() is returned, we failed to select MIPS instruction opcode.
175 unsigned
176 MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I,
177                                                MachineRegisterInfo &MRI) const {
178   const Register ValueReg = I.getOperand(0).getReg();
179   const LLT Ty = MRI.getType(ValueReg);
180   const unsigned TySize = Ty.getSizeInBits();
181   const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize();
182   unsigned Opc = I.getOpcode();
183   const bool isStore = Opc == TargetOpcode::G_STORE;
184 
185   if (isRegInGprb(ValueReg, MRI)) {
186     assert(((Ty.isScalar() && TySize == 32) ||
187             (Ty.isPointer() && TySize == 32 && MemSizeInBytes == 4)) &&
188            "Unsupported register bank, LLT, MemSizeInBytes combination");
189     (void)TySize;
190     if (isStore)
191       switch (MemSizeInBytes) {
192       case 4:
193         return Mips::SW;
194       case 2:
195         return Mips::SH;
196       case 1:
197         return Mips::SB;
198       default:
199         return Opc;
200       }
201     else
202       // Unspecified extending load is selected into zeroExtending load.
203       switch (MemSizeInBytes) {
204       case 4:
205         return Mips::LW;
206       case 2:
207         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
208       case 1:
209         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
210       default:
211         return Opc;
212       }
213   }
214 
215   if (isRegInFprb(ValueReg, MRI)) {
216     if (Ty.isScalar()) {
217       assert(((TySize == 32 && MemSizeInBytes == 4) ||
218               (TySize == 64 && MemSizeInBytes == 8)) &&
219              "Unsupported register bank, LLT, MemSizeInBytes combination");
220 
221       if (MemSizeInBytes == 4)
222         return isStore ? Mips::SWC1 : Mips::LWC1;
223 
224       if (STI.isFP64bit())
225         return isStore ? Mips::SDC164 : Mips::LDC164;
226       return isStore ? Mips::SDC1 : Mips::LDC1;
227     }
228 
229     if (Ty.isVector()) {
230       assert(STI.hasMSA() && "Vector instructions require target with MSA.");
231       assert((TySize == 128 && MemSizeInBytes == 16) &&
232              "Unsupported register bank, LLT, MemSizeInBytes combination");
233       switch (Ty.getElementType().getSizeInBits()) {
234       case 8:
235         return isStore ? Mips::ST_B : Mips::LD_B;
236       case 16:
237         return isStore ? Mips::ST_H : Mips::LD_H;
238       case 32:
239         return isStore ? Mips::ST_W : Mips::LD_W;
240       case 64:
241         return isStore ? Mips::ST_D : Mips::LD_D;
242       default:
243         return Opc;
244       }
245     }
246   }
247 
248   return Opc;
249 }
250 
251 bool MipsInstructionSelector::select(MachineInstr &I) {
252 
253   MachineBasicBlock &MBB = *I.getParent();
254   MachineFunction &MF = *MBB.getParent();
255   MachineRegisterInfo &MRI = MF.getRegInfo();
256 
257   if (!isPreISelGenericOpcode(I.getOpcode())) {
258     if (I.isCopy())
259       return selectCopy(I, MRI);
260 
261     return true;
262   }
263 
264   if (I.getOpcode() == Mips::G_MUL &&
265       isRegInGprb(I.getOperand(0).getReg(), MRI)) {
266     MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
267                             .add(I.getOperand(0))
268                             .add(I.getOperand(1))
269                             .add(I.getOperand(2));
270     if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
271       return false;
272     Mul->getOperand(3).setIsDead(true);
273     Mul->getOperand(4).setIsDead(true);
274 
275     I.eraseFromParent();
276     return true;
277   }
278 
279   if (selectImpl(I, *CoverageInfo))
280     return true;
281 
282   MachineInstr *MI = nullptr;
283   using namespace TargetOpcode;
284 
285   switch (I.getOpcode()) {
286   case G_UMULH: {
287     Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
288     MachineInstr *PseudoMULTu, *PseudoMove;
289 
290     PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
291                       .addDef(PseudoMULTuReg)
292                       .add(I.getOperand(1))
293                       .add(I.getOperand(2));
294     if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
295       return false;
296 
297     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
298                      .addDef(I.getOperand(0).getReg())
299                      .addUse(PseudoMULTuReg);
300     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
301       return false;
302 
303     I.eraseFromParent();
304     return true;
305   }
306   case G_PTR_ADD: {
307     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
308              .add(I.getOperand(0))
309              .add(I.getOperand(1))
310              .add(I.getOperand(2));
311     break;
312   }
313   case G_INTTOPTR:
314   case G_PTRTOINT: {
315     I.setDesc(TII.get(COPY));
316     return selectCopy(I, MRI);
317   }
318   case G_FRAME_INDEX: {
319     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
320              .add(I.getOperand(0))
321              .add(I.getOperand(1))
322              .addImm(0);
323     break;
324   }
325   case G_BRCOND: {
326     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
327              .add(I.getOperand(0))
328              .addUse(Mips::ZERO)
329              .add(I.getOperand(1));
330     break;
331   }
332   case G_BRJT: {
333     unsigned EntrySize =
334         MF.getJumpTableInfo()->getEntrySize(MF.getDataLayout());
335     assert(isPowerOf2_32(EntrySize) &&
336            "Non-power-of-two jump-table entry size not supported.");
337 
338     Register JTIndex = MRI.createVirtualRegister(&Mips::GPR32RegClass);
339     MachineInstr *SLL = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SLL))
340                             .addDef(JTIndex)
341                             .addUse(I.getOperand(2).getReg())
342                             .addImm(Log2_32(EntrySize));
343     if (!constrainSelectedInstRegOperands(*SLL, TII, TRI, RBI))
344       return false;
345 
346     Register DestAddress = MRI.createVirtualRegister(&Mips::GPR32RegClass);
347     MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
348                              .addDef(DestAddress)
349                              .addUse(I.getOperand(0).getReg())
350                              .addUse(JTIndex);
351     if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
352       return false;
353 
354     Register Dest = MRI.createVirtualRegister(&Mips::GPR32RegClass);
355     MachineInstr *LW =
356         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
357             .addDef(Dest)
358             .addUse(DestAddress)
359             .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_LO)
360             .addMemOperand(MF.getMachineMemOperand(
361                 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, 4));
362     if (!constrainSelectedInstRegOperands(*LW, TII, TRI, RBI))
363       return false;
364 
365     if (MF.getTarget().isPositionIndependent()) {
366       Register DestTmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
367       LW->getOperand(0).setReg(DestTmp);
368       MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
369                                .addDef(Dest)
370                                .addUse(DestTmp)
371                                .addUse(MF.getInfo<MipsFunctionInfo>()
372                                            ->getGlobalBaseRegForGlobalISel());
373       if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
374         return false;
375     }
376 
377     MachineInstr *Branch =
378         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
379             .addUse(Dest);
380     if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
381       return false;
382 
383     I.eraseFromParent();
384     return true;
385   }
386   case G_BRINDIRECT: {
387     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
388              .add(I.getOperand(0));
389     break;
390   }
391   case G_PHI: {
392     const Register DestReg = I.getOperand(0).getReg();
393 
394     const TargetRegisterClass *DefRC = nullptr;
395     if (Register::isPhysicalRegister(DestReg))
396       DefRC = TRI.getRegClass(DestReg);
397     else
398       DefRC = getRegClassForTypeOnBank(DestReg, MRI);
399 
400     I.setDesc(TII.get(TargetOpcode::PHI));
401     return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
402   }
403   case G_STORE:
404   case G_LOAD:
405   case G_ZEXTLOAD:
406   case G_SEXTLOAD: {
407     const unsigned NewOpc = selectLoadStoreOpCode(I, MRI);
408     if (NewOpc == I.getOpcode())
409       return false;
410 
411     MachineOperand BaseAddr = I.getOperand(1);
412     int64_t SignedOffset = 0;
413     // Try to fold load/store + G_PTR_ADD + G_CONSTANT
414     // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate
415     // %Addr:(p0) = G_PTR_ADD %BaseAddr, %SignedOffset
416     // %LoadResult/%StoreSrc = load/store %Addr(p0)
417     // into:
418     // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate
419 
420     MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg());
421     if (Addr->getOpcode() == G_PTR_ADD) {
422       MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg());
423       if (Offset->getOpcode() == G_CONSTANT) {
424         APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue();
425         if (OffsetValue.isSignedIntN(16)) {
426           BaseAddr = Addr->getOperand(1);
427           SignedOffset = OffsetValue.getSExtValue();
428         }
429       }
430     }
431 
432     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
433              .add(I.getOperand(0))
434              .add(BaseAddr)
435              .addImm(SignedOffset)
436              .addMemOperand(*I.memoperands_begin());
437     break;
438   }
439   case G_UDIV:
440   case G_UREM:
441   case G_SDIV:
442   case G_SREM: {
443     Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
444     bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
445     bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
446 
447     MachineInstr *PseudoDIV, *PseudoMove;
448     PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
449                         TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
450                     .addDef(HILOReg)
451                     .add(I.getOperand(1))
452                     .add(I.getOperand(2));
453     if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
454       return false;
455 
456     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
457                          TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
458                      .addDef(I.getOperand(0).getReg())
459                      .addUse(HILOReg);
460     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
461       return false;
462 
463     I.eraseFromParent();
464     return true;
465   }
466   case G_SELECT: {
467     // Handle operands with pointer type.
468     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
469              .add(I.getOperand(0))
470              .add(I.getOperand(2))
471              .add(I.getOperand(1))
472              .add(I.getOperand(3));
473     break;
474   }
475   case G_IMPLICIT_DEF: {
476     Register Dst = I.getOperand(0).getReg();
477     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
478              .addDef(Dst);
479 
480     // Set class based on register bank, there can be fpr and gpr implicit def.
481     MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst, MRI));
482     break;
483   }
484   case G_CONSTANT: {
485     MachineIRBuilder B(I);
486     if (!materialize32BitImm(I.getOperand(0).getReg(),
487                              I.getOperand(1).getCImm()->getValue(), B))
488       return false;
489 
490     I.eraseFromParent();
491     return true;
492   }
493   case G_FCONSTANT: {
494     const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
495     APInt APImm = FPimm.bitcastToAPInt();
496     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
497 
498     if (Size == 32) {
499       Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
500       MachineIRBuilder B(I);
501       if (!materialize32BitImm(GPRReg, APImm, B))
502         return false;
503 
504       MachineInstrBuilder MTC1 =
505           B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
506       if (!MTC1.constrainAllUses(TII, TRI, RBI))
507         return false;
508     }
509     if (Size == 64) {
510       Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
511       Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
512       MachineIRBuilder B(I);
513       if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
514         return false;
515       if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
516         return false;
517 
518       MachineInstrBuilder PairF64 = B.buildInstr(
519           STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
520           {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
521       if (!PairF64.constrainAllUses(TII, TRI, RBI))
522         return false;
523     }
524 
525     I.eraseFromParent();
526     return true;
527   }
528   case G_FABS: {
529     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
530     unsigned FABSOpcode =
531         Size == 32 ? Mips::FABS_S
532                    : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
533     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
534              .add(I.getOperand(0))
535              .add(I.getOperand(1));
536     break;
537   }
538   case G_FPTOSI: {
539     unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
540     unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
541     (void)ToSize;
542     assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
543     assert((FromSize == 32 || FromSize == 64) &&
544            "Unsupported floating point size for G_FPTOSI");
545 
546     unsigned Opcode;
547     if (FromSize == 32)
548       Opcode = Mips::TRUNC_W_S;
549     else
550       Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
551     Register ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
552     MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
553                 .addDef(ResultInFPR)
554                 .addUse(I.getOperand(1).getReg());
555     if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
556       return false;
557 
558     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
559                              .addDef(I.getOperand(0).getReg())
560                              .addUse(ResultInFPR);
561     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
562       return false;
563 
564     I.eraseFromParent();
565     return true;
566   }
567   case G_GLOBAL_VALUE: {
568     const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
569     if (MF.getTarget().isPositionIndependent()) {
570       MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
571                                 .addDef(I.getOperand(0).getReg())
572                                 .addReg(MF.getInfo<MipsFunctionInfo>()
573                                             ->getGlobalBaseRegForGlobalISel())
574                                 .addGlobalAddress(GVal);
575       // Global Values that don't have local linkage are handled differently
576       // when they are part of call sequence. MipsCallLowering::lowerCall
577       // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
578       // MO_GOT_CALL flag when Callee doesn't have local linkage.
579       if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
580         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
581       else
582         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
583       LWGOT->addMemOperand(
584           MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
585                                       MachineMemOperand::MOLoad, 4, 4));
586       if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
587         return false;
588 
589       if (GVal->hasLocalLinkage()) {
590         Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
591         LWGOT->getOperand(0).setReg(LWGOTDef);
592 
593         MachineInstr *ADDiu =
594             BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
595                 .addDef(I.getOperand(0).getReg())
596                 .addReg(LWGOTDef)
597                 .addGlobalAddress(GVal);
598         ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
599         if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
600           return false;
601       }
602     } else {
603       Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
604 
605       MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
606                               .addDef(LUiReg)
607                               .addGlobalAddress(GVal);
608       LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
609       if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
610         return false;
611 
612       MachineInstr *ADDiu =
613           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
614               .addDef(I.getOperand(0).getReg())
615               .addUse(LUiReg)
616               .addGlobalAddress(GVal);
617       ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
618       if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
619         return false;
620     }
621     I.eraseFromParent();
622     return true;
623   }
624   case G_JUMP_TABLE: {
625     if (MF.getTarget().isPositionIndependent()) {
626       MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
627                .addDef(I.getOperand(0).getReg())
628                .addReg(MF.getInfo<MipsFunctionInfo>()
629                            ->getGlobalBaseRegForGlobalISel())
630                .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_GOT)
631                .addMemOperand(
632                    MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
633                                            MachineMemOperand::MOLoad, 4, 4));
634     } else {
635       MI =
636           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
637               .addDef(I.getOperand(0).getReg())
638               .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_HI);
639     }
640     break;
641   }
642   case G_ICMP: {
643     struct Instr {
644       unsigned Opcode;
645       Register Def, LHS, RHS;
646       Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
647           : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
648 
649       bool hasImm() const {
650         if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
651           return true;
652         return false;
653       }
654     };
655 
656     SmallVector<struct Instr, 2> Instructions;
657     Register ICMPReg = I.getOperand(0).getReg();
658     Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
659     Register LHS = I.getOperand(2).getReg();
660     Register RHS = I.getOperand(3).getReg();
661     CmpInst::Predicate Cond =
662         static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
663 
664     switch (Cond) {
665     case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
666       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
667       Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
668       break;
669     case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
670       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
671       Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
672       break;
673     case CmpInst::ICMP_UGT: // LHS >  RHS -> RHS < LHS
674       Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
675       break;
676     case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
677       Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
678       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
679       break;
680     case CmpInst::ICMP_ULT: // LHS <  RHS -> LHS < RHS
681       Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
682       break;
683     case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
684       Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
685       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
686       break;
687     case CmpInst::ICMP_SGT: // LHS >  RHS -> RHS < LHS
688       Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
689       break;
690     case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
691       Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
692       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
693       break;
694     case CmpInst::ICMP_SLT: // LHS <  RHS -> LHS < RHS
695       Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
696       break;
697     case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
698       Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
699       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
700       break;
701     default:
702       return false;
703     }
704 
705     MachineIRBuilder B(I);
706     for (const struct Instr &Instruction : Instructions) {
707       MachineInstrBuilder MIB = B.buildInstr(
708           Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
709 
710       if (Instruction.hasImm())
711         MIB.addImm(Instruction.RHS);
712       else
713         MIB.addUse(Instruction.RHS);
714 
715       if (!MIB.constrainAllUses(TII, TRI, RBI))
716         return false;
717     }
718 
719     I.eraseFromParent();
720     return true;
721   }
722   case G_FCMP: {
723     unsigned MipsFCMPCondCode;
724     bool isLogicallyNegated;
725     switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
726                 I.getOperand(1).getPredicate())) {
727     case CmpInst::FCMP_UNO: // Unordered
728     case CmpInst::FCMP_ORD: // Ordered (OR)
729       MipsFCMPCondCode = Mips::FCOND_UN;
730       isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
731       break;
732     case CmpInst::FCMP_OEQ: // Equal
733     case CmpInst::FCMP_UNE: // Not Equal (NEQ)
734       MipsFCMPCondCode = Mips::FCOND_OEQ;
735       isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
736       break;
737     case CmpInst::FCMP_UEQ: // Unordered or Equal
738     case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
739       MipsFCMPCondCode = Mips::FCOND_UEQ;
740       isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
741       break;
742     case CmpInst::FCMP_OLT: // Ordered or Less Than
743     case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
744       MipsFCMPCondCode = Mips::FCOND_OLT;
745       isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
746       break;
747     case CmpInst::FCMP_ULT: // Unordered or Less Than
748     case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
749       MipsFCMPCondCode = Mips::FCOND_ULT;
750       isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
751       break;
752     case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
753     case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
754       MipsFCMPCondCode = Mips::FCOND_OLE;
755       isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
756       break;
757     case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
758     case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
759       MipsFCMPCondCode = Mips::FCOND_ULE;
760       isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
761       break;
762     default:
763       return false;
764     }
765 
766     // Default compare result in gpr register will be `true`.
767     // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
768     // using MOVF_I. When orignal predicate (Cond) is logically negated
769     // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
770     unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
771 
772     Register TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
773     BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
774         .addDef(TrueInReg)
775         .addUse(Mips::ZERO)
776         .addImm(1);
777 
778     unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
779     unsigned FCMPOpcode =
780         Size == 32 ? Mips::FCMP_S32
781                    : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
782     MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
783                              .addUse(I.getOperand(2).getReg())
784                              .addUse(I.getOperand(3).getReg())
785                              .addImm(MipsFCMPCondCode);
786     if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
787       return false;
788 
789     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
790                              .addDef(I.getOperand(0).getReg())
791                              .addUse(Mips::ZERO)
792                              .addUse(Mips::FCC0)
793                              .addUse(TrueInReg);
794     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
795       return false;
796 
797     I.eraseFromParent();
798     return true;
799   }
800   case G_FENCE: {
801     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
802     break;
803   }
804   case G_VASTART: {
805     MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
806     int FI = FuncInfo->getVarArgsFrameIndex();
807 
808     Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
809     MachineInstr *LEA_ADDiu =
810         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
811             .addDef(LeaReg)
812             .addFrameIndex(FI)
813             .addImm(0);
814     if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
815       return false;
816 
817     MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
818                               .addUse(LeaReg)
819                               .addUse(I.getOperand(0).getReg())
820                               .addImm(0);
821     if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
822       return false;
823 
824     I.eraseFromParent();
825     return true;
826   }
827   default:
828     return false;
829   }
830 
831   I.eraseFromParent();
832   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
833 }
834 
835 namespace llvm {
836 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
837                                                    MipsSubtarget &Subtarget,
838                                                    MipsRegisterBankInfo &RBI) {
839   return new MipsInstructionSelector(TM, Subtarget, RBI);
840 }
841 } // end namespace llvm
842