<div dir="ltr">Hi, this causes 37 failures under check-profile. Reverting this change fixes those. Could you take a look and fix/revert?<div><br></div><div>They mostly seem to fail with</div><div>/usr/bin/ld: __llvm_prf_data has both ordered and unordered sections<br>/usr/bin/ld: final link failed: bad value<br>clang-11: error: linker command failed with exit code 1 (use -v to see invocation)</div><div><br></div><div>  Profile-i386 :: Linux/comdat_rename.test<br>  Profile-i386 :: Linux/counter_promo_for.c<br>  Profile-i386 :: Linux/counter_promo_nest.c<br>  Profile-i386 :: Linux/counter_promo_while.c<br>  Profile-i386 :: Linux/coverage_test.cpp<br>  Profile-i386 :: Linux/extern_template.test<br>  Profile-i386 :: Linux/instrprof-cs.c<br>  Profile-i386 :: Linux/instrprof-dynamic-two-shared.test<br>  Profile-i386 :: Linux/instrprof-merge-vp.c<br>  Profile-i386 :: Linux/instrprof-value-merge.c<br>  Profile-i386 :: Linux/instrprof-value-prof-warn.test<br>  Profile-i386 :: Posix/instrprof-dlopen.test<br>  Profile-i386 :: Posix/instrprof-dynamic-one-shared.test<br>  Profile-i386 :: Posix/instrprof-dynamic-two-shared.test<br>  Profile-i386 :: Posix/instrprof-value-prof-shared.test<br>  Profile-i386 :: Posix/instrprof-visibility.cpp<br>  Profile-i386 :: coverage-inline.cpp<br>  Profile-i386 :: infinite_loop.c<br>  Profile-i386 :: instrprof-basic.c<br>  Profile-i386 :: instrprof-dump.c<br>  Profile-i386 :: instrprof-gc-sections.c<br>  Profile-i386 :: instrprof-icall-promo.test<br>  Profile-i386 :: instrprof-merge-match.test<br>  Profile-i386 :: instrprof-merge.c<br>  Profile-i386 :: instrprof-merging.cpp<br>  Profile-i386 :: instrprof-override-filename-with-env.c<br>  Profile-i386 :: instrprof-override-filename.c<br>  Profile-i386 :: instrprof-reset-counters.c<br>  Profile-i386 :: instrprof-set-dir-mode.c<br>  Profile-i386 :: instrprof-value-prof-2.c<br>  Profile-i386 :: instrprof-value-prof-evict.test<br>  Profile-i386 :: instrprof-value-prof-reset.c<br>  Profile-i386 :: instrprof-value-prof.c<br>  Profile-i386 :: instrprof-value-prof.test<br>  Profile-i386 :: instrprof-write-file-only.c<br>  Profile-i386 :: instrprof-write-file.c<br>  Profile-i386 :: runtime_infinite.c<br><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jun 8, 2020 at 3:08 PM Petr Hosek via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Petr Hosek<br>
Date: 2020-06-08T15:07:43-07:00<br>
New Revision: 603d58b5e49c76e4a2e5bf1450b71b100a3396ba<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/603d58b5e49c76e4a2e5bf1450b71b100a3396ba" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/603d58b5e49c76e4a2e5bf1450b71b100a3396ba</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/603d58b5e49c76e4a2e5bf1450b71b100a3396ba.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/603d58b5e49c76e4a2e5bf1450b71b100a3396ba.diff</a><br>
<br>
LOG: [InstrProfiling] Use !associated metadata for counters, data and values<br>
<br>
The !associated metadata may be attached to a global object declaration<br>
with a single argument that references another global object. This<br>
metadata prevents discarding of the global object in linker GC unless<br>
the referenced object is also discarded.<br>
<br>
Furthermore, when a function symbol is discarded by the linker, setting<br>
up !associated metadata allows linker to discard counters, data and<br>
values associated with that function symbol. This is not possible today<br>
because there's metadata to guide the linker. This approach is also used<br>
by other instrumentations like sanitizers.<br>
<br>
Note that !associated metadata is only supported by ELF, it does not have<br>
any effect on non-ELF targets.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D76802" rel="noreferrer" target="_blank">https://reviews.llvm.org/D76802</a><br>
<br>
Added: <br>
    compiler-rt/test/profile/instrprof-gc-sections.c<br>
    llvm/test/Instrumentation/InstrProfiling/associated.ll<br>
    llvm/test/Transforms/PGOProfile/associated.ll<br>
<br>
Modified: <br>
    compiler-rt/lib/profile/InstrProfilingPlatformLinux.c<br>
    llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp<br>
    llvm/test/Transforms/PGOProfile/counter_promo.ll<br>
    llvm/test/Transforms/PGOProfile/counter_promo_mexits.ll<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c<br>
