[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