mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 17:43:35 +03:00
[PGO] Update llvm-profdata-3.9 and profile-rt-39 to LLVM r269788.
This commit is contained in:
parent
e1c06c1e64
commit
103c6f557e
13 changed files with 390 additions and 315 deletions
|
@ -88,6 +88,33 @@ INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
|
||||||
#undef INSTR_PROF_DATA
|
#undef INSTR_PROF_DATA
|
||||||
/* INSTR_PROF_DATA end. */
|
/* INSTR_PROF_DATA end. */
|
||||||
|
|
||||||
|
|
||||||
|
/* This is an internal data structure used by value profiler. It
|
||||||
|
* is defined here to allow serialization code sharing by LLVM
|
||||||
|
* to be used in unit test.
|
||||||
|
*
|
||||||
|
* typedef struct ValueProfNode {
|
||||||
|
* // InstrProfValueData VData;
|
||||||
|
* uint64_t Value;
|
||||||
|
* uint64_t Count;
|
||||||
|
* struct ValueProfNode *Next;
|
||||||
|
* } ValueProfNode;
|
||||||
|
*/
|
||||||
|
/* INSTR_PROF_VALUE_NODE start. */
|
||||||
|
#ifndef INSTR_PROF_VALUE_NODE
|
||||||
|
#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer)
|
||||||
|
#else
|
||||||
|
#define INSTR_PROF_DATA_DEFINED
|
||||||
|
#endif
|
||||||
|
INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \
|
||||||
|
ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
|
||||||
|
INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \
|
||||||
|
ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
|
||||||
|
INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
|
||||||
|
ConstantInt::get(llvm::Type::GetInt8PtrTy(Ctx), 0))
|
||||||
|
#undef INSTR_PROF_VALUE_NODE
|
||||||
|
/* INSTR_PROF_VALUE_NODE end. */
|
||||||
|
|
||||||
/* INSTR_PROF_RAW_HEADER start */
|
/* INSTR_PROF_RAW_HEADER start */
|
||||||
/* Definition of member fields of the raw profile header data structure. */
|
/* Definition of member fields of the raw profile header data structure. */
|
||||||
#ifndef INSTR_PROF_RAW_HEADER
|
#ifndef INSTR_PROF_RAW_HEADER
|
||||||
|
@ -103,8 +130,6 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||||
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
|
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
|
||||||
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||||
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||||
INSTR_PROF_RAW_HEADER(uint64_t, ValueDataSize, ValueDataSize)
|
|
||||||
INSTR_PROF_RAW_HEADER(uint64_t, ValueDataDelta, (uintptr_t)ValueDataBegin)
|
|
||||||
#undef INSTR_PROF_RAW_HEADER
|
#undef INSTR_PROF_RAW_HEADER
|
||||||
/* INSTR_PROF_RAW_HEADER end */
|
/* INSTR_PROF_RAW_HEADER end */
|
||||||
|
|
||||||
|
@ -133,7 +158,7 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
|
||||||
#else
|
#else
|
||||||
#define INSTR_PROF_DATA_DEFINED
|
#define INSTR_PROF_DATA_DEFINED
|
||||||
#endif
|
#endif
|
||||||
/* For indirect function call value profiling, the address of the target
|
/* For indirect function call value profiling, the addresses of the target
|
||||||
* functions are profiled by the instrumented code. The target addresses are
|
* functions are profiled by the instrumented code. The target addresses are
|
||||||
* written in the raw profile data and converted to target function name's MD5
|
* written in the raw profile data and converted to target function name's MD5
|
||||||
* hash by the profile reader during deserialization. Typically, this happens
|
* hash by the profile reader during deserialization. Typically, this happens
|
||||||
|
@ -363,45 +388,11 @@ typedef struct ValueProfRecordClosure {
|
||||||
ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
|
ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
|
||||||
} ValueProfRecordClosure;
|
} ValueProfRecordClosure;
|
||||||
|
|
||||||
/*
|
|
||||||
* A wrapper struct that represents value profile runtime data.
|
|
||||||
* Like InstrProfRecord class which is used by profiling host tools,
|
|
||||||
* ValueProfRuntimeRecord also implements the abstract intefaces defined in
|
|
||||||
* ValueProfRecordClosure so that the runtime data can be serialized using
|
|
||||||
* shared C implementation. In this structure, NumValueSites and Nodes
|
|
||||||
* members are the primary fields while other fields hold the derived
|
|
||||||
* information for fast implementation of closure interfaces.
|
|
||||||
*/
|
|
||||||
typedef struct ValueProfRuntimeRecord {
|
|
||||||
/* Number of sites for each value profile kind. */
|
|
||||||
const uint16_t *NumValueSites;
|
|
||||||
/* An array of linked-list headers. The size of of the array is the
|
|
||||||
* total number of value profile sites : sum(NumValueSites[*])). Each
|
|
||||||
* linked-list stores the values profiled for a value profile site. */
|
|
||||||
ValueProfNode **Nodes;
|
|
||||||
|
|
||||||
/* Total number of value profile kinds which have at least one
|
|
||||||
* value profile sites. */
|
|
||||||
uint32_t NumValueKinds;
|
|
||||||
/* An array recording the number of values tracked at each site.
|
|
||||||
* The size of the array is TotalNumValueSites. */
|
|
||||||
uint8_t *SiteCountArray[IPVK_Last + 1];
|
|
||||||
ValueProfNode **NodesKind[IPVK_Last + 1];
|
|
||||||
} ValueProfRuntimeRecord;
|
|
||||||
|
|
||||||
/* Forward declarations of C interfaces. */
|
|
||||||
int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
|
|
||||||
const uint16_t *NumValueSites,
|
|
||||||
ValueProfNode **Nodes);
|
|
||||||
void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord);
|
|
||||||
uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record);
|
|
||||||
ValueProfData *
|
|
||||||
serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
|
|
||||||
ValueProfData *Dst);
|
|
||||||
uint32_t getNumValueKindsRT(const void *R);
|
|
||||||
ValueProfRecord *getFirstValueProfRecord(ValueProfData *VPD);
|
ValueProfRecord *getFirstValueProfRecord(ValueProfData *VPD);
|
||||||
ValueProfRecord *getValueProfRecordNext(ValueProfRecord *VPR);
|
ValueProfRecord *getValueProfRecordNext(ValueProfRecord *VPR);
|
||||||
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *VPR);
|
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *VPR);
|
||||||
|
uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites);
|
||||||
|
|
||||||
#undef INSTR_PROF_VALUE_PROF_DATA
|
#undef INSTR_PROF_VALUE_PROF_DATA
|
||||||
#endif /* INSTR_PROF_VALUE_PROF_DATA */
|
#endif /* INSTR_PROF_VALUE_PROF_DATA */
|
||||||
|
@ -495,9 +486,6 @@ uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) {
|
||||||
uint32_t Kind;
|
uint32_t Kind;
|
||||||
uint32_t TotalSize = sizeof(ValueProfData);
|
uint32_t TotalSize = sizeof(ValueProfData);
|
||||||
const void *Record = Closure->Record;
|
const void *Record = Closure->Record;
|
||||||
uint32_t NumValueKinds = Closure->GetNumValueKinds(Record);
|
|
||||||
if (NumValueKinds == 0)
|
|
||||||
return TotalSize;
|
|
||||||
|
|
||||||
for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
|
for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
|
||||||
uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind);
|
uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind);
|
||||||
|
@ -533,12 +521,15 @@ void serializeValueProfRecordFrom(ValueProfRecord *This,
|
||||||
/*!
|
/*!
|
||||||
* Extract value profile data of a function from the \c Closure
|
* Extract value profile data of a function from the \c Closure
|
||||||
* and serialize the data into \c DstData if it is not NULL or heap
|
* and serialize the data into \c DstData if it is not NULL or heap
|
||||||
* memory allocated by the \c Closure's allocator method.
|
* memory allocated by the \c Closure's allocator method. If \c
|
||||||
|
* DstData is not null, the caller is expected to set the TotalSize
|
||||||
|
* in DstData.
|
||||||
*/
|
*/
|
||||||
ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||||
ValueProfData *DstData) {
|
ValueProfData *DstData) {
|
||||||
uint32_t Kind;
|
uint32_t Kind;
|
||||||
uint32_t TotalSize = getValueProfDataSize(Closure);
|
uint32_t TotalSize =
|
||||||
|
DstData ? DstData->TotalSize : getValueProfDataSize(Closure);
|
||||||
|
|
||||||
ValueProfData *VPD =
|
ValueProfData *VPD =
|
||||||
DstData ? DstData : Closure->AllocValueProfData(TotalSize);
|
DstData ? DstData : Closure->AllocValueProfData(TotalSize);
|
||||||
|
@ -556,130 +547,6 @@ ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||||
return VPD;
|
return VPD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The value profiler runtime library stores the value profile data
|
|
||||||
* for a given function in \c NumValueSites and \c Nodes structures.
|
|
||||||
* \c ValueProfRuntimeRecord class is used to encapsulate the runtime
|
|
||||||
* profile data and provides fast interfaces to retrieve the profile
|
|
||||||
* information. This interface is used to initialize the runtime record
|
|
||||||
* and pre-compute the information needed for efficient implementation
|
|
||||||
* of callbacks required by ValueProfRecordClosure class.
|
|
||||||
*/
|
|
||||||
int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
|
|
||||||
const uint16_t *NumValueSites,
|
|
||||||
ValueProfNode **Nodes) {
|
|
||||||
unsigned I, J, S = 0, NumValueKinds = 0;
|
|
||||||
RuntimeRecord->NumValueSites = NumValueSites;
|
|
||||||
RuntimeRecord->Nodes = Nodes;
|
|
||||||
for (I = 0; I <= IPVK_Last; I++) {
|
|
||||||
uint16_t N = NumValueSites[I];
|
|
||||||
if (!N) {
|
|
||||||
RuntimeRecord->SiteCountArray[I] = INSTR_PROF_NULLPTR;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
NumValueKinds++;
|
|
||||||
RuntimeRecord->SiteCountArray[I] = (uint8_t *)calloc(N, 1);
|
|
||||||
if (!RuntimeRecord->SiteCountArray[I])
|
|
||||||
return 1;
|
|
||||||
RuntimeRecord->NodesKind[I] = Nodes ? &Nodes[S] : INSTR_PROF_NULLPTR;
|
|
||||||
for (J = 0; J < N; J++) {
|
|
||||||
/* Compute value count for each site. */
|
|
||||||
uint32_t C = 0;
|
|
||||||
ValueProfNode *Site =
|
|
||||||
Nodes ? RuntimeRecord->NodesKind[I][J] : INSTR_PROF_NULLPTR;
|
|
||||||
while (Site) {
|
|
||||||
C++;
|
|
||||||
Site = Site->Next;
|
|
||||||
}
|
|
||||||
if (C > UCHAR_MAX)
|
|
||||||
C = UCHAR_MAX;
|
|
||||||
RuntimeRecord->SiteCountArray[I][J] = C;
|
|
||||||
}
|
|
||||||
S += N;
|
|
||||||
}
|
|
||||||
RuntimeRecord->NumValueKinds = NumValueKinds;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord) {
|
|
||||||
unsigned I;
|
|
||||||
for (I = 0; I <= IPVK_Last; I++) {
|
|
||||||
if (RuntimeRecord->SiteCountArray[I])
|
|
||||||
free(RuntimeRecord->SiteCountArray[I]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ValueProfRecordClosure Interface implementation for
|
|
||||||
* ValueProfDataRuntimeRecord. */
|
|
||||||
uint32_t getNumValueKindsRT(const void *R) {
|
|
||||||
return ((const ValueProfRuntimeRecord *)R)->NumValueKinds;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
|
|
||||||
return ((const ValueProfRuntimeRecord *)R)->NumValueSites[VK];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK, uint32_t S) {
|
|
||||||
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
|
|
||||||
return Record->SiteCountArray[VK][S];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
|
|
||||||
unsigned I, S = 0;
|
|
||||||
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
|
|
||||||
if (Record->SiteCountArray[VK] == INSTR_PROF_NULLPTR)
|
|
||||||
return 0;
|
|
||||||
for (I = 0; I < Record->NumValueSites[VK]; I++)
|
|
||||||
S += Record->SiteCountArray[VK][I];
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
void getValueForSiteRT(const void *R, InstrProfValueData *Dst, uint32_t VK,
|
|
||||||
uint32_t S) {
|
|
||||||
unsigned I, N = 0;
|
|
||||||
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
|
|
||||||
N = getNumValueDataForSiteRT(R, VK, S);
|
|
||||||
if (N == 0)
|
|
||||||
return;
|
|
||||||
ValueProfNode *VNode = Record->NodesKind[VK][S];
|
|
||||||
for (I = 0; I < N; I++) {
|
|
||||||
Dst[I] = VNode->VData;
|
|
||||||
VNode = VNode->Next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueProfData *allocValueProfDataRT(size_t TotalSizeInBytes) {
|
|
||||||
return (ValueProfData *)calloc(TotalSizeInBytes, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ValueProfRecordClosure RTRecordClosure = {
|
|
||||||
INSTR_PROF_NULLPTR, getNumValueKindsRT, getNumValueSitesRT,
|
|
||||||
getNumValueDataRT, getNumValueDataForSiteRT, INSTR_PROF_NULLPTR,
|
|
||||||
getValueForSiteRT, allocValueProfDataRT};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the size of ValueProfData structure to store data
|
|
||||||
* recorded in the runtime record.
|
|
||||||
*/
|
|
||||||
uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record) {
|
|
||||||
RTRecordClosure.Record = Record;
|
|
||||||
return getValueProfDataSize(&RTRecordClosure);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a ValueProfData instance that stores the data collected
|
|
||||||
* from runtime. If \c DstData is provided by the caller, the value
|
|
||||||
* profile data will be store in *DstData and DstData is returned,
|
|
||||||
* otherwise the method will allocate space for the value data and
|
|
||||||
* return pointer to the newly allocated space.
|
|
||||||
*/
|
|
||||||
ValueProfData *
|
|
||||||
serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
|
|
||||||
ValueProfData *DstData) {
|
|
||||||
RTRecordClosure.Record = Record;
|
|
||||||
return serializeValueProfDataFrom(&RTRecordClosure, DstData);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef INSTR_PROF_COMMON_API_IMPL
|
#undef INSTR_PROF_COMMON_API_IMPL
|
||||||
#endif /* INSTR_PROF_COMMON_API_IMPL */
|
#endif /* INSTR_PROF_COMMON_API_IMPL */
|
||||||
|
|
||||||
|
@ -711,7 +578,7 @@ serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
|
||||||
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
|
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
|
||||||
|
|
||||||
/* Raw profile format version (start from 1). */
|
/* Raw profile format version (start from 1). */
|
||||||
#define INSTR_PROF_RAW_VERSION 3
|
#define INSTR_PROF_RAW_VERSION 4
|
||||||
/* Indexed profile format version (start from 1). */
|
/* Indexed profile format version (start from 1). */
|
||||||
#define INSTR_PROF_INDEX_VERSION 4
|
#define INSTR_PROF_INDEX_VERSION 4
|
||||||
/* Coverage mapping format vresion (start from 0). */
|
/* Coverage mapping format vresion (start from 0). */
|
||||||
|
@ -770,15 +637,6 @@ typedef struct InstrProfValueData {
|
||||||
uint64_t Count;
|
uint64_t Count;
|
||||||
} InstrProfValueData;
|
} InstrProfValueData;
|
||||||
|
|
||||||
/* This is an internal data structure used by value profiler. It
|
|
||||||
* is defined here to allow serialization code sharing by LLVM
|
|
||||||
* to be used in unit test.
|
|
||||||
*/
|
|
||||||
typedef struct ValueProfNode {
|
|
||||||
InstrProfValueData VData;
|
|
||||||
struct ValueProfNode *Next;
|
|
||||||
} ValueProfNode;
|
|
||||||
|
|
||||||
#endif /* INSTR_PROF_DATA_INC */
|
#endif /* INSTR_PROF_DATA_INC */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#define INSTR_PROF_VALUE_PROF_DATA
|
#define INSTR_PROF_VALUE_PROF_DATA
|
||||||
#include "InstrProfData.inc"
|
#include "InstrProfData.inc"
|
||||||
|
|
||||||
char *(*GetEnvHook)(const char *) = 0;
|
COMPILER_RT_VISIBILITY char *(*GetEnvHook)(const char *) = 0;
|
||||||
|
|
||||||
COMPILER_RT_WEAK uint64_t __llvm_profile_raw_version = INSTR_PROF_RAW_VERSION;
|
COMPILER_RT_WEAK uint64_t __llvm_profile_raw_version = INSTR_PROF_RAW_VERSION;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
|
||||||
ValueProfNode *CurrentVNode = ValueCounters[i];
|
ValueProfNode *CurrentVNode = ValueCounters[i];
|
||||||
|
|
||||||
while (CurrentVNode) {
|
while (CurrentVNode) {
|
||||||
CurrentVNode->VData.Count = 0;
|
CurrentVNode->Count = 0;
|
||||||
CurrentVNode = CurrentVNode->Next;
|
CurrentVNode = CurrentVNode->Next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,12 @@ typedef struct __llvm_profile_header {
|
||||||
#include "InstrProfData.inc"
|
#include "InstrProfData.inc"
|
||||||
} __llvm_profile_header;
|
} __llvm_profile_header;
|
||||||
|
|
||||||
|
typedef struct ValueProfNode * PtrToNodeT;
|
||||||
|
typedef struct ValueProfNode {
|
||||||
|
#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer) Type Name;
|
||||||
|
#include "InstrProfData.inc"
|
||||||
|
} ValueProfNode;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Get number of bytes necessary to pad the argument to eight
|
* \brief Get number of bytes necessary to pad the argument to eight
|
||||||
* byte boundary.
|
* byte boundary.
|
||||||
|
@ -94,15 +100,7 @@ int __llvm_profile_check_compatibility(const char *Profile,
|
||||||
void INSTR_PROF_VALUE_PROF_FUNC(
|
void INSTR_PROF_VALUE_PROF_FUNC(
|
||||||
#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) ArgType ArgName
|
#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) ArgType ArgName
|
||||||
#include "InstrProfData.inc"
|
#include "InstrProfData.inc"
|
||||||
);
|
);
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Prepares the value profiling data for output.
|
|
||||||
*
|
|
||||||
* Returns an array of pointers to value profile data.
|
|
||||||
*/
|
|
||||||
struct ValueProfData;
|
|
||||||
struct ValueProfData **__llvm_profile_gather_value_data(uint64_t *Size);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Write instrumentation data to the current file.
|
* \brief Write instrumentation data to the current file.
|
||||||
|
|
|
@ -46,7 +46,7 @@ uint64_t __llvm_profile_get_size_for_buffer_internal(
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
|
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
|
||||||
return lprofWriteData(lprofBufferWriter, Buffer, 0, 0);
|
return lprofWriteData(lprofBufferWriter, Buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
||||||
|
@ -54,6 +54,6 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
||||||
const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
|
const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
|
||||||
const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
|
const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
|
||||||
return lprofWriteDataImpl(lprofBufferWriter, Buffer, DataBegin, DataEnd,
|
return lprofWriteDataImpl(lprofBufferWriter, Buffer, DataBegin, DataEnd,
|
||||||
CountersBegin, CountersEnd, 0, 0, NamesBegin,
|
CountersBegin, CountersEnd, 0, NamesBegin,
|
||||||
NamesEnd);
|
NamesEnd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,22 +32,25 @@ static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY ProfBufferIO *
|
COMPILER_RT_VISIBILITY ProfBufferIO *
|
||||||
lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
|
lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
|
||||||
CallocHook = calloc;
|
FreeHook = &free;
|
||||||
FreeHook = free;
|
DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
|
||||||
return lprofCreateBufferIO(fileWriter, File, BufferSz);
|
VPBufferSize = BufferSz;
|
||||||
|
return lprofCreateBufferIO(fileWriter, File);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupIOBuffer() {
|
||||||
|
const char *BufferSzStr = 0;
|
||||||
|
BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
|
||||||
|
if (BufferSzStr && BufferSzStr[0]) {
|
||||||
|
VPBufferSize = atoi(BufferSzStr);
|
||||||
|
DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeFile(FILE *File) {
|
static int writeFile(FILE *File) {
|
||||||
const char *BufferSzStr = 0;
|
|
||||||
uint64_t ValueDataSize = 0;
|
|
||||||
struct ValueProfData **ValueDataArray =
|
|
||||||
__llvm_profile_gather_value_data(&ValueDataSize);
|
|
||||||
FreeHook = &free;
|
FreeHook = &free;
|
||||||
CallocHook = &calloc;
|
setupIOBuffer();
|
||||||
BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
|
return lprofWriteData(fileWriter, File, lprofGetVPDataReader());
|
||||||
if (BufferSzStr && BufferSzStr[0])
|
|
||||||
VPBufferSize = atoi(BufferSzStr);
|
|
||||||
return lprofWriteData(fileWriter, File, ValueDataArray, ValueDataSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeFileWithName(const char *OutputName) {
|
static int writeFileWithName(const char *OutputName) {
|
||||||
|
|
|
@ -68,12 +68,13 @@ typedef struct ProfBufferIO {
|
||||||
} ProfBufferIO;
|
} ProfBufferIO;
|
||||||
|
|
||||||
/* The creator interface used by testing. */
|
/* The creator interface used by testing. */
|
||||||
ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t DefaultBufferSz);
|
ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t BufferSz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This is the interface to create a handle for buffered IO.
|
* This is the interface to create a handle for buffered IO.
|
||||||
*/
|
*/
|
||||||
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File,
|
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File);
|
||||||
uint32_t DefaultBufferSz);
|
|
||||||
/*!
|
/*!
|
||||||
* The interface to destroy the bufferIO handle and reclaim
|
* The interface to destroy the bufferIO handle and reclaim
|
||||||
* the memory.
|
* the memory.
|
||||||
|
@ -98,26 +99,61 @@ int lprofBufferIOFlush(ProfBufferIO *BufferIO);
|
||||||
uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
|
uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
|
||||||
void **WriterCtx);
|
void **WriterCtx);
|
||||||
|
|
||||||
|
struct ValueProfData;
|
||||||
|
struct ValueProfRecord;
|
||||||
|
struct InstrProfValueData;
|
||||||
|
struct ValueProfNode;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The class that defines a set of methods to read value profile
|
||||||
|
* data for streaming/serialization from the instrumentation runtime.
|
||||||
|
*/
|
||||||
|
typedef struct VPDataReaderType {
|
||||||
|
uint32_t (*InitRTRecord)(const __llvm_profile_data *Data,
|
||||||
|
uint8_t *SiteCountArray[]);
|
||||||
|
/* Function pointer to getValueProfRecordHeader method. */
|
||||||
|
uint32_t (*GetValueProfRecordHeaderSize)(uint32_t NumSites);
|
||||||
|
/* Function pointer to getFristValueProfRecord method. */
|
||||||
|
struct ValueProfRecord *(*GetFirstValueProfRecord)(struct ValueProfData *);
|
||||||
|
/* Return the number of value data for site \p Site. */
|
||||||
|
uint32_t (*GetNumValueDataForSite)(uint32_t VK, uint32_t Site);
|
||||||
|
/* Return the total size of the value profile data of the
|
||||||
|
* current function. */
|
||||||
|
uint32_t (*GetValueProfDataSize)(void);
|
||||||
|
/*!
|
||||||
|
* Read the next \p N value data for site \p Site and store the data
|
||||||
|
* in \p Dst. \p StartNode is the first value node to start with if
|
||||||
|
* it is not null. The function returns the pointer to the value
|
||||||
|
* node pointer to be used as the \p StartNode of the next batch reading.
|
||||||
|
* If there is nothing left, it returns NULL.
|
||||||
|
*/
|
||||||
|
struct ValueProfNode *(*GetValueData)(uint32_t ValueKind, uint32_t Site,
|
||||||
|
struct InstrProfValueData *Dst,
|
||||||
|
struct ValueProfNode *StartNode,
|
||||||
|
uint32_t N);
|
||||||
|
} VPDataReaderType;
|
||||||
|
|
||||||
int lprofWriteData(WriterCallback Writer, void *WriterCtx,
|
int lprofWriteData(WriterCallback Writer, void *WriterCtx,
|
||||||
struct ValueProfData **ValueDataArray,
|
VPDataReaderType *VPDataReader);
|
||||||
const uint64_t ValueDataSize);
|
|
||||||
int lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
int lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||||
const __llvm_profile_data *DataBegin,
|
const __llvm_profile_data *DataBegin,
|
||||||
const __llvm_profile_data *DataEnd,
|
const __llvm_profile_data *DataEnd,
|
||||||
const uint64_t *CountersBegin,
|
const uint64_t *CountersBegin,
|
||||||
const uint64_t *CountersEnd,
|
const uint64_t *CountersEnd,
|
||||||
struct ValueProfData **ValueDataBeginArray,
|
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||||
const uint64_t ValueDataSize, const char *NamesBegin,
|
|
||||||
const char *NamesEnd);
|
const char *NamesEnd);
|
||||||
|
|
||||||
/* Merge value profile data pointed to by SrcValueProfData into
|
/* Merge value profile data pointed to by SrcValueProfData into
|
||||||
* in-memory profile counters pointed by to DstData. */
|
* in-memory profile counters pointed by to DstData. */
|
||||||
void lprofMergeValueProfData(struct ValueProfData *SrcValueProfData,
|
void lprofMergeValueProfData(struct ValueProfData *SrcValueProfData,
|
||||||
__llvm_profile_data *DstData);
|
__llvm_profile_data *DstData);
|
||||||
|
|
||||||
extern char *(*GetEnvHook)(const char *);
|
VPDataReaderType *lprofGetVPDataReader();
|
||||||
extern void (*FreeHook)(void *);
|
|
||||||
extern void *(*CallocHook)(size_t, size_t);
|
COMPILER_RT_VISIBILITY extern char *(*GetEnvHook)(const char *);
|
||||||
|
COMPILER_RT_VISIBILITY extern void (*FreeHook)(void *);
|
||||||
|
COMPILER_RT_VISIBILITY extern uint8_t *DynamicBufferIOBuffer;
|
||||||
|
COMPILER_RT_VISIBILITY extern uint32_t VPBufferSize;
|
||||||
extern void (*VPMergeHook)(struct ValueProfData *, __llvm_profile_data *);
|
extern void (*VPMergeHook)(struct ValueProfData *, __llvm_profile_data *);
|
||||||
extern uint32_t VPBufferSize;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,8 +46,7 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
|
||||||
|
|
||||||
if (ProfileSize < sizeof(__llvm_profile_header) +
|
if (ProfileSize < sizeof(__llvm_profile_header) +
|
||||||
Header->DataSize * sizeof(__llvm_profile_data) +
|
Header->DataSize * sizeof(__llvm_profile_data) +
|
||||||
Header->NamesSize + Header->CountersSize +
|
Header->NamesSize + Header->CountersSize)
|
||||||
Header->ValueDataSize)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
for (SrcData = SrcDataStart,
|
for (SrcData = SrcDataStart,
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
#define COMPILER_RT_ALIGNAS(x) __declspec(align(x))
|
#define COMPILER_RT_ALIGNAS(x) __declspec(align(x))
|
||||||
#define COMPILER_RT_VISIBILITY
|
#define COMPILER_RT_VISIBILITY
|
||||||
#define COMPILER_RT_WEAK __declspec(selectany)
|
#define COMPILER_RT_WEAK __declspec(selectany)
|
||||||
|
#define COMPILER_RT_ALLOCA _alloca
|
||||||
#elif __GNUC__
|
#elif __GNUC__
|
||||||
#define COMPILER_RT_ALIGNAS(x) __attribute__((aligned(x)))
|
#define COMPILER_RT_ALIGNAS(x) __attribute__((aligned(x)))
|
||||||
#define COMPILER_RT_VISIBILITY __attribute__((visibility("hidden")))
|
#define COMPILER_RT_VISIBILITY __attribute__((visibility("hidden")))
|
||||||
#define COMPILER_RT_WEAK __attribute__((weak))
|
#define COMPILER_RT_WEAK __attribute__((weak))
|
||||||
|
#define COMPILER_RT_ALLOCA __builtin_alloca
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COMPILER_RT_SECTION(Sect) __attribute__((section(Sect)))
|
#define COMPILER_RT_SECTION(Sect) __attribute__((section(Sect)))
|
||||||
|
@ -25,7 +27,7 @@
|
||||||
#define COMPILER_RT_MAX_HOSTLEN 128
|
#define COMPILER_RT_MAX_HOSTLEN 128
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define COMPILER_RT_GETHOSTNAME(Name, Len) gethostname(Name, Len)
|
#define COMPILER_RT_GETHOSTNAME(Name, Len) gethostname(Name, Len)
|
||||||
#elif defined(__PS4__)
|
#elif defined(__ORBIS__)
|
||||||
#define COMPILER_RT_GETHOSTNAME(Name, Len) (-1)
|
#define COMPILER_RT_GETHOSTNAME(Name, Len) (-1)
|
||||||
#else
|
#else
|
||||||
#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
|
#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
|
||||||
|
@ -42,19 +44,29 @@
|
||||||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||||
(InterlockedCompareExchange64((LONGLONG volatile *)Ptr, (LONGLONG)NewV, \
|
(InterlockedCompareExchange64((LONGLONG volatile *)Ptr, (LONGLONG)NewV, \
|
||||||
(LONGLONG)OldV) == (LONGLONG)OldV)
|
(LONGLONG)OldV) == (LONGLONG)OldV)
|
||||||
|
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||||
|
(DomType *)InterlockedExchangeAdd64((LONGLONG volatile *)&PtrVar, \
|
||||||
|
(LONGLONG)sizeof(DomType) * PtrIncr)
|
||||||
#else /* !defined(_WIN64) */
|
#else /* !defined(_WIN64) */
|
||||||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||||
(InterlockedCompareExchange((LONG volatile *)Ptr, (LONG)NewV, (LONG)OldV) == \
|
(InterlockedCompareExchange((LONG volatile *)Ptr, (LONG)NewV, (LONG)OldV) == \
|
||||||
(LONG)OldV)
|
(LONG)OldV)
|
||||||
|
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||||
|
(DomType *)InterlockedExchangeAdd((LONG volatile *)&PtrVar, \
|
||||||
|
(LONG)sizeof(DomType) * PtrIncr)
|
||||||
#endif
|
#endif
|
||||||
#else /* !defined(_MSC_VER) */
|
#else /* !defined(_MSC_VER) */
|
||||||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||||
__sync_bool_compare_and_swap(Ptr, OldV, NewV)
|
__sync_bool_compare_and_swap(Ptr, OldV, NewV)
|
||||||
|
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||||
|
(DomType *)__sync_fetch_and_add((long *)&PtrVar, sizeof(DomType) * PtrIncr)
|
||||||
#endif
|
#endif
|
||||||
#else /* COMPILER_RT_HAS_ATOMICS != 1 */
|
#else /* COMPILER_RT_HAS_ATOMICS != 1 */
|
||||||
#include "InstrProfilingUtil.h"
|
#include "InstrProfilingUtil.h"
|
||||||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||||
lprofBoolCmpXchg((void **)Ptr, OldV, NewV)
|
lprofBoolCmpXchg((void **)Ptr, OldV, NewV)
|
||||||
|
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||||
|
(DomType *)lprofPtrFetchAdd((void **)&PtrVar, sizeof(DomType) * PtrIncr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PROF_ERR(Format, ...) \
|
#define PROF_ERR(Format, ...) \
|
||||||
|
|
|
@ -51,6 +51,13 @@ uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
COMPILER_RT_VISIBILITY
|
||||||
|
void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
|
||||||
|
void *Old = *Mem;
|
||||||
|
*((char **)Mem) += ByteIncr;
|
||||||
|
return Old;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef COMPILER_RT_HAS_UNAME
|
#ifdef COMPILER_RT_HAS_UNAME
|
||||||
|
|
|
@ -16,12 +16,13 @@
|
||||||
void __llvm_profile_recursive_mkdir(char *Pathname);
|
void __llvm_profile_recursive_mkdir(char *Pathname);
|
||||||
|
|
||||||
/* PS4 doesn't have getenv. Define a shim. */
|
/* PS4 doesn't have getenv. Define a shim. */
|
||||||
#if __PS4__
|
#if __ORBIS__
|
||||||
static inline char *getenv(const char *name) { return NULL; }
|
static inline char *getenv(const char *name) { return NULL; }
|
||||||
#endif /* #if __PS4__ */
|
#endif /* #if __ORBIS__ */
|
||||||
|
|
||||||
int lprofGetHostName(char *Name, int Len);
|
int lprofGetHostName(char *Name, int Len);
|
||||||
|
|
||||||
unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
|
unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
|
||||||
|
void *lprofPtrFetchAdd(void **Mem, long ByteIncr);
|
||||||
|
|
||||||
#endif /* PROFILE_INSTRPROFILINGUTIL_H */
|
#endif /* PROFILE_INSTRPROFILINGUTIL_H */
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#define PROF_OOM_RETURN(Msg) \
|
#define PROF_OOM_RETURN(Msg) \
|
||||||
{ \
|
{ \
|
||||||
PROF_OOM(Msg) \
|
PROF_OOM(Msg) \
|
||||||
free(ValueDataArray); \
|
|
||||||
return NULL; \
|
return NULL; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +85,8 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
|
||||||
|
|
||||||
uint8_t VDataCount = 0;
|
uint8_t VDataCount = 0;
|
||||||
while (CurrentVNode) {
|
while (CurrentVNode) {
|
||||||
if (TargetValue == CurrentVNode->VData.Value) {
|
if (TargetValue == CurrentVNode->Value) {
|
||||||
CurrentVNode->VData.Count++;
|
CurrentVNode->Count++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PrevVNode = CurrentVNode;
|
PrevVNode = CurrentVNode;
|
||||||
|
@ -102,8 +101,8 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
|
||||||
if (!CurrentVNode)
|
if (!CurrentVNode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CurrentVNode->VData.Value = TargetValue;
|
CurrentVNode->Value = TargetValue;
|
||||||
CurrentVNode->VData.Count++;
|
CurrentVNode->Count++;
|
||||||
|
|
||||||
uint32_t Success = 0;
|
uint32_t Success = 0;
|
||||||
if (!ValueCounters[CounterIndex])
|
if (!ValueCounters[CounterIndex])
|
||||||
|
@ -118,51 +117,109 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY ValueProfData **
|
/*
|
||||||
__llvm_profile_gather_value_data(uint64_t *ValueDataSize) {
|
* A wrapper struct that represents value profile runtime data.
|
||||||
size_t S = 0;
|
* Like InstrProfRecord class which is used by profiling host tools,
|
||||||
__llvm_profile_data *I;
|
* ValueProfRuntimeRecord also implements the abstract intefaces defined in
|
||||||
ValueProfData **ValueDataArray;
|
* ValueProfRecordClosure so that the runtime data can be serialized using
|
||||||
|
* shared C implementation.
|
||||||
|
*/
|
||||||
|
typedef struct ValueProfRuntimeRecord {
|
||||||
|
const __llvm_profile_data *Data;
|
||||||
|
ValueProfNode **NodesKind[IPVK_Last + 1];
|
||||||
|
uint8_t **SiteCountArray;
|
||||||
|
} ValueProfRuntimeRecord;
|
||||||
|
|
||||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
/* ValueProfRecordClosure Interface implementation. */
|
||||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
|
||||||
|
|
||||||
if (!ValueDataSize)
|
static uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
|
||||||
return NULL;
|
return ((const ValueProfRuntimeRecord *)R)->Data->NumValueSites[VK];
|
||||||
|
}
|
||||||
ValueDataArray = (ValueProfData **)calloc(
|
|
||||||
__llvm_profile_get_data_size(DataBegin, DataEnd), sizeof(void *));
|
static uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
|
||||||
if (!ValueDataArray)
|
uint32_t S = 0, I;
|
||||||
PROF_OOM_RETURN("Failed to write value profile data ");
|
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
|
||||||
|
if (Record->SiteCountArray[VK] == INSTR_PROF_NULLPTR)
|
||||||
/*
|
return 0;
|
||||||
* Compute the total Size of the buffer to hold ValueProfData
|
for (I = 0; I < Record->Data->NumValueSites[VK]; I++)
|
||||||
* structures for functions with value profile data.
|
S += Record->SiteCountArray[VK][I];
|
||||||
*/
|
return S;
|
||||||
for (I = (__llvm_profile_data *)DataBegin; I < DataEnd; ++I) {
|
}
|
||||||
ValueProfRuntimeRecord R;
|
|
||||||
if (initializeValueProfRuntimeRecord(&R, I->NumValueSites, I->Values))
|
static uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK,
|
||||||
PROF_OOM_RETURN("Failed to write value profile data ");
|
uint32_t S) {
|
||||||
|
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
|
||||||
/* Compute the size of ValueProfData from this runtime record. */
|
return Record->SiteCountArray[VK][S];
|
||||||
if (getNumValueKindsRT(&R) != 0) {
|
}
|
||||||
ValueProfData *VD = NULL;
|
|
||||||
uint32_t VS = getValueProfDataSizeRT(&R);
|
static ValueProfRuntimeRecord RTRecord;
|
||||||
VD = (ValueProfData *)calloc(VS, sizeof(uint8_t));
|
static ValueProfRecordClosure RTRecordClosure = {
|
||||||
if (!VD)
|
&RTRecord, INSTR_PROF_NULLPTR, /* GetNumValueKinds */
|
||||||
PROF_OOM_RETURN("Failed to write value profile data ");
|
getNumValueSitesRT, getNumValueDataRT, getNumValueDataForSiteRT,
|
||||||
serializeValueProfDataFromRT(&R, VD);
|
INSTR_PROF_NULLPTR, /* RemapValueData */
|
||||||
ValueDataArray[I - DataBegin] = VD;
|
INSTR_PROF_NULLPTR, /* GetValueForSite, */
|
||||||
S += VS;
|
INSTR_PROF_NULLPTR /* AllocValueProfData */
|
||||||
}
|
};
|
||||||
finalizeValueProfRuntimeRecord(&R);
|
|
||||||
}
|
static uint32_t
|
||||||
|
initializeValueProfRuntimeRecord(const __llvm_profile_data *Data,
|
||||||
if (!S) {
|
uint8_t *SiteCountArray[]) {
|
||||||
free(ValueDataArray);
|
unsigned I, J, S = 0, NumValueKinds = 0;
|
||||||
ValueDataArray = NULL;
|
ValueProfNode **Nodes = (ValueProfNode **)Data->Values;
|
||||||
}
|
RTRecord.Data = Data;
|
||||||
|
RTRecord.SiteCountArray = SiteCountArray;
|
||||||
*ValueDataSize = S;
|
for (I = 0; I <= IPVK_Last; I++) {
|
||||||
return ValueDataArray;
|
uint16_t N = Data->NumValueSites[I];
|
||||||
|
if (!N)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NumValueKinds++;
|
||||||
|
|
||||||
|
RTRecord.NodesKind[I] = Nodes ? &Nodes[S] : INSTR_PROF_NULLPTR;
|
||||||
|
for (J = 0; J < N; J++) {
|
||||||
|
/* Compute value count for each site. */
|
||||||
|
uint32_t C = 0;
|
||||||
|
ValueProfNode *Site =
|
||||||
|
Nodes ? RTRecord.NodesKind[I][J] : INSTR_PROF_NULLPTR;
|
||||||
|
while (Site) {
|
||||||
|
C++;
|
||||||
|
Site = Site->Next;
|
||||||
|
}
|
||||||
|
if (C > UCHAR_MAX)
|
||||||
|
C = UCHAR_MAX;
|
||||||
|
RTRecord.SiteCountArray[I][J] = C;
|
||||||
|
}
|
||||||
|
S += N;
|
||||||
|
}
|
||||||
|
return NumValueKinds;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ValueProfNode *getNextNValueData(uint32_t VK, uint32_t Site,
|
||||||
|
InstrProfValueData *Dst,
|
||||||
|
ValueProfNode *StartNode, uint32_t N) {
|
||||||
|
unsigned I;
|
||||||
|
ValueProfNode *VNode = StartNode ? StartNode : RTRecord.NodesKind[VK][Site];
|
||||||
|
for (I = 0; I < N; I++) {
|
||||||
|
Dst[I].Value = VNode->Value;
|
||||||
|
Dst[I].Count = VNode->Count;
|
||||||
|
VNode = VNode->Next;
|
||||||
|
}
|
||||||
|
return VNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t getValueProfDataSizeWrapper() {
|
||||||
|
return getValueProfDataSize(&RTRecordClosure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t getNumValueDataForSiteWrapper(uint32_t VK, uint32_t S) {
|
||||||
|
return getNumValueDataForSiteRT(&RTRecord, VK, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VPDataReaderType TheVPDataReader = {
|
||||||
|
initializeValueProfRuntimeRecord, getValueProfRecordHeaderSize,
|
||||||
|
getFirstValueProfRecord, getNumValueDataForSiteWrapper,
|
||||||
|
getValueProfDataSizeWrapper, getNextNValueData};
|
||||||
|
|
||||||
|
COMPILER_RT_VISIBILITY VPDataReaderType *lprofGetVPDataReader() {
|
||||||
|
return &TheVPDataReader;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,24 @@
|
||||||
|
|
||||||
#include "InstrProfiling.h"
|
#include "InstrProfiling.h"
|
||||||
#include "InstrProfilingInternal.h"
|
#include "InstrProfilingInternal.h"
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* For _alloca */
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define INSTR_PROF_VALUE_PROF_DATA
|
#define INSTR_PROF_VALUE_PROF_DATA
|
||||||
#include "InstrProfData.inc"
|
#include "InstrProfData.inc"
|
||||||
void (*FreeHook)(void *) = NULL;
|
|
||||||
void* (*CallocHook)(size_t, size_t) = NULL;
|
COMPILER_RT_VISIBILITY void (*FreeHook)(void *) = NULL;
|
||||||
uint32_t VPBufferSize = 0;
|
static ProfBufferIO TheBufferIO;
|
||||||
|
#define VP_BUFFER_SIZE 8 * 1024
|
||||||
|
static uint8_t BufferIOBuffer[VP_BUFFER_SIZE];
|
||||||
|
static InstrProfValueData VPDataArray[16];
|
||||||
|
static uint32_t VPDataArraySize = sizeof(VPDataArray) / sizeof(*VPDataArray);
|
||||||
|
|
||||||
|
COMPILER_RT_VISIBILITY uint8_t *DynamicBufferIOBuffer = 0;
|
||||||
|
COMPILER_RT_VISIBILITY uint32_t VPBufferSize = 0;
|
||||||
|
|
||||||
/* The buffer writer is reponsponsible in keeping writer state
|
/* The buffer writer is reponsponsible in keeping writer state
|
||||||
* across the call.
|
* across the call.
|
||||||
|
@ -43,20 +54,23 @@ static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY ProfBufferIO *
|
COMPILER_RT_VISIBILITY ProfBufferIO *
|
||||||
lprofCreateBufferIO(WriterCallback FileWriter, void *File, uint32_t BufferSz) {
|
lprofCreateBufferIO(WriterCallback FileWriter, void *File) {
|
||||||
ProfBufferIO *BufferIO = (ProfBufferIO *)CallocHook(1, sizeof(ProfBufferIO));
|
uint8_t *Buffer = DynamicBufferIOBuffer;
|
||||||
uint8_t *Buffer = (uint8_t *)CallocHook(1, BufferSz);
|
uint32_t BufferSize = VPBufferSize;
|
||||||
if (!Buffer) {
|
if (!Buffer) {
|
||||||
FreeHook(BufferIO);
|
Buffer = &BufferIOBuffer[0];
|
||||||
return 0;
|
BufferSize = sizeof(BufferIOBuffer);
|
||||||
}
|
}
|
||||||
llvmInitBufferIO(BufferIO, FileWriter, File, Buffer, BufferSz);
|
llvmInitBufferIO(&TheBufferIO, FileWriter, File, Buffer, BufferSize);
|
||||||
return BufferIO;
|
return &TheBufferIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) {
|
COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) {
|
||||||
FreeHook(BufferIO->BufferStart);
|
if (DynamicBufferIOBuffer) {
|
||||||
FreeHook(BufferIO);
|
FreeHook(DynamicBufferIOBuffer);
|
||||||
|
DynamicBufferIOBuffer = 0;
|
||||||
|
VPBufferSize = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY int
|
COMPILER_RT_VISIBILITY int
|
||||||
|
@ -91,41 +105,116 @@ COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
|
/* Write out value profile data for function specified with \c Data.
|
||||||
void *WriterCtx,
|
* The implementation does not use the method \c serializeValueProfData
|
||||||
ValueProfData **ValueDataArray,
|
* which depends on dynamic memory allocation. In this implementation,
|
||||||
const uint64_t ValueDataSize) {
|
* value profile data is written out to \c BufferIO piecemeal.
|
||||||
/* Match logic in __llvm_profile_write_buffer(). */
|
*/
|
||||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
static int writeOneValueProfData(ProfBufferIO *BufferIO,
|
||||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
VPDataReaderType *VPDataReader,
|
||||||
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
|
const __llvm_profile_data *Data) {
|
||||||
const uint64_t *CountersEnd = __llvm_profile_end_counters();
|
unsigned I, NumValueKinds = 0;
|
||||||
const char *NamesBegin = __llvm_profile_begin_names();
|
ValueProfData VPHeader;
|
||||||
const char *NamesEnd = __llvm_profile_end_names();
|
uint8_t *SiteCountArray[IPVK_Last + 1];
|
||||||
return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
|
|
||||||
CountersBegin, CountersEnd, ValueDataArray,
|
|
||||||
ValueDataSize, NamesBegin, NamesEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VP_BUFFER_SIZE 8 * 1024
|
for (I = 0; I <= IPVK_Last; I++) {
|
||||||
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
if (!Data->NumValueSites[I])
|
||||||
ValueProfData **ValueDataBegin,
|
SiteCountArray[I] = 0;
|
||||||
uint64_t NumVData) {
|
else {
|
||||||
ProfBufferIO *BufferIO;
|
uint32_t Sz =
|
||||||
uint32_t I = 0, BufferSz;
|
VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
|
||||||
|
offsetof(ValueProfRecord, SiteCountArray);
|
||||||
|
/* Only use alloca for this small byte array to avoid excessive
|
||||||
|
* stack growth. */
|
||||||
|
SiteCountArray[I] = (uint8_t *)COMPILER_RT_ALLOCA(Sz);
|
||||||
|
memset(SiteCountArray[I], 0, Sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ValueDataBegin)
|
/* If NumValueKinds returned is 0, there is nothing to write, report
|
||||||
|
success and return. This should match the raw profile reader's behavior. */
|
||||||
|
if (!(NumValueKinds = VPDataReader->InitRTRecord(Data, SiteCountArray)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
BufferSz = VPBufferSize ? VPBufferSize : VP_BUFFER_SIZE;
|
/* First write the header structure. */
|
||||||
BufferIO = lprofCreateBufferIO(Writer, WriterCtx, BufferSz);
|
VPHeader.TotalSize = VPDataReader->GetValueProfDataSize();
|
||||||
|
VPHeader.NumValueKinds = NumValueKinds;
|
||||||
|
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPHeader,
|
||||||
|
sizeof(ValueProfData)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
for (I = 0; I < NumVData; I++) {
|
/* Make sure nothing else needs to be written before value profile
|
||||||
ValueProfData *CurVData = ValueDataBegin[I];
|
* records. */
|
||||||
if (!CurVData)
|
if ((void *)VPDataReader->GetFirstValueProfRecord(&VPHeader) !=
|
||||||
|
(void *)(&VPHeader + 1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Write out the value profile record for each value kind
|
||||||
|
* one by one. */
|
||||||
|
for (I = 0; I <= IPVK_Last; I++) {
|
||||||
|
uint32_t J;
|
||||||
|
ValueProfRecord RecordHeader;
|
||||||
|
/* The size of the value prof record header without counting the
|
||||||
|
* site count array .*/
|
||||||
|
uint32_t RecordHeaderSize = offsetof(ValueProfRecord, SiteCountArray);
|
||||||
|
uint32_t SiteCountArraySize;
|
||||||
|
|
||||||
|
if (!Data->NumValueSites[I])
|
||||||
continue;
|
continue;
|
||||||
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)CurVData,
|
|
||||||
CurVData->TotalSize) != 0)
|
/* Write out the record header. */
|
||||||
|
RecordHeader.Kind = I;
|
||||||
|
RecordHeader.NumValueSites = Data->NumValueSites[I];
|
||||||
|
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&RecordHeader,
|
||||||
|
RecordHeaderSize))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Write out the site value count array including padding space. */
|
||||||
|
SiteCountArraySize =
|
||||||
|
VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
|
||||||
|
RecordHeaderSize;
|
||||||
|
if (lprofBufferIOWrite(BufferIO, SiteCountArray[I], SiteCountArraySize))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Write out the value profile data for each value site. */
|
||||||
|
for (J = 0; J < Data->NumValueSites[I]; J++) {
|
||||||
|
uint32_t NRead, NRemain;
|
||||||
|
ValueProfNode *NextStartNode = 0;
|
||||||
|
NRemain = VPDataReader->GetNumValueDataForSite(I, J);
|
||||||
|
if (!NRemain)
|
||||||
|
continue;
|
||||||
|
/* Read and write out value data in small chunks till it is done. */
|
||||||
|
do {
|
||||||
|
NRead = (NRemain > VPDataArraySize ? VPDataArraySize : NRemain);
|
||||||
|
NextStartNode =
|
||||||
|
VPDataReader->GetValueData(I, /* ValueKind */
|
||||||
|
J, /* Site */
|
||||||
|
&VPDataArray[0], NextStartNode, NRead);
|
||||||
|
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPDataArray[0],
|
||||||
|
NRead * sizeof(InstrProfValueData)))
|
||||||
|
return -1;
|
||||||
|
NRemain -= NRead;
|
||||||
|
} while (NRemain != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* All done report success. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
||||||
|
VPDataReaderType *VPDataReader,
|
||||||
|
const __llvm_profile_data *DataBegin,
|
||||||
|
const __llvm_profile_data *DataEnd) {
|
||||||
|
ProfBufferIO *BufferIO;
|
||||||
|
const __llvm_profile_data *DI = 0;
|
||||||
|
|
||||||
|
if (!VPDataReader)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
BufferIO = lprofCreateBufferIO(Writer, WriterCtx);
|
||||||
|
|
||||||
|
for (DI = DataBegin; DI < DataEnd; DI++) {
|
||||||
|
if (writeOneValueProfData(BufferIO, VPDataReader, DI))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,13 +225,28 @@ static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
|
||||||
|
void *WriterCtx,
|
||||||
|
VPDataReaderType *VPDataReader) {
|
||||||
|
/* Match logic in __llvm_profile_write_buffer(). */
|
||||||
|
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||||
|
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||||
|
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
|
||||||
|
const uint64_t *CountersEnd = __llvm_profile_end_counters();
|
||||||
|
const char *NamesBegin = __llvm_profile_begin_names();
|
||||||
|
const char *NamesEnd = __llvm_profile_end_names();
|
||||||
|
return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
|
||||||
|
CountersBegin, CountersEnd, VPDataReader,
|
||||||
|
NamesBegin, NamesEnd);
|
||||||
|
}
|
||||||
|
|
||||||
COMPILER_RT_VISIBILITY int
|
COMPILER_RT_VISIBILITY int
|
||||||
lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||||
const __llvm_profile_data *DataBegin,
|
const __llvm_profile_data *DataBegin,
|
||||||
const __llvm_profile_data *DataEnd,
|
const __llvm_profile_data *DataEnd,
|
||||||
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
|
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
|
||||||
ValueProfData **ValueDataBegin, const uint64_t ValueDataSize,
|
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||||
const char *NamesBegin, const char *NamesEnd) {
|
const char *NamesEnd) {
|
||||||
|
|
||||||
/* Calculate size of sections. */
|
/* Calculate size of sections. */
|
||||||
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||||
|
@ -159,7 +263,7 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||||
if (!DataSize)
|
if (!DataSize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Initialize header struture. */
|
/* Initialize header structure. */
|
||||||
#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init;
|
#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init;
|
||||||
#include "InstrProfData.inc"
|
#include "InstrProfData.inc"
|
||||||
|
|
||||||
|
@ -172,5 +276,6 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||||
if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
|
if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return writeValueProfData(Writer, WriterCtx, ValueDataBegin, DataSize);
|
return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin,
|
||||||
|
DataEnd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "llvm/Support/Signals.h"
|
#include "llvm/Support/Signals.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue