10b57cec5SDimitry Andric //===-------------------------- CodeRegion.h -------------------*- C++ -* -===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// 10bdd1243dSDimitry Andric /// This file implements class CodeRegion and CodeRegions, InstrumentRegion, 11bdd1243dSDimitry Andric /// AnalysisRegions, and InstrumentRegions. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric /// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA 140b57cec5SDimitry Andric /// comment directives. 150b57cec5SDimitry Andric /// 160b57cec5SDimitry Andric /// # LLVM-MCA-BEGIN foo 170b57cec5SDimitry Andric /// ... ## asm 180b57cec5SDimitry Andric /// # LLVM-MCA-END 190b57cec5SDimitry Andric /// 200b57cec5SDimitry Andric /// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a 210b57cec5SDimitry Andric /// new region of code. 220b57cec5SDimitry Andric /// A comment starting with substring LLVM-MCA-END marks the end of the 230b57cec5SDimitry Andric /// last-seen region of code. 240b57cec5SDimitry Andric /// 250b57cec5SDimitry Andric /// Code regions are not allowed to overlap. Each region can have a optional 260b57cec5SDimitry Andric /// description; internally, regions are described by a range of source 270b57cec5SDimitry Andric /// locations (SMLoc objects). 280b57cec5SDimitry Andric /// 29bdd1243dSDimitry Andric /// An instruction (a MCInst) is added to a CodeRegion R only if its 30bdd1243dSDimitry Andric /// location is in range [R.RangeStart, R.RangeEnd]. 31bdd1243dSDimitry Andric /// 32bdd1243dSDimitry Andric /// A InstrumentRegion describes a region of assembly code guarded by 33bdd1243dSDimitry Andric /// special LLVM-MCA comment directives. 34bdd1243dSDimitry Andric /// 35bdd1243dSDimitry Andric /// # LLVM-MCA-<INSTRUMENTATION_TYPE> <data> 36bdd1243dSDimitry Andric /// ... ## asm 37bdd1243dSDimitry Andric /// 38bdd1243dSDimitry Andric /// where INSTRUMENTATION_TYPE is a type defined in llvm and expects to use 39bdd1243dSDimitry Andric /// data. 40bdd1243dSDimitry Andric /// 41bdd1243dSDimitry Andric /// A comment starting with substring LLVM-MCA-<INSTRUMENTATION_TYPE> 42bdd1243dSDimitry Andric /// brings data into scope for llvm-mca to use in its analysis for 43bdd1243dSDimitry Andric /// all following instructions. 44bdd1243dSDimitry Andric /// 45bdd1243dSDimitry Andric /// If the same INSTRUMENTATION_TYPE is found later in the instruction list, 46bdd1243dSDimitry Andric /// then the original InstrumentRegion will be automatically ended, 47bdd1243dSDimitry Andric /// and a new InstrumentRegion will begin. 48bdd1243dSDimitry Andric /// 49bdd1243dSDimitry Andric /// If there are comments containing the different INSTRUMENTATION_TYPEs, 50bdd1243dSDimitry Andric /// then both data sets remain available. In contrast with a CodeRegion, 51bdd1243dSDimitry Andric /// an InstrumentRegion does not need a comment to end the region. 52bdd1243dSDimitry Andric // 53bdd1243dSDimitry Andric // An instruction (a MCInst) is added to an InstrumentRegion R only 54bdd1243dSDimitry Andric // if its location is in range [R.RangeStart, R.RangeEnd]. 550b57cec5SDimitry Andric // 560b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric #ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H 590b57cec5SDimitry Andric #define LLVM_TOOLS_LLVM_MCA_CODEREGION_H 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 62*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 630b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 645ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h" 650b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 660b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 67bdd1243dSDimitry Andric #include "llvm/MCA/CustomBehaviour.h" 685ffd83dbSDimitry Andric #include "llvm/Support/Error.h" 690b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 700b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h" 710b57cec5SDimitry Andric #include <vector> 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric namespace llvm { 740b57cec5SDimitry Andric namespace mca { 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric /// A region of assembly code. 770b57cec5SDimitry Andric /// 780b57cec5SDimitry Andric /// It identifies a sequence of machine instructions. 790b57cec5SDimitry Andric class CodeRegion { 800b57cec5SDimitry Andric // An optional descriptor for this region. 810b57cec5SDimitry Andric llvm::StringRef Description; 820b57cec5SDimitry Andric // Instructions that form this region. 83fe6060f1SDimitry Andric llvm::SmallVector<llvm::MCInst, 16> Instructions; 840b57cec5SDimitry Andric // Source location range. 850b57cec5SDimitry Andric llvm::SMLoc RangeStart; 860b57cec5SDimitry Andric llvm::SMLoc RangeEnd; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric CodeRegion(const CodeRegion &) = delete; 890b57cec5SDimitry Andric CodeRegion &operator=(const CodeRegion &) = delete; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric public: CodeRegion(llvm::StringRef Desc,llvm::SMLoc Start)920b57cec5SDimitry Andric CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start) 9304eeddc0SDimitry Andric : Description(Desc), RangeStart(Start) {} 940b57cec5SDimitry Andric 9506c3fb27SDimitry Andric virtual ~CodeRegion() = default; 9606c3fb27SDimitry Andric addInstruction(const llvm::MCInst & Instruction)970b57cec5SDimitry Andric void addInstruction(const llvm::MCInst &Instruction) { 980b57cec5SDimitry Andric Instructions.emplace_back(Instruction); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 101*0fca6ea1SDimitry Andric // Remove the given instructions from the set, for unsupported instructions 102*0fca6ea1SDimitry Andric // being skipped. Returns an ArrayRef for the updated vector of Instructions. 103*0fca6ea1SDimitry Andric [[nodiscard]] llvm::ArrayRef<llvm::MCInst> dropInstructions(const llvm::SmallPtrSetImpl<const llvm::MCInst * > & Insts)104*0fca6ea1SDimitry Andric dropInstructions(const llvm::SmallPtrSetImpl<const llvm::MCInst *> &Insts) { 105*0fca6ea1SDimitry Andric if (Insts.empty()) 106*0fca6ea1SDimitry Andric return Instructions; 107*0fca6ea1SDimitry Andric llvm::erase_if(Instructions, [&Insts](const llvm::MCInst &Inst) { 108*0fca6ea1SDimitry Andric return Insts.contains(&Inst); 109*0fca6ea1SDimitry Andric }); 110*0fca6ea1SDimitry Andric return Instructions; 111*0fca6ea1SDimitry Andric } 112*0fca6ea1SDimitry Andric startLoc()1130b57cec5SDimitry Andric llvm::SMLoc startLoc() const { return RangeStart; } endLoc()1140b57cec5SDimitry Andric llvm::SMLoc endLoc() const { return RangeEnd; } 1150b57cec5SDimitry Andric setEndLocation(llvm::SMLoc End)1160b57cec5SDimitry Andric void setEndLocation(llvm::SMLoc End) { RangeEnd = End; } empty()1170b57cec5SDimitry Andric bool empty() const { return Instructions.empty(); } 1180b57cec5SDimitry Andric bool isLocInRange(llvm::SMLoc Loc) const; 1190b57cec5SDimitry Andric getInstructions()1200b57cec5SDimitry Andric llvm::ArrayRef<llvm::MCInst> getInstructions() const { return Instructions; } 1210b57cec5SDimitry Andric getDescription()1220b57cec5SDimitry Andric llvm::StringRef getDescription() const { return Description; } 1230b57cec5SDimitry Andric }; 1240b57cec5SDimitry Andric 125bdd1243dSDimitry Andric /// Alias AnalysisRegion with CodeRegion since CodeRegionGenerator 126bdd1243dSDimitry Andric /// is absract and AnalysisRegionGenerator operates on AnalysisRegions 127bdd1243dSDimitry Andric using AnalysisRegion = CodeRegion; 128bdd1243dSDimitry Andric 129bdd1243dSDimitry Andric /// A CodeRegion that contains instrumentation that can be used 130bdd1243dSDimitry Andric /// in analysis of the region. 131bdd1243dSDimitry Andric class InstrumentRegion : public CodeRegion { 132bdd1243dSDimitry Andric /// Instrument for this region. 13306c3fb27SDimitry Andric UniqueInstrument I; 134bdd1243dSDimitry Andric 135bdd1243dSDimitry Andric public: InstrumentRegion(llvm::StringRef Desc,llvm::SMLoc Start,UniqueInstrument I)13606c3fb27SDimitry Andric InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, UniqueInstrument I) 13706c3fb27SDimitry Andric : CodeRegion(Desc, Start), I(std::move(I)) {} 138bdd1243dSDimitry Andric 139bdd1243dSDimitry Andric public: getInstrument()14006c3fb27SDimitry Andric Instrument *getInstrument() const { return I.get(); } 141bdd1243dSDimitry Andric }; 142bdd1243dSDimitry Andric 1430b57cec5SDimitry Andric class CodeRegionParseError final : public Error {}; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric class CodeRegions { 146bdd1243dSDimitry Andric CodeRegions(const CodeRegions &) = delete; 147bdd1243dSDimitry Andric CodeRegions &operator=(const CodeRegions &) = delete; 148bdd1243dSDimitry Andric 149bdd1243dSDimitry Andric protected: 1500b57cec5SDimitry Andric // A source manager. Used by the tool to generate meaningful warnings. 1510b57cec5SDimitry Andric llvm::SourceMgr &SM; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric using UniqueCodeRegion = std::unique_ptr<CodeRegion>; 1540b57cec5SDimitry Andric std::vector<UniqueCodeRegion> Regions; 1550b57cec5SDimitry Andric llvm::StringMap<unsigned> ActiveRegions; 1560b57cec5SDimitry Andric bool FoundErrors; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric public: CodeRegions(llvm::SourceMgr & S)159bdd1243dSDimitry Andric CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {} 16006c3fb27SDimitry Andric virtual ~CodeRegions() = default; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric typedef std::vector<UniqueCodeRegion>::iterator iterator; 1630b57cec5SDimitry Andric typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator; 1640b57cec5SDimitry Andric begin()1650b57cec5SDimitry Andric iterator begin() { return Regions.begin(); } end()1660b57cec5SDimitry Andric iterator end() { return Regions.end(); } begin()1670b57cec5SDimitry Andric const_iterator begin() const { return Regions.cbegin(); } end()1680b57cec5SDimitry Andric const_iterator end() const { return Regions.cend(); } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric void addInstruction(const llvm::MCInst &Instruction); getSourceMgr()1710b57cec5SDimitry Andric llvm::SourceMgr &getSourceMgr() const { return SM; } 1720b57cec5SDimitry Andric getInstructionSequence(unsigned Idx)1730b57cec5SDimitry Andric llvm::ArrayRef<llvm::MCInst> getInstructionSequence(unsigned Idx) const { 1740b57cec5SDimitry Andric return Regions[Idx]->getInstructions(); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric empty()1770b57cec5SDimitry Andric bool empty() const { 1780b57cec5SDimitry Andric return llvm::all_of(Regions, [](const UniqueCodeRegion &Region) { 1790b57cec5SDimitry Andric return Region->empty(); 1800b57cec5SDimitry Andric }); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric isValid()1830b57cec5SDimitry Andric bool isValid() const { return !FoundErrors; } 184bdd1243dSDimitry Andric isRegionActive(llvm::StringRef Description)185bdd1243dSDimitry Andric bool isRegionActive(llvm::StringRef Description) const { 18606c3fb27SDimitry Andric return ActiveRegions.contains(Description); 187bdd1243dSDimitry Andric } 18806c3fb27SDimitry Andric 18906c3fb27SDimitry Andric virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0; 19006c3fb27SDimitry Andric virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc, 19106c3fb27SDimitry Andric UniqueInstrument Instrument) = 0; 19206c3fb27SDimitry Andric virtual void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0; 193bdd1243dSDimitry Andric }; 194bdd1243dSDimitry Andric 195bdd1243dSDimitry Andric struct AnalysisRegions : public CodeRegions { 196bdd1243dSDimitry Andric AnalysisRegions(llvm::SourceMgr &S); 197bdd1243dSDimitry Andric 19806c3fb27SDimitry Andric void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override; beginRegionAnalysisRegions19906c3fb27SDimitry Andric void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc, 20006c3fb27SDimitry Andric UniqueInstrument Instrument) override {} 20106c3fb27SDimitry Andric void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override; 202bdd1243dSDimitry Andric }; 203bdd1243dSDimitry Andric 204bdd1243dSDimitry Andric struct InstrumentRegions : public CodeRegions { 20506c3fb27SDimitry Andric 206bdd1243dSDimitry Andric InstrumentRegions(llvm::SourceMgr &S); 207bdd1243dSDimitry Andric beginRegionInstrumentRegions20806c3fb27SDimitry Andric void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override{}; 209bdd1243dSDimitry Andric void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc, 21006c3fb27SDimitry Andric UniqueInstrument Instrument) override; 21106c3fb27SDimitry Andric void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override; 212bdd1243dSDimitry Andric 21306c3fb27SDimitry Andric const SmallVector<Instrument *> getActiveInstruments(llvm::SMLoc Loc) const; 2140b57cec5SDimitry Andric }; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric } // namespace mca 2170b57cec5SDimitry Andric } // namespace llvm 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric #endif 220