1 //===-- TraceHTR.h --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_TARGET_TRACE_HTR_H
10 #define LLDB_TARGET_TRACE_HTR_H
12 #include "lldb/Target/Thread.h"
13 #include "lldb/Target/Trace.h"
16 #include <unordered_map>
17 #include <unordered_set>
19 namespace lldb_private
{
21 /// Metadata associated with an HTR block
22 /// See lldb/docs/htr.rst for comprehensive HTR documentation
23 class HTRBlockMetadata
{
25 /// Constructor for a block's metadata.
27 /// \param[in] first_instruction_load_address
28 /// The load address of the block's first instruction.
30 /// \param[in] num_instructions
31 /// The total number of instructions in the block.
33 /// \param[in] func_calls
34 /// The map of a function name to the number of times it is called from
36 HTRBlockMetadata(lldb::addr_t first_instruction_load_address
,
37 size_t num_instructions
,
38 llvm::DenseMap
<ConstString
, size_t> &&func_calls
)
39 : m_first_instruction_load_address(first_instruction_load_address
),
40 m_num_instructions(num_instructions
), m_func_calls(func_calls
) {}
42 /// Merge two \a HTRBlockMetadata in place.
44 /// \param[in][out] merged_metadata
45 /// Metadata that metadata_to_merge will be merged into.
47 /// \param[in] metadata_to_merge
48 /// Metadata to merge into merged_metadata.
49 static void MergeMetadata(HTRBlockMetadata
&merged_metadata
,
50 HTRBlockMetadata
const &metadata_to_merge
);
51 /// Get the number of instructions in the block.
54 /// The number of instructions in the block.
55 size_t GetNumInstructions() const;
57 /// Get the name of the most frequently called function from the block.
60 /// The name of the function that is called the most from this block or
61 /// std::nullopt if no function is called from this block.
62 std::optional
<llvm::StringRef
> GetMostFrequentlyCalledFunction() const;
64 /// Get the load address of the first instruction in the block.
67 /// The load address of the first instruction in the block.
68 lldb::addr_t
GetFirstInstructionLoadAddress() const;
70 /// Get the function calls map for the block.
71 /// Function calls are identified in the instruction layer by finding 'call'
72 /// instructions and determining the function they are calling. As these
73 /// instructions are merged into blocks, we merge these different function
74 /// calls into a single map containing the function names to the number of
75 /// times it is called from this block.
78 /// The mapping of function name to the number of times it is called from
80 llvm::DenseMap
<ConstString
, size_t> const &GetFunctionCalls() const;
83 lldb::addr_t m_first_instruction_load_address
;
84 size_t m_num_instructions
;
85 llvm::DenseMap
<ConstString
, size_t> m_func_calls
;
88 /// Block structure representing a sequence of trace "units" (ie instructions).
89 /// Sequences of blocks are merged to create a new, single block
90 /// See lldb/docs/htr.rst for comprehensive HTR documentation
93 /// Constructor for a block of an HTR layer.
96 /// The offset of the start of this block in the previous layer.
99 /// Number of blocks/instructions that make up this block in the previous
102 /// \param[in] metadata
103 /// General metadata for this block.
104 HTRBlock(size_t offset
, size_t size
, HTRBlockMetadata metadata
)
105 : m_offset(offset
), m_size(size
), m_metadata(metadata
) {}
107 /// Get the offset of the start of this block in the previous layer.
110 /// The offset of the block.
111 size_t GetOffset() const;
113 /// Get the number of blocks/instructions that make up this block in the
117 /// The size of the block.
118 size_t GetSize() const;
120 /// Get the metadata for this block.
123 /// The metadata of the block.
124 HTRBlockMetadata
const &GetMetadata() const;
127 /// Offset in the previous layer
129 /// Number of blocks/instructions that make up this block in the previous
132 /// General metadata for this block
133 HTRBlockMetadata m_metadata
;
136 /// HTR layer interface
137 /// See lldb/docs/htr.rst for comprehensive HTR documentation
140 /// Construct new HTR layer.
144 IHTRLayer(size_t id
) : m_layer_id(id
) {}
146 /// Get the ID of the layer.
149 /// The layer ID of this layer.
150 size_t GetLayerId() const;
152 /// Get the metadata of a unit (instruction or block) in the layer.
155 /// The position of the unit in the layer.
158 /// The metadata of the unit in the layer.
159 virtual HTRBlockMetadata
GetMetadataByIndex(size_t index
) const = 0;
161 /// Get the total number of units (instruction or block) in this layer.
164 /// The total number of units in the layer.
165 virtual size_t GetNumUnits() const = 0;
167 /// Creates a new block from the result of merging a contiguous sequence of
168 /// "units" (instructions or blocks depending on layer type) in this layer
169 /// This allows the implementation class to decide how to store/generate this
170 /// metadata. For example, in the case of the instruction layer we want to
171 /// lazily generate this metadata instead of storing it for each instruction.
173 /// \param[in] start_unit_index
174 /// The index of the first unit to be merged.
176 /// \param[in] num_units
177 /// The number of units to be merged. Must be >= 1, since merging 0 blocks
178 /// does not make sense.
181 /// A new block instance representing the merge of the specified units.
182 HTRBlock
MergeUnits(size_t start_unit_index
, size_t num_units
);
184 virtual ~IHTRLayer() = default;
191 /// "Base" layer of HTR representing the dynamic instructions of the trace.
192 /// See lldb/docs/htr.rst for comprehensive HTR documentation
193 class HTRInstructionLayer
: public IHTRLayer
{
195 /// Construct new instruction layer.
199 HTRInstructionLayer(size_t id
) : IHTRLayer(id
) {}
201 size_t GetNumUnits() const override
;
203 HTRBlockMetadata
GetMetadataByIndex(size_t index
) const override
;
205 /// Get the dynamic instruction trace.
208 /// The dynamic instruction trace.
209 llvm::ArrayRef
<lldb::addr_t
> GetInstructionTrace() const;
211 /// Add metadata for a 'call' instruction of the trace.
213 /// \param[in] load_addr
214 /// The load address of the 'call' instruction.
216 /// \param[in] func_name
217 /// The name of the function the 'call' instruction is calling if it can
218 /// be determined, std::nullopt otherwise.
219 void AddCallInstructionMetadata(lldb::addr_t load_addr
,
220 std::optional
<ConstString
> func_name
);
222 /// Append the load address of an instruction to the dynamic instruction
225 /// \param[in] load_addr
226 /// The load address of the instruction.
227 void AppendInstruction(lldb::addr_t load_addr
);
230 // Dynamic instructions of trace are stored in chronological order.
231 std::vector
<lldb::addr_t
> m_instruction_trace
;
232 // Only store metadata for instructions of interest (call instructions)
233 // If we stored metadata for each instruction this would be wasteful since
234 // most instructions don't contain useful metadata
236 // This map contains the load address of all the call instructions.
237 // load address maps to the name of the function it calls (std::nullopt if
238 // function name can't be determined)
239 std::unordered_map
<lldb::addr_t
, std::optional
<ConstString
>> m_call_isns
;
242 /// HTR layer composed of blocks of the trace.
243 /// See lldb/docs/htr.rst for comprehensive HTR documentation
244 class HTRBlockLayer
: public IHTRLayer
{
246 /// Construct new block layer.
250 HTRBlockLayer(size_t id
) : IHTRLayer(id
) {}
252 size_t GetNumUnits() const override
;
254 HTRBlockMetadata
GetMetadataByIndex(size_t index
) const override
;
256 /// Get an \a HTRBlock from its block id.
258 /// \param[in] block_id
259 /// The id of the block to retrieve.
262 /// The \a HTRBlock with the specified id, nullptr if no there is no block
263 /// in the layer with the specified block id.
264 HTRBlock
const *GetBlockById(size_t block_id
) const;
266 /// Get the block ID trace for this layer.
267 /// This block ID trace stores the block ID of each block that occured in the
268 /// trace and the block defs map maps block ID to the corresponding \a
272 /// The block ID trace for this layer.
273 llvm::ArrayRef
<size_t> GetBlockIdTrace() const;
275 /// Appends a new block to the layer.
277 /// \param[in] block_id
278 /// The block id of the new block.
281 /// The new \a HTRBlock to be appended to the layer. This block is moved
283 void AppendNewBlock(size_t block_id
, HTRBlock
&&block
);
285 /// Appends a repeated block to the layer.
287 /// \param[in] block_id
288 /// The block id of the repeated block.
289 void AppendRepeatedBlock(size_t block_id
);
292 /// Maps a unique Block ID to the corresponding HTRBlock
293 std::unordered_map
<size_t, HTRBlock
> m_block_defs
;
294 /// Reduce memory footprint by just storing a trace of block IDs and use
295 /// m_block_defs to map a block_id to its corresponding HTRBlock
296 std::vector
<size_t> m_block_id_trace
;
299 typedef std::unique_ptr
<lldb_private::HTRBlockLayer
> HTRBlockLayerUP
;
300 typedef std::unique_ptr
<lldb_private::HTRInstructionLayer
>
301 HTRInstructionLayerUP
;
303 /// Top-level HTR class
304 /// See lldb/docs/htr.rst for comprehensive HTR documentation
308 /// Constructor for a trace's HTR.
310 /// \param[in] thread
311 /// The thread the trace belongs to.
313 /// \param[in] cursor
314 /// The trace cursor that gives access to the trace's contents.
315 TraceHTR(Thread
&thread
, TraceCursor
&cursor
);
317 /// Executes passes on the HTR layers until no further
318 /// summarization/compression is achieved
319 void ExecutePasses();
321 /// Export HTR layers to the specified format and outfile.
323 /// \param[in] outfile
324 /// The file that the exported HTR data will be written to.
327 /// Success if the export is successful, Error otherwise.
328 llvm::Error
Export(std::string outfile
);
330 /// Get the block layers of this HTR.
333 /// The block layers of this HTR.
334 llvm::ArrayRef
<HTRBlockLayerUP
> GetBlockLayers() const;
336 /// Get the instruction layer of this HTR.
339 /// The instruction layer of this HTR.
340 HTRInstructionLayer
const &GetInstructionLayer() const;
342 /// Add a new block layer to this HTR.
345 /// The new block layer to be added.
346 void AddNewBlockLayer(HTRBlockLayerUP
&&block_layer
);
349 // There is a single instruction layer per HTR
350 HTRInstructionLayerUP m_instruction_layer_up
;
351 // There are one or more block layers per HTR
352 std::vector
<HTRBlockLayerUP
> m_block_layer_ups
;
355 // Serialization functions for exporting HTR to Chrome Trace Format
356 llvm::json::Value
toJSON(const TraceHTR
&htr
);
357 llvm::json::Value
toJSON(const HTRBlock
&block
);
358 llvm::json::Value
toJSON(const HTRBlockMetadata
&metadata
);
360 /// The HTR passes are defined below:
362 /// Creates a new layer by merging the "basic super blocks" in the current layer
364 /// A "basic super block" is the longest sequence of blocks that always occur in
365 /// the same order. (The concept is akin to “Basic Block" in compiler theory,
366 /// but refers to dynamic occurrences rather than CFG nodes)
368 /// Procedure to find all basic super blocks:
370 /// - For each block, compute the number of distinct predecessor and
371 /// successor blocks.
372 /// Predecessor - the block that occurs directly before (to the left of)
373 /// the current block Successor - the block that occurs directly after
374 /// (to the right of) the current block
375 /// - A block with more than one distinct successor is always the start of a
376 /// super block, the super block will continue until the next block with
377 /// more than one distinct predecessor or successor.
379 /// The implementation makes use of two terms - 'heads' and 'tails' known as
380 /// the 'endpoints' of a basic super block:
381 /// A 'head' is defined to be a block in the trace that doesn't have a
382 /// unique predecessor
383 /// A 'tail' is defined to be a block in the trace that doesn't have a
386 /// A basic super block is defined to be a sequence of blocks between two
389 /// A head represents the start of the next group, so the current group
390 /// ends at the block preceding the head and the next group begins with
393 /// A tail represents the end of the current group, so the current group
394 /// ends with the tail block and the next group begins with the
397 /// See lldb/docs/htr.rst for comprehensive HTR documentation
400 /// The layer to execute the pass on.
403 /// A new layer instance representing the merge of blocks in the
405 HTRBlockLayerUP
BasicSuperBlockMerge(IHTRLayer
&layer
);
407 } // namespace lldb_private
409 #endif // LLDB_TARGET_TRACE_HTR_H