xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1349cc55cSDimitry Andric //===-- TraceHTR.h --------------------------------------------------------===//
2349cc55cSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #ifndef LLDB_TARGET_TRACE_HTR_H
10349cc55cSDimitry Andric #define LLDB_TARGET_TRACE_HTR_H
11349cc55cSDimitry Andric 
12349cc55cSDimitry Andric #include "lldb/Target/Thread.h"
13349cc55cSDimitry Andric #include "lldb/Target/Trace.h"
14349cc55cSDimitry Andric 
15bdd1243dSDimitry Andric #include <optional>
16349cc55cSDimitry Andric #include <unordered_map>
17349cc55cSDimitry Andric #include <unordered_set>
18349cc55cSDimitry Andric 
19349cc55cSDimitry Andric namespace lldb_private {
20349cc55cSDimitry Andric 
21349cc55cSDimitry Andric /// Metadata associated with an HTR block
22349cc55cSDimitry Andric /// See lldb/docs/htr.rst for comprehensive HTR documentation
23349cc55cSDimitry Andric class HTRBlockMetadata {
24349cc55cSDimitry Andric public:
25349cc55cSDimitry Andric   /// Constructor for a block's metadata.
26349cc55cSDimitry Andric   ///
27349cc55cSDimitry Andric   /// \param[in] first_instruction_load_address
28349cc55cSDimitry Andric   ///     The load address of the block's first instruction.
29349cc55cSDimitry Andric   ///
30349cc55cSDimitry Andric   /// \param[in] num_instructions
31349cc55cSDimitry Andric   ///     The total number of instructions in the block.
32349cc55cSDimitry Andric   ///
33349cc55cSDimitry Andric   /// \param[in] func_calls
34349cc55cSDimitry Andric   ///     The map of a function name to the number of times it is called from
35349cc55cSDimitry Andric   ///     the block.
HTRBlockMetadata(lldb::addr_t first_instruction_load_address,size_t num_instructions,llvm::DenseMap<ConstString,size_t> && func_calls)36349cc55cSDimitry Andric   HTRBlockMetadata(lldb::addr_t first_instruction_load_address,
37349cc55cSDimitry Andric                    size_t num_instructions,
38349cc55cSDimitry Andric                    llvm::DenseMap<ConstString, size_t> &&func_calls)
39349cc55cSDimitry Andric       : m_first_instruction_load_address(first_instruction_load_address),
40349cc55cSDimitry Andric         m_num_instructions(num_instructions), m_func_calls(func_calls) {}
41349cc55cSDimitry Andric 
42349cc55cSDimitry Andric   /// Merge two \a HTRBlockMetadata in place.
43349cc55cSDimitry Andric   ///
44349cc55cSDimitry Andric   /// \param[in][out] merged_metadata
45349cc55cSDimitry Andric   ///     Metadata that metadata_to_merge will be merged into.
46349cc55cSDimitry Andric   ///
47349cc55cSDimitry Andric   /// \param[in] metadata_to_merge
48349cc55cSDimitry Andric   ///     Metadata to merge into merged_metadata.
49349cc55cSDimitry Andric   static void MergeMetadata(HTRBlockMetadata &merged_metadata,
50349cc55cSDimitry Andric                             HTRBlockMetadata const &metadata_to_merge);
51349cc55cSDimitry Andric   /// Get the number of instructions in the block.
52349cc55cSDimitry Andric   ///
53349cc55cSDimitry Andric   /// \return
54349cc55cSDimitry Andric   ///     The number of instructions in the block.
55349cc55cSDimitry Andric   size_t GetNumInstructions() const;
56349cc55cSDimitry Andric 
57349cc55cSDimitry Andric   /// Get the name of the most frequently called function from the block.
58349cc55cSDimitry Andric   ///
59349cc55cSDimitry Andric   /// \return
60349cc55cSDimitry Andric   ///     The name of the function that is called the most from this block or
61bdd1243dSDimitry Andric   ///     std::nullopt if no function is called from this block.
62bdd1243dSDimitry Andric   std::optional<llvm::StringRef> GetMostFrequentlyCalledFunction() const;
63349cc55cSDimitry Andric 
64349cc55cSDimitry Andric   /// Get the load address of the first instruction in the block.
65349cc55cSDimitry Andric   ///
66349cc55cSDimitry Andric   /// \return
67349cc55cSDimitry Andric   ///     The load address of the first instruction in the block.
68349cc55cSDimitry Andric   lldb::addr_t GetFirstInstructionLoadAddress() const;
69349cc55cSDimitry Andric 
70349cc55cSDimitry Andric   /// Get the function calls map for the block.
71349cc55cSDimitry Andric   /// Function calls are identified in the instruction layer by finding 'call'
72349cc55cSDimitry Andric   /// instructions and determining the function they are calling. As these
73349cc55cSDimitry Andric   /// instructions are merged into blocks, we merge these different function
74349cc55cSDimitry Andric   /// calls into a single map containing the function names to the number of
75349cc55cSDimitry Andric   /// times it is called from this block.
76349cc55cSDimitry Andric   ///
77349cc55cSDimitry Andric   /// \return
78349cc55cSDimitry Andric   ///     The mapping of function name to the number of times it is called from
79349cc55cSDimitry Andric   ///     this block.
80349cc55cSDimitry Andric   llvm::DenseMap<ConstString, size_t> const &GetFunctionCalls() const;
81349cc55cSDimitry Andric 
82349cc55cSDimitry Andric private:
83349cc55cSDimitry Andric   lldb::addr_t m_first_instruction_load_address;
84349cc55cSDimitry Andric   size_t m_num_instructions;
85349cc55cSDimitry Andric   llvm::DenseMap<ConstString, size_t> m_func_calls;
86349cc55cSDimitry Andric };
87349cc55cSDimitry Andric 
88349cc55cSDimitry Andric /// Block structure representing a sequence of trace "units" (ie instructions).
89349cc55cSDimitry Andric /// Sequences of blocks are merged to create a new, single block
90349cc55cSDimitry Andric /// See lldb/docs/htr.rst for comprehensive HTR documentation
91349cc55cSDimitry Andric class HTRBlock {
92349cc55cSDimitry Andric public:
93349cc55cSDimitry Andric   /// Constructor for a block of an HTR layer.
94349cc55cSDimitry Andric   ///
95349cc55cSDimitry Andric   /// \param[in] offset
96349cc55cSDimitry Andric   ///     The offset of the start of this block in the previous layer.
97349cc55cSDimitry Andric   ///
98349cc55cSDimitry Andric   /// \param[in] size
99349cc55cSDimitry Andric   ///     Number of blocks/instructions that make up this block in the previous
100349cc55cSDimitry Andric   ///     layer.
101349cc55cSDimitry Andric   ///
102349cc55cSDimitry Andric   /// \param[in] metadata
103349cc55cSDimitry Andric   ///     General metadata for this block.
HTRBlock(size_t offset,size_t size,HTRBlockMetadata metadata)104349cc55cSDimitry Andric   HTRBlock(size_t offset, size_t size, HTRBlockMetadata metadata)
105349cc55cSDimitry Andric       : m_offset(offset), m_size(size), m_metadata(metadata) {}
106349cc55cSDimitry Andric 
107349cc55cSDimitry Andric   /// Get the offset of the start of this block in the previous layer.
108349cc55cSDimitry Andric   ///
109349cc55cSDimitry Andric   /// \return
110349cc55cSDimitry Andric   ///     The offset of the block.
111349cc55cSDimitry Andric   size_t GetOffset() const;
112349cc55cSDimitry Andric 
113349cc55cSDimitry Andric   /// Get the number of blocks/instructions that make up this block in the
114349cc55cSDimitry Andric   /// previous layer.
115349cc55cSDimitry Andric   ///
116349cc55cSDimitry Andric   /// \return
117349cc55cSDimitry Andric   ///     The size of the block.
118349cc55cSDimitry Andric   size_t GetSize() const;
119349cc55cSDimitry Andric 
120349cc55cSDimitry Andric   /// Get the metadata for this block.
121349cc55cSDimitry Andric   ///
122349cc55cSDimitry Andric   /// \return
123349cc55cSDimitry Andric   ///     The metadata of the block.
124349cc55cSDimitry Andric   HTRBlockMetadata const &GetMetadata() const;
125349cc55cSDimitry Andric 
126349cc55cSDimitry Andric private:
127349cc55cSDimitry Andric   /// Offset in the previous layer
128349cc55cSDimitry Andric   size_t m_offset;
129349cc55cSDimitry Andric   /// Number of blocks/instructions that make up this block in the previous
130349cc55cSDimitry Andric   /// layer
131349cc55cSDimitry Andric   size_t m_size;
132349cc55cSDimitry Andric   /// General metadata for this block
133349cc55cSDimitry Andric   HTRBlockMetadata m_metadata;
134349cc55cSDimitry Andric };
135349cc55cSDimitry Andric 
136349cc55cSDimitry Andric /// HTR layer interface
137349cc55cSDimitry Andric /// See lldb/docs/htr.rst for comprehensive HTR documentation
138349cc55cSDimitry Andric class IHTRLayer {
139349cc55cSDimitry Andric public:
140349cc55cSDimitry Andric   /// Construct new HTR layer.
141349cc55cSDimitry Andric   //
142349cc55cSDimitry Andric   /// \param[in] id
143349cc55cSDimitry Andric   ///     The layer's id.
IHTRLayer(size_t id)144349cc55cSDimitry Andric   IHTRLayer(size_t id) : m_layer_id(id) {}
145349cc55cSDimitry Andric 
146349cc55cSDimitry Andric   /// Get the ID of the layer.
147349cc55cSDimitry Andric   ///
148349cc55cSDimitry Andric   /// \return
149349cc55cSDimitry Andric   ///     The layer ID of this layer.
150349cc55cSDimitry Andric   size_t GetLayerId() const;
151349cc55cSDimitry Andric 
152349cc55cSDimitry Andric   /// Get the metadata of a unit (instruction or block) in the layer.
153349cc55cSDimitry Andric   ///
154349cc55cSDimitry Andric   /// \param[in] index
155349cc55cSDimitry Andric   ///     The position of the unit in the layer.
156349cc55cSDimitry Andric   ///
157349cc55cSDimitry Andric   /// \return
158349cc55cSDimitry Andric   ///     The metadata of the unit in the layer.
159349cc55cSDimitry Andric   virtual HTRBlockMetadata GetMetadataByIndex(size_t index) const = 0;
160349cc55cSDimitry Andric 
161349cc55cSDimitry Andric   /// Get the total number of units (instruction or block) in this layer.
162349cc55cSDimitry Andric   ///
163349cc55cSDimitry Andric   /// \return
164349cc55cSDimitry Andric   ///     The total number of units in the layer.
165349cc55cSDimitry Andric   virtual size_t GetNumUnits() const = 0;
166349cc55cSDimitry Andric 
167349cc55cSDimitry Andric   /// Creates a new block from the result of merging a contiguous sequence of
168349cc55cSDimitry Andric   /// "units" (instructions or blocks depending on layer type) in this layer
169349cc55cSDimitry Andric   /// This allows the implementation class to decide how to store/generate this
170349cc55cSDimitry Andric   /// metadata. For example, in the case of the instruction layer we want to
171349cc55cSDimitry Andric   /// lazily generate this metadata instead of storing it for each instruction.
172349cc55cSDimitry Andric   ///
173349cc55cSDimitry Andric   /// \param[in] start_unit_index
174349cc55cSDimitry Andric   ///     The index of the first unit to be merged.
175349cc55cSDimitry Andric   ///
176349cc55cSDimitry Andric   /// \param[in] num_units
177349cc55cSDimitry Andric   ///     The number of units to be merged. Must be >= 1, since merging 0 blocks
178349cc55cSDimitry Andric   ///     does not make sense.
179349cc55cSDimitry Andric   ///
180349cc55cSDimitry Andric   /// \return
181349cc55cSDimitry Andric   ///     A new block instance representing the merge of the specified units.
182349cc55cSDimitry Andric   HTRBlock MergeUnits(size_t start_unit_index, size_t num_units);
183349cc55cSDimitry Andric 
184349cc55cSDimitry Andric   virtual ~IHTRLayer() = default;
185349cc55cSDimitry Andric 
186349cc55cSDimitry Andric protected:
187349cc55cSDimitry Andric   /// ID of the layer.
188349cc55cSDimitry Andric   size_t m_layer_id;
189349cc55cSDimitry Andric };
190349cc55cSDimitry Andric 
191349cc55cSDimitry Andric /// "Base" layer of HTR representing the dynamic instructions of the trace.
192349cc55cSDimitry Andric /// See lldb/docs/htr.rst for comprehensive HTR documentation
193349cc55cSDimitry Andric class HTRInstructionLayer : public IHTRLayer {
194349cc55cSDimitry Andric public:
195349cc55cSDimitry Andric   /// Construct new instruction layer.
196349cc55cSDimitry Andric   //
197349cc55cSDimitry Andric   /// \param[in] id
198349cc55cSDimitry Andric   ///     The layer's id.
HTRInstructionLayer(size_t id)199349cc55cSDimitry Andric   HTRInstructionLayer(size_t id) : IHTRLayer(id) {}
200349cc55cSDimitry Andric 
201349cc55cSDimitry Andric   size_t GetNumUnits() const override;
202349cc55cSDimitry Andric 
203349cc55cSDimitry Andric   HTRBlockMetadata GetMetadataByIndex(size_t index) const override;
204349cc55cSDimitry Andric 
205349cc55cSDimitry Andric   /// Get the dynamic instruction trace.
206349cc55cSDimitry Andric   ///
207349cc55cSDimitry Andric   /// \return
208349cc55cSDimitry Andric   ///     The dynamic instruction trace.
209349cc55cSDimitry Andric   llvm::ArrayRef<lldb::addr_t> GetInstructionTrace() const;
210349cc55cSDimitry Andric 
211349cc55cSDimitry Andric   /// Add metadata for a 'call' instruction of the trace.
212349cc55cSDimitry Andric   ///
213349cc55cSDimitry Andric   /// \param[in] load_addr
214349cc55cSDimitry Andric   ///     The load address of the 'call' instruction.
215349cc55cSDimitry Andric   ///
216349cc55cSDimitry Andric   /// \param[in] func_name
217349cc55cSDimitry Andric   ///     The name of the function the 'call' instruction is calling if it can
218*06c3fb27SDimitry Andric   ///     be determined, std::nullopt otherwise.
219349cc55cSDimitry Andric   void AddCallInstructionMetadata(lldb::addr_t load_addr,
220bdd1243dSDimitry Andric                                   std::optional<ConstString> func_name);
221349cc55cSDimitry Andric 
222349cc55cSDimitry Andric   /// Append the load address of an instruction to the dynamic instruction
223349cc55cSDimitry Andric   /// trace.
224349cc55cSDimitry Andric   ///
225349cc55cSDimitry Andric   /// \param[in] load_addr
226349cc55cSDimitry Andric   ///     The load address of the instruction.
227349cc55cSDimitry Andric   void AppendInstruction(lldb::addr_t load_addr);
228349cc55cSDimitry Andric 
229349cc55cSDimitry Andric private:
230349cc55cSDimitry Andric   // Dynamic instructions of trace are stored in chronological order.
231349cc55cSDimitry Andric   std::vector<lldb::addr_t> m_instruction_trace;
232349cc55cSDimitry Andric   // Only store metadata for instructions of interest (call instructions)
233349cc55cSDimitry Andric   // If we stored metadata for each instruction this would be wasteful since
234349cc55cSDimitry Andric   // most instructions don't contain useful metadata
235349cc55cSDimitry Andric 
236349cc55cSDimitry Andric   // This map contains the load address of all the call instructions.
237bdd1243dSDimitry Andric   // load address maps to the name of the function it calls (std::nullopt if
238bdd1243dSDimitry Andric   // function name can't be determined)
239bdd1243dSDimitry Andric   std::unordered_map<lldb::addr_t, std::optional<ConstString>> m_call_isns;
240349cc55cSDimitry Andric };
241349cc55cSDimitry Andric 
242349cc55cSDimitry Andric /// HTR layer composed of blocks of the trace.
243349cc55cSDimitry Andric /// See lldb/docs/htr.rst for comprehensive HTR documentation
244349cc55cSDimitry Andric class HTRBlockLayer : public IHTRLayer {
245349cc55cSDimitry Andric public:
246349cc55cSDimitry Andric   /// Construct new block layer.
247349cc55cSDimitry Andric   //
248349cc55cSDimitry Andric   /// \param[in] id
249349cc55cSDimitry Andric   ///     The layer's id.
HTRBlockLayer(size_t id)250349cc55cSDimitry Andric   HTRBlockLayer(size_t id) : IHTRLayer(id) {}
251349cc55cSDimitry Andric 
252349cc55cSDimitry Andric   size_t GetNumUnits() const override;
253349cc55cSDimitry Andric 
254349cc55cSDimitry Andric   HTRBlockMetadata GetMetadataByIndex(size_t index) const override;
255349cc55cSDimitry Andric 
256349cc55cSDimitry Andric   /// Get an \a HTRBlock from its block id.
257349cc55cSDimitry Andric   ///
258349cc55cSDimitry Andric   /// \param[in] block_id
259349cc55cSDimitry Andric   ///     The id of the block to retrieve.
260349cc55cSDimitry Andric   ///
261349cc55cSDimitry Andric   /// \return
262349cc55cSDimitry Andric   ///     The \a HTRBlock with the specified id, nullptr if no there is no block
263349cc55cSDimitry Andric   ///     in the layer with the specified block id.
264349cc55cSDimitry Andric   HTRBlock const *GetBlockById(size_t block_id) const;
265349cc55cSDimitry Andric 
266349cc55cSDimitry Andric   /// Get the block ID trace for this layer.
267349cc55cSDimitry Andric   /// This block ID trace stores the block ID of each block that occured in the
268349cc55cSDimitry Andric   /// trace and the block defs map maps block ID to the corresponding \a
269349cc55cSDimitry Andric   /// HTRBlock.
270349cc55cSDimitry Andric   ///
271349cc55cSDimitry Andric   /// \return
272349cc55cSDimitry Andric   ///     The block ID trace for this layer.
273349cc55cSDimitry Andric   llvm::ArrayRef<size_t> GetBlockIdTrace() const;
274349cc55cSDimitry Andric 
275349cc55cSDimitry Andric   /// Appends a new block to the layer.
276349cc55cSDimitry Andric   ///
277349cc55cSDimitry Andric   /// \param[in] block_id
278349cc55cSDimitry Andric   ///     The block id of the new block.
279349cc55cSDimitry Andric   ///
280349cc55cSDimitry Andric   /// \param[in] block
281349cc55cSDimitry Andric   ///     The new \a HTRBlock to be appended to the layer. This block is moved
282349cc55cSDimitry Andric   ///     into the layer.
283349cc55cSDimitry Andric   void AppendNewBlock(size_t block_id, HTRBlock &&block);
284349cc55cSDimitry Andric 
285349cc55cSDimitry Andric   /// Appends a repeated block to the layer.
286349cc55cSDimitry Andric   ///
287349cc55cSDimitry Andric   /// \param[in] block_id
288349cc55cSDimitry Andric   ///     The block id of the repeated block.
289349cc55cSDimitry Andric   void AppendRepeatedBlock(size_t block_id);
290349cc55cSDimitry Andric 
291349cc55cSDimitry Andric private:
292349cc55cSDimitry Andric   /// Maps a unique Block ID to the corresponding HTRBlock
293349cc55cSDimitry Andric   std::unordered_map<size_t, HTRBlock> m_block_defs;
294349cc55cSDimitry Andric   /// Reduce memory footprint by just storing a trace of block IDs and use
295349cc55cSDimitry Andric   /// m_block_defs to map a block_id to its corresponding HTRBlock
296349cc55cSDimitry Andric   std::vector<size_t> m_block_id_trace;
297349cc55cSDimitry Andric };
298349cc55cSDimitry Andric 
299349cc55cSDimitry Andric typedef std::unique_ptr<lldb_private::HTRBlockLayer> HTRBlockLayerUP;
300349cc55cSDimitry Andric typedef std::unique_ptr<lldb_private::HTRInstructionLayer>
301349cc55cSDimitry Andric     HTRInstructionLayerUP;
302349cc55cSDimitry Andric 
303349cc55cSDimitry Andric /// Top-level HTR class
304349cc55cSDimitry Andric /// See lldb/docs/htr.rst for comprehensive HTR documentation
305349cc55cSDimitry Andric class TraceHTR {
306349cc55cSDimitry Andric 
307349cc55cSDimitry Andric public:
308349cc55cSDimitry Andric   /// Constructor for a trace's HTR.
309349cc55cSDimitry Andric   ///
310349cc55cSDimitry Andric   /// \param[in] thread
311349cc55cSDimitry Andric   ///     The thread the trace belongs to.
312349cc55cSDimitry Andric   ///
313349cc55cSDimitry Andric   /// \param[in] cursor
314349cc55cSDimitry Andric   ///     The trace cursor that gives access to the trace's contents.
315349cc55cSDimitry Andric   TraceHTR(Thread &thread, TraceCursor &cursor);
316349cc55cSDimitry Andric 
317349cc55cSDimitry Andric   /// Executes passes on the HTR layers until no further
318349cc55cSDimitry Andric   /// summarization/compression is achieved
319349cc55cSDimitry Andric   void ExecutePasses();
320349cc55cSDimitry Andric 
321349cc55cSDimitry Andric   /// Export HTR layers to the specified format and outfile.
322349cc55cSDimitry Andric   ///
323349cc55cSDimitry Andric   /// \param[in] outfile
324349cc55cSDimitry Andric   ///     The file that the exported HTR data will be written to.
325349cc55cSDimitry Andric   ///
326349cc55cSDimitry Andric   /// \return
327349cc55cSDimitry Andric   ///     Success if the export is successful, Error otherwise.
328349cc55cSDimitry Andric   llvm::Error Export(std::string outfile);
329349cc55cSDimitry Andric 
330349cc55cSDimitry Andric   /// Get the block layers of this HTR.
331349cc55cSDimitry Andric   ///
332349cc55cSDimitry Andric   /// \return
333349cc55cSDimitry Andric   ///     The block layers of this HTR.
334349cc55cSDimitry Andric   llvm::ArrayRef<HTRBlockLayerUP> GetBlockLayers() const;
335349cc55cSDimitry Andric 
336349cc55cSDimitry Andric   /// Get the instruction layer of this HTR.
337349cc55cSDimitry Andric   ///
338349cc55cSDimitry Andric   /// \return
339349cc55cSDimitry Andric   ///     The instruction layer of this HTR.
340349cc55cSDimitry Andric   HTRInstructionLayer const &GetInstructionLayer() const;
341349cc55cSDimitry Andric 
342349cc55cSDimitry Andric   /// Add a new block layer to this HTR.
343349cc55cSDimitry Andric   ///
344349cc55cSDimitry Andric   /// \param[in]
345349cc55cSDimitry Andric   ///     The new block layer to be added.
346349cc55cSDimitry Andric   void AddNewBlockLayer(HTRBlockLayerUP &&block_layer);
347349cc55cSDimitry Andric 
348349cc55cSDimitry Andric private:
349349cc55cSDimitry Andric   // There is a single instruction layer per HTR
350349cc55cSDimitry Andric   HTRInstructionLayerUP m_instruction_layer_up;
351349cc55cSDimitry Andric   // There are one or more block layers per HTR
352349cc55cSDimitry Andric   std::vector<HTRBlockLayerUP> m_block_layer_ups;
353349cc55cSDimitry Andric };
354349cc55cSDimitry Andric 
355349cc55cSDimitry Andric // Serialization functions for exporting HTR to Chrome Trace Format
356349cc55cSDimitry Andric llvm::json::Value toJSON(const TraceHTR &htr);
357349cc55cSDimitry Andric llvm::json::Value toJSON(const HTRBlock &block);
358349cc55cSDimitry Andric llvm::json::Value toJSON(const HTRBlockMetadata &metadata);
359349cc55cSDimitry Andric 
360349cc55cSDimitry Andric /// The HTR passes are defined below:
361349cc55cSDimitry Andric 
362349cc55cSDimitry Andric /// Creates a new layer by merging the "basic super blocks" in the current layer
363349cc55cSDimitry Andric ///
364349cc55cSDimitry Andric /// A "basic super block" is the longest sequence of blocks that always occur in
365349cc55cSDimitry Andric /// the same order. (The concept is akin to “Basic Block" in compiler theory,
366349cc55cSDimitry Andric /// but refers to dynamic occurrences rather than CFG nodes)
367349cc55cSDimitry Andric ///
368349cc55cSDimitry Andric /// Procedure to find all basic super blocks:
369349cc55cSDimitry Andric //
370349cc55cSDimitry Andric ///   - For each block, compute the number of distinct predecessor and
371349cc55cSDimitry Andric ///   successor blocks.
372349cc55cSDimitry Andric ///       Predecessor - the block that occurs directly before (to the left of)
373349cc55cSDimitry Andric ///       the current block Successor  - the block that occurs directly after
374349cc55cSDimitry Andric ///       (to the right of) the current block
375349cc55cSDimitry Andric ///   - A block with more than one distinct successor is always the start of a
376349cc55cSDimitry Andric ///   super block, the super block will continue until the next block with
377349cc55cSDimitry Andric ///   more than one distinct predecessor or successor.
378349cc55cSDimitry Andric ///
379349cc55cSDimitry Andric /// The implementation makes use of two terms - 'heads' and 'tails' known as
380349cc55cSDimitry Andric /// the 'endpoints' of a basic super block:
381349cc55cSDimitry Andric ///   A 'head' is defined to be a block in the trace that doesn't have a
382349cc55cSDimitry Andric ///   unique predecessor
383349cc55cSDimitry Andric ///   A 'tail' is defined to be a block in the trace that doesn't have a
384349cc55cSDimitry Andric ///   unique successor
385349cc55cSDimitry Andric ///
386349cc55cSDimitry Andric /// A basic super block is defined to be a sequence of blocks between two
387349cc55cSDimitry Andric /// endpoints
388349cc55cSDimitry Andric ///
389349cc55cSDimitry Andric /// A head represents the start of the next group, so the current group
390349cc55cSDimitry Andric /// ends at the block preceding the head and the next group begins with
391349cc55cSDimitry Andric /// this head block
392349cc55cSDimitry Andric ///
393349cc55cSDimitry Andric /// A tail represents the end of the current group, so the current group
394349cc55cSDimitry Andric /// ends with the tail block and the next group begins with the
395349cc55cSDimitry Andric /// following block.
396349cc55cSDimitry Andric ///
397349cc55cSDimitry Andric /// See lldb/docs/htr.rst for comprehensive HTR documentation
398349cc55cSDimitry Andric ///
399349cc55cSDimitry Andric /// \param[in] layer
400349cc55cSDimitry Andric ///     The layer to execute the pass on.
401349cc55cSDimitry Andric ///
402349cc55cSDimitry Andric /// \return
403349cc55cSDimitry Andric ///     A new layer instance representing the merge of blocks in the
404349cc55cSDimitry Andric ///     previous layer
405349cc55cSDimitry Andric HTRBlockLayerUP BasicSuperBlockMerge(IHTRLayer &layer);
406349cc55cSDimitry Andric 
407349cc55cSDimitry Andric } // namespace lldb_private
408349cc55cSDimitry Andric 
409349cc55cSDimitry Andric #endif // LLDB_TARGET_TRACE_HTR_H
410