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:
FeatureBitset(const std::array<uint64_t,MAX_SUBTARGET_WORDS> & B)47   constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
48       : Bits{B} {}
49 
50 public:
51   constexpr FeatureBitset() = default;
FeatureBitset(std::initializer_list<unsigned> Init)52   constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
53     for (auto I : Init)
54       set(I);
55   }
56 
set()57   FeatureBitset &set() {
58     std::fill(std::begin(Bits), std::end(Bits), -1ULL);
59     return *this;
60   }
61 
set(unsigned I)62   constexpr FeatureBitset &set(unsigned I) {
63     Bits[I / 64] |= uint64_t(1) << (I % 64);
64     return *this;
65   }
66 
reset(unsigned I)67   constexpr FeatureBitset &reset(unsigned I) {
68     Bits[I / 64] &= ~(uint64_t(1) << (I % 64));
69     return *this;
70   }
71 
flip(unsigned I)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 
test(unsigned I)82   constexpr bool test(unsigned I) const { return (*this)[I]; }
83 
size()84   constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
85 
any()86   bool any() const {
87     return llvm::any_of(Bits, [](uint64_t I) { return I != 0; });
88   }
none()89   bool none() const { return !any(); }
count()90   size_t count() const {
91     size_t Count = 0;
92     for (auto B : Bits)
93       Count += llvm::popcount(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(std::begin(Bits), std::end(Bits), std::begin(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:
FeatureBitArray(const std::array<uint64_t,MAX_SUBTARGET_WORDS> & B)158   constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
159       : FeatureBitset(B) {}
160 
getAsBitset()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.
getFeatures()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 '-'
hasFlag(StringRef Feature)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.
StripFlag(StringRef Feature)210   static StringRef StripFlag(StringRef Feature) {
211     return hasFlag(Feature) ? Feature.substr(1) : Feature;
212   }
213 
214   /// Return true if enable flag; '+'.
isEnabled(StringRef Feature)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