LLVM: lib/Transforms/IPO/SampleContextTracker.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

19#include

20#include

21#include

22

23using namespace llvm;

25

26#define DEBUG_TYPE "sample-context-tracker"

27

28namespace llvm {

29

32 if (CalleeName.empty())

34

36 auto It = AllChildContext.find(Hash);

37 if (It != AllChildContext.end())

38 return &It->second;

39 return nullptr;

40}

41

44

45

46

48 uint64_t MaxCalleeSamples = 0;

49 for (auto &It : AllChildContext) {

51 if (ChildNode.CallSiteLoc != CallSite)

52 continue;

54 if (!Samples)

55 continue;

57 ChildNodeRet = &ChildNode;

59 }

60 }

61

62 return ChildNodeRet;

63}

64

66SampleContextTracker::moveContextSamples(ContextTrieNode &ToNodeParent,

71 std::map<uint64_t, ContextTrieNode> &AllChildContext =

73 assert(!AllChildContext.count(Hash) && "Node to remove must exist");

75 NewNode = NodeToMove;

77

78

79

80

81 std::queue<ContextTrieNode *> NodeToUpdate;

83 NodeToUpdate.push(&NewNode);

84

85 while (!NodeToUpdate.empty()) {

87 NodeToUpdate.pop();

89

90 if (FSamples) {

91 setContextNode(FSamples, Node);

93 }

94

95 for (auto &It : Node->getAllChildContext()) {

98 NodeToUpdate.push(ChildNode);

99 }

100 }

101

102 return NewNode;

103}

104

108

109 AllChildContext.erase(Hash);

110}

111

113 return AllChildContext;

114}

115

117

119 return FuncSamples;

120}

121

123 FuncSamples = FSamples;

124}

125

127 return FuncSize;

128}

129

131 if (!FuncSize)

132 FuncSize = 0;

133

134 FuncSize = *FuncSize + FSize;

135}

136

138

140 return ParentContext;

141}

142

144 ParentContext = Parent;

145}

146

148 CallSiteLoc = Loc;

149}

150

152 dbgs() << "Node: " << FuncName << "\n"

153 << " Callsite: " << CallSiteLoc << "\n"

154 << " Size: " << FuncSize << "\n"

155 << " Children:\n";

156

157 for (auto &It : AllChildContext) {

158 dbgs() << " Node: " << It.second.getFuncName() << "\n";

159 }

160}

161

163 dbgs() << "Context Profile Tree:\n";

164 std::queue<ContextTrieNode *> NodeQueue;

165 NodeQueue.push(this);

166

167 while (!NodeQueue.empty()) {

169 NodeQueue.pop();

170 Node->dumpNode();

171

172 for (auto &It : Node->getAllChildContext()) {

174 NodeQueue.push(ChildNode);

175 }

176 }

177}

178

182 auto It = AllChildContext.find(Hash);

183 if (It != AllChildContext.end()) {

184 assert(It->second.getFuncName() == CalleeName &&

185 "Hash collision for child context node");

186 return &It->second;

187 }

188

189 if (!AllowCreate)

190 return nullptr;

191

193 ACC = ContextTrieNode(this, CalleeName, nullptr, CallSite);

194 return &ACC;

195}

196

197

201 : GUIDToFuncNameMap(GUIDToFuncNameMap) {

202 for (auto &FuncSample : Profiles) {

204 SampleContext Context = FuncSample.second.getContext();

205 LLVM_DEBUG(dbgs() << "Tracking Context for function: " << Context.toString()

206 << "\n");

209 "New node can't have sample profile");

211 }

213}

214

216 for (auto *Node : *this) {

218 if (FSamples) {

220 setContextNode(FSamples, Node);

221 FuncToCtxtProfiles[Node->getFuncName()].push_back(FSamples);

222 }

223 }

224}

225

229 LLVM_DEBUG(dbgs() << "Getting callee context for instr: " << Inst << "\n");

231 if (!DIL)

232 return nullptr;

233

235

237

238

239

240 ContextTrieNode *CalleeContext = getCalleeContextFor(DIL, FName);

