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);
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);
83 bool tryCombineRestoreWithPrevInst(MachineBasicBlock &
MBB,
112 (
MI->getOpcode() == SP::RESTORErr
113 ||
MI->getOpcode() == SP::RESTOREri)) {
120 if (!Subtarget->isV9() &&
121 (
MI->getOpcode() == SP::FCMPS ||
MI->getOpcode() == SP::FCMPD
122 ||
MI->getOpcode() == SP::FCMPQ)) {
129 if (!
MI->hasDelaySlot())
135 D = findDelayInstr(
MBB,
MI);
145 unsigned structSize = 0;
146 if (
TII->needsUnimp(*
MI, structSize)) {
149 assert (J !=
MBB.
end() &&
"MI needs a delay instruction.");
162Filler::findDelayInstr(MachineBasicBlock &
MBB,
165 SmallSet<unsigned, 32> RegDefs;
166 SmallSet<unsigned, 32> RegUses;
167 bool sawLoad =
false;
168 bool sawStore =
false;
173 unsigned Opc = slot->getOpcode();
175 if (
Opc == SP::RET ||
Opc == SP::TLS_CALL)
178 if (
Opc == SP::RETL ||
Opc == SP::TAIL_CALL ||
Opc == SP::TAIL_CALLri) {
182 if (J->getOpcode() == SP::RESTORErr
183 || J->getOpcode() == SP::RESTOREri) {
193 insertCallDefsUses(slot, RegDefs, RegUses);
195 insertDefsUses(slot, RegDefs, RegUses);
208 if (
I->isMetaInstruction())
211 if (
I->hasUnmodeledSideEffects() ||
I->isInlineAsm() ||
I->isPosition() ||
212 I->hasDelaySlot() ||
I->isBundledWithSucc())
215 if (delayHasHazard(
I, sawLoad, sawStore, RegDefs, RegUses)) {
216 insertDefsUses(
I, RegDefs, RegUses);
228 SmallSet<unsigned, 32> &RegDefs,
229 SmallSet<unsigned, 32> &RegUses)
232 if (candidate->isImplicitDef() || candidate->isKill())
235 if (candidate->mayLoad()) {
241 if (candidate->mayStore()) {
249 for (
const MachineOperand &MO : candidate->operands()) {
257 if (IsRegInSet(RegDefs,
Reg) || IsRegInSet(RegUses,
Reg))
262 if (IsRegInSet(RegDefs,
Reg))
267 unsigned Opcode = candidate->getOpcode();
270 if (Subtarget->insertNOPLoad()
272 Opcode >= SP::LDDArr && Opcode <= SP::LDrr)
276 if (Subtarget->fixAllFDIVSQRT()
278 Opcode >= SP::FDIVD && Opcode <= SP::FSQRTD)
281 if (Subtarget->fixTN0009() && candidate->mayStore())
284 if (Subtarget->fixTN0013()) {
301 SmallSet<unsigned, 32>& RegDefs,
302 SmallSet<unsigned, 32>& RegUses)
306 switch(
MI->getOpcode()) {
317 case SP::TAIL_CALLri:
319 const MachineOperand &
Reg =
MI->getOperand(0);
320 assert(
Reg.isReg() &&
"CALL first operand is not a register.");
321 assert(
Reg.isUse() &&
"CALL first operand is not a use.");
324 const MachineOperand &Operand1 =
MI->getOperand(1);
327 assert(Operand1.
isReg() &&
"CALLrr second operand is not a register.");
328 assert(Operand1.
isUse() &&
"CALLrr second operand is not a use.");
336 SmallSet<unsigned, 32>& RegDefs,
337 SmallSet<unsigned, 32>& RegUses)
339 for (
const MachineOperand &MO :
MI->operands()) {
351 if (MO.isImplicit() &&
MI->getOpcode() == SP::RETL)
359bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet,
unsigned Reg)
364 if (RegSet.
count(*AI))
379 Register reg = AddMI->getOperand(0).getReg();
380 if (reg < SP::I0 || reg > SP::I7)
386 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
388 if (IsCall && AddMI->getOpcode() == SP::ADDrr &&
389 AddMI->readsRegister(SP::O7,
TRI))
392 if (IsCall && AddMI->getOpcode() == SP::ADDri &&
393 AddMI->readsRegister(SP::O7,
TRI))
397 RestoreMI->eraseFromParent();
400 AddMI->setDesc(
TII->get((AddMI->getOpcode() == SP::ADDrr)
405 AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
421 Register reg = OrMI->getOperand(0).getReg();
422 if (reg < SP::I0 || reg > SP::I7)
426 if (OrMI->getOpcode() == SP::ORrr
427 && OrMI->getOperand(1).getReg() != SP::G0
428 && OrMI->getOperand(2).getReg() != SP::G0)
431 if (OrMI->getOpcode() == SP::ORri
432 && OrMI->getOperand(1).getReg() != SP::G0
433 && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
439 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
441 if (IsCall && OrMI->getOpcode() == SP::ORrr &&
442 OrMI->readsRegister(SP::O7,
TRI))
446 RestoreMI->eraseFromParent();
449 OrMI->setDesc(
TII->get((OrMI->getOpcode() == SP::ORrr)
454 OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
468 Register reg = SetHiMI->getOperand(0).getReg();
469 if (reg < SP::I0 || reg > SP::I7)
472 if (!SetHiMI->getOperand(1).isImm())
475 int64_t imm = SetHiMI->getOperand(1).getImm();
482 imm = (imm << 10) & 0x1FFF;
484 assert(RestoreMI->getOpcode() == SP::RESTORErr);
486 RestoreMI->setDesc(
TII->get(SP::RESTOREri));
488 RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
489 RestoreMI->getOperand(1).setReg(SP::G0);
490 RestoreMI->getOperand(2).ChangeToImmediate(imm);
494 SetHiMI->eraseFromParent();
499bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &
MBB,
508 &&
MBBI->getOperand(0).getReg() == SP::G0
509 &&
MBBI->getOperand(1).getReg() == SP::G0
510 &&
MBBI->getOperand(2).getReg() == SP::G0);
515 if (PrevInst->isBundledWithSucc())
520 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.
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