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/ADT/iterator.h"
24#include "llvm/Support/Compiler.h"
25#include "llvm/Support/MathExtras.h"
26#include <array>
27#include <initializer_list>
28#include <string>
29#include <vector>
30
31namespace llvm {
32
33class raw_ostream;
34class Triple;
35
36const unsigned MAX_SUBTARGET_WORDS = 6;
37const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
38
39/// Container class for subtarget features.
40/// This is a constexpr reimplementation of a subset of std::bitset. It would be
41/// nice to use std::bitset directly, but it doesn't support constant
42/// initialization.
43class FeatureBitset {
44 static_assert((MAX_SUBTARGET_FEATURES % 64) == 0,
45 "Should be a multiple of 64!");
46 std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits{};
47
48protected:
49 constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
50 : Bits{B} {}
51
52public:
53 constexpr FeatureBitset() = default;
54 constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
55 for (auto I : Init)
56 set(I);
57 }
58
59 FeatureBitset &set() {
60 llvm::fill(Range&: Bits, Value: -1ULL);
61 return *this;
62 }
63
64 constexpr FeatureBitset &set(unsigned I) {
65 Bits[I / 64] |= uint64_t(1) << (I % 64);
66 return *this;
67 }
68
69 constexpr FeatureBitset &reset(unsigned I) {
70 Bits[I / 64] &= ~(uint64_t(1) << (I % 64));
71 return *this;
72 }
73
74 constexpr FeatureBitset &flip(unsigned I) {
75 Bits[I / 64] ^= uint64_t(1) << (I % 64);
76 return *this;
77 }
78
79 constexpr bool operator[](unsigned I) const {
80 uint64_t Mask = uint64_t(1) << (I % 64);
81 return (Bits[I / 64] & Mask) != 0;
82 }
83
84 constexpr bool test(unsigned I) const { return (*this)[I]; }
85
86 constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
87
88 /// Index of the first set bit at or after Begin, or size() if none.
89 unsigned find_first_from(unsigned Begin) const {
90 for (unsigned Word = Begin / 64; Word < Bits.size(); ++Word) {
91 uint64_t Masked = Bits[Word] & maskTrailingZeros<uint64_t>(N: Begin % 64);
92 if (Masked)
93 return Word * 64 + llvm::countr_zero(Val: Masked);
94 Begin = (Word + 1) * 64;
95 }
96 return size();
97 }
98
99 /// Yields the index of each set bit, skipping unset bits via countr_zero.
100 class const_iterator
101 : public iterator_facade_base<const_iterator, std::forward_iterator_tag,
102 const unsigned, std::ptrdiff_t,
103 const unsigned *, unsigned> {
104 const FeatureBitset *Parent = nullptr;
105 unsigned Index = 0;
106
107 public:
108 const_iterator() = default;
109 const_iterator(const FeatureBitset &Parent, unsigned Index)
110 : Parent(&Parent), Index(Index) {}
111
112 unsigned operator*() const { return Index; }
113 const_iterator &operator++() {
114 Index = Parent->find_first_from(Begin: Index + 1);
115 return *this;
116 }
117 bool operator==(const const_iterator &RHS) const {
118 return Index == RHS.Index;
119 }
120 };
121
122 const_iterator begin() const {
123 return const_iterator(*this, find_first_from(Begin: 0));
124 }
125 const_iterator end() const { return const_iterator(*this, size()); }
126
127 bool any() const {
128 return llvm::any_of(Range: Bits, P: [](uint64_t I) { return I != 0; });
129 }
130 bool none() const { return !any(); }
131 size_t count() const {
132 size_t Count = 0;
133 for (auto B : Bits)
134 Count += llvm::popcount(Value: B);
135 return Count;
136 }
137
138 constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) {
139 for (unsigned I = 0, E = Bits.size(); I != E; ++I) {
140 Bits[I] ^= RHS.Bits[I];
141 }
142 return *this;
143 }
144 constexpr FeatureBitset operator^(const FeatureBitset &RHS) const {
145 FeatureBitset Result = *this;
146 Result ^= RHS;
147 return Result;
148 }
149
150 constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
151 for (unsigned I = 0, E = Bits.size(); I != E; ++I)
152 Bits[I] &= RHS.Bits[I];
153 return *this;
154 }
155 constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
156 FeatureBitset Result = *this;
157 Result &= RHS;
158 return Result;
159 }
160
161 constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
162 for (unsigned I = 0, E = Bits.size(); I != E; ++I) {
163 Bits[I] |= RHS.Bits[I];
164 }
165 return *this;
166 }
167 constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
168 FeatureBitset Result = *this;
169 Result |= RHS;
170 return Result;
171 }
172
173 constexpr FeatureBitset operator~() const {
174 FeatureBitset Result = *this;
175 for (auto &B : Result.Bits)
176 B = ~B;
177 return Result;
178 }
179
180 bool operator==(const FeatureBitset &RHS) const {
181 return std::equal(first1: std::begin(cont: Bits), last1: std::end(cont: Bits), first2: std::begin(cont: RHS.Bits));
182 }
183
184 bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); }
185
186 bool operator < (const FeatureBitset &Other) const {
187 for (unsigned I = 0, E = size(); I != E; ++I) {
188 bool LHS = test(I), RHS = Other.test(I);
189 if (LHS != RHS)
190 return LHS < RHS;
191 }
192 return false;
193 }
194};
195
196/// Class used to store the subtarget bits in the tables created by tablegen.
197class FeatureBitArray : public FeatureBitset {
198public:
199 constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
200 : FeatureBitset(B) {}
201
202 const FeatureBitset &getAsBitset() const { return *this; }
203};
204
205//===----------------------------------------------------------------------===//
206
207/// Manages the enabling and disabling of subtarget specific features.
208///
209/// Features are encoded as a string of the form
210/// "+attr1,+attr2,-attr3,...,+attrN"
211/// A comma separates each feature from the next (all lowercase.)
212/// Each of the remaining features is prefixed with + or - indicating whether
213/// that feature should be enabled or disabled contrary to the cpu
214/// specification.
215class SubtargetFeatures {
216 std::vector<std::string> Features; ///< Subtarget features as a vector
217
218public:
219 LLVM_ABI explicit SubtargetFeatures(StringRef Initial = "");
220
221 /// Returns features as a string.
222 LLVM_ABI std::string getString() const;
223
224 /// Adds Features.
225 LLVM_ABI void AddFeature(StringRef String, bool Enable = true);
226
227 LLVM_ABI void addFeaturesVector(const ArrayRef<std::string> OtherFeatures);
228
229 /// Returns the vector of individual subtarget features.
230 const std::vector<std::string> &getFeatures() const { return Features; }
231
232 /// Prints feature string.
233 LLVM_ABI void print(raw_ostream &OS) const;
234
235 // Dumps feature info.
236 LLVM_ABI void dump() const;
237
238 /// Adds the default features for the specified target triple.
239 LLVM_ABI void getDefaultSubtargetFeatures(const Triple &Triple);
240
241 /// Determine if a feature has a flag; '+' or '-'
242 static bool hasFlag(StringRef Feature) {
243 assert(!Feature.empty() && "Empty string");
244 // Get first character
245 char Ch = Feature[0];
246 // Check if first character is '+' or '-' flag
247 return Ch == '+' || Ch =='-';
248 }
249
250 /// Return string stripped of flag.
251 static StringRef StripFlag(StringRef Feature) {
252 return hasFlag(Feature) ? Feature.substr(Start: 1) : Feature;
253 }
254
255 /// Return true if enable flag; '+'.
256 static inline bool isEnabled(StringRef Feature) {
257 assert(!Feature.empty() && "Empty string");
258 // Get first character
259 char Ch = Feature[0];
260 // Check if first character is '+' for enabled
261 return Ch == '+';
262 }
263
264 /// Splits a string of comma separated items in to a vector of strings.
265 LLVM_ABI static void Split(std::vector<std::string> &V, StringRef S);
266};
267
268} // end namespace llvm
269
270#endif // LLVM_TARGETPARSER_SUBTARGETFEATURE_H
271