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