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