LLVM 22.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) return nullptr;
32 // Return the found array item
33 return F;
34}
35
36/// For each feature that is (transitively) implied by this feature, set it.
37static
38void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
39 ArrayRef<SubtargetFeatureKV> FeatureTable) {
40 // OR the Implies bits in outside the loop. This allows the Implies for CPUs
41 // which might imply features not in FeatureTable to use this.
42 Bits |= Implies;
43 for (const SubtargetFeatureKV &FE : FeatureTable)
44 if (Implies.test(FE.Value))
45 SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
46}
47
48/// For each feature that (transitively) implies this feature, clear it.
49static
51 ArrayRef<SubtargetFeatureKV> FeatureTable) {
52 for (const SubtargetFeatureKV &FE : FeatureTable) {
53 if (FE.Implies.getAsBitset().test(Value)) {
54 Bits.reset(FE.Value);
55 ClearImpliedBits(Bits, FE.Value, FeatureTable);
56 }
57 }
58}
59
60static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
61 ArrayRef<SubtargetFeatureKV> FeatureTable) {
63 "Feature flags should start with '+' or '-'");
64
65 // Find feature in table.
66 const SubtargetFeatureKV *FeatureEntry =
67 Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
68 // If there is a match
69 if (FeatureEntry) {
70 // Enable/disable feature in bits
71 if (SubtargetFeatures::isEnabled(Feature)) {
72 Bits.set(FeatureEntry->Value);
73
74 // For each feature that this implies, set it.
75 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
76 } else {
77 Bits.reset(FeatureEntry->Value);
78
79 // For each feature that implies this, clear it.
80 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
81 }
82 } else {
83 errs() << "'" << Feature << "' is not a recognized feature for this target"
84 << " (ignoring feature)\n";
85 }
86}
87
88/// Return the length of the longest entry in the table.
90 size_t MaxLen = 0;
91 for (auto &I : Table)
92 MaxLen = std::max(MaxLen, std::strlen(I.Key));
93 return MaxLen;
94}
95
97 size_t MaxLen = 0;
98 for (StringRef I : Table)
99 MaxLen = std::max(MaxLen, I.size());
100 return MaxLen;
101}
102
103/// Display help for feature and mcpu choices.
104static void Help(ArrayRef<StringRef> CPUNames,
106 // the static variable ensures that the help information only gets
107 // printed once even though a target machine creates multiple subtargets
108 static bool PrintOnce = false;
109 if (PrintOnce) {
110 return;
111 }
112
113 // Determine the length of the longest CPU and Feature entries.
114 unsigned MaxCPULen = getLongestEntryLength(CPUNames);
115 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
116
117 // Print the CPU table.
118 errs() << "Available CPUs for this target:\n\n";
119 for (auto &CPUName : CPUNames) {
120 // Skip apple-latest, as that's only meant to be used in
121 // disassemblers/debuggers, and we don't want normal code to be built with
122 // it as an -mcpu=
123 if (CPUName == "apple-latest")
124 continue;
125 errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen,
126 CPUName.str().c_str(), CPUName.str().c_str());
127 }
128 errs() << '\n';
129
130 // Print the Feature table.
131 errs() << "Available features for this target:\n\n";
132 for (auto &Feature : FeatTable)
133 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
134 errs() << '\n';
135
136 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
137 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
138
139 PrintOnce = true;
140}
141
142/// Display help for mcpu choices only
143static void cpuHelp(ArrayRef<StringRef> CPUNames) {
144 // the static variable ensures that the help information only gets
145 // printed once even though a target machine creates multiple subtargets
146 static bool PrintOnce = false;
147 if (PrintOnce) {
148 return;
149 }
150
151 // Print the CPU table.
152 errs() << "Available CPUs for this target:\n\n";
153 for (auto &CPU : CPUNames) {
154 // Skip apple-latest, as that's only meant to be used in
155 // disassemblers/debuggers, and we don't want normal code to be built with
156 // it as an -mcpu=
157 if (CPU == "apple-latest")
158 continue;
159 errs() << "\t" << CPU << "\n";
160 }
161 errs() << '\n';
162
163 errs() << "Use -mcpu or -mtune to specify the target's processor.\n"
164 "For example, clang --target=aarch64-unknown-linux-gnu "
165 "-mcpu=cortex-a35\n";
166
167 PrintOnce = true;
168}
169
171 StringRef TuneCPU, StringRef FS,
172 ArrayRef<StringRef> ProcNames,
174 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
175 SubtargetFeatures Features(FS);
176
177 if (ProcDesc.empty() || ProcFeatures.empty())
178 return FeatureBitset();
179
180 assert(llvm::is_sorted(ProcDesc) && "CPU table is not sorted");
181 assert(llvm::is_sorted(ProcFeatures) && "CPU features table is not sorted");
182 // Resulting bits
183 FeatureBitset Bits;
184
185 // Check if help is needed
186 if (CPU == "help")
187 Help(ProcNames, ProcFeatures);
188
189 // Find CPU entry if CPU name is specified.
190 else if (!CPU.empty()) {
191 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
192
193 // If there is a match
194 if (CPUEntry) {
195 // Set the features implied by this CPU feature, if any.
196 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
197 } else {
198 errs() << "'" << CPU << "' is not a recognized processor for this target"
199 << " (ignoring processor)\n";
200 }
201 }
202
203 if (!TuneCPU.empty()) {
204 const SubtargetSubTypeKV *CPUEntry = Find(TuneCPU, ProcDesc);
205
206 // If there is a match
207 if (CPUEntry) {
208 // Set the features implied by this CPU feature, if any.
209 SetImpliedBits(Bits, CPUEntry->TuneImplies.getAsBitset(), ProcFeatures);
210 } else if (TuneCPU != CPU) {
211 errs() << "'" << TuneCPU << "' is not a recognized processor for this "
212 << "target (ignoring processor)\n";
213 }
214 }
215
216 // Iterate through each feature
217 for (const std::string &Feature : Features.getFeatures()) {
218 // Check for help
219 if (Feature == "+help")
220 Help(ProcNames, ProcFeatures);
221 else if (Feature == "+cpuhelp")
222 cpuHelp(ProcNames);
223 else
224 ApplyFeatureFlag(Bits, Feature, ProcFeatures);
225 }
226
227 return Bits;
228}
229
231 StringRef FS) {
232 FeatureBits =
233 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
234 FeatureString = std::string(FS);
235
236 if (!TuneCPU.empty())
237 CPUSchedModel = &getSchedModelForCPU(TuneCPU);
238 else
239 CPUSchedModel = &MCSchedModel::Default;
240}
241
243 StringRef FS) {
244 FeatureBits =
245 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
246 FeatureString = std::string(FS);
247}
248
250 const Triple &TT, StringRef C, StringRef TC, StringRef FS,
253 const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
254 const InstrStage *IS, const unsigned *OC, const unsigned *FP)
255 : TargetTriple(TT), CPU(std::string(C)), TuneCPU(std::string(TC)),
256 ProcNames(PN), ProcFeatures(PF), ProcDesc(PD), WriteProcResTable(WPR),
257 WriteLatencyTable(WL), ReadAdvanceTable(RA), Stages(IS),
258 OperandCycles(OC), ForwardingPaths(FP) {
259 InitMCProcessorInfo(CPU, TuneCPU, FS);
260}
261
263 FeatureBits.flip(FB);
264 return FeatureBits;
265}
266
268 FeatureBits ^= FB;
269 return FeatureBits;
270}
271
273 const FeatureBitset &FB) {
274 SetImpliedBits(FeatureBits, FB, ProcFeatures);
275 return FeatureBits;
276}
277
279 const FeatureBitset &FB) {
280 for (unsigned I = 0, E = FB.size(); I < E; I++) {
281 if (FB[I]) {
282 FeatureBits.reset(I);
283 ClearImpliedBits(FeatureBits, I, ProcFeatures);
284 }
285 }
286 return FeatureBits;
287}
288
290 // Find feature in table.
291 const SubtargetFeatureKV *FeatureEntry =
292 Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
293 // If there is a match
294 if (FeatureEntry) {
295 if (FeatureBits.test(FeatureEntry->Value)) {
296 FeatureBits.reset(FeatureEntry->Value);
297 // For each feature that implies this, clear it.
298 ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
299 } else {
300 FeatureBits.set(FeatureEntry->Value);
301
302 // For each feature that this implies, set it.
303 SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
304 ProcFeatures);
305 }
306 } else {
307 errs() << "'" << Feature << "' is not a recognized feature for this target"
308 << " (ignoring feature)\n";
309 }
310
311 return FeatureBits;
312}
313
315 ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
316 return FeatureBits;
317}
318
321 return all_of(T.getFeatures(), [this](const std::string &F) {
322 assert(SubtargetFeatures::hasFlag(F) &&
323 "Feature flags should start with '+' or '-'");
324 const SubtargetFeatureKV *FeatureEntry =
325 Find(SubtargetFeatures::StripFlag(F), ProcFeatures);
326 if (!FeatureEntry)
327 report_fatal_error(Twine("'") + F +
328 "' is not a recognized feature for this target");
329
330 return FeatureBits.test(FeatureEntry->Value) ==
331 SubtargetFeatures::isEnabled(F);
332 });
333}
334
336 assert(llvm::is_sorted(ProcDesc) &&
337 "Processor machine model table is not sorted");
338
339 // Find entry
340 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
341
342 if (!CPUEntry) {
343 if (CPU != "help") // Don't error if the user asked for help.
344 errs() << "'" << CPU
345 << "' is not a recognized processor for this target"
346 << " (ignoring processor)\n";
348 }
349 assert(CPUEntry->SchedModel && "Missing processor SchedModel value");
350 return *CPUEntry->SchedModel;
351}
352
355 const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
356 return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
357}
358
360 InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
361 ForwardingPaths);
362}
363
364std::vector<SubtargetFeatureKV>
366 std::vector<SubtargetFeatureKV> EnabledFeatures;
367 auto IsEnabled = [&](const SubtargetFeatureKV &FeatureKV) {
368 return FeatureBits.test(FeatureKV.Value);
369 };
370 llvm::copy_if(ProcFeatures, std::back_inserter(EnabledFeatures), IsEnabled);
371 return EnabledFeatures;
372}
373
374std::optional<unsigned> MCSubtargetInfo::getCacheSize(unsigned Level) const {
375 return std::nullopt;
376}
377
378std::optional<unsigned>
380 return std::nullopt;
381}
382
383std::optional<unsigned>
385 return std::nullopt;
386}
387
389 return 0;
390}
391
393 return UINT_MAX;
394}
395
397 return false;
398}
399
400unsigned MCSubtargetInfo::getMinPrefetchStride(unsigned NumMemAccesses,
401 unsigned NumStridedMemAccesses,
402 unsigned NumPrefetches,
403 bool HasCall) const {
404 return 1;
405}
406
408 return !AS;
409}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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 SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies, ArrayRef< SubtargetFeatureKV > FeatureTable)
For each feature that is (transitively) implied by this feature, set it.
static void Help(ArrayRef< StringRef > CPUNames, ArrayRef< SubtargetFeatureKV > FeatTable)
Display help for feature and mcpu choices.
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 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:55
#define I(x, y, z)
Definition: MD5.cpp:58
SI optimize exec mask operations pre RA
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:142
const FeatureBitset & getAsBitset() const
Container class for subtarget features.
constexpr FeatureBitset & reset(unsigned I)
constexpr bool test(unsigned I) const
constexpr FeatureBitset & flip(unsigned I)
FeatureBitset & set()
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.
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.
virtual unsigned getPrefetchDistance() const
Return the preferred prefetch distance in terms of instructions.
std::vector< SubtargetFeatureKV > getEnabledProcessorFeatures() const
Return the list of processor features currently enabled.
FeatureBitset ApplyFeatureFlag(StringRef FS)
Apply a feature flag and return the re-computed feature bits, including all feature bits implied by t...
virtual std::optional< unsigned > getCacheAssociativity(unsigned Level) const
Return the cache associatvity for the given level of cache.
FeatureBitset SetFeatureBitsTransitively(const FeatureBitset &FB)
Set/clear additional feature bits, including all other bits they imply.
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const
Get scheduling itinerary of a CPU.
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.
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
void InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU, StringRef FS)
Initialize the scheduling model and feature bits.
void initInstrItins(InstrItineraryData &InstrItins) const
Initialize an InstrItineraryData instance.
FeatureBitset ClearFeatureBitsTransitively(const FeatureBitset &FB)
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:151
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
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.
Definition: AddressRanges.h:18
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:1744
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1796
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:1939
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:126
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:2013
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
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:108
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:258
static LLVM_ABI const MCSchedModel Default
Returns the default initialized model.
Definition: MCSchedule.h:424
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition: MCSchedule.h:91
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition: MCSchedule.h:68
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.
const MCSchedModel * SchedModel
FeatureBitArray Implies
K-V bit mask.
FeatureBitArray TuneImplies
K-V bit mask.