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