xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Mips/MipsInstructionSelector.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// This file implements the targeting of the InstructionSelector class for
100b57cec5SDimitry Andric /// Mips.
110b57cec5SDimitry Andric /// \todo This should be generated by TableGen.
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "MCTargetDesc/MipsInstPrinter.h"
150b57cec5SDimitry Andric #include "MipsMachineFunction.h"
160b57cec5SDimitry Andric #include "MipsRegisterBankInfo.h"
170b57cec5SDimitry Andric #include "MipsTargetMachine.h"
1806c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
208bcb0991SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
21480093f4SDimitry Andric #include "llvm/IR/IntrinsicsMips.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #define DEBUG_TYPE "mips-isel"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define GET_GLOBALISEL_PREDICATE_BITSET
300b57cec5SDimitry Andric #include "MipsGenGlobalISel.inc"
310b57cec5SDimitry Andric #undef GET_GLOBALISEL_PREDICATE_BITSET
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric class MipsInstructionSelector : public InstructionSelector {
340b57cec5SDimitry Andric public:
350b57cec5SDimitry Andric   MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
360b57cec5SDimitry Andric                           const MipsRegisterBankInfo &RBI);
370b57cec5SDimitry Andric 
388bcb0991SDimitry Andric   bool select(MachineInstr &I) override;
390b57cec5SDimitry Andric   static const char *getName() { return DEBUG_TYPE; }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric private:
420b57cec5SDimitry Andric   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
43480093f4SDimitry Andric   bool isRegInGprb(Register Reg, MachineRegisterInfo &MRI) const;
44480093f4SDimitry Andric   bool isRegInFprb(Register Reg, MachineRegisterInfo &MRI) const;
450b57cec5SDimitry Andric   bool materialize32BitImm(Register DestReg, APInt Imm,
460b57cec5SDimitry Andric                            MachineIRBuilder &B) const;
470b57cec5SDimitry Andric   bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
480b57cec5SDimitry Andric   const TargetRegisterClass *
49480093f4SDimitry Andric   getRegClassForTypeOnBank(Register Reg, MachineRegisterInfo &MRI) const;
508bcb0991SDimitry Andric   unsigned selectLoadStoreOpCode(MachineInstr &I,
518bcb0991SDimitry Andric                                  MachineRegisterInfo &MRI) const;
525ffd83dbSDimitry Andric   bool buildUnalignedStore(MachineInstr &I, unsigned Opc,
535ffd83dbSDimitry Andric                            MachineOperand &BaseAddr, unsigned Offset,
545ffd83dbSDimitry Andric                            MachineMemOperand *MMO) const;
555ffd83dbSDimitry Andric   bool buildUnalignedLoad(MachineInstr &I, unsigned Opc, Register Dest,
565ffd83dbSDimitry Andric                           MachineOperand &BaseAddr, unsigned Offset,
575ffd83dbSDimitry Andric                           Register TiedDest, MachineMemOperand *MMO) const;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   const MipsTargetMachine &TM;
600b57cec5SDimitry Andric   const MipsSubtarget &STI;
610b57cec5SDimitry Andric   const MipsInstrInfo &TII;
620b57cec5SDimitry Andric   const MipsRegisterInfo &TRI;
630b57cec5SDimitry Andric   const MipsRegisterBankInfo &RBI;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric #define GET_GLOBALISEL_PREDICATES_DECL
660b57cec5SDimitry Andric #include "MipsGenGlobalISel.inc"
670b57cec5SDimitry Andric #undef GET_GLOBALISEL_PREDICATES_DECL
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric #define GET_GLOBALISEL_TEMPORARIES_DECL
700b57cec5SDimitry Andric #include "MipsGenGlobalISel.inc"
710b57cec5SDimitry Andric #undef GET_GLOBALISEL_TEMPORARIES_DECL
720b57cec5SDimitry Andric };
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric } // end anonymous namespace
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric #define GET_GLOBALISEL_IMPL
770b57cec5SDimitry Andric #include "MipsGenGlobalISel.inc"
780b57cec5SDimitry Andric #undef GET_GLOBALISEL_IMPL
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric MipsInstructionSelector::MipsInstructionSelector(
810b57cec5SDimitry Andric     const MipsTargetMachine &TM, const MipsSubtarget &STI,
820b57cec5SDimitry Andric     const MipsRegisterBankInfo &RBI)
8304eeddc0SDimitry Andric     : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
8404eeddc0SDimitry Andric       RBI(RBI),
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric #define GET_GLOBALISEL_PREDICATES_INIT
870b57cec5SDimitry Andric #include "MipsGenGlobalISel.inc"
880b57cec5SDimitry Andric #undef GET_GLOBALISEL_PREDICATES_INIT
890b57cec5SDimitry Andric #define GET_GLOBALISEL_TEMPORARIES_INIT
900b57cec5SDimitry Andric #include "MipsGenGlobalISel.inc"
910b57cec5SDimitry Andric #undef GET_GLOBALISEL_TEMPORARIES_INIT
920b57cec5SDimitry Andric {
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
95480093f4SDimitry Andric bool MipsInstructionSelector::isRegInGprb(Register Reg,
96480093f4SDimitry Andric                                           MachineRegisterInfo &MRI) const {
97480093f4SDimitry Andric   return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::GPRBRegBankID;
98480093f4SDimitry Andric }
99480093f4SDimitry Andric 
100480093f4SDimitry Andric bool MipsInstructionSelector::isRegInFprb(Register Reg,
101480093f4SDimitry Andric                                           MachineRegisterInfo &MRI) const {
102480093f4SDimitry Andric   return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::FPRBRegBankID;
103480093f4SDimitry Andric }
104480093f4SDimitry Andric 
1050b57cec5SDimitry Andric bool MipsInstructionSelector::selectCopy(MachineInstr &I,
1060b57cec5SDimitry Andric                                          MachineRegisterInfo &MRI) const {
1070b57cec5SDimitry Andric   Register DstReg = I.getOperand(0).getReg();
108bdd1243dSDimitry Andric   if (DstReg.isPhysical())
1090b57cec5SDimitry Andric     return true;
1100b57cec5SDimitry Andric 
111480093f4SDimitry Andric   const TargetRegisterClass *RC = getRegClassForTypeOnBank(DstReg, MRI);
1120b57cec5SDimitry Andric   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1130b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1140b57cec5SDimitry Andric                       << " operand\n");
1150b57cec5SDimitry Andric     return false;
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric   return true;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
121480093f4SDimitry Andric     Register Reg, MachineRegisterInfo &MRI) const {
122480093f4SDimitry Andric   const LLT Ty = MRI.getType(Reg);
123480093f4SDimitry Andric   const unsigned TySize = Ty.getSizeInBits();
124480093f4SDimitry Andric 
125480093f4SDimitry Andric   if (isRegInGprb(Reg, MRI)) {
126480093f4SDimitry Andric     assert((Ty.isScalar() || Ty.isPointer()) && TySize == 32 &&
127480093f4SDimitry Andric            "Register class not available for LLT, register bank combination");
1280b57cec5SDimitry Andric     return &Mips::GPR32RegClass;
129480093f4SDimitry Andric   }
1300b57cec5SDimitry Andric 
131480093f4SDimitry Andric   if (isRegInFprb(Reg, MRI)) {
132480093f4SDimitry Andric     if (Ty.isScalar()) {
133480093f4SDimitry Andric       assert((TySize == 32 || TySize == 64) &&
134480093f4SDimitry Andric              "Register class not available for LLT, register bank combination");
135480093f4SDimitry Andric       if (TySize == 32)
136480093f4SDimitry Andric         return &Mips::FGR32RegClass;
137480093f4SDimitry Andric       return STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
138480093f4SDimitry Andric     }
139480093f4SDimitry Andric   }
1400b57cec5SDimitry Andric 
141480093f4SDimitry Andric   llvm_unreachable("Unsupported register bank.");
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
1450b57cec5SDimitry Andric                                                   MachineIRBuilder &B) const {
1460b57cec5SDimitry Andric   assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
1470b57cec5SDimitry Andric   // Ori zero extends immediate. Used for values with zeros in high 16 bits.
148349cc55cSDimitry Andric   if (Imm.getHiBits(16).isZero()) {
149480093f4SDimitry Andric     MachineInstr *Inst =
150480093f4SDimitry Andric         B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
1510b57cec5SDimitry Andric             .addImm(Imm.getLoBits(16).getLimitedValue());
1520b57cec5SDimitry Andric     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric   // Lui places immediate in high 16 bits and sets low 16 bits to zero.
155349cc55cSDimitry Andric   if (Imm.getLoBits(16).isZero()) {
1560b57cec5SDimitry Andric     MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
1570b57cec5SDimitry Andric                              .addImm(Imm.getHiBits(16).getLimitedValue());
1580b57cec5SDimitry Andric     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric   // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
1610b57cec5SDimitry Andric   if (Imm.isSignedIntN(16)) {
162480093f4SDimitry Andric     MachineInstr *Inst =
163480093f4SDimitry Andric         B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
1640b57cec5SDimitry Andric             .addImm(Imm.getLoBits(16).getLimitedValue());
1650b57cec5SDimitry Andric     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric   // Values that cannot be materialized with single immediate instruction.
1680b57cec5SDimitry Andric   Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
1690b57cec5SDimitry Andric   MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
1700b57cec5SDimitry Andric                           .addImm(Imm.getHiBits(16).getLimitedValue());
1710b57cec5SDimitry Andric   MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
1720b57cec5SDimitry Andric                           .addImm(Imm.getLoBits(16).getLimitedValue());
1730b57cec5SDimitry Andric   if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
1740b57cec5SDimitry Andric     return false;
1750b57cec5SDimitry Andric   if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
1760b57cec5SDimitry Andric     return false;
1770b57cec5SDimitry Andric   return true;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
180480093f4SDimitry Andric /// When I.getOpcode() is returned, we failed to select MIPS instruction opcode.
1818bcb0991SDimitry Andric unsigned
1828bcb0991SDimitry Andric MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I,
1838bcb0991SDimitry Andric                                                MachineRegisterInfo &MRI) const {
184480093f4SDimitry Andric   const Register ValueReg = I.getOperand(0).getReg();
185480093f4SDimitry Andric   const LLT Ty = MRI.getType(ValueReg);
186480093f4SDimitry Andric   const unsigned TySize = Ty.getSizeInBits();
187*0fca6ea1SDimitry Andric   const unsigned MemSizeInBytes =
188*0fca6ea1SDimitry Andric       (*I.memoperands_begin())->getSize().getValue();
1898bcb0991SDimitry Andric   unsigned Opc = I.getOpcode();
1908bcb0991SDimitry Andric   const bool isStore = Opc == TargetOpcode::G_STORE;
191480093f4SDimitry Andric 
192480093f4SDimitry Andric   if (isRegInGprb(ValueReg, MRI)) {
193480093f4SDimitry Andric     assert(((Ty.isScalar() && TySize == 32) ||
194480093f4SDimitry Andric             (Ty.isPointer() && TySize == 32 && MemSizeInBytes == 4)) &&
195480093f4SDimitry Andric            "Unsupported register bank, LLT, MemSizeInBytes combination");
196480093f4SDimitry Andric     (void)TySize;
1970b57cec5SDimitry Andric     if (isStore)
1980b57cec5SDimitry Andric       switch (MemSizeInBytes) {
1990b57cec5SDimitry Andric       case 4:
2000b57cec5SDimitry Andric         return Mips::SW;
2010b57cec5SDimitry Andric       case 2:
2020b57cec5SDimitry Andric         return Mips::SH;
2030b57cec5SDimitry Andric       case 1:
2040b57cec5SDimitry Andric         return Mips::SB;
2050b57cec5SDimitry Andric       default:
2060b57cec5SDimitry Andric         return Opc;
2070b57cec5SDimitry Andric       }
2080b57cec5SDimitry Andric     else
2090b57cec5SDimitry Andric       // Unspecified extending load is selected into zeroExtending load.
2100b57cec5SDimitry Andric       switch (MemSizeInBytes) {
2110b57cec5SDimitry Andric       case 4:
2120b57cec5SDimitry Andric         return Mips::LW;
2130b57cec5SDimitry Andric       case 2:
2140b57cec5SDimitry Andric         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
2150b57cec5SDimitry Andric       case 1:
2160b57cec5SDimitry Andric         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
2170b57cec5SDimitry Andric       default:
2180b57cec5SDimitry Andric         return Opc;
2190b57cec5SDimitry Andric       }
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric 
222480093f4SDimitry Andric   if (isRegInFprb(ValueReg, MRI)) {
223480093f4SDimitry Andric     if (Ty.isScalar()) {
224480093f4SDimitry Andric       assert(((TySize == 32 && MemSizeInBytes == 4) ||
225480093f4SDimitry Andric               (TySize == 64 && MemSizeInBytes == 8)) &&
226480093f4SDimitry Andric              "Unsupported register bank, LLT, MemSizeInBytes combination");
227480093f4SDimitry Andric 
228480093f4SDimitry Andric       if (MemSizeInBytes == 4)
2290b57cec5SDimitry Andric         return isStore ? Mips::SWC1 : Mips::LWC1;
230480093f4SDimitry Andric 
2318bcb0991SDimitry Andric       if (STI.isFP64bit())
2320b57cec5SDimitry Andric         return isStore ? Mips::SDC164 : Mips::LDC164;
2330b57cec5SDimitry Andric       return isStore ? Mips::SDC1 : Mips::LDC1;
2348bcb0991SDimitry Andric     }
235480093f4SDimitry Andric 
236480093f4SDimitry Andric     if (Ty.isVector()) {
237480093f4SDimitry Andric       assert(STI.hasMSA() && "Vector instructions require target with MSA.");
238480093f4SDimitry Andric       assert((TySize == 128 && MemSizeInBytes == 16) &&
239480093f4SDimitry Andric              "Unsupported register bank, LLT, MemSizeInBytes combination");
240480093f4SDimitry Andric       switch (Ty.getElementType().getSizeInBits()) {
241480093f4SDimitry Andric       case 8:
242480093f4SDimitry Andric         return isStore ? Mips::ST_B : Mips::LD_B;
243480093f4SDimitry Andric       case 16:
244480093f4SDimitry Andric         return isStore ? Mips::ST_H : Mips::LD_H;
245480093f4SDimitry Andric       case 32:
246480093f4SDimitry Andric         return isStore ? Mips::ST_W : Mips::LD_W;
247480093f4SDimitry Andric       case 64:
248480093f4SDimitry Andric         return isStore ? Mips::ST_D : Mips::LD_D;
2490b57cec5SDimitry Andric       default:
2500b57cec5SDimitry Andric         return Opc;
2510b57cec5SDimitry Andric       }
2520b57cec5SDimitry Andric     }
253480093f4SDimitry Andric   }
254480093f4SDimitry Andric 
2550b57cec5SDimitry Andric   return Opc;
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2585ffd83dbSDimitry Andric bool MipsInstructionSelector::buildUnalignedStore(
2595ffd83dbSDimitry Andric     MachineInstr &I, unsigned Opc, MachineOperand &BaseAddr, unsigned Offset,
2605ffd83dbSDimitry Andric     MachineMemOperand *MMO) const {
2615ffd83dbSDimitry Andric   MachineInstr *NewInst =
2625ffd83dbSDimitry Andric       BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opc))
2635ffd83dbSDimitry Andric           .add(I.getOperand(0))
2645ffd83dbSDimitry Andric           .add(BaseAddr)
2655ffd83dbSDimitry Andric           .addImm(Offset)
2665ffd83dbSDimitry Andric           .addMemOperand(MMO);
2675ffd83dbSDimitry Andric   if (!constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI))
2685ffd83dbSDimitry Andric     return false;
2695ffd83dbSDimitry Andric   return true;
2705ffd83dbSDimitry Andric }
2715ffd83dbSDimitry Andric 
2725ffd83dbSDimitry Andric bool MipsInstructionSelector::buildUnalignedLoad(
2735ffd83dbSDimitry Andric     MachineInstr &I, unsigned Opc, Register Dest, MachineOperand &BaseAddr,
2745ffd83dbSDimitry Andric     unsigned Offset, Register TiedDest, MachineMemOperand *MMO) const {
2755ffd83dbSDimitry Andric   MachineInstr *NewInst =
2765ffd83dbSDimitry Andric       BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opc))
2775ffd83dbSDimitry Andric           .addDef(Dest)
2785ffd83dbSDimitry Andric           .add(BaseAddr)
2795ffd83dbSDimitry Andric           .addImm(Offset)
2805ffd83dbSDimitry Andric           .addUse(TiedDest)
2815ffd83dbSDimitry Andric           .addMemOperand(*I.memoperands_begin());
2825ffd83dbSDimitry Andric   if (!constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI))
2835ffd83dbSDimitry Andric     return false;
2845ffd83dbSDimitry Andric   return true;
2855ffd83dbSDimitry Andric }
2865ffd83dbSDimitry Andric 
2878bcb0991SDimitry Andric bool MipsInstructionSelector::select(MachineInstr &I) {
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   MachineBasicBlock &MBB = *I.getParent();
2900b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
2910b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   if (!isPreISelGenericOpcode(I.getOpcode())) {
2940b57cec5SDimitry Andric     if (I.isCopy())
2950b57cec5SDimitry Andric       return selectCopy(I, MRI);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric     return true;
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
300480093f4SDimitry Andric   if (I.getOpcode() == Mips::G_MUL &&
301480093f4SDimitry Andric       isRegInGprb(I.getOperand(0).getReg(), MRI)) {
3020b57cec5SDimitry Andric     MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
3030b57cec5SDimitry Andric                             .add(I.getOperand(0))
3040b57cec5SDimitry Andric                             .add(I.getOperand(1))
3050b57cec5SDimitry Andric                             .add(I.getOperand(2));
3060b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
3070b57cec5SDimitry Andric       return false;
3080b57cec5SDimitry Andric     Mul->getOperand(3).setIsDead(true);
3090b57cec5SDimitry Andric     Mul->getOperand(4).setIsDead(true);
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric     I.eraseFromParent();
3120b57cec5SDimitry Andric     return true;
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3158bcb0991SDimitry Andric   if (selectImpl(I, *CoverageInfo))
3160b57cec5SDimitry Andric     return true;
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   MachineInstr *MI = nullptr;
3190b57cec5SDimitry Andric   using namespace TargetOpcode;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   switch (I.getOpcode()) {
3220b57cec5SDimitry Andric   case G_UMULH: {
3230b57cec5SDimitry Andric     Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
3240b57cec5SDimitry Andric     MachineInstr *PseudoMULTu, *PseudoMove;
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric     PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
3270b57cec5SDimitry Andric                       .addDef(PseudoMULTuReg)
3280b57cec5SDimitry Andric                       .add(I.getOperand(1))
3290b57cec5SDimitry Andric                       .add(I.getOperand(2));
3300b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
3310b57cec5SDimitry Andric       return false;
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
3340b57cec5SDimitry Andric                      .addDef(I.getOperand(0).getReg())
3350b57cec5SDimitry Andric                      .addUse(PseudoMULTuReg);
3360b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
3370b57cec5SDimitry Andric       return false;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric     I.eraseFromParent();
3400b57cec5SDimitry Andric     return true;
3410b57cec5SDimitry Andric   }
342480093f4SDimitry Andric   case G_PTR_ADD: {
3430b57cec5SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
3440b57cec5SDimitry Andric              .add(I.getOperand(0))
3450b57cec5SDimitry Andric              .add(I.getOperand(1))
3460b57cec5SDimitry Andric              .add(I.getOperand(2));
3470b57cec5SDimitry Andric     break;
3480b57cec5SDimitry Andric   }
3498bcb0991SDimitry Andric   case G_INTTOPTR:
3508bcb0991SDimitry Andric   case G_PTRTOINT: {
3518bcb0991SDimitry Andric     I.setDesc(TII.get(COPY));
3528bcb0991SDimitry Andric     return selectCopy(I, MRI);
3538bcb0991SDimitry Andric   }
3540b57cec5SDimitry Andric   case G_FRAME_INDEX: {
3550b57cec5SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
3560b57cec5SDimitry Andric              .add(I.getOperand(0))
3570b57cec5SDimitry Andric              .add(I.getOperand(1))
3580b57cec5SDimitry Andric              .addImm(0);
3590b57cec5SDimitry Andric     break;
3600b57cec5SDimitry Andric   }
3618bcb0991SDimitry Andric   case G_BRJT: {
3628bcb0991SDimitry Andric     unsigned EntrySize =
3638bcb0991SDimitry Andric         MF.getJumpTableInfo()->getEntrySize(MF.getDataLayout());
3648bcb0991SDimitry Andric     assert(isPowerOf2_32(EntrySize) &&
3658bcb0991SDimitry Andric            "Non-power-of-two jump-table entry size not supported.");
3668bcb0991SDimitry Andric 
3678bcb0991SDimitry Andric     Register JTIndex = MRI.createVirtualRegister(&Mips::GPR32RegClass);
3688bcb0991SDimitry Andric     MachineInstr *SLL = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SLL))
3698bcb0991SDimitry Andric                             .addDef(JTIndex)
3708bcb0991SDimitry Andric                             .addUse(I.getOperand(2).getReg())
3718bcb0991SDimitry Andric                             .addImm(Log2_32(EntrySize));
3728bcb0991SDimitry Andric     if (!constrainSelectedInstRegOperands(*SLL, TII, TRI, RBI))
3738bcb0991SDimitry Andric       return false;
3748bcb0991SDimitry Andric 
3758bcb0991SDimitry Andric     Register DestAddress = MRI.createVirtualRegister(&Mips::GPR32RegClass);
3768bcb0991SDimitry Andric     MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
3778bcb0991SDimitry Andric                              .addDef(DestAddress)
3788bcb0991SDimitry Andric                              .addUse(I.getOperand(0).getReg())
3798bcb0991SDimitry Andric                              .addUse(JTIndex);
3808bcb0991SDimitry Andric     if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
3818bcb0991SDimitry Andric       return false;
3828bcb0991SDimitry Andric 
3838bcb0991SDimitry Andric     Register Dest = MRI.createVirtualRegister(&Mips::GPR32RegClass);
3848bcb0991SDimitry Andric     MachineInstr *LW =
3858bcb0991SDimitry Andric         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
3868bcb0991SDimitry Andric             .addDef(Dest)
3878bcb0991SDimitry Andric             .addUse(DestAddress)
3888bcb0991SDimitry Andric             .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_LO)
3898bcb0991SDimitry Andric             .addMemOperand(MF.getMachineMemOperand(
3905ffd83dbSDimitry Andric                 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, Align(4)));
3918bcb0991SDimitry Andric     if (!constrainSelectedInstRegOperands(*LW, TII, TRI, RBI))
3928bcb0991SDimitry Andric       return false;
3938bcb0991SDimitry Andric 
3948bcb0991SDimitry Andric     if (MF.getTarget().isPositionIndependent()) {
3958bcb0991SDimitry Andric       Register DestTmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
3968bcb0991SDimitry Andric       LW->getOperand(0).setReg(DestTmp);
3978bcb0991SDimitry Andric       MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
3988bcb0991SDimitry Andric                                .addDef(Dest)
3998bcb0991SDimitry Andric                                .addUse(DestTmp)
4008bcb0991SDimitry Andric                                .addUse(MF.getInfo<MipsFunctionInfo>()
4015ffd83dbSDimitry Andric                                            ->getGlobalBaseRegForGlobalISel(MF));
4028bcb0991SDimitry Andric       if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
4038bcb0991SDimitry Andric         return false;
4048bcb0991SDimitry Andric     }
4058bcb0991SDimitry Andric 
4068bcb0991SDimitry Andric     MachineInstr *Branch =
4078bcb0991SDimitry Andric         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
4088bcb0991SDimitry Andric             .addUse(Dest);
4098bcb0991SDimitry Andric     if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
4108bcb0991SDimitry Andric       return false;
4118bcb0991SDimitry Andric 
4128bcb0991SDimitry Andric     I.eraseFromParent();
4138bcb0991SDimitry Andric     return true;
4148bcb0991SDimitry Andric   }
4158bcb0991SDimitry Andric   case G_BRINDIRECT: {
4168bcb0991SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
4178bcb0991SDimitry Andric              .add(I.getOperand(0));
4188bcb0991SDimitry Andric     break;
4198bcb0991SDimitry Andric   }
4200b57cec5SDimitry Andric   case G_PHI: {
4210b57cec5SDimitry Andric     const Register DestReg = I.getOperand(0).getReg();
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric     const TargetRegisterClass *DefRC = nullptr;
424bdd1243dSDimitry Andric     if (DestReg.isPhysical())
4250b57cec5SDimitry Andric       DefRC = TRI.getRegClass(DestReg);
4260b57cec5SDimitry Andric     else
427480093f4SDimitry Andric       DefRC = getRegClassForTypeOnBank(DestReg, MRI);
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric     I.setDesc(TII.get(TargetOpcode::PHI));
4300b57cec5SDimitry Andric     return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric   case G_STORE:
4330b57cec5SDimitry Andric   case G_LOAD:
4340b57cec5SDimitry Andric   case G_ZEXTLOAD:
4350b57cec5SDimitry Andric   case G_SEXTLOAD: {
4365ffd83dbSDimitry Andric     auto MMO = *I.memoperands_begin();
4378bcb0991SDimitry Andric     MachineOperand BaseAddr = I.getOperand(1);
4388bcb0991SDimitry Andric     int64_t SignedOffset = 0;
439480093f4SDimitry Andric     // Try to fold load/store + G_PTR_ADD + G_CONSTANT
4408bcb0991SDimitry Andric     // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate
441480093f4SDimitry Andric     // %Addr:(p0) = G_PTR_ADD %BaseAddr, %SignedOffset
4428bcb0991SDimitry Andric     // %LoadResult/%StoreSrc = load/store %Addr(p0)
4438bcb0991SDimitry Andric     // into:
4448bcb0991SDimitry Andric     // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate
4458bcb0991SDimitry Andric 
4468bcb0991SDimitry Andric     MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg());
447480093f4SDimitry Andric     if (Addr->getOpcode() == G_PTR_ADD) {
4488bcb0991SDimitry Andric       MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg());
4498bcb0991SDimitry Andric       if (Offset->getOpcode() == G_CONSTANT) {
4508bcb0991SDimitry Andric         APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue();
4518bcb0991SDimitry Andric         if (OffsetValue.isSignedIntN(16)) {
4528bcb0991SDimitry Andric           BaseAddr = Addr->getOperand(1);
4538bcb0991SDimitry Andric           SignedOffset = OffsetValue.getSExtValue();
4548bcb0991SDimitry Andric         }
4558bcb0991SDimitry Andric       }
4568bcb0991SDimitry Andric     }
4578bcb0991SDimitry Andric 
4585ffd83dbSDimitry Andric     // Unaligned memory access
459*0fca6ea1SDimitry Andric     if ((!MMO->getSize().hasValue() ||
460*0fca6ea1SDimitry Andric          MMO->getAlign() < MMO->getSize().getValue()) &&
4615ffd83dbSDimitry Andric         !STI.systemSupportsUnalignedAccess()) {
4625ffd83dbSDimitry Andric       if (MMO->getSize() != 4 || !isRegInGprb(I.getOperand(0).getReg(), MRI))
4635ffd83dbSDimitry Andric         return false;
4645ffd83dbSDimitry Andric 
4655ffd83dbSDimitry Andric       if (I.getOpcode() == G_STORE) {
4665ffd83dbSDimitry Andric         if (!buildUnalignedStore(I, Mips::SWL, BaseAddr, SignedOffset + 3, MMO))
4675ffd83dbSDimitry Andric           return false;
4685ffd83dbSDimitry Andric         if (!buildUnalignedStore(I, Mips::SWR, BaseAddr, SignedOffset, MMO))
4695ffd83dbSDimitry Andric           return false;
4705ffd83dbSDimitry Andric         I.eraseFromParent();
4715ffd83dbSDimitry Andric         return true;
4725ffd83dbSDimitry Andric       }
4735ffd83dbSDimitry Andric 
4745ffd83dbSDimitry Andric       if (I.getOpcode() == G_LOAD) {
4755ffd83dbSDimitry Andric         Register ImplDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
4765ffd83dbSDimitry Andric         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
4775ffd83dbSDimitry Andric             .addDef(ImplDef);
4785ffd83dbSDimitry Andric         Register Tmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
4795ffd83dbSDimitry Andric         if (!buildUnalignedLoad(I, Mips::LWL, Tmp, BaseAddr, SignedOffset + 3,
4805ffd83dbSDimitry Andric                                 ImplDef, MMO))
4815ffd83dbSDimitry Andric           return false;
4825ffd83dbSDimitry Andric         if (!buildUnalignedLoad(I, Mips::LWR, I.getOperand(0).getReg(),
4835ffd83dbSDimitry Andric                                 BaseAddr, SignedOffset, Tmp, MMO))
4845ffd83dbSDimitry Andric           return false;
4855ffd83dbSDimitry Andric         I.eraseFromParent();
4865ffd83dbSDimitry Andric         return true;
4875ffd83dbSDimitry Andric       }
4885ffd83dbSDimitry Andric 
4895ffd83dbSDimitry Andric       return false;
4905ffd83dbSDimitry Andric     }
4915ffd83dbSDimitry Andric 
4925ffd83dbSDimitry Andric     const unsigned NewOpc = selectLoadStoreOpCode(I, MRI);
4935ffd83dbSDimitry Andric     if (NewOpc == I.getOpcode())
4945ffd83dbSDimitry Andric       return false;
4955ffd83dbSDimitry Andric 
4960b57cec5SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
4970b57cec5SDimitry Andric              .add(I.getOperand(0))
4988bcb0991SDimitry Andric              .add(BaseAddr)
4998bcb0991SDimitry Andric              .addImm(SignedOffset)
5005ffd83dbSDimitry Andric              .addMemOperand(MMO);
5010b57cec5SDimitry Andric     break;
5020b57cec5SDimitry Andric   }
5030b57cec5SDimitry Andric   case G_UDIV:
5040b57cec5SDimitry Andric   case G_UREM:
5050b57cec5SDimitry Andric   case G_SDIV:
5060b57cec5SDimitry Andric   case G_SREM: {
5070b57cec5SDimitry Andric     Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
5080b57cec5SDimitry Andric     bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
5090b57cec5SDimitry Andric     bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric     MachineInstr *PseudoDIV, *PseudoMove;
5120b57cec5SDimitry Andric     PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
5130b57cec5SDimitry Andric                         TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
5140b57cec5SDimitry Andric                     .addDef(HILOReg)
5150b57cec5SDimitry Andric                     .add(I.getOperand(1))
5160b57cec5SDimitry Andric                     .add(I.getOperand(2));
5170b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
5180b57cec5SDimitry Andric       return false;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
5210b57cec5SDimitry Andric                          TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
5220b57cec5SDimitry Andric                      .addDef(I.getOperand(0).getReg())
5230b57cec5SDimitry Andric                      .addUse(HILOReg);
5240b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
5250b57cec5SDimitry Andric       return false;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric     I.eraseFromParent();
5280b57cec5SDimitry Andric     return true;
5290b57cec5SDimitry Andric   }
5300b57cec5SDimitry Andric   case G_SELECT: {
5310b57cec5SDimitry Andric     // Handle operands with pointer type.
5320b57cec5SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
5330b57cec5SDimitry Andric              .add(I.getOperand(0))
5340b57cec5SDimitry Andric              .add(I.getOperand(2))
5350b57cec5SDimitry Andric              .add(I.getOperand(1))
5360b57cec5SDimitry Andric              .add(I.getOperand(3));
5370b57cec5SDimitry Andric     break;
5380b57cec5SDimitry Andric   }
5395ffd83dbSDimitry Andric   case G_UNMERGE_VALUES: {
5405ffd83dbSDimitry Andric     if (I.getNumOperands() != 3)
5415ffd83dbSDimitry Andric       return false;
5425ffd83dbSDimitry Andric     Register Src = I.getOperand(2).getReg();
5435ffd83dbSDimitry Andric     Register Lo = I.getOperand(0).getReg();
5445ffd83dbSDimitry Andric     Register Hi = I.getOperand(1).getReg();
5455ffd83dbSDimitry Andric     if (!isRegInFprb(Src, MRI) ||
5465ffd83dbSDimitry Andric         !(isRegInGprb(Lo, MRI) && isRegInGprb(Hi, MRI)))
5475ffd83dbSDimitry Andric       return false;
5485ffd83dbSDimitry Andric 
5495ffd83dbSDimitry Andric     unsigned Opcode =
5505ffd83dbSDimitry Andric         STI.isFP64bit() ? Mips::ExtractElementF64_64 : Mips::ExtractElementF64;
5515ffd83dbSDimitry Andric 
5525ffd83dbSDimitry Andric     MachineInstr *ExtractLo = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
5535ffd83dbSDimitry Andric                                   .addDef(Lo)
5545ffd83dbSDimitry Andric                                   .addUse(Src)
5555ffd83dbSDimitry Andric                                   .addImm(0);
5565ffd83dbSDimitry Andric     if (!constrainSelectedInstRegOperands(*ExtractLo, TII, TRI, RBI))
5575ffd83dbSDimitry Andric       return false;
5585ffd83dbSDimitry Andric 
5595ffd83dbSDimitry Andric     MachineInstr *ExtractHi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
5605ffd83dbSDimitry Andric                                   .addDef(Hi)
5615ffd83dbSDimitry Andric                                   .addUse(Src)
5625ffd83dbSDimitry Andric                                   .addImm(1);
5635ffd83dbSDimitry Andric     if (!constrainSelectedInstRegOperands(*ExtractHi, TII, TRI, RBI))
5645ffd83dbSDimitry Andric       return false;
5655ffd83dbSDimitry Andric 
5665ffd83dbSDimitry Andric     I.eraseFromParent();
5675ffd83dbSDimitry Andric     return true;
5685ffd83dbSDimitry Andric   }
5698bcb0991SDimitry Andric   case G_IMPLICIT_DEF: {
570480093f4SDimitry Andric     Register Dst = I.getOperand(0).getReg();
5718bcb0991SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
572480093f4SDimitry Andric              .addDef(Dst);
5738bcb0991SDimitry Andric 
5748bcb0991SDimitry Andric     // Set class based on register bank, there can be fpr and gpr implicit def.
575480093f4SDimitry Andric     MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst, MRI));
5768bcb0991SDimitry Andric     break;
5778bcb0991SDimitry Andric   }
5780b57cec5SDimitry Andric   case G_CONSTANT: {
5790b57cec5SDimitry Andric     MachineIRBuilder B(I);
5800b57cec5SDimitry Andric     if (!materialize32BitImm(I.getOperand(0).getReg(),
5810b57cec5SDimitry Andric                              I.getOperand(1).getCImm()->getValue(), B))
5820b57cec5SDimitry Andric       return false;
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric     I.eraseFromParent();
5850b57cec5SDimitry Andric     return true;
5860b57cec5SDimitry Andric   }
5870b57cec5SDimitry Andric   case G_FCONSTANT: {
5880b57cec5SDimitry Andric     const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
5890b57cec5SDimitry Andric     APInt APImm = FPimm.bitcastToAPInt();
5900b57cec5SDimitry Andric     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric     if (Size == 32) {
5930b57cec5SDimitry Andric       Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
5940b57cec5SDimitry Andric       MachineIRBuilder B(I);
5950b57cec5SDimitry Andric       if (!materialize32BitImm(GPRReg, APImm, B))
5960b57cec5SDimitry Andric         return false;
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric       MachineInstrBuilder MTC1 =
5990b57cec5SDimitry Andric           B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
6000b57cec5SDimitry Andric       if (!MTC1.constrainAllUses(TII, TRI, RBI))
6010b57cec5SDimitry Andric         return false;
6020b57cec5SDimitry Andric     }
6030b57cec5SDimitry Andric     if (Size == 64) {
6040b57cec5SDimitry Andric       Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
6050b57cec5SDimitry Andric       Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
6060b57cec5SDimitry Andric       MachineIRBuilder B(I);
6070b57cec5SDimitry Andric       if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
6080b57cec5SDimitry Andric         return false;
6090b57cec5SDimitry Andric       if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
6100b57cec5SDimitry Andric         return false;
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric       MachineInstrBuilder PairF64 = B.buildInstr(
6130b57cec5SDimitry Andric           STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
6140b57cec5SDimitry Andric           {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
6150b57cec5SDimitry Andric       if (!PairF64.constrainAllUses(TII, TRI, RBI))
6160b57cec5SDimitry Andric         return false;
6170b57cec5SDimitry Andric     }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric     I.eraseFromParent();
6200b57cec5SDimitry Andric     return true;
6210b57cec5SDimitry Andric   }
6220b57cec5SDimitry Andric   case G_FABS: {
6230b57cec5SDimitry Andric     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
6240b57cec5SDimitry Andric     unsigned FABSOpcode =
6250b57cec5SDimitry Andric         Size == 32 ? Mips::FABS_S
6260b57cec5SDimitry Andric                    : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
6270b57cec5SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
6280b57cec5SDimitry Andric              .add(I.getOperand(0))
6290b57cec5SDimitry Andric              .add(I.getOperand(1));
6300b57cec5SDimitry Andric     break;
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric   case G_FPTOSI: {
6330b57cec5SDimitry Andric     unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
6340b57cec5SDimitry Andric     unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
6350b57cec5SDimitry Andric     (void)ToSize;
6360b57cec5SDimitry Andric     assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
6370b57cec5SDimitry Andric     assert((FromSize == 32 || FromSize == 64) &&
6380b57cec5SDimitry Andric            "Unsupported floating point size for G_FPTOSI");
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric     unsigned Opcode;
6410b57cec5SDimitry Andric     if (FromSize == 32)
6420b57cec5SDimitry Andric       Opcode = Mips::TRUNC_W_S;
6430b57cec5SDimitry Andric     else
6440b57cec5SDimitry Andric       Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
6458bcb0991SDimitry Andric     Register ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
6460b57cec5SDimitry Andric     MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
6470b57cec5SDimitry Andric                 .addDef(ResultInFPR)
6480b57cec5SDimitry Andric                 .addUse(I.getOperand(1).getReg());
6490b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
6500b57cec5SDimitry Andric       return false;
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
6530b57cec5SDimitry Andric                              .addDef(I.getOperand(0).getReg())
6540b57cec5SDimitry Andric                              .addUse(ResultInFPR);
6550b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
6560b57cec5SDimitry Andric       return false;
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric     I.eraseFromParent();
6590b57cec5SDimitry Andric     return true;
6600b57cec5SDimitry Andric   }
6610b57cec5SDimitry Andric   case G_GLOBAL_VALUE: {
6620b57cec5SDimitry Andric     const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
6630b57cec5SDimitry Andric     if (MF.getTarget().isPositionIndependent()) {
6640b57cec5SDimitry Andric       MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
6650b57cec5SDimitry Andric                                 .addDef(I.getOperand(0).getReg())
6660b57cec5SDimitry Andric                                 .addReg(MF.getInfo<MipsFunctionInfo>()
6675ffd83dbSDimitry Andric                                             ->getGlobalBaseRegForGlobalISel(MF))
6680b57cec5SDimitry Andric                                 .addGlobalAddress(GVal);
6690b57cec5SDimitry Andric       // Global Values that don't have local linkage are handled differently
6700b57cec5SDimitry Andric       // when they are part of call sequence. MipsCallLowering::lowerCall
6710b57cec5SDimitry Andric       // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
6720b57cec5SDimitry Andric       // MO_GOT_CALL flag when Callee doesn't have local linkage.
6730b57cec5SDimitry Andric       if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
6740b57cec5SDimitry Andric         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
6750b57cec5SDimitry Andric       else
6760b57cec5SDimitry Andric         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
6770b57cec5SDimitry Andric       LWGOT->addMemOperand(
6780b57cec5SDimitry Andric           MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
6795ffd83dbSDimitry Andric                                       MachineMemOperand::MOLoad, 4, Align(4)));
6800b57cec5SDimitry Andric       if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
6810b57cec5SDimitry Andric         return false;
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric       if (GVal->hasLocalLinkage()) {
6840b57cec5SDimitry Andric         Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
6850b57cec5SDimitry Andric         LWGOT->getOperand(0).setReg(LWGOTDef);
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric         MachineInstr *ADDiu =
6880b57cec5SDimitry Andric             BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
6890b57cec5SDimitry Andric                 .addDef(I.getOperand(0).getReg())
6900b57cec5SDimitry Andric                 .addReg(LWGOTDef)
6910b57cec5SDimitry Andric                 .addGlobalAddress(GVal);
6920b57cec5SDimitry Andric         ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
6930b57cec5SDimitry Andric         if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
6940b57cec5SDimitry Andric           return false;
6950b57cec5SDimitry Andric       }
6960b57cec5SDimitry Andric     } else {
6970b57cec5SDimitry Andric       Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric       MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
7000b57cec5SDimitry Andric                               .addDef(LUiReg)
7010b57cec5SDimitry Andric                               .addGlobalAddress(GVal);
7020b57cec5SDimitry Andric       LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
7030b57cec5SDimitry Andric       if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
7040b57cec5SDimitry Andric         return false;
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric       MachineInstr *ADDiu =
7070b57cec5SDimitry Andric           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
7080b57cec5SDimitry Andric               .addDef(I.getOperand(0).getReg())
7090b57cec5SDimitry Andric               .addUse(LUiReg)
7100b57cec5SDimitry Andric               .addGlobalAddress(GVal);
7110b57cec5SDimitry Andric       ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
7120b57cec5SDimitry Andric       if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
7130b57cec5SDimitry Andric         return false;
7140b57cec5SDimitry Andric     }
7150b57cec5SDimitry Andric     I.eraseFromParent();
7160b57cec5SDimitry Andric     return true;
7170b57cec5SDimitry Andric   }
7188bcb0991SDimitry Andric   case G_JUMP_TABLE: {
7198bcb0991SDimitry Andric     if (MF.getTarget().isPositionIndependent()) {
7208bcb0991SDimitry Andric       MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
7218bcb0991SDimitry Andric                .addDef(I.getOperand(0).getReg())
7228bcb0991SDimitry Andric                .addReg(MF.getInfo<MipsFunctionInfo>()
7235ffd83dbSDimitry Andric                            ->getGlobalBaseRegForGlobalISel(MF))
7248bcb0991SDimitry Andric                .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_GOT)
7255ffd83dbSDimitry Andric                .addMemOperand(MF.getMachineMemOperand(
7265ffd83dbSDimitry Andric                    MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, 4,
7275ffd83dbSDimitry Andric                    Align(4)));
7288bcb0991SDimitry Andric     } else {
7298bcb0991SDimitry Andric       MI =
7308bcb0991SDimitry Andric           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
7318bcb0991SDimitry Andric               .addDef(I.getOperand(0).getReg())
7328bcb0991SDimitry Andric               .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_HI);
7338bcb0991SDimitry Andric     }
7348bcb0991SDimitry Andric     break;
7358bcb0991SDimitry Andric   }
7360b57cec5SDimitry Andric   case G_ICMP: {
7370b57cec5SDimitry Andric     struct Instr {
7380b57cec5SDimitry Andric       unsigned Opcode;
7390b57cec5SDimitry Andric       Register Def, LHS, RHS;
7400b57cec5SDimitry Andric       Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
7410b57cec5SDimitry Andric           : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric       bool hasImm() const {
7440b57cec5SDimitry Andric         if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
7450b57cec5SDimitry Andric           return true;
7460b57cec5SDimitry Andric         return false;
7470b57cec5SDimitry Andric       }
7480b57cec5SDimitry Andric     };
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric     SmallVector<struct Instr, 2> Instructions;
7510b57cec5SDimitry Andric     Register ICMPReg = I.getOperand(0).getReg();
7520b57cec5SDimitry Andric     Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
7530b57cec5SDimitry Andric     Register LHS = I.getOperand(2).getReg();
7540b57cec5SDimitry Andric     Register RHS = I.getOperand(3).getReg();
7550b57cec5SDimitry Andric     CmpInst::Predicate Cond =
7560b57cec5SDimitry Andric         static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric     switch (Cond) {
7590b57cec5SDimitry Andric     case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
7600b57cec5SDimitry Andric       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
7610b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
7620b57cec5SDimitry Andric       break;
7630b57cec5SDimitry Andric     case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
7640b57cec5SDimitry Andric       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
7650b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
7660b57cec5SDimitry Andric       break;
7670b57cec5SDimitry Andric     case CmpInst::ICMP_UGT: // LHS >  RHS -> RHS < LHS
7680b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
7690b57cec5SDimitry Andric       break;
7700b57cec5SDimitry Andric     case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
7710b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
7720b57cec5SDimitry Andric       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
7730b57cec5SDimitry Andric       break;
7740b57cec5SDimitry Andric     case CmpInst::ICMP_ULT: // LHS <  RHS -> LHS < RHS
7750b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
7760b57cec5SDimitry Andric       break;
7770b57cec5SDimitry Andric     case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
7780b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
7790b57cec5SDimitry Andric       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
7800b57cec5SDimitry Andric       break;
7810b57cec5SDimitry Andric     case CmpInst::ICMP_SGT: // LHS >  RHS -> RHS < LHS
7820b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
7830b57cec5SDimitry Andric       break;
7840b57cec5SDimitry Andric     case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
7850b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
7860b57cec5SDimitry Andric       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
7870b57cec5SDimitry Andric       break;
7880b57cec5SDimitry Andric     case CmpInst::ICMP_SLT: // LHS <  RHS -> LHS < RHS
7890b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
7900b57cec5SDimitry Andric       break;
7910b57cec5SDimitry Andric     case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
7920b57cec5SDimitry Andric       Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
7930b57cec5SDimitry Andric       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
7940b57cec5SDimitry Andric       break;
7950b57cec5SDimitry Andric     default:
7960b57cec5SDimitry Andric       return false;
7970b57cec5SDimitry Andric     }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric     MachineIRBuilder B(I);
8000b57cec5SDimitry Andric     for (const struct Instr &Instruction : Instructions) {
8010b57cec5SDimitry Andric       MachineInstrBuilder MIB = B.buildInstr(
8020b57cec5SDimitry Andric           Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric       if (Instruction.hasImm())
8050b57cec5SDimitry Andric         MIB.addImm(Instruction.RHS);
8060b57cec5SDimitry Andric       else
8070b57cec5SDimitry Andric         MIB.addUse(Instruction.RHS);
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric       if (!MIB.constrainAllUses(TII, TRI, RBI))
8100b57cec5SDimitry Andric         return false;
8110b57cec5SDimitry Andric     }
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric     I.eraseFromParent();
8140b57cec5SDimitry Andric     return true;
8150b57cec5SDimitry Andric   }
8160b57cec5SDimitry Andric   case G_FCMP: {
8170b57cec5SDimitry Andric     unsigned MipsFCMPCondCode;
8180b57cec5SDimitry Andric     bool isLogicallyNegated;
8190b57cec5SDimitry Andric     switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
8200b57cec5SDimitry Andric                 I.getOperand(1).getPredicate())) {
8210b57cec5SDimitry Andric     case CmpInst::FCMP_UNO: // Unordered
8220b57cec5SDimitry Andric     case CmpInst::FCMP_ORD: // Ordered (OR)
8230b57cec5SDimitry Andric       MipsFCMPCondCode = Mips::FCOND_UN;
8240b57cec5SDimitry Andric       isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
8250b57cec5SDimitry Andric       break;
8260b57cec5SDimitry Andric     case CmpInst::FCMP_OEQ: // Equal
8270b57cec5SDimitry Andric     case CmpInst::FCMP_UNE: // Not Equal (NEQ)
8280b57cec5SDimitry Andric       MipsFCMPCondCode = Mips::FCOND_OEQ;
8290b57cec5SDimitry Andric       isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
8300b57cec5SDimitry Andric       break;
8310b57cec5SDimitry Andric     case CmpInst::FCMP_UEQ: // Unordered or Equal
8320b57cec5SDimitry Andric     case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
8330b57cec5SDimitry Andric       MipsFCMPCondCode = Mips::FCOND_UEQ;
8340b57cec5SDimitry Andric       isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
8350b57cec5SDimitry Andric       break;
8360b57cec5SDimitry Andric     case CmpInst::FCMP_OLT: // Ordered or Less Than
8370b57cec5SDimitry Andric     case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
8380b57cec5SDimitry Andric       MipsFCMPCondCode = Mips::FCOND_OLT;
8390b57cec5SDimitry Andric       isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
8400b57cec5SDimitry Andric       break;
8410b57cec5SDimitry Andric     case CmpInst::FCMP_ULT: // Unordered or Less Than
8420b57cec5SDimitry Andric     case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
8430b57cec5SDimitry Andric       MipsFCMPCondCode = Mips::FCOND_ULT;
8440b57cec5SDimitry Andric       isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
8450b57cec5SDimitry Andric       break;
8460b57cec5SDimitry Andric     case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
8470b57cec5SDimitry Andric     case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
8480b57cec5SDimitry Andric       MipsFCMPCondCode = Mips::FCOND_OLE;
8490b57cec5SDimitry Andric       isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
8500b57cec5SDimitry Andric       break;
8510b57cec5SDimitry Andric     case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
8520b57cec5SDimitry Andric     case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
8530b57cec5SDimitry Andric       MipsFCMPCondCode = Mips::FCOND_ULE;
8540b57cec5SDimitry Andric       isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
8550b57cec5SDimitry Andric       break;
8560b57cec5SDimitry Andric     default:
8570b57cec5SDimitry Andric       return false;
8580b57cec5SDimitry Andric     }
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric     // Default compare result in gpr register will be `true`.
8610b57cec5SDimitry Andric     // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
8620b57cec5SDimitry Andric     // using MOVF_I. When orignal predicate (Cond) is logically negated
8630b57cec5SDimitry Andric     // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
8640b57cec5SDimitry Andric     unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
8650b57cec5SDimitry Andric 
8668bcb0991SDimitry Andric     Register TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
8670b57cec5SDimitry Andric     BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
8680b57cec5SDimitry Andric         .addDef(TrueInReg)
8690b57cec5SDimitry Andric         .addUse(Mips::ZERO)
8700b57cec5SDimitry Andric         .addImm(1);
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric     unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
8730b57cec5SDimitry Andric     unsigned FCMPOpcode =
8740b57cec5SDimitry Andric         Size == 32 ? Mips::FCMP_S32
8750b57cec5SDimitry Andric                    : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
8760b57cec5SDimitry Andric     MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
8770b57cec5SDimitry Andric                              .addUse(I.getOperand(2).getReg())
8780b57cec5SDimitry Andric                              .addUse(I.getOperand(3).getReg())
8790b57cec5SDimitry Andric                              .addImm(MipsFCMPCondCode);
8800b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
8810b57cec5SDimitry Andric       return false;
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
8840b57cec5SDimitry Andric                              .addDef(I.getOperand(0).getReg())
8850b57cec5SDimitry Andric                              .addUse(Mips::ZERO)
8860b57cec5SDimitry Andric                              .addUse(Mips::FCC0)
8870b57cec5SDimitry Andric                              .addUse(TrueInReg);
8880b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
8890b57cec5SDimitry Andric       return false;
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric     I.eraseFromParent();
8920b57cec5SDimitry Andric     return true;
8930b57cec5SDimitry Andric   }
8948bcb0991SDimitry Andric   case G_FENCE: {
8958bcb0991SDimitry Andric     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
8968bcb0991SDimitry Andric     break;
8978bcb0991SDimitry Andric   }
8988bcb0991SDimitry Andric   case G_VASTART: {
8998bcb0991SDimitry Andric     MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
9008bcb0991SDimitry Andric     int FI = FuncInfo->getVarArgsFrameIndex();
9018bcb0991SDimitry Andric 
9028bcb0991SDimitry Andric     Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
9038bcb0991SDimitry Andric     MachineInstr *LEA_ADDiu =
9048bcb0991SDimitry Andric         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
9058bcb0991SDimitry Andric             .addDef(LeaReg)
9068bcb0991SDimitry Andric             .addFrameIndex(FI)
9078bcb0991SDimitry Andric             .addImm(0);
9088bcb0991SDimitry Andric     if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
9098bcb0991SDimitry Andric       return false;
9108bcb0991SDimitry Andric 
9118bcb0991SDimitry Andric     MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
9128bcb0991SDimitry Andric                               .addUse(LeaReg)
9138bcb0991SDimitry Andric                               .addUse(I.getOperand(0).getReg())
9148bcb0991SDimitry Andric                               .addImm(0);
9158bcb0991SDimitry Andric     if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
9168bcb0991SDimitry Andric       return false;
9178bcb0991SDimitry Andric 
9188bcb0991SDimitry Andric     I.eraseFromParent();
9198bcb0991SDimitry Andric     return true;
9208bcb0991SDimitry Andric   }
9210b57cec5SDimitry Andric   default:
9220b57cec5SDimitry Andric     return false;
9230b57cec5SDimitry Andric   }
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric   I.eraseFromParent();
9260b57cec5SDimitry Andric   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
9270b57cec5SDimitry Andric }
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric namespace llvm {
930*0fca6ea1SDimitry Andric InstructionSelector *
931*0fca6ea1SDimitry Andric createMipsInstructionSelector(const MipsTargetMachine &TM,
932*0fca6ea1SDimitry Andric                               const MipsSubtarget &Subtarget,
933*0fca6ea1SDimitry Andric                               const MipsRegisterBankInfo &RBI) {
9340b57cec5SDimitry Andric   return new MipsInstructionSelector(TM, Subtarget, RBI);
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric } // end namespace llvm
937