diff options
| -rw-r--r-- | compiler-rt/lib/profile/InstrProfiling.c | 102 | ||||
| -rw-r--r-- | compiler-rt/lib/profile/InstrProfiling.h | 6 |
2 files changed, 61 insertions, 47 deletions
diff --git a/compiler-rt/lib/profile/InstrProfiling.c b/compiler-rt/lib/profile/InstrProfiling.c index ec9b8ef39dd..cc86370427a 100644 --- a/compiler-rt/lib/profile/InstrProfiling.c +++ b/compiler-rt/lib/profile/InstrProfiling.c @@ -12,8 +12,7 @@ #include <stdlib.h> #include <string.h> -__attribute__((visibility("hidden"))) -uint64_t __llvm_profile_get_magic(void) { +__attribute__((visibility("hidden"))) uint64_t __llvm_profile_get_magic(void) { /* Magic number to detect file format and endianness. * * Use 255 at one end, since no UTF-8 file can use that character. Avoid 0, @@ -24,34 +23,29 @@ uint64_t __llvm_profile_get_magic(void) { * for 32-bit platforms. */ unsigned char R = sizeof(void *) == sizeof(uint64_t) ? 'r' : 'R'; - return - (uint64_t)255 << 56 | - (uint64_t)'l' << 48 | - (uint64_t)'p' << 40 | - (uint64_t)'r' << 32 | - (uint64_t)'o' << 24 | - (uint64_t)'f' << 16 | - (uint64_t) R << 8 | - (uint64_t)129; + return (uint64_t)255 << 56 | (uint64_t)'l' << 48 | (uint64_t)'p' << 40 | + (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | + (uint64_t)R << 8 | (uint64_t)129; } -__attribute__((visibility("hidden"))) -uint8_t __llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes) { +/* Return the number of bytes needed to add to SizeInBytes to make it + the result a multiple of 8. */ +__attribute__((visibility("hidden"))) uint8_t +__llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes) { return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); } -__attribute__((visibility("hidden"))) -uint64_t __llvm_profile_get_version(void) { +__attribute__((visibility("hidden"))) uint64_t +__llvm_profile_get_version(void) { /* This should be bumped any time the output format changes. */ return 2; } -__attribute__((visibility("hidden"))) -void __llvm_profile_reset_counters(void) { +__attribute__((visibility("hidden"))) void __llvm_profile_reset_counters(void) { uint64_t *I = __llvm_profile_begin_counters(); uint64_t *E = __llvm_profile_end_counters(); - memset(I, 0, sizeof(uint64_t)*(E - I)); + memset(I, 0, sizeof(uint64_t) * (E - I)); const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); @@ -76,33 +70,48 @@ void __llvm_profile_reset_counters(void) { } } +// Total number of value profile data in bytes. static uint64_t TotalValueDataSize = 0; -__attribute__((visibility("hidden"))) -void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data_, - uint32_t CounterIndex) { +/* Allocate an array that holds the pointers to the linked lists of + value profile counter nodes. The number of element of the array + is the total number of value profile sites instrumented. Returns + 0 if allocation fails. */ - __llvm_profile_data *Data = (__llvm_profile_data*)Data_; +static int allocateValueProfileCounters(__llvm_profile_data *Data) { + uint64_t NumVSites = 0; + uint32_t VKI; + for (VKI = VK_FIRST; VKI <= VK_LAST; ++VKI) + NumVSites += Data->NumValueSites[VKI]; + + __llvm_profile_value_node **Mem = (__llvm_profile_value_node **)calloc( + NumVSites, sizeof(__llvm_profile_value_node *)); + if (!Mem) + return 0; + if (!__sync_bool_compare_and_swap(&Data->ValueCounters, 0, Mem)) { + free(Mem); + return 0; + } + /* In the raw format, there will be an value count array preceding + the value profile data. The element type of the array is uint8_t, + and there is one element in array per value site. The element + stores the number of values profiled for the corresponding site. */ + uint8_t Padding = __llvm_profile_get_num_padding_bytes(NumVSites); + __sync_fetch_and_add(&TotalValueDataSize, NumVSites + Padding); + return 1; +} + +__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; - uint32_t VKI; - for (VKI = VK_FIRST; VKI <= VK_LAST; ++VKI) - NumVSites += Data->NumValueSites[VKI]; - - __llvm_profile_value_node** Mem = (__llvm_profile_value_node**) - calloc(NumVSites, sizeof(__llvm_profile_value_node*)); - if (!Mem) + if (!allocateValueProfileCounters(Data)) 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; @@ -122,8 +131,8 @@ void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data_, if (VDataCount >= UCHAR_MAX) return; - CurrentVNode = (__llvm_profile_value_node*) - calloc(1, sizeof(__llvm_profile_value_node)); + CurrentVNode = + (__llvm_profile_value_node *)calloc(1, sizeof(__llvm_profile_value_node)); if (!CurrentVNode) return; @@ -132,8 +141,8 @@ void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data_, uint32_t Success = 0; if (!Data->ValueCounters[CounterIndex]) - Success = __sync_bool_compare_and_swap( - &(Data->ValueCounters[CounterIndex]), 0, CurrentVNode); + 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); @@ -145,14 +154,14 @@ void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data_, Success * sizeof(__llvm_profile_value_data)); } -__attribute__((visibility("hidden"))) -uint64_t __llvm_profile_gather_value_data(uint8_t **VDataArray) { +__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)); + *VDataArray = (uint8_t *)calloc(NumData, sizeof(uint8_t)); if (!*VDataArray) return 0; @@ -161,8 +170,7 @@ uint64_t __llvm_profile_gather_value_data(uint8_t **VDataArray) { const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); __llvm_profile_data *I; - for (I = (__llvm_profile_data *)DataBegin; - I != DataEnd; ++I) { + for (I = (__llvm_profile_data *)DataBegin; I != DataEnd; ++I) { uint64_t NumVSites = 0; uint32_t VKI, i; @@ -183,7 +191,7 @@ uint64_t __llvm_profile_gather_value_data(uint8_t **VDataArray) { __llvm_profile_value_node *VNode = I->ValueCounters[i]; uint8_t VDataCount = 0; - while (VNode && ((uint8_t*)(VDataPtr + 1) <= VDataEnd)) { + while (VNode && ((uint8_t *)(VDataPtr + 1) <= VDataEnd)) { *VDataPtr = VNode->VData; VNode = VNode->Next; ++VDataPtr; diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h index d709282fccb..99c22aff6a8 100644 --- a/compiler-rt/lib/profile/InstrProfiling.h +++ b/compiler-rt/lib/profile/InstrProfiling.h @@ -100,6 +100,12 @@ uint64_t *__llvm_profile_begin_counters(void); uint64_t *__llvm_profile_end_counters(void); /*! + * \brief Clear profile counters to zero. + * + */ +void __llvm_profile_reset_counters(void); + +/*! * \brief Counts the number of times a target value is seen. * * Records the target value for the CounterIndex if not seen before. Otherwise, |

