blob: 33538cec9e8ed8450ac97156d85e60badb7d4022 [file] [log] [blame]
Vikram S. Adve0799fc42001-09-18 12:58:33 +00001//===-- SchedInfo.cpp - Generic code to support target schedulers ----------==//
John Criswellb576c942003-10-20 19:43:21 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Vikram S. Adve0799fc42001-09-18 12:58:33 +00009//
10// This file implements the generic part of a Scheduler description for a
11// target. This functionality is defined in the llvm/Target/SchedInfo.h file.
12//
13//===----------------------------------------------------------------------===//
14
Chris Lattnerd0f166a2002-12-29 03:13:05 +000015#include "llvm/Target/TargetSchedInfo.h"
Chris Lattner884f4b52002-02-03 07:47:05 +000016#include "llvm/Target/TargetMachine.h"
Vikram S. Adve0799fc42001-09-18 12:58:33 +000017
Brian Gaeked0fde302003-11-11 22:41:34 +000018namespace llvm {
19
Vikram S. Adve0799fc42001-09-18 12:58:33 +000020resourceId_t MachineResource::nextId = 0;
21
22// Check if fromRVec and toRVec have *any* common entries.
23// Assume the vectors are sorted in increasing order.
24// Algorithm copied from function set_intersection() for sorted ranges
25// (stl_algo.h).
26//
27inline static bool
Chris Lattner697954c2002-01-20 22:54:45 +000028RUConflict(const std::vector<resourceId_t>& fromRVec,
29 const std::vector<resourceId_t>& toRVec)
Vikram S. Adve0799fc42001-09-18 12:58:33 +000030{
31
32 unsigned fN = fromRVec.size(), tN = toRVec.size();
33 unsigned fi = 0, ti = 0;
34
Misha Brukmanb10cea82003-08-05 00:02:06 +000035 while (fi < fN && ti < tN) {
36 if (fromRVec[fi] < toRVec[ti])
37 ++fi;
38 else if (toRVec[ti] < fromRVec[fi])
39 ++ti;
40 else
41 return true;
42 }
Vikram S. Adve0799fc42001-09-18 12:58:33 +000043 return false;
44}
45
46
47static cycles_t
48ComputeMinGap(const InstrRUsage &fromRU,
49 const InstrRUsage &toRU)
50{
51 cycles_t minGap = 0;
52
53 if (fromRU.numBubbles > 0)
54 minGap = fromRU.numBubbles;
55
Misha Brukmanb10cea82003-08-05 00:02:06 +000056 if (minGap < fromRU.numCycles) {
57 // only need to check from cycle `minGap' onwards
58 for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++) {
59 // check if instr. #2 can start executing `gap' cycles after #1
60 // by checking for resource conflicts in each overlapping cycle
61 cycles_t numOverlap =std::min(fromRU.numCycles - gap, toRU.numCycles);
62 for (cycles_t c = 0; c <= numOverlap-1; c++)
63 if (RUConflict(fromRU.resourcesByCycle[gap + c],
64 toRU.resourcesByCycle[c])) {
65 // conflict found so minGap must be more than `gap'
66 minGap = gap+1;
67 break;
68 }
Vikram S. Adve0799fc42001-09-18 12:58:33 +000069 }
Misha Brukmanb10cea82003-08-05 00:02:06 +000070 }
Vikram S. Adve0799fc42001-09-18 12:58:33 +000071
72 return minGap;
73}
74
75
76//---------------------------------------------------------------------------
Chris Lattnerd0f166a2002-12-29 03:13:05 +000077// class TargetSchedInfo
Vikram S. Adve0799fc42001-09-18 12:58:33 +000078// Interface to machine description for instruction scheduling
79//---------------------------------------------------------------------------
80
Chris Lattnerd0f166a2002-12-29 03:13:05 +000081TargetSchedInfo::TargetSchedInfo(const TargetMachine& tgt,
82 int NumSchedClasses,
83 const InstrClassRUsage* ClassRUsages,
84 const InstrRUsageDelta* UsageDeltas,
85 const InstrIssueDelta* IssueDeltas,
86 unsigned NumUsageDeltas,
87 unsigned NumIssueDeltas)
Vikram S. Adve7a2f1e72001-11-08 05:15:08 +000088 : target(tgt),
89 numSchedClasses(NumSchedClasses), mii(& tgt.getInstrInfo()),
Vikram S. Adve0799fc42001-09-18 12:58:33 +000090 classRUsages(ClassRUsages), usageDeltas(UsageDeltas),
91 issueDeltas(IssueDeltas), numUsageDeltas(NumUsageDeltas),
92 numIssueDeltas(NumIssueDeltas)
93{}
94
95void
Chris Lattnerd0f166a2002-12-29 03:13:05 +000096TargetSchedInfo::initializeResources()
Vikram S. Adve0799fc42001-09-18 12:58:33 +000097{
98 assert(MAX_NUM_SLOTS >= (int)getMaxNumIssueTotal()
99 && "Insufficient slots for static data! Increase MAX_NUM_SLOTS");
100
101 // First, compute common resource usage info for each class because
102 // most instructions will probably behave the same as their class.
103 // Cannot allocate a vector of InstrRUsage so new each one.
104 //
Chris Lattner697954c2002-01-20 22:54:45 +0000105 std::vector<InstrRUsage> instrRUForClasses;
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000106 instrRUForClasses.resize(numSchedClasses);
107 for (InstrSchedClass sc = 0; sc < numSchedClasses; sc++) {
108 // instrRUForClasses.push_back(new InstrRUsage);
109 instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal());
Chris Lattner30587612002-02-04 05:56:30 +0000110 instrRUForClasses[sc].setTo(classRUsages[sc]);
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000111 }
112
113 computeInstrResources(instrRUForClasses);
114 computeIssueGaps(instrRUForClasses);
115}
116
117
118void
Chris Lattnerd0f166a2002-12-29 03:13:05 +0000119TargetSchedInfo::computeInstrResources(const std::vector<InstrRUsage>&
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000120 instrRUForClasses)
121{
Chris Lattnerbceb6882004-02-29 06:31:16 +0000122 int numOpCodes = mii->getNumOpcodes();
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000123 instrRUsages.resize(numOpCodes);
124
125 // First get the resource usage information from the class resource usages.
126 for (MachineOpCode op = 0; op < numOpCodes; ++op) {
127 InstrSchedClass sc = getSchedClass(op);
Chris Lattner07541a22002-10-28 04:59:43 +0000128 assert(sc < numSchedClasses);
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000129 instrRUsages[op] = instrRUForClasses[sc];
130 }
131
132 // Now, modify the resource usages as specified in the deltas.
133 for (unsigned i = 0; i < numUsageDeltas; ++i) {
134 MachineOpCode op = usageDeltas[i].opCode;
135 assert(op < numOpCodes);
136 instrRUsages[op].addUsageDelta(usageDeltas[i]);
137 }
138
139 // Then modify the issue restrictions as specified in the deltas.
140 for (unsigned i = 0; i < numIssueDeltas; ++i) {
141 MachineOpCode op = issueDeltas[i].opCode;
142 assert(op < numOpCodes);
143 instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]);
144 }
145}
146
147
148void
Chris Lattnerd0f166a2002-12-29 03:13:05 +0000149TargetSchedInfo::computeIssueGaps(const std::vector<InstrRUsage>&
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000150 instrRUForClasses)
151{
Chris Lattnerbceb6882004-02-29 06:31:16 +0000152 int numOpCodes = mii->getNumOpcodes();
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000153 issueGaps.resize(numOpCodes);
154 conflictLists.resize(numOpCodes);
155
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000156 assert(numOpCodes < (1 << MAX_OPCODE_SIZE) - 1
157 && "numOpCodes invalid for implementation of class OpCodePair!");
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000158
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000159 // First, compute issue gaps between pairs of classes based on common
160 // resources usages for each class, because most instruction pairs will
161 // usually behave the same as their class.
162 //
163 int classPairGaps[numSchedClasses][numSchedClasses];
164 for (InstrSchedClass fromSC=0; fromSC < numSchedClasses; fromSC++)
Misha Brukmanb10cea82003-08-05 00:02:06 +0000165 for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++) {
166 int classPairGap = ComputeMinGap(instrRUForClasses[fromSC],
167 instrRUForClasses[toSC]);
168 classPairGaps[fromSC][toSC] = classPairGap;
169 }
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000170
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000171 // Now, for each pair of instructions, use the class pair gap if both
172 // instructions have identical resource usage as their respective classes.
173 // If not, recompute the gap for the pair from scratch.
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000174
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000175 longestIssueConflict = 0;
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000176
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000177 for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++)
Misha Brukmanb10cea82003-08-05 00:02:06 +0000178 for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++) {
179 int instrPairGap =
180 (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass)
181 ? classPairGaps[getSchedClass(fromOp)][getSchedClass(toOp)]
182 : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]);
Vikram S. Adve5aefcad2002-10-13 00:37:46 +0000183
Misha Brukmanb10cea82003-08-05 00:02:06 +0000184 if (instrPairGap > 0) {
185 this->setGap(instrPairGap, fromOp, toOp);
186 conflictLists[fromOp].push_back(toOp);
187 longestIssueConflict=std::max(longestIssueConflict, instrPairGap);
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000188 }
Misha Brukmanb10cea82003-08-05 00:02:06 +0000189 }
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000190}
191
Chris Lattner30587612002-02-04 05:56:30 +0000192
193void InstrRUsage::setTo(const InstrClassRUsage& classRU) {
194 sameAsClass = true;
195 isSingleIssue = classRU.isSingleIssue;
196 breaksGroup = classRU.breaksGroup;
197 numBubbles = classRU.numBubbles;
198
Misha Brukmanb10cea82003-08-05 00:02:06 +0000199 for (unsigned i=0; i < classRU.numSlots; i++) {
200 unsigned slot = classRU.feasibleSlots[i];
201 assert(slot < feasibleSlots.size() && "Invalid slot specified!");
202 this->feasibleSlots[slot] = true;
203 }
Chris Lattner30587612002-02-04 05:56:30 +0000204
205 numCycles = classRU.totCycles;
206 resourcesByCycle.resize(this->numCycles);
207
208 for (unsigned i=0; i < classRU.numRUEntries; i++)
209 for (unsigned c=classRU.V[i].startCycle, NC = c + classRU.V[i].numCycles;
210 c < NC; c++)
211 this->resourcesByCycle[c].push_back(classRU.V[i].resourceId);
212
Misha Brukmanb10cea82003-08-05 00:02:06 +0000213 // Sort each resource usage vector by resourceId_t to speed up conflict
214 // checking
Chris Lattner30587612002-02-04 05:56:30 +0000215 for (unsigned i=0; i < this->resourcesByCycle.size(); i++)
216 sort(resourcesByCycle[i].begin(), resourcesByCycle[i].end());
Chris Lattner30587612002-02-04 05:56:30 +0000217}
218
219// Add the extra resource usage requirements specified in the delta.
220// Note that a negative value of `numCycles' means one entry for that
221// resource should be deleted for each cycle.
222//
223void InstrRUsage::addUsageDelta(const InstrRUsageDelta &delta) {
224 int NC = delta.numCycles;
225 sameAsClass = false;
226
227 // resize the resources vector if more cycles are specified
228 unsigned maxCycles = this->numCycles;
229 maxCycles = std::max(maxCycles, delta.startCycle + abs(NC) - 1);
Misha Brukmanb10cea82003-08-05 00:02:06 +0000230 if (maxCycles > this->numCycles) {
231 this->resourcesByCycle.resize(maxCycles);
232 this->numCycles = maxCycles;
233 }
Chris Lattner30587612002-02-04 05:56:30 +0000234
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.
Misha Brukmanb10cea82003-08-05 00:02:06 +0000240 for (unsigned c=delta.startCycle, last=(c-NC)-1; c <= last; c++) {
241 // Look for the resource backwards so we remove the last entry
242 // for that resource in each cycle.
243 std::vector<resourceId_t>& rvec = this->resourcesByCycle[c];
244 int r;
245 for (r = rvec.size() - 1; r >= 0; r--)
246 if (rvec[r] == delta.resourceId) {
247 // found last entry for the resource
248 rvec.erase(rvec.begin() + r);
249 break;
250 }
251 assert(r >= 0 && "Resource to remove was unused in cycle c!");
252 }
Chris Lattner30587612002-02-04 05:56:30 +0000253}
Brian Gaeked0fde302003-11-11 22:41:34 +0000254
255} // End llvm namespace