322 lines · cpp
1//===- bolt/Utils/CommandLineOpts.cpp - BOLT CLI options ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// BOLT CLI options10//11//===----------------------------------------------------------------------===//12 13#include "bolt/Utils/CommandLineOpts.h"14#include "VCSVersion.inc"15#include "llvm/Support/Regex.h"16 17using namespace llvm;18 19namespace llvm {20namespace bolt {21const char *BoltRevision =22#ifdef BOLT_REVISION23 BOLT_REVISION;24#else25 "<unknown>";26#endif27}28}29 30namespace opts {31 32HeatmapModeKind HeatmapMode = HM_None;33bool BinaryAnalysisMode = false;34 35cl::OptionCategory BoltCategory("BOLT generic options");36cl::OptionCategory BoltDiffCategory("BOLTDIFF generic options");37cl::OptionCategory BoltOptCategory("BOLT optimization options");38cl::OptionCategory BoltRelocCategory("BOLT options in relocation mode");39cl::OptionCategory BoltOutputCategory("Output options");40cl::OptionCategory AggregatorCategory("Data aggregation options");41cl::OptionCategory BoltInstrCategory("BOLT instrumentation options");42cl::OptionCategory HeatmapCategory("Heatmap options");43cl::OptionCategory BinaryAnalysisCategory("BinaryAnalysis options");44 45cl::opt<unsigned> AlignText("align-text",46 cl::desc("alignment of .text section"), cl::Hidden,47 cl::cat(BoltCategory));48 49cl::opt<unsigned> AlignFunctions(50 "align-functions",51 cl::desc("align functions at a given value (relocation mode)"),52 cl::init(64), cl::cat(BoltOptCategory));53 54cl::opt<bool>55AggregateOnly("aggregate-only",56 cl::desc("exit after writing aggregated data file"),57 cl::Hidden,58 cl::cat(AggregatorCategory));59 60cl::opt<unsigned>61 BucketsPerLine("line-size",62 cl::desc("number of entries per line (default 256)"),63 cl::init(256), cl::Optional, cl::cat(HeatmapCategory));64 65cl::opt<bool>66 CompactCodeModel("compact-code-model",67 cl::desc("generate code for binaries <128MB on AArch64"),68 cl::init(false), cl::cat(BoltCategory));69 70cl::opt<bool>71DiffOnly("diff-only",72 cl::desc("stop processing once we have enough to compare two binaries"),73 cl::Hidden,74 cl::cat(BoltDiffCategory));75 76cl::opt<bool>77EnableBAT("enable-bat",78 cl::desc("write BOLT Address Translation tables"),79 cl::init(false),80 cl::ZeroOrMore,81 cl::cat(BoltCategory));82 83cl::opt<bool> EqualizeBBCounts(84 "equalize-bb-counts",85 cl::desc("use same count for BBs that should have equivalent count (used "86 "in non-LBR and shrink wrapping)"),87 cl::ZeroOrMore, cl::init(false), cl::Hidden, cl::cat(BoltOptCategory));88 89llvm::cl::opt<bool> ForcePatch(90 "force-patch",91 llvm::cl::desc("force patching of original entry points to ensure "92 "execution follows only the new/optimized code."),93 llvm::cl::Hidden, llvm::cl::cat(BoltCategory));94 95cl::opt<bool> RemoveSymtab("remove-symtab", cl::desc("Remove .symtab section"),96 cl::cat(BoltCategory));97 98cl::opt<unsigned>99ExecutionCountThreshold("execution-count-threshold",100 cl::desc("perform profiling accuracy-sensitive optimizations only if "101 "function execution count >= the threshold (default: 0)"),102 cl::init(0),103 cl::ZeroOrMore,104 cl::Hidden,105 cl::cat(BoltOptCategory));106 107cl::opt<SplitFunctionsStrategy> SplitStrategy(108 "split-strategy", cl::init(SplitFunctionsStrategy::Profile2),109 cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",110 "split each function into a hot and cold fragment "111 "using profiling information")),112 cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",113 "split each function into a hot, warm, and cold "114 "fragment using profiling information")),115 cl::values(clEnumValN(116 SplitFunctionsStrategy::Random2, "random2",117 "split each function into a hot and cold fragment at a randomly chosen "118 "split point (ignoring any available profiling information)")),119 cl::values(clEnumValN(120 SplitFunctionsStrategy::RandomN, "randomN",121 "split each function into N fragments at a randomly chosen split "122 "points (ignoring any available profiling information)")),123 cl::values(clEnumValN(124 SplitFunctionsStrategy::All, "all",125 "split all basic blocks of each function into fragments such that each "126 "fragment contains exactly a single basic block")),127 cl::desc("strategy used to partition blocks into fragments"),128 cl::cat(BoltOptCategory));129 130bool HeatmapBlockSpecParser::parse(cl::Option &O, StringRef ArgName,131 StringRef Arg, HeatmapBlockSizes &Val) {132 // Parses a human-readable suffix into a shift amount or nullopt on error.133 auto parseSuffix = [](StringRef Suffix) -> std::optional<unsigned> {134 if (Suffix.empty())135 return 0;136 if (!Regex{"^[kKmMgG]i?[bB]?$"}.match(Suffix))137 return std::nullopt;138 // clang-format off139 switch (Suffix.front()) {140 case 'k': case 'K': return 10;141 case 'm': case 'M': return 20;142 case 'g': case 'G': return 30;143 }144 // clang-format on145 llvm_unreachable("Unexpected suffix");146 };147 148 SmallVector<StringRef> Sizes;149 Arg.split(Sizes, ',');150 unsigned PreviousSize = 0;151 for (StringRef Size : Sizes) {152 StringRef OrigSize = Size;153 unsigned &SizeVal = Val.emplace_back(0);154 if (Size.consumeInteger(10, SizeVal)) {155 O.error("'" + OrigSize + "' value can't be parsed as an integer");156 return true;157 }158 if (std::optional<unsigned> ShiftAmt = parseSuffix(Size)) {159 SizeVal <<= *ShiftAmt;160 } else {161 O.error("'" + Size + "' value can't be parsed as a suffix");162 return true;163 }164 if (SizeVal <= PreviousSize || (PreviousSize && SizeVal % PreviousSize)) {165 O.error("'" + OrigSize + "' must be a multiple of previous value");166 return true;167 }168 PreviousSize = SizeVal;169 }170 return false;171}172 173cl::opt<opts::HeatmapBlockSizes, false, opts::HeatmapBlockSpecParser>174 HeatmapBlock(175 "block-size", cl::value_desc("initial_size{,zoom-out_size,...}"),176 cl::desc("heatmap bucket size, optionally followed by zoom-out sizes "177 "for coarse-grained heatmaps (default 64B, 4K, 256K)."),178 cl::init(HeatmapBlockSizes{/*Initial*/ 64, /*Zoom-out*/ 4096, 262144}),179 cl::cat(HeatmapCategory));180 181cl::opt<unsigned long long> HeatmapMaxAddress(182 "max-address", cl::init(0xffffffff),183 cl::desc("maximum address considered valid for heatmap (default 4GB)"),184 cl::Optional, cl::cat(HeatmapCategory));185 186cl::opt<unsigned long long> HeatmapMinAddress(187 "min-address", cl::init(0x0),188 cl::desc("minimum address considered valid for heatmap (default 0)"),189 cl::Optional, cl::cat(HeatmapCategory));190 191cl::opt<bool> HeatmapPrintMappings(192 "print-mappings", cl::init(false),193 cl::desc("print mappings in the legend, between characters/blocks and text "194 "sections (default false)"),195 cl::Optional, cl::cat(HeatmapCategory));196 197cl::opt<std::string> HeatmapOutput("heatmap",198 cl::desc("print heatmap to a given file"),199 cl::Optional, cl::cat(HeatmapCategory));200 201cl::opt<bool> HotData("hot-data",202 cl::desc("hot data symbols support (relocation mode)"),203 cl::cat(BoltCategory));204 205cl::opt<bool> HotFunctionsAtEnd(206 "hot-functions-at-end",207 cl::desc(208 "if reorder-functions is used, order functions putting hottest last"),209 cl::cat(BoltCategory));210 211cl::opt<bool> HotText(212 "hot-text",213 cl::desc(214 "Generate hot text symbols. Apply this option to a precompiled binary "215 "that manually calls into hugify, such that at runtime hugify call "216 "will put hot code into 2M pages. This requires relocation."),217 cl::ZeroOrMore, cl::cat(BoltCategory));218 219cl::opt<bool>220 Instrument("instrument",221 cl::desc("instrument code to generate accurate profile data"),222 cl::cat(BoltOptCategory));223 224cl::opt<bool> Lite("lite", cl::desc("skip processing of cold functions"),225 cl::cat(BoltCategory));226 227cl::opt<std::string>228OutputFilename("o",229 cl::desc("<output file>"),230 cl::Optional,231 cl::cat(BoltOutputCategory));232 233cl::opt<std::string> PerfData("perfdata", cl::desc("<data file>"), cl::Optional,234 cl::cat(AggregatorCategory),235 cl::sub(cl::SubCommand::getAll()));236 237static cl::alias238PerfDataA("p",239 cl::desc("alias for -perfdata"),240 cl::aliasopt(PerfData),241 cl::cat(AggregatorCategory));242 243cl::opt<bool> PrintCacheMetrics(244 "print-cache-metrics",245 cl::desc("calculate and print various metrics for instruction cache"),246 cl::cat(BoltOptCategory));247 248cl::list<std::string> PrintOnly("print-only", cl::CommaSeparated,249 cl::desc("list of functions to print"),250 cl::value_desc("func1,func2,func3,..."),251 cl::Hidden, cl::cat(BoltCategory));252 253cl::opt<std::string>254 PrintOnlyFile("print-only-file",255 cl::desc("file with list of functions to print"), cl::Hidden,256 cl::cat(BoltCategory));257 258cl::opt<bool> PrintSections("print-sections",259 cl::desc("print all registered sections"),260 cl::Hidden, cl::cat(BoltCategory));261 262cl::opt<ProfileFormatKind> ProfileFormat(263 "profile-format",264 cl::desc(265 "format to dump profile output in aggregation mode, default is fdata"),266 cl::init(PF_Fdata),267 cl::values(clEnumValN(PF_Fdata, "fdata", "offset-based plaintext format"),268 clEnumValN(PF_YAML, "yaml", "dense YAML representation")),269 cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory));270 271cl::opt<std::string> SaveProfile("w",272 cl::desc("save recorded profile to a file"),273 cl::cat(BoltOutputCategory));274 275cl::opt<bool> ShowDensity("show-density",276 cl::desc("show profile density details"),277 cl::Optional, cl::cat(AggregatorCategory));278 279cl::opt<bool> SplitEH("split-eh", cl::desc("split C++ exception handling code"),280 cl::Hidden, cl::cat(BoltOptCategory));281 282cl::opt<bool>283 StrictMode("strict",284 cl::desc("trust the input to be from a well-formed source"),285 286 cl::cat(BoltCategory));287 288cl::opt<bool> TimeOpts("time-opts",289 cl::desc("print time spent in each optimization"),290 cl::cat(BoltOptCategory));291 292cl::opt<bool> TimeRewrite("time-rewrite",293 cl::desc("print time spent in rewriting passes"),294 cl::Hidden, cl::cat(BoltCategory));295 296cl::opt<bool> UseOldText(297 "use-old-text",298 cl::desc("reuse space in old .text if possible (relocation mode)"),299 cl::cat(BoltCategory));300 301cl::opt<bool> UpdateDebugSections(302 "update-debug-sections",303 cl::desc("update DWARF debug sections of the executable"),304 cl::cat(BoltCategory));305 306cl::opt<unsigned>307 Verbosity("v", cl::desc("set verbosity level for diagnostic output"),308 cl::init(0), cl::ZeroOrMore, cl::cat(BoltCategory),309 cl::sub(cl::SubCommand::getAll()));310 311bool processAllFunctions() {312 if (opts::AggregateOnly)313 return false;314 315 if (UseOldText || StrictMode)316 return true;317 318 return false;319}320 321} // namespace opts322