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

Profile-guided optimizations (PGO) #1219

Merged
merged 27 commits into from
Jun 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e0d9c58
[PGO] Add PGO to LDC. Supported for LLVM >= 3.7
Nov 16, 2015
e52ce7d
[PGO] Implement correct calculation of region execution count for `br…
JohanEngelen Mar 6, 2016
ebbd2a3
[PGO] Remove hot/cold function marking from LDC, because LLVM >= 3.8 …
JohanEngelen Mar 8, 2016
7cce21e
Remove commented-out remnants from Clang source. [NFC]
JohanEngelen Mar 8, 2016
62896f8
[PGO] Separate the statements involving exceptions from the other sta…
JohanEngelen Mar 26, 2016
ec6c095
Update profile-rt to trunk rev. 265227
JohanEngelen Mar 26, 2016
91c066b
[PGO] Fix bug with multiple defined MaxFunctionCounts when compiling …
JohanEngelen Apr 5, 2016
81fe81e
[PGO] Add test for -singleobj compilation.
JohanEngelen Apr 24, 2016
5ac4832
[PGO] Emit profile summary for LLVM >= 3.9
JohanEngelen Apr 24, 2016
c42e543
[PGO] If a function is in a comdat group, set the linkage of __profn_…
JohanEngelen Apr 24, 2016
9233813
[PGO] Attempt to fix Windows linking problem.
JohanEngelen Apr 25, 2016
3e03380
Update llvm-profdata-3.9
JohanEngelen Apr 28, 2016
cb4b77d
Fix LLVM3.9 build.
JohanEngelen Apr 28, 2016
a82e816
add PGO message to cmake
JohanEngelen Apr 29, 2016
5633042
Fix multilib building of ldc-profile-rt
JohanEngelen Apr 29, 2016
e1c06c1
[PGO] Move link hint for ws2_32.lib to cmake script
JohanEngelen May 17, 2016
103c6f5
[PGO] Update llvm-profdata-3.9 and profile-rt-39 to LLVM r269788.
JohanEngelen May 17, 2016
002dc5d
Attempt to fix profdata linking issue.
JohanEngelen May 18, 2016
0f22a88
Remove unused variables.
JohanEngelen May 18, 2016
20c9f3f
[PGO] Fix profile-rt linking: put it before Phobos.
JohanEngelen May 21, 2016
ea7a2e0
[PGO] Update ldc-profdata-3.9 and profile-rt-39 to svn r270319
JohanEngelen May 21, 2016
8bae926
clang format
JohanEngelen May 23, 2016
aadb45a
[PGO] Fix LLVM 3.9 error handling code.
JohanEngelen May 23, 2016
4a7a5de
Fix initialization order warning.
JohanEngelen May 23, 2016
33a54a9
[PGO] Fix ldc-profile-rt.lib linking on Windows.
JohanEngelen May 24, 2016
176961f
[PGO] Fix tests on Win x86. Add testcase for extern(C++) function pas…
JohanEngelen May 25, 2016
21c2c6d
[PGO] Update ldc-profdata-3.9 and profile-rt-39 to svn r273081
JohanEngelen Jun 20, 2016
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
30 changes: 30 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ elseif(D_VERSION EQUAL 2)
set(DDMDFE_PATH ddmd)
set(LDC_EXE ldc2)
set(LDMD_EXE ldmd2)
set(LDCPROFDATA_EXE ldc-profdata)
set(RUNTIME druntime)
append("-DDMDV2" CMAKE_CXX_FLAGS)
else()
Expand All @@ -99,6 +100,7 @@ endif()

set(LDC_EXE_NAME ${PROGRAM_PREFIX}${LDC_EXE}${PROGRAM_SUFFIX})
set(LDMD_EXE_NAME ${PROGRAM_PREFIX}${LDMD_EXE}${PROGRAM_SUFFIX})
set(LDCPROFDATA_EXE_NAME ${PROGRAM_PREFIX}${LDCPROFDATA_EXE}${PROGRAM_SUFFIX})

file(MAKE_DIRECTORY
${PROJECT_BINARY_DIR}
Expand Down Expand Up @@ -435,6 +437,18 @@ source_group("Source Files\\ir" FILES ${IR_SRC})
source_group("Header Files\\ir" FILES ${IR_HDR})
source_group("Generated Files" REGULAR_EXPRESSION "(id\\.[cdh]|impcnvtab\\.c)$")


#
# Enable PGO if supported for this platform and LLVM version.
# LLVM >= 3.7 is required for PGO.
#
set(LDC_WITH_PGO False) # must be a valid Python boolean constant (case sensitive)
if (NOT (LDC_LLVM_VER LESS 307))
message(STATUS "Building LDC with PGO support")
add_definitions(-DLDC_WITH_PGO)
set(LDC_WITH_PGO True)
endif()

#
# Includes, defines.
#
Expand Down Expand Up @@ -670,6 +684,22 @@ set_target_properties(
)
target_link_libraries(not ${LLVM_LIBRARIES} ${TERMINFO_LIBS} ${CMAKE_DL_LIBS} ${LLVM_LDFLAGS})

# Build ldc-profdata for converting profile data formats (source version depends on LLVM version)
set(LDCPROFDATA_SRC utils/llvm-profdata-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.cpp)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LDCPROFDATA_SRC})
add_executable(ldc-profdata ${LDCPROFDATA_SRC})
set_target_properties(
ldc-profdata PROPERTIES
OUTPUT_NAME "${LDCPROFDATA_EXE_NAME}"
RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin
COMPILE_FLAGS "${LLVM_CXXFLAGS} ${CMAKE_CXX_FLAGS_RELEASE}"
LINK_FLAGS "${SANITIZE_LDFLAGS}"
)
target_link_libraries(ldc-profdata ${LLVM_LIBRARIES} ${TERMINFO_LIBS} ${CMAKE_DL_LIBS} ${LLVM_LDFLAGS})
install(TARGETS ${LDCPROFDATA_EXE} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif()


#
# LDMD
#
Expand Down
15 changes: 15 additions & 0 deletions ddmd/attrib.d
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,21 @@ public:
}
return createNewScope(sc, sc.stc, sc.linkage, sc.protection, sc.explicitProtection, sc.structalign, inlining);
}
else if (IN_LLVM && ident == Id.LDC_profile_instr) {
bool emitInstr = true;
if (!args || args.dim != 1 || !DtoCheckProfileInstrPragma((*args)[0], emitInstr)) {
error("pragma(LDC_profile_instr, true or false) expected");
(*args)[0] = new ErrorExp();
} else {
// Only create a new scope if the emitInstrumentation flag is changed
if (sc.emitInstrumentation != emitInstr) {
auto newscope = sc.copy();
newscope.emitInstrumentation = emitInstr;
return newscope;
}
}
}

return sc;
}

Expand Down
4 changes: 4 additions & 0 deletions ddmd/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,10 @@ class FuncDeclaration : public Declaration

// true if set with the pragma(LDC_never_inline); statement
bool neverInline;

// Whether to emit instrumentation code if -fprofile-instr-generate is specified,
// the value is set with pragma(LDC_profile_instr, true|false)
bool emitInstrumentation;
#endif

Identifier *outId; // identifier for out statement
Expand Down
5 changes: 5 additions & 0 deletions ddmd/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ struct Scope
// user defined attributes
UserAttributeDeclaration userAttribDecl;

version(IN_LLVM)
{
bool emitInstrumentation = true; // whether to emit instrumentation with -fprofile-instr-generate
}

DocComment* lastdc; // documentation comment for last symbol at this scope
uint[void*] anchorCounts; // lookup duplicate anchor name count
Identifier prevAnchor; // qualified symbol name of last doc anchor
Expand Down
9 changes: 9 additions & 0 deletions ddmd/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ public:

// true if set with the pragma(LDC_never_inline); statement
bool neverInline = false;

// Whether to emit instrumentation code if -fprofile-instr-generate is specified,
// the value is set with pragma(LDC_profile_instr, true|false)
bool emitInstrumentation = true;
}

Identifier outId; // identifier for out statement
Expand Down Expand Up @@ -637,6 +641,11 @@ public:
inlining = sc.inlining;
protection = sc.protection;
userAttribDecl = sc.userAttribDecl;
version(IN_LLVM)
{
emitInstrumentation = sc.emitInstrumentation;
}

if (!originalType)
originalType = type.syntaxCopy();
if (!type.deco)
Expand Down
4 changes: 4 additions & 0 deletions ddmd/globals.d
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ struct Param
bool verbose_cg;
bool hasObjectiveC;

// 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
const(void)* targetTriple; // const llvm::Triple*

Expand Down
4 changes: 4 additions & 0 deletions ddmd/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ struct Param
bool verbose_cg;
bool hasObjectiveC;

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

// Codegen cl options
Expand Down
1 change: 1 addition & 0 deletions ddmd/idgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ Msgtable[] msgtable =
{ "LDC_global_crt_ctor" },
{ "LDC_global_crt_dtor" },
{ "LDC_extern_weak" },
{ "LDC_profile_instr" },

// IN_LLVM: LDC-specific traits.
{ "targetCPU" },
Expand Down
4 changes: 4 additions & 0 deletions ddmd/scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ struct Scope

UserAttributeDeclaration *userAttribDecl; // user defined attributes

#if IN_LLVM
bool emitInstrumentation; // whether to emit instrumentation with -fprofile-instr-generate
#endif

DocComment *lastdc; // documentation comment for last symbol at this scope
AA *anchorCounts; // lookup duplicate anchor name count
Identifier *prevAnchor; // qualified symbol name of last doc anchor
Expand Down
51 changes: 51 additions & 0 deletions ddmd/statement.d
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ import ddmd.staticassert;
import ddmd.target;
import ddmd.tokens;
import ddmd.visitor;
version(IN_LLVM)
{
import gen.dpragma;
}

extern (C++) Identifier fixupLabelName(Scope* sc, Identifier ident)
{
Expand Down Expand Up @@ -3679,6 +3683,26 @@ public:
{
sc.func.neverInline = true;
}
// IN_LLVM. FIXME Move to pragma.cpp
else if (ident == Id.LDC_profile_instr)
{
bool emitInstr = true;
if (!args || args.dim != 1 || !DtoCheckProfileInstrPragma((*args)[0], emitInstr))
{
error("pragma(LDC_profile_instr, true or false) expected");
goto Lerror;
}
else
{
FuncDeclaration fd = sc.func;
if (fd is null)
{
error("pragma(LDC_profile_instr, ...) is not inside a function");
goto Lerror;
}
fd.emitInstrumentation = emitInstr;
}
}
else if (ident == Id.startaddress)
{
if (!args || args.dim != 1)
Expand Down Expand Up @@ -3803,6 +3827,10 @@ public:
CaseStatements* cases; // array of CaseStatement's
int hasNoDefault; // !=0 if no default statement
int hasVars; // !=0 if has variable case values
version(IN_LLVM)
{
bool hasGotoDefault; // true iff there is a `goto default` statement for this switch
}

extern (D) this(Loc loc, Expression c, Statement b, bool isFinal)
{
Expand Down Expand Up @@ -3903,6 +3931,10 @@ public:
if (cs.exp.equals(gcs.exp))
{
gcs.cs = cs;
version(IN_LLVM)
{
cs.gototarget = true;
}
goto Lfoundcase;
}
}
Expand Down Expand Up @@ -3963,6 +3995,17 @@ public:
cs = new CompoundStatement(loc, a);
_body = cs;
}
version(IN_LLVM)
{
/+ hasGotoDefault is set by GotoDefaultStatement.semantic
+ at which point sdefault may still be null, therefore
+ set sdefault.gototarget here.
+/
if (hasGotoDefault) {
assert(sdefault);
sdefault.gototarget = true;
}
}
sc.pop();
return this;
Lerror:
Expand Down Expand Up @@ -3992,6 +4035,7 @@ public:

version(IN_LLVM)
{
bool gototarget; // true iff this is the target of a 'goto case'
void* bodyBB; // llvm::BasicBlock*
void* llvmIdx; // llvm::Value*
}
Expand Down Expand Up @@ -4222,6 +4266,7 @@ public:

version(IN_LLVM)
{
bool gototarget; // true iff this is the target of a 'goto default'
void* bodyBB; // llvm::BasicBlock*
}

Expand Down Expand Up @@ -4311,6 +4356,12 @@ public:
error("goto default not allowed in final switch statement");
return new ErrorStatement();
}

version(IN_LLVM)
{
sw.hasGotoDefault = true;
}

return this;
}

Expand Down
6 changes: 6 additions & 0 deletions ddmd/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ class SwitchStatement : public Statement
int hasNoDefault; // !=0 if no default statement
int hasVars; // !=0 if has variable case values

#if IN_LLVM
bool hasGotoDefault; // true iff there is a `goto default` statement for this switch
#endif

SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Expand All @@ -458,6 +462,7 @@ class CaseStatement : public Statement
int index; // which case it is (since we sort this)

#if IN_LLVM
bool gototarget; // true iff this is the target of a 'goto case'
llvm::BasicBlock* bodyBB;
llvm::Value* llvmIdx;
#endif
Expand Down Expand Up @@ -492,6 +497,7 @@ class DefaultStatement : public Statement
Statement *statement;

#if IN_LLVM
bool gototarget; // true iff this is the target of a 'goto default'
llvm::BasicBlock* bodyBB;
#endif

Expand Down
13 changes: 13 additions & 0 deletions driver/cl_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,19 @@ cl::opt<unsigned char, true, CoverageParser> coverageAnalysis(
"minimum required coverage)"),
cl::location(global.params.covPercent), cl::ValueOptional, cl::init(127));

#if LDC_WITH_PGO
cl::opt<std::string>
genfileInstrProf("fprofile-instr-generate", cl::value_desc("filename"),
cl::desc("Generate instrumented code to collect "
"execution counts (e.g. for PGO)"),
cl::ValueOptional);

cl::opt<std::string> usefileInstrProf(
"fprofile-instr-use", cl::value_desc("filename"),
cl::desc("Use instrumentation data for profile-guided optimization"),
cl::ValueRequired);
#endif

static cl::extrahelp footer(
"\n"
"-d-debug can also be specified without options, in which case it enables "
Expand Down
5 changes: 5 additions & 0 deletions driver/cl_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ extern bool nonSafeBoundsChecks;

extern cl::opt<unsigned, true> nestedTemplateDepth;

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

// Arguments to -d-debug
extern std::vector<std::string> debugArgs;
// Arguments to -run
Expand Down
1 change: 1 addition & 0 deletions driver/codegenerator.d
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern (C++) void genCmain(Scope *sc) {
*/
static __gshared const(char)[] code =
q{
pragma(LDC_profile_instr, false):
extern(C)
{
int _d_run_main(int argc, char **argv, void* mainFunc);
Expand Down
30 changes: 29 additions & 1 deletion driver/linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Path.h"
Expand Down Expand Up @@ -165,6 +166,21 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
args.push_back(p);
}

// Link with profile-rt library when generating an instrumented binary.
// profile-rt uses Phobos (MD5 hashing) and therefore must be passed on the
// commandline before Phobos.
if (global.params.genInstrProf) {
#if LDC_LLVM_VER >= 308
if (global.params.targetTriple->isOSLinux()) {
// For Linux, explicitly define __llvm_profile_runtime as undefined
// symbol, so that the initialization part of profile-rt is linked in.
args.push_back(
("-Wl,-u," + llvm::getInstrProfRuntimeHookVarName()).str());
}
#endif
args.push_back("-lldc-profile-rt");
}

// user libs
for (unsigned i = 0; i < global.params.libfiles->dim; i++) {
const char *p = static_cast<const char *>(global.params.libfiles->data[i]);
Expand Down Expand Up @@ -227,7 +243,11 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
switch (global.params.targetTriple->getOS()) {
case llvm::Triple::Linux:
addSoname = true;
if (!opts::disableLinkerStripDead) {
// Make sure we don't do --gc-sections when generating a profile-
// 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) {
args.push_back("-Wl,--gc-sections");
}
if (global.params.targetTriple->getEnvironment() == llvm::Triple::Android) {
Expand Down Expand Up @@ -587,6 +607,14 @@ static int linkObjToBinaryWin(bool sharedLib) {
args.push_back(p);
}

// Link with profile-rt library when generating an instrumented binary
// profile-rt depends on Phobos (MD5 hashing).
if (global.params.genInstrProf) {
args.push_back("ldc-profile-rt.lib");
// profile-rt depends on ws2_32 for symbol `gethostname`
args.push_back("ws2_32.lib");
}

// user libs
for (unsigned i = 0; i < global.params.libfiles->dim; i++) {
const char *p = static_cast<const char *>(global.params.libfiles->data[i]);
Expand Down
Loading