Reland compiler-rt support for order file instrumentation.

r355343 was landed and was reverted in r355363 due to build breakage.
This patch adds Linux/Windows support on top of r355343.

In this patch, Darwin should be working with testing case. Linux should be working,
I will enable the testing case in a follwup diff. Windows/Other should be building.
Correct implementation for Other platforms will be added.

Thanks David for reviewing the original diff, helping me with issues on Linux, and
giving suggestions for adding support for Other platforms.

llvm-svn: 355701
This commit is contained in:
Manman Ren 2019-03-08 15:30:56 +00:00
parent 62d1d024ab
commit e73ae9a142
10 changed files with 172 additions and 0 deletions

View File

@ -265,6 +265,9 @@ INSTR_PROF_SECT_ENTRY(IPSK_vnodes, \
INSTR_PROF_SECT_ENTRY(IPSK_covmap, \
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \
INSTR_PROF_COVMAP_COFF, "__LLVM_COV,")
INSTR_PROF_SECT_ENTRY(IPSK_orderfile, \
INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON), \
INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COFF), "__DATA,")
#undef INSTR_PROF_SECT_ENTRY
#endif
@ -656,6 +659,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile
/* Windows section names. Because these section names contain dollar characters,
* they must be quoted.
*/
@ -665,6 +669,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
#define INSTR_PROF_VALS_COFF ".lprfv$M"
#define INSTR_PROF_VNODES_COFF ".lprfnd$M"
#define INSTR_PROF_COVMAP_COFF ".lcovmap$M"
#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M"
#ifdef _WIN32
/* Runtime section names and name strings. */
@ -678,6 +683,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
/* Value profile nodes section. */
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF
#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF
#else
/* Runtime section names and name strings. */
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
@ -690,8 +696,18 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
/* Value profile nodes section. */
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON)
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON)
/* Order file instrumentation. */
#define INSTR_PROF_ORDERFILE_SECT_NAME \
INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON)
#endif
#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer
#define INSTR_PROF_ORDERFILE_BUFFER_NAME_STR \
INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_NAME)
#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME _llvm_order_file_buffer_idx
#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR \
INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME)
/* Macros to define start/stop section symbol for a given
* section on Linux. For instance
* INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will
@ -725,6 +741,12 @@ typedef struct InstrProfValueData {
#endif /* INSTR_PROF_DATA_INC */
#ifndef INSTR_ORDER_FILE_INC
// The maximal # of functions: 128*1024 (the buffer size will be 128*4 KB).
#define INSTR_ORDER_FILE_BUFFER_SIZE 131072
#define INSTR_ORDER_FILE_BUFFER_BITS 17
#define INSTR_ORDER_FILE_BUFFER_MASK 0x1ffff
#endif /* INSTR_ORDER_FILE_INC */
#else
#undef INSTR_PROF_DATA_DEFINED
#endif

View File

