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