X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSubtargetFeature.cpp;h=664a43cbcca7bfab28c78d35c972793002a4f777;hb=3859638b5f33255975534f2bfad170beeb72b0ae;hp=29afeff87783eb357cebff308f29b7356cc8e782;hpb=3eb3369a251db620a5a07ddacb49b4cdd9952dd5;p=oota-llvm.git diff --git a/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp index 29afeff8778..664a43cbcca 100644 --- a/lib/Target/SubtargetFeature.cpp +++ b/lib/Target/SubtargetFeature.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Jim Laskey and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -12,18 +12,55 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/SubtargetFeature.h" - -#include +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" #include -#include #include #include - using namespace llvm; -/// Splits a string of comma separated items in to a vector of strings. -void SubtargetFeatures::Split(std::vector &V, - const std::string &S) { +//===----------------------------------------------------------------------===// +// Static Helper Functions +//===----------------------------------------------------------------------===// + +/// hasFlag - Determine if a feature has a flag; '+' or '-' +/// +static inline bool hasFlag(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' or '-' flag + return Ch == '+' || Ch =='-'; +} + +/// StripFlag - Return string stripped of flag. +/// +static inline std::string StripFlag(const std::string &Feature) { + return hasFlag(Feature) ? Feature.substr(1) : Feature; +} + +/// isEnabled - Return true if enable flag; '+'. +/// +static inline bool isEnabled(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' for enabled + return Ch == '+'; +} + +/// PrependFlag - Return a string with a prepended flag; '+' or '-'. +/// +static inline std::string PrependFlag(const std::string &Feature, + bool IsEnabled) { + assert(!Feature.empty() && "Empty string"); + if (hasFlag(Feature)) return Feature; + return std::string(IsEnabled ? "+" : "-") + Feature; +} + +/// Split - Splits a string of comma separated items in to a vector of strings. +/// +static void Split(std::vector &V, const std::string &S) { // Start at beginning of string. size_t Pos = 0; while (true) { @@ -43,7 +80,8 @@ void SubtargetFeatures::Split(std::vector &V, } /// Join a vector of strings to a string with a comma separating each element. -std::string SubtargetFeatures::Join(const std::vector &V) { +/// +static std::string Join(const std::vector &V) { // Start with empty string. std::string Result; // If the vector is not empty @@ -62,73 +100,155 @@ std::string SubtargetFeatures::Join(const std::vector &V) { return Result; } -/// Convert a string to lowercase. -std::string SubtargetFeatures::toLower(const std::string &S) { - // Copy the string - std::string Result = S; - // For each character in string - for (size_t i = 0; i < Result.size(); i++) { - // Convert character to lowercase - Result[i] = std::tolower(Result[i]); - } - // Return the lowercased string - return Result; -} - /// Adding features. void SubtargetFeatures::AddFeature(const std::string &String, bool IsEnabled) { // Don't add empty features if (!String.empty()) { // Convert to lowercase, prepend flag and add to vector - Features.push_back(PrependFlag(toLower(String), IsEnabled)); + Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); } } -/// Find item in array using binary search. -const SubtargetFeatureKV * -SubtargetFeatures::Find(const std::string &S, - const SubtargetFeatureKV *A, size_t L) { +/// Find KV in array using binary search. +template const T *Find(const std::string &S, const T *A, size_t L) { + // Make the lower bound element we're looking for + T KV; + KV.Key = S.c_str(); // Determine the end of the array - const SubtargetFeatureKV *Hi = A + L; + const T *Hi = A + L; // Binary search the array - const SubtargetFeatureKV *F = std::lower_bound(A, Hi, S); + const T *F = std::lower_bound(A, Hi, KV); // If not found then return NULL if (F == Hi || std::string(F->Key) != S) return NULL; // 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) { + size_t MaxLen = 0; + for (size_t i = 0; i < Size; i++) + MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); + return MaxLen; +} + /// Display help for feature choices. -void SubtargetFeatures::Help(const char *Heading, - const SubtargetFeatureKV *Table, size_t TableSize) { - // Determine the length of the longest key - size_t MaxLen = 0; - for (size_t i = 0; i < TableSize; i++) - MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); - // Print heading - std::cerr << "Help for " << Heading << " choices\n\n"; - // For each feature - for (size_t i = 0; i < TableSize; i++) { - // Compute required padding - size_t Pad = MaxLen - std::strlen(Table[i].Key) + 1; - // Print details - std::cerr << Table[i].Key << std::string(Pad, ' ') << " - " - << Table[i].Desc << "\n"; +/// +static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, + const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { + // Determine the length of the longest CPU and Feature entries. + unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); + unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); + + // Print the CPU table. + errs() << "Available CPUs for this target:\n\n"; + for (size_t i = 0; i != CPUTableSize; i++) + errs() << " " << CPUTable[i].Key + << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') + << " - " << CPUTable[i].Desc << ".\n"; + errs() << "\n"; + + // Print the Feature table. + errs() << "Available features for this target:\n\n"; + for (size_t i = 0; i != FeatTableSize; i++) + errs() << " " << FeatTable[i].Key + << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') + << " - " << FeatTable[i].Desc << ".\n"; + errs() << "\n"; + + errs() << "Use +feature to enable a feature, or -feature to disable it.\n" + << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; + exit(1); +} + +//===----------------------------------------------------------------------===// +// SubtargetFeatures Implementation +//===----------------------------------------------------------------------===// + +SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { + // Break up string into separate features + Split(Features, Initial); +} + + +std::string SubtargetFeatures::getString() const { + return Join(Features); +} +void SubtargetFeatures::setString(const std::string &Initial) { + // Throw out old features + Features.clear(); + // Break up string into separate features + Split(Features, LowercaseString(Initial)); +} + + +/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" +/// clears CPU. +void SubtargetFeatures::setCPU(const std::string &String) { + Features[0] = LowercaseString(String); +} + + +/// setCPUIfNone - Setting CPU string only if no string is set. +/// +void SubtargetFeatures::setCPUIfNone(const std::string &String) { + if (Features[0].empty()) setCPU(String); +} + +/// getCPU - Returns current CPU. +/// +const std::string & SubtargetFeatures::getCPU() const { + return Features[0]; +} + + +/// SetImpliedBits - For each feature that is (transitively) implied by this +/// feature, set it. +/// +static +void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FeatureEntry->Implies & FE.Value) { + Bits |= FE.Value; + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); } - // Wrap it up - std::cerr << "\n\n"; - // Leave tool - exit(1); -} - -/// Parse feature string for quick usage. -uint32_t SubtargetFeatures::Parse(const std::string &String, - const std::string &DefaultCPU, - const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { + } +} + +/// ClearImpliedBits - For each feature that (transitively) implies this +/// feature, clear it. +/// +static +void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FE.Implies & FeatureEntry->Value) { + Bits &= ~FE.Value; + ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// getBits - Get feature bits. +/// +uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { assert(CPUTable && "missing CPU table"); assert(FeatureTable && "missing features table"); #ifndef NDEBUG @@ -141,14 +261,12 @@ uint32_t SubtargetFeatures::Parse(const std::string &String, "CPU features table is not sorted"); } #endif - std::vector Features; // Subtarget features as a vector uint32_t Bits = 0; // Resulting bits - // Split up features - Split(Features, String); - // Check if default is needed - if (Features[0].empty()) Features[0] = DefaultCPU; - // Check for help - if (Features[0] == "help") Help("CPU", CPUTable, CPUTableSize); + + // Check if help is needed + if (Features[0] == "help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + // Find CPU entry const SubtargetFeatureKV *CPUEntry = Find(Features[0], CPUTable, CPUTableSize); @@ -156,45 +274,86 @@ uint32_t SubtargetFeatures::Parse(const std::string &String, 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); + } } else { - std::cerr << "'" << Features[0] - << "' is not a recognized processor for this target" - << " (ignoring processor)" - << "\n"; + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; } // Iterate through each feature for (size_t i = 1; i < Features.size(); i++) { - // Get next feature const std::string &Feature = Features[i]; + // Check for help - if (Feature == "+help") Help("feature", FeatureTable, FeatureTableSize); + if (Feature == "+help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + // Find feature in table. const SubtargetFeatureKV *FeatureEntry = Find(StripFlag(Feature), FeatureTable, FeatureTableSize); // If there is a match if (FeatureEntry) { // Enable/disable feature in bits - if (isEnabled(Feature)) Bits |= FeatureEntry->Value; - else Bits &= ~FeatureEntry->Value; + if (isEnabled(Feature)) { + Bits |= FeatureEntry->Value; + + // For each feature that this implies, set it. + SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } else { + Bits &= ~FeatureEntry->Value; + + // For each feature that implies this, clear it. + ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } } else { - std::cerr << "'" << Feature - << "' is not a recognized feature for this target" - << " (ignoring feature)" - << "\n"; + errs() << "'" << Feature + << "' is not a recognized feature for this target" + << " (ignoring feature)\n"; } } + return Bits; } -/// Print feature string. -void SubtargetFeatures::print(std::ostream &OS) const { - for (size_t i = 0; i < Features.size(); i++) { - OS << Features[i] << " "; +/// Get info pointer +void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, + size_t TableSize) { + assert(Table && "missing table"); +#ifndef NDEBUG + for (size_t i = 1; i < TableSize; i++) { + assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); + } +#endif + + // Find entry + const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); + + if (Entry) { + return Entry->Value; + } else { + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; + return NULL; } +} + +/// 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] << " "; OS << "\n"; } -/// Dump feature info. +/// dump - Dump feature info. +/// void SubtargetFeatures::dump() const { - print(std::cerr); + print(errs()); }