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