[BOLT] Organize options in categories for pretty printing (near NFC).

Summary:
Each BOLT-specific option now belongs to BoltCategory or BoltOptCategory.

Use alphabetical order for options in source code (does not affect
output).

The result is a cleaner output of "llvm-bolt -help" which does not
include any unrelated llvm options and is close to the following:

.....

BOLT generic options:

  -data=<string>                                       - <data file>
  -dyno-stats                                          - print execution info based on profile
  -hot-text                                            - hot text symbols support (relocation mode)
  -o=<string>                                          - <output file>
  -relocs                                              - relocation mode - use relocations to move functions in the binary
  -update-debug-sections                               - update DWARF debug sections of the executable
  -use-gnu-stack                                       - use GNU_STACK program header for new segment (workaround for issues with strip/objcopy)
  -use-old-text                                        - re-use space in old .text if possible (relocation mode)
  -v=<uint>                                            - set verbosity level for diagnostic output

BOLT optimization options:

  -align-blocks                                        - try to align BBs inserting nops
  -align-functions=<uint>                              - align functions at a given value (relocation mode)
  -align-functions-max-bytes=<uint>                    - maximum number of bytes to use to align functions
  -boost-macroops                                      - try to boost macro-op fusions by avoiding the cache-line boundary
  -eliminate-unreachable                               - eliminate unreachable code
  -frame-opt                                           - optimize stack frame accesses
  ......

(cherry picked from FBD4793684)
This commit is contained in:
Maksim Panchenko 2017-03-28 14:40:20 -07:00
parent d5a0264a9e
commit 0bde796e50
10 changed files with 700 additions and 561 deletions

View File

@ -24,12 +24,15 @@ using namespace bolt;
namespace opts {
extern cl::OptionCategory BoltCategory;
extern cl::opt<bool> Relocs;
static cl::opt<bool>
PrintDebugInfo("print-debug-info",
cl::desc("print debug info when printing functions"),
cl::Hidden);
cl::desc("print debug info when printing functions"),
cl::Hidden,
cl::cat(BoltCategory));
} // namespace opts

View File

