blob: d64652398ae7421eb8b7cb7e5220ecf127b4377b [file] [log] [blame]
Vikram S. Adve0799fc42001-09-18 12:58:33 +00001//===-- SchedInfo.cpp - Generic code to support target schedulers ----------==//
2//
3// This file implements the generic part of a Scheduler description for a
4// target. This functionality is defined in the llvm/Target/SchedInfo.h file.
5//
6//===----------------------------------------------------------------------===//
7
Chris Lattnerd0f166a2002-12-29 03:13:05 +00008#include "llvm/Target/TargetSchedInfo.h"
Chris Lattner884f4b52002-02-03 07:47:05 +00009#include "llvm/Target/TargetMachine.h"
Vikram S. Adve0799fc42001-09-18 12:58:33 +000010
Vikram S. Adve0799fc42001-09-18 12:58:33 +000011resourceId_t MachineResource::nextId = 0;
12
13// Check if fromRVec and toRVec have *any* common entries.
14// Assume the vectors are sorted in increasing order.
15// Algorithm copied from function set_intersection() for sorted ranges
16// (stl_algo.h).
17//
18inline static bool
Chris Lattner697954c2002-01-20 22:54:45 +000019RUConflict(const std::vector<resourceId_t>& fromRVec,
20 const std::vector<resourceId_t>& toRVec)
Vikram S. Adve0799fc42001-09-18 12:58:33 +000021{
22
23 unsigned fN = fromRVec.size(), tN = toRVec.size();
24 unsigned fi = 0, ti = 0;
25
26 while (fi < fN && ti < tN)
27 {
28 if (fromRVec[fi] < toRVec[ti])
29 ++fi;
30 else if (toRVec[ti] < fromRVec[fi])
31 ++ti;
32 else
33 return true;
34 }
35 return false;
36}
37
38
39static cycles_t
40ComputeMinGap(const InstrRUsage &fromRU,
41 const InstrRUsage &toRU)
42{
43 cycles_t minGap = 0;
44
45 if (fromRU.numBubbles > 0)
46 minGap = fromRU.numBubbles;
47
48 if (minGap < fromRU.numCycles)
49 {
50 // only need to check from cycle `minGap' onwards
51 for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++)
52 {
53 // check if instr. #2 can start executing `gap' cycles after #1
54 // by checking for resource conflicts in each overlapping cycle
Chris Lattner697954c2002-01-20 22:54:45 +000055 cycles_t numOverlap =std::min(fromRU.numCycles - gap, toRU.numCycles);
Vikram S. Adve0799fc42001-09-18 12:58:33 +000056 for (cycles_t c = 0; c <= numOverlap-1; c++)
57 if (RUConflict(fromRU.resourcesByCycle[gap + c],
58 toRU.resourcesByCycle[c]))
59 {
60 // conflict found so minGap must be more than `gap'
61 minGap = gap+1;
62 break;
63 }
64 }
65 }
66
67 return minGap;
68}
69
70
71//---------------------------------------------------------------------------
Chris Lattnerd0f166a2002-12-29 03:13:05 +000072// class TargetSchedInfo
Vikram S. Adve0799fc42001-09-18 12:58:33 +000073// Interface to machine description for instruction scheduling
74//---------------------------------------------------------------------------
75
Chris Lattnerd0f166a2002-12-29 03:13:05 +000076TargetSchedInfo::TargetSchedInfo(const TargetMachine& tgt,
77 int NumSchedClasses,
78 const InstrClassRUsage* ClassRUsages,
79 const InstrRUsageDelta* UsageDeltas,
80 const InstrIssueDelta* IssueDeltas,
81 unsigned NumUsageDeltas,
82 unsigned NumIssueDeltas)
Vikram S. Adve7a2f1e72001-11-08 05:15:08 +000083 : target(tgt),
84 numSchedClasses(NumSchedClasses), mii(& tgt.getInstrInfo()),
Vikram S. Adve0799fc42001-09-18 12:58:33 +000085 classRUsages(ClassRUsages), usageDeltas(UsageDeltas),
86 issueDeltas(IssueDeltas), numUsageDeltas(NumUsageDeltas),
87 numIssueDeltas(NumIssueDeltas)
88{}
89
90void
Chris Lattnerd0f166a2002-12-29 03:13:05 +000091TargetSchedInfo::initializeResources()
Vikram S. Adve0799fc42001-09-18 12:58:33 +000092{
93 assert(MAX_NUM_SLOTS >= (int)getMaxNumIssueTotal()
94 && "Insufficient slots for static data! Increase MAX_NUM_SLOTS");
95
96 // First, compute common resource usage info for each class because
97 // most instructions will probably behave the same as their class.
98 // Cannot allocate a vector of InstrRUsage so new each one.
99 //
Chris Lattner697954c2002-01-20 22:54:45 +0000100 std::vector<InstrRUsage> instrRUForClasses;
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000101 instrRUForClasses.resize(numSchedClasses);
102 for (InstrSchedClass sc = 0; sc < numSchedClasses; sc++) {
103 // instrRUForClasses.push_back(new InstrRUsage);
104 instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal());
Chris Lattner30587612002-02-04 05:56:30 +0000105 instrRUForClasses[sc].setTo(classRUsages[sc]);
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000106 }
107
108 computeInstrResources(instrRUForClasses);
109 computeIssueGaps(instrRUForClasses);
110}
111
112
113void
Chris Lattnerd0f166a2002-12-29 03:13:05 +0000114TargetSchedInfo::computeInstrResources(const std::vector<InstrRUsage>&
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000115 instrRUForClasses)
116{
117 int numOpCodes = mii->getNumRealOpCodes();
118 instrRUsages.resize(numOpCodes);
119
120 // First get the resource usage information from the class resource usages.
121 for (MachineOpCode op = 0; op < numOpCodes; ++op) {
122 InstrSchedClass sc = getSchedClass(op);
Chris Lattner07541a22002-10-28 04:59:43 +0000123 assert(sc < numSchedClasses);
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000124 instrRUsages[op] = instrRUForClasses[sc];
125 }
126
127 // Now, modify the resource usages as specified in the deltas.
128 for (unsigned i = 0; i < numUsageDeltas; ++i) {
129 MachineOpCode op = usageDeltas[i].opCode;
130 assert(op < numOpCodes);
131 instrRUsages[op].addUsageDelta(usageDeltas[i]);
132 }
133
134 // Then modify the issue restrictions as specified in the deltas.
135 for (unsigned i = 0; i < numIssueDeltas; ++i) {
136 MachineOpCode op = issueDeltas[i].opCode;
137 assert(op < numOpCodes);
138 instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]);
139 }
140}
141
142
143void
Chris Lattnerd0f166a2002-12-29 03:13:05 +0000144TargetSchedInfo::computeIssueGaps(const std::vector<InstrRUsage>&
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000145 instrRUForClasses)
146{
147 int numOpCodes = mii->getNumRealOpCodes();
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000148 issueGaps.resize(numOpCodes);
149 conflictLists.resize(numOpCodes);
150
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000151 assert(numOpCodes < (1 << MAX_OPCODE_SIZE) - 1
152 && "numOpCodes invalid for implementation of class OpCodePair!");
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000153
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000154 // First, compute issue gaps between pairs of classes based on common
155 // resources usages for each class, because most instruction pairs will
156 // usually behave the same as their class.
157 //
158 int classPairGaps[numSchedClasses][numSchedClasses];
159 for (InstrSchedClass fromSC=0; fromSC < numSchedClasses; fromSC++)
160 for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++)
161 {
162 int classPairGap = ComputeMinGap(instrRUForClasses[fromSC],
163 instrRUForClasses[toSC]);
164 classPairGaps[fromSC][toSC] = classPairGap;
165 }
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000166
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000167 // Now, for each pair of instructions, use the class pair gap if both
168 // instructions have identical resource usage as their respective classes.
169 // If not, recompute the gap for the pair from scratch.
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000170
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000171 longestIssueConflict = 0;
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000172
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000173 for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++)
174 for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++)
175 {
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000176 int instrPairGap =
177 (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass)
178 ? classPairGaps[getSchedClass(fromOp)][getSchedClass(toOp)]
179 : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]);
180
181 if (instrPairGap > 0)
182 {
183 this->setGap(instrPairGap, fromOp, toOp);
184 conflictLists[fromOp].push_back(toOp);
185 longestIssueConflict=std::max(longestIssueConflict, instrPairGap);
186 }
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000187 }
188}
189
Chris Lattner30587612002-02-04 05:56:30 +0000190
191void InstrRUsage::setTo(const InstrClassRUsage& classRU) {
192 sameAsClass = true;
193 isSingleIssue = classRU.isSingleIssue;
194 breaksGroup = classRU.breaksGroup;
195 numBubbles = classRU.numBubbles;
196
197 for (unsigned i=0; i < classRU.numSlots; i++)
198 {
199 unsigned slot = classRU.feasibleSlots[i];
200 assert(slot < feasibleSlots.size() && "Invalid slot specified!");
201 this->feasibleSlots[slot] = true;
202 }
203
204 numCycles = classRU.totCycles;
205 resourcesByCycle.resize(this->numCycles);
206
207 for (unsigned i=0; i < classRU.numRUEntries; i++)
208 for (unsigned c=classRU.V[i].startCycle, NC = c + classRU.V[i].numCycles;
209 c < NC; c++)
210 this->resourcesByCycle[c].push_back(classRU.V[i].resourceId);
211
212 // Sort each resource usage vector by resourceId_t to speed up conflict checking
213 for (unsigned i=0; i < this->resourcesByCycle.size(); i++)
214 sort(resourcesByCycle[i].begin(), resourcesByCycle[i].end());
215
216}
217
218// Add the extra resource usage requirements specified in the delta.
219// Note that a negative value of `numCycles' means one entry for that
220// resource should be deleted for each cycle.
221//
222void InstrRUsage::addUsageDelta(const InstrRUsageDelta &delta) {
223 int NC = delta.numCycles;
224 sameAsClass = false;
225
226 // resize the resources vector if more cycles are specified
227 unsigned maxCycles = this->numCycles;
228 maxCycles = std::max(maxCycles, delta.startCycle + abs(NC) - 1);
229 if (maxCycles > this->numCycles)
230 {
231 this->resourcesByCycle.resize(maxCycles);
232 this->numCycles = maxCycles;
233 }
234
235 if (NC >= 0)
236 for (unsigned c=delta.startCycle, last=c+NC-1; c <= last; c++)
237 this->resourcesByCycle[c].push_back(delta.resourceId);
238 else
239 // Remove the resource from all NC cycles.
240 for (unsigned c=delta.startCycle, last=(c-NC)-1; c <= last; c++)
241 {
242 // Look for the resource backwards so we remove the last entry
243 // for that resource in each cycle.
244 std::vector<resourceId_t>& rvec = this->resourcesByCycle[c];
245 int r;
246 for (r = (int) rvec.size(); r >= 0; r--)
247 if (rvec[r] == delta.resourceId)
248 {// found last entry for the resource
249 rvec.erase(rvec.begin() + r);
250 break;
251 }
252 assert(r >= 0 && "Resource to remove was unused in cycle c!");
253 }
254}