Use std::bitset for SubtargetFeatures
[oota-llvm.git] / lib / MC / SubtargetFeature.cpp
index 7625abd465fa10277583c32a66046808e14d50e7..2740839cd99065e6b4fc17f0594d333a0e5d88fc 100644 (file)
@@ -27,7 +27,7 @@ using namespace llvm;
 
 /// hasFlag - Determine if a feature has a flag; '+' or '-'
 ///
-static inline bool hasFlag(const StringRef Feature) {
+static inline bool hasFlag(StringRef Feature) {
   assert(!Feature.empty() && "Empty string");
   // Get first character
   char Ch = Feature[0];
@@ -37,13 +37,13 @@ static inline bool hasFlag(const StringRef Feature) {
 
 /// StripFlag - Return string stripped of flag.
 ///
-static inline std::string StripFlag(const StringRef Feature) {
+static inline std::string StripFlag(StringRef Feature) {
   return hasFlag(Feature) ? Feature.substr(1) : Feature;
 }
 
 /// isEnabled - Return true if enable flag; '+'.
 ///
-static inline bool isEnabled(const StringRef Feature) {
+static inline bool isEnabled(StringRef Feature) {
   assert(!Feature.empty() && "Empty string");
   // Get first character
   char Ch = Feature[0];
@@ -51,40 +51,12 @@ static inline bool isEnabled(const StringRef Feature) {
   return Ch == '+';
 }
 
-/// PrependFlag - Return a string with a prepended flag; '+' or '-'.
-///
-static inline std::string PrependFlag(const StringRef Feature,
-                                    bool IsEnabled) {
-  assert(!Feature.empty() && "Empty string");
-  if (hasFlag(Feature))
-    return Feature;
-  std::string Prefix = IsEnabled ? "+" : "-";
-  Prefix += Feature;
-  return Prefix;
-}
-
 /// Split - Splits a string of comma separated items in to a vector of strings.
 ///
-static void Split(std::vector<std::string> &V, const StringRef S) {
-  if (S.empty())
-    return;
-
-  // Start at beginning of string.
-  size_t Pos = 0;
-  while (true) {
-    // Find the next comma
-    size_t Comma = S.find(',', Pos);
-    // If no comma found then the rest of the string is used
-    if (Comma == std::string::npos) {
-      // Add string to vector
-      V.push_back(S.substr(Pos));
-      break;
-    }
-    // Otherwise add substring to vector
-    V.push_back(S.substr(Pos, Comma - Pos));
-    // Advance to next item
-    Pos = Comma + 1;
-  }
+static void Split(std::vector<std::string> &V, StringRef S) {
+  SmallVector<StringRef, 3> Tmp;
+  S.split(Tmp, ",", -1, false /* KeepEmpty */);
+  V.assign(Tmp.begin(), Tmp.end());
 }
 
 /// Join a vector of strings to a string with a comma separating each element.
@@ -109,73 +81,62 @@ static std::string Join(const std::vector<std::string> &V) {
 }
 
 /// Adding features.
-void SubtargetFeatures::AddFeature(const StringRef String,
-                                   bool IsEnabled) {
-  // Don't add empty features
-  if (!String.empty()) {
-    // Convert to lowercase, prepend flag and add to vector
-    Features.push_back(PrependFlag(String.lower(), IsEnabled));
-  }
+void SubtargetFeatures::AddFeature(StringRef String) {
+  // Don't add empty features or features we already have.
+  if (!String.empty())
+    // Convert to lowercase, prepend flag if we don't already have a flag.
+    Features.push_back(hasFlag(String) ? String.str() : "+" + String.lower());
 }
 
 /// Find KV in array using binary search.
-static const SubtargetFeatureKV *Find(StringRef S, const SubtargetFeatureKV *A,
-                                      size_t L) {
-  // Make the lower bound element we're looking for
-  SubtargetFeatureKV KV;
-  KV.Key = S.data();
-  // Determine the end of the array
-  const SubtargetFeatureKV *Hi = A + L;
+static const SubtargetFeatureKV *Find(StringRef S,
+                                      ArrayRef<SubtargetFeatureKV> A) {
   // Binary search the array
-  const SubtargetFeatureKV *F = std::lower_bound(A, Hi, KV);
+  auto F = std::lower_bound(A.begin(), A.end(), S);
   // If not found then return NULL
-  if (F == Hi || StringRef(F->Key) != S) return NULL;
+  if (F == A.end() || StringRef(F->Key) != S) return nullptr;
   // Return the found array item
   return F;
 }
 
 /// getLongestEntryLength - Return the length of the longest entry in the table.
 ///
-static size_t getLongestEntryLength(const SubtargetFeatureKV *Table,
-                                    size_t Size) {
+static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
   size_t MaxLen = 0;
-  for (size_t i = 0; i < Size; i++)
-    MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
+  for (auto &I : Table)
+    MaxLen = std::max(MaxLen, std::strlen(I.Key));
   return MaxLen;
 }
 
 /// Display help for feature choices.
 ///
-static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize,
-                 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) {
+static void Help(ArrayRef<SubtargetFeatureKV> CPUTable,
+                 ArrayRef<SubtargetFeatureKV> FeatTable) {
   // Determine the length of the longest CPU and Feature entries.
-  unsigned MaxCPULen  = getLongestEntryLength(CPUTable, CPUTableSize);
-  unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize);
+  unsigned MaxCPULen  = getLongestEntryLength(CPUTable);
+  unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
 
   // Print the CPU table.
   errs() << "Available CPUs for this target:\n\n";
-  for (size_t i = 0; i != CPUTableSize; i++)
-    errs() << format("  %-*s - %s.\n",
-                     MaxCPULen, CPUTable[i].Key, CPUTable[i].Desc);
+  for (auto &CPU : CPUTable)
+    errs() << format("  %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
   errs() << '\n';
 
   // Print the Feature table.
   errs() << "Available features for this target:\n\n";
-  for (size_t i = 0; i != FeatTableSize; i++)
-    errs() << format("  %-*s - %s.\n",
-                     MaxFeatLen, FeatTable[i].Key, FeatTable[i].Desc);
+  for (auto &Feature : FeatTable)
+    errs() << format("  %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
   errs() << '\n';
 
   errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
             "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
-  std::exit(1);
 }
 
 //===----------------------------------------------------------------------===//
 //                    SubtargetFeatures Implementation
 //===----------------------------------------------------------------------===//
 
-SubtargetFeatures::SubtargetFeatures(const StringRef Initial) {
+SubtargetFeatures::SubtargetFeatures(StringRef Initial) {
   // Break up string into separate features
   Split(Features, Initial);
 }
@@ -189,17 +150,14 @@ std::string SubtargetFeatures::getString() const {
 /// feature, set it.
 ///
 static
-void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
-                    const SubtargetFeatureKV *FeatureTable,
-                    size_t FeatureTableSize) {
-  for (size_t i = 0; i < FeatureTableSize; ++i) {
-    const SubtargetFeatureKV &FE = FeatureTable[i];
-
+void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV *FeatureEntry,
+                    ArrayRef<SubtargetFeatureKV> FeatureTable) {
+  for (auto &FE : FeatureTable) {
     if (FeatureEntry->Value == FE.Value) continue;
 
-    if (FeatureEntry->Implies & FE.Value) {
+    if ((FeatureEntry->Implies & FE.Value).any()) {
       Bits |= FE.Value;
-      SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
+      SetImpliedBits(Bits, &FE, FeatureTable);
     }
   }
 }
@@ -208,42 +166,39 @@ void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
 /// feature, clear it.
 ///
 static
-void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
-                      const SubtargetFeatureKV *FeatureTable,
-                      size_t FeatureTableSize) {
-  for (size_t i = 0; i < FeatureTableSize; ++i) {
-    const SubtargetFeatureKV &FE = FeatureTable[i];
-
+void ClearImpliedBits(FeatureBitset &Bits, 
+                      const SubtargetFeatureKV *FeatureEntry,
+                      ArrayRef<SubtargetFeatureKV> FeatureTable) {
+  for (auto &FE : FeatureTable) {
     if (FeatureEntry->Value == FE.Value) continue;
 
-    if (FE.Implies & FeatureEntry->Value) {
+    if ((FE.Implies & FeatureEntry->Value).any()) {
       Bits &= ~FE.Value;
-      ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
+      ClearImpliedBits(Bits, &FE, FeatureTable);
     }
   }
 }
 
 /// ToggleFeature - Toggle a feature and returns the newly updated feature
 /// bits.
-uint64_t
-SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature,
-                                 const SubtargetFeatureKV *FeatureTable,
-                                 size_t FeatureTableSize) {
+FeatureBitset
+SubtargetFeatures::ToggleFeature(FeatureBitset Bits, StringRef Feature,
+                                 ArrayRef<SubtargetFeatureKV> FeatureTable) {
+
   // Find feature in table.
   const SubtargetFeatureKV *FeatureEntry =
-    Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
+      Find(StripFlag(Feature), FeatureTable);
   // If there is a match
   if (FeatureEntry) {
     if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
       Bits &= ~FeatureEntry->Value;
-
       // For each feature that implies this, clear it.
-      ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
+      ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
     } else {
       Bits |=  FeatureEntry->Value;
 
       // For each feature that this implies, set it.
-      SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
+      SetImpliedBits(Bits, FeatureEntry, FeatureTable);
     }
   } else {
     errs() << "'" << Feature
@@ -257,43 +212,44 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature,
 
 /// getFeatureBits - Get feature bits a CPU.
 ///
-uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU,
-                                         const SubtargetFeatureKV *CPUTable,
-                                         size_t CPUTableSize,
-                                         const SubtargetFeatureKV *FeatureTable,
-                                         size_t FeatureTableSize) {
-  if (!FeatureTableSize || !CPUTableSize)
-    return 0;
+FeatureBitset
+SubtargetFeatures::getFeatureBits(StringRef CPU,
+                                  ArrayRef<SubtargetFeatureKV> CPUTable,
+                                  ArrayRef<SubtargetFeatureKV> FeatureTable) {
+
+  if (CPUTable.empty() || FeatureTable.empty())
+    return FeatureBitset();
 
 #ifndef NDEBUG
-  for (size_t i = 1; i < CPUTableSize; i++) {
+  for (size_t i = 1, e = CPUTable.size(); i != e; ++i) {
     assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
            "CPU table is not sorted");
   }
-  for (size_t i = 1; i < FeatureTableSize; i++) {
+  for (size_t i = 1, e = FeatureTable.size(); i != e; ++i) {
     assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
           "CPU features table is not sorted");
   }
 #endif
-  uint64_t Bits = 0;                    // Resulting bits
+  // Resulting bits
+  FeatureBitset Bits;
 
   // Check if help is needed
   if (CPU == "help")
-    Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);
+    Help(CPUTable, FeatureTable);
 
   // Find CPU entry if CPU name is specified.
-  if (!CPU.empty()) {
-    const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable, CPUTableSize);
+  else if (!CPU.empty()) {
+    const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable);
+
     // If there is a match
     if (CPUEntry) {
       // Set base feature bits
       Bits = CPUEntry->Value;
 
       // Set the feature implied by this CPU feature, if any.
-      for (size_t i = 0; i < FeatureTableSize; ++i) {
-        const SubtargetFeatureKV &FE = FeatureTable[i];
-        if (CPUEntry->Value & FE.Value)
-          SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
+      for (auto &FE : FeatureTable) {
+        if ((CPUEntry->Value & FE.Value).any())
+          SetImpliedBits(Bits, &FE, FeatureTable);
       }
     } else {
       errs() << "'" << CPU
@@ -303,16 +259,14 @@ uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU,
   }
 
   // Iterate through each feature
-  for (size_t i = 0, E = Features.size(); i < E; i++) {
-    const StringRef Feature = Features[i];
-
+  for (auto &Feature : Features) {
     // Check for help
     if (Feature == "+help")
-      Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);
+      Help(CPUTable, FeatureTable);
 
     // Find feature in table.
     const SubtargetFeatureKV *FeatureEntry =
-                       Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
+        Find(StripFlag(Feature), FeatureTable);
     // If there is a match
     if (FeatureEntry) {
       // Enable/disable feature in bits
@@ -320,12 +274,12 @@ uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU,
         Bits |=  FeatureEntry->Value;
 
         // For each feature that this implies, set it.
-        SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
+        SetImpliedBits(Bits, FeatureEntry, FeatureTable);
       } else {
         Bits &= ~FeatureEntry->Value;
 
         // For each feature that implies this, clear it.
-        ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
+        ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
       }
     } else {
       errs() << "'" << Feature
@@ -340,8 +294,8 @@ uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU,
 /// print - Print feature string.
 ///
 void SubtargetFeatures::print(raw_ostream &OS) const {
-  for (size_t i = 0, e = Features.size(); i != e; ++i)
-    OS << Features[i] << "  ";
+  for (auto &F : Features)
+    OS << F << " ";
   OS << "\n";
 }
 
@@ -353,8 +307,7 @@ void SubtargetFeatures::dump() const {
 }
 #endif
 
-/// getDefaultSubtargetFeatures - Return a string listing the features
-/// associated with the target triple.
+/// Adds the default features for the specified target triple.
 ///
 /// FIXME: This is an inelegant way of specifying the features of a
 /// subtarget. It would be better if we could encode this information