25#define GET_INSTRINFO_CTOR_DTOR
26#include "LoongArchGenInstrInfo.inc"
30 LoongArch::ADJCALLSTACKUP),
45 bool RenamableSrc)
const {
46 if (LoongArch::GPRRegClass.
contains(DstReg, SrcReg)) {
54 if (LoongArch::LSX128RegClass.
contains(DstReg, SrcReg)) {
62 if (LoongArch::LASX256RegClass.
contains(DstReg, SrcReg)) {
70 if (LoongArch::CFRRegClass.
contains(DstReg) &&
71 LoongArch::GPRRegClass.
contains(SrcReg)) {
77 if (LoongArch::GPRRegClass.
contains(DstReg) &&
78 LoongArch::CFRRegClass.
contains(SrcReg)) {
84 if (LoongArch::CFRRegClass.
contains(DstReg, SrcReg)) {
92 if (LoongArch::FPR32RegClass.
contains(DstReg, SrcReg)) {
93 Opc = LoongArch::FMOV_S;
94 }
else if (LoongArch::FPR64RegClass.
contains(DstReg, SrcReg)) {
95 Opc = LoongArch::FMOV_D;
96 }
else if (LoongArch::GPRRegClass.
contains(DstReg) &&
97 LoongArch::FPR32RegClass.
contains(SrcReg)) {
99 Opc = LoongArch::MOVFR2GR_S;
100 }
else if (LoongArch::GPRRegClass.
contains(DstReg) &&
101 LoongArch::FPR64RegClass.
contains(SrcReg)) {
103 Opc = LoongArch::MOVFR2GR_D;
122 if (LoongArch::GPRRegClass.hasSubClassEq(RC))
123 Opcode =
TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
126 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
127 Opcode = LoongArch::FST_S;
128 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
129 Opcode = LoongArch::FST_D;
130 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
131 Opcode = LoongArch::VST;
132 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
133 Opcode = LoongArch::XVST;
134 else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
135 Opcode = LoongArch::PseudoST_CFR;
158 DL =
I->getDebugLoc();
161 if (LoongArch::GPRRegClass.hasSubClassEq(RC))
162 Opcode =
TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
165 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
166 Opcode = LoongArch::FLD_S;
167 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
168 Opcode = LoongArch::FLD_D;
169 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
170 Opcode = LoongArch::VLD;
171 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
172 Opcode = LoongArch::XVLD;
173 else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
174 Opcode = LoongArch::PseudoLD_CFR;
200 for (
auto &Inst : Seq) {
202 case LoongArch::LU12I_W:
207 case LoongArch::ADDI_W:
209 case LoongArch::LU32I_D:
210 case LoongArch::LU52I_D:
216 case LoongArch::BSTRINS_D:
225 assert(
false &&
"Unknown insn emitted by LoongArchMatInt");
234 unsigned Opcode =
MI.getOpcode();
236 if (Opcode == TargetOpcode::INLINEASM ||
237 Opcode == TargetOpcode::INLINEASM_BR) {
240 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(), *MAI);
243 unsigned NumBytes = 0;
249 switch (
Desc.getOpcode()) {
251 return Desc.getSize();
252 case TargetOpcode::STATEPOINT:
254 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
264 const unsigned Opcode =
MI.getOpcode();
268 case LoongArch::ADDI_D:
270 case LoongArch::XORI:
271 return (
MI.getOperand(1).isReg() &&
272 MI.getOperand(1).getReg() == LoongArch::R0) ||
273 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
275 return MI.isAsCheapAsAMove();
280 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
282 return MI.getOperand(
MI.getNumExplicitOperands() - 1).getMBB();
289 "Unknown conditional branch");
294 for (
int i = 0; i < NumOp - 1; i++)
302 bool AllowModify)
const {
308 if (
I ==
MBB.
end() || !isUnpredicatedTerminator(*
I))
314 int NumTerminators = 0;
315 for (
auto J =
I.getReverse(); J !=
MBB.
rend() && isUnpredicatedTerminator(*J);
318 if (J->getDesc().isUnconditionalBranch() ||
319 J->getDesc().isIndirectBranch()) {
326 if (AllowModify && FirstUncondOrIndirectBr !=
MBB.
end()) {
327 while (std::next(FirstUncondOrIndirectBr) !=
MBB.
end()) {
328 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
331 I = FirstUncondOrIndirectBr;
335 if (NumTerminators == 1 &&
I->getDesc().isUnconditionalBranch()) {
341 if (NumTerminators == 1 &&
I->getDesc().isConditionalBranch()) {
347 if (NumTerminators == 2 && std::prev(
I)->getDesc().isConditionalBranch() &&
348 I->getDesc().isUnconditionalBranch()) {
359 int64_t BrOffset)
const {
367 case LoongArch::BLTU:
368 case LoongArch::BGEU:
369 return isInt<18>(BrOffset);
370 case LoongArch::BEQZ:
371 case LoongArch::BNEZ:
372 case LoongArch::BCEQZ:
373 case LoongArch::BCNEZ:
374 return isInt<23>(BrOffset);
376 case LoongArch::PseudoBR:
377 return isInt<28>(BrOffset);
387 auto MII =
MI.getIterator();
419 switch (
MI.getOpcode()) {
420 case LoongArch::PCALAU12I: {
421 auto AddI = std::next(MII);
422 if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D)
424 auto Lu32I = std::next(AddI);
425 if (Lu32I == MIE || Lu32I->getOpcode() != LoongArch::LU32I_D)
427 auto MO0 =
MI.getOperand(1).getTargetFlags();
428 auto MO1 = AddI->getOperand(2).getTargetFlags();
429 auto MO2 = Lu32I->getOperand(2).getTargetFlags();
446 case LoongArch::LU52I_D: {
447 auto MO =
MI.getOperand(2).getTargetFlags();
458 if (
STI.hasFeature(LoongArch::FeatureRelax)) {
475 unsigned AddiOp =
STI.
is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
476 unsigned LdOp =
STI.
is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
477 switch (
MI.getOpcode()) {
478 case LoongArch::PCALAU12I: {
480 auto SecondOp = std::next(MII);
482 if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp)
484 auto Ld = std::next(SecondOp);
485 if (Ld == MIE || Ld->getOpcode() != LdOp)
493 if (SecondOp == MIE ||
494 (SecondOp->getOpcode() != AddiOp && SecondOp->getOpcode() != LdOp))
509 case LoongArch::ADDI_W:
510 case LoongArch::ADDI_D: {
516 case LoongArch::LD_W:
517 case LoongArch::LD_D: {
523 case LoongArch::PseudoDESC_CALL: {
538 int *BytesRemoved)
const {
545 if (!
I->getDesc().isBranch())
551 I->eraseFromParent();
558 if (!
I->getDesc().isConditionalBranch())
564 I->eraseFromParent();
577 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
579 "LoongArch branch conditions have at most two components!");
591 for (
unsigned i = 1; i <
Cond.size(); ++i)
614 assert(RS &&
"RegScavenger required for long branching");
616 "new block should be inserted for expanding unconditional branch");
625 if (!isInt<32>(BrOffset))
627 "Branch offsets outside of the signed 32-bit range not supported");
629 Register ScratchReg =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
647 LoongArch::GPRRegClass, PCALAU12I.
getIterator(),
false,
649 if (Scav != LoongArch::NoRegister)
654 Scav = LoongArch::R20;
656 if (FrameIndex == -1)
666 TRI->eliminateFrameIndex(RestoreBB.
back(),
669 MRI.replaceRegWith(ScratchReg, Scav);
678 return LoongArch::BNE;
680 return LoongArch::BEQ;
681 case LoongArch::BEQZ:
682 return LoongArch::BNEZ;
683 case LoongArch::BNEZ:
684 return LoongArch::BEQZ;
685 case LoongArch::BCEQZ:
686 return LoongArch::BCNEZ;
687 case LoongArch::BCNEZ:
688 return LoongArch::BCEQZ;
690 return LoongArch::BGE;
692 return LoongArch::BLT;
693 case LoongArch::BLTU:
694 return LoongArch::BGEU;
695 case LoongArch::BGEU:
696 return LoongArch::BLTU;
702 assert((
Cond.size() &&
Cond.size() <= 3) &&
"Invalid branch condition!");
707std::pair<unsigned, unsigned>
710 return std::make_pair(TF & Mask, TF & ~Mask);
715 using namespace LoongArchII;
717 static const std::pair<unsigned, const char *> TargetFlags[] = {
718 {MO_CALL,
"loongarch-call"},
719 {MO_CALL_PLT,
"loongarch-call-plt"},
720 {MO_PCREL_HI,
"loongarch-pcrel-hi"},
721 {MO_PCREL_LO,
"loongarch-pcrel-lo"},
722 {MO_PCREL64_LO,
"loongarch-pcrel64-lo"},
723 {MO_PCREL64_HI,
"loongarch-pcrel64-hi"},
724 {MO_GOT_PC_HI,
"loongarch-got-pc-hi"},
725 {MO_GOT_PC_LO,
"loongarch-got-pc-lo"},
726 {MO_GOT_PC64_LO,
"loongarch-got-pc64-lo"},
727 {MO_GOT_PC64_HI,
"loongarch-got-pc64-hi"},
728 {MO_LE_HI,
"loongarch-le-hi"},
729 {MO_LE_LO,
"loongarch-le-lo"},
730 {MO_LE64_LO,
"loongarch-le64-lo"},
731 {MO_LE64_HI,
"loongarch-le64-hi"},
732 {MO_IE_PC_HI,
"loongarch-ie-pc-hi"},
733 {MO_IE_PC_LO,
"loongarch-ie-pc-lo"},
734 {MO_IE_PC64_LO,
"loongarch-ie-pc64-lo"},
735 {MO_IE_PC64_HI,
"loongarch-ie-pc64-hi"},
736 {MO_LD_PC_HI,
"loongarch-ld-pc-hi"},
737 {MO_GD_PC_HI,
"loongarch-gd-pc-hi"},
738 {MO_CALL36,
"loongarch-call36"},
739 {MO_DESC_PC_HI,
"loongarch-desc-pc-hi"},
740 {MO_DESC_PC_LO,
"loongarch-desc-pc-lo"},
741 {MO_DESC64_PC_LO,
"loongarch-desc64-pc-lo"},
742 {MO_DESC64_PC_HI,
"loongarch-desc64-pc-hi"},
743 {MO_DESC_LD,
"loongarch-desc-ld"},
744 {MO_DESC_CALL,
"loongarch-desc-call"},
745 {MO_LE_HI_R,
"loongarch-le-hi-r"},
746 {MO_LE_ADD_R,
"loongarch-le-add-r"},
747 {MO_LE_LO_R,
"loongarch-le-lo-r"}};
753 using namespace LoongArchII;
754 static const std::pair<unsigned, const char *> TargetFlags[] = {
755 {MO_RELAX,
"loongarch-relax"}};
761 return MI.getOpcode() == LoongArch::ADDI_W &&
MI.getOperand(1).isReg() &&
762 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0;
unsigned const MachineRegisterInfo * MRI
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static unsigned getOppositeBranchOpc(unsigned Opcode)
unsigned const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< std::pair< unsigned, const char * > > getSerializableBitmaskMachineOperandTargetFlags() const override
const LoongArchSubtarget & STI
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool isAsCheapAsAMove(const MachineInstr &MI) const override
LoongArchInstrInfo(LoongArchSubtarget &STI)
MCInst getNop() const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, uint64_t Val, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &dl, int *BytesAdded=nullptr) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
int getBranchRelaxationSpillFrameIndex()
This class is intended to be used as a base class for asm properties and features specific to the tar...
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
bool isConditionalBranch() const
Return true if this is a branch which may fall through to the next instruction or may transfer contro...
Wrapper class representing physical registers. Should be passed by value.
unsigned pred_size() const
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineBasicBlock * getMBB() const
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
void enterBasicBlockEnd(MachineBasicBlock &MBB)
Start tracking liveness from the end of basic block MBB.
void setRegUsed(Register Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Tell the scavenger a register is used.
Register scavengeRegisterBackwards(const TargetRegisterClass &RC, MachineBasicBlock::iterator To, bool RestoreAfter, int SPAdj, bool AllowSpill=true)
Make a register of the specific register class available from the current position backwards to the p...
Wrapper class representing virtual and physical registers.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
MI-level Statepoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
Target - Wrapper for Target specific information.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getDirectFlags(const MachineOperand &MO)
InstSeq generateInstSeq(int64_t Val)
bool isSEXT_W(const MachineInstr &MI)
@ Kill
The last use of a register.
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.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
unsigned getKillRegState(bool B)
Description of the encoding of one expression Op.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.