@ -64,6 +64,7 @@ uint64_t *__llvm_profile_begin_counters(void);
uint64_t *__llvm_profile_end_counters(void);
ValueProfNode *__llvm_profile_begin_vnodes();
ValueProfNode *__llvm_profile_end_vnodes();
uint32_t *__llvm_profile_begin_orderfile();
/*!
* \brief Clear profile counters to zero.
@ -120,6 +121,7 @@ void __llvm_profile_instrument_target_value(uint64_t TargetValue, void *Data,
*/
int __llvm_profile_write_file(void);
int __llvm_orderfile_write_file(void);
/*!
* \brief this is a wrapper interface to \c __llvm_profile_write_file.
* After this interface is invoked, a arleady dumped flag will be set
@ -142,6 +144,8 @@ int __llvm_profile_write_file(void);
*/
int __llvm_profile_dump(void);
int __llvm_orderfile_dump(void);
/*!
* \brief Set the filename for writing instrumentation data.
*

View File

@ -111,6 +111,15 @@ static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
return 0;
}
/* TODO: make buffer size controllable by an internal option, and compiler can pass the size
to runtime via a variable. */
static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) !=
INSTR_ORDER_FILE_BUFFER_SIZE)
return 1;
return 0;
}
static void initFileWriter(ProfDataWriter *This, FILE *File) {
This->Write = fileWriter;
This->WriterCtx = File;
@ -260,6 +269,27 @@ static int writeFile(const char *OutputName) {
return RetVal;
}
/* Write order data to file \c OutputName. */
static int writeOrderFile(const char *OutputName) {
int RetVal;
FILE *OutputFile;
OutputFile = fopen(OutputName, "w");
if (!OutputFile) {
PROF_WARN("can't open file with mode ab: %s\n", OutputName);
return -1;
}
FreeHook = &free;
setupIOBuffer();
const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
RetVal = orderFileWriter(OutputFile, DataBegin);
fclose(OutputFile);
return RetVal;
}
static void truncateCurrentFile(void) {
const char *Filename;
char *FilenameBuf;
@ -648,6 +678,62 @@ int __llvm_profile_dump(void) {
return rc;
}
/* Order file data will be saved in a file with suffx .order. */
static const char *OrderFileSuffix = ".order";
COMPILER_RT_VISIBILITY
int __llvm_orderfile_write_file(void) {
int rc, Length, LengthBeforeAppend, SuffixLength;
const char *Filename;
char *FilenameBuf;
int PDeathSig = 0;
SuffixLength = strlen(OrderFileSuffix);
Length = getCurFilenameLength() + SuffixLength;
FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
Filename = getCurFilename(FilenameBuf, 1);
/* Check the filename. */
if (!Filename) {
PROF_ERR("Failed to write file : %s\n", "Filename not set");
return -1;
}
/* Append order file suffix */
LengthBeforeAppend = strlen(Filename);
memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
/* Check if there is llvm/runtime version mismatch. */
if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
PROF_ERR("Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n",
INSTR_PROF_RAW_VERSION,
(int)GET_VERSION(__llvm_profile_get_version()));
return -1;
}
// Temporarily suspend getting SIGKILL when the parent exits.
PDeathSig = lprofSuspendSigKill();
/* Write order data to the file. */
rc = writeOrderFile(Filename);
if (rc)
PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
// Restore SIGKILL.
if (PDeathSig == 1)
lprofRestoreSigKill();
return rc;
}
COMPILER_RT_VISIBILITY
int __llvm_orderfile_dump(void) {
int rc = __llvm_orderfile_write_file();
return rc;
}
static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
COMPILER_RT_VISIBILITY

View File

@ -27,6 +27,9 @@ extern uint64_t
COMPILER_RT_VISIBILITY
extern uint64_t
CountersEnd __asm("section$end$__DATA$" INSTR_PROF_CNTS_SECT_NAME);
COMPILER_RT_VISIBILITY
extern uint32_t
OrderFileStart __asm("section$start$__DATA$" INSTR_PROF_ORDERFILE_SECT_NAME);
COMPILER_RT_VISIBILITY
extern ValueProfNode
@ -49,6 +52,8 @@ COMPILER_RT_VISIBILITY
uint64_t *__llvm_profile_begin_counters(void) { return &CountersStart; }
COMPILER_RT_VISIBILITY
uint64_t *__llvm_profile_end_counters(void) { return &CountersEnd; }
COMPILER_RT_VISIBILITY
uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; }
COMPILER_RT_VISIBILITY
ValueProfNode *__llvm_profile_begin_vnodes(void) {

View File

@ -19,6 +19,7 @@
#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_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)
@ -29,6 +30,7 @@ extern __llvm_profile_data PROF_DATA_START COMPILER_RT_VISIBILITY;
extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY;
extern uint64_t PROF_CNTS_START COMPILER_RT_VISIBILITY;
extern uint64_t PROF_CNTS_STOP COMPILER_RT_VISIBILITY;
extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY;
extern char PROF_NAME_START COMPILER_RT_VISIBILITY;
extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY;
extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY;
@ -39,6 +41,8 @@ __llvm_profile_data
__prof_data_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_DATA_SECT_NAME);
uint64_t
__prof_cnts_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_CNTS_SECT_NAME);
uint32_t
__prof_orderfile_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_ORDERFILE_SECT_NAME);
char __prof_nms_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_NAME_SECT_NAME);
ValueProfNode __prof_vnodes_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_VNODES_SECT_NAME);
@ -62,6 +66,9 @@ COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_begin_counters(void) {
COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_end_counters(void) {
return &PROF_CNTS_STOP;
}
COMPILER_RT_VISIBILITY uint32_t *__llvm_profile_begin_orderfile(void) {
return &PROF_ORDERFILE_START;
}
COMPILER_RT_VISIBILITY ValueProfNode *
__llvm_profile_begin_vnodes(void) {

View File

@ -21,6 +21,7 @@ static const char *NamesFirst = NULL;
static const char *NamesLast = NULL;
static uint64_t *CountersFirst = NULL;
static uint64_t *CountersLast = NULL;
static uint32_t *OrderFileFirst = NULL;
static const void *getMinAddr(const void *A1, const void *A2) {
return A1 < A2 ? A1 : A2;
@ -82,6 +83,9 @@ COMPILER_RT_VISIBILITY
uint64_t *__llvm_profile_begin_counters(void) { return CountersFirst; }
COMPILER_RT_VISIBILITY
uint64_t *__llvm_profile_end_counters(void) { return CountersLast; }
/* TODO: correctly set up OrderFileFirst. */
COMPILER_RT_VISIBILITY
uint32_t *__llvm_profile_begin_orderfile(void) { return OrderFileFirst; }
COMPILER_RT_VISIBILITY
ValueProfNode *__llvm_profile_begin_vnodes(void) {

View File

@ -29,6 +29,7 @@
#pragma section(".lprfd$Z", read, write)
#pragma section(".lprfc$A", read, write)
#pragma section(".lprfc$Z", read, write)
#pragma section(".lorderfile$A", read, write)
#pragma section(".lprfnd$A", read, write)
#pragma section(".lprfnd$Z", read, write)
#endif
@ -41,6 +42,7 @@ const char COMPILER_RT_SECTION(".lprfn$Z") NamesEnd = '\0';
uint64_t COMPILER_RT_SECTION(".lprfc$A") CountersStart;
uint64_t COMPILER_RT_SECTION(".lprfc$Z") CountersEnd;
uint32_t COMPILER_RT_SECTION(".lorderfile$A") OrderFileStart;
ValueProfNode COMPILER_RT_SECTION(".lprfnd$A") VNodesStart;
ValueProfNode COMPILER_RT_SECTION(".lprfnd$Z") VNodesEnd;
@ -55,6 +57,7 @@ const char *__llvm_profile_end_names(void) { return &NamesEnd; }
uint64_t *__llvm_profile_begin_counters(void) { return &CountersStart + 1; }
uint64_t *__llvm_profile_end_counters(void) { return &CountersEnd; }
uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; }
ValueProfNode *__llvm_profile_begin_vnodes(void) { return &VNodesStart + 1; }
ValueProfNode *__llvm_profile_end_vnodes(void) { return &VNodesEnd; }

View File

@ -0,0 +1,7 @@
__attribute__((noinline)) int f(int a) {
return a + 1;
}
__attribute__((noinline)) int g(int a) {
return a + 2;
}

View File

@ -0,0 +1,17 @@
void __llvm_profile_initialize_file(void);
int __llvm_orderfile_dump(void);
__attribute__((noinline)) int f(int a);
__attribute__((noinline)) int g(int a);
int main(int argc, const char *argv[]) {
int a = f(argc);
int t = 0;
for (int i = 0; i < argc; i++)
t += g(a);
f(t);
__llvm_profile_initialize_file();
__llvm_orderfile_dump();
return 0;
}

View File

@ -0,0 +1,17 @@
// UNSUPPORTED: windows
// REQUIRES: darwin
// RUN: rm -rf %t.dir && mkdir -p %t.dir
// RUN: cd %t.dir
//
// RUN: %clang -forder-file-instrumentation -O1 -o %t.2 %S/Inputs/instrprof-order-file-2.c %S/Inputs/instrprof-order-file.c -mllvm -orderfile-write-mapping="mapping.txt"
// RUN: %run %t.2 ANY
// RUN: od -h default.profraw.order | FileCheck %s
// RUN: cat mapping.txt | FileCheck %s --check-prefix=MAPPING
// Make sure we have MD5 for main, then f, then g.
// CHECK: 0000000 d5fa e78d 6436 db95 a18f dd4c 4f75 cc91
// CHECK: 0000020 f5b2 47ff 6643 b671 0000 0000 0000 0000
// MAPPING: MD5 cc914f75dd4ca18f f
// MAPPING: MD5 b671664347fff5b2 g
// MAPPING: MD5 db956436e78dd5fa main