Skip to content

Commit 6c49bdd

Browse files
committed
LLVM-MC profiling to measure disassembly times
1 parent 5223317 commit 6c49bdd

File tree

3 files changed

+76
-22
lines changed

3 files changed

+76
-22
lines changed

llvm/tools/llvm-mc/Disassembler.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "Disassembler.h"
15+
#include "llvm/ADT/Sequence.h"
1516
#include "llvm/ADT/StringExtras.h"
1617
#include "llvm/MC/MCAsmInfo.h"
1718
#include "llvm/MC/MCContext.h"
@@ -24,6 +25,7 @@
2425
#include "llvm/MC/TargetRegistry.h"
2526
#include "llvm/Support/MemoryBuffer.h"
2627
#include "llvm/Support/SourceMgr.h"
28+
#include "llvm/Support/TimeProfiler.h"
2729
#include "llvm/Support/raw_ostream.h"
2830
#include "llvm/TargetParser/Triple.h"
2931

@@ -32,24 +34,25 @@ using namespace llvm;
3234
typedef std::pair<std::vector<unsigned char>, std::vector<const char *>>
3335
ByteArrayTy;
3436

35-
static bool PrintInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
37+
static bool printInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
3638
SourceMgr &SM, MCStreamer &Streamer, bool InAtomicBlock,
37-
const MCSubtargetInfo &STI) {
39+
const MCSubtargetInfo &STI, unsigned BenchmarkNumRuns) {
3840
ArrayRef<uint8_t> Data(Bytes.first);
3941

4042
// Disassemble it to strings.
4143
uint64_t Size;
42-
uint64_t Index;
4344

44-
for (Index = 0; Index < Bytes.first.size(); Index += Size) {
45-
MCInst Inst;
45+
for (uint64_t Index = 0; Index < Bytes.first.size(); Index += Size) {
46+
auto getInstruction = [&](MCInst &Inst) -> MCDisassembler::DecodeStatus {
47+
if (STI.getTargetTriple().getArch() == Triple::hexagon)
48+
return DisAsm.getInstructionBundle(Inst, Size, Data.slice(Index), Index,
49+
nulls());
50+
return DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index,
51+
nulls());
52+
};
4653

47-
MCDisassembler::DecodeStatus S;
48-
if (STI.getTargetTriple().getArch() == Triple::hexagon)
49-
S = DisAsm.getInstructionBundle(Inst, Size, Data.slice(Index), Index,
50-
nulls());
51-
else
52-
S = DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index, nulls());
54+
MCInst Inst;
55+
MCDisassembler::DecodeStatus S = getInstruction(Inst);
5356
switch (S) {
5457
case MCDisassembler::Fail:
5558
SM.PrintMessage(SMLoc::getFromPointer(Bytes.second[Index]),
@@ -74,12 +77,24 @@ static bool PrintInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
7477
Streamer.emitInstruction(Inst, STI);
7578
break;
7679
}
80+
81+
if (S == MCDisassembler::Success && BenchmarkNumRuns != 0) {
82+
// Benchmark mode, collect timing for decoding the instruction several
83+
// times.
84+
MCInst BMInst;
85+
TimeTraceScope timeScope("getInstruction");
86+
for (unsigned _ : llvm::seq<unsigned>(BenchmarkNumRuns)) {
87+
BMInst.clear();
88+
BMInst.setOpcode(0);
89+
S = getInstruction(BMInst);
90+
}
91+
}
7792
}
7893

7994
return false;
8095
}
8196

