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) 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 void SetImpliedBits(FeatureBitset &Bits, FeatureBitset Implies,
38 ArrayRef<SubtargetFeatureKV> FeatureTable) {
39 // Transitively set all features implied. We don't assume that the features in
40 // Bits have already had their implied features set.
41 FeatureBitset NewBits = Implies;
42 while (Implies.any()) {
43 FeatureBitset Implied;
44 for (const SubtargetFeatureKV &FE : FeatureTable) {
45 if (Implies.test(FE.Value))
46 Implied |= FE.Implies.getAsBitset();
47 }
48
49 // Only continue for bits that haven't been set yet.
50 Implies = Implied & ~NewBits;
51 NewBits |= Implies;
52 }
53 Bits |= NewBits;
54}
55
56/// For each feature that (transitively) implies this feature, clear it.
57static
59 ArrayRef<SubtargetFeatureKV> FeatureTable) {
60 for (const SubtargetFeatureKV &FE : FeatureTable) {
61 if (FE.Implies.getAsBitset().test(Value)) {
62 Bits.reset(FE.Value);
63 ClearImpliedBits(Bits, FE.Value, FeatureTable);
64 }
65 }
66}
67
68static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
69 ArrayRef<SubtargetFeatureKV> FeatureTable) {
71 "Feature flags should start with '+' or '-'");
72
73 // Find feature in table.
74 const SubtargetFeatureKV *FeatureEntry =
75 Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
76 // If there is a match
77 if (FeatureEntry) {
78 // Enable/disable feature in bits
79 if (SubtargetFeatures::isEnabled(Feature)) {
80 Bits.set(FeatureEntry->Value);
81
82 // For each feature that this implies, set it.
83 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
84 } else {
85 Bits.reset(FeatureEntry->Value);
86
87 // For each feature that implies this, clear it.
88 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
89 }
90 } else {
91 errs() << "'" << Feature << "' is not a recognized feature for this target"
92 << " (ignoring feature)\n";
93 }
94}
95
96/// Return the length of the longest entry in the table.
98 size_t MaxLen = 0;
99 for (auto &I : Table)
100 MaxLen = std::max(MaxLen, std::strlen(I.Key));
101 return MaxLen;
102}
103
105 size_t MaxLen = 0;
106 for (StringRef I : Table)
107 MaxLen = std::max(MaxLen, I.size());
108 return MaxLen;
109}
110
111/// Display help for feature and mcpu choices.
112static void Help(ArrayRef<StringRef> CPUNames,
114 // the static variable ensures that the help information only gets
115 // printed once even though a target machine creates multiple subtargets
116 static bool PrintOnce = false;
117 if (PrintOnce) {
118 return;
119 }
120
121 // Determine the length of the longest CPU and Feature entries.
122 unsigned MaxCPULen = getLongestEntryLength(CPUNames);
123 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
124
125 // Print the CPU table.
126 errs() << "Available CPUs for this target:\n\n";
127 for (auto &CPUName : CPUNames) {
128 // Skip apple-latest, as that's only meant to be used in
129 // disassemblers/debuggers, and we don't want normal code to be built with
130 // it as an -mcpu=
131 if (CPUName == "apple-latest")
132 continue;
133 errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen,
134 CPUName.str().c_str(), CPUName.str().c_str());
135 }
136 errs() << '\n';
137
138 // Print the Feature table.
139 errs() << "Available features for this target:\n\n";
140 for (auto &Feature : FeatTable)
141 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
142 errs() << '\n';
143
144 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
145 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
146
147 PrintOnce = true;
148}
149
150/// Display help for mcpu choices only
151static void cpuHelp(ArrayRef<StringRef> CPUNames) {
152 // the static variable ensures that the help information only gets
153 // printed once even though a target machine creates multiple subtargets
154 static bool PrintOnce = false;
155 if (PrintOnce) {
156 return;
157 }
158
159 // Print the CPU table.
160 errs() << "Available CPUs for this target:\n\n";
161 for (auto &CPU : CPUNames) {
162 // Skip apple-latest, as that's only meant to be used in
163 // disassemblers/debuggers, and we don't want normal code to be built with
164 // it as an -mcpu=
165 if (CPU == "apple-latest")
166 continue;
167 errs() << "\t" << CPU << "\n";
168 }
169 errs() << '\n';
170
171 errs() << "Use -mcpu or -mtune to specify the target's processor.\n"
172 "For example, clang --target=aarch64-unknown-linux-gnu "
173 "-mcpu=cortex-a35\n";
174
175 PrintOnce = true;
176}
177
179 StringRef TuneCPU, StringRef FS,
180 ArrayRef<StringRef> ProcNames,
182 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
183 SubtargetFeatures Features(FS);
184
185 if (ProcDesc.empty() || ProcFeatures.empty())
186 return FeatureBitset();
187
188 assert(llvm::is_sorted(ProcDesc) && "CPU table is not sorted");
189 assert(llvm::is_sorted(ProcFeatures) && "CPU features table is not sorted");
190 // Resulting bits
191 FeatureBitset Bits;
192
193 // Check if help is needed
194 if (CPU == "help")
195 Help(ProcNames, ProcFeatures);
196
197 // Find CPU entry if CPU name is specified.
198 else if (!CPU.empty()) {
199 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
200
201 // If there is a match
202 if (CPUEntry) {
203 // Set the features implied by this CPU feature, if any.
204 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
205 } else {
206 errs() << "'" << CPU << "' is not a recognized processor for this target"
207 << " (ignoring processor)\n";
208 }
209 }
210
211 if (!TuneCPU.empty()) {
212 const SubtargetSubTypeKV *CPUEntry = Find(TuneCPU, ProcDesc);
213
214 // If there is a match
215 if (CPUEntry) {
216 // Set the features implied by this CPU feature, if any.
217 SetImpliedBits(Bits, CPUEntry->TuneImplies.getAsBitset(), ProcFeatures);
218 } else if (TuneCPU != CPU) {
219 errs() << "'" << TuneCPU << "' is not a recognized processor for this "
220 << "target (ignoring processor)\n";
221 }
222 }
223
224 // Iterate through each feature
225 for (const std::string &Feature : Features.getFeatures()) {
226 // Check for help
227 if (Feature == "+help")
228 Help(ProcNames, ProcFeatures);
229 else if (Feature == "+cpuhelp")
230 cpuHelp(ProcNames);
231 else
232 ApplyFeatureFlag(Bits, Feature, ProcFeatures);
233 }
234
235 return Bits;
236}
237
239 StringRef FS) {
240 FeatureBits =
241 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
242 FeatureString = std::string(FS);
243
244 if (!TuneCPU.empty())
245 CPUSchedModel = &getSchedModelForCPU(TuneCPU);
246 else
247 CPUSchedModel = &MCSchedModel::Default;
248}
249
251 StringRef FS) {
252 FeatureBits =
253 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
254 FeatureString = std::string(FS);
255}
256
258 const Triple &TT, StringRef C, StringRef TC, StringRef FS,
261 const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
262 const InstrStage *IS, const unsigned *OC, const unsigned *FP)
263 : TargetTriple(TT), CPU(std::string(C)), TuneCPU(std::string(TC)),
264 ProcNames(PN), ProcFeatures(PF), ProcDesc(PD), WriteProcResTable(WPR),
265 WriteLatencyTable(WL), ReadAdvanceTable(RA), Stages(IS),
266 OperandCycles(OC), ForwardingPaths(FP) {
267 InitMCProcessorInfo(CPU, TuneCPU, FS);
268}
269
271 FeatureBits.flip(FB);
272 return FeatureBits;
273}
274
276 FeatureBits ^= FB;
277 return FeatureBits;
278}
279
280const FeatureBitset &
282 SetImpliedBits(FeatureBits, FB, ProcFeatures);
283 return FeatureBits;
284}
285
286const FeatureBitset &
288 for (unsigned I = 0, E = FB.size(); I < E; I++) {
289 if (FB[I]) {
290 FeatureBits.reset(I);
291 ClearImpliedBits(FeatureBits, I, ProcFeatures);
292 }
293 }
294 return FeatureBits;
295}
296
298 // Find feature in table.
299 const SubtargetFeatureKV *FeatureEntry =
300 Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
301 // If there is a match
302 if (FeatureEntry) {
303 if (FeatureBits.test(FeatureEntry->Value)) {
304 FeatureBits.reset(FeatureEntry->Value);
305 // For each feature that implies this, clear it.
306 ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
307 } else {
308 FeatureBits.set(FeatureEntry->Value);
309
310 // For each feature that this implies, set it.
311 SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
312 ProcFeatures);
313 }
314 } else {
315 errs() << "'" << Feature << "' is not a recognized feature for this target"
316 << " (ignoring feature)\n";
317 }
318
319 return FeatureBits;
320}
321
323 ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
324 return FeatureBits;
325}
326
329 return all_of(T.getFeatures(), [this](const std::string &F) {
330 assert(SubtargetFeatures::hasFlag(F) &&
331 "Feature flags should start with '+' or '-'");
332 const SubtargetFeatureKV *FeatureEntry =
333 Find(SubtargetFeatures::StripFlag(F), ProcFeatures);
334 if (!FeatureEntry)
335 report_fatal_error(Twine("'") + F +
336 "' is not a recognized feature for this target");
337
338 return FeatureBits.test(FeatureEntry->Value) ==
339 SubtargetFeatures::isEnabled(F);
340 });
341}
342
344 assert(llvm::is_sorted(ProcDesc) &&
345 "Processor machine model table is not sorted");
346
347 // Find entry
348 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
349
350 if (!CPUEntry) {
351 if (CPU != "help") // Don't error if the user asked for help.
352 errs() << "'" << CPU
353 << "' is not a recognized processor for this target"
354 << " (ignoring processor)\n";
356 }
357 assert(CPUEntry->SchedModel && "Missing processor SchedModel value");
358 return *CPUEntry->SchedModel;
359}
360
363 const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
364 return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
365}
366
368 InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
369 ForwardingPaths);
370}
371
372std::vector<SubtargetFeatureKV>
374 std::vector<SubtargetFeatureKV> EnabledFeatures;
375 auto IsEnabled = [&](const SubtargetFeatureKV &FeatureKV) {
376 return FeatureBits.test(FeatureKV.Value);
377 };
378 llvm::copy_if(ProcFeatures, std::back_inserter(EnabledFeatures), IsEnabled);
379 return EnabledFeatures;
380}
381
382std::optional<unsigned> MCSubtargetInfo::getCacheSize(unsigned Level) const {
383 return std::nullopt;
384}
385
386std::optional<unsigned>
388 return std::nullopt;
389}
390
391std::optional<unsigned>
393 return std::nullopt;
394}
395
397 return 0;
398}
399
401 return UINT_MAX;
402}
403
405 return false;
406}
407
408unsigned MCSubtargetInfo::getMinPrefetchStride(unsigned NumMemAccesses,
409 unsigned NumStridedMemAccesses,
410 unsigned NumPrefetches,
411 bool HasCall) const {
412 return 1;
413}
414
416 return !AS;
417}
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 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 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
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.
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.
std::vector< SubtargetFeatureKV > getEnabledProcessorFeatures() const
Return the list of processor features currently enabled.
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)
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
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
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.
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:1738
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:1790
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:1969
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:129
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:2051
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:874
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:429
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.