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 28 namespace llvm { 29 30 class raw_ostream; 31 class Triple; 32 33 const unsigned MAX_SUBTARGET_WORDS = 3; 34 const 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. 40 class 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 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 for (unsigned I = 0; I != B.size(); ++I) 49 Bits[I] = B[I]; 50 } 51 52 public: 53 constexpr FeatureBitset() = default; FeatureBitset(std::initializer_list<unsigned> Init)54 constexpr FeatureBitset(std::initializer_list<unsigned> Init) { 55 for (auto I : Init) 56 set(I); 57 } 58 set()59 FeatureBitset &set() { 60 std::fill(std::begin(Bits), std::end(Bits), -1ULL); 61 return *this; 62 } 63 set(unsigned I)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 reset(unsigned I)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 flip(unsigned I)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 test(unsigned I)90 constexpr bool test(unsigned I) const { return (*this)[I]; } 91 size()92 constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; } 93 any()94 bool any() const { 95 return llvm::any_of(Bits, [](uint64_t I) { return I != 0; }); 96 } none()97 bool none() const { return !any(); } count()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. 165 class FeatureBitArray : public FeatureBitset { 166 public: FeatureBitArray(const std::array<uint64_t,MAX_SUBTARGET_WORDS> & B)167 constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) 168 : FeatureBitset(B) {} 169 getAsBitset()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. 183 class SubtargetFeatures { 184 std::vector<std::string> Features; ///< Subtarget features as a vector 185 186 public: 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. 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 std::string 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