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->isDebugInstr())
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)
309 switch(
MI->getOpcode()) {
316 const MachineOperand &
Reg =
MI->getOperand(0);
317 assert(
Reg.isReg() &&
"CALL first operand is not a register.");
318 assert(
Reg.isUse() &&
"CALL first operand is not a use.");
321 const MachineOperand &Operand1 =
MI->getOperand(1);
324 assert(Operand1.
isReg() &&
"CALLrr second operand is not a register.");
325 assert(Operand1.
isUse() &&
"CALLrr second operand is not a use.");
333 SmallSet<unsigned, 32>& RegDefs,
334 SmallSet<unsigned, 32>& RegUses)
336 for (
const MachineOperand &MO :
MI->operands()) {
348 if (MO.isImplicit() &&
MI->getOpcode() == SP::RETL)
356bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet,
unsigned Reg)
361 if (RegSet.
count(*AI))
371 unsigned structSizeOpNum = 0;
372 switch (
I->getOpcode()) {
381 case SP::TLS_CALL:
return false;
382 case SP::TAIL_CALLri:
383 case SP::TAIL_CALL:
return false;
386 const MachineOperand &MO =
I->getOperand(structSizeOpNum);
402 Register reg = AddMI->getOperand(0).getReg();
403 if (reg < SP::I0 || reg > SP::I7)
407 RestoreMI->eraseFromParent();
410 AddMI->setDesc(
TII->get((AddMI->getOpcode() == SP::ADDrr)
415 AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
430 Register reg = OrMI->getOperand(0).getReg();
431 if (reg < SP::I0 || reg > SP::I7)
435 if (OrMI->getOpcode() == SP::ORrr
436 && OrMI->getOperand(1).getReg() != SP::G0
437 && OrMI->getOperand(2).getReg() != SP::G0)
440 if (OrMI->getOpcode() == SP::ORri
441 && OrMI->getOperand(1).getReg() != SP::G0
442 && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
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 combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator SetHiMI, const TargetInstrInfo *TII)
static bool combineRestoreOR(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator OrMI, 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 combineRestoreADD(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator AddMI, const TargetInstrInfo *TII)
const HexagonInstrInfo * TII
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.
#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