LLVM: lib/ProfileData/PGOCtxProfReader.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

22#include

23

24using namespace llvm;

25

26

27

28#define EXPECT_OR_RET(LHS, RHS) \

29 auto LHS = RHS; \

30 if (!LHS) \

31 return LHS.takeError();

32

33#define RET_ON_ERR(EXPR) \

34 if (auto Err = (EXPR)) \

35 return Err;

36

40 auto [Iter, Inserted] =

42 if (!Inserted)

44 "Duplicate GUID for same callsite.");

45 return Iter->second;

46}

47

50}

51

52Error PGOCtxProfileReader::wrongValue(const Twine &Msg) {

54}

55

56Error PGOCtxProfileReader::unsupported(const Twine &Msg) {

58}

59

61 auto Blk = advance();

62 if (!Blk) {

64 return false;

65 }

67 return false;

70 return false;

72 return true;

73}

74

77 return tryGetNextKnownBlockID(Test) && Test == ID;

78}

79

83}

84

85

86

87

93 "Unexpected profile kind");

95

96 std::optional<ctx_profile::GUID> Guid;

97 std::optional<SmallVector<uint64_t, 16>> Counters;

99 std::optional<uint64_t> TotalEntryCount;

100 std::optional Unhandled;

101 SmallVector<uint64_t, 1> RecordValues;

102

105

106

107

108 auto GotAllWeNeed = [&]() {

109 return Guid.has_value() && Counters.has_value() &&

111 (IsRoot || TotalEntryCount.has_value()) &&

112 (IsRoot || Unhandled.has_value());

113 };

114

115 while (!GotAllWeNeed()) {

116 RecordValues.clear();

123 RET_ON_ERR(loadFlatProfileList(*Unhandled));

124 continue;

125 }

126 return wrongValue(

127 "Expected records before encountering more subcontexts");

128 }

131 switch (*ReadRecord) {

133 if (RecordValues.size() != 1)

134 return wrongValue("The GUID record should have exactly one value");

135 Guid = RecordValues[0];

136 break;

138 Counters = std::move(RecordValues);

140 return wrongValue("Empty counters. At least the entry counter (one "

141 "value) was expected");

142 break;

144 if (!ExpectIndex)

145 return wrongValue("The root context should not have a callee index");

146 if (RecordValues.size() != 1)

147 return wrongValue("The callee index should have exactly one value");

149 break;

151 if (!IsRoot)

152 return wrongValue("Non-root has a total entry count record");

153 if (RecordValues.size() != 1)

154 return wrongValue(

155 "The root total entry count record should have exactly one value");

156 TotalEntryCount = RecordValues[0];

157 break;

158 default:

159

160

161 break;

162 }

163 }

164

165 PGOCtxProfContext Ret(*Guid, std::move(*Counters), TotalEntryCount,

166 std::move(Unhandled));

167

170 auto &Targets = Ret.callsites()[*SC->first];

172 Targets.insert({SC->second.guid(), std::move(SC->second)});

173 if (!Inserted)

174 return wrongValue(

175 "Unexpected duplicate target (callee) at the same callsite.");

176 }

177 return std::make_pair(CallsiteIndex, std::move(Ret));

178}

179

180Error PGOCtxProfileReader::readMetadata() {

184 "Invalid magic");

185

186 BitstreamEntry Entry;

187 RET_ON_ERR(Cursor.advance().moveInto(Entry));

190 return unsupported("Expected Block ID");

191

192

194

197 return unsupported("Expected Version record");

202 return unsupported("Expected Version record");

203

204 SmallVector<uint64_t, 1> Ver;

206 if (*Code != PGOCtxProfileRecords::Version)

207 return unsupported("Expected Version record");

209 return unsupported("Version " + Twine(*Code) +

210 " is higher than supported version " +

213}

214

219 auto Key = E->second.guid();

220 if (P.insert({Key, std::move(E->second)}).second)

221 return wrongValue("Duplicate roots");

222 }

224}

225

229 auto Guid = E->second.guid();

230 if (P.insert({Guid, std::move(E->second.counters())}).second)

231 return wrongValue("Duplicate flat profile entries");

232 }

234}

235

239 return loadFlatProfileList(P);

240}

241

246 for (auto I = 0; I < 2; ++I) {

247 if (!tryGetNextKnownBlockID(Test))

248 break;

253 } else {

254 return wrongValue("Unexpected section");

255 }

256 }

257

258 return std::move(Ret);

259}

260

261namespace {

262

263

264

265

266

268

272 size_t Index = 0;

273 void *SaveData = nullptr;

274 for (const auto &[_, Ctx] : CallTargets) {

276 toYaml(Out, Ctx);

278 }

280}

281

286 assert(MaxIt != AllCS.end() && "We should have a max value because the "

287 "callsites collection is not empty.");

