[profile] Add -fprofile-instr-generate tests for weak definition and various linkages
authorFangrui Song <i@maskray.me>
Wed, 2 Jun 2021 23:12:08 +0000 (16:12 -0700)
committerFangrui Song <i@maskray.me>
Wed, 2 Jun 2021 23:12:08 +0000 (16:12 -0700)
compiler-rt/test/profile/Linux/coverage-linkage-lld.cpp [new file with mode: 0644]
compiler-rt/test/profile/Linux/coverage-linkage.cpp [new file with mode: 0644]
compiler-rt/test/profile/Linux/coverage-weak-lld.cpp [new file with mode: 0644]
compiler-rt/test/profile/Windows/coverage-linkage-lld.cpp [new file with mode: 0644]
compiler-rt/test/profile/Windows/coverage-linkage.cpp [new file with mode: 0644]
compiler-rt/test/profile/Windows/coverage-weak-lld.cpp [new file with mode: 0644]

diff --git a/compiler-rt/test/profile/Linux/coverage-linkage-lld.cpp b/compiler-rt/test/profile/Linux/coverage-linkage-lld.cpp
new file mode 100644 (file)
index 0000000..5496338
--- /dev/null
@@ -0,0 +1,8 @@
+// REQUIRES: lld-available
+/// With lld --gc-sections we can ensure discarded[01] and their profc/profd
+/// variables are discarded.
+
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -fuse-ld=lld -Wl,--gc-sections %S/coverage-linkage.cpp -o %t
+// RUN: llvm-nm %t | FileCheck %s
+
+// CHECK-NOT: discarded{{.*}}
diff --git a/compiler-rt/test/profile/Linux/coverage-linkage.cpp b/compiler-rt/test/profile/Linux/coverage-linkage.cpp
new file mode 100644 (file)
index 0000000..df0674e
--- /dev/null
@@ -0,0 +1,46 @@
+/// Test instrumentation can handle various linkages.
+// RUN: %clang_profgen -fcoverage-mapping %s -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s
+
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -Wl,--gc-sections %s -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s
+
+// CHECK:      {{.*}}external{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      {{.*}}weak{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      main:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      {{.*}}internal{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      {{.*}}linkonce_odr{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+
+#include <stdio.h>
+
+void discarded0() {}
+__attribute__((weak)) void discarded1() {}
+
+void external() { puts("external"); }
+__attribute__((weak)) void weak() { puts("weak"); }
+static void internal() { puts("internal"); }
+__attribute__((noinline)) inline void linkonce_odr() { puts("linkonce_odr"); }
+
+int main() {
+  internal();
+  external();
+  weak();
+  linkonce_odr();
+}
diff --git a/compiler-rt/test/profile/Linux/coverage-weak-lld.cpp b/compiler-rt/test/profile/Linux/coverage-weak-lld.cpp
new file mode 100644 (file)
index 0000000..de624dd
--- /dev/null
@@ -0,0 +1,103 @@
+// REQUIRES: lld-available
+
+// RUN: %clang_profgen -fcoverage-mapping -c %s -o %t0.o
+// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_1 -o %t1.o
+// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_2 -o %t2.o
+
+/// An external symbol can override a weak external symbol.
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_NOGC
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_NOGC
+
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t2.o -o %t2
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_NOGC
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t2.o -o %t2
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_GC
+
+/// Repeat the above tests with -ffunction-sections.
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -o %t0.o
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_1 -o %t1.o
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_2 -o %t2.o
+
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_NOGC
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_GC
+
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t2.o -o %t2
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_NOGC
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t2.o -o %t2
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_GC
+
+// CHECK1: strong
+// CHECK1: strong
+
+/// __profc__Z4weakv in %t1.o is local and has a zero value.
+/// Without GC it takes a duplicate entry.
+// PROFILE1_NOGC:      _Z4weakv:
+// PROFILE1_NOGC-NEXT:    Hash:
+// PROFILE1_NOGC-NEXT:    Counters: 1
+// PROFILE1_NOGC-NEXT:    Function count: 0
+// PROFILE1_NOGC:      _Z4weakv:
+// PROFILE1_NOGC-NEXT:    Hash:
+// PROFILE1_NOGC-NEXT:    Counters: 1
+// PROFILE1_NOGC-NEXT:    Function count: 2
+
+// PROFILE1_GC:      _Z4weakv:
+// PROFILE1_GC-NEXT:    Hash:
+// PROFILE1_GC-NEXT:    Counters: 1
+// PROFILE1_GC-NEXT:    Function count: 2
+// PROFILE1_GC-NOT:  _Z4weakv:
+
+// CHECK2: weak
+// CHECK2: weak
+
+/// __profc__Z4weakv in %t2.o is weak and resolves to the value of %t0.o's copy.
+/// Without GC it takes a duplicate entry.
+// PROFILE2_NOGC:      _Z4weakv:
+// PROFILE2_NOGC-NEXT:    Hash:
+// PROFILE2_NOGC-NEXT:    Counters: 1
+// PROFILE2_NOGC-NEXT:    Function count: 2
+// PROFILE2_NOGC:      _Z4weakv:
+// PROFILE2_NOGC-NEXT:    Hash:
+// PROFILE2_NOGC-NEXT:    Counters: 1
+// PROFILE2_NOGC-NEXT:    Function count: 2
+
+// PROFILE2_GC:      _Z4weakv:
+// PROFILE2_GC-NEXT:    Hash:
+// PROFILE2_GC-NEXT:    Counters: 1
+// PROFILE2_GC-NEXT:    Function count: 2
+// PROFILE2_GC-NOT:  _Z4weakv:
+
+#ifdef OBJ_1
+#include <stdio.h>
+
+void weak() { puts("strong"); }
+void foo() { weak(); }
+
+#elif defined(OBJ_2)
+#include <stdio.h>
+
+__attribute__((weak)) void weak() { puts("unreachable"); }
+void foo() { weak(); }
+
+#else
+#include <stdio.h>
+
+__attribute__((weak)) void weak() { puts("weak"); }
+void foo();
+
+int main() {
+  foo();
+  weak();
+}
+#endif
diff --git a/compiler-rt/test/profile/Windows/coverage-linkage-lld.cpp b/compiler-rt/test/profile/Windows/coverage-linkage-lld.cpp
new file mode 100644 (file)
index 0000000..714e451
--- /dev/null
@@ -0,0 +1,11 @@
+// REQUIRES: lld-available
+/// With lld -opt:ref we can ensure discarded[01] and their profc/profd
+/// variables are discarded.
+
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -fuse-ld=lld -Wl,-debug:symtab,-opt:noref %S/coverage-linkage.cpp -o %t
+// RUN: llvm-nm %t | FileCheck %s --check-prefix=NOGC
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -fuse-ld=lld -Wl,-debug:symtab,-opt:ref %S/coverage-linkage.cpp -o %t
+// RUN: llvm-nm %t | FileCheck %s --check-prefix=GC
+
+// NOGC:   T ?discarded{{.*}}
+// GC-NOT: T ?discarded{{.*}}
diff --git a/compiler-rt/test/profile/Windows/coverage-linkage.cpp b/compiler-rt/test/profile/Windows/coverage-linkage.cpp
new file mode 100644 (file)
index 0000000..648b3fb
--- /dev/null
@@ -0,0 +1,46 @@
+/// Test instrumentation can handle various linkages.
+// RUN: %clang_profgen -fcoverage-mapping %s -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s
+
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -Wl,-opt:ref %s -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s
+
+// CHECK:      {{.*}}external{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      {{.*}}weak{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      main:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      {{.*}}internal{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+// CHECK:      {{.*}}linkonce_odr{{.*}}:
+// CHECK-NEXT:    Hash:
+// CHECK-NEXT:    Counters: 1
+// CHECK-NEXT:    Function count: 1
+
+#include <stdio.h>
+
+void discarded0() {}
+__attribute__((weak)) void discarded1() {}
+
+void external() { puts("external"); }
+__attribute__((weak)) void weak() { puts("weak"); }
+static void internal() { puts("internal"); }
+__attribute__((noinline)) inline void linkonce_odr() { puts("linkonce_odr"); }
+
+int main() {
+  internal();
+  external();
+  weak();
+  linkonce_odr();
+}
diff --git a/compiler-rt/test/profile/Windows/coverage-weak-lld.cpp b/compiler-rt/test/profile/Windows/coverage-weak-lld.cpp
new file mode 100644 (file)
index 0000000..b170843
--- /dev/null
@@ -0,0 +1,85 @@
+// REQUIRES: lld-available
+
+// RUN: %clang_profgen -fcoverage-mapping -c %s -o %t0.o
+// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_1 -o %t1.o
+// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_2 -o %t2.o
+
+/// An external symbol can override a weak external symbol.
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:noref %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:ref %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1
+
+/// link.exe does not support weak overridding weak.
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-lldmingw,-opt:ref %t0.o %t2.o -o %t2
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2
+
+/// Repeat the above tests with -ffunction-sections (associative comdat).
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -o %t0.o
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_1 -o %t1.o
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_2 -o %t2.o
+
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:noref %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:ref %t0.o %t1.o -o %t1
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1
+
+// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-lldmingw,-opt:ref %t0.o %t2.o -o %t2
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2
+// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2
+
+// CHECK1: strong
+// CHECK1: strong
+
+/// Document the current behavior:
+///  __profc_?weak@@YAXXZ in %t1.o is local and has a zero value.
+/// Without GC it takes a duplicate entry.
+// PROFILE1:      ?weak@@YAXXZ:
+// PROFILE1-NEXT:    Hash:
+// PROFILE1-NEXT:    Counters: 1
+// PROFILE1-NEXT:    Function count: 0
+// PROFILE1:      ?weak@@YAXXZ:
+// PROFILE1-NEXT:    Hash:
+// PROFILE1-NEXT:    Counters: 1
+// PROFILE1-NEXT:    Function count: 2
+
+// CHECK2: weak
+// CHECK2: weak
+
+// PROFILE2:      ?weak@@YAXXZ:
+// PROFILE2-NEXT:    Hash:
+// PROFILE2-NEXT:    Counters: 1
+// PROFILE2-NEXT:    Function count: 2
+// PROFILE2:      ?weak@@YAXXZ:
+// PROFILE2-NEXT:    Hash:
+// PROFILE2-NEXT:    Counters: 1
+// PROFILE2-NEXT:    Function count: 0
+
+#ifdef OBJ_1
+#include <stdio.h>
+
+void weak() { puts("strong"); }
+void foo() { weak(); }
+
+#elif defined(OBJ_2)
+#include <stdio.h>
+
+__attribute__((weak)) void weak() { puts("unreachable"); }
+void foo() { weak(); }
+
+#else
+#include <stdio.h>
+
+__attribute__((weak)) void weak() { puts("weak"); }
+void foo();
+
+int main() {
+  foo();
+  weak();
+}
+#endif