summaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/CtxProfAnalysis.cpp
diff options
context:
space:
mode:
authorFlorian Mayer <fmayer@google.com>2024-08-07 14:00:51 -0700
committerFlorian Mayer <fmayer@google.com>2024-08-07 14:00:51 -0700
commit10fbc246b146dbdf6b7cd9083bf392505c534fbc (patch)
tree898a2504a8bc941166603c77021937fd995e79ce /llvm/lib/Analysis/CtxProfAnalysis.cpp
parent191d02015fba3458bdf6381ee93c32e485daf25e (diff)
parenta05fa131db58f2d66a1f9e68fea74068f9218c2b (diff)
Created using spr 1.3.4
Diffstat (limited to 'llvm/lib/Analysis/CtxProfAnalysis.cpp')
-rw-r--r--llvm/lib/Analysis/CtxProfAnalysis.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/CtxProfAnalysis.cpp b/llvm/lib/Analysis/CtxProfAnalysis.cpp
new file mode 100644
index 000000000000..f56f910bd778
--- /dev/null
+++ b/llvm/lib/Analysis/CtxProfAnalysis.cpp
@@ -0,0 +1,95 @@
+//===- CtxProfAnalysis.cpp - contextual profile analysis ------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the contextual profile analysis, which maintains contextual
+// profiling info through IPO passes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CtxProfAnalysis.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Analysis.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/ProfileData/PGOCtxProfReader.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#define DEBUG_TYPE "ctx_prof"
+
+namespace llvm {
+namespace json {
+Value toJSON(const PGOCtxProfContext &P) {
+ Object Ret;
+ Ret["Guid"] = P.guid();
+ Ret["Counters"] = Array(P.counters());
+ if (P.callsites().empty())
+ return Ret;
+ auto AllCS =
+ ::llvm::map_range(P.callsites(), [](const auto &P) { return P.first; });
+ auto MaxIt = ::llvm::max_element(AllCS);
+ assert(MaxIt != AllCS.end() && "We should have a max value because the "
+ "callsites collection is not empty.");
+ Array CSites;
+ // Iterate to, and including, the maximum index.
+ for (auto I = 0U, Max = *MaxIt; I <= Max; ++I) {
+ CSites.push_back(Array());
+ Array &Targets = *CSites.back().getAsArray();
+ if (P.hasCallsite(I))
+ for (const auto &[_, Ctx] : P.callsite(I))
+ Targets.push_back(toJSON(Ctx));
+ }
+ Ret["Callsites"] = std::move(CSites);
+
+ return Ret;
+}
+
+Value toJSON(const PGOCtxProfContext::CallTargetMapTy &P) {
+ Array Ret;
+ for (const auto &[_, Ctx] : P)
+ Ret.push_back(toJSON(Ctx));
+ return Ret;
+}
+} // namespace json
+} // namespace llvm
+
+using namespace llvm;
+
+AnalysisKey CtxProfAnalysis::Key;
+
+CtxProfAnalysis::Result CtxProfAnalysis::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MB = MemoryBuffer::getFile(Profile);
+ if (auto EC = MB.getError()) {
+ M.getContext().emitError("could not open contextual profile file: " +
+ EC.message());
+ return {};
+ }
+ PGOCtxProfileReader Reader(MB.get()->getBuffer());
+ auto MaybeCtx = Reader.loadContexts();
+ if (!MaybeCtx) {
+ M.getContext().emitError("contextual profile file is invalid: " +
+ toString(MaybeCtx.takeError()));
+ return {};
+ }
+ return Result(std::move(*MaybeCtx));
+}
+
+PreservedAnalyses CtxProfAnalysisPrinterPass::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+ CtxProfAnalysis::Result &C = MAM.getResult<CtxProfAnalysis>(M);
+ if (!C) {
+ M.getContext().emitError("Invalid CtxProfAnalysis");
+ return PreservedAnalyses::all();
+ }
+ const auto JSONed = ::llvm::json::toJSON(C.profiles());
+
+ OS << formatv("{0:2}", JSONed);
+ OS << "\n";
+ return PreservedAnalyses::all();
+}