aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
diff options
context:
space:
mode:
authorTeresa Johnson <tejohnson@google.com>2023-01-05 09:55:33 -0800
committerTeresa Johnson <tejohnson@google.com>2023-05-05 16:26:32 -0700
commitcfad2d3a3d62fee089ad2ac1e87029bb3d00f17f (patch)
tree4210f53a2baeb4bf29e87da46f1558b25d7e5e75 /llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
parent8f0eee16d9b420c0b5339bf9c386dc6cbbf29b42 (diff)
downloadllvm-cfad2d3a3d62fee089ad2ac1e87029bb3d00f17f.zip
llvm-cfad2d3a3d62fee089ad2ac1e87029bb3d00f17f.tar.gz
llvm-cfad2d3a3d62fee089ad2ac1e87029bb3d00f17f.tar.bz2
[MemProf] Context disambiguation cloning pass [patch 4/4]
Applies ThinLTO cloning decisions made during the thin link and recorded in the summary index to the IR during the ThinLTO backend. Depends on D141077. Differential Revision: https://reviews.llvm.org/D149117
Diffstat (limited to 'llvm/lib/Analysis/ModuleSummaryAnalysis.cpp')
-rw-r--r--llvm/lib/Analysis/ModuleSummaryAnalysis.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
index d84cfbf..3830edc 100644
--- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -284,6 +284,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;
@@ -427,6 +431,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
@@ -437,6 +445,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(
@@ -546,6 +562,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 ||
@@ -1042,3 +1077,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;
+}