LLVM 23.0.0git
MCSubtargetInfo.cpp
Go to the documentation of this file.
1//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===//
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
10#include "llvm/ADT/ArrayRef.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/ADT/Twine.h"
14#include "llvm/MC/MCSchedule.h"
15#include "llvm/Support/Format.h"
18#include <algorithm>
19#include <cassert>
20#include <cstring>
21#include <optional>
22
23using namespace llvm;
24
25/// Find KV in array using binary search.
26template <typename T>
27static const T *Find(StringRef S, ArrayRef<T> A) {
28 // Binary search the array
29 auto F = llvm::lower_bound(A, S);
30 // If not found then return NULL
31 if (F == A.end() || StringRef(F->key()) != S)
32 return nullptr;
33 // Return the found array item
34 return F;
35}
36
37/// For each feature that is (transitively) implied by this feature, set it.
38static void SetImpliedBits(FeatureBitset &Bits, FeatureBitset Implies,
39 ArrayRef<SubtargetFeatureKV> FeatureTable) {
40 // Transitively set all features implied. We don't assume that the features in
41 // Bits have already had their implied features set.
42 FeatureBitset NewBits = Implies;
43 while (Implies.any()) {
44 FeatureBitset Implied;
45 for (const SubtargetFeatureKV &FE : FeatureTable) {
46 if (Implies.test(FE.Value))
47 Implied |= FE.Implies.getAsBitset();
48 }
49
50 // Only continue for bits that haven't been set yet.
51 Implies = Implied & ~NewBits;
52 NewBits |= Implies;
53 }
54 Bits |= NewBits;
55}
56
57/// For each feature that (transitively) implies this feature, clear it.
58static
60 ArrayRef<SubtargetFeatureKV> FeatureTable) {
61 for (const SubtargetFeatureKV &FE : FeatureTable) {
62 if (FE.Implies.getAsBitset().test(Value)) {
63 Bits.reset(FE.Value);
64 ClearImpliedBits(Bits, FE.Value, FeatureTable);
65 }
66 }
67}
68
69static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
70 ArrayRef<SubtargetFeatureKV> FeatureTable) {
72 "Feature flags should start with '+' or '-'");
73
74 // Find feature in table.
75 const SubtargetFeatureKV *FeatureEntry =
76 Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
77 // If there is a match
78 if (FeatureEntry) {
79 // Enable/disable feature in bits
80 if (SubtargetFeatures::isEnabled(Feature)) {
81 Bits.set(FeatureEntry->Value);
82
83 // For each feature that this implies, set it.
84 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
85 } else {
86 Bits.reset(FeatureEntry->Value);
87
88 // For each feature that implies this, clear it.
89 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
90 }
91 } else {
92 errs() << "'" << Feature << "' is not a recognized feature for this target"
93 << " (ignoring feature)\n";
94 }
95}
96
97/// Return the length of the longest entry in the table.
99 size_t MaxLen = 0;
100 for (auto &I : Table)
101 MaxLen = std::max(MaxLen, std::strlen(I.key()));
102 return MaxLen;
103}
104
106 size_t MaxLen = 0;
107 for (StringRef I : Table)
108 MaxLen = std::max(MaxLen, I.size());
109 return MaxLen;
110}
111
112/// Display help for feature and mcpu choices.
113static void Help(ArrayRef<StringRef> CPUNames,
115 // the static variable ensures that the help information only gets
116 // printed once even though a target machine creates multiple subtargets
117 static bool PrintOnce = false;
118 if (PrintOnce) {
119 return;
120 }
121
122 // Determine the length of the longest CPU and Feature entries.
123 unsigned MaxCPULen = getLongestEntryLength(CPUNames);
124 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
125
126 // Print the CPU table.
127 errs() << "Available CPUs for this target:\n\n";
128 for (auto &CPUName : CPUNames) {
129 // Skip apple-latest, as that's only meant to be used in
130 // disassemblers/debuggers, and we don't want normal code to be built with
131 // it as an -mcpu=
132 if (CPUName == "apple-latest")
133 continue;
134 errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen,
135 CPUName.str().c_str(), CPUName.str().c_str());
136 }
137 errs() << '\n';
138
139 // Print the Feature table.
140 errs() << "Available features for this target:\n\n";
141 for (auto &Feature : FeatTable)
142 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.key(),
143 Feature.desc());
144 errs() << '\n';
145
146 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
147 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
148
149 PrintOnce = true;
150}
151
152/// Display help for mcpu choices only
153static void cpuHelp(ArrayRef<StringRef> CPUNames) {
154 // the static variable ensures that the help information only gets
155 // printed once even though a target machine creates multiple subtargets
156 static bool PrintOnce = false;
157 if (PrintOnce) {
158 return;
159 }
160
161 // Print the CPU table.
162 errs() << "Available CPUs for this target:\n\n";
163 for (auto &CPU : CPUNames) {
164 // Skip apple-latest, as that's only meant to be used in
165 // disassemblers/debuggers, and we don't want normal code to be built with
166 // it as an -mcpu=
167 if (CPU == "apple-latest")
168 continue;
169 errs() << "\t" << CPU << "\n";
170 }
171 errs() << '\n';
172
173 errs() << "Use -mcpu or -mtune to specify the target's processor.\n"
174 "For example, clang --target=aarch64-unknown-linux-gnu "
175 "-mcpu=cortex-a35\n";
176
177 PrintOnce = true;
178}
179
181 StringRef TuneCPU, StringRef FS,
182 ArrayRef<StringRef> ProcNames,
184 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
185 SubtargetFeatures Features(FS);
186
187 if (ProcDesc.empty() || ProcFeatures.empty())
188 return FeatureBitset();
189
190 assert(llvm::is_sorted(ProcDesc) && "CPU table is not sorted");
191 assert(llvm::is_sorted(ProcFeatures) && "CPU features table is not sorted");
192 // Resulting bits
193 FeatureBitset Bits;
194
195 // Check if help is needed
196 if (CPU == "help")
197 Help(ProcNames, ProcFeatures);
198
199 // Find CPU entry if CPU name is specified.
200 else if (!CPU.empty()) {
201 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
202
203 // If there is a match
204 if (CPUEntry) {
205 // Set the features implied by this CPU feature, if any.
206 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
207 } else {
208 errs() << "'" << CPU << "' is not a recognized processor for this target"
209 << " (ignoring processor)\n";
210 }
211 }
212
213 if (!TuneCPU.empty()) {
214 const SubtargetSubTypeKV *CPUEntry = Find(TuneCPU, ProcDesc);
215
216 // If there is a match
217 if (CPUEntry) {
218 // Set the features implied by this CPU feature, if any.
219 SetImpliedBits(Bits, CPUEntry->TuneImplies.getAsBitset(), ProcFeatures);
220 } else if (TuneCPU != CPU) {
221 errs() << "'" << TuneCPU << "' is not a recognized processor for this "
222 << "target (ignoring processor)\n";
223 }
224 }
225
226 // Iterate through each feature
227 for (const std::string &Feature : Features.getFeatures()) {
228 // Check for help
229 if (Feature == "+help")
230 Help(ProcNames, ProcFeatures);
231 else if (Feature == "+cpuhelp")
232 cpuHelp(ProcNames);
233 else
234 ApplyFeatureFlag(Bits, Feature, ProcFeatures);
235 }
236
237 return Bits;
238}
239
241 StringRef FS) {
242 FeatureBits =
243 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
244 FeatureString = std::string(FS);
245
246 if (!TuneCPU.empty())
247 CPUSchedModel = &getSchedModelForCPU(TuneCPU);
248 else
249 CPUSchedModel = &MCSchedModel::Default;
250}
251
253 StringRef FS) {
254 FeatureBits =
255 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
256 FeatureString = std::string(FS);
257}
258
260 const Triple &TT, StringRef C, StringRef TC, StringRef FS,
263 const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
264 const InstrStage *IS, const unsigned *OC, const unsigned *FP)
265 : TargetTriple(TT), CPU(std::string(C)), TuneCPU(std::string(TC)),
266 ProcNames(PN), ProcFeatures(PF), ProcDesc(PD), WriteProcResTable(WPR),
267 WriteLatencyTable(WL), ReadAdvanceTable(RA), Stages(IS),
268 OperandCycles(OC), ForwardingPaths(FP) {
269 InitMCProcessorInfo(CPU, TuneCPU, FS);
270}
271
273 FeatureBits.flip(FB);
274 return FeatureBits;
275}
276
278 FeatureBits ^= FB;
279 return FeatureBits;
280}
281
282const FeatureBitset &
284 SetImpliedBits(FeatureBits, FB, ProcFeatures);
285 return FeatureBits;
286}
287
288const FeatureBitset &
290 for (unsigned I = 0, E = FB.size(); I < E; I++) {
291 if (FB[I]) {
292 FeatureBits.reset(I);
293 ClearImpliedBits(FeatureBits, I, ProcFeatures);
294 }
295 }
296 return FeatureBits;
297}
298
300 // Find feature in table.
301 const SubtargetFeatureKV *FeatureEntry =
302 Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
303 // If there is a match
304 if (FeatureEntry) {
305 if (FeatureBits.test(FeatureEntry->Value)) {
306 FeatureBits.reset(FeatureEntry->Value);
307 // For each feature that implies this, clear it.
308 ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
309 } else {
310 FeatureBits.set(FeatureEntry->Value);
311
312 // For each feature that this implies, set it.
313 SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
314 ProcFeatures);
315 }
316 } else {
317 errs() << "'" << Feature << "' is not a recognized feature for this target"
318 << " (ignoring feature)\n";
319 }
320
321 return FeatureBits;
322}
323
325 ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
326 return FeatureBits;
327}
328
331 return all_of(T.getFeatures(), [this](const std::string &F) {
332 assert(SubtargetFeatures::hasFlag(F) &&
333 "Feature flags should start with '+' or '-'");
334 const SubtargetFeatureKV *FeatureEntry =
335 Find(SubtargetFeatures::StripFlag(F), ProcFeatures);
336 if (!FeatureEntry) {
337 reportFatalInternalError(Twine("'") + F +
338 "' is not a recognized feature for this target");
339 }
340
341 return FeatureBits.test(FeatureEntry->Value) ==
343 });
344}
345
346static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits,
347 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
348 bool ShouldBeEnabled = true;
349 if (!Feature.consume_front("+") && Feature.consume_front("-"))
350 ShouldBeEnabled = false;
351
352 const SubtargetFeatureKV *FeatureEntry = Find(Feature, ProcFeatures);
353 if (!FeatureEntry) {
354 reportFatalInternalError(Twine("'") + Feature +
355 "' is not a recognized feature for this target");
356 }
357
358 return FeatureBits.test(FeatureEntry->Value) == ShouldBeEnabled;
359}
360
361namespace {
362class FeatureExpressionParser {
363 StringRef Expr;
364 const FeatureBitset &FeatureBits;
365 ArrayRef<SubtargetFeatureKV> ProcFeatures;
366 size_t Pos = 0;
367
368public:
369 FeatureExpressionParser(StringRef Expr, const FeatureBitset &FeatureBits,
370 ArrayRef<SubtargetFeatureKV> ProcFeatures)
371 : Expr(Expr), FeatureBits(FeatureBits), ProcFeatures(ProcFeatures) {}
372
373 bool parse() {
374 bool Result = parseOr();
375 if (Pos != Expr.size())
376 reportFatalInternalError("malformed target feature expression");
377 return Result;
378 }
379
380private:
381 bool consume(char C) {
382 if (Pos == Expr.size() || Expr[Pos] != C)
383 return false;
384 ++Pos;
385 return true;
386 }
387
388 bool parseOr() {
389 bool Result = parseAnd();
390 while (consume('|')) {
391 bool RHS = parseAnd();
392 Result |= RHS;
393 }
394 return Result;
395 }
396
397 bool parseAnd() {
398 bool Result = parsePrimary();
399 while (consume(',')) {
400 bool RHS = parsePrimary();
401 Result &= RHS;
402 }
403 return Result;
404 }
405
406 bool parsePrimary() {
407 if (consume('(')) {
408 bool Result = parseOr();
409 if (!consume(')'))
410 reportFatalInternalError("malformed target feature expression");
411 return Result;
412 }
413
414 size_t Start = Pos;
415 Pos = Expr.find_first_of(",|()", Pos);
416 if (Pos == StringRef::npos)
417 Pos = Expr.size();
418
419 if (Start == Pos)
420 reportFatalInternalError("malformed target feature expression");
421
422 return hasFeature(Expr.slice(Start, Pos), FeatureBits, ProcFeatures);
423 }
424};
425} // namespace
426
428 if (FeatureExpr.empty())
429 return true;
430 if (FeatureExpr.contains(' ')) {
432 "spaces are not allowed in target feature expressions");
433 }
434 FeatureExpressionParser Parser(FeatureExpr, FeatureBits, ProcFeatures);
435 return Parser.parse();
436}
437
439 assert(llvm::is_sorted(ProcDesc) &&
440 "Processor machine model table is not sorted");
441
442 // Find entry
443 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
444
445 if (!CPUEntry) {
446 if (CPU != "help") // Don't error if the user asked for help.
447 errs() << "'" << CPU
448 << "' is not a recognized processor for this target"
449 << " (ignoring processor)\n";
451 }
452 assert(CPUEntry->schedModel() && "Missing processor SchedModel value");
453 return *CPUEntry->schedModel();
454}
455
458 const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
459 return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
460}
461
463 InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
464 ForwardingPaths);
465}
466
467std::vector<const SubtargetFeatureKV *>
469 std::vector<const SubtargetFeatureKV *> EnabledFeatures;
470 for (const SubtargetFeatureKV &FeatureKV : ProcFeatures)
471 if (FeatureBits.test(FeatureKV.Value))
472 EnabledFeatures.push_back(&FeatureKV);
473 return EnabledFeatures;
474}
475
476std::optional<unsigned> MCSubtargetInfo::getCacheSize(unsigned Level) const {
477 return std::nullopt;
478}
479
480std::optional<unsigned>
482 return std::nullopt;
483}
484
485std::optional<unsigned>
487 return std::nullopt;
488}
489
491 return 0;
492}
493
495 return UINT_MAX;
496}
497
499 return false;
500}
501
502unsigned MCSubtargetInfo::getMinPrefetchStride(unsigned NumMemAccesses,
503 unsigned NumStridedMemAccesses,
504 unsigned NumPrefetches,
505 bool HasCall) const {
506 return 1;
507}
508
510 return !AS;
511}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static llvm::Error parse(GsymDataExtractor &Data, uint64_t BaseAddr, LineEntryCallback const &Callback)
Definition LineTable.cpp:54
static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, ArrayRef< SubtargetFeatureKV > FeatureTable)
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
static void Help(ArrayRef< StringRef > CPUNames, ArrayRef< SubtargetFeatureKV > FeatTable)
Display help for feature and mcpu choices.
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
static void cpuHelp(ArrayRef< StringRef > CPUNames)
Display help for mcpu choices only.
static size_t getLongestEntryLength(ArrayRef< SubtargetFeatureKV > Table)
Return the length of the longest entry in the table.
static void SetImpliedBits(FeatureBitset &Bits, FeatureBitset Implies, ArrayRef< SubtargetFeatureKV > FeatureTable)
For each feature that is (transitively) implied by this feature, set it.
static void ClearImpliedBits(FeatureBitset &Bits, unsigned Value, ArrayRef< SubtargetFeatureKV > FeatureTable)
For each feature that (transitively) implies this feature, clear it.
static FeatureBitset getFeatures(MCSubtargetInfo &STI, StringRef CPU, StringRef TuneCPU, StringRef FS, ArrayRef< StringRef > ProcNames, ArrayRef< SubtargetSubTypeKV > ProcDesc, ArrayRef< SubtargetFeatureKV > ProcFeatures)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
SI optimize exec mask operations pre RA
Value * RHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
const FeatureBitset & getAsBitset() const
Container class for subtarget features.
constexpr bool test(unsigned I) const
constexpr FeatureBitset & flip(unsigned I)
constexpr size_t size() const
Itinerary data supplied by a subtarget to be used by a target.
Generic base class for all target subtargets.
virtual unsigned getCacheLineSize() const
Return the target cache line size in bytes.
bool checkFeatures(StringRef FS) const
Check whether the subtarget features are enabled/disabled as per the provided string,...
virtual std::optional< unsigned > getCacheSize(unsigned Level) const
Return the cache size in bytes for the given level of cache.
virtual bool shouldPrefetchAddressSpace(unsigned AS) const
const MCSchedModel & getSchedModelForCPU(StringRef CPU) const
Get the machine model of a CPU.
std::vector< const SubtargetFeatureKV * > getEnabledProcessorFeatures() const
Return the list of processor features currently enabled.
virtual unsigned getMinPrefetchStride(unsigned NumMemAccesses, unsigned NumStridedMemAccesses, unsigned NumPrefetches, bool HasCall) const
Return the minimum stride necessary to trigger software prefetching.
virtual bool enableWritePrefetching() const
virtual unsigned getMaxPrefetchIterationsAhead() const
Return the maximum prefetch distance in terms of loop iterations.
const FeatureBitset & ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
virtual unsigned getPrefetchDistance() const
Return the preferred prefetch distance in terms of instructions.
virtual std::optional< unsigned > getCacheAssociativity(unsigned Level) const
Return the cache associatvity for the given level of cache.
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const
Get scheduling itinerary of a CPU.
const FeatureBitset & ApplyFeatureFlag(StringRef FS)
Apply a feature flag and return the re-computed feature bits, including all feature bits implied by t...
void setDefaultFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS)
Set the features to the default for the given CPU and TuneCPU, with ano appended feature string.
void InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU, StringRef FS)
Initialize the scheduling model and feature bits.
const FeatureBitset & ClearFeatureBitsTransitively(const FeatureBitset &FB)
bool checkFeatureExpression(StringRef FeatureExpr) const
Check whether the current subtarget satisfies a target feature expression.
void initInstrItins(InstrItineraryData &InstrItins) const
Initialize an InstrItineraryData instance.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
const FeatureBitset & SetFeatureBitsTransitively(const FeatureBitset &FB)
Set/clear additional feature bits, including all other bits they imply.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static constexpr size_t npos
Definition StringRef.h:58
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition StringRef.h:720
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Definition StringRef.h:396
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
Manages the enabling and disabling of subtarget specific features.
const std::vector< std::string > & getFeatures() const
Returns the vector of individual subtarget features.
static bool hasFlag(StringRef Feature)
Determine if a feature has a flag; '+' or '-'.
static StringRef StripFlag(StringRef Feature)
Return string stripped of flag.
static bool isEnabled(StringRef Feature)
Return true if enable flag; '+'.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
Definition STLExtras.h:1970
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:94
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2052
ArrayRef(const T &OneElt) -> ArrayRef< T >
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860
These values represent a non-pipelined step in the execution of an instruction.
Specify the number of cycles allowed after instruction issue before a particular use operand reads it...
Definition MCSchedule.h:114
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:264
static LLVM_ABI const MCSchedModel Default
Returns the default initialized model.
Definition MCSchedule.h:435
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition MCSchedule.h:97
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition MCSchedule.h:74
Used to provide key value pairs for feature and CPU bit flags.
unsigned Value
K-V integer value.
FeatureBitArray Implies
K-V bit mask.
Used to provide key value pairs for feature and CPU bit flags.
FeatureBitArray Implies
K-V bit mask.
FeatureBitArray TuneImplies
K-V bit mask.
const MCSchedModel * schedModel() const