#include "bolt/Passes/SplitFunctions.h"
#include "bolt/Core/BinaryBasicBlock.h"
#include "bolt/Core/BinaryFunction.h"
#include "bolt/Core/FunctionLayout.h"
#include "bolt/Core/ParallelUtilities.h"
#include "bolt/Utils/CommandLineOpts.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormatVariadic.h"
#include <algorithm>
#include <iterator>
#include <memory>
#include <numeric>
#include <random>
#include <vector>
#define DEBUG_TYPE …
usingnamespacellvm;
usingnamespacebolt;
namespace {
class DeprecatedSplitFunctionOptionParser : public cl::parser<bool> { … };
}
namespace opts {
extern cl::OptionCategory BoltOptCategory;
extern cl::opt<bool> SplitEH;
extern cl::opt<unsigned> ExecutionCountThreshold;
extern cl::opt<uint32_t> RandomSeed;
static cl::opt<bool> AggressiveSplitting(
"split-all-cold", cl::desc("outline as many cold basic blocks as possible"),
cl::cat(BoltOptCategory));
static cl::opt<unsigned> SplitAlignThreshold(
"split-align-threshold",
cl::desc("when deciding to split a function, apply this alignment "
"while doing the size comparison (see -split-threshold). "
"Default value: 2."),
cl::init(2),
cl::Hidden, cl::cat(BoltOptCategory));
static cl::opt<bool, false, DeprecatedSplitFunctionOptionParser>
SplitFunctions("split-functions",
cl::desc("split functions into fragments"),
cl::cat(BoltOptCategory));
static cl::opt<unsigned> SplitThreshold(
"split-threshold",
cl::desc("split function only if its main size is reduced by more than "
"given amount of bytes. Default value: 0, i.e. split iff the "
"size is reduced. Note that on some architectures the size can "
"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)"),
cl::init(0.95), cl::ReallyHidden, cl::cat(BoltOptCategory));
static cl::opt<double>
CallPower("call-power",
cl::desc("Call score power (when --split-strategy=cdsplit)"),
cl::init(0.05), cl::ReallyHidden, cl::cat(BoltOptCategory));
static cl::opt<double>
JumpPower("jump-power",
cl::desc("Jump score power (when --split-strategy=cdsplit)"),
cl::init(0.15), cl::ReallyHidden, cl::cat(BoltOptCategory));
}
namespace {
bool hasFullProfile(const BinaryFunction &BF) { … }
bool allBlocksCold(const BinaryFunction &BF) { … }
struct SplitProfile2 final : public SplitStrategy { … };
struct SplitCacheDirected final : public SplitStrategy { … };
struct SplitRandom2 final : public SplitStrategy { … };
struct SplitRandomN final : public SplitStrategy { … };
struct SplitAll final : public SplitStrategy { … };
}
namespace llvm {
namespace bolt {
bool SplitFunctions::shouldOptimize(const BinaryFunction &BF) const { … }
Error SplitFunctions::runOnFunctions(BinaryContext &BC) { … }
void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) { … }
SplitFunctions::TrampolineSetType
SplitFunctions::createEHTrampolines(BinaryFunction &BF) const { … }
SplitFunctions::BasicBlockOrderType SplitFunctions::mergeEHTrampolines(
BinaryFunction &BF, SplitFunctions::BasicBlockOrderType &Layout,
const SplitFunctions::TrampolineSetType &Trampolines) const { … }
}
}