[llvm] [ctx_profile] Profile reader and writer (PR #91859)
Snehasish Kumar via llvm-commits
llvm-commits at lists.llvm.org
Tue May 14 14:33:16 PDT 2024
================
@@ -0,0 +1,167 @@
+//===- PGOCtxProfReader.cpp - Contextual Instrumentation profile reader ---===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Read a contextual profile into a datastructure suitable for maintenance
+// throughout IPO
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/PGOCtxProfReader.h"
+#include "llvm/Bitstream/BitCodeEnums.h"
+#include "llvm/Bitstream/BitstreamReader.h"
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/ProfileData/PGOCtxProfWriter.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+
+// FIXME(#92054) - these Error handling macros are (re-)invented in a few
+// places.
+#define EXPECT_OR_RET(LHS, RHS) \
+ auto LHS = RHS; \
+ if (!LHS) \
+ return LHS.takeError();
+
+#define RET_ON_ERR(EXPR) \
+ if (auto Err = (EXPR)) \
+ return Err;
+
+Expected<PGOContextualProfile &>
+PGOContextualProfile::getOrEmplace(uint32_t Index, GlobalValue::GUID G,
+ SmallVectorImpl<uint64_t> &&Counters) {
+ auto I = Callsites[Index].insert(
+ {G, PGOContextualProfile(G, std::move(Counters))});
+ if (!I.second)
+ return make_error<StringError>(llvm::errc::invalid_argument,
+ "Duplicate GUID for same callsite.");
+ return I.first->second;
+}
+
+void PGOContextualProfile::getContainedGuids(
+ DenseSet<GlobalValue::GUID> &Guids) const {
+ Guids.insert(GUID);
+ for (const auto &[_, Callsite] : Callsites)
+ for (const auto &[_, Callee] : Callsite)
+ Callee.getContainedGuids(Guids);
+}
+
+Expected<BitstreamEntry> PGOCtxProfileReader::advance() {
+ return Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
+}
+
+Error PGOCtxProfileReader::wrongValue(const Twine &Msg) {
+ return make_error<InstrProfError>(instrprof_error::invalid_prof, Msg);
+}
+
+Error PGOCtxProfileReader::unsupported(const Twine &Msg) {
+ return make_error<InstrProfError>(instrprof_error::unsupported_version, Msg);
+}
+
+bool PGOCtxProfileReader::canReadContext() {
+ auto Blk = advance();
+ if (!Blk) {
+ consumeError(Blk.takeError());
+ return false;
+ }
+ return Blk->Kind == BitstreamEntry::SubBlock &&
+ Blk->ID == PGOCtxProfileBlockIDs::ContextNodeBlockID;
+}
+
+Expected<std::pair<std::optional<uint32_t>, PGOContextualProfile>>
+PGOCtxProfileReader::readContext(bool ExpectIndex) {
+ RET_ON_ERR(Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID));
+
+ std::optional<ctx_profile::GUID> Guid;
+ std::optional<SmallVector<uint64_t, 16>> Counters;
+ std::optional<uint32_t> CallsiteIndex;
+
+ SmallVector<uint64_t, 1> RecordValues;
+
+ // We don't prescribe the order in which the records come in, and we are ok
+ // if other unsupported records appear. We seek in the current subblock until
+ // we get all we know.
+ while (!Guid || !Counters || (ExpectIndex && !CallsiteIndex)) {
+ RecordValues.clear();
+ EXPECT_OR_RET(Entry, advance());
+ if (Entry->Kind != BitstreamEntry::Record)
+ return wrongValue(
+ "Expected records before encountering more subcontexts");
+ EXPECT_OR_RET(ReadRecord,
+ Cursor.readRecord(bitc::UNABBREV_RECORD, RecordValues));
+ switch (*ReadRecord) {
+ case PGOCtxProfileRecords::Guid:
+ if (RecordValues.size() != 1)
+ return wrongValue("The GUID record should have exactly one value");
+ Guid = RecordValues[0];
+ break;
+ case PGOCtxProfileRecords::Counters:
+ Counters = std::move(RecordValues);
+ if (Counters->empty())
+ return wrongValue("Empty counters. At least the entry counter (one "
+ "value) was expected");
+ break;
+ case PGOCtxProfileRecords::CalleeIndex:
+ if (!ExpectIndex)
+ return wrongValue("The root context should not have a callee index");
+ if (RecordValues.size() != 1)
+ return wrongValue("The callee index should have exactly one value");
+ CallsiteIndex = RecordValues[0];
+ break;
+ default:
+ // OK if we see records we do not understand, like records (profiles)
----------------
snehasish wrote:
Did you mean s/profiles/value profiles/? (since I recall that mentioned elsewhere).
https://github.com/llvm/llvm-project/pull/91859
More information about the llvm-commits
mailing list