1 //===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the SubtargetFeature interface. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/MC/SubtargetFeature.h" 15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/Format.h" 18 #include "llvm/Support/raw_ostream.h" 19 #include <algorithm> 20 #include <cassert> 21 #include <cctype> 22 #include <cstdlib> 23 using namespace llvm; 24 25 //===----------------------------------------------------------------------===// 26 // Static Helper Functions 27 //===----------------------------------------------------------------------===// 28 29 /// hasFlag - Determine if a feature has a flag; '+' or '-' 30 /// 31 static inline bool hasFlag(StringRef Feature) { 32 assert(!Feature.empty() && "Empty string"); 33 // Get first character 34 char Ch = Feature[0]; 35 // Check if first character is '+' or '-' flag 36 return Ch == '+' || Ch =='-'; 37 } 38 39 /// StripFlag - Return string stripped of flag. 40 /// 41 static inline std::string StripFlag(StringRef Feature) { 42 return hasFlag(Feature) ? Feature.substr(1) : Feature; 43 } 44 45 /// isEnabled - Return true if enable flag; '+'. 46 /// 47 static inline bool isEnabled(StringRef Feature) { 48 assert(!Feature.empty() && "Empty string"); 49 // Get first character 50 char Ch = Feature[0]; 51 // Check if first character is '+' for enabled 52 return Ch == '+'; 53 } 54 55 /// Split - Splits a string of comma separated items in to a vector of strings. 56 /// 57 static void Split(std::vector<std::string> &V, StringRef S) { 58 SmallVector<StringRef, 3> Tmp; 59 S.split(Tmp, ',', -1, false /* KeepEmpty */); 60 V.assign(Tmp.begin(), Tmp.end()); 61 } 62 63 /// Adding features. 64 void SubtargetFeatures::AddFeature(StringRef String, bool Enable) { 65 // Don't add empty features. 66 if (!String.empty()) 67 // Convert to lowercase, prepend flag if we don't already have a flag. 68 Features.push_back(hasFlag(String) ? String.lower() 69 : (Enable ? "+" : "-") + String.lower()); 70 } 71 72 /// Find KV in array using binary search. 73 static const SubtargetFeatureKV *Find(StringRef S, 74 ArrayRef<SubtargetFeatureKV> A) { 75 // Binary search the array 76 auto F = std::lower_bound(A.begin(), A.end(), S); 77 // If not found then return NULL 78 if (F == A.end() || StringRef(F->Key) != S) return nullptr; 79 // Return the found array item 80 return F; 81 } 82 83 /// getLongestEntryLength - Return the length of the longest entry in the table. 84 /// 85 static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) { 86 size_t MaxLen = 0; 87 for (auto &I : Table) 88 MaxLen = std::max(MaxLen, std::strlen(I.Key)); 89 return MaxLen; 90 } 91 92 /// Display help for feature choices. 93 /// 94 static void Help(ArrayRef<SubtargetFeatureKV> CPUTable, 95 ArrayRef<SubtargetFeatureKV> FeatTable) { 96 // Determine the length of the longest CPU and Feature entries. 97 unsigned MaxCPULen = getLongestEntryLength(CPUTable); 98 unsigned MaxFeatLen = getLongestEntryLength(FeatTable); 99 100 // Print the CPU table. 101 errs() << "Available CPUs for this target:\n\n"; 102 for (auto &CPU : CPUTable) 103 errs() << format(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc); 104 errs() << '\n'; 105 106 // Print the Feature table. 107 errs() << "Available features for this target:\n\n"; 108 for (auto &Feature : FeatTable) 109 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); 110 errs() << '\n'; 111 112 errs() << "Use +feature to enable a feature, or -feature to disable it.\n" 113 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; 114 } 115 116 //===----------------------------------------------------------------------===// 117 // SubtargetFeatures Implementation 118 //===----------------------------------------------------------------------===// 119 120 SubtargetFeatures::SubtargetFeatures(StringRef Initial) { 121 // Break up string into separate features 122 Split(Features, Initial); 123 } 124 125 126 std::string SubtargetFeatures::getString() const { 127 return join(Features.begin(), Features.end(), ","); 128 } 129 130 /// SetImpliedBits - For each feature that is (transitively) implied by this 131 /// feature, set it. 132 /// 133 static 134 void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV *FeatureEntry, 135 ArrayRef<SubtargetFeatureKV> FeatureTable) { 136 for (auto &FE : FeatureTable) { 137 if (FeatureEntry->Value == FE.Value) continue; 138 139 if ((FeatureEntry->Implies & FE.Value).any()) { 140 Bits |= FE.Value; 141 SetImpliedBits(Bits, &FE, FeatureTable); 142 } 143 } 144 } 145 146 /// ClearImpliedBits - For each feature that (transitively) implies this 147 /// feature, clear it. 148 /// 149 static 150 void ClearImpliedBits(FeatureBitset &Bits, 151 const SubtargetFeatureKV *FeatureEntry, 152 ArrayRef<SubtargetFeatureKV> FeatureTable) { 153 for (auto &FE : FeatureTable) { 154 if (FeatureEntry->Value == FE.Value) continue; 155 156 if ((FE.Implies & FeatureEntry->Value).any()) { 157 Bits &= ~FE.Value; 158 ClearImpliedBits(Bits, &FE, FeatureTable); 159 } 160 } 161 } 162 163 /// ToggleFeature - Toggle a feature and returns the newly updated feature 164 /// bits. 165 FeatureBitset 166 SubtargetFeatures::ToggleFeature(FeatureBitset Bits, StringRef Feature, 167 ArrayRef<SubtargetFeatureKV> FeatureTable) { 168 169 // Find feature in table. 170 const SubtargetFeatureKV *FeatureEntry = 171 Find(StripFlag(Feature), FeatureTable); 172 // If there is a match 173 if (FeatureEntry) { 174 if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) { 175 Bits &= ~FeatureEntry->Value; 176 // For each feature that implies this, clear it. 177 ClearImpliedBits(Bits, FeatureEntry, FeatureTable); 178 } else { 179 Bits |= FeatureEntry->Value; 180 181 // For each feature that this implies, set it. 182 SetImpliedBits(Bits, FeatureEntry, FeatureTable); 183 } 184 } else { 185 errs() << "'" << Feature 186 << "' is not a recognized feature for this target" 187 << " (ignoring feature)\n"; 188 } 189 190 return Bits; 191 } 192 193 FeatureBitset 194 SubtargetFeatures::ApplyFeatureFlag(FeatureBitset Bits, StringRef Feature, 195 ArrayRef<SubtargetFeatureKV> FeatureTable) { 196 197 assert(hasFlag(Feature)); 198 199 // Find feature in table. 200 const SubtargetFeatureKV *FeatureEntry = 201 Find(StripFlag(Feature), FeatureTable); 202 // If there is a match 203 if (FeatureEntry) { 204 // Enable/disable feature in bits 205 if (isEnabled(Feature)) { 206 Bits |= FeatureEntry->Value; 207 208 // For each feature that this implies, set it. 209 SetImpliedBits(Bits, FeatureEntry, FeatureTable); 210 } else { 211 Bits &= ~FeatureEntry->Value; 212 213 // For each feature that implies this, clear it. 214 ClearImpliedBits(Bits, FeatureEntry, FeatureTable); 215 } 216 } else { 217 errs() << "'" << Feature 218 << "' is not a recognized feature for this target" 219 << " (ignoring feature)\n"; 220 } 221 222 return Bits; 223 } 224 225 226 /// getFeatureBits - Get feature bits a CPU. 227 /// 228 FeatureBitset 229 SubtargetFeatures::getFeatureBits(StringRef CPU, 230 ArrayRef<SubtargetFeatureKV> CPUTable, 231 ArrayRef<SubtargetFeatureKV> FeatureTable) { 232 233 if (CPUTable.empty() || FeatureTable.empty()) 234 return FeatureBitset(); 235 236 #ifndef NDEBUG 237 for (size_t i = 1, e = CPUTable.size(); i != e; ++i) { 238 assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && 239 "CPU table is not sorted"); 240 } 241 for (size_t i = 1, e = FeatureTable.size(); i != e; ++i) { 242 assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && 243 "CPU features table is not sorted"); 244 } 245 #endif 246 // Resulting bits 247 FeatureBitset Bits; 248 249 // Check if help is needed 250 if (CPU == "help") 251 Help(CPUTable, FeatureTable); 252 253 // Find CPU entry if CPU name is specified. 254 else if (!CPU.empty()) { 255 const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable); 256 257 // If there is a match 258 if (CPUEntry) { 259 // Set base feature bits 260 Bits = CPUEntry->Value; 261 262 // Set the feature implied by this CPU feature, if any. 263 for (auto &FE : FeatureTable) { 264 if ((CPUEntry->Value & FE.Value).any()) 265 SetImpliedBits(Bits, &FE, FeatureTable); 266 } 267 } else { 268 errs() << "'" << CPU 269 << "' is not a recognized processor for this target" 270 << " (ignoring processor)\n"; 271 } 272 } 273 274 // Iterate through each feature 275 for (auto &Feature : Features) { 276 // Check for help 277 if (Feature == "+help") 278 Help(CPUTable, FeatureTable); 279 280 Bits = ApplyFeatureFlag(Bits, Feature, FeatureTable); 281 } 282 283 return Bits; 284 } 285 286 /// print - Print feature string. 287 /// 288 void SubtargetFeatures::print(raw_ostream &OS) const { 289 for (auto &F : Features) 290 OS << F << " "; 291 OS << "\n"; 292 } 293 294 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 295 /// dump - Dump feature info. 296 /// 297 void SubtargetFeatures::dump() const { 298 print(dbgs()); 299 } 300 #endif 301 302 /// Adds the default features for the specified target triple. 303 /// 304 /// FIXME: This is an inelegant way of specifying the features of a 305 /// subtarget. It would be better if we could encode this information 306 /// into the IR. See <rdar://5972456>. 307 /// 308 void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) { 309 if (Triple.getVendor() == Triple::Apple) { 310 if (Triple.getArch() == Triple::ppc) { 311 // powerpc-apple-* 312 AddFeature("altivec"); 313 } else if (Triple.getArch() == Triple::ppc64) { 314 // powerpc64-apple-* 315 AddFeature("64bit"); 316 AddFeature("altivec"); 317 } 318 } 319 } 320