[compiler-rt] r262736 - [PGO] Add API to check compatibility of profile data in buffer

Xinliang David Li via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 4 10:58:31 PST 2016


Author: davidxl
Date: Fri Mar  4 12:58:30 2016
New Revision: 262736

URL: http://llvm.org/viewvc/llvm-project?rev=262736&view=rev
Log:
[PGO] Add API to check compatibility of profile data in buffer

This is needed by client which uses in-process merge API.


Added:
    compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match-lib.c
    compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match.c
    compiler-rt/trunk/test/profile/instrprof-merge-match.test
Modified:
    compiler-rt/trunk/lib/profile/InstrProfiling.h
    compiler-rt/trunk/lib/profile/InstrProfilingMerge.c

Modified: compiler-rt/trunk/lib/profile/InstrProfiling.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfiling.h?rev=262736&r1=262735&r2=262736&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfiling.h (original)
+++ compiler-rt/trunk/lib/profile/InstrProfiling.h Fri Mar  4 12:58:30 2016
@@ -63,7 +63,9 @@ uint64_t *__llvm_profile_end_counters(vo
 void __llvm_profile_reset_counters(void);
 
 /*!
- * \brief Read profile data form buffer and merge with
+ * \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
@@ -71,6 +73,16 @@ void __llvm_profile_reset_counters(void)
  */
 void __llvm_profile_merge_from_buffer(const char *Profile, uint64_t Size);
 
+/*! \brief Check if profile in buffer matches the current binary.
+ *
+ *  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).
+ */
+int __llvm_profile_check_compatibility(const char *Profile,
+                                       uint64_t Size);
+
 /*!
  * \brief Counts the number of times a target value is seen.
  *

Modified: compiler-rt/trunk/lib/profile/InstrProfilingMerge.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingMerge.c?rev=262736&r1=262735&r2=262736&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingMerge.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingMerge.c Fri Mar  4 12:58:30 2016
@@ -20,6 +20,48 @@
 COMPILER_RT_WEAK void (*VPMergeHook)(ValueProfData *,
                                      __llvm_profile_data *) = NULL;
 
+/* Returns 1 if profile is not structurally compatible.  */
+COMPILER_RT_VISIBILITY
+int __llvm_profile_check_compatibility(const char *ProfileData,
+                                       uint64_t ProfileSize) {
+  /* Check profile header only for now  */
+  __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
+  __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData;
+  SrcDataStart =
+      (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header));
+  SrcDataEnd = SrcDataStart + Header->DataSize;
+
+  /* Check the header first.  */
+  if (Header->Magic != __llvm_profile_get_magic() ||
+      Header->Version != __llvm_profile_get_version() ||
+      Header->DataSize !=
+          (uint64_t)(__llvm_profile_end_data() - __llvm_profile_begin_data()) ||
+      Header->CountersSize != (uint64_t)(__llvm_profile_end_counters() -
+                                         __llvm_profile_begin_counters()) ||
+      Header->NamesSize != (uint64_t)(__llvm_profile_end_names() -
+                                      __llvm_profile_begin_names()) ||
+      Header->ValueKindLast != IPVK_Last)
+    return 1;
+
+  if (ProfileSize < sizeof(__llvm_profile_header) +
+                        Header->DataSize * sizeof(__llvm_profile_data) +
+                        Header->NamesSize + Header->CountersSize +
+                        Header->ValueDataSize)
+    return 1;
+
+  for (SrcData = SrcDataStart,
+       DstData = (__llvm_profile_data *)__llvm_profile_begin_data();
+       SrcData < SrcDataEnd; ++SrcData, ++DstData) {
+    if (SrcData->NameRef != DstData->NameRef ||
+        SrcData->FuncHash != DstData->FuncHash ||
+        SrcData->NumCounters != DstData->NumCounters)
+      return 1;
+  }
+
+  /* Matched! */
+  return 0;
+}
+
 COMPILER_RT_VISIBILITY
 void __llvm_profile_merge_from_buffer(const char *ProfileData,
                                       uint64_t ProfileSize) {

Added: compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match-lib.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match-lib.c?rev=262736&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match-lib.c (added)
+++ compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match-lib.c Fri Mar  4 12:58:30 2016
@@ -0,0 +1,39 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int __llvm_profile_runtime = 0;
+uint64_t __llvm_profile_get_size_for_buffer(void);
+int __llvm_profile_write_buffer(char *);
+void __llvm_profile_reset_counters(void);
+int __llvm_profile_check_compatibility(const char *, uint64_t);
+
+int gg = 0;
+void bar(char c) {
+  if (c == '1')
+    gg++;
+  else
+    gg--;
+}
+
+/* Returns 0 (size) when an error occurs. */
+uint64_t libEntry(char *Buffer, uint64_t MaxSize) {
+
+  uint64_t Size = __llvm_profile_get_size_for_buffer();
+  if (Size > MaxSize)
+    return 1;
+
+  __llvm_profile_reset_counters();
+
+  bar('1');
+
+  if (__llvm_profile_write_buffer(Buffer))
+    return 0;
+
+  /* Now check compatibility. Should return 0.  */
+  if (__llvm_profile_check_compatibility(Buffer, Size))
+    return 0;
+
+  return Size;
+}
+

Added: compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match.c?rev=262736&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match.c (added)
+++ compiler-rt/trunk/test/profile/Inputs/instrprof-merge-match.c Fri Mar  4 12:58:30 2016
@@ -0,0 +1,54 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+int __llvm_profile_runtime = 0;
+uint64_t __llvm_profile_get_size_for_buffer(void);
+int __llvm_profile_write_buffer(char *);
+void __llvm_profile_reset_counters(void);
+int  __llvm_profile_check_compatibility(const char *, uint64_t);
+
+int g = 0;
+void foo(char c) {
+  if (c == '1')
+    g++;
+  else
+    g--;
+}
+
+extern uint64_t libEntry(char *Buffer, uint64_t MaxSize);
+
+int main(int argc, const char *argv[]) {
+  const uint64_t MaxSize = 10000;
+  static char Buffer[MaxSize];
+
+  uint64_t Size = __llvm_profile_get_size_for_buffer();
+  if (Size > MaxSize)
+    return 1;
+
+  __llvm_profile_reset_counters();
+  foo('0');
+
+  if (__llvm_profile_write_buffer(Buffer))
+    return 1;
+
+  /* Now check compatibility. Should return 0.  */
+  if (__llvm_profile_check_compatibility(Buffer, Size))
+    return 1;
+
+  /* Clear the buffer. */
+  memset(Buffer, 0, MaxSize);
+
+  /* Collect profile from shared library.  */
+  Size = libEntry(Buffer, MaxSize);
+
+  if (!Size)
+    return 1;
+
+  /* Shared library's profile should not match main executable's. */
+  if (!__llvm_profile_check_compatibility(Buffer, Size))
+    return 1;
+
+  return 0;
+}
+

Added: compiler-rt/trunk/test/profile/instrprof-merge-match.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/instrprof-merge-match.test?rev=262736&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/instrprof-merge-match.test (added)
+++ compiler-rt/trunk/test/profile/instrprof-merge-match.test Fri Mar  4 12:58:30 2016
@@ -0,0 +1,5 @@
+// RUN: mkdir -p %t.d
+// RUN: %clang_profgen  -o %t.d/libt.so -fPIC -shared %S/Inputs/instrprof-merge-match-lib.c
+// RUN: %clang_profgen  -o %t -L %t.d -rpath %t.d  %S/Inputs/instrprof-merge-match.c -lt
+// RUN: %run %t
+




More information about the llvm-commits mailing list