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