mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 10:57:35 +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 "driver/cl_options_instrumentation.h"
|
||||||
|
|
||||||
|
#include "errors.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
namespace cl = llvm::cl;
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 309
|
#if LDC_LLVM_VER >= 309
|
||||||
/// Option for generating IR-based PGO instrumentation (LLVM pass)
|
/// Option for generating IR-based PGO instrumentation (LLVM pass)
|
||||||
|
@ -82,6 +84,29 @@ void initializeInstrumentationOptionsFromCmdline() {
|
||||||
pgoMode = PGO_ASTBasedUse;
|
pgoMode = PGO_ASTBasedUse;
|
||||||
initFromPathString(global.params.datafileInstrProf, ASTPGOInstrUseFile);
|
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)
|
if (dmdFunctionTrace)
|
||||||
global.params.trace = true;
|
global.params.trace = true;
|
||||||
|
|
|
@ -24,7 +24,8 @@ namespace cl = llvm::cl;
|
||||||
extern cl::opt<bool> instrumentFunctions;
|
extern cl::opt<bool> instrumentFunctions;
|
||||||
|
|
||||||
/// This initializes the instrumentation options, and checks the validity of the
|
/// 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();
|
void initializeInstrumentationOptionsFromCmdline();
|
||||||
|
|
||||||
enum PGOKind {
|
enum PGOKind {
|
||||||
|
|
|
@ -431,7 +431,6 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
opts::initializeInstrumentationOptionsFromCmdline();
|
|
||||||
opts::initializeSanitizerOptionsFromCmdline();
|
opts::initializeSanitizerOptionsFromCmdline();
|
||||||
|
|
||||||
processVersions(debugArgs, "debug", DebugCondition::setGlobalLevel,
|
processVersions(debugArgs, "debug", DebugCondition::setGlobalLevel,
|
||||||
|
@ -1067,6 +1066,8 @@ int cppmain(int argc, char **argv) {
|
||||||
global.lib_ext = "a";
|
global.lib_ext = "a";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts::initializeInstrumentationOptionsFromCmdline();
|
||||||
|
|
||||||
Strings libmodules;
|
Strings libmodules;
|
||||||
return mars_mainBody(files, libmodules);
|
return mars_mainBody(files, libmodules);
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,8 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds PGO instrumentation generation and use passes.
|
// 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()) {
|
if (opts::isInstrumentingForASTBasedPGO()) {
|
||||||
InstrProfOptions options;
|
InstrProfOptions options;
|
||||||
options.NoRedZone = global.params.disableRedZone;
|
options.NoRedZone = global.params.disableRedZone;
|
||||||
|
@ -227,6 +228,16 @@ static void addPGOPasses(legacy::PassManagerBase &mpm, unsigned optLevel) {
|
||||||
}
|
}
|
||||||
#endif
|
#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,
|
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||||
addStripExternalsPass);
|
addStripExternalsPass);
|
||||||
|
|
||||||
addPGOPasses(mpm, optLevel);
|
addPGOPasses(builder, mpm, optLevel);
|
||||||
|
|
||||||
builder.populateFunctionPassManager(fpm);
|
builder.populateFunctionPassManager(fpm);
|
||||||
builder.populateModulePassManager(mpm);
|
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