27#define DEBUG_TYPE "delay-slot-filler"
29STATISTIC(FilledSlots,
"Number of delay slots filled");
32 "disable-sparc-delay-filler",
34 cl::desc(
"Disable the Sparc delay slot filler."),
44 StringRef getPassName()
const override {
return "SPARC Delay Slot Filler"; }
46 bool runOnMachineBasicBlock(MachineBasicBlock &
MBB);
47 bool runOnMachineFunction(MachineFunction &
F)
override {
49 Subtarget = &
F.getSubtarget<SparcSubtarget>();
53 F.getRegInfo().invalidateLiveness();
55 for (MachineBasicBlock &
MBB :
F)
60 MachineFunctionProperties getRequiredProperties()
const override {
61 return MachineFunctionProperties().setNoVRegs();
65 SmallSet<unsigned, 32>& RegDefs,
66 SmallSet<unsigned, 32>& RegUses);
69 SmallSet<unsigned, 32>& RegDefs,
70 SmallSet<unsigned, 32>& RegUses);
72 bool IsRegInSet(SmallSet<unsigned, 32>& RegSet,
76 bool &sawLoad,
bool &sawStore,
77 SmallSet<unsigned, 32> &RegDefs,
78 SmallSet<unsigned, 32> &RegUses);
85 bool tryCombineRestoreWithPrevInst(MachineBasicBlock &
MBB,
114 (
MI->getOpcode() == SP::RESTORErr
115 ||
MI->getOpcode() == SP::RESTOREri)) {
122 if (!Subtarget->isV9() &&
123 (
MI->getOpcode() == SP::FCMPS ||
MI->getOpcode() == SP::FCMPD
124 ||
MI->getOpcode() == SP::FCMPQ)) {
131 if (!
MI->hasDelaySlot())
137 D = findDelayInstr(
MBB,
MI);
147 unsigned structSize = 0;
148 if (needsUnimp(
MI, structSize)) {
151 assert (J !=
MBB.
end() &&
"MI needs a delay instruction.");
164Filler::findDelayInstr(MachineBasicBlock &
MBB,
167 SmallSet<unsigned, 32> RegDefs;
168 SmallSet<unsigned, 32> RegUses;
169 bool sawLoad =
false;
170 bool sawStore =
false;
175 unsigned Opc = slot->getOpcode();
177 if (
Opc == SP::RET ||
Opc == SP::TLS_CALL)
180 if (
Opc == SP::RETL ||
Opc == SP::TAIL_CALL ||
Opc == SP::TAIL_CALLri) {
184 if (J->getOpcode() == SP::RESTORErr
185 || J->getOpcode() == SP::RESTOREri) {
195 insertCallDefsUses(slot, RegDefs, RegUses);
197 insertDefsUses(slot, RegDefs, RegUses);
210 if (
I->isMetaInstruction())
213 if (
I->hasUnmodeledSideEffects() ||
I->isInlineAsm() ||
I->isPosition() ||
214 I->hasDelaySlot() ||
I->isBundledWithSucc())
217 if (delayHasHazard(
I, sawLoad, sawStore, RegDefs, RegUses)) {
218 insertDefsUses(
I, RegDefs, RegUses);
230 SmallSet<unsigned, 32> &RegDefs,
231 SmallSet<unsigned, 32> &RegUses)
234 if (candidate->isImplicitDef() || candidate->isKill())
237 if (candidate->mayLoad()) {
243 if (candidate->mayStore()) {
251 for (
const MachineOperand &MO : candidate->operands()) {
259 if (IsRegInSet(RegDefs,
Reg) || IsRegInSet(RegUses,
Reg))
264 if (IsRegInSet(RegDefs,
Reg))
269 unsigned Opcode = candidate->getOpcode();
272 if (Subtarget->insertNOPLoad()
274 Opcode >= SP::LDDArr && Opcode <= SP::LDrr)
278 if (Subtarget->fixAllFDIVSQRT()
280 Opcode >= SP::FDIVD && Opcode <= SP::FSQRTD)
283 if (Subtarget->fixTN0009() && candidate->mayStore())
286 if (Subtarget->fixTN0013()) {
303 SmallSet<unsigned, 32>& RegDefs,
304 SmallSet<unsigned, 32>& RegUses)
308 switch(
MI->getOpcode()) {
319 case SP::TAIL_CALLri:
321 const MachineOperand &
Reg =
MI->getOperand(0);
322 assert(
Reg.isReg() &&
"CALL first operand is not a register.");
323 assert(
Reg.isUse() &&
"CALL first operand is not a use.");
326 const MachineOperand &Operand1 =
MI->getOperand(1);
329 assert(Operand1.
isReg() &&
"CALLrr second operand is not a register.");
330 assert(Operand1.
isUse() &&
"CALLrr second operand is not a use.");
338 SmallSet<unsigned, 32>& RegDefs,
339 SmallSet<unsigned, 32>& RegUses)
341 for (
const MachineOperand &MO :
MI->operands()) {
353 if (MO.isImplicit() &&
MI->getOpcode() == SP::RETL)
361bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet,
unsigned Reg)
366 if (RegSet.
count(*AI))
376 unsigned structSizeOpNum = 0;
377 switch (
I->getOpcode()) {
386 case SP::TLS_CALL:
return false;
387 case SP::TAIL_CALLri:
388 case SP::TAIL_CALL:
return false;
391 const MachineOperand &MO =
I->getOperand(structSizeOpNum);
408 Register reg = AddMI->getOperand(0).getReg();
409 if (reg < SP::I0 || reg > SP::I7)
415 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
417 if (IsCall && AddMI->getOpcode() == SP::ADDrr &&
418 AddMI->readsRegister(SP::O7,
TRI))
421 if (IsCall && AddMI->getOpcode() == SP::ADDri &&
422 AddMI->readsRegister(SP::O7,
TRI))
426 RestoreMI->eraseFromParent();
429 AddMI->setDesc(
TII->get((AddMI->getOpcode() == SP::ADDrr)
434 AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
450 Register reg = OrMI->getOperand(0).getReg();
451 if (reg < SP::I0 || reg > SP::I7)
455 if (OrMI->getOpcode() == SP::ORrr
456 && OrMI->getOperand(1).getReg() != SP::G0
457 && OrMI->getOperand(2).getReg() != SP::G0)
460 if (OrMI->getOpcode() == SP::ORri
461 && OrMI->getOperand(1).getReg() != SP::G0
462 && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
468 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
470 if (IsCall && OrMI->getOpcode() == SP::ORrr &&
471 OrMI->readsRegister(SP::O7,
TRI))
475 RestoreMI->eraseFromParent();
478 OrMI->setDesc(
TII->get((OrMI->getOpcode() == SP::ORrr)
483 OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
497 Register reg = SetHiMI->getOperand(0).getReg();
498 if (reg < SP::I0 || reg > SP::I7)
501 if (!SetHiMI->getOperand(1).isImm())
504 int64_t imm = SetHiMI->getOperand(1).getImm();
511 imm = (imm << 10) & 0x1FFF;
513 assert(RestoreMI->getOpcode() == SP::RESTORErr);
515 RestoreMI->setDesc(
TII->get(SP::RESTOREri));
517 RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
518 RestoreMI->getOperand(1).setReg(SP::G0);
519 RestoreMI->getOperand(2).ChangeToImmediate(imm);
523 SetHiMI->eraseFromParent();
528bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &
MBB,
537 &&
MBBI->getOperand(0).getReg() == SP::G0
538 &&
MBBI->getOperand(1).getReg() == SP::G0
539 &&
MBBI->getOperand(2).getReg() == SP::G0);
544 if (PrevInst->isBundledWithSucc())
549 switch (PrevInst->getOpcode()) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static bool combineRestoreADD(MachineBasicBlock &MBB, MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator AddMI, const TargetInstrInfo *TII)
static bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator SetHiMI, const TargetInstrInfo *TII)
static cl::opt< bool > DisableDelaySlotFiller("disable-sparc-delay-filler", cl::init(false), cl::desc("Disable the Sparc delay slot filler."), cl::Hidden)
static bool combineRestoreOR(MachineBasicBlock &MBB, MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator OrMI, const TargetInstrInfo *TII)
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static cl::opt< bool > DisableDelaySlotFiller("disable-mips-delay-filler", cl::init(false), cl::desc("Fill all delay slots with NOPs."), cl::Hidden)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
FunctionPass class - This class is used to implement most global optimizations.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
const SparcRegisterInfo * getRegisterInfo() const override
const SparcInstrInfo * getInstrInfo() const override
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
FunctionPass * createSparcDelaySlotFillerPass()
createSparcDelaySlotFillerPass - Returns a pass that fills in delay slots in Sparc MachineFunctions