2014-03-20 06:10:27 +08:00
|
|
|
/*===- InstrProfiling.c - Support library for PGO instrumentation ---------===*\
|
|
|
|
|*
|
|
|
|
|* The LLVM Compiler Infrastructure
|
|
|
|
|*
|
|
|
|
|* This file is distributed under the University of Illinois Open Source
|
|
|
|
|* License. See LICENSE.TXT for details.
|
|
|
|
|*
|
|
|
|
\*===----------------------------------------------------------------------===*/
|
|
|
|
|
|
|
|
#include "InstrProfiling.h"
|
2015-11-19 02:12:35 +08:00
|
|
|
#include <limits.h>
|
|
|
|
#include <stdlib.h>
|
2014-03-21 03:44:31 +08:00
|
|
|
#include <string.h>
|
2014-03-20 06:10:27 +08:00
|
|
|
|
2014-05-16 09:30:24 +08:00
|
|
|
__attribute__((visibility("hidden")))
|
2014-03-22 02:29:15 +08:00
|
|
|
uint64_t __llvm_profile_get_magic(void) {
|
2014-03-22 04:42:40 +08:00
|
|
|
/* Magic number to detect file format and endianness.
|
|
|
|
*
|
|
|
|
* Use 255 at one end, since no UTF-8 file can use that character. Avoid 0,
|
2014-03-23 11:38:05 +08:00
|
|
|
* so that utilities, like strings, don't grab it as a string. 129 is also
|
|
|
|
* invalid UTF-8, and high enough to be interesting.
|
2014-03-22 04:42:40 +08:00
|
|
|
*
|
2014-03-23 11:38:05 +08:00
|
|
|
* Use "lprofr" in the centre to stand for "LLVM Profile Raw", or "lprofR"
|
|
|
|
* for 32-bit platforms.
|
2014-03-22 04:42:40 +08:00
|
|
|
*/
|
2014-03-23 11:38:05 +08:00
|
|
|
unsigned char R = sizeof(void *) == sizeof(uint64_t) ? 'r' : 'R';
|
2014-03-22 02:25:56 +08:00
|
|
|
return
|
2014-03-22 04:42:40 +08:00
|
|
|
(uint64_t)255 << 56 |
|
|
|
|
(uint64_t)'l' << 48 |
|
|
|
|
(uint64_t)'p' << 40 |
|
|
|
|
(uint64_t)'r' << 32 |
|
|
|
|
(uint64_t)'o' << 24 |
|
|
|
|
(uint64_t)'f' << 16 |
|
2014-03-23 11:38:05 +08:00
|
|
|
(uint64_t) R << 8 |
|
2014-03-22 04:42:40 +08:00
|
|
|
(uint64_t)129;
|
2014-03-22 02:25:56 +08:00
|
|
|
}
|
2014-03-21 08:27:50 +08:00
|
|
|
|
2015-11-19 02:12:35 +08:00
|
|
|
__attribute__((visibility("hidden")))
|
|
|
|
uint8_t __llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes) {
|
|
|
|
return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
|
|
|
|
}
|
|
|
|
|
2014-05-16 09:30:24 +08:00
|
|
|
__attribute__((visibility("hidden")))
|
2014-03-22 02:29:15 +08:00
|
|
|
uint64_t __llvm_profile_get_version(void) {
|
|
|
|
/* This should be bumped any time the output format changes. */
|
2015-11-19 02:12:35 +08:00
|
|
|
return 2;
|
2014-03-20 06:10:27 +08:00
|
|
|
}
|
|
|
|
|
2014-05-16 09:30:24 +08:00
|
|
|
__attribute__((visibility("hidden")))
|
2014-03-21 04:00:44 +08:00
|
|
|
void __llvm_profile_reset_counters(void) {
|
2014-09-04 23:45:31 +08:00
|
|
|
uint64_t *I = __llvm_profile_begin_counters();
|
|
|
|
uint64_t *E = __llvm_profile_end_counters();
|
2014-03-21 03:44:31 +08:00
|
|
|
|
|
|
|
memset(I, 0, sizeof(uint64_t)*(E - I));
|
2015-11-19 02:12:35 +08:00
|
|
|
|
|
|
|
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
|
|
|
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
2015-11-19 04:20:15 +08:00
|
|
|
const __llvm_profile_data *DI;
|
|
|
|
for (DI = DataBegin; DI != DataEnd; ++DI) {
|
|
|
|
uint64_t CurrentVSiteCount = 0;
|
|
|
|
uint32_t VKI, i;
|
2015-11-19 02:12:35 +08:00
|
|
|
if (!DI->ValueCounters)
|
|
|
|
continue;
|
|
|
|
|
2015-11-19 04:20:15 +08:00
|
|
|
for (VKI = VK_FIRST; VKI <= VK_LAST; ++VKI)
|
2015-11-19 02:12:35 +08:00
|
|
|
CurrentVSiteCount += DI->NumValueSites[VKI];
|
|
|
|
|
2015-11-19 04:20:15 +08:00
|
|
|
for (i = 0; i < CurrentVSiteCount; ++i) {
|
2015-11-19 02:12:35 +08:00
|
|
|
__llvm_profile_value_node *CurrentVNode = DI->ValueCounters[i];
|
|
|
|
|
|
|
|
while (CurrentVNode) {
|
|
|
|
CurrentVNode->VData.NumTaken = 0;
|
|
|
|
CurrentVNode = CurrentVNode->Next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64_t TotalValueDataSize = 0;
|
|
|
|
|
|
|
|
__attribute__((visibility("hidden")))
|
|
|
|
void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data_,
|
|
|
|
uint32_t CounterIndex) {
|
|
|
|
|
|
|
|
__llvm_profile_data *Data = (__llvm_profile_data*)Data_;
|
|
|
|
if (!Data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!Data->ValueCounters) {
|
|
|
|
uint64_t NumVSites = 0;
|
2015-11-19 04:20:15 +08:00
|
|
|
uint32_t VKI;
|
|
|
|
for (VKI = VK_FIRST; VKI <= VK_LAST; ++VKI)
|
2015-11-19 02:12:35 +08:00
|
|
|
NumVSites += Data->NumValueSites[VKI];
|
|
|
|
|
|
|
|
__llvm_profile_value_node** Mem = (__llvm_profile_value_node**)
|
|
|
|
calloc(NumVSites, sizeof(__llvm_profile_value_node*));
|
|
|
|
if (!Mem)
|
|
|
|
return;
|
|
|
|
if (!__sync_bool_compare_and_swap(&Data->ValueCounters, 0, Mem)) {
|
|
|
|
free(Mem);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Acccount for padding during write out.
|
|
|
|
uint8_t Padding = __llvm_profile_get_num_padding_bytes(NumVSites);
|
|
|
|
__sync_fetch_and_add(&TotalValueDataSize, NumVSites + Padding);
|
|
|
|
}
|
|
|
|
|
|
|
|
__llvm_profile_value_node *PrevVNode = NULL;
|
|
|
|
__llvm_profile_value_node *CurrentVNode = Data->ValueCounters[CounterIndex];
|
|
|
|
|
|
|
|
uint8_t VDataCount = 0;
|
|
|
|
while (CurrentVNode) {
|
|
|
|
if (TargetValue == CurrentVNode->VData.TargetValue) {
|
|
|
|
CurrentVNode->VData.NumTaken++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PrevVNode = CurrentVNode;
|
|
|
|
CurrentVNode = CurrentVNode->Next;
|
|
|
|
++VDataCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VDataCount >= UCHAR_MAX)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CurrentVNode = (__llvm_profile_value_node*)
|
|
|
|
calloc(1, sizeof(__llvm_profile_value_node));
|
|
|
|
if (!CurrentVNode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CurrentVNode->VData.TargetValue = TargetValue;
|
|
|
|
CurrentVNode->VData.NumTaken++;
|
|
|
|
|
|
|
|
uint32_t Success = 0;
|
|
|
|
if (!Data->ValueCounters[CounterIndex])
|
|
|
|
Success = __sync_bool_compare_and_swap(
|
|
|
|
&(Data->ValueCounters[CounterIndex]), 0, CurrentVNode);
|
|
|
|
else if (PrevVNode && !PrevVNode->Next)
|
|
|
|
Success = __sync_bool_compare_and_swap(&(PrevVNode->Next), 0, CurrentVNode);
|
|
|
|
|
|
|
|
if (!Success) {
|
|
|
|
free(CurrentVNode);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
__sync_fetch_and_add(&TotalValueDataSize,
|
|
|
|
Success * sizeof(__llvm_profile_value_data));
|
|
|
|
}
|
|
|
|
|
|
|
|
__attribute__((visibility("hidden")))
|
|
|
|
uint64_t __llvm_profile_gather_value_data(uint8_t **VDataArray) {
|
|
|
|
|
|
|
|
if (!VDataArray || 0 == TotalValueDataSize)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
uint64_t NumData = TotalValueDataSize;
|
|
|
|
*VDataArray = (uint8_t*) calloc(NumData, sizeof(uint8_t));
|
|
|
|
if (!*VDataArray)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
uint8_t *VDataEnd = *VDataArray + NumData;
|
|
|
|
uint8_t *PerSiteCountsHead = *VDataArray;
|
|
|
|
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
|
|
|
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
2015-11-19 04:20:15 +08:00
|
|
|
__llvm_profile_data *I;
|
|
|
|
for (I = (__llvm_profile_data *)DataBegin;
|
2015-11-19 02:12:35 +08:00
|
|
|
I != DataEnd; ++I) {
|
|
|
|
|
2015-11-19 04:20:15 +08:00
|
|
|
uint64_t NumVSites = 0;
|
|
|
|
uint32_t VKI, i;
|
|
|
|
|
2015-11-19 02:12:35 +08:00
|
|
|
if (!I->ValueCounters)
|
|
|
|
continue;
|
|
|
|
|
2015-11-19 04:20:15 +08:00
|
|
|
for (VKI = VK_FIRST; VKI <= VK_LAST; ++VKI)
|
2015-11-19 02:12:35 +08:00
|
|
|
NumVSites += I->NumValueSites[VKI];
|
|
|
|
uint8_t Padding = __llvm_profile_get_num_padding_bytes(NumVSites);
|
|
|
|
|
|
|
|
uint8_t *PerSiteCountPtr = PerSiteCountsHead;
|
|
|
|
__llvm_profile_value_data *VDataPtr =
|
|
|
|
(__llvm_profile_value_data *)(PerSiteCountPtr + NumVSites + Padding);
|
|
|
|
|
2015-11-19 04:20:15 +08:00
|
|
|
for (i = 0; i < NumVSites; ++i) {
|
2015-11-19 02:12:35 +08:00
|
|
|
|
|
|
|
__llvm_profile_value_node *VNode = I->ValueCounters[i];
|
|
|
|
|
|
|
|
uint8_t VDataCount = 0;
|
|
|
|
while (VNode && ((uint8_t*)(VDataPtr + 1) <= VDataEnd)) {
|
|
|
|
*VDataPtr = VNode->VData;
|
|
|
|
VNode = VNode->Next;
|
|
|
|
++VDataPtr;
|
|
|
|
if (++VDataCount == UCHAR_MAX)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*PerSiteCountPtr = VDataCount;
|
|
|
|
++PerSiteCountPtr;
|
|
|
|
}
|
|
|
|
I->ValueCounters = (void *)PerSiteCountsHead;
|
|
|
|
PerSiteCountsHead = (uint8_t *)VDataPtr;
|
|
|
|
}
|
|
|
|
return PerSiteCountsHead - *VDataArray;
|
2014-03-21 03:44:31 +08:00
|
|
|
}
|