31#define DEBUG_TYPE "delay-slot-filler"
33STATISTIC(FilledSlots,
"Number of delay slots filled");
40 StringRef getPassName()
const override {
return "SPARC Delay Slot Filler"; }
44 MachineFunctionProperties getRequiredProperties()
const override {
45 return MachineFunctionProperties().setNoVRegs();
48 void getAnalysisUsage(AnalysisUsage &AU)
const override {
53char SparcDelaySlotFillerLegacy::ID = 0;
60 return new SparcDelaySlotFillerLegacy;
73 Register reg = AddMI->getOperand(0).getReg();
74 if (reg < SP::I0 || reg > SP::I7)
80 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
82 if (IsCall && AddMI->getOpcode() == SP::ADDrr &&
83 AddMI->readsRegister(SP::O7,
TRI))
86 if (IsCall && AddMI->getOpcode() == SP::ADDri &&
87 AddMI->readsRegister(SP::O7,
TRI))
91 RestoreMI->eraseFromParent();
94 AddMI->setDesc(
TII->get((AddMI->getOpcode() == SP::ADDrr) ? SP::RESTORErr
98 AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
114 Register reg = OrMI->getOperand(0).getReg();
115 if (reg < SP::I0 || reg > SP::I7)
119 if (OrMI->getOpcode() == SP::ORrr && OrMI->getOperand(1).getReg() != SP::G0 &&
120 OrMI->getOperand(2).getReg() != SP::G0)
123 if (OrMI->getOpcode() == SP::ORri && OrMI->getOperand(1).getReg() != SP::G0 &&
124 (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
130 bool IsCall = LastInst !=
MBB.end() && LastInst->isCall();
132 if (IsCall && OrMI->getOpcode() == SP::ORrr &&
133 OrMI->readsRegister(SP::O7,
TRI))
137 RestoreMI->eraseFromParent();
140 OrMI->setDesc(
TII->get((OrMI->getOpcode() == SP::ORrr) ? SP::RESTORErr
144 OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
157 Register reg = SetHiMI->getOperand(0).getReg();
158 if (reg < SP::I0 || reg > SP::I7)
161 if (!SetHiMI->getOperand(1).isImm())
164 int64_t imm = SetHiMI->getOperand(1).getImm();
171 imm = (imm << 10) & 0x1FFF;
173 assert(RestoreMI->getOpcode() == SP::RESTORErr);
175 RestoreMI->setDesc(
TII->get(SP::RESTOREri));
177 RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
178 RestoreMI->getOperand(1).setReg(SP::G0);
179 RestoreMI->getOperand(2).ChangeToImmediate(imm);
182 SetHiMI->eraseFromParent();
196 MBBI->getOperand(0).getReg() == SP::G0 &&
197 MBBI->getOperand(1).getReg() == SP::G0 &&
198 MBBI->getOperand(2).getReg() == SP::G0);
203 if (PrevInst->isBundledWithSucc())
208 switch (PrevInst->getOpcode()) {
232 unsigned Opc = slot->getOpcode();
233 if ((
Opc != SP::TAIL_CALL &&
Opc != SP::TAIL_CALLri) || slot ==
MBB.begin())
239 }
while (J->isMetaInstruction() && J !=
MBB.begin());
241 if (J->getOpcode() == SP::RESTORErr || J->getOpcode() == SP::RESTOREri)
243 if (
Opc == SP::TAIL_CALL && J->getOpcode() == SP::ORrr &&
244 J->getOperand(0).getReg() == SP::O7)
254 switch (
MI->getOpcode()) {
266 case SP::TAIL_CALLri:
269 assert(
Reg.isReg() &&
"CALL first operand is not a register.");
270 assert(
Reg.isUse() &&
"CALL first operand is not a use.");
276 assert(Operand1.
isReg() &&
"CALLrr second operand is not a register.");
277 assert(Operand1.
isUse() &&
"CALLrr second operand is not a use.");
300 if (MO.isImplicit() &&
MI->getOpcode() == SP::RETL)
313 if (RegSet.
count(*AI))
323 if (candidate->isImplicitDef() || candidate->isKill())
326 if (candidate->mayLoad()) {
332 if (candidate->mayStore()) {
359 unsigned Opcode = candidate->getOpcode();
362 if (Subtarget->insertNOPLoad()
364 Opcode >= SP::LDDArr && Opcode <= SP::LDrr)
368 if (Subtarget->fixAllFDIVSQRT()
370 Opcode >= SP::FDIVD && Opcode <= SP::FSQRTD)
373 if (Subtarget->fixTN0009() && candidate->mayStore())
376 if (Subtarget->fixTN0013()) {
396 bool sawLoad =
false;
397 bool sawStore =
false;
399 if (slot ==
MBB.begin())
402 unsigned Opc = slot->getOpcode();
404 if (
Opc == SP::RET ||
Opc == SP::TLS_CALL)
407 if (
Opc == SP::RETL ||
Opc == SP::TAIL_CALL ||
Opc == SP::TAIL_CALLri) {
411 if (J->getOpcode() == SP::RESTORErr || J->getOpcode() == SP::RESTOREri) {
430 done = (
I ==
MBB.begin());
436 if (
I->isMetaInstruction())
439 if (
I->hasUnmodeledSideEffects() ||
I->isInlineAsm() ||
I->isPosition() ||
440 I->hasDelaySlot() ||
I->isBundledWithSucc())
443 if (
delayHasHazard(
I, sawLoad, sawStore, RegDefs, RegUses, Subtarget)) {
461 !Subtarget->
getCLOpts().disable_sparc_delay_filler &&
470 if (FillSlots && (
MI->getOpcode() == SP::RESTORErr ||
471 MI->getOpcode() == SP::RESTOREri)) {
478 if (!Subtarget->isV9() &&
479 (
MI->getOpcode() == SP::FCMPS ||
MI->getOpcode() == SP::FCMPD ||
480 MI->getOpcode() == SP::FCMPQ)) {
487 if (!
MI->hasDelaySlot())
492 if (
D ==
MBB.end() && FillSlots)
503 unsigned structSize = 0;
504 if (
TII->needsUnimp(*
MI, structSize)) {
507 assert(J !=
MBB.end() &&
"MI needs a delay instruction.");
531bool SparcDelaySlotFillerLegacy::runOnMachineFunction(
MachineFunction &MF) {
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 tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const SparcSubtarget *Subtarget)
static void insertDefsUses(MachineBasicBlock::iterator MI, SmallSet< unsigned, 32 > &RegDefs, SmallSet< unsigned, 32 > &RegUses, const SparcSubtarget *Subtarget)
static bool combineRestoreADD(MachineBasicBlock &MBB, MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator AddMI, const TargetInstrInfo *TII)
static void insertCallDefsUses(MachineBasicBlock::iterator MI, SmallSet< unsigned, 32 > &RegDefs, SmallSet< unsigned, 32 > &RegUses)
static bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator SetHiMI, const TargetInstrInfo *TII)
static MachineBasicBlock::iterator findRequiredDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot)
The restore before a tail call must run in its delay slot: jmp reg reads a register of the current wi...
static bool runDelaySlotFillerOnMachineFunction(MachineFunction &MF)
static MachineBasicBlock::iterator findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot, const SparcSubtarget *Subtarget)
static bool combineRestoreOR(MachineBasicBlock &MBB, MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator OrMI, const TargetInstrInfo *TII)
static bool runOnMachineBasicBlock(MachineBasicBlock &MBB)
runOnMachineBasicBlock - Fill in delay slots for the given basic block.
static bool delayHasHazard(MachineBasicBlock::iterator candidate, bool &sawLoad, bool &sawStore, SmallSet< unsigned, 32 > &RegDefs, SmallSet< unsigned, 32 > &RegUses, const SparcSubtarget *Subtarget)
static bool IsRegInSet(SmallSet< unsigned, 32 > &RegSet, unsigned Reg, const SparcSubtarget *Subtarget)
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
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)
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
MCRegAliasIterator enumerates all registers aliasing Reg.
An RAII based helper class to modify MachineFunctionProperties when running pass.
Helper class for constructing bundles of MachineInstrs.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineOperand class - Representation of each machine instruction 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.
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
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.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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...
Pass manager infrastructure for declaring and invalidating analyses.
#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.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createSparcDelaySlotFillerLegacyPass()
createSparcDelaySlotFillerPass - Returns a pass that fills in delay slots in Sparc MachineFunctions