[LV] Add test showing debug output for loops with uncountable BTCs.
[llvm-project.git] / compiler-rt / include / profile / MemProfData.inc
blob3f785bd23fce3cd82573daacb22cdaf7bf8c024a
1 #ifndef MEMPROF_DATA_INC
2 #define MEMPROF_DATA_INC
3 /*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\
4 |*
5 |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6 |* See https://llvm.org/LICENSE.txt for license information.
7 |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 |*
9 \*===----------------------------------------------------------------------===*/
11  * This is the main file that defines all the data structure, signature,
12  * constant literals that are shared across profiling runtime library,
13  * and host tools (reader/writer).
14  *
15  * This file has two identical copies. The primary copy lives in LLVM and
16  * the other one sits in compiler-rt/include/profile directory. To make changes
17  * in this file, first modify the primary copy and copy it over to compiler-rt.
18  * Testing of any change in this file can start only after the two copies are
19  * synced up.
20  *
21 \*===----------------------------------------------------------------------===*/
22 #include <string.h>
24 #ifdef _MSC_VER
25 #define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
26 #else
27 #define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
28 #endif
30 // A 64-bit magic number to uniquely identify the raw binary memprof profile file.
31 #define MEMPROF_RAW_MAGIC_64                                                                        \
32   ((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 |          \
33    (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
35 // The version number of the raw binary format.
36 #define MEMPROF_RAW_VERSION 4ULL
38 // Currently supported versions.
39 #define MEMPROF_RAW_SUPPORTED_VERSIONS                                         \
40   { 3ULL, 4ULL }
42 #define MEMPROF_V3_MIB_SIZE 132ULL;
44 #define MEMPROF_BUILDID_MAX_SIZE 32ULL
46 namespace llvm {
47 namespace memprof {
48 // A struct describing the header used for the raw binary memprof profile format.
49 PACKED(struct Header {
50   uint64_t Magic;
51   uint64_t Version;
52   uint64_t TotalSize;
53   uint64_t SegmentOffset;
54   uint64_t MIBOffset;
55   uint64_t StackOffset;
56 });
58 // A struct describing the information necessary to describe a /proc/maps
59 // segment entry for a particular binary/library identified by its build id.
60 PACKED(struct SegmentEntry {
61   uint64_t Start;
62   uint64_t End;
63   uint64_t Offset;
64   uint64_t BuildIdSize;
65   uint8_t BuildId[MEMPROF_BUILDID_MAX_SIZE] = {0};
67   // This constructor is only used in tests so don't set the BuildId.
68   SegmentEntry(uint64_t S, uint64_t E, uint64_t O)
69       : Start(S), End(E), Offset(O), BuildIdSize(0) {}
71   SegmentEntry(const SegmentEntry& S) {
72     Start = S.Start;
73     End = S.End;
74     Offset = S.Offset;
75     BuildIdSize = S.BuildIdSize;
76     memcpy(BuildId, S.BuildId, S.BuildIdSize);
77   }
79   SegmentEntry& operator=(const SegmentEntry& S) {
80     Start = S.Start;
81     End = S.End;
82     Offset = S.Offset;
83     BuildIdSize = S.BuildIdSize;
84     memcpy(BuildId, S.BuildId, S.BuildIdSize);
85     return *this;
86   }
88   bool operator==(const SegmentEntry& S) const {
89     return Start == S.Start && End == S.End && Offset == S.Offset &&
90            BuildIdSize == S.BuildIdSize &&
91            memcmp(BuildId, S.BuildId, S.BuildIdSize) == 0;
92   }
93 });
95 // Packed struct definition for MSVC. We can't use the PACKED macro defined in
96 // MemProfData.inc since it would mean we are embedding a directive (the
97 // #include for MIBEntryDef) into the macros which is undefined behaviour.
98 #ifdef _MSC_VER
99 __pragma(pack(push,1))
100 #endif
102 // A struct representing the heap allocation characteristics of a particular
103 // runtime context. This struct is shared between the compiler-rt runtime and
104 // the raw profile reader. The indexed format uses a separate, self-describing
105 // backwards compatible format.
106 struct MemInfoBlock{
108 #define MIBEntryDef(NameTag, Name, Type) Type Name;
109 #include "MIBEntryDef.inc"
110 #undef MIBEntryDef
112 bool operator==(const MemInfoBlock& Other) const {
113   bool IsEqual = true;
114 #define MIBEntryDef(NameTag, Name, Type) \
115   IsEqual = (IsEqual && Name == Other.Name);
116 #include "MIBEntryDef.inc"
117 #undef MIBEntryDef
118   return IsEqual;
121 MemInfoBlock() {
122 #define MIBEntryDef(NameTag, Name, Type) Name = Type();
123 #include "MIBEntryDef.inc"
124 #undef MIBEntryDef
127 MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
128              uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu,
129              uintptr_t Histogram, uint32_t HistogramSize)
130     : MemInfoBlock() {
131   AllocCount = 1U;
132   TotalAccessCount = AccessCount;
133   MinAccessCount = AccessCount;
134   MaxAccessCount = AccessCount;
135   TotalSize = Size;
136   MinSize = Size;
137   MaxSize = Size;
138   AllocTimestamp = AllocTs;
139   DeallocTimestamp = DeallocTs;
140   TotalLifetime = DeallocTimestamp - AllocTimestamp;
141   MinLifetime = TotalLifetime;
142   MaxLifetime = TotalLifetime;
143   // Access density is accesses per byte. Multiply by 100 to include the
144   // fractional part.
145   TotalAccessDensity = AccessCount * 100 / Size;
146   MinAccessDensity = TotalAccessDensity;
147   MaxAccessDensity = TotalAccessDensity;
148   // Lifetime access density is the access density per second of lifetime.
149   // Multiply by 1000 to convert denominator lifetime to seconds (using a
150   // minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first
151   // to reduce truncations to 0.
152   TotalLifetimeAccessDensity =
153       TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1);
154   MinLifetimeAccessDensity = TotalLifetimeAccessDensity;
155   MaxLifetimeAccessDensity = TotalLifetimeAccessDensity;
156   AllocCpuId = AllocCpu;
157   DeallocCpuId = DeallocCpu;
158   NumMigratedCpu = AllocCpuId != DeallocCpuId;
159   AccessHistogramSize = HistogramSize;
160   AccessHistogram = Histogram;
163 void Merge(const MemInfoBlock &newMIB) {
164   AllocCount += newMIB.AllocCount;
166   TotalAccessCount += newMIB.TotalAccessCount;
167   MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
168   MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
170   TotalSize += newMIB.TotalSize;
171   MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
172   MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
174   TotalLifetime += newMIB.TotalLifetime;
175   MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
176   MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
178   TotalAccessDensity += newMIB.TotalAccessDensity;
179   MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
180                          ? newMIB.MinAccessDensity
181                          : MinAccessDensity;
182   MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
183                          ? newMIB.MaxAccessDensity
184                          : MaxAccessDensity;
186   TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity;
187   MinLifetimeAccessDensity =
188       newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity
189           ? newMIB.MinLifetimeAccessDensity
190           : MinLifetimeAccessDensity;
191   MaxLifetimeAccessDensity =
192       newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity
193           ? newMIB.MaxLifetimeAccessDensity
194           : MaxLifetimeAccessDensity;
196   // We know newMIB was deallocated later, so just need to check if it was
197   // allocated before last one deallocated.
198   NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
199   AllocTimestamp = newMIB.AllocTimestamp;
200   DeallocTimestamp = newMIB.DeallocTimestamp;
202   NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId;
203   NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId;
204   AllocCpuId = newMIB.AllocCpuId;
205   DeallocCpuId = newMIB.DeallocCpuId;
207   // For merging histograms, we always keep the longer histogram, and add
208   // values of shorter histogram to larger one.
209   uintptr_t ShorterHistogram;
210   uint32_t ShorterHistogramSize;
211   if (newMIB.AccessHistogramSize > AccessHistogramSize) {
212     ShorterHistogram = AccessHistogram;
213     ShorterHistogramSize = AccessHistogramSize;
214     // Swap histogram of current to larger histogram
215     AccessHistogram = newMIB.AccessHistogram;
216     AccessHistogramSize = newMIB.AccessHistogramSize;
217   } else {
218     ShorterHistogram = newMIB.AccessHistogram;
219     ShorterHistogramSize = newMIB.AccessHistogramSize;
220   }
221   for (size_t i = 0; i < ShorterHistogramSize; ++i) {
222     ((uint64_t *)AccessHistogram)[i] += ((uint64_t *)ShorterHistogram)[i];
223   }
226 #ifdef _MSC_VER
227 } __pragma(pack(pop));
228 #else
229 } __attribute__((__packed__));
230 #endif
232 } // namespace memprof
233 } // namespace llvm
235 #endif