LLVM API Documentation
00001 //===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the SubtargetFeature interface. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/MC/SubtargetFeature.h" 00015 #include "llvm/Support/Debug.h" 00016 #include "llvm/Support/Format.h" 00017 #include "llvm/Support/raw_ostream.h" 00018 #include <algorithm> 00019 #include <cassert> 00020 #include <cctype> 00021 #include <cstdlib> 00022 using namespace llvm; 00023 00024 //===----------------------------------------------------------------------===// 00025 // Static Helper Functions 00026 //===----------------------------------------------------------------------===// 00027 00028 /// hasFlag - Determine if a feature has a flag; '+' or '-' 00029 /// 00030 static inline bool hasFlag(StringRef Feature) { 00031 assert(!Feature.empty() && "Empty string"); 00032 // Get first character 00033 char Ch = Feature[0]; 00034 // Check if first character is '+' or '-' flag 00035 return Ch == '+' || Ch =='-'; 00036 } 00037 00038 /// StripFlag - Return string stripped of flag. 00039 /// 00040 static inline std::string StripFlag(StringRef Feature) { 00041 return hasFlag(Feature) ? Feature.substr(1) : Feature; 00042 } 00043 00044 /// isEnabled - Return true if enable flag; '+'. 00045 /// 00046 static inline bool isEnabled(StringRef Feature) { 00047 assert(!Feature.empty() && "Empty string"); 00048 // Get first character 00049 char Ch = Feature[0]; 00050 // Check if first character is '+' for enabled 00051 return Ch == '+'; 00052 } 00053 00054 /// Split - Splits a string of comma separated items in to a vector of strings. 00055 /// 00056 static void Split(std::vector<std::string> &V, StringRef S) { 00057 SmallVector<StringRef, 3> Tmp; 00058 S.split(Tmp, ",", -1, false /* KeepEmpty */); 00059 V.assign(Tmp.begin(), Tmp.end()); 00060 } 00061 00062 /// Join a vector of strings to a string with a comma separating each element. 00063 /// 00064 static std::string Join(const std::vector<std::string> &V) { 00065 // Start with empty string. 00066 std::string Result; 00067 // If the vector is not empty 00068 if (!V.empty()) { 00069 // Start with the first feature 00070 Result = V[0]; 00071 // For each successive feature 00072 for (size_t i = 1; i < V.size(); i++) { 00073 // Add a comma 00074 Result += ","; 00075 // Add the feature 00076 Result += V[i]; 00077 } 00078 } 00079 // Return the features string 00080 return Result; 00081 } 00082 00083 /// Adding features. 00084 void SubtargetFeatures::AddFeature(StringRef String) { 00085 // Don't add empty features or features we already have. 00086 if (!String.empty()) 00087 // Convert to lowercase, prepend flag if we don't already have a flag. 00088 Features.push_back(hasFlag(String) ? String.str() : "+" + String.lower()); 00089 } 00090 00091 /// Find KV in array using binary search. 00092 static const SubtargetFeatureKV *Find(StringRef S, 00093 ArrayRef<SubtargetFeatureKV> A) { 00094 // Binary search the array 00095 auto F = std::lower_bound(A.begin(), A.end(), S); 00096 // If not found then return NULL 00097 if (F == A.end() || StringRef(F->Key) != S) return nullptr; 00098 // Return the found array item 00099 return F; 00100 } 00101 00102 /// getLongestEntryLength - Return the length of the longest entry in the table. 00103 /// 00104 static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) { 00105 size_t MaxLen = 0; 00106 for (auto &I : Table) 00107 MaxLen = std::max(MaxLen, std::strlen(I.Key)); 00108 return MaxLen; 00109 } 00110 00111 /// Display help for feature choices. 00112 /// 00113 static void Help(ArrayRef<SubtargetFeatureKV> CPUTable, 00114 ArrayRef<SubtargetFeatureKV> FeatTable) { 00115 // Determine the length of the longest CPU and Feature entries. 00116 unsigned MaxCPULen = getLongestEntryLength(CPUTable); 00117 unsigned MaxFeatLen = getLongestEntryLength(FeatTable); 00118 00119 // Print the CPU table. 00120 errs() << "Available CPUs for this target:\n\n"; 00121 for (auto &CPU : CPUTable) 00122 errs() << format(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc); 00123 errs() << '\n'; 00124 00125 // Print the Feature table. 00126 errs() << "Available features for this target:\n\n"; 00127 for (auto &Feature : FeatTable) 00128 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); 00129 errs() << '\n'; 00130 00131 errs() << "Use +feature to enable a feature, or -feature to disable it.\n" 00132 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; 00133 } 00134 00135 //===----------------------------------------------------------------------===// 00136 // SubtargetFeatures Implementation 00137 //===----------------------------------------------------------------------===// 00138 00139 SubtargetFeatures::SubtargetFeatures(StringRef Initial) { 00140 // Break up string into separate features 00141 Split(Features, Initial); 00142 } 00143 00144 00145 std::string SubtargetFeatures::getString() const { 00146 return Join(Features); 00147 } 00148 00149 /// SetImpliedBits - For each feature that is (transitively) implied by this 00150 /// feature, set it. 00151 /// 00152 static 00153 void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, 00154 ArrayRef<SubtargetFeatureKV> FeatureTable) { 00155 for (auto &FE : FeatureTable) { 00156 if (FeatureEntry->Value == FE.Value) continue; 00157 00158 if (FeatureEntry->Implies & FE.Value) { 00159 Bits |= FE.Value; 00160 SetImpliedBits(Bits, &FE, FeatureTable); 00161 } 00162 } 00163 } 00164 00165 /// ClearImpliedBits - For each feature that (transitively) implies this 00166 /// feature, clear it. 00167 /// 00168 static 00169 void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, 00170 ArrayRef<SubtargetFeatureKV> FeatureTable) { 00171 for (auto &FE : FeatureTable) { 00172 if (FeatureEntry->Value == FE.Value) continue; 00173 00174 if (FE.Implies & FeatureEntry->Value) { 00175 Bits &= ~FE.Value; 00176 ClearImpliedBits(Bits, &FE, FeatureTable); 00177 } 00178 } 00179 } 00180 00181 /// ToggleFeature - Toggle a feature and returns the newly updated feature 00182 /// bits. 00183 uint64_t 00184 SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature, 00185 ArrayRef<SubtargetFeatureKV> FeatureTable) { 00186 00187 // Find feature in table. 00188 const SubtargetFeatureKV *FeatureEntry = 00189 Find(StripFlag(Feature), FeatureTable); 00190 // If there is a match 00191 if (FeatureEntry) { 00192 if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) { 00193 Bits &= ~FeatureEntry->Value; 00194 00195 // For each feature that implies this, clear it. 00196 ClearImpliedBits(Bits, FeatureEntry, FeatureTable); 00197 } else { 00198 Bits |= FeatureEntry->Value; 00199 00200 // For each feature that this implies, set it. 00201 SetImpliedBits(Bits, FeatureEntry, FeatureTable); 00202 } 00203 } else { 00204 errs() << "'" << Feature 00205 << "' is not a recognized feature for this target" 00206 << " (ignoring feature)\n"; 00207 } 00208 00209 return Bits; 00210 } 00211 00212 00213 /// getFeatureBits - Get feature bits a CPU. 00214 /// 00215 uint64_t 00216 SubtargetFeatures::getFeatureBits(StringRef CPU, 00217 ArrayRef<SubtargetFeatureKV> CPUTable, 00218 ArrayRef<SubtargetFeatureKV> FeatureTable) { 00219 00220 if (CPUTable.empty() || FeatureTable.empty()) 00221 return 0; 00222 00223 #ifndef NDEBUG 00224 for (size_t i = 1, e = CPUTable.size(); i != e; ++i) { 00225 assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && 00226 "CPU table is not sorted"); 00227 } 00228 for (size_t i = 1, e = FeatureTable.size(); i != e; ++i) { 00229 assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && 00230 "CPU features table is not sorted"); 00231 } 00232 #endif 00233 uint64_t Bits = 0; // Resulting bits 00234 00235 // Check if help is needed 00236 if (CPU == "help") 00237 Help(CPUTable, FeatureTable); 00238 00239 // Find CPU entry if CPU name is specified. 00240 else if (!CPU.empty()) { 00241 const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable); 00242 00243 // If there is a match 00244 if (CPUEntry) { 00245 // Set base feature bits 00246 Bits = CPUEntry->Value; 00247 00248 // Set the feature implied by this CPU feature, if any. 00249 for (auto &FE : FeatureTable) { 00250 if (CPUEntry->Value & FE.Value) 00251 SetImpliedBits(Bits, &FE, FeatureTable); 00252 } 00253 } else { 00254 errs() << "'" << CPU 00255 << "' is not a recognized processor for this target" 00256 << " (ignoring processor)\n"; 00257 } 00258 } 00259 00260 // Iterate through each feature 00261 for (auto &Feature : Features) { 00262 // Check for help 00263 if (Feature == "+help") 00264 Help(CPUTable, FeatureTable); 00265 00266 // Find feature in table. 00267 const SubtargetFeatureKV *FeatureEntry = 00268 Find(StripFlag(Feature), FeatureTable); 00269 // If there is a match 00270 if (FeatureEntry) { 00271 // Enable/disable feature in bits 00272 if (isEnabled(Feature)) { 00273 Bits |= FeatureEntry->Value; 00274 00275 // For each feature that this implies, set it. 00276 SetImpliedBits(Bits, FeatureEntry, FeatureTable); 00277 } else { 00278 Bits &= ~FeatureEntry->Value; 00279 00280 // For each feature that implies this, clear it. 00281 ClearImpliedBits(Bits, FeatureEntry, FeatureTable); 00282 } 00283 } else { 00284 errs() << "'" << Feature 00285 << "' is not a recognized feature for this target" 00286 << " (ignoring feature)\n"; 00287 } 00288 } 00289 00290 return Bits; 00291 } 00292 00293 /// print - Print feature string. 00294 /// 00295 void SubtargetFeatures::print(raw_ostream &OS) const { 00296 for (auto &F : Features) 00297 OS << F << " "; 00298 OS << "\n"; 00299 } 00300 00301 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 00302 /// dump - Dump feature info. 00303 /// 00304 void SubtargetFeatures::dump() const { 00305 print(dbgs()); 00306 } 00307 #endif 00308 00309 /// Adds the default features for the specified target triple. 00310 /// 00311 /// FIXME: This is an inelegant way of specifying the features of a 00312 /// subtarget. It would be better if we could encode this information 00313 /// into the IR. See <rdar://5972456>. 00314 /// 00315 void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) { 00316 if (Triple.getVendor() == Triple::Apple) { 00317 if (Triple.getArch() == Triple::ppc) { 00318 // powerpc-apple-* 00319 AddFeature("altivec"); 00320 } else if (Triple.getArch() == Triple::ppc64) { 00321 // powerpc64-apple-* 00322 AddFeature("64bit"); 00323 AddFeature("altivec"); 00324 } 00325 } 00326 }