1b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
2b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//
3b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//                     The LLVM Compiler Infrastructure
4b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//
8b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//===----------------------------------------------------------------------===//
9b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//
10b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey// This file implements the SubtargetFeature interface.
11b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//
12b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey//===----------------------------------------------------------------------===//
13b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
14ab8be96fd30ca9396e6b84fdddf1ac6208984cadEvan Cheng#include "llvm/MC/SubtargetFeature.h"
159759c305c2dbca2ba46645638ed39d5cb40b66d1David Greene#include "llvm/Support/Debug.h"
16962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer#include "llvm/Support/Format.h"
17e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner#include "llvm/Support/raw_ostream.h"
18b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey#include <algorithm>
19b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey#include <cassert>
207cd57f4c452c39ee595de19633787ec37933eb34Jeff Cohen#include <cctype>
21476b242fe7a61e5f9ac6214b0bc5c680d24f152eNick Lewycky#include <cstdlib>
22b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskeyusing namespace llvm;
23b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
2454195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner//===----------------------------------------------------------------------===//
2554195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner//                          Static Helper Functions
2654195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner//===----------------------------------------------------------------------===//
2754195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
2854195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner/// hasFlag - Determine if a feature has a flag; '+' or '-'
2954195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
30e1bff38386b0af24b5564c3d20888c7bbb045099Evan Chengstatic inline bool hasFlag(const StringRef Feature) {
3154195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  assert(!Feature.empty() && "Empty string");
3254195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  // Get first character
3354195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  char Ch = Feature[0];
3454195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  // Check if first character is '+' or '-' flag
3554195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  return Ch == '+' || Ch =='-';
3654195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner}
3754195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
3854195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner/// StripFlag - Return string stripped of flag.
3954195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
40e1bff38386b0af24b5564c3d20888c7bbb045099Evan Chengstatic inline std::string StripFlag(const StringRef Feature) {
4154195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  return hasFlag(Feature) ? Feature.substr(1) : Feature;
4254195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner}
4354195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
4454195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner/// isEnabled - Return true if enable flag; '+'.
4554195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
46e1bff38386b0af24b5564c3d20888c7bbb045099Evan Chengstatic inline bool isEnabled(const StringRef Feature) {
4754195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  assert(!Feature.empty() && "Empty string");
4854195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  // Get first character
4954195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  char Ch = Feature[0];
5054195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  // Check if first character is '+' for enabled
5154195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  return Ch == '+';
5254195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner}
5354195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
5454195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner/// PrependFlag - Return a string with a prepended flag; '+' or '-'.
5554195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
5624e11afad266498ca447649b8522e01ac2073798Francois Pichetstatic inline std::string PrependFlag(const StringRef Feature,
57e1bff38386b0af24b5564c3d20888c7bbb045099Evan Cheng                                    bool IsEnabled) {
5854195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  assert(!Feature.empty() && "Empty string");
59e1bff38386b0af24b5564c3d20888c7bbb045099Evan Cheng  if (hasFlag(Feature))
60e1bff38386b0af24b5564c3d20888c7bbb045099Evan Cheng    return Feature;
61e1bff38386b0af24b5564c3d20888c7bbb045099Evan Cheng  std::string Prefix = IsEnabled ? "+" : "-";
62e1bff38386b0af24b5564c3d20888c7bbb045099Evan Cheng  Prefix += Feature;
6324e11afad266498ca447649b8522e01ac2073798Francois Pichet  return Prefix;
6454195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner}
6554195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
6654195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner/// Split - Splits a string of comma separated items in to a vector of strings.
6754195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
68e1bff38386b0af24b5564c3d20888c7bbb045099Evan Chengstatic void Split(std::vector<std::string> &V, const StringRef S) {
69276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng  if (S.empty())
70276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng    return;
71276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng
72b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // Start at beginning of string.
73b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  size_t Pos = 0;
74b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  while (true) {
75b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    // Find the next comma
76b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    size_t Comma = S.find(',', Pos);
77f451cb870efcf9e0302d25ed05f4cac6bb494e42Dan Gohman    // If no comma found then the rest of the string is used
78b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    if (Comma == std::string::npos) {
79b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      // Add string to vector
80b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      V.push_back(S.substr(Pos));
81b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      break;
82b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    }
83b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    // Otherwise add substring to vector
84b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    V.push_back(S.substr(Pos, Comma - Pos));
85b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    // Advance to next item
86b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    Pos = Comma + 1;
87b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  }
88b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey}
89b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
90b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey/// Join a vector of strings to a string with a comma separating each element.
9154195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
9254195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattnerstatic std::string Join(const std::vector<std::string> &V) {
93b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // Start with empty string.
94b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  std::string Result;
952684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach  // If the vector is not empty
96b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  if (!V.empty()) {
97276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng    // Start with the first feature
98b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    Result = V[0];
99b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    // For each successive feature
100b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    for (size_t i = 1; i < V.size(); i++) {
101b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      // Add a comma
102b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      Result += ",";
103b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      // Add the feature
104b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      Result += V[i];
105b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    }
106b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  }
1072684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach  // Return the features string
108b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  return Result;
109b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey}
110b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
111b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey/// Adding features.
112e1bff38386b0af24b5564c3d20888c7bbb045099Evan Chengvoid SubtargetFeatures::AddFeature(const StringRef String,
113b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey                                   bool IsEnabled) {
114b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // Don't add empty features
115b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  if (!String.empty()) {
116b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    // Convert to lowercase, prepend flag and add to vector
117590853667345d6fb191764b9d0bd2ff13589e3a3Benjamin Kramer    Features.push_back(PrependFlag(String.lower(), IsEnabled));
118b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  }
119b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey}
120b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
12134bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey/// Find KV in array using binary search.
122e1bff38386b0af24b5564c3d20888c7bbb045099Evan Chengtemplate<typename T> const T *Find(const StringRef S, const T *A, size_t L) {
1239471c8a93b117d8ac01c4ef1cb9faa583e03dec0Jeff Cohen  // Make the lower bound element we're looking for
1249471c8a93b117d8ac01c4ef1cb9faa583e03dec0Jeff Cohen  T KV;
125e1bff38386b0af24b5564c3d20888c7bbb045099Evan Cheng  KV.Key = S.data();
126b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // Determine the end of the array
12734bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  const T *Hi = A + L;
128b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // Binary search the array
1299471c8a93b117d8ac01c4ef1cb9faa583e03dec0Jeff Cohen  const T *F = std::lower_bound(A, Hi, KV);
130b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // If not found then return NULL
1314d9af61a48639f37f1e0db745b26e4bf9ccdf1a0Evan Cheng  if (F == Hi || StringRef(F->Key) != S) return NULL;
132b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // Return the found array item
133b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  return F;
134b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey}
135b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
1363e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner/// getLongestEntryLength - Return the length of the longest entry in the table.
13754195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
1383e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattnerstatic size_t getLongestEntryLength(const SubtargetFeatureKV *Table,
1393e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner                                    size_t Size) {
14054195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  size_t MaxLen = 0;
1413e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  for (size_t i = 0; i < Size; i++)
14254195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner    MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
1433e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  return MaxLen;
1443e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner}
145ba76c21858bac5fd953d4dbe2f0624d8e884c7b5Chris Lattner
1463e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner/// Display help for feature choices.
1473e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner///
1483e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattnerstatic void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize,
1493e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner                 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) {
1503e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  // Determine the length of the longest CPU and Feature entries.
1513e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  unsigned MaxCPULen  = getLongestEntryLength(CPUTable, CPUTableSize);
1523e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize);
153ba76c21858bac5fd953d4dbe2f0624d8e884c7b5Chris Lattner
1543e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  // Print the CPU table.
155e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner  errs() << "Available CPUs for this target:\n\n";
1563e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  for (size_t i = 0; i != CPUTableSize; i++)
157962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer    errs() << format("  %-*s - %s.\n",
158962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer                     MaxCPULen, CPUTable[i].Key, CPUTable[i].Desc);
159962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer  errs() << '\n';
160962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer
1613e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  // Print the Feature table.
162e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner  errs() << "Available features for this target:\n\n";
1633e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner  for (size_t i = 0; i != FeatTableSize; i++)
164962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer    errs() << format("  %-*s - %s.\n",
165962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer                     MaxFeatLen, FeatTable[i].Key, FeatTable[i].Desc);
166962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer  errs() << '\n';
167962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer
168e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
169962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer            "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
1702402123413080aee8e9418e4f08b8613ef5cc360Nick Lewycky  std::exit(1);
17154195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner}
17254195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
17354195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner//===----------------------------------------------------------------------===//
17454195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner//                    SubtargetFeatures Implementation
17554195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner//===----------------------------------------------------------------------===//
17654195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
177e1bff38386b0af24b5564c3d20888c7bbb045099Evan ChengSubtargetFeatures::SubtargetFeatures(const StringRef Initial) {
17854195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  // Break up string into separate features
17954195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  Split(Features, Initial);
180839615a510c582ddcdb09a8e2934f30775daa032Jim Laskey}
181839615a510c582ddcdb09a8e2934f30775daa032Jim Laskey
18254195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
1833f9b9eb57dafc2a25a6e3d9ee570bd5a884b11e3Rafael Espindolastd::string SubtargetFeatures::getString() const {
18454195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner  return Join(Features);
18554195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner}
18654195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner
1874222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling/// SetImpliedBits - For each feature that is (transitively) implied by this
1884222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling/// feature, set it.
18941a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov///
1904222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendlingstatic
191b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Chengvoid SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
1924222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling                    const SubtargetFeatureKV *FeatureTable,
1934222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling                    size_t FeatureTableSize) {
1944222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling  for (size_t i = 0; i < FeatureTableSize; ++i) {
1954222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const SubtargetFeatureKV &FE = FeatureTable[i];
1964222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
1974222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    if (FeatureEntry->Value == FE.Value) continue;
1984222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
1994222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    if (FeatureEntry->Implies & FE.Value) {
2004222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      Bits |= FE.Value;
2014222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
2024222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    }
2034222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling  }
2044222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling}
2054222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
2064222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling/// ClearImpliedBits - For each feature that (transitively) implies this
2074222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling/// feature, clear it.
2082684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach///
2094222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendlingstatic
210b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Chengvoid ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
2114222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling                      const SubtargetFeatureKV *FeatureTable,
2124222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling                      size_t FeatureTableSize) {
2134222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling  for (size_t i = 0; i < FeatureTableSize; ++i) {
2144222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const SubtargetFeatureKV &FE = FeatureTable[i];
2154222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
2164222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    if (FeatureEntry->Value == FE.Value) continue;
2174222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
2184222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    if (FE.Implies & FeatureEntry->Value) {
2194222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      Bits &= ~FE.Value;
2204222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
2214222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    }
2224222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling  }
2234222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling}
22434bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey
225ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng/// ToggleFeature - Toggle a feature and returns the newly updated feature
226ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng/// bits.
227ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Chenguint64_t
228ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan ChengSubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature,
229ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng                                 const SubtargetFeatureKV *FeatureTable,
230ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng                                 size_t FeatureTableSize) {
231ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  // Find feature in table.
232ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  const SubtargetFeatureKV *FeatureEntry =
233ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng    Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
234ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  // If there is a match
235ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  if (FeatureEntry) {
236ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng    if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
237ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng      Bits &= ~FeatureEntry->Value;
238ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng
239ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng      // For each feature that implies this, clear it.
240ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng      ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
241ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng    } else {
242ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng      Bits |=  FeatureEntry->Value;
243ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng
244ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng      // For each feature that this implies, set it.
245ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng      SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
246ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng    }
247ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  } else {
248ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng    errs() << "'" << Feature
249ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng           << "' is not a recognized feature for this target"
250ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng           << " (ignoring feature)\n";
251ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  }
252ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng
253ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  return Bits;
254ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng}
2552684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach
256ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng
257276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng/// getFeatureBits - Get feature bits a CPU.
25854195c1a9d8ac23d2dc1dfca818384cd26abe19bChris Lattner///
259e1bff38386b0af24b5564c3d20888c7bbb045099Evan Chenguint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU,
260276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng                                         const SubtargetFeatureKV *CPUTable,
261276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng                                         size_t CPUTableSize,
262276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng                                         const SubtargetFeatureKV *FeatureTable,
263276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng                                         size_t FeatureTableSize) {
2640ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  if (!FeatureTableSize || !CPUTableSize)
2650ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng    return 0;
2660ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng
267b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey#ifndef NDEBUG
268b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  for (size_t i = 1; i < CPUTableSize; i++) {
269b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
270b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey           "CPU table is not sorted");
271b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  }
272b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  for (size_t i = 1; i < FeatureTableSize; i++) {
273b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
274b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey          "CPU features table is not sorted");
275b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  }
276b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey#endif
277b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  uint64_t Bits = 0;                    // Resulting bits
2783e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner
27934bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  // Check if help is needed
280276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng  if (CPU == "help")
2813e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner    Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);
2822684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach
2830ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  // Find CPU entry if CPU name is specified.
2840ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  if (!CPU.empty()) {
2850ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng    const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable, CPUTableSize);
2860ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng    // If there is a match
2870ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng    if (CPUEntry) {
2880ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      // Set base feature bits
2890ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      Bits = CPUEntry->Value;
2901a636de33bccc31337c1ea0811c7019fa0b31eeaBill Wendling
2910ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      // Set the feature implied by this CPU feature, if any.
2920ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      for (size_t i = 0; i < FeatureTableSize; ++i) {
2930ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng        const SubtargetFeatureKV &FE = FeatureTable[i];
2940ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng        if (CPUEntry->Value & FE.Value)
2950ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng          SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
2960ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      }
2970ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng    } else {
2980ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      errs() << "'" << CPU
2990ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng             << "' is not a recognized processor for this target"
3000ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng             << " (ignoring processor)\n";
3011a636de33bccc31337c1ea0811c7019fa0b31eeaBill Wendling    }
302b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  }
3030ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng
304b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  // Iterate through each feature
305276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng  for (size_t i = 0, E = Features.size(); i < E; i++) {
306e1bff38386b0af24b5564c3d20888c7bbb045099Evan Cheng    const StringRef Feature = Features[i];
3072684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach
308839615a510c582ddcdb09a8e2934f30775daa032Jim Laskey    // Check for help
3093e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner    if (Feature == "+help")
3103e808a45b334608595a045c2ace7e2a107fb3b2bChris Lattner      Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);
3112684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach
312b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    // Find feature in table.
313b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    const SubtargetFeatureKV *FeatureEntry =
314b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey                       Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
315b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    // If there is a match
316b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    if (FeatureEntry) {
317b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey      // Enable/disable feature in bits
3184222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      if (isEnabled(Feature)) {
3194222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        Bits |=  FeatureEntry->Value;
3204222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
3214222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        // For each feature that this implies, set it.
3224222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
3234222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      } else {
3244222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        Bits &= ~FeatureEntry->Value;
3254222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
3264222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        // For each feature that implies this, clear it.
3274222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
3284222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      }
329b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    } else {
330e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner      errs() << "'" << Feature
331e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner             << "' is not a recognized feature for this target"
332e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner             << " (ignoring feature)\n";
333b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    }
334b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  }
3354222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
336b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  return Bits;
337b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey}
338b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
339276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng/// Get scheduling itinerary of a CPU.
34098eb98b0f2e6573f5aee67ce3e75624392d637b7Roman Divackyconst void *SubtargetFeatures::getItinerary(const StringRef CPU,
34198eb98b0f2e6573f5aee67ce3e75624392d637b7Roman Divacky                                            const SubtargetInfoKV *Table,
34298eb98b0f2e6573f5aee67ce3e75624392d637b7Roman Divacky                                            size_t TableSize) {
34334bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  assert(Table && "missing table");
34434bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey#ifndef NDEBUG
34534bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  for (size_t i = 1; i < TableSize; i++) {
34634bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey    assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted");
34734bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  }
34834bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey#endif
34934bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey
35034bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  // Find entry
351276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng  const SubtargetInfoKV *Entry = Find(CPU, Table, TableSize);
3522684d9e3c702b2ef9fd430155d94671d12fa994fJim Grosbach
35334bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  if (Entry) {
35434bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey    return Entry->Value;
35534bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  } else {
356276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng    errs() << "'" << CPU
357e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner           << "' is not a recognized processor for this target"
358e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner           << " (ignoring processor)\n";
35934bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey    return NULL;
36034bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey  }
36134bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey}
36234bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey
36334bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey/// print - Print feature string.
36434bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey///
365e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattnervoid SubtargetFeatures::print(raw_ostream &OS) const {
366e0c86afac63a2dbbcff0ad79ed7b93d860451385Chris Lattner  for (size_t i = 0, e = Features.size(); i != e; ++i)
367b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey    OS << Features[i] << "  ";
368b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey  OS << "\n";
369b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey}
370b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey
371cc77eece74c8db09acc2af425e7e6c88a5bb30d1Manman Ren#ifndef NDEBUG
37234bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey/// dump - Dump feature info.
37334bd5d5d876212611d8b66a18f4c8604b342c6ebJim Laskey///
374b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskeyvoid SubtargetFeatures::dump() const {
3759759c305c2dbca2ba46645638ed39d5cb40b66d1David Greene  print(dbgs());
376b3302db18a779527a4b1cd7a2024543ade7e83c6Jim Laskey}
377cc77eece74c8db09acc2af425e7e6c88a5bb30d1Manman Ren#endif
378e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov
37981043ee5dc4cca470db8d45e080ba0a38efbffc2Bill Wendling/// getDefaultSubtargetFeatures - Return a string listing the features
38081043ee5dc4cca470db8d45e080ba0a38efbffc2Bill Wendling/// associated with the target triple.
381e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov///
382e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov/// FIXME: This is an inelegant way of specifying the features of a
383e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov/// subtarget. It would be better if we could encode this information
384e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov/// into the IR. See <rdar://5972456>.
385e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov///
386276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Chengvoid SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) {
387f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling  if (Triple.getVendor() == Triple::Apple) {
388f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling    if (Triple.getArch() == Triple::ppc) {
389f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling      // powerpc-apple-*
390f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling      AddFeature("altivec");
391f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling    } else if (Triple.getArch() == Triple::ppc64) {
392f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling      // powerpc64-apple-*
393f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling      AddFeature("64bit");
394f6d8481adad4b763a380186ea62637df2d480c99Bill Wendling      AddFeature("altivec");
395e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov    }
39681043ee5dc4cca470db8d45e080ba0a38efbffc2Bill Wendling  }
397e823db8bae7fe42cd4f1fa861bec8c36a636702bViktor Kutuzov}
398