26#define DEBUG_TYPE "delay-slot-filler"
28STATISTIC(FilledSlots,
"Number of delay slots filled");
37 StringRef getPassName()
const override {
return "SPARC Delay Slot Filler"; }
39 bool runOnMachineBasicBlock(MachineBasicBlock &
MBB);
42 Subtarget = &
F.getSubtarget<SparcSubtarget>();
46 F.getRegInfo().invalidateLiveness();
48 for (MachineBasicBlock &
MBB :
F)
53 MachineFunctionProperties getRequiredProperties()
const override {
54 return MachineFunctionProperties().setNoVRegs();
58 SmallSet<unsigned, 32>& RegDefs,
59 SmallSet<unsigned, 32>& RegUses);
62 SmallSet<unsigned, 32>& RegDefs,
63 SmallSet<unsigned, 32>& RegUses);
65 bool IsRegInSet(SmallSet<unsigned, 32>& RegSet,
69 bool &sawLoad,
bool &sawStore,
70 SmallSet<unsigned, 32> &RegDefs,
71 SmallSet<unsigned, 32> &RegUses);
76 bool tryCombineRestoreWithPrevInst(MachineBasicBlock &
MBB,
104 if (!Subtarget->
getCLOpts().disable_sparc_delay_filler &&
105 (
MI->getOpcode() == SP::RESTORErr ||
106 MI->getOpcode() == SP::RESTOREri)) {
113 if (!Subtarget->isV9() &&
114 (
MI->getOpcode() == SP::FCMPS ||
MI->getOpcode() == SP::FCMPD
115 ||
MI->getOpcode() == SP::FCMPQ)) {
122 if (!
MI->hasDelaySlot())
127 if (!Subtarget->
getCLOpts().disable_sparc_delay_filler)
128 D = findDelayInstr(
MBB,
MI);
138 unsigned structSize = 0;
139 if (
TII->needsUnimp(*
MI, structSize)) {
142 assert (J !=
MBB.
end() &&
"MI needs a delay instruction.");
155Filler::findDelayInstr(MachineBasicBlock &
MBB,
158 SmallSet<unsigned, 32> RegDefs;
159 SmallSet<unsigned, 32> RegUses;
160 bool sawLoad =
false;
161 bool sawStore =
false;
166 unsigned Opc = slot->getOpcode();
168 if (
Opc == SP::RET ||
Opc == SP::TLS_CALL)
171 if (
Opc == SP::RETL ||
Opc == SP::TAIL_CALL ||
Opc == SP::TAIL_CALLri) {
175 if (J->getOpcode() == SP::RESTORErr
176 || J->getOpcode() == SP::RESTOREri) {
186 insertCallDefsUses(slot, RegDefs, RegUses);
188 insertDefsUses(slot, RegDefs, RegUses);
201 if (
I->isMetaInstruction())
204 if (
I->hasUnmodeledSideEffects() ||
I->isInlineAsm() ||
I->isPosition() ||
205 I->hasDelaySlot() ||
I->isBundledWithSucc())
208 if (delayHasHazard(
I, sawLoad, sawStore, RegDefs, RegUses)) {
209 insertDefsUses(
I, RegDefs, RegUses);
221 SmallSet<unsigned, 32> &RegDefs,
222 SmallSet<unsigned, 32> &RegUses)
225 if (candidate->isImplicitDef() || candidate->isKill())
228 if (candidate->mayLoad()) {
234 if (candidate->mayStore()) {
242 for (
const MachineOperand &MO : candidate->operands()) {
250 if (IsRegInSet(RegDefs,
Reg) || IsRegInSet(RegUses,
Reg))
255 if (IsRegInSet(RegDefs,
Reg))
260 unsigned Opcode = candidate->getOpcode();
263 if (Subtarget->insertNOPLoad()
265 Opcode >= SP::LDDArr && Opcode <= SP::LDrr)
269 if (Subtarget->fixAllFDIVSQRT()
271 Opcode >= SP::FDIVD && Opcode <= SP::FSQRTD)
274 if (Subtarget->fixTN0009() && candidate->mayStore())
277 if (Subtarget->fixTN0013()) {
294 SmallSet<unsigned, 32>& RegDefs,
295 SmallSet<unsigned, 32>& RegUses)
299 switch(
MI->getOpcode()) {
310 case SP::TAIL_CALLri:
312 const MachineOperand &
Reg =
MI->getOperand(0);
313 assert(
Reg.isReg() &&
"CALL first operand is not a register.");
314 assert(
Reg.isUse() &&
"CALL first operand is not a use.");
317 const MachineOperand &Operand1 =
MI->getOperand(1);
320 assert(Operand1.
isReg() &&
"CALLrr second operand is not a register.");
321 assert(Operand1.
isUse() &&
"CALLrr second operand is not a use.");
329 SmallSet<unsigned, 32>& RegDefs,
330 SmallSet<unsigned, 32>& RegUses)
332 for (
const MachineOperand &MO :
MI->operands()) {
344 if (MO.isImplicit() &&
MI->getOpcode() == SP::RETL)
352bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet,
unsigned Reg)
357 if (RegSet.
count(*AI))
372 Register reg = AddMI->getOperand(0).getReg();
373 if (reg < SP::I0 || reg > SP::I7)
379 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
381 if (IsCall && AddMI->getOpcode() == SP::ADDrr &&
382 AddMI->readsRegister(SP::O7,
TRI))
385 if (IsCall && AddMI->getOpcode() == SP::ADDri &&
386 AddMI->readsRegister(SP::O7,
TRI))
390 RestoreMI->eraseFromParent();
393 AddMI->setDesc(
TII->get((AddMI->getOpcode() == SP::ADDrr)
398 AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
414 Register reg = OrMI->getOperand(0).getReg();
415 if (reg < SP::I0 || reg > SP::I7)
419 if (OrMI->getOpcode() == SP::ORrr
420 && OrMI->getOperand(1).getReg() != SP::G0
421 && OrMI->getOperand(2).getReg() != SP::G0)
424 if (OrMI->getOpcode() == SP::ORri
425 && OrMI->getOperand(1).getReg() != SP::G0
426 && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
432 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
434 if (IsCall && OrMI->getOpcode() == SP::ORrr &&
435 OrMI->readsRegister(SP::O7,
TRI))
439 RestoreMI->eraseFromParent();
442 OrMI->setDesc(
TII->get((OrMI->getOpcode() == SP::ORrr)
447 OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
461 Register reg = SetHiMI->getOperand(0).getReg();
462 if (reg < SP::I0 || reg > SP::I7)
465 if (!SetHiMI->getOperand(1).isImm())
468 int64_t imm = SetHiMI->getOperand(1).getImm();
475 imm = (imm << 10) & 0x1FFF;
477 assert(RestoreMI->getOpcode() == SP::RESTORErr);
479 RestoreMI->setDesc(
TII->get(SP::RESTOREri));
481 RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
482 RestoreMI->getOperand(1).setReg(SP::G0);
483 RestoreMI->getOperand(2).ChangeToImmediate(imm);
487 SetHiMI->eraseFromParent();
492bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &
MBB,
501 &&
MBBI->getOperand(0).getReg() == SP::G0
502 &&
MBBI->getOperand(1).getReg() == SP::G0
503 &&
MBBI->getOperand(2).getReg() == SP::G0);
508 if (PrevInst->isBundledWithSucc())
513 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 bool combineRestoreOR(MachineBasicBlock &MBB, MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator OrMI, const TargetInstrInfo *TII)
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
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 SparcOptions & getCLOpts() const
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.
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