diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp --- a/lld/COFF/LTO.cpp +++ b/lld/COFF/LTO.cpp @@ -222,7 +222,7 @@ continue; if (config->saveTemps) - saveBuffer(buf[i], ltoObjName); + saveBuffer(objBuf, ltoObjName); ret.push_back(make(MemoryBufferRef(objBuf, ltoObjName))); } diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -54,6 +54,7 @@ #include "llvm/Transforms/IPO/WholeProgramDevirt.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/Transforms/Utils/SplitModule.h" +#include "llvm/ProfileData/InstrProf.h" #include @@ -846,6 +847,15 @@ M.setModuleInlineAsm(NewIA + M.getModuleInlineAsm()); } + // Since IRPGO flag symbol (__llvm_profile_raw_version) has external linkage, + // it may not be kept if it's not prevailing in a mixed-LTO mode (both regular + // and thin LTO modules) compilation. This symbol will be used in later PGO + // Instrumentation phase by isIRPGOFlagSet. Keep this symbol will cause a + // duplicate symbol error on ELF. Try set the Module flag beforehand that can + // be evaluated later through enablesValueProfiling in PGO pass. + if (isIRPGOFlagSet(&M)) + M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling", 1); + assert(MsymI == MsymE); return std::move(Mod); } 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 @@ -746,13 +746,28 @@ CoverageNamesVar->eraseFromParent(); } +static uint64_t getIntModuleFlagOrZero(const Module &M, StringRef Flag) { + auto *MD = dyn_cast_or_null(M.getModuleFlag(Flag)); + if (!MD) + return 0; + + // If the flag is a ConstantAsMetadata, it should be an integer representable + // in 64-bits. + return cast(MD->getValue())->getZExtValue(); +} + +static bool enablesValueProfiling(const Module &M) { + return getIntModuleFlagOrZero(M, "EnableValueProfiling") != 0 || + isIRPGOFlagSet(&M); +} + /// Get the name of a profiling variable for a particular function. static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) { StringRef NamePrefix = getInstrProfNameVarPrefix(); StringRef Name = Inc->getName()->getName().substr(NamePrefix.size()); Function *F = Inc->getParent()->getParent(); Module *M = F->getParent(); - if (!DoHashBasedCounterSplit || !isIRPGOFlagSet(M) || + if (!DoHashBasedCounterSplit || !enablesValueProfiling(*M) || !canRenameComdatFunc(*F)) return (Prefix + Name).str(); uint64_t FuncHash = Inc->getHash()->getZExtValue(); @@ -762,20 +777,6 @@ return (Prefix + Name + "." + Twine(FuncHash)).str(); } -static uint64_t getIntModuleFlagOrZero(const Module &M, StringRef Flag) { - auto *MD = dyn_cast_or_null(M.getModuleFlag(Flag)); - if (!MD) - return 0; - - // If the flag is a ConstantAsMetadata, it should be an integer representable - // in 64-bits. - return cast(MD->getValue())->getZExtValue(); -} - -static bool enablesValueProfiling(const Module &M) { - return isIRPGOFlagSet(&M) || - getIntModuleFlagOrZero(M, "EnableValueProfiling") != 0; -} // Conservatively returns true if data variables may be referenced by code. static bool profDataReferencedByCode(const Module &M) { diff --git a/llvm/test/Transforms/PGOProfile/lto_cspgo_gen.ll b/llvm/test/Transforms/PGOProfile/lto_cspgo_gen.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/lto_cspgo_gen.ll @@ -0,0 +1,32 @@ +; REQUIRES: x86-registered-target + +; RUN: opt -module-summary %s -o %t1.bc +; RUN: llvm-lto2 run -lto-cspgo-profile-file=alloc -lto-cspgo-gen -save-temps -o %t %t1.bc \ +; RUN: -r=%t1.bc,f,pl \ +; RUN: -r=%t1.bc,__llvm_profile_filename,x \ +; RUN: -r=%t1.bc,__llvm_profile_raw_version,x +; RUN: llvm-dis %t.0.0.preopt.bc -o - | FileCheck %s --check-prefix=VALUEPROFILE + +; VALUEPROFILE: !3 = !{i32 2, !"EnableValueProfiling", i32 1} + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +$__llvm_profile_filename = comdat any +$__llvm_profile_raw_version = comdat any +@__llvm_profile_filename = local_unnamed_addr constant [19 x i8] c"default_%m.profraw\00", comdat +@__llvm_profile_raw_version = local_unnamed_addr constant i64 216172782113783813, comdat + +; Function Attrs: nofree norecurse nosync nounwind readnone uwtable willreturn mustprogress +define dso_local i32 @f() local_unnamed_addr #0 { +entry: + ret i32 1 +} + +attributes #0 = { "target-cpu"="x86-64" } + +!llvm.module.flags = !{!0, !1, !2} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 7, !"uwtable", i32 1} +!2 = !{i32 1, !"ThinLTO", i32 0}