241 if (CalleeContext) {

245 << "\n";

246 });

247 return FSamples;

248 }

249

250 return nullptr;

251}

252

253std::vector<const FunctionSamples *>

256 std::vector<const FunctionSamples *> R;

257 if (!DIL)

258 return R;

259

265 continue;

267 R.push_back(CalleeSamples);

268 }

269

270 return R;

271}

272

275 assert(DIL && "Expect non-null location");

276

278 if (!ContextNode)

279 return nullptr;

280

281

282

283

284

285

286

288 if (Samples && ContextNode->getParentContext() != &RootContext)

290

291 return Samples;

292}

293

298 return nullptr;

299

300 return Node->getFunctionSamples();

301}

302

308

313

315 bool MergeContext) {

318}

319

321 bool MergeContext) {

322 LLVM_DEBUG(dbgs() << "Getting base profile for function: " << Name << "\n");

323

324

325

326

327

329 if (MergeContext) {

330 LLVM_DEBUG(dbgs() << " Merging context profile into base profile: " << Name

331 << "\n");

332

333

334

335

336 for (auto *CSamples : FuncToCtxtProfiles[Name]) {

338

340 continue;

341

343 if (FromNode == Node)

344 continue;

345

347 assert((Node || Node == &ToNode) && "Expect only one base profile");

348 Node = &ToNode;

349 }

350 }

351

352

354 return nullptr;

355

356 return Node->getFunctionSamples();

357}

358

361 assert(InlinedSamples && "Expect non-null inlined samples");

362 LLVM_DEBUG(dbgs() << "Marking context profile as inlined: "

365}

366

368

371 LLVM_DEBUG(dbgs() << "Promoting and merging context tree for instr: \n"

372 << Inst << "\n");

373

374

377 if (!CallerNode)

378 return;

379

380

382

383

384 if (CalleeName.empty()) {

388 continue;

391 continue;

393 }

394 return;

395 }

396

397

400 if (!NodeToPromo)

401 return;

402

404}

405

408

409

410

411

413 assert(FromSamples && "Shouldn't promote a context without profile");

414 (void)FromSamples;

415

416 LLVM_DEBUG(dbgs() << " Found context tree root to promote: "

418

420 "Shouldn't promote inlined context profile");

422}

423

424#ifndef NDEBUG

425std::string

429

430std::string

433 if (Node == &RootContext)

434 return std::string();

436

438 Node = Node->getParentContext();

439 while (Node && Node != &RootContext) {

441 PreNode = Node;

442 Node = Node->getParentContext();

443 }

444

445 std::reverse(Res.begin(), Res.end());

446

448}

449#endif

450

452

455 return Node->getFuncName().stringRef();

456 assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first");

457 return GUIDToFuncNameMap->lookup(Node->getFuncName().getHashCode());

458}

459

464

466SampleContextTracker::getCalleeContextFor(const DILocation *DIL,

468 assert(DIL && "Expect non-null location");

469

471 if (!CallContext)

472 return nullptr;

473

474

475

478}

479

481 assert(DIL && "Expect non-null location");

483

484

486 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {

487 StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();

488 if (Name.empty())

489 Name = PrevDIL->getScope()->getSubprogram()->getName();

493 PrevDIL = DIL;

494 }

495

496

497

498 StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();

499 if (RootName.empty())

500 RootName = PrevDIL->getScope()->getSubprogram()->getName();

501 S.push_back(std::make_pair(LineLocation(0, 0),

503

504 ContextTrieNode *ContextNode = &RootContext;

505 int I = S.size();

506 while (--I >= 0 && ContextNode) {

507 LineLocation &CallSite = S[I].first;

508 FunctionId CalleeName = S[I].second;

509 ContextNode = ContextNode->getChildContext(CallSite, CalleeName);

510 }

511

512 if (I < 0)

513 return ContextNode;

514

515 return nullptr;

516}

517

520 bool AllowCreate) {

523

524 for (const auto &Callsite : Context.getContextFrames()) {

525

526 if (AllowCreate) {

527 ContextNode =

529 } else {

530 ContextNode =

531 ContextNode->getChildContext(CallSiteLoc, Callsite.Func);

532 }

533 CallSiteLoc = Callsite.Location;

534 }

535

536 assert((!AllowCreate || ContextNode) &&

537 "Node must exist if creation is allowed");

538 return ContextNode;

539}

