[PGO] Update llvm-profdata-3.9 and profile-rt-39 to LLVM r269788.

This commit is contained in:
Johan Engelen 2016-05-17 20:08:03 +02:00
parent e1c06c1e64
commit 103c6f557e
13 changed files with 390 additions and 315 deletions

View file

@ -88,6 +88,33 @@ INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
#undef INSTR_PROF_DATA
/* 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 */
/* Definition of member fields of the raw profile header data structure. */
#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, NamesDelta, (uintptr_t)NamesBegin)
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
/* INSTR_PROF_RAW_HEADER end */
@ -133,7 +158,7 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
#else
#define INSTR_PROF_DATA_DEFINED
#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
* written in the raw profile data and converted to target function name's MD5
* hash by the profile reader during deserialization. Typically, this happens
@ -363,45 +388,11 @@ typedef struct ValueProfRecordClosure {
ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
} 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 *getValueProfRecordNext(ValueProfRecord *VPR);
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *VPR);
uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites);
#undef 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 TotalSize = sizeof(ValueProfData);
const void *Record = Closure->Record;
uint32_t NumValueKinds = Closure->GetNumValueKinds(Record);
if (NumValueKinds == 0)
return TotalSize;
for (Kind = IPVK_First; Kind <= IPVK_Last; 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
* 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 *DstData) {
uint32_t Kind;
uint32_t TotalSize = getValueProfDataSize(Closure);
uint32_t TotalSize =
DstData ? DstData->TotalSize : getValueProfDataSize(Closure);
ValueProfData *VPD =
DstData ? DstData : Closure->AllocValueProfData(TotalSize);
@ -556,130 +547,6 @@ ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
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
#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
/* 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). */
#define INSTR_PROF_INDEX_VERSION 4
/* Coverage mapping format vresion (start from 0). */
@ -770,15 +637,6 @@ typedef struct InstrProfValueData {
uint64_t Count;
} 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 */
#else

View file

@ -16,7 +16,7 @@
#define INSTR_PROF_VALUE_PROF_DATA
#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;
@ -61,7 +61,7 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
ValueProfNode *CurrentVNode = ValueCounters[i];
while (CurrentVNode) {
CurrentVNode->VData.Count = 0;
CurrentVNode->Count = 0;
CurrentVNode = CurrentVNode->Next;
}
}

View file

@ -30,6 +30,12 @@ typedef struct __llvm_profile_header {
#include "InstrProfData.inc"
} __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
* byte boundary.
@ -94,15 +100,7 @@ int __llvm_profile_check_compatibility(const char *Profile,
void INSTR_PROF_VALUE_PROF_FUNC(
#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) ArgType ArgName
#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.

View file

@ -46,7 +46,7 @@ uint64_t __llvm_profile_get_size_for_buffer_internal(
}
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(
@ -54,6 +54,6 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
return lprofWriteDataImpl(lprofBufferWriter, Buffer, DataBegin, DataEnd,
CountersBegin, CountersEnd, 0, 0, NamesBegin,
CountersBegin, CountersEnd, 0, NamesBegin,
NamesEnd);
}

View file

@ -32,22 +32,25 @@ static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
COMPILER_RT_VISIBILITY ProfBufferIO *
lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
CallocHook = calloc;
FreeHook = free;
return lprofCreateBufferIO(fileWriter, File, BufferSz);
FreeHook = &free;
DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
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) {
const char *BufferSzStr = 0;
uint64_t ValueDataSize = 0;
struct ValueProfData **ValueDataArray =
__llvm_profile_gather_value_data(&ValueDataSize);
FreeHook = &free;
CallocHook = &calloc;
BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
if (BufferSzStr && BufferSzStr[0])
VPBufferSize = atoi(BufferSzStr);
return lprofWriteData(fileWriter, File, ValueDataArray, ValueDataSize);
setupIOBuffer();
return lprofWriteData(fileWriter, File, lprofGetVPDataReader());
}
static int writeFileWithName(const char *OutputName) {

View file

@ -68,12 +68,13 @@ typedef struct ProfBufferIO {
} ProfBufferIO;
/* 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.
*/
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File,
uint32_t DefaultBufferSz);
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File);
/*!
* The interface to destroy the bufferIO handle and reclaim
* the memory.
@ -98,26 +99,61 @@ int lprofBufferIOFlush(ProfBufferIO *BufferIO);
uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
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,
struct ValueProfData **ValueDataArray,
const uint64_t ValueDataSize);
VPDataReaderType *VPDataReader);
int lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd,
const uint64_t *CountersBegin,
const uint64_t *CountersEnd,
struct ValueProfData **ValueDataBeginArray,
const uint64_t ValueDataSize, const char *NamesBegin,
VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd);
/* Merge value profile data pointed to by SrcValueProfData into
* in-memory profile counters pointed by to DstData. */
void lprofMergeValueProfData(struct ValueProfData *SrcValueProfData,
__llvm_profile_data *DstData);
extern char *(*GetEnvHook)(const char *);
extern void (*FreeHook)(void *);
extern void *(*CallocHook)(size_t, size_t);
VPDataReaderType *lprofGetVPDataReader();
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 uint32_t VPBufferSize;
#endif

