Index: llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -1027,13 +1027,10 @@ // data variable live under linker GC, the data variable can be private. This // optimization applies to ELF. // - // On COFF, a comdat leader cannot be local so we require DataReferencedByCode - // to be false. - // - // If profd is in a deduplicate comdat, NS==0 with a hash suffix guarantees - // that other copies must have the same CFG and cannot have value profiling. - // If no hash suffix, other profd copies may be referenced by code. - if (NS == 0 && !(DataReferencedByCode && NeedComdat && !Renamed) && + // We cannot set profd to private if the assoicated function is a COMDAT: + // LTO might dissolve the COMDAT group, resulting duplicated profd and + // duplicated function entries in the profile. + if (NS == 0 && !NeedComdat && (TT.isOSBinFormatELF() || (!DataReferencedByCode && TT.isOSBinFormatCOFF()))) { Linkage = GlobalValue::PrivateLinkage; Index: llvm/test/Instrumentation/InstrProfiling/comdat.ll =================================================================== --- llvm/test/Instrumentation/InstrProfiling/comdat.ll +++ llvm/test/Instrumentation/InstrProfiling/comdat.ll @@ -24,15 +24,11 @@ @__profn_foo_extern = linkonce_odr hidden constant [10 x i8] c"foo_extern" @__profn_foo_private_profn = private constant [17 x i8] c"foo_private_profn" -;; When value profiling is disabled, __profd_ variables are not referenced by -;; code. We can use private linkage. When enabled, __profd_ needs to be -;; non-local which requires separate comdat on COFF due to a link.exe limitation. - ; ELF: @__profc_foo_inline = linkonce_odr hidden global {{.*}}, section "__llvm_prf_cnts", comdat, align 8 -; ELF0: @__profd_foo_inline = private global {{.*}}, section "__llvm_prf_data", comdat($__profc_foo_inline), align 8 +; ELF0: @__profd_foo_inline = linkonce_odr hidden global {{.*}}, section "__llvm_prf_data", comdat($__profc_foo_inline), align 8 ; ELF1: @__profd_foo_inline = linkonce_odr hidden global {{.*}}, section "__llvm_prf_data", comdat($__profc_foo_inline), align 8 ; COFF0: @__profc_foo_inline = linkonce_odr hidden global {{.*}}, section ".lprfc$M", comdat, align 8 -; COFF0: @__profd_foo_inline = internal global {{.*}}, section ".lprfd$M", comdat($__profc_foo_inline), align 8 +; COFF0: @__profd_foo_inline = linkonce_odr hidden global {{.*}}, section ".lprfd$M", comdat($__profc_foo_inline), align 8 ; COFF1: @__profc_foo_inline = linkonce_odr hidden global {{.*}}, section ".lprfc$M", comdat, align 8 ; COFF1: @__profd_foo_inline = linkonce_odr hidden global {{.*}}, section ".lprfd$M", comdat, align 8 define weak_odr void @foo_inline() comdat { @@ -41,10 +37,10 @@ } ; ELF: @__profc_foo_extern = linkonce_odr hidden global{{.*}}, section "__llvm_prf_cnts", comdat, align 8 -; ELF0: @__profd_foo_extern = private global{{.*}}, section "__llvm_prf_data", comdat($__profc_foo_extern), align 8 +; ELF0: @__profd_foo_extern = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($__profc_foo_extern), align 8 ; ELF1: @__profd_foo_extern = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($__profc_foo_extern), align 8 ; COFF: @__profc_foo_extern = linkonce_odr hidden global{{.*}}, section ".lprfc$M", comdat, align 8 -; COFF0: @__profd_foo_extern = internal global{{.*}}, section ".lprfd$M", comdat($__profc_foo_extern), align 8 +; COFF0: @__profd_foo_extern = linkonce_odr hidden global{{.*}}, section ".lprfd$M", comdat($__profc_foo_extern), align 8 ; COFF1: @__profd_foo_extern = linkonce_odr hidden global{{.*}}, section ".lprfd$M", comdat, align 8 define available_externally void @foo_extern() { call void @llvm.instrprof.increment(ptr @__profn_foo_extern, i64 0, i32 1, i32 0) Index: llvm/test/Instrumentation/InstrProfiling/profiling.ll =================================================================== --- llvm/test/Instrumentation/InstrProfiling/profiling.ll +++ llvm/test/Instrumentation/InstrProfiling/profiling.ll @@ -83,11 +83,11 @@ } ; ELF: @__profc_foo_extern = linkonce_odr hidden global {{.*}}section "__llvm_prf_cnts", comdat, align 8 -; ELF: @__profd_foo_extern = private global {{.*}}section "__llvm_prf_data", comdat($__profc_foo_extern), align 8 +; ELF: @__profd_foo_extern = linkonce_odr hidden global {{.*}}section "__llvm_prf_data", comdat($__profc_foo_extern), align 8 ; MACHO: @__profc_foo_extern = linkonce_odr hidden global ; MACHO: @__profd_foo_extern = linkonce_odr hidden global ; COFF: @__profc_foo_extern = linkonce_odr hidden global {{.*}}section ".lprfc$M", comdat, align 8 -; COFF: @__profd_foo_extern = internal global {{.*}}section ".lprfd$M", comdat($__profc_foo_extern), align 8 +; COFF: @__profd_foo_extern = linkonce_odr hidden global {{.*}}section ".lprfd$M", comdat($__profc_foo_extern), align 8 ; XCOFF: @__profc_foo_extern = private global ; XCOFF: @__profd_foo_extern = private global define available_externally void @foo_extern() { Index: llvm/test/Transforms/PGOProfile/comdat.ll =================================================================== --- llvm/test/Transforms/PGOProfile/comdat.ll +++ llvm/test/Transforms/PGOProfile/comdat.ll @@ -9,7 +9,7 @@ ;; so definitions with the same name in other modules must have the same CFG and ;; cannot have value profiling, either. profd can be made private for ELF. ; ELF: @__profc_linkonceodr.[[#]] = linkonce_odr hidden global {{.*}} comdat, align 8 -; ELF: @__profd_linkonceodr.[[#]] = private global {{.*}} comdat($__profc_linkonceodr.[[#]]), align 8 +; ELF: @__profd_linkonceodr.[[#]] = linkonce_odr hidden global {{.*}} comdat($__profc_linkonceodr.[[#]]), align 8 ; COFF: @__profc_linkonceodr.[[#]] = linkonce_odr hidden global {{.*}} comdat, align 8 ; COFF: @__profd_linkonceodr.[[#]] = linkonce_odr hidden global {{.*}} comdat, align 8 define linkonce_odr void @linkonceodr() comdat { Index: llvm/test/Transforms/PGOProfile/indirect_call_profile.ll =================================================================== --- llvm/test/Transforms/PGOProfile/indirect_call_profile.ll +++ llvm/test/Transforms/PGOProfile/indirect_call_profile.ll @@ -15,8 +15,7 @@ ; GEN: @__profn_vp_inline = linkonce_odr hidden constant [9 x i8] c"vp_inline" ;; Test that a linkonce function's address is recorded. -;; We allow a linkonce profd to be private if the function does not use value profiling. -; LOWER: @__profd_novp_inline.[[HASH:[0-9]+]] = private global {{.*}} @__profc_novp_inline.[[HASH]] +; LOWER: @__profd_novp_inline.[[HASH:[0-9]+]] = linkonce_odr hidden global {{.*}} @__profc_novp_inline.[[HASH]] ; LOWER-SAME: ptr @novp_inline ; LOWER: @__profd_foo = private {{.*}} @__profc_foo