1fac93e28SPetar Jovanovic //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===//
2fac93e28SPetar Jovanovic //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fac93e28SPetar Jovanovic //
7fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
8fac93e28SPetar Jovanovic /// \file
9fac93e28SPetar Jovanovic /// This file implements the targeting of the InstructionSelector class for
10fac93e28SPetar Jovanovic /// Mips.
11fac93e28SPetar Jovanovic /// \todo This should be generated by TableGen.
12fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
13fac93e28SPetar Jovanovic 
1422e99c43SPetar Avramovic #include "MCTargetDesc/MipsInstPrinter.h"
15efcd3c00SPetar Avramovic #include "MipsMachineFunction.h"
16fac93e28SPetar Jovanovic #include "MipsRegisterBankInfo.h"
17fac93e28SPetar Jovanovic #include "MipsTargetMachine.h"
18366857a2SPetar Jovanovic #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
19ce4dd0aeSPetar Jovanovic #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20caef9306SPetar Avramovic #include "llvm/CodeGen/MachineJumpTableInfo.h"
215d986953SReid Kleckner #include "llvm/IR/IntrinsicsMips.h"
22fac93e28SPetar Jovanovic 
23366857a2SPetar Jovanovic #define DEBUG_TYPE "mips-isel"
24366857a2SPetar Jovanovic 
25fac93e28SPetar Jovanovic using namespace llvm;
26fac93e28SPetar Jovanovic 
27fac93e28SPetar Jovanovic namespace {
28fac93e28SPetar Jovanovic 
29366857a2SPetar Jovanovic #define GET_GLOBALISEL_PREDICATE_BITSET
30366857a2SPetar Jovanovic #include "MipsGenGlobalISel.inc"
31366857a2SPetar Jovanovic #undef GET_GLOBALISEL_PREDICATE_BITSET
32366857a2SPetar Jovanovic 
33fac93e28SPetar Jovanovic class MipsInstructionSelector : public InstructionSelector {
34fac93e28SPetar Jovanovic public:
35fac93e28SPetar Jovanovic   MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
36fac93e28SPetar Jovanovic                           const MipsRegisterBankInfo &RBI);
37fac93e28SPetar Jovanovic 
38e14c91b7SAmara Emerson   bool select(MachineInstr &I) override;
getName()39366857a2SPetar Jovanovic   static const char *getName() { return DEBUG_TYPE; }
40fac93e28SPetar Jovanovic 
41fac93e28SPetar Jovanovic private:
42366857a2SPetar Jovanovic   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
43d32a6f08SPetar Avramovic   bool isRegInGprb(Register Reg, MachineRegisterInfo &MRI) const;
44d32a6f08SPetar Avramovic   bool isRegInFprb(Register Reg, MachineRegisterInfo &MRI) const;
45faeaedf8SMatt Arsenault   bool materialize32BitImm(Register DestReg, APInt Imm,
463e0da146SPetar Avramovic                            MachineIRBuilder &B) const;
47a034a64fSPetar Avramovic   bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
487d0778eaSPetar Avramovic   const TargetRegisterClass *
49d32a6f08SPetar Avramovic   getRegClassForTypeOnBank(Register Reg, MachineRegisterInfo &MRI) const;
50599591f3SPetar Avramovic   unsigned selectLoadStoreOpCode(MachineInstr &I,
51599591f3SPetar Avramovic                                  MachineRegisterInfo &MRI) const;
525171d152SPetar Avramovic   bool buildUnalignedStore(MachineInstr &I, unsigned Opc,
535171d152SPetar Avramovic                            MachineOperand &BaseAddr, unsigned Offset,
545171d152SPetar Avramovic                            MachineMemOperand *MMO) const;
555171d152SPetar Avramovic   bool buildUnalignedLoad(MachineInstr &I, unsigned Opc, Register Dest,
565171d152SPetar Avramovic                           MachineOperand &BaseAddr, unsigned Offset,
575171d152SPetar Avramovic                           Register TiedDest, MachineMemOperand *MMO) const;
58366857a2SPetar Jovanovic 
59366857a2SPetar Jovanovic   const MipsTargetMachine &TM;
60366857a2SPetar Jovanovic   const MipsSubtarget &STI;
61fac93e28SPetar Jovanovic   const MipsInstrInfo &TII;
62fac93e28SPetar Jovanovic   const MipsRegisterInfo &TRI;
63366857a2SPetar Jovanovic   const MipsRegisterBankInfo &RBI;
64366857a2SPetar Jovanovic 
65366857a2SPetar Jovanovic #define GET_GLOBALISEL_PREDICATES_DECL
66366857a2SPetar Jovanovic #include "MipsGenGlobalISel.inc"
67366857a2SPetar Jovanovic #undef GET_GLOBALISEL_PREDICATES_DECL
68366857a2SPetar Jovanovic 
69366857a2SPetar Jovanovic #define GET_GLOBALISEL_TEMPORARIES_DECL
70366857a2SPetar Jovanovic #include "MipsGenGlobalISel.inc"
71366857a2SPetar Jovanovic #undef GET_GLOBALISEL_TEMPORARIES_DECL
72fac93e28SPetar Jovanovic };
73fac93e28SPetar Jovanovic 
74fac93e28SPetar Jovanovic } // end anonymous namespace
75fac93e28SPetar Jovanovic 
76366857a2SPetar Jovanovic #define GET_GLOBALISEL_IMPL
77366857a2SPetar Jovanovic #include "MipsGenGlobalISel.inc"
78366857a2SPetar Jovanovic #undef GET_GLOBALISEL_IMPL
79366857a2SPetar Jovanovic 
MipsInstructionSelector(const MipsTargetMachine & TM,const MipsSubtarget & STI,const MipsRegisterBankInfo & RBI)80fac93e28SPetar Jovanovic MipsInstructionSelector::MipsInstructionSelector(
81fac93e28SPetar Jovanovic     const MipsTargetMachine &TM, const MipsSubtarget &STI,
82fac93e28SPetar Jovanovic     const MipsRegisterBankInfo &RBI)
83*f3a344d2SKazu Hirata     : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
84*f3a344d2SKazu Hirata       RBI(RBI),
85366857a2SPetar Jovanovic 
86366857a2SPetar Jovanovic #define GET_GLOBALISEL_PREDICATES_INIT
87366857a2SPetar Jovanovic #include "MipsGenGlobalISel.inc"
88366857a2SPetar Jovanovic #undef GET_GLOBALISEL_PREDICATES_INIT
89366857a2SPetar Jovanovic #define GET_GLOBALISEL_TEMPORARIES_INIT
90366857a2SPetar Jovanovic #include "MipsGenGlobalISel.inc"
91366857a2SPetar Jovanovic #undef GET_GLOBALISEL_TEMPORARIES_INIT
92366857a2SPetar Jovanovic {
93366857a2SPetar Jovanovic }
94366857a2SPetar Jovanovic 
isRegInGprb(Register Reg,MachineRegisterInfo & MRI) const95d32a6f08SPetar Avramovic bool MipsInstructionSelector::isRegInGprb(Register Reg,
96d32a6f08SPetar Avramovic                                           MachineRegisterInfo &MRI) const {
97d32a6f08SPetar Avramovic   return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::GPRBRegBankID;
98d32a6f08SPetar Avramovic }
99d32a6f08SPetar Avramovic 
isRegInFprb(Register Reg,MachineRegisterInfo & MRI) const100d32a6f08SPetar Avramovic bool MipsInstructionSelector::isRegInFprb(Register Reg,
101d32a6f08SPetar Avramovic                                           MachineRegisterInfo &MRI) const {
102d32a6f08SPetar Avramovic   return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::FPRBRegBankID;
103d32a6f08SPetar Avramovic }
104d32a6f08SPetar Avramovic 
selectCopy(MachineInstr & I,MachineRegisterInfo & MRI) const105a034a64fSPetar Avramovic bool MipsInstructionSelector::selectCopy(MachineInstr &I,
106a034a64fSPetar Avramovic                                          MachineRegisterInfo &MRI) const {
107faeaedf8SMatt Arsenault   Register DstReg = I.getOperand(0).getReg();
1082bea69bfSDaniel Sanders   if (Register::isPhysicalRegister(DstReg))
109366857a2SPetar Jovanovic     return true;
110366857a2SPetar Jovanovic 
111d32a6f08SPetar Avramovic   const TargetRegisterClass *RC = getRegClassForTypeOnBank(DstReg, MRI);
112366857a2SPetar Jovanovic   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
113d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
114366857a2SPetar Jovanovic                       << " operand\n");
115366857a2SPetar Jovanovic     return false;
116366857a2SPetar Jovanovic   }
117366857a2SPetar Jovanovic   return true;
118366857a2SPetar Jovanovic }
119fac93e28SPetar Jovanovic 
getRegClassForTypeOnBank(Register Reg,MachineRegisterInfo & MRI) const1207d0778eaSPetar Avramovic const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
121d32a6f08SPetar Avramovic     Register Reg, MachineRegisterInfo &MRI) const {
122d32a6f08SPetar Avramovic   const LLT Ty = MRI.getType(Reg);
123d32a6f08SPetar Avramovic   const unsigned TySize = Ty.getSizeInBits();
124d32a6f08SPetar Avramovic 
125d32a6f08SPetar Avramovic   if (isRegInGprb(Reg, MRI)) {
126d32a6f08SPetar Avramovic     assert((Ty.isScalar() || Ty.isPointer()) && TySize == 32 &&
127d32a6f08SPetar Avramovic            "Register class not available for LLT, register bank combination");
1287d0778eaSPetar Avramovic     return &Mips::GPR32RegClass;
129d32a6f08SPetar Avramovic   }
1307d0778eaSPetar Avramovic 
131d32a6f08SPetar Avramovic   if (isRegInFprb(Reg, MRI)) {
132d32a6f08SPetar Avramovic     if (Ty.isScalar()) {
133d32a6f08SPetar Avramovic       assert((TySize == 32 || TySize == 64) &&
134d32a6f08SPetar Avramovic              "Register class not available for LLT, register bank combination");
135d32a6f08SPetar Avramovic       if (TySize == 32)
136d32a6f08SPetar Avramovic         return &Mips::FGR32RegClass;
137d32a6f08SPetar Avramovic       return STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
138d32a6f08SPetar Avramovic     }
139d32a6f08SPetar Avramovic   }
1407d0778eaSPetar Avramovic 
141d32a6f08SPetar Avramovic   llvm_unreachable("Unsupported register bank.");
1427d0778eaSPetar Avramovic }
1437d0778eaSPetar Avramovic 
materialize32BitImm(Register DestReg,APInt Imm,MachineIRBuilder & B) const144faeaedf8SMatt Arsenault bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
1453e0da146SPetar Avramovic                                                   MachineIRBuilder &B) const {
1463e0da146SPetar Avramovic   assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
1473e0da146SPetar Avramovic   // Ori zero extends immediate. Used for values with zeros in high 16 bits.
148a9bceb2bSJay Foad   if (Imm.getHiBits(16).isZero()) {
1490bd82a96SSimon Atanasyan     MachineInstr *Inst =
1500bd82a96SSimon Atanasyan         B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
1513e0da146SPetar Avramovic             .addImm(Imm.getLoBits(16).getLimitedValue());
1523e0da146SPetar Avramovic     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
1533e0da146SPetar Avramovic   }
1543e0da146SPetar Avramovic   // Lui places immediate in high 16 bits and sets low 16 bits to zero.
155a9bceb2bSJay Foad   if (Imm.getLoBits(16).isZero()) {
1563e0da146SPetar Avramovic     MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
1573e0da146SPetar Avramovic                              .addImm(Imm.getHiBits(16).getLimitedValue());
1583e0da146SPetar Avramovic     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
1593e0da146SPetar Avramovic   }
1603e0da146SPetar Avramovic   // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
1613e0da146SPetar Avramovic   if (Imm.isSignedIntN(16)) {
1620bd82a96SSimon Atanasyan     MachineInstr *Inst =
1630bd82a96SSimon Atanasyan         B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
1643e0da146SPetar Avramovic             .addImm(Imm.getLoBits(16).getLimitedValue());
1653e0da146SPetar Avramovic     return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
1663e0da146SPetar Avramovic   }
1673e0da146SPetar Avramovic   // Values that cannot be materialized with single immediate instruction.
168faeaedf8SMatt Arsenault   Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
1693e0da146SPetar Avramovic   MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
1703e0da146SPetar Avramovic                           .addImm(Imm.getHiBits(16).getLimitedValue());
1713e0da146SPetar Avramovic   MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
1723e0da146SPetar Avramovic                           .addImm(Imm.getLoBits(16).getLimitedValue());
1733e0da146SPetar Avramovic   if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
1743e0da146SPetar Avramovic     return false;
1753e0da146SPetar Avramovic   if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
1763e0da146SPetar Avramovic     return false;
1773e0da146SPetar Avramovic   return true;
1783e0da146SPetar Avramovic }
1793e0da146SPetar Avramovic 
180d32a6f08SPetar Avramovic /// When I.getOpcode() is returned, we failed to select MIPS instruction opcode.
181599591f3SPetar Avramovic unsigned
selectLoadStoreOpCode(MachineInstr & I,MachineRegisterInfo & MRI) const182599591f3SPetar Avramovic MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I,
183599591f3SPetar Avramovic                                                MachineRegisterInfo &MRI) const {
184d32a6f08SPetar Avramovic   const Register ValueReg = I.getOperand(0).getReg();
185d32a6f08SPetar Avramovic   const LLT Ty = MRI.getType(ValueReg);
186d32a6f08SPetar Avramovic   const unsigned TySize = Ty.getSizeInBits();
187599591f3SPetar Avramovic   const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize();
188599591f3SPetar Avramovic   unsigned Opc = I.getOpcode();
189599591f3SPetar Avramovic   const bool isStore = Opc == TargetOpcode::G_STORE;
190d32a6f08SPetar Avramovic 
191d32a6f08SPetar Avramovic   if (isRegInGprb(ValueReg, MRI)) {
192d32a6f08SPetar Avramovic     assert(((Ty.isScalar() && TySize == 32) ||
193d32a6f08SPetar Avramovic             (Ty.isPointer() && TySize == 32 && MemSizeInBytes == 4)) &&
194d32a6f08SPetar Avramovic            "Unsupported register bank, LLT, MemSizeInBytes combination");
19545ee0d6dSFangrui Song     (void)TySize;
1967b31491aSPetar Avramovic     if (isStore)
19779df8596SPetar Avramovic       switch (MemSizeInBytes) {
19879df8596SPetar Avramovic       case 4:
19979df8596SPetar Avramovic         return Mips::SW;
200c98b26d3SPetar Avramovic       case 2:
201c98b26d3SPetar Avramovic         return Mips::SH;
202c98b26d3SPetar Avramovic       case 1:
203c98b26d3SPetar Avramovic         return Mips::SB;
20479df8596SPetar Avramovic       default:
20579df8596SPetar Avramovic         return Opc;
20679df8596SPetar Avramovic       }
20779df8596SPetar Avramovic     else
208c98b26d3SPetar Avramovic       // Unspecified extending load is selected into zeroExtending load.
20979df8596SPetar Avramovic       switch (MemSizeInBytes) {
21079df8596SPetar Avramovic       case 4:
21179df8596SPetar Avramovic         return Mips::LW;
21279df8596SPetar Avramovic       case 2:
21379df8596SPetar Avramovic         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
21479df8596SPetar Avramovic       case 1:
21579df8596SPetar Avramovic         return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
21679df8596SPetar Avramovic       default:
21779df8596SPetar Avramovic         return Opc;
21879df8596SPetar Avramovic       }
21979df8596SPetar Avramovic   }
22079df8596SPetar Avramovic 
221d32a6f08SPetar Avramovic   if (isRegInFprb(ValueReg, MRI)) {
222d32a6f08SPetar Avramovic     if (Ty.isScalar()) {
223d32a6f08SPetar Avramovic       assert(((TySize == 32 && MemSizeInBytes == 4) ||
224d32a6f08SPetar Avramovic               (TySize == 64 && MemSizeInBytes == 8)) &&
225d32a6f08SPetar Avramovic              "Unsupported register bank, LLT, MemSizeInBytes combination");
226d32a6f08SPetar Avramovic 
227d32a6f08SPetar Avramovic       if (MemSizeInBytes == 4)
2287b31491aSPetar Avramovic         return isStore ? Mips::SWC1 : Mips::LWC1;
229d32a6f08SPetar Avramovic 
230599591f3SPetar Avramovic       if (STI.isFP64bit())
2317b31491aSPetar Avramovic         return isStore ? Mips::SDC164 : Mips::LDC164;
2327b31491aSPetar Avramovic       return isStore ? Mips::SDC1 : Mips::LDC1;
233599591f3SPetar Avramovic     }
234d32a6f08SPetar Avramovic 
235d32a6f08SPetar Avramovic     if (Ty.isVector()) {
236d32a6f08SPetar Avramovic       assert(STI.hasMSA() && "Vector instructions require target with MSA.");
237d32a6f08SPetar Avramovic       assert((TySize == 128 && MemSizeInBytes == 16) &&
238d32a6f08SPetar Avramovic              "Unsupported register bank, LLT, MemSizeInBytes combination");
239d32a6f08SPetar Avramovic       switch (Ty.getElementType().getSizeInBits()) {
240d32a6f08SPetar Avramovic       case 8:
241d32a6f08SPetar Avramovic         return isStore ? Mips::ST_B : Mips::LD_B;
242d32a6f08SPetar Avramovic       case 16:
243d32a6f08SPetar Avramovic         return isStore ? Mips::ST_H : Mips::LD_H;
244d32a6f08SPetar Avramovic       case 32:
245d32a6f08SPetar Avramovic         return isStore ? Mips::ST_W : Mips::LD_W;
246d32a6f08SPetar Avramovic       case 64:
247d32a6f08SPetar Avramovic         return isStore ? Mips::ST_D : Mips::LD_D;
2487b31491aSPetar Avramovic       default:
2497b31491aSPetar Avramovic         return Opc;
2507b31491aSPetar Avramovic       }
2517b31491aSPetar Avramovic     }
252d32a6f08SPetar Avramovic   }
253d32a6f08SPetar Avramovic 
2547b31491aSPetar Avramovic   return Opc;
2557b31491aSPetar Avramovic }
2567b31491aSPetar Avramovic 
buildUnalignedStore(MachineInstr & I,unsigned Opc,MachineOperand & BaseAddr,unsigned Offset,MachineMemOperand * MMO) const2575171d152SPetar Avramovic bool MipsInstructionSelector::buildUnalignedStore(
2585171d152SPetar Avramovic     MachineInstr &I, unsigned Opc, MachineOperand &BaseAddr, unsigned Offset,
2595171d152SPetar Avramovic     MachineMemOperand *MMO) const {
2605171d152SPetar Avramovic   MachineInstr *NewInst =
2615171d152SPetar Avramovic       BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opc))
2625171d152SPetar Avramovic           .add(I.getOperand(0))
2635171d152SPetar Avramovic           .add(BaseAddr)
2645171d152SPetar Avramovic           .addImm(Offset)
2655171d152SPetar Avramovic           .addMemOperand(MMO);
2665171d152SPetar Avramovic   if (!constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI))
2675171d152SPetar Avramovic     return false;
2685171d152SPetar Avramovic   return true;
2695171d152SPetar Avramovic }
2705171d152SPetar Avramovic 
buildUnalignedLoad(MachineInstr & I,unsigned Opc,Register Dest,MachineOperand & BaseAddr,unsigned Offset,Register TiedDest,MachineMemOperand * MMO) const2715171d152SPetar Avramovic bool MipsInstructionSelector::buildUnalignedLoad(
2725171d152SPetar Avramovic     MachineInstr &I, unsigned Opc, Register Dest, MachineOperand &BaseAddr,
2735171d152SPetar Avramovic     unsigned Offset, Register TiedDest, MachineMemOperand *MMO) const {
2745171d152SPetar Avramovic   MachineInstr *NewInst =
2755171d152SPetar Avramovic       BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opc))
2765171d152SPetar Avramovic           .addDef(Dest)
2775171d152SPetar Avramovic           .add(BaseAddr)
2785171d152SPetar Avramovic           .addImm(Offset)
2795171d152SPetar Avramovic           .addUse(TiedDest)
2805171d152SPetar Avramovic           .addMemOperand(*I.memoperands_begin());
2815171d152SPetar Avramovic   if (!constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI))
2825171d152SPetar Avramovic     return false;
2835171d152SPetar Avramovic   return true;
2845171d152SPetar Avramovic }
2855171d152SPetar Avramovic 
select(MachineInstr & I)286e14c91b7SAmara Emerson bool MipsInstructionSelector::select(MachineInstr &I) {
287fac93e28SPetar Jovanovic 
288366857a2SPetar Jovanovic   MachineBasicBlock &MBB = *I.getParent();
289366857a2SPetar Jovanovic   MachineFunction &MF = *MBB.getParent();
290366857a2SPetar Jovanovic   MachineRegisterInfo &MRI = MF.getRegInfo();
291366857a2SPetar Jovanovic 
292fac93e28SPetar Jovanovic   if (!isPreISelGenericOpcode(I.getOpcode())) {
293366857a2SPetar Jovanovic     if (I.isCopy())
294a034a64fSPetar Avramovic       return selectCopy(I, MRI);
295366857a2SPetar Jovanovic 
296fac93e28SPetar Jovanovic     return true;
297fac93e28SPetar Jovanovic   }
298fac93e28SPetar Jovanovic 
299d1815dacSPetar Avramovic   if (I.getOpcode() == Mips::G_MUL &&
300d32a6f08SPetar Avramovic       isRegInGprb(I.getOperand(0).getReg(), MRI)) {
3013d3120dcSPetar Avramovic     MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
3023d3120dcSPetar Avramovic                             .add(I.getOperand(0))
3033d3120dcSPetar Avramovic                             .add(I.getOperand(1))
3043d3120dcSPetar Avramovic                             .add(I.getOperand(2));
3053d3120dcSPetar Avramovic     if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
3063d3120dcSPetar Avramovic       return false;
3073d3120dcSPetar Avramovic     Mul->getOperand(3).setIsDead(true);
3083d3120dcSPetar Avramovic     Mul->getOperand(4).setIsDead(true);
3093d3120dcSPetar Avramovic 
3103d3120dcSPetar Avramovic     I.eraseFromParent();
311366857a2SPetar Jovanovic     return true;
312366857a2SPetar Jovanovic   }
313021e4c82SPetar Jovanovic 
314e14c91b7SAmara Emerson   if (selectImpl(I, *CoverageInfo))
3153d3120dcSPetar Avramovic     return true;
3163d3120dcSPetar Avramovic 
317021e4c82SPetar Jovanovic   MachineInstr *MI = nullptr;
318021e4c82SPetar Jovanovic   using namespace TargetOpcode;
319021e4c82SPetar Jovanovic 
320021e4c82SPetar Jovanovic   switch (I.getOpcode()) {
321a48285a1SPetar Avramovic   case G_UMULH: {
322faeaedf8SMatt Arsenault     Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
323a48285a1SPetar Avramovic     MachineInstr *PseudoMULTu, *PseudoMove;
324a48285a1SPetar Avramovic 
325a48285a1SPetar Avramovic     PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
326a48285a1SPetar Avramovic                       .addDef(PseudoMULTuReg)
327a48285a1SPetar Avramovic                       .add(I.getOperand(1))
328a48285a1SPetar Avramovic                       .add(I.getOperand(2));
329a48285a1SPetar Avramovic     if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
330a48285a1SPetar Avramovic       return false;
331a48285a1SPetar Avramovic 
332a48285a1SPetar Avramovic     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
333a48285a1SPetar Avramovic                      .addDef(I.getOperand(0).getReg())
334a48285a1SPetar Avramovic                      .addUse(PseudoMULTuReg);
335a48285a1SPetar Avramovic     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
336a48285a1SPetar Avramovic       return false;
337a48285a1SPetar Avramovic 
338a48285a1SPetar Avramovic     I.eraseFromParent();
339a48285a1SPetar Avramovic     return true;
340a48285a1SPetar Avramovic   }
341e74c5b96SDaniel Sanders   case G_PTR_ADD: {
342021e4c82SPetar Jovanovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
343021e4c82SPetar Jovanovic              .add(I.getOperand(0))
344021e4c82SPetar Jovanovic              .add(I.getOperand(1))
345021e4c82SPetar Jovanovic              .add(I.getOperand(2));
346021e4c82SPetar Jovanovic     break;
347021e4c82SPetar Jovanovic   }
348b1fc6f61SPetar Avramovic   case G_INTTOPTR:
349b1fc6f61SPetar Avramovic   case G_PTRTOINT: {
350b1fc6f61SPetar Avramovic     I.setDesc(TII.get(COPY));
351b1fc6f61SPetar Avramovic     return selectCopy(I, MRI);
352b1fc6f61SPetar Avramovic   }
353021e4c82SPetar Jovanovic   case G_FRAME_INDEX: {
354021e4c82SPetar Jovanovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
355021e4c82SPetar Jovanovic              .add(I.getOperand(0))
356021e4c82SPetar Jovanovic              .add(I.getOperand(1))
357021e4c82SPetar Jovanovic              .addImm(0);
358021e4c82SPetar Jovanovic     break;
359021e4c82SPetar Jovanovic   }
3605d9b8eedSPetar Avramovic   case G_BRCOND: {
3615d9b8eedSPetar Avramovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
3625d9b8eedSPetar Avramovic              .add(I.getOperand(0))
3635d9b8eedSPetar Avramovic              .addUse(Mips::ZERO)
3645d9b8eedSPetar Avramovic              .add(I.getOperand(1));
3655d9b8eedSPetar Avramovic     break;
3665d9b8eedSPetar Avramovic   }
367caef9306SPetar Avramovic   case G_BRJT: {
368caef9306SPetar Avramovic     unsigned EntrySize =
369caef9306SPetar Avramovic         MF.getJumpTableInfo()->getEntrySize(MF.getDataLayout());
370caef9306SPetar Avramovic     assert(isPowerOf2_32(EntrySize) &&
371caef9306SPetar Avramovic            "Non-power-of-two jump-table entry size not supported.");
372caef9306SPetar Avramovic 
373caef9306SPetar Avramovic     Register JTIndex = MRI.createVirtualRegister(&Mips::GPR32RegClass);
374caef9306SPetar Avramovic     MachineInstr *SLL = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SLL))
375caef9306SPetar Avramovic                             .addDef(JTIndex)
376caef9306SPetar Avramovic                             .addUse(I.getOperand(2).getReg())
377caef9306SPetar Avramovic                             .addImm(Log2_32(EntrySize));
378caef9306SPetar Avramovic     if (!constrainSelectedInstRegOperands(*SLL, TII, TRI, RBI))
379caef9306SPetar Avramovic       return false;
380caef9306SPetar Avramovic 
381caef9306SPetar Avramovic     Register DestAddress = MRI.createVirtualRegister(&Mips::GPR32RegClass);
382caef9306SPetar Avramovic     MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
383caef9306SPetar Avramovic                              .addDef(DestAddress)
384caef9306SPetar Avramovic                              .addUse(I.getOperand(0).getReg())
385caef9306SPetar Avramovic                              .addUse(JTIndex);
386caef9306SPetar Avramovic     if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
387caef9306SPetar Avramovic       return false;
388caef9306SPetar Avramovic 
389caef9306SPetar Avramovic     Register Dest = MRI.createVirtualRegister(&Mips::GPR32RegClass);
390caef9306SPetar Avramovic     MachineInstr *LW =
391caef9306SPetar Avramovic         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
392caef9306SPetar Avramovic             .addDef(Dest)
393caef9306SPetar Avramovic             .addUse(DestAddress)
394caef9306SPetar Avramovic             .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_LO)
395caef9306SPetar Avramovic             .addMemOperand(MF.getMachineMemOperand(
396c9d5c195SGuillaume Chatelet                 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, Align(4)));
397caef9306SPetar Avramovic     if (!constrainSelectedInstRegOperands(*LW, TII, TRI, RBI))
398caef9306SPetar Avramovic       return false;
399caef9306SPetar Avramovic 
400caef9306SPetar Avramovic     if (MF.getTarget().isPositionIndependent()) {
401caef9306SPetar Avramovic       Register DestTmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
402caef9306SPetar Avramovic       LW->getOperand(0).setReg(DestTmp);
403caef9306SPetar Avramovic       MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
404caef9306SPetar Avramovic                                .addDef(Dest)
405caef9306SPetar Avramovic                                .addUse(DestTmp)
406caef9306SPetar Avramovic                                .addUse(MF.getInfo<MipsFunctionInfo>()
407669bb311SMatt Arsenault                                            ->getGlobalBaseRegForGlobalISel(MF));
408caef9306SPetar Avramovic       if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
409caef9306SPetar Avramovic         return false;
410caef9306SPetar Avramovic     }
411caef9306SPetar Avramovic 
412caef9306SPetar Avramovic     MachineInstr *Branch =
413caef9306SPetar Avramovic         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
414caef9306SPetar Avramovic             .addUse(Dest);
415caef9306SPetar Avramovic     if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
416caef9306SPetar Avramovic       return false;
417caef9306SPetar Avramovic 
418caef9306SPetar Avramovic     I.eraseFromParent();
419caef9306SPetar Avramovic     return true;
420caef9306SPetar Avramovic   }
421ff6ac1ebSPetar Avramovic   case G_BRINDIRECT: {
422ff6ac1ebSPetar Avramovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
423ff6ac1ebSPetar Avramovic              .add(I.getOperand(0));
424ff6ac1ebSPetar Avramovic     break;
425ff6ac1ebSPetar Avramovic   }
42614c7ecfeSPetar Avramovic   case G_PHI: {
427faeaedf8SMatt Arsenault     const Register DestReg = I.getOperand(0).getReg();
42814c7ecfeSPetar Avramovic 
4297d0778eaSPetar Avramovic     const TargetRegisterClass *DefRC = nullptr;
4302bea69bfSDaniel Sanders     if (Register::isPhysicalRegister(DestReg))
4317d0778eaSPetar Avramovic       DefRC = TRI.getRegClass(DestReg);
4327d0778eaSPetar Avramovic     else
433d32a6f08SPetar Avramovic       DefRC = getRegClassForTypeOnBank(DestReg, MRI);
43414c7ecfeSPetar Avramovic 
43514c7ecfeSPetar Avramovic     I.setDesc(TII.get(TargetOpcode::PHI));
43614c7ecfeSPetar Avramovic     return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
43714c7ecfeSPetar Avramovic   }
438021e4c82SPetar Jovanovic   case G_STORE:
43979df8596SPetar Avramovic   case G_LOAD:
44079df8596SPetar Avramovic   case G_ZEXTLOAD:
44179df8596SPetar Avramovic   case G_SEXTLOAD: {
4425171d152SPetar Avramovic     auto MMO = *I.memoperands_begin();
4438a40cedfSPetar Avramovic     MachineOperand BaseAddr = I.getOperand(1);
4448a40cedfSPetar Avramovic     int64_t SignedOffset = 0;
445e74c5b96SDaniel Sanders     // Try to fold load/store + G_PTR_ADD + G_CONSTANT
4468a40cedfSPetar Avramovic     // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate
447e74c5b96SDaniel Sanders     // %Addr:(p0) = G_PTR_ADD %BaseAddr, %SignedOffset
4488a40cedfSPetar Avramovic     // %LoadResult/%StoreSrc = load/store %Addr(p0)
4498a40cedfSPetar Avramovic     // into:
4508a40cedfSPetar Avramovic     // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate
4518a40cedfSPetar Avramovic 
4528a40cedfSPetar Avramovic     MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg());
453e74c5b96SDaniel Sanders     if (Addr->getOpcode() == G_PTR_ADD) {
4548a40cedfSPetar Avramovic       MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg());
4558a40cedfSPetar Avramovic       if (Offset->getOpcode() == G_CONSTANT) {
4568a40cedfSPetar Avramovic         APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue();
4578a40cedfSPetar Avramovic         if (OffsetValue.isSignedIntN(16)) {
4588a40cedfSPetar Avramovic           BaseAddr = Addr->getOperand(1);
4598a40cedfSPetar Avramovic           SignedOffset = OffsetValue.getSExtValue();
4608a40cedfSPetar Avramovic         }
4618a40cedfSPetar Avramovic       }
4628a40cedfSPetar Avramovic     }
4638a40cedfSPetar Avramovic 
4645171d152SPetar Avramovic     // Unaligned memory access
46574eac903SGuillaume Chatelet     if (MMO->getAlign() < MMO->getSize() &&
4665171d152SPetar Avramovic         !STI.systemSupportsUnalignedAccess()) {
4675171d152SPetar Avramovic       if (MMO->getSize() != 4 || !isRegInGprb(I.getOperand(0).getReg(), MRI))
4685171d152SPetar Avramovic         return false;
4695171d152SPetar Avramovic 
4705171d152SPetar Avramovic       if (I.getOpcode() == G_STORE) {
4715171d152SPetar Avramovic         if (!buildUnalignedStore(I, Mips::SWL, BaseAddr, SignedOffset + 3, MMO))
4725171d152SPetar Avramovic           return false;
4735171d152SPetar Avramovic         if (!buildUnalignedStore(I, Mips::SWR, BaseAddr, SignedOffset, MMO))
4745171d152SPetar Avramovic           return false;
4755171d152SPetar Avramovic         I.eraseFromParent();
4765171d152SPetar Avramovic         return true;
4775171d152SPetar Avramovic       }
4785171d152SPetar Avramovic 
4795171d152SPetar Avramovic       if (I.getOpcode() == G_LOAD) {
4805171d152SPetar Avramovic         Register ImplDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
4815171d152SPetar Avramovic         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
4825171d152SPetar Avramovic             .addDef(ImplDef);
4835171d152SPetar Avramovic         Register Tmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
4845171d152SPetar Avramovic         if (!buildUnalignedLoad(I, Mips::LWL, Tmp, BaseAddr, SignedOffset + 3,
4855171d152SPetar Avramovic                                 ImplDef, MMO))
4865171d152SPetar Avramovic           return false;
4875171d152SPetar Avramovic         if (!buildUnalignedLoad(I, Mips::LWR, I.getOperand(0).getReg(),
4885171d152SPetar Avramovic                                 BaseAddr, SignedOffset, Tmp, MMO))
4895171d152SPetar Avramovic           return false;
4905171d152SPetar Avramovic         I.eraseFromParent();
4915171d152SPetar Avramovic         return true;
4925171d152SPetar Avramovic       }
4935171d152SPetar Avramovic 
4945171d152SPetar Avramovic       return false;
4955171d152SPetar Avramovic     }
4965171d152SPetar Avramovic 
4975171d152SPetar Avramovic     const unsigned NewOpc = selectLoadStoreOpCode(I, MRI);
4985171d152SPetar Avramovic     if (NewOpc == I.getOpcode())
4995171d152SPetar Avramovic       return false;
5005171d152SPetar Avramovic 
501021e4c82SPetar Jovanovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
502021e4c82SPetar Jovanovic              .add(I.getOperand(0))
5038a40cedfSPetar Avramovic              .add(BaseAddr)
5048a40cedfSPetar Avramovic              .addImm(SignedOffset)
5055171d152SPetar Avramovic              .addMemOperand(MMO);
506021e4c82SPetar Jovanovic     break;
507021e4c82SPetar Jovanovic   }
5080a5e4eb7SPetar Avramovic   case G_UDIV:
5090a5e4eb7SPetar Avramovic   case G_UREM:
5100a5e4eb7SPetar Avramovic   case G_SDIV:
5110a5e4eb7SPetar Avramovic   case G_SREM: {
512faeaedf8SMatt Arsenault     Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
5130a5e4eb7SPetar Avramovic     bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
5140a5e4eb7SPetar Avramovic     bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
5150a5e4eb7SPetar Avramovic 
5160a5e4eb7SPetar Avramovic     MachineInstr *PseudoDIV, *PseudoMove;
5170a5e4eb7SPetar Avramovic     PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
5180a5e4eb7SPetar Avramovic                         TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
5190a5e4eb7SPetar Avramovic                     .addDef(HILOReg)
5200a5e4eb7SPetar Avramovic                     .add(I.getOperand(1))
5210a5e4eb7SPetar Avramovic                     .add(I.getOperand(2));
5220a5e4eb7SPetar Avramovic     if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
5230a5e4eb7SPetar Avramovic       return false;
5240a5e4eb7SPetar Avramovic 
5250a5e4eb7SPetar Avramovic     PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
5260a5e4eb7SPetar Avramovic                          TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
5270a5e4eb7SPetar Avramovic                      .addDef(I.getOperand(0).getReg())
5280a5e4eb7SPetar Avramovic                      .addUse(HILOReg);
5290a5e4eb7SPetar Avramovic     if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
5300a5e4eb7SPetar Avramovic       return false;
5310a5e4eb7SPetar Avramovic 
5320a5e4eb7SPetar Avramovic     I.eraseFromParent();
5330a5e4eb7SPetar Avramovic     return true;
5340a5e4eb7SPetar Avramovic   }
53509dff333SPetar Avramovic   case G_SELECT: {
53609dff333SPetar Avramovic     // Handle operands with pointer type.
53709dff333SPetar Avramovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
53809dff333SPetar Avramovic              .add(I.getOperand(0))
53909dff333SPetar Avramovic              .add(I.getOperand(2))
54009dff333SPetar Avramovic              .add(I.getOperand(1))
54109dff333SPetar Avramovic              .add(I.getOperand(3));
54209dff333SPetar Avramovic     break;
54309dff333SPetar Avramovic   }
54492c80529SPetar Avramovic   case G_UNMERGE_VALUES: {
54592c80529SPetar Avramovic     if (I.getNumOperands() != 3)
54692c80529SPetar Avramovic       return false;
54792c80529SPetar Avramovic     Register Src = I.getOperand(2).getReg();
54892c80529SPetar Avramovic     Register Lo = I.getOperand(0).getReg();
54992c80529SPetar Avramovic     Register Hi = I.getOperand(1).getReg();
55092c80529SPetar Avramovic     if (!isRegInFprb(Src, MRI) ||
55192c80529SPetar Avramovic         !(isRegInGprb(Lo, MRI) && isRegInGprb(Hi, MRI)))
55292c80529SPetar Avramovic       return false;
55392c80529SPetar Avramovic 
55492c80529SPetar Avramovic     unsigned Opcode =
55592c80529SPetar Avramovic         STI.isFP64bit() ? Mips::ExtractElementF64_64 : Mips::ExtractElementF64;
55692c80529SPetar Avramovic 
55792c80529SPetar Avramovic     MachineInstr *ExtractLo = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
55892c80529SPetar Avramovic                                   .addDef(Lo)
55992c80529SPetar Avramovic                                   .addUse(Src)
56092c80529SPetar Avramovic                                   .addImm(0);
56192c80529SPetar Avramovic     if (!constrainSelectedInstRegOperands(*ExtractLo, TII, TRI, RBI))
56292c80529SPetar Avramovic       return false;
56392c80529SPetar Avramovic 
56492c80529SPetar Avramovic     MachineInstr *ExtractHi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
56592c80529SPetar Avramovic                                   .addDef(Hi)
56692c80529SPetar Avramovic                                   .addUse(Src)
56792c80529SPetar Avramovic                                   .addImm(1);
56892c80529SPetar Avramovic     if (!constrainSelectedInstRegOperands(*ExtractHi, TII, TRI, RBI))
56992c80529SPetar Avramovic       return false;
57092c80529SPetar Avramovic 
57192c80529SPetar Avramovic     I.eraseFromParent();
57292c80529SPetar Avramovic     return true;
57392c80529SPetar Avramovic   }
57475e43a60SPetar Avramovic   case G_IMPLICIT_DEF: {
575d32a6f08SPetar Avramovic     Register Dst = I.getOperand(0).getReg();
57675e43a60SPetar Avramovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
577d32a6f08SPetar Avramovic              .addDef(Dst);
57875e43a60SPetar Avramovic 
57975e43a60SPetar Avramovic     // Set class based on register bank, there can be fpr and gpr implicit def.
580d32a6f08SPetar Avramovic     MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst, MRI));
58175e43a60SPetar Avramovic     break;
58275e43a60SPetar Avramovic   }
583021e4c82SPetar Jovanovic   case G_CONSTANT: {
5843e0da146SPetar Avramovic     MachineIRBuilder B(I);
5853e0da146SPetar Avramovic     if (!materialize32BitImm(I.getOperand(0).getReg(),
5863e0da146SPetar Avramovic                              I.getOperand(1).getCImm()->getValue(), B))
587021e4c82SPetar Jovanovic       return false;
588021e4c82SPetar Jovanovic 
589021e4c82SPetar Jovanovic     I.eraseFromParent();
590021e4c82SPetar Jovanovic     return true;
591021e4c82SPetar Jovanovic   }
5921af05df3SPetar Avramovic   case G_FCONSTANT: {
5931af05df3SPetar Avramovic     const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
5941af05df3SPetar Avramovic     APInt APImm = FPimm.bitcastToAPInt();
5951af05df3SPetar Avramovic     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
5961af05df3SPetar Avramovic 
5971af05df3SPetar Avramovic     if (Size == 32) {
598faeaedf8SMatt Arsenault       Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
5991af05df3SPetar Avramovic       MachineIRBuilder B(I);
6001af05df3SPetar Avramovic       if (!materialize32BitImm(GPRReg, APImm, B))
6011af05df3SPetar Avramovic         return false;
6021af05df3SPetar Avramovic 
6031af05df3SPetar Avramovic       MachineInstrBuilder MTC1 =
6041af05df3SPetar Avramovic           B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
6051af05df3SPetar Avramovic       if (!MTC1.constrainAllUses(TII, TRI, RBI))
6061af05df3SPetar Avramovic         return false;
6071af05df3SPetar Avramovic     }
6081af05df3SPetar Avramovic     if (Size == 64) {
609faeaedf8SMatt Arsenault       Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
610faeaedf8SMatt Arsenault       Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
6111af05df3SPetar Avramovic       MachineIRBuilder B(I);
6121af05df3SPetar Avramovic       if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
6131af05df3SPetar Avramovic         return false;
6141af05df3SPetar Avramovic       if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
6151af05df3SPetar Avramovic         return false;
6161af05df3SPetar Avramovic 
6171af05df3SPetar Avramovic       MachineInstrBuilder PairF64 = B.buildInstr(
6181af05df3SPetar Avramovic           STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
6191af05df3SPetar Avramovic           {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
6201af05df3SPetar Avramovic       if (!PairF64.constrainAllUses(TII, TRI, RBI))
6211af05df3SPetar Avramovic         return false;
6221af05df3SPetar Avramovic     }
6231af05df3SPetar Avramovic 
6241af05df3SPetar Avramovic     I.eraseFromParent();
6251af05df3SPetar Avramovic     return true;
6261af05df3SPetar Avramovic   }
6270a1fd355SPetar Avramovic   case G_FABS: {
6280a1fd355SPetar Avramovic     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
6290a1fd355SPetar Avramovic     unsigned FABSOpcode =
6300a1fd355SPetar Avramovic         Size == 32 ? Mips::FABS_S
6310a1fd355SPetar Avramovic                    : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
6320a1fd355SPetar Avramovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
6330a1fd355SPetar Avramovic              .add(I.getOperand(0))
6340a1fd355SPetar Avramovic              .add(I.getOperand(1));
6350a1fd355SPetar Avramovic     break;
6360a1fd355SPetar Avramovic   }
6374b4dae1cSPetar Avramovic   case G_FPTOSI: {
6384b4dae1cSPetar Avramovic     unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
6394b4dae1cSPetar Avramovic     unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
640ddd056c9SFangrui Song     (void)ToSize;
6414b4dae1cSPetar Avramovic     assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
6424b4dae1cSPetar Avramovic     assert((FromSize == 32 || FromSize == 64) &&
6434b4dae1cSPetar Avramovic            "Unsupported floating point size for G_FPTOSI");
6444b4dae1cSPetar Avramovic 
6454b4dae1cSPetar Avramovic     unsigned Opcode;
6464b4dae1cSPetar Avramovic     if (FromSize == 32)
6474b4dae1cSPetar Avramovic       Opcode = Mips::TRUNC_W_S;
6484b4dae1cSPetar Avramovic     else
6494b4dae1cSPetar Avramovic       Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
6500c476111SDaniel Sanders     Register ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
6514b4dae1cSPetar Avramovic     MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
6524b4dae1cSPetar Avramovic                 .addDef(ResultInFPR)
6534b4dae1cSPetar Avramovic                 .addUse(I.getOperand(1).getReg());
6544b4dae1cSPetar Avramovic     if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
6554b4dae1cSPetar Avramovic       return false;
6564b4dae1cSPetar Avramovic 
6574b4dae1cSPetar Avramovic     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
6584b4dae1cSPetar Avramovic                              .addDef(I.getOperand(0).getReg())
6594b4dae1cSPetar Avramovic                              .addUse(ResultInFPR);
6604b4dae1cSPetar Avramovic     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
6614b4dae1cSPetar Avramovic       return false;
6624b4dae1cSPetar Avramovic 
6634b4dae1cSPetar Avramovic     I.eraseFromParent();
6644b4dae1cSPetar Avramovic     return true;
6654b4dae1cSPetar Avramovic   }
66664c10ba8SPetar Jovanovic   case G_GLOBAL_VALUE: {
667efcd3c00SPetar Avramovic     const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
668efcd3c00SPetar Avramovic     if (MF.getTarget().isPositionIndependent()) {
669efcd3c00SPetar Avramovic       MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
670efcd3c00SPetar Avramovic                                 .addDef(I.getOperand(0).getReg())
671efcd3c00SPetar Avramovic                                 .addReg(MF.getInfo<MipsFunctionInfo>()
672669bb311SMatt Arsenault                                             ->getGlobalBaseRegForGlobalISel(MF))
673efcd3c00SPetar Avramovic                                 .addGlobalAddress(GVal);
674efcd3c00SPetar Avramovic       // Global Values that don't have local linkage are handled differently
675efcd3c00SPetar Avramovic       // when they are part of call sequence. MipsCallLowering::lowerCall
676efcd3c00SPetar Avramovic       // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
677efcd3c00SPetar Avramovic       // MO_GOT_CALL flag when Callee doesn't have local linkage.
678efcd3c00SPetar Avramovic       if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
679efcd3c00SPetar Avramovic         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
680efcd3c00SPetar Avramovic       else
681efcd3c00SPetar Avramovic         LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
682efcd3c00SPetar Avramovic       LWGOT->addMemOperand(
683efcd3c00SPetar Avramovic           MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
684c9d5c195SGuillaume Chatelet                                       MachineMemOperand::MOLoad, 4, Align(4)));
685efcd3c00SPetar Avramovic       if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
68664c10ba8SPetar Jovanovic         return false;
68764c10ba8SPetar Jovanovic 
688efcd3c00SPetar Avramovic       if (GVal->hasLocalLinkage()) {
689faeaedf8SMatt Arsenault         Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
690efcd3c00SPetar Avramovic         LWGOT->getOperand(0).setReg(LWGOTDef);
69164c10ba8SPetar Jovanovic 
692efcd3c00SPetar Avramovic         MachineInstr *ADDiu =
693efcd3c00SPetar Avramovic             BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
694efcd3c00SPetar Avramovic                 .addDef(I.getOperand(0).getReg())
695efcd3c00SPetar Avramovic                 .addReg(LWGOTDef)
696efcd3c00SPetar Avramovic                 .addGlobalAddress(GVal);
697efcd3c00SPetar Avramovic         ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
698efcd3c00SPetar Avramovic         if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
699efcd3c00SPetar Avramovic           return false;
700efcd3c00SPetar Avramovic       }
701efcd3c00SPetar Avramovic     } else {
702faeaedf8SMatt Arsenault       Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
703efcd3c00SPetar Avramovic 
704efcd3c00SPetar Avramovic       MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
70564c10ba8SPetar Jovanovic                               .addDef(LUiReg)
70664c10ba8SPetar Jovanovic                               .addGlobalAddress(GVal);
70764c10ba8SPetar Jovanovic       LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
708efcd3c00SPetar Avramovic       if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
709efcd3c00SPetar Avramovic         return false;
71064c10ba8SPetar Jovanovic 
711efcd3c00SPetar Avramovic       MachineInstr *ADDiu =
712efcd3c00SPetar Avramovic           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
71364c10ba8SPetar Jovanovic               .addDef(I.getOperand(0).getReg())
71464c10ba8SPetar Jovanovic               .addUse(LUiReg)
71564c10ba8SPetar Jovanovic               .addGlobalAddress(GVal);
71664c10ba8SPetar Jovanovic       ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
71764c10ba8SPetar Jovanovic       if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
71864c10ba8SPetar Jovanovic         return false;
719efcd3c00SPetar Avramovic     }
72064c10ba8SPetar Jovanovic     I.eraseFromParent();
72164c10ba8SPetar Jovanovic     return true;
72264c10ba8SPetar Jovanovic   }
723caef9306SPetar Avramovic   case G_JUMP_TABLE: {
724caef9306SPetar Avramovic     if (MF.getTarget().isPositionIndependent()) {
725caef9306SPetar Avramovic       MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
726caef9306SPetar Avramovic                .addDef(I.getOperand(0).getReg())
727caef9306SPetar Avramovic                .addReg(MF.getInfo<MipsFunctionInfo>()
728669bb311SMatt Arsenault                            ->getGlobalBaseRegForGlobalISel(MF))
729caef9306SPetar Avramovic                .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_GOT)
730c9d5c195SGuillaume Chatelet                .addMemOperand(MF.getMachineMemOperand(
731c9d5c195SGuillaume Chatelet                    MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, 4,
732c9d5c195SGuillaume Chatelet                    Align(4)));
733caef9306SPetar Avramovic     } else {
734caef9306SPetar Avramovic       MI =
735caef9306SPetar Avramovic           BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
736caef9306SPetar Avramovic               .addDef(I.getOperand(0).getReg())
737caef9306SPetar Avramovic               .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_HI);
738caef9306SPetar Avramovic     }
739caef9306SPetar Avramovic     break;
740caef9306SPetar Avramovic   }
741ce4dd0aeSPetar Jovanovic   case G_ICMP: {
742ce4dd0aeSPetar Jovanovic     struct Instr {
743faeaedf8SMatt Arsenault       unsigned Opcode;
744faeaedf8SMatt Arsenault       Register Def, LHS, RHS;
745faeaedf8SMatt Arsenault       Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
746ce4dd0aeSPetar Jovanovic           : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
747021e4c82SPetar Jovanovic 
748ce4dd0aeSPetar Jovanovic       bool hasImm() const {
749ce4dd0aeSPetar Jovanovic         if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
750ce4dd0aeSPetar Jovanovic           return true;
751ce4dd0aeSPetar Jovanovic         return false;
752ce4dd0aeSPetar Jovanovic       }
753ce4dd0aeSPetar Jovanovic     };
754ce4dd0aeSPetar Jovanovic 
755ce4dd0aeSPetar Jovanovic     SmallVector<struct Instr, 2> Instructions;
756faeaedf8SMatt Arsenault     Register ICMPReg = I.getOperand(0).getReg();
757faeaedf8SMatt Arsenault     Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
758faeaedf8SMatt Arsenault     Register LHS = I.getOperand(2).getReg();
759faeaedf8SMatt Arsenault     Register RHS = I.getOperand(3).getReg();
760ce4dd0aeSPetar Jovanovic     CmpInst::Predicate Cond =
761ce4dd0aeSPetar Jovanovic         static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
762ce4dd0aeSPetar Jovanovic 
763ce4dd0aeSPetar Jovanovic     switch (Cond) {
764ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
765ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
766ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
767ce4dd0aeSPetar Jovanovic       break;
768ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
769ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
770ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
771ce4dd0aeSPetar Jovanovic       break;
772ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_UGT: // LHS >  RHS -> RHS < LHS
773ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
774ce4dd0aeSPetar Jovanovic       break;
775ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
776ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
777ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
778ce4dd0aeSPetar Jovanovic       break;
779ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_ULT: // LHS <  RHS -> LHS < RHS
780ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
781ce4dd0aeSPetar Jovanovic       break;
782ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
783ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
784ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
785ce4dd0aeSPetar Jovanovic       break;
786ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_SGT: // LHS >  RHS -> RHS < LHS
787ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
788ce4dd0aeSPetar Jovanovic       break;
789ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
790ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
791ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
792ce4dd0aeSPetar Jovanovic       break;
793ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_SLT: // LHS <  RHS -> LHS < RHS
794ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
795ce4dd0aeSPetar Jovanovic       break;
796ce4dd0aeSPetar Jovanovic     case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
797ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
798ce4dd0aeSPetar Jovanovic       Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
799ce4dd0aeSPetar Jovanovic       break;
800ce4dd0aeSPetar Jovanovic     default:
801ce4dd0aeSPetar Jovanovic       return false;
802ce4dd0aeSPetar Jovanovic     }
803ce4dd0aeSPetar Jovanovic 
804ce4dd0aeSPetar Jovanovic     MachineIRBuilder B(I);
805ce4dd0aeSPetar Jovanovic     for (const struct Instr &Instruction : Instructions) {
806cef44a23SAditya Nandakumar       MachineInstrBuilder MIB = B.buildInstr(
807cef44a23SAditya Nandakumar           Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
808ce4dd0aeSPetar Jovanovic 
809ce4dd0aeSPetar Jovanovic       if (Instruction.hasImm())
810ce4dd0aeSPetar Jovanovic         MIB.addImm(Instruction.RHS);
811ce4dd0aeSPetar Jovanovic       else
812ce4dd0aeSPetar Jovanovic         MIB.addUse(Instruction.RHS);
813ce4dd0aeSPetar Jovanovic 
814ce4dd0aeSPetar Jovanovic       if (!MIB.constrainAllUses(TII, TRI, RBI))
815ce4dd0aeSPetar Jovanovic         return false;
816ce4dd0aeSPetar Jovanovic     }
817ce4dd0aeSPetar Jovanovic 
818ce4dd0aeSPetar Jovanovic     I.eraseFromParent();
819ce4dd0aeSPetar Jovanovic     return true;
820ce4dd0aeSPetar Jovanovic   }
82122e99c43SPetar Avramovic   case G_FCMP: {
82222e99c43SPetar Avramovic     unsigned MipsFCMPCondCode;
82322e99c43SPetar Avramovic     bool isLogicallyNegated;
82422e99c43SPetar Avramovic     switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
82522e99c43SPetar Avramovic                 I.getOperand(1).getPredicate())) {
82622e99c43SPetar Avramovic     case CmpInst::FCMP_UNO: // Unordered
82722e99c43SPetar Avramovic     case CmpInst::FCMP_ORD: // Ordered (OR)
82822e99c43SPetar Avramovic       MipsFCMPCondCode = Mips::FCOND_UN;
82922e99c43SPetar Avramovic       isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
83022e99c43SPetar Avramovic       break;
83122e99c43SPetar Avramovic     case CmpInst::FCMP_OEQ: // Equal
83222e99c43SPetar Avramovic     case CmpInst::FCMP_UNE: // Not Equal (NEQ)
83322e99c43SPetar Avramovic       MipsFCMPCondCode = Mips::FCOND_OEQ;
83422e99c43SPetar Avramovic       isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
83522e99c43SPetar Avramovic       break;
83622e99c43SPetar Avramovic     case CmpInst::FCMP_UEQ: // Unordered or Equal
83722e99c43SPetar Avramovic     case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
83822e99c43SPetar Avramovic       MipsFCMPCondCode = Mips::FCOND_UEQ;
83922e99c43SPetar Avramovic       isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
84022e99c43SPetar Avramovic       break;
84122e99c43SPetar Avramovic     case CmpInst::FCMP_OLT: // Ordered or Less Than
84222e99c43SPetar Avramovic     case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
84322e99c43SPetar Avramovic       MipsFCMPCondCode = Mips::FCOND_OLT;
84422e99c43SPetar Avramovic       isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
84522e99c43SPetar Avramovic       break;
84622e99c43SPetar Avramovic     case CmpInst::FCMP_ULT: // Unordered or Less Than
84722e99c43SPetar Avramovic     case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
84822e99c43SPetar Avramovic       MipsFCMPCondCode = Mips::FCOND_ULT;
84922e99c43SPetar Avramovic       isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
85022e99c43SPetar Avramovic       break;
85122e99c43SPetar Avramovic     case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
85222e99c43SPetar Avramovic     case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
85322e99c43SPetar Avramovic       MipsFCMPCondCode = Mips::FCOND_OLE;
85422e99c43SPetar Avramovic       isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
85522e99c43SPetar Avramovic       break;
85622e99c43SPetar Avramovic     case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
85722e99c43SPetar Avramovic     case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
85822e99c43SPetar Avramovic       MipsFCMPCondCode = Mips::FCOND_ULE;
85922e99c43SPetar Avramovic       isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
86022e99c43SPetar Avramovic       break;
86122e99c43SPetar Avramovic     default:
86222e99c43SPetar Avramovic       return false;
86322e99c43SPetar Avramovic     }
86422e99c43SPetar Avramovic 
86522e99c43SPetar Avramovic     // Default compare result in gpr register will be `true`.
86622e99c43SPetar Avramovic     // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
86722e99c43SPetar Avramovic     // using MOVF_I. When orignal predicate (Cond) is logically negated
86822e99c43SPetar Avramovic     // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
86922e99c43SPetar Avramovic     unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
87022e99c43SPetar Avramovic 
8710c476111SDaniel Sanders     Register TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
87222e99c43SPetar Avramovic     BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
87322e99c43SPetar Avramovic         .addDef(TrueInReg)
87422e99c43SPetar Avramovic         .addUse(Mips::ZERO)
87522e99c43SPetar Avramovic         .addImm(1);
87622e99c43SPetar Avramovic 
87722e99c43SPetar Avramovic     unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
87822e99c43SPetar Avramovic     unsigned FCMPOpcode =
87922e99c43SPetar Avramovic         Size == 32 ? Mips::FCMP_S32
88022e99c43SPetar Avramovic                    : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
88122e99c43SPetar Avramovic     MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
88222e99c43SPetar Avramovic                              .addUse(I.getOperand(2).getReg())
88322e99c43SPetar Avramovic                              .addUse(I.getOperand(3).getReg())
88422e99c43SPetar Avramovic                              .addImm(MipsFCMPCondCode);
88522e99c43SPetar Avramovic     if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
88622e99c43SPetar Avramovic       return false;
88722e99c43SPetar Avramovic 
88822e99c43SPetar Avramovic     MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
88922e99c43SPetar Avramovic                              .addDef(I.getOperand(0).getReg())
89022e99c43SPetar Avramovic                              .addUse(Mips::ZERO)
89122e99c43SPetar Avramovic                              .addUse(Mips::FCC0)
89222e99c43SPetar Avramovic                              .addUse(TrueInReg);
89322e99c43SPetar Avramovic     if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
89422e99c43SPetar Avramovic       return false;
89522e99c43SPetar Avramovic 
89622e99c43SPetar Avramovic     I.eraseFromParent();
89722e99c43SPetar Avramovic     return true;
89822e99c43SPetar Avramovic   }
899a4bfc8dfSPetar Avramovic   case G_FENCE: {
900a4bfc8dfSPetar Avramovic     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
901a4bfc8dfSPetar Avramovic     break;
902a4bfc8dfSPetar Avramovic   }
903c063b0b0SPetar Avramovic   case G_VASTART: {
904c063b0b0SPetar Avramovic     MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
905c063b0b0SPetar Avramovic     int FI = FuncInfo->getVarArgsFrameIndex();
906c063b0b0SPetar Avramovic 
907c063b0b0SPetar Avramovic     Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
908c063b0b0SPetar Avramovic     MachineInstr *LEA_ADDiu =
909c063b0b0SPetar Avramovic         BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
910c063b0b0SPetar Avramovic             .addDef(LeaReg)
911c063b0b0SPetar Avramovic             .addFrameIndex(FI)
912c063b0b0SPetar Avramovic             .addImm(0);
913c063b0b0SPetar Avramovic     if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
914c063b0b0SPetar Avramovic       return false;
915c063b0b0SPetar Avramovic 
916c063b0b0SPetar Avramovic     MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
917c063b0b0SPetar Avramovic                               .addUse(LeaReg)
918c063b0b0SPetar Avramovic                               .addUse(I.getOperand(0).getReg())
919c063b0b0SPetar Avramovic                               .addImm(0);
920c063b0b0SPetar Avramovic     if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
921c063b0b0SPetar Avramovic       return false;
922c063b0b0SPetar Avramovic 
923c063b0b0SPetar Avramovic     I.eraseFromParent();
924c063b0b0SPetar Avramovic     return true;
925c063b0b0SPetar Avramovic   }
926021e4c82SPetar Jovanovic   default:
927021e4c82SPetar Jovanovic     return false;
928021e4c82SPetar Jovanovic   }
929021e4c82SPetar Jovanovic 
930021e4c82SPetar Jovanovic   I.eraseFromParent();
931021e4c82SPetar Jovanovic   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
932fac93e28SPetar Jovanovic }
933fac93e28SPetar Jovanovic 
934fac93e28SPetar Jovanovic namespace llvm {
createMipsInstructionSelector(const MipsTargetMachine & TM,MipsSubtarget & Subtarget,MipsRegisterBankInfo & RBI)935fac93e28SPetar Jovanovic InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
936fac93e28SPetar Jovanovic                                                    MipsSubtarget &Subtarget,
937fac93e28SPetar Jovanovic                                                    MipsRegisterBankInfo &RBI) {
938fac93e28SPetar Jovanovic   return new MipsInstructionSelector(TM, Subtarget, RBI);
939fac93e28SPetar Jovanovic }
940fac93e28SPetar Jovanovic } // end namespace llvm
941