View file

@ -46,8 +46,7 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
if (ProfileSize < sizeof(__llvm_profile_header) +
Header->DataSize * sizeof(__llvm_profile_data) +
Header->NamesSize + Header->CountersSize +
Header->ValueDataSize)
Header->NamesSize + Header->CountersSize)
return 1;
for (SrcData = SrcDataStart,

View file

@ -14,10 +14,12 @@
#define COMPILER_RT_ALIGNAS(x) __declspec(align(x))
#define COMPILER_RT_VISIBILITY
#define COMPILER_RT_WEAK __declspec(selectany)
#define COMPILER_RT_ALLOCA _alloca
#elif __GNUC__
#define COMPILER_RT_ALIGNAS(x) __attribute__((aligned(x)))
#define COMPILER_RT_VISIBILITY __attribute__((visibility("hidden")))
#define COMPILER_RT_WEAK __attribute__((weak))
#define COMPILER_RT_ALLOCA __builtin_alloca
#endif
#define COMPILER_RT_SECTION(Sect) __attribute__((section(Sect)))
@ -25,7 +27,7 @@
#define COMPILER_RT_MAX_HOSTLEN 128
#ifdef _MSC_VER
#define COMPILER_RT_GETHOSTNAME(Name, Len) gethostname(Name, Len)
#elif defined(__PS4__)
#elif defined(__ORBIS__)
#define COMPILER_RT_GETHOSTNAME(Name, Len) (-1)
#else
#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
@ -42,19 +44,29 @@
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
(InterlockedCompareExchange64((LONGLONG volatile *)Ptr, (LONGLONG)NewV, \
(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) */
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
(InterlockedCompareExchange((LONG volatile *)Ptr, (LONG)NewV, (LONG)OldV) == \
(LONG)OldV)
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
(DomType *)InterlockedExchangeAdd((LONG volatile *)&PtrVar, \
(LONG)sizeof(DomType) * PtrIncr)
#endif
#else /* !defined(_MSC_VER) */
#define COMPILER_RT_BOOL_CMPXCHG(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
#else /* COMPILER_RT_HAS_ATOMICS != 1 */
#include "InstrProfilingUtil.h"
#define COMPILER_RT_BOOL_CMPXCHG(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
#define PROF_ERR(Format, ...) \

View file

@ -51,6 +51,13 @@ uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
}
return 0;
}
COMPILER_RT_VISIBILITY
void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
void *Old = *Mem;
*((char **)Mem) += ByteIncr;
return Old;
}
#endif
#ifdef COMPILER_RT_HAS_UNAME

View file

@ -16,12 +16,13 @@
void __llvm_profile_recursive_mkdir(char *Pathname);
/* PS4 doesn't have getenv. Define a shim. */
#if __PS4__
#if __ORBIS__
static inline char *getenv(const char *name) { return NULL; }
#endif /* #if __PS4__ */
#endif /* #if __ORBIS__ */
int lprofGetHostName(char *Name, int Len);
unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
void *lprofPtrFetchAdd(void **Mem, long ByteIncr);
#endif /* PROFILE_INSTRPROFILINGUTIL_H */
#endif /* PROFILE_INSTRPROFILINGUTIL_H */

