Use std::is_sorted instead of manual loops. NFC
[oota-llvm.git] / lib / MC / SubtargetFeature.cpp
index 3be6d9641b3653061989151d451080de410e9f91..c1f5fc95cf57dda06b9f420dd0938b8e8c21ed78 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/MC/SubtargetFeature.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
@@ -27,7 +28,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 +38,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];
@@ -53,55 +54,19 @@ static inline bool isEnabled(const StringRef Feature) {
 
 /// 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;
-  }
-}
-
-/// Join a vector of strings to a string with a comma separating each element.
-///
-static std::string Join(const std::vector<std::string> &V) {
-  // Start with empty string.
-  std::string Result;
-  // If the vector is not empty
-  if (!V.empty()) {
-    // Start with the first feature
-    Result = V[0];
-    // For each successive feature
-    for (size_t i = 1; i < V.size(); i++) {
-      // Add a comma
-      Result += ",";
-      // Add the feature
-      Result += V[i];
-    }
-  }
-  // Return the features string
-  return Result;
+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());
 }
 
 /// Adding features.
-void SubtargetFeatures::AddFeature(const StringRef String) {
-  // Don't add empty features or features we already have.
+void SubtargetFeatures::AddFeature(StringRef String, bool Enable) {
+  // Don't add empty features.
   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());
+    Features.push_back(hasFlag(String) ? String.lower()
+                                       : (Enable ? "+" : "-") + String.lower());
 }
 
 /// Find KV in array using binary search.
@@ -152,26 +117,26 @@ static void Help(ArrayRef<SubtargetFeatureKV> CPUTable,
 //                    SubtargetFeatures Implementation
 //===----------------------------------------------------------------------===//
 
-SubtargetFeatures::SubtargetFeatures(const StringRef Initial) {
+SubtargetFeatures::SubtargetFeatures(StringRef Initial) {
   // Break up string into separate features
   Split(Features, Initial);
 }
 
 
 std::string SubtargetFeatures::getString() const {
-  return Join(Features);
+  return join(Features.begin(), Features.end(), ",");
 }
 
 /// SetImpliedBits - For each feature that is (transitively) implied by this
 /// feature, set it.
 ///
 static
-void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
+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);
     }
@@ -182,12 +147,13 @@ void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
 /// feature, clear it.
 ///
 static
-void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
+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);
     }
@@ -196,8 +162,8 @@ void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
 
 /// ToggleFeature - Toggle a feature and returns the newly updated feature
 /// bits.
-uint64_t
-SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature,
+FeatureBitset
+SubtargetFeatures::ToggleFeature(FeatureBitset Bits, StringRef Feature,
                                  ArrayRef<SubtargetFeatureKV> FeatureTable) {
 
   // Find feature in table.
@@ -207,7 +173,6 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature,
   if (FeatureEntry) {
     if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
       Bits &= ~FeatureEntry->Value;
-
       // For each feature that implies this, clear it.
       ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
     } else {
@@ -225,28 +190,57 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature,
   return Bits;
 }
 
+FeatureBitset
+SubtargetFeatures::ApplyFeatureFlag(FeatureBitset Bits, StringRef Feature,
+                                    ArrayRef<SubtargetFeatureKV> FeatureTable) {
+
+  assert(hasFlag(Feature));
+
+  // Find feature in table.
+  const SubtargetFeatureKV *FeatureEntry =
+      Find(StripFlag(Feature), FeatureTable);
+  // If there is a match
+  if (FeatureEntry) {
+    // Enable/disable feature in bits
+    if (isEnabled(Feature)) {
+      Bits |=  FeatureEntry->Value;
+
+      // For each feature that this implies, set it.
+      SetImpliedBits(Bits, FeatureEntry, FeatureTable);
+    } else {
+      Bits &= ~FeatureEntry->Value;
+
+      // For each feature that implies this, clear it.
+      ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
+    }
+  } else {
+    errs() << "'" << Feature
+           << "' is not a recognized feature for this target"
+           << " (ignoring feature)\n";
+  }
+
+  return Bits;
+}
+
 
 /// getFeatureBits - Get feature bits a CPU.
 ///
-uint64_t
-SubtargetFeatures::getFeatureBits(const StringRef CPU,
+FeatureBitset
+SubtargetFeatures::getFeatureBits(StringRef CPU,
                                   ArrayRef<SubtargetFeatureKV> CPUTable,
                                   ArrayRef<SubtargetFeatureKV> FeatureTable) {
 
   if (CPUTable.empty() || FeatureTable.empty())
-    return 0;
+    return FeatureBitset();
 
 #ifndef NDEBUG
-  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, e = FeatureTable.size(); i != e; ++i) {
-    assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
-          "CPU features table is not sorted");
-  }
+  assert(std::is_sorted(std::begin(CPUTable), std::end(CPUTable)) &&
+         "CPU table is not sorted");
+  assert(std::is_sorted(std::begin(FeatureTable), std::end(FeatureTable)) &&
+         "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")
@@ -263,7 +257,7 @@ SubtargetFeatures::getFeatureBits(const StringRef CPU,
 
       // Set the feature implied by this CPU feature, if any.
       for (auto &FE : FeatureTable) {
-        if (CPUEntry->Value & FE.Value)
+        if ((CPUEntry->Value & FE.Value).any())
           SetImpliedBits(Bits, &FE, FeatureTable);
       }
     } else {
@@ -279,28 +273,7 @@ SubtargetFeatures::getFeatureBits(const StringRef CPU,
     if (Feature == "+help")
       Help(CPUTable, FeatureTable);
 
-    // Find feature in table.
-    const SubtargetFeatureKV *FeatureEntry =
-        Find(StripFlag(Feature), FeatureTable);
-    // If there is a match
-    if (FeatureEntry) {
-      // Enable/disable feature in bits
-      if (isEnabled(Feature)) {
-        Bits |=  FeatureEntry->Value;
-
-        // For each feature that this implies, set it.
-        SetImpliedBits(Bits, FeatureEntry, FeatureTable);
-      } else {
-        Bits &= ~FeatureEntry->Value;
-
-        // For each feature that implies this, clear it.
-        ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
-      }
-    } else {
-      errs() << "'" << Feature
-             << "' is not a recognized feature for this target"
-             << " (ignoring feature)\n";
-    }
+    Bits = ApplyFeatureFlag(Bits, Feature, FeatureTable);
   }
 
   return Bits;