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