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 
21 #define DEBUG_TYPE "mips-isel"
22 
23 using namespace llvm;
24 
25 namespace {
26 
27 #define GET_GLOBALISEL_PREDICATE_BITSET
28 #include "MipsGenGlobalISel.inc"
29 #undef GET_GLOBALISEL_PREDICATE_BITSET
30 
31 class MipsInstructionSelector : public InstructionSelector {
32 public:
33   MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
34                           const MipsRegisterBankInfo &RBI);
35 
36   bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
37   static const char *getName() { return DEBUG_TYPE; }
38 
39 private:
40   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
41   bool materialize32BitImm(Register DestReg, APInt Imm,
42                            MachineIRBuilder &B) const;
43   bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
44   const TargetRegisterClass *
45   getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB,
46                            const RegisterBankInfo &RBI) const;
47 
48   const MipsTargetMachine &TM;
49   const MipsSubtarget &STI;
50   const MipsInstrInfo &TII;
51   const MipsRegisterInfo &TRI;
52   const MipsRegisterBankInfo &RBI;
53 
54 #define GET_GLOBALISEL_PREDICATES_DECL
55 #include "MipsGenGlobalISel.inc"
56 #undef GET_GLOBALISEL_PREDICATES_DECL
57 
58 #define GET_GLOBALISEL_TEMPORARIES_DECL
59 #include "MipsGenGlobalISel.inc"
60 #undef GET_GLOBALISEL_TEMPORARIES_DECL
61 };
62 
63 } // end anonymous namespace
64 
65 #define GET_GLOBALISEL_IMPL
66 #include "MipsGenGlobalISel.inc"
67 #undef GET_GLOBALISEL_IMPL
68 
69 MipsInstructionSelector::MipsInstructionSelector(
70     const MipsTargetMachine &TM, const MipsSubtarget &STI,
71     const MipsRegisterBankInfo &RBI)
72     : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
73       TRI(*STI.getRegisterInfo()), RBI(RBI),
74 
75 #define GET_GLOBALISEL_PREDICATES_INIT
76 #include "MipsGenGlobalISel.inc"
77 #undef GET_GLOBALISEL_PREDICATES_INIT
78 #define GET_GLOBALISEL_TEMPORARIES_INIT
79 #include "MipsGenGlobalISel.inc"
80 #undef GET_GLOBALISEL_TEMPORARIES_INIT
81 {
82 }
83 
84 bool MipsInstructionSelector::selectCopy(MachineInstr &I,
85                                          MachineRegisterInfo &MRI) const {
86   Register DstReg = I.getOperand(0).getReg();
87   if (TargetRegisterInfo::isPhysicalRegister(DstReg))
88     return true;
89 
90   const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
91   const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
92 
93   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
94   if (RegBank->getID() == Mips::FPRBRegBankID) {
95     if (DstSize == 32)
96       RC = &Mips::FGR32RegClass;
97     else if (DstSize == 64)
98       RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
99     else
100       llvm_unreachable("Unsupported destination size");
101   }
102   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
103     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
104                       << " operand\n");
105     return false;
106   }
107   return true;
108 }
109 
110 const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
111     unsigned OpSize, const RegisterBank &RB,
112     const RegisterBankInfo &RBI) const {
113   if (RB.getID() == Mips::GPRBRegBankID)
114     return &Mips::GPR32RegClass;
115 
116   if (RB.getID() == Mips::FPRBRegBankID)
117     return OpSize == 32
118                ? &Mips::FGR32RegClass
119                : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass
120                                                       : &Mips::AFGR64RegClass;
121 
122   llvm_unreachable("getRegClassForTypeOnBank can't find register class.");
123   return nullptr;
124 }
125 
126 bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
127                                                   MachineIRBuilder &B) const {
128   assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
129   // Ori zero extends immediate. Used for values with zeros in high 16 bits.
130   if (Imm.getHiBits(16).isNullValue()) {
131     MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
132                              .addImm(Imm.getLoBits(16).getLimitedValue());
133     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
134   }
135   // Lui places immediate in high 16 bits and sets low 16 bits to zero.
136   if (Imm.getLoBits(16).isNullValue()) {
137     MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
138                              .addImm(Imm.getHiBits(16).getLimitedValue());
139     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
140   }
141   // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
142   if (Imm.isSignedIntN(16)) {
143     MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
144                              .addImm(Imm.getLoBits(16).getLimitedValue());
145     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
146   }
147   // Values that cannot be materialized with single immediate instruction.
148   Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
149   MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
150                           .addImm(Imm.getHiBits(16).getLimitedValue());
151   MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
152                           .addImm(Imm.getLoBits(16).getLimitedValue());
153   if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
154     return false;
155   if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
156     return false;
157   return true;
158 }
159 
160 /// Returning Opc indicates that we failed to select MIPS instruction opcode.
161 static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes,
162                                       unsigned RegBank, bool isFP64) {
163   bool isStore = Opc == TargetOpcode::G_STORE;
164   if (RegBank == Mips::GPRBRegBankID) {
165     if (isStore)
166       switch (MemSizeInBytes) {
167       case 4:
168         return Mips::SW;
169       case 2:
170         return Mips::SH;
171       case 1:
172         return Mips::SB;
173       default:
174         return Opc;
175       }
176     else
177       // Unspecified extending load is selected into zeroExtending load.
178       switch (MemSizeInBytes) {
179       case 4:
180         return Mips::LW;
181       case 2:
182         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
183       case 1:
184         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
185       default:
186         return Opc;
187       }
188   }
189 
190   if (RegBank == Mips::FPRBRegBankID) {
191     switch (MemSizeInBytes) {
192     case 4:
193       return isStore ? Mips::SWC1 : Mips::LWC1;
194     case 8:
195       if (isFP64)
196         return isStore ? Mips::SDC164 : Mips::LDC164;
197       else
198         return isStore ? Mips::SDC1 : Mips::LDC1;
199     default:
200       return Opc;
201     }
202   }
203   return Opc;
204 }
205 
206 bool MipsInstructionSelector::select(MachineInstr &I,
207                                      CodeGenCoverage &CoverageInfo) const {
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_PHI: {
288     const Register DestReg = I.getOperand(0).getReg();
289     const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
290 
291     const TargetRegisterClass *DefRC = nullptr;
292     if (TargetRegisterInfo::isPhysicalRegister(DestReg))
293       DefRC = TRI.getRegClass(DestReg);
294     else
295       DefRC = getRegClassForTypeOnBank(OpSize,
296                                        *RBI.getRegBank(DestReg, MRI, TRI), RBI);
297 
298     I.setDesc(TII.get(TargetOpcode::PHI));
299     return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
300   }
301   case G_STORE:
302   case G_LOAD:
303   case G_ZEXTLOAD:
304   case G_SEXTLOAD: {
305     const Register DestReg = I.getOperand(0).getReg();
306     const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
307     const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
308     const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();
309 
310     if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32)
311       return false;
312 
313     if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64)
314       return false;
315 
316     const unsigned NewOpc = selectLoadStoreOpCode(
317         I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit());
318     if (NewOpc == I.getOpcode())
319       return false;
320 
321     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
322              .add(I.getOperand(0))
323              .add(I.getOperand(1))
324              .addImm(0)
325              .addMemOperand(*I.memoperands_begin());
326     break;
327   }
328   case G_UDIV:
329   case G_UREM:
330   case G_SDIV:
331   case G_SREM: {
332     Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
333     bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
334     bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
335 
336     MachineInstr *PseudoDIV, *PseudoMove;
337     PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
338                         TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
339                     .addDef(HILOReg)
340                     .add(I.getOperand(1))
341                     .add(I.getOperand(2));
342     if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
343       return false;
344 
345     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
346                          TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
347                      .addDef(I.getOperand(0).getReg())
348                      .addUse(HILOReg);
349     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
350       return false;
351 
352     I.eraseFromParent();
353     return true;
354   }
355   case G_SELECT: {
356     // Handle operands with pointer type.
357     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
358              .add(I.getOperand(0))
359              .add(I.getOperand(2))
360              .add(I.getOperand(1))
361              .add(I.getOperand(3));
362     break;
363   }
364   case G_CONSTANT: {
365     MachineIRBuilder B(I);
366     if (!materialize32BitImm(I.getOperand(0).getReg(),
367                              I.getOperand(1).getCImm()->getValue(), B))
368       return false;
369 
370     I.eraseFromParent();
371     return true;
372   }
373   case G_FCONSTANT: {
374     const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
375     APInt APImm = FPimm.bitcastToAPInt();
376     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
377 
378     if (Size == 32) {
379       Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
380       MachineIRBuilder B(I);
381       if (!materialize32BitImm(GPRReg, APImm, B))
382         return false;
383 
384       MachineInstrBuilder MTC1 =
385           B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
386       if (!MTC1.constrainAllUses(TII, TRI, RBI))
387         return false;
388     }
389     if (Size == 64) {
390       Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
391       Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
392       MachineIRBuilder B(I);
393       if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
394         return false;
395       if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
396         return false;
397 
398       MachineInstrBuilder PairF64 = B.buildInstr(
399           STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
400           {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
401       if (!PairF64.constrainAllUses(TII, TRI, RBI))
402         return false;
403     }
404 
405     I.eraseFromParent();
406     return true;
407   }
408   case G_FABS: {
409     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
410     unsigned FABSOpcode =
411         Size == 32 ? Mips::FABS_S
412                    : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
413     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
414              .add(I.getOperand(0))
415              .add(I.getOperand(1));
416     break;
417   }
418   case G_FPTOSI: {
419     unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
420     unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
421     (void)ToSize;
422     assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
423     assert((FromSize == 32 || FromSize == 64) &&
424            "Unsupported floating point size for G_FPTOSI");
425 
426     unsigned Opcode;
427     if (FromSize == 32)
428       Opcode = Mips::TRUNC_W_S;
429     else
430       Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
431     unsigned ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
432     MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
433                 .addDef(ResultInFPR)
434                 .addUse(I.getOperand(1).getReg());
435     if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
436       return false;
437 
438     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
439                              .addDef(I.getOperand(0).getReg())
440                              .addUse(ResultInFPR);
441     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
442       return false;
443 
444     I.eraseFromParent();
445     return true;
446   }
447   case G_GLOBAL_VALUE: {
448     const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
449     if (MF.getTarget().isPositionIndependent()) {
450       MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
451                                 .addDef(I.getOperand(0).getReg())
452                                 .addReg(MF.getInfo<MipsFunctionInfo>()
453                                             ->getGlobalBaseRegForGlobalISel())
454                                 .addGlobalAddress(GVal);
455       // Global Values that don't have local linkage are handled differently
456       // when they are part of call sequence. MipsCallLowering::lowerCall
457       // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
458       // MO_GOT_CALL flag when Callee doesn't have local linkage.
459       if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
460         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
461       else
462         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
463       LWGOT->addMemOperand(
464           MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
465                                       MachineMemOperand::MOLoad, 4, 4));
466       if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
467         return false;
468 
469       if (GVal->hasLocalLinkage()) {
470         Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
471         LWGOT->getOperand(0).setReg(LWGOTDef);
472 
473         MachineInstr *ADDiu =
474             BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
475                 .addDef(I.getOperand(0).getReg())
476                 .addReg(LWGOTDef)
477                 .addGlobalAddress(GVal);
478         ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
479         if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
480           return false;
481       }
482     } else {
483       Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
484 
485       MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
486                               .addDef(LUiReg)
487                               .addGlobalAddress(GVal);
488       LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
489       if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
490         return false;
491 
492       MachineInstr *ADDiu =
493           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
494               .addDef(I.getOperand(0).getReg())
495               .addUse(LUiReg)
496               .addGlobalAddress(GVal);
497       ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
498       if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
499         return false;
500     }
501     I.eraseFromParent();
502     return true;
503   }
504   case G_ICMP: {
505     struct Instr {
506       unsigned Opcode;
507       Register Def, LHS, RHS;
508       Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
509           : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
510 
511       bool hasImm() const {
512         if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
513           return true;
514         return false;
515       }
516     };
517 
518     SmallVector<struct Instr, 2> Instructions;
519     Register ICMPReg = I.getOperand(0).getReg();
520     Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
521     Register LHS = I.getOperand(2).getReg();
522     Register RHS = I.getOperand(3).getReg();
523     CmpInst::Predicate Cond =
524         static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
525 
526     switch (Cond) {
527     case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
528       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
529       Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
530       break;
531     case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
532       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
533       Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
534       break;
535     case CmpInst::ICMP_UGT: // LHS >  RHS -> RHS < LHS
536       Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
537       break;
538     case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
539       Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
540       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
541       break;
542     case CmpInst::ICMP_ULT: // LHS <  RHS -> LHS < RHS
543       Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
544       break;
545     case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
546       Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
547       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
548       break;
549     case CmpInst::ICMP_SGT: // LHS >  RHS -> RHS < LHS
550       Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
551       break;
552     case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
553       Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
554       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
555       break;
556     case CmpInst::ICMP_SLT: // LHS <  RHS -> LHS < RHS
557       Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
558       break;
559     case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
560       Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
561       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
562       break;
563     default:
564       return false;
565     }
566 
567     MachineIRBuilder B(I);
568     for (const struct Instr &Instruction : Instructions) {
569       MachineInstrBuilder MIB = B.buildInstr(
570           Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
571 
572       if (Instruction.hasImm())
573         MIB.addImm(Instruction.RHS);
574       else
575         MIB.addUse(Instruction.RHS);
576 
577       if (!MIB.constrainAllUses(TII, TRI, RBI))
578         return false;
579     }
580 
581     I.eraseFromParent();
582     return true;
583   }
584   case G_FCMP: {
585     unsigned MipsFCMPCondCode;
586     bool isLogicallyNegated;
587     switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
588                 I.getOperand(1).getPredicate())) {
589     case CmpInst::FCMP_UNO: // Unordered
590     case CmpInst::FCMP_ORD: // Ordered (OR)
591       MipsFCMPCondCode = Mips::FCOND_UN;
592       isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
593       break;
594     case CmpInst::FCMP_OEQ: // Equal
595     case CmpInst::FCMP_UNE: // Not Equal (NEQ)
596       MipsFCMPCondCode = Mips::FCOND_OEQ;
597       isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
598       break;
599     case CmpInst::FCMP_UEQ: // Unordered or Equal
600     case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
601       MipsFCMPCondCode = Mips::FCOND_UEQ;
602       isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
603       break;
604     case CmpInst::FCMP_OLT: // Ordered or Less Than
605     case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
606       MipsFCMPCondCode = Mips::FCOND_OLT;
607       isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
608       break;
609     case CmpInst::FCMP_ULT: // Unordered or Less Than
610     case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
611       MipsFCMPCondCode = Mips::FCOND_ULT;
612       isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
613       break;
614     case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
615     case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
616       MipsFCMPCondCode = Mips::FCOND_OLE;
617       isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
618       break;
619     case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
620     case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
621       MipsFCMPCondCode = Mips::FCOND_ULE;
622       isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
623       break;
624     default:
625       return false;
626     }
627 
628     // Default compare result in gpr register will be `true`.
629     // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
630     // using MOVF_I. When orignal predicate (Cond) is logically negated
631     // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
632     unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
633 
634     unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
635     BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
636         .addDef(TrueInReg)
637         .addUse(Mips::ZERO)
638         .addImm(1);
639 
640     unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
641     unsigned FCMPOpcode =
642         Size == 32 ? Mips::FCMP_S32
643                    : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
644     MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
645                              .addUse(I.getOperand(2).getReg())
646                              .addUse(I.getOperand(3).getReg())
647                              .addImm(MipsFCMPCondCode);
648     if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
649       return false;
650 
651     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
652                              .addDef(I.getOperand(0).getReg())
653                              .addUse(Mips::ZERO)
654                              .addUse(Mips::FCC0)
655                              .addUse(TrueInReg);
656     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
657       return false;
658 
659     I.eraseFromParent();
660     return true;
661   }
662   default:
663     return false;
664   }
665 
666   I.eraseFromParent();
667   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
668 }
669 
670 namespace llvm {
671 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
672                                                    MipsSubtarget &Subtarget,
673                                                    MipsRegisterBankInfo &RBI) {
674   return new MipsInstructionSelector(TM, Subtarget, RBI);
675 }
676 } // end namespace llvm
677