1 //===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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.
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_MC_SUBTARGETFEATURE_H
18 #define LLVM_MC_SUBTARGETFEATURE_H
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/MathExtras.h"
24 #include <initializer_list>
33 const unsigned MAX_SUBTARGET_WORDS
= 3;
34 const unsigned MAX_SUBTARGET_FEATURES
= MAX_SUBTARGET_WORDS
* 64;
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
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
] = {};
47 constexpr FeatureBitset(const std::array
<uint64_t, MAX_SUBTARGET_WORDS
> &B
) {
48 for (unsigned I
= 0; I
!= B
.size(); ++I
)
53 constexpr FeatureBitset() = default;
54 constexpr FeatureBitset(std::initializer_list
<unsigned> Init
) {
59 FeatureBitset
&set() {
60 std::fill(std::begin(Bits
), std::end(Bits
), -1ULL);
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
;
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
;
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
;
85 constexpr bool operator[](unsigned I
) const {
86 uint64_t Mask
= uint64_t(1) << (I
% 64);
87 return (Bits
[I
/ 64] & Mask
) != 0;
90 constexpr bool test(unsigned I
) const { return (*this)[I
]; }
92 constexpr size_t size() const { return MAX_SUBTARGET_FEATURES
; }
95 return llvm::any_of(Bits
, [](uint64_t I
) { return I
!= 0; });
97 bool none() const { return !any(); }
98 size_t count() const {
101 Count
+= countPopulation(B
);
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
];
111 constexpr FeatureBitset
operator^(const FeatureBitset
&RHS
) const {
112 FeatureBitset Result
= *this;
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
];
123 constexpr FeatureBitset
operator&(const FeatureBitset
&RHS
) const {
124 FeatureBitset Result
= *this;
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
];
135 constexpr FeatureBitset
operator|(const FeatureBitset
&RHS
) const {
136 FeatureBitset Result
= *this;
141 constexpr FeatureBitset
operator~() const {
142 FeatureBitset Result
= *this;
143 for (auto &B
: Result
.Bits
)
148 bool operator==(const FeatureBitset
&RHS
) const {
149 return std::equal(std::begin(Bits
), std::end(Bits
), std::begin(RHS
.Bits
));
152 bool operator!=(const FeatureBitset
&RHS
) const { return !(*this == RHS
); }
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
);
164 /// Class used to store the subtarget bits in the tables created by tablegen.
165 class FeatureBitArray
: public FeatureBitset
{
167 constexpr FeatureBitArray(const std::array
<uint64_t, MAX_SUBTARGET_WORDS
> &B
)
168 : FeatureBitset(B
) {}
170 const FeatureBitset
&getAsBitset() const { return *this; }
173 //===----------------------------------------------------------------------===//
175 /// Manages the enabling and disabling of subtarget specific features.
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
183 class SubtargetFeatures
{
184 std::vector
<std::string
> Features
; ///< Subtarget features as a vector
187 explicit SubtargetFeatures(StringRef Initial
= "");
189 /// Returns features as a string.
190 std::string
getString() const;
193 void AddFeature(StringRef String
, bool Enable
= true);
195 /// Returns the vector of individual subtarget features.
196 const std::vector
<std::string
> &getFeatures() const { return Features
; }
198 /// Prints feature string.
199 void print(raw_ostream
&OS
) const;
201 // Dumps feature info.
204 /// Adds the default features for the specified target triple.
205 void getDefaultSubtargetFeatures(const Triple
& Triple
);
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
=='-';
216 /// Return string stripped of flag.
217 static std::string
StripFlag(StringRef Feature
) {
218 return hasFlag(Feature
) ? Feature
.substr(1) : Feature
;
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
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
);
234 } // end namespace llvm
236 #endif // LLVM_MC_SUBTARGETFEATURE_H