forked from OSchip/llvm-project
[PGO] Add API to check compatibility of profile data in buffer
This is needed by client which uses in-process merge API. llvm-svn: 262736
This commit is contained in:
parent
d4530c6eb8
commit
31f251f1f0
|
@ -63,7 +63,9 @@ uint64_t *__llvm_profile_end_counters(void);
|
|||
void __llvm_profile_reset_counters(void);
|
||||
|
||||
/*!
|
||||
* \brief Read profile data form buffer and merge with
|
||||
* \brief Merge profile data from buffer.
|
||||
*
|
||||
* Read profile data form buffer \p Profile and merge with
|
||||
* in-process profile counters. The client is expected to
|
||||
* have checked or already knows the profile data in the
|
||||
* buffer matches the in-process counter structure before
|
||||
|
@ -71,6 +73,16 @@ void __llvm_profile_reset_counters(void);
|
|||
*/
|
||||
void __llvm_profile_merge_from_buffer(const char *Profile, uint64_t Size);
|
||||
|
||||
/*! \brief Check if profile in buffer matches the current binary.
|
||||
*
|
||||
* Returns 0 (success) if the profile data in buffer \p Profile with size
|
||||
* \p Size was generated by the same binary and therefore matches
|
||||
* structurally the in-process counters. If the profile data in buffer is
|
||||
* not compatible, the interface returns 1 (failure).
|
||||
*/
|
||||
int __llvm_profile_check_compatibility(const char *Profile,
|
||||
uint64_t Size);
|
||||
|
||||
/*!
|
||||
* \brief Counts the number of times a target value is seen.
|
||||
*
|
||||
|
|
|
@ -20,6 +20,48 @@
|
|||
COMPILER_RT_WEAK void (*VPMergeHook)(ValueProfData *,
|
||||
__llvm_profile_data *) = NULL;
|
||||
|
||||
/* Returns 1 if profile is not structurally compatible. */
|
||||
COMPILER_RT_VISIBILITY
|
||||
int __llvm_profile_check_compatibility(const char *ProfileData,
|
||||
uint64_t ProfileSize) {
|
||||
/* Check profile header only for now */
|
||||
__llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
|
||||
__llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData;
|
||||
SrcDataStart =
|
||||
(__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header));
|
||||
SrcDataEnd = SrcDataStart + Header->DataSize;
|
||||
|
||||
/* Check the header first. */
|
||||
if (Header->Magic != __llvm_profile_get_magic() ||
|
||||
Header->Version != __llvm_profile_get_version() ||
|
||||
Header->DataSize !=
|
||||
(uint64_t)(__llvm_profile_end_data() - __llvm_profile_begin_data()) ||
|
||||
Header->CountersSize != (uint64_t)(__llvm_profile_end_counters() -
|
||||
__llvm_profile_begin_counters()) ||
|
||||
Header->NamesSize != (uint64_t)(__llvm_profile_end_names() -
|
||||
__llvm_profile_begin_names()) ||
|
||||
Header->ValueKindLast != IPVK_Last)
|
||||
return 1;
|
||||
|
||||
if (ProfileSize < sizeof(__llvm_profile_header) +
|
||||
Header->DataSize * sizeof(__llvm_profile_data) +
|
||||
Header->NamesSize + Header->CountersSize +
|
||||
Header->ValueDataSize)
|
||||
return 1;
|
||||
|
||||
for (SrcData = SrcDataStart,
|
||||
DstData = (__llvm_profile_data *)__llvm_profile_begin_data();
|
||||
SrcData < SrcDataEnd; ++SrcData, ++DstData) {
|
||||
if (SrcData->NameRef != DstData->NameRef ||
|
||||
SrcData->FuncHash != DstData->FuncHash ||
|
||||
SrcData->NumCounters != DstData->NumCounters)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Matched! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
void __llvm_profile_merge_from_buffer(const char *ProfileData,
|
||||
uint64_t ProfileSize) {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int __llvm_profile_runtime = 0;
|
||||
uint64_t __llvm_profile_get_size_for_buffer(void);
|
||||
int __llvm_profile_write_buffer(char *);
|
||||
void __llvm_profile_reset_counters(void);
|
||||
int __llvm_profile_check_compatibility(const char *, uint64_t);
|
||||
|
||||
int gg = 0;
|
||||
void bar(char c) {
|
||||
if (c == '1')
|
||||
gg++;
|
||||
else
|
||||
gg--;
|
||||
}
|
||||
|
||||
/* Returns 0 (size) when an error occurs. */
|
||||
uint64_t libEntry(char *Buffer, uint64_t MaxSize) {
|
||||
|
||||
uint64_t Size = __llvm_profile_get_size_for_buffer();
|
||||
if (Size > MaxSize)
|
||||
return 1;
|
||||
|
||||
__llvm_profile_reset_counters();
|
||||
|
||||
bar('1');
|
||||
|
||||
if (__llvm_profile_write_buffer(Buffer))
|
||||
return 0;
|
||||
|
||||
/* Now check compatibility. Should return 0. */
|
||||
if (__llvm_profile_check_compatibility(Buffer, Size))
|
||||
return 0;
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int __llvm_profile_runtime = 0;
|
||||
uint64_t __llvm_profile_get_size_for_buffer(void);
|
||||
int __llvm_profile_write_buffer(char *);
|
||||
void __llvm_profile_reset_counters(void);
|
||||
int __llvm_profile_check_compatibility(const char *, uint64_t);
|
||||
|
||||
int g = 0;
|
||||
void foo(char c) {
|
||||
if (c == '1')
|
||||
g++;
|
||||
else
|
||||
g--;
|
||||
}
|
||||
|
||||
extern uint64_t libEntry(char *Buffer, uint64_t MaxSize);
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
const uint64_t MaxSize = 10000;
|
||||
static char Buffer[MaxSize];
|
||||
|
||||
uint64_t Size = __llvm_profile_get_size_for_buffer();
|
||||
if (Size > MaxSize)
|
||||
return 1;
|
||||
|
||||
__llvm_profile_reset_counters();
|
||||
foo('0');
|
||||
|
||||
if (__llvm_profile_write_buffer(Buffer))
|
||||
return 1;
|
||||
|
||||
/* Now check compatibility. Should return 0. */
|
||||
if (__llvm_profile_check_compatibility(Buffer, Size))
|
||||
return 1;
|
||||
|
||||
/* Clear the buffer. */
|
||||
memset(Buffer, 0, MaxSize);
|
||||
|
||||
/* Collect profile from shared library. */
|
||||
Size = libEntry(Buffer, MaxSize);
|
||||
|
||||
if (!Size)
|
||||
return 1;
|
||||
|
||||
/* Shared library's profile should not match main executable's. */
|
||||
if (!__llvm_profile_check_compatibility(Buffer, Size))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// RUN: mkdir -p %t.d
|
||||
// RUN: %clang_profgen -o %t.d/libt.so -fPIC -shared %S/Inputs/instrprof-merge-match-lib.c
|
||||
// RUN: %clang_profgen -o %t -L %t.d -rpath %t.d %S/Inputs/instrprof-merge-match.c -lt
|
||||
// RUN: %run %t
|
||||
|
Loading…
Reference in New Issue