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