aboutsummaryrefslogtreecommitdiff
path: root/test/profile
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:52:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:52:19 +0000
commit5c909fa013fc285f010a95e8d387e0ef3412da9c (patch)
tree1059d068ad281f4776ff44cd414574f99a460023 /test/profile
parentf31bcc68c72371a2bf63aead9f3373a1ff2053b6 (diff)
downloadsrc-5c909fa013fc285f010a95e8d387e0ef3412da9c.tar.gz
src-5c909fa013fc285f010a95e8d387e0ef3412da9c.zip
Vendor import of compiler-rt trunk r256633:vendor/compiler-rt/compiler-rt-trunk-r256633
Notes
Notes: svn path=/vendor/compiler-rt/dist/; revision=292925 svn path=/vendor/compiler-rt/compiler-rt-trunk-r256633/; revision=292926; tag=vendor/compiler-rt/compiler-rt-trunk-r256633
Diffstat (limited to 'test/profile')
-rw-r--r--test/profile/Inputs/instrprof-shared-lib.c9
-rw-r--r--test/profile/Inputs/instrprof-shared-main.c13
-rw-r--r--test/profile/instrprof-bufferio.c128
-rw-r--r--test/profile/instrprof-error.c12
-rw-r--r--test/profile/instrprof-shared.test75
-rw-r--r--test/profile/instrprof-value-prof-2.c135
-rw-r--r--test/profile/instrprof-value-prof.c253
-rw-r--r--test/profile/instrprof-without-libc.c6
8 files changed, 631 insertions, 0 deletions
diff --git a/test/profile/Inputs/instrprof-shared-lib.c b/test/profile/Inputs/instrprof-shared-lib.c
new file mode 100644
index 000000000000..d22b0a54a017
--- /dev/null
+++ b/test/profile/Inputs/instrprof-shared-lib.c
@@ -0,0 +1,9 @@
+int g1 = 0;
+int g2 = 1;
+
+void foo(int n) {
+ if (n % 5 == 0)
+ g1++;
+ else
+ g2++;
+}
diff --git a/test/profile/Inputs/instrprof-shared-main.c b/test/profile/Inputs/instrprof-shared-main.c
new file mode 100644
index 000000000000..60da3b42c63f
--- /dev/null
+++ b/test/profile/Inputs/instrprof-shared-main.c
@@ -0,0 +1,13 @@
+extern int g1, g2;
+extern void foo(int n);
+
+int main() {
+ int i, j;
+ for (i = 0; i < 1000; i++)
+ for (j = 0; j < 1000; j++)
+ foo(i * j);
+
+ if (g2 - g1 == 280001)
+ return 0;
+ return 1;
+}
diff --git a/test/profile/instrprof-bufferio.c b/test/profile/instrprof-bufferio.c
new file mode 100644
index 000000000000..eed548fd0da2
--- /dev/null
+++ b/test/profile/instrprof-bufferio.c
@@ -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
diff --git a/test/profile/instrprof-error.c b/test/profile/instrprof-error.c
new file mode 100644
index 000000000000..4386d5321878
--- /dev/null
+++ b/test/profile/instrprof-error.c
@@ -0,0 +1,12 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: touch %t.profraw
+// RUN: chmod -w %t.profraw
+// RUN: LLVM_PROFILE_FILE=%t.profraw LLVM_PROFILE_VERBOSE_ERRORS=1 %run %t 1 2>&1 | FileCheck %s
+// RUN: chmod +w %t.profraw
+
+int main(int argc, const char *argv[]) {
+ if (argc < 2)
+ return 1;
+ return 0;
+}
+// CHECK: LLVM Profile: Failed to write file
diff --git a/test/profile/instrprof-shared.test b/test/profile/instrprof-shared.test
new file mode 100644
index 000000000000..851578b0f2c0
--- /dev/null
+++ b/test/profile/instrprof-shared.test
@@ -0,0 +1,75 @@
+"""
+This test produces three shared libraries:
+
+1. libt-instr.so is instrumented
+2. libt-no-instr1.so is not instrumented
+3. libt-no-instr2.so is compiled with instrumentation enabled, but the object file is built
+ with instrumentation turned off.
+
+After the libraries are built, the main program is then built with/without instrumentation and linked
+against 3 libraries above.
+
+The test is to verify that programs linked against these shared objects with and without instrumentation
+enabled behave as expected.
+"""
+
+RUN: mkdir -p %t.d
+RUN: %clang_profgen -o %t.d/libt-instr.so -fPIC -shared %S/Inputs/instrprof-shared-lib.c
+RUN: %clang -o %t.d/libt-no-instr1.so -fPIC -shared %S/Inputs/instrprof-shared-lib.c
+RUN: %clang -c -o %t.d/instrprof-shared-lib-no-instr2.o -fPIC %S/Inputs/instrprof-shared-lib.c
+RUN: %clang_profgen -o %t.d/libt-no-instr2.so -fPIC -shared %t.d/instrprof-shared-lib-no-instr2.o
+
+RUN: %clang_profgen -o %t-instr-instr -L%t.d -rpath %t.d -lt-instr %S/Inputs/instrprof-shared-main.c
+RUN: %clang_profgen -o %t-instr-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %S/Inputs/instrprof-shared-main.c
+RUN: %clang_profgen -o %t-instr-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %S/Inputs/instrprof-shared-main.c
+RUN: %clang -o %t-no-instr1-instr -L%t.d -rpath %t.d -lt-instr %S/Inputs/instrprof-shared-main.c
+RUN: %clang -o %t-no-instr1-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %S/Inputs/instrprof-shared-main.c
+RUN: %clang -o %t-no-instr1-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %S/Inputs/instrprof-shared-main.c
+RUN: %clang -c -o %t.d/instrprof-shared-main-no-instr2.o %S/Inputs/instrprof-shared-main.c
+RUN: %clang -o %t-no-instr2-instr -L%t.d -rpath %t.d -lt-instr %t.d/instrprof-shared-main-no-instr2.o
+RUN: %clang -o %t-no-instr2-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %t.d/instrprof-shared-main-no-instr2.o
+RUN: %clang -o %t-no-instr2-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %t.d/instrprof-shared-main-no-instr2.o
+
+RUN: env LLVM_PROFILE_FILE=%t-instr-instr.profraw %run %t-instr-instr
+RUN: env LLVM_PROFILE_FILE=%t-instr-no-instr1.profraw %run %t-instr-no-instr1
+RUN: env LLVM_PROFILE_FILE=%t-instr-no-instr2.profraw %run %t-instr-no-instr2
+RUN: env LLVM_PROFILE_FILE=%t-no-instr1-instr.profraw %run %t-no-instr1-instr
+RUN: env LLVM_PROFILE_FILE=%t-no-instr2-instr.profraw %run %t-no-instr2-instr
+RUN: env LLVM_PROFILE_FILE=%t-no-instr1-no-instr1.profraw %run %t-no-instr1-no-instr1
+RUN: env LLVM_PROFILE_FILE=%t-no-instr1-no-instr2.profraw %run %t-no-instr1-no-instr2
+RUN: env LLVM_PROFILE_FILE=%t-no-instr2-no-instr1.profraw %run %t-no-instr2-no-instr1
+RUN: env LLVM_PROFILE_FILE=%t-no-instr2-no-instr2.profraw %run %t-no-instr2-no-instr2
+
+RUN: llvm-profdata merge -o %t-instr-instr.profdata %t-instr-instr.profraw
+RUN: llvm-profdata merge -o %t-instr-no-instr1.profdata %t-instr-no-instr1.profraw
+RUN: llvm-profdata merge -o %t-instr-no-instr2.profdata %t-instr-no-instr2.profraw
+RUN: llvm-profdata merge -o %t-no-instr1-instr.profdata %t-no-instr1-instr.profraw
+RUN: llvm-profdata merge -o %t-no-instr2-instr.profdata %t-no-instr2-instr.profraw
+
+RUN: not llvm-profdata merge -o %t-no-instr1-no-instr1.profdata %t-no-instr1-no-instr1.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-FILE
+RUN: not llvm-profdata merge -o %t-no-instr2-no-instr1.profdata %t-no-instr2-no-instr1.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-FILE
+MISSING-FILE: profraw
+
+RUN: llvm-profdata show -counts --function main %t-instr-instr.profdata | grep -v 'Total\|Maximum' > %t-main-1
+RUN: llvm-profdata show -counts --function main %t-instr-no-instr1.profdata | grep -v 'Total\|Maximum' > %t-main-2
+RUN: llvm-profdata show -counts --function main %t-instr-no-instr2.profdata | grep -v 'Total\|Maximum' > %t-main-3
+RUN: llvm-profdata show -counts --function foo %t-instr-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-1
+RUN: llvm-profdata show -counts --function foo %t-no-instr1-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-2
+RUN: llvm-profdata show -counts --function foo %t-no-instr2-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-3
+
+RUN: %clang_profuse=%t-instr-instr.profdata -o %t-main-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c
+RUN: %clang_profuse=%t-instr-no-instr1.profdata -o %t-main-instr-no-instr1.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c
+RUN: %clang_profuse=%t-instr-no-instr2.profdata -o %t-main-instr-no-instr2.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c
+RUN: %clang_profuse=%t-instr-instr.profdata -o %t-lib-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c
+RUN: %clang_profuse=%t-no-instr1-instr.profdata -o %t-lib-no-instr1-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c
+RUN: %clang_profuse=%t-no-instr2-instr.profdata -o %t-lib-no-instr2-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c
+RUN: %clang_profuse=%t-instr-instr.profdata -o %t-lib-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c
+
+RUN: diff %t-main-instr-no-instr1.ll %t-main-instr-no-instr2.ll
+RUN: diff %t-lib-no-instr1-instr.ll %t-lib-no-instr2-instr.ll
+
+RUN: diff %t-main-1 %t-main-2
+RUN: diff %t-main-1 %t-main-3
+RUN: diff %t-foo-1 %t-foo-2
+RUN: diff %t-foo-1 %t-foo-3
+
diff --git a/test/profile/instrprof-value-prof-2.c b/test/profile/instrprof-value-prof-2.c
new file mode 100644
index 000000000000..989353e1f53e
--- /dev/null
+++ b/test/profile/instrprof-value-prof-2.c
@@ -0,0 +1,135 @@
+// RUN: %clang_profgen -O2 -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %s
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+typedef struct __llvm_profile_data __llvm_profile_data;
+const __llvm_profile_data *__llvm_profile_begin_data(void);
+const __llvm_profile_data *__llvm_profile_end_data(void);
+void __llvm_profile_set_num_value_sites(__llvm_profile_data *Data,
+ uint32_t ValueKind,
+ uint16_t NumValueSites);
+__llvm_profile_data *
+__llvm_profile_iterate_data(const __llvm_profile_data *Data);
+void *__llvm_get_function_addr(const __llvm_profile_data *Data);
+void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
+ uint32_t CounterIndex);
+void callee1() {}
+void callee2() {}
+
+void caller_without_value_site1() {}
+void caller_with_value_site_never_called1() {}
+void caller_with_vp1() {}
+void caller_with_value_site_never_called2() {}
+void caller_without_value_site2() {}
+void caller_with_vp2() {}
+
+int main(int argc, const char *argv[]) {
+ unsigned S, NS = 10, V;
+ const __llvm_profile_data *Data, *DataEnd;
+
+ Data = __llvm_profile_begin_data();
+ DataEnd = __llvm_profile_end_data();
+ for (; Data < DataEnd; Data = __llvm_profile_iterate_data(Data)) {
+ void *func = __llvm_get_function_addr(Data);
+ if (func == caller_without_value_site1 ||
+ func == caller_without_value_site2 ||
+ func == callee1 || func == callee2 || func == main)
+ continue;
+
+ __llvm_profile_set_num_value_sites((__llvm_profile_data *)Data,
+ 0 /*IPVK_IndirectCallTarget */, 10);
+
+ if (func == caller_with_value_site_never_called1 ||
+ func == caller_with_value_site_never_called2)
+ continue;
+ for (S = 0; S < NS; S++) {
+ unsigned C;
+ for (C = 0; C < S + 1; C++) {
+ __llvm_profile_instrument_target((uint64_t)&callee1, (void *)Data, S);
+ if (C % 2 == 0)
+ __llvm_profile_instrument_target((uint64_t)&callee2, (void *)Data, S);
+ }
+ }
+ }
+}
+
+// CHECK-LABEL: caller_with_value_site_never_called2:
+// CHECK-NEXT: Hash: 0x0000000000000000
+// CHECK-NEXT: Counters:
+// CHECK-NEXT: Function count
+// CHECK-NEXT: Indirect Call Site Count: 10
+// CHECK-NEXT: Indirect Target Results:
+// CHECK-LABEL: caller_with_vp2:
+// CHECK-NEXT: Hash: 0x0000000000000000
+// CHECK-NEXT: Counters:
+// CHECK-NEXT: Function count:
+// CHECK-NEXT: Indirect Call Site Count: 10
+// CHECK-NEXT: Indirect Target Results:
+// CHECK-NEXT: [ 0, callee1, 1 ]
+// CHECK-NEXT: [ 0, callee2, 1 ]
+// CHECK-NEXT: [ 1, callee1, 2 ]
+// CHECK-NEXT: [ 1, callee2, 1 ]
+// CHECK-NEXT: [ 2, callee1, 3 ]
+// CHECK-NEXT: [ 2, callee2, 2 ]
+// CHECK-NEXT: [ 3, callee1, 4 ]
+// CHECK-NEXT: [ 3, callee2, 2 ]
+// CHECK-NEXT: [ 4, callee1, 5 ]
+// CHECK-NEXT: [ 4, callee2, 3 ]
+// CHECK-NEXT: [ 5, callee1, 6 ]
+// CHECK-NEXT: [ 5, callee2, 3 ]
+// CHECK-NEXT: [ 6, callee1, 7 ]
+// CHECK-NEXT: [ 6, callee2, 4 ]
+// CHECK-NEXT: [ 7, callee1, 8 ]
+// CHECK-NEXT: [ 7, callee2, 4 ]
+// CHECK-NEXT: [ 8, callee1, 9 ]
+// CHECK-NEXT: [ 8, callee2, 5 ]
+// CHECK-NEXT: [ 9, callee1, 10 ]
+// CHECK-NEXT: [ 9, callee2, 5 ]
+// CHECK-LABEL: caller_with_vp1:
+// CHECK-NEXT: Hash: 0x0000000000000000
+// CHECK-NEXT: Counters:
+// CHECK-NEXT: Function count
+// CHECK-NEXT: Indirect Call Site Count: 10
+// CHECK-NEXT: Indirect Target Results:
+// CHECK-NEXT: [ 0, callee1, 1 ]
+// CHECK-NEXT: [ 0, callee2, 1 ]
+// CHECK-NEXT: [ 1, callee1, 2 ]
+// CHECK-NEXT: [ 1, callee2, 1 ]
+// CHECK-NEXT: [ 2, callee1, 3 ]
+// CHECK-NEXT: [ 2, callee2, 2 ]
+// CHECK-NEXT: [ 3, callee1, 4 ]
+// CHECK-NEXT: [ 3, callee2, 2 ]
+// CHECK-NEXT: [ 4, callee1, 5 ]
+// CHECK-NEXT: [ 4, callee2, 3 ]
+// CHECK-NEXT: [ 5, callee1, 6 ]
+// CHECK-NEXT: [ 5, callee2, 3 ]
+// CHECK-NEXT: [ 6, callee1, 7 ]
+// CHECK-NEXT: [ 6, callee2, 4 ]
+// CHECK-NEXT: [ 7, callee1, 8 ]
+// CHECK-NEXT: [ 7, callee2, 4 ]
+// CHECK-NEXT: [ 8, callee1, 9 ]
+// CHECK-NEXT: [ 8, callee2, 5 ]
+// CHECK-NEXT: [ 9, callee1, 10 ]
+// CHECK-NEXT: [ 9, callee2, 5 ]
+// CHECK-LABEL: caller_with_value_site_never_called1:
+// CHECK-NEXT: Hash: 0x0000000000000000
+// CHECK-NEXT: Counters:
+// CHECK-NEXT: Function count:
+// CHECK-NEXT: Indirect Call Site Count: 10
+// CHECK-NEXT: Indirect Target Results:
+// CHECK-LABEL: caller_without_value_site2:
+// CHECK-NEXT: Hash: 0x0000000000000000
+// CHECK-NEXT: Counters:
+// CHECK-NEXT: Function count:
+// CHECK-NEXT: Indirect Call Site Count: 0
+// CHECK-NEXT: Indirect Target Results:
+// CHECK-LABEL: caller_without_value_site1:
+// CHECK-NEXT: Hash: 0x0000000000000000
+// CHECK-NEXT: Counters:
+// CHECK-NEXT: Function count:
+// CHECK-NEXT: Indirect Call Site Count: 0
+// CHECK-NEXT: Indirect Target Results:
diff --git a/test/profile/instrprof-value-prof.c b/test/profile/instrprof-value-prof.c
new file mode 100644
index 000000000000..3ccecbe75593
--- /dev/null
+++ b/test/profile/instrprof-value-prof.c
@@ -0,0 +1,253 @@
+// RUN: %clang_profgen -O2 -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t 1
+// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-profdata merge -o %t-2.profdata %t-2.profraw
+// RUN: llvm-profdata merge -o %t-merged.profdata %t.profraw %t-2.profdata
+// RUN: llvm-profdata show --all-functions -ic-targets %t-2.profdata | FileCheck %s -check-prefix=NO-VALUE
+// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %s
+// value profile merging current do sorting based on target values -- this will destroy the order of the target
+// in the list leading to comparison problem. For now just check a small subset of output.
+// RUN: llvm-profdata show --all-functions -ic-targets %t-merged.profdata | FileCheck %s -check-prefix=MERGE
+//
+// RUN: env LLVM_PROFILE_FILE=%t-3.profraw LLVM_VP_BUFFER_SIZE=1 %run %t 1
+// RUN: env LLVM_PROFILE_FILE=%t-4.profraw LLVM_VP_BUFFER_SIZE=8 %run %t 1
+// RUN: env LLVM_PROFILE_FILE=%t-5.profraw LLVM_VP_BUFFER_SIZE=128 %run %t 1
+// RUN: env LLVM_PROFILE_FILE=%t-6.profraw LLVM_VP_BUFFER_SIZE=1024 %run %t 1
+// RUN: env LLVM_PROFILE_FILE=%t-7.profraw LLVM_VP_BUFFER_SIZE=102400 %run %t 1
+// RUN: llvm-profdata merge -o %t-3.profdata %t-3.profraw
+// RUN: llvm-profdata merge -o %t-4.profdata %t-4.profraw
+// RUN: llvm-profdata merge -o %t-5.profdata %t-5.profraw
+// RUN: llvm-profdata merge -o %t-6.profdata %t-6.profraw
+// RUN: llvm-profdata merge -o %t-7.profdata %t-7.profraw
+// RUN: llvm-profdata show --all-functions -ic-targets %t-3.profdata | FileCheck %s
+// RUN: llvm-profdata show --all-functions -ic-targets %t-4.profdata | FileCheck %s
+// RUN: llvm-profdata show --all-functions -ic-targets %t-5.profdata | FileCheck %s
+// RUN: llvm-profdata show --all-functions -ic-targets %t-6.profdata | FileCheck %s
+// RUN: llvm-profdata show --all-functions -ic-targets %t-7.profdata | FileCheck %s
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+typedef struct __llvm_profile_data __llvm_profile_data;
+const __llvm_profile_data *__llvm_profile_begin_data(void);
+const __llvm_profile_data *__llvm_profile_end_data(void);
+void __llvm_profile_set_num_value_sites(__llvm_profile_data *Data,
+ uint32_t ValueKind,
+ uint16_t NumValueSites);
+__llvm_profile_data *
+__llvm_profile_iterate_data(const __llvm_profile_data *Data);
+void *__llvm_get_function_addr(const __llvm_profile_data *Data);
+void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
+ uint32_t CounterIndex);
+
+#define DEF_FUNC(x) \
+ void x() {}
+#define DEF_2_FUNCS(x) DEF_FUNC(x##_1) DEF_FUNC(x##_2)
+#define DEF_4_FUNCS(x) DEF_2_FUNCS(x##_1) DEF_2_FUNCS(x##_2)
+#define DEF_8_FUNCS(x) DEF_4_FUNCS(x##_1) DEF_4_FUNCS(x##_2)
+#define DEF_16_FUNCS(x) DEF_8_FUNCS(x##_1) DEF_8_FUNCS(x##_2)
+#define DEF_32_FUNCS(x) DEF_16_FUNCS(x##_1) DEF_16_FUNCS(x##_2)
+#define DEF_64_FUNCS(x) DEF_32_FUNCS(x##_1) DEF_32_FUNCS(x##_2)
+#define DEF_128_FUNCS(x) DEF_64_FUNCS(x##_1) DEF_64_FUNCS(x##_2)
+
+#define FUNC_ADDR(x) &x,
+#define FUNC_2_ADDRS(x) FUNC_ADDR(x##_1) FUNC_ADDR(x##_2)
+#define FUNC_4_ADDRS(x) FUNC_2_ADDRS(x##_1) FUNC_2_ADDRS(x##_2)
+#define FUNC_8_ADDRS(x) FUNC_4_ADDRS(x##_1) FUNC_4_ADDRS(x##_2)
+#define FUNC_16_ADDRS(x) FUNC_8_ADDRS(x##_1) FUNC_8_ADDRS(x##_2)
+#define FUNC_32_ADDRS(x) FUNC_16_ADDRS(x##_1) FUNC_16_ADDRS(x##_2)
+#define FUNC_64_ADDRS(x) FUNC_32_ADDRS(x##_1) FUNC_32_ADDRS(x##_2)
+#define FUNC_128_ADDRS(x) FUNC_64_ADDRS(x##_1) FUNC_64_ADDRS(x##_2)
+
+DEF_8_FUNCS(callee)
+DEF_128_FUNCS(caller)
+
+void *CallerAddrs[] = {FUNC_128_ADDRS(caller)};
+void *CalleeAddrs[] = {FUNC_8_ADDRS(callee)};
+typedef struct CallerInfo {
+ void *CallerAddr;
+ uint32_t NS; /* Number value sites. */
+} CallerInfo;
+
+CallerInfo CallerInfos[128];
+
+int cmpaddr(const void *p1, const void *p2) {
+ CallerInfo *addr1 = (CallerInfo *)p1;
+ CallerInfo *addr2 = (CallerInfo *)p2;
+ return (intptr_t)addr2->CallerAddr - (intptr_t)addr1->CallerAddr;
+}
+
+int main(int argc, const char *argv[]) {
+ unsigned S, NS = 0, I, V, doInstrument = 1;
+ const __llvm_profile_data *Data, *DataEnd;
+
+ if (argc < 2)
+ doInstrument = 0;
+
+ for (I = 0; I < 128; I++) {
+ CallerInfos[I].CallerAddr = CallerAddrs[I];
+ CallerInfos[I].NS = I;
+ }
+ qsort(CallerInfos, sizeof(CallerInfos) / sizeof(CallerInfo), sizeof(CallerInfo),
+ cmpaddr);
+
+ /* We will synthesis value profile data for 128 callers functions.
+ * The number of * value sites. The number values for each value site
+ * ranges from 0 to 8. */
+
+ Data = __llvm_profile_begin_data();
+ DataEnd = __llvm_profile_end_data();
+
+ for (; Data < DataEnd; Data = __llvm_profile_iterate_data(Data)) {
+ void *func = __llvm_get_function_addr(Data);
+ CallerInfo Key, *Res;
+ Key.CallerAddr = func;
+ Res = (CallerInfo *) bsearch(&Key, CallerInfos, sizeof(CallerInfos) / sizeof(CallerInfo),
+ sizeof(CallerInfo), cmpaddr);
+ if (Res) {
+ NS = Res->NS;
+ __llvm_profile_set_num_value_sites((__llvm_profile_data *)Data,
+ 0 /*IPVK_IndirectCallTarget */, NS);
+ if (!doInstrument) {
+ continue;
+ }
+ for (S = 0; S < NS; S++) {
+ for (V = 0; V < S % 8; V++) {
+ unsigned C;
+ for (C = 0; C < V + 1; C++)
+ __llvm_profile_instrument_target((uint64_t)CalleeAddrs[V],
+ (void *)Data, S);
+ }
+ }
+ }
+ }
+}
+
+// NO-VALUE: Indirect Call Site Count: 127
+// NO-VALUE-NEXT: Indirect Target Results:
+// MERGE-LABEL: caller_1_1_1_1_2_2_1:
+// MERGE: Indirect Call Site Count: 6
+// MERGE: Indirect Target Results:
+// MERGE: [ 1, callee_1_1_1, 1 ]
+// MERGE: [ 2, callee_1_1_1, 1 ]
+// MERGE: [ 2, callee_1_1_2, 2 ]
+// MERGE: [ 3, callee_1_1_1, 1 ]
+// MERGE: [ 3, callee_1_1_2, 2 ]
+// MERGE: [ 3, callee_1_2_1, 3 ]
+// MERGE: [ 4, callee_1_1_1, 1 ]
+// MERGE: [ 4, callee_1_1_2, 2 ]
+// MERGE: [ 4, callee_1_2_1, 3 ]
+// MERGE: [ 4, callee_1_2_2, 4 ]
+// MERGE: [ 5, callee_1_1_1, 1 ]
+// MERGE: [ 5, callee_1_1_2, 2 ]
+// MERGE: [ 5, callee_1_2_1, 3 ]
+// MERGE: [ 5, callee_1_2_2, 4 ]
+// MERGE: [ 5, callee_2_1_1, 5 ]
+// MERGE-LABEL: caller_2_2_2_2_2_2_2:
+// MERGE: Indirect Call Site Count: 127
+// MERGE-NEXT: Indirect Target Results:
+// MERGE-NEXT: [ 1, callee_1_1_1, 1 ]
+// MERGE: [ 2, callee_1_1_1, 1 ]
+// MERGE: [ 2, callee_1_1_2, 2 ]
+// MERGE: [ 3, callee_1_1_1, 1 ]
+// MERGE: [ 3, callee_1_1_2, 2 ]
+// MERGE: [ 3, callee_1_2_1, 3 ]
+// CHECK-LABEL: caller_1_1_1_1_2_2_1:
+// CHECK: Indirect Call Site Count: 6
+// CHECK-NEXT: Indirect Target Results:
+// CHECK-NEXT: [ 1, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 2, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 2, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 3, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 3, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 3, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 4, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 4, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 4, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 4, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 5, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 5, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 5, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 5, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 5, callee_2_1_1, 5 ]
+// CHECK-LABEL: caller_2_2_2_2_2_2_2:
+// CHECK: Indirect Call Site Count: 127
+// CHECK-NEXT: Indirect Target Results:
+// CHECK-NEXT: [ 1, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 2, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 2, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 3, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 3, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 3, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 4, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 4, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 4, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 4, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 5, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 5, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 5, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 5, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 5, callee_2_1_1, 5 ]
+// CHECK-NEXT: [ 6, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 6, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 6, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 6, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 6, callee_2_1_1, 5 ]
+// CHECK-NEXT: [ 6, callee_2_1_2, 6 ]
+// CHECK-NEXT: [ 7, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 7, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 7, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 7, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 7, callee_2_1_1, 5 ]
+// CHECK-NEXT: [ 7, callee_2_1_2, 6 ]
+// CHECK-NEXT: [ 7, callee_2_2_1, 7 ]
+// CHECK-NEXT: [ 9, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 10, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 10, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 11, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 11, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 11, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 12, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 12, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 12, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 12, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 13, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 13, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 13, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 13, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 13, callee_2_1_1, 5 ]
+// CHECK-NEXT: [ 14, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 14, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 14, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 14, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 14, callee_2_1_1, 5 ]
+// CHECK-NEXT: [ 14, callee_2_1_2, 6 ]
+// CHECK-NEXT: [ 15, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 15, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 15, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 15, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 15, callee_2_1_1, 5 ]
+// CHECK-NEXT: [ 15, callee_2_1_2, 6 ]
+// CHECK-NEXT: [ 15, callee_2_2_1, 7 ]
+// CHECK-NEXT: [ 17, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 18, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 18, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 19, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 19, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 19, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 20, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 20, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 20, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 20, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 21, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 21, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 21, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 21, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 21, callee_2_1_1, 5 ]
+// CHECK-NEXT: [ 22, callee_1_1_1, 1 ]
+// CHECK-NEXT: [ 22, callee_1_1_2, 2 ]
+// CHECK-NEXT: [ 22, callee_1_2_1, 3 ]
+// CHECK-NEXT: [ 22, callee_1_2_2, 4 ]
+// CHECK-NEXT: [ 22, callee_2_1_1, 5 ]
+
diff --git a/test/profile/instrprof-without-libc.c b/test/profile/instrprof-without-libc.c
index fc6c9b25b3ba..eb0a76ded39f 100644
--- a/test/profile/instrprof-without-libc.c
+++ b/test/profile/instrprof-without-libc.c
@@ -56,5 +56,11 @@ int main(int argc, const char *argv[]) {
// CHECK-SYMBOLS-NOT: _fopen
// CHECK-SYMBOLS-NOT: _fwrite
// CHECK-SYMBOLS-NOT: _getenv
+// CHECK-SYMBOLS-NOT: getenv
// CHECK-SYMBOLS-NOT: _malloc
+// CHECK-SYMBOLS-NOT: malloc
+// CHECK-SYMBOLS-NOT: _calloc
+// CHECK-SYMBOLS-NOT: calloc
+// CHECK-SYMBOLS-NOT: _free
+// CHECK-SYMBOLS-NOT: free
// CHECK-SYMBOLS-NOT: _open