Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IR-based PGO #2474

Merged
merged 2 commits into from
Jan 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion ddmd/globals.d
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ struct Param
bool cleanupObjectFiles;

// Profile-guided optimization:
bool genInstrProf; // Whether to generate PGO instrumented code
const(char)* datafileInstrProf; // Either the input or output file for PGO data

// target stuff
Expand Down
1 change: 0 additions & 1 deletion ddmd/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ struct Param
bool cleanupObjectFiles;

// Profile-guided optimization:
bool genInstrProf; // Whether to generate PGO instrumented code
const char *datafileInstrProf; // Either the input or output file for PGO data

const llvm::Triple *targetTriple;
Expand Down
81 changes: 64 additions & 17 deletions driver/cl_options_instrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,48 @@

#include "driver/cl_options_instrumentation.h"

#include "errors.h"
#include "globals.h"

namespace opts {
namespace {
namespace cl = llvm::cl;

cl::opt<std::string>
genfileInstrProf("fprofile-instr-generate", cl::value_desc("filename"),
cl::desc("Generate instrumented code to collect a runtime "
"profile into default.profraw (overriden by "
"'=<filename>' or LLVM_PROFILE_FILE env var)"),
cl::ZeroOrMore, cl::ValueOptional);
#if LDC_LLVM_VER >= 309
/// Option for generating IR-based PGO instrumentation (LLVM pass)
cl::opt<std::string> IRPGOInstrGenFile(
"fprofile-generate", cl::value_desc("filename"),
cl::desc("Generate instrumented code to collect a runtime "
"profile into default.profraw (overriden by "
"'=<filename>' or LLVM_PROFILE_FILE env var)"),
cl::ZeroOrMore, cl::ValueOptional);

cl::opt<std::string> usefileInstrProf(
/// Option for generating IR-based PGO instrumentation (LLVM pass)
cl::opt<std::string> IRPGOInstrUseFile(
"fprofile-use", cl::ZeroOrMore, cl::value_desc("filename"),
cl::desc("Use instrumentation data for profile-guided optimization"),
cl::ValueRequired);
#endif

/// Option for generating frontend-based PGO instrumentation
cl::opt<std::string> ASTPGOInstrGenFile(
"fprofile-instr-generate", cl::value_desc("filename"),
cl::desc("Generate instrumented code to collect a runtime "
"profile into default.profraw (overriden by "
"'=<filename>' or LLVM_PROFILE_FILE env var)"),
cl::ZeroOrMore, cl::ValueOptional);

/// Option for generating frontend-based PGO instrumentation
cl::opt<std::string> ASTPGOInstrUseFile(
"fprofile-instr-use", cl::ZeroOrMore, cl::value_desc("filename"),
cl::desc("Use instrumentation data for profile-guided optimization"),
cl::ValueRequired);

} // anonymous namespace

namespace opts {

PGOKind pgoMode = PGO_None;

cl::opt<bool>
instrumentFunctions("finstrument-functions", cl::ZeroOrMore,
cl::desc("Instrument function entry and exit with "
Expand All @@ -42,23 +68,44 @@ static cl::opt<bool> dmdFunctionTrace(
cl::desc("DMD-style runtime performance profiling of generated code"));

void initializeInstrumentationOptionsFromCmdline() {
if (genfileInstrProf.getNumOccurrences() > 0) {
global.params.genInstrProf = true;
if (genfileInstrProf.empty()) {
if (ASTPGOInstrGenFile.getNumOccurrences() > 0) {
pgoMode = PGO_ASTBasedInstr;
if (ASTPGOInstrGenFile.empty()) {
#if LDC_LLVM_VER >= 309
// profile-rt provides a default filename by itself
global.params.datafileInstrProf = nullptr;
#else
global.params.datafileInstrProf = "default.profraw";
#endif
} else {
initFromPathString(global.params.datafileInstrProf, genfileInstrProf);
initFromPathString(global.params.datafileInstrProf, ASTPGOInstrGenFile);
}
} else {
global.params.genInstrProf = false;
// If we don't have to generate instrumentation, we could be given a
// profdata file:
initFromPathString(global.params.datafileInstrProf, usefileInstrProf);
} else if (!ASTPGOInstrUseFile.empty()) {
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)
Expand Down
30 changes: 25 additions & 5 deletions driver/cl_options_instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,35 @@
namespace opts {
namespace cl = llvm::cl;

// PGO options
extern cl::opt<std::string> genfileInstrProf;
extern cl::opt<std::string> usefileInstrProf;

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 {
PGO_None,
PGO_ASTBasedInstr,
PGO_ASTBasedUse,
PGO_IRBasedInstr,
PGO_IRBasedUse,
};
extern PGOKind pgoMode;
inline bool isInstrumentingForPGO() {
return pgoMode == PGO_ASTBasedInstr || pgoMode == PGO_IRBasedInstr;
}
inline bool isUsingPGOProfile() {
return pgoMode == PGO_ASTBasedUse || pgoMode == PGO_IRBasedUse;
}
inline bool isInstrumentingForASTBasedPGO() {
return pgoMode == PGO_ASTBasedInstr;
}
inline bool isUsingASTBasedPGOProfile() { return pgoMode == PGO_ASTBasedUse; }
inline bool isInstrumentingForIRBasedPGO() {
return pgoMode == PGO_IRBasedInstr;
}
inline bool isUsingIRBasedPGOProfile() { return pgoMode == PGO_IRBasedUse; }

} // namespace opts
#endif // LDC_DRIVER_CL_OPTIONS_INSTRUMENTATION_H
3 changes: 2 additions & 1 deletion driver/codegenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "module.h"
#include "scope.h"
#include "driver/cl_options.h"
#include "driver/cl_options_instrumentation.h"
#include "driver/linker.h"
#include "driver/toobj.h"
#include "gen/logger.h"
Expand Down Expand Up @@ -68,7 +69,7 @@ createAndSetDiagnosticsOutputFile(IRState &irs, llvm::LLVMContext &ctx,
llvm::make_unique<llvm::yaml::Output>(diagnosticsOutputFile->os()));

// If there is instrumentation data available, also output function hotness
if (!global.params.genInstrProf && global.params.datafileInstrProf) {
if (opts::isUsingPGOProfile()) {
#if LDC_LLVM_VER >= 500
ctx.setDiagnosticsHotnessRequested(true);
#else
Expand Down
5 changes: 3 additions & 2 deletions driver/linker-gcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "errors.h"
#include "driver/cl_options.h"
#include "driver/cl_options_instrumentation.h"
#include "driver/cl_options_sanitizers.h"
#include "driver/exe_path.h"
#include "driver/tool.h"
Expand Down Expand Up @@ -329,7 +330,7 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
}

// Link with profile-rt library when generating an instrumented binary.
if (global.params.genInstrProf) {
if (opts::isInstrumentingForPGO()) {
#if LDC_LLVM_VER >= 308
if (global.params.targetTriple->isOSLinux()) {
// For Linux, explicitly define __llvm_profile_runtime as undefined
Expand Down Expand Up @@ -386,7 +387,7 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
// instrumented binary. The runtime relies on magic sections, which
// would be stripped by gc-section on older version of ld, see bug:
// https://sourceware.org/bugzilla/show_bug.cgi?id=19161
if (!opts::disableLinkerStripDead && !global.params.genInstrProf) {
if (!opts::disableLinkerStripDead && !opts::isInstrumentingForPGO()) {
addLdFlag("--gc-sections");
}
}
Expand Down
4 changes: 2 additions & 2 deletions driver/linker-msvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "errors.h"
#include "driver/cl_options.h"
#include "driver/cl_options_instrumentation.h"
#include "driver/tool.h"
#include "gen/logger.h"

Expand Down Expand Up @@ -110,8 +111,7 @@ int linkObjToBinaryMSVC(llvm::StringRef outputPath, bool useInternalLinker,
args.push_back(std::string("/DEF:") + global.params.deffile);

// Link with profile-rt library when generating an instrumented binary
// profile-rt depends on Phobos (MD5 hashing).
if (global.params.genInstrProf) {
if (opts::isInstrumentingForPGO()) {
args.push_back("ldc-profile-rt.lib");
// profile-rt depends on ws2_32 for symbol `gethostname`
args.push_back("ws2_32.lib");
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();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i had to place the call here, after the triple has been initialized. The option sanity-checking needs to know the target triple, and I didn't want to separate the sanity checking from the initialization code.


Strings libmodules;
return mars_mainBody(files, libmodules);
}
Expand Down
2 changes: 1 addition & 1 deletion gen/funcgenstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define LDC_GEN_FUNCGENSTATE_H

#include "gen/irstate.h"
#include "gen/pgo.h"
#include "gen/pgo_ASTbased.h"
#include "gen/trycatchfinally.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallSite.h"
Expand Down
2 changes: 1 addition & 1 deletion gen/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#include "gen/mangling.h"
#include "gen/nested.h"
#include "gen/optimizer.h"
#include "gen/pgo.h"
#include "gen/pgo_ASTbased.h"
#include "gen/pragma.h"
#include "gen/runtime.h"
#include "gen/dynamiccompile.h"
Expand Down
6 changes: 3 additions & 3 deletions gen/modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "statement.h"
#include "target.h"
#include "template.h"
#include "driver/cl_options_instrumentation.h"
#include "gen/abi.h"
#include "gen/arrays.h"
#include "gen/functions.h"
Expand Down Expand Up @@ -611,9 +612,8 @@ void addCoverageAnalysisInitializer(Module *m) {
// TODO: This is probably not the right place, we should load it once for all
// modules?
void loadInstrProfileData(IRState *irs) {
// Only load from datafileInstrProf if we are not generating instrumented
// code.
if (!global.params.genInstrProf && global.params.datafileInstrProf) {
// Only load from datafileInstrProf if we are doing frontend-based PGO.
if (opts::isUsingASTBasedPGOProfile() && global.params.datafileInstrProf) {
IF_LOG Logger::println("Read profile data from %s",
global.params.datafileInstrProf);

Expand Down
21 changes: 16 additions & 5 deletions gen/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "gen/logger.h"
#include "gen/passes/Passes.h"
#include "driver/cl_options.h"
#include "driver/cl_options_instrumentation.h"
#include "driver/cl_options_sanitizers.h"
#include "driver/targetmachine.h"
#include "llvm/LinkAllPasses.h"
Expand Down Expand Up @@ -206,9 +207,9 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
}

// Adds PGO instrumentation generation and use passes.
static void addPGOPasses(legacy::PassManagerBase &mpm, unsigned optLevel) {
if (global.params.genInstrProf) {
// We are generating PGO instrumented code.
static void addPGOPasses(PassManagerBuilder &builder,
legacy::PassManagerBase &mpm, unsigned optLevel) {
if (opts::isInstrumentingForASTBasedPGO()) {
InstrProfOptions options;
options.NoRedZone = global.params.disableRedZone;
if (global.params.datafileInstrProf)
Expand All @@ -218,7 +219,7 @@ static void addPGOPasses(legacy::PassManagerBase &mpm, unsigned optLevel) {
#else
mpm.add(createInstrProfilingPass(options));
#endif
} else if (global.params.datafileInstrProf) {
} else if (opts::isUsingASTBasedPGOProfile()) {
// We are generating code with PGO profile information available.
#if LDC_LLVM_VER >= 500
// Do indirect call promotion from -O1
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
Loading