Skip to content
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
19 changes: 0 additions & 19 deletions bolt/include/bolt/Passes/SplitFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,6 @@
namespace llvm {
namespace bolt {

/// Strategy used to partition blocks into fragments.
enum SplitFunctionsStrategy : char {
/// Split each function into a hot and cold fragment using profiling
/// information.
Profile2 = 0,
/// Split each function into a hot, warm, and cold fragment using
/// profiling information.
CDSplit,
/// Split each function into a hot and cold fragment at a randomly chosen
/// split point (ignoring any available profiling information).
Random2,
/// Split each function into N fragments at a randomly chosen split points
/// (ignoring any available profiling information).
RandomN,
/// Split all basic blocks of each function into fragments such that each
/// fragment contains exactly a single basic block.
All
};

class SplitStrategy {
public:
using BlockIt = BinaryFunction::BasicBlockOrderType::iterator;
Expand Down
20 changes: 20 additions & 0 deletions bolt/include/bolt/Utils/CommandLineOpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ enum HeatmapModeKind {
HM_Optional // perf2bolt --heatmap
};

/// Strategy used to partition blocks into fragments.
enum SplitFunctionsStrategy : char {
/// Split each function into a hot and cold fragment using profiling
/// information.
Profile2 = 0,
/// Split each function into a hot, warm, and cold fragment using
/// profiling information.
CDSplit,
/// Split each function into a hot and cold fragment at a randomly chosen
/// split point (ignoring any available profiling information).
Random2,
/// Split each function into N fragments at a randomly chosen split points
/// (ignoring any available profiling information).
RandomN,
/// Split all basic blocks of each function into fragments such that each
/// fragment contains exactly a single basic block.
All
};

using HeatmapBlockSizes = std::vector<unsigned>;
struct HeatmapBlockSpecParser : public llvm::cl::parser<HeatmapBlockSizes> {
explicit HeatmapBlockSpecParser(llvm::cl::Option &O)
Expand Down Expand Up @@ -78,6 +97,7 @@ extern llvm::cl::opt<std::string> OutputFilename;
extern llvm::cl::opt<std::string> PerfData;
extern llvm::cl::opt<bool> PrintCacheMetrics;
extern llvm::cl::opt<bool> PrintSections;
extern llvm::cl::opt<SplitFunctionsStrategy> SplitStrategy;

// The format to use with -o in aggregation mode (perf2bolt)
enum ProfileFormatKind { PF_Fdata, PF_YAML };
Expand Down
4 changes: 4 additions & 0 deletions bolt/lib/Passes/LongJmp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,10 @@ void LongJmpPass::relaxLocalBranches(BinaryFunction &BF) {

Error LongJmpPass::runOnFunctions(BinaryContext &BC) {

assert((opts::CompactCodeModel ||
opts::SplitStrategy != opts::SplitFunctionsStrategy::CDSplit) &&
"LongJmp cannot work with functions split in more than two fragments");

if (opts::CompactCodeModel) {
BC.outs()
<< "BOLT-INFO: relaxing branches for compact code model (<128MB)\n";
Expand Down
35 changes: 6 additions & 29 deletions bolt/lib/Passes/SplitFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,29 +86,6 @@ static cl::opt<unsigned> SplitThreshold(
"increase after splitting."),
cl::init(0), cl::Hidden, cl::cat(BoltOptCategory));

static cl::opt<SplitFunctionsStrategy> SplitStrategy(
"split-strategy", cl::init(SplitFunctionsStrategy::Profile2),
cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",
"split each function into a hot and cold fragment "
"using profiling information")),
cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",
"split each function into a hot, warm, and cold "
"fragment using profiling information")),
cl::values(clEnumValN(
SplitFunctionsStrategy::Random2, "random2",
"split each function into a hot and cold fragment at a randomly chosen "
"split point (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::RandomN, "randomN",
"split each function into N fragments at a randomly chosen split "
"points (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::All, "all",
"split all basic blocks of each function into fragments such that each "
"fragment contains exactly a single basic block")),
cl::desc("strategy used to partition blocks into fragments"),
cl::cat(BoltOptCategory));

static cl::opt<double> CallScale(
"call-scale",
cl::desc("Call score scale coefficient (when --split-strategy=cdsplit)"),
Expand Down Expand Up @@ -724,14 +701,14 @@ Error SplitFunctions::runOnFunctions(BinaryContext &BC) {
// If split strategy is not CDSplit, then a second run of the pass is not
// needed after function reordering.
if (BC.HasFinalizedFunctionOrder &&
opts::SplitStrategy != SplitFunctionsStrategy::CDSplit)
opts::SplitStrategy != opts::SplitFunctionsStrategy::CDSplit)
return Error::success();

std::unique_ptr<SplitStrategy> Strategy;
bool ForceSequential = false;

switch (opts::SplitStrategy) {
case SplitFunctionsStrategy::CDSplit:
case opts::SplitFunctionsStrategy::CDSplit:
// CDSplit runs two splitting passes: hot-cold splitting (SplitPrfoile2)
// before function reordering and hot-warm-cold splitting
// (SplitCacheDirected) after function reordering.
Expand All @@ -742,21 +719,21 @@ Error SplitFunctions::runOnFunctions(BinaryContext &BC) {
opts::AggressiveSplitting = true;
BC.HasWarmSection = true;
break;
case SplitFunctionsStrategy::Profile2:
case opts::SplitFunctionsStrategy::Profile2:
Strategy = std::make_unique<SplitProfile2>();
break;
case SplitFunctionsStrategy::Random2:
case opts::SplitFunctionsStrategy::Random2:
Strategy = std::make_unique<SplitRandom2>();
// If we split functions randomly, we need to ensure that across runs with
// the same input, we generate random numbers for each function in the same
// order.
ForceSequential = true;
break;
case SplitFunctionsStrategy::RandomN:
case opts::SplitFunctionsStrategy::RandomN:
Strategy = std::make_unique<SplitRandomN>();
ForceSequential = true;
break;
case SplitFunctionsStrategy::All:
case opts::SplitFunctionsStrategy::All:
Strategy = std::make_unique<SplitAll>();
break;
}
Expand Down
7 changes: 7 additions & 0 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,13 @@ void RewriteInstance::adjustCommandLineOptions() {
opts::SplitEH = false;
}

if (BC->isAArch64() && !opts::CompactCodeModel &&
opts::SplitStrategy == opts::SplitFunctionsStrategy::CDSplit) {
BC->errs() << "BOLT-ERROR: CDSplit is not supported with LongJmp. Try with "
"'--compact-code-model'\n";
exit(1);
}

if (opts::StrictMode && !BC->HasRelocations) {
BC->errs()
<< "BOLT-WARNING: disabling strict mode (-strict) in non-relocation "
Expand Down
23 changes: 23 additions & 0 deletions bolt/lib/Utils/CommandLineOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,29 @@ ExecutionCountThreshold("execution-count-threshold",
cl::Hidden,
cl::cat(BoltOptCategory));

cl::opt<SplitFunctionsStrategy> SplitStrategy(
"split-strategy", cl::init(SplitFunctionsStrategy::Profile2),
cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",
"split each function into a hot and cold fragment "
"using profiling information")),
cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",
"split each function into a hot, warm, and cold "
"fragment using profiling information")),
cl::values(clEnumValN(
SplitFunctionsStrategy::Random2, "random2",
"split each function into a hot and cold fragment at a randomly chosen "
"split point (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::RandomN, "randomN",
"split each function into N fragments at a randomly chosen split "
"points (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::All, "all",
"split all basic blocks of each function into fragments such that each "
"fragment contains exactly a single basic block")),
cl::desc("strategy used to partition blocks into fragments"),
cl::cat(BoltOptCategory));

bool HeatmapBlockSpecParser::parse(cl::Option &O, StringRef ArgName,
StringRef Arg, HeatmapBlockSizes &Val) {
// Parses a human-readable suffix into a shift amount or nullopt on error.
Expand Down
7 changes: 5 additions & 2 deletions bolt/test/AArch64/unsupported-passes.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// REQUIRES: system-linux,asserts,target=aarch64{{.*}}

RUN: %clang %cflags %p/../Inputs/hello.c -o %t -Wl,-q
RUN: not llvm-bolt %t -o %t.bolt --frame-opt=all 2>&1 | FileCheck %s
RUN: not llvm-bolt %t -o %t.bolt --frame-opt=all 2>&1 | FileCheck %s --check-prefix=CHECK-FRAME-OPT

CHECK: BOLT-ERROR: frame-optimizer is supported only on X86
CHECK-FRAME-OPT: BOLT-ERROR: frame-optimizer is supported only on X86

RUN: not llvm-bolt %t -o %t.bolt split-functions --split-strategy=cdsplit 2>&1 | FileCheck %s --check-prefix=CHECK-CDSPLIT
CHECK-CDSPLIT: BOLT-ERROR: CDSplit is not supported with LongJmp. Try with '--compact-code-model'
Loading