82-
static bool SkipToToken(StringRef &Str) {
97+
static bool skipToToken(StringRef &Str) {
8398
for (;;) {
8499
if (Str.empty())
85100
return false;
@@ -101,7 +116,7 @@ static bool SkipToToken(StringRef &Str) {
101116

102117
static bool byteArrayFromString(ByteArrayTy &ByteArray, StringRef &Str,
103118
SourceMgr &SM, bool HexBytes) {
104-
while (SkipToToken(Str)) {
119+
while (skipToToken(Str)) {
105120
// Handled by higher level
106121
if (Str[0] == '[' || Str[0] == ']')
107122
return false;
@@ -151,7 +166,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
151166
MCSubtargetInfo &STI, MCStreamer &Streamer,
152167
MemoryBuffer &Buffer, SourceMgr &SM,
153168
MCContext &Ctx, const MCTargetOptions &MCOptions,
154-
bool HexBytes) {
169+
bool HexBytes, unsigned BenchmarkNumRuns) {
155170
std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple));
156171
if (!MRI) {
157172
errs() << "error: no register info for target " << Triple << "\n";
@@ -179,7 +194,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
179194
StringRef Str = Buffer.getBuffer();
180195
bool InAtomicBlock = false;
181196

182-
while (SkipToToken(Str)) {
197+
while (skipToToken(Str)) {
183198
ByteArray.first.clear();
184199
ByteArray.second.clear();
185200

@@ -207,8 +222,8 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
207222
ErrorOccurred |= byteArrayFromString(ByteArray, Str, SM, HexBytes);
208223

209224
if (!ByteArray.first.empty())
210-
ErrorOccurred |=
211-
PrintInsts(*DisAsm, ByteArray, SM, Streamer, InAtomicBlock, STI);
225+
ErrorOccurred |= printInsts(*DisAsm, ByteArray, SM, Streamer,
226+
InAtomicBlock, STI, BenchmarkNumRuns);
212227
}
213228

214229
if (InAtomicBlock) {

llvm/tools/llvm-mc/Disassembler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class Disassembler {
3232
static int disassemble(const Target &T, const std::string &Triple,
3333
MCSubtargetInfo &STI, MCStreamer &Streamer,
3434
MemoryBuffer &Buffer, SourceMgr &SM, MCContext &Ctx,
35-
const MCTargetOptions &MCOptions, bool HexBytes);
35+
const MCTargetOptions &MCOptions, bool HexBytes,
36+
unsigned BenchmarkNumRuns);
3637
};
3738

3839
} // namespace llvm

llvm/tools/llvm-mc/llvm-mc.cpp

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "Disassembler.h"
15+
#include "llvm/ADT/ScopeExit.h"
1516
#include "llvm/DWARFCFIChecker/DWARFCFIFunctionFrameAnalyzer.h"
1617
#include "llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h"
1718
#include "llvm/MC/MCAsmBackend.h"
@@ -37,6 +38,7 @@
3738
#include "llvm/Support/MemoryBuffer.h"
3839
#include "llvm/Support/SourceMgr.h"
3940
#include "llvm/Support/TargetSelect.h"
41+
#include "llvm/Support/TimeProfiler.h"
4042
#include "llvm/Support/ToolOutputFile.h"
4143
#include "llvm/Support/WithColor.h"
4244
#include "llvm/TargetParser/Host.h"
@@ -240,6 +242,24 @@ static cl::opt<ActionType> Action(
240242
"Colored disassembly of strings of hex bytes")),
241243
cl::cat(MCCategory));
242244

245+
static cl::opt<unsigned>
246+
BenchmarkNumRuns("benchmark-num-runs",
247+
cl::desc("Number of runs for decoder benchmarking"),
248+
cl::cat(MCCategory));
249+
250+
static cl::opt<bool> TimeTrace("time-trace", cl::desc("Record time trace"));
251+
252+
static cl::opt<unsigned> TimeTraceGranularity(
253+
"time-trace-granularity",
254+
cl::desc(
255+
"Minimum time granularity (in microseconds) traced by time profiler"),
256+
cl::init(500), cl::Hidden);
257+
258+
static cl::opt<std::string>
259+
TimeTraceFile("time-trace-file",
260+
cl::desc("Specify time trace file destination"),
261+
cl::value_desc("filename"));
262+
243263
static const Target *GetTarget(const char *ProgName) {
244264
// Figure out the target triple.
245265
if (TripleName.empty())
@@ -371,6 +391,22 @@ int main(int argc, char **argv) {
371391

372392
cl::HideUnrelatedOptions({&MCCategory, &getColorCategory()});
373393
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
394+
395+
if (TimeTrace)
396+
timeTraceProfilerInitialize(TimeTraceGranularity, argv[0]);
397+
398+
auto TimeTraceScopeExit = make_scope_exit([]() {
399+
if (!TimeTrace)
400+
return;
401+
if (auto E = timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) {
402+
handleAllErrors(std::move(E), [&](const StringError &SE) {
403+
errs() << SE.getMessage() << "\n";
404+
});
405+
return;
406+
}
407+
timeTraceProfilerCleanup();
408+
});
409+
374410
MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
375411
MCOptions.CompressDebugSections = CompressDebugSections.getValue();
376412
MCOptions.ShowMCInst = ShowInst;
@@ -603,7 +639,7 @@ int main(int argc, char **argv) {
603639
}
604640

605641
int Res = 1;
606-
bool disassemble = false;
642+
bool Disassemble = false;
607643
switch (Action) {
608644
case AC_AsLex:
609645
Res = AsLexInput(SrcMgr, *MAI, Out->os());
@@ -615,18 +651,20 @@ int main(int argc, char **argv) {
615651
case AC_MDisassemble:
616652
case AC_CDisassemble:
617653
case AC_Disassemble:
618-
disassemble = true;
654+
Disassemble = true;
619655
break;
620656
}
621-
if (disassemble)
657+
if (Disassemble)
622658
Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer,
623-
SrcMgr, Ctx, MCOptions, HexBytes);
659+
SrcMgr, Ctx, MCOptions, HexBytes,
660+
BenchmarkNumRuns);
624661

625662
// Keep output if no errors.
626663
if (Res == 0) {
627664
Out->keep();
628665
if (DwoOut)
629666
DwoOut->keep();
630667
}
668+
631669
return Res;
632670
}

0 commit comments

Comments
 (0)