LLVM 20.0.0git
PGOCtxProfWriter.cpp
Go to the documentation of this file.
1//===- PGOCtxProfWriter.cpp - Contextual Instrumentation profile writer ---===//
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//
9// Write a contextual profile to bitstream.
10//
11//===----------------------------------------------------------------------===//
12
16#include "llvm/Support/Error.h"
17#include "llvm/Support/JSON.h"
21
22using namespace llvm;
23using namespace llvm::ctx_profile;
24
26 raw_ostream &Out, std::optional<unsigned> VersionOverride)
27 : Writer(Out, 0) {
28 static_assert(ContainerMagic.size() == 4);
30 Writer.EnterBlockInfoBlock();
31 {
32 auto DescribeBlock = [&](unsigned ID, StringRef Name) {
36 llvm::arrayRefFromStringRef(Name));
37 };
39 auto DescribeRecord = [&](unsigned RecordID, StringRef Name) {
40 Data.clear();
41 Data.push_back(RecordID);
44 };
45 DescribeBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, "Metadata");
46 DescribeRecord(PGOCtxProfileRecords::Version, "Version");
47 DescribeBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID, "Context");
48 DescribeRecord(PGOCtxProfileRecords::Guid, "GUID");
49 DescribeRecord(PGOCtxProfileRecords::CalleeIndex, "CalleeIndex");
50 DescribeRecord(PGOCtxProfileRecords::Counters, "Counters");
51 }
52 Writer.ExitBlock();
54 const auto Version = VersionOverride.value_or(CurrentVersion);
57}
58
59void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) {
62 Writer.EmitVBR(Node.counters_size(), VBREncodingBits);
63 for (uint32_t I = 0U; I < Node.counters_size(); ++I)
64 Writer.EmitVBR64(Node.counters()[I], VBREncodingBits);
65}
66
67// recursively write all the subcontexts. We do need to traverse depth first to
68// model the context->subcontext implicitly, and since this captures call
69// stacks, we don't really need to be worried about stack overflow and we can
70// keep the implementation simple.
71void PGOCtxProfileWriter::writeImpl(std::optional<uint32_t> CallerIndex,
72 const ContextNode &Node) {
76 if (CallerIndex)
78 SmallVector<uint64_t, 1>{*CallerIndex});
79 writeCounters(Node);
80 for (uint32_t I = 0U; I < Node.callsites_size(); ++I)
81 for (const auto *Subcontext = Node.subContexts()[I]; Subcontext;
82 Subcontext = Subcontext->next())
83 writeImpl(I, *Subcontext);
84 Writer.ExitBlock();
85}
86
88 writeImpl(std::nullopt, RootNode);
89}
90
91namespace {
93createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
94 const std::vector<SerializableCtxRepresentation> &DCList);
95
96// Convert a DeserializableCtx into a ContextNode, potentially linking it to
97// its sibling (e.g. callee at same callsite) "Next".
99createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
101 ctx_profile::ContextNode *Next = nullptr) {
102 auto AllocSize = ctx_profile::ContextNode::getAllocSize(DC.Counters.size(),
103 DC.Callsites.size());
104 auto *Mem = Nodes.emplace_back(std::make_unique<char[]>(AllocSize)).get();
105 std::memset(Mem, 0, AllocSize);
106 auto *Ret = new (Mem) ctx_profile::ContextNode(DC.Guid, DC.Counters.size(),
107 DC.Callsites.size(), Next);
108 std::memcpy(Ret->counters(), DC.Counters.data(),
109 sizeof(uint64_t) * DC.Counters.size());
110 for (const auto &[I, DCList] : llvm::enumerate(DC.Callsites))
111 Ret->subContexts()[I] = createNode(Nodes, DCList);
112 return Ret;
113}
114
115// Convert a list of SerializableCtxRepresentation into a linked list of
116// ContextNodes.
118createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
119 const std::vector<SerializableCtxRepresentation> &DCList) {
121 for (const auto &DC : DCList)
122 List = createNode(Nodes, DC, List);
123 return List;
124}
125} // namespace
126
128LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<SerializableCtxRepresentation>)
130 static void mapping(yaml::IO &IO, SerializableCtxRepresentation &SCR) {
131 IO.mapRequired("Guid", SCR.Guid);
132 IO.mapRequired("Counters", SCR.Counters);
133 IO.mapOptional("Callsites", SCR.Callsites);
134 }
135};
136
138 yaml::Input In(Profile);
139 std::vector<SerializableCtxRepresentation> DCList;
140 In >> DCList;
141 if (In.error())
142 return createStringError(In.error(), "incorrect yaml content");
143 std::vector<std::unique_ptr<char[]>> Nodes;
144 std::error_code EC;
145 if (EC)
146 return createStringError(EC, "failed to open output");
147 PGOCtxProfileWriter Writer(Out);
148 for (const auto &DC : DCList) {
149 auto *TopList = createNode(Nodes, DC);
150 if (!TopList)
151 return createStringError(
152 "Unexpected error converting internal structure to ctx profile");
153 Writer.write(*TopList);
154 }
155 if (EC)
156 return createStringError(EC, "failed to write output");
157 return Error::success();
158}
std::string Name
This file supports working with JSON data.
#define I(x, y, z)
Definition: MD5.cpp:58
Load MIR Sample Profile
#define LLVM_YAML_IS_SEQUENCE_VECTOR(type)
void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev=0)
EmitRecord - Emit the specified record to the stream, using an abbrev if we have one to compress the ...
void EmitCode(unsigned Val)
EmitCode - Emit the specified code.
void EmitVBR64(uint64_t Val, unsigned NumBits)
void EnterBlockInfoBlock()
EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
void EmitVBR(uint32_t Val, unsigned NumBits)
void EnterSubblock(unsigned BlockID, unsigned CodeLen)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Write one or more ContextNodes to the provided raw_fd_stream.
static constexpr unsigned VBREncodingBits
static constexpr uint32_t CurrentVersion
static constexpr StringRef ContainerMagic
PGOCtxProfileWriter(raw_ostream &Out, std::optional< unsigned > VersionOverride=std::nullopt)
void write(const ctx_profile::ContextNode &)
static constexpr unsigned CodeLen
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:150
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:144
static size_t getAllocSize(uint32_t NumCounters, uint32_t NumCallsites)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
raw_ostream & write(unsigned char C)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ BLOCKINFO_CODE_BLOCKNAME
Definition: BitCodeEnums.h:82
@ BLOCKINFO_CODE_SETRECORDNAME
Definition: BitCodeEnums.h:83
@ BLOCKINFO_CODE_SETBID
Definition: BitCodeEnums.h:81
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition: STLExtras.h:2448
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2115
Error createCtxProfFromYAML(StringRef Profile, raw_ostream &Out)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1291
@ ContextNodeBlockID
@ ProfileMetadataBlockID
Representation of the context node suitable for yaml / json serialization / deserialization.
std::vector< std::vector< SerializableCtxRepresentation > > Callsites
std::vector< uint64_t > Counters
static void mapping(yaml::IO &IO, SerializableCtxRepresentation &SCR)