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