xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/TraceExporter/common/TraceHTR.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1*f6aab3d8Srobert //===-- TraceHTR.h --------------------------------------------------------===//
2*f6aab3d8Srobert //
3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information.
5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*f6aab3d8Srobert //
7*f6aab3d8Srobert //===----------------------------------------------------------------------===//
8*f6aab3d8Srobert 
9*f6aab3d8Srobert #ifndef LLDB_TARGET_TRACE_HTR_H
10*f6aab3d8Srobert #define LLDB_TARGET_TRACE_HTR_H
11*f6aab3d8Srobert 
12*f6aab3d8Srobert #include "lldb/Target/Thread.h"
13*f6aab3d8Srobert #include "lldb/Target/Trace.h"
14*f6aab3d8Srobert 
15*f6aab3d8Srobert #include <optional>
16*f6aab3d8Srobert #include <unordered_map>
17*f6aab3d8Srobert #include <unordered_set>
18*f6aab3d8Srobert 
19*f6aab3d8Srobert namespace lldb_private {
20*f6aab3d8Srobert 
21*f6aab3d8Srobert /// Metadata associated with an HTR block
22*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation
23*f6aab3d8Srobert class HTRBlockMetadata {
24*f6aab3d8Srobert public:
25*f6aab3d8Srobert   /// Constructor for a block's metadata.
26*f6aab3d8Srobert   ///
27*f6aab3d8Srobert   /// \param[in] first_instruction_load_address
28*f6aab3d8Srobert   ///     The load address of the block's first instruction.
29*f6aab3d8Srobert   ///
30*f6aab3d8Srobert   /// \param[in] num_instructions
31*f6aab3d8Srobert   ///     The total number of instructions in the block.
32*f6aab3d8Srobert   ///
33*f6aab3d8Srobert   /// \param[in] func_calls
34*f6aab3d8Srobert   ///     The map of a function name to the number of times it is called from
35*f6aab3d8Srobert   ///     the block.
HTRBlockMetadata(lldb::addr_t first_instruction_load_address,size_t num_instructions,llvm::DenseMap<ConstString,size_t> && func_calls)36*f6aab3d8Srobert   HTRBlockMetadata(lldb::addr_t first_instruction_load_address,
37*f6aab3d8Srobert                    size_t num_instructions,
38*f6aab3d8Srobert                    llvm::DenseMap<ConstString, size_t> &&func_calls)
39*f6aab3d8Srobert       : m_first_instruction_load_address(first_instruction_load_address),
40*f6aab3d8Srobert         m_num_instructions(num_instructions), m_func_calls(func_calls) {}
41*f6aab3d8Srobert 
42*f6aab3d8Srobert   /// Merge two \a HTRBlockMetadata in place.
43*f6aab3d8Srobert   ///
44*f6aab3d8Srobert   /// \param[in][out] merged_metadata
45*f6aab3d8Srobert   ///     Metadata that metadata_to_merge will be merged into.
46*f6aab3d8Srobert   ///
47*f6aab3d8Srobert   /// \param[in] metadata_to_merge
48*f6aab3d8Srobert   ///     Metadata to merge into merged_metadata.
49*f6aab3d8Srobert   static void MergeMetadata(HTRBlockMetadata &merged_metadata,
50*f6aab3d8Srobert                             HTRBlockMetadata const &metadata_to_merge);
51*f6aab3d8Srobert   /// Get the number of instructions in the block.
52*f6aab3d8Srobert   ///
53*f6aab3d8Srobert   /// \return
54*f6aab3d8Srobert   ///     The number of instructions in the block.
55*f6aab3d8Srobert   size_t GetNumInstructions() const;
56*f6aab3d8Srobert 
57*f6aab3d8Srobert   /// Get the name of the most frequently called function from the block.
58*f6aab3d8Srobert   ///
59*f6aab3d8Srobert   /// \return
60*f6aab3d8Srobert   ///     The name of the function that is called the most from this block or
61*f6aab3d8Srobert   ///     std::nullopt if no function is called from this block.
62*f6aab3d8Srobert   std::optional<llvm::StringRef> GetMostFrequentlyCalledFunction() const;
63*f6aab3d8Srobert 
64*f6aab3d8Srobert   /// Get the load address of the first instruction in the block.
65*f6aab3d8Srobert   ///
66*f6aab3d8Srobert   /// \return
67*f6aab3d8Srobert   ///     The load address of the first instruction in the block.
68*f6aab3d8Srobert   lldb::addr_t GetFirstInstructionLoadAddress() const;
69*f6aab3d8Srobert 
70*f6aab3d8Srobert   /// Get the function calls map for the block.
71*f6aab3d8Srobert   /// Function calls are identified in the instruction layer by finding 'call'
72*f6aab3d8Srobert   /// instructions and determining the function they are calling. As these
73*f6aab3d8Srobert   /// instructions are merged into blocks, we merge these different function
74*f6aab3d8Srobert   /// calls into a single map containing the function names to the number of
75*f6aab3d8Srobert   /// times it is called from this block.
76*f6aab3d8Srobert   ///
77*f6aab3d8Srobert   /// \return
78*f6aab3d8Srobert   ///     The mapping of function name to the number of times it is called from
79*f6aab3d8Srobert   ///     this block.
80*f6aab3d8Srobert   llvm::DenseMap<ConstString, size_t> const &GetFunctionCalls() const;
81*f6aab3d8Srobert 
82*f6aab3d8Srobert private:
83*f6aab3d8Srobert   lldb::addr_t m_first_instruction_load_address;
84*f6aab3d8Srobert   size_t m_num_instructions;
85*f6aab3d8Srobert   llvm::DenseMap<ConstString, size_t> m_func_calls;
86*f6aab3d8Srobert };
87*f6aab3d8Srobert 
88*f6aab3d8Srobert /// Block structure representing a sequence of trace "units" (ie instructions).
89*f6aab3d8Srobert /// Sequences of blocks are merged to create a new, single block
90*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation
91*f6aab3d8Srobert class HTRBlock {
92*f6aab3d8Srobert public:
93*f6aab3d8Srobert   /// Constructor for a block of an HTR layer.
94*f6aab3d8Srobert   ///
95*f6aab3d8Srobert   /// \param[in] offset
96*f6aab3d8Srobert   ///     The offset of the start of this block in the previous layer.
97*f6aab3d8Srobert   ///
98*f6aab3d8Srobert   /// \param[in] size
99*f6aab3d8Srobert   ///     Number of blocks/instructions that make up this block in the previous
100*f6aab3d8Srobert   ///     layer.
101*f6aab3d8Srobert   ///
102*f6aab3d8Srobert   /// \param[in] metadata
103*f6aab3d8Srobert   ///     General metadata for this block.
HTRBlock(size_t offset,size_t size,HTRBlockMetadata metadata)104*f6aab3d8Srobert   HTRBlock(size_t offset, size_t size, HTRBlockMetadata metadata)
105*f6aab3d8Srobert       : m_offset(offset), m_size(size), m_metadata(metadata) {}
106*f6aab3d8Srobert 
107*f6aab3d8Srobert   /// Get the offset of the start of this block in the previous layer.
108*f6aab3d8Srobert   ///
109*f6aab3d8Srobert   /// \return
110*f6aab3d8Srobert   ///     The offset of the block.
111*f6aab3d8Srobert   size_t GetOffset() const;
112*f6aab3d8Srobert 
113*f6aab3d8Srobert   /// Get the number of blocks/instructions that make up this block in the
114*f6aab3d8Srobert   /// previous layer.
115*f6aab3d8Srobert   ///
116*f6aab3d8Srobert   /// \return
117*f6aab3d8Srobert   ///     The size of the block.
118*f6aab3d8Srobert   size_t GetSize() const;
119*f6aab3d8Srobert 
120*f6aab3d8Srobert   /// Get the metadata for this block.
121*f6aab3d8Srobert   ///
122*f6aab3d8Srobert   /// \return
123*f6aab3d8Srobert   ///     The metadata of the block.
124*f6aab3d8Srobert   HTRBlockMetadata const &GetMetadata() const;
125*f6aab3d8Srobert 
126*f6aab3d8Srobert private:
127*f6aab3d8Srobert   /// Offset in the previous layer
128*f6aab3d8Srobert   size_t m_offset;
129*f6aab3d8Srobert   /// Number of blocks/instructions that make up this block in the previous
130*f6aab3d8Srobert   /// layer
131*f6aab3d8Srobert   size_t m_size;
132*f6aab3d8Srobert   /// General metadata for this block
133*f6aab3d8Srobert   HTRBlockMetadata m_metadata;
134*f6aab3d8Srobert };
135*f6aab3d8Srobert 
136*f6aab3d8Srobert /// HTR layer interface
137*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation
138*f6aab3d8Srobert class IHTRLayer {
139*f6aab3d8Srobert public:
140*f6aab3d8Srobert   /// Construct new HTR layer.
141*f6aab3d8Srobert   //
142*f6aab3d8Srobert   /// \param[in] id
143*f6aab3d8Srobert   ///     The layer's id.
IHTRLayer(size_t id)144*f6aab3d8Srobert   IHTRLayer(size_t id) : m_layer_id(id) {}
145*f6aab3d8Srobert 
146*f6aab3d8Srobert   /// Get the ID of the layer.
147*f6aab3d8Srobert   ///
148*f6aab3d8Srobert   /// \return
149*f6aab3d8Srobert   ///     The layer ID of this layer.
150*f6aab3d8Srobert   size_t GetLayerId() const;
151*f6aab3d8Srobert 
152*f6aab3d8Srobert   /// Get the metadata of a unit (instruction or block) in the layer.
153*f6aab3d8Srobert   ///
154*f6aab3d8Srobert   /// \param[in] index
155*f6aab3d8Srobert   ///     The position of the unit in the layer.
156*f6aab3d8Srobert   ///
157*f6aab3d8Srobert   /// \return
158*f6aab3d8Srobert   ///     The metadata of the unit in the layer.
159*f6aab3d8Srobert   virtual HTRBlockMetadata GetMetadataByIndex(size_t index) const = 0;
160*f6aab3d8Srobert 
161*f6aab3d8Srobert   /// Get the total number of units (instruction or block) in this layer.
162*f6aab3d8Srobert   ///
163*f6aab3d8Srobert   /// \return
164*f6aab3d8Srobert   ///     The total number of units in the layer.
165*f6aab3d8Srobert   virtual size_t GetNumUnits() const = 0;
166*f6aab3d8Srobert 
167*f6aab3d8Srobert   /// Creates a new block from the result of merging a contiguous sequence of
168*f6aab3d8Srobert   /// "units" (instructions or blocks depending on layer type) in this layer
169*f6aab3d8Srobert   /// This allows the implementation class to decide how to store/generate this
170*f6aab3d8Srobert   /// metadata. For example, in the case of the instruction layer we want to
171*f6aab3d8Srobert   /// lazily generate this metadata instead of storing it for each instruction.
172*f6aab3d8Srobert   ///
173*f6aab3d8Srobert   /// \param[in] start_unit_index
174*f6aab3d8Srobert   ///     The index of the first unit to be merged.
175*f6aab3d8Srobert   ///
176*f6aab3d8Srobert   /// \param[in] num_units
177*f6aab3d8Srobert   ///     The number of units to be merged. Must be >= 1, since merging 0 blocks
178*f6aab3d8Srobert   ///     does not make sense.
179*f6aab3d8Srobert   ///
180*f6aab3d8Srobert   /// \return
181*f6aab3d8Srobert   ///     A new block instance representing the merge of the specified units.
182*f6aab3d8Srobert   HTRBlock MergeUnits(size_t start_unit_index, size_t num_units);
183*f6aab3d8Srobert 
184*f6aab3d8Srobert   virtual ~IHTRLayer() = default;
185*f6aab3d8Srobert 
186*f6aab3d8Srobert protected:
187*f6aab3d8Srobert   /// ID of the layer.
188*f6aab3d8Srobert   size_t m_layer_id;
189*f6aab3d8Srobert };
190*f6aab3d8Srobert 
191*f6aab3d8Srobert /// "Base" layer of HTR representing the dynamic instructions of the trace.
192*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation
193*f6aab3d8Srobert class HTRInstructionLayer : public IHTRLayer {
194*f6aab3d8Srobert public:
195*f6aab3d8Srobert   /// Construct new instruction layer.
196*f6aab3d8Srobert   //
197*f6aab3d8Srobert   /// \param[in] id
198*f6aab3d8Srobert   ///     The layer's id.
HTRInstructionLayer(size_t id)199*f6aab3d8Srobert   HTRInstructionLayer(size_t id) : IHTRLayer(id) {}
200*f6aab3d8Srobert 
201*f6aab3d8Srobert   size_t GetNumUnits() const override;
202*f6aab3d8Srobert 
203*f6aab3d8Srobert   HTRBlockMetadata GetMetadataByIndex(size_t index) const override;
204*f6aab3d8Srobert 
205*f6aab3d8Srobert   /// Get the dynamic instruction trace.
206*f6aab3d8Srobert   ///
207*f6aab3d8Srobert   /// \return
208*f6aab3d8Srobert   ///     The dynamic instruction trace.
209*f6aab3d8Srobert   llvm::ArrayRef<lldb::addr_t> GetInstructionTrace() const;
210*f6aab3d8Srobert 
211*f6aab3d8Srobert   /// Add metadata for a 'call' instruction of the trace.
212*f6aab3d8Srobert   ///
213*f6aab3d8Srobert   /// \param[in] load_addr
214*f6aab3d8Srobert   ///     The load address of the 'call' instruction.
215*f6aab3d8Srobert   ///
216*f6aab3d8Srobert   /// \param[in] func_name
217*f6aab3d8Srobert   ///     The name of the function the 'call' instruction is calling if it can
218*f6aab3d8Srobert   ///     be determined, None otherwise.
219*f6aab3d8Srobert   void AddCallInstructionMetadata(lldb::addr_t load_addr,
220*f6aab3d8Srobert                                   std::optional<ConstString> func_name);
221*f6aab3d8Srobert 
222*f6aab3d8Srobert   /// Append the load address of an instruction to the dynamic instruction
223*f6aab3d8Srobert   /// trace.
224*f6aab3d8Srobert   ///
225*f6aab3d8Srobert   /// \param[in] load_addr
226*f6aab3d8Srobert   ///     The load address of the instruction.
227*f6aab3d8Srobert   void AppendInstruction(lldb::addr_t load_addr);
228*f6aab3d8Srobert 
229*f6aab3d8Srobert private:
230*f6aab3d8Srobert   // Dynamic instructions of trace are stored in chronological order.
231*f6aab3d8Srobert   std::vector<lldb::addr_t> m_instruction_trace;
232*f6aab3d8Srobert   // Only store metadata for instructions of interest (call instructions)
233*f6aab3d8Srobert   // If we stored metadata for each instruction this would be wasteful since
234*f6aab3d8Srobert   // most instructions don't contain useful metadata
235*f6aab3d8Srobert 
236*f6aab3d8Srobert   // This map contains the load address of all the call instructions.
237*f6aab3d8Srobert   // load address maps to the name of the function it calls (std::nullopt if
238*f6aab3d8Srobert   // function name can't be determined)
239*f6aab3d8Srobert   std::unordered_map<lldb::addr_t, std::optional<ConstString>> m_call_isns;
240*f6aab3d8Srobert };
241*f6aab3d8Srobert 
242*f6aab3d8Srobert /// HTR layer composed of blocks of the trace.
243*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation
244*f6aab3d8Srobert class HTRBlockLayer : public IHTRLayer {
245*f6aab3d8Srobert public:
246*f6aab3d8Srobert   /// Construct new block layer.
247*f6aab3d8Srobert   //
248*f6aab3d8Srobert   /// \param[in] id
249*f6aab3d8Srobert   ///     The layer's id.
HTRBlockLayer(size_t id)250*f6aab3d8Srobert   HTRBlockLayer(size_t id) : IHTRLayer(id) {}
251*f6aab3d8Srobert 
252*f6aab3d8Srobert   size_t GetNumUnits() const override;
253*f6aab3d8Srobert 
254*f6aab3d8Srobert   HTRBlockMetadata GetMetadataByIndex(size_t index) const override;
255*f6aab3d8Srobert 
256*f6aab3d8Srobert   /// Get an \a HTRBlock from its block id.
257*f6aab3d8Srobert   ///
258*f6aab3d8Srobert   /// \param[in] block_id
259*f6aab3d8Srobert   ///     The id of the block to retrieve.
260*f6aab3d8Srobert   ///
261*f6aab3d8Srobert   /// \return
262*f6aab3d8Srobert   ///     The \a HTRBlock with the specified id, nullptr if no there is no block
263*f6aab3d8Srobert   ///     in the layer with the specified block id.
264*f6aab3d8Srobert   HTRBlock const *GetBlockById(size_t block_id) const;
265*f6aab3d8Srobert 
266*f6aab3d8Srobert   /// Get the block ID trace for this layer.
267*f6aab3d8Srobert   /// This block ID trace stores the block ID of each block that occured in the
268*f6aab3d8Srobert   /// trace and the block defs map maps block ID to the corresponding \a
269*f6aab3d8Srobert   /// HTRBlock.
270*f6aab3d8Srobert   ///
271*f6aab3d8Srobert   /// \return
272*f6aab3d8Srobert   ///     The block ID trace for this layer.
273*f6aab3d8Srobert   llvm::ArrayRef<size_t> GetBlockIdTrace() const;
274*f6aab3d8Srobert 
275*f6aab3d8Srobert   /// Appends a new block to the layer.
276*f6aab3d8Srobert   ///
277*f6aab3d8Srobert   /// \param[in] block_id
278*f6aab3d8Srobert   ///     The block id of the new block.
279*f6aab3d8Srobert   ///
280*f6aab3d8Srobert   /// \param[in] block
281*f6aab3d8Srobert   ///     The new \a HTRBlock to be appended to the layer. This block is moved
282*f6aab3d8Srobert   ///     into the layer.
283*f6aab3d8Srobert   void AppendNewBlock(size_t block_id, HTRBlock &&block);
284*f6aab3d8Srobert 
285*f6aab3d8Srobert   /// Appends a repeated block to the layer.
286*f6aab3d8Srobert   ///
287*f6aab3d8Srobert   /// \param[in] block_id
288*f6aab3d8Srobert   ///     The block id of the repeated block.
289*f6aab3d8Srobert   void AppendRepeatedBlock(size_t block_id);
290*f6aab3d8Srobert 
291*f6aab3d8Srobert private:
292*f6aab3d8Srobert   /// Maps a unique Block ID to the corresponding HTRBlock
293*f6aab3d8Srobert   std::unordered_map<size_t, HTRBlock> m_block_defs;
294*f6aab3d8Srobert   /// Reduce memory footprint by just storing a trace of block IDs and use
295*f6aab3d8Srobert   /// m_block_defs to map a block_id to its corresponding HTRBlock
296*f6aab3d8Srobert   std::vector<size_t> m_block_id_trace;
297*f6aab3d8Srobert };
298*f6aab3d8Srobert 
299*f6aab3d8Srobert typedef std::unique_ptr<lldb_private::HTRBlockLayer> HTRBlockLayerUP;
300*f6aab3d8Srobert typedef std::unique_ptr<lldb_private::HTRInstructionLayer>
301*f6aab3d8Srobert     HTRInstructionLayerUP;
302*f6aab3d8Srobert 
303*f6aab3d8Srobert /// Top-level HTR class
304*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation
305*f6aab3d8Srobert class TraceHTR {
306*f6aab3d8Srobert 
307*f6aab3d8Srobert public:
308*f6aab3d8Srobert   /// Constructor for a trace's HTR.
309*f6aab3d8Srobert   ///
310*f6aab3d8Srobert   /// \param[in] thread
311*f6aab3d8Srobert   ///     The thread the trace belongs to.
312*f6aab3d8Srobert   ///
313*f6aab3d8Srobert   /// \param[in] cursor
314*f6aab3d8Srobert   ///     The trace cursor that gives access to the trace's contents.
315*f6aab3d8Srobert   TraceHTR(Thread &thread, TraceCursor &cursor);
316*f6aab3d8Srobert 
317*f6aab3d8Srobert   /// Executes passes on the HTR layers until no further
318*f6aab3d8Srobert   /// summarization/compression is achieved
319*f6aab3d8Srobert   void ExecutePasses();
320*f6aab3d8Srobert 
321*f6aab3d8Srobert   /// Export HTR layers to the specified format and outfile.
322*f6aab3d8Srobert   ///
323*f6aab3d8Srobert   /// \param[in] outfile
324*f6aab3d8Srobert   ///     The file that the exported HTR data will be written to.
325*f6aab3d8Srobert   ///
326*f6aab3d8Srobert   /// \return
327*f6aab3d8Srobert   ///     Success if the export is successful, Error otherwise.
328*f6aab3d8Srobert   llvm::Error Export(std::string outfile);
329*f6aab3d8Srobert 
330*f6aab3d8Srobert   /// Get the block layers of this HTR.
331*f6aab3d8Srobert   ///
332*f6aab3d8Srobert   /// \return
333*f6aab3d8Srobert   ///     The block layers of this HTR.
334*f6aab3d8Srobert   llvm::ArrayRef<HTRBlockLayerUP> GetBlockLayers() const;
335*f6aab3d8Srobert 
336*f6aab3d8Srobert   /// Get the instruction layer of this HTR.
337*f6aab3d8Srobert   ///
338*f6aab3d8Srobert   /// \return
339*f6aab3d8Srobert   ///     The instruction layer of this HTR.
340*f6aab3d8Srobert   HTRInstructionLayer const &GetInstructionLayer() const;
341*f6aab3d8Srobert 
342*f6aab3d8Srobert   /// Add a new block layer to this HTR.
343*f6aab3d8Srobert   ///
344*f6aab3d8Srobert   /// \param[in]
345*f6aab3d8Srobert   ///     The new block layer to be added.
346*f6aab3d8Srobert   void AddNewBlockLayer(HTRBlockLayerUP &&block_layer);
347*f6aab3d8Srobert 
348*f6aab3d8Srobert private:
349*f6aab3d8Srobert   // There is a single instruction layer per HTR
350*f6aab3d8Srobert   HTRInstructionLayerUP m_instruction_layer_up;
351*f6aab3d8Srobert   // There are one or more block layers per HTR
352*f6aab3d8Srobert   std::vector<HTRBlockLayerUP> m_block_layer_ups;
353*f6aab3d8Srobert };
354*f6aab3d8Srobert 
355*f6aab3d8Srobert // Serialization functions for exporting HTR to Chrome Trace Format
356*f6aab3d8Srobert llvm::json::Value toJSON(const TraceHTR &htr);
357*f6aab3d8Srobert llvm::json::Value toJSON(const HTRBlock &block);
358*f6aab3d8Srobert llvm::json::Value toJSON(const HTRBlockMetadata &metadata);
359*f6aab3d8Srobert 
360*f6aab3d8Srobert /// The HTR passes are defined below:
361*f6aab3d8Srobert 
362*f6aab3d8Srobert /// Creates a new layer by merging the "basic super blocks" in the current layer
363*f6aab3d8Srobert ///
364*f6aab3d8Srobert /// A "basic super block" is the longest sequence of blocks that always occur in
365*f6aab3d8Srobert /// the same order. (The concept is akin to “Basic Block" in compiler theory,
366*f6aab3d8Srobert /// but refers to dynamic occurrences rather than CFG nodes)
367*f6aab3d8Srobert ///
368*f6aab3d8Srobert /// Procedure to find all basic super blocks:
369*f6aab3d8Srobert //
370*f6aab3d8Srobert ///   - For each block, compute the number of distinct predecessor and
371*f6aab3d8Srobert ///   successor blocks.
372*f6aab3d8Srobert ///       Predecessor - the block that occurs directly before (to the left of)
373*f6aab3d8Srobert ///       the current block Successor  - the block that occurs directly after
374*f6aab3d8Srobert ///       (to the right of) the current block
375*f6aab3d8Srobert ///   - A block with more than one distinct successor is always the start of a
376*f6aab3d8Srobert ///   super block, the super block will continue until the next block with
377*f6aab3d8Srobert ///   more than one distinct predecessor or successor.
378*f6aab3d8Srobert ///
379*f6aab3d8Srobert /// The implementation makes use of two terms - 'heads' and 'tails' known as
380*f6aab3d8Srobert /// the 'endpoints' of a basic super block:
381*f6aab3d8Srobert ///   A 'head' is defined to be a block in the trace that doesn't have a
382*f6aab3d8Srobert ///   unique predecessor
383*f6aab3d8Srobert ///   A 'tail' is defined to be a block in the trace that doesn't have a
384*f6aab3d8Srobert ///   unique successor
385*f6aab3d8Srobert ///
386*f6aab3d8Srobert /// A basic super block is defined to be a sequence of blocks between two
387*f6aab3d8Srobert /// endpoints
388*f6aab3d8Srobert ///
389*f6aab3d8Srobert /// A head represents the start of the next group, so the current group
390*f6aab3d8Srobert /// ends at the block preceding the head and the next group begins with
391*f6aab3d8Srobert /// this head block
392*f6aab3d8Srobert ///
393*f6aab3d8Srobert /// A tail represents the end of the current group, so the current group
394*f6aab3d8Srobert /// ends with the tail block and the next group begins with the
395*f6aab3d8Srobert /// following block.
396*f6aab3d8Srobert ///
397*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation
398*f6aab3d8Srobert ///
399*f6aab3d8Srobert /// \param[in] layer
400*f6aab3d8Srobert ///     The layer to execute the pass on.
401*f6aab3d8Srobert ///
402*f6aab3d8Srobert /// \return
403*f6aab3d8Srobert ///     A new layer instance representing the merge of blocks in the
404*f6aab3d8Srobert ///     previous layer
405*f6aab3d8Srobert HTRBlockLayerUP BasicSuperBlockMerge(IHTRLayer &layer);
406*f6aab3d8Srobert 
407*f6aab3d8Srobert } // namespace lldb_private
408*f6aab3d8Srobert 
409*f6aab3d8Srobert #endif // LLDB_TARGET_TRACE_HTR_H
410