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