Skip to content

Commit 23f7106

Browse files
Matt DavisMatt Davis
Matt Davis
authored and
Matt Davis
committed
[llvm-mca] Move the AssembleInput logic into its own class.
Summary: This patch introduces a CodeRegionGenerator class which is responsible for parsing some type of input and creating a 'CodeRegions' instance for use by llvm-mca. In the future, we will also have a CodeRegionGenerator subclass for converting an input object file into CodeRegions. For now, we only have the subclass for converting input assembly into CodeRegions. This is mostly a NFC patch, as the logic remains close to the original, but now encapsulated in its own class and moved outside of llvm-mca.cpp. Reviewers: andreadb, courbet, RKSimon Reviewed By: andreadb Subscribers: mgorny, tschuett, gbedwell, llvm-commits Differential Revision: https://reviews.llvm.org/D54179 llvm-svn: 346344
1 parent 2a6f3f5 commit 23f7106

File tree

5 files changed

+218
-103
lines changed

5 files changed

+218
-103
lines changed

llvm/tools/llvm-mca/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set(LLVM_LINK_COMPONENTS
1414
add_llvm_tool(llvm-mca
1515
llvm-mca.cpp
1616
CodeRegion.cpp
17+
CodeRegionGenerator.cpp
1718
PipelinePrinter.cpp
1819
Views/DispatchStatistics.cpp
1920
Views/InstructionInfoView.cpp

llvm/tools/llvm-mca/CodeRegion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class CodeRegions {
106106
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
107107
void endRegion(llvm::SMLoc Loc);
108108
void addInstruction(const llvm::MCInst &Instruction);
109+
llvm::SourceMgr &getSourceMgr() const { return SM; }
109110

110111
CodeRegions(llvm::SourceMgr &S) : SM(S) {
111112
// Create a default region for the input code sequence.
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
//===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
/// \file
10+
///
11+
/// This file defines classes responsible for generating llvm-mca
12+
/// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
13+
/// so the classes here provide the input-to-CodeRegions translation.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "CodeRegionGenerator.h"
18+
#include "llvm/ADT/ArrayRef.h"
19+
#include "llvm/ADT/StringRef.h"
20+
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
21+
#include "llvm/MC/MCStreamer.h"
22+
#include "llvm/MC/MCTargetOptions.h"
23+
#include "llvm/Support/Error.h"
24+
#include "llvm/Support/SMLoc.h"
25+
#include <memory>
26+
27+
namespace llvm {
28+
namespace mca {
29+
30+
// This virtual dtor serves as the anchor for the CodeRegionGenerator class.
31+
CodeRegionGenerator::~CodeRegionGenerator() {}
32+
33+
// A comment consumer that parses strings. The only valid tokens are strings.
34+
class MCACommentConsumer : public AsmCommentConsumer {
35+
public:
36+
CodeRegions &Regions;
37+
38+
MCACommentConsumer(CodeRegions &R) : Regions(R) {}
39+
void HandleComment(SMLoc Loc, StringRef CommentText) override;
40+
};
41+
42+
// This class provides the callbacks that occur when parsing input assembly.
43+
class MCStreamerWrapper final : public MCStreamer {
44+
CodeRegions &Regions;
45+
46+
public:
47+
MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
48+
: MCStreamer(Context), Regions(R) {}
49+
50+
// We only want to intercept the emission of new instructions.
51+
virtual void EmitInstruction(const MCInst &Inst,
52+
const MCSubtargetInfo & /* unused */,
53+
bool /* unused */) override {
54+
Regions.addInstruction(Inst);
55+
}
56+
57+
bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
58+
return true;
59+
}
60+
61+
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
62+
unsigned ByteAlignment) override {}
63+
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
64+
uint64_t Size = 0, unsigned ByteAlignment = 0,
65+
SMLoc Loc = SMLoc()) override {}
66+
void EmitGPRel32Value(const MCExpr *Value) override {}
67+
void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
68+
void EmitCOFFSymbolStorageClass(int StorageClass) override {}
69+
void EmitCOFFSymbolType(int Type) override {}
70+
void EndCOFFSymbolDef() override {}
71+
72+
ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
73+
return Regions.getInstructionSequence(Index);
74+
}
75+
};
76+
77+
void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) {
78+
// Skip empty comments.
79+
StringRef Comment(CommentText);
80+
if (Comment.empty())
81+
return;
82+
83+
// Skip spaces and tabs.
84+
unsigned Position = Comment.find_first_not_of(" \t");
85+
if (Position >= Comment.size())
86+
// We reached the end of the comment. Bail out.
87+
return;
88+
89+
Comment = Comment.drop_front(Position);
90+
if (Comment.consume_front("LLVM-MCA-END")) {
91+
Regions.endRegion(Loc);
92+
return;
93+
}
94+
95+
// Try to parse the LLVM-MCA-BEGIN comment.
96+
if (!Comment.consume_front("LLVM-MCA-BEGIN"))
97+
return;
98+
99+
// Skip spaces and tabs.
100+
Position = Comment.find_first_not_of(" \t");
101+
if (Position < Comment.size())
102+
Comment = Comment.drop_front(Position);
103+
// Use the rest of the string as a descriptor for this code snippet.
104+
Regions.beginRegion(Comment, Loc);
105+
}
106+
107+
Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions() {
108+
MCTargetOptions Opts;
109+
Opts.PreserveAsmComments = false;
110+
MCStreamerWrapper Str(Ctx, Regions);
111+
112+
// Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
113+
// comments.
114+
std::unique_ptr<MCAsmParser> Parser(
115+
createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
116+
MCAsmLexer &Lexer = Parser->getLexer();
117+
MCACommentConsumer CC(Regions);
118+
Lexer.setCommentConsumer(&CC);
119+
120+
// Create a target-specific parser and perform the parse.
121+
std::unique_ptr<MCTargetAsmParser> TAP(
122+
TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
123+
if (!TAP)
124+
return make_error<StringError>(
125+
"This target does not support assembly parsing.",
126+
inconvertibleErrorCode());
127+
Parser->setTargetParser(*TAP);
128+
Parser->Run(false);
129+
130+
// Get the assembler dialect from the input. llvm-mca will use this as the
131+
// default dialect when printing reports.
132+
AssemblerDialect = Parser->getAssemblerDialect();
133+
return Regions;
134+
}
135+
136+
} // namespace mca
137+
} // namespace llvm
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===----------------------- CodeRegionGenerator.h --------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
/// \file
10+
///
11+
/// This file declares classes responsible for generating llvm-mca
12+
/// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
13+
/// so the classes here provide the input-to-CodeRegions translation.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
18+
#define LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
19+
20+
#include "CodeRegion.h"
21+
#include "llvm/MC/MCAsmInfo.h"
22+
#include "llvm/MC/MCContext.h"
23+
#include "llvm/MC/MCSubtargetInfo.h"
24+
#include "llvm/Support/Error.h"
25+
#include "llvm/Support/SourceMgr.h"
26+
#include "llvm/Support/TargetRegistry.h"
27+
#include <memory>
28+
29+
namespace llvm {
30+
namespace mca {
31+
32+
/// This class is responsible for parsing the input given to the llvm-mca
33+
/// driver, and converting that into a CodeRegions instance.
34+
class CodeRegionGenerator {
35+
protected:
36+
CodeRegions Regions;
37+
CodeRegionGenerator(const CodeRegionGenerator &) = delete;
38+
CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;
39+
40+
public:
41+
CodeRegionGenerator(SourceMgr &SM) : Regions(SM) {}
42+
virtual ~CodeRegionGenerator();
43+
virtual Expected<const CodeRegions &> parseCodeRegions() = 0;
44+
};
45+
46+
/// This class is responsible for parsing input ASM and generating
47+
/// a CodeRegions instance.
48+
class AsmCodeRegionGenerator final : public CodeRegionGenerator {
49+
const Target &TheTarget;
50+
MCContext &Ctx;
51+
const MCAsmInfo &MAI;
52+
const MCSubtargetInfo &STI;
53+
const MCInstrInfo &MCII;
54+
unsigned AssemblerDialect; // This is set during parsing.
55+
56+
public:
57+
AsmCodeRegionGenerator(const Target &T, SourceMgr &SM, MCContext &C,
58+
const MCAsmInfo &A, const MCSubtargetInfo &S,
59+
const MCInstrInfo &I)
60+
: CodeRegionGenerator(SM), TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I),
61+
AssemblerDialect(0) {}
62+
63+
unsigned getAssemblerDialect() const { return AssemblerDialect; }
64+
Expected<const CodeRegions &> parseCodeRegions() override;
65+
};
66+
67+
} // namespace mca
68+
} // namespace llvm
69+
70+
#endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H

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

