21#include "llvm/IR/IntrinsicsMips.h"
23#define DEBUG_TYPE "mips-isel"
29#define GET_GLOBALISEL_PREDICATE_BITSET
30#include "MipsGenGlobalISel.inc"
31#undef GET_GLOBALISEL_PREDICATE_BITSET
65#define GET_GLOBALISEL_PREDICATES_DECL
66#include "MipsGenGlobalISel.inc"
67#undef GET_GLOBALISEL_PREDICATES_DECL
69#define GET_GLOBALISEL_TEMPORARIES_DECL
70#include "MipsGenGlobalISel.inc"
71#undef GET_GLOBALISEL_TEMPORARIES_DECL
76#define GET_GLOBALISEL_IMPL
77#include "MipsGenGlobalISel.inc"
78#undef GET_GLOBALISEL_IMPL
80MipsInstructionSelector::MipsInstructionSelector(
83 :
TM(
TM), STI(STI),
TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()),
87#include
"MipsGenGlobalISel.inc"
90#include
"MipsGenGlobalISel.inc"
95bool MipsInstructionSelector::isRegInGprb(
Register Reg,
97 return RBI.getRegBank(Reg,
MRI,
TRI)->getID() == Mips::GPRBRegBankID;
100bool MipsInstructionSelector::isRegInFprb(
Register Reg,
102 return RBI.getRegBank(Reg,
MRI,
TRI)->getID() == Mips::FPRBRegBankID;
107 Register DstReg =
I.getOperand(0).getReg();
112 if (!RBI.constrainGenericRegister(DstReg, *RC,
MRI)) {
122 const LLT Ty =
MRI.getType(Reg);
125 if (isRegInGprb(Reg,
MRI)) {
127 "Register class not available for LLT, register bank combination");
128 return &Mips::GPR32RegClass;
131 if (isRegInFprb(Reg,
MRI)) {
133 assert((TySize == 32 || TySize == 64) &&
134 "Register class not available for LLT, register bank combination");
136 return &Mips::FGR32RegClass;
137 return STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
144bool MipsInstructionSelector::materialize32BitImm(
Register DestReg,
APInt Imm,
146 assert(
Imm.getBitWidth() == 32 &&
"Unsupported immediate size.");
148 if (
Imm.getHiBits(16).isZero()) {
150 B.buildInstr(Mips::ORi, {DestReg}, {
Register(Mips::ZERO)})
151 .addImm(
Imm.getLoBits(16).getLimitedValue());
155 if (
Imm.getLoBits(16).isZero()) {
157 .addImm(
Imm.getHiBits(16).getLimitedValue());
161 if (
Imm.isSignedIntN(16)) {
163 B.buildInstr(Mips::ADDiu, {DestReg}, {
Register(Mips::ZERO)})
164 .addImm(
Imm.getLoBits(16).getLimitedValue());
168 Register LUiReg =
B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
170 .addImm(
Imm.getHiBits(16).getLimitedValue());
171 MachineInstr *ORi =
B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
172 .addImm(
Imm.getLoBits(16).getLimitedValue());
182MipsInstructionSelector::selectLoadStoreOpCode(
MachineInstr &
I,
184 const Register ValueReg =
I.getOperand(0).getReg();
185 const LLT Ty =
MRI.getType(ValueReg);
187 const unsigned MemSizeInBytes = (*
I.memoperands_begin())->
getSize();
188 unsigned Opc =
I.getOpcode();
189 const bool isStore = Opc == TargetOpcode::G_STORE;
191 if (isRegInGprb(ValueReg,
MRI)) {
193 (Ty.
isPointer() && TySize == 32 && MemSizeInBytes == 4)) &&
194 "Unsupported register bank, LLT, MemSizeInBytes combination");
197 switch (MemSizeInBytes) {
209 switch (MemSizeInBytes) {
213 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
215 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
221 if (isRegInFprb(ValueReg,
MRI)) {
223 assert(((TySize == 32 && MemSizeInBytes == 4) ||
224 (TySize == 64 && MemSizeInBytes == 8)) &&
225 "Unsupported register bank, LLT, MemSizeInBytes combination");
227 if (MemSizeInBytes == 4)
228 return isStore ? Mips::SWC1 : Mips::LWC1;
231 return isStore ? Mips::SDC164 : Mips::LDC164;
232 return isStore ? Mips::SDC1 : Mips::LDC1;
236 assert(STI.hasMSA() &&
"Vector instructions require target with MSA.");
237 assert((TySize == 128 && MemSizeInBytes == 16) &&
238 "Unsupported register bank, LLT, MemSizeInBytes combination");
241 return isStore ? Mips::ST_B : Mips::LD_B;
243 return isStore ? Mips::ST_H : Mips::LD_H;
245 return isStore ? Mips::ST_W : Mips::LD_W;
247 return isStore ? Mips::ST_D : Mips::LD_D;
257bool MipsInstructionSelector::buildUnalignedStore(
262 .
add(
I.getOperand(0))
271bool MipsInstructionSelector::buildUnalignedLoad(
299 if (
I.getOpcode() == Mips::G_MUL &&
300 isRegInGprb(
I.getOperand(0).getReg(),
MRI)) {
302 .
add(
I.getOperand(0))
303 .
add(
I.getOperand(1))
304 .
add(
I.getOperand(2));
314 if (selectImpl(
I, *CoverageInfo))
318 using namespace TargetOpcode;
320 switch (
I.getOpcode()) {
322 Register PseudoMULTuReg =
MRI.createVirtualRegister(&Mips::ACC64RegClass);
325 PseudoMULTu =
BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(Mips::PseudoMULTu))
327 .
add(
I.getOperand(1))
328 .
add(
I.getOperand(2));
332 PseudoMove =
BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(Mips::PseudoMFHI))
333 .
addDef(
I.getOperand(0).getReg())
343 .
add(
I.getOperand(0))
344 .
add(
I.getOperand(1))
345 .
add(
I.getOperand(2));
350 I.setDesc(
TII.get(COPY));
353 case G_FRAME_INDEX: {
355 .
add(
I.getOperand(0))
356 .
add(
I.getOperand(1))
364 "Non-power-of-two jump-table entry size not supported.");
366 Register JTIndex =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
369 .
addUse(
I.getOperand(2).getReg())
374 Register DestAddress =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
377 .
addUse(
I.getOperand(0).getReg())
382 Register Dest =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
394 Register DestTmp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
416 .
add(
I.getOperand(0));
420 const Register DestReg =
I.getOperand(0).getReg();
424 DefRC =
TRI.getRegClass(DestReg);
426 DefRC = getRegClassForTypeOnBank(DestReg,
MRI);
428 I.setDesc(
TII.get(TargetOpcode::PHI));
429 return RBI.constrainGenericRegister(DestReg, *DefRC,
MRI);
435 auto MMO = *
I.memoperands_begin();
437 int64_t SignedOffset = 0;
446 if (
Addr->getOpcode() == G_PTR_ADD) {
448 if (
Offset->getOpcode() == G_CONSTANT) {
449 APInt OffsetValue =
Offset->getOperand(1).getCImm()->getValue();
459 !STI.systemSupportsUnalignedAccess()) {
460 if (MMO->
getSize() != 4 || !isRegInGprb(
I.getOperand(0).getReg(),
MRI))
463 if (
I.getOpcode() == G_STORE) {
464 if (!buildUnalignedStore(
I, Mips::SWL, BaseAddr, SignedOffset + 3, MMO))
466 if (!buildUnalignedStore(
I, Mips::SWR, BaseAddr, SignedOffset, MMO))
472 if (
I.getOpcode() == G_LOAD) {
473 Register ImplDef =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
476 Register Tmp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
477 if (!buildUnalignedLoad(
I, Mips::LWL, Tmp, BaseAddr, SignedOffset + 3,
480 if (!buildUnalignedLoad(
I, Mips::LWR,
I.getOperand(0).getReg(),
481 BaseAddr, SignedOffset, Tmp, MMO))
490 const unsigned NewOpc = selectLoadStoreOpCode(
I,
MRI);
491 if (NewOpc ==
I.getOpcode())
495 .
add(
I.getOperand(0))
505 Register HILOReg =
MRI.createVirtualRegister(&Mips::ACC64RegClass);
506 bool IsSigned =
I.getOpcode() == G_SREM ||
I.getOpcode() == G_SDIV;
507 bool IsDiv =
I.getOpcode() == G_UDIV ||
I.getOpcode() == G_SDIV;
511 TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
513 .
add(
I.getOperand(1))
514 .
add(
I.getOperand(2));
519 TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
520 .
addDef(
I.getOperand(0).getReg())
531 .
add(
I.getOperand(0))
532 .
add(
I.getOperand(2))
533 .
add(
I.getOperand(1))
534 .
add(
I.getOperand(3));
537 case G_UNMERGE_VALUES: {
538 if (
I.getNumOperands() != 3)
543 if (!isRegInFprb(Src,
MRI) ||
544 !(isRegInGprb(
Lo,
MRI) && isRegInGprb(
Hi,
MRI)))
548 STI.isFP64bit() ? Mips::ExtractElementF64_64 : Mips::ExtractElementF64;
567 case G_IMPLICIT_DEF: {
573 MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst,
MRI));
578 if (!materialize32BitImm(
I.getOperand(0).getReg(),
579 I.getOperand(1).getCImm()->getValue(),
B))
586 const APFloat &FPimm =
I.getOperand(1).getFPImm()->getValueAPF();
588 unsigned Size =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
591 Register GPRReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
593 if (!materialize32BitImm(GPRReg, APImm,
B))
597 B.buildInstr(Mips::MTC1, {
I.getOperand(0).
getReg()}, {GPRReg});
602 Register GPRRegHigh =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
603 Register GPRRegLow =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
605 if (!materialize32BitImm(GPRRegHigh, APImm.
getHiBits(32).
trunc(32),
B))
611 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
612 {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
621 unsigned Size =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
622 unsigned FABSOpcode =
623 Size == 32 ? Mips::FABS_S
624 : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
626 .
add(
I.getOperand(0))
627 .
add(
I.getOperand(1));
631 unsigned FromSize =
MRI.getType(
I.getOperand(1).getReg()).getSizeInBits();
632 unsigned ToSize =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
634 assert((ToSize == 32) &&
"Unsupported integer size for G_FPTOSI");
635 assert((FromSize == 32 || FromSize == 64) &&
636 "Unsupported floating point size for G_FPTOSI");
640 Opcode = Mips::TRUNC_W_S;
642 Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
643 Register ResultInFPR =
MRI.createVirtualRegister(&Mips::FGR32RegClass);
646 .
addUse(
I.getOperand(1).getReg());
651 .
addDef(
I.getOperand(0).getReg())
659 case G_GLOBAL_VALUE: {
663 .
addDef(
I.getOperand(0).getReg())
682 Register LWGOTDef =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
687 .
addDef(
I.getOperand(0).getReg())
695 Register LUiReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
706 .
addDef(
I.getOperand(0).getReg())
719 .
addDef(
I.getOperand(0).getReg())
729 .
addDef(
I.getOperand(0).getReg())
742 if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
749 Register ICMPReg =
I.getOperand(0).getReg();
750 Register Temp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
759 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
763 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
766 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
770 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
773 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
777 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
780 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
784 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
787 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
791 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
798 for (
const struct Instr &
Instruction : Instructions) {
800 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
815 unsigned MipsFCMPCondCode;
816 bool isLogicallyNegated;
818 I.getOperand(1).getPredicate())) {
862 unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
864 Register TrueInReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
870 unsigned Size =
MRI.getType(
I.getOperand(2).getReg()).getSizeInBits();
871 unsigned FCMPOpcode =
872 Size == 32 ? Mips::FCMP_S32
873 : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
875 .
addUse(
I.getOperand(2).getReg())
876 .
addUse(
I.getOperand(3).getReg())
877 .
addImm(MipsFCMPCondCode);
882 .
addDef(
I.getOperand(0).getReg())
900 Register LeaReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
911 .
addUse(
I.getOperand(0).getReg())
931 return new MipsInstructionSelector(
TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool isStore(int Opcode)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
This file declares the targeting of the RegisterBankInfo class for Mips.
const char LLVMTargetMachineRef TM
static StringRef getName(Value *V)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getSize(unsigned Kind)
support::ulittle16_t & Lo
support::ulittle16_t & Hi
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
APInt getHiBits(unsigned numBits) const
Compute an APInt containing numBits highbits from this APInt.
APInt trunc(unsigned width) const
Truncate to new width.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
int64_t getSExtValue() const
Get sign extended value.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
bool hasLocalLinkage() const
virtual bool select(MachineInstr &I)=0
Select the (possibly generic) instruction I to only use target-specific opcodes.
constexpr bool isScalar() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
Helper class to build MachineInstr.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
unsigned getEntrySize(const DataLayout &TD) const
getEntrySize - Return the size of each entry in the jump table.
A description of a memory reference used in the backend.
uint64_t getSize() const
Return the size in bytes of the memory reference.
@ MOLoad
The memory access reads data.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
void setTargetFlags(unsigned F)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
Register getGlobalBaseRegForGlobalISel(MachineFunction &MF)
int getVarArgsFrameIndex() const
This class provides the information for the target register banks.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool isPositionIndependent() const
Value * getOperand(unsigned i) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_GOT_CALL
MO_GOT_CALL - Represents the offset into the global offset table at which the address of a call site ...
@ MO_GOT
MO_GOT - Represents the offset into the global offset table at which the address the relocation entry...
@ MO_ABS_HI
MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol address.
bool hasImm(uint64_t TSFlags)
NodeAddr< InstrNode * > Instr
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
InstructionSelector * createMipsInstructionSelector(const MipsTargetMachine &, MipsSubtarget &, MipsRegisterBankInfo &)
This struct is a compact representation of a valid (non-zero power of two) alignment.
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.