1 | //=== llvm/TargetParser/SubtargetFeature.h - CPU characteristics-*- C++ -*-===// |
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 | // |
9 | /// \file Defines and manages user or tool specified CPU characteristics. |
10 | /// The intent is to be able to package specific features that should or should |
11 | /// not be used on a specific target processor. A tool, such as llc, could, as |
12 | /// as example, gather chip info from the command line, a long with features |
13 | /// that should be used on that chip. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef LLVM_TARGETPARSER_SUBTARGETFEATURE_H |
18 | #define LLVM_TARGETPARSER_SUBTARGETFEATURE_H |
19 | |
20 | #include "llvm/ADT/ArrayRef.h" |
21 | #include "llvm/ADT/STLExtras.h" |
22 | #include "llvm/ADT/StringRef.h" |
23 | #include "llvm/Support/MathExtras.h" |
24 | #include <array> |
25 | #include <initializer_list> |
26 | #include <string> |
27 | #include <vector> |
28 | |
29 | namespace llvm { |
30 | |
31 | class raw_ostream; |
32 | class Triple; |
33 | |
34 | const unsigned MAX_SUBTARGET_WORDS = 5; |
35 | const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64; |
36 | |
37 | /// Container class for subtarget features. |
38 | /// This is a constexpr reimplementation of a subset of std::bitset. It would be |
39 | /// nice to use std::bitset directly, but it doesn't support constant |
40 | /// initialization. |
41 | class FeatureBitset { |
42 | static_assert((MAX_SUBTARGET_FEATURES % 64) == 0, |
43 | "Should be a multiple of 64!" ); |
44 | std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits{}; |
45 | |
46 | protected: |
47 | constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) |
48 | : Bits{B} {} |
49 | |
50 | public: |
51 | constexpr FeatureBitset() = default; |
52 | constexpr FeatureBitset(std::initializer_list<unsigned> Init) { |
53 | for (auto I : Init) |
54 | set(I); |
55 | } |
56 | |
57 | FeatureBitset &set() { |
58 | std::fill(first: std::begin(cont&: Bits), last: std::end(cont&: Bits), value: -1ULL); |
59 | return *this; |
60 | } |
61 | |
62 | constexpr FeatureBitset &set(unsigned I) { |
63 | Bits[I / 64] |= uint64_t(1) << (I % 64); |
64 | return *this; |
65 | } |
66 | |
67 | constexpr FeatureBitset &reset(unsigned I) { |
68 | Bits[I / 64] &= ~(uint64_t(1) << (I % 64)); |
69 | return *this; |
70 | } |
71 | |
72 | constexpr FeatureBitset &flip(unsigned I) { |
73 | Bits[I / 64] ^= uint64_t(1) << (I % 64); |
74 | return *this; |
75 | } |
76 | |
77 | constexpr bool operator[](unsigned I) const { |
78 | uint64_t Mask = uint64_t(1) << (I % 64); |
79 | return (Bits[I / 64] & Mask) != 0; |
80 | } |
81 | |
82 | constexpr bool test(unsigned I) const { return (*this)[I]; } |
83 | |
84 | constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; } |
85 | |
86 | bool any() const { |
87 | return llvm::any_of(Range: Bits, P: [](uint64_t I) { return I != 0; }); |
88 | } |
89 | bool none() const { return !any(); } |
90 | size_t count() const { |
91 | size_t Count = 0; |
92 | for (auto B : Bits) |
93 | Count += llvm::popcount(Value: B); |
94 | return Count; |
95 | } |
96 | |
97 | constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) { |
98 | for (unsigned I = 0, E = Bits.size(); I != E; ++I) { |
99 | Bits[I] ^= RHS.Bits[I]; |
100 | } |
101 | return *this; |
102 | } |
103 | constexpr FeatureBitset operator^(const FeatureBitset &RHS) const { |
104 | FeatureBitset Result = *this; |
105 | Result ^= RHS; |
106 | return Result; |
107 | } |
108 | |
109 | constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) { |
110 | for (unsigned I = 0, E = Bits.size(); I != E; ++I) |
111 | Bits[I] &= RHS.Bits[I]; |
112 | return *this; |
113 | } |
114 | constexpr FeatureBitset operator&(const FeatureBitset &RHS) const { |
115 | FeatureBitset Result = *this; |
116 | Result &= RHS; |
117 | return Result; |
118 | } |
119 | |
120 | constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) { |
121 | for (unsigned I = 0, E = Bits.size(); I != E; ++I) { |
122 | Bits[I] |= RHS.Bits[I]; |
123 | } |
124 | return *this; |
125 | } |
126 | constexpr FeatureBitset operator|(const FeatureBitset &RHS) const { |
127 | FeatureBitset Result = *this; |
128 | Result |= RHS; |
129 | return Result; |
130 | } |
131 | |
132 | constexpr FeatureBitset operator~() const { |
133 | FeatureBitset Result = *this; |
134 | for (auto &B : Result.Bits) |
135 | B = ~B; |
136 | return Result; |
137 | } |
138 | |
139 | bool operator==(const FeatureBitset &RHS) const { |
140 | return std::equal(first1: std::begin(cont: Bits), last1: std::end(cont: Bits), first2: std::begin(cont: RHS.Bits)); |
141 | } |
142 | |
143 | bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); } |
144 | |
145 | bool operator < (const FeatureBitset &Other) const { |
146 | for (unsigned I = 0, E = size(); I != E; ++I) { |
147 | bool LHS = test(I), RHS = Other.test(I); |
148 | if (LHS != RHS) |
149 | return LHS < RHS; |
150 | } |
151 | return false; |
152 | } |
153 | }; |
154 | |
155 | /// Class used to store the subtarget bits in the tables created by tablegen. |
156 | class FeatureBitArray : public FeatureBitset { |
157 | public: |
158 | constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) |
159 | : FeatureBitset(B) {} |
160 | |
161 | const FeatureBitset &getAsBitset() const { return *this; } |
162 | }; |
163 | |
164 | //===----------------------------------------------------------------------===// |
165 | |
166 | /// Manages the enabling and disabling of subtarget specific features. |
167 | /// |
168 | /// Features are encoded as a string of the form |
169 | /// "+attr1,+attr2,-attr3,...,+attrN" |
170 | /// A comma separates each feature from the next (all lowercase.) |
171 | /// Each of the remaining features is prefixed with + or - indicating whether |
172 | /// that feature should be enabled or disabled contrary to the cpu |
173 | /// specification. |
174 | class SubtargetFeatures { |
175 | std::vector<std::string> Features; ///< Subtarget features as a vector |
176 | |
177 | public: |
178 | explicit SubtargetFeatures(StringRef Initial = "" ); |
179 | |
180 | /// Returns features as a string. |
181 | std::string getString() const; |
182 | |
183 | /// Adds Features. |
184 | void AddFeature(StringRef String, bool Enable = true); |
185 | |
186 | void addFeaturesVector(const ArrayRef<std::string> OtherFeatures); |
187 | |
188 | /// Returns the vector of individual subtarget features. |
189 | const std::vector<std::string> &getFeatures() const { return Features; } |
190 | |
191 | /// Prints feature string. |
192 | void print(raw_ostream &OS) const; |
193 | |
194 | // Dumps feature info. |
195 | void dump() const; |
196 | |
197 | /// Adds the default features for the specified target triple. |
198 | void getDefaultSubtargetFeatures(const Triple& Triple); |
199 | |
200 | /// Determine if a feature has a flag; '+' or '-' |
201 | static bool hasFlag(StringRef Feature) { |
202 | assert(!Feature.empty() && "Empty string" ); |
203 | // Get first character |
204 | char Ch = Feature[0]; |
205 | // Check if first character is '+' or '-' flag |
206 | return Ch == '+' || Ch =='-'; |
207 | } |
208 | |
209 | /// Return string stripped of flag. |
210 | static StringRef StripFlag(StringRef Feature) { |
211 | return hasFlag(Feature) ? Feature.substr(Start: 1) : Feature; |
212 | } |
213 | |
214 | /// Return true if enable flag; '+'. |
215 | static inline bool isEnabled(StringRef Feature) { |
216 | assert(!Feature.empty() && "Empty string" ); |
217 | // Get first character |
218 | char Ch = Feature[0]; |
219 | // Check if first character is '+' for enabled |
220 | return Ch == '+'; |
221 | } |
222 | |
223 | /// Splits a string of comma separated items in to a vector of strings. |
224 | static void Split(std::vector<std::string> &V, StringRef S); |
225 | }; |
226 | |
227 | } // end namespace llvm |
228 | |
229 | #endif // LLVM_TARGETPARSER_SUBTARGETFEATURE_H |
230 | |