xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- PGOCtxProfWriter.h - Contextual Profile Writer -----------*- C++ -*-===//
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 // This file declares a utility for writing a contextual profile to bitstream.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_
14 #define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_
15 
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/Bitstream/BitCodeEnums.h"
18 #include "llvm/Bitstream/BitstreamWriter.h"
19 #include "llvm/ProfileData/CtxInstrContextNode.h"
20 #include "llvm/Support/Compiler.h"
21 
22 namespace llvm {
23 enum PGOCtxProfileRecords {
24   Invalid = 0,
25   Version,
26   Guid,
27   CallsiteIndex,
28   Counters,
29   TotalRootEntryCount
30 };
31 
32 enum PGOCtxProfileBlockIDs {
33   FIRST_VALID = bitc::FIRST_APPLICATION_BLOCKID,
34   ProfileMetadataBlockID = FIRST_VALID,
35   ContextsSectionBlockID = ProfileMetadataBlockID + 1,
36   ContextRootBlockID = ContextsSectionBlockID + 1,
37   ContextNodeBlockID = ContextRootBlockID + 1,
38   FlatProfilesSectionBlockID = ContextNodeBlockID + 1,
39   FlatProfileBlockID = FlatProfilesSectionBlockID + 1,
40   UnhandledBlockID = FlatProfileBlockID + 1,
41   LAST_VALID = UnhandledBlockID
42 };
43 
44 /// Write one or more ContextNodes to the provided raw_fd_stream.
45 /// The caller must destroy the PGOCtxProfileWriter object before closing the
46 /// stream.
47 /// The design allows serializing a bunch of contexts embedded in some other
48 /// file. The overall format is:
49 ///
50 ///  [... other data written to the stream...]
51 ///  SubBlock(ProfileMetadataBlockID)
52 ///   Version
53 ///   SubBlock(ContextNodeBlockID)
54 ///     [RECORDS]
55 ///     SubBlock(ContextNodeBlockID)
56 ///       [RECORDS]
57 ///       [... more SubBlocks]
58 ///     EndBlock
59 ///   EndBlock
60 ///
61 /// The "RECORDS" are bitsream records. The IDs are in CtxProfileCodes (except)
62 /// for Version, which is just for metadata). All contexts will have Guid and
63 /// Counters, and all but the roots have CalleeIndex. The order in which the
64 /// records appear does not matter, but they must precede any subcontexts,
65 /// because that helps keep the reader code simpler.
66 ///
67 /// Subblock containment captures the context->subcontext relationship. The
68 /// "next()" relationship in the raw profile, between call targets of indirect
69 /// calls, are just modeled as peer subblocks where the callee index is the
70 /// same.
71 ///
72 /// Versioning: the writer may produce additional records not known by the
73 /// reader. The version number indicates a more structural change.
74 /// The current version, in particular, is set up to expect optional extensions
75 /// like value profiling - which would appear as additional records. For
76 /// example, value profiling would produce a new record with a new record ID,
77 /// containing the profiled values (much like the counters)
78 class LLVM_ABI PGOCtxProfileWriter final : public ctx_profile::ProfileWriter {
79   enum class EmptyContextCriteria { None, EntryIsZero, AllAreZero };
80 
81   BitstreamWriter Writer;
82   const bool IncludeEmpty;
83 
84   void writeGuid(ctx_profile::GUID Guid);
85   void writeCallsiteIndex(uint32_t Index);
86   void writeRootEntryCount(uint64_t EntryCount);
87   void writeCounters(ArrayRef<uint64_t> Counters);
88   void writeNode(uint32_t CallerIndex, const ctx_profile::ContextNode &Node);
89   void writeSubcontexts(const ctx_profile::ContextNode &Node);
90 
91 public:
92   PGOCtxProfileWriter(raw_ostream &Out,
93                       std::optional<unsigned> VersionOverride = std::nullopt,
94                       bool IncludeEmpty = false);
~PGOCtxProfileWriter()95   ~PGOCtxProfileWriter() { Writer.ExitBlock(); }
96 
97   void startContextSection() override;
98   void writeContextual(const ctx_profile::ContextNode &RootNode,
99                        const ctx_profile::ContextNode *Unhandled,
100                        uint64_t TotalRootEntryCount) override;
101   void endContextSection() override;
102 
103   void startFlatSection() override;
104   void writeFlat(ctx_profile::GUID Guid, const uint64_t *Buffer,
105                  size_t BufferSize) override;
106   void endFlatSection() override;
107 
108   // constants used in writing which a reader may find useful.
109   static constexpr unsigned CodeLen = 2;
110   static constexpr uint32_t CurrentVersion = 4;
111   static constexpr unsigned VBREncodingBits = 6;
112   static constexpr StringRef ContainerMagic = "CTXP";
113 };
114 
115 LLVM_ABI Error createCtxProfFromYAML(StringRef Profile, raw_ostream &Out);
116 } // namespace llvm
117 #endif
118