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 update the feature bits. 164 void 165 SubtargetFeatures::ToggleFeature(FeatureBitset &Bits, StringRef Feature, 166 ArrayRef<SubtargetFeatureKV> FeatureTable) { 167 168 // Find feature in table. 169 const SubtargetFeatureKV *FeatureEntry = 170 Find(StripFlag(Feature), FeatureTable); 171 // If there is a match 172 if (FeatureEntry) { 173 if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) { 174 Bits &= ~FeatureEntry->Value; 175 // For each feature that implies this, clear it. 176 ClearImpliedBits(Bits, FeatureEntry, FeatureTable); 177 } else { 178 Bits |= FeatureEntry->Value; 179 180 // For each feature that this implies, set it. 181 SetImpliedBits(Bits, FeatureEntry, FeatureTable); 182 } 183 } else { 184 errs() << "'" << Feature 185 << "' is not a recognized feature for this target" 186 << " (ignoring feature)\n"; 187 } 188 } 189 190 void SubtargetFeatures::ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, 191 ArrayRef<SubtargetFeatureKV> FeatureTable) { 192 193 assert(hasFlag(Feature)); 194 195 // Find feature in table. 196 const SubtargetFeatureKV *FeatureEntry = 197 Find(StripFlag(Feature), FeatureTable); 198 // If there is a match 199 if (FeatureEntry) { 200 // Enable/disable feature in bits 201 if (isEnabled(Feature)) { 202 Bits |= FeatureEntry->Value; 203 204 // For each feature that this implies, set it. 205 SetImpliedBits(Bits, FeatureEntry, FeatureTable); 206 } else { 207 Bits &= ~FeatureEntry->Value; 208 209 // For each feature that implies this, clear it. 210 ClearImpliedBits(Bits, FeatureEntry, FeatureTable); 211 } 212 } else { 213 errs() << "'" << Feature 214 << "' is not a recognized feature for this target" 215 << " (ignoring feature)\n"; 216 } 217 } 218 219 220 /// getFeatureBits - Get feature bits a CPU. 221 /// 222 FeatureBitset 223 SubtargetFeatures::getFeatureBits(StringRef CPU, 224 ArrayRef<SubtargetFeatureKV> CPUTable, 225 ArrayRef<SubtargetFeatureKV> FeatureTable) { 226 227 if (CPUTable.empty() || FeatureTable.empty()) 228 return FeatureBitset(); 229 230 #ifndef NDEBUG 231 assert(std::is_sorted(std::begin(CPUTable), std::end(CPUTable)) && 232 "CPU table is not sorted"); 233 assert(std::is_sorted(std::begin(FeatureTable), std::end(FeatureTable)) && 234 "CPU features table is not sorted"); 235 #endif 236 // Resulting bits 237 FeatureBitset Bits; 238 239 // Check if help is needed 240 if (CPU == "help") 241 Help(CPUTable, FeatureTable); 242 243 // Find CPU entry if CPU name is specified. 244 else if (!CPU.empty()) { 245 const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable); 246 247 // If there is a match 248 if (CPUEntry) { 249 // Set base feature bits 250 Bits = CPUEntry->Value; 251 252 // Set the feature implied by this CPU feature, if any. 253 for (auto &FE : FeatureTable) { 254 if ((CPUEntry->Value & FE.Value).any()) 255 SetImpliedBits(Bits, &FE, FeatureTable); 256 } 257 } else { 258 errs() << "'" << CPU 259 << "' is not a recognized processor for this target" 260 << " (ignoring processor)\n"; 261 } 262 } 263 264 // Iterate through each feature 265 for (auto &Feature : Features) { 266 // Check for help 267 if (Feature == "+help") 268 Help(CPUTable, FeatureTable); 269 270 ApplyFeatureFlag(Bits, Feature, FeatureTable); 271 } 272 273 return Bits; 274 } 275 276 /// print - Print feature string. 277 /// 278 void SubtargetFeatures::print(raw_ostream &OS) const { 279 for (auto &F : Features) 280 OS << F << " "; 281 OS << "\n"; 282 } 283 284 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 285 /// dump - Dump feature info. 286 /// 287 LLVM_DUMP_METHOD void SubtargetFeatures::dump() const { 288 print(dbgs()); 289 } 290 #endif 291 292 /// Adds the default features for the specified target triple. 293 /// 294 /// FIXME: This is an inelegant way of specifying the features of a 295 /// subtarget. It would be better if we could encode this information 296 /// into the IR. See <rdar://5972456>. 297 /// 298 void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) { 299 if (Triple.getVendor() == Triple::Apple) { 300 if (Triple.getArch() == Triple::ppc) { 301 // powerpc-apple-* 302 AddFeature("altivec"); 303 } else if (Triple.getArch() == Triple::ppc64) { 304 // powerpc64-apple-* 305 AddFeature("64bit"); 306 AddFeature("altivec"); 307 } 308 } 309 } 310