mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 17:43:35 +03:00
[PGO] Add PGO to LDC. Supported for LLVM >= 3.7
Add the commandline options -fprofile-instr-generate[=filename] and -profile-instr-use=filename -fprofile-instr-generate -- Add instrumentation on branches, switches, and function entry; uses LLVM's InstrProf pass. -- Link to profile runtime that writes instrumentation counters to a file. -fprofile-instr-use -- Read profile data from a file and apply branch weights to branches and switches, and annotate functions with entrycount in LLVM IR. -- Functions with low or high entrycount are marked with 'cold' or 'inlinehint'. The only statement type without PGO yet is "try-finally". A new pragma, `pragma(LDC_profile_instr, [ true | false ])`, is added to selectively disable/enable instrumentation of functions (granularity = whole functions). The runtime library ldc-profile-rt is a copy of LLVM compiler-rt lib/profile. It has to be exactly in-sync with the LLVM version, and thus we need a copy for each PGO-supported LLVM (>=3.7). import ldc.profile for a D interface to ldc-profile-rt (for example to reset execution counts after a program startup phase). The instrumentation data is mainly passed on to LLVM: function-entry counts and branch counts/probabilities. LDC marks functions as hot when "execution count is 30% of the maximum function execution count", and marks functions as cold if their count is 1% of maximum function execution count. The source of LLVM's llvm-profdata tool is hereby included in LDCs repository (different source for each LLVM version), and the binary is included in the install bin folder. The executable is named "ldc-profdata" to avoid clashing with llvm-profdata on the same machine. This is needed because profdata executable has to be in-sync with the LLVM version used to build LDC. Maintenance burden: for trunk LLVM, we have to keep ldc-profile-rt and llvm-profdata in sync. There is no diff with upstream; but because of active development there are the occasional API changes.
This commit is contained in:
parent
a81ac7d790
commit
e0d9c58443
99 changed files with 11857 additions and 64 deletions
|
@ -28,9 +28,10 @@ GotoJump::GotoJump(Loc loc, llvm::BasicBlock *sourceBlock,
|
|||
tentativeTarget(tentativeTarget), targetLabel(targetLabel) {}
|
||||
|
||||
CatchScope::CatchScope(llvm::Constant *classInfoPtr,
|
||||
llvm::BasicBlock *bodyBlock, CleanupCursor cleanupScope)
|
||||
llvm::BasicBlock *bodyBlock, CleanupCursor cleanupScope,
|
||||
llvm::MDNode *branchWeights)
|
||||
: classInfoPtr(classInfoPtr), bodyBlock(bodyBlock),
|
||||
cleanupScope(cleanupScope) {}
|
||||
branchWeights(branchWeights), cleanupScope(cleanupScope) {}
|
||||
|
||||
bool useMSVCEH() {
|
||||
#if LDC_LLVM_VER >= 308
|
||||
|
@ -54,7 +55,7 @@ llvm::BasicBlock *executeCleanupCopying(IRState *irs, CleanupScope &scope,
|
|||
llvm::BasicBlock *sourceBlock,
|
||||
llvm::BasicBlock *continueWith,
|
||||
llvm::BasicBlock *unwindTo,
|
||||
llvm::Value* funclet) {
|
||||
llvm::Value *funclet) {
|
||||
if (isCatchSwitchBlock(scope.beginBlock))
|
||||
return continueWith;
|
||||
if (scope.cleanupBlocks.empty()) {
|
||||
|
@ -253,7 +254,6 @@ llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope,
|
|||
if (isCatchSwitchBlock(cleanupScopes[scope].beginBlock))
|
||||
return cleanupScopes[scope].beginBlock;
|
||||
|
||||
|
||||
// each cleanup block is bracketed by a pair of cleanuppad/cleanupret
|
||||
// instructions, any unwinding should also just continue at the next
|
||||
// cleanup block, e.g.:
|
||||
|
@ -261,7 +261,7 @@ llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope,
|
|||
// cleanuppad:
|
||||
// %0 = cleanuppad within %funclet[]
|
||||
// %frame = nullptr
|
||||
// if (!_d_enter_cleanup(%frame)) br label %cleanupret
|
||||
// if (!_d_enter_cleanup(%frame)) br label %cleanupret
|
||||
// else br label %copy
|
||||
//
|
||||
// copy:
|
||||
|
@ -279,7 +279,7 @@ llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope,
|
|||
llvm::BasicBlock *cleanupret =
|
||||
llvm::BasicBlock::Create(irs->context(), "cleanupret", irs->topfunc());
|
||||
|
||||
// preparation to allocate some space on the stack where _d_enter_cleanup
|
||||
// preparation to allocate some space on the stack where _d_enter_cleanup
|
||||
// can place an exception frame (but not done here)
|
||||
auto frame = getNullPtr(getVoidPtrType());
|
||||
|
||||
|
@ -320,8 +320,8 @@ void ScopeStack::popCleanups(CleanupCursor targetScope) {
|
|||
llvm::BasicBlock *tentative = gotoJump.tentativeTarget;
|
||||
#if LDC_LLVM_VER >= 308
|
||||
if (useMSVCEH()) {
|
||||
llvm::BasicBlock *continueWith =
|
||||
llvm::BasicBlock::Create(irs->context(), "jumpcleanup", irs->topfunc());
|
||||
llvm::BasicBlock *continueWith = llvm::BasicBlock::Create(
|
||||
irs->context(), "jumpcleanup", irs->topfunc());
|
||||
auto startCleanup =
|
||||
executeCleanupCopying(irs, cleanupScopes[i], gotoJump.sourceBlock,
|
||||
continueWith, nullptr, nullptr);
|
||||
|
@ -350,14 +350,16 @@ void ScopeStack::popCleanups(CleanupCursor targetScope) {
|
|||
}
|
||||
|
||||
void ScopeStack::pushCatch(llvm::Constant *classInfoPtr,
|
||||
llvm::BasicBlock *bodyBlock) {
|
||||
llvm::BasicBlock *bodyBlock,
|
||||
llvm::MDNode *matchWeights) {
|
||||
if (useMSVCEH()) {
|
||||
#if LDC_LLVM_VER >= 308
|
||||
assert(isCatchSwitchBlock(bodyBlock));
|
||||
pushCleanup(bodyBlock, bodyBlock);
|
||||
#endif
|
||||
} else {
|
||||
catchScopes.emplace_back(classInfoPtr, bodyBlock, currentCleanupScope());
|
||||
catchScopes.emplace_back(classInfoPtr, bodyBlock, currentCleanupScope(),
|
||||
matchWeights);
|
||||
currentLandingPads().push_back(nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -585,7 +587,7 @@ llvm::BasicBlock *ScopeStack::emitLandingPad() {
|
|||
irs->ir->CreateCondBr(
|
||||
irs->ir->CreateICmpEQ(irs->ir->CreateLoad(irs->func()->ehSelectorSlot),
|
||||
ehTypeId),
|
||||
it->bodyBlock, mismatchBB);
|
||||
it->bodyBlock, mismatchBB, it->branchWeights);
|
||||
irs->scope() = IRScope(mismatchBB);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue