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;
getName()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
MipsInstructionSelector(const MipsTargetMachine & TM,const MipsSubtarget & STI,const MipsRegisterBankInfo & RBI)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
isRegInGprb(Register Reg,MachineRegisterInfo & MRI) const95480093f4SDimitry 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
isRegInFprb(Register Reg,MachineRegisterInfo & MRI) const100480093f4SDimitry 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
selectCopy(MachineInstr & I,MachineRegisterInfo & MRI) const1050b57cec5SDimitry 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
getRegClassForTypeOnBank(Register Reg,MachineRegisterInfo & MRI) const1200b57cec5SDimitry 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
materialize32BitImm(Register DestReg,APInt Imm,MachineIRBuilder & B) const1440b57cec5SDimitry 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
selectLoadStoreOpCode(MachineInstr & I,MachineRegisterInfo & MRI) const1828bcb0991SDimitry 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
buildUnalignedStore(MachineInstr & I,unsigned Opc,MachineOperand & BaseAddr,unsigned Offset,MachineMemOperand * MMO) const2585ffd83dbSDimitry 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
buildUnalignedLoad(MachineInstr & I,unsigned Opc,Register Dest,MachineOperand & BaseAddr,unsigned Offset,Register TiedDest,MachineMemOperand * MMO) const2725ffd83dbSDimitry 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
select(MachineInstr & I)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 *
createMipsInstructionSelector(const MipsTargetMachine & TM,const MipsSubtarget & Subtarget,const MipsRegisterBankInfo & RBI)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