109467b48Spatrick //===-------------------------- CodeRegion.h -------------------*- C++ -* -===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick /// \file 909467b48Spatrick /// 10*d415bd75Srobert /// This file implements class CodeRegion and CodeRegions, InstrumentRegion, 11*d415bd75Srobert /// AnalysisRegions, and InstrumentRegions. 1209467b48Spatrick /// 1309467b48Spatrick /// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA 1409467b48Spatrick /// comment directives. 1509467b48Spatrick /// 1609467b48Spatrick /// # LLVM-MCA-BEGIN foo 1709467b48Spatrick /// ... ## asm 1809467b48Spatrick /// # LLVM-MCA-END 1909467b48Spatrick /// 2009467b48Spatrick /// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a 2109467b48Spatrick /// new region of code. 2209467b48Spatrick /// A comment starting with substring LLVM-MCA-END marks the end of the 2309467b48Spatrick /// last-seen region of code. 2409467b48Spatrick /// 2509467b48Spatrick /// Code regions are not allowed to overlap. Each region can have a optional 2609467b48Spatrick /// description; internally, regions are described by a range of source 2709467b48Spatrick /// locations (SMLoc objects). 2809467b48Spatrick /// 29*d415bd75Srobert /// An instruction (a MCInst) is added to a CodeRegion R only if its 30*d415bd75Srobert /// location is in range [R.RangeStart, R.RangeEnd]. 31*d415bd75Srobert /// 32*d415bd75Srobert /// A InstrumentRegion describes a region of assembly code guarded by 33*d415bd75Srobert /// special LLVM-MCA comment directives. 34*d415bd75Srobert /// 35*d415bd75Srobert /// # LLVM-MCA-<INSTRUMENTATION_TYPE> <data> 36*d415bd75Srobert /// ... ## asm 37*d415bd75Srobert /// 38*d415bd75Srobert /// where INSTRUMENTATION_TYPE is a type defined in llvm and expects to use 39*d415bd75Srobert /// data. 40*d415bd75Srobert /// 41*d415bd75Srobert /// A comment starting with substring LLVM-MCA-<INSTRUMENTATION_TYPE> 42*d415bd75Srobert /// brings data into scope for llvm-mca to use in its analysis for 43*d415bd75Srobert /// all following instructions. 44*d415bd75Srobert /// 45*d415bd75Srobert /// If the same INSTRUMENTATION_TYPE is found later in the instruction list, 46*d415bd75Srobert /// then the original InstrumentRegion will be automatically ended, 47*d415bd75Srobert /// and a new InstrumentRegion will begin. 48*d415bd75Srobert /// 49*d415bd75Srobert /// If there are comments containing the different INSTRUMENTATION_TYPEs, 50*d415bd75Srobert /// then both data sets remain available. In contrast with a CodeRegion, 51*d415bd75Srobert /// an InstrumentRegion does not need a comment to end the region. 52*d415bd75Srobert // 53*d415bd75Srobert // An instruction (a MCInst) is added to an InstrumentRegion R only 54*d415bd75Srobert // if its location is in range [R.RangeStart, R.RangeEnd]. 5509467b48Spatrick // 5609467b48Spatrick //===----------------------------------------------------------------------===// 5709467b48Spatrick 5809467b48Spatrick #ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H 5909467b48Spatrick #define LLVM_TOOLS_LLVM_MCA_CODEREGION_H 6009467b48Spatrick 6109467b48Spatrick #include "llvm/ADT/ArrayRef.h" 6209467b48Spatrick #include "llvm/ADT/SmallVector.h" 63097a140dSpatrick #include "llvm/ADT/StringMap.h" 6409467b48Spatrick #include "llvm/ADT/StringRef.h" 6509467b48Spatrick #include "llvm/MC/MCInst.h" 66*d415bd75Srobert #include "llvm/MCA/CustomBehaviour.h" 67097a140dSpatrick #include "llvm/Support/Error.h" 6809467b48Spatrick #include "llvm/Support/SMLoc.h" 6909467b48Spatrick #include "llvm/Support/SourceMgr.h" 7009467b48Spatrick #include <vector> 7109467b48Spatrick 7209467b48Spatrick namespace llvm { 7309467b48Spatrick namespace mca { 7409467b48Spatrick 7509467b48Spatrick /// A region of assembly code. 7609467b48Spatrick /// 7709467b48Spatrick /// It identifies a sequence of machine instructions. 7809467b48Spatrick class CodeRegion { 7909467b48Spatrick // An optional descriptor for this region. 8009467b48Spatrick llvm::StringRef Description; 8109467b48Spatrick // Instructions that form this region. 8273471bf0Spatrick llvm::SmallVector<llvm::MCInst, 16> Instructions; 8309467b48Spatrick // Source location range. 8409467b48Spatrick llvm::SMLoc RangeStart; 8509467b48Spatrick llvm::SMLoc RangeEnd; 8609467b48Spatrick 8709467b48Spatrick CodeRegion(const CodeRegion &) = delete; 8809467b48Spatrick CodeRegion &operator=(const CodeRegion &) = delete; 8909467b48Spatrick 9009467b48Spatrick public: CodeRegion(llvm::StringRef Desc,llvm::SMLoc Start)9109467b48Spatrick CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start) 92*d415bd75Srobert : Description(Desc), RangeStart(Start) {} 9309467b48Spatrick addInstruction(const llvm::MCInst & Instruction)9409467b48Spatrick void addInstruction(const llvm::MCInst &Instruction) { 9509467b48Spatrick Instructions.emplace_back(Instruction); 9609467b48Spatrick } 9709467b48Spatrick startLoc()9809467b48Spatrick llvm::SMLoc startLoc() const { return RangeStart; } endLoc()9909467b48Spatrick llvm::SMLoc endLoc() const { return RangeEnd; } 10009467b48Spatrick setEndLocation(llvm::SMLoc End)10109467b48Spatrick void setEndLocation(llvm::SMLoc End) { RangeEnd = End; } empty()10209467b48Spatrick bool empty() const { return Instructions.empty(); } 10309467b48Spatrick bool isLocInRange(llvm::SMLoc Loc) const; 10409467b48Spatrick getInstructions()10509467b48Spatrick llvm::ArrayRef<llvm::MCInst> getInstructions() const { return Instructions; } 10609467b48Spatrick getDescription()10709467b48Spatrick llvm::StringRef getDescription() const { return Description; } 10809467b48Spatrick }; 10909467b48Spatrick 110*d415bd75Srobert /// Alias AnalysisRegion with CodeRegion since CodeRegionGenerator 111*d415bd75Srobert /// is absract and AnalysisRegionGenerator operates on AnalysisRegions 112*d415bd75Srobert using AnalysisRegion = CodeRegion; 113*d415bd75Srobert 114*d415bd75Srobert /// A CodeRegion that contains instrumentation that can be used 115*d415bd75Srobert /// in analysis of the region. 116*d415bd75Srobert class InstrumentRegion : public CodeRegion { 117*d415bd75Srobert /// Instrument for this region. 118*d415bd75Srobert SharedInstrument Instrument; 119*d415bd75Srobert 120*d415bd75Srobert public: InstrumentRegion(llvm::StringRef Desc,llvm::SMLoc Start,SharedInstrument I)121*d415bd75Srobert InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, SharedInstrument I) 122*d415bd75Srobert : CodeRegion(Desc, Start), Instrument(I) {} 123*d415bd75Srobert 124*d415bd75Srobert public: getInstrument()125*d415bd75Srobert SharedInstrument getInstrument() const { return Instrument; } 126*d415bd75Srobert }; 127*d415bd75Srobert 12809467b48Spatrick class CodeRegionParseError final : public Error {}; 12909467b48Spatrick 13009467b48Spatrick class CodeRegions { 131*d415bd75Srobert CodeRegions(const CodeRegions &) = delete; 132*d415bd75Srobert CodeRegions &operator=(const CodeRegions &) = delete; 133*d415bd75Srobert 134*d415bd75Srobert protected: 13509467b48Spatrick // A source manager. Used by the tool to generate meaningful warnings. 13609467b48Spatrick llvm::SourceMgr &SM; 13709467b48Spatrick 13809467b48Spatrick using UniqueCodeRegion = std::unique_ptr<CodeRegion>; 13909467b48Spatrick std::vector<UniqueCodeRegion> Regions; 14009467b48Spatrick llvm::StringMap<unsigned> ActiveRegions; 14109467b48Spatrick bool FoundErrors; 14209467b48Spatrick 14309467b48Spatrick public: CodeRegions(llvm::SourceMgr & S)144*d415bd75Srobert CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {} 14509467b48Spatrick 14609467b48Spatrick typedef std::vector<UniqueCodeRegion>::iterator iterator; 14709467b48Spatrick typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator; 14809467b48Spatrick begin()14909467b48Spatrick iterator begin() { return Regions.begin(); } end()15009467b48Spatrick iterator end() { return Regions.end(); } begin()15109467b48Spatrick const_iterator begin() const { return Regions.cbegin(); } end()15209467b48Spatrick const_iterator end() const { return Regions.cend(); } 15309467b48Spatrick 15409467b48Spatrick void addInstruction(const llvm::MCInst &Instruction); getSourceMgr()15509467b48Spatrick llvm::SourceMgr &getSourceMgr() const { return SM; } 15609467b48Spatrick getInstructionSequence(unsigned Idx)15709467b48Spatrick llvm::ArrayRef<llvm::MCInst> getInstructionSequence(unsigned Idx) const { 15809467b48Spatrick return Regions[Idx]->getInstructions(); 15909467b48Spatrick } 16009467b48Spatrick empty()16109467b48Spatrick bool empty() const { 16209467b48Spatrick return llvm::all_of(Regions, [](const UniqueCodeRegion &Region) { 16309467b48Spatrick return Region->empty(); 16409467b48Spatrick }); 16509467b48Spatrick } 16609467b48Spatrick isValid()16709467b48Spatrick bool isValid() const { return !FoundErrors; } 168*d415bd75Srobert isRegionActive(llvm::StringRef Description)169*d415bd75Srobert bool isRegionActive(llvm::StringRef Description) const { 170*d415bd75Srobert return ActiveRegions.find(Description) != ActiveRegions.end(); 171*d415bd75Srobert } 172*d415bd75Srobert }; 173*d415bd75Srobert 174*d415bd75Srobert struct AnalysisRegions : public CodeRegions { 175*d415bd75Srobert AnalysisRegions(llvm::SourceMgr &S); 176*d415bd75Srobert 177*d415bd75Srobert void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc); 178*d415bd75Srobert void endRegion(llvm::StringRef Description, llvm::SMLoc Loc); 179*d415bd75Srobert }; 180*d415bd75Srobert 181*d415bd75Srobert struct InstrumentRegions : public CodeRegions { 182*d415bd75Srobert InstrumentRegions(llvm::SourceMgr &S); 183*d415bd75Srobert 184*d415bd75Srobert void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc, 185*d415bd75Srobert SharedInstrument Instrument); 186*d415bd75Srobert void endRegion(llvm::StringRef Description, llvm::SMLoc Loc); 187*d415bd75Srobert 188*d415bd75Srobert const SmallVector<SharedInstrument> 189*d415bd75Srobert getActiveInstruments(llvm::SMLoc Loc) const; 19009467b48Spatrick }; 19109467b48Spatrick 19209467b48Spatrick } // namespace mca 19309467b48Spatrick } // namespace llvm 19409467b48Spatrick 19509467b48Spatrick #endif 196