1 //===- InstrProfWriter.h - Instrumented profiling writer --------*- C++ -*-===//
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 // This file contains support for writing profiling data for instrumentation
10 // based PGO and coverage.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H
15 #define LLVM_PROFILEDATA_INSTRPROFWRITER_H
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ProfileData/InstrProf.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/Error.h"
22 #include "llvm/Support/MemoryBuffer.h"
28 /// Writer for instrumentation based profile data.
29 class InstrProfRecordWriterTrait
;
33 class InstrProfWriter
{
35 using ProfilingData
= SmallDenseMap
<uint64_t, InstrProfRecord
>;
36 // PF_IRLevelWithCS is the profile from context sensitive IR instrumentation.
37 enum ProfKind
{ PF_Unknown
= 0, PF_FE
, PF_IRLevel
, PF_IRLevelWithCS
};
41 StringMap
<ProfilingData
> FunctionData
;
42 ProfKind ProfileKind
= PF_Unknown
;
43 // Use raw pointer here for the incomplete type object.
44 InstrProfRecordWriterTrait
*InfoObj
;
47 InstrProfWriter(bool Sparse
= false);
50 /// Add function counts for the given function. If there are already counts
51 /// for this function and the hash and number of counts match, each counter is
52 /// summed. Optionally scale counts by \p Weight.
53 void addRecord(NamedInstrProfRecord
&&I
, uint64_t Weight
,
54 function_ref
<void(Error
)> Warn
);
55 void addRecord(NamedInstrProfRecord
&&I
, function_ref
<void(Error
)> Warn
) {
56 addRecord(std::move(I
), 1, Warn
);
59 /// Merge existing function counts from the given writer.
60 void mergeRecordsFromWriter(InstrProfWriter
&&IPW
,
61 function_ref
<void(Error
)> Warn
);
63 /// Write the profile to \c OS
64 void write(raw_fd_ostream
&OS
);
66 /// Write the profile in text format to \c OS
67 Error
writeText(raw_fd_ostream
&OS
);
69 /// Write \c Record in text format to \c OS
70 static void writeRecordInText(StringRef Name
, uint64_t Hash
,
71 const InstrProfRecord
&Counters
,
72 InstrProfSymtab
&Symtab
, raw_fd_ostream
&OS
);
74 /// Write the profile, returning the raw data. For testing.
75 std::unique_ptr
<MemoryBuffer
> writeBuffer();
77 /// Set the ProfileKind. Report error if mixing FE and IR level profiles.
78 /// \c WithCS indicates if this is for contenxt sensitive instrumentation.
79 Error
setIsIRLevelProfile(bool IsIRLevel
, bool WithCS
) {
80 if (ProfileKind
== PF_Unknown
) {
82 ProfileKind
= WithCS
? PF_IRLevelWithCS
: PF_IRLevel
;
85 return Error::success();
88 if (((ProfileKind
!= PF_FE
) && !IsIRLevel
) ||
89 ((ProfileKind
== PF_FE
) && IsIRLevel
))
90 return make_error
<InstrProfError
>(instrprof_error::unsupported_version
);
92 // When merging a context-sensitive profile (WithCS == true) with an IRLevel
93 // profile, set the kind to PF_IRLevelWithCS.
94 if (ProfileKind
== PF_IRLevel
&& WithCS
)
95 ProfileKind
= PF_IRLevelWithCS
;
97 return Error::success();
100 // Internal interface for testing purpose only.
101 void setValueProfDataEndianness(support::endianness Endianness
);
102 void setOutputSparse(bool Sparse
);
103 // Compute the overlap b/w this object and Other. Program level result is
104 // stored in Overlap and function level result is stored in FuncLevelOverlap.
105 void overlapRecord(NamedInstrProfRecord
&&Other
, OverlapStats
&Overlap
,
106 OverlapStats
&FuncLevelOverlap
,
107 const OverlapFuncFilters
&FuncFilter
);
110 void addRecord(StringRef Name
, uint64_t Hash
, InstrProfRecord
&&I
,
111 uint64_t Weight
, function_ref
<void(Error
)> Warn
);
112 bool shouldEncodeData(const ProfilingData
&PD
);
113 void writeImpl(ProfOStream
&OS
);
116 } // end namespace llvm
118 #endif // LLVM_PROFILEDATA_INSTRPROFWRITER_H