index becfe1fd9f5a..4e3230bfb24c 100644<br>
--- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c<br>
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c<br>
@@ -24,27 +24,21 @@<br>
 #define PROF_VNODES_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNODES_COMMON)<br>
<br>
 /* Declare section start and stop symbols for various sections<br>
- * generated by compiler instrumentation.<br>
+ * generated by compiler instrumentation. These symbols are<br>
+ * declared as weak, which means that they'll end up as NULL if<br>
+ * those sections are empty, and any code that iterates over the<br>
+ * content using __llvm_profile_begin_* and __llvm_profile_end_*<br>
+ * functions defined below will be a no-op.<br>
  */<br>
-extern __llvm_profile_data PROF_DATA_START COMPILER_RT_VISIBILITY;<br>
-extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY;<br>
-extern uint64_t PROF_CNTS_START COMPILER_RT_VISIBILITY;<br>
-extern uint64_t PROF_CNTS_STOP COMPILER_RT_VISIBILITY;<br>
-extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY;<br>
-extern char PROF_NAME_START COMPILER_RT_VISIBILITY;<br>
-extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY;<br>
-extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY;<br>
-extern ValueProfNode PROF_VNODES_STOP COMPILER_RT_VISIBILITY;<br>
-<br>
-/* Add dummy data to ensure the section is always created. */<br>
-__llvm_profile_data<br>
-    __prof_data_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_DATA_SECT_NAME);<br>
-uint64_t<br>
-    __prof_cnts_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_CNTS_SECT_NAME);<br>
-uint32_t<br>
-    __prof_orderfile_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_ORDERFILE_SECT_NAME);<br>
-char __prof_nms_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_NAME_SECT_NAME);<br>
-ValueProfNode __prof_vnodes_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_VNODES_SECT_NAME);<br>
+extern __llvm_profile_data PROF_DATA_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern uint64_t PROF_CNTS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern uint64_t PROF_CNTS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern char PROF_NAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
+extern ValueProfNode PROF_VNODES_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;<br>
<br>
 COMPILER_RT_VISIBILITY const __llvm_profile_data *<br>
 __llvm_profile_begin_data(void) {<br>
<br>
diff  --git a/compiler-rt/test/profile/instrprof-gc-sections.c b/compiler-rt/test/profile/instrprof-gc-sections.c<br>
new file mode 100644<br>
index 000000000000..a3d0fa466c30<br>
--- /dev/null<br>
+++ b/compiler-rt/test/profile/instrprof-gc-sections.c<br>
@@ -0,0 +1,91 @@<br>
+// REQUIRES: linux, lld-available<br>
+<br>
+// RUN: %clang_profgen=%t.profraw -fuse-ld=lld -fcoverage-mapping -mllvm -enable-name-compression=false -DCODE=1 -ffunction-sections -fdata-sections -Wl,--gc-sections -o %t %s<br>
+// RUN: %run %t<br>
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw<br>
+// RUN: llvm-profdata show --all-functions %t.profdata | FileCheck %s -check-prefix=PROF<br>
+// RUN: llvm-cov show %t -instr-profile %t.profdata | FileCheck %s -check-prefix=COV<br>
+// RUN: llvm-nm %t | FileCheck %s -check-prefix=NM<br>
+// RUN: llvm-readelf -x __llvm_prf_names %t | FileCheck %s -check-prefix=PRF_NAMES<br>
+// RUN: llvm-readelf -x __llvm_prf_cnts %t | FileCheck %s -check-prefix=PRF_CNTS<br>
+<br>
+// RUN: %clang_lto_profgen=%t.lto.profraw -fuse-ld=lld -fcoverage-mapping -mllvm -enable-name-compression=false -DCODE=1 -ffunction-sections -fdata-sections -Wl,--gc-sections -flto -o %t.lto %s<br>
+// RUN: %run %t.lto<br>
+// RUN: llvm-profdata merge -o %t.lto.profdata %t.lto.profraw<br>
+// RUN: llvm-profdata show --all-functions %t.lto.profdata | FileCheck %s -check-prefix=PROF<br>
+// RUN: llvm-cov show %t.lto -instr-profile %t.lto.profdata | FileCheck %s -check-prefix=COV<br>
+// RUN: llvm-nm %t.lto | FileCheck %s -check-prefix=NM<br>
+// RUN: llvm-readelf -x __llvm_prf_names %t.lto | FileCheck %s -check-prefix=PRF_NAMES<br>
+// RUN: llvm-readelf -x __llvm_prf_cnts %t.lto | FileCheck %s -check-prefix=PRF_CNTS<br>
+<br>
+// Note: We expect foo() and some of the profiling data associated with it to<br>
+// be garbage collected.<br>
+<br>
+// Note: When there is no code in a program, we expect to see the exact same<br>
+// set of external functions provided by the profile runtime.<br>
+<br>
+// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -fdata-sections -Wl,--gc-sections -shared -o %<a href="http://t.nocode.so" rel="noreferrer" target="_blank">t.nocode.so</a> %s<br>
+// RUN: llvm-nm -jgU %<a href="http://t.nocode.so" rel="noreferrer" target="_blank">t.nocode.so</a> | grep -vE "__start_.*|__stop_.*" > %t.nocode.syms<br>
+// RUN: llvm-nm -jgU %t | grep -vE "main|foo|_start|__libc_.*" > %t.code.syms<br>
+// RUN: <br>
diff  %t.nocode.syms %t.code.syms<br>
+<br>
+// Note: We also check the IR instrumentation and expect foo() to be garbage<br>
+// collected as well.<br>
+<br>
+// RUN: %clang_pgogen=%t.pgo.profraw -fuse-ld=lld -DCODE=1 -ffunction-sections -fdata-sections -Wl,--gc-sections -o %t.pgo %s<br>
+// RUN: %run %t.pgo<br>
+// RUN: llvm-profdata merge -o %t.pgo.profdata %t.pgo.profraw<br>
+// RUN: llvm-profdata show --all-functions %t.pgo.profdata | FileCheck %s -check-prefix=PGO<br>
+// RUN: llvm-nm %t.pgo | FileCheck %s -check-prefix=NM<br>
+<br>
+#ifdef CODE<br>
+<br>
+// COV: [[@LINE+1]]{{ *}}|{{ *}}0|void foo()<br>
+void foo() {}<br>
+<br>
+// COV: [[@LINE+1]]{{ *}}|{{ *}}1|int main<br>
+int main() { return 0; }<br>
+<br>
+#endif // CODE<br>
+<br>
+// NM-NOT: foo<br>
+<br>
+// PROF: Counters:<br>
+// PROF-NEXT:   main:<br>
+// PROF-NEXT:     Hash:<br>
+// PROF-NEXT:     Counters: 1<br>
+// PROF-NEXT:     Function count: 1<br>
+// PROF-NEXT: Instrumentation level: Front-end<br>
+// PROF-NEXT: Functions shown: 1<br>
+// PROF-NEXT: Total functions: 1<br>
+// PROF-NEXT: Maximum function count:<br>
+// PROF-NEXT: Maximum internal block count:<br>
+<br>
+// Note: We don't expect the names of garbage collected functions to disappear<br>
+// from __llvm_prf_names, because collectPGOFuncNameStrings() glues the names<br>
+// together.<br>
+<br>
+// PRF_NAMES: Hex dump of section '__llvm_prf_names':<br>
+// PRF_NAMES-NEXT: {{.*}} 0800666f 6f016d61 696e {{.*$}}<br>
+//                        | | f o  o # m a  i n<br>
+//                        | |___________|<br>
+//                        |             |<br>
+//               UncompressedLen = 8    |<br>
+//                                      |<br>
+//                               CompressedLen = 0<br>
+<br>
+// Note: We expect the profile counters for garbage collected functions to also<br>
+// be garbage collected.<br>
+<br>
+// PRF_CNTS: Hex dump of section '__llvm_prf_cnts':<br>
+// PRF_CNTS-NEXT: {{.*}} 00000000 00000000 {{.*$}}<br>
+<br>
+// PGO: Counters:<br>
+// PGO-NEXT:   main:<br>
+// PGO-NEXT:     Hash:<br>
+// PGO-NEXT:     Counters: 1<br>
+// PGO-NEXT: Instrumentation level: IR<br>
+// PGO-NEXT: Functions shown: 1<br>
+// PGO-NEXT: Total functions: 1<br>
+// PGO-NEXT: Maximum function count:<br>
+// PGO-NEXT: Maximum internal block count:<br>
<br>
diff  --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp<br>
index ceceafa86030..06ccf439501a 100644<br>
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp<br>
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp<br>
@@ -844,6 +844,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {<br>
   CounterPtr->setAlignment(Align(8));<br>
   MaybeSetComdat(CounterPtr);<br>
   CounterPtr->setLinkage(Linkage);<br>
+  CounterPtr->setMetadata(LLVMContext::MD_associated,<br>
+                          MDNode::get(Ctx, ValueAsMetadata::get(CounterPtr)));<br>
<br>
   auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);<br>
   // Allocate statically the array of pointers to value profile nodes for<br>
@@ -865,6 +867,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {<br>
           getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));<br>
       ValuesVar->setAlignment(Align(8));<br>
       MaybeSetComdat(ValuesVar);<br>
