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

source code of llvm/include/llvm/MC/SubtargetFeature.h