Lines changed: 9 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
//===----------------------------------------------------------------------===//
2323

2424
#include "CodeRegion.h"
25+
#include "CodeRegionGenerator.h"
2526
#include "PipelinePrinter.h"
2627
#include "Stages/FetchStage.h"
2728
#include "Stages/InstructionTables.h"
@@ -39,9 +40,7 @@
3940
#include "llvm/MC/MCAsmInfo.h"
4041
#include "llvm/MC/MCContext.h"
4142
#include "llvm/MC/MCObjectFileInfo.h"
42-
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
4343
#include "llvm/MC/MCRegisterInfo.h"
44-
#include "llvm/MC/MCStreamer.h"
4544
#include "llvm/Support/CommandLine.h"
4645
#include "llvm/Support/ErrorHandling.h"
4746
#include "llvm/Support/ErrorOr.h"
@@ -199,59 +198,6 @@ const Target *getTarget(const char *ProgName) {
199198
return TheTarget;
200199
}
201200

202-
// A comment consumer that parses strings.
203-
// The only valid tokens are strings.
204-
class MCACommentConsumer : public AsmCommentConsumer {
205-
public:
206-
mca::CodeRegions &Regions;
207-
208-
MCACommentConsumer(mca::CodeRegions &R) : Regions(R) {}
209-
void HandleComment(SMLoc Loc, StringRef CommentText) override {
210-
// Skip empty comments.
211-
StringRef Comment(CommentText);
212-
if (Comment.empty())
213-
return;
214-
215-
// Skip spaces and tabs
216-
unsigned Position = Comment.find_first_not_of(" \t");
217-
if (Position >= Comment.size())
218-
// We reached the end of the comment. Bail out.
219-
return;
220-
221-
Comment = Comment.drop_front(Position);
222-
if (Comment.consume_front("LLVM-MCA-END")) {
223-
Regions.endRegion(Loc);
224-
return;
225-
}
226-
227-
// Now try to parse string LLVM-MCA-BEGIN
228-
if (!Comment.consume_front("LLVM-MCA-BEGIN"))
229-
return;
230-
231-
// Skip spaces and tabs
232-
Position = Comment.find_first_not_of(" \t");
233-
if (Position < Comment.size())
234-
Comment = Comment.drop_front(Position);
235-
// Use the rest of the string as a descriptor for this code snippet.
236-
Regions.beginRegion(Comment, Loc);
237-
}
238-
};
239-
240-
int AssembleInput(MCAsmParser &Parser, const Target *TheTarget,
241-
MCSubtargetInfo &STI, MCInstrInfo &MCII,
242-
MCTargetOptions &MCOptions) {
243-
std::unique_ptr<MCTargetAsmParser> TAP(
244-
TheTarget->createMCAsmParser(STI, Parser, MCII, MCOptions));
245-
246-
if (!TAP) {
247-
WithColor::error() << "this target does not support assembly parsing.\n";
248-
return 1;
249-
}
250-
251-
Parser.setTargetParser(*TAP);
252-
return Parser.Run(false);
253-
}
254-
255201
ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() {
256202
if (OutputFilename == "")
257203
OutputFilename = "-";
@@ -262,40 +208,6 @@ ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() {
262208
return std::move(Out);
263209
return EC;
264210
}
265-
266-
class MCStreamerWrapper final : public MCStreamer {
267-
mca::CodeRegions &Regions;
268-
269-
public:
270-
MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
271-
: MCStreamer(Context), Regions(R) {}
272-
273-
// We only want to intercept the emission of new instructions.
274-
virtual void EmitInstruction(const MCInst &Inst,
275-
const MCSubtargetInfo & /* unused */,
276-
bool /* unused */) override {
277-
Regions.addInstruction(Inst);
278-
}
279-
280-
bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
281-
return true;
282-
}
283-
284-
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
285-
unsigned ByteAlignment) override {}
286-
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
287-
uint64_t Size = 0, unsigned ByteAlignment = 0,
288-
SMLoc Loc = SMLoc()) override {}
289-
void EmitGPRel32Value(const MCExpr *Value) override {}
290-
void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
291-
void EmitCOFFSymbolStorageClass(int StorageClass) override {}
292-
void EmitCOFFSymbolType(int Type) override {}
293-
void EndCOFFSymbolDef() override {}
294-
295-
ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
296-
return Regions.getInstructionSequence(Index);
297-
}
298-
};
299211
} // end of anonymous namespace
300212

