diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -98,6 +98,25 @@ CmdArgs.push_back("-bnoentry"); } + // Specify PGO linker option + if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, + false) || + Args.hasFlag(options::OPT_fprofile_generate, + options::OPT_fno_profile_generate, false) || + Args.hasFlag(options::OPT_fprofile_generate_EQ, + options::OPT_fno_profile_generate, false) || + Args.hasFlag(options::OPT_fprofile_instr_generate, + options::OPT_fno_profile_instr_generate, false) || + Args.hasFlag(options::OPT_fprofile_instr_generate_EQ, + options::OPT_fno_profile_instr_generate, false) || + Args.hasFlag(options::OPT_fcs_profile_generate, + options::OPT_fno_profile_generate, false) || + Args.hasFlag(options::OPT_fcs_profile_generate_EQ, + options::OPT_fno_profile_generate, false) || + Args.hasArg(options::OPT_fcreate_profile) || + Args.hasArg(options::OPT_coverage))) + CmdArgs.push_back("-bdbg:namedcsects"); + // Specify linker output file. assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); if (Output.isFilename()) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -795,11 +795,6 @@ } if (TC.getTriple().isOSAIX()) { - if (PGOGenerateArg) - if (!D.isUsingLTO(false /*IsDeviceOffloadAction */) || - D.getLTOMode() != LTOK_Full) - D.Diag(clang::diag::err_drv_argument_only_allowed_with) - << PGOGenerateArg->getSpelling() << "-flto"; if (ProfileGenerateArg) D.Diag(diag::err_drv_unsupported_opt_for_target) << ProfileGenerateArg->getSpelling() << TC.getTriple().str(); diff --git a/clang/test/Driver/unsupported-option.c b/clang/test/Driver/unsupported-option.c --- a/clang/test/Driver/unsupported-option.c +++ b/clang/test/Driver/unsupported-option.c @@ -14,14 +14,6 @@ // RUN: FileCheck %s --check-prefix=AIX-PROFILE-SAMPLE // AIX-PROFILE-SAMPLE: error: unsupported option '-fprofile-sample-use=' for target -// RUN: not %clang -fprofile-generate --target=powerpc-ibm-aix %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=AIX-PROFILE-LTO -// AIX-PROFILE-LTO: error: invalid argument '-fprofile-generate' only allowed with '-flto' - -// RUN: not %clang -fprofile-generate -flto=thin --target=powerpc64-ibm-aix %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=AIX-PROFILE-THINLTO -// AIX-PROFILE-THINLTO: error: invalid argument '-fprofile-generate' only allowed with '-flto' - // RUN: not %clang --target=powerpc-ibm-aix %s -mlong-double-128 2>&1 | \ // RUN: FileCheck %s --check-prefix=AIX-LONGDOUBLE128-ERR // AIX-LONGDOUBLE128-ERR: error: unsupported option '-mlong-double-128' for target 'powerpc-ibm-aix' diff --git a/clang/test/Profile/cxx-templates.cpp b/clang/test/Profile/cxx-templates.cpp --- a/clang/test/Profile/cxx-templates.cpp +++ b/clang/test/Profile/cxx-templates.cpp @@ -10,8 +10,10 @@ // RUN: FileCheck --input-file=%tuse -check-prefix=T0USE -check-prefix=ALL %s // RUN: FileCheck --input-file=%tuse -check-prefix=T100USE -check-prefix=ALL %s -// T0GEN: @[[T0C:__profc__Z4loopILj0EEvv]] = linkonce_odr {{(hidden|dso_local)}} global [2 x i64] zeroinitializer -// T100GEN: @[[T100C:__profc__Z4loopILj100EEvv]] = linkonce_odr {{(hidden|dso_local)}} global [2 x i64] zeroinitializer +// The linkage can be target dependent, so accept all linkage here, +// the linkage tests for different target are in llvm/test/Instrumentation/InstrProfiling/profiling.ll +// T0GEN: @[[T0C:__profc__Z4loopILj0EEvv]] = {{.*}} global [2 x i64] zeroinitializer +// T100GEN: @[[T100C:__profc__Z4loopILj100EEvv]] = {{.*}} global [2 x i64] zeroinitializer // T0GEN-LABEL: define linkonce_odr {{.*}}void @_Z4loopILj0EEvv() // T0USE-LABEL: define linkonce_odr {{.*}}void @_Z4loopILj0EEvv() diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -862,6 +862,15 @@ GlobalValue::LinkageTypes Linkage = NamePtr->getLinkage(); GlobalValue::VisibilityTypes Visibility = NamePtr->getVisibility(); + // Due to the current limitation of binder, the duplicate weak symbols in the + // same csect won't be discarded. When there are duplicate weak symbols, + // we can NOT guarantee that the relocations get resolved to the intended weak + // symbol, so we can not ensure the correctness of the relative CounterPtr, so + // we have to use private linkage for counter and data symbols. + if (TT.isOSBinFormatXCOFF()) { + Linkage = GlobalValue::PrivateLinkage; + Visibility = GlobalValue::DefaultVisibility; + } // Move the name variable to the right section. Place them in a COMDAT group // if the associated function is a COMDAT. This will make sure that only one // copy of counters of the COMDAT function will be emitted after linking. Keep @@ -966,7 +975,7 @@ // 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) && - (TT.isOSBinFormatELF() || + (TT.isOSBinFormatELF() || TT.isOSBinFormatXCOFF() || (!DataReferencedByCode && TT.isOSBinFormatCOFF()))) { Linkage = GlobalValue::PrivateLinkage; Visibility = GlobalValue::DefaultVisibility; diff --git a/llvm/test/Instrumentation/InstrProfiling/profiling.ll b/llvm/test/Instrumentation/InstrProfiling/profiling.ll --- a/llvm/test/Instrumentation/InstrProfiling/profiling.ll +++ b/llvm/test/Instrumentation/InstrProfiling/profiling.ll @@ -45,8 +45,8 @@ ; MACHO: @__profd_foo_weak = weak hidden global ; COFF: @__profc_foo_weak = weak hidden global ; COFF: @__profd_foo_weak = private global -; XCOFF: @__profc_foo_weak = weak hidden global -; XCOFF: @__profd_foo_weak = weak hidden global +; XCOFF: @__profc_foo_weak = private global +; XCOFF: @__profd_foo_weak = private 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) ret void @@ -71,8 +71,8 @@ ; MACHO: @__profd_foo_inline = linkonce_odr hidden global ; COFF: @__profc_foo_inline = linkonce_odr hidden global{{.*}} section ".lprfc$M", align 8 ; COFF: @__profd_foo_inline = private global{{.*}} section ".lprfd$M", align 8 -; XCOFF: @__profc_foo_inline = linkonce_odr hidden global -; XCOFF: @__profd_foo_inline = linkonce_odr hidden global +; XCOFF: @__profc_foo_inline = private global +; XCOFF: @__profd_foo_inline = private global 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 @@ -84,8 +84,8 @@ ; 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 = private global {{.*}}section ".lprfd$M", comdat($__profc_foo_extern), align 8 -; XCOFF: @__profc_foo_extern = linkonce_odr hidden global -; XCOFF: @__profd_foo_extern = linkonce_odr hidden global +; XCOFF: @__profc_foo_extern = private global +; XCOFF: @__profd_foo_extern = private global define available_externally void @foo_extern() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_extern, i32 0, i32 0), i64 0, i32 1, i32 0) ret void