diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 | 
| commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
| tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/tools/llvm-mca | |
| parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
| parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/tools/llvm-mca')
7 files changed, 461 insertions, 99 deletions
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp index 7662538e3b68..c91ed759ee77 100644 --- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp +++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp @@ -16,11 +16,6 @@  namespace llvm {  namespace mca { -CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) { -  // Create a default region for the input code sequence. -  Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc())); -} -  bool CodeRegion::isLocInRange(SMLoc Loc) const {    if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())      return false; @@ -29,7 +24,19 @@ bool CodeRegion::isLocInRange(SMLoc Loc) const {    return true;  } -void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) { +void CodeRegions::addInstruction(const MCInst &Instruction) { +  SMLoc Loc = Instruction.getLoc(); +  for (UniqueCodeRegion &Region : Regions) +    if (Region->isLocInRange(Loc)) +      Region->addInstruction(Instruction); +} + +AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) { +  // Create a default region for the input code sequence. +  Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc())); +} + +void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {    if (ActiveRegions.empty()) {      // Remove the default region if there is at least one user defined region.      // By construction, only the default region has an invalid start location. @@ -44,17 +51,17 @@ void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {      if (It != ActiveRegions.end()) {        const CodeRegion &R = *Regions[It->second];        if (Description.empty()) { -        SM.PrintMessage(Loc, SourceMgr::DK_Error, +        SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,                          "found multiple overlapping anonymous regions"); -        SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note, +        SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,                          "Previous anonymous region was defined here");          FoundErrors = true;          return;        } -      SM.PrintMessage(Loc, SourceMgr::DK_Error, +      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,                        "overlapping regions cannot have the same name"); -      SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note, +      SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,                        "region " + Description + " was previously defined here");        FoundErrors = true;        return; @@ -65,7 +72,7 @@ void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {    Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));  } -void CodeRegions::endRegion(StringRef Description, SMLoc Loc) { +void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {    if (Description.empty()) {      // Special case where there is only one user defined region,      // and this LLVM-MCA-END directive doesn't provide a region name. @@ -94,22 +101,73 @@ void CodeRegions::endRegion(StringRef Description, SMLoc Loc) {    }    FoundErrors = true; -  SM.PrintMessage(Loc, SourceMgr::DK_Error, +  SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,                    "found an invalid region end directive");    if (!Description.empty()) { -    SM.PrintMessage(Loc, SourceMgr::DK_Note, +    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,                      "unable to find an active region named " + Description);    } else { -    SM.PrintMessage(Loc, SourceMgr::DK_Note, +    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,                      "unable to find an active anonymous region");    }  } -void CodeRegions::addInstruction(const MCInst &Instruction) { -  SMLoc Loc = Instruction.getLoc(); -  for (UniqueCodeRegion &Region : Regions) -    if (Region->isLocInRange(Loc)) -      Region->addInstruction(Instruction); +InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {} + +void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc, +                                    SharedInstrument I) { +  if (Description.empty()) { +    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, +                    "anonymous instrumentation regions are not permitted"); +    FoundErrors = true; +    return; +  } + +  auto It = ActiveRegions.find(Description); +  if (It != ActiveRegions.end()) { +    const CodeRegion &R = *Regions[It->second]; +    SM.PrintMessage( +        Loc, llvm::SourceMgr::DK_Error, +        "overlapping instrumentation regions cannot be of the same kind"); +    SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note, +                    "instrumentation region " + Description + +                        " was previously defined here"); +    FoundErrors = true; +    return; +  } + +  ActiveRegions[Description] = Regions.size(); +  Regions.emplace_back(std::make_unique<InstrumentRegion>(Description, Loc, I)); +} + +void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) { +  auto It = ActiveRegions.find(Description); +  if (It != ActiveRegions.end()) { +    Regions[It->second]->setEndLocation(Loc); +    ActiveRegions.erase(It); +    return; +  } + +  FoundErrors = true; +  SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, +                  "found an invalid instrumentation region end directive"); +  if (!Description.empty()) { +    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note, +                    "unable to find an active instrumentation region named " + +                        Description); +  } +} + +const SmallVector<SharedInstrument> +InstrumentRegions::getActiveInstruments(SMLoc Loc) const { +  SmallVector<SharedInstrument> AI; +  for (auto &R : Regions) { +    if (R->isLocInRange(Loc)) { +      InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get()); +      AI.emplace_back(IR->getInstrument()); +    } +  } +  return AI;  }  } // namespace mca diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h index 0e1e02a533d8..b5b2f3a0d118 100644 --- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h +++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h @@ -7,7 +7,8 @@  //===----------------------------------------------------------------------===//  /// \file  /// -/// This file implements class CodeRegion and CodeRegions. +/// This file implements class CodeRegion and CodeRegions, InstrumentRegion, +/// AnalysisRegions, and InstrumentRegions.  ///  /// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA  /// comment directives. @@ -25,8 +26,32 @@  /// 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]. +/// An instruction (a MCInst) is added to a CodeRegion R only if its +/// location is in range [R.RangeStart, R.RangeEnd]. +/// +/// A InstrumentRegion describes a region of assembly code guarded by +/// special LLVM-MCA comment directives. +/// +///   # LLVM-MCA-<INSTRUMENTATION_TYPE> <data> +///     ...  ## asm +/// +/// where INSTRUMENTATION_TYPE is a type defined in llvm and expects to use +/// data. +/// +/// A comment starting with substring LLVM-MCA-<INSTRUMENTATION_TYPE> +/// brings data into scope for llvm-mca to use in its analysis for +/// all following instructions. +/// +/// If the same INSTRUMENTATION_TYPE is found later in the instruction list, +/// then the original InstrumentRegion will be automatically ended, +/// and a new InstrumentRegion will begin. +/// +/// If there are comments containing the different INSTRUMENTATION_TYPEs, +/// then both data sets remain available. In contrast with a CodeRegion, +/// an InstrumentRegion does not need a comment to end the region. +// +// An instruction (a MCInst) is added to an InstrumentRegion R only +// if its location is in range [R.RangeStart, R.RangeEnd].  //  //===----------------------------------------------------------------------===// @@ -38,6 +63,7 @@  #include "llvm/ADT/StringMap.h"  #include "llvm/ADT/StringRef.h"  #include "llvm/MC/MCInst.h" +#include "llvm/MCA/CustomBehaviour.h"  #include "llvm/Support/Error.h"  #include "llvm/Support/SMLoc.h"  #include "llvm/Support/SourceMgr.h" @@ -81,9 +107,31 @@ public:    llvm::StringRef getDescription() const { return Description; }  }; +/// Alias AnalysisRegion with CodeRegion since CodeRegionGenerator +/// is absract and AnalysisRegionGenerator operates on AnalysisRegions +using AnalysisRegion = CodeRegion; + +/// A CodeRegion that contains instrumentation that can be used +/// in analysis of the region. +class InstrumentRegion : public CodeRegion { +  /// Instrument for this region. +  SharedInstrument Instrument; + +public: +  InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, SharedInstrument I) +      : CodeRegion(Desc, Start), Instrument(I) {} + +public: +  SharedInstrument getInstrument() const { return Instrument; } +}; +  class CodeRegionParseError final : public Error {};  class CodeRegions { +  CodeRegions(const CodeRegions &) = delete; +  CodeRegions &operator=(const CodeRegions &) = delete; + +protected:    // A source manager. Used by the tool to generate meaningful warnings.    llvm::SourceMgr &SM; @@ -92,11 +140,8 @@ class CodeRegions {    llvm::StringMap<unsigned> ActiveRegions;    bool FoundErrors; -  CodeRegions(const CodeRegions &) = delete; -  CodeRegions &operator=(const CodeRegions &) = delete; -  public: -  CodeRegions(llvm::SourceMgr &S); +  CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {}    typedef std::vector<UniqueCodeRegion>::iterator iterator;    typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator; @@ -106,8 +151,6 @@ public:    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::StringRef Description, llvm::SMLoc Loc);    void addInstruction(const llvm::MCInst &Instruction);    llvm::SourceMgr &getSourceMgr() const { return SM; } @@ -122,6 +165,28 @@ public:    }    bool isValid() const { return !FoundErrors; } + +  bool isRegionActive(llvm::StringRef Description) const { +    return ActiveRegions.find(Description) != ActiveRegions.end(); +  } +}; + +struct AnalysisRegions : public CodeRegions { +  AnalysisRegions(llvm::SourceMgr &S); + +  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc); +  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc); +}; + +struct InstrumentRegions : public CodeRegions { +  InstrumentRegions(llvm::SourceMgr &S); + +  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc, +                   SharedInstrument Instrument); +  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc); + +  const SmallVector<SharedInstrument> +  getActiveInstruments(llvm::SMLoc Loc) const;  };  } // namespace mca diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp index cdecfba9a375..b8e10fa69c2d 100644 --- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp @@ -16,7 +16,6 @@  #include "CodeRegionGenerator.h"  #include "llvm/ADT/ArrayRef.h"  #include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCParser/MCAsmLexer.h"  #include "llvm/MC/MCParser/MCTargetAsmParser.h"  #include "llvm/MC/MCStreamer.h"  #include "llvm/MC/MCTargetOptions.h" @@ -30,15 +29,6 @@ namespace mca {  // This virtual dtor serves as the anchor for the CodeRegionGenerator class.  CodeRegionGenerator::~CodeRegionGenerator() {} -// A comment consumer that parses strings.  The only valid tokens are strings. -class MCACommentConsumer : public AsmCommentConsumer { -public: -  CodeRegions &Regions; - -  MCACommentConsumer(CodeRegions &R) : Regions(R) {} -  void HandleComment(SMLoc Loc, StringRef CommentText) override; -}; -  // This class provides the callbacks that occur when parsing input assembly.  class MCStreamerWrapper final : public MCStreamer {    CodeRegions &Regions; @@ -58,9 +48,9 @@ public:    }    void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, -                        unsigned ByteAlignment) override {} +                        Align ByteAlignment) override {}    void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, -                    uint64_t Size = 0, unsigned ByteAlignment = 0, +                    uint64_t Size = 0, Align ByteAlignment = Align(1),                      SMLoc Loc = SMLoc()) override {}    void emitGPRel32Value(const MCExpr *Value) override {}    void beginCOFFSymbolDef(const MCSymbol *Symbol) override {} @@ -73,7 +63,53 @@ public:    }  }; -void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) { +Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions( +    const std::unique_ptr<MCInstPrinter> &IP) { +  MCTargetOptions Opts; +  Opts.PreserveAsmComments = false; +  CodeRegions &Regions = getRegions(); +  MCStreamerWrapper Str(Ctx, Regions); + +  // Need to initialize an MCTargetStreamer otherwise +  // certain asm directives will cause a segfault. +  // Using nulls() so that anything emitted by the MCTargetStreamer +  // doesn't show up in the llvm-mca output. +  raw_ostream &OSRef = nulls(); +  formatted_raw_ostream FOSRef(OSRef); +  TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(), +                                    /*IsVerboseAsm=*/true); + +  // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM +  // comments. +  std::unique_ptr<MCAsmParser> Parser( +      createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI)); +  MCAsmLexer &Lexer = Parser->getLexer(); +  MCACommentConsumer *CCP = getCommentConsumer(); +  Lexer.setCommentConsumer(CCP); +  // Enable support for MASM literal numbers (example: 05h, 101b). +  Lexer.setLexMasmIntegers(true); + +  std::unique_ptr<MCTargetAsmParser> TAP( +      TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts)); +  if (!TAP) +    return make_error<StringError>( +        "This target does not support assembly parsing.", +        inconvertibleErrorCode()); +  Parser->setTargetParser(*TAP); +  Parser->Run(false); + +  if (CCP->hadErr()) +    return make_error<StringError>("There was an error parsing comments.", +                                   inconvertibleErrorCode()); + +  // Set the assembler dialect from the input. llvm-mca will use this as the +  // default dialect when printing reports. +  AssemblerDialect = Parser->getAssemblerDialect(); +  return Regions; +} + +void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc, +                                                  StringRef CommentText) {    // Skip empty comments.    StringRef Comment(CommentText);    if (Comment.empty()) @@ -107,44 +143,66 @@ void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) {    Regions.beginRegion(Comment, Loc);  } -Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions( -    const std::unique_ptr<MCInstPrinter> &IP) { -  MCTargetOptions Opts; -  Opts.PreserveAsmComments = false; -  MCStreamerWrapper Str(Ctx, Regions); +void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc, +                                                    StringRef CommentText) { +  // Skip empty comments. +  StringRef Comment(CommentText); +  if (Comment.empty()) +    return; -  // Need to initialize an MCTargetStreamer otherwise -  // certain asm directives will cause a segfault. -  // Using nulls() so that anything emitted by the MCTargetStreamer -  // doesn't show up in the llvm-mca output. -  raw_ostream &OSRef = nulls(); -  formatted_raw_ostream FOSRef(OSRef); -  TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(), -                                    /*IsVerboseAsm=*/true); +  // 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); -  // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM -  // comments. -  std::unique_ptr<MCAsmParser> Parser( -      createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI)); -  MCAsmLexer &Lexer = Parser->getLexer(); -  MCACommentConsumer CC(Regions); -  Lexer.setCommentConsumer(&CC); -  // Enable support for MASM literal numbers (example: 05h, 101b). -  Lexer.setLexMasmIntegers(true); +  // Bail out if not an MCA style comment +  if (!Comment.consume_front("LLVM-MCA-")) +    return; -  std::unique_ptr<MCTargetAsmParser> TAP( -      TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts)); -  if (!TAP) -    return make_error<StringError>( -        "This target does not support assembly parsing.", -        inconvertibleErrorCode()); -  Parser->setTargetParser(*TAP); -  Parser->Run(false); +  // Skip AnalysisRegion comments +  if (Comment.consume_front("BEGIN") || Comment.consume_front("END")) +    return; -  // Set the assembler dialect from the input. llvm-mca will use this as the -  // default dialect when printing reports. -  AssemblerDialect = Parser->getAssemblerDialect(); -  return Regions; +  if (IM.shouldIgnoreInstruments()) +    return; + +  auto [InstrumentKind, Data] = Comment.split(" "); + +  // An error if not of the form LLVM-MCA-TARGET-KIND +  if (!IM.supportsInstrumentType(InstrumentKind)) { +    if (InstrumentKind.empty()) +      SM.PrintMessage( +          Loc, llvm::SourceMgr::DK_Error, +          "No instrumentation kind was provided in LLVM-MCA comment"); +    else +      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, +                      "Unknown instrumentation type in LLVM-MCA comment: " + +                          InstrumentKind); +    FoundError = true; +    return; +  } + +  SharedInstrument I = IM.createInstrument(InstrumentKind, Data); +  if (!I) { +    if (Data.empty()) +      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, +                      "Failed to create " + InstrumentKind + +                          " instrument with no data"); +    else +      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, +                      "Failed to create " + InstrumentKind + +                          " instrument with data: " + Data); +    FoundError = true; +    return; +  } + +  // End InstrumentType region if one is open +  if (Regions.isRegionActive(InstrumentKind)) +    Regions.endRegion(InstrumentKind, Loc); +  // Start new instrumentation region +  Regions.beginRegion(InstrumentKind, Loc, I);  }  } // namespace mca diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h index ac02131b2f39..88621ed856c5 100644 --- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h +++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h @@ -19,8 +19,10 @@  #include "CodeRegion.h"  #include "llvm/MC/MCAsmInfo.h"  #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCParser/MCAsmLexer.h"  #include "llvm/MC/MCSubtargetInfo.h"  #include "llvm/MC/TargetRegistry.h" +#include "llvm/MCA/CustomBehaviour.h"  #include "llvm/Support/Error.h"  #include "llvm/Support/SourceMgr.h"  #include <memory> @@ -28,24 +30,96 @@  namespace llvm {  namespace mca { -/// This class is responsible for parsing the input given to the llvm-mca -/// driver, and converting that into a CodeRegions instance. +class MCACommentConsumer : public AsmCommentConsumer { +protected: +  bool FoundError; + +public: +  MCACommentConsumer() : FoundError(false) {} + +  bool hadErr() const { return FoundError; } +}; + +/// A comment consumer that parses strings.  The only valid tokens are strings. +class AnalysisRegionCommentConsumer : public MCACommentConsumer { +  AnalysisRegions &Regions; + +public: +  AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {} + +  /// Parses a comment. It begins a new region if it is of the form +  /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END. +  /// Regions can be optionally named if they are of the form +  /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are +  /// permitted, but a region that begins while another region is active +  /// must be ended before the outer region is ended. If thre is only one +  /// active region, LLVM-MCA-END does not need to provide a name. +  void HandleComment(SMLoc Loc, StringRef CommentText) override; +}; + +/// A comment consumer that parses strings to create InstrumentRegions. +/// The only valid tokens are strings. +class InstrumentRegionCommentConsumer : public MCACommentConsumer { +  llvm::SourceMgr &SM; + +  InstrumentRegions &Regions; + +  InstrumentManager &IM; + +public: +  InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R, +                                  InstrumentManager &IM) +      : SM(SM), Regions(R), IM(IM) {} + +  /// Parses a comment. It begins a new region if it is of the form +  /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE +  /// is a valid InstrumentKind. If there is already an active +  /// region of type INSTRUMENATION_TYPE, then it will end the active +  /// one and begin a new one using the new data. +  void HandleComment(SMLoc Loc, StringRef CommentText) override; +}; + +/// This abstract class is responsible for parsing the input given to +/// the llvm-mca driver, and converting that into a CodeRegions instance.  class CodeRegionGenerator {  protected: -  CodeRegions Regions;    CodeRegionGenerator(const CodeRegionGenerator &) = delete;    CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete; +  virtual Expected<const CodeRegions &> +  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;  public: -  CodeRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {} +  CodeRegionGenerator() {}    virtual ~CodeRegionGenerator(); -  virtual Expected<const CodeRegions &> -  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;  }; -/// This class is responsible for parsing input ASM and generating -/// a CodeRegions instance. -class AsmCodeRegionGenerator final : public CodeRegionGenerator { +/// Abastract CodeRegionGenerator with AnalysisRegions member +class AnalysisRegionGenerator : public virtual CodeRegionGenerator { +protected: +  AnalysisRegions Regions; + +public: +  AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {} + +  virtual Expected<const AnalysisRegions &> +  parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0; +}; + +/// Abstract CodeRegionGenerator with InstrumentRegionsRegions member +class InstrumentRegionGenerator : public virtual CodeRegionGenerator { +protected: +  InstrumentRegions Regions; + +public: +  InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {} + +  virtual Expected<const InstrumentRegions &> +  parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0; +}; + +/// This abstract class is responsible for parsing input ASM and +/// generating a CodeRegions instance. +class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {    const Target &TheTarget;    MCContext &Ctx;    const MCAsmInfo &MAI; @@ -54,17 +128,77 @@ class AsmCodeRegionGenerator final : public CodeRegionGenerator {    unsigned AssemblerDialect; // This is set during parsing.  public: -  AsmCodeRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C, -                         const MCAsmInfo &A, const MCSubtargetInfo &S, -                         const MCInstrInfo &I) -      : CodeRegionGenerator(SM), TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I), -        AssemblerDialect(0) {} +  AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A, +                         const MCSubtargetInfo &S, const MCInstrInfo &I) +      : TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I), AssemblerDialect(0) {} + +  virtual MCACommentConsumer *getCommentConsumer() = 0; +  virtual CodeRegions &getRegions() = 0;    unsigned getAssemblerDialect() const { return AssemblerDialect; }    Expected<const CodeRegions &>    parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override;  }; +class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator, +                                         public AsmCodeRegionGenerator { +  AnalysisRegionCommentConsumer CC; + +public: +  AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C, +                             const MCAsmInfo &A, const MCSubtargetInfo &S, +                             const MCInstrInfo &I) +      : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I), +        CC(Regions) {} + +  MCACommentConsumer *getCommentConsumer() override { return &CC; }; +  CodeRegions &getRegions() override { return Regions; }; + +  Expected<const AnalysisRegions &> +  parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override { +    Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP); +    if (!RegionsOrErr) +      return RegionsOrErr.takeError(); +    else +      return static_cast<const AnalysisRegions &>(*RegionsOrErr); +  } + +  Expected<const CodeRegions &> +  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override { +    return AsmCodeRegionGenerator::parseCodeRegions(IP); +  } +}; + +class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator, +                                           public AsmCodeRegionGenerator { +  InstrumentRegionCommentConsumer CC; + +public: +  AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM, +                               MCContext &C, const MCAsmInfo &A, +                               const MCSubtargetInfo &S, const MCInstrInfo &I, +                               InstrumentManager &IM) +      : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I), +        CC(SM, Regions, IM) {} + +  MCACommentConsumer *getCommentConsumer() override { return &CC; }; +  CodeRegions &getRegions() override { return Regions; }; + +  Expected<const InstrumentRegions &> +  parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override { +    Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP); +    if (!RegionsOrErr) +      return RegionsOrErr.takeError(); +    else +      return static_cast<const InstrumentRegions &>(*RegionsOrErr); +  } + +  Expected<const CodeRegions &> +  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override { +    return AsmCodeRegionGenerator::parseCodeRegions(IP); +  } +}; +  } // namespace mca  } // namespace llvm diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp index d3f9738b6323..257fdca8cb36 100644 --- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp +++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp @@ -71,7 +71,7 @@ void InstructionInfoView::printView(raw_ostream &OS) const {        TempStream << ' ';      if (IIVDEntry.RThroughput) { -      double RT = IIVDEntry.RThroughput.value(); +      double RT = *IIVDEntry.RThroughput;        TempStream << format("%.2f", RT) << ' ';        if (RT < 10.0)          TempStream << "  "; diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h index c35d316775f4..bddd01a086b5 100644 --- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h +++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h @@ -61,7 +61,7 @@ class InstructionInfoView : public InstructionView {    struct InstructionInfoViewData {      unsigned NumMicroOpcodes = 0;      unsigned Latency = 0; -    Optional<double> RThroughput = 0.0; +    std::optional<double> RThroughput = 0.0;      bool mayLoad = false;      bool mayStore = false;      bool hasUnmodeledSideEffects = false; diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp index 6f7b74fd11ec..73c341891ab7 100644 --- a/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp @@ -231,6 +231,12 @@ static cl::opt<bool> DisableCustomBehaviour(          "Disable custom behaviour (use the default class which does nothing)."),      cl::cat(ViewOptions), cl::init(false)); +static cl::opt<bool> DisableInstrumentManager( +    "disable-im", +    cl::desc("Disable instrumentation manager (use the default class which " +             "ignores instruments.)."), +    cl::cat(ViewOptions), cl::init(false)); +  namespace {  const Target *getTarget(const char *ProgName) { @@ -316,6 +322,9 @@ int main(int argc, char **argv) {    InitializeAllAsmParsers();    InitializeAllTargetMCAs(); +  // Register the Target and CPU printer for --version. +  cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU); +    // Enable printing of available targets when flag --version is specified.    cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); @@ -407,7 +416,7 @@ int main(int argc, char **argv) {    // Need to initialize an MCInstPrinter as it is    // required for initializing the MCTargetStreamer -  // which needs to happen within the CRG.parseCodeRegions() call below. +  // which needs to happen within the CRG.parseAnalysisRegions() call below.    // Without an MCTargetStreamer, certain assembly directives can trigger a    // segfault. (For example, the .cv_fpo_proc directive on x86 will segfault if    // we don't initialize the MCTargetStreamer.) @@ -424,9 +433,10 @@ int main(int argc, char **argv) {    }    // Parse the input and create CodeRegions that llvm-mca can analyze. -  mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII); -  Expected<const mca::CodeRegions &> RegionsOrErr = -      CRG.parseCodeRegions(std::move(IPtemp)); +  mca::AsmAnalysisRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, +                                      *MCII); +  Expected<const mca::AnalysisRegions &> RegionsOrErr = +      CRG.parseAnalysisRegions(std::move(IPtemp));    if (!RegionsOrErr) {      if (auto Err =              handleErrors(RegionsOrErr.takeError(), [](const StringError &E) { @@ -437,7 +447,7 @@ int main(int argc, char **argv) {      }      return 1;    } -  const mca::CodeRegions &Regions = *RegionsOrErr; +  const mca::AnalysisRegions &Regions = *RegionsOrErr;    // Early exit if errors were found by the code region parsing logic.    if (!Regions.isValid()) @@ -448,6 +458,39 @@ int main(int argc, char **argv) {      return 1;    } +  std::unique_ptr<mca::InstrumentManager> IM; +  if (!DisableInstrumentManager) { +    IM = std::unique_ptr<mca::InstrumentManager>( +        TheTarget->createInstrumentManager(*STI, *MCII)); +  } +  if (!IM) { +    // If the target doesn't have its own IM implemented (or the -disable-cb +    // flag is set) then we use the base class (which does nothing). +    IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII); +  } + +  // Parse the input and create InstrumentRegion that llvm-mca +  // can use to improve analysis. +  mca::AsmInstrumentRegionGenerator IRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, +                                        *MCII, *IM); +  Expected<const mca::InstrumentRegions &> InstrumentRegionsOrErr = +      IRG.parseInstrumentRegions(std::move(IPtemp)); +  if (!InstrumentRegionsOrErr) { +    if (auto Err = handleErrors(InstrumentRegionsOrErr.takeError(), +                                [](const StringError &E) { +                                  WithColor::error() << E.getMessage() << '\n'; +                                })) { +      // Default case. +      WithColor::error() << toString(std::move(Err)) << '\n'; +    } +    return 1; +  } +  const mca::InstrumentRegions &InstrumentRegions = *InstrumentRegionsOrErr; + +  // Early exit if errors were found by the instrumentation parsing logic. +  if (!InstrumentRegions.isValid()) +    return 1; +    // Now initialize the output file.    auto OF = getOutputStream();    if (std::error_code EC = OF.getError()) { @@ -491,7 +534,7 @@ int main(int argc, char **argv) {    }    // Create an instruction builder. -  mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get()); +  mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM);    // Create a context to control ownership of the pipeline hardware.    mca::Context MCA(*MRI, *STI); @@ -512,7 +555,7 @@ int main(int argc, char **argv) {    assert(MAB && "Unable to create asm backend!");    json::Object JSONOutput; -  for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) { +  for (const std::unique_ptr<mca::AnalysisRegion> &Region : Regions) {      // Skip empty code regions.      if (Region->empty())        continue; @@ -527,8 +570,12 @@ int main(int argc, char **argv) {      SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence;      for (const MCInst &MCI : Insts) { +      SMLoc Loc = MCI.getLoc(); +      const SmallVector<mca::SharedInstrument> Instruments = +          InstrumentRegions.getActiveInstruments(Loc); +        Expected<std::unique_ptr<mca::Instruction>> Inst = -          IB.createInstruction(MCI); +          IB.createInstruction(MCI, Instruments);        if (!Inst) {          if (auto NewE = handleErrors(                  Inst.takeError(),  | 
