mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 13:50:11 +00:00
Reland "[InstrProf][compiler-rt] Enable MC/DC Support in LLVM Source-based Code Coverage (1/3)"
Part 1 of 3. This includes the LLVM back-end processing and profile reading/writing components. compiler-rt changes are included. Differential Revision: https://reviews.llvm.org/D138846
This commit is contained in:
parent
dc8c2a7794
commit
f95b2f1acf
@ -1400,7 +1400,7 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
|
||||
addExportedSymbol(CmdArgs, "_reset_fn_list");
|
||||
}
|
||||
|
||||
// Align __llvm_prf_{cnts,data} sections to the maximum expected page
|
||||
// Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page
|
||||
// alignment. This allows profile counters to be mmap()'d to disk. Note that
|
||||
// it's not enough to just page-align __llvm_prf_cnts: the following section
|
||||
// must also be page-aligned so that its data is not clobbered by mmap().
|
||||
@ -1410,7 +1410,7 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
|
||||
// extra alignment also allows the same binary to be used with/without sync
|
||||
// enabled.
|
||||
if (!ForGCOV) {
|
||||
for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_data}) {
|
||||
for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {
|
||||
addSectalignToPage(
|
||||
Args, CmdArgs, "__DATA",
|
||||
llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
|
||||
|
@ -336,7 +336,7 @@
|
||||
// RUN: FileCheck -check-prefix=PROFILE_SECTALIGN %s < %t.log
|
||||
// RUN: %clang -target arm64-apple-ios12 -fprofile-instr-generate -### %t.o 2> %t.log
|
||||
// RUN: FileCheck -check-prefix=PROFILE_SECTALIGN %s < %t.log
|
||||
// PROFILE_SECTALIGN: "-sectalign" "__DATA" "__llvm_prf_cnts" "0x4000" "-sectalign" "__DATA" "__llvm_prf_data" "0x4000"
|
||||
// PROFILE_SECTALIGN: "-sectalign" "__DATA" "__llvm_prf_cnts" "0x4000" "-sectalign" "__DATA" "__llvm_prf_bits" "0x4000" "-sectalign" "__DATA" "__llvm_prf_data" "0x4000"
|
||||
|
||||
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate --coverage -### %t.o 2> %t.log
|
||||
// RUN: FileCheck -check-prefix=NO_PROFILE_EXPORT %s < %t.log
|
||||
|
@ -76,6 +76,7 @@ INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \
|
||||
ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
|
||||
Inc->getHash()->getZExtValue()))
|
||||
INSTR_PROF_DATA(const IntPtrT, IntPtrTy, CounterPtr, RelativeCounterPtr)
|
||||
INSTR_PROF_DATA(const IntPtrT, IntPtrTy, BitmapPtr, RelativeBitmapPtr)
|
||||
/* This is used to map function pointers for the indirect call targets to
|
||||
* function name hashes during the conversion from raw to merged profile
|
||||
* data.
|
||||
@ -87,7 +88,9 @@ INSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \
|
||||
INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \
|
||||
ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters))
|
||||
INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
|
||||
ConstantArray::get(Int16ArrayTy, Int16ArrayVals))
|
||||
ConstantArray::get(Int16ArrayTy, Int16ArrayVals)) \
|
||||
INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumBitmapBytes, \
|
||||
ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumBitmapBytes))
|
||||
#undef INSTR_PROF_DATA
|
||||
/* INSTR_PROF_DATA end. */
|
||||
|
||||
@ -132,9 +135,13 @@ INSTR_PROF_RAW_HEADER(uint64_t, NumData, NumData)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NumCounters, NumCounters)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NumBitmapBytes, NumBitmapBytes)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterBitmapBytes, PaddingBytesAfterBitmapBytes)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta,
|
||||
(uintptr_t)CountersBegin - (uintptr_t)DataBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, BitmapDelta,
|
||||
(uintptr_t)BitmapBegin - (uintptr_t)DataBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||
#undef INSTR_PROF_RAW_HEADER
|
||||
@ -267,6 +274,9 @@ INSTR_PROF_SECT_ENTRY(IPSK_data, \
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_cnts, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \
|
||||
INSTR_PROF_CNTS_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_bitmap, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_BITS_COMMON), \
|
||||
INSTR_PROF_BITS_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_name, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \
|
||||
INSTR_PROF_NAME_COFF, "__DATA,")
|
||||
@ -645,11 +655,11 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
|
||||
|
||||
/* Raw profile format version (start from 1). */
|
||||
#define INSTR_PROF_RAW_VERSION 8
|
||||
#define INSTR_PROF_RAW_VERSION 9
|
||||
/* Indexed profile format version (start from 1). */
|
||||
#define INSTR_PROF_INDEX_VERSION 10
|
||||
#define INSTR_PROF_INDEX_VERSION 11
|
||||
/* Coverage mapping format version (start from 0). */
|
||||
#define INSTR_PROF_COVMAP_VERSION 5
|
||||
#define INSTR_PROF_COVMAP_VERSION 6
|
||||
|
||||
/* Profile version is always of type uint64_t. Reserve the upper 32 bits in the
|
||||
* version for other variants of profile. We set the 8th most significant bit
|
||||
@ -686,6 +696,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_COMMON __llvm_prf_data
|
||||
#define INSTR_PROF_NAME_COMMON __llvm_prf_names
|
||||
#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts
|
||||
#define INSTR_PROF_BITS_COMMON __llvm_prf_bits
|
||||
#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
|
||||
#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
|
||||
#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
|
||||
@ -697,6 +708,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_COFF ".lprfd$M"
|
||||
#define INSTR_PROF_NAME_COFF ".lprfn$M"
|
||||
#define INSTR_PROF_CNTS_COFF ".lprfc$M"
|
||||
#define INSTR_PROF_BITS_COFF ".lprfb$M"
|
||||
#define INSTR_PROF_VALS_COFF ".lprfv$M"
|
||||
#define INSTR_PROF_VNODES_COFF ".lprfnd$M"
|
||||
#define INSTR_PROF_COVMAP_COFF ".lcovmap$M"
|
||||
@ -708,6 +720,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF
|
||||
#define INSTR_PROF_BITS_SECT_NAME INSTR_PROF_BITS_COFF
|
||||
/* Array of pointers. Each pointer points to a list
|
||||
* of value nodes associated with one value site.
|
||||
*/
|
||||
@ -722,6 +735,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON)
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON)
|
||||
#define INSTR_PROF_BITS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_BITS_COMMON)
|
||||
/* Array of pointers. Each pointer points to a list
|
||||
* of value nodes associated with one value site.
|
||||
*/
|
||||
|
@ -60,6 +60,10 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
|
||||
(__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) ? 0xFF : 0;
|
||||
memset(I, ResetValue, E - I);
|
||||
|
||||
I = __llvm_profile_begin_bitmap();
|
||||
E = __llvm_profile_end_bitmap();
|
||||
memset(I, 0x0, E - I);
|
||||
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const __llvm_profile_data *DI;
|
||||
|
@ -88,6 +88,8 @@ const char *__llvm_profile_begin_names(void);
|
||||
const char *__llvm_profile_end_names(void);
|
||||
char *__llvm_profile_begin_counters(void);
|
||||
char *__llvm_profile_end_counters(void);
|
||||
char *__llvm_profile_begin_bitmap(void);
|
||||
char *__llvm_profile_end_bitmap(void);
|
||||
ValueProfNode *__llvm_profile_begin_vnodes();
|
||||
ValueProfNode *__llvm_profile_end_vnodes();
|
||||
uint32_t *__llvm_profile_begin_orderfile();
|
||||
@ -101,11 +103,11 @@ void __llvm_profile_reset_counters(void);
|
||||
/*!
|
||||
* \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 calling
|
||||
* it. Returns 0 (success) if the profile data is valid. Upon reading
|
||||
* invalid/corrupted profile data, returns 1 (failure).
|
||||
* Read profile data from buffer \p Profile and merge with in-process profile
|
||||
* counters and bitmaps. The client is expected to have checked or already
|
||||
* know the profile data in the buffer matches the in-process counter
|
||||
* structure before calling it. Returns 0 (success) if the profile data is
|
||||
* valid. Upon reading invalid/corrupted profile data, returns 1 (failure).
|
||||
*/
|
||||
int __llvm_profile_merge_from_buffer(const char *Profile, uint64_t Size);
|
||||
|
||||
@ -113,8 +115,8 @@ int __llvm_profile_merge_from_buffer(const char *Profile, uint64_t Size);
|
||||
*
|
||||
* 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).
|
||||
* structurally the in-process counters and bitmaps. 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);
|
||||
@ -276,6 +278,10 @@ uint64_t __llvm_profile_get_num_counters(const char *Begin, const char *End);
|
||||
/*! \brief Get the size of the profile counters section in bytes. */
|
||||
uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End);
|
||||
|
||||
/*! \brief Get the number of bytes in the profile bitmap section. */
|
||||
uint64_t __llvm_profile_get_num_bitmap_bytes(const char *Begin,
|
||||
const char *End);
|
||||
|
||||
/* ! \brief Given the sizes of the data and counter information, return the
|
||||
* number of padding bytes before and after the counters, and after the names,
|
||||
* in the raw profile.
|
||||
@ -286,8 +292,9 @@ uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End);
|
||||
* needed to achieve that.
|
||||
*/
|
||||
void __llvm_profile_get_padding_sizes_for_counters(
|
||||
uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
|
||||
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
|
||||
uint64_t DataSize, uint64_t CountersSize, uint64_t NumBitmapBytes,
|
||||
uint64_t NamesSize, uint64_t *PaddingBytesBeforeCounters,
|
||||
uint64_t *PaddingBytesAfterCounters, uint64_t *PaddingBytesAfterBitmap,
|
||||
uint64_t *PaddingBytesAfterNames);
|
||||
|
||||
/*!
|
||||
|
@ -43,11 +43,14 @@ uint64_t __llvm_profile_get_size_for_buffer(void) {
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const char *CountersBegin = __llvm_profile_begin_counters();
|
||||
const char *CountersEnd = __llvm_profile_end_counters();
|
||||
const char *BitmapBegin = __llvm_profile_begin_bitmap();
|
||||
const char *BitmapEnd = __llvm_profile_end_bitmap();
|
||||
const char *NamesBegin = __llvm_profile_begin_names();
|
||||
const char *NamesEnd = __llvm_profile_end_names();
|
||||
|
||||
return __llvm_profile_get_size_for_buffer_internal(
|
||||
DataBegin, DataEnd, CountersBegin, CountersEnd, NamesBegin, NamesEnd);
|
||||
DataBegin, DataEnd, CountersBegin, CountersEnd, BitmapBegin, BitmapEnd,
|
||||
NamesBegin, NamesEnd);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
@ -83,6 +86,12 @@ uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End) {
|
||||
__llvm_profile_counter_entry_size();
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
uint64_t __llvm_profile_get_num_bitmap_bytes(const char *Begin,
|
||||
const char *End) {
|
||||
return (End - Begin);
|
||||
}
|
||||
|
||||
/// Calculate the number of padding bytes needed to add to \p Offset in order
|
||||
/// for (\p Offset + Padding) to be page-aligned.
|
||||
static uint64_t calculateBytesNeededToPageAlign(uint64_t Offset) {
|
||||
@ -102,13 +111,16 @@ static int needsCounterPadding(void) {
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
void __llvm_profile_get_padding_sizes_for_counters(
|
||||
uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
|
||||
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
|
||||
uint64_t DataSize, uint64_t CountersSize, uint64_t NumBitmapBytes,
|
||||
uint64_t NamesSize, uint64_t *PaddingBytesBeforeCounters,
|
||||
uint64_t *PaddingBytesAfterCounters, uint64_t *PaddingBytesAfterBitmapBytes,
|
||||
uint64_t *PaddingBytesAfterNames) {
|
||||
if (!needsCounterPadding()) {
|
||||
*PaddingBytesBeforeCounters = 0;
|
||||
*PaddingBytesAfterCounters =
|
||||
__llvm_profile_get_num_padding_bytes(CountersSize);
|
||||
*PaddingBytesAfterBitmapBytes =
|
||||
__llvm_profile_get_num_padding_bytes(NumBitmapBytes);
|
||||
*PaddingBytesAfterNames = __llvm_profile_get_num_padding_bytes(NamesSize);
|
||||
return;
|
||||
}
|
||||
@ -118,31 +130,37 @@ void __llvm_profile_get_padding_sizes_for_counters(
|
||||
*PaddingBytesBeforeCounters =
|
||||
calculateBytesNeededToPageAlign(sizeof(__llvm_profile_header) + DataSize);
|
||||
*PaddingBytesAfterCounters = calculateBytesNeededToPageAlign(CountersSize);
|
||||
*PaddingBytesAfterBitmapBytes =
|
||||
calculateBytesNeededToPageAlign(NumBitmapBytes);
|
||||
*PaddingBytesAfterNames = calculateBytesNeededToPageAlign(NamesSize);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
uint64_t __llvm_profile_get_size_for_buffer_internal(
|
||||
const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
|
||||
const char *CountersBegin, const char *CountersEnd, const char *NamesBegin,
|
||||
const char *NamesEnd) {
|
||||
const char *CountersBegin, const char *CountersEnd, const char *BitmapBegin,
|
||||
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd) {
|
||||
/* Match logic in __llvm_profile_write_buffer(). */
|
||||
const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
|
||||
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||
uint64_t CountersSize =
|
||||
__llvm_profile_get_counters_size(CountersBegin, CountersEnd);
|
||||
const uint64_t NumBitmapBytes =
|
||||
__llvm_profile_get_num_bitmap_bytes(BitmapBegin, BitmapEnd);
|
||||
|
||||
/* Determine how much padding is needed before/after the counters and after
|
||||
* the names. */
|
||||
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
|
||||
PaddingBytesAfterNames;
|
||||
PaddingBytesAfterNames, PaddingBytesAfterBitmapBytes;
|
||||
__llvm_profile_get_padding_sizes_for_counters(
|
||||
DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
|
||||
&PaddingBytesAfterCounters, &PaddingBytesAfterNames);
|
||||
DataSize, CountersSize, NumBitmapBytes, NamesSize,
|
||||
&PaddingBytesBeforeCounters, &PaddingBytesAfterCounters,
|
||||
&PaddingBytesAfterBitmapBytes, &PaddingBytesAfterNames);
|
||||
|
||||
return sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) +
|
||||
DataSize + PaddingBytesBeforeCounters + CountersSize +
|
||||
PaddingBytesAfterCounters + NamesSize + PaddingBytesAfterNames;
|
||||
PaddingBytesAfterCounters + NumBitmapBytes +
|
||||
PaddingBytesAfterBitmapBytes + NamesSize + PaddingBytesAfterNames;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
@ -160,9 +178,11 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
|
||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
||||
char *Buffer, const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd, const char *CountersBegin,
|
||||
const char *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
|
||||
const char *CountersEnd, const char *BitmapBegin, const char *BitmapEnd,
|
||||
const char *NamesBegin, const char *NamesEnd) {
|
||||
ProfDataWriter BufferWriter;
|
||||
initBufferWriter(&BufferWriter, Buffer);
|
||||
return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin,
|
||||
CountersEnd, 0, NamesBegin, NamesEnd, 0);
|
||||
CountersEnd, BitmapBegin, BitmapEnd, 0, NamesBegin,
|
||||
NamesEnd, 0);
|
||||
}
|
||||
|
@ -108,14 +108,18 @@ static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const char *CountersBegin = __llvm_profile_begin_counters();
|
||||
const char *CountersEnd = __llvm_profile_end_counters();
|
||||
const char *BitmapBegin = __llvm_profile_begin_bitmap();
|
||||
const char *BitmapEnd = __llvm_profile_end_bitmap();
|
||||
const char *NamesBegin = __llvm_profile_begin_names();
|
||||
const char *NamesEnd = __llvm_profile_end_names();
|
||||
const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
|
||||
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||
uint64_t CountersSize =
|
||||
__llvm_profile_get_counters_size(CountersBegin, CountersEnd);
|
||||
uint64_t NumBitmapBytes =
|
||||
__llvm_profile_get_num_bitmap_bytes(BitmapBegin, BitmapEnd);
|
||||
|
||||
/* Check that the counter and data sections in this image are
|
||||
/* Check that the counter, bitmap, and data sections in this image are
|
||||
* page-aligned. */
|
||||
unsigned PageSize = getpagesize();
|
||||
if ((intptr_t)CountersBegin % PageSize != 0) {
|
||||
@ -123,6 +127,11 @@ static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
|
||||
CountersBegin, PageSize);
|
||||
return 1;
|
||||
}
|
||||
if ((intptr_t)BitmapBegin % PageSize != 0) {
|
||||
PROF_ERR("Bitmap section not page-aligned (start = %p, pagesz = %u).\n",
|
||||
BitmapBegin, PageSize);
|
||||
return 1;
|
||||
}
|
||||
if ((intptr_t)DataBegin % PageSize != 0) {
|
||||
PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
|
||||
DataBegin, PageSize);
|
||||
@ -132,10 +141,11 @@ static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
|
||||
/* Determine how much padding is needed before/after the counters and
|
||||
* after the names. */
|
||||
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
|
||||
PaddingBytesAfterNames;
|
||||
PaddingBytesAfterNames, PaddingBytesAfterBitmapBytes;
|
||||
__llvm_profile_get_padding_sizes_for_counters(
|
||||
DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
|
||||
&PaddingBytesAfterCounters, &PaddingBytesAfterNames);
|
||||
DataSize, CountersSize, NumBitmapBytes, NamesSize,
|
||||
&PaddingBytesBeforeCounters, &PaddingBytesAfterCounters,
|
||||
&PaddingBytesAfterBitmapBytes, &PaddingBytesAfterNames);
|
||||
|
||||
uint64_t PageAlignedCountersLength = CountersSize + PaddingBytesAfterCounters;
|
||||
uint64_t FileOffsetToCounters = CurrentFileOffset +
|
||||
@ -155,6 +165,31 @@ static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
|
||||
FileOffsetToCounters);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Also mmap MCDC bitmap bytes. If there aren't any bitmap bytes, mmap()
|
||||
* will fail with EINVAL. */
|
||||
if (NumBitmapBytes == 0)
|
||||
return 0;
|
||||
|
||||
uint64_t PageAlignedBitmapLength =
|
||||
NumBitmapBytes + PaddingBytesAfterBitmapBytes;
|
||||
uint64_t FileOffsetToBitmap =
|
||||
CurrentFileOffset + sizeof(__llvm_profile_header) + DataSize +
|
||||
PaddingBytesBeforeCounters + CountersSize + PaddingBytesAfterCounters;
|
||||
void *BitmapMmap =
|
||||
mmap((void *)BitmapBegin, PageAlignedBitmapLength, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_SHARED, Fileno, FileOffsetToBitmap);
|
||||
if (BitmapMmap != BitmapBegin) {
|
||||
PROF_ERR(
|
||||
"Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
|
||||
" - BitmapBegin: %p\n"
|
||||
" - PageAlignedBitmapLength: %" PRIu64 "\n"
|
||||
" - Fileno: %d\n"
|
||||
" - FileOffsetToBitmap: %" PRIu64 "\n",
|
||||
strerror(errno), BitmapBegin, PageAlignedBitmapLength, Fileno,
|
||||
FileOffsetToBitmap);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#elif defined(__ELF__) || defined(_WIN32)
|
||||
@ -197,6 +232,8 @@ static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const char *CountersBegin = __llvm_profile_begin_counters();
|
||||
const char *CountersEnd = __llvm_profile_end_counters();
|
||||
const char *BitmapBegin = __llvm_profile_begin_bitmap();
|
||||
const char *BitmapEnd = __llvm_profile_end_bitmap();
|
||||
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||
/* Get the file size. */
|
||||
uint64_t FileSize = 0;
|
||||
@ -218,6 +255,11 @@ static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
|
||||
|
||||
/* Return the memory allocated for counters to OS. */
|
||||
lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd);
|
||||
|
||||
/* BIAS MODE not supported yet for Bitmap (MCDC). */
|
||||
|
||||
/* Return the memory allocated for counters to OS. */
|
||||
lprofReleaseMemoryPagesToOS((uintptr_t)BitmapBegin, (uintptr_t)BitmapEnd);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
@ -21,8 +21,8 @@
|
||||
*/
|
||||
uint64_t __llvm_profile_get_size_for_buffer_internal(
|
||||
const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
|
||||
const char *CountersBegin, const char *CountersEnd, const char *NamesBegin,
|
||||
const char *NamesEnd);
|
||||
const char *CountersBegin, const char *CountersEnd, const char *BitmapBegin,
|
||||
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd);
|
||||
|
||||
/*!
|
||||
* \brief Write instrumentation data to the given buffer, given explicit
|
||||
@ -36,7 +36,8 @@ uint64_t __llvm_profile_get_size_for_buffer_internal(
|
||||
int __llvm_profile_write_buffer_internal(
|
||||
char *Buffer, const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd, const char *CountersBegin,
|
||||
const char *CountersEnd, const char *NamesBegin, const char *NamesEnd);
|
||||
const char *CountersEnd, const char *BitmapBegin, const char *BitmapEnd,
|
||||
const char *NamesBegin, const char *NamesEnd);
|
||||
|
||||
/*!
|
||||
* The data structure describing the data to be written by the
|
||||
@ -153,6 +154,7 @@ int lprofWriteDataImpl(ProfDataWriter *Writer,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd,
|
||||
const char *CountersBegin, const char *CountersEnd,
|
||||
const char *BitmapBegin, const char *BitmapEnd,
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd, int SkipNameDataWrite);
|
||||
|
||||
|
@ -66,6 +66,9 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
|
||||
Header->NumCounters !=
|
||||
__llvm_profile_get_num_counters(__llvm_profile_begin_counters(),
|
||||
__llvm_profile_end_counters()) ||
|
||||
Header->NumBitmapBytes !=
|
||||
__llvm_profile_get_num_bitmap_bytes(__llvm_profile_begin_bitmap(),
|
||||
__llvm_profile_end_bitmap()) ||
|
||||
Header->NamesSize != (uint64_t)(__llvm_profile_end_names() -
|
||||
__llvm_profile_begin_names()) ||
|
||||
Header->ValueKindLast != IPVK_Last)
|
||||
@ -74,7 +77,8 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
|
||||
if (ProfileSize <
|
||||
sizeof(__llvm_profile_header) + Header->BinaryIdsSize +
|
||||
Header->NumData * sizeof(__llvm_profile_data) + Header->NamesSize +
|
||||
Header->NumCounters * __llvm_profile_counter_entry_size())
|
||||
Header->NumCounters * __llvm_profile_counter_entry_size() +
|
||||
Header->NumBitmapBytes)
|
||||
return 1;
|
||||
|
||||
for (SrcData = SrcDataStart,
|
||||
@ -82,7 +86,8 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
|
||||
SrcData < SrcDataEnd; ++SrcData, ++DstData) {
|
||||
if (SrcData->NameRef != DstData->NameRef ||
|
||||
SrcData->FuncHash != DstData->FuncHash ||
|
||||
SrcData->NumCounters != DstData->NumCounters)
|
||||
SrcData->NumCounters != DstData->NumCounters ||
|
||||
SrcData->NumBitmapBytes != DstData->NumBitmapBytes)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -112,9 +117,11 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
|
||||
__llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
|
||||
char *SrcCountersStart, *DstCounter;
|
||||
const char *SrcCountersEnd, *SrcCounter;
|
||||
const char *SrcBitmapStart;
|
||||
const char *SrcNameStart;
|
||||
const char *SrcValueProfDataStart, *SrcValueProfData;
|
||||
uintptr_t CountersDelta = Header->CountersDelta;
|
||||
uintptr_t BitmapDelta = Header->BitmapDelta;
|
||||
|
||||
SrcDataStart =
|
||||
(__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header) +
|
||||
@ -123,11 +130,12 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
|
||||
SrcCountersStart = (char *)SrcDataEnd;
|
||||
SrcCountersEnd = SrcCountersStart +
|
||||
Header->NumCounters * __llvm_profile_counter_entry_size();
|
||||
SrcNameStart = SrcCountersEnd;
|
||||
SrcBitmapStart = SrcCountersEnd;
|
||||
SrcNameStart = SrcBitmapStart + Header->NumBitmapBytes;
|
||||
SrcValueProfDataStart =
|
||||
SrcNameStart + Header->NamesSize +
|
||||
__llvm_profile_get_num_padding_bytes(Header->NamesSize);
|
||||
if (SrcNameStart < SrcCountersStart)
|
||||
if (SrcNameStart < SrcCountersStart || SrcNameStart < SrcBitmapStart)
|
||||
return 1;
|
||||
|
||||
// Merge counters by iterating the entire counter section when debug info
|
||||
@ -157,6 +165,8 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
|
||||
// extend CounterPtr to get the original value.
|
||||
char *DstCounters =
|
||||
(char *)((uintptr_t)DstData + signextIfWin64(DstData->CounterPtr));
|
||||
char *DstBitmap =
|
||||
(char *)((uintptr_t)DstData + signextIfWin64(DstData->BitmapPtr));
|
||||
unsigned NVK = 0;
|
||||
|
||||
// SrcData is a serialized representation of the memory image. We need to
|
||||
@ -186,6 +196,21 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
|
||||
}
|
||||
}
|
||||
|
||||
const char *SrcBitmap =
|
||||
SrcBitmapStart + ((uintptr_t)SrcData->BitmapPtr - BitmapDelta);
|
||||
// BitmapDelta also needs to be decreased as we advance to the next data
|
||||
// record.
|
||||
BitmapDelta -= sizeof(*SrcData);
|
||||
unsigned NB = SrcData->NumBitmapBytes;
|
||||
// NumBitmapBytes may legitimately be 0. Just keep going.
|
||||
if (NB != 0) {
|
||||
if (SrcBitmap < SrcBitmapStart || (SrcBitmap + NB) > SrcNameStart)
|
||||
return 1;
|
||||
// Merge Src and Dst Bitmap bytes by simply ORing them together.
|
||||
for (unsigned I = 0; I < NB; I++)
|
||||
DstBitmap[I] |= SrcBitmap[I];
|
||||
}
|
||||
|
||||
/* Now merge value profile data. */
|
||||
if (!VPMergeHook)
|
||||
continue;
|
||||
|
@ -187,6 +187,8 @@ void __llvm_profile_register_names_function(void *NamesStart,
|
||||
// define these zero length variables in each of the above 4 sections.
|
||||
static int dummy_cnts[0] COMPILER_RT_SECTION(
|
||||
COMPILER_RT_SEG INSTR_PROF_CNTS_SECT_NAME);
|
||||
static int dummy_bits[0] COMPILER_RT_SECTION(
|
||||
COMPILER_RT_SEG INSTR_PROF_BITS_SECT_NAME);
|
||||
static int dummy_data[0] COMPILER_RT_SECTION(
|
||||
COMPILER_RT_SEG INSTR_PROF_DATA_SECT_NAME);
|
||||
static const int dummy_name[0] COMPILER_RT_SECTION(
|
||||
@ -202,8 +204,9 @@ static int dummy_vnds[0] COMPILER_RT_SECTION(
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
#endif
|
||||
COMPILER_RT_VISIBILITY
|
||||
void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_data,
|
||||
(void *)&dummy_name, (void *)&dummy_vnds};
|
||||
void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_bits,
|
||||
(void *)&dummy_data, (void *)&dummy_name,
|
||||
(void *)&dummy_vnds};
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
@ -31,6 +31,11 @@ extern char
|
||||
COMPILER_RT_VISIBILITY
|
||||
extern char CountersEnd __asm("section$end$__DATA$" INSTR_PROF_CNTS_SECT_NAME);
|
||||
COMPILER_RT_VISIBILITY
|
||||
extern char
|
||||
BitmapStart __asm("section$start$__DATA$" INSTR_PROF_BITS_SECT_NAME);
|
||||
COMPILER_RT_VISIBILITY
|
||||
extern char BitmapEnd __asm("section$end$__DATA$" INSTR_PROF_BITS_SECT_NAME);
|
||||
COMPILER_RT_VISIBILITY
|
||||
extern uint32_t
|
||||
OrderFileStart __asm("section$start$__DATA$" INSTR_PROF_ORDERFILE_SECT_NAME);
|
||||
|
||||
@ -56,6 +61,10 @@ char *__llvm_profile_begin_counters(void) { return &CountersStart; }
|
||||
COMPILER_RT_VISIBILITY
|
||||
char *__llvm_profile_end_counters(void) { return &CountersEnd; }
|
||||
COMPILER_RT_VISIBILITY
|
||||
char *__llvm_profile_begin_bitmap(void) { return &BitmapStart; }
|
||||
COMPILER_RT_VISIBILITY
|
||||
char *__llvm_profile_end_bitmap(void) { return &BitmapEnd; }
|
||||
COMPILER_RT_VISIBILITY
|
||||
uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; }
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
|
@ -35,6 +35,8 @@
|
||||
#define PROF_NAME_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_NAME_COMMON)
|
||||
#define PROF_CNTS_START INSTR_PROF_SECT_START(INSTR_PROF_CNTS_COMMON)
|
||||
#define PROF_CNTS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_CNTS_COMMON)
|
||||
#define PROF_BITS_START INSTR_PROF_SECT_START(INSTR_PROF_BITS_COMMON)
|
||||
#define PROF_BITS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_BITS_COMMON)
|
||||
#define PROF_ORDERFILE_START INSTR_PROF_SECT_START(INSTR_PROF_ORDERFILE_COMMON)
|
||||
#define PROF_VNODES_START INSTR_PROF_SECT_START(INSTR_PROF_VNODES_COMMON)
|
||||
#define PROF_VNODES_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNODES_COMMON)
|
||||
@ -48,6 +50,8 @@ extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY
|
||||
COMPILER_RT_WEAK;
|
||||
extern char PROF_CNTS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
|
||||
extern char PROF_CNTS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
|
||||
extern char PROF_BITS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
|
||||
extern char PROF_BITS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
|
||||
extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
|
||||
extern char PROF_NAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
|
||||
extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
|
||||
@ -74,6 +78,12 @@ COMPILER_RT_VISIBILITY char *__llvm_profile_begin_counters(void) {
|
||||
COMPILER_RT_VISIBILITY char *__llvm_profile_end_counters(void) {
|
||||
return &PROF_CNTS_STOP;
|
||||
}
|
||||
COMPILER_RT_VISIBILITY char *__llvm_profile_begin_bitmap(void) {
|
||||
return &PROF_BITS_START;
|
||||
}
|
||||
COMPILER_RT_VISIBILITY char *__llvm_profile_end_bitmap(void) {
|
||||
return &PROF_BITS_STOP;
|
||||
}
|
||||
COMPILER_RT_VISIBILITY uint32_t *__llvm_profile_begin_orderfile(void) {
|
||||
return &PROF_ORDERFILE_START;
|
||||
}
|
||||
|
@ -88,6 +88,10 @@ COMPILER_RT_VISIBILITY
|
||||
char *__llvm_profile_begin_counters(void) { return CountersFirst; }
|
||||
COMPILER_RT_VISIBILITY
|
||||
char *__llvm_profile_end_counters(void) { return CountersLast; }
|
||||
COMPILER_RT_VISIBILITY
|
||||
char *__llvm_profile_begin_bitmap(void) { return BitmapFirst; }
|
||||
COMPILER_RT_VISIBILITY
|
||||
char *__llvm_profile_end_bitmap(void) { return BitmapLast; }
|
||||
/* TODO: correctly set up OrderFileFirst. */
|
||||
COMPILER_RT_VISIBILITY
|
||||
uint32_t *__llvm_profile_begin_orderfile(void) { return OrderFileFirst; }
|
||||
|
@ -14,6 +14,7 @@
|
||||
#if defined(_MSC_VER)
|
||||
/* Merge read-write sections into .data. */
|
||||
#pragma comment(linker, "/MERGE:.lprfc=.data")
|
||||
#pragma comment(linker, "/MERGE:.lprfb=.data")
|
||||
#pragma comment(linker, "/MERGE:.lprfd=.data")
|
||||
#pragma comment(linker, "/MERGE:.lprfv=.data")
|
||||
#pragma comment(linker, "/MERGE:.lprfnd=.data")
|
||||
@ -30,6 +31,8 @@
|
||||
#pragma section(".lprfd$Z", read, write)
|
||||
#pragma section(".lprfc$A", read, write)
|
||||
#pragma section(".lprfc$Z", read, write)
|
||||
#pragma section(".lprfb$A", read, write)
|
||||
#pragma section(".lprfb$Z", read, write)
|
||||
#pragma section(".lorderfile$A", read, write)
|
||||
#pragma section(".lprfnd$A", read, write)
|
||||
#pragma section(".lprfnd$Z", read, write)
|
||||
@ -43,6 +46,8 @@ const char COMPILER_RT_SECTION(".lprfn$Z") NamesEnd = '\0';
|
||||
|
||||
char COMPILER_RT_SECTION(".lprfc$A") CountersStart;
|
||||
char COMPILER_RT_SECTION(".lprfc$Z") CountersEnd;
|
||||
char COMPILER_RT_SECTION(".lprfb$A") BitmapStart;
|
||||
char COMPILER_RT_SECTION(".lprfb$Z") BitmapEnd;
|
||||
uint32_t COMPILER_RT_SECTION(".lorderfile$A") OrderFileStart;
|
||||
|
||||
ValueProfNode COMPILER_RT_SECTION(".lprfnd$A") VNodesStart;
|
||||
@ -58,6 +63,8 @@ const char *__llvm_profile_end_names(void) { return &NamesEnd; }
|
||||
|
||||
char *__llvm_profile_begin_counters(void) { return &CountersStart + 1; }
|
||||
char *__llvm_profile_end_counters(void) { return &CountersEnd; }
|
||||
char *__llvm_profile_begin_bitmap(void) { return &BitmapStart + 1; }
|
||||
char *__llvm_profile_end_bitmap(void) { return &BitmapEnd; }
|
||||
uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; }
|
||||
|
||||
ValueProfNode *__llvm_profile_begin_vnodes(void) { return &VNodesStart + 1; }
|
||||
|
@ -246,17 +246,20 @@ COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer,
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const char *CountersBegin = __llvm_profile_begin_counters();
|
||||
const char *CountersEnd = __llvm_profile_end_counters();
|
||||
const char *BitmapBegin = __llvm_profile_begin_bitmap();
|
||||
const char *BitmapEnd = __llvm_profile_end_bitmap();
|
||||
const char *NamesBegin = __llvm_profile_begin_names();
|
||||
const char *NamesEnd = __llvm_profile_end_names();
|
||||
return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin,
|
||||
CountersEnd, VPDataReader, NamesBegin, NamesEnd,
|
||||
SkipNameDataWrite);
|
||||
CountersEnd, BitmapBegin, BitmapEnd, VPDataReader,
|
||||
NamesBegin, NamesEnd, SkipNameDataWrite);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int
|
||||
lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd,
|
||||
const char *CountersBegin, const char *CountersEnd,
|
||||
const char *BitmapBegin, const char *BitmapEnd,
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd, int SkipNameDataWrite) {
|
||||
int DebugInfoCorrelate =
|
||||
@ -271,6 +274,8 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
|
||||
__llvm_profile_get_counters_size(CountersBegin, CountersEnd);
|
||||
const uint64_t NumCounters =
|
||||
__llvm_profile_get_num_counters(CountersBegin, CountersEnd);
|
||||
const uint64_t NumBitmapBytes =
|
||||
__llvm_profile_get_num_bitmap_bytes(BitmapBegin, BitmapEnd);
|
||||
const uint64_t NamesSize = DebugInfoCorrelate ? 0 : NamesEnd - NamesBegin;
|
||||
|
||||
/* Create the header. */
|
||||
@ -279,11 +284,11 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
|
||||
/* Determine how much padding is needed before/after the counters and after
|
||||
* the names. */
|
||||
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
|
||||
PaddingBytesAfterNames;
|
||||
PaddingBytesAfterNames, PaddingBytesAfterBitmapBytes;
|
||||
__llvm_profile_get_padding_sizes_for_counters(
|
||||
DataSectionSize, CountersSectionSize, NamesSize,
|
||||
DataSectionSize, CountersSectionSize, NumBitmapBytes, NamesSize,
|
||||
&PaddingBytesBeforeCounters, &PaddingBytesAfterCounters,
|
||||
&PaddingBytesAfterNames);
|
||||
&PaddingBytesAfterBitmapBytes, &PaddingBytesAfterNames);
|
||||
|
||||
{
|
||||
/* Initialize header structure. */
|
||||
@ -295,6 +300,7 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
|
||||
* CountersDelta to match. */
|
||||
#ifdef _WIN64
|
||||
Header.CountersDelta = (uint32_t)Header.CountersDelta;
|
||||
Header.BitmapDelta = (uint32_t)Header.BitmapDelta;
|
||||
#endif
|
||||
|
||||
/* The data and names sections are omitted in lightweight mode. */
|
||||
@ -319,6 +325,8 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
|
||||
{NULL, sizeof(uint8_t), PaddingBytesBeforeCounters, 1},
|
||||
{CountersBegin, sizeof(uint8_t), CountersSectionSize, 0},
|
||||
{NULL, sizeof(uint8_t), PaddingBytesAfterCounters, 1},
|
||||
{BitmapBegin, sizeof(uint8_t), NumBitmapBytes, 0},
|
||||
{NULL, sizeof(uint8_t), PaddingBytesAfterBitmapBytes, 1},
|
||||
{(SkipNameDataWrite || DebugInfoCorrelate) ? NULL : NamesBegin,
|
||||
sizeof(uint8_t), NamesSize, 0},
|
||||
{NULL, sizeof(uint8_t), PaddingBytesAfterNames, 1}};
|
||||
|
@ -25,17 +25,18 @@ const char *__llvm_profile_begin_names(void);
|
||||
const char *__llvm_profile_end_names(void);
|
||||
char *__llvm_profile_begin_counters(void);
|
||||
char *__llvm_profile_end_counters(void);
|
||||
char *__llvm_profile_begin_bitmap(void);
|
||||
char *__llvm_profile_end_bitmap(void);
|
||||
|
||||
uint64_t __llvm_profile_get_size_for_buffer_internal(
|
||||
const void *DataBegin, const void *DataEnd, const char *CountersBegin,
|
||||
const char *CountersEnd, const char *NamesBegin, const char *NamesEnd);
|
||||
const char *CountersEnd, const char *BitmapBegin, const char *BitmapEnd,
|
||||
const char *NamesBegin, const char *NamesEnd);
|
||||
|
||||
int __llvm_profile_write_buffer_internal(char *Buffer, const void *DataBegin,
|
||||
const void *DataEnd,
|
||||
const char *CountersBegin,
|
||||
const char *CountersEnd,
|
||||
const char *NamesBegin,
|
||||
const char *NamesEnd);
|
||||
int __llvm_profile_write_buffer_internal(
|
||||
char *Buffer, const void *DataBegin, const void *DataEnd,
|
||||
const char *CountersBegin, const char *CountersEnd, const char *BitmapBegin,
|
||||
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd);
|
||||
|
||||
void __llvm_profile_set_dumped(void);
|
||||
|
||||
@ -43,12 +44,14 @@ int main(int argc, const char *argv[]) {
|
||||
uint64_t bufsize = __llvm_profile_get_size_for_buffer_internal(
|
||||
__llvm_profile_begin_data(), __llvm_profile_end_data(),
|
||||
__llvm_profile_begin_counters(), __llvm_profile_end_counters(),
|
||||
__llvm_profile_begin_bitmap(), __llvm_profile_end_bitmap(),
|
||||
__llvm_profile_begin_names(), __llvm_profile_end_names());
|
||||
|
||||
char *buf = malloc(bufsize);
|
||||
int ret = __llvm_profile_write_buffer_internal(buf,
|
||||
__llvm_profile_begin_data(), __llvm_profile_end_data(),
|
||||
int ret = __llvm_profile_write_buffer_internal(
|
||||
buf, __llvm_profile_begin_data(), __llvm_profile_end_data(),
|
||||
__llvm_profile_begin_counters(), __llvm_profile_end_counters(),
|
||||
__llvm_profile_begin_bitmap(), __llvm_profile_end_bitmap(),
|
||||
__llvm_profile_begin_names(), __llvm_profile_end_names());
|
||||
|
||||
if (ret != 0) {
|
||||
|
@ -13954,6 +13954,144 @@ pass will generate the appropriate data structures and replace the
|
||||
``llvm.instrprof.value.profile`` intrinsic with the call to the profile
|
||||
runtime library with proper arguments.
|
||||
|
||||
'``llvm.instrprof.mcdc.parameters``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
declare void @llvm.instrprof.mcdc.parameters(ptr <name>, i64 <hash>,
|
||||
i32 <bitmap-bytes>)
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``llvm.instrprof.mcdc.parameters``' intrinsic is used to initiate MC/DC
|
||||
code coverage instrumentation for a function.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The first argument is a pointer to a global variable containing the
|
||||
name of the entity being instrumented. This should generally be the
|
||||
(mangled) function name for a set of counters.
|
||||
|
||||
The second argument is a hash value that can be used by the consumer
|
||||
of the profile data to detect changes to the instrumented source.
|
||||
|
||||
The third argument is the number of bitmap bytes required by the function to
|
||||
record the number of test vectors executed for each boolean expression.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
This intrinsic represents basic MC/DC parameters initiating one or more MC/DC
|
||||
instrumentation sequences in a function. It will cause the ``-instrprof`` pass
|
||||
to generate the appropriate data structures and the code to instrument MC/DC
|
||||
test vectors in a format that can be written out by a compiler runtime and
|
||||
consumed via the ``llvm-profdata`` tool.
|
||||
|
||||
'``llvm.instrprof.mcdc.condbitmap.update``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
declare void @llvm.instrprof.mcdc.condbitmap.update(ptr <name>, i64 <hash>,
|
||||
i32 <condition-id>,
|
||||
ptr <mcdc-temp-addr>,
|
||||
i1 <bool-value>)
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``llvm.instrprof.mcdc.condbitmap.update``' intrinsic is used to track
|
||||
MC/DC condition evaluation for each condition in a boolean expression.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The first argument is a pointer to a global variable containing the
|
||||
name of the entity being instrumented. This should generally be the
|
||||
(mangled) function name for a set of counters.
|
||||
|
||||
The second argument is a hash value that can be used by the consumer
|
||||
of the profile data to detect changes to the instrumented source.
|
||||
|
||||
The third argument is an ID of a condition to track. This value is used as a
|
||||
bit index into the condition bitmap.
|
||||
|
||||
The fourth argument is the address of the condition bitmap.
|
||||
|
||||
The fifth argument is the boolean value representing the evaluation of the
|
||||
condition (true or false)
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
This intrinsic represents the update of a condition bitmap that is local to a
|
||||
function and will cause the ``-instrprof`` pass to generate the code to
|
||||
instrument the control flow around each condition in a boolean expression. The
|
||||
ID of each condition corresponds to a bit index in the condition bitmap which
|
||||
is set based on the evaluation of the condition.
|
||||
|
||||
'``llvm.instrprof.mcdc.tvbitmap.update``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
declare void @llvm.instrprof.mcdc.tvbitmap.update(ptr <name>, i64 <hash>,
|
||||
i32 <bitmap-bytes>)
|
||||
i32 <bitmap-index>,
|
||||
ptr <mcdc-temp-addr>)
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``llvm.instrprof.mcdc.tvbitmap.update``' intrinsic is used to track MC/DC
|
||||
test vector execution after each boolean expression has been fully executed.
|
||||
The overall value of the condition bitmap, after it has been successively
|
||||
updated using the '``llvm.instrprof.mcdc.condbitmap.update``' intrinsic with
|
||||
the true or false evaluation of each condition, uniquely identifies an executed
|
||||
MC/DC test vector and is used as a bit index into the global test vector
|
||||
bitmap.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The first argument is a pointer to a global variable containing the
|
||||
name of the entity being instrumented. This should generally be the
|
||||
(mangled) function name for a set of counters.
|
||||
|
||||
The second argument is a hash value that can be used by the consumer
|
||||
of the profile data to detect changes to the instrumented source.
|
||||
|
||||
The third argument is the number of bitmap bytes required by the function to
|
||||
record the number of test vectors executed for each boolean expression.
|
||||
|
||||
The fourth argument is the byte index into the global test vector bitmap
|
||||
corresponding to the function.
|
||||
|
||||
The fifth argument is the address of the condition bitmap, which contains a
|
||||
value representing an executed MC/DC test vector. It is loaded and used as the
|
||||
bit index of the test vector bitmap.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
This intrinsic represents the final operation of an MC/DC instrumentation
|
||||
sequence and will cause the ``-instrprof`` pass to generate the code to
|
||||
instrument an update of a function's global test vector bitmap to indicate that
|
||||
a test vector has been executed. The global test vector bitmap can be consumed
|
||||
by the ``llvm-profdata`` and ``llvm-cov`` tools.
|
||||
|
||||
'``llvm.thread.pointer``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -1424,6 +1424,11 @@ public:
|
||||
ConstantInt *getHash() const {
|
||||
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
|
||||
}
|
||||
};
|
||||
|
||||
/// A base class for all instrprof counter intrinsics.
|
||||
class InstrProfCntrInstBase : public InstrProfInstBase {
|
||||
public:
|
||||
// The number of counters for the instrumented function.
|
||||
ConstantInt *getNumCounters() const;
|
||||
// The index of the counter that this instruction acts on.
|
||||
@ -1431,7 +1436,7 @@ public:
|
||||
};
|
||||
|
||||
/// This represents the llvm.instrprof.cover intrinsic.
|
||||
class InstrProfCoverInst : public InstrProfInstBase {
|
||||
class InstrProfCoverInst : public InstrProfCntrInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_cover;
|
||||
@ -1442,7 +1447,7 @@ public:
|
||||
};
|
||||
|
||||
/// This represents the llvm.instrprof.increment intrinsic.
|
||||
class InstrProfIncrementInst : public InstrProfInstBase {
|
||||
class InstrProfIncrementInst : public InstrProfCntrInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_increment ||
|
||||
@ -1466,7 +1471,7 @@ public:
|
||||
};
|
||||
|
||||
/// This represents the llvm.instrprof.timestamp intrinsic.
|
||||
class InstrProfTimestampInst : public InstrProfInstBase {
|
||||
class InstrProfTimestampInst : public InstrProfCntrInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_timestamp;
|
||||
@ -1477,7 +1482,7 @@ public:
|
||||
};
|
||||
|
||||
/// This represents the llvm.instrprof.value.profile intrinsic.
|
||||
class InstrProfValueProfileInst : public InstrProfInstBase {
|
||||
class InstrProfValueProfileInst : public InstrProfCntrInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_value_profile;
|
||||
@ -1500,6 +1505,87 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// A base class for instrprof mcdc intrinsics that require global bitmap bytes.
|
||||
class InstrProfMCDCBitmapInstBase : public InstrProfInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_parameters ||
|
||||
I->getIntrinsicID() == Intrinsic::instrprof_mcdc_tvbitmap_update;
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
|
||||
/// \return The number of bytes used for the MCDC bitmaps for the instrumented
|
||||
/// function.
|
||||
ConstantInt *getNumBitmapBytes() const {
|
||||
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents the llvm.instrprof.mcdc.parameters intrinsic.
|
||||
class InstrProfMCDCBitmapParameters : public InstrProfMCDCBitmapInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_parameters;
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents the llvm.instrprof.mcdc.tvbitmap.update intrinsic.
|
||||
class InstrProfMCDCTVBitmapUpdate : public InstrProfMCDCBitmapInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_tvbitmap_update;
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
|
||||
/// \return The index of the TestVector Bitmap upon which this intrinsic
|
||||
/// acts.
|
||||
ConstantInt *getBitmapIndex() const {
|
||||
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
|
||||
}
|
||||
|
||||
/// \return The address of the corresponding condition bitmap containing
|
||||
/// the index of the TestVector to update within the TestVector Bitmap.
|
||||
Value *getMCDCCondBitmapAddr() const {
|
||||
return cast<Value>(const_cast<Value *>(getArgOperand(4)));
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents the llvm.instrprof.mcdc.condbitmap.update intrinsic.
|
||||
/// It does not pertain to global bitmap updates or parameters and so doesn't
|
||||
/// inherit from InstrProfMCDCBitmapInstBase.
|
||||
class InstrProfMCDCCondBitmapUpdate : public InstrProfInstBase {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_condbitmap_update;
|
||||
}
|
||||
static bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
|
||||
/// \return The ID of the condition to update.
|
||||
ConstantInt *getCondID() const {
|
||||
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
|
||||
}
|
||||
|
||||
/// \return The address of the corresponding condition bitmap.
|
||||
Value *getMCDCCondBitmapAddr() const {
|
||||
return cast<Value>(const_cast<Value *>(getArgOperand(3)));
|
||||
}
|
||||
|
||||
/// \return The boolean value to set in the condition bitmap for the
|
||||
/// corresponding condition ID. This represents how the condition evaluated.
|
||||
Value *getCondBool() const {
|
||||
return cast<Value>(const_cast<Value *>(getArgOperand(4)));
|
||||
}
|
||||
};
|
||||
|
||||
class PseudoProbeInst : public IntrinsicInst {
|
||||
public:
|
||||
static bool classof(const IntrinsicInst *I) {
|
||||
|
@ -909,6 +909,21 @@ def int_instrprof_value_profile : Intrinsic<[],
|
||||
llvm_i64_ty, llvm_i32_ty,
|
||||
llvm_i32_ty]>;
|
||||
|
||||
// A parameter configuration for instrumentation based MCDC profiling.
|
||||
def int_instrprof_mcdc_parameters : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i64_ty,
|
||||
llvm_i32_ty]>;
|
||||
|
||||
// A test vector bitmap update for instrumentation based MCDC profiling.
|
||||
def int_instrprof_mcdc_tvbitmap_update : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i64_ty,
|
||||
llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty]>;
|
||||
|
||||
// A condition bitmap value update for instrumentation based MCDC profiling.
|
||||
def int_instrprof_mcdc_condbitmap_update : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i64_ty,
|
||||
llvm_i32_ty, llvm_ptr_ty, llvm_i1_ty]>;
|
||||
|
||||
def int_call_preallocated_setup : DefaultAttrsIntrinsic<[llvm_token_ty], [llvm_i32_ty]>;
|
||||
def int_call_preallocated_arg : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_i32_ty]>;
|
||||
def int_call_preallocated_teardown : DefaultAttrsIntrinsic<[], [llvm_token_ty]>;
|
||||
|
@ -1027,7 +1027,9 @@ enum CovMapVersion {
|
||||
// Compilation directory is stored separately and combined with relative
|
||||
// filenames to produce an absolute file path.
|
||||
Version6 = 5,
|
||||
// The current version is Version6.
|
||||
// Branch regions extended and Decision Regions added for MC/DC.
|
||||
Version7 = 6,
|
||||
// The current version is Version7.
|
||||
CurrentVersion = INSTR_PROF_COVMAP_VERSION
|
||||
};
|
||||
|
||||
|
@ -96,6 +96,9 @@ inline StringRef getInstrProfDataVarPrefix() { return "__profd_"; }
|
||||
/// Return the name prefix of profile counter variables.
|
||||
inline StringRef getInstrProfCountersVarPrefix() { return "__profc_"; }
|
||||
|
||||
/// Return the name prefix of profile bitmap variables.
|
||||
inline StringRef getInstrProfBitmapVarPrefix() { return "__profbm_"; }
|
||||
|
||||
/// Return the name prefix of value profile variables.
|
||||
inline StringRef getInstrProfValuesVarPrefix() { return "__profvp_"; }
|
||||
|
||||
@ -338,6 +341,7 @@ enum class instrprof_error {
|
||||
invalid_prof,
|
||||
hash_mismatch,
|
||||
count_mismatch,
|
||||
bitmap_mismatch,
|
||||
counter_overflow,
|
||||
value_site_count_mismatch,
|
||||
compress_failed,
|
||||
@ -693,18 +697,23 @@ struct InstrProfValueSiteRecord {
|
||||
/// Profiling information for a single function.
|
||||
struct InstrProfRecord {
|
||||
std::vector<uint64_t> Counts;
|
||||
std::vector<uint8_t> BitmapBytes;
|
||||
|
||||
InstrProfRecord() = default;
|
||||
InstrProfRecord(std::vector<uint64_t> Counts) : Counts(std::move(Counts)) {}
|
||||
InstrProfRecord(std::vector<uint64_t> Counts,
|
||||
std::vector<uint8_t> BitmapBytes)
|
||||
: Counts(std::move(Counts)), BitmapBytes(std::move(BitmapBytes)) {}
|
||||
InstrProfRecord(InstrProfRecord &&) = default;
|
||||
InstrProfRecord(const InstrProfRecord &RHS)
|
||||
: Counts(RHS.Counts),
|
||||
: Counts(RHS.Counts), BitmapBytes(RHS.BitmapBytes),
|
||||
ValueData(RHS.ValueData
|
||||
? std::make_unique<ValueProfData>(*RHS.ValueData)
|
||||
: nullptr) {}
|
||||
InstrProfRecord &operator=(InstrProfRecord &&) = default;
|
||||
InstrProfRecord &operator=(const InstrProfRecord &RHS) {
|
||||
Counts = RHS.Counts;
|
||||
BitmapBytes = RHS.BitmapBytes;
|
||||
if (!RHS.ValueData) {
|
||||
ValueData = nullptr;
|
||||
return *this;
|
||||
@ -883,6 +892,11 @@ struct NamedInstrProfRecord : InstrProfRecord {
|
||||
NamedInstrProfRecord(StringRef Name, uint64_t Hash,
|
||||
std::vector<uint64_t> Counts)
|
||||
: InstrProfRecord(std::move(Counts)), Name(Name), Hash(Hash) {}
|
||||
NamedInstrProfRecord(StringRef Name, uint64_t Hash,
|
||||
std::vector<uint64_t> Counts,
|
||||
std::vector<uint8_t> BitmapBytes)
|
||||
: InstrProfRecord(std::move(Counts), std::move(BitmapBytes)), Name(Name),
|
||||
Hash(Hash) {}
|
||||
|
||||
static bool hasCSFlagInHash(uint64_t FuncHash) {
|
||||
return ((FuncHash >> CS_FLAG_IN_FUNC_HASH) & 1);
|
||||
@ -1014,7 +1028,9 @@ enum ProfVersion {
|
||||
Version9 = 9,
|
||||
// An additional (optional) temporal profile traces section is added.
|
||||
Version10 = 10,
|
||||
// The current version is 10.
|
||||
// An additional field is used for bitmap bytes.
|
||||
Version11 = 11,
|
||||
// The current version is 11.
|
||||
CurrentVersion = INSTR_PROF_INDEX_VERSION
|
||||
};
|
||||
const uint64_t Version = ProfVersion::CurrentVersion;
|
||||
@ -1152,6 +1168,7 @@ namespace RawInstrProf {
|
||||
// Version 6: Added binary id.
|
||||
// Version 7: Reorder binary id and include version in signature.
|
||||
// Version 8: Use relative counter pointer.
|
||||
// Version 9: Added relative bitmap bytes pointer and count used by MC/DC.
|
||||
const uint64_t Version = INSTR_PROF_RAW_VERSION;
|
||||
|
||||
template <class IntPtrT> inline uint64_t getMagic();
|
||||
|
@ -76,6 +76,7 @@ INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \
|
||||
ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
|
||||
Inc->getHash()->getZExtValue()))
|
||||
INSTR_PROF_DATA(const IntPtrT, IntPtrTy, CounterPtr, RelativeCounterPtr)
|
||||
INSTR_PROF_DATA(const IntPtrT, IntPtrTy, BitmapPtr, RelativeBitmapPtr)
|
||||
/* This is used to map function pointers for the indirect call targets to
|
||||
* function name hashes during the conversion from raw to merged profile
|
||||
* data.
|
||||
@ -87,7 +88,9 @@ INSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \
|
||||
INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \
|
||||
ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters))
|
||||
INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
|
||||
ConstantArray::get(Int16ArrayTy, Int16ArrayVals))
|
||||
ConstantArray::get(Int16ArrayTy, Int16ArrayVals)) \
|
||||
INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumBitmapBytes, \
|
||||
ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumBitmapBytes))
|
||||
#undef INSTR_PROF_DATA
|
||||
/* INSTR_PROF_DATA end. */
|
||||
|
||||
@ -132,9 +135,13 @@ INSTR_PROF_RAW_HEADER(uint64_t, NumData, NumData)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NumCounters, NumCounters)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NumBitmapBytes, NumBitmapBytes)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterBitmapBytes, PaddingBytesAfterBitmapBytes)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta,
|
||||
(uintptr_t)CountersBegin - (uintptr_t)DataBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, BitmapDelta,
|
||||
(uintptr_t)BitmapBegin - (uintptr_t)DataBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||
#undef INSTR_PROF_RAW_HEADER
|
||||
@ -267,6 +274,9 @@ INSTR_PROF_SECT_ENTRY(IPSK_data, \
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_cnts, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \
|
||||
INSTR_PROF_CNTS_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_bitmap, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_BITS_COMMON), \
|
||||
INSTR_PROF_BITS_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_name, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \
|
||||
INSTR_PROF_NAME_COFF, "__DATA,")
|
||||
@ -645,11 +655,11 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
|
||||
|
||||
/* Raw profile format version (start from 1). */
|
||||
#define INSTR_PROF_RAW_VERSION 8
|
||||
#define INSTR_PROF_RAW_VERSION 9
|
||||
/* Indexed profile format version (start from 1). */
|
||||
#define INSTR_PROF_INDEX_VERSION 10
|
||||
#define INSTR_PROF_INDEX_VERSION 11
|
||||
/* Coverage mapping format version (start from 0). */
|
||||
#define INSTR_PROF_COVMAP_VERSION 5
|
||||
#define INSTR_PROF_COVMAP_VERSION 6
|
||||
|
||||
/* Profile version is always of type uint64_t. Reserve the upper 32 bits in the
|
||||
* version for other variants of profile. We set the 8th most significant bit
|
||||
@ -686,6 +696,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_COMMON __llvm_prf_data
|
||||
#define INSTR_PROF_NAME_COMMON __llvm_prf_names
|
||||
#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts
|
||||
#define INSTR_PROF_BITS_COMMON __llvm_prf_bits
|
||||
#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
|
||||
#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
|
||||
#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
|
||||
@ -697,6 +708,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_COFF ".lprfd$M"
|
||||
#define INSTR_PROF_NAME_COFF ".lprfn$M"
|
||||
#define INSTR_PROF_CNTS_COFF ".lprfc$M"
|
||||
#define INSTR_PROF_BITS_COFF ".lprfb$M"
|
||||
#define INSTR_PROF_VALS_COFF ".lprfv$M"
|
||||
#define INSTR_PROF_VNODES_COFF ".lprfnd$M"
|
||||
#define INSTR_PROF_COVMAP_COFF ".lcovmap$M"
|
||||
@ -708,6 +720,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF
|
||||
#define INSTR_PROF_BITS_SECT_NAME INSTR_PROF_BITS_COFF
|
||||
/* Array of pointers. Each pointer points to a list
|
||||
* of value nodes associated with one value site.
|
||||
*/
|
||||
@ -722,6 +735,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON)
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON)
|
||||
#define INSTR_PROF_BITS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_BITS_COMMON)
|
||||
/* Array of pointers. Each pointer points to a list
|
||||
* of value nodes associated with one value site.
|
||||
*/
|
||||
|
@ -323,11 +323,14 @@ private:
|
||||
// the variant types of the profile.
|
||||
uint64_t Version;
|
||||
uint64_t CountersDelta;
|
||||
uint64_t BitmapDelta;
|
||||
uint64_t NamesDelta;
|
||||
const RawInstrProf::ProfileData<IntPtrT> *Data;
|
||||
const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
|
||||
const char *CountersStart;
|
||||
const char *CountersEnd;
|
||||
const char *BitmapStart;
|
||||
const char *BitmapEnd;
|
||||
const char *NamesStart;
|
||||
const char *NamesEnd;
|
||||
// After value profile is all read, this pointer points to
|
||||
@ -428,6 +431,7 @@ private:
|
||||
Error readName(NamedInstrProfRecord &Record);
|
||||
Error readFuncHash(NamedInstrProfRecord &Record);
|
||||
Error readRawCounts(InstrProfRecord &Record);
|
||||
Error readRawBitmapBytes(InstrProfRecord &Record);
|
||||
Error readValueProfilingData(InstrProfRecord &Record);
|
||||
bool atEnd() const { return Data == DataEnd; }
|
||||
|
||||
@ -440,6 +444,7 @@ private:
|
||||
// As we advance to the next record, we maintain the correct CountersDelta
|
||||
// with respect to the next record.
|
||||
CountersDelta -= sizeof(*Data);
|
||||
BitmapDelta -= sizeof(*Data);
|
||||
}
|
||||
Data++;
|
||||
ValueDataStart += CurValueDataSize;
|
||||
@ -733,6 +738,10 @@ public:
|
||||
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
|
||||
std::vector<uint64_t> &Counts);
|
||||
|
||||
/// Fill Bitmap Bytes with the profile data for the given function name.
|
||||
Error getFunctionBitmapBytes(StringRef FuncName, uint64_t FuncHash,
|
||||
std::vector<uint8_t> &BitmapBytes);
|
||||
|
||||
/// Return the maximum of all known function counts.
|
||||
/// \c UseCS indicates whether to use the context-sensitive count.
|
||||
uint64_t getMaximumFunctionCount(bool UseCS) {
|
||||
|
@ -50,6 +50,7 @@ private:
|
||||
uint32_t NumValueSites[IPVK_Last + 1];
|
||||
GlobalVariable *RegionCounters = nullptr;
|
||||
GlobalVariable *DataVar = nullptr;
|
||||
GlobalVariable *RegionBitmaps = nullptr;
|
||||
|
||||
PerFunctionProfileData() {
|
||||
memset(NumValueSites, 0, sizeof(uint32_t) * (IPVK_Last + 1));
|
||||
@ -105,20 +106,59 @@ private:
|
||||
/// Force emitting of name vars for unused functions.
|
||||
void lowerCoverageData(GlobalVariable *CoverageNamesVar);
|
||||
|
||||
/// Replace instrprof.mcdc.tvbitmask.update with a shift and or instruction
|
||||
/// using the index represented by the a temp value into a bitmap.
|
||||
void lowerMCDCTestVectorBitmapUpdate(InstrProfMCDCTVBitmapUpdate *Ins);
|
||||
|
||||
/// Replace instrprof.mcdc.temp.update with a shift and or instruction using
|
||||
/// the corresponding condition ID.
|
||||
void lowerMCDCCondBitmapUpdate(InstrProfMCDCCondBitmapUpdate *Ins);
|
||||
|
||||
/// Compute the address of the counter value that this profiling instruction
|
||||
/// acts on.
|
||||
Value *getCounterAddress(InstrProfInstBase *I);
|
||||
Value *getCounterAddress(InstrProfCntrInstBase *I);
|
||||
|
||||
/// Get the region counters for an increment, creating them if necessary.
|
||||
///
|
||||
/// If the counter array doesn't yet exist, the profile data variables
|
||||
/// referring to them will also be created.
|
||||
GlobalVariable *getOrCreateRegionCounters(InstrProfInstBase *Inc);
|
||||
GlobalVariable *getOrCreateRegionCounters(InstrProfCntrInstBase *Inc);
|
||||
|
||||
/// Create the region counters.
|
||||
GlobalVariable *createRegionCounters(InstrProfInstBase *Inc, StringRef Name,
|
||||
GlobalVariable *createRegionCounters(InstrProfCntrInstBase *Inc,
|
||||
StringRef Name,
|
||||
GlobalValue::LinkageTypes Linkage);
|
||||
|
||||
/// Compute the address of the test vector bitmap that this profiling
|
||||
/// instruction acts on.
|
||||
Value *getBitmapAddress(InstrProfMCDCTVBitmapUpdate *I);
|
||||
|
||||
/// Get the region bitmaps for an increment, creating them if necessary.
|
||||
///
|
||||
/// If the bitmap array doesn't yet exist, the profile data variables
|
||||
/// referring to them will also be created.
|
||||
GlobalVariable *getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc);
|
||||
|
||||
/// Create the MC/DC bitmap as a byte-aligned array of bytes associated with
|
||||
/// an MC/DC Decision region. The number of bytes required is indicated by
|
||||
/// the intrinsic used (type InstrProfMCDCBitmapInstBase). This is called
|
||||
/// as part of setupProfileSection() and is conceptually very similar to
|
||||
/// what is done for profile data counters in createRegionCounters().
|
||||
GlobalVariable *createRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc,
|
||||
StringRef Name,
|
||||
GlobalValue::LinkageTypes Linkage);
|
||||
|
||||
/// Set Comdat property of GV, if required.
|
||||
void maybeSetComdat(GlobalVariable *GV, Function *Fn, StringRef VarName);
|
||||
|
||||
/// Setup the sections into which counters and bitmaps are allocated.
|
||||
GlobalVariable *setupProfileSection(InstrProfInstBase *Inc,
|
||||
InstrProfSectKind IPSK);
|
||||
|
||||
/// Create INSTR_PROF_DATA variable for counters and bitmaps.
|
||||
void createDataVariable(InstrProfCntrInstBase *Inc,
|
||||
InstrProfMCDCBitmapParameters *Update);
|
||||
|
||||
/// Emit the section with compressed function names.
|
||||
void emitNameData();
|
||||
|
||||
|
@ -7197,6 +7197,12 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
|
||||
llvm_unreachable("instrprof failed to lower a timestamp");
|
||||
case Intrinsic::instrprof_value_profile:
|
||||
llvm_unreachable("instrprof failed to lower a value profiling call");
|
||||
case Intrinsic::instrprof_mcdc_parameters:
|
||||
llvm_unreachable("instrprof failed to lower mcdc parameters");
|
||||
case Intrinsic::instrprof_mcdc_tvbitmap_update:
|
||||
llvm_unreachable("instrprof failed to lower an mcdc tvbitmap update");
|
||||
case Intrinsic::instrprof_mcdc_condbitmap_update:
|
||||
llvm_unreachable("instrprof failed to lower an mcdc condbitmap update");
|
||||
case Intrinsic::localescape: {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
const TargetInstrInfo *TII = DAG.getSubtarget().getInstrInfo();
|
||||
|
@ -270,13 +270,13 @@ int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ConstantInt *InstrProfInstBase::getNumCounters() const {
|
||||
ConstantInt *InstrProfCntrInstBase::getNumCounters() const {
|
||||
if (InstrProfValueProfileInst::classof(this))
|
||||
llvm_unreachable("InstrProfValueProfileInst does not have counters!");
|
||||
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
|
||||
}
|
||||
|
||||
ConstantInt *InstrProfInstBase::getIndex() const {
|
||||
ConstantInt *InstrProfCntrInstBase::getIndex() const {
|
||||
if (InstrProfValueProfileInst::classof(this))
|
||||
llvm_unreachable("Please use InstrProfValueProfileInst::getIndex()");
|
||||
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
|
||||
|
@ -783,6 +783,7 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
|
||||
case CovMapVersion::Version4:
|
||||
case CovMapVersion::Version5:
|
||||
case CovMapVersion::Version6:
|
||||
case CovMapVersion::Version7:
|
||||
// Decompress the name data.
|
||||
if (Error E = P.create(P.getNameData()))
|
||||
return std::move(E);
|
||||
@ -801,6 +802,9 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
|
||||
else if (Version == CovMapVersion::Version6)
|
||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||
CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
|
||||
else if (Version == CovMapVersion::Version7)
|
||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||
CovMapVersion::Version7, IntPtrT, Endian>>(P, R, D, F);
|
||||
}
|
||||
llvm_unreachable("Unsupported version");
|
||||
}
|
||||
|
@ -136,6 +136,9 @@ static std::string getInstrProfErrString(instrprof_error Err,
|
||||
case instrprof_error::count_mismatch:
|
||||
OS << "function basic block count change detected (counter mismatch)";
|
||||
break;
|
||||
case instrprof_error::bitmap_mismatch:
|
||||
OS << "function bitmap size change detected (bitmap size mismatch)";
|
||||
break;
|
||||
case instrprof_error::counter_overflow:
|
||||
OS << "counter overflow";
|
||||
break;
|
||||
@ -815,6 +818,18 @@ void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight,
|
||||
Warn(instrprof_error::counter_overflow);
|
||||
}
|
||||
|
||||
// If the number of bitmap bytes doesn't match we either have bad data
|
||||
// or a hash collision.
|
||||
if (BitmapBytes.size() != Other.BitmapBytes.size()) {
|
||||
Warn(instrprof_error::bitmap_mismatch);
|
||||
return;
|
||||
}
|
||||
|
||||
// Bitmap bytes are merged by simply ORing them together.
|
||||
for (size_t I = 0, E = Other.BitmapBytes.size(); I < E; ++I) {
|
||||
BitmapBytes[I] = Other.BitmapBytes[I] | BitmapBytes[I];
|
||||
}
|
||||
|
||||
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
|
||||
mergeValueProfData(Kind, Other, Weight, Warn);
|
||||
}
|
||||
@ -1487,9 +1502,11 @@ Expected<Header> Header::readFromBuffer(const unsigned char *Buffer) {
|
||||
// When a new field is added in the header add a case statement here to
|
||||
// populate it.
|
||||
static_assert(
|
||||
IndexedInstrProf::ProfVersion::CurrentVersion == Version10,
|
||||
IndexedInstrProf::ProfVersion::CurrentVersion == Version11,
|
||||
"Please update the reading code below if a new field has been added, "
|
||||
"if not add a case statement to fall through to the latest version.");
|
||||
case 11ull:
|
||||
[[fallthrough]];
|
||||
case 10ull:
|
||||
H.TemporalProfTracesOffset =
|
||||
read(Buffer, offsetOf(&Header::TemporalProfTracesOffset));
|
||||
@ -1513,10 +1530,12 @@ size_t Header::size() const {
|
||||
// When a new field is added to the header add a case statement here to
|
||||
// compute the size as offset of the new field + size of the new field. This
|
||||
// relies on the field being added to the end of the list.
|
||||
static_assert(IndexedInstrProf::ProfVersion::CurrentVersion == Version10,
|
||||
static_assert(IndexedInstrProf::ProfVersion::CurrentVersion == Version11,
|
||||
"Please update the size computation below if a new field has "
|
||||
"been added to the header, if not add a case statement to "
|
||||
"fall through to the latest version.");
|
||||
case 11ull:
|
||||
[[fallthrough]];
|
||||
case 10ull:
|
||||
return offsetOf(&Header::TemporalProfTracesOffset) +
|
||||
sizeof(Header::TemporalProfTracesOffset);
|
||||
|
@ -210,11 +210,15 @@ void InstrProfCorrelatorImpl<IntPtrT>::addProbe(StringRef FunctionName,
|
||||
// In this mode, CounterPtr actually stores the section relative address
|
||||
// of the counter.
|
||||
maybeSwap<IntPtrT>(CounterOffset),
|
||||
// TODO: MC/DC is not yet supported.
|
||||
/*BitmapOffset=*/maybeSwap<IntPtrT>(0),
|
||||
maybeSwap<IntPtrT>(FunctionPtr),
|
||||
// TODO: Value profiling is not yet supported.
|
||||
/*ValuesPtr=*/maybeSwap<IntPtrT>(0),
|
||||
maybeSwap<uint32_t>(NumCounters),
|
||||
/*NumValueSites=*/{maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)},
|
||||
// TODO: MC/DC is not yet supported.
|
||||
/*NumBitmapBytes=*/maybeSwap<uint32_t>(0),
|
||||
});
|
||||
NamesVec.push_back(FunctionName.str());
|
||||
}
|
||||
|
@ -434,6 +434,29 @@ Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
|
||||
Record.Counts.push_back(Count);
|
||||
}
|
||||
|
||||
// Bitmap byte information is indicated with special character.
|
||||
if (Line->startswith("$")) {
|
||||
Record.BitmapBytes.clear();
|
||||
// Read the number of bitmap bytes.
|
||||
uint64_t NumBitmapBytes;
|
||||
if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes))
|
||||
return error(instrprof_error::malformed,
|
||||
"number of bitmap bytes is not a valid integer");
|
||||
if (NumBitmapBytes != 0) {
|
||||
// Read each bitmap and fill our internal storage with the values.
|
||||
Record.BitmapBytes.reserve(NumBitmapBytes);
|
||||
for (uint8_t I = 0; I < NumBitmapBytes; ++I) {
|
||||
if (Line.is_at_end())
|
||||
return error(instrprof_error::truncated);
|
||||
uint8_t BitmapByte;
|
||||
if ((Line++)->getAsInteger(0, BitmapByte))
|
||||
return error(instrprof_error::malformed,
|
||||
"bitmap byte is not a valid integer");
|
||||
Record.BitmapBytes.push_back(BitmapByte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if value profile data exists and read it if so.
|
||||
if (Error E = readValueProfileData(Record))
|
||||
return error(std::move(E));
|
||||
@ -550,11 +573,14 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
|
||||
return error(instrprof_error::bad_header);
|
||||
|
||||
CountersDelta = swap(Header.CountersDelta);
|
||||
BitmapDelta = swap(Header.BitmapDelta);
|
||||
NamesDelta = swap(Header.NamesDelta);
|
||||
auto NumData = swap(Header.NumData);
|
||||
auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
|
||||
auto CountersSize = swap(Header.NumCounters) * getCounterTypeSize();
|
||||
auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
|
||||
auto NumBitmapBytes = swap(Header.NumBitmapBytes);
|
||||
auto PaddingBytesAfterBitmapBytes = swap(Header.PaddingBytesAfterBitmapBytes);
|
||||
auto NamesSize = swap(Header.NamesSize);
|
||||
ValueKindLast = swap(Header.ValueKindLast);
|
||||
|
||||
@ -564,8 +590,10 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
|
||||
// Profile data starts after profile header and binary ids if exist.
|
||||
ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize;
|
||||
ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
|
||||
ptrdiff_t NamesOffset =
|
||||
ptrdiff_t BitmapOffset =
|
||||
CountersOffset + CountersSize + PaddingBytesAfterCounters;
|
||||
ptrdiff_t NamesOffset =
|
||||
BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes;
|
||||
ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
|
||||
|
||||
auto *Start = reinterpret_cast<const char *>(&Header);
|
||||
@ -594,6 +622,8 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
|
||||
reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
|
||||
CountersStart = Start + CountersOffset;
|
||||
CountersEnd = CountersStart + CountersSize;
|
||||
BitmapStart = Start + BitmapOffset;
|
||||
BitmapEnd = BitmapStart + NumBitmapBytes;
|
||||
ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
|
||||
|
||||
const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
|
||||
@ -684,6 +714,49 @@ Error RawInstrProfReader<IntPtrT>::readRawCounts(
|
||||
return success();
|
||||
}
|
||||
|
||||
template <class IntPtrT>
|
||||
Error RawInstrProfReader<IntPtrT>::readRawBitmapBytes(InstrProfRecord &Record) {
|
||||
uint32_t NumBitmapBytes = swap(Data->NumBitmapBytes);
|
||||
|
||||
Record.BitmapBytes.clear();
|
||||
Record.BitmapBytes.reserve(NumBitmapBytes);
|
||||
|
||||
// It's possible MCDC is either not enabled or only used for some functions
|
||||
// and not others. So if we record 0 bytes, just move on.
|
||||
if (NumBitmapBytes == 0)
|
||||
return success();
|
||||
|
||||
// BitmapDelta decreases as we advance to the next data record.
|
||||
ptrdiff_t BitmapOffset = swap(Data->BitmapPtr) - BitmapDelta;
|
||||
if (BitmapOffset < 0)
|
||||
return error(
|
||||
instrprof_error::malformed,
|
||||
("bitmap offset " + Twine(BitmapOffset) + " is negative").str());
|
||||
|
||||
if (BitmapOffset >= BitmapEnd - BitmapStart)
|
||||
return error(instrprof_error::malformed,
|
||||
("bitmap offset " + Twine(BitmapOffset) +
|
||||
" is greater than the maximum bitmap offset " +
|
||||
Twine(BitmapEnd - BitmapStart - 1))
|
||||
.str());
|
||||
|
||||
uint64_t MaxNumBitmapBytes =
|
||||
(BitmapEnd - (BitmapStart + BitmapOffset)) / sizeof(uint8_t);
|
||||
if (NumBitmapBytes > MaxNumBitmapBytes)
|
||||
return error(instrprof_error::malformed,
|
||||
("number of bitmap bytes " + Twine(NumBitmapBytes) +
|
||||
" is greater than the maximum number of bitmap bytes " +
|
||||
Twine(MaxNumBitmapBytes))
|
||||
.str());
|
||||
|
||||
for (uint32_t I = 0; I < NumBitmapBytes; I++) {
|
||||
const char *Ptr = BitmapStart + BitmapOffset + I;
|
||||
Record.BitmapBytes.push_back(swap(*Ptr));
|
||||
}
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
template <class IntPtrT>
|
||||
Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
|
||||
InstrProfRecord &Record) {
|
||||
@ -734,6 +807,10 @@ Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record)
|
||||
if (Error E = readRawCounts(Record))
|
||||
return error(std::move(E));
|
||||
|
||||
// Read raw bitmap bytes and set Record.
|
||||
if (Error E = readRawBitmapBytes(Record))
|
||||
return error(std::move(E));
|
||||
|
||||
// Read value data and set Record.
|
||||
if (Error E = readValueProfilingData(Record))
|
||||
return error(std::move(E));
|
||||
@ -795,6 +872,7 @@ data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
|
||||
|
||||
DataBuffer.clear();
|
||||
std::vector<uint64_t> CounterBuffer;
|
||||
std::vector<uint8_t> BitmapByteBuffer;
|
||||
|
||||
const unsigned char *End = D + N;
|
||||
while (D < End) {
|
||||
@ -823,7 +901,26 @@ data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
|
||||
CounterBuffer.push_back(
|
||||
endian::readNext<uint64_t, llvm::endianness::little, unaligned>(D));
|
||||
|
||||
DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
|
||||
// Read bitmap bytes for GET_VERSION(FormatVersion) > 10.
|
||||
if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version10) {
|
||||
uint64_t BitmapBytes = 0;
|
||||
if (D + sizeof(uint64_t) > End)
|
||||
return data_type();
|
||||
BitmapBytes =
|
||||
endian::readNext<uint64_t, llvm::endianness::little, unaligned>(D);
|
||||
// Read bitmap byte values.
|
||||
if (D + BitmapBytes * sizeof(uint8_t) > End)
|
||||
return data_type();
|
||||
BitmapByteBuffer.clear();
|
||||
BitmapByteBuffer.reserve(BitmapBytes);
|
||||
for (uint64_t J = 0; J < BitmapBytes; ++J)
|
||||
BitmapByteBuffer.push_back(static_cast<uint8_t>(
|
||||
endian::readNext<uint64_t, llvm::endianness::little, unaligned>(
|
||||
D)));
|
||||
}
|
||||
|
||||
DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer),
|
||||
std::move(BitmapByteBuffer));
|
||||
|
||||
// Read value profiling data.
|
||||
if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
|
||||
@ -1337,6 +1434,16 @@ Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
|
||||
return success();
|
||||
}
|
||||
|
||||
Error IndexedInstrProfReader::getFunctionBitmapBytes(
|
||||
StringRef FuncName, uint64_t FuncHash, std::vector<uint8_t> &BitmapBytes) {
|
||||
Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
|
||||
if (Error E = Record.takeError())
|
||||
return error(std::move(E));
|
||||
|
||||
BitmapBytes = Record.get().BitmapBytes;
|
||||
return success();
|
||||
}
|
||||
|
||||
Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
|
||||
ArrayRef<NamedInstrProfRecord> Data;
|
||||
|
||||
|
@ -132,6 +132,8 @@ public:
|
||||
M += sizeof(uint64_t); // The function hash
|
||||
M += sizeof(uint64_t); // The size of the Counts vector
|
||||
M += ProfRecord.Counts.size() * sizeof(uint64_t);
|
||||
M += sizeof(uint64_t); // The size of the Bitmap vector
|
||||
M += ProfRecord.BitmapBytes.size() * sizeof(uint64_t);
|
||||
|
||||
// Value data
|
||||
M += ValueProfData::getSize(ProfileData.second);
|
||||
@ -161,6 +163,10 @@ public:
|
||||
for (uint64_t I : ProfRecord.Counts)
|
||||
LE.write<uint64_t>(I);
|
||||
|
||||
LE.write<uint64_t>(ProfRecord.BitmapBytes.size());
|
||||
for (uint64_t I : ProfRecord.BitmapBytes)
|
||||
LE.write<uint64_t>(I);
|
||||
|
||||
// Write value data
|
||||
std::unique_ptr<ValueProfData> VDataPtr =
|
||||
ValueProfData::serializeFrom(ProfileData.second);
|
||||
@ -380,6 +386,8 @@ bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
|
||||
const InstrProfRecord &IPR = Func.second;
|
||||
if (llvm::any_of(IPR.Counts, [](uint64_t Count) { return Count > 0; }))
|
||||
return true;
|
||||
if (llvm::any_of(IPR.BitmapBytes, [](uint8_t Byte) { return Byte > 0; }))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -703,6 +711,17 @@ void InstrProfWriter::writeRecordInText(StringRef Name, uint64_t Hash,
|
||||
for (uint64_t Count : Func.Counts)
|
||||
OS << Count << "\n";
|
||||
|
||||
if (Func.BitmapBytes.size() > 0) {
|
||||
OS << "# Num Bitmap Bytes:\n$" << Func.BitmapBytes.size() << "\n";
|
||||
OS << "# Bitmap Byte Values:\n";
|
||||
for (uint8_t Byte : Func.BitmapBytes) {
|
||||
OS << "0x";
|
||||
OS.write_hex(Byte);
|
||||
OS << "\n";
|
||||
}
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
uint32_t NumValueKinds = Func.getNumValueKinds();
|
||||
if (!NumValueKinds) {
|
||||
OS << "\n";
|
||||
|
@ -432,6 +432,15 @@ bool InstrProfiling::lowerIntrinsics(Function *F) {
|
||||
} else if (auto *IPVP = dyn_cast<InstrProfValueProfileInst>(&Instr)) {
|
||||
lowerValueProfileInst(IPVP);
|
||||
MadeChange = true;
|
||||
} else if (auto *IPMP = dyn_cast<InstrProfMCDCBitmapParameters>(&Instr)) {
|
||||
IPMP->eraseFromParent();
|
||||
MadeChange = true;
|
||||
} else if (auto *IPBU = dyn_cast<InstrProfMCDCTVBitmapUpdate>(&Instr)) {
|
||||
lowerMCDCTestVectorBitmapUpdate(IPBU);
|
||||
MadeChange = true;
|
||||
} else if (auto *IPTU = dyn_cast<InstrProfMCDCCondBitmapUpdate>(&Instr)) {
|
||||
lowerMCDCCondBitmapUpdate(IPTU);
|
||||
MadeChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -546,19 +555,33 @@ bool InstrProfiling::run(
|
||||
// the instrumented function. This is counting the number of instrumented
|
||||
// target value sites to enter it as field in the profile data variable.
|
||||
for (Function &F : M) {
|
||||
InstrProfInstBase *FirstProfInst = nullptr;
|
||||
for (BasicBlock &BB : F)
|
||||
for (auto I = BB.begin(), E = BB.end(); I != E; I++)
|
||||
InstrProfCntrInstBase *FirstProfInst = nullptr;
|
||||
InstrProfMCDCBitmapParameters *FirstProfMCDCParams = nullptr;
|
||||
for (BasicBlock &BB : F) {
|
||||
for (auto I = BB.begin(), E = BB.end(); I != E; I++) {
|
||||
if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(I))
|
||||
computeNumValueSiteCounts(Ind);
|
||||
else if (FirstProfInst == nullptr &&
|
||||
(isa<InstrProfIncrementInst>(I) || isa<InstrProfCoverInst>(I)))
|
||||
FirstProfInst = dyn_cast<InstrProfInstBase>(I);
|
||||
else {
|
||||
if (FirstProfInst == nullptr &&
|
||||
(isa<InstrProfIncrementInst>(I) || isa<InstrProfCoverInst>(I)))
|
||||
FirstProfInst = dyn_cast<InstrProfCntrInstBase>(I);
|
||||
if (FirstProfMCDCParams == nullptr)
|
||||
FirstProfMCDCParams = dyn_cast<InstrProfMCDCBitmapParameters>(I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Value profiling intrinsic lowering requires per-function profile data
|
||||
// variable to be created first.
|
||||
if (FirstProfInst != nullptr)
|
||||
// If the MCDCBitmapParameters intrinsic was seen, create the bitmaps.
|
||||
if (FirstProfMCDCParams != nullptr) {
|
||||
static_cast<void>(getOrCreateRegionBitmaps(FirstProfMCDCParams));
|
||||
}
|
||||
|
||||
// Use a profile intrinsic to create the region counters and data variable.
|
||||
// Also create the data variable based on the MCDCParams.
|
||||
if (FirstProfInst != nullptr) {
|
||||
static_cast<void>(getOrCreateRegionCounters(FirstProfInst));
|
||||
createDataVariable(FirstProfInst, FirstProfMCDCParams);
|
||||
}
|
||||
}
|
||||
|
||||
for (Function &F : M)
|
||||
@ -672,7 +695,7 @@ void InstrProfiling::lowerValueProfileInst(InstrProfValueProfileInst *Ind) {
|
||||
Ind->eraseFromParent();
|
||||
}
|
||||
|
||||
Value *InstrProfiling::getCounterAddress(InstrProfInstBase *I) {
|
||||
Value *InstrProfiling::getCounterAddress(InstrProfCntrInstBase *I) {
|
||||
auto *Counters = getOrCreateRegionCounters(I);
|
||||
IRBuilder<> Builder(I);
|
||||
|
||||
@ -712,6 +735,25 @@ Value *InstrProfiling::getCounterAddress(InstrProfInstBase *I) {
|
||||
return Builder.CreateIntToPtr(Add, Addr->getType());
|
||||
}
|
||||
|
||||
Value *InstrProfiling::getBitmapAddress(InstrProfMCDCTVBitmapUpdate *I) {
|
||||
auto *Bitmaps = getOrCreateRegionBitmaps(I);
|
||||
IRBuilder<> Builder(I);
|
||||
|
||||
auto *Addr = Builder.CreateConstInBoundsGEP2_32(
|
||||
Bitmaps->getValueType(), Bitmaps, 0, I->getBitmapIndex()->getZExtValue());
|
||||
|
||||
if (isRuntimeCounterRelocationEnabled()) {
|
||||
LLVMContext &Ctx = M->getContext();
|
||||
Ctx.diagnose(DiagnosticInfoPGOProfile(
|
||||
M->getName().data(),
|
||||
Twine("Runtime counter relocation is presently not supported for MC/DC "
|
||||
"bitmaps."),
|
||||
DS_Warning));
|
||||
}
|
||||
|
||||
return Addr;
|
||||
}
|
||||
|
||||
void InstrProfiling::lowerCover(InstrProfCoverInst *CoverInstruction) {
|
||||
auto *Addr = getCounterAddress(CoverInstruction);
|
||||
IRBuilder<> Builder(CoverInstruction);
|
||||
@ -771,6 +813,86 @@ void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageNamesVar) {
|
||||
CoverageNamesVar->eraseFromParent();
|
||||
}
|
||||
|
||||
void InstrProfiling::lowerMCDCTestVectorBitmapUpdate(
|
||||
InstrProfMCDCTVBitmapUpdate *Update) {
|
||||
IRBuilder<> Builder(Update);
|
||||
auto *Int8Ty = Type::getInt8Ty(M->getContext());
|
||||
auto *Int8PtrTy = Type::getInt8PtrTy(M->getContext());
|
||||
auto *Int32Ty = Type::getInt32Ty(M->getContext());
|
||||
auto *Int64Ty = Type::getInt64Ty(M->getContext());
|
||||
auto *MCDCCondBitmapAddr = Update->getMCDCCondBitmapAddr();
|
||||
auto *BitmapAddr = getBitmapAddress(Update);
|
||||
|
||||
// Load Temp Val.
|
||||
// %mcdc.temp = load i32, ptr %mcdc.addr, align 4
|
||||
auto *Temp = Builder.CreateLoad(Int32Ty, MCDCCondBitmapAddr, "mcdc.temp");
|
||||
|
||||
// Calculate byte offset using div8.
|
||||
// %1 = lshr i32 %mcdc.temp, 3
|
||||
auto *BitmapByteOffset = Builder.CreateLShr(Temp, 0x3);
|
||||
|
||||
// Add byte offset to section base byte address.
|
||||
// %2 = zext i32 %1 to i64
|
||||
// %3 = add i64 ptrtoint (ptr @__profbm_test to i64), %2
|
||||
auto *BitmapByteAddr =
|
||||
Builder.CreateAdd(Builder.CreatePtrToInt(BitmapAddr, Int64Ty),
|
||||
Builder.CreateZExtOrBitCast(BitmapByteOffset, Int64Ty));
|
||||
|
||||
// Convert to a pointer.
|
||||
// %4 = inttoptr i32 %3 to ptr
|
||||
BitmapByteAddr = Builder.CreateIntToPtr(BitmapByteAddr, Int8PtrTy);
|
||||
|
||||
// Calculate bit offset into bitmap byte by using div8 remainder (AND ~8)
|
||||
// %5 = and i32 %mcdc.temp, 7
|
||||
// %6 = trunc i32 %5 to i8
|
||||
auto *BitToSet = Builder.CreateTrunc(Builder.CreateAnd(Temp, 0x7), Int8Ty);
|
||||
|
||||
// Shift bit offset left to form a bitmap.
|
||||
// %7 = shl i8 1, %6
|
||||
auto *ShiftedVal = Builder.CreateShl(Builder.getInt8(0x1), BitToSet);
|
||||
|
||||
// Load profile bitmap byte.
|
||||
// %mcdc.bits = load i8, ptr %4, align 1
|
||||
auto *Bitmap = Builder.CreateLoad(Int8Ty, BitmapByteAddr, "mcdc.bits");
|
||||
|
||||
// Perform logical OR of profile bitmap byte and shifted bit offset.
|
||||
// %8 = or i8 %mcdc.bits, %7
|
||||
auto *Result = Builder.CreateOr(Bitmap, ShiftedVal);
|
||||
|
||||
// Store the updated profile bitmap byte.
|
||||
// store i8 %8, ptr %3, align 1
|
||||
Builder.CreateStore(Result, BitmapByteAddr);
|
||||
Update->eraseFromParent();
|
||||
}
|
||||
|
||||
void InstrProfiling::lowerMCDCCondBitmapUpdate(
|
||||
InstrProfMCDCCondBitmapUpdate *Update) {
|
||||
IRBuilder<> Builder(Update);
|
||||
auto *Int32Ty = Type::getInt32Ty(M->getContext());
|
||||
auto *MCDCCondBitmapAddr = Update->getMCDCCondBitmapAddr();
|
||||
|
||||
// Load the MCDC temporary value from the stack.
|
||||
// %mcdc.temp = load i32, ptr %mcdc.addr, align 4
|
||||
auto *Temp = Builder.CreateLoad(Int32Ty, MCDCCondBitmapAddr, "mcdc.temp");
|
||||
|
||||
// Zero-extend the evaluated condition boolean value (0 or 1) by 32bits.
|
||||
// %1 = zext i1 %tobool to i32
|
||||
auto *CondV_32 = Builder.CreateZExt(Update->getCondBool(), Int32Ty);
|
||||
|
||||
// Shift the boolean value left (by the condition's ID) to form a bitmap.
|
||||
// %2 = shl i32 %1, <Update->getCondID()>
|
||||
auto *ShiftedVal = Builder.CreateShl(CondV_32, Update->getCondID());
|
||||
|
||||
// Perform logical OR of the bitmap against the loaded MCDC temporary value.
|
||||
// %3 = or i32 %mcdc.temp, %2
|
||||
auto *Result = Builder.CreateOr(Temp, ShiftedVal);
|
||||
|
||||
// Store the updated temporary value back to the stack.
|
||||
// store i32 %3, ptr %mcdc.addr, align 4
|
||||
Builder.CreateStore(Result, MCDCCondBitmapAddr);
|
||||
Update->eraseFromParent();
|
||||
}
|
||||
|
||||
/// Get the name of a profiling variable for a particular function.
|
||||
static std::string getVarName(InstrProfInstBase *Inc, StringRef Prefix,
|
||||
bool &Renamed) {
|
||||
@ -926,37 +1048,31 @@ static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
GlobalVariable *
|
||||
InstrProfiling::createRegionCounters(InstrProfInstBase *Inc, StringRef Name,
|
||||
GlobalValue::LinkageTypes Linkage) {
|
||||
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
|
||||
auto &Ctx = M->getContext();
|
||||
GlobalVariable *GV;
|
||||
if (isa<InstrProfCoverInst>(Inc)) {
|
||||
auto *CounterTy = Type::getInt8Ty(Ctx);
|
||||
auto *CounterArrTy = ArrayType::get(CounterTy, NumCounters);
|
||||
// TODO: `Constant::getAllOnesValue()` does not yet accept an array type.
|
||||
std::vector<Constant *> InitialValues(NumCounters,
|
||||
Constant::getAllOnesValue(CounterTy));
|
||||
GV = new GlobalVariable(*M, CounterArrTy, false, Linkage,
|
||||
ConstantArray::get(CounterArrTy, InitialValues),
|
||||
Name);
|
||||
GV->setAlignment(Align(1));
|
||||
} else {
|
||||
auto *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters);
|
||||
GV = new GlobalVariable(*M, CounterTy, false, Linkage,
|
||||
Constant::getNullValue(CounterTy), Name);
|
||||
GV->setAlignment(Align(8));
|
||||
}
|
||||
return GV;
|
||||
void InstrProfiling::maybeSetComdat(GlobalVariable *GV, Function *Fn,
|
||||
StringRef VarName) {
|
||||
bool DataReferencedByCode = profDataReferencedByCode(*M);
|
||||
bool NeedComdat = needsComdatForCounter(*Fn, *M);
|
||||
bool UseComdat = (NeedComdat || TT.isOSBinFormatELF());
|
||||
|
||||
if (!UseComdat)
|
||||
return;
|
||||
|
||||
StringRef GroupName =
|
||||
TT.isOSBinFormatCOFF() && DataReferencedByCode ? GV->getName() : VarName;
|
||||
Comdat *C = M->getOrInsertComdat(GroupName);
|
||||
if (!NeedComdat)
|
||||
C->setSelectionKind(Comdat::NoDeduplicate);
|
||||
GV->setComdat(C);
|
||||
// COFF doesn't allow the comdat group leader to have private linkage, so
|
||||
// upgrade private linkage to internal linkage to produce a symbol table
|
||||
// entry.
|
||||
if (TT.isOSBinFormatCOFF() && GV->hasPrivateLinkage())
|
||||
GV->setLinkage(GlobalValue::InternalLinkage);
|
||||
}
|
||||
|
||||
GlobalVariable *
|
||||
InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
|
||||
GlobalVariable *InstrProfiling::setupProfileSection(InstrProfInstBase *Inc,
|
||||
InstrProfSectKind IPSK) {
|
||||
GlobalVariable *NamePtr = Inc->getName();
|
||||
auto &PD = ProfileDataMap[NamePtr];
|
||||
if (PD.RegionCounters)
|
||||
return PD.RegionCounters;
|
||||
|
||||
// Match the linkage and visibility of the name global.
|
||||
Function *Fn = Inc->getParent()->getParent();
|
||||
@ -995,42 +1111,100 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
|
||||
// nodeduplicate COMDAT which is lowered to a zero-flag section group. This
|
||||
// allows -z start-stop-gc to discard the entire group when the function is
|
||||
// discarded.
|
||||
bool DataReferencedByCode = profDataReferencedByCode(*M);
|
||||
bool NeedComdat = needsComdatForCounter(*Fn, *M);
|
||||
bool Renamed;
|
||||
std::string CntsVarName =
|
||||
getVarName(Inc, getInstrProfCountersVarPrefix(), Renamed);
|
||||
std::string DataVarName =
|
||||
getVarName(Inc, getInstrProfDataVarPrefix(), Renamed);
|
||||
auto MaybeSetComdat = [&](GlobalVariable *GV) {
|
||||
bool UseComdat = (NeedComdat || TT.isOSBinFormatELF());
|
||||
if (UseComdat) {
|
||||
StringRef GroupName = TT.isOSBinFormatCOFF() && DataReferencedByCode
|
||||
? GV->getName()
|
||||
: CntsVarName;
|
||||
Comdat *C = M->getOrInsertComdat(GroupName);
|
||||
if (!NeedComdat)
|
||||
C->setSelectionKind(Comdat::NoDeduplicate);
|
||||
GV->setComdat(C);
|
||||
// COFF doesn't allow the comdat group leader to have private linkage, so
|
||||
// upgrade private linkage to internal linkage to produce a symbol table
|
||||
// entry.
|
||||
if (TT.isOSBinFormatCOFF() && GV->hasPrivateLinkage())
|
||||
GV->setLinkage(GlobalValue::InternalLinkage);
|
||||
}
|
||||
};
|
||||
GlobalVariable *Ptr;
|
||||
StringRef VarPrefix;
|
||||
std::string VarName;
|
||||
if (IPSK == IPSK_cnts) {
|
||||
VarPrefix = getInstrProfCountersVarPrefix();
|
||||
VarName = getVarName(Inc, VarPrefix, Renamed);
|
||||
InstrProfCntrInstBase *CntrIncrement = dyn_cast<InstrProfCntrInstBase>(Inc);
|
||||
Ptr = createRegionCounters(CntrIncrement, VarName, Linkage);
|
||||
} else if (IPSK == IPSK_bitmap) {
|
||||
VarPrefix = getInstrProfBitmapVarPrefix();
|
||||
VarName = getVarName(Inc, VarPrefix, Renamed);
|
||||
InstrProfMCDCBitmapInstBase *BitmapUpdate =
|
||||
dyn_cast<InstrProfMCDCBitmapInstBase>(Inc);
|
||||
Ptr = createRegionBitmaps(BitmapUpdate, VarName, Linkage);
|
||||
} else {
|
||||
llvm_unreachable("Profile Section must be for Counters or Bitmaps");
|
||||
}
|
||||
|
||||
Ptr->setVisibility(Visibility);
|
||||
// Put the counters and bitmaps in their own sections so linkers can
|
||||
// remove unneeded sections.
|
||||
Ptr->setSection(getInstrProfSectionName(IPSK, TT.getObjectFormat()));
|
||||
Ptr->setLinkage(Linkage);
|
||||
maybeSetComdat(Ptr, Fn, VarName);
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
GlobalVariable *
|
||||
InstrProfiling::createRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc,
|
||||
StringRef Name,
|
||||
GlobalValue::LinkageTypes Linkage) {
|
||||
uint64_t NumBytes = Inc->getNumBitmapBytes()->getZExtValue();
|
||||
auto *BitmapTy = ArrayType::get(Type::getInt8Ty(M->getContext()), NumBytes);
|
||||
auto GV = new GlobalVariable(*M, BitmapTy, false, Linkage,
|
||||
Constant::getNullValue(BitmapTy), Name);
|
||||
GV->setAlignment(Align(1));
|
||||
return GV;
|
||||
}
|
||||
|
||||
GlobalVariable *
|
||||
InstrProfiling::getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc) {
|
||||
GlobalVariable *NamePtr = Inc->getName();
|
||||
auto &PD = ProfileDataMap[NamePtr];
|
||||
if (PD.RegionBitmaps)
|
||||
return PD.RegionBitmaps;
|
||||
|
||||
// If RegionBitmaps doesn't already exist, create it by first setting up
|
||||
// the corresponding profile section.
|
||||
auto *BitmapPtr = setupProfileSection(Inc, IPSK_bitmap);
|
||||
PD.RegionBitmaps = BitmapPtr;
|
||||
return PD.RegionBitmaps;
|
||||
}
|
||||
|
||||
GlobalVariable *
|
||||
InstrProfiling::createRegionCounters(InstrProfCntrInstBase *Inc, StringRef Name,
|
||||
GlobalValue::LinkageTypes Linkage) {
|
||||
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
|
||||
LLVMContext &Ctx = M->getContext();
|
||||
auto &Ctx = M->getContext();
|
||||
GlobalVariable *GV;
|
||||
if (isa<InstrProfCoverInst>(Inc)) {
|
||||
auto *CounterTy = Type::getInt8Ty(Ctx);
|
||||
auto *CounterArrTy = ArrayType::get(CounterTy, NumCounters);
|
||||
// TODO: `Constant::getAllOnesValue()` does not yet accept an array type.
|
||||
std::vector<Constant *> InitialValues(NumCounters,
|
||||
Constant::getAllOnesValue(CounterTy));
|
||||
GV = new GlobalVariable(*M, CounterArrTy, false, Linkage,
|
||||
ConstantArray::get(CounterArrTy, InitialValues),
|
||||
Name);
|
||||
GV->setAlignment(Align(1));
|
||||
} else {
|
||||
auto *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters);
|
||||
GV = new GlobalVariable(*M, CounterTy, false, Linkage,
|
||||
Constant::getNullValue(CounterTy), Name);
|
||||
GV->setAlignment(Align(8));
|
||||
}
|
||||
return GV;
|
||||
}
|
||||
|
||||
auto *CounterPtr = createRegionCounters(Inc, CntsVarName, Linkage);
|
||||
CounterPtr->setVisibility(Visibility);
|
||||
CounterPtr->setSection(
|
||||
getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat()));
|
||||
CounterPtr->setLinkage(Linkage);
|
||||
MaybeSetComdat(CounterPtr);
|
||||
GlobalVariable *
|
||||
InstrProfiling::getOrCreateRegionCounters(InstrProfCntrInstBase *Inc) {
|
||||
GlobalVariable *NamePtr = Inc->getName();
|
||||
auto &PD = ProfileDataMap[NamePtr];
|
||||
if (PD.RegionCounters)
|
||||
return PD.RegionCounters;
|
||||
|
||||
// If RegionCounters doesn't already exist, create it by first setting up
|
||||
// the corresponding profile section.
|
||||
auto *CounterPtr = setupProfileSection(Inc, IPSK_cnts);
|
||||
PD.RegionCounters = CounterPtr;
|
||||
|
||||
if (DebugInfoCorrelate) {
|
||||
LLVMContext &Ctx = M->getContext();
|
||||
Function *Fn = Inc->getParent()->getParent();
|
||||
if (auto *SP = Fn->getSubprogram()) {
|
||||
DIBuilder DB(*M, true, SP->getUnit());
|
||||
Metadata *FunctionNameAnnotation[] = {
|
||||
@ -1059,8 +1233,50 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
|
||||
CounterPtr->addDebugInfo(DICounter);
|
||||
DB.finalize();
|
||||
}
|
||||
|
||||
// Mark the counter variable as used so that it isn't optimized out.
|
||||
CompilerUsedVars.push_back(PD.RegionCounters);
|
||||
}
|
||||
|
||||
return PD.RegionCounters;
|
||||
}
|
||||
|
||||
void InstrProfiling::createDataVariable(InstrProfCntrInstBase *Inc,
|
||||
InstrProfMCDCBitmapParameters *Params) {
|
||||
// When debug information is correlated to profile data, a data variable
|
||||
// is not needed.
|
||||
if (DebugInfoCorrelate)
|
||||
return;
|
||||
|
||||
GlobalVariable *NamePtr = Inc->getName();
|
||||
auto &PD = ProfileDataMap[NamePtr];
|
||||
|
||||
LLVMContext &Ctx = M->getContext();
|
||||
|
||||
Function *Fn = Inc->getParent()->getParent();
|
||||
GlobalValue::LinkageTypes Linkage = NamePtr->getLinkage();
|
||||
GlobalValue::VisibilityTypes Visibility = NamePtr->getVisibility();
|
||||
|
||||
// Due to the limitation of binder as of 2021/09/28, the duplicate weak
|
||||
// symbols in the same csect won't be discarded. When there are duplicate weak
|
||||
// symbols, we can NOT guarantee that the relocations get resolved to the
|
||||
// intended weak symbol, so we can not ensure the correctness of the relative
|
||||
// CounterPtr, so we have to use private linkage for counter and data symbols.
|
||||
if (TT.isOSBinFormatXCOFF()) {
|
||||
Linkage = GlobalValue::PrivateLinkage;
|
||||
Visibility = GlobalValue::DefaultVisibility;
|
||||
}
|
||||
|
||||
bool DataReferencedByCode = profDataReferencedByCode(*M);
|
||||
bool NeedComdat = needsComdatForCounter(*Fn, *M);
|
||||
bool Renamed;
|
||||
|
||||
// The Data Variable section is anchored to profile counters.
|
||||
std::string CntsVarName =
|
||||
getVarName(Inc, getInstrProfCountersVarPrefix(), Renamed);
|
||||
std::string DataVarName =
|
||||
getVarName(Inc, getInstrProfDataVarPrefix(), Renamed);
|
||||
|
||||
auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
|
||||
// Allocate statically the array of pointers to value profile nodes for
|
||||
// the current function.
|
||||
@ -1078,16 +1294,17 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
|
||||
ValuesVar->setSection(
|
||||
getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
|
||||
ValuesVar->setAlignment(Align(8));
|
||||
MaybeSetComdat(ValuesVar);
|
||||
maybeSetComdat(ValuesVar, Fn, CntsVarName);
|
||||
ValuesPtrExpr =
|
||||
ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
|
||||
}
|
||||
|
||||
if (DebugInfoCorrelate) {
|
||||
// Mark the counter variable as used so that it isn't optimized out.
|
||||
CompilerUsedVars.push_back(PD.RegionCounters);
|
||||
return PD.RegionCounters;
|
||||
}
|
||||
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
|
||||
auto *CounterPtr = PD.RegionCounters;
|
||||
|
||||
uint64_t NumBitmapBytes = 0;
|
||||
if (Params != nullptr)
|
||||
NumBitmapBytes = Params->getNumBitmapBytes()->getZExtValue();
|
||||
|
||||
// Create data variable.
|
||||
auto *IntPtrTy = M->getDataLayout().getIntPtrType(M->getContext());
|
||||
@ -1130,6 +1347,16 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
|
||||
ConstantExpr::getSub(ConstantExpr::getPtrToInt(CounterPtr, IntPtrTy),
|
||||
ConstantExpr::getPtrToInt(Data, IntPtrTy));
|
||||
|
||||
// Bitmaps are relative to the same data variable as profile counters.
|
||||
GlobalVariable *BitmapPtr = PD.RegionBitmaps;
|
||||
Constant *RelativeBitmapPtr = ConstantInt::get(IntPtrTy, 0);
|
||||
|
||||
if (BitmapPtr != nullptr) {
|
||||
RelativeBitmapPtr =
|
||||
ConstantExpr::getSub(ConstantExpr::getPtrToInt(BitmapPtr, IntPtrTy),
|
||||
ConstantExpr::getPtrToInt(Data, IntPtrTy));
|
||||
}
|
||||
|
||||
Constant *DataVals[] = {
|
||||
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init,
|
||||
#include "llvm/ProfileData/InstrProfData.inc"
|
||||
@ -1139,7 +1366,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
|
||||
Data->setVisibility(Visibility);
|
||||
Data->setSection(getInstrProfSectionName(IPSK_data, TT.getObjectFormat()));
|
||||
Data->setAlignment(Align(INSTR_PROF_DATA_ALIGNMENT));
|
||||
MaybeSetComdat(Data);
|
||||
maybeSetComdat(Data, Fn, CntsVarName);
|
||||
|
||||
PD.DataVar = Data;
|
||||
|
||||
@ -1151,8 +1378,6 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
|
||||
NamePtr->setLinkage(GlobalValue::PrivateLinkage);
|
||||
// Collect the referenced names to be used by emitNameData.
|
||||
ReferencedNames.push_back(NamePtr);
|
||||
|
||||
return PD.RegionCounters;
|
||||
}
|
||||
|
||||
void InstrProfiling::emitVNodes() {
|
||||
|
53
llvm/test/Instrumentation/InstrProfiling/mcdc.ll
Normal file
53
llvm/test/Instrumentation/InstrProfiling/mcdc.ll
Normal file
@ -0,0 +1,53 @@
|
||||
; Check that MC/DC intrinsics are properly lowered
|
||||
; RUN: opt < %s -passes=instrprof -S | FileCheck %s
|
||||
; RUN: opt < %s -passes=instrprof -runtime-counter-relocation -S 2>&1 | FileCheck %s --check-prefix RELOC
|
||||
|
||||
; RELOC: Runtime counter relocation is presently not supported for MC/DC bitmaps
|
||||
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
@__profn_test = private constant [4 x i8] c"test"
|
||||
|
||||
; CHECK: @__profbm_test = private global [1 x i8] zeroinitializer, section "__llvm_prf_bits", comdat, align 1
|
||||
|
||||
define dso_local void @test(i32 noundef %A) {
|
||||
entry:
|
||||
%A.addr = alloca i32, align 4
|
||||
%mcdc.addr = alloca i32, align 4
|
||||
call void @llvm.instrprof.cover(ptr @__profn_test, i64 99278, i32 5, i32 0)
|
||||
; CHECK: store i8 0, ptr @__profc_test, align 1
|
||||
|
||||
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_test, i64 99278, i32 1)
|
||||
store i32 0, ptr %mcdc.addr, align 4
|
||||
%0 = load i32, ptr %A.addr, align 4
|
||||
%tobool = icmp ne i32 %0, 0
|
||||
|
||||
call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 99278, i32 0, ptr %mcdc.addr, i1 %tobool)
|
||||
; CHECK: %mcdc.temp = load i32, ptr %mcdc.addr, align 4
|
||||
; CHECK-NEXT: %1 = zext i1 %tobool to i32
|
||||
; CHECK-NEXT: %2 = shl i32 %1, 0
|
||||
; CHECK-NEXT: %3 = or i32 %mcdc.temp, %2
|
||||
; CHECK-NEXT: store i32 %3, ptr %mcdc.addr, align 4
|
||||
|
||||
call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 99278, i32 1, i32 0, ptr %mcdc.addr)
|
||||
; CHECK: %mcdc.temp1 = load i32, ptr %mcdc.addr, align 4
|
||||
; CHECK-NEXT: %4 = lshr i32 %mcdc.temp1, 3
|
||||
; CHECK-NEXT: %5 = zext i32 %4 to i64
|
||||
; CHECK-NEXT: %6 = add i64 ptrtoint (ptr @__profbm_test to i64), %5
|
||||
; CHECK-NEXT: %7 = inttoptr i64 %6 to ptr
|
||||
; CHECK-NEXT: %8 = and i32 %mcdc.temp1, 7
|
||||
; CHECK-NEXT: %9 = trunc i32 %8 to i8
|
||||
; CHECK-NEXT: %10 = shl i8 1, %9
|
||||
; CHECK-NEXT: %mcdc.bits = load i8, ptr %7, align 1
|
||||
; CHECK-NEXT: %11 = or i8 %mcdc.bits, %10
|
||||
; CHECK-NEXT: store i8 %11, ptr %7, align 1
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.instrprof.cover(ptr, i64, i32, i32)
|
||||
|
||||
declare void @llvm.instrprof.mcdc.parameters(ptr, i64, i32)
|
||||
|
||||
declare void @llvm.instrprof.mcdc.condbitmap.update(ptr, i64, i32, ptr, i1)
|
||||
|
||||
declare void @llvm.instrprof.mcdc.tvbitmap.update(ptr, i64, i32, i32, ptr)
|
@ -13,9 +13,9 @@ $foo = comdat any
|
||||
; CHECK: @__llvm_profile_raw_version = hidden constant i64 {{[0-9]+}}, comdat
|
||||
; CHECK-NOT: __profn__stdin__foo
|
||||
; CHECK: @__profc__stdin__foo.[[#FOO_HASH]] = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8
|
||||
; CHECK: @__profd__stdin__foo.[[#FOO_HASH]] = private global { i64, i64, i64, ptr, ptr, i32, [2 x i16] } { i64 {{.*}}, i64 [[#FOO_HASH]], i64 sub (i64 ptrtoint (ptr @__profc__stdin__foo.742261418966908927 to i64), i64 ptrtoint (ptr @__profd__stdin__foo.742261418966908927 to i64)), ptr null
|
||||
; CHECK: @__profd__stdin__foo.[[#FOO_HASH]] = private global { i64, i64, i64, i64, ptr, ptr, i32, [2 x i16], i32 } { i64 {{.*}}, i64 [[#FOO_HASH]], i64 sub (i64 ptrtoint (ptr @__profc__stdin__foo.742261418966908927 to i64), i64 ptrtoint (ptr @__profd__stdin__foo.742261418966908927 to i64)), i64 0, ptr null
|
||||
; CHECK-NOT: @foo
|
||||
; CHECK-SAME: , ptr null, i32 1, [2 x i16] zeroinitializer }, section "__llvm_prf_data", comdat($__profc__stdin__foo.[[#FOO_HASH]]), align 8
|
||||
; CHECK-SAME: , ptr null, i32 1, [2 x i16] zeroinitializer, i32 0 }, section "__llvm_prf_data", comdat($__profc__stdin__foo.[[#FOO_HASH]]), align 8
|
||||
; CHECK: @__llvm_prf_nm
|
||||
; CHECK: @llvm.compiler.used
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
BIN
llvm/test/tools/llvm-profdata/Inputs/compat.profdata.v10
Normal file
BIN
llvm/test/tools/llvm-profdata/Inputs/compat.profdata.v10
Normal file
Binary file not shown.
Binary file not shown.
@ -5,13 +5,15 @@
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NumBitmaskBytes, NumBitmaskBytes)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BitmaskDelta, (uintptr_t)BitmaskBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||
|
||||
RUN: printf '\201rforpl\377' > %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t.profraw
|
||||
// There will be 2 20-byte binary IDs, so the total Binary IDs size will be 64 bytes.
|
||||
// 2 * 8 binary ID sizes
|
||||
// + 2 * 20 binary IDs (of size 20)
|
||||
@ -23,8 +25,11 @@ RUN: printf '\2\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\3\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\20\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\2\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
@ -51,14 +56,18 @@ RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
RUN: printf '\067\265\035\031\112\165\023\344' >> %t.profraw
|
||||
RUN: printf '\02\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\xd8\xff\3\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\xc8\xff\3\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\02\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
RUN: printf '\023\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\067\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
@ -87,3 +87,26 @@ large_numbers
|
||||
# FORMATV4: Total functions: 3
|
||||
# FORMATV4: Maximum function count: 2305843009213693952
|
||||
# FORMATV4: Maximum internal block count: 1152921504606846976
|
||||
|
||||
# RUN: llvm-profdata show %S/Inputs/compat.profdata.v10 -all-functions --counts | FileCheck %s -check-prefix=FORMATV10
|
||||
|
||||
# FORMATV10: Counters:
|
||||
# FORMATV10: large_numbers:
|
||||
# FORMATV10: Hash: 0x3fffffffffffffff
|
||||
# FORMATV10: Counters: 6
|
||||
# FORMATV10: Function count: 2305843009213693952
|
||||
# FORMATV10: Block counts: [1152921504606846976, 576460752303423488, 288230376151711744, 144115188075855872, 72057594037927936]
|
||||
# FORMATV10: name with spaces:
|
||||
# FORMATV10: Hash: 0x0000000000000400
|
||||
# FORMATV10: Counters: 2
|
||||
# FORMATV10: Function count: 0
|
||||
# FORMATV10: Block counts: [0]
|
||||
# FORMATV10: function_count_only:
|
||||
# FORMATV10: Hash: 0x0000000000000000
|
||||
# FORMATV10: Counters: 1
|
||||
# FORMATV10: Function count: 97531
|
||||
# FORMATV10: Block counts: []
|
||||
# FORMATV10: Functions shown: 3
|
||||
# FORMATV10: Total functions: 3
|
||||
# FORMATV10: Maximum function count: 2305843009213693952
|
||||
# FORMATV10: Maximum internal block count: 1152921504606846976
|
||||
|
@ -1,5 +1,5 @@
|
||||
RUN: printf '\201rforpl\377' > %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\40\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
@ -9,6 +9,9 @@ RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
// Check for a corrupted size being too large past the end of the file.
|
||||
RUN: printf '\7\7\7\7\7\7\7\7' >> %t.profraw
|
||||
|
@ -5,20 +5,25 @@
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NumBitmaskBytes, NumBitmaskBytes)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BitmaskDelta, (uintptr_t)BitmaskBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||
|
||||
RUN: printf '\201rforpl\377' > %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\2\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
@ -35,7 +40,9 @@ RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
RUN: printf '\023\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\3\0foo\0\0\0' >> %t.profraw
|
||||
|
@ -5,20 +5,26 @@
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NumBitmaskBytes, NumBitmaskBytes)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BitmaskDelta, (uintptr_t)BitmaskBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||
|
||||
RUN: printf '\201rforpl\377' > %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\2\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
@ -35,8 +41,10 @@ RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
// Make NumCounters = 0 so that we get "number of counters is zero" error message
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
RUN: printf '\023\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\3\0foo\0\0\0' >> %t.profraw
|
||||
|
@ -5,20 +5,25 @@
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NumBitmaskBytes, NumBitmaskBytes)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, BitmaskDelta, (uintptr_t)BitmaskBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||
// INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||
|
||||
RUN: printf '\201rforpl\377' > %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\2\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\6\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\6\0\2\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
@ -38,10 +43,12 @@ RUN: printf '\02\0\0\0\0\0\0\0' >> %t.profraw
|
||||
// Octal '\11' is 9 in decimal: this should push CounterOffset to 1. As there are two counters,
|
||||
// the profile reader should error out.
|
||||
RUN: printf '\11\0\6\0\1\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\02\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
||||
// Counter Section
|
||||
|
||||
|
201
llvm/test/tools/llvm-profdata/mcdc-bitmap.test
Normal file
201
llvm/test/tools/llvm-profdata/mcdc-bitmap.test
Normal file
@ -0,0 +1,201 @@
|
||||
# Test MC/DC bitmap reading and merging.
|
||||
|
||||
# Merge as profdata.
|
||||
RUN: split-file %s %t
|
||||
RUN: llvm-profdata merge %t/mcdc-1.proftext %t/mcdc-2.proftext -o %t.profdata
|
||||
RUN: llvm-profdata show %t.profdata --text -all-functions | FileCheck %s --check-prefix=MCDC
|
||||
# Merge as proftext.
|
||||
RUN: llvm-profdata merge %t/mcdc-1.proftext %t/mcdc-2.proftext -o %t.proftext
|
||||
RUN: llvm-profdata show %t.proftext --text -all-functions | FileCheck %s --check-prefix=MCDC
|
||||
|
||||
MCDC: # Num Bitmap Bytes:
|
||||
MCDC-NEXT: $1
|
||||
MCDC-NEXT: # Bitmap Byte Values:
|
||||
MCDC-NEXT: a
|
||||
MCDC: # Num Bitmap Bytes:
|
||||
MCDC-NEXT: $2
|
||||
MCDC-NEXT: # Bitmap Byte Values:
|
||||
MCDC-NEXT: 0x29
|
||||
MCDC-NEXT: 0x0
|
||||
|
||||
# Merge as profdata.
|
||||
RUN: llvm-profdata merge %t/mcdc-3.proftext %t/mcdc-4.proftext -o %t.profdata
|
||||
RUN: llvm-profdata show %t.profdata --text -all-functions | FileCheck %s --check-prefix=MCDC2
|
||||
# Merge as proftext.
|
||||
RUN: llvm-profdata merge %t/mcdc-3.proftext %t/mcdc-4.proftext -o %t.proftext
|
||||
RUN: llvm-profdata show %t.proftext --text -all-functions | FileCheck %s --check-prefix=MCDC2
|
||||
|
||||
MCDC2: # Num Bitmap Bytes:
|
||||
MCDC2-NEXT: $8
|
||||
MCDC2-NEXT: # Bitmap Byte Values:
|
||||
MCDC2-NEXT: 0x1
|
||||
MCDC2-NEXT: 0x2
|
||||
MCDC2-NEXT: 0x3
|
||||
MCDC2-NEXT: 0xf
|
||||
MCDC2-NEXT: 0xf
|
||||
MCDC2-NEXT: 0xe
|
||||
MCDC2-NEXT: 0xf
|
||||
MCDC2-NEXT: 0xa
|
||||
|
||||
# Incompatible size mismatch.
|
||||
RUN: llvm-profdata merge %t/mcdc-2.proftext %t/mcdc-4.proftext -o %t.profdata 2>&1 | FileCheck %s --check-prefix=MCDC3
|
||||
# Merge as proftext
|
||||
RUN: llvm-profdata merge %t/mcdc-2.proftext %t/mcdc-4.proftext -o %t.proftext 2>&1 | FileCheck %s --check-prefix=MCDC3
|
||||
|
||||
MCDC3: function bitmap size change detected (bitmap size mismatch)
|
||||
|
||||
# Invalid number of bitmap bytes.
|
||||
RUN: not llvm-profdata merge %t/mcdc-3.proftext %t/mcdc-err0.proftext -o %t.proftext 2>&1 | FileCheck %s --check-prefix=MCDC4
|
||||
|
||||
MCDC4: malformed instrumentation profile data: number of bitmap bytes is not a valid integer
|
||||
|
||||
# Invalid bitmap byte.
|
||||
RUN: not llvm-profdata merge %t/mcdc-3.proftext %t/mcdc-err1.proftext -o %t.proftext 2>&1 | FileCheck %s --check-prefix=MCDC5
|
||||
|
||||
MCDC5: malformed instrumentation profile data: bitmap byte is not a valid integer
|
||||
|
||||
;--- mcdc-1.proftext
|
||||
main
|
||||
# Func Hash:
|
||||
702755447896
|
||||
# Num Counters:
|
||||
4
|
||||
# Counter Values:
|
||||
1
|
||||
0
|
||||
1
|
||||
0
|
||||
# Num Bitmask Bytes:
|
||||
$1
|
||||
# Bitmask Byte Values:
|
||||
2
|
||||
;--- mcdc-2.proftext
|
||||
main
|
||||
# Func Hash:
|
||||
702755447896
|
||||
# Num Counters:
|
||||
4
|
||||
# Counter Values:
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
# Num Bitmask Bytes:
|
||||
$1
|
||||
# Bitmask Byte Values:
|
||||
8
|
||||
|
||||
|
||||
test3
|
||||
# Func Hash:
|
||||
15288018065
|
||||
# Num Counters:
|
||||
6
|
||||
# Counter Values:
|
||||
4
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
2
|
||||
# Num Bitmask Bytes:
|
||||
$0x2
|
||||
# Bitmask Byte Values:
|
||||
0x29
|
||||
0x0
|
||||
;--- mcdc-3.proftext
|
||||
test3
|
||||
# Func Hash:
|
||||
15288018065
|
||||
# Num Counters:
|
||||
6
|
||||
# Counter Values:
|
||||
4
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
2
|
||||
# Num Bitmask Bytes:
|
||||
$8
|
||||
# Bitmask Byte Values:
|
||||
0x0
|
||||
0x2
|
||||
0x3
|
||||
0xf
|
||||
0xf
|
||||
0xa
|
||||
0xc
|
||||
0x2
|
||||
;--- mcdc-4.proftext
|
||||
test3
|
||||
# Func Hash:
|
||||
15288018065
|
||||
# Num Counters:
|
||||
6
|
||||
# Counter Values:
|
||||
4
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
2
|
||||
# Num Bitmask Bytes:
|
||||
$ 8
|
||||
# Bitmask Byte Values:
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
;--- mcdc-err0.proftext
|
||||
test3
|
||||
# Func Hash:
|
||||
15288018065
|
||||
# Num Counters:
|
||||
6
|
||||
# Counter Values:
|
||||
4
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
2
|
||||
# Num Bitmask Bytes:
|
||||
$8.9
|
||||
# Bitmask Byte Values:
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
;--- mcdc-err1.proftext
|
||||
test3
|
||||
# Func Hash:
|
||||
15288018065
|
||||
# Num Counters:
|
||||
6
|
||||
# Counter Values:
|
||||
4
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
2
|
||||
# Num Bitmask Bytes:
|
||||
$8
|
||||
# Bitmask Byte Values:
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5.4
|
||||
6
|
||||
7
|
||||
8
|
@ -1,5 +1,5 @@
|
||||
RUN: printf '\201rforpl\377' > %t.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t.profraw
|
||||
// We should fail on this because the binary IDs is not a multiple of 8 bytes.
|
||||
RUN: printf '\77\0\0\0\0\0\0\0' >> %t.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
|
||||
|
@ -8,6 +8,9 @@ RUN: printf '\0\0\0\0\0\0\0\2' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\3' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\20' >> %t
|
||||
RUN: printf '\0\0\0\1\0\4\0\0' >> %t
|
||||
RUN: printf '\0\0\0\2\0\4\0\0' >> %t
|
||||
|
@ -1,37 +1,46 @@
|
||||
RUN: printf '\377lprofR\201' > %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\10' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\11' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\2' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\3' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\4' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\20' >> %t
|
||||
RUN: printf '\0\0\0\0\1\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\3\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\2\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\134\370\302\114\333\030\275\254' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\1' >> %t
|
||||
RUN: printf '\1\0\0\0' >> %t
|
||||
RUN: printf '\3\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\1' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\3' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\344\023\165\112\031\035\265\067' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\2' >> %t
|
||||
RUN: printf '\0\xff\xff\xe0' >> %t
|
||||
RUN: printf '\0\xff\xff\xd8' >> %t
|
||||
RUN: printf '\2\xff\xff\xd3' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\2' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\1' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\0\0\0\0\0\0\0\023' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\067' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\101' >> %t
|
||||
RUN: printf '\125\125\125\052' >> %t
|
||||
RUN: printf '\7\0foo\1bar\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s
|
||||
RUN: llvm-profdata show %t -all-functions -text | FileCheck %s -check-prefix=MCDC
|
||||
|
||||
CHECK: Counters:
|
||||
CHECK: foo:
|
||||
@ -48,3 +57,14 @@ CHECK: Functions shown: 2
|
||||
CHECK: Total functions: 2
|
||||
CHECK: Maximum function count: 55
|
||||
CHECK: Maximum internal block count: 65
|
||||
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $3
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $1
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 0x2a
|
||||
|
@ -1,37 +1,46 @@
|
||||
RUN: printf '\201Rforpl\377' > %t
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\2\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\3\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\4\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\20\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\1\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\3\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\2\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\254\275\030\333\114\302\370\134' >> %t
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\1' >> %t
|
||||
RUN: printf '\0\0\0\3' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\1\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\3\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\067\265\035\031\112\165\023\344' >> %t
|
||||
RUN: printf '\02\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\xe0\xff\xff\0' >> %t
|
||||
RUN: printf '\xd8\xff\xff\0' >> %t
|
||||
RUN: printf '\xd3\xff\xff\2' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
RUN: printf '\2\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\1\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\023\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\067\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\101\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\125\125\125\052' >> %t
|
||||
RUN: printf '\7\0foo\1bar\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s
|
||||
RUN: llvm-profdata show %t -all-functions -text | FileCheck %s -check-prefix=MCDC
|
||||
|
||||
CHECK: Counters:
|
||||
CHECK: foo:
|
||||
@ -48,3 +57,14 @@ CHECK: Functions shown: 2
|
||||
CHECK: Total functions: 2
|
||||
CHECK: Maximum function count: 55
|
||||
CHECK: Maximum internal block count: 65
|
||||
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $3
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $1
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 0x2a
|
||||
|
@ -1,35 +1,44 @@
|
||||
RUN: printf '\377lprofr\201' > %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\10' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\11' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\2' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\3' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\4' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\20' >> %t
|
||||
RUN: printf '\0\0\0\1\0\4\0\0' >> %t
|
||||
RUN: printf '\0\0\0\3\0\4\0\0' >> %t
|
||||
RUN: printf '\0\0\0\2\0\4\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\134\370\302\114\333\030\275\254' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\1' >> %t
|
||||
RUN: printf '\0\0\0\1\0\4\0\0' >> %t
|
||||
RUN: printf '\0\0\0\3\0\4\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\1\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\3\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\344\023\165\112\031\035\265\067' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\02' >> %t
|
||||
RUN: printf '\0\0\0\1\0\3\xff\xd8' >> %t
|
||||
RUN: printf '\0\0\0\1\0\3\xff\xc8' >> %t
|
||||
RUN: printf '\0\0\0\3\0\3\xff\xc3' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\02\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\1\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\0\0\0\0\0\0\0\023' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\067' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\101' >> %t
|
||||
RUN: printf '\125\125\125\052' >> %t
|
||||
RUN: printf '\7\0foo\1bar\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s
|
||||
RUN: llvm-profdata show %t -all-functions -text | FileCheck %s -check-prefix=MCDC
|
||||
|
||||
CHECK: Counters:
|
||||
CHECK: foo:
|
||||
@ -46,3 +55,14 @@ CHECK: Functions shown: 2
|
||||
CHECK: Total functions: 2
|
||||
CHECK: Maximum function count: 55
|
||||
CHECK: Maximum internal block count: 65
|
||||
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $3
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $1
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 0x2a
|
||||
|
@ -1,35 +1,44 @@
|
||||
RUN: printf '\201rforpl\377' > %t
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\2\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\3\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\4\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\20\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t
|
||||
RUN: printf '\0\0\4\0\3\0\0\0' >> %t
|
||||
RUN: printf '\0\0\4\0\2\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\254\275\030\333\114\302\370\134' >> %t
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t
|
||||
RUN: printf '\0\0\4\0\3\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\3\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\067\265\035\031\112\165\023\344' >> %t
|
||||
RUN: printf '\02\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\xd8\xff\3\0\1\0\0\0' >> %t
|
||||
RUN: printf '\xc8\xff\3\0\1\0\0\0' >> %t
|
||||
RUN: printf '\xc3\xff\3\0\3\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\02\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: printf '\023\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\067\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\101\0\0\0\0\0\0\0' >> %t
|
||||
RUN: printf '\125\125\125\052' >> %t
|
||||
RUN: printf '\7\0foo\1bar\0\0\0\0\0\0\0' >> %t
|
||||
|
||||
RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s
|
||||
RUN: llvm-profdata show %t -all-functions -text | FileCheck %s -check-prefix=MCDC
|
||||
|
||||
CHECK: Counters:
|
||||
CHECK: foo:
|
||||
@ -46,3 +55,14 @@ CHECK: Functions shown: 2
|
||||
CHECK: Total functions: 2
|
||||
CHECK: Maximum function count: 55
|
||||
CHECK: Maximum internal block count: 65
|
||||
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $3
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC-NEXT: 55
|
||||
MCDC: Num Bitmap Bytes:
|
||||
MCDC-NEXT: $1
|
||||
MCDC-NEXT: Bitmap Byte Values:
|
||||
MCDC-NEXT: 0x2a
|
||||
|
@ -1,12 +1,15 @@
|
||||
RUN: printf '\201rforpl\377' > %t-foo.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\4\0\2\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
|
||||
@ -15,20 +18,25 @@ RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
|
||||
RUN: printf '\023\0\0\0\0\0\0\0' >> %t-foo.profraw
|
||||
RUN: printf '\3\0foo\0\0\0' >> %t-foo.profraw
|
||||
|
||||
RUN: printf '\201rforpl\377' > %t-bar.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\11\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\1\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\10\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\6\0\2\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
|
||||
@ -37,7 +45,9 @@ RUN: printf '\02\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\02\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
|
||||
RUN: printf '\067\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
RUN: printf '\101\0\0\0\0\0\0\0' >> %t-bar.profraw
|
||||
|
Loading…
Reference in New Issue
Block a user