Skip to content

Commit

Permalink
PGO: Add IR-based PGO.
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanEngelen committed Jan 15, 2018
1 parent 3ec7917 commit e8e28b3
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 4 deletions.
25 changes: 25 additions & 0 deletions driver/cl_options_instrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion driver/cl_options_instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion driver/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,6 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
}
#endif

opts::initializeInstrumentationOptionsFromCmdline();
opts::initializeSanitizerOptionsFromCmdline();

processVersions(debugArgs, "debug", DebugCondition::setGlobalLevel,
Expand Down Expand Up @@ -1067,6 +1066,8 @@ int cppmain(int argc, char **argv) {
global.lib_ext = "a";
}

opts::initializeInstrumentationOptionsFromCmdline();

Strings libmodules;
return mars_mainBody(files, libmodules);
}
Expand Down
15 changes: 13 additions & 2 deletions gen/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
}

/**
Expand Down Expand Up @@ -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);
Expand Down
62 changes: 62 additions & 0 deletions tests/PGO/irbased_indirect_calls.d
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit e8e28b3

Please sign in to comment.