540

542SampleContextTracker::getTopLevelContextNode(FunctionId FName) {

543 assert(!FName.empty() && "Top level node query must provide valid name");

545}

546

548SampleContextTracker::addTopLevelContextNode(FunctionId FName) {

549 assert(!getTopLevelContextNode(FName) && "Node to add must not exist");

551}

552

553void SampleContextTracker::mergeContextNode(ContextTrieNode &FromNode,

557 if (FromSamples && ToSamples) {

558

559 ToSamples->merge(*FromSamples);

564 } else if (FromSamples) {

565

567 setContextNode(FromSamples, &ToNode);

569 }

570}

571

574

575

576 LineLocation NewCallSiteLoc = LineLocation(0, 0);

577 LineLocation OldCallSiteLoc = FromNode.getCallSiteLoc();

578 ContextTrieNode &FromNodeParent = *FromNode.getParentContext();

579 ContextTrieNode *ToNode = nullptr;

580 bool MoveToRoot = (&ToNodeParent == &RootContext);

581 if (!MoveToRoot) {

582 NewCallSiteLoc = OldCallSiteLoc;

583 }

584

585

587 if (!ToNode) {

588

589

590 ToNode =

591 &moveContextSamples(ToNodeParent, NewCallSiteLoc, std::move(FromNode));

594 << "\n";

595 });

596 } else {

597

598 mergeContextNode(FromNode, *ToNode);

601 dbgs() << " Context promoted and merged to: "

603 });

604

605

607 ContextTrieNode &FromChildNode = It.second;

609 }

610

611

613 }

614

615

616 if (MoveToRoot)

618

619 return *ToNode;

620}

621

624 for (auto *Node : *this) {

626

627 if (FProfile)

628 ContextLessProfiles.create(Node->getFuncName()).merge(*FProfile);

629 }

630}

631}

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

This file provides the interface for context-sensitive profile tracker used by CSSPGO.

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

LLVM_ABI ContextTrieNode * getOrCreateChildContext(const LineLocation &CallSite, FunctionId ChildName, bool AllowCreate=true)

Definition SampleContextTracker.cpp:179

LLVM_ABI std::map< uint64_t, ContextTrieNode > & getAllChildContext()

Definition SampleContextTracker.cpp:112

LLVM_ABI void setCallSiteLoc(const LineLocation &Loc)

Definition SampleContextTracker.cpp:147

LLVM_ABI LineLocation getCallSiteLoc() const

Definition SampleContextTracker.cpp:137

LLVM_ABI FunctionSamples * getFunctionSamples() const

Definition SampleContextTracker.cpp:118

LLVM_ABI std::optional< uint32_t > getFunctionSize() const

Definition SampleContextTracker.cpp:126

LLVM_ABI ContextTrieNode * getHottestChildContext(const LineLocation &CallSite)

Definition SampleContextTracker.cpp:43

LLVM_ABI void setParentContext(ContextTrieNode *Parent)

Definition SampleContextTracker.cpp:143

LLVM_ABI void dumpNode()

Definition SampleContextTracker.cpp:151

LLVM_ABI void removeChildContext(const LineLocation &CallSite, FunctionId ChildName)

Definition SampleContextTracker.cpp:105

LLVM_ABI void dumpTree()

Definition SampleContextTracker.cpp:162

LLVM_ABI void addFunctionSize(uint32_t FSize)

Definition SampleContextTracker.cpp:130

LLVM_ABI FunctionId getFuncName() const

Definition SampleContextTracker.cpp:116

LLVM_ABI ContextTrieNode * getChildContext(const LineLocation &CallSite, FunctionId ChildName)

Definition SampleContextTracker.cpp:30

LLVM_ABI ContextTrieNode * getParentContext() const

