Skip to content

Commit

Permalink
PGO: refactor such that there can be IR-based and frontend-based PGO.
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanEngelen committed Dec 28, 2017
1 parent 66ad379 commit 7cf6565
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 49 deletions.
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
52 changes: 36 additions & 16 deletions driver/cl_options_instrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,63 @@
namespace opts {

#if LDC_WITH_PGO
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);

cl::opt<std::string> usefileInstrProf(
#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);

/// 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);

#endif

cl::opt<bool>
instrumentFunctions("finstrument-functions", cl::ZeroOrMore,
cl::desc("Instrument function entry and exit with "
"GCC-compatible profiling calls"));

PGOKind pgoMode = PGO_None;

void initializeInstrumentationOptionsFromCmdline() {
#if LDC_WITH_PGO
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);
}
#endif
}
Expand Down
28 changes: 23 additions & 5 deletions driver/cl_options_instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,34 @@
namespace opts {
namespace cl = llvm::cl;

#if LDC_WITH_PGO
extern cl::opt<std::string> genfileInstrProf;
extern cl::opt<std::string> usefileInstrProf;
#endif

extern cl::opt<bool> instrumentFunctions;

/// This initializes the instrumentation options, and checks the validity of the
/// commandline flags. 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 @@ -383,7 +384,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 @@ -109,8 +110,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
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 @@ -612,9 +613,8 @@ void addCoverageAnalysisInitializer(Module *m) {
// modules?
void loadInstrProfileData(IRState *irs) {
#if LDC_WITH_PGO
// 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
6 changes: 3 additions & 3 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 @@ -202,8 +203,7 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
// Adds PGO instrumentation generation and use passes.
static void addPGOPasses(legacy::PassManagerBase &mpm, unsigned optLevel) {
#if LDC_WITH_PGO
if (global.params.genInstrProf) {
// We are generating PGO instrumented code.
if (opts::isInstrumentingForASTBasedPGO()) {
InstrProfOptions options;
options.NoRedZone = global.params.disableRedZone;
if (global.params.datafileInstrProf)
Expand All @@ -213,7 +213,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 Down
20 changes: 12 additions & 8 deletions gen/pgo.cpp → gen/pgo_ASTbased.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===-- gen/pgo.cpp ---------------------------------------------*- C++ -*-===//
//===-- gen/pgo_ASTbased.cpp ------------------------------------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
Expand All @@ -8,11 +8,12 @@
//
//===----------------------------------------------------------------------===//
//
// Instrumentation-based profile-guided optimization
// Instrumentation-based profile-guided optimization. This is AST-based PGO, in
// contrast to LLVM's IR-based PGO.
//
//===----------------------------------------------------------------------===//

#include "gen/pgo.h"
#include "gen/pgo_ASTbased.h"

// Conditionally include PGO
#if LDC_WITH_PGO
Expand All @@ -21,6 +22,7 @@
#include "init.h"
#include "statement.h"
#include "llvm.h"
#include "driver/cl_options_instrumentation.h"
#include "gen/cl_helpers.h"
#include "gen/irstate.h"
#include "gen/logger.h"
Expand Down Expand Up @@ -770,7 +772,7 @@ void CodeGenPGO::setFuncName(llvm::StringRef Name,
: llvm::IndexedInstrProf::Version);

// If we're generating a profile, create a variable for the name.
if (global.params.genInstrProf && emitInstrumentation) {
if (opts::isInstrumentingForASTBasedPGO() && emitInstrumentation) {
FuncNameVar = llvm::createPGOFuncNameVar(gIR->module, Linkage, FuncName);

// If Linkage is private, and the function is in a comdat "any" group, set
Expand All @@ -791,7 +793,7 @@ void CodeGenPGO::setFuncName(llvm::StringRef Name,
FuncName = RawFuncName;

// If we're generating a profile, create a variable for the name.
if (global.params.genInstrProf && emitInstrumentation)
if (opts::isInstrumentingForASTBasedPGO() && emitInstrumentation)
createFuncNameVar(Linkage);
#endif
}
Expand Down Expand Up @@ -828,7 +830,7 @@ void CodeGenPGO::createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage) {
void CodeGenPGO::assignRegionCounters(const FuncDeclaration *D,
llvm::Function *fn) {
llvm::IndexedInstrProfReader *PGOReader = gIR->getPGOReader();
if (!global.params.genInstrProf && !PGOReader)
if (!opts::isInstrumentingForASTBasedPGO() && !PGOReader)
return;

emitInstrumentation = D->emitInstrumentation;
Expand Down Expand Up @@ -870,7 +872,8 @@ void CodeGenPGO::applyFunctionAttributes(llvm::Function *Fn) {
}

void CodeGenPGO::emitCounterIncrement(const RootObject *S) const {
if (!global.params.genInstrProf || !RegionCounterMap || !emitInstrumentation)
if (!opts::isInstrumentingForASTBasedPGO() || !RegionCounterMap ||
!emitInstrumentation)
return;

auto counter_it = (*RegionCounterMap).find(S);
Expand Down Expand Up @@ -1083,7 +1086,8 @@ void CodeGenPGO::valueProfile(uint32_t valueKind, llvm::Instruction *valueSite,
if (!value || !valueSite)
return;

bool instrumentValueSites = global.params.genInstrProf && emitInstrumentation;
bool instrumentValueSites =
opts::isInstrumentingForASTBasedPGO() && emitInstrumentation;
if (instrumentValueSites && RegionCounterMap) {
// Instrumentation must be inserted just before the valueSite instruction.
// Save the current insertion point to be able to restore it later.
Expand Down
10 changes: 5 additions & 5 deletions gen/pgo.h → gen/pgo_ASTbased.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===-- gen/pgo.h - Code Coverage Analysis ----------------------*- C++ -*-===//
//===-- gen/pgo_ASTbased.h - Code Coverage Analysis -------------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
Expand All @@ -9,14 +9,14 @@
//===----------------------------------------------------------------------===//
//
// This file contains functions to generate instrumentation code for
// profile-guided optimization.
// AST-based profile-guided optimization.
// PGO is enabled by compiling first with "-fprofile-instr-generate",
// and then with "-fprofile-instr-use=filename.profdata".
//
//===----------------------------------------------------------------------===//

#ifndef LDC_GEN_PGO_H
#define LDC_GEN_PGO_H
#ifndef LDC_GEN_PGO_ASTBASED_H
#define LDC_GEN_PGO_ASTBASED_H

#include "gen/llvm.h"
#include "llvm/ProfileData/InstrProf.h"
Expand Down Expand Up @@ -238,4 +238,4 @@ class CodeGenPGO {

#endif // LLVM version

#endif // LDC_GEN_PGO_H
#endif // LDC_GEN_PGO_ASTBASED_H

0 comments on commit 7cf6565

Please sign in to comment.