diff options
Diffstat (limited to 'llvm/tools')
-rw-r--r-- | llvm/tools/llvm-mca/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/CodeRegion.cpp | 66 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/CodeRegion.h | 131 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/SourceMgr.h | 7 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/llvm-mca.cpp | 147 |
5 files changed, 306 insertions, 46 deletions
diff --git a/llvm/tools/llvm-mca/CMakeLists.txt b/llvm/tools/llvm-mca/CMakeLists.txt index 2964fde0309..0a29f3b66fd 100644 --- a/llvm/tools/llvm-mca/CMakeLists.txt +++ b/llvm/tools/llvm-mca/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_tool(llvm-mca Backend.cpp BackendPrinter.cpp BackendStatistics.cpp + CodeRegion.cpp Dispatch.cpp HWEventListener.cpp InstrBuilder.cpp diff --git a/llvm/tools/llvm-mca/CodeRegion.cpp b/llvm/tools/llvm-mca/CodeRegion.cpp new file mode 100644 index 00000000000..89686599650 --- /dev/null +++ b/llvm/tools/llvm-mca/CodeRegion.cpp @@ -0,0 +1,66 @@ +//===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements methods from the CodeRegions interface. +/// +//===----------------------------------------------------------------------===// + +#include "CodeRegion.h" + +using namespace llvm; + +namespace mca { + +bool CodeRegion::isLocInRange(SMLoc Loc) const { + if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer()) + return false; + if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer()) + return false; + return true; +} + +void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) { + assert(!Regions.empty() && "Missing Default region"); + const CodeRegion &CurrentRegion = *Regions.back(); + if (CurrentRegion.startLoc().isValid() && !CurrentRegion.endLoc().isValid()) { + SM.PrintMessage(Loc, SourceMgr::DK_Warning, + "Ignoring invalid region start"); + return; + } + + // Remove the default region if there are user defined regions. + if (!CurrentRegion.startLoc().isValid()) + Regions.erase(Regions.begin()); + addRegion(Description, Loc); +} + +void CodeRegions::endRegion(SMLoc Loc) { + assert(!Regions.empty() && "Missing Default region"); + CodeRegion &CurrentRegion = *Regions.back(); + if (CurrentRegion.endLoc().isValid()) { + SM.PrintMessage(Loc, SourceMgr::DK_Warning, "Ignoring invalid region end"); + return; + } + + CurrentRegion.setEndLocation(Loc); +} + +void CodeRegions::addInstruction(std::unique_ptr<const MCInst> Instruction) { + const SMLoc &Loc = Instruction->getLoc(); + const auto It = + std::find_if(Regions.rbegin(), Regions.rend(), + [Loc](const std::unique_ptr<CodeRegion> &Region) { + return Region->isLocInRange(Loc); + }); + if (It != Regions.rend()) + (*It)->addInstruction(std::move(Instruction)); +} + +} // namespace mca diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h new file mode 100644 index 00000000000..6dc3f01332f --- /dev/null +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -0,0 +1,131 @@ +//===-------------------------- CodeRegion.h -------------------*- C++ -* -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements class CodeRegion and CodeRegions. +/// +/// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA +/// comment directives. +/// +/// # LLVM-MCA-BEGIN foo +/// ... ## asm +/// # LLVM-MCA-END +/// +/// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a +/// new region of code. +/// A comment starting with substring LLVM-MCA-END marks the end of the +/// last-seen region of code. +/// +/// Code regions are not allowed to overlap. Each region can have a optional +/// description; internally, regions are described by a range of source +/// locations (SMLoc objects). +/// +/// An instruction (a MCInst) is added to a region R only if its location is in +/// range [R.RangeStart, R.RangeEnd]. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H +#define LLVM_TOOLS_LLVM_MCA_CODEREGION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/SourceMgr.h" +#include <vector> + +namespace mca { + +/// \brief A region of assembly code. +/// +/// It identifies a sequence of machine instructions. +class CodeRegion { + // An optional descriptor for this region. + llvm::StringRef Description; + // Instructions that form this region. + std::vector<std::unique_ptr<const llvm::MCInst>> Instructions; + // Source location range. + llvm::SMLoc RangeStart; + llvm::SMLoc RangeEnd; + + CodeRegion(const CodeRegion &) = delete; + CodeRegion &operator=(const CodeRegion &) = delete; + +public: + CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start) + : Description(Desc), RangeStart(Start), RangeEnd() {} + + void addInstruction(std::unique_ptr<const llvm::MCInst> Instruction) { + Instructions.emplace_back(std::move(Instruction)); + } + + llvm::SMLoc startLoc() const { return RangeStart; } + llvm::SMLoc endLoc() const { return RangeEnd; } + + void setEndLocation(llvm::SMLoc End) { RangeEnd = End; } + bool empty() const { return Instructions.empty(); } + bool isLocInRange(llvm::SMLoc Loc) const; + + const std::vector<std::unique_ptr<const llvm::MCInst>> & + getInstructions() const { + return Instructions; + } + + llvm::StringRef getDescription() const { return Description; } +}; + +class CodeRegions { + // A source manager. Used by the tool to generate meaningful warnings. + llvm::SourceMgr &SM; + + std::vector<std::unique_ptr<CodeRegion>> Regions; + + // Construct a new region of code guarded by LLVM-MCA comments. + void addRegion(llvm::StringRef Description, llvm::SMLoc Loc) { + Regions.emplace_back(llvm::make_unique<CodeRegion>(Description, Loc)); + } + + CodeRegions(const CodeRegions &) = delete; + CodeRegions &operator=(const CodeRegions &) = delete; + +public: + typedef std::vector<std::unique_ptr<CodeRegion>>::iterator iterator; + typedef std::vector<std::unique_ptr<CodeRegion>>::const_iterator + const_iterator; + + iterator begin() { return Regions.begin(); } + iterator end() { return Regions.end(); } + const_iterator begin() const { return Regions.cbegin(); } + const_iterator end() const { return Regions.cend(); } + + void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc); + void endRegion(llvm::SMLoc Loc); + void addInstruction(std::unique_ptr<const llvm::MCInst> Instruction); + + CodeRegions(llvm::SourceMgr &S) : SM(S) { + // Create a default region for the input code sequence. + addRegion("Default", llvm::SMLoc()); + } + + const std::vector<std::unique_ptr<const llvm::MCInst>> & + getInstructionSequence(unsigned Idx) const { + return Regions[Idx]->getInstructions(); + } + + bool empty() const { + return std::all_of(Regions.begin(), Regions.end(), + [](const std::unique_ptr<CodeRegion> &Region) { + return Region->empty(); + }); + } +}; + +} // namespace mca + +#endif diff --git a/llvm/tools/llvm-mca/SourceMgr.h b/llvm/tools/llvm-mca/SourceMgr.h index ec8abaf5940..d7695705107 100644 --- a/llvm/tools/llvm-mca/SourceMgr.h +++ b/llvm/tools/llvm-mca/SourceMgr.h @@ -25,21 +25,20 @@ typedef std::pair<unsigned, const llvm::MCInst *> InstRef; class SourceMgr { using InstVec = std::vector<std::unique_ptr<const llvm::MCInst>>; - InstVec Sequence; + const InstVec &Sequence; unsigned Current; unsigned Iterations; static const unsigned DefaultIterations = 70; public: - SourceMgr(unsigned NumIterations) - : Current(0), + SourceMgr(const InstVec &MCInstSequence, unsigned NumIterations) + : Sequence(MCInstSequence), Current(0), Iterations(NumIterations ? NumIterations : DefaultIterations) {} unsigned getCurrentIteration() const { return Current / Sequence.size(); } unsigned getNumIterations() const { return Iterations; } unsigned size() const { return Sequence.size(); } const InstVec &getSequence() const { return Sequence; } - InstVec &getSequence() { return Sequence; } bool hasNext() { return Current < (Iterations * size()); } void updateNext() { Current++; } diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 91bcb90b3a4..3f9682da17f 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -23,6 +23,7 @@ #include "BackendPrinter.h" #include "BackendStatistics.h" +#include "CodeRegion.h" #include "InstructionInfoView.h" #include "InstructionTables.h" #include "RegisterFileStatistics.h" @@ -158,6 +159,44 @@ const Target *getTarget(const char *ProgName) { return TheTarget; } +// A comment consumer that parses strings. +// The only valid tokens are strings. +class MCACommentConsumer : public AsmCommentConsumer { +public: + mca::CodeRegions &Regions; + + MCACommentConsumer(mca::CodeRegions &R) : Regions(R) {} + void HandleComment(SMLoc Loc, StringRef CommentText) override { + // Skip empty comments. + StringRef Comment(CommentText); + if (Comment.empty()) + return; + + // Skip spaces and tabs + unsigned Position = Comment.find_first_not_of(" \t"); + if (Position >= Comment.size()) + // we reached the end of the comment. Bail out. + return; + + Comment = Comment.drop_front(Position); + if (Comment.consume_front("LLVM-MCA-END")) { + Regions.endRegion(Loc); + return; + } + + // Now try to parse string LLVM-MCA-BEGIN + if (!Comment.consume_front("LLVM-MCA-BEGIN")) + return; + + // Skip spaces and tabs + Position = Comment.find_first_not_of(" \t"); + if (Position < Comment.size()) + Comment.drop_front(Position); + // Use the rest of the string as a descriptor for this code snippet. + Regions.beginRegion(Comment, Loc); + } +}; + int AssembleInput(const char *ProgName, MCAsmParser &Parser, const Target *TheTarget, MCSubtargetInfo &STI, MCInstrInfo &MCII, MCTargetOptions &MCOptions) { @@ -186,17 +225,16 @@ ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() { } class MCStreamerWrapper final : public MCStreamer { - using InstVec = std::vector<std::unique_ptr<const MCInst>>; - InstVec &Insts; + mca::CodeRegions &Regions; public: - MCStreamerWrapper(MCContext &Context, InstVec &Vec) - : MCStreamer(Context), Insts(Vec) {} + MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R) + : MCStreamer(Context), Regions(R) {} // We only want to intercept the emission of new instructions. virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool /* unused */) override { - Insts.emplace_back(new MCInst(Inst)); + Regions.addInstruction(llvm::make_unique<const MCInst>(Inst)); } bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { @@ -213,7 +251,10 @@ public: void EmitCOFFSymbolType(int Type) override {} void EndCOFFSymbolDef() override {} - const InstVec &GetInstructionSequence() const { return Insts; } + const std::vector<std::unique_ptr<const MCInst>> & + GetInstructionSequence(unsigned Index) const { + return Regions.getInstructionSequence(Index); + } }; } // end of anonymous namespace @@ -272,9 +313,8 @@ int main(int argc, char **argv) { std::unique_ptr<buffer_ostream> BOS; - std::unique_ptr<mca::SourceMgr> S = llvm::make_unique<mca::SourceMgr>( - PrintInstructionTables ? 1 : Iterations); - MCStreamerWrapper Str(Ctx, S->getSequence()); + mca::CodeRegions Regions(SrcMgr); + MCStreamerWrapper Str(Ctx, Regions); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI( @@ -310,10 +350,14 @@ int main(int argc, char **argv) { } std::unique_ptr<MCAsmParser> P(createMCAsmParser(SrcMgr, Ctx, Str, *MAI)); + MCAsmLexer &Lexer = P->getLexer(); + MCACommentConsumer CC(Regions); + Lexer.setCommentConsumer(&CC); + if (AssembleInput(ProgName, *P, TheTarget, *STI, *MCII, MCOptions)) return 1; - if (S->isEmpty()) { + if (Regions.empty()) { errs() << "error: no assembly instructions found.\n"; return 1; } @@ -336,49 +380,68 @@ int main(int argc, char **argv) { // Create an instruction builder. mca::InstrBuilder IB(*STI, *MCII); - if (PrintInstructionTables) { - mca::InstructionTables IT(STI->getSchedModel(), IB, *S); - - if (PrintInstructionInfoView) { - IT.addView( - llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, *S, *IP)); + // Number each region in the sequence. + unsigned RegionIdx = 0; + for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) { + // Skip empty code regions. + if (Region->empty()) + continue; + + // Don't print the header of this region if it is the default region, and + // it doesn't have an end location. + if (Region->startLoc().isValid() || Region->endLoc().isValid()) { + TOF->os() << "\n[" << RegionIdx++ << "] Code Region"; + StringRef Desc = Region->getDescription(); + if (!Desc.empty()) + TOF->os() << " - " << Desc; + TOF->os() << "\n\n"; } - IT.addView(llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, *S)); - IT.run(); - IT.printReport(TOF->os()); - TOF->keep(); - return 0; - } + mca::SourceMgr S(Region->getInstructions(), + PrintInstructionTables ? 1 : Iterations); + + if (PrintInstructionTables) { + mca::InstructionTables IT(STI->getSchedModel(), IB, S); + + if (PrintInstructionInfoView) { + IT.addView( + llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, S, *IP)); + } - mca::Backend B(*STI, *MRI, IB, *S, Width, RegisterFileSize, LoadQueueSize, - StoreQueueSize, AssumeNoAlias); - mca::BackendPrinter Printer(B); + IT.addView(llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S)); + IT.run(); + IT.printReport(TOF->os()); + continue; + } + + mca::Backend B(*STI, *MRI, IB, S, Width, RegisterFileSize, LoadQueueSize, + StoreQueueSize, AssumeNoAlias); + mca::BackendPrinter Printer(B); - Printer.addView(llvm::make_unique<mca::SummaryView>(*S, Width)); + Printer.addView(llvm::make_unique<mca::SummaryView>(S, Width)); + if (PrintInstructionInfoView) + Printer.addView( + llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, S, *IP)); - if (PrintInstructionInfoView) - Printer.addView( - llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, *S, *IP)); + if (PrintModeVerbose) + Printer.addView(llvm::make_unique<mca::BackendStatistics>(*STI)); - if (PrintModeVerbose) - Printer.addView(llvm::make_unique<mca::BackendStatistics>(*STI)); + if (PrintRegisterFileStats) + Printer.addView(llvm::make_unique<mca::RegisterFileStatistics>(*STI)); - if (PrintRegisterFileStats) - Printer.addView(llvm::make_unique<mca::RegisterFileStatistics>(*STI)); + if (PrintResourcePressureView) + Printer.addView( + llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S)); - if (PrintResourcePressureView) - Printer.addView( - llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, *S)); + if (PrintTimelineView) { + Printer.addView(llvm::make_unique<mca::TimelineView>( + *STI, *IP, S, TimelineMaxIterations, TimelineMaxCycles)); + } - if (PrintTimelineView) { - Printer.addView(llvm::make_unique<mca::TimelineView>( - *STI, *IP, *S, TimelineMaxIterations, TimelineMaxCycles)); + B.run(); + Printer.printReport(TOF->os()); } - B.run(); - Printer.printReport(TOF->os()); TOF->keep(); - return 0; } |