xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-------------------------- CodeRegion.h -------------------*- C++ -* -===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file implements class CodeRegion and CodeRegions, InstrumentRegion,
11 /// AnalysisRegions, and InstrumentRegions.
12 ///
13 /// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA
14 /// comment directives.
15 ///
16 ///   # LLVM-MCA-BEGIN foo
17 ///     ...  ## asm
18 ///   # LLVM-MCA-END
19 ///
20 /// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a
21 /// new region of code.
22 /// A comment starting with substring LLVM-MCA-END marks the end of the
23 /// last-seen region of code.
24 ///
25 /// Code regions are not allowed to overlap. Each region can have a optional
26 /// description; internally, regions are described by a range of source
27 /// locations (SMLoc objects).
28 ///
29 /// An instruction (a MCInst) is added to a CodeRegion R only if its
30 /// location is in range [R.RangeStart, R.RangeEnd].
31 ///
32 /// A InstrumentRegion describes a region of assembly code guarded by
33 /// special LLVM-MCA comment directives.
34 ///
35 ///   # LLVM-MCA-<INSTRUMENTATION_TYPE> <data>
36 ///     ...  ## asm
37 ///
38 /// where INSTRUMENTATION_TYPE is a type defined in llvm and expects to use
39 /// data.
40 ///
41 /// A comment starting with substring LLVM-MCA-<INSTRUMENTATION_TYPE>
42 /// brings data into scope for llvm-mca to use in its analysis for
43 /// all following instructions.
44 ///
45 /// If the same INSTRUMENTATION_TYPE is found later in the instruction list,
46 /// then the original InstrumentRegion will be automatically ended,
47 /// and a new InstrumentRegion will begin.
48 ///
49 /// If there are comments containing the different INSTRUMENTATION_TYPEs,
50 /// then both data sets remain available. In contrast with a CodeRegion,
51 /// an InstrumentRegion does not need a comment to end the region.
52 //
53 // An instruction (a MCInst) is added to an InstrumentRegion R only
54 // if its location is in range [R.RangeStart, R.RangeEnd].
55 //
56 //===----------------------------------------------------------------------===//
57 
58 #ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H
59 #define LLVM_TOOLS_LLVM_MCA_CODEREGION_H
60 
61 #include "llvm/ADT/ArrayRef.h"
62 #include "llvm/ADT/SmallPtrSet.h"
63 #include "llvm/ADT/SmallVector.h"
64 #include "llvm/ADT/StringMap.h"
65 #include "llvm/ADT/StringRef.h"
66 #include "llvm/MC/MCInst.h"
67 #include "llvm/MCA/CustomBehaviour.h"
68 #include "llvm/Support/Error.h"
69 #include "llvm/Support/SMLoc.h"
70 #include "llvm/Support/SourceMgr.h"
71 #include <vector>
72 
73 namespace llvm {
74 namespace mca {
75 
76 /// A region of assembly code.
77 ///
78 /// It identifies a sequence of machine instructions.
79 class CodeRegion {
80   // An optional descriptor for this region.
81   llvm::StringRef Description;
82   // Instructions that form this region.
83   llvm::SmallVector<llvm::MCInst, 16> Instructions;
84   // Source location range.
85   llvm::SMLoc RangeStart;
86   llvm::SMLoc RangeEnd;
87 
88   CodeRegion(const CodeRegion &) = delete;
89   CodeRegion &operator=(const CodeRegion &) = delete;
90 
91 public:
CodeRegion(llvm::StringRef Desc,llvm::SMLoc Start)92   CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start)
93       : Description(Desc), RangeStart(Start) {}
94 
95   virtual ~CodeRegion() = default;
96 
addInstruction(const llvm::MCInst & Instruction)97   void addInstruction(const llvm::MCInst &Instruction) {
98     Instructions.emplace_back(Instruction);
99   }
100 
101   // Remove the given instructions from the set, for unsupported instructions
102   // being skipped. Returns an ArrayRef for the updated vector of Instructions.
103   [[nodiscard]] llvm::ArrayRef<llvm::MCInst>
dropInstructions(const llvm::SmallPtrSetImpl<const llvm::MCInst * > & Insts)104   dropInstructions(const llvm::SmallPtrSetImpl<const llvm::MCInst *> &Insts) {
105     if (Insts.empty())
106       return Instructions;
107     llvm::erase_if(Instructions, [&Insts](const llvm::MCInst &Inst) {
108       return Insts.contains(&Inst);
109     });
110     return Instructions;
111   }
112 
startLoc()113   llvm::SMLoc startLoc() const { return RangeStart; }
endLoc()114   llvm::SMLoc endLoc() const { return RangeEnd; }
115 
setEndLocation(llvm::SMLoc End)116   void setEndLocation(llvm::SMLoc End) { RangeEnd = End; }
empty()117   bool empty() const { return Instructions.empty(); }
118   bool isLocInRange(llvm::SMLoc Loc) const;
119 
getInstructions()120   llvm::ArrayRef<llvm::MCInst> getInstructions() const { return Instructions; }
121 
getDescription()122   llvm::StringRef getDescription() const { return Description; }
123 };
124 
125 /// Alias AnalysisRegion with CodeRegion since CodeRegionGenerator
126 /// is absract and AnalysisRegionGenerator operates on AnalysisRegions
127 using AnalysisRegion = CodeRegion;
128 
129 /// A CodeRegion that contains instrumentation that can be used
130 /// in analysis of the region.
131 class InstrumentRegion : public CodeRegion {
132   /// Instrument for this region.
133   UniqueInstrument I;
134 
135 public:
InstrumentRegion(llvm::StringRef Desc,llvm::SMLoc Start,UniqueInstrument I)136   InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, UniqueInstrument I)
137       : CodeRegion(Desc, Start), I(std::move(I)) {}
138 
139 public:
getInstrument()140   Instrument *getInstrument() const { return I.get(); }
141 };
142 
143 class CodeRegionParseError final : public Error {};
144 
145 class CodeRegions {
146   CodeRegions(const CodeRegions &) = delete;
147   CodeRegions &operator=(const CodeRegions &) = delete;
148 
149 protected:
150   // A source manager. Used by the tool to generate meaningful warnings.
151   llvm::SourceMgr &SM;
152 
153   using UniqueCodeRegion = std::unique_ptr<CodeRegion>;
154   std::vector<UniqueCodeRegion> Regions;
155   llvm::StringMap<unsigned> ActiveRegions;
156   bool FoundErrors;
157 
158 public:
CodeRegions(llvm::SourceMgr & S)159   CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {}
160   virtual ~CodeRegions() = default;
161 
162   typedef std::vector<UniqueCodeRegion>::iterator iterator;
163   typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator;
164 
begin()165   iterator begin() { return Regions.begin(); }
end()166   iterator end() { return Regions.end(); }
begin()167   const_iterator begin() const { return Regions.cbegin(); }
end()168   const_iterator end() const { return Regions.cend(); }
169 
170   void addInstruction(const llvm::MCInst &Instruction);
getSourceMgr()171   llvm::SourceMgr &getSourceMgr() const { return SM; }
172 
getInstructionSequence(unsigned Idx)173   llvm::ArrayRef<llvm::MCInst> getInstructionSequence(unsigned Idx) const {
174     return Regions[Idx]->getInstructions();
175   }
176 
empty()177   bool empty() const {
178     return llvm::all_of(Regions, [](const UniqueCodeRegion &Region) {
179       return Region->empty();
180     });
181   }
182 
isValid()183   bool isValid() const { return !FoundErrors; }
184 
isRegionActive(llvm::StringRef Description)185   bool isRegionActive(llvm::StringRef Description) const {
186     return ActiveRegions.contains(Description);
187   }
188 
189   virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
190   virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
191                            UniqueInstrument Instrument) = 0;
192   virtual void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
193 };
194 
195 struct AnalysisRegions : public CodeRegions {
196   AnalysisRegions(llvm::SourceMgr &S);
197 
198   void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
beginRegionAnalysisRegions199   void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
200                    UniqueInstrument Instrument) override {}
201   void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
202 };
203 
204 struct InstrumentRegions : public CodeRegions {
205 
206   InstrumentRegions(llvm::SourceMgr &S);
207 
beginRegionInstrumentRegions208   void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override{};
209   void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
210                    UniqueInstrument Instrument) override;
211   void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
212 
213   const SmallVector<Instrument *> getActiveInstruments(llvm::SMLoc Loc) const;
214 };
215 
216 } // namespace mca
217 } // namespace llvm
218 
219 #endif
220