Mercurial > hg > CbC > CbC_llvm
comparison lib/Target/SystemZ/SystemZMachineScheduler.cpp @ 121:803732b1fca8
LLVM 5.0
author | kono |
---|---|
date | Fri, 27 Oct 2017 17:07:41 +0900 |
parents | 1172e4bd9c6f |
children | 3a76565eade5 |
comparison
equal
deleted
inserted
replaced
120:1172e4bd9c6f | 121:803732b1fca8 |
---|---|
9 // | 9 // |
10 // -------------------------- Post RA scheduling ---------------------------- // | 10 // -------------------------- Post RA scheduling ---------------------------- // |
11 // SystemZPostRASchedStrategy is a scheduling strategy which is plugged into | 11 // SystemZPostRASchedStrategy is a scheduling strategy which is plugged into |
12 // the MachineScheduler. It has a sorted Available set of SUs and a pickNode() | 12 // the MachineScheduler. It has a sorted Available set of SUs and a pickNode() |
13 // implementation that looks to optimize decoder grouping and balance the | 13 // implementation that looks to optimize decoder grouping and balance the |
14 // usage of processor resources. | 14 // usage of processor resources. Scheduler states are saved for the end |
15 // region of each MBB, so that a successor block can learn from it. | |
15 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
16 | 17 |
17 #include "SystemZMachineScheduler.h" | 18 #include "SystemZMachineScheduler.h" |
18 | 19 |
19 using namespace llvm; | 20 using namespace llvm; |
20 | 21 |
21 #define DEBUG_TYPE "misched" | 22 #define DEBUG_TYPE "machine-scheduler" |
22 | 23 |
23 #ifndef NDEBUG | 24 #ifndef NDEBUG |
24 // Print the set of SUs | 25 // Print the set of SUs |
25 void SystemZPostRASchedStrategy::SUSet:: | 26 void SystemZPostRASchedStrategy::SUSet:: |
26 dump(SystemZHazardRecognizer &HazardRec) { | 27 dump(SystemZHazardRecognizer &HazardRec) const { |
27 dbgs() << "{"; | 28 dbgs() << "{"; |
28 for (auto &SU : *this) { | 29 for (auto &SU : *this) { |
29 HazardRec.dumpSU(SU, dbgs()); | 30 HazardRec.dumpSU(SU, dbgs()); |
30 if (SU != *rbegin()) | 31 if (SU != *rbegin()) |
31 dbgs() << ", "; | 32 dbgs() << ", "; |
32 } | 33 } |
33 dbgs() << "}\n"; | 34 dbgs() << "}\n"; |
34 } | 35 } |
35 #endif | 36 #endif |
36 | 37 |
38 // Try to find a single predecessor that would be interesting for the | |
39 // scheduler in the top-most region of MBB. | |
40 static MachineBasicBlock *getSingleSchedPred(MachineBasicBlock *MBB, | |
41 const MachineLoop *Loop) { | |
42 MachineBasicBlock *PredMBB = nullptr; | |
43 if (MBB->pred_size() == 1) | |
44 PredMBB = *MBB->pred_begin(); | |
45 | |
46 // The loop header has two predecessors, return the latch, but not for a | |
47 // single block loop. | |
48 if (MBB->pred_size() == 2 && Loop != nullptr && Loop->getHeader() == MBB) { | |
49 for (auto I = MBB->pred_begin(); I != MBB->pred_end(); ++I) | |
50 if (Loop->contains(*I)) | |
51 PredMBB = (*I == MBB ? nullptr : *I); | |
52 } | |
53 | |
54 assert ((PredMBB == nullptr || !Loop || Loop->contains(PredMBB)) | |
55 && "Loop MBB should not consider predecessor outside of loop."); | |
56 | |
57 return PredMBB; | |
58 } | |
59 | |
60 void SystemZPostRASchedStrategy:: | |
61 advanceTo(MachineBasicBlock::iterator NextBegin) { | |
62 MachineBasicBlock::iterator LastEmittedMI = HazardRec->getLastEmittedMI(); | |
63 MachineBasicBlock::iterator I = | |
64 ((LastEmittedMI != nullptr && LastEmittedMI->getParent() == MBB) ? | |
65 std::next(LastEmittedMI) : MBB->begin()); | |
66 | |
67 for (; I != NextBegin; ++I) { | |
68 if (I->isPosition() || I->isDebugValue()) | |
69 continue; | |
70 HazardRec->emitInstruction(&*I); | |
71 } | |
72 } | |
73 | |
74 void SystemZPostRASchedStrategy::enterMBB(MachineBasicBlock *NextMBB) { | |
75 assert ((SchedStates.find(NextMBB) == SchedStates.end()) && | |
76 "Entering MBB twice?"); | |
77 DEBUG (dbgs() << "+++ Entering MBB#" << NextMBB->getNumber()); | |
78 | |
79 MBB = NextMBB; | |
80 /// Create a HazardRec for MBB, save it in SchedStates and set HazardRec to | |
81 /// point to it. | |
82 HazardRec = SchedStates[MBB] = new SystemZHazardRecognizer(TII, &SchedModel); | |
83 DEBUG (const MachineLoop *Loop = MLI->getLoopFor(MBB); | |
84 if(Loop && Loop->getHeader() == MBB) | |
85 dbgs() << " (Loop header)"; | |
86 dbgs() << ":\n";); | |
87 | |
88 // Try to take over the state from a single predecessor, if it has been | |
89 // scheduled. If this is not possible, we are done. | |
90 MachineBasicBlock *SinglePredMBB = | |
91 getSingleSchedPred(MBB, MLI->getLoopFor(MBB)); | |
92 if (SinglePredMBB == nullptr || | |
93 SchedStates.find(SinglePredMBB) == SchedStates.end()) | |
94 return; | |
95 | |
96 DEBUG (dbgs() << "+++ Continued scheduling from MBB#" | |
97 << SinglePredMBB->getNumber() << "\n";); | |
98 | |
99 HazardRec->copyState(SchedStates[SinglePredMBB]); | |
100 | |
101 // Emit incoming terminator(s). Be optimistic and assume that branch | |
102 // prediction will generally do "the right thing". | |
103 for (MachineBasicBlock::iterator I = SinglePredMBB->getFirstTerminator(); | |
104 I != SinglePredMBB->end(); I++) { | |
105 DEBUG (dbgs() << "+++ Emitting incoming branch: "; I->dump();); | |
106 bool TakenBranch = (I->isBranch() && | |
107 (TII->getBranchInfo(*I).Target->isReg() || // Relative branch | |
108 TII->getBranchInfo(*I).Target->getMBB() == MBB)); | |
109 HazardRec->emitInstruction(&*I, TakenBranch); | |
110 if (TakenBranch) | |
111 break; | |
112 } | |
113 } | |
114 | |
115 void SystemZPostRASchedStrategy::leaveMBB() { | |
116 DEBUG (dbgs() << "+++ Leaving MBB#" << MBB->getNumber() << "\n";); | |
117 | |
118 // Advance to first terminator. The successor block will handle terminators | |
119 // dependent on CFG layout (T/NT branch etc). | |
120 advanceTo(MBB->getFirstTerminator()); | |
121 } | |
122 | |
37 SystemZPostRASchedStrategy:: | 123 SystemZPostRASchedStrategy:: |
38 SystemZPostRASchedStrategy(const MachineSchedContext *C) | 124 SystemZPostRASchedStrategy(const MachineSchedContext *C) |
39 : DAG(nullptr), HazardRec(C) {} | 125 : MLI(C->MLI), |
40 | 126 TII(static_cast<const SystemZInstrInfo *> |
41 void SystemZPostRASchedStrategy::initialize(ScheduleDAGMI *dag) { | 127 (C->MF->getSubtarget().getInstrInfo())), |
42 DAG = dag; | 128 MBB(nullptr), HazardRec(nullptr) { |
43 HazardRec.setDAG(dag); | 129 const TargetSubtargetInfo *ST = &C->MF->getSubtarget(); |
44 HazardRec.Reset(); | 130 SchedModel.init(ST->getSchedModel(), ST, TII); |
131 } | |
132 | |
133 SystemZPostRASchedStrategy::~SystemZPostRASchedStrategy() { | |
134 // Delete hazard recognizers kept around for each MBB. | |
135 for (auto I : SchedStates) { | |
136 SystemZHazardRecognizer *hazrec = I.second; | |
137 delete hazrec; | |
138 } | |
139 } | |
140 | |
141 void SystemZPostRASchedStrategy::initPolicy(MachineBasicBlock::iterator Begin, | |
142 MachineBasicBlock::iterator End, | |
143 unsigned NumRegionInstrs) { | |
144 // Don't emit the terminators. | |
145 if (Begin->isTerminator()) | |
146 return; | |
147 | |
148 // Emit any instructions before start of region. | |
149 advanceTo(Begin); | |
45 } | 150 } |
46 | 151 |
47 // Pick the next node to schedule. | 152 // Pick the next node to schedule. |
48 SUnit *SystemZPostRASchedStrategy::pickNode(bool &IsTopNode) { | 153 SUnit *SystemZPostRASchedStrategy::pickNode(bool &IsTopNode) { |
49 // Only scheduling top-down. | 154 // Only scheduling top-down. |
53 return nullptr; | 158 return nullptr; |
54 | 159 |
55 // If only one choice, return it. | 160 // If only one choice, return it. |
56 if (Available.size() == 1) { | 161 if (Available.size() == 1) { |
57 DEBUG (dbgs() << "+++ Only one: "; | 162 DEBUG (dbgs() << "+++ Only one: "; |
58 HazardRec.dumpSU(*Available.begin(), dbgs()); dbgs() << "\n";); | 163 HazardRec->dumpSU(*Available.begin(), dbgs()); dbgs() << "\n";); |
59 return *Available.begin(); | 164 return *Available.begin(); |
60 } | 165 } |
61 | 166 |
62 // All nodes that are possible to schedule are stored by in the | 167 // All nodes that are possible to schedule are stored by in the |
63 // Available set. | 168 // Available set. |
64 DEBUG(dbgs() << "+++ Available: "; Available.dump(HazardRec);); | 169 DEBUG(dbgs() << "+++ Available: "; Available.dump(*HazardRec);); |
65 | 170 |
66 Candidate Best; | 171 Candidate Best; |
67 for (auto *SU : Available) { | 172 for (auto *SU : Available) { |
68 | 173 |
69 // SU is the next candidate to be compared against current Best. | 174 // SU is the next candidate to be compared against current Best. |
70 Candidate c(SU, HazardRec); | 175 Candidate c(SU, *HazardRec); |
71 | 176 |
72 // Remeber which SU is the best candidate. | 177 // Remeber which SU is the best candidate. |
73 if (Best.SU == nullptr || c < Best) { | 178 if (Best.SU == nullptr || c < Best) { |
74 Best = c; | 179 Best = c; |
75 DEBUG(dbgs() << "+++ Best sofar: "; | 180 DEBUG(dbgs() << "+++ Best sofar: "; |
76 HazardRec.dumpSU(Best.SU, dbgs()); | 181 HazardRec->dumpSU(Best.SU, dbgs()); |
77 if (Best.GroupingCost != 0) | 182 if (Best.GroupingCost != 0) |
78 dbgs() << "\tGrouping cost:" << Best.GroupingCost; | 183 dbgs() << "\tGrouping cost:" << Best.GroupingCost; |
79 if (Best.ResourcesCost != 0) | 184 if (Best.ResourcesCost != 0) |
80 dbgs() << " Resource cost:" << Best.ResourcesCost; | 185 dbgs() << " Resource cost:" << Best.ResourcesCost; |
81 dbgs() << " Height:" << Best.SU->getHeight(); | 186 dbgs() << " Height:" << Best.SU->getHeight(); |
136 void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) { | 241 void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) { |
137 DEBUG(dbgs() << "+++ Scheduling SU(" << SU->NodeNum << ")\n";); | 242 DEBUG(dbgs() << "+++ Scheduling SU(" << SU->NodeNum << ")\n";); |
138 | 243 |
139 // Remove SU from Available set and update HazardRec. | 244 // Remove SU from Available set and update HazardRec. |
140 Available.erase(SU); | 245 Available.erase(SU); |
141 HazardRec.EmitInstruction(SU); | 246 HazardRec->EmitInstruction(SU); |
142 } | 247 } |
143 | 248 |
144 void SystemZPostRASchedStrategy::releaseTopNode(SUnit *SU) { | 249 void SystemZPostRASchedStrategy::releaseTopNode(SUnit *SU) { |
145 // Set isScheduleHigh flag on all SUs that we want to consider first in | 250 // Set isScheduleHigh flag on all SUs that we want to consider first in |
146 // pickNode(). | 251 // pickNode(). |
147 const MCSchedClassDesc *SC = DAG->getSchedClass(SU); | 252 const MCSchedClassDesc *SC = HazardRec->getSchedClass(SU); |
148 bool AffectsGrouping = (SC->isValid() && (SC->BeginGroup || SC->EndGroup)); | 253 bool AffectsGrouping = (SC->isValid() && (SC->BeginGroup || SC->EndGroup)); |
149 SU->isScheduleHigh = (AffectsGrouping || SU->isUnbuffered); | 254 SU->isScheduleHigh = (AffectsGrouping || SU->isUnbuffered); |
150 | 255 |
151 // Put all released SUs in the Available set. | 256 // Put all released SUs in the Available set. |
152 Available.insert(SU); | 257 Available.insert(SU); |