mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 19:06:02 +03:00
PGO: Add IR-based PGO.
This commit is contained in:
parent
3ec79179b4
commit
e8e28b33b2
5 changed files with 104 additions and 4 deletions
|
@ -15,9 +15,11 @@
|
|||
|
||||
#include "driver/cl_options_instrumentation.h"
|
||||
|
||||
#include "errors.h"
|
||||
#include "globals.h"
|
||||
|
||||
namespace {
|
||||
namespace cl = llvm::cl;
|
||||
|
||||
#if LDC_LLVM_VER >= 309
|
||||
/// Option for generating IR-based PGO instrumentation (LLVM pass)
|
||||
|
@ -82,6 +84,29 @@ void initializeInstrumentationOptionsFromCmdline() {
|
|||
pgoMode = PGO_ASTBasedUse;
|
||||
initFromPathString(global.params.datafileInstrProf, ASTPGOInstrUseFile);
|
||||
}
|
||||
#if LDC_LLVM_VER >= 309
|
||||
else if (IRPGOInstrGenFile.getNumOccurrences() > 0) {
|
||||
pgoMode = PGO_IRBasedInstr;
|
||||
if (IRPGOInstrGenFile.empty()) {
|
||||
global.params.datafileInstrProf = "default_%m.profraw";
|
||||
} else {
|
||||
initFromPathString(global.params.datafileInstrProf, IRPGOInstrGenFile);
|
||||
}
|
||||
} else if (!IRPGOInstrUseFile.empty()) {
|
||||
pgoMode = PGO_IRBasedUse;
|
||||
initFromPathString(global.params.datafileInstrProf, IRPGOInstrUseFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
// There is a bug in (our use of?) LLVM where codegen errors with
|
||||
// PGO_IRBasedInstr for Windows targets. So disable IRBased PGO on Windows for
|
||||
// now.
|
||||
assert(global.params.targetTriple);
|
||||
if ((pgoMode == PGO_IRBasedInstr) &&
|
||||
global.params.targetTriple->isOSWindows()) {
|
||||
error(Loc(),
|
||||
"'-fprofile-generate' is not yet supported for Windows targets.");
|
||||
}
|
||||
|
||||
if (dmdFunctionTrace)
|
||||
global.params.trace = true;
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace cl = llvm::cl;
|
|||
extern cl::opt<bool> instrumentFunctions;
|
||||
|
||||
/// This initializes the instrumentation options, and checks the validity of the
|
||||
/// commandline flags. It should be called only once.
|
||||
/// commandline flags. targetTriple should be initialized before calling this.
|
||||
/// It should be called only once.
|
||||
void initializeInstrumentationOptionsFromCmdline();
|
||||
|
||||
enum PGOKind {
|
||||
|
|
|
@ -431,7 +431,6 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
|
|||
}
|
||||
#endif
|
||||
|
||||
opts::initializeInstrumentationOptionsFromCmdline();
|
||||
opts::initializeSanitizerOptionsFromCmdline();
|
||||
|
||||
processVersions(debugArgs, "debug", DebugCondition::setGlobalLevel,
|
||||
|
@ -1067,6 +1066,8 @@ int cppmain(int argc, char **argv) {
|
|||
global.lib_ext = "a";
|
||||
}
|
||||
|
||||
opts::initializeInstrumentationOptionsFromCmdline();
|
||||
|
||||
Strings libmodules;
|
||||
return mars_mainBody(files, libmodules);
|
||||
}
|
||||
|
|
|
@ -207,7 +207,8 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
|
|||
}
|
||||
|
||||
// Adds PGO instrumentation generation and use passes.
|
||||
static void addPGOPasses(legacy::PassManagerBase &mpm, unsigned optLevel) {
|
||||
static void addPGOPasses(PassManagerBuilder &builder,
|
||||
legacy::PassManagerBase &mpm, unsigned optLevel) {
|
||||
if (opts::isInstrumentingForASTBasedPGO()) {
|
||||
InstrProfOptions options;
|
||||
options.NoRedZone = global.params.disableRedZone;
|
||||
|
@ -227,6 +228,16 @@ static void addPGOPasses(legacy::PassManagerBase &mpm, unsigned optLevel) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#if LDC_LLVM_VER >= 309
|
||||
else if (opts::isInstrumentingForIRBasedPGO()) {
|
||||
#if LDC_LLVM_VER >= 400
|
||||
builder.EnablePGOInstrGen = true;
|
||||
#endif
|
||||
builder.PGOInstrGen = global.params.datafileInstrProf;
|
||||
} else if (opts::isUsingIRBasedPGOProfile()) {
|
||||
builder.PGOInstrUse = global.params.datafileInstrProf;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -328,7 +339,7 @@ static void addOptimizationPasses(legacy::PassManagerBase &mpm,
|
|||
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addStripExternalsPass);
|
||||
|
||||
addPGOPasses(mpm, optLevel);
|
||||
addPGOPasses(builder, mpm, optLevel);
|
||||
|
||||
builder.populateFunctionPassManager(fpm);
|
||||
builder.populateModulePassManager(mpm);
|
||||
|
|
62
tests/PGO/irbased_indirect_calls.d
Normal file
62
tests/PGO/irbased_indirect_calls.d
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Test instrumentation of indirect calls
|
||||
|
||||
// REQUIRES: atleast_llvm309
|
||||
|
||||
// There is an LLVM bug, this test currently errors during LLVM codegen for Windows.
|
||||
// XFAIL: Windows
|
||||
|
||||
// RUN: %ldc -O3 -fprofile-generate=%t.profraw -run %s \
|
||||
// RUN: && %profdata merge %t.profraw -o %t.profdata \
|
||||
// RUN: && %ldc -O3 -c -output-ll -of=%t.use.ll -fprofile-use=%t.profdata %s \
|
||||
// RUN: && FileCheck %s -check-prefix=PROFUSE < %t.use.ll
|
||||
|
||||
import ldc.attributes : weak;
|
||||
|
||||
extern (C)
|
||||
{ // simplify name mangling for simpler string matching
|
||||
|
||||
@weak // disable reasoning about this function
|
||||
void hot()
|
||||
{
|
||||
}
|
||||
|
||||
void luke()
|
||||
{
|
||||
}
|
||||
|
||||
void cold()
|
||||
{
|
||||
}
|
||||
|
||||
void function() foo;
|
||||
|
||||
@weak // disable reasoning about this function
|
||||
void select_func(int i)
|
||||
{
|
||||
if (i < 1700)
|
||||
foo = &hot;
|
||||
else if (i < 1990)
|
||||
foo = &luke;
|
||||
else
|
||||
foo = &cold;
|
||||
}
|
||||
|
||||
} // extern C
|
||||
|
||||
// PROFUSE-LABEL: @_Dmain(
|
||||
int main()
|
||||
{
|
||||
for (int i; i < 2000; ++i)
|
||||
{
|
||||
select_func(i);
|
||||
|
||||
// PROFUSE: [[REG1:%[0-9]+]] = load void ()*, void ()** @foo
|
||||
// PROFUSE: [[REG2:%[0-9]+]] = icmp eq void ()* [[REG1]], @hot
|
||||
// PROFUSE: call void @hot()
|
||||
// PROFUSE: call void [[REG1]]()
|
||||
|
||||
foo();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue