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