Definition SampleContextTracker.cpp:139

LLVM_ABI void setFunctionSamples(FunctionSamples *FSamples)

Definition SampleContextTracker.cpp:122

ContextTrieNode(ContextTrieNode *Parent=nullptr, FunctionId FName=FunctionId(), FunctionSamples *FSamples=nullptr, LineLocation CallLoc={0, 0})

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

LLVM_ABI void promoteMergeContextSamplesTree(const Instruction &Inst, FunctionId CalleeName)

Definition SampleContextTracker.cpp:369

LLVM_ABI FunctionSamples * getBaseSamplesFor(const Function &Func, bool MergeContext=true)

Definition SampleContextTracker.cpp:314

LLVM_ABI ContextTrieNode * getOrCreateContextPath(const SampleContext &Context, bool AllowCreate)

Definition SampleContextTracker.cpp:519

LLVM_ABI StringRef getFuncNameFor(ContextTrieNode *Node) const

Definition SampleContextTracker.cpp:453

LLVM_ABI void populateFuncToCtxtMap()

Definition SampleContextTracker.cpp:215

LLVM_ABI ContextTrieNode & getRootContext()

Definition SampleContextTracker.cpp:367

LLVM_ABI std::string getContextString(const FunctionSamples &FSamples) const

Definition SampleContextTracker.cpp:426

ContextTrieNode * getContextNodeForProfile(const FunctionSamples *FSamples) const

LLVM_ABI FunctionSamples * getContextSamplesFor(const DILocation *DIL)

Definition SampleContextTracker.cpp:274

std::vector< FunctionSamples * > ContextSamplesTy

LLVM_ABI void dump()

Definition SampleContextTracker.cpp:451

LLVM_ABI ContextSamplesTy & getAllContextSamplesFor(const Function &Func)

Definition SampleContextTracker.cpp:304

LLVM_ABI void markContextSamplesInlined(const FunctionSamples *InlinedSamples)

Definition SampleContextTracker.cpp:359

LLVM_ABI void createContextLessProfileMap(SampleProfileMap &ContextLessProfiles)

Definition SampleContextTracker.cpp:622

LLVM_ABI std::vector< const FunctionSamples * > getIndirectCalleeContextSamplesFor(const DILocation *DIL)

Definition SampleContextTracker.cpp:254

SampleContextTracker()=default

LLVM_ABI FunctionSamples * getCalleeContextSamplesFor(const CallBase &Inst, StringRef CalleeName)

Definition SampleContextTracker.cpp:227

LLVM_ABI ContextTrieNode * getContextFor(const SampleContext &Context)

Definition SampleContextTracker.cpp:461

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

constexpr bool empty() const

empty - Check if the string is empty.

This class represents a function that is read from a sample profile.

Representation of the samples collected for a function.

static uint64_t getCallSiteHash(FunctionId Callee, const LineLocation &Callsite)

Returns a unique hash code for a combination of a callsite location and the callee function name.

static StringRef getCanonicalFnName(const Function &F)

Return the canonical name for a function, taking into account suffix elision policy attributes.

SampleContext & getContext() const

uint64_t getTotalSamples() const

Return the total number of samples collected inside the function.

sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)

Merge the samples in Other into this one.

static LLVM_ABI LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)

Returns a unique call site identifier for a given debug location of a call instruction.

static LLVM_ABI bool UseMD5

Whether the profile uses MD5 to represent string.

bool hasState(ContextStateMask S)

static std::string getContextString(SampleContextFrames Context, bool IncludeLeafLineLocation=false)

void setState(ContextStateMask S)

void setAttribute(ContextAttributeMask A)

bool hasAttribute(ContextAttributeMask A)

This class provides operator overloads to the map container using MD5 as the key type,...

mapped_type & create(const SampleContext &Ctx)

static FunctionId getRepInFormat(StringRef Name)

Get the proper representation of a string according to whether the current Format uses MD5 to represe...

SmallVector< SampleContextFrame, 1 > SampleContextFrameVector

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

Represents the relative location of an instruction.