+      ValuesVar->setMetadata(LLVMContext::MD_associated,<br>
+                             MDNode::get(Ctx, ValueAsMetadata::get(CounterPtr)));<br>
       ValuesPtrExpr =<br>
           ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));<br>
     }<br>
@@ -899,6 +903,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {<br>
   Data->setAlignment(Align(INSTR_PROF_DATA_ALIGNMENT));<br>
   MaybeSetComdat(Data);<br>
   Data->setLinkage(Linkage);<br>
+  Data->setMetadata(LLVMContext::MD_associated,<br>
+                    MDNode::get(Ctx, ValueAsMetadata::get(CounterPtr)));<br>
<br>
   PD.RegionCounters = CounterPtr;<br>
   PD.DataVar = Data;<br>
<br>
diff  --git a/llvm/test/Instrumentation/InstrProfiling/associated.ll b/llvm/test/Instrumentation/InstrProfiling/associated.ll<br>
new file mode 100644<br>
index 000000000000..dbb496dd8bdb<br>
--- /dev/null<br>
+++ b/llvm/test/Instrumentation/InstrProfiling/associated.ll<br>
@@ -0,0 +1,16 @@<br>
+; RUN: opt < %s -instrprof -S | FileCheck %s<br>
+; RUN: opt < %s -passes=instrprof -S | FileCheck %s<br>
+<br>
+@__profn_foo = hidden constant [3 x i8] c"foo"<br>
+<br>
+; CHECK: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8, !associated !0<br>
+; CHECK: @__profd_foo = hidden global {{.*}}, section "__llvm_prf_data", align 8, !associated !0<br>
+<br>
+define void @foo() {<br>
+  call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 0, i32 1, i32 0)<br>
+  ret void<br>
+}<br>
+<br>
+declare void @llvm.instrprof.increment(i8*, i64, i32, i32)<br>
+<br>
+; CHECK: !0 = !{[1 x i64]* @__profc_foo}<br>
<br>
diff  --git a/llvm/test/Transforms/PGOProfile/associated.ll b/llvm/test/Transforms/PGOProfile/associated.ll<br>
new file mode 100644<br>
index 000000000000..2d12d19d05ed<br>
--- /dev/null<br>
+++ b/llvm/test/Transforms/PGOProfile/associated.ll<br>
@@ -0,0 +1,11 @@<br>
+; RUN: opt < %s -pgo-instr-gen -instrprof -S | FileCheck %s<br>
+; RUN: opt < %s -passes=pgo-instr-gen,instrprof -S | FileCheck %s<br>
+<br>
+; CHECK: @__profc_foo = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8, !associated !0<br>
+; CHECK: @__profd_foo = private global {{.*}}, section "__llvm_prf_data", align 8, !associated !0<br>
+<br>
+define void @foo() {<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK: !0 = !{[1 x i64]* @__profc_foo}<br>
<br>
diff  --git a/llvm/test/Transforms/PGOProfile/counter_promo.ll b/llvm/test/Transforms/PGOProfile/counter_promo.ll<br>
index 812d0fefaa79..da08ace84933 100644<br>
--- a/llvm/test/Transforms/PGOProfile/counter_promo.ll<br>
+++ b/llvm/test/Transforms/PGOProfile/counter_promo.ll<br>
@@ -60,7 +60,7 @@ bb12:                                             ; preds = %bb9<br>
 ; ATOMIC_PROMO: atomicrmw add {{.*}} @__profc_foo{{.*}}0), i64 %[[LIVEOUT1]] seq_cst<br>
 ; ATOMIC_PROMO-NEXT: atomicrmw add {{.*}} @__profc_foo{{.*}}1), i64 %[[LIVEOUT2]] seq_cst<br>
 ; ATOMIC_PROMO-NEXT: atomicrmw add {{.*}} @__profc_foo{{.*}}2), i64 %[[LIVEOUT3]] seq_cst<br>
-; PROMO-NOT: @__profc_foo<br>
+; PROMO-NOT: @__profc_foo{{.*}})<br>
<br>
<br>
 }<br>
<br>
diff  --git a/llvm/test/Transforms/PGOProfile/counter_promo_mexits.ll b/llvm/test/Transforms/PGOProfile/counter_promo_mexits.ll<br>
index bb799757a47c..8e907acb34da 100644<br>
--- a/llvm/test/Transforms/PGOProfile/counter_promo_mexits.ll<br>
+++ b/llvm/test/Transforms/PGOProfile/counter_promo_mexits.ll<br>
@@ -69,7 +69,7 @@ bb15_0:                                             ; preds = %bb11<br>
 ; PROMO-NEXT:  %pgocount{{.*}} = load {{.*}} @__profc_foo{{.*}} 4)<br>
 ; PROMO-NEXT: add <br>
 ; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}4)<br>
-; PROMO-NOT: @__profc_foo<br>
+; PROMO-NOT: @__profc_foo{{.*}})<br>
<br>
<br>
 bb15:                                             ; preds = %bb14, %bb4<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>