[compiler-rt] r256604 - [PGO]: Refactor VP data writer
Xinliang David Li via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 29 15:54:41 PST 2015
Author: davidxl
Date: Tue Dec 29 17:54:41 2015
New Revision: 256604
URL: http://llvm.org/viewvc/llvm-project?rev=256604&view=rev
Log:
[PGO]: Refactor VP data writer
Extract the buffered filer writer code used by value profile
writer and turn it into common/sharable buffered fileIO
interfaces. Added a test case for the buffered file writer and
rewrite the VP dumping using the new APIs.
Added:
compiler-rt/trunk/test/profile/instrprof-bufferio.c
Modified:
compiler-rt/trunk/lib/profile/InstrProfilingFile.c
compiler-rt/trunk/lib/profile/InstrProfilingInternal.h
compiler-rt/trunk/lib/profile/InstrProfilingWriter.c
Modified: compiler-rt/trunk/lib/profile/InstrProfilingFile.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingFile.c?rev=256604&r1=256603&r2=256604&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingFile.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingFile.c Tue Dec 29 17:54:41 2015
@@ -30,6 +30,13 @@ static uint32_t fileWriter(ProfDataIOVec
return 0;
}
+COMPILER_RT_VISIBILITY ProfBufferIO *
+llvmCreateBufferIOInternal(void *File, uint32_t BufferSz) {
+ CallocHook = calloc;
+ FreeHook = free;
+ return llvmCreateBufferIO(fileWriter, File, BufferSz);
+}
+
static int writeFile(FILE *File) {
const char *BufferSzStr = 0;
uint64_t ValueDataSize = 0;
Modified: compiler-rt/trunk/lib/profile/InstrProfilingInternal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingInternal.h?rev=256604&r1=256603&r2=256604&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingInternal.h (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingInternal.h Tue Dec 29 17:54:41 2015
@@ -39,7 +39,8 @@ int __llvm_profile_write_buffer_internal
const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd);
/*!
- * This is an internal function not intended to be used externally.
+ * The data structure describing the data to be written by the
+ * low level writer callback function.
*/
typedef struct ProfDataIOVec {
const void *Data;
@@ -49,8 +50,54 @@ typedef struct ProfDataIOVec {
typedef uint32_t (*WriterCallback)(ProfDataIOVec *, uint32_t NumIOVecs,
void **WriterCtx);
+
+/*!
+ * The data structure for buffered IO of profile data.
+ */
+typedef struct ProfBufferIO {
+ /* File handle. */
+ void *File;
+ /* Low level IO callback. */
+ WriterCallback FileWriter;
+ /* The start of the buffer. */
+ uint8_t *BufferStart;
+ /* Total size of the buffer. */
+ uint32_t BufferSz;
+ /* Current byte offset from the start of the buffer. */
+ uint32_t CurOffset;
+} ProfBufferIO;
+
+/* The creator interface used by testing. */
+ProfBufferIO *llvmCreateBufferIOInternal(void *File, uint32_t DefaultBufferSz);
+/*!
+ * This is the interface to create a handle for buffered IO.
+ */
+ProfBufferIO *llvmCreateBufferIO(WriterCallback FileWriter, void *File,
+ uint32_t DefaultBufferSz);
+/*!
+ * The interface to destroy the bufferIO handle and reclaim
+ * the memory.
+ */
+void llvmDeleteBufferIO(ProfBufferIO *BufferIO);
+
+/*!
+ * This is the interface to write \c Data of \c Size bytes through
+ * \c BufferIO. Returns 0 if successful, otherwise return -1.
+ */
+int llvmBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data,
+ uint32_t Size);
+/*!
+ * The interface to flush the remaining data in the buffer.
+ * through the low level writer callback.
+ */
+int llvmBufferIOFlush(ProfBufferIO *BufferIO);
+
+/* The low level interface to write data into a buffer. It is used as the
+ * callback by other high level writer methods such as buffered IO writer
+ * and profile data writer. */
uint32_t llvmBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
void **WriterCtx);
+
int llvmWriteProfData(WriterCallback Writer, void *WriterCtx,
struct ValueProfData **ValueDataArray,
const uint64_t ValueDataSize);
Modified: compiler-rt/trunk/lib/profile/InstrProfilingWriter.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingWriter.c?rev=256604&r1=256603&r2=256604&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingWriter.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingWriter.c Tue Dec 29 17:54:41 2015
@@ -33,6 +33,64 @@ COMPILER_RT_VISIBILITY uint32_t llvmBuff
return 0;
}
+static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter,
+ void *File, uint8_t *Buffer, uint32_t BufferSz) {
+ BufferIO->File = File;
+ BufferIO->FileWriter = FileWriter;
+ BufferIO->BufferStart = Buffer;
+ BufferIO->BufferSz = BufferSz;
+ BufferIO->CurOffset = 0;
+}
+
+COMPILER_RT_VISIBILITY ProfBufferIO *
+llvmCreateBufferIO(WriterCallback FileWriter, void *File, uint32_t BufferSz) {
+ ProfBufferIO *BufferIO = (ProfBufferIO *)CallocHook(1, sizeof(ProfBufferIO));
+ uint8_t *Buffer = (uint8_t *)CallocHook(1, BufferSz);
+ if (!Buffer) {
+ FreeHook(BufferIO);
+ return 0;
+ }
+ llvmInitBufferIO(BufferIO, FileWriter, File, Buffer, BufferSz);
+ return BufferIO;
+}
+
+COMPILER_RT_VISIBILITY void llvmDeleteBufferIO(ProfBufferIO *BufferIO) {
+ FreeHook(BufferIO->BufferStart);
+ FreeHook(BufferIO);
+}
+
+COMPILER_RT_VISIBILITY int
+llvmBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) {
+ /* Buffer is not large enough, it is time to flush. */
+ if (Size + BufferIO->CurOffset > BufferIO->BufferSz) {
+ if (llvmBufferIOFlush(BufferIO) != 0)
+ return -1;
+ }
+ /* Special case, bypass the buffer completely. */
+ ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size}};
+ if (Size > BufferIO->BufferSz) {
+ if (BufferIO->FileWriter(IO, 1, &BufferIO->File))
+ return -1;
+ } else {
+ /* Write the data to buffer */
+ uint8_t *Buffer = BufferIO->BufferStart + BufferIO->CurOffset;
+ llvmBufferWriter(IO, 1, (void **)&Buffer);
+ BufferIO->CurOffset = Buffer - BufferIO->BufferStart;
+ }
+ return 0;
+}
+
+COMPILER_RT_VISIBILITY int llvmBufferIOFlush(ProfBufferIO *BufferIO) {
+ if (BufferIO->CurOffset) {
+ ProfDataIOVec IO[] = {
+ {BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset}};
+ if (BufferIO->FileWriter(IO, 1, &BufferIO->File))
+ return -1;
+ BufferIO->CurOffset = 0;
+ }
+ return 0;
+}
+
COMPILER_RT_VISIBILITY int llvmWriteProfData(WriterCallback Writer,
void *WriterCtx,
ValueProfData **ValueDataArray,
@@ -53,64 +111,28 @@ COMPILER_RT_VISIBILITY int llvmWriteProf
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
ValueProfData **ValueDataBegin,
uint64_t NumVData) {
- ValueProfData **ValueDataArray = ValueDataBegin;
- char *BufferStart = 0, *Buffer;
- ValueProfData *CurVData;
+ ProfBufferIO *BufferIO;
uint32_t I = 0, BufferSz;
if (!ValueDataBegin)
return 0;
BufferSz = VPBufferSize ? VPBufferSize : VP_BUFFER_SIZE;
- BufferStart = (char *)CallocHook(BufferSz, sizeof(uint8_t));
- if (!BufferStart)
- return -1;
+ BufferIO = llvmCreateBufferIO(Writer, WriterCtx, BufferSz);
- uint32_t WriteSize = 0;
- Buffer = BufferStart;
- do {
- CurVData = ValueDataArray[I];
- if (!CurVData) {
- I++;
+ for (I = 0; I < NumVData; I++) {
+ ValueProfData *CurVData = ValueDataBegin[I];
+ if (!CurVData)
continue;
- }
-
- /* Buffer is full or not large enough, it is time to flush. */
- if (CurVData->TotalSize + WriteSize > BufferSz) {
- if (WriteSize) {
- ProfDataIOVec IO[] = {{BufferStart, sizeof(uint8_t), WriteSize}};
- if (Writer(IO, 1, &WriterCtx))
- return -1;
- WriteSize = 0;
- Buffer = BufferStart;
- }
- /* Special case, bypass the buffer completely. */
- if (CurVData->TotalSize > BufferSz) {
- ProfDataIOVec IO[] = {{CurVData, sizeof(uint8_t), CurVData->TotalSize}};
- if (Writer(IO, 1, &WriterCtx))
- return -1;
- FreeHook(ValueDataArray[I]);
- I++;
- }
- } else {
- /* Write the data to buffer */
- ProfDataIOVec IO[] = {{CurVData, sizeof(uint8_t), CurVData->TotalSize}};
- llvmBufferWriter(IO, 1, (void **)&Buffer);
- WriteSize += CurVData->TotalSize;
- FreeHook(ValueDataArray[I]);
- I++;
- }
- } while (I < NumVData);
-
- /* Final flush. */
- if (WriteSize) {
- ProfDataIOVec IO[] = {{BufferStart, sizeof(uint8_t), WriteSize}};
- if (Writer(IO, 1, &WriterCtx))
+ if (llvmBufferIOWrite(BufferIO, (const uint8_t *)CurVData,
+ CurVData->TotalSize) != 0)
return -1;
}
- FreeHook(ValueDataBegin);
- FreeHook(BufferStart);
+ if (llvmBufferIOFlush(BufferIO) != 0)
+ return -1;
+ llvmDeleteBufferIO(BufferIO);
+
return 0;
}
Added: compiler-rt/trunk/test/profile/instrprof-bufferio.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/instrprof-bufferio.c?rev=256604&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/instrprof-bufferio.c (added)
+++ compiler-rt/trunk/test/profile/instrprof-bufferio.c Tue Dec 29 17:54:41 2015
@@ -0,0 +1,128 @@
+// RUN: %clang_profgen -O3 -o %t %s
+// RUN: %run %t %t.out.1 %t.out.2 %t.out.3 %t.out.4
+// RUN: cat %t.out.1 | FileCheck %s
+// RUN: diff %t.out.1 %t.out.2
+// RUN: diff %t.out.2 %t.out.3
+// RUN: diff %t.out.3 %t.out.4
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct ProfBufferIO ProfBufferIO;
+ProfBufferIO *llvmCreateBufferIOInternal(FILE *File, uint32_t DefaultBufferSz);
+void llvmDeleteBufferIO(ProfBufferIO *BufferIO);
+
+int llvmBufferIOWrite(ProfBufferIO *BufferIO, const char *Data, uint32_t Size);
+int llvmBufferIOFlush(ProfBufferIO *BufferIO);
+
+int __llvm_profile_runtime = 0;
+
+const char *SmallData = "ABC\n";
+const char *MediumData =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n";
+char LargeData[10 * 1024];
+int main(int argc, const char *argv[]) {
+ ProfBufferIO *BufferIO;
+ FILE *File[4];
+ uint32_t IOBufferSize[4] = {8, 128, 8 * 1024, 11 * 1024};
+ int I, J;
+ if (argc < 5)
+ return 1;
+
+ for (I = 0; I < 10 * 1024 - 2; I++)
+ LargeData[I] = 'A';
+
+ LargeData[I++] = '\n';
+ LargeData[I++] = '\0';
+
+ for (J = 0; J < 4; J++) {
+ File[J] = fopen(argv[1 + J], "w");
+ if (!File[J])
+ return 1;
+
+ BufferIO = llvmCreateBufferIOInternal(File[J], IOBufferSize[J]);
+
+ llvmBufferIOWrite(BufferIO, "Short Strings:\n", strlen("Short Strings:\n"));
+ for (I = 0; I < 1024; I++) {
+ llvmBufferIOWrite(BufferIO, SmallData, strlen(SmallData));
+ }
+ llvmBufferIOWrite(BufferIO, "Long Strings:\n", strlen("Long Strings:\n"));
+ for (I = 0; I < 1024; I++) {
+ llvmBufferIOWrite(BufferIO, MediumData, strlen(MediumData));
+ }
+ llvmBufferIOWrite(BufferIO, "Extra Long Strings:\n",
+ strlen("Extra Long Strings:\n"));
+ for (I = 0; I < 10; I++) {
+ llvmBufferIOWrite(BufferIO, LargeData, strlen(LargeData));
+ }
+ llvmBufferIOWrite(BufferIO, "Mixed Strings:\n", strlen("Mixed Strings:\n"));
+ for (I = 0; I < 1024; I++) {
+ llvmBufferIOWrite(BufferIO, MediumData, strlen(MediumData));
+ llvmBufferIOWrite(BufferIO, SmallData, strlen(SmallData));
+ }
+ llvmBufferIOWrite(BufferIO, "Endings:\n", strlen("Endings:\n"));
+ llvmBufferIOWrite(BufferIO, "END\n", strlen("END\n"));
+ llvmBufferIOWrite(BufferIO, "ENDEND\n", strlen("ENDEND\n"));
+ llvmBufferIOWrite(BufferIO, "ENDENDEND\n", strlen("ENDENDEND\n"));
+ llvmBufferIOWrite(BufferIO, "ENDENDENDEND\n", strlen("ENDENDENDEND\n"));
+ llvmBufferIOFlush(BufferIO);
+
+ llvmDeleteBufferIO(BufferIO);
+
+ fclose(File[J]);
+ }
+ return 0;
+}
+
+// CHECK-LABEL: Short Strings:
+// CHECK: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABC
+// CHECK-LABEL: Long Strings:
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-LABEL: Mixed Strings:
+// CHECK: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+// CHECK-NEXT: ABC
+// CHECK-LABEL: Endings:
+// CHECK: END
+// CHECK-NEXT: ENDEND
+// CHECK-NEXT: ENDENDEND
+// CHECK-NEXT: ENDENDENDEND
More information about the llvm-commits
mailing list