blob: 41d013e6389eb4fb5c848af67344ab73c128ceb4 [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
8#include "llvm/Target/MachineSchedInfo.h"
Chris Lattner884f4b52002-02-03 07:47:05 +00009#include "llvm/Target/TargetMachine.h"
Vikram S. Adve0799fc42001-09-18 12:58:33 +000010
11// External object describing the machine instructions
12// Initialized only when the TargetMachine class is created
13// and reset when that class is destroyed.
14//
15const MachineInstrDescriptor* TargetInstrDescriptors = 0;
16
17resourceId_t MachineResource::nextId = 0;
18
19// Check if fromRVec and toRVec have *any* common entries.
20// Assume the vectors are sorted in increasing order.
21// Algorithm copied from function set_intersection() for sorted ranges
22// (stl_algo.h).
23//
24inline static bool
Chris Lattner697954c2002-01-20 22:54:45 +000025RUConflict(const std::vector<resourceId_t>& fromRVec,
26 const std::vector<resourceId_t>& toRVec)
Vikram S. Adve0799fc42001-09-18 12:58:33 +000027{
28
29 unsigned fN = fromRVec.size(), tN = toRVec.size();
30 unsigned fi = 0, ti = 0;
31
32 while (fi < fN && ti < tN)
33 {
34 if (fromRVec[fi] < toRVec[ti])
35 ++fi;
36 else if (toRVec[ti] < fromRVec[fi])
37 ++ti;
38 else
39 return true;
40 }
41 return false;
42}
43
44
45static cycles_t
46ComputeMinGap(const InstrRUsage &fromRU,
47 const InstrRUsage &toRU)
48{
49 cycles_t minGap = 0;
50
51 if (fromRU.numBubbles > 0)
52 minGap = fromRU.numBubbles;
53
54 if (minGap < fromRU.numCycles)
55 {
56 // only need to check from cycle `minGap' onwards
57 for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++)
58 {
59 // check if instr. #2 can start executing `gap' cycles after #1
60 // by checking for resource conflicts in each overlapping cycle
Chris Lattner697954c2002-01-20 22:54:45 +000061 cycles_t numOverlap =std::min(fromRU.numCycles - gap, toRU.numCycles);
Vikram S. Adve0799fc42001-09-18 12:58:33 +000062 for (cycles_t c = 0; c <= numOverlap-1; c++)
63 if (RUConflict(fromRU.resourcesByCycle[gap + c],
64 toRU.resourcesByCycle[c]))
65 {
66 // conflict found so minGap must be more than `gap'
67 minGap = gap+1;
68 break;
69 }
70 }
71 }
72
73 return minGap;
74}
75
76
77//---------------------------------------------------------------------------
78// class MachineSchedInfo
79// Interface to machine description for instruction scheduling
80//---------------------------------------------------------------------------
81
Vikram S. Adve7a2f1e72001-11-08 05:15:08 +000082MachineSchedInfo::MachineSchedInfo(const TargetMachine& tgt,
83 int NumSchedClasses,
Vikram S. Adve0799fc42001-09-18 12:58:33 +000084 const InstrClassRUsage* ClassRUsages,
85 const InstrRUsageDelta* UsageDeltas,
86 const InstrIssueDelta* IssueDeltas,
87 unsigned int NumUsageDeltas,
88 unsigned int NumIssueDeltas)
Vikram S. Adve7a2f1e72001-11-08 05:15:08 +000089 : target(tgt),
90 numSchedClasses(NumSchedClasses), mii(& tgt.getInstrInfo()),
Vikram S. Adve0799fc42001-09-18 12:58:33 +000091 classRUsages(ClassRUsages), usageDeltas(UsageDeltas),
92 issueDeltas(IssueDeltas), numUsageDeltas(NumUsageDeltas),
93 numIssueDeltas(NumIssueDeltas)
94{}
95
96void
97MachineSchedInfo::initializeResources()
98{
99 assert(MAX_NUM_SLOTS >= (int)getMaxNumIssueTotal()
100 && "Insufficient slots for static data! Increase MAX_NUM_SLOTS");
101
102 // First, compute common resource usage info for each class because
103 // most instructions will probably behave the same as their class.
104 // Cannot allocate a vector of InstrRUsage so new each one.
105 //
Chris Lattner697954c2002-01-20 22:54:45 +0000106 std::vector<InstrRUsage> instrRUForClasses;
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000107 instrRUForClasses.resize(numSchedClasses);
108 for (InstrSchedClass sc = 0; sc < numSchedClasses; sc++) {
109 // instrRUForClasses.push_back(new InstrRUsage);
110 instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal());
111 instrRUForClasses[sc] = classRUsages[sc];
112 }
113
114 computeInstrResources(instrRUForClasses);
115 computeIssueGaps(instrRUForClasses);
116}
117
118
119void
Chris Lattner697954c2002-01-20 22:54:45 +0000120MachineSchedInfo::computeInstrResources(const std::vector<InstrRUsage>&
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000121 instrRUForClasses)
122{
123 int numOpCodes = mii->getNumRealOpCodes();
124 instrRUsages.resize(numOpCodes);
125
126 // First get the resource usage information from the class resource usages.
127 for (MachineOpCode op = 0; op < numOpCodes; ++op) {
128 InstrSchedClass sc = getSchedClass(op);
129 assert(sc >= 0 && sc < numSchedClasses);
130 instrRUsages[op] = instrRUForClasses[sc];
131 }
132
133 // Now, modify the resource usages as specified in the deltas.
134 for (unsigned i = 0; i < numUsageDeltas; ++i) {
135 MachineOpCode op = usageDeltas[i].opCode;
136 assert(op < numOpCodes);
137 instrRUsages[op].addUsageDelta(usageDeltas[i]);
138 }
139
140 // Then modify the issue restrictions as specified in the deltas.
141 for (unsigned i = 0; i < numIssueDeltas; ++i) {
142 MachineOpCode op = issueDeltas[i].opCode;
143 assert(op < numOpCodes);
144 instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]);
145 }
146}
147
148
149void
Chris Lattner697954c2002-01-20 22:54:45 +0000150MachineSchedInfo::computeIssueGaps(const std::vector<InstrRUsage>&
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000151 instrRUForClasses)
152{
153 int numOpCodes = mii->getNumRealOpCodes();
154 instrRUsages.resize(numOpCodes);
155
156 assert(numOpCodes < (1 << MAX_OPCODE_SIZE) - 1
157 && "numOpCodes invalid for implementation of class OpCodePair!");
158
159 // 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++)
165 for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++)
166 {
167 int classPairGap = ComputeMinGap(instrRUForClasses[fromSC],
168 instrRUForClasses[toSC]);
169 classPairGaps[fromSC][toSC] = classPairGap;
170 }
171
172 // Now, for each pair of instructions, use the class pair gap if both
173 // instructions have identical resource usage as their respective classes.
174 // If not, recompute the gap for the pair from scratch.
175
176 longestIssueConflict = 0;
177
178 for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++)
179 for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++)
180 {
181 int instrPairGap =
182 (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass)
183 ? classPairGaps[getSchedClass(fromOp)][getSchedClass(toOp)]
184 : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]);
185
186 if (instrPairGap > 0)
187 {
188 issueGaps[OpCodePair(fromOp,toOp)] = instrPairGap;
189 conflictLists[fromOp].push_back(toOp);
Chris Lattner697954c2002-01-20 22:54:45 +0000190 longestIssueConflict = std::max(longestIssueConflict, instrPairGap);
Vikram S. Adve0799fc42001-09-18 12:58:33 +0000191 }
192 }
193}
194