LLVM 20.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"
13#include "llvm/MC/MCSchedule.h"
14#include "llvm/Support/Format.h"
17#include <algorithm>
18#include <cassert>
19#include <cstring>
20#include <optional>
21
22using namespace llvm;
23
24/// Find KV in array using binary search.
25template <typename T>
26static const T *Find(StringRef S, ArrayRef<T> A) {
27 // Binary search the array
28 auto F = llvm::lower_bound(A, S);
29 // If not found then return NULL
30 if (F == A.end() || StringRef(F->Key) != S) return nullptr;
31 // Return the found array item
32 return F;
33}
34
35/// For each feature that is (transitively) implied by this feature, set it.
36static
37void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
38 ArrayRef<SubtargetFeatureKV> FeatureTable) {
39 // OR the Implies bits in outside the loop. This allows the Implies for CPUs
40 // which might imply features not in FeatureTable to use this.
41 Bits |= Implies;
42 for (const SubtargetFeatureKV &FE : FeatureTable)
43 if (Implies.test(FE.Value))
44 SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
45}
46
47/// For each feature that (transitively) implies this feature, clear it.
48static
50 ArrayRef<SubtargetFeatureKV> FeatureTable) {
51 for (const SubtargetFeatureKV &FE : FeatureTable) {
52 if (FE.Implies.getAsBitset().test(Value)) {
53 Bits.reset(FE.Value);
54 ClearImpliedBits(Bits, FE.Value, FeatureTable);
55 }
56 }
57}
58
59static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
60 ArrayRef<SubtargetFeatureKV> FeatureTable) {
62 "Feature flags should start with '+' or '-'");
63
64 // Find feature in table.
65 const SubtargetFeatureKV *FeatureEntry =
66 Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
67 // If there is a match
68 if (FeatureEntry) {
69 // Enable/disable feature in bits
70 if (SubtargetFeatures::isEnabled(Feature)) {
71 Bits.set(FeatureEntry->Value);
72
73 // For each feature that this implies, set it.
74 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
75 } else {
76 Bits.reset(FeatureEntry->Value);
77
78 // For each feature that implies this, clear it.
79 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
80 }
81 } else {
82 errs() << "'" << Feature << "' is not a recognized feature for this target"
83 << " (ignoring feature)\n";
84 }
85}
86
87/// Return the length of the longest entry in the table.
89 size_t MaxLen = 0;
90 for (auto &I : Table)
91 MaxLen = std::max(MaxLen, std::strlen(I.Key));
92 return MaxLen;
93}
94
96 size_t MaxLen = 0;
97 for (StringRef I : Table)
98 MaxLen = std::max(MaxLen, I.size());
99 return MaxLen;
100}
101
102/// Display help for feature and mcpu choices.
103static void Help(ArrayRef<StringRef> CPUNames,
105 // the static variable ensures that the help information only gets
106 // printed once even though a target machine creates multiple subtargets
107 static bool PrintOnce = false;
108 if (PrintOnce) {
109 return;
110 }
111
112 // Determine the length of the longest CPU and Feature entries.
113 unsigned MaxCPULen = getLongestEntryLength(CPUNames);
114 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
115
116 // Print the CPU table.
117 errs() << "Available CPUs for this target:\n\n";
118 for (auto &CPUName : CPUNames) {
119 // Skip apple-latest, as that's only meant to be used in
120 // disassemblers/debuggers, and we don't want normal code to be built with
121 // it as an -mcpu=
122 if (CPUName == "apple-latest")
123 continue;
124 errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen,
125 CPUName.str().c_str(), CPUName.str().c_str());
126 }
127 errs() << '\n';
128
129 // Print the Feature table.
130 errs() << "Available features for this target:\n\n";
131 for (auto &Feature : FeatTable)
132 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
133 errs() << '\n';
134
135 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
136 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
137
138 PrintOnce = true;
139}
140
141/// Display help for mcpu choices only
142static void cpuHelp(ArrayRef<StringRef> CPUNames) {
143 // the static variable ensures that the help information only gets
144 // printed once even though a target machine creates multiple subtargets
145 static bool PrintOnce = false;
146 if (PrintOnce) {
147 return;
148 }
149
150 // Print the CPU table.
151 errs() << "Available CPUs for this target:\n\n";
152 for (auto &CPU : CPUNames) {
153 // Skip apple-latest, as that's only meant to be used in
154 // disassemblers/debuggers, and we don't want normal code to be built with
155 // it as an -mcpu=
156 if (CPU == "apple-latest")
157 continue;
158 errs() << "\t" << CPU << "\n";
159 }
160 errs() << '\n';
161
162 errs() << "Use -mcpu or -mtune to specify the target's processor.\n"
163 "For example, clang --target=aarch64-unknown-linux-gnu "
164 "-mcpu=cortex-a35\n";
165
166 PrintOnce = true;
167}
168
170 StringRef TuneCPU, StringRef FS,
171 ArrayRef<StringRef> ProcNames,
173 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
174 SubtargetFeatures Features(FS);
175
176 if (ProcDesc.empty() || ProcFeatures.empty())
177 return FeatureBitset();
178
179 assert(llvm::is_sorted(ProcDesc) && "CPU table is not sorted");
180 assert(llvm::is_sorted(ProcFeatures) && "CPU features table is not sorted");
181 // Resulting bits
182 FeatureBitset Bits;
183
184 // Check if help is needed
185 if (CPU == "help")
186 Help(ProcNames, ProcFeatures);
187
188 // Find CPU entry if CPU name is specified.
189 else if (!CPU.empty()) {
190 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
191
192 // If there is a match
193 if (CPUEntry) {
194 // Set the features implied by this CPU feature, if any.
195 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
196 } else {
197 errs() << "'" << CPU << "' is not a recognized processor for this target"
198 << " (ignoring processor)\n";
199 }
200 }
201
202 if (!TuneCPU.empty()) {
203 const SubtargetSubTypeKV *CPUEntry = Find(TuneCPU, ProcDesc);
204
205 // If there is a match
206 if (CPUEntry) {
207 // Set the features implied by this CPU feature, if any.
208 SetImpliedBits(Bits, CPUEntry->TuneImplies.getAsBitset(), ProcFeatures);
209 } else if (TuneCPU != CPU) {
210 errs() << "'" << TuneCPU << "' is not a recognized processor for this "
211 << "target (ignoring processor)\n";
212 }
213 }
214
215 // Iterate through each feature
216 for (const std::string &Feature : Features.getFeatures()) {
217 // Check for help
218 if (Feature == "+help")
219 Help(ProcNames, ProcFeatures);
220 else if (Feature == "+cpuhelp")
221 cpuHelp(ProcNames);
222 else
223 ApplyFeatureFlag(Bits, Feature, ProcFeatures);
224 }
225
226 return Bits;
227}
228
230 StringRef FS) {
231 FeatureBits =
232 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
233 FeatureString = std::string(FS);
234
235 if (!TuneCPU.empty())
236 CPUSchedModel = &getSchedModelForCPU(TuneCPU);
237 else
238 CPUSchedModel = &MCSchedModel::Default;
239}
240
242 StringRef FS) {
243 FeatureBits =
244 getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);
245 FeatureString = std::string(FS);
246}
247
249 const Triple &TT, StringRef C, StringRef TC, StringRef FS,
252 const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
253 const InstrStage *IS, const unsigned *OC, const unsigned *FP)
254 : TargetTriple(TT), CPU(std::string(C)), TuneCPU(std::string(TC)),
255 ProcNames(PN), ProcFeatures(PF), ProcDesc(PD), WriteProcResTable(WPR),
256 WriteLatencyTable(WL), ReadAdvanceTable(RA), Stages(IS),
257 OperandCycles(OC), ForwardingPaths(FP) {
258 InitMCProcessorInfo(CPU, TuneCPU, FS);
259}
260
262 FeatureBits.flip(FB);
263 return FeatureBits;
264}
265
267 FeatureBits ^= FB;
268 return FeatureBits;
269}
270
272 const FeatureBitset &FB) {
273 SetImpliedBits(FeatureBits, FB, ProcFeatures);
274 return FeatureBits;
275}
276
278 const FeatureBitset &FB) {
279 for (unsigned I = 0, E = FB.size(); I < E; I++) {
280 if (FB[I]) {
281 FeatureBits.reset(I);
282 ClearImpliedBits(FeatureBits, I, ProcFeatures);
283 }
284 }
285 return FeatureBits;
286}
287
289 // Find feature in table.
290 const SubtargetFeatureKV *FeatureEntry =
291 Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
292 // If there is a match
293 if (FeatureEntry) {
294 if (FeatureBits.test(FeatureEntry->Value)) {
295 FeatureBits.reset(FeatureEntry->Value);
296 // For each feature that implies this, clear it.
297 ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
298 } else {
299 FeatureBits.set(FeatureEntry->Value);
300
301 // For each feature that this implies, set it.
302 SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
303 ProcFeatures);
304 }
305 } else {
306 errs() << "'" << Feature << "' is not a recognized feature for this target"
307 << " (ignoring feature)\n";
308 }
309
310 return FeatureBits;
311}
312
314 ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
315 return FeatureBits;
316}
317
320 FeatureBitset Set, All;
321 for (std::string F : T.getFeatures()) {
322 ::ApplyFeatureFlag(Set, F, ProcFeatures);
323 if (F[0] == '-')
324 F[0] = '+';
325 ::ApplyFeatureFlag(All, F, ProcFeatures);
326 }
327 return (FeatureBits & All) == Set;
328}
329
331 assert(llvm::is_sorted(ProcDesc) &&
332 "Processor machine model table is not sorted");
333
334 // Find entry
335 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
336
337 if (!CPUEntry) {
338 if (CPU != "help") // Don't error if the user asked for help.
339 errs() << "'" << CPU
340 << "' is not a recognized processor for this target"
341 << " (ignoring processor)\n";
343 }
344 assert(CPUEntry->SchedModel && "Missing processor SchedModel value");
345 return *CPUEntry->SchedModel;
346}
347
350 const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
351 return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
352}
353
355 InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
356 ForwardingPaths);
357}
358
359std::vector<SubtargetFeatureKV>
361 std::vector<SubtargetFeatureKV> EnabledFeatures;
362 auto IsEnabled = [&](const SubtargetFeatureKV &FeatureKV) {
363 return FeatureBits.test(FeatureKV.Value);
364 };
365 llvm::copy_if(ProcFeatures, std::back_inserter(EnabledFeatures), IsEnabled);
366 return EnabledFeatures;
367}
368
369std::optional<unsigned> MCSubtargetInfo::getCacheSize(unsigned Level) const {
370 return std::nullopt;
371}
372
373std::optional<unsigned>
375 return std::nullopt;
376}
377
378std::optional<unsigned>
380 return std::nullopt;
381}
382
384 return 0;
385}
386
388 return UINT_MAX;
389}
390
392 return false;
393}
394
395unsigned MCSubtargetInfo::getMinPrefetchStride(unsigned NumMemAccesses,
396 unsigned NumStridedMemAccesses,
397 unsigned NumPrefetches,
398 bool HasCall) const {
399 return 1;
400}
401
403 return !AS;
404}
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:163
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:51
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
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:44
LLVM Value Representation.
Definition: Value.h:74
@ 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
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:1785
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:1926
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
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:1978
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
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:106
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:256
static const MCSchedModel Default
Returns the default initialized model.
Definition: MCSchedule.h:406
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition: MCSchedule.h:89
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition: MCSchedule.h:66
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.