Home | History | Annotate | Download | only in profile
      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;
     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 }
     38 
     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 
     50   if (ProfileSize < sizeof(__llvm_profile_header))
     51     return 1;
     52 
     53   /* Check the header first.  */
     54   if (Header->Magic != __llvm_profile_get_magic() ||
     55       Header->Version != __llvm_profile_get_version() ||
     56       Header->DataSize !=
     57           __llvm_profile_get_data_size(__llvm_profile_begin_data(),
     58                                        __llvm_profile_end_data()) ||
     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) +
     68                         Header->NamesSize + Header->CountersSize)
     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 
     84 COMPILER_RT_VISIBILITY
     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 }
    133