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))
362 .
add(
I.getOperand(0))
364 .
add(
I.getOperand(1));
371 "Non-power-of-two jump-table entry size not supported.");
373 Register JTIndex =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
376 .
addUse(
I.getOperand(2).getReg())
381 Register DestAddress =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
384 .
addUse(
I.getOperand(0).getReg())
389 Register Dest =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
401 Register DestTmp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
423 .
add(
I.getOperand(0));
427 const Register DestReg =
I.getOperand(0).getReg();
431 DefRC =
TRI.getRegClass(DestReg);
433 DefRC = getRegClassForTypeOnBank(DestReg,
MRI);
435 I.setDesc(
TII.get(TargetOpcode::PHI));
436 return RBI.constrainGenericRegister(DestReg, *DefRC,
MRI);
442 auto MMO = *
I.memoperands_begin();
444 int64_t SignedOffset = 0;
453 if (
Addr->getOpcode() == G_PTR_ADD) {
455 if (
Offset->getOpcode() == G_CONSTANT) {
456 APInt OffsetValue =
Offset->getOperand(1).getCImm()->getValue();
466 !STI.systemSupportsUnalignedAccess()) {
467 if (MMO->
getSize() != 4 || !isRegInGprb(
I.getOperand(0).getReg(),
MRI))
470 if (
I.getOpcode() == G_STORE) {
471 if (!buildUnalignedStore(
I, Mips::SWL, BaseAddr, SignedOffset + 3, MMO))
473 if (!buildUnalignedStore(
I, Mips::SWR, BaseAddr, SignedOffset, MMO))
479 if (
I.getOpcode() == G_LOAD) {
480 Register ImplDef =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
483 Register Tmp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
484 if (!buildUnalignedLoad(
I, Mips::LWL, Tmp, BaseAddr, SignedOffset + 3,
487 if (!buildUnalignedLoad(
I, Mips::LWR,
I.getOperand(0).getReg(),
488 BaseAddr, SignedOffset, Tmp, MMO))
497 const unsigned NewOpc = selectLoadStoreOpCode(
I,
MRI);
498 if (NewOpc ==
I.getOpcode())
502 .
add(
I.getOperand(0))
512 Register HILOReg =
MRI.createVirtualRegister(&Mips::ACC64RegClass);
513 bool IsSigned =
I.getOpcode() == G_SREM ||
I.getOpcode() == G_SDIV;
514 bool IsDiv =
I.getOpcode() == G_UDIV ||
I.getOpcode() == G_SDIV;
518 TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
520 .
add(
I.getOperand(1))
521 .
add(
I.getOperand(2));
526 TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
527 .
addDef(
I.getOperand(0).getReg())
538 .
add(
I.getOperand(0))
539 .
add(
I.getOperand(2))
540 .
add(
I.getOperand(1))
541 .
add(
I.getOperand(3));
544 case G_UNMERGE_VALUES: {
545 if (
I.getNumOperands() != 3)
550 if (!isRegInFprb(Src,
MRI) ||
551 !(isRegInGprb(
Lo,
MRI) && isRegInGprb(
Hi,
MRI)))
555 STI.isFP64bit() ? Mips::ExtractElementF64_64 : Mips::ExtractElementF64;
574 case G_IMPLICIT_DEF: {
580 MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst,
MRI));
585 if (!materialize32BitImm(
I.getOperand(0).getReg(),
586 I.getOperand(1).getCImm()->getValue(),
B))
593 const APFloat &FPimm =
I.getOperand(1).getFPImm()->getValueAPF();
595 unsigned Size =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
598 Register GPRReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
600 if (!materialize32BitImm(GPRReg, APImm,
B))
604 B.buildInstr(Mips::MTC1, {
I.getOperand(0).
getReg()}, {GPRReg});
609 Register GPRRegHigh =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
610 Register GPRRegLow =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
612 if (!materialize32BitImm(GPRRegHigh, APImm.
getHiBits(32).
trunc(32),
B))
618 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
619 {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
628 unsigned Size =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
629 unsigned FABSOpcode =
630 Size == 32 ? Mips::FABS_S
631 : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
633 .
add(
I.getOperand(0))
634 .
add(
I.getOperand(1));
638 unsigned FromSize =
MRI.getType(
I.getOperand(1).getReg()).getSizeInBits();
639 unsigned ToSize =
MRI.getType(
I.getOperand(0).getReg()).getSizeInBits();
641 assert((ToSize == 32) &&
"Unsupported integer size for G_FPTOSI");
642 assert((FromSize == 32 || FromSize == 64) &&
643 "Unsupported floating point size for G_FPTOSI");
649 Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
650 Register ResultInFPR =
MRI.createVirtualRegister(&Mips::FGR32RegClass);
653 .
addUse(
I.getOperand(1).getReg());
658 .
addDef(
I.getOperand(0).getReg())
666 case G_GLOBAL_VALUE: {
670 .
addDef(
I.getOperand(0).getReg())
689 Register LWGOTDef =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
694 .
addDef(
I.getOperand(0).getReg())
702 Register LUiReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
713 .
addDef(
I.getOperand(0).getReg())
726 .
addDef(
I.getOperand(0).getReg())
736 .
addDef(
I.getOperand(0).getReg())
756 Register ICMPReg =
I.getOperand(0).getReg();
757 Register Temp =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
766 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
770 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
773 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
777 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
780 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
784 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
787 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
791 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
794 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
798 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
805 for (
const struct Instr &
Instruction : Instructions) {
807 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
822 unsigned MipsFCMPCondCode;
823 bool isLogicallyNegated;
825 I.getOperand(1).getPredicate())) {
869 unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
871 Register TrueInReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
877 unsigned Size =
MRI.getType(
I.getOperand(2).getReg()).getSizeInBits();
878 unsigned FCMPOpcode =
879 Size == 32 ? Mips::FCMP_S32
880 : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
882 .
addUse(
I.getOperand(2).getReg())
883 .
addUse(
I.getOperand(3).getReg())
884 .
addImm(MipsFCMPCondCode);
889 .
addDef(
I.getOperand(0).getReg())
907 Register LeaReg =
MRI.createVirtualRegister(&Mips::GPR32RegClass);
918 .
addUse(
I.getOperand(0).getReg())
938 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
static constexpr uint32_t Opcode
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.