@ -42,6 +42,10 @@ using namespace bolt;
namespace opts {
extern cl::OptionCategory BoltCategory;
extern cl::OptionCategory BoltOptCategory;
extern cl::OptionCategory BoltRelocCategory;
extern bool shouldProcess(const BinaryFunction &);
extern cl::opt<bool> PrintDynoStats;
@ -51,25 +55,30 @@ extern cl::opt<unsigned> Verbosity;
static cl::opt<bool>
AggressiveSplitting("split-all-cold",
cl::desc("outline as many cold basic blocks as possible"),
cl::ZeroOrMore);
cl::desc("outline as many cold basic blocks as possible"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
AlignBlocks("align-blocks",
cl::desc("try to align BBs inserting nops"),
cl::ZeroOrMore);
cl::desc("try to align BBs inserting nops"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
DotToolTipCode("dot-tooltip-code",
cl::desc("add basic block instructions as tool tips on nodes"),
cl::ZeroOrMore,
cl::Hidden);
cl::desc("add basic block instructions as tool tips on nodes"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<uint32_t>
DynoStatsScale("dyno-stats-scale",
cl::desc("scale to be applied while reporting dyno stats"),
cl::Optional,
cl::init(1));
cl::desc("scale to be applied while reporting dyno stats"),
cl::Optional,
cl::init(1),
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<JumpTableSupportLevel>
JumpTables("jump-tables",
@ -89,26 +98,30 @@ JumpTables("jump-tables",
"aggressively split jump tables section based on usage "
"of the tables"),
clEnumValEnd),
cl::ZeroOrMore);
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintJumpTables("print-jump-tables",
cl::desc("print jump tables"),
cl::ZeroOrMore,
cl::Hidden);
cl::desc("print jump tables"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
static cl::list<std::string>
PrintOnly("print-only",
cl::CommaSeparated,
cl::desc("list of functions to print"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden);
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
SplitEH("split-eh",
cl::desc("split C++ exception handling code (experimental)"),
cl::ZeroOrMore,
cl::Hidden);
cl::desc("split C++ exception handling code (experimental)"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
bool shouldPrint(const BinaryFunction &Function) {
if (PrintOnly.empty())

View File

@ -19,160 +19,186 @@ using namespace llvm;
namespace opts {
extern cl::OptionCategory BoltOptCategory;
extern cl::opt<bool> PrintAll;
extern cl::opt<bool> DumpDotAll;
extern cl::opt<bool> DynoStatsAll;
llvm::cl::opt<bool> TimeOpts("time-opts",
cl::desc("print time spent in each optimization"),
cl::init(false), cl::ZeroOrMore);
static llvm::cl::opt<bool>
VerifyCFG("verify-cfg",
cl::desc("verify the CFG after every pass"),
cl::init(false),
cl::Hidden,
cl::ZeroOrMore);
static cl::opt<bool>
EliminateUnreachable("eliminate-unreachable",
cl::desc("eliminate unreachable code"),
cl::init(true),
cl::ZeroOrMore);
static cl::opt<bool>
OptimizeBodylessFunctions(
"optimize-bodyless-functions",
cl::desc("optimize functions that just do a tail call"),
cl::ZeroOrMore);
cl::desc("eliminate unreachable code"),
cl::init(true),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
IndirectCallPromotion("indirect-call-promotion",
cl::desc("indirect call promotion"),
cl::ZeroOrMore);
cl::desc("indirect call promotion"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
InlineSmallFunctions(
"inline-small-functions",
cl::desc("inline functions with a single basic block"),
cl::ZeroOrMore);
static cl::opt<bool>
SimplifyConditionalTailCalls("simplify-conditional-tail-calls",
cl::desc("simplify conditional tail calls "
"by removing unnecessary jumps"),
cl::ZeroOrMore);
static cl::opt<bool>
Peepholes("peepholes",
cl::desc("run peephole optimizations"),
cl::ZeroOrMore);
static cl::opt<bool>
SimplifyRODataLoads("simplify-rodata-loads",
cl::desc("simplify loads from read-only sections by "
"replacing the memory operand with the "
"constant found in the corresponding "
"section"),
cl::ZeroOrMore);
static cl::opt<bool>
StripRepRet("strip-rep-ret",
cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"),
cl::init(true),
cl::ZeroOrMore);
static cl::opt<bool> OptimizeFrameAccesses(
"frame-opt", cl::desc("optimize stack frame accesses"), cl::ZeroOrMore);
static cl::opt<bool>
PrintReordered("print-reordered",
cl::desc("print functions after layout optimization"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintReorderedFunctions("print-reordered-functions",
cl::desc("print functions after clustering"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintOptimizeBodyless("print-optimize-bodyless",
cl::desc("print functions after bodyless optimization"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintAfterBranchFixup("print-after-branch-fixup",
cl::desc("print function after fixing local branches"),
cl::Hidden);
static cl::opt<bool>
PrintFinalized("print-finalized",
cl::desc("print function after CFG is finalized"),
cl::Hidden);
static cl::opt<bool>
PrintAfterLowering("print-after-lowering",
cl::desc("print function after instruction lowering"),
cl::Hidden);
static cl::opt<bool>
PrintUCE("print-uce",
cl::desc("print functions after unreachable code elimination"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintSCTC("print-sctc",
cl::desc("print functions after conditional tail call simplification"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintPeepholes("print-peepholes",
cl::desc("print functions after peephole optimization"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintSimplifyROLoads("print-simplify-rodata-loads",
cl::desc("print functions after simplification of RO data"
" loads"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintICF("print-icf",
cl::desc("print functions after ICF optimization"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintICP("print-icp",
cl::desc("print functions after indirect call promotion"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintInline("print-inline",
cl::desc("print functions after inlining optimization"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintFOP("print-fop",
cl::desc("print functions after frame optimizer pass"),
cl::ZeroOrMore,
cl::Hidden);
InlineSmallFunctions("inline-small-functions",
cl::desc("inline functions with a single basic block"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
NeverPrint("never-print",
cl::desc("never print"),
cl::init(false),
cl::ZeroOrMore,
cl::ReallyHidden);
cl::desc("never print"),
cl::init(false),
cl::ZeroOrMore,
cl::ReallyHidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
OptimizeBodylessFunctions("optimize-bodyless-functions",
cl::desc("optimize functions that just do a tail call"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
OptimizeFrameAccesses("frame-opt",
cl::desc("optimize stack frame accesses"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
Peepholes("peepholes",
cl::desc("run peephole optimizations"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintAfterBranchFixup("print-after-branch-fixup",
cl::desc("print function after fixing local branches"),
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintAfterLowering("print-after-lowering",
cl::desc("print function after instruction lowering"),
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintFOP("print-fop",
cl::desc("print functions after frame optimizer pass"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintFinalized("print-finalized",
cl::desc("print function after CFG is finalized"),
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintICF("print-icf",
cl::desc("print functions after ICF optimization"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintICP("print-icp",
cl::desc("print functions after indirect call promotion"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintInline("print-inline",
cl::desc("print functions after inlining optimization"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintOptimizeBodyless("print-optimize-bodyless",
cl::desc("print functions after bodyless optimization"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintPeepholes("print-peepholes",
cl::desc("print functions after peephole optimization"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintReordered("print-reordered",
cl::desc("print functions after layout optimization"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintReorderedFunctions("print-reordered-functions",
cl::desc("print functions after clustering"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintSCTC("print-sctc",
cl::desc("print functions after conditional tail call simplification"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintSimplifyROLoads("print-simplify-rodata-loads",
cl::desc("print functions after simplification of RO data loads"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
PrintUCE("print-uce",
cl::desc("print functions after unreachable code elimination"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
SimplifyConditionalTailCalls("simplify-conditional-tail-calls",
cl::desc("simplify conditional tail calls by removing unnecessary jumps"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
SimplifyRODataLoads("simplify-rodata-loads",
cl::desc("simplify loads from read-only sections by replacing the memory "
"operand with the constant found in the corresponding section"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
StripRepRet("strip-rep-ret",
cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"),
cl::init(true),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static llvm::cl::opt<bool>
TimeOpts("time-opts",
cl::desc("print time spent in each optimization"),
cl::init(false),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static llvm::cl::opt<bool>
VerifyCFG("verify-cfg",
cl::desc("verify the CFG after every pass"),
cl::init(false),
cl::Hidden,
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
} // namespace opts

View File

@ -37,13 +37,16 @@ using namespace llvm::dwarf;
namespace opts {
extern llvm::cl::OptionCategory BoltCategory;
extern llvm::cl::opt<unsigned> Verbosity;
static llvm::cl::opt<bool>
PrintExceptions("print-exceptions",
llvm::cl::desc("print exception handling data"),
llvm::cl::ZeroOrMore,
llvm::cl::Hidden);
llvm::cl::desc("print exception handling data"),
llvm::cl::ZeroOrMore,
llvm::cl::Hidden,
llvm::cl::cat(BoltCategory));
} // namespace opts

View File

@ -49,6 +49,8 @@ const char* dynoStatsOptDesc(const bolt::DynoStats::Category C) {
namespace opts {
extern cl::OptionCategory BoltOptCategory;
extern cl::opt<unsigned> Verbosity;
extern cl::opt<uint32_t> RandomSeed;
extern cl::opt<bool> Relocs;
@ -56,117 +58,174 @@ extern cl::opt<bolt::BinaryFunction::SplittingType> SplitFunctions;
extern bool shouldProcess(const bolt::BinaryFunction &Function);
extern size_t padFunction(const bolt::BinaryFunction &Function);
static cl::opt<unsigned>
IndirectCallPromotionThreshold(
"indirect-call-promotion-threshold",
cl::desc("threshold for optimizing a frequently taken indirect call"),
cl::init(90),
cl::ZeroOrMore);
static cl::opt<unsigned>
IndirectCallPromotionMispredictThreshold(
"indirect-call-promotion-mispredict-threshold",
cl::desc("misprediction threshold for skipping ICP on an "
"indirect call"),
cl::init(2),
cl::ZeroOrMore);
static cl::opt<bool>
IndirectCallPromotionUseMispredicts(
"indirect-call-promotion-use-mispredicts",
cl::desc("use misprediction frequency for determining whether or not ICP "
"should be applied at a callsite. The "
"-indirect-call-promotion-mispredict-threshold value will be used "
"by this heuristic"),
cl::ZeroOrMore);
static cl::opt<unsigned>
IndirectCallPromotionTopN(
"indirect-call-promotion-topn",
cl::desc("number of targets to consider when doing indirect "
"call promotion"),
cl::init(1),
cl::ZeroOrMore);
static cl::list<std::string>
ICPFuncsList("icp-funcs",
cl::CommaSeparated,
cl::desc("list of functions to enable ICP for"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden);
static cl::opt<bool>
ICPOldCodeSequence(
"icp-old-code-sequence",
cl::desc("use old code sequence for promoted calls"),
cl::init(false),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bolt::BinaryFunction::LayoutType>
ReorderBlocks(
"reorder-blocks",
cl::desc("change layout of basic blocks in a function"),
cl::init(bolt::BinaryFunction::LT_NONE),
cl::values(clEnumValN(bolt::BinaryFunction::LT_NONE,
"none",
"do not reorder basic blocks"),
clEnumValN(bolt::BinaryFunction::LT_REVERSE,
"reverse",
"layout blocks in reverse order"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE,
"normal",
"perform optimal layout based on profile"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE_BRANCH,
"branch-predictor",
"perform optimal layout prioritizing branch "
"predictions"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE_CACHE,
"cache",
"perform optimal layout prioritizing I-cache "
"behavior"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE_SHUFFLE,
"cluster-shuffle",
"perform random layout of clusters"),
clEnumValEnd),
cl::ZeroOrMore);
static cl::opt<bool>
MinBranchClusters(
"min-branch-clusters",
cl::desc("use a modified clustering algorithm geared towards "
"minimizing branches"),
cl::ZeroOrMore,
cl::Hidden);
static cl::list<bolt::DynoStats::Category>
PrintSortedBy(
"print-sorted-by",
cl::CommaSeparated,
cl::desc("print functions sorted by order of dyno stats"),
cl::value_desc("key1,key2,key3,..."),
cl::values(
#define D(name, ...) \
clEnumValN(bolt::DynoStats::name, \
dynoStatsOptName(bolt::DynoStats::name), \
dynoStatsOptDesc(bolt::DynoStats::name)),
DYNO_STATS
#undef D
clEnumValEnd),
cl::ZeroOrMore);
enum DynoStatsSortOrder : char {
Ascending,
Descending
};
static cl::opt<DynoStatsSortOrder>
DynoStatsSortOrderOpt(
"print-sorted-by-order",
cl::desc("use ascending or descending order when printing "
"functions ordered by dyno stats"),
cl::ZeroOrMore,
cl::init(DynoStatsSortOrder::Descending));
DynoStatsSortOrderOpt("print-sorted-by-order",
cl::desc("use ascending or descending order when printing functions "
"ordered by dyno stats"),
cl::ZeroOrMore,
cl::init(DynoStatsSortOrder::Descending),
cl::cat(BoltOptCategory));
static cl::opt<std::string>
FunctionOrderFile("function-order",
cl::desc("file containing an ordered list of functions to use for function "
"reordering"),
cl::cat(BoltOptCategory));
static cl::opt<bool>
ICF("icf",
cl::desc("fold functions with identical code"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
ICFUseDFS("icf-dfs",
cl::desc("use DFS ordering when using -icf option"),
cl::ReallyHidden,
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::list<std::string>
ICPFuncsList("icp-funcs",
cl::CommaSeparated,
cl::desc("list of functions to enable ICP for"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<bool>
ICPOldCodeSequence("icp-old-code-sequence",
cl::desc("use old code sequence for promoted calls"),
cl::init(false),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::opt<unsigned>
IndirectCallPromotionMispredictThreshold(
"indirect-call-promotion-mispredict-threshold",
cl::desc("misprediction threshold for skipping ICP on an "
"indirect call"),
cl::init(2),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<unsigned>
IndirectCallPromotionThreshold("indirect-call-promotion-threshold",
cl::desc("threshold for optimizing a frequently taken indirect call"),
cl::init(90),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<unsigned>
IndirectCallPromotionTopN("indirect-call-promotion-topn",
cl::desc("number of targets to consider when doing indirect "
"call promotion"),
cl::init(1),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
IndirectCallPromotionUseMispredicts("indirect-call-promotion-use-mispredicts",
cl::desc("use misprediction frequency for determining whether or not ICP "
"should be applied at a callsite. The "
"-indirect-call-promotion-mispredict-threshold value will be used "
"by this heuristic"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
MinBranchClusters("min-branch-clusters",
cl::desc("use a modified clustering algorithm geared towards minimizing "
"branches"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::list<bolt::DynoStats::Category>
PrintSortedBy("print-sorted-by",
cl::CommaSeparated,
cl::desc("print functions sorted by order of dyno stats"),
cl::value_desc("key1,key2,key3,..."),
cl::values(
#define D(name, ...) \
clEnumValN(bolt::DynoStats::name, \
dynoStatsOptName(bolt::DynoStats::name), \
dynoStatsOptDesc(bolt::DynoStats::name)),
DYNO_STATS
#undef D
clEnumValEnd),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bolt::BinaryFunction::LayoutType>
ReorderBlocks("reorder-blocks",
cl::desc("change layout of basic blocks in a function"),
cl::init(bolt::BinaryFunction::LT_NONE),
cl::values(
clEnumValN(bolt::BinaryFunction::LT_NONE,
"none",
"do not reorder basic blocks"),
clEnumValN(bolt::BinaryFunction::LT_REVERSE,
"reverse",
"layout blocks in reverse order"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE,
"normal",
"perform optimal layout based on profile"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE_BRANCH,
"branch-predictor",
"perform optimal layout prioritizing branch "
"predictions"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE_CACHE,
"cache",
"perform optimal layout prioritizing I-cache "
"behavior"),
clEnumValN(bolt::BinaryFunction::LT_OPTIMIZE_SHUFFLE,
"cluster-shuffle",
"perform random layout of clusters"),
clEnumValEnd),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
cl::opt<bolt::BinaryFunction::ReorderType>
ReorderFunctions("reorder-functions",
cl::desc("reorder and cluster functions (works only with relocations)"),
cl::init(bolt::BinaryFunction::RT_NONE),
cl::values(clEnumValN(bolt::BinaryFunction::RT_NONE,
"none",
"do not reorder functions"),
clEnumValN(bolt::BinaryFunction::RT_EXEC_COUNT,
"exec-count",
"order by execution count"),
clEnumValN(bolt::BinaryFunction::RT_HFSORT,
"hfsort",
"use hfsort algorithm"),
clEnumValN(bolt::BinaryFunction::RT_HFSORT_PLUS,
"hfsort+",
"use hfsort+ algorithm"),
clEnumValN(bolt::BinaryFunction::RT_PETTIS_HANSEN,
"pettis-hansen",
"use Pettis-Hansen algorithm"),
clEnumValN(bolt::BinaryFunction::RT_RANDOM,
"random",
"reorder functions randomly"),
clEnumValN(bolt::BinaryFunction::RT_USER,
"user",
"use function order specified by -function-order"),
clEnumValEnd),
cl::cat(BoltOptCategory));
static cl::opt<bool>
ReorderFunctionsUseHotSize("reorder-functions-use-hot-size",
cl::desc("use a function's hot size when doing clustering"),
cl::init(true),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
enum SctcModes : char {
SctcAlways,
@ -175,80 +234,27 @@ enum SctcModes : char {
};
static cl::opt<SctcModes>
SctcMode(
"sctc-mode",
cl::desc("mode for simplify conditional tail calls"),
cl::init(SctcHeuristic),
cl::values(clEnumValN(SctcAlways, "always", "always perform sctc"),
clEnumValN(SctcPreserveDirection,
"preserve",
"only perform sctc when branch direction is "
"preserved"),
clEnumValN(SctcHeuristic,
"heuristic",
"use branch prediction data to control sctc"),
clEnumValEnd),
cl::ZeroOrMore);
SctcMode("sctc-mode",
cl::desc("mode for simplify conditional tail calls"),
cl::init(SctcHeuristic),
cl::values(clEnumValN(SctcAlways, "always", "always perform sctc"),
clEnumValN(SctcPreserveDirection,
"preserve",
"only perform sctc when branch direction is "
"preserved"),
clEnumValN(SctcHeuristic,
"heuristic",
"use branch prediction data to control sctc"),
clEnumValEnd),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool>
IdenticalCodeFolding(
"icf",
cl::desc("fold functions with identical code"),
cl::ZeroOrMore);
static cl::opt<bool>
UseDFSForICF(
"icf-dfs",
cl::desc("use DFS ordering when using -icf option"),
cl::ReallyHidden,
cl::ZeroOrMore);
cl::opt<bolt::BinaryFunction::ReorderType>
ReorderFunctions(
"reorder-functions",
cl::desc("reorder and cluster functions (works only with relocations)"),
cl::init(bolt::BinaryFunction::RT_NONE),
cl::values(clEnumValN(bolt::BinaryFunction::RT_NONE,
"none",
"do not reorder functions"),
clEnumValN(bolt::BinaryFunction::RT_EXEC_COUNT,
"exec-count",
"order by execution count"),
clEnumValN(bolt::BinaryFunction::RT_HFSORT,
"hfsort",
"use hfsort algorithm"),
clEnumValN(bolt::BinaryFunction::RT_HFSORT_PLUS,
"hfsort+",
"use hfsort+ algorithm"),
clEnumValN(bolt::BinaryFunction::RT_PETTIS_HANSEN,
"pettis-hansen",
"use Pettis-Hansen algorithm"),
clEnumValN(bolt::BinaryFunction::RT_RANDOM,
"random",
"reorder functions randomly"),
clEnumValN(bolt::BinaryFunction::RT_USER,
"user",
"use function order specified by -function-order"),
clEnumValEnd));
static cl::opt<std::string>
FunctionOrderFile("function-order",
cl::desc("file containing an ordered list of functions to use"
" for function reordering"));
static cl::opt<bool>
ReorderFunctionsUseHotSize(
"reorder-functions-use-hot-size",
cl::desc("use a function's hot size when doing clustering"),
cl::init(true),
cl::ZeroOrMore);
static cl::opt<bool>
UseEdgeCounts(
"use-edge-counts",
cl::desc("use edge count data when doing clustering"),
cl::init(true),
cl::ZeroOrMore);
UseEdgeCounts("use-edge-counts",
cl::desc("use edge count data when doing clustering"),
cl::init(true),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
} // namespace opts
@ -848,7 +854,7 @@ void SimplifyRODataLoads::runOnFunctions(
void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC,
std::map<uint64_t, BinaryFunction> &BFs,
std::set<uint64_t> &) {
if (!opts::IdenticalCodeFolding)
if (!opts::ICF)
return;
const auto OriginalFunctionCount = BFs.size();
@ -856,7 +862,7 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC,
uint64_t NumJTFunctionsFolded = 0;
uint64_t BytesSavedEstimate = 0;
uint64_t CallsSavedEstimate = 0;
static bool UseDFS = opts::UseDFSForICF;
static bool UseDFS = opts::ICFUseDFS;
// This hash table is used to identify identical functions. It maps
// a function to a bucket of functions identical to it.

View File

@ -17,19 +17,23 @@
using namespace llvm;
namespace opts {
static cl::list<std::string>
ForceInlineFunctions("force-inline",
cl::CommaSeparated,
cl::desc("list of functions to always consider "
"for inlining"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden);
extern cl::OptionCategory BoltOptCategory;
static cl::opt<bool>
AggressiveInlining("aggressive-inlining",
cl::desc("perform aggressive inlining"),
cl::ZeroOrMore,
cl::Hidden);
cl::desc("perform aggressive inlining"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
static cl::list<std::string>
ForceInlineFunctions("force-inline",
cl::CommaSeparated,
cl::desc("list of functions to always consider for inlining"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden,
cl::cat(BoltOptCategory));
}

View File

@ -26,14 +26,22 @@ using namespace bolt;
namespace opts {
extern cl::OptionCategory BoltOptCategory;
static cl::opt<bool>
PrintClusters("print-clusters", cl::desc("print clusters"), cl::ZeroOrMore);
PrintClusters("print-clusters",
cl::desc("print clusters"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
cl::opt<uint32_t>
RandomSeed("bolt-seed",
cl::desc("seed for randomization"),
cl::init(42),
cl::ZeroOrMore);
cl::desc("seed for randomization"),
cl::init(42),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltOptCategory));
} // namespace opts

View File

@ -66,11 +66,232 @@ using namespace bolt;
namespace opts {
extern cl::OptionCategory BoltCategory;
extern cl::OptionCategory BoltOptCategory;
extern cl::opt<JumpTableSupportLevel> JumpTables;
extern cl::opt<BinaryFunction::ReorderType> ReorderFunctions;
static cl::opt<std::string>
OutputFilename("o", cl::desc("<output file>"), cl::Required);
OutputFilename("o",
cl::desc("<output file>"),
cl::Required,
cl::cat(BoltCategory));
static cl::opt<unsigned>
AlignFunctions("align-functions",
cl::desc("align functions at a given value (relocation mode)"),
cl::init(64),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<unsigned>
AlignFunctionsMaxBytes("align-functions-max-bytes",
cl::desc("maximum number of bytes to use to align functions"),
cl::init(7),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
cl::opt<bool>
AllowStripped("allow-stripped",
cl::desc("allow processing of stripped binaries"),
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
BoostMacroops("boost-macroops",
cl::desc("try to boost macro-op fusions by avoiding the cache-line boundary"),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::list<std::string>
BreakFunctionNames("break-funcs",
cl::CommaSeparated,
cl::desc("list of functions to core dump on (debugging)"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
DumpDotAll("dump-dot-all",
cl::desc("dump function CFGs to graphviz format after each stage"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
DumpEHFrame("dump-eh-frame",
cl::desc("dump parsed .eh_frame (debugging)"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
DynoStatsAll("dyno-stats-all",
cl::desc("print dyno stats after each stage"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
FixDebugInfoLargeFunctions("fix-debuginfo-large-functions",
cl::init(true),
cl::desc("do another pass if we encounter large functions, to correct their "
"debug info."),
cl::ZeroOrMore,
cl::ReallyHidden,
cl::cat(BoltCategory));
static cl::list<std::string>
FunctionNames("funcs",
cl::CommaSeparated,
cl::desc("list of functions to optimize"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<std::string>
FunctionNamesFile("funcs-file",
cl::desc("file with list of functions to optimize"),
cl::Hidden,
cl::cat(BoltCategory));
static cl::list<std::string>
FunctionPadSpec("pad-funcs",
cl::CommaSeparated,
cl::desc("list of functions to pad with amount of bytes"),
cl::value_desc("func1:pad1,func2:pad2,func3:pad3,..."),
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
HotText("hot-text",
cl::desc("hot text symbols support (relocation mode)"),
cl::ZeroOrMore,
cl::cat(BoltCategory));
static cl::opt<bool>
KeepTmp("keep-tmp",
cl::desc("preserve intermediate .o file"),
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
MarkFuncs("mark-funcs",
cl::desc("mark function boundaries with break instruction to make "
"sure we accidentally don't cross them"),
cl::ReallyHidden,
cl::ZeroOrMore,
cl::cat(BoltCategory));
static cl::opt<unsigned>
MaxFunctions("max-funcs",
cl::desc("maximum number of functions to overwrite"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
PrintAll("print-all",
cl::desc("print functions after each stage"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
PrintCFG("print-cfg",
cl::desc("print functions after CFG construction"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
PrintDisasm("print-disasm",
cl::desc("print function after disassembly"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
PrintDynoStats("dyno-stats",
cl::desc("print execution info based on profile"),
cl::cat(BoltCategory));
static cl::opt<bool>
PrintLoopInfo("print-loops",
cl::desc("print loop related information"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
Relocs("relocs",
cl::desc("relocation mode - use relocations to move functions in the binary"),
cl::ZeroOrMore,
cl::cat(BoltCategory));
static cl::list<std::string>
SkipFunctionNames("skip-funcs",
cl::CommaSeparated,
cl::desc("list of functions to skip"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<std::string>
SkipFunctionNamesFile("skip-funcs-file",
cl::desc("file with list of functions to skip"),
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<BinaryFunction::SplittingType>
SplitFunctions("split-functions",
cl::desc("split functions into hot and cold regions"),
cl::init(BinaryFunction::ST_NONE),
cl::values(clEnumValN(BinaryFunction::ST_NONE, "0",
"do not split any function"),
clEnumValN(BinaryFunction::ST_EH, "1",
"split all landing pads"),
clEnumValN(BinaryFunction::ST_LARGE, "2",
"also split if function too large to fit"),
clEnumValN(BinaryFunction::ST_ALL, "3",
"split all functions"),
clEnumValEnd),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<unsigned>
TopCalledLimit("top-called-limit",
cl::desc("maximum number of functions to print in top called "
"functions section"),
cl::init(100),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
TrapOldCode("trap-old-code",
cl::desc("insert traps in old function bodies (relocation mode)"),
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
UpdateDebugSections("update-debug-sections",
cl::desc("update DWARF debug sections of the executable"),
cl::ZeroOrMore,
cl::cat(BoltCategory));
static cl::opt<bool>
UseGnuStack("use-gnu-stack",
cl::desc("use GNU_STACK program header for new segment (workaround for "
"issues with strip/objcopy)"),
cl::ZeroOrMore,
cl::cat(BoltCategory));
cl::opt<bool>
UseOldText("use-old-text",
cl::desc("re-use space in old .text if possible (relocation mode)"),
cl::cat(BoltCategory));
// The default verbosity level (0) is pretty terse, level 1 is fairly
// verbose and usually prints some informational message for every
@ -85,181 +306,10 @@ OutputFilename("o", cl::desc("<output file>"), cl::Required);
// dbgs() for output within DEBUG().
cl::opt<unsigned>
Verbosity("v",
cl::desc("set verbosity level for diagnostic output"),
cl::init(0),
cl::ZeroOrMore);
static cl::opt<unsigned>
AlignFunctions("align-functions",
cl::desc("align functions at a given value"),
cl::init(64),
cl::ZeroOrMore);
static cl::opt<unsigned>
AlignFunctionsMaxBytes("align-functions-max-bytes",
cl::desc("maximum number of bytes to use to align functions"),
cl::init(7),
cl::ZeroOrMore);
static cl::list<std::string>
BreakFunctionNames("break-funcs",
cl::CommaSeparated,
cl::desc("list of functions to core dump on (debugging)"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden);
cl::opt<bool>
UseOldText("use-old-text",
cl::desc("re-use space in old .text if possible"),
cl::Hidden);
cl::opt<bool>
TrapOldCode("trap-old-code",
cl::desc("insert traps in old function bodies"),
cl::Hidden);
cl::opt<bool>
PrintDynoStats("dyno-stats",
cl::desc("print execution info based on profile"));
cl::opt<bool>
DynoStatsAll("dyno-stats-all", cl::desc("print dyno stats after each stage"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<unsigned>
TopCalledLimit("top-called-limit",
cl::desc("maximum number of functions to print in top called "
"functions section"),
cl::init(100),
cl::ZeroOrMore,
cl::Hidden);
cl::opt<bool>
HotText("hot-text",
cl::desc("hot text symbols support"),
cl::ZeroOrMore);
static cl::list<std::string>
FunctionNames("funcs",
cl::CommaSeparated,
cl::desc("list of functions to optimize"),
cl::value_desc("func1,func2,func3,..."));
static cl::opt<std::string>
FunctionNamesFile("funcs-file",
cl::desc("file with list of functions to optimize"));
cl::opt<bool>
Relocs("relocs",
cl::desc("relocation support (experimental)"),
cl::ZeroOrMore);
static cl::list<std::string>
FunctionPadSpec("pad-funcs",
cl::CommaSeparated,
cl::desc("list of functions to pad with amount of bytes"),
cl::value_desc("func1:pad1,func2:pad2,func3:pad3,..."));
static cl::list<std::string>
SkipFunctionNames("skip-funcs",
cl::CommaSeparated,
cl::desc("list of functions to skip"),
cl::value_desc("func1,func2,func3,..."));
static cl::opt<std::string>
SkipFunctionNamesFile("skip-funcs-file",
cl::desc("file with list of functions to skip"));
static cl::opt<bool>
MarkFuncs("mark-funcs",
cl::desc("mark function boundaries with break instruction to make "
"sure we accidentally don't cross them"),
cl::ReallyHidden,
cl::ZeroOrMore);
static cl::opt<unsigned>
MaxFunctions("max-funcs",
cl::desc("maximum # of functions to overwrite"),
cl::ZeroOrMore);
cl::opt<BinaryFunction::SplittingType>
SplitFunctions("split-functions",
cl::desc("split functions into hot and cold regions"),
cl::init(BinaryFunction::ST_NONE),
cl::values(clEnumValN(BinaryFunction::ST_NONE, "0",
"do not split any function"),
clEnumValN(BinaryFunction::ST_EH, "1",
"split all landing pads"),
clEnumValN(BinaryFunction::ST_LARGE, "2",
"also split if function too large to fit"),
clEnumValN(BinaryFunction::ST_ALL, "3",
"split all functions"),
clEnumValEnd),
cl::ZeroOrMore);
cl::opt<bool>
UpdateDebugSections("update-debug-sections",
cl::desc("update DWARF debug sections of the executable"),
cl::ZeroOrMore);
static cl::opt<bool>
FixDebugInfoLargeFunctions("fix-debuginfo-large-functions",
cl::init(true),
cl::desc("do another pass if we encounter large "
"functions, to correct their debug info."),
cl::ZeroOrMore,
cl::ReallyHidden);
static cl::opt<bool>
AlignBlocks("align-blocks",
cl::desc("try to align BBs inserting nops"),
cl::ZeroOrMore);
static cl::opt<bool>
UseGnuStack("use-gnu-stack",
cl::desc("use GNU_STACK program header for new segment"),
cl::ZeroOrMore);
static cl::opt<bool>
DumpEHFrame("dump-eh-frame", cl::desc("dump parsed .eh_frame (debugging)"),
cl::ZeroOrMore,
cl::Hidden);
cl::opt<bool>
PrintAll("print-all", cl::desc("print functions after each stage"),
cl::ZeroOrMore,
cl::Hidden);
cl::opt<bool>
DumpDotAll("dump-dot-all",
cl::desc("dump function CFGs to graphviz format after each stage"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintCFG("print-cfg", cl::desc("print functions after CFG construction"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintLoopInfo("print-loops", cl::desc("print loop related information"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
PrintDisasm("print-disasm", cl::desc("print function after disassembly"),
cl::ZeroOrMore,
cl::Hidden);
static cl::opt<bool>
KeepTmp("keep-tmp",
cl::desc("preserve intermediate .o file"),
cl::Hidden);
cl::opt<bool>
AllowStripped("allow-stripped",
cl::desc("allow processing of stripped binaries"),
cl::Hidden);
cl::desc("set verbosity level for diagnostic output"),
cl::init(0),
cl::ZeroOrMore,
cl::cat(BoltCategory));
// Check against lists of functions from options if we should
// optimize the function with a given name.

View File

@ -32,15 +32,32 @@ using namespace bolt;
namespace opts {
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<executable>"), cl::Required);
cl::OptionCategory BoltCategory("BOLT generic options");
cl::OptionCategory BoltOptCategory("BOLT optimization options");
cl::OptionCategory BoltRelocCategory("BOLT options in relocation mode");
static cl::opt<std::string>
InputDataFilename("data", cl::desc("<data file>"), cl::Optional);
static cl::OptionCategory *BoltCategories[] = {&BoltCategory,
&BoltOptCategory,
&BoltRelocCategory};
static cl::opt<bool>
DumpData("dump-data", cl::desc("dump parsed bolt data and exit (debugging)"),
cl::Hidden);
DumpData("dump-data",
cl::desc("dump parsed bolt data and exit (debugging)"),
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<std::string>
InputDataFilename("data",
cl::desc("<data file>"),
cl::Optional,
cl::cat(BoltCategory));
static cl::opt<std::string>
InputFilename(
cl::Positional,
cl::desc("<executable>"),
cl::Required,
cl::cat(BoltCategory));
} // namespace opts
@ -68,6 +85,8 @@ int main(int argc, char **argv) {
llvm::InitializeAllTargets();
llvm::InitializeAllAsmPrinters();
cl::HideUnrelatedOptions(makeArrayRef(opts::BoltCategories));
// Register the target printer for --version.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);

View File

@ -27,6 +27,8 @@ using namespace bolt;
namespace opts {
cl::OptionCategory MergeFdataCategory("merge-fdata options");
enum SortType : char {
ST_NONE,
ST_EXEC_COUNT, /// Sort based on function execution count.
@ -34,32 +36,35 @@ enum SortType : char {
};
static cl::list<std::string>
InputDataFilenames(cl::Positional,
cl::CommaSeparated,
cl::desc("<fdata1> [<fdata2>]..."),
cl::OneOrMore);
InputDataFilenames(
cl::Positional,
cl::CommaSeparated,
cl::desc("<fdata1> [<fdata2>]..."),
cl::OneOrMore,
cl::cat(MergeFdataCategory));
static cl::opt<SortType>
PrintFunctionList("print",
cl::desc("print the list of objects with count to stderr"),
cl::init(ST_NONE),
cl::values(clEnumValN(ST_NONE,
"none",
"do not print objects/functions"),
clEnumValN(ST_EXEC_COUNT,
"exec",
"print functions sorted by execution count"),
clEnumValN(ST_TOTAL_BRANCHES,
"branches",
"print functions sorted by total branch count"),
clEnumValEnd),
cl::cat(MergeFdataCategory));
static cl::opt<bool>
SuppressMergedDataOutput("q",
cl::desc("do not print merged data to stdout"),
cl::init(false),
cl::Optional);
static cl::opt<SortType>
PrintFunctionList(
"print",
cl::desc("print the list of objects with count to stderr"),
cl::init(ST_NONE),
cl::values(clEnumValN(ST_NONE,
"none",
"do not print objects/functions"),
clEnumValN(ST_EXEC_COUNT,
"exec",
"print functions sorted by execution count"),
clEnumValN(ST_TOTAL_BRANCHES,
"branches",
"print functions sorted by total branch count"),
clEnumValEnd));
cl::desc("do not print merged data to stdout"),
cl::init(false),
cl::Optional,
cl::cat(MergeFdataCategory));
} // namespace opts
@ -78,6 +83,8 @@ int main(int argc, char **argv) {
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::HideUnrelatedOptions(opts::MergeFdataCategory);
cl::ParseCommandLineOptions(argc, argv,
"merge fdata into a single file");