Index: llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h =================================================================== --- llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h +++ llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h @@ -44,6 +44,7 @@ private: InstrProfOptions Options; Module *M; + std::string ModuleUniqueId; Triple TT; const TargetLibraryInfo *TLI; struct PerFunctionProfileData { Index: llvm/lib/ProfileData/InstrProf.cpp =================================================================== --- llvm/lib/ProfileData/InstrProf.cpp +++ llvm/lib/ProfileData/InstrProf.cpp @@ -1049,21 +1049,6 @@ if (!Triple(M.getTargetTriple()).supportsCOMDAT()) return false; - // See createPGOFuncNameVar for more details. To avoid link errors, profile - // counters for function with available_externally linkage needs to be changed - // to linkonce linkage. On ELF based systems, this leads to weak symbols to be - // created. Without using comdat, duplicate entries won't be removed by the - // linker leading to increased data segement size and raw profile size. Even - // worse, since the referenced counter from profile per-function data object - // will be resolved to the common strong definition, the profile counts for - // available_externally functions will end up being duplicated in raw profile - // data. This can result in distorted profile as the counts of those dups - // will be accumulated by the profile merger. - GlobalValue::LinkageTypes Linkage = F.getLinkage(); - if (Linkage != GlobalValue::ExternalWeakLinkage && - Linkage != GlobalValue::AvailableExternallyLinkage) - return false; - return true; } Index: llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -484,6 +484,7 @@ bool InstrProfiling::run(Module &M, const TargetLibraryInfo &TLI) { this->M = &M; + ModuleUniqueId = getUniqueModuleId(this->M); this->TLI = &TLI; NamesVar = nullptr; NamesSize = 0; @@ -760,7 +761,12 @@ CmdtPrefix = getInstrProfCountersVarPrefix(); CounterLinkage = GlobalValue::LinkOnceODRLinkage; } - Cmdt = M->getOrInsertComdat(getVarName(Inc, CmdtPrefix)); + GlobalValue::LinkageTypes Linkage = Fn->getLinkage(); + if (Linkage == GlobalValue::ExternalWeakLinkage || + Linkage == GlobalValue::AvailableExternallyLinkage) + Cmdt = M->getOrInsertComdat(getVarName(Inc, CmdtPrefix)); + else + Cmdt = GetOrCreateFunctionComdat(*Fn, TT, ModuleUniqueId); } uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); Index: llvm/test/Instrumentation/InstrProfiling/PR23499.ll =================================================================== --- llvm/test/Instrumentation/InstrProfiling/PR23499.ll +++ llvm/test/Instrumentation/InstrProfiling/PR23499.ll @@ -14,14 +14,14 @@ @__profn__Z3barIvEvv = linkonce_odr hidden constant [11 x i8] c"_Z3barIvEvv", align 1 ; CHECK-NOT: __profn__Z3barIvEvv -; CHECK: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}__llvm_prf_cnts", comdat($__profv__Z3barIvEvv), align 8 -; CHECK: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data{{.*}}", comdat($__profv__Z3barIvEvv), align 8 +; CHECK: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}__llvm_prf_cnts", comdat($_Z3barIvEvv), align 8 +; CHECK: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data{{.*}}", comdat($_Z3barIvEvv), align 8 ; CHECK: @__llvm_prf_nm = private constant [{{.*}} x i8] c"{{.*}}", section "{{.*}}__llvm_prf_names" ; COFF-NOT: __profn__Z3barIvEvv -; COFF: @__profc__Z3barIvEvv = linkonce_odr dso_local global [1 x i64] zeroinitializer, section "{{.*}}prfc$M", comdat, align 8 -; COFF: @__profd__Z3barIvEvv = internal global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat($__profc__Z3barIvEvv), align 8 +; COFF: @__profc__Z3barIvEvv = linkonce_odr dso_local global [1 x i64] zeroinitializer, section "{{.*}}prfc$M", comdat($_Z3barIvEvv), align 8 +; COFF: @__profd__Z3barIvEvv = internal global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat($_Z3barIvEvv), align 8 declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1 Index: llvm/test/Instrumentation/InstrProfiling/comdat.ll =================================================================== --- llvm/test/Instrumentation/InstrProfiling/comdat.ll +++ llvm/test/Instrumentation/InstrProfiling/comdat.ll @@ -15,10 +15,10 @@ @__profn_foo_inline = linkonce_odr hidden constant [10 x i8] c"foo_inline" -; ELF: @__profc_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_cnts", comdat($__profv_foo_inline), align 8 -; ELF: @__profd_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($__profv_foo_inline), align 8 -; COFF: @__profc_foo_inline = linkonce_odr dso_local global{{.*}}, section ".lprfc$M", comdat, align 8 -; COFF: @__profd_foo_inline = internal global{{.*}}, section ".lprfd$M", comdat($__profc_foo_inline), align 8 +; ELF: @__profc_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_cnts", comdat($foo_inline), align 8 +; ELF: @__profd_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($foo_inline), align 8 +; COFF: @__profc_foo_inline = linkonce_odr dso_local global{{.*}}, section ".lprfc$M", comdat($foo_inline), align 8 +; COFF: @__profd_foo_inline = internal global{{.*}}, section ".lprfd$M", comdat($foo_inline), align 8 define weak_odr void @foo_inline() comdat { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_inline, i32 0, i32 0), i64 0, i32 1, i32 0) ret void Index: llvm/test/Instrumentation/InstrProfiling/linkage.ll =================================================================== --- llvm/test/Instrumentation/InstrProfiling/linkage.ll +++ llvm/test/Instrumentation/InstrProfiling/linkage.ll @@ -18,8 +18,7 @@ ; POSIX: @__profc_foo = hidden global ; POSIX: @__profd_foo = hidden global -; COFF: @__profc_foo = internal global -; COFF-NOT: comdat +; COFF: @__profc_foo = linkonce_odr dso_local global ; COFF: @__profd_foo = internal global define void @foo() { 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) @@ -28,7 +27,7 @@ ; POSIX: @__profc_foo_weak = weak hidden global ; POSIX: @__profd_foo_weak = weak hidden global -; COFF: @__profc_foo_weak = internal global +; COFF: @__profc_foo_weak = linkonce_odr dso_local global ; COFF: @__profd_foo_weak = internal global define weak void @foo_weak() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @__profn_foo_weak, i32 0, i32 0), i64 0, i32 1, i32 0) @@ -37,7 +36,7 @@ ; POSIX: @"__profc_linkage.ll:foo_internal" = internal global ; POSIX: @"__profd_linkage.ll:foo_internal" = internal global -; COFF: @"__profc_linkage.ll:foo_internal" = internal global +; COFF: @"__profc_linkage.ll:foo_internal" = linkonce_odr dso_local global ; COFF: @"__profd_linkage.ll:foo_internal" = internal global define internal void @foo_internal() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @"__profn_linkage.ll:foo_internal", i32 0, i32 0), i64 0, i32 1, i32 0) @@ -46,8 +45,8 @@ ; POSIX: @__profc_foo_inline = linkonce_odr hidden global ; POSIX: @__profd_foo_inline = linkonce_odr hidden global -; COFF: @__profc_foo_inline = internal global{{.*}} section ".lprfc$M", align 8 -; COFF: @__profd_foo_inline = internal global{{.*}} section ".lprfd$M", align 8 +; COFF: @__profc_foo_inline = linkonce_odr dso_local global{{.*}} section ".lprfc$M", comdat($foo_inline), align 8 +; COFF: @__profd_foo_inline = internal global{{.*}} section ".lprfd$M", comdat($foo_inline), align 8 define linkonce_odr void @foo_inline() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_inline, i32 0, i32 0), i64 0, i32 1, i32 0) ret void Index: llvm/test/Instrumentation/InstrProfiling/platform.ll =================================================================== --- llvm/test/Instrumentation/InstrProfiling/platform.ll +++ llvm/test/Instrumentation/InstrProfiling/platform.ll @@ -19,12 +19,12 @@ ; WINDOWS-NOT: __profn_foo ; MACHO: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 -; ELF: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8 -; WINDOWS: @__profc_foo = internal global [1 x i64] zeroinitializer, section ".lprfc$M", align 8 +; ELF: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat($foo), align 8 +; WINDOWS: @__profc_foo = linkonce_odr dso_local global [1 x i64] zeroinitializer, section ".lprfc$M", comdat($foo), align 8 ; MACHO: @__profd_foo = hidden {{.*}}, section "__DATA,__llvm_prf_data,regular,live_support", align 8 -; ELF: @__profd_foo = hidden {{.*}}, section "__llvm_prf_data", align 8 -; WINDOWS: @__profd_foo = internal global {{.*}}, section ".lprfd$M", align 8 +; ELF: @__profd_foo = hidden {{.*}}, section "__llvm_prf_data", comdat($foo), align 8 +; WINDOWS: @__profd_foo = internal global {{.*}}, section ".lprfd$M", comdat($foo), align 8 ; ELF: @__llvm_prf_nm = private constant [{{.*}} x i8] c"{{.*}}", section "{{.*}}__llvm_prf_names", align 1 ; WINDOWS: @__llvm_prf_nm = private constant [{{.*}} x i8] c"{{.*}}", section "{{.*}}lprfn$M", align 1 Index: llvm/test/Transforms/PGOProfile/comdat_internal.ll =================================================================== --- llvm/test/Transforms/PGOProfile/comdat_internal.ll +++ llvm/test/Transforms/PGOProfile/comdat_internal.ll @@ -7,16 +7,15 @@ ; CHECK: $foo = comdat any ; CHECK: $__llvm_profile_raw_version = comdat any -; CHECK: $__profv__stdin__foo.[[FOO_HASH:[0-9]+]] = comdat any @bar = global i32 ()* @foo, align 8 ; CHECK: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat ; CHECK-NOT: __profn__stdin__foo -; CHECK: @__profc__stdin__foo.[[FOO_HASH]] = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat($__profv__stdin__foo.[[FOO_HASH]]), align 8 +; CHECK: @__profc__stdin__foo.[[FOO_HASH:[0-9]+]] = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat($foo), align 8 ; CHECK: @__profd__stdin__foo.[[FOO_HASH]] = private global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 -5640069336071256030, i64 [[FOO_HASH]], i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__stdin__foo.[[FOO_HASH]], i32 0, i32 0), i8* null ; CHECK-NOT: bitcast (i32 ()* @foo to i8*) -; CHECK-SAME: , i8* null, i32 1, [2 x i16] zeroinitializer }, section "__llvm_prf_data", comdat($__profv__stdin__foo.[[FOO_HASH]]), align 8 +; CHECK-SAME: , i8* null, i32 1, [2 x i16] zeroinitializer }, section "__llvm_prf_data", comdat($foo), align 8 ; CHECK: @__llvm_prf_nm ; CHECK: @llvm.used