]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Mips / MipsInstructionSelector.cpp
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_FRAME_INDEX: {
269     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
270              .add(I.getOperand(0))
271              .add(I.getOperand(1))
272              .addImm(0);
273     break;
274   }
275   case G_BRCOND: {
276     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
277              .add(I.getOperand(0))
278              .addUse(Mips::ZERO)
279              .add(I.getOperand(1));
280     break;
281   }
282   case G_PHI: {
283     const Register DestReg = I.getOperand(0).getReg();
284     const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
285
286     const TargetRegisterClass *DefRC = nullptr;
287     if (TargetRegisterInfo::isPhysicalRegister(DestReg))
288       DefRC = TRI.getRegClass(DestReg);
289     else
290       DefRC = getRegClassForTypeOnBank(OpSize,
291                                        *RBI.getRegBank(DestReg, MRI, TRI), RBI);
292
293     I.setDesc(TII.get(TargetOpcode::PHI));
294     return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
295   }
296   case G_STORE:
297   case G_LOAD:
298   case G_ZEXTLOAD:
299   case G_SEXTLOAD: {
300     const Register DestReg = I.getOperand(0).getReg();
301     const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
302     const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
303     const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();
304
305     if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32)
306       return false;
307
308     if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64)
309       return false;
310
311     const unsigned NewOpc = selectLoadStoreOpCode(
312         I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit());
313     if (NewOpc == I.getOpcode())
314       return false;
315
316     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
317              .add(I.getOperand(0))
318              .add(I.getOperand(1))
319              .addImm(0)
320              .addMemOperand(*I.memoperands_begin());
321     break;
322   }
323   case G_UDIV:
324   case G_UREM:
325   case G_SDIV:
326   case G_SREM: {
327     Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
328     bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
329     bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
330
331     MachineInstr *PseudoDIV, *PseudoMove;
332     PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
333                         TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
334                     .addDef(HILOReg)
335                     .add(I.getOperand(1))
336                     .add(I.getOperand(2));
337     if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
338       return false;
339
340     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
341                          TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
342                      .addDef(I.getOperand(0).getReg())
343                      .addUse(HILOReg);
344     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
345       return false;
346
347     I.eraseFromParent();
348     return true;
349   }
350   case G_SELECT: {
351     // Handle operands with pointer type.
352     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
353              .add(I.getOperand(0))
354              .add(I.getOperand(2))
355              .add(I.getOperand(1))
356              .add(I.getOperand(3));
357     break;
358   }
359   case G_CONSTANT: {
360     MachineIRBuilder B(I);
361     if (!materialize32BitImm(I.getOperand(0).getReg(),
362                              I.getOperand(1).getCImm()->getValue(), B))
363       return false;
364
365     I.eraseFromParent();
366     return true;
367   }
368   case G_FCONSTANT: {
369     const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
370     APInt APImm = FPimm.bitcastToAPInt();
371     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
372
373     if (Size == 32) {
374       Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
375       MachineIRBuilder B(I);
376       if (!materialize32BitImm(GPRReg, APImm, B))
377         return false;
378
379       MachineInstrBuilder MTC1 =
380           B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
381       if (!MTC1.constrainAllUses(TII, TRI, RBI))
382         return false;
383     }
384     if (Size == 64) {
385       Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
386       Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
387       MachineIRBuilder B(I);
388       if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
389         return false;
390       if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
391         return false;
392
393       MachineInstrBuilder PairF64 = B.buildInstr(
394           STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
395           {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
396       if (!PairF64.constrainAllUses(TII, TRI, RBI))
397         return false;
398     }
399
400     I.eraseFromParent();
401     return true;
402   }
403   case G_FABS: {
404     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
405     unsigned FABSOpcode =
406         Size == 32 ? Mips::FABS_S
407                    : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
408     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
409              .add(I.getOperand(0))
410              .add(I.getOperand(1));
411     break;
412   }
413   case G_FPTOSI: {
414     unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
415     unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
416     (void)ToSize;
417     assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
418     assert((FromSize == 32 || FromSize == 64) &&
419            "Unsupported floating point size for G_FPTOSI");
420
421     unsigned Opcode;
422     if (FromSize == 32)
423       Opcode = Mips::TRUNC_W_S;
424     else
425       Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
426     unsigned ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
427     MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
428                 .addDef(ResultInFPR)
429                 .addUse(I.getOperand(1).getReg());
430     if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
431       return false;
432
433     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
434                              .addDef(I.getOperand(0).getReg())
435                              .addUse(ResultInFPR);
436     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
437       return false;
438
439     I.eraseFromParent();
440     return true;
441   }
442   case G_GLOBAL_VALUE: {
443     const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
444     if (MF.getTarget().isPositionIndependent()) {
445       MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
446                                 .addDef(I.getOperand(0).getReg())
447                                 .addReg(MF.getInfo<MipsFunctionInfo>()
448                                             ->getGlobalBaseRegForGlobalISel())
449                                 .addGlobalAddress(GVal);
450       // Global Values that don't have local linkage are handled differently
451       // when they are part of call sequence. MipsCallLowering::lowerCall
452       // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
453       // MO_GOT_CALL flag when Callee doesn't have local linkage.
454       if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
455         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
456       else
457         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
458       LWGOT->addMemOperand(
459           MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
460                                       MachineMemOperand::MOLoad, 4, 4));
461       if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
462         return false;
463
464       if (GVal->hasLocalLinkage()) {
465         Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
466         LWGOT->getOperand(0).setReg(LWGOTDef);
467
468         MachineInstr *ADDiu =
469             BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
470                 .addDef(I.getOperand(0).getReg())
471                 .addReg(LWGOTDef)
472                 .addGlobalAddress(GVal);
473         ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
474         if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
475           return false;
476       }
477     } else {
478       Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
479
480       MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
481                               .addDef(LUiReg)
482                               .addGlobalAddress(GVal);
483       LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
484       if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
485         return false;
486
487       MachineInstr *ADDiu =
488           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
489               .addDef(I.getOperand(0).getReg())
490               .addUse(LUiReg)
491               .addGlobalAddress(GVal);
492       ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
493       if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
494         return false;
495     }
496     I.eraseFromParent();
497     return true;
498   }
499   case G_ICMP: {
500     struct Instr {
501       unsigned Opcode;
502       Register Def, LHS, RHS;
503       Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
504           : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
505
506       bool hasImm() const {
507         if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
508           return true;
509         return false;
510       }
511     };
512
513     SmallVector<struct Instr, 2> Instructions;
514     Register ICMPReg = I.getOperand(0).getReg();
515     Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
516     Register LHS = I.getOperand(2).getReg();
517     Register RHS = I.getOperand(3).getReg();
518     CmpInst::Predicate Cond =
519         static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
520
521     switch (Cond) {
522     case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
523       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
524       Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
525       break;
526     case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
527       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
528       Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
529       break;
530     case CmpInst::ICMP_UGT: // LHS >  RHS -> RHS < LHS
531       Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
532       break;
533     case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
534       Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
535       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
536       break;
537     case CmpInst::ICMP_ULT: // LHS <  RHS -> LHS < RHS
538       Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
539       break;
540     case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
541       Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
542       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
543       break;
544     case CmpInst::ICMP_SGT: // LHS >  RHS -> RHS < LHS
545       Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
546       break;
547     case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
548       Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
549       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
550       break;
551     case CmpInst::ICMP_SLT: // LHS <  RHS -> LHS < RHS
552       Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
553       break;
554     case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
555       Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
556       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
557       break;
558     default:
559       return false;
560     }
561
562     MachineIRBuilder B(I);
563     for (const struct Instr &Instruction : Instructions) {
564       MachineInstrBuilder MIB = B.buildInstr(
565           Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
566
567       if (Instruction.hasImm())
568         MIB.addImm(Instruction.RHS);
569       else
570         MIB.addUse(Instruction.RHS);
571
572       if (!MIB.constrainAllUses(TII, TRI, RBI))
573         return false;
574     }
575
576     I.eraseFromParent();
577     return true;
578   }
579   case G_FCMP: {
580     unsigned MipsFCMPCondCode;
581     bool isLogicallyNegated;
582     switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
583                 I.getOperand(1).getPredicate())) {
584     case CmpInst::FCMP_UNO: // Unordered
585     case CmpInst::FCMP_ORD: // Ordered (OR)
586       MipsFCMPCondCode = Mips::FCOND_UN;
587       isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
588       break;
589     case CmpInst::FCMP_OEQ: // Equal
590     case CmpInst::FCMP_UNE: // Not Equal (NEQ)
591       MipsFCMPCondCode = Mips::FCOND_OEQ;
592       isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
593       break;
594     case CmpInst::FCMP_UEQ: // Unordered or Equal
595     case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
596       MipsFCMPCondCode = Mips::FCOND_UEQ;
597       isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
598       break;
599     case CmpInst::FCMP_OLT: // Ordered or Less Than
600     case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
601       MipsFCMPCondCode = Mips::FCOND_OLT;
602       isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
603       break;
604     case CmpInst::FCMP_ULT: // Unordered or Less Than
605     case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
606       MipsFCMPCondCode = Mips::FCOND_ULT;
607       isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
608       break;
609     case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
610     case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
611       MipsFCMPCondCode = Mips::FCOND_OLE;
612       isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
613       break;
614     case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
615     case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
616       MipsFCMPCondCode = Mips::FCOND_ULE;
617       isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
618       break;
619     default:
620       return false;
621     }
622
623     // Default compare result in gpr register will be `true`.
624     // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
625     // using MOVF_I. When orignal predicate (Cond) is logically negated
626     // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
627     unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
628
629     unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
630     BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
631         .addDef(TrueInReg)
632         .addUse(Mips::ZERO)
633         .addImm(1);
634
635     unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
636     unsigned FCMPOpcode =
637         Size == 32 ? Mips::FCMP_S32
638                    : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
639     MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
640                              .addUse(I.getOperand(2).getReg())
641                              .addUse(I.getOperand(3).getReg())
642                              .addImm(MipsFCMPCondCode);
643     if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
644       return false;
645
646     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
647                              .addDef(I.getOperand(0).getReg())
648                              .addUse(Mips::ZERO)
649                              .addUse(Mips::FCC0)
650                              .addUse(TrueInReg);
651     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
652       return false;
653
654     I.eraseFromParent();
655     return true;
656   }
657   default:
658     return false;
659   }
660
661   I.eraseFromParent();
662   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
663 }
664
665 namespace llvm {
666 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
667                                                    MipsSubtarget &Subtarget,
668                                                    MipsRegisterBankInfo &RBI) {
669   return new MipsInstructionSelector(TM, Subtarget, RBI);
670 }
671 } // end namespace llvm