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 =
188 (*
I.memoperands_begin())->
getSize().getValue();
189 unsigned Opc =
I.getOpcode();
190 const bool isStore = Opc == TargetOpcode::G_STORE;
192 if (isRegInGprb(ValueReg,
MRI)) {
194 (Ty.
isPointer() && TySize == 32 && MemSizeInBytes == 4)) &&
195 "Unsupported register bank, LLT, MemSizeInBytes combination");
198 switch (MemSizeInBytes) {
210 switch (MemSizeInBytes) {
214 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
216 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
222 if (isRegInFprb(ValueReg,
MRI)) {
224 assert(((TySize == 32 && MemSizeInBytes == 4) ||
225 (TySize == 64 && MemSizeInBytes == 8)) &&
226 "Unsupported register bank, LLT, MemSizeInBytes combination");
228 if (MemSizeInBytes == 4)
229 return isStore ? Mips::SWC1 : Mips::LWC1;
232 return isStore ? Mips::SDC164 : Mips::LDC164;
233 return isStore ? Mips::SDC1 : Mips::LDC1;
237 assert(STI.hasMSA() &&
"Vector instructions require target with MSA.");
238 assert((TySize == 128 && MemSizeInBytes == 16) &&
239 "Unsupported register bank, LLT, MemSizeInBytes combination");
242 return isStore ? Mips::ST_B : Mips::LD_B;
244 return isStore ? Mips::ST_H : Mips::LD_H;
246 return isStore ? Mips::ST_W : Mips::LD_W;
248 return isStore ? Mips::ST_D : Mips::LD_D;
258bool MipsInstructionSelector::buildUnalignedStore(
263 .
add(
I.getOperand(0))
272bool MipsInstructionSelector::buildUnalignedLoad(
300 if (
I.getOpcode() == Mips::G_MUL &&
301 isRegInGprb(
I.getOperand(0).getReg(),
MRI)) {
303 .
add(
I.getOperand(0))
304 .
add(
I.getOperand(1))
305 .
add(
I.getOperand(2));
315 if (selectImpl(
I, *CoverageInfo))
319 using namespace TargetOpcode;
321 switch (
I.getOpcode()) {
323 Register PseudoMULTuReg =
MRI.createVirtualRegister(&Mips::ACC64RegClass);
326 PseudoMULTu =
BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(Mips::PseudoMULTu))
328 .
add(
I.getOperand(1))
329 .
add(
I.getOperand(2));
333 PseudoMove =
BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(Mips::PseudoMFHI))
334 .
addDef(
I.getOperand(0).getReg())
344 .
add(
I.getOperand(0))
345 .
add(
I.getOperand(1))
346 .
add(
I.getOperand(2));
351 I.setDesc(
TII.get(COPY));
354 case G_FRAME_INDEX: {
356 .
add(
I.getOperand(0))
357 .
add(
I.getOperand(1))
365 "Non-power-of-two jump-table entry size not supported.");
367 Register JTIndex =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
370 .
addUse(
I.getOperand(2).getReg())
375 Register DestAddress =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
378 .
addUse(
I.getOperand(0).getReg())
383 Register Dest =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
395 Register DestTmp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
417 .
add(
I.getOperand(0));
421 const Register DestReg =
I.getOperand(0).getReg();
425 DefRC =
TRI.getRegClass(DestReg);
427 DefRC = getRegClassForTypeOnBank(DestReg,
MRI);
429 I.setDesc(
TII.get(TargetOpcode::PHI));
430 return RBI.constrainGenericRegister(DestReg, *DefRC,
MRI);
436 auto MMO = *
I.memoperands_begin();
438 int64_t SignedOffset = 0;
447 if (
Addr->getOpcode() == G_PTR_ADD) {
449 if (
Offset->getOpcode() == G_CONSTANT) {
450 APInt OffsetValue =
Offset->getOperand(1).getCImm()->getValue();
461 !STI.systemSupportsUnalignedAccess()) {
462 if (MMO->
getSize() != 4 || !isRegInGprb(
I.getOperand(0).getReg(),
MRI))
465 if (
I.getOpcode() == G_STORE) {
466 if (!buildUnalignedStore(
I, Mips::SWL, BaseAddr, SignedOffset + 3, MMO))
468 if (!buildUnalignedStore(
I, Mips::SWR, BaseAddr, SignedOffset, MMO))
474 if (
I.getOpcode() == G_LOAD) {
475 Register ImplDef =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
478 Register Tmp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
479 if (!buildUnalignedLoad(
I, Mips::LWL, Tmp, BaseAddr, SignedOffset + 3,
482 if (!buildUnalignedLoad(
I, Mips::LWR,
I.getOperand(0).getReg(),
483 BaseAddr, SignedOffset, Tmp, MMO))
492 const unsigned NewOpc = selectLoadStoreOpCode(
I,
MRI);
493 if (NewOpc ==
I.getOpcode())
497 .
add(
I.getOperand(0))
507 Register HILOReg =
MRI.createVirtualRegister(&Mips::ACC64RegClass);
508 bool IsSigned =
I.getOpcode() == G_SREM ||
I.getOpcode() == G_SDIV;
509 bool IsDiv =
I.getOpcode() == G_UDIV ||
I.getOpcode() == G_SDIV;
513 TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
515 .
add(
I.getOperand(1))
516 .
add(
I.getOperand(2));
521 TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
522 .
addDef(
I.getOperand(0).getReg())
533 .
add(
I.getOperand(0))
534 .
add(
I.getOperand(2))
535 .
add(
I.getOperand(1))
536 .
add(
I.getOperand(3));
539 case G_UNMERGE_VALUES: {
540 if (
I.getNumOperands() != 3)
545 if (!isRegInFprb(Src,
MRI) ||
546 !(isRegInGprb(
Lo,
MRI) && isRegInGprb(
Hi,
MRI)))
550 STI.isFP64bit() ? Mips::ExtractElementF64_64 : Mips::ExtractElementF64;
569 case G_IMPLICIT_DEF: {
575 MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst,
MRI));
580 if (!materialize32BitImm(
I.getOperand(0).getReg(),
581 I.getOperand(1).getCImm()->getValue(),
B))
588 const APFloat &FPimm =
I.getOperand(1).getFPImm()->getValueAPF();
590 unsigned Size =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
593 Register GPRReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
595 if (!materialize32BitImm(GPRReg, APImm,
B))
599 B.buildInstr(Mips::MTC1, {
I.getOperand(0).
getReg()}, {GPRReg});
604 Register GPRRegHigh =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
605 Register GPRRegLow =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
607 if (!materialize32BitImm(GPRRegHigh, APImm.
getHiBits(32).
trunc(32),
B))
613 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
614 {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
623 unsigned Size =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
624 unsigned FABSOpcode =
625 Size == 32 ? Mips::FABS_S
626 : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
628 .
add(
I.getOperand(0))
629 .
add(
I.getOperand(1));
633 unsigned FromSize =
MRI.getType(
I.getOperand(1).getReg()).getSizeInBits();
634 unsigned ToSize =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
636 assert((ToSize == 32) &&
"Unsupported integer size for G_FPTOSI");
637 assert((FromSize == 32 || FromSize == 64) &&
638 "Unsupported floating point size for G_FPTOSI");
642 Opcode = Mips::TRUNC_W_S;
644 Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
645 Register ResultInFPR =
MRI.createVirtualRegister(&Mips::FGR32RegClass);
648 .
addUse(
I.getOperand(1).getReg());
653 .
addDef(
I.getOperand(0).getReg())
661 case G_GLOBAL_VALUE: {
665 .
addDef(
I.getOperand(0).getReg())
684 Register LWGOTDef =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
689 .
addDef(
I.getOperand(0).getReg())
697 Register LUiReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
708 .
addDef(
I.getOperand(0).getReg())
721 .
addDef(
I.getOperand(0).getReg())
731 .
addDef(
I.getOperand(0).getReg())
744 if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
751 Register ICMPReg =
I.getOperand(0).getReg();
752 Register Temp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
761 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
765 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
768 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
772 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
775 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
779 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
782 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
786 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
789 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
793 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
800 for (
const struct Instr &
Instruction : Instructions) {
802 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
817 unsigned MipsFCMPCondCode;
818 bool isLogicallyNegated;
820 I.getOperand(1).getPredicate())) {
864 unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
866 Register TrueInReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
872 unsigned Size =
MRI.getType(
I.getOperand(2).getReg()).getSizeInBits();
873 unsigned FCMPOpcode =
874 Size == 32 ? Mips::FCMP_S32
875 : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
877 .
addUse(
I.getOperand(2).getReg())
878 .
addUse(
I.getOperand(3).getReg())
879 .
addImm(MipsFCMPCondCode);
884 .
addDef(
I.getOperand(0).getReg())
902 Register LeaReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
913 .
addUse(
I.getOperand(0).getReg())
934 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.
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.
TypeSize getValue() const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, 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.
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.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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.
LocationSize 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.
InstructionSelector * createMipsInstructionSelector(const MipsTargetMachine &, const MipsSubtarget &, const MipsRegisterBankInfo &)
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.
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.