View file

@ -21,7 +21,6 @@
#define PROF_OOM_RETURN(Msg) \
{ \
PROF_OOM(Msg) \
free(ValueDataArray); \
return NULL; \
}
@ -86,8 +85,8 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
uint8_t VDataCount = 0;
while (CurrentVNode) {
if (TargetValue == CurrentVNode->VData.Value) {
CurrentVNode->VData.Count++;
if (TargetValue == CurrentVNode->Value) {
CurrentVNode->Count++;
return;
}
PrevVNode = CurrentVNode;
@ -102,8 +101,8 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
if (!CurrentVNode)
return;
CurrentVNode->VData.Value = TargetValue;
CurrentVNode->VData.Count++;
CurrentVNode->Value = TargetValue;
CurrentVNode->Count++;
uint32_t Success = 0;
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) {
size_t S = 0;
__llvm_profile_data *I;
ValueProfData **ValueDataArray;
/*
* 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.
*/
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();
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
/* ValueProfRecordClosure Interface implementation. */
if (!ValueDataSize)
return NULL;
ValueDataArray = (ValueProfData **)calloc(
__llvm_profile_get_data_size(DataBegin, DataEnd), sizeof(void *));
if (!ValueDataArray)
PROF_OOM_RETURN("Failed to write value profile data ");
/*
* Compute the total Size of the buffer to hold ValueProfData
* structures for functions with value profile data.
*/
for (I = (__llvm_profile_data *)DataBegin; I < DataEnd; ++I) {
ValueProfRuntimeRecord R;
if (initializeValueProfRuntimeRecord(&R, I->NumValueSites, I->Values))
PROF_OOM_RETURN("Failed to write value profile data ");
/* Compute the size of ValueProfData from this runtime record. */
if (getNumValueKindsRT(&R) != 0) {
ValueProfData *VD = NULL;
uint32_t VS = getValueProfDataSizeRT(&R);
VD = (ValueProfData *)calloc(VS, sizeof(uint8_t));
if (!VD)
PROF_OOM_RETURN("Failed to write value profile data ");
serializeValueProfDataFromRT(&R, VD);
ValueDataArray[I - DataBegin] = VD;
S += VS;
}
finalizeValueProfRuntimeRecord(&R);
}
if (!S) {
free(ValueDataArray);
ValueDataArray = NULL;
}
*ValueDataSize = S;
return ValueDataArray;
static uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
return ((const ValueProfRuntimeRecord *)R)->Data->NumValueSites[VK];
}
static uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
uint32_t S = 0, I;
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
if (Record->SiteCountArray[VK] == INSTR_PROF_NULLPTR)
return 0;
for (I = 0; I < Record->Data->NumValueSites[VK]; I++)
S += Record->SiteCountArray[VK][I];
return S;
}
static uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK,
uint32_t S) {
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
return Record->SiteCountArray[VK][S];
}
static ValueProfRuntimeRecord RTRecord;
static ValueProfRecordClosure RTRecordClosure = {
&RTRecord, INSTR_PROF_NULLPTR, /* GetNumValueKinds */
getNumValueSitesRT, getNumValueDataRT, getNumValueDataForSiteRT,
INSTR_PROF_NULLPTR, /* RemapValueData */
INSTR_PROF_NULLPTR, /* GetValueForSite, */
INSTR_PROF_NULLPTR /* AllocValueProfData */
};
static uint32_t
initializeValueProfRuntimeRecord(const __llvm_profile_data *Data,
uint8_t *SiteCountArray[]) {
unsigned I, J, S = 0, NumValueKinds = 0;
ValueProfNode **Nodes = (ValueProfNode **)Data->Values;
RTRecord.Data = Data;
RTRecord.SiteCountArray = SiteCountArray;
for (I = 0; I <= IPVK_Last; I++) {
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;
}

View file

@ -9,13 +9,24 @@
#include "InstrProfiling.h"
#include "InstrProfilingInternal.h"
#ifdef _MSC_VER
/* For _alloca */
#include <malloc.h>
#endif
#include <string.h>
#define INSTR_PROF_VALUE_PROF_DATA
#include "InstrProfData.inc"
void (*FreeHook)(void *) = NULL;
void* (*CallocHook)(size_t, size_t) = NULL;
uint32_t VPBufferSize = 0;
COMPILER_RT_VISIBILITY void (*FreeHook)(void *) = NULL;
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
* across the call.
@ -43,20 +54,23 @@ static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter,
}
COMPILER_RT_VISIBILITY ProfBufferIO *
lprofCreateBufferIO(WriterCallback FileWriter, void *File, uint32_t BufferSz) {
ProfBufferIO *BufferIO = (ProfBufferIO *)CallocHook(1, sizeof(ProfBufferIO));
uint8_t *Buffer = (uint8_t *)CallocHook(1, BufferSz);
lprofCreateBufferIO(WriterCallback FileWriter, void *File) {
uint8_t *Buffer = DynamicBufferIOBuffer;
uint32_t BufferSize = VPBufferSize;
if (!Buffer) {
FreeHook(BufferIO);
return 0;
Buffer = &BufferIOBuffer[0];
BufferSize = sizeof(BufferIOBuffer);
}
llvmInitBufferIO(BufferIO, FileWriter, File, Buffer, BufferSz);
return BufferIO;
llvmInitBufferIO(&TheBufferIO, FileWriter, File, Buffer, BufferSize);
return &TheBufferIO;
}
COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) {
FreeHook(BufferIO->BufferStart);
FreeHook(BufferIO);
if (DynamicBufferIOBuffer) {
FreeHook(DynamicBufferIOBuffer);
DynamicBufferIOBuffer = 0;
VPBufferSize = 0;
}
}
COMPILER_RT_VISIBILITY int
@ -91,41 +105,116 @@ COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) {
return 0;
}
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
void *WriterCtx,
ValueProfData **ValueDataArray,
const uint64_t ValueDataSize) {
/* 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, ValueDataArray,
ValueDataSize, NamesBegin, NamesEnd);
}
/* Write out value profile data for function specified with \c Data.
* The implementation does not use the method \c serializeValueProfData
* which depends on dynamic memory allocation. In this implementation,
* value profile data is written out to \c BufferIO piecemeal.
*/
static int writeOneValueProfData(ProfBufferIO *BufferIO,
VPDataReaderType *VPDataReader,
const __llvm_profile_data *Data) {
unsigned I, NumValueKinds = 0;
ValueProfData VPHeader;
uint8_t *SiteCountArray[IPVK_Last + 1];
#define VP_BUFFER_SIZE 8 * 1024
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
ValueProfData **ValueDataBegin,
uint64_t NumVData) {
ProfBufferIO *BufferIO;
uint32_t I = 0, BufferSz;
for (I = 0; I <= IPVK_Last; I++) {
if (!Data->NumValueSites[I])
SiteCountArray[I] = 0;
else {
uint32_t Sz =
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;
BufferSz = VPBufferSize ? VPBufferSize : VP_BUFFER_SIZE;
BufferIO = lprofCreateBufferIO(Writer, WriterCtx, BufferSz);
/* First write the header structure. */
VPHeader.TotalSize = VPDataReader->GetValueProfDataSize();
VPHeader.NumValueKinds = NumValueKinds;
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPHeader,
sizeof(ValueProfData)))
return -1;
for (I = 0; I < NumVData; I++) {
ValueProfData *CurVData = ValueDataBegin[I];
if (!CurVData)
/* Make sure nothing else needs to be written before value profile
* records. */
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;
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;
}
@ -136,13 +225,28 @@ static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
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
lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd,
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
ValueProfData **ValueDataBegin, const uint64_t ValueDataSize,
const char *NamesBegin, const char *NamesEnd) {
VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd) {
/* Calculate size of sections. */
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
@ -159,7 +263,7 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
if (!DataSize)
return 0;
/* Initialize header struture. */
/* Initialize header structure. */
#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init;
#include "InstrProfData.inc"
@ -172,5 +276,6 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
return -1;
return writeValueProfData(Writer, WriterCtx, ValueDataBegin, DataSize);
return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin,
DataEnd);
}

View file

@ -31,7 +31,6 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <tuple>
using namespace llvm;