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