27#define GET_INSTRINFO_CTOR_DTOR
28#include "SparcGenInstrInfo.inc"
31void SparcInstrInfo::anchor() {}
35 RI(ST), Subtarget(ST) {}
39 return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
50 switch (
MI.getOpcode()) {
69 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
70 MI.getOperand(2).getImm() == 0) {
71 FrameIndex =
MI.getOperand(1).getIndex();
72 return MI.getOperand(0).getReg();
85 switch (
MI.getOpcode()) {
104 if (
MI.getOperand(0).isFI() &&
MI.getOperand(1).isImm() &&
105 MI.getOperand(1).getImm() == 0) {
106 FrameIndex =
MI.getOperand(0).getIndex();
107 return MI.getOperand(2).getReg();
192 return Opc == SP::BCOND ||
Opc == SP::BPICC ||
Opc == SP::BPICCA ||
193 Opc == SP::BPICCNT ||
Opc == SP::BPICCANT;
197 return Opc == SP::BPXCC ||
Opc == SP::BPXCCA ||
Opc == SP::BPXCCNT ||
202 return Opc == SP::BPR ||
Opc == SP::BPRA ||
Opc == SP::BPRNT ||
207 return Opc == SP::FBCOND ||
Opc == SP::FBCONDA ||
Opc == SP::FBCOND_V9 ||
208 Opc == SP::FBCONDA_V9;
217 return Opc == SP::BINDrr ||
Opc == SP::BINDri;
240 switch (
MI.getOpcode()) {
266 case SP::CALL_LONGJUMP:
267 return MI.getOperand(0).getMBB();
275 bool AllowModify)
const {
280 if (!isUnpredicatedTerminator(*
I))
285 unsigned LastOpc = LastInst->
getOpcode();
288 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
303 unsigned SecondLastOpc = SecondLastInst->
getOpcode();
310 LastInst = SecondLastInst;
312 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
317 SecondLastInst = &*
I;
318 SecondLastOpc = SecondLastInst->
getOpcode();
324 if (SecondLastInst &&
I !=
MBB.begin() && isUnpredicatedTerminator(*--
I))
346 I->eraseFromParent();
359 int *BytesAdded)
const {
360 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
362 "Sparc branch conditions should have at most three components!");
365 assert(!FBB &&
"Unconditional branch with multiple successors!");
373 unsigned Opc =
Cond[0].getImm();
374 unsigned CC =
Cond[1].getImm();
398 assert(RS &&
"RegScavenger required for long branching");
400 "new block should be inserted for expanding unconditional branch");
401 assert(
MBB.pred_size() == 1 &&
"should only have a single predecessor");
403 "restore block should be inserted for restoring clobbered registers");
410 "Branch offsets outside of the signed 32-bit range not supported");
411 RS->enterBasicBlockEnd(
MBB);
420 bool IsO7Used = RS->isRegUsed(SP::O7);
421 Register ScratchReg = RS->FindUnusedReg(&SP::IntRegsRegClass);
428 RS->setRegUsed(ScratchReg);
434 Subtarget.is64Bit() ? SP::I64RegsRegClass : SP::IntRegsRegClass;
438 TRI.eliminateFrameIndex(std::prev(
I), 0, 0, RS);
443 .
addMBB(IsO7Used ? &RestoreBB : &NewDestBB);
452 Subtarget.is64Bit() ? SP::I64RegsRegClass : SP::IntRegsRegClass;
456 TRI.eliminateFrameIndex(std::prev(
I), 0, 1, RS);
462 int *BytesRemoved)
const {
466 while (
I !=
MBB.begin()) {
469 if (
I->isDebugInstr())
477 I->eraseFromParent();
483 *BytesRemoved = Removed;
497 assert((
Offset & 0b11) == 0 &&
"Malformed branch offset");
499 case SP::CALL_LONGJUMP:
523 return isIntN(Subtarget.getCLOpts().bpcc_offset_bits,
Offset >> 2);
529 return isIntN(Subtarget.getCLOpts().bpr_offset_bits,
Offset >> 2);
539 bool RenamableDest,
bool RenamableSrc)
const {
540 unsigned numSubRegs = 0;
542 const unsigned *subRegIdx =
nullptr;
543 bool ExtraG0 =
false;
545 const unsigned DW_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
546 const unsigned DFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
547 const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };
548 const unsigned QFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd,
549 SP::sub_odd64_then_sub_even,
550 SP::sub_odd64_then_sub_odd };
552 if (SP::IntRegsRegClass.
contains(DestReg, SrcReg))
555 else if (SP::IntPairRegClass.
contains(DestReg, SrcReg)) {
556 subRegIdx = DW_SubRegsIdx;
560 }
else if (SP::FPRegsRegClass.
contains(DestReg, SrcReg))
563 else if (SP::DFPRegsRegClass.
contains(DestReg, SrcReg)) {
564 if (Subtarget.isV9()) {
569 subRegIdx = DFP_FP_SubRegsIdx;
573 }
else if (SP::QFPRegsRegClass.
contains(DestReg, SrcReg)) {
574 if (Subtarget.isV9()) {
575 if (Subtarget.hasHardQuad()) {
580 subRegIdx = QFP_DFP_SubRegsIdx;
586 subRegIdx = QFP_FP_SubRegsIdx;
590 }
else if (SP::ASRRegsRegClass.
contains(DestReg) &&
591 SP::IntRegsRegClass.
contains(SrcReg)) {
595 }
else if (SP::IntRegsRegClass.
contains(DestReg) &&
596 SP::ASRRegsRegClass.
contains(SrcReg)) {
602 if (numSubRegs == 0 || subRegIdx ==
nullptr || movOpc == 0)
608 for (
unsigned i = 0; i != numSubRegs; ++i) {
609 Register Dst =
TRI->getSubReg(DestReg, subRegIdx[i]);
610 Register Src =
TRI->getSubReg(SrcReg, subRegIdx[i]);
611 assert(Dst && Src &&
"Bad sub-register");
627 Register SrcReg,
bool isKill,
int FI,
632 if (
I !=
MBB.end())
DL =
I->getDebugLoc();
641 if (RC == &SP::I64RegsRegClass)
644 else if (RC == &SP::IntRegsRegClass)
647 else if (RC == &SP::IntPairRegClass)
650 else if (RC == &SP::FPRegsRegClass)
653 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
656 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
672 if (
I !=
MBB.end())
DL =
I->getDebugLoc();
680 if (RC == &SP::I64RegsRegClass)
683 else if (RC == &SP::IntRegsRegClass)
686 else if (RC == &SP::IntPairRegClass)
689 else if (RC == &SP::FPRegsRegClass)
692 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
695 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
708 return GlobalBaseReg;
716 Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
717 GlobalBaseReg = RegInfo.createVirtualRegister(PtrRC);
724 return GlobalBaseReg;
728 unsigned &StructSize)
const {
732 unsigned StructSizeOpNum = 0;
733 switch (
MI.getOpcode()) {
745 case SP::TAIL_CALLri:
758 return StructSize != 0;
762 unsigned Opcode =
MI.getOpcode();
764 if (
MI.isInlineAsm()) {
766 const char *AsmStr =
MI.getOperand(0).getSymbolName();
770 if (Opcode == TargetOpcode::BUNDLE)
771 return getInstBundleSize(
MI);
773 if (
MI.getOpcode() == SP::GETPCX) {
792 if (
MI.hasDelaySlot()) {
793 unsigned StructSize = 0;
796 return get(Opcode).getSize();
800 Register &SrcReg2, int64_t &CmpMask,
801 int64_t &CmpValue)
const {
803 switch (
MI.getOpcode()) {
807 DstReg =
MI.getOperand(0).getReg();
808 SrcReg =
MI.getOperand(1).getReg();
811 CmpValue =
MI.getOperand(2).getImm();
812 return DstReg == SP::G0 && CmpValue == 0;
814 DstReg =
MI.getOperand(0).getReg();
815 SrcReg =
MI.getOperand(1).getReg();
816 SrcReg2 =
MI.getOperand(2).getReg();
819 return DstReg == SP::G0 && SrcReg2 == SP::G0;
839 switch (
MI->getOpcode()) {
841 NewOpcode = SP::ANDNCCrr;
844 NewOpcode = SP::ANDNCCri;
847 NewOpcode = SP::ANDCCrr;
850 NewOpcode = SP::ANDCCri;
853 NewOpcode = SP::ORCCrr;
856 NewOpcode = SP::ORCCri;
859 NewOpcode = SP::ORNCCrr;
862 NewOpcode = SP::ORNCCri;
865 NewOpcode = SP::XORCCrr;
868 NewOpcode = SP::XNORCCri;
871 NewOpcode = SP::XNORCCrr;
874 NewOpcode = SP::ADDCCrr;
877 NewOpcode = SP::ADDCCri;
880 NewOpcode = SP::SUBCCrr;
883 NewOpcode = SP::SUBCCri;
889 bool IsICCModified =
false;
897 if (
I->modifiesRegister(SP::ICC,
TRI) ||
I->readsRegister(SP::ICC,
TRI))
903 if (
I->readsRegister(SP::ICC,
TRI)) {
904 bool IsICCBranch =
I->getOpcode() == SP::BCOND ||
905 I->getOpcode() == SP::BPICC ||
906 I->getOpcode() == SP::BPXCC;
908 I->getOpcode() == SP::MOVICCrr ||
I->getOpcode() == SP::MOVICCri ||
909 I->getOpcode() == SP::MOVXCCrr ||
I->getOpcode() == SP::MOVXCCri;
910 bool IsICCConditional = IsICCBranch || IsICCMove;
911 if (!IsICCConditional ||
912 (
I->getOperand(IsICCBranch ? 1 : 3).getImm() !=
SPCC::ICC_E &&
913 I->getOperand(IsICCBranch ? 1 : 3).getImm() !=
SPCC::ICC_NE))
915 }
else if (
I->modifiesRegister(SP::ICC,
TRI)) {
916 IsICCModified =
true;
921 if (!IsICCModified) {
928 if (
MRI->hasOneNonDBGUse(SrcReg))
929 MI->getOperand(0).setReg(SP::G0);
931 MI->setDesc(
get(NewOpcode));
932 MI->addRegisterDefined(SP::ICC);
939 switch (
MI.getOpcode()) {
940 case TargetOpcode::LOAD_STACK_GUARD: {
941 assert(Subtarget.getTargetTriple().isOSLinux() &&
942 "Only Linux target is expected to contain LOAD_STACK_GUARD");
944 const int64_t
Offset = Subtarget.is64Bit() ? 0x28 : 0x14;
945 MI.setDesc(
get(Subtarget.is64Bit() ? SP::LDXri : SP::LDri));
952 assert(!Subtarget.isV9() &&
953 "V8BAR should not be emitted on V9 processors!");
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
Register const TargetRegisterInfo * TRI
Promote Memory to Register
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallVector class.
static bool isFCondBranchOpcode(int Opc)
static bool isRegCondBranchOpcode(int Opc)
static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
static bool isI32CondBranchOpcode(int Opc)
static bool isI64CondBranchOpcode(int Opc)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
MCRegisterClass - Base class of TargetRegisterClass.
Helper class for constructing bundles of MachineInstrs.
MachineInstrBundleIterator< MachineInstr > iterator
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.
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 MachineBasicBlock & front() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool needsUnimp(const MachineInstr &MI, unsigned &StructSize) const
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const override
isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot,...
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t Offset) const override
Determine if the branch target is in range.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Register getGlobalBaseReg(MachineFunction *MF) const
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const override
isStoreToStackSlot - If the specified machine instruction is a direct store to a stack slot,...
SparcInstrInfo(const SparcSubtarget &ST)
const SparcRegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
const TargetRegisterClass * getInlineAsmMemoryOperandRegClass(InlineAsm::ConstraintCode C) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
bool expandPostRAPseudo(MachineInstr &MI) const override
Register getGlobalBaseReg() const
int getBranchRelaxationSpillFrameIndex()
void setGlobalBaseReg(Register Reg)
Primary interface to the complete machine description for the target machine.
bool isPositionIndependent() const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
static bool isCondBranchOpcode(int Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Kill
The last use of a register.
constexpr RegState getKillRegState(bool B)
static bool isIndirectBranchOpcode(int Opc)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
static bool isUncondBranchOpcode(int Opc)
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
MCRegisterClass TargetRegisterClass
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.