Skip to content

Commit 8fb6767

Browse files
[MCA] Rework InstructionInfoView printing to be able to add full view
Option instruction-tables is an enumeration now but legacy behavior (boolean) is kept available. New option: -instruction-tables=<none,normal,full>. -instruction-tables is equivalent to -instruction-tables=normal. -instruction-tables=none is the default. -instruction-tables=full is equivalent to: -instruction-tables and -scheduling-info -sheduling-info option removed.
1 parent 62cb386 commit 8fb6767

File tree

5 files changed

+134
-87
lines changed

5 files changed

+134
-87
lines changed

llvm/docs/CommandGuide/llvm-mca.rst

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,6 @@ option specifies "``-``", then the output will also be sent to standard output.
170170
Enable extra scheduler statistics. This view collects and analyzes instruction
171171
issue events. This view is disabled by default.
172172

173-
.. option:: -scheduling-info
174-
175-
Enable scheduling info view. This view reports scheduling information defined
176-
in LLVM target description in the form:
177-
``<uOps> <Latency> <Bypass Latency> <Throughput> <LLVM Opcode Name> <Resources
178-
units> <instruction and comment (// or /* */) if defined>``
179-
It allows to compare scheduling info with architecture documents and fix them
180-
in target description by fixing InstrRW for the reported LLVM opcode.
181-
Scheduling information can be defined in the same order in each instruction
182-
comments to check easily reported and reference scheduling information.
183-
Suggested information in comment:
184-
``// <architecture instruction form> \\ <scheduling documentation title> \\
185-
<uOps>, <Latency>, <Bypass Latency>, <Throughput>, <Resources units>``
186-
187173
.. option:: -retire-stats
188174

189175
Enable extra retire control unit statistics. This view is disabled by default.
@@ -211,14 +197,25 @@ option specifies "``-``", then the output will also be sent to standard output.
211197

212198
Enable all the view.
213199

214-
.. option:: -instruction-tables
200+
.. option:: -instruction-tables=<level>
215201

216202
Prints resource pressure information based on the static information
217203
available from the processor model. This differs from the resource pressure
218204
view because it doesn't require that the code is simulated. It instead prints
219205
the theoretical uniform distribution of resource pressure for every
220206
instruction in sequence.
221207

208+
The choice of `<level>` controls number of printed information.
209+
`<level>` may be `none` (default), `normal`, `full`.
210+
Note: If the option is used without `<label>`, default is `normal` (legacy).
211+
212+
When `<level>` is `full`, additional information are:
213+
- `<Bypass Latency>`: Latency when a bypass is implemented between operands
214+
in pipelines (see SchedReadAdvance).
215+
- `<LLVM Opcode Name>`: mnemonic plus operands identifier.
216+
- `<Resources units>`: Used resources associated with LLVM Opcode.
217+
- `<instruction comment>`: reports comment if any from source assembly.
218+
222219
.. option:: -bottleneck-analysis
223220

224221
Print information about bottlenecks that affect the throughput. This analysis

llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-sve-instructions.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
2-
# RUN: llvm-mca -mtriple=aarch64 -mcpu=neoverse-v1 -instruction-tables -scheduling-info < %s | FileCheck %s
2+
# RUN: llvm-mca -mtriple=aarch64 -mcpu=neoverse-v1 -instruction-tables=full < %s | FileCheck %s
33

44
abs z0.b, p0/m, z0.b
55
abs z0.d, p0/m, z0.d

llvm/tools/llvm-mca/Views/InstructionInfoView.cpp

Lines changed: 66 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ void InstructionInfoView::printSchedulingInfoView(raw_ostream &OS) const {
132132
void InstructionInfoView::printView(raw_ostream &OS) const {
133133
std::string Buffer;
134134
raw_string_ostream TempStream(Buffer);
135+
formatted_raw_ostream FOS(TempStream);
135136

136137
ArrayRef<llvm::MCInst> Source = getSource();
137138
if (!Source.size())
@@ -140,7 +141,7 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
140141
IIVDVec IIVD(Source.size());
141142
collectData(IIVD);
142143

143-
if (PrintSchedulingInfo) {
144+
if (PrintFullInfo) {
144145
if (PrintEncodings)
145146
WithColor::warning()
146147
<< "No encodings printed when -scheduling-info option enabled.\n";
@@ -152,82 +153,94 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
152153
return;
153154
}
154155

155-
TempStream << "\n\nInstruction Info:\n";
156-
TempStream << "[1]: #uOps\n[2]: Latency\n[3]: RThroughput\n"
157-
<< "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n";
156+
std::vector<unsigned> paddings = {0, 7, 14, 21, 28, 35};
157+
std::vector<std::string> fields = {"#uOps", "Latency", "RThroughput",
158+
"MayLoad", "MayStore", "HasSideEffects (U)"};
159+
std::vector<std::string> end_fields;
160+
unsigned last_padding = 35;
158161
if (PrintBarriers) {
159-
TempStream << "[7]: LoadBarrier\n[8]: StoreBarrier\n";
162+
paddings.push_back(last_padding + 7);
163+
paddings.push_back(last_padding + 14);
164+
last_padding += 14;
165+
fields.push_back("LoadBarrier"); fields.push_back("StoreBarrier");
160166
}
161167
if (PrintEncodings) {
162-
if (PrintBarriers) {
163-
TempStream << "[9]: Encoding Size\n";
164-
TempStream << "\n[1] [2] [3] [4] [5] [6] [7] [8] "
165-
<< "[9] Encodings: Instructions:\n";
166-
} else {
167-
TempStream << "[7]: Encoding Size\n";
168-
TempStream << "\n[1] [2] [3] [4] [5] [6] [7] "
169-
<< "Encodings: Instructions:\n";
168+
paddings.push_back(last_padding + 7);
169+
paddings.push_back(last_padding + 14);
170+
paddings.push_back(last_padding + 44);
171+
last_padding += 44;
172+
fields.push_back("Encoding Size");
173+
end_fields.push_back("Encodings:");
174+
end_fields.push_back("Instructions:");
175+
}
176+
else {
177+
paddings.push_back(last_padding + 7);
178+
last_padding += 7;
179+
end_fields.push_back("Instructions:");
180+
}
181+
182+
FOS << "\n\nInstruction Info:\n";
183+
for (unsigned i = 0; i < fields.size(); i++) {
184+
FOS << "[" << i + 1 << "]: " << fields[i] << "\n";
185+
}
186+
FOS << "\n";
187+
188+
for (unsigned i = 0; i < paddings.size(); i++) {
189+
if (paddings[i] != 0)
190+
FOS.PadToColumn(paddings[i]);
191+
if (i < fields.size()) {
192+
FOS << "[" << i + 1 << "]";
170193
}
171-
} else {
172-
if (PrintBarriers) {
173-
TempStream << "\n[1] [2] [3] [4] [5] [6] [7] [8] "
174-
<< "Instructions:\n";
175-
} else {
176-
TempStream << "\n[1] [2] [3] [4] [5] [6] "
177-
<< "Instructions:\n";
194+
else {
195+
FOS << end_fields[i - fields.size()];
178196
}
179197
}
198+
FOS << "\n";
180199

181200
for (const auto &[Index, IIVDEntry, Inst] : enumerate(IIVD, Source)) {
182-
TempStream << ' ' << IIVDEntry.NumMicroOpcodes << " ";
183-
if (IIVDEntry.NumMicroOpcodes < 10)
184-
TempStream << " ";
185-
else if (IIVDEntry.NumMicroOpcodes < 100)
186-
TempStream << ' ';
187-
TempStream << IIVDEntry.Latency << " ";
188-
if (IIVDEntry.Latency < 10)
189-
TempStream << " ";
190-
else if (IIVDEntry.Latency < 100)
191-
TempStream << ' ';
201+
FOS.PadToColumn(paddings[0]+1);
202+
FOS << IIVDEntry.NumMicroOpcodes;
203+
FOS.PadToColumn(paddings[1]+1);
204+
FOS << IIVDEntry.Latency;
192205

206+
FOS.PadToColumn(paddings[2]);
193207
if (IIVDEntry.RThroughput) {
194208
double RT = *IIVDEntry.RThroughput;
195-
TempStream << format("%.2f", RT) << ' ';
196-
if (RT < 10.0)
197-
TempStream << " ";
198-
else if (RT < 100.0)
199-
TempStream << ' ';
209+
FOS << format("%.2f", RT);
200210
} else {
201-
TempStream << " - ";
211+
FOS << " -";
202212
}
203-
TempStream << (IIVDEntry.mayLoad ? " * " : " ");
204-
TempStream << (IIVDEntry.mayStore ? " * " : " ");
205-
TempStream << (IIVDEntry.hasUnmodeledSideEffects ? " U " : " ");
213+
FOS.PadToColumn(paddings[3]+1);
214+
FOS << (IIVDEntry.mayLoad ? "*" : " ");
215+
FOS.PadToColumn(paddings[4]+1);
216+
FOS << (IIVDEntry.mayStore ? "*" : " ");
217+
FOS.PadToColumn(paddings[5]+1);
218+
FOS << (IIVDEntry.hasUnmodeledSideEffects ? "U" : " ");
219+
unsigned last_padding_idx = 5;
206220

207221
if (PrintBarriers) {
208-
TempStream << (LoweredInsts[Index]->isALoadBarrier() ? " * "
209-
: " ");
210-
TempStream << (LoweredInsts[Index]->isAStoreBarrier() ? " * "
211-
: " ");
222+
FOS.PadToColumn(paddings[last_padding_idx + 1]+1);
223+
FOS << (LoweredInsts[Index]->isALoadBarrier() ? "*" : " ");
224+
FOS.PadToColumn(paddings[last_padding_idx + 2]+1);
225+
FOS << (LoweredInsts[Index]->isAStoreBarrier() ? "*" : " ");
226+
last_padding_idx += 2;
212227
}
213228

214229
if (PrintEncodings) {
215230
StringRef Encoding(CE.getEncoding(Index));
216231
unsigned EncodingSize = Encoding.size();
217-
TempStream << " " << EncodingSize
218-
<< (EncodingSize < 10 ? " " : " ");
219-
TempStream.flush();
220-
formatted_raw_ostream FOS(TempStream);
232+
FOS.PadToColumn(paddings[last_padding_idx + 1]+1);
233+
FOS << EncodingSize;
234+
FOS.PadToColumn(paddings[last_padding_idx + 2]);
221235
for (unsigned i = 0, e = Encoding.size(); i != e; ++i)
222236
FOS << format("%02x ", (uint8_t)Encoding[i]);
223-
FOS.PadToColumn(30);
224-
FOS.flush();
237+
last_padding_idx += 2;
225238
}
226-
227-
TempStream << printInstructionString(Inst) << '\n';
239+
FOS.PadToColumn(paddings[last_padding_idx + 1]);
240+
FOS << printInstructionString(Inst) << '\n';
228241
}
229242

230-
TempStream.flush();
243+
FOS.flush();
231244
OS << Buffer;
232245
}
233246

@@ -265,7 +278,7 @@ void InstructionInfoView::collectData(
265278
IIVDEntry.mayStore = MCDesc.mayStore();
266279
IIVDEntry.hasUnmodeledSideEffects = MCDesc.hasUnmodeledSideEffects();
267280

268-
if (PrintSchedulingInfo) {
281+
if (PrintFullInfo) {
269282
// Get latency with bypass
270283
IIVDEntry.Bypass =
271284
IIVDEntry.Latency - MCSchedModel::getBypassDelayCycles(STI, SCDesc);
@@ -283,7 +296,6 @@ void InstructionInfoView::collectData(
283296
// Output ReleaseAtCycle between [] if not 1 (default)
284297
// This is to be able to evaluate throughput.
285298
// See getReciprocalThroughput in MCSchedule.cpp
286-
// TODO: report AcquireAtCycle to check this scheduling info.
287299
TempStream << sep
288300
<< format("%s[%d]", MCProc->Name, Index->ReleaseAtCycle);
289301
} else {

llvm/tools/llvm-mca/Views/InstructionInfoView.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class InstructionInfoView : public InstructionView {
5656
CodeEmitter &CE;
5757
bool PrintEncodings;
5858
bool PrintBarriers;
59-
bool PrintSchedulingInfo;
59+
bool PrintFullInfo;
6060
using UniqueInst = std::unique_ptr<Instruction>;
6161
ArrayRef<UniqueInst> LoweredInsts;
6262
const InstrumentManager &IM;
@@ -94,13 +94,13 @@ class InstructionInfoView : public InstructionView {
9494
bool ShouldPrintEncodings, llvm::ArrayRef<llvm::MCInst> S,
9595
llvm::MCInstPrinter &IP,
9696
ArrayRef<UniqueInst> LoweredInsts,
97-
bool ShouldPrintBarriers, bool ShouldPrintSchedulingInfo,
97+
bool ShouldPrintBarriers, bool ShouldPrintFullInfo,
9898
const InstrumentManager &IM,
9999
const InstToInstrumentsT &InstToInstruments)
100100
: InstructionView(ST, IP, S), MCII(II), CE(C),
101101
PrintEncodings(ShouldPrintEncodings),
102102
PrintBarriers(ShouldPrintBarriers),
103-
PrintSchedulingInfo(ShouldPrintSchedulingInfo),
103+
PrintFullInfo(ShouldPrintFullInfo),
104104
LoweredInsts(LoweredInsts), IM(IM),
105105
InstToInstruments(InstToInstruments) {}
106106

llvm/tools/llvm-mca/llvm-mca.cpp

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,51 @@ static cl::opt<unsigned> StoreQueueSize("squeue",
225225
cl::desc("Size of the store queue"),
226226
cl::cat(ToolOptions), cl::init(0));
227227

228-
static cl::opt<bool>
229-
PrintInstructionTables("instruction-tables",
230-
cl::desc("Print instruction tables"),
231-
cl::cat(ToolOptions), cl::init(false));
228+
enum class InstructionTablesType { NONE, NORMAL, FULL };
229+
230+
class InstructionTablesOptionParser :
231+
public cl::parser<enum InstructionTablesType> {
232+
public:
233+
explicit InstructionTablesOptionParser(cl::Option &O)
234+
: cl::parser<enum InstructionTablesType>(O) {}
235+
236+
bool parse(cl::Option &O, StringRef ArgName, StringRef Arg,
237+
enum InstructionTablesType &Value) {
238+
if (Arg.empty()) {
239+
Value = InstructionTablesType::NORMAL;
240+
return false;
241+
}
242+
return cl::parser<enum InstructionTablesType>::parse(O, ArgName, Arg, Value);
243+
}
244+
};
245+
246+
static cl::opt<enum InstructionTablesType, false, InstructionTablesOptionParser>
247+
InstructionTablesOption("instruction-tables",
248+
cl::desc("Print instruction tables"),
249+
cl::values(
250+
clEnumValN(InstructionTablesType::NONE, "none",
251+
"Do not print instruction tables"),
252+
clEnumValN(InstructionTablesType::NORMAL, "normal",
253+
"Print instruction tables"),
254+
clEnumValN(InstructionTablesType::FULL, "full",
255+
"Print instruction tables with additional"
256+
" information: bypass latency, LLVM opcode,"
257+
" used resources")),
258+
cl::cat(ToolOptions), cl::init(InstructionTablesType::NONE));
259+
260+
bool PrintInstructionTables() {
261+
if (InstructionTablesOption == InstructionTablesType::NONE)
262+
return false;
263+
264+
return true;
265+
}
266+
267+
bool PrintInstructionTables(enum InstructionTablesType ITType) {
268+
if (InstructionTablesOption == ITType)
269+
return true;
270+
271+
return false;
272+
}
232273

233274
static cl::opt<bool> PrintInstructionInfoView(
234275
"instruction-info",
@@ -259,12 +300,6 @@ static cl::opt<bool> ShowBarriers(
259300
cl::desc("Print memory barrier information in the instruction info view"),
260301
cl::cat(ViewOptions), cl::init(false));
261302

262-
static cl::opt<bool>
263-
ShowSchedulingInfo("scheduling-info",
264-
cl::desc("Print the instruction scheduling information "
265-
"in the instruction info view"),
266-
cl::cat(ViewOptions), cl::init(false));
267-
268303
static cl::opt<bool> DisableCustomBehaviour(
269304
"disable-cb",
270305
cl::desc(
@@ -370,6 +405,8 @@ int main(int argc, char **argv) {
370405

371406
cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions});
372407

408+
InstructionTablesOption.setValueExpectedFlag(cl::ValueOptional);
409+
373410
// Parse flags and initialize target options.
374411
cl::ParseCommandLineOptions(argc, argv,
375412
"llvm machine code performance analyzer.\n");
@@ -668,9 +705,9 @@ int main(int argc, char **argv) {
668705
NonEmptyRegions++;
669706

670707
mca::CircularSourceMgr S(LoweredSequence,
671-
PrintInstructionTables ? 1 : Iterations);
708+
PrintInstructionTables() ? 1 : Iterations);
672709

673-
if (PrintInstructionTables) {
710+
if (PrintInstructionTables()) {
674711
// Create a pipeline, stages, and a printer.
675712
auto P = std::make_unique<mca::Pipeline>();
676713
P->appendStage(std::make_unique<mca::EntryStage>(S));
@@ -686,7 +723,8 @@ int main(int argc, char **argv) {
686723
if (PrintInstructionInfoView) {
687724
Printer.addView(std::make_unique<mca::InstructionInfoView>(
688725
*STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,
689-
ShowBarriers, ShowSchedulingInfo, *IM, InstToInstruments));
726+
ShowBarriers, PrintInstructionTables(InstructionTablesType::FULL),
727+
*IM, InstToInstruments));
690728
}
691729

692730
Printer.addView(
@@ -764,7 +802,7 @@ int main(int argc, char **argv) {
764802
if (PrintInstructionInfoView)
765803
Printer.addView(std::make_unique<mca::InstructionInfoView>(
766804
*STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,
767-
ShowBarriers, ShowSchedulingInfo, *IM, InstToInstruments));
805+
ShowBarriers, false, *IM, InstToInstruments));
768806

769807
// Fetch custom Views that are to be placed after the InstructionInfoView.
770808
// Refer to the comment paired with the CB->getStartViews(*IP, Insts); line

0 commit comments

Comments
 (0)