301213
static void processOptionImpl(cl::opt<bool> &O, const cl::opt<bool> &Default) {
@@ -352,9 +264,6 @@ int main(int argc, char **argv) {
352264
cl::ParseCommandLineOptions(argc, argv,
353265
"llvm machine code performance analyzer.\n");
354266

355-
MCTargetOptions MCOptions;
356-
MCOptions.PreserveAsmComments = false;
357-
358267
// Get the target from the triple. If a triple is not specified, then select
359268
// the default triple for the host. If the triple doesn't correspond to any
360269
// registered target, then exit with an error message.
@@ -394,9 +303,6 @@ int main(int argc, char **argv) {
394303

395304
std::unique_ptr<buffer_ostream> BOS;
396305

397-
mca::CodeRegions Regions(SrcMgr);
398-
MCStreamerWrapper Str(Ctx, Regions);
399-
400306
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
401307

402308
std::unique_ptr<MCInstrAnalysis> MCIA(
@@ -429,14 +335,14 @@ int main(int argc, char **argv) {
429335
return 1;
430336
}
431337

432-
std::unique_ptr<MCAsmParser> P(createMCAsmParser(SrcMgr, Ctx, Str, *MAI));
433-
MCAsmLexer &Lexer = P->getLexer();
434-
MCACommentConsumer CC(Regions);
435-
Lexer.setCommentConsumer(&CC);
436-
437-
if (AssembleInput(*P, TheTarget, *STI, *MCII, MCOptions))
338+
// Parse the input and create CodeRegions that llvm-mca can analyze.
339+
mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII);
340+
Expected<const mca::CodeRegions &> RegionsOrErr = CRG.parseCodeRegions();
341+
if (auto Err = RegionsOrErr.takeError()) {
342+
WithColor::error() << Err << "\n";
438343
return 1;
439-
344+
}
345+
const mca::CodeRegions &Regions = *RegionsOrErr;
440346
if (Regions.empty()) {
441347
WithColor::error() << "no assembly instructions found.\n";
442348
return 1;
@@ -449,7 +355,7 @@ int main(int argc, char **argv) {
449355
return 1;
450356
}
451357

452-
unsigned AssemblerDialect = P->getAssemblerDialect();
358+
unsigned AssemblerDialect = CRG.getAssemblerDialect();
453359
if (OutputAsmVariant >= 0)
454360
AssemblerDialect = static_cast<unsigned>(OutputAsmVariant);
455361
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(

0 commit comments

Comments
 (0)