@@ -18,41 +18,63 @@ using namespace llvm;
18
18
19
19
namespace mca {
20
20
21
- void TimelineView::initialize (unsigned MaxIterations) {
22
- unsigned NumInstructions =
23
- AsmSequence.getNumIterations () * AsmSequence.size ();
21
+ TimelineView::TimelineView (const MCSubtargetInfo &sti, MCInstPrinter &Printer,
22
+ const SourceMgr &S, unsigned MaxIterations,
23
+ unsigned Cycles)
24
+ : STI(sti), MCIP(Printer), AsmSequence(S), CurrentCycle(0 ),
25
+ MaxCycle (Cycles == 0 ? 80 : Cycles), LastCycle(0 ), WaitTime(S.size()),
26
+ UsedBuffer(S.size()) {
27
+ unsigned NumInstructions = AsmSequence.size ();
24
28
if (!MaxIterations)
25
29
MaxIterations = DEFAULT_ITERATIONS;
26
- unsigned NumEntries =
27
- std::min (NumInstructions, MaxIterations * AsmSequence.size ());
28
- Timeline.resize (NumEntries);
29
- TimelineViewEntry NullTVEntry = {0 , 0 , 0 , 0 , 0 };
30
- std::fill (Timeline.begin (), Timeline.end (), NullTVEntry);
31
-
32
- WaitTime.resize (AsmSequence.size ());
33
- WaitTimeEntry NullWTEntry = {0 , 0 , 0 , 0 };
30
+ NumInstructions *= std::min (MaxIterations, AsmSequence.getNumIterations ());
31
+ Timeline.resize (NumInstructions);
32
+
33
+ WaitTimeEntry NullWTEntry = {0 , 0 , 0 };
34
34
std::fill (WaitTime.begin (), WaitTime.end (), NullWTEntry);
35
35
}
36
36
37
+ void TimelineView::onReservedBuffers (const InstRef &IR,
38
+ ArrayRef<unsigned > Buffers) {
39
+ if (IR.getSourceIndex () >= AsmSequence.size ())
40
+ return ;
41
+
42
+ const MCSchedModel &SM = STI.getSchedModel ();
43
+ std::pair<unsigned , unsigned > BufferInfo = {0 , 0 };
44
+ for (const unsigned Buffer : Buffers) {
45
+ const MCProcResourceDesc &MCDesc = *SM.getProcResource (Buffer);
46
+ if (MCDesc.BufferSize <= 0 )
47
+ continue ;
48
+ unsigned OtherSize = static_cast <unsigned >(MCDesc.BufferSize );
49
+ if (!BufferInfo.first || BufferInfo.second > OtherSize) {
50
+ BufferInfo.first = Buffer;
51
+ BufferInfo.second = OtherSize;
52
+ }
53
+ }
54
+
55
+ UsedBuffer[IR.getSourceIndex ()] = BufferInfo;
56
+ }
57
+
37
58
void TimelineView::onEvent (const HWInstructionEvent &Event) {
38
59
const unsigned Index = Event.IR .getSourceIndex ();
39
- if (CurrentCycle >= MaxCycle || Index >= Timeline.size ())
60
+ if (Index >= Timeline.size ())
40
61
return ;
62
+
41
63
switch (Event.Type ) {
42
64
case HWInstructionEvent::Retired: {
43
65
TimelineViewEntry &TVEntry = Timeline[Index];
44
- TVEntry.CycleRetired = CurrentCycle;
66
+ if (CurrentCycle < MaxCycle)
67
+ TVEntry.CycleRetired = CurrentCycle;
45
68
46
69
// Update the WaitTime entry which corresponds to this Index.
47
70
WaitTimeEntry &WTEntry = WaitTime[Index % AsmSequence.size ()];
48
- WTEntry.Executions ++;
49
71
WTEntry.CyclesSpentInSchedulerQueue +=
50
72
TVEntry.CycleIssued - TVEntry.CycleDispatched ;
51
73
assert (TVEntry.CycleDispatched <= TVEntry.CycleReady );
52
74
WTEntry.CyclesSpentInSQWhileReady +=
53
75
TVEntry.CycleIssued - TVEntry.CycleReady ;
54
76
WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
55
- (TVEntry. CycleRetired - 1 ) - TVEntry.CycleExecuted ;
77
+ (CurrentCycle - 1 ) - TVEntry.CycleExecuted ;
56
78
break ;
57
79
}
58
80
case HWInstructionEvent::Ready:
@@ -70,57 +92,83 @@ void TimelineView::onEvent(const HWInstructionEvent &Event) {
70
92
default :
71
93
return ;
72
94
}
73
- LastCycle = std::max (LastCycle, CurrentCycle);
95
+ if (CurrentCycle < MaxCycle)
96
+ LastCycle = std::max (LastCycle, CurrentCycle);
97
+ }
98
+
99
+ static raw_ostream::Colors chooseColor (unsigned CumulativeCycles,
100
+ unsigned Executions,
101
+ unsigned BufferSize) {
102
+ if (CumulativeCycles && BufferSize == 0 )
103
+ return raw_ostream::MAGENTA;
104
+ if (CumulativeCycles >= (BufferSize * Executions))
105
+ return raw_ostream::RED;
106
+ if ((CumulativeCycles * 2 ) >= (BufferSize * Executions))
107
+ return raw_ostream::YELLOW;
108
+ return raw_ostream::SAVEDCOLOR;
109
+ }
110
+
111
+ static void tryChangeColor (raw_ostream &OS, unsigned Cycles,
112
+ unsigned Executions, unsigned BufferSize) {
113
+ if (!OS.has_colors ())
114
+ return ;
115
+
116
+ raw_ostream::Colors Color = chooseColor (Cycles, Executions, BufferSize);
117
+ if (Color == raw_ostream::SAVEDCOLOR) {
118
+ OS.resetColor ();
119
+ return ;
120
+ }
121
+ OS.changeColor (Color, /* bold */ true , /* BG */ false );
74
122
}
75
123
76
124
void TimelineView::printWaitTimeEntry (formatted_raw_ostream &OS,
77
125
const WaitTimeEntry &Entry,
78
- unsigned SourceIndex) const {
126
+ unsigned SourceIndex,
127
+ unsigned Executions) const {
79
128
OS << SourceIndex << ' .' ;
80
129
OS.PadToColumn (7 );
81
130
82
- if (Entry.Executions == 0 ) {
83
- OS << " - - - - " ;
84
- } else {
85
- double AverageTime1, AverageTime2, AverageTime3;
86
- unsigned Executions = Entry.Executions ;
87
- AverageTime1 = (double )Entry.CyclesSpentInSchedulerQueue / Executions;
88
- AverageTime2 = (double )Entry.CyclesSpentInSQWhileReady / Executions;
89
- AverageTime3 = (double )Entry.CyclesSpentAfterWBAndBeforeRetire / Executions;
90
-
91
- OS << Executions;
92
- OS.PadToColumn (13 );
93
-
94
- OS << format (" %.1f" , floor ((AverageTime1 * 10 ) + 0.5 ) / 10 );
95
- OS.PadToColumn (20 );
96
- OS << format (" %.1f" , floor ((AverageTime2 * 10 ) + 0.5 ) / 10 );
97
- OS.PadToColumn (27 );
98
- OS << format (" %.1f" , floor ((AverageTime3 * 10 ) + 0.5 ) / 10 );
99
- OS.PadToColumn (34 );
100
- }
101
- }
131
+ double AverageTime1, AverageTime2, AverageTime3;
132
+ AverageTime1 = (double )Entry.CyclesSpentInSchedulerQueue / Executions;
133
+ AverageTime2 = (double )Entry.CyclesSpentInSQWhileReady / Executions;
134
+ AverageTime3 = (double )Entry.CyclesSpentAfterWBAndBeforeRetire / Executions;
102
135
103
- void TimelineView::printAverageWaitTimes (raw_ostream &OS) const {
104
- if (WaitTime.empty ())
105
- return ;
136
+ OS << Executions;
137
+ OS.PadToColumn (13 );
138
+ unsigned BufferSize = UsedBuffer[SourceIndex].second ;
139
+ tryChangeColor (OS, Entry.CyclesSpentInSchedulerQueue , Executions, BufferSize);
140
+ OS << format (" %.1f" , floor ((AverageTime1 * 10 ) + 0.5 ) / 10 );
141
+ OS.PadToColumn (20 );
142
+ tryChangeColor (OS, Entry.CyclesSpentInSQWhileReady , Executions, BufferSize);
143
+ OS << format (" %.1f" , floor ((AverageTime2 * 10 ) + 0.5 ) / 10 );
144
+ OS.PadToColumn (27 );
145
+ tryChangeColor (OS, Entry.CyclesSpentAfterWBAndBeforeRetire , Executions,
146
+ STI.getSchedModel ().MicroOpBufferSize );
147
+ OS << format (" %.1f" , floor ((AverageTime3 * 10 ) + 0.5 ) / 10 );
106
148
107
- std::string Buffer;
108
- raw_string_ostream TempStream (Buffer);
109
- formatted_raw_ostream FOS (TempStream);
149
+ if (OS.has_colors ())
150
+ OS.resetColor ();
151
+ OS.PadToColumn (34 );
152
+ }
110
153
111
- FOS << " \n\n Average Wait times (based on the timeline view):\n "
112
- << " [0]: Executions\n "
113
- << " [1]: Average time spent waiting in a scheduler's queue\n "
114
- << " [2]: Average time spent waiting in a scheduler's queue while ready\n "
115
- << " [3]: Average time elapsed from WB until retire stage\n\n " ;
116
- FOS << " [0] [1] [2] [3]\n " ;
154
+ void TimelineView::printAverageWaitTimes (raw_ostream &OS) const {
155
+ std::string Header =
156
+ " \n\n Average Wait times (based on the timeline view):\n "
157
+ " [0]: Executions\n "
158
+ " [1]: Average time spent waiting in a scheduler's queue\n "
159
+ " [2]: Average time spent waiting in a scheduler's queue while ready\n "
160
+ " [3]: Average time elapsed from WB until retire stage\n\n "
161
+ " [0] [1] [2] [3]\n " ;
162
+ OS << Header;
117
163
118
- // Use a different string stream for the instruction .
164
+ // Use a different string stream for printing instructions .
119
165
std::string Instruction;
120
166
raw_string_ostream InstrStream (Instruction);
121
167
168
+ formatted_raw_ostream FOS (OS);
169
+ unsigned Executions = Timeline.size () / AsmSequence.size ();
122
170
for (unsigned I = 0 , E = WaitTime.size (); I < E; ++I) {
123
- printWaitTimeEntry (FOS, WaitTime[I], I);
171
+ printWaitTimeEntry (FOS, WaitTime[I], I, Executions );
124
172
// Append the instruction info at the end of the line.
125
173
const MCInst &Inst = AsmSequence.getMCInstFromIndex (I);
126
174
@@ -133,9 +181,6 @@ void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
133
181
FOS << " " << Str << ' \n ' ;
134
182
FOS.flush ();
135
183
Instruction = " " ;
136
-
137
- OS << Buffer;
138
- Buffer = " " ;
139
184
}
140
185
}
141
186
@@ -202,20 +247,15 @@ static void printTimelineHeader(formatted_raw_ostream &OS, unsigned Cycles) {
202
247
}
203
248
204
249
void TimelineView::printTimeline (raw_ostream &OS) const {
205
- std::string Buffer;
206
- raw_string_ostream StringStream (Buffer);
207
- formatted_raw_ostream FOS (StringStream);
208
-
250
+ formatted_raw_ostream FOS (OS);
209
251
printTimelineHeader (FOS, LastCycle);
210
252
FOS.flush ();
211
- OS << Buffer;
212
253
213
254
// Use a different string stream for the instruction.
214
255
std::string Instruction;
215
256
raw_string_ostream InstrStream (Instruction);
216
257
217
258
for (unsigned I = 0 , E = Timeline.size (); I < E; ++I) {
218
- Buffer = " " ;
219
259
const TimelineViewEntry &Entry = Timeline[I];
220
260
if (Entry.CycleRetired == 0 )
221
261
return ;
@@ -234,7 +274,6 @@ void TimelineView::printTimeline(raw_ostream &OS) const {
234
274
FOS << " " << Str << ' \n ' ;
235
275
FOS.flush ();
236
276
Instruction = " " ;
237
- OS << Buffer;
238
277
}
239
278
}
240
279
} // namespace mca
0 commit comments