Similar to D97585.
D25456 used `S_ATTR_LIVE_SUPPORT` to ensure the data variable will be retained
or discarded as a unit with the counter variable, so llvm.compiler.used is
sufficient. It allows ld to dead strip unneeded profc and profd variables.
Reviewed By: vsk
Differential Revision: https://reviews.llvm.org/D105445
--- /dev/null
+/// 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 -Wl,-dead_strip %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();
+}
--- /dev/null
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os not in ['Darwin']:
+ config.unsupported = True
// GlobalOpt/ConstantMerge) may not discard associated sections as a unit, so
// we conservatively retain all unconditionally in the compiler.
//
- // On ELF, the linker can guarantee the associated sections will be retained
- // or discarded as a unit, so llvm.compiler.used is sufficient. Similarly on
- // COFF, if prof data is not referenced by code we use one comdat and ensure
- // this GC property as well. Otherwise, we have to conservatively make all of
- // the sections retained by the linker.
- if (TT.isOSBinFormatELF() ||
+ // On ELF and Mach-O, the linker can guarantee the associated sections will be
+ // retained or discarded as a unit, so llvm.compiler.used is sufficient.
+ // Similarly on COFF, if prof data is not referenced by code we use one comdat
+ // and ensure this GC property as well. Otherwise, we have to conservatively
+ // make all of the sections retained by the linker.
+ if (TT.isOSBinFormatELF() || TT.isOSBinFormatMachO() ||
(TT.isOSBinFormatCOFF() && !profDataReferencedByCode(*M)))
appendToCompilerUsed(*M, CompilerUsedVars);
else
; ELF: @llvm.compiler.used = appending global {{.*}} @__profd_foo {{.*}}
; ELF_GENERIC: @llvm.compiler.used = appending global {{.*}} @__llvm_profile_runtime {{.*}} @__profd_foo {{.*}}
-; MACHO: @llvm.used = appending global {{.*}} @__llvm_profile_runtime_user {{.*}} @__profd_foo {{.*}}
+; MACHO: @llvm.compiler.used = appending global {{.*}} @__llvm_profile_runtime_user {{.*}} @__profd_foo {{.*}}
; COFF: @llvm.compiler.used = appending global {{.*}} @__llvm_profile_runtime_user {{.*}} @__profd_foo {{.*}}
; MACHO: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() {{.*}} {