diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | |
parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | 77 |
1 files changed, 68 insertions, 9 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index efe60586979a..3dfa2d821e83 100644 --- a/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -24,6 +24,7 @@ #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/IndirectCallPromotionAnalysis.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/MemoryProfileInfo.h" #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/Analysis/TypeMetadataUtils.h" @@ -56,14 +57,18 @@ #include <vector> using namespace llvm; +using namespace llvm::memprof; #define DEBUG_TYPE "module-summary-analysis" // Option to force edges cold which will block importing when the // -import-cold-multiplier is set to 0. Useful for debugging. +namespace llvm { FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold = FunctionSummary::FSHT_None; -cl::opt<FunctionSummary::ForceSummaryHotnessType, true> FSEC( +} // namespace llvm + +static cl::opt<FunctionSummary::ForceSummaryHotnessType, true> FSEC( "force-summary-edges-cold", cl::Hidden, cl::location(ForceSummaryEdgesCold), cl::desc("Force all edges in the function summary to cold"), cl::values(clEnumValN(FunctionSummary::FSHT_None, "none", "None."), @@ -71,10 +76,9 @@ cl::opt<FunctionSummary::ForceSummaryHotnessType, true> FSEC( "all-non-critical", "All non-critical edges."), clEnumValN(FunctionSummary::FSHT_All, "all", "All edges."))); -cl::opt<std::string> ModuleSummaryDotFile( - "module-summary-dot-file", cl::init(""), cl::Hidden, - cl::value_desc("filename"), - cl::desc("File to emit dot graph of new summary into.")); +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")); // Walk through the operands of a given User via worklist iteration and populate // the set of GlobalValue references encountered. Invoked either on an @@ -275,6 +279,9 @@ static void computeFunctionSummary( std::vector<const Instruction *> NonVolatileLoads; std::vector<const Instruction *> NonVolatileStores; + std::vector<CallsiteInfo> Callsites; + std::vector<AllocInfo> Allocs; + bool HasInlineAsmMaybeReferencingInternal = false; bool HasIndirBranchToBlockAddress = false; bool HasUnknownCall = false; @@ -417,6 +424,57 @@ static void computeFunctionSummary( CallGraphEdges[Index.getOrInsertValueInfo(Candidate.Value)] .updateHotness(getHotness(Candidate.Count, PSI)); } + + // 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 + // will also be important because we will have a different set of clone + // versions per target. This handling needs to match that in the ThinLTO + // backend so we handle things consistently for matching of callsite + // summaries to instructions. + if (!CalledFunction) + continue; + + // 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( + I.getMetadata(LLVMContext::MD_callsite)); + auto *MemProfMD = I.getMetadata(LLVMContext::MD_memprof); + if (MemProfMD) { + std::vector<MIBInfo> MIBs; + for (auto &MDOp : MemProfMD->operands()) { + auto *MIBMD = cast<const MDNode>(MDOp); + MDNode *StackNode = getMIBStackNode(MIBMD); + assert(StackNode); + SmallVector<unsigned> StackIdIndices; + CallStack<MDNode, MDNode::op_iterator> StackContext(StackNode); + // Collapse out any on the allocation call (inlining). + for (auto ContextIter = + StackContext.beginAfterSharedPrefix(InstCallsite); + ContextIter != StackContext.end(); ++ContextIter) { + unsigned StackIdIdx = Index.addOrGetStackIdIndex(*ContextIter); + // If this is a direct recursion, simply skip the duplicate + // entries. If this is mutual recursion, handling is left to + // the LTO link analysis client. + if (StackIdIndices.empty() || StackIdIndices.back() != StackIdIdx) + StackIdIndices.push_back(StackIdIdx); + } + MIBs.push_back( + MIBInfo(getMIBAllocType(MIBMD), std::move(StackIdIndices))); + } + Allocs.push_back(AllocInfo(std::move(MIBs))); + } else if (!InstCallsite.empty()) { + SmallVector<unsigned> StackIdIndices; + for (auto StackId : InstCallsite) + StackIdIndices.push_back(Index.addOrGetStackIdIndex(StackId)); + // Use the original CalledValue, in case it was an alias. We want + // to record the call edge to the alias in that case. Eventually + // an alias summary will be created to associate the alias and + // aliasee. + auto CalleeValueInfo = + Index.getOrInsertValueInfo(cast<GlobalValue>(CalledValue)); + Callsites.push_back({CalleeValueInfo, StackIdIndices}); + } } } Index.addBlockCount(F.size()); @@ -492,8 +550,7 @@ static void computeFunctionSummary( F.getLinkage(), F.getVisibility(), NotEligibleForImport, /* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable()); FunctionSummary::FFlags FunFlags{ - F.hasFnAttribute(Attribute::ReadNone), - F.hasFnAttribute(Attribute::ReadOnly), + F.doesNotAccessMemory(), F.onlyReadsMemory() && !F.doesNotAccessMemory(), F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(), // FIXME: refactor this to use the same code that inliner is using. // Don't try to import functions with noinline attribute. @@ -509,7 +566,8 @@ static void computeFunctionSummary( CallGraphEdges.takeVector(), TypeTests.takeVector(), TypeTestAssumeVCalls.takeVector(), TypeCheckedLoadVCalls.takeVector(), TypeTestAssumeConstVCalls.takeVector(), - TypeCheckedLoadConstVCalls.takeVector(), std::move(ParamAccesses)); + TypeCheckedLoadConstVCalls.takeVector(), std::move(ParamAccesses), + std::move(Callsites), std::move(Allocs)); if (NonRenamableLocal) CantBePromoted.insert(F.getGUID()); Index.addGlobalValueSummary(F, std::move(FuncSummary)); @@ -758,7 +816,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( ArrayRef<FunctionSummary::VFuncId>{}, ArrayRef<FunctionSummary::ConstVCall>{}, ArrayRef<FunctionSummary::ConstVCall>{}, - ArrayRef<FunctionSummary::ParamAccess>{}); + ArrayRef<FunctionSummary::ParamAccess>{}, + ArrayRef<CallsiteInfo>{}, ArrayRef<AllocInfo>{}); Index.addGlobalValueSummary(*GV, std::move(Summary)); } else { std::unique_ptr<GlobalVarSummary> Summary = |