blob: a2021154df734b5eee1a110d8c53c0766c4e90f5 [file] [log] [blame]
Xinliang David Lidd12e9a2016-03-03 18:54:46 +00001/*===- InstrProfilingMerge.c - Profile in-process Merging ---------------===*\
2|*
3|* The LLVM Compiler Infrastructure
4|*
5|* This file is distributed under the University of Illinois Open Source
6|* License. See LICENSE.TXT for details.
7|*
8|*===----------------------------------------------------------------------===*
9|* This file defines the API needed for in-process merging of profile data
10|* stored in memory buffer.
11\*===---------------------------------------------------------------------===*/
12
13#include "InstrProfiling.h"
14#include "InstrProfilingInternal.h"
15#include "InstrProfilingUtil.h"
16
17#define INSTR_PROF_VALUE_PROF_DATA
18#include "InstrProfData.inc"
19
20COMPILER_RT_WEAK void (*VPMergeHook)(ValueProfData *,
21 __llvm_profile_data *) = NULL;
Xinliang David Lie2ce2e02016-06-08 23:43:56 +000022COMPILER_RT_VISIBILITY
23uint64_t lprofGetLoadModuleSignature() {
24 /* A very fast way to compute a module signature. */
25 uint64_t CounterSize = (uint64_t)(__llvm_profile_end_counters() -
26 __llvm_profile_begin_counters());
27 uint64_t DataSize = __llvm_profile_get_data_size(__llvm_profile_begin_data(),
28 __llvm_profile_end_data());
29 uint64_t NamesSize =
30 (uint64_t)(__llvm_profile_end_names() - __llvm_profile_begin_names());
31 uint64_t NumVnodes =
32 (uint64_t)(__llvm_profile_end_vnodes() - __llvm_profile_begin_vnodes());
33 const __llvm_profile_data *FirstD = __llvm_profile_begin_data();
34
35 return (NamesSize << 40) + (CounterSize << 30) + (DataSize << 20) +
36 (NumVnodes << 10) + (DataSize > 0 ? FirstD->NameRef : 0);
37}
Xinliang David Lidd12e9a2016-03-03 18:54:46 +000038
Xinliang David Li31f251f2016-03-04 18:58:30 +000039/* Returns 1 if profile is not structurally compatible. */
40COMPILER_RT_VISIBILITY
41int __llvm_profile_check_compatibility(const char *ProfileData,
42 uint64_t ProfileSize) {
43 /* Check profile header only for now */
44 __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
45 __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData;
46 SrcDataStart =
47 (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header));
48 SrcDataEnd = SrcDataStart + Header->DataSize;
49
Xinliang David Lie2ce2e02016-06-08 23:43:56 +000050 if (ProfileSize < sizeof(__llvm_profile_header))
51 return 1;
52
Xinliang David Li31f251f2016-03-04 18:58:30 +000053 /* Check the header first. */
54 if (Header->Magic != __llvm_profile_get_magic() ||
55 Header->Version != __llvm_profile_get_version() ||
56 Header->DataSize !=
Xinliang David Li5f58c272016-03-09 21:45:37 +000057 __llvm_profile_get_data_size(__llvm_profile_begin_data(),
58 __llvm_profile_end_data()) ||
Xinliang David Li31f251f2016-03-04 18:58:30 +000059 Header->CountersSize != (uint64_t)(__llvm_profile_end_counters() -
60 __llvm_profile_begin_counters()) ||
61 Header->NamesSize != (uint64_t)(__llvm_profile_end_names() -
62 __llvm_profile_begin_names()) ||
63 Header->ValueKindLast != IPVK_Last)
64 return 1;
65
66 if (ProfileSize < sizeof(__llvm_profile_header) +
67 Header->DataSize * sizeof(__llvm_profile_data) +
Xinliang David Liac96ea42016-05-06 02:13:12 +000068 Header->NamesSize + Header->CountersSize)
Xinliang David Li31f251f2016-03-04 18:58:30 +000069 return 1;
70
71 for (SrcData = SrcDataStart,
72 DstData = (__llvm_profile_data *)__llvm_profile_begin_data();
73 SrcData < SrcDataEnd; ++SrcData, ++DstData) {
74 if (SrcData->NameRef != DstData->NameRef ||
75 SrcData->FuncHash != DstData->FuncHash ||
76 SrcData->NumCounters != DstData->NumCounters)
77 return 1;
78 }
79
80 /* Matched! */
81 return 0;
82}
83
Xinliang David Li6534a8a2016-03-04 18:33:49 +000084COMPILER_RT_VISIBILITY
Xinliang David Lidd12e9a2016-03-03 18:54:46 +000085void __llvm_profile_merge_from_buffer(const char *ProfileData,
86 uint64_t ProfileSize) {
87 __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData;
88 __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
89 uint64_t *SrcCountersStart;
90 const char *SrcNameStart;
91 ValueProfData *SrcValueProfDataStart, *SrcValueProfData;
92
93 SrcDataStart =
94 (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header));
95 SrcDataEnd = SrcDataStart + Header->DataSize;
96 SrcCountersStart = (uint64_t *)SrcDataEnd;
97 SrcNameStart = (const char *)(SrcCountersStart + Header->CountersSize);
98 SrcValueProfDataStart =
99 (ValueProfData *)(SrcNameStart + Header->NamesSize +
100 __llvm_profile_get_num_padding_bytes(
101 Header->NamesSize));
102
103 for (SrcData = SrcDataStart,
104 DstData = (__llvm_profile_data *)__llvm_profile_begin_data(),
105 SrcValueProfData = SrcValueProfDataStart;
106 SrcData < SrcDataEnd; ++SrcData, ++DstData) {
107 uint64_t *SrcCounters;
108 uint64_t *DstCounters = (uint64_t *)DstData->CounterPtr;
109 unsigned I, NC, NVK = 0;
110
111 NC = SrcData->NumCounters;
112 SrcCounters = SrcCountersStart +
113 ((size_t)SrcData->CounterPtr - Header->CountersDelta) /
114 sizeof(uint64_t);
115 for (I = 0; I < NC; I++)
116 DstCounters[I] += SrcCounters[I];
117
118 /* Now merge value profile data. */
119 if (!VPMergeHook)
120 continue;
121
122 for (I = 0; I <= IPVK_Last; I++)
123 NVK += (SrcData->NumValueSites[I] != 0);
124
125 if (!NVK)
126 continue;
127
128 VPMergeHook(SrcValueProfData, DstData);
129 SrcValueProfData = (ValueProfData *)((char *)SrcValueProfData +
130 SrcValueProfData->TotalSize);
131 }
132}