1 /*===- InstrProfilingValue.c - Support library for PGO instrumentation ----===*\
3 |* The LLVM Compiler Infrastructure
5 |* This file is distributed under the University of Illinois Open Source
6 |* License. See LICENSE.TXT for details.
8 \*===----------------------------------------------------------------------===*/
10 #include "InstrProfiling.h"
11 #include "InstrProfilingInternal.h"
16 #define INSTR_PROF_VALUE_PROF_DATA
17 #define INSTR_PROF_COMMON_API_IMPL
18 #include "InstrProfData.inc"
20 #define PROF_OOM(Msg) PROF_ERR(Msg ":%s\n", "Out of memory");
21 #define PROF_OOM_RETURN(Msg) \
24 free(ValueDataArray); \
28 #if COMPILER_RT_HAS_ATOMICS != 1
29 COMPILER_RT_VISIBILITY
30 uint32_t BoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
40 /* This method is only used in value profiler mock testing. */
41 COMPILER_RT_VISIBILITY void
42 __llvm_profile_set_num_value_sites(__llvm_profile_data *Data,
43 uint32_t ValueKind, uint16_t NumValueSites) {
44 *((uint16_t *)&Data->NumValueSites[ValueKind]) = NumValueSites;
47 /* This method is only used in value profiler mock testing. */
48 COMPILER_RT_VISIBILITY const __llvm_profile_data *
49 __llvm_profile_iterate_data(const __llvm_profile_data *Data) {
53 /* This method is only used in value profiler mock testing. */
54 COMPILER_RT_VISIBILITY void *
55 __llvm_get_function_addr(const __llvm_profile_data *Data) {
56 return Data->FunctionPointer;
59 /* Allocate an array that holds the pointers to the linked lists of
60 * value profile counter nodes. The number of element of the array
61 * is the total number of value profile sites instrumented. Returns
62 * 0 if allocation fails.
65 static int allocateValueProfileCounters(__llvm_profile_data *Data) {
66 uint64_t NumVSites = 0;
68 for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI)
69 NumVSites += Data->NumValueSites[VKI];
72 (ValueProfNode **)calloc(NumVSites, sizeof(ValueProfNode *));
75 if (!COMPILER_RT_BOOL_CMPXCHG(&Data->Values, 0, Mem)) {
82 COMPILER_RT_VISIBILITY void
83 __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
84 uint32_t CounterIndex) {
86 __llvm_profile_data *PData = (__llvm_profile_data *)Data;
91 if (!allocateValueProfileCounters(PData))
95 ValueProfNode **ValueCounters = (ValueProfNode **)PData->Values;
96 ValueProfNode *PrevVNode = NULL;
97 ValueProfNode *CurrentVNode = ValueCounters[CounterIndex];
99 uint8_t VDataCount = 0;
100 while (CurrentVNode) {
101 if (TargetValue == CurrentVNode->VData.Value) {
102 CurrentVNode->VData.Count++;
105 PrevVNode = CurrentVNode;
106 CurrentVNode = CurrentVNode->Next;
110 if (VDataCount >= INSTR_PROF_MAX_NUM_VAL_PER_SITE)
113 CurrentVNode = (ValueProfNode *)calloc(1, sizeof(ValueProfNode));
117 CurrentVNode->VData.Value = TargetValue;
118 CurrentVNode->VData.Count++;
120 uint32_t Success = 0;
121 if (!ValueCounters[CounterIndex])
123 COMPILER_RT_BOOL_CMPXCHG(&ValueCounters[CounterIndex], 0, CurrentVNode);
124 else if (PrevVNode && !PrevVNode->Next)
125 Success = COMPILER_RT_BOOL_CMPXCHG(&(PrevVNode->Next), 0, CurrentVNode);
133 COMPILER_RT_VISIBILITY ValueProfData **
134 __llvm_profile_gather_value_data(uint64_t *ValueDataSize) {
136 __llvm_profile_data *I;
137 ValueProfData **ValueDataArray;
139 const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
140 const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
146 (ValueProfData **)calloc(DataEnd - DataBegin, sizeof(void *));
148 PROF_OOM_RETURN("Failed to write value profile data ");
151 * Compute the total Size of the buffer to hold ValueProfData
152 * structures for functions with value profile data.
154 for (I = (__llvm_profile_data *)DataBegin; I != DataEnd; ++I) {
155 ValueProfRuntimeRecord R;
156 if (initializeValueProfRuntimeRecord(&R, I->NumValueSites, I->Values))
157 PROF_OOM_RETURN("Failed to write value profile data ");
159 /* Compute the size of ValueProfData from this runtime record. */
160 if (getNumValueKindsRT(&R) != 0) {
161 ValueProfData *VD = NULL;
162 uint32_t VS = getValueProfDataSizeRT(&R);
163 VD = (ValueProfData *)calloc(VS, sizeof(uint8_t));
165 PROF_OOM_RETURN("Failed to write value profile data ");
166 serializeValueProfDataFromRT(&R, VD);
167 ValueDataArray[I - DataBegin] = VD;
170 finalizeValueProfRuntimeRecord(&R);
174 free(ValueDataArray);
175 ValueDataArray = NULL;
179 return ValueDataArray;