21 #define DEBUG_TYPE "post-RA-sched"
51 STATISTIC(NumNoops,
"Number of noops inserted");
52 STATISTIC(NumStalls,
"Number of pipeline stalls");
53 STATISTIC(NumFixedAnti,
"Number of fixed anti-dependencies");
60 cl::desc(
"Enable scheduling after register allocation"),
64 cl::desc(
"Break post-RA scheduling anti-dependencies: "
65 "\"critical\", \"all\", or \"none\""),
71 cl::desc(
"Debug control MBBs that are scheduled"),
75 cl::desc(
"Debug control MBBs that are scheduled"),
113 std::vector<SUnit*> PendingQueue;
137 SchedulePostRATDList(
143 ~SchedulePostRATDList();
151 void setEndIndex(
unsigned EndIdx) { EndIndex = EndIdx; }
157 unsigned regioninstrs);
160 virtual void exitRegion();
183 void ReleaseSucc(
SUnit *SU,
SDep *SuccEdge);
184 void ReleaseSuccessors(
SUnit *SU);
185 void ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle);
186 void ListScheduleTopDown();
194 void dumpSchedule()
const;
201 "Post RA top-down list latency scheduler",
false,
false)
203 SchedulePostRATDList::SchedulePostRATDList(
209 LiveRegs(TRI->getNumRegs()), EndIndex(0)
217 MRI.tracksLiveness()) &&
218 "Live-ins must be accurate for anti-dependency breaking");
226 SchedulePostRATDList::~SchedulePostRATDList() {
235 unsigned regioninstrs) {
241 void SchedulePostRATDList::exitRegion() {
243 dbgs() <<
"*** Final schedule ***\n";
250 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
252 void SchedulePostRATDList::dumpSchedule()
const {
253 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
257 dbgs() <<
"**** NOOP ****\n";
269 RegClassInfo.runOnMachineFunction(Fn);
298 SchedulePostRATDList
Scheduler(Fn, MLI, MDT, AA, RegClassInfo, AntiDepMode,
303 MBB != MBBe; ++MBB) {
307 static int bbcnt = 0;
311 <<
":BB#" << MBB->getNumber() <<
" ***\n";
321 unsigned Count = MBB->size(), CurrentCount = Count;
329 Scheduler.enterRegion(MBB,
I, Current, CurrentCount - Count);
335 CurrentCount = Count;
342 assert(Count == 0 &&
"Instruction count mismatch!");
343 assert((MBB->begin() == Current || CurrentCount != 0) &&
344 "Instruction count mismatch!");
345 Scheduler.enterRegion(MBB, MBB->begin(), Current, CurrentCount);
370 if (AntiDepBreak != NULL)
371 AntiDepBreak->StartBlock(BB);
376 void SchedulePostRATDList::schedule() {
380 if (AntiDepBreak != NULL) {
382 AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
383 EndIndex, DbgValues);
395 NumFixedAnti += Broken;
399 DEBUG(
dbgs() <<
"********** List Scheduling **********\n");
400 DEBUG(
for (
unsigned su = 0, e = SUnits.size(); su != e; ++su)
401 SUnits[su].dumpAll(
this));
403 AvailableQueue.initNodes(SUnits);
404 ListScheduleTopDown();
405 AvailableQueue.releaseState();
411 void SchedulePostRATDList::Observe(
MachineInstr *MI,
unsigned Count) {
412 if (AntiDepBreak != NULL)
413 AntiDepBreak->Observe(MI, Count, EndIndex);
418 void SchedulePostRATDList::finishBlock() {
419 if (AntiDepBreak != NULL)
420 AntiDepBreak->FinishBlock();
434 SE = BB->
succ_end(); SI != SE; ++SI) {
436 E = (*SI)->livein_end();
I != E; ++
I) {
441 LiveRegs.set(*SubRegs);
446 bool SchedulePostRATDList::ToggleKillFlag(
MachineInstr *MI,
455 if (LiveRegs.test(MO.
getReg())) {
464 const unsigned SuperReg = MO.
getReg();
467 if (LiveRegs.test(*SubRegs)) {
486 StartBlockForKills(MBB);
489 unsigned Count = MBB->
size();
503 if (!MO.
isReg())
continue;
504 unsigned Reg = MO.
getReg();
505 if (Reg == 0)
continue;
506 if (!MO.
isDef())
continue;
513 LiveRegs.reset(*SubRegs);
523 unsigned Reg = MO.
getReg();
524 if ((Reg == 0) ||
MRI.isReserved(Reg))
continue;
527 if (!killedRegs.test(Reg)) {
531 if (LiveRegs.test(*SubRegs)) {
540 kill = !LiveRegs.test(Reg);
543 if (MO.
isKill() != kill) {
544 DEBUG(
dbgs() <<
"Fixing " << MO <<
" in ");
546 ToggleKillFlag(MI, MO);
558 unsigned Reg = MO.
getReg();
559 if ((Reg == 0) ||
MRI.isReserved(Reg))
continue;
563 LiveRegs.set(*SubRegs);
574 void SchedulePostRATDList::ReleaseSucc(
SUnit *SU,
SDep *SuccEdge) {
583 dbgs() <<
"*** Scheduling failed! ***\n";
585 dbgs() <<
" has been released too many times!\n";
605 PendingQueue.push_back(SuccSU);
609 void SchedulePostRATDList::ReleaseSuccessors(
SUnit *SU) {
612 ReleaseSucc(SU, &*
I);
619 void SchedulePostRATDList::ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle) {
620 DEBUG(
dbgs() <<
"*** Scheduling [" << CurCycle <<
"]: ");
624 assert(CurCycle >= SU->
getDepth() &&
625 "Node scheduled above its depth!");
628 ReleaseSuccessors(SU);
630 AvailableQueue.scheduledNode(SU);
635 void SchedulePostRATDList::ListScheduleTopDown() {
636 unsigned CurCycle = 0;
645 ReleaseSuccessors(&EntrySU);
648 for (
unsigned i = 0, e = SUnits.size(); i != e; ++i) {
650 if (!SUnits[i].NumPredsLeft && !SUnits[i].
isAvailable) {
651 AvailableQueue.push(&SUnits[i]);
652 SUnits[i].isAvailable =
true;
658 bool CycleHasInsts =
false;
662 std::vector<SUnit*> NotReady;
664 while (!AvailableQueue.empty() || !PendingQueue.empty()) {
667 unsigned MinDepth = ~0u;
668 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
669 if (PendingQueue[i]->getDepth() <= CurCycle) {
670 AvailableQueue.push(PendingQueue[i]);
671 PendingQueue[i]->isAvailable =
true;
672 PendingQueue[i] = PendingQueue.back();
673 PendingQueue.pop_back();
675 }
else if (PendingQueue[i]->getDepth() < MinDepth)
676 MinDepth = PendingQueue[i]->getDepth();
679 DEBUG(
dbgs() <<
"\n*** Examining Available\n"; AvailableQueue.dump(
this));
681 SUnit *FoundSUnit = 0;
682 bool HasNoopHazards =
false;
683 while (!AvailableQueue.empty()) {
684 SUnit *CurSUnit = AvailableQueue.pop();
687 HazardRec->getHazardType(CurSUnit, 0);
689 FoundSUnit = CurSUnit;
696 NotReady.push_back(CurSUnit);
700 if (!NotReady.empty()) {
701 AvailableQueue.push_all(NotReady);
708 ScheduleNodeTopDown(FoundSUnit, CurCycle);
709 HazardRec->EmitInstruction(FoundSUnit);
710 CycleHasInsts =
true;
711 if (HazardRec->atIssueLimit()) {
712 DEBUG(
dbgs() <<
"*** Max instructions per cycle " << CurCycle <<
'\n');
713 HazardRec->AdvanceCycle();
715 CycleHasInsts =
false;
719 DEBUG(
dbgs() <<
"*** Finished cycle " << CurCycle <<
'\n');
720 HazardRec->AdvanceCycle();
721 }
else if (!HasNoopHazards) {
724 DEBUG(
dbgs() <<
"*** Stall in cycle " << CurCycle <<
'\n');
725 HazardRec->AdvanceCycle();
731 DEBUG(
dbgs() <<
"*** Emitting noop in cycle " << CurCycle <<
'\n');
732 HazardRec->EmitNoop();
738 CycleHasInsts =
false;
743 unsigned ScheduledNodes = VerifyScheduledDAG(
false);
745 for (
unsigned i = 0, e =
Sequence.size(); i != e; ++i)
748 assert(
Sequence.size() - Noops == ScheduledNodes &&
749 "The number of nodes scheduled doesn't match the expected number!");
754 void SchedulePostRATDList::EmitSchedule() {
755 RegionBegin = RegionEnd;
759 BB->
splice(RegionEnd, BB, FirstDbgValue);
762 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
767 TII->insertNoop(*BB, RegionEnd);
772 RegionBegin =
prior(RegionEnd);
776 for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
777 DI = DbgValues.end(),
DE = DbgValues.begin(); DI !=
DE; --DI) {
778 std::pair<MachineInstr *, MachineInstr *>
P = *
prior(DI);
781 BB->
splice(++OrigPrivMI, BB, DbgValue);
784 FirstDbgValue = NULL;
const_iterator end(StringRef path)
Get end iterator over path.
virtual void finishBlock()
finishBlock - Clean up after scheduling in the given block.
AnalysisUsage & addPreserved()
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
std::vector< unsigned >::const_iterator livein_iterator
MachineInstr * getInstr() const
virtual ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *, const ScheduleDAG *DAG) const
const_iterator begin(StringRef path)
Get begin iterator over path.
static cl::opt< int > DebugDiv("postra-sched-debugdiv", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
virtual void startBlock(MachineBasicBlock *BB)
startBlock - Prepare to perform scheduling in the given block.
AnalysisUsage & addRequired()
unsigned getBundleSize() const
const HexagonInstrInfo * TII
static cl::opt< bool > EnablePostRAScheduler("post-RA-scheduler", cl::desc("Enable scheduling after register allocation"), cl::init(false), cl::Hidden)
#define llvm_unreachable(msg)
INITIALIZE_PASS(PostRAScheduler,"post-RA-sched","Post RA top-down list latency scheduler", false, false) SchedulePostRATDList
bool isReg() const
isReg - Tests if this is a MO_Register operand.
std::vector< MachineBasicBlock * >::iterator succ_iterator
ID
LLVM Calling Convention Representation.
virtual const InstrItineraryData * getInstrItineraryData() const
unsigned getNumOperands() const
virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the scheduler state for the next scheduling region.
bool isDebugValue() const
void setDepthToAtLeast(unsigned NewDepth)
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
void clearDAG()
clearDAG - clear the DAG state (between regions).
const MachineOperand & getOperand(unsigned i) const
virtual void exitRegion()
Notify that the scheduler has finished scheduling the current region.
STATISTIC(NumNoops,"Number of noops inserted")
succ_iterator succ_begin()
void setIsKill(bool Val=true)
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
virtual const TargetInstrInfo * getInstrInfo() const
const STC & getSubtarget() const
const uint32_t * getRegMask() const
Class AggressiveAntiDepBreaker.
static cl::opt< std::string > EnableAntiDepBreaking("break-anti-dependencies", cl::desc("Break post-RA scheduling anti-dependencies: ""\"critical\", \"all\", or \"none\""), cl::init("none"), cl::Hidden)
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
unsigned getDepth() const
static cl::opt< int > DebugMod("postra-sched-debugmod", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, AntiDepBreakMode &Mode, RegClassVector &CriticalPathRCs) const
virtual ~AntiDepBreaker()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
virtual void getAnalysisUsage(AnalysisUsage &AU) const
bool isCall(QueryType Type=AnyInBundle) const
const TargetMachine & getTarget() const
unsigned getReg() const
getReg - Returns the register number.
SmallVector< SDep, 4 > Succs
BasicBlockListType::iterator iterator
ItTy prior(ItTy it, Dist n)
Machine Instruction Scheduler
const MCRegisterInfo & MRI
StringRef getName() const
bool isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx=0) const
void dump(const ScheduleDAG *G) const
SUnit - Scheduling unit. This is a node in the scheduling DAG.