Xinliang David Li | dd12e9a | 2016-03-03 18:54:46 +0000 | [diff] [blame] | 1 | /*===- 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 | |
| 20 | COMPILER_RT_WEAK void (*VPMergeHook)(ValueProfData *, |
| 21 | __llvm_profile_data *) = NULL; |
Xinliang David Li | e2ce2e0 | 2016-06-08 23:43:56 +0000 | [diff] [blame] | 22 | COMPILER_RT_VISIBILITY |
| 23 | uint64_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 Li | dd12e9a | 2016-03-03 18:54:46 +0000 | [diff] [blame] | 38 | |
Xinliang David Li | 31f251f | 2016-03-04 18:58:30 +0000 | [diff] [blame] | 39 | /* Returns 1 if profile is not structurally compatible. */ |
| 40 | COMPILER_RT_VISIBILITY |
| 41 | int __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 Li | e2ce2e0 | 2016-06-08 23:43:56 +0000 | [diff] [blame] | 50 | if (ProfileSize < sizeof(__llvm_profile_header)) |
| 51 | return 1; |
| 52 | |
Xinliang David Li | 31f251f | 2016-03-04 18:58:30 +0000 | [diff] [blame] | 53 | /* Check the header first. */ |
| 54 | if (Header->Magic != __llvm_profile_get_magic() || |
| 55 | Header->Version != __llvm_profile_get_version() || |
| 56 | Header->DataSize != |
Xinliang David Li | 5f58c27 | 2016-03-09 21:45:37 +0000 | [diff] [blame] | 57 | __llvm_profile_get_data_size(__llvm_profile_begin_data(), |
| 58 | __llvm_profile_end_data()) || |
Xinliang David Li | 31f251f | 2016-03-04 18:58:30 +0000 | [diff] [blame] | 59 | 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 Li | ac96ea4 | 2016-05-06 02:13:12 +0000 | [diff] [blame] | 68 | Header->NamesSize + Header->CountersSize) |
Xinliang David Li | 31f251f | 2016-03-04 18:58:30 +0000 | [diff] [blame] | 69 | 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 Li | 6534a8a | 2016-03-04 18:33:49 +0000 | [diff] [blame] | 84 | COMPILER_RT_VISIBILITY |
Xinliang David Li | dd12e9a | 2016-03-03 18:54:46 +0000 | [diff] [blame] | 85 | void __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 | } |