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