xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ProfileData/PGOCtxProfReader.h (revision b1879975794772ee51f0b4865753364c7d7626c3)
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 /// The loaded contextual profile, suitable for mutation during IPO passes. We
28 /// generally expect a fraction of counters and of callsites to be populated.
29 /// We continue to model counters as vectors, but callsites are modeled as a map
30 /// of a map. The expectation is that, typically, there is a small number of
31 /// indirect targets (usually, 1 for direct calls); but potentially a large
32 /// number of callsites, and, as inlining progresses, the callsite count of a
33 /// caller will grow.
34 class PGOContextualProfile final {
35 public:
36   using CallTargetMapTy = std::map<GlobalValue::GUID, PGOContextualProfile>;
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 
45   PGOContextualProfile(GlobalValue::GUID G,
46                        SmallVectorImpl<uint64_t> &&Counters)
47       : GUID(G), Counters(std::move(Counters)) {}
48 
49   Expected<PGOContextualProfile &>
50   getOrEmplace(uint32_t Index, GlobalValue::GUID G,
51                SmallVectorImpl<uint64_t> &&Counters);
52 
53 public:
54   PGOContextualProfile(const PGOContextualProfile &) = delete;
55   PGOContextualProfile &operator=(const PGOContextualProfile &) = delete;
56   PGOContextualProfile(PGOContextualProfile &&) = default;
57   PGOContextualProfile &operator=(PGOContextualProfile &&) = default;
58 
59   GlobalValue::GUID guid() const { return GUID; }
60   const SmallVectorImpl<uint64_t> &counters() const { return Counters; }
61   const CallsiteMapTy &callsites() const { return Callsites; }
62   CallsiteMapTy &callsites() { return Callsites; }
63 
64   bool hasCallsite(uint32_t I) const {
65     return Callsites.find(I) != Callsites.end();
66   }
67 
68   const CallTargetMapTy &callsite(uint32_t I) const {
69     assert(hasCallsite(I) && "Callsite not found");
70     return Callsites.find(I)->second;
71   }
72   void getContainedGuids(DenseSet<GlobalValue::GUID> &Guids) const;
73 };
74 
75 class PGOCtxProfileReader final {
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>, PGOContextualProfile>>
83   readContext(bool ExpectIndex);
84   bool canReadContext();
85 
86 public:
87   PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {}
88 
89   Expected<std::map<GlobalValue::GUID, PGOContextualProfile>> loadContexts();
90 };
91 } // namespace llvm
92 #endif
93