14 #define DEBUG_TYPE "delay-slot-filler"
35 STATISTIC(FilledSlots,
"Number of delay slots filled");
36 STATISTIC(UsefulSlots,
"Number of delay slots filled with instructions that"
40 "disable-mips-delay-filler",
42 cl::desc(
"Fill all delay slots with NOPs."),
46 "disable-mips-df-forward-search",
48 cl::desc(
"Disallow MIPS delay filler to search forward."),
52 "disable-mips-df-succbb-search",
54 cl::desc(
"Disallow MIPS delay filler to search successor basic blocks."),
58 "disable-mips-df-backward-search",
60 cl::desc(
"Disallow MIPS delay filler to search backward."),
75 return Prob.getEdgeWeight(&Src, Dst0) < Prob.getEdgeWeight(&Src, Dst1);
105 bool isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const;
112 class InspectMemInstr {
114 InspectMemInstr(
bool ForbidMemInstr_)
116 SeenStore(
false), ForbidMemInstr(ForbidMemInstr_) {}
121 virtual ~InspectMemInstr() {}
125 bool OrigSeenLoad, OrigSeenStore, SeenLoad, SeenStore;
136 class NoMemInstr :
public InspectMemInstr {
138 NoMemInstr() : InspectMemInstr(
true) {}
144 class LoadFromStackOrConst :
public InspectMemInstr {
146 LoadFromStackOrConst() : InspectMemInstr(
false) {}
153 class MemDefsUses :
public InspectMemInstr {
174 bool SeenNoObjLoad, SeenNoObjStore;
182 virtual const char *getPassName()
const {
183 return "Mips Delay Slot Filler";
187 bool Changed =
false;
190 Changed |= runOnMachineBasicBlock(*FI);
205 bool delayHasHazard(
const MachineInstr &Candidate, RegDefsUses &RegDU,
206 InspectMemInstr &IM)
const;
210 template<
typename IterTy>
212 RegDefsUses &RegDU, InspectMemInstr &IM,
213 IterTy &Filler)
const;
234 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
240 RegDefsUses &RegDU,
bool &HasMultipleSuccs,
241 BB2BrMap &BrMap)
const;
243 bool terminateSearch(
const MachineInstr &Candidate)
const;
260 for (BB2BrMap::const_iterator
I = BrMap.begin();
I != BrMap.end(); ++
I) {
272 for (
unsigned I = 0, E = Filler->getNumOperands();
I != E; ++
I) {
282 "Shouldn't move an instruction with unallocatable registers across "
283 "basic block boundaries.");
292 : TRI(*TM.getRegisterInfo()), Defs(TRI.getNumRegs(),
false),
293 Uses(TRI.getNumRegs(),
false) {}
308 Defs.reset(Mips::AT);
312 void RegDefsUses::setCallerSaved(
const MachineInstr &MI) {
316 BitVector CallerSavedRegs(TRI.getNumRegs(),
true);
318 CallerSavedRegs.
reset(Mips::ZERO);
319 CallerSavedRegs.
reset(Mips::ZERO_64);
321 for (
const MCPhysReg *R = TRI.getCalleeSavedRegs(); *R; ++R)
323 CallerSavedRegs.
reset(*AI);
325 Defs |= CallerSavedRegs;
329 BitVector AllocSet = TRI.getAllocatableSet(MF);
335 AllocSet.
set(Mips::ZERO);
336 AllocSet.
set(Mips::ZERO_64);
338 Defs |= AllocSet.
flip();
344 SE = MBB.
succ_end(); SI != SE; ++SI)
347 LE = (*SI)->livein_end();
LI !=
LE; ++
LI)
351 bool RegDefsUses::update(
const MachineInstr &MI,
unsigned Begin,
unsigned End) {
352 BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs());
353 bool HasHazard =
false;
355 for (
unsigned I = Begin;
I != End; ++
I) {
359 HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.
getReg(), MO.
isDef());
369 unsigned Reg,
bool IsDef)
const {
373 return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg));
378 return isRegInSet(Defs, Reg);
381 bool RegDefsUses::isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const {
384 if (RegSet.
test(*AI))
389 bool InspectMemInstr::hasHazard(
const MachineInstr &MI) {
396 OrigSeenLoad = SeenLoad;
397 OrigSeenStore = SeenStore;
404 ForbidMemInstr =
true;
408 return hasHazard_(MI);
411 bool LoadFromStackOrConst::hasHazard_(
const MachineInstr &MI) {
420 if (isa<FixedStackPseudoSourceValue>(V))
424 return !PSV->isConstant(0) && V != PseudoSourceValue::getStack();
430 : InspectMemInstr(
false), MFI(MFI_), SeenNoObjLoad(
false),
431 SeenNoObjStore(
false) {}
434 bool HasHazard =
false;
440 I != Objs.
end(); ++
I)
441 HasHazard |= updateDefsUses(*
I, MI.
mayStore());
447 HasHazard = MI.
mayStore() && (OrigSeenLoad || OrigSeenStore);
448 HasHazard |= MI.
mayLoad() || OrigSeenStore;
456 bool MemDefsUses::updateDefsUses(
const Value *V,
bool MayStore) {
458 return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad;
461 return Defs.count(V) || SeenNoObjStore;
478 if (PSV->isAliased(MFI))
492 bool Changed =
false;
503 if (searchBackward(MBB,
I))
506 if (
I->isTerminator()) {
507 if (searchSuccBBs(MBB,
I))
509 }
else if (searchForward(MBB,
I)) {
527 return new Filler(tm);
530 template<
typename IterTy>
532 RegDefsUses &RegDU, InspectMemInstr& IM,
533 IterTy &Filler)
const {
534 for (IterTy
I = Begin;
I != End; ++
I) {
536 if (
I->isDebugValue())
539 if (terminateSearch(*
I))
542 assert((!
I->isCall() && !
I->isReturn() && !
I->isBranch()) &&
543 "Cannot put calls, returns or branches in delay slot.");
545 if (delayHasHazard(*
I, RegDU, IM))
559 RegDefsUses RegDU(
TM);
565 if (!searchRange(MBB, ReverseIter(Slot), MBB.
rend(), RegDU, MemDU, Filler))
579 RegDefsUses RegDU(
TM);
583 RegDU.setCallerSaved(*Slot);
585 if (!searchRange(MBB,
llvm::next(Slot), MBB.
end(), RegDU, NM, Filler))
603 RegDefsUses RegDU(
TM);
604 bool HasMultipleSuccs =
false;
611 PE = SuccBB->
pred_end(); PI != PE; ++PI)
612 if (!examinePred(**PI, *SuccBB, RegDU, HasMultipleSuccs, BrMap))
617 RegDU.setUnallocatableRegs(*MBB.
getParent());
621 if (HasMultipleSuccs) {
622 IM.
reset(
new LoadFromStackOrConst());
625 IM.
reset(
new MemDefsUses(MFI));
628 if (!searchRange(MBB, SuccBB->
begin(), SuccBB->
end(), RegDU, *IM, Filler))
633 Filler->eraseFromParent();
643 CmpWeight Cmp(B, getAnalysis<MachineBranchProbabilityInfo>());
648 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
657 TII->
AnalyzeBranch(MBB, TrueBB, FalseBB, Cond,
false, BranchInstrs);
659 if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch))
662 if (R != MipsInstrInfo::BT_CondUncond) {
664 return std::make_pair(MipsInstrInfo::BT_None, (
MachineInstr*)NULL);
666 assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst)));
668 return std::make_pair(R, BranchInstrs[0]);
671 assert((TrueBB == &Dst) || (FalseBB == &Dst));
675 return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]);
679 return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]);
681 return std::make_pair(MipsInstrInfo::BT_None, (
MachineInstr*)NULL);
685 RegDefsUses &RegDU,
bool &HasMultipleSuccs,
686 BB2BrMap &BrMap)
const {
687 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
P =
688 getBranch(Pred, Succ);
692 if (P.first == MipsInstrInfo::BT_None)
695 if ((P.first != MipsInstrInfo::BT_Uncond) &&
696 (P.first != MipsInstrInfo::BT_NoBranch)) {
697 HasMultipleSuccs =
true;
698 RegDU.addLiveOut(Pred, Succ);
701 BrMap[&Pred] = P.second;
705 bool Filler::delayHasHazard(
const MachineInstr &Candidate, RegDefsUses &RegDU,
706 InspectMemInstr &IM)
const {
709 HasHazard |= IM.hasHazard(Candidate);
710 HasHazard |= RegDU.update(Candidate, 0, Candidate.
getNumOperands());
715 bool Filler::terminateSearch(
const MachineInstr &Candidate)
const {
void push_back(const T &Elt)
const MachineFunction * getParent() const
void GetUnderlyingObjects(Value *V, SmallVectorImpl< Value * > &Objects, const DataLayout *TD=0, unsigned MaxLookup=6)
bool isBranch(QueryType Type=AnyInBundle) const
int find_next(unsigned Prev) const
std::vector< unsigned >::const_iterator livein_iterator
bool mayStore(QueryType Type=AnyInBundle) const
bool hasOrderedMemoryRef() const
void addLiveIn(unsigned Reg)
const MCInstrDesc & getDesc() const
static bool hasUnoccupiedSlot(const MachineInstr *MI)
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
Branch Analysis.
bool isTerminator(QueryType Type=AnyInBundle) const
LoopInfoBase< BlockT, LoopT > * LI
static cl::opt< bool > DisableDelaySlotFiller("disable-mips-delay-filler", cl::init(false), cl::desc("Fill all delay slots with NOPs."), cl::Hidden)
static void getUnderlyingObjects(const Value *V, SmallVectorImpl< Value * > &Objects)
AnalysisUsage & addRequired()
const HexagonInstrInfo * TII
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool mayLoad(QueryType Type=AnyInBundle) const
Abstract Stack Frame Information.
ID
LLVM Calling Convention Representation.
unsigned getNumOperands() const
bool isIdentifiedObject(const Value *V)
bool isBundledWithSucc() const
static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB)
This function adds registers Filler defines to MBB's live-in register list.
bool hasDelaySlot(QueryType Type=AnyInBundle) const
static cl::opt< bool > DisableBackwardSearch("disable-mips-df-backward-search", cl::init(false), cl::desc("Disallow MIPS delay filler to search backward."), cl::Hidden)
std::vector< MachineBasicBlock * >::iterator pred_iterator
static cl::opt< bool > DisableForwardSearch("disable-mips-df-forward-search", cl::init(true), cl::desc("Disallow MIPS delay filler to search forward."), cl::Hidden)
bool isImplicitDef() const
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
const MachineOperand & getOperand(unsigned i) const
BitVector getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC=NULL) const
ItTy next(ItTy it, Dist n)
bool hasOneMemOperand() const
bool hasUnmodeledSideEffects() const
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
succ_iterator succ_begin()
static cl::opt< bool > DisableSuccBBSearch("disable-mips-df-succbb-search", cl::init(true), cl::desc("Disallow MIPS delay filler to search successor basic blocks."), cl::Hidden)
pred_iterator pred_begin()
STATISTIC(FilledSlots,"Number of delay slots filled")
static ManagedStatic< LeakDetectorImpl< void > > Objects
MachineInstr * CloneMachineInstr(const MachineInstr *Orig)
bool test(unsigned Idx) const
MachineFrameInfo * getFrameInfo()
FunctionPass * createMipsDelaySlotFillerPass(MipsTargetMachine &TM)
bool isLandingPad() const
static void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap)
This function inserts clones of Filler into predecessor blocks.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
bool isLiveIn(unsigned Reg) const
virtual void getAnalysisUsage(AnalysisUsage &AU) const
bool isCall(QueryType Type=AnyInBundle) const
const TargetMachine & getTarget() const
virtual const TargetRegisterInfo * getRegisterInfo() const
unsigned getReg() const
getReg - Returns the register number.
MIBundleBuilder & append(MachineInstr *MI)
std::vector< MachineBasicBlock * >::const_iterator const_succ_iterator
std::reverse_iterator< iterator > reverse_iterator
LLVM Value Representation.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction. Note that variadic (isVari...
BasicBlockListType::iterator iterator
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.