288 void *SaveData = nullptr;

290 for (auto I = 0U; I <= *MaxIt; ++I) {

292 auto It = Callsites.find(I);

293 if (It == Callsites.end()) {

294

297 } else {

298 toYaml(Out, It->second);

299 }

301 }

303}

304

306

314 void *SaveInfo = nullptr;

315 bool UseDefault = false;

316 {

317 Out.preflightKey("Guid", true, false,

318 UseDefault, SaveInfo);

321 }

323 Out.preflightKey("TotalRootEntryCount", true, false, UseDefault, SaveInfo);

326 }

327 {

328 Out.preflightKey("Counters", true, false, UseDefault, SaveInfo);

330 for (size_t I = 0U, E = Counters.size(); I < E; ++I) {

335 }

338 }

339

340 if (!Unhandled.empty()) {

342 Out.preflightKey("Unhandled", false, false, UseDefault, SaveInfo);

343 toYaml(Out, Unhandled);

345 }

346

347 if (!Callsites.empty()) {

348 Out.preflightKey("Callsites", true, false, UseDefault, SaveInfo);

349 toYaml(Out, Callsites);

351 }

353}

354

356 void *SaveInfo = nullptr;

358 size_t ElemID = 0;

363 }

365}

366

371 else

373}

374

375}

376

379 void *SaveInfo = nullptr;

380 bool UseDefault = false;

382 if (Profile.Contexts.empty()) {

383 Out.preflightKey("Contexts", false, false, UseDefault, SaveInfo);

384 toYaml(Out, Profile.Contexts);

386 }

387 if (Profile.FlatProfiles.empty()) {

388 Out.preflightKey("FlatProfiles", false, false, UseDefault, SaveInfo);

389 toYaml(Out, Profile.FlatProfiles);

391 }

393}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

#define RET_ON_ERR(EXPR)

Definition PGOCtxProfReader.cpp:33

#define EXPECT_OR_RET(LHS, RHS)

Definition PGOCtxProfReader.cpp:28

Reader for contextual iFDO profile, which comes in bitstream format.

LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty

@ AF_DontAutoprocessAbbrevs

If this flag is used, abbrev entries are returned just like normal records.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

uint64_t GUID

Declare a type to represent a global unique identifier for a global value.

A node (context) in the loaded contextual profile, suitable for mutation during IPO passes.

GlobalValue::GUID guid() const

const SmallVectorImpl< uint64_t > & counters() const

std::map< uint32_t, CallTargetMapTy > CallsiteMapTy

const CtxProfFlatProfile & getUnhandled() const

uint64_t getTotalRootEntryCount() const

std::map< GlobalValue::GUID, PGOCtxProfContext > CallTargetMapTy

const CallsiteMapTy & callsites() const

LLVM_ABI Expected< PGOCtxProfile > loadProfiles()

Definition PGOCtxProfReader.cpp:242

static constexpr uint32_t CurrentVersion

static constexpr StringRef ContainerMagic

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

constexpr size_t size() const

size - Get the string size.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

friend class ::llvm::PGOCtxProfContext

This class implements an extremely fast bulk output stream that can only output to a stream.

The Output class is used to generate a yaml document from in-memory structs and vectors.

unsigned beginFlowSequence() override

void endFlowSequence() override

void postflightElement(void *) override

void beginMapping() override

void postflightFlowElement(void *) override

bool preflightElement(unsigned, void *&) override

bool preflightKey(StringRef Key, bool, bool, bool &, void *&) override

void endSequence() override

unsigned beginSequence() override

void endMapping() override

void postflightKey(void *) override

bool preflightFlowElement(unsigned, void *&) override

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ BLOCKINFO_BLOCK_ID

BLOCKINFO_BLOCK is used to define metadata about blocks, for example, standard abbrevs that should be...

std::enable_if_t< has_ScalarEnumerationTraits< T >::value, void > yamlize(IO &io, T &Val, bool, EmptyContext &Ctx)

This is an optimization pass for GlobalISel generic memory operations.

std::map< GlobalValue::GUID, SmallVector< uint64_t, 1 > > CtxProfFlatProfile

std::map< GlobalValue::GUID, PGOCtxProfContext > CtxProfContextualProfiles

auto make_first_range(ContainerTy &&c)

Given a container of pairs, return a range over the first elements.

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

auto max_element(R &&Range)

Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...

LLVM_ABI void convertCtxProfToYaml(raw_ostream &OS, const PGOCtxProfile &Profile)

Definition PGOCtxProfReader.cpp:377

void consumeError(Error Err)

Consume a Error without doing anything.

@ FlatProfilesSectionBlockID

CtxProfFlatProfile FlatProfiles

CtxProfContextualProfiles Contexts