aboutsummaryrefslogtreecommitdiff
path: root/test/profile
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-01-07 19:55:37 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-01-07 19:55:37 +0000
commitca9211ecdede9bdedb812b2243a4abdb8dacd1b9 (patch)
tree9b19e801150082c33e9152275829a6ce90614b55 /test/profile
parent8ef50bf3d1c287b5013c3168de77a462dfce3495 (diff)
downloadsrc-ca9211ecdede9bdedb812b2243a4abdb8dacd1b9.tar.gz
src-ca9211ecdede9bdedb812b2243a4abdb8dacd1b9.zip
Notes
Diffstat (limited to 'test/profile')
-rw-r--r--test/profile/CMakeLists.txt16
-rw-r--r--test/profile/Inputs/instrprof-dlopen-func.c1
-rw-r--r--test/profile/Inputs/instrprof-dlopen-func2.c1
-rw-r--r--test/profile/Inputs/instrprof-dlopen-main.c47
-rw-r--r--test/profile/Inputs/instrprof-dynamic-a.cpp7
-rw-r--r--test/profile/Inputs/instrprof-dynamic-b.cpp7
-rw-r--r--test/profile/Inputs/instrprof-dynamic-header.h5
-rw-r--r--test/profile/Inputs/instrprof-dynamic-main.cpp9
-rw-r--r--test/profile/instrprof-basic.c31
-rw-r--r--test/profile/instrprof-dlopen.test34
-rw-r--r--test/profile/instrprof-dynamic-one-shared.test23
-rw-r--r--test/profile/instrprof-dynamic-two-shared.test24
-rw-r--r--test/profile/instrprof-reset-counters.c19
-rw-r--r--test/profile/instrprof-set-filename.c14
-rw-r--r--test/profile/instrprof-without-libc.c60
-rw-r--r--test/profile/instrprof-write-file-atexit-explicitly.c17
-rw-r--r--test/profile/instrprof-write-file-only.c35
-rw-r--r--test/profile/instrprof-write-file.c34
-rw-r--r--test/profile/lit.cfg53
-rw-r--r--test/profile/lit.site.cfg.in11
20 files changed, 448 insertions, 0 deletions
diff --git a/test/profile/CMakeLists.txt b/test/profile/CMakeLists.txt
new file mode 100644
index 000000000000..28fb35a9f6f8
--- /dev/null
+++ b/test/profile/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(PROFILE_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(PROFILE_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+set(PROFILE_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+if(NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND PROFILE_TEST_DEPS profile llvm-profdata)
+endif()
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ )
+add_lit_testsuite(check-profile "Running the profile tests"
+ ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${PROFILE_TEST_DEPS})
+set_target_properties(check-profile PROPERTIES FOLDER "Profile tests")
diff --git a/test/profile/Inputs/instrprof-dlopen-func.c b/test/profile/Inputs/instrprof-dlopen-func.c
new file mode 100644
index 000000000000..f2de3883535a
--- /dev/null
+++ b/test/profile/Inputs/instrprof-dlopen-func.c
@@ -0,0 +1 @@
+void func(int K) { if (K) {} }
diff --git a/test/profile/Inputs/instrprof-dlopen-func2.c b/test/profile/Inputs/instrprof-dlopen-func2.c
new file mode 100644
index 000000000000..d4d93dc0b256
--- /dev/null
+++ b/test/profile/Inputs/instrprof-dlopen-func2.c
@@ -0,0 +1 @@
+void func2(int K) { if (K) {} }
diff --git a/test/profile/Inputs/instrprof-dlopen-main.c b/test/profile/Inputs/instrprof-dlopen-main.c
new file mode 100644
index 000000000000..ec357fe05bd5
--- /dev/null
+++ b/test/profile/Inputs/instrprof-dlopen-main.c
@@ -0,0 +1,47 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef DLOPEN_FUNC_DIR
+#include <dlfcn.h>
+#else
+void func(int K);
+void func2(int K);
+#endif
+
+int main(int argc, char *argv[]) {
+#ifdef DLOPEN_FUNC_DIR
+ dlerror();
+ void *f1_handle = dlopen(DLOPEN_FUNC_DIR"/func.shared", DLOPEN_FLAGS);
+ if (f1_handle == NULL) {
+ fprintf(stderr, "unable to open '" DLOPEN_FUNC_DIR "/func.shared': %s\n",
+ dlerror());
+ return EXIT_FAILURE;
+ }
+
+ void (*func)(int) = (void (*)(int))dlsym(f1_handle, "func");
+ if (func == NULL) {
+ fprintf(stderr, "unable to lookup symbol 'func': %s\n", dlerror());
+ return EXIT_FAILURE;
+ }
+
+ void *f2_handle = dlopen(DLOPEN_FUNC_DIR"/func2.shared", DLOPEN_FLAGS);
+ if (f2_handle == NULL) {
+ fprintf(stderr, "unable to open '" DLOPEN_FUNC_DIR "/func2.shared': %s\n",
+ dlerror());
+ return EXIT_FAILURE;
+ }
+
+ void (*func2)(int) = (void (*)(int))dlsym(f2_handle, "func2");
+ if (func2 == NULL) {
+ fprintf(stderr, "unable to lookup symbol 'func2': %s\n", dlerror());
+ return EXIT_FAILURE;
+ }
+#endif
+
+ func(1);
+ func2(0);
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/test/profile/Inputs/instrprof-dynamic-a.cpp b/test/profile/Inputs/instrprof-dynamic-a.cpp
new file mode 100644
index 000000000000..67de263c4d88
--- /dev/null
+++ b/test/profile/Inputs/instrprof-dynamic-a.cpp
@@ -0,0 +1,7 @@
+#include "instrprof-dynamic-header.h"
+void a() {
+ if (true) {
+ bar<void>();
+ bar<char>();
+ }
+}
diff --git a/test/profile/Inputs/instrprof-dynamic-b.cpp b/test/profile/Inputs/instrprof-dynamic-b.cpp
new file mode 100644
index 000000000000..c8fb75ef52ed
--- /dev/null
+++ b/test/profile/Inputs/instrprof-dynamic-b.cpp
@@ -0,0 +1,7 @@
+#include "instrprof-dynamic-header.h"
+void b() {
+ if (true) {
+ bar<void>();
+ bar<int>();
+ }
+}
diff --git a/test/profile/Inputs/instrprof-dynamic-header.h b/test/profile/Inputs/instrprof-dynamic-header.h
new file mode 100644
index 000000000000..1dc2e37ef82c
--- /dev/null
+++ b/test/profile/Inputs/instrprof-dynamic-header.h
@@ -0,0 +1,5 @@
+template <class T> void bar() {
+ if (true) {}
+}
+void a();
+void b();
diff --git a/test/profile/Inputs/instrprof-dynamic-main.cpp b/test/profile/Inputs/instrprof-dynamic-main.cpp
new file mode 100644
index 000000000000..0dd60213926e
--- /dev/null
+++ b/test/profile/Inputs/instrprof-dynamic-main.cpp
@@ -0,0 +1,9 @@
+#include "instrprof-dynamic-header.h"
+void foo(int K) { if (K) {} }
+int main(int argc, char *argv[]) {
+ foo(5);
+ bar<void>();
+ a();
+ b();
+ return 0;
+}
diff --git a/test/profile/instrprof-basic.c b/test/profile/instrprof-basic.c
new file mode 100644
index 000000000000..fd3516cfad03
--- /dev/null
+++ b/test/profile/instrprof-basic.c
@@ -0,0 +1,31 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+int begin(int i) {
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (i)
+ return 0;
+ return 1;
+}
+
+int end(int i) {
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]]
+ if (i)
+ return 0;
+ return 1;
+}
+
+int main(int argc, const char *argv[]) {
+ begin(0);
+ end(1);
+
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]]
+ if (argc)
+ return 0;
+ return 1;
+}
+
+// CHECK: ![[PD1]] = metadata !{metadata !"branch_weights", i32 1, i32 2}
+// CHECK: ![[PD2]] = metadata !{metadata !"branch_weights", i32 2, i32 1}
diff --git a/test/profile/instrprof-dlopen.test b/test/profile/instrprof-dlopen.test
new file mode 100644
index 000000000000..ba386e34773b
--- /dev/null
+++ b/test/profile/instrprof-dlopen.test
@@ -0,0 +1,34 @@
+RUN: mkdir -p %t.d
+RUN: %clang_profgen -o %t.d/func.shared -fPIC -shared %S/Inputs/instrprof-dlopen-func.c
+RUN: %clang_profgen -o %t.d/func2.shared -fPIC -shared %S/Inputs/instrprof-dlopen-func2.c
+RUN: %clang -o %t-local -fPIC -DDLOPEN_FUNC_DIR=\"%t.d\" -DDLOPEN_FLAGS="RTLD_LAZY | RTLD_LOCAL" %S/Inputs/instrprof-dlopen-main.c
+RUN: %clang -o %t-global -fPIC -DDLOPEN_FUNC_DIR=\"%t.d\" -DDLOPEN_FLAGS="RTLD_LAZY | RTLD_GLOBAL" %S/Inputs/instrprof-dlopen-main.c
+
+RUN: %clang -c -o %t.d/main.o %S/Inputs/instrprof-dlopen-main.c
+RUN: %clang_profgen -o %t-static %S/Inputs/instrprof-dlopen-func.c %S/Inputs/instrprof-dlopen-func2.c %t.d/main.o
+
+RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static
+RUN: env LLVM_PROFILE_FILE=%t-local.profraw %run %t-local
+RUN: env LLVM_PROFILE_FILE=%t-global.profraw %run %t-global
+
+RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw
+RUN: llvm-profdata merge -o %t-local.profdata %t-local.profraw
+RUN: llvm-profdata merge -o %t-global.profdata %t-global.profraw
+
+RUN: %clang_profuse=%t-static.profdata -o %t-func.static.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-func.c
+RUN: %clang_profuse=%t-local.profdata -o %t-func.local.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-func.c
+RUN: %clang_profuse=%t-global.profdata -o %t-func.global.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-func.c
+RUN: diff %t-func.static.ll %t-func.local.ll
+RUN: diff %t-func.static.ll %t-func.global.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-func2.static.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-func2.c
+RUN: %clang_profuse=%t-local.profdata -o %t-func2.local.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-func2.c
+RUN: %clang_profuse=%t-global.profdata -o %t-func2.global.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-func2.c
+RUN: diff %t-func2.static.ll %t-func2.local.ll
+RUN: diff %t-func2.static.ll %t-func2.global.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-main.c
+RUN: %clang_profuse=%t-local.profdata -o %t-main.local.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-main.c
+RUN: %clang_profuse=%t-local.profdata -o %t-main.global.ll -S -emit-llvm %S/Inputs/instrprof-dlopen-main.c
+RUN: diff %t-main.static.ll %t-main.local.ll
+RUN: diff %t-main.static.ll %t-main.global.ll
diff --git a/test/profile/instrprof-dynamic-one-shared.test b/test/profile/instrprof-dynamic-one-shared.test
new file mode 100644
index 000000000000..38be4fe8bc4e
--- /dev/null
+++ b/test/profile/instrprof-dynamic-one-shared.test
@@ -0,0 +1,23 @@
+RUN: mkdir -p %t.d
+RUN: %clang_profgen -o %t.d/a.shared -fPIC -shared %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profgen -o %t-shared -fPIC -rpath %t.d %t.d/a.shared %S/Inputs/instrprof-dynamic-b.cpp %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: %clang_profgen -o %t-static %S/Inputs/instrprof-dynamic-a.cpp %S/Inputs/instrprof-dynamic-b.cpp %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static
+RUN: env LLVM_PROFILE_FILE=%t-shared.profraw %run %t-shared
+
+RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw
+RUN: llvm-profdata merge -o %t-shared.profdata %t-shared.profraw
+
+RUN: %clang_profuse=%t-static.profdata -o %t-a.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-a.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: diff %t-a.static.ll %t-a.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-b.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-b.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: diff %t-b.static.ll %t-b.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-main.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: diff %t-main.static.ll %t-main.shared.ll
diff --git a/test/profile/instrprof-dynamic-two-shared.test b/test/profile/instrprof-dynamic-two-shared.test
new file mode 100644
index 000000000000..830359dec44f
--- /dev/null
+++ b/test/profile/instrprof-dynamic-two-shared.test
@@ -0,0 +1,24 @@
+RUN: mkdir -p %t.d
+RUN: %clang_profgen -o %t.d/a.shared -fPIC -shared %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profgen -o %t.d/b.shared -fPIC -shared %S/Inputs/instrprof-dynamic-b.cpp
+RUN: %clang_profgen -o %t-shared -fPIC -rpath %t.d %t.d/a.shared %t.d/b.shared %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: %clang_profgen -o %t-static %S/Inputs/instrprof-dynamic-a.cpp %S/Inputs/instrprof-dynamic-b.cpp %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static
+RUN: env LLVM_PROFILE_FILE=%t-shared.profraw %run %t-shared
+
+RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw
+RUN: llvm-profdata merge -o %t-shared.profdata %t-shared.profraw
+
+RUN: %clang_profuse=%t-static.profdata -o %t-a.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-a.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: diff %t-a.static.ll %t-a.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-b.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-b.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: diff %t-b.static.ll %t-b.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-main.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: diff %t-main.static.ll %t-main.shared.ll
diff --git a/test/profile/instrprof-reset-counters.c b/test/profile/instrprof-reset-counters.c
new file mode 100644
index 000000000000..c92732baf45d
--- /dev/null
+++ b/test/profile/instrprof-reset-counters.c
@@ -0,0 +1,19 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+void __llvm_profile_reset_counters(void);
+void foo(int);
+int main(void) {
+ foo(0);
+ __llvm_profile_reset_counters();
+ foo(1);
+ return 0;
+}
+void foo(int N) {
+ // CHECK-LABEL: define void @foo(
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[FOO:[0-9]+]]
+ if (N) {}
+}
+// CHECK: ![[FOO]] = metadata !{metadata !"branch_weights", i32 2, i32 1}
diff --git a/test/profile/instrprof-set-filename.c b/test/profile/instrprof-set-filename.c
new file mode 100644
index 000000000000..045821899e44
--- /dev/null
+++ b/test/profile/instrprof-set-filename.c
@@ -0,0 +1,14 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: %run %t %t.profraw
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+void __llvm_profile_set_filename(const char *);
+int main(int argc, const char *argv[]) {
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+ __llvm_profile_set_filename(argv[1]);
+ return 0;
+}
+// CHECK: ![[PD1]] = metadata !{metadata !"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-without-libc.c b/test/profile/instrprof-without-libc.c
new file mode 100644
index 000000000000..60ca9496c611
--- /dev/null
+++ b/test/profile/instrprof-without-libc.c
@@ -0,0 +1,60 @@
+// RUN: %clang_profgen -DCHECK_SYMBOLS -O3 -o %t.symbols %s
+// RUN: llvm-nm %t.symbols | FileCheck %s --check-prefix=CHECK-SYMBOLS
+// RUN: %clang_profgen -O3 -o %t %s
+// RUN: %run %t %t.profraw
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifndef CHECK_SYMBOLS
+#include <stdio.h>
+#endif
+
+int __llvm_profile_runtime = 0;
+uint64_t __llvm_profile_get_size_for_buffer(void);
+int __llvm_profile_write_buffer(char *);
+int write_buffer(uint64_t, const char *);
+int main(int argc, const char *argv[]) {
+ // CHECK-LABEL: define {{.*}} @main(
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+
+ const uint64_t MaxSize = 10000;
+ static char Buffer[MaxSize];
+
+ uint64_t Size = __llvm_profile_get_size_for_buffer();
+ if (Size > MaxSize)
+ return 1;
+ int Write = __llvm_profile_write_buffer(Buffer);
+ if (__llvm_profile_write_buffer(Buffer))
+ return Write;
+
+#ifdef CHECK_SYMBOLS
+ // Don't write it out. Since we're checking the symbols, we don't have libc
+ // available.
+ return 0;
+#else
+ // Actually write it out so we can FileCheck the output.
+ FILE *File = fopen(argv[1], "w");
+ if (!File)
+ return 1;
+ if (fwrite(Buffer, 1, Size, File) != Size)
+ return 1;
+ return fclose(File);
+#endif
+}
+// CHECK: ![[PD1]] = metadata !{metadata !"branch_weights", i32 1, i32 2}
+
+// CHECK-SYMBOLS-NOT: ___cxx_global_var_init
+// CHECK-SYMBOLS-NOT: ___llvm_profile_register_write_file_atexit
+// CHECK-SYMBOLS-NOT: ___llvm_profile_set_filename
+// CHECK-SYMBOLS-NOT: ___llvm_profile_write_file
+// CHECK-SYMBOLS-NOT: _fdopen
+// CHECK-SYMBOLS-NOT: _fopen
+// CHECK-SYMBOLS-NOT: _fwrite
+// CHECK-SYMBOLS-NOT: _getenv
+// CHECK-SYMBOLS-NOT: _malloc
+// CHECK-SYMBOLS-NOT: _open
diff --git a/test/profile/instrprof-write-file-atexit-explicitly.c b/test/profile/instrprof-write-file-atexit-explicitly.c
new file mode 100644
index 000000000000..ba229b9144fa
--- /dev/null
+++ b/test/profile/instrprof-write-file-atexit-explicitly.c
@@ -0,0 +1,17 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: %run %t %t.profraw
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+int __llvm_profile_runtime = 0;
+int __llvm_profile_register_write_file_atexit(void);
+void __llvm_profile_set_filename(const char *);
+int main(int argc, const char *argv[]) {
+ __llvm_profile_register_write_file_atexit();
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+ __llvm_profile_set_filename(argv[1]);
+ return 0;
+}
+// CHECK: ![[PD1]] = metadata !{metadata !"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-write-file-only.c b/test/profile/instrprof-write-file-only.c
new file mode 100644
index 000000000000..0dd61de39f1a
--- /dev/null
+++ b/test/profile/instrprof-write-file-only.c
@@ -0,0 +1,35 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+int __llvm_profile_runtime = 0;
+void __llvm_profile_initialize_file(void);
+int __llvm_profile_write_file(void);
+void __llvm_profile_set_filename(const char *);
+int foo(int);
+int main(int argc, const char *argv[]) {
+ // CHECK-LABEL: define {{.*}} @main(
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc > 1)
+ return 1;
+
+ // Since the runtime has been suppressed, initialize the file name, as the
+ // writing will fail below as the file name has not been specified.
+ __llvm_profile_initialize_file();
+
+ // Write out the profile.
+ __llvm_profile_write_file();
+
+ // Change the profile.
+ return foo(0);
+}
+int foo(int X) {
+ // There should be no profiling information for @foo, since it was called
+ // after the profile was written (and the atexit was suppressed by defining
+ // profile_runtime).
+ // CHECK-LABEL: define {{.*}} @foo(
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{[^,]+$}}
+ return X <= 0 ? -X : X;
+}
+// CHECK: ![[PD1]] = metadata !{metadata !"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-write-file.c b/test/profile/instrprof-write-file.c
new file mode 100644
index 000000000000..12967cb94a55
--- /dev/null
+++ b/test/profile/instrprof-write-file.c
@@ -0,0 +1,34 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: env LLVM_PROFILE_FILE=%t1.profraw %run %t %t2.profraw
+// RUN: llvm-profdata merge -o %t1.profdata %t1.profraw
+// RUN: %clang_profuse=%t1.profdata -o - -S -emit-llvm %s | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK
+// RUN: llvm-profdata merge -o %t2.profdata %t2.profraw
+// RUN: %clang_profuse=%t2.profdata -o - -S -emit-llvm %s | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK
+
+int __llvm_profile_write_file(void);
+void __llvm_profile_set_filename(const char *);
+int foo(int);
+int main(int argc, const char *argv[]) {
+ // CHECK-LABEL: define {{.*}} @main(
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+
+ // Write out the profile.
+ __llvm_profile_write_file();
+
+ // Change the profile.
+ int Ret = foo(0);
+
+ // It'll write out again at exit; change the filename so we get two files.
+ __llvm_profile_set_filename(argv[1]);
+ return Ret;
+}
+int foo(int X) {
+ // CHECK-LABEL: define {{.*}} @foo(
+ // CHECK1: br i1 %{{.*}}, label %{{.*}}, label %{{[^,]+$}}
+ // CHECK2: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]]
+ return X <= 0 ? -X : X;
+}
+// CHECK: ![[PD1]] = metadata !{metadata !"branch_weights", i32 1, i32 2}
+// CHECK2: ![[PD2]] = metadata !{metadata !"branch_weights", i32 2, i32 1}
diff --git a/test/profile/lit.cfg b/test/profile/lit.cfg
new file mode 100644
index 000000000000..e4910abbe7a4
--- /dev/null
+++ b/test/profile/lit.cfg
@@ -0,0 +1,53 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'Profile'
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Setup executable root.
+if hasattr(config, 'profile_lit_binary_dir') and \
+ config.profile_lit_binary_dir is not None:
+ config.test_exec_root = config.profile_lit_binary_dir
+
+# If the above check didn't work, we're probably in the source tree. Use some
+# magic to re-execute from the build tree.
+if config.test_exec_root is None:
+ # The magic relies on knowing compilerrt_site_basedir.
+ compilerrt_basedir = lit_config.params.get('compilerrt_site_basedir', None)
+ if compilerrt_basedir:
+ site_cfg = os.path.join(compilerrt_basedir, 'profile', 'lit.site.cfg')
+ if os.path.exists(site_cfg):
+ lit_config.load_config(config, site_cfg)
+ raise SystemExit
+
+if config.host_os in ['Linux']:
+ extra_linkflags = ["-ldl"]
+else:
+ extra_linkflags = []
+
+# Test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.ll', '.test']
+
+# What to exclude.
+config.excludes = ['Inputs']
+
+# Clang flags.
+clang_cflags = [config.target_cflags] + extra_linkflags
+
+def build_invocation(compile_flags):
+ return " " + " ".join([config.clang] + compile_flags) + " "
+
+# Add clang substitutions.
+config.substitutions.append( ("%clang ", build_invocation(clang_cflags)) )
+config.substitutions.append( ("%clang_profgen ", build_invocation(clang_cflags) + " -fprofile-instr-generate ") )
+config.substitutions.append( ("%clang_profuse=", build_invocation(clang_cflags) + " -fprofile-instr-use=") )
+
+if config.host_os not in ['Darwin', 'FreeBSD', 'Linux']:
+ config.unsupported = True
+
+if config.target_arch in ['armv7l']:
+ config.unsupported = True
diff --git a/test/profile/lit.site.cfg.in b/test/profile/lit.site.cfg.in
new file mode 100644
index 000000000000..758568d6753a
--- /dev/null
+++ b/test/profile/lit.site.cfg.in
@@ -0,0 +1,11 @@
+## Autogenerated by LLVM/Clang configuration.
+# Do not edit!
+
+# Tool-specific config options.
+config.profile_lit_binary_dir = "@PROFILE_LIT_BINARY_DIR@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@PROFILE_LIT_SOURCE_DIR@/lit.cfg")