2
0

SubtargetFeature.cpp 9.6 KB

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