• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- PGOCtxProfReader.h - Contextual profile reader ---------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 ///
11 /// Reader for contextual iFDO profile, which comes in bitstream format.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H
16 #define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H
17 
18 #include "llvm/ADT/DenseSet.h"
19 #include "llvm/Bitstream/BitstreamReader.h"
20 #include "llvm/IR/GlobalValue.h"
21 #include "llvm/ProfileData/PGOCtxProfWriter.h"
22 #include "llvm/Support/Error.h"
23 #include <map>
24 #include <vector>
25 
26 namespace llvm {
27 /// A node (context) in the loaded contextual profile, suitable for mutation
28 /// during IPO passes. We generally expect a fraction of counters and
29 /// callsites to be populated. We continue to model counters as vectors, but
30 /// callsites are modeled as a map of a map. The expectation is that, typically,
31 /// there is a small number of indirect targets (usually, 1 for direct calls);
32 /// but potentially a large number of callsites, and, as inlining progresses,
33 /// the callsite count of a caller will grow.
34 class PGOCtxProfContext final {
35 public:
36   using CallTargetMapTy = std::map<GlobalValue::GUID, PGOCtxProfContext>;
37   using CallsiteMapTy = DenseMap<uint32_t, CallTargetMapTy>;
38 
39 private:
40   friend class PGOCtxProfileReader;
41   GlobalValue::GUID GUID = 0;
42   SmallVector<uint64_t, 16> Counters;
43   CallsiteMapTy Callsites;
44 
PGOCtxProfContext(GlobalValue::GUID G,SmallVectorImpl<uint64_t> && Counters)45   PGOCtxProfContext(GlobalValue::GUID G, SmallVectorImpl<uint64_t> &&Counters)
46       : GUID(G), Counters(std::move(Counters)) {}
47 
48   Expected<PGOCtxProfContext &>
49   getOrEmplace(uint32_t Index, GlobalValue::GUID G,
50                SmallVectorImpl<uint64_t> &&Counters);
51 
52 public:
53   PGOCtxProfContext(const PGOCtxProfContext &) = delete;
54   PGOCtxProfContext &operator=(const PGOCtxProfContext &) = delete;
55   PGOCtxProfContext(PGOCtxProfContext &&) = default;
56   PGOCtxProfContext &operator=(PGOCtxProfContext &&) = default;
57 
guid()58   GlobalValue::GUID guid() const { return GUID; }
counters()59   const SmallVectorImpl<uint64_t> &counters() const { return Counters; }
callsites()60   const CallsiteMapTy &callsites() const { return Callsites; }
callsites()61   CallsiteMapTy &callsites() { return Callsites; }
62 
hasCallsite(uint32_t I)63   bool hasCallsite(uint32_t I) const {
64     return Callsites.find(I) != Callsites.end();
65   }
66 
callsite(uint32_t I)67   const CallTargetMapTy &callsite(uint32_t I) const {
68     assert(hasCallsite(I) && "Callsite not found");
69     return Callsites.find(I)->second;
70   }
71   void getContainedGuids(DenseSet<GlobalValue::GUID> &Guids) const;
72 };
73 
74 class PGOCtxProfileReader final {
75   StringRef Magic;
76   BitstreamCursor Cursor;
77   Expected<BitstreamEntry> advance();
78   Error readMetadata();
79   Error wrongValue(const Twine &);
80   Error unsupported(const Twine &);
81 
82   Expected<std::pair<std::optional<uint32_t>, PGOCtxProfContext>>
83   readContext(bool ExpectIndex);
84   bool canReadContext();
85 
86 public:
PGOCtxProfileReader(StringRef Buffer)87   PGOCtxProfileReader(StringRef Buffer)
88       : Magic(Buffer.substr(0, PGOCtxProfileWriter::ContainerMagic.size())),
89         Cursor(Buffer.substr(PGOCtxProfileWriter::ContainerMagic.size())) {}
90 
91   Expected<std::map<GlobalValue::GUID, PGOCtxProfContext>> loadContexts();
92 };
93 } // namespace llvm
94 #endif
95