1 //===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
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
7 //===----------------------------------------------------------------------===//
9 /// \file Implements the SubtargetFeature interface.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/MC/SubtargetFeature.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Config/llvm-config.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/raw_ostream.h"
34 /// Determine if a feature has a flag; '+' or '-'
35 static inline bool hasFlag(StringRef Feature
) {
36 assert(!Feature
.empty() && "Empty string");
37 // Get first character
39 // Check if first character is '+' or '-' flag
40 return Ch
== '+' || Ch
=='-';
43 /// Return string stripped of flag.
44 static inline std::string
StripFlag(StringRef Feature
) {
45 return hasFlag(Feature
) ? Feature
.substr(1) : Feature
;
48 /// Return true if enable flag; '+'.
49 static inline bool isEnabled(StringRef Feature
) {
50 assert(!Feature
.empty() && "Empty string");
51 // Get first character
53 // Check if first character is '+' for enabled
57 /// Splits a string of comma separated items in to a vector of strings.
58 static void Split(std::vector
<std::string
> &V
, StringRef S
) {
59 SmallVector
<StringRef
, 3> Tmp
;
60 S
.split(Tmp
, ',', -1, false /* KeepEmpty */);
61 V
.assign(Tmp
.begin(), Tmp
.end());
64 void SubtargetFeatures::AddFeature(StringRef String
, bool Enable
) {
65 // Don't add empty features.
67 // Convert to lowercase, prepend flag if we don't already have a flag.
68 Features
.push_back(hasFlag(String
) ? String
.lower()
69 : (Enable
? "+" : "-") + String
.lower());
72 /// Find KV in array using binary search.
73 static const SubtargetFeatureKV
*Find(StringRef S
,
74 ArrayRef
<SubtargetFeatureKV
> A
) {
75 // Binary search the array
76 auto F
= std::lower_bound(A
.begin(), A
.end(), S
);
77 // If not found then return NULL
78 if (F
== A
.end() || StringRef(F
->Key
) != S
) return nullptr;
79 // Return the found array item
83 /// Return the length of the longest entry in the table.
84 static size_t getLongestEntryLength(ArrayRef
<SubtargetFeatureKV
> Table
) {
87 MaxLen
= std::max(MaxLen
, std::strlen(I
.Key
));
91 /// Display help for feature choices.
92 static void Help(ArrayRef
<SubtargetFeatureKV
> CPUTable
,
93 ArrayRef
<SubtargetFeatureKV
> FeatTable
) {
94 // Determine the length of the longest CPU and Feature entries.
95 unsigned MaxCPULen
= getLongestEntryLength(CPUTable
);
96 unsigned MaxFeatLen
= getLongestEntryLength(FeatTable
);
98 // Print the CPU table.
99 errs() << "Available CPUs for this target:\n\n";
100 for (auto &CPU
: CPUTable
)
101 errs() << format(" %-*s - %s.\n", MaxCPULen
, CPU
.Key
, CPU
.Desc
);
104 // Print the Feature table.
105 errs() << "Available features for this target:\n\n";
106 for (auto &Feature
: FeatTable
)
107 errs() << format(" %-*s - %s.\n", MaxFeatLen
, Feature
.Key
, Feature
.Desc
);
110 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
111 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
114 SubtargetFeatures::SubtargetFeatures(StringRef Initial
) {
115 // Break up string into separate features
116 Split(Features
, Initial
);
119 std::string
SubtargetFeatures::getString() const {
120 return join(Features
.begin(), Features
.end(), ",");
123 /// For each feature that is (transitively) implied by this feature, set it.
125 void SetImpliedBits(FeatureBitset
&Bits
, const SubtargetFeatureKV
&FeatureEntry
,
126 ArrayRef
<SubtargetFeatureKV
> FeatureTable
) {
127 for (const SubtargetFeatureKV
&FE
: FeatureTable
) {
128 if (FeatureEntry
.Value
== FE
.Value
) continue;
130 if (FeatureEntry
.Implies
.test(FE
.Value
)) {
132 SetImpliedBits(Bits
, FE
, FeatureTable
);
137 /// For each feature that (transitively) implies this feature, clear it.
139 void ClearImpliedBits(FeatureBitset
&Bits
,
140 const SubtargetFeatureKV
&FeatureEntry
,
141 ArrayRef
<SubtargetFeatureKV
> FeatureTable
) {
142 for (const SubtargetFeatureKV
&FE
: FeatureTable
) {
143 if (FeatureEntry
.Value
== FE
.Value
) continue;
145 if (FE
.Implies
.test(FeatureEntry
.Value
)) {
146 Bits
.reset(FE
.Value
);
147 ClearImpliedBits(Bits
, FE
, FeatureTable
);
153 SubtargetFeatures::ToggleFeature(FeatureBitset
&Bits
, StringRef Feature
,
154 ArrayRef
<SubtargetFeatureKV
> FeatureTable
) {
155 // Find feature in table.
156 const SubtargetFeatureKV
*FeatureEntry
=
157 Find(StripFlag(Feature
), FeatureTable
);
158 // If there is a match
160 if (Bits
.test(FeatureEntry
->Value
)) {
161 Bits
.reset(FeatureEntry
->Value
);
162 // For each feature that implies this, clear it.
163 ClearImpliedBits(Bits
, *FeatureEntry
, FeatureTable
);
165 Bits
.set(FeatureEntry
->Value
);
167 // For each feature that this implies, set it.
168 SetImpliedBits(Bits
, *FeatureEntry
, FeatureTable
);
171 errs() << "'" << Feature
<< "' is not a recognized feature for this target"
172 << " (ignoring feature)\n";
176 void SubtargetFeatures::ApplyFeatureFlag(FeatureBitset
&Bits
, StringRef Feature
,
177 ArrayRef
<SubtargetFeatureKV
> FeatureTable
) {
178 assert(hasFlag(Feature
));
180 // Find feature in table.
181 const SubtargetFeatureKV
*FeatureEntry
=
182 Find(StripFlag(Feature
), FeatureTable
);
183 // If there is a match
185 // Enable/disable feature in bits
186 if (isEnabled(Feature
)) {
187 Bits
.set(FeatureEntry
->Value
);
189 // For each feature that this implies, set it.
190 SetImpliedBits(Bits
, *FeatureEntry
, FeatureTable
);
192 Bits
.reset(FeatureEntry
->Value
);
194 // For each feature that implies this, clear it.
195 ClearImpliedBits(Bits
, *FeatureEntry
, FeatureTable
);
198 errs() << "'" << Feature
<< "' is not a recognized feature for this target"
199 << " (ignoring feature)\n";
204 SubtargetFeatures::getFeatureBits(StringRef CPU
,
205 ArrayRef
<SubtargetFeatureKV
> CPUTable
,
206 ArrayRef
<SubtargetFeatureKV
> FeatureTable
) {
207 if (CPUTable
.empty() || FeatureTable
.empty())
208 return FeatureBitset();
210 assert(std::is_sorted(std::begin(CPUTable
), std::end(CPUTable
)) &&
211 "CPU table is not sorted");
212 assert(std::is_sorted(std::begin(FeatureTable
), std::end(FeatureTable
)) &&
213 "CPU features table is not sorted");
217 // Check if help is needed
219 Help(CPUTable
, FeatureTable
);
221 // Find CPU entry if CPU name is specified.
222 else if (!CPU
.empty()) {
223 const SubtargetFeatureKV
*CPUEntry
= Find(CPU
, CPUTable
);
225 // If there is a match
227 // Set base feature bits
228 Bits
= CPUEntry
->Implies
;
230 // Set the feature implied by this CPU feature, if any.
231 for (auto &FE
: FeatureTable
) {
232 if (CPUEntry
->Implies
.test(FE
.Value
))
233 SetImpliedBits(Bits
, FE
, FeatureTable
);
236 errs() << "'" << CPU
<< "' is not a recognized processor for this target"
237 << " (ignoring processor)\n";
241 // Iterate through each feature
242 for (const std::string
&Feature
: Features
) {
244 if (Feature
== "+help")
245 Help(CPUTable
, FeatureTable
);
247 ApplyFeatureFlag(Bits
, Feature
, FeatureTable
);
253 void SubtargetFeatures::print(raw_ostream
&OS
) const {
254 for (auto &F
: Features
)
259 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
260 LLVM_DUMP_METHOD
void SubtargetFeatures::dump() const {
265 void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple
& Triple
) {
266 // FIXME: This is an inelegant way of specifying the features of a
267 // subtarget. It would be better if we could encode this information
268 // into the IR. See <rdar://5972456>.
269 if (Triple
.getVendor() == Triple::Apple
) {
270 if (Triple
.getArch() == Triple::ppc
) {
272 AddFeature("altivec");
273 } else if (Triple
.getArch() == Triple::ppc64
) {
276 AddFeature("altivec");