@@ -55,10 +55,12 @@ PGOCtxProfileWriter::PGOCtxProfileWriter(
5555 DescribeBlock (PGOCtxProfileBlockIDs::ContextsSectionBlockID, " Contexts" );
5656 DescribeBlock (PGOCtxProfileBlockIDs::ContextRootBlockID, " Root" );
5757 DescribeRecord (PGOCtxProfileRecords::Guid, " GUID" );
58+ DescribeRecord (PGOCtxProfileRecords::TotalRootEntryCount,
59+ " TotalRootEntryCount" );
5860 DescribeRecord (PGOCtxProfileRecords::Counters, " Counters" );
5961 DescribeBlock (PGOCtxProfileBlockIDs::ContextNodeBlockID, " Context" );
6062 DescribeRecord (PGOCtxProfileRecords::Guid, " GUID" );
61- DescribeRecord (PGOCtxProfileRecords::CalleeIndex , " CalleeIndex" );
63+ DescribeRecord (PGOCtxProfileRecords::CallsiteIndex , " CalleeIndex" );
6264 DescribeRecord (PGOCtxProfileRecords::Counters, " Counters" );
6365 DescribeBlock (PGOCtxProfileBlockIDs::FlatProfilesSectionBlockID,
6466 " FlatProfiles" );
@@ -85,29 +87,39 @@ void PGOCtxProfileWriter::writeGuid(ctx_profile::GUID Guid) {
8587 Writer.EmitRecord (PGOCtxProfileRecords::Guid, SmallVector<uint64_t , 1 >{Guid});
8688}
8789
90+ void PGOCtxProfileWriter::writeCallsiteIndex (uint32_t CallsiteIndex) {
91+ Writer.EmitRecord (PGOCtxProfileRecords::CallsiteIndex,
92+ SmallVector<uint64_t , 1 >{CallsiteIndex});
93+ }
94+
95+ void PGOCtxProfileWriter::writeRootEntryCount (uint64_t TotalRootEntryCount) {
96+ Writer.EmitRecord (PGOCtxProfileRecords::TotalRootEntryCount,
97+ SmallVector<uint64_t , 1 >{TotalRootEntryCount});
98+ }
99+
88100// recursively write all the subcontexts. We do need to traverse depth first to
89101// model the context->subcontext implicitly, and since this captures call
90102// stacks, we don't really need to be worried about stack overflow and we can
91103// keep the implementation simple.
92- void PGOCtxProfileWriter::writeImpl (std::optional< uint32_t > CallerIndex ,
104+ void PGOCtxProfileWriter::writeNode ( uint32_t CallsiteIndex ,
93105 const ContextNode &Node) {
94106 // A node with no counters is an error. We don't expect this to happen from
95107 // the runtime, rather, this is interesting for testing the reader.
96108 if (!IncludeEmpty && (Node.counters_size () > 0 && Node.entrycount () == 0 ))
97109 return ;
98- Writer.EnterSubblock (CallerIndex ? PGOCtxProfileBlockIDs::ContextNodeBlockID
99- : PGOCtxProfileBlockIDs::ContextRootBlockID,
100- CodeLen);
110+ Writer.EnterSubblock (PGOCtxProfileBlockIDs::ContextNodeBlockID, CodeLen);
101111 writeGuid (Node.guid ());
102- if (CallerIndex)
103- Writer.EmitRecord (PGOCtxProfileRecords::CalleeIndex,
104- SmallVector<uint64_t , 1 >{*CallerIndex});
112+ writeCallsiteIndex (CallsiteIndex);
105113 writeCounters ({Node.counters (), Node.counters_size ()});
114+ writeSubcontexts (Node);
115+ Writer.ExitBlock ();
116+ }
117+
118+ void PGOCtxProfileWriter::writeSubcontexts (const ContextNode &Node) {
106119 for (uint32_t I = 0U ; I < Node.callsites_size (); ++I)
107120 for (const auto *Subcontext = Node.subContexts ()[I]; Subcontext;
108121 Subcontext = Subcontext->next ())
109- writeImpl (I, *Subcontext);
110- Writer.ExitBlock ();
122+ writeNode (I, *Subcontext);
111123}
112124
113125void PGOCtxProfileWriter::startContextSection () {
@@ -122,8 +134,17 @@ void PGOCtxProfileWriter::startFlatSection() {
122134void PGOCtxProfileWriter::endContextSection () { Writer.ExitBlock (); }
123135void PGOCtxProfileWriter::endFlatSection () { Writer.ExitBlock (); }
124136
125- void PGOCtxProfileWriter::writeContextual (const ContextNode &RootNode) {
126- writeImpl (std::nullopt , RootNode);
137+ void PGOCtxProfileWriter::writeContextual (const ContextNode &RootNode,
138+ uint64_t TotalRootEntryCount) {
139+ if (!IncludeEmpty && (!TotalRootEntryCount || (RootNode.counters_size () > 0 &&
140+ RootNode.entrycount () == 0 )))
141+ return ;
142+ Writer.EnterSubblock (PGOCtxProfileBlockIDs::ContextRootBlockID, CodeLen);
143+ writeGuid (RootNode.guid ());
144+ writeRootEntryCount (TotalRootEntryCount);
145+ writeCounters ({RootNode.counters (), RootNode.counters_size ()});
146+ writeSubcontexts (RootNode);
147+ Writer.ExitBlock ();
127148}
128149
129150void PGOCtxProfileWriter::writeFlat (ctx_profile::GUID Guid,
@@ -144,11 +165,15 @@ struct SerializableCtxRepresentation {
144165 std::vector<std::vector<SerializableCtxRepresentation>> Callsites;
145166};
146167
168+ struct SerializableRootRepresentation : public SerializableCtxRepresentation {
169+ uint64_t TotalRootEntryCount = 0 ;
170+ };
171+
147172using SerializableFlatProfileRepresentation =
148173 std::pair<ctx_profile::GUID, std::vector<uint64_t >>;
149174
150175struct SerializableProfileRepresentation {
151- std::vector<SerializableCtxRepresentation > Contexts;
176+ std::vector<SerializableRootRepresentation > Contexts;
152177 std::vector<SerializableFlatProfileRepresentation> FlatProfiles;
153178};
154179
@@ -189,6 +214,7 @@ createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
189214
190215LLVM_YAML_IS_SEQUENCE_VECTOR (SerializableCtxRepresentation)
191216LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<SerializableCtxRepresentation>)
217+ LLVM_YAML_IS_SEQUENCE_VECTOR(SerializableRootRepresentation)
192218LLVM_YAML_IS_SEQUENCE_VECTOR(SerializableFlatProfileRepresentation)
193219template <> struct yaml::MappingTraits<SerializableCtxRepresentation> {
194220 static void mapping (yaml::IO &IO, SerializableCtxRepresentation &SCR) {
@@ -198,6 +224,13 @@ template <> struct yaml::MappingTraits<SerializableCtxRepresentation> {
198224 }
199225};
200226
227+ template <> struct yaml ::MappingTraits<SerializableRootRepresentation> {
228+ static void mapping (yaml::IO &IO, SerializableRootRepresentation &R) {
229+ yaml::MappingTraits<SerializableCtxRepresentation>::mapping (IO, R);
230+ IO.mapRequired (" TotalRootEntryCount" , R.TotalRootEntryCount );
231+ }
232+ };
233+
201234template <> struct yaml ::MappingTraits<SerializableProfileRepresentation> {
202235 static void mapping (yaml::IO &IO, SerializableProfileRepresentation &SPR) {
203236 IO.mapOptional (" Contexts" , SPR.Contexts );
@@ -232,7 +265,7 @@ Error llvm::createCtxProfFromYAML(StringRef Profile, raw_ostream &Out) {
232265 if (!TopList)
233266 return createStringError (
234267 " Unexpected error converting internal structure to ctx profile" );
235- Writer.writeContextual (*TopList);
268+ Writer.writeContextual (*TopList, DC. TotalRootEntryCount );
236269 }
237270 Writer.endContextSection ();
238271 }
0 commit comments