diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-01-07 17:46:17 +0000 |
commit | fe013be447cd855ccaf6094a1d06aea570450629 (patch) | |
tree | 9adc1e0a5d25b6280995832bb29d592fb80554a6 /contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | |
parent | 2f3b605b2e159522ecab77fd518e8139aaf581e9 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | 102 |
1 files changed, 93 insertions, 9 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index 3dfa2d821e83..2076ed48ea34 100644 --- a/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -80,6 +80,8 @@ static cl::opt<std::string> ModuleSummaryDotFile( "module-summary-dot-file", cl::Hidden, cl::value_desc("filename"), cl::desc("File to emit dot graph of new summary into")); +extern cl::opt<bool> ScalePartialSampleProfileWorkingSetSize; + // Walk through the operands of a given User via worklist iteration and populate // the set of GlobalValue references encountered. Invoked either on an // Instruction or a GlobalVariable (which walks its initializer). @@ -196,6 +198,7 @@ static void addIntrinsicToSummary( break; } + case Intrinsic::type_checked_load_relative: case Intrinsic::type_checked_load: { auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(2)); auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata()); @@ -263,7 +266,9 @@ static void computeFunctionSummary( unsigned NumInsts = 0; // Map from callee ValueId to profile count. Used to accumulate profile // counts for all static calls to a given callee. - MapVector<ValueInfo, CalleeInfo> CallGraphEdges; + MapVector<ValueInfo, CalleeInfo, DenseMap<ValueInfo, unsigned>, + std::vector<std::pair<ValueInfo, CalleeInfo>>> + CallGraphEdges; SetVector<ValueInfo> RefEdges, LoadRefEdges, StoreRefEdges; SetVector<GlobalValue::GUID> TypeTests; SetVector<FunctionSummary::VFuncId> TypeTestAssumeVCalls, @@ -282,6 +287,10 @@ static void computeFunctionSummary( std::vector<CallsiteInfo> Callsites; std::vector<AllocInfo> Allocs; +#ifndef NDEBUG + DenseSet<const CallBase *> CallsThatMayHaveMemprofSummary; +#endif + bool HasInlineAsmMaybeReferencingInternal = false; bool HasIndirBranchToBlockAddress = false; bool HasUnknownCall = false; @@ -425,6 +434,10 @@ static void computeFunctionSummary( .updateHotness(getHotness(Candidate.Count, PSI)); } + // Summarize memprof related metadata. This is only needed for ThinLTO. + if (!IsThinLTO) + continue; + // TODO: Skip indirect calls for now. Need to handle these better, likely // by creating multiple Callsites, one per target, then speculatively // devirtualize while applying clone info in the ThinLTO backends. This @@ -435,6 +448,14 @@ static void computeFunctionSummary( if (!CalledFunction) continue; + // Ensure we keep this analysis in sync with the handling in the ThinLTO + // backend (see MemProfContextDisambiguation::applyImport). Save this call + // so that we can skip it in checking the reverse case later. + assert(mayHaveMemprofSummary(CB)); +#ifndef NDEBUG + CallsThatMayHaveMemprofSummary.insert(CB); +#endif + // Compute the list of stack ids first (so we can trim them from the stack // ids on any MIBs). CallStack<MDNode, MDNode::op_iterator> InstCallsite( @@ -477,7 +498,9 @@ static void computeFunctionSummary( } } } - Index.addBlockCount(F.size()); + + if (PSI->hasPartialSampleProfile() && ScalePartialSampleProfileWorkingSetSize) + Index.addBlockCount(F.size()); std::vector<ValueInfo> Refs; if (IsThinLTO) { @@ -542,6 +565,25 @@ static void computeFunctionSummary( ? CalleeInfo::HotnessType::Cold : CalleeInfo::HotnessType::Critical); +#ifndef NDEBUG + // Make sure that all calls we decided could not have memprof summaries get a + // false value for mayHaveMemprofSummary, to ensure that this handling remains + // in sync with the ThinLTO backend handling. + if (IsThinLTO) { + for (const BasicBlock &BB : F) { + for (const Instruction &I : BB) { + const auto *CB = dyn_cast<CallBase>(&I); + if (!CB) + continue; + // We already checked these above. + if (CallsThatMayHaveMemprofSummary.count(CB)) + continue; + assert(!mayHaveMemprofSummary(CB)); + } + } + } +#endif + bool NonRenamableLocal = isNonRenamableLocal(F); bool NotEligibleForImport = NonRenamableLocal || HasInlineAsmMaybeReferencingInternal || @@ -583,12 +625,17 @@ static void findFuncPointers(const Constant *I, uint64_t StartingOffset, VTableFuncList &VTableFuncs) { // First check if this is a function pointer. if (I->getType()->isPointerTy()) { - auto Fn = dyn_cast<Function>(I->stripPointerCasts()); - // We can disregard __cxa_pure_virtual as a possible call target, as - // calls to pure virtuals are UB. - if (Fn && Fn->getName() != "__cxa_pure_virtual") - VTableFuncs.push_back({Index.getOrInsertValueInfo(Fn), StartingOffset}); - return; + auto C = I->stripPointerCasts(); + auto A = dyn_cast<GlobalAlias>(C); + if (isa<Function>(C) || (A && isa<Function>(A->getAliasee()))) { + auto GV = dyn_cast<GlobalValue>(C); + assert(GV); + // We can disregard __cxa_pure_virtual as a possible call target, as + // calls to pure virtuals are UB. + if (GV && GV->getName() != "__cxa_pure_virtual") + VTableFuncs.push_back({Index.getOrInsertValueInfo(GV), StartingOffset}); + return; + } } // Walk through the elements in the constant struct or array and recursively @@ -741,10 +788,14 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( std::function<const StackSafetyInfo *(const Function &F)> GetSSICallback) { assert(PSI); bool EnableSplitLTOUnit = false; + bool UnifiedLTO = false; if (auto *MD = mdconst::extract_or_null<ConstantInt>( M.getModuleFlag("EnableSplitLTOUnit"))) EnableSplitLTOUnit = MD->getZExtValue(); - ModuleSummaryIndex Index(/*HaveGVs=*/true, EnableSplitLTOUnit); + if (auto *MD = + mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("UnifiedLTO"))) + UnifiedLTO = MD->getZExtValue(); + ModuleSummaryIndex Index(/*HaveGVs=*/true, EnableSplitLTOUnit, UnifiedLTO); // Identify the local values in the llvm.used and llvm.compiler.used sets, // which should not be exported as they would then require renaming and @@ -1033,3 +1084,36 @@ ImmutablePass *llvm::createImmutableModuleSummaryIndexWrapperPass( INITIALIZE_PASS(ImmutableModuleSummaryIndexWrapperPass, "module-summary-info", "Module summary info", false, true) + +bool llvm::mayHaveMemprofSummary(const CallBase *CB) { + if (!CB) + return false; + if (CB->isDebugOrPseudoInst()) + return false; + auto *CI = dyn_cast<CallInst>(CB); + auto *CalledValue = CB->getCalledOperand(); + auto *CalledFunction = CB->getCalledFunction(); + if (CalledValue && !CalledFunction) { + CalledValue = CalledValue->stripPointerCasts(); + // Stripping pointer casts can reveal a called function. + CalledFunction = dyn_cast<Function>(CalledValue); + } + // Check if this is an alias to a function. If so, get the + // called aliasee for the checks below. + if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) { + assert(!CalledFunction && + "Expected null called function in callsite for alias"); + CalledFunction = dyn_cast<Function>(GA->getAliaseeObject()); + } + // Check if this is a direct call to a known function or a known + // intrinsic, or an indirect call with profile data. + if (CalledFunction) { + if (CI && CalledFunction->isIntrinsic()) + return false; + } else { + // TODO: For now skip indirect calls. See comments in + // computeFunctionSummary for what is needed to handle this. + return false; + } + return true; +} |