diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -1142,8 +1142,16 @@ const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR)); Type *IntTy64 = Type::getInt64Ty(M.getContext()); uint64_t ProfileVersion = (INSTR_PROF_RAW_VERSION | VARIANT_MASK_IR_PROF); - if (IsCS) + if (IsCS) { ProfileVersion |= VARIANT_MASK_CSIR_PROF; + + // The IRPGO flag var (__llvm_profile_raw_version) has external linkage, + // it may not be kept if it's non-prevailing for both regular and thin LTO + // compilation. This symbol may be accessed in PGO Instrumentation phase + // through isIRPGOFlagSet. Keep it may involve too much hassel in multiple + // places. Simply set a CSIRPGO module flag to be evaluated instead. + M.addModuleFlag(llvm::Module::Warning, "CSIRPGO", 1); + } if (InstrEntryBBEnabled) ProfileVersion |= VARIANT_MASK_INSTR_ENTRY; auto IRLevelVersionVariable = new GlobalVariable( 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 @@ -757,13 +757,32 @@ 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 enablesIRPGOFlag(const Module &M) { + return isIRPGOFlagSet(&M) || getIntModuleFlagOrZero(M, "CSIRPGO") != 0; +} + +static bool enablesValueProfiling(const Module &M) { + return enablesIRPGOFlag(M) || + getIntModuleFlagOrZero(M, "EnableValueProfiling") != 0; +} + /// 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 || !enablesIRPGOFlag(*M) || !canRenameComdatFunc(*F)) return (Prefix + Name).str(); uint64_t FuncHash = Inc->getHash()->getZExtValue(); @@ -773,20 +792,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,31 @@ +; REQUIRES: x86-registered-target + +; RUN: opt -passes='thinlto-pre-link' --cs-profilegen-file=alloc -cspgo-kind=cspgo-instr-gen-pipeline -module-summary %s -o %t.bc +; RUN: llvm-dis %t.bc -o - | FileCheck %s --check-prefix=IRPGO + +; RUN: llvm-lto2 run -lto-cspgo-profile-file=alloc -lto-cspgo-gen -save-temps -o %t %t.bc \ +; RUN: -r=%t.bc,f,px \ +; RUN: -r=%t.bc,__llvm_profile_filename,x \ +; RUN: -r=%t.bc,__llvm_profile_raw_version,x +; RUN: llvm-dis %t.0.0.preopt.bc -o - | FileCheck %s --check-prefix=IRPGO + +; IRPGO: {{.*}} !"CSIRPGO", 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" + +$f = comdat any + +; Function Attrs: nofree norecurse nosync nounwind readnone uwtable willreturn mustprogress +define 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}