1303235Sdim/*===- InstrProfilingMerge.c - Profile in-process Merging ---------------===*\ 2303235Sdim|* 3353358Sdim|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim|* See https://llvm.org/LICENSE.txt for license information. 5353358Sdim|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303235Sdim|* 7303235Sdim|*===----------------------------------------------------------------------===* 8303235Sdim|* This file defines the API needed for in-process merging of profile data 9303235Sdim|* stored in memory buffer. 10303235Sdim\*===---------------------------------------------------------------------===*/ 11303235Sdim 12303235Sdim#include "InstrProfiling.h" 13303235Sdim#include "InstrProfilingInternal.h" 14303235Sdim#include "InstrProfilingUtil.h" 15303235Sdim 16303235Sdim#define INSTR_PROF_VALUE_PROF_DATA 17360784Sdim#include "profile/InstrProfData.inc" 18303235Sdim 19303235SdimCOMPILER_RT_VISIBILITY 20341825Sdimvoid (*VPMergeHook)(ValueProfData *, __llvm_profile_data *); 21341825Sdim 22341825SdimCOMPILER_RT_VISIBILITY 23303235Sdimuint64_t lprofGetLoadModuleSignature() { 24303235Sdim /* A very fast way to compute a module signature. */ 25303235Sdim uint64_t CounterSize = (uint64_t)(__llvm_profile_end_counters() - 26303235Sdim __llvm_profile_begin_counters()); 27303235Sdim uint64_t DataSize = __llvm_profile_get_data_size(__llvm_profile_begin_data(), 28303235Sdim __llvm_profile_end_data()); 29303235Sdim uint64_t NamesSize = 30303235Sdim (uint64_t)(__llvm_profile_end_names() - __llvm_profile_begin_names()); 31303235Sdim uint64_t NumVnodes = 32303235Sdim (uint64_t)(__llvm_profile_end_vnodes() - __llvm_profile_begin_vnodes()); 33303235Sdim const __llvm_profile_data *FirstD = __llvm_profile_begin_data(); 34303235Sdim 35303235Sdim return (NamesSize << 40) + (CounterSize << 30) + (DataSize << 20) + 36303235Sdim (NumVnodes << 10) + (DataSize > 0 ? FirstD->NameRef : 0); 37303235Sdim} 38303235Sdim 39303235Sdim/* Returns 1 if profile is not structurally compatible. */ 40303235SdimCOMPILER_RT_VISIBILITY 41303235Sdimint __llvm_profile_check_compatibility(const char *ProfileData, 42303235Sdim uint64_t ProfileSize) { 43303235Sdim /* Check profile header only for now */ 44303235Sdim __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; 45303235Sdim __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; 46303235Sdim SrcDataStart = 47303235Sdim (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); 48303235Sdim SrcDataEnd = SrcDataStart + Header->DataSize; 49303235Sdim 50303235Sdim if (ProfileSize < sizeof(__llvm_profile_header)) 51303235Sdim return 1; 52303235Sdim 53303235Sdim /* Check the header first. */ 54303235Sdim if (Header->Magic != __llvm_profile_get_magic() || 55303235Sdim Header->Version != __llvm_profile_get_version() || 56303235Sdim Header->DataSize != 57303235Sdim __llvm_profile_get_data_size(__llvm_profile_begin_data(), 58303235Sdim __llvm_profile_end_data()) || 59303235Sdim Header->CountersSize != (uint64_t)(__llvm_profile_end_counters() - 60303235Sdim __llvm_profile_begin_counters()) || 61303235Sdim Header->NamesSize != (uint64_t)(__llvm_profile_end_names() - 62303235Sdim __llvm_profile_begin_names()) || 63303235Sdim Header->ValueKindLast != IPVK_Last) 64303235Sdim return 1; 65303235Sdim 66303235Sdim if (ProfileSize < sizeof(__llvm_profile_header) + 67303235Sdim Header->DataSize * sizeof(__llvm_profile_data) + 68303235Sdim Header->NamesSize + Header->CountersSize) 69303235Sdim return 1; 70303235Sdim 71303235Sdim for (SrcData = SrcDataStart, 72303235Sdim DstData = (__llvm_profile_data *)__llvm_profile_begin_data(); 73303235Sdim SrcData < SrcDataEnd; ++SrcData, ++DstData) { 74303235Sdim if (SrcData->NameRef != DstData->NameRef || 75303235Sdim SrcData->FuncHash != DstData->FuncHash || 76303235Sdim SrcData->NumCounters != DstData->NumCounters) 77303235Sdim return 1; 78303235Sdim } 79303235Sdim 80303235Sdim /* Matched! */ 81303235Sdim return 0; 82303235Sdim} 83303235Sdim 84303235SdimCOMPILER_RT_VISIBILITY 85303235Sdimvoid __llvm_profile_merge_from_buffer(const char *ProfileData, 86303235Sdim uint64_t ProfileSize) { 87303235Sdim __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; 88303235Sdim __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; 89303235Sdim uint64_t *SrcCountersStart; 90303235Sdim const char *SrcNameStart; 91303235Sdim ValueProfData *SrcValueProfDataStart, *SrcValueProfData; 92303235Sdim 93303235Sdim SrcDataStart = 94303235Sdim (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); 95303235Sdim SrcDataEnd = SrcDataStart + Header->DataSize; 96303235Sdim SrcCountersStart = (uint64_t *)SrcDataEnd; 97303235Sdim SrcNameStart = (const char *)(SrcCountersStart + Header->CountersSize); 98303235Sdim SrcValueProfDataStart = 99303235Sdim (ValueProfData *)(SrcNameStart + Header->NamesSize + 100303235Sdim __llvm_profile_get_num_padding_bytes( 101303235Sdim Header->NamesSize)); 102303235Sdim 103303235Sdim for (SrcData = SrcDataStart, 104303235Sdim DstData = (__llvm_profile_data *)__llvm_profile_begin_data(), 105303235Sdim SrcValueProfData = SrcValueProfDataStart; 106303235Sdim SrcData < SrcDataEnd; ++SrcData, ++DstData) { 107303235Sdim uint64_t *SrcCounters; 108303235Sdim uint64_t *DstCounters = (uint64_t *)DstData->CounterPtr; 109303235Sdim unsigned I, NC, NVK = 0; 110303235Sdim 111303235Sdim NC = SrcData->NumCounters; 112303235Sdim SrcCounters = SrcCountersStart + 113303235Sdim ((size_t)SrcData->CounterPtr - Header->CountersDelta) / 114303235Sdim sizeof(uint64_t); 115303235Sdim for (I = 0; I < NC; I++) 116303235Sdim DstCounters[I] += SrcCounters[I]; 117303235Sdim 118303235Sdim /* Now merge value profile data. */ 119303235Sdim if (!VPMergeHook) 120303235Sdim continue; 121303235Sdim 122303235Sdim for (I = 0; I <= IPVK_Last; I++) 123303235Sdim NVK += (SrcData->NumValueSites[I] != 0); 124303235Sdim 125303235Sdim if (!NVK) 126303235Sdim continue; 127303235Sdim 128303235Sdim VPMergeHook(SrcValueProfData, DstData); 129303235Sdim SrcValueProfData = (ValueProfData *)((char *)SrcValueProfData + 130303235Sdim SrcValueProfData->TotalSize); 131303235Sdim } 132303235Sdim} 133