106c3fb27SDimitry Andric //=== llvm/TargetParser/SubtargetFeature.h - CPU characteristics-*- C++ -*-===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric // 906c3fb27SDimitry Andric /// \file Defines and manages user or tool specified CPU characteristics. 1006c3fb27SDimitry Andric /// The intent is to be able to package specific features that should or should 1106c3fb27SDimitry Andric /// not be used on a specific target processor. A tool, such as llc, could, as 1206c3fb27SDimitry Andric /// as example, gather chip info from the command line, a long with features 1306c3fb27SDimitry Andric /// that should be used on that chip. 1406c3fb27SDimitry Andric // 1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1606c3fb27SDimitry Andric 1706c3fb27SDimitry Andric #ifndef LLVM_TARGETPARSER_SUBTARGETFEATURE_H 1806c3fb27SDimitry Andric #define LLVM_TARGETPARSER_SUBTARGETFEATURE_H 1906c3fb27SDimitry Andric 2006c3fb27SDimitry Andric #include "llvm/ADT/ArrayRef.h" 2106c3fb27SDimitry Andric #include "llvm/ADT/STLExtras.h" 2206c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h" 2306c3fb27SDimitry Andric #include "llvm/Support/MathExtras.h" 2406c3fb27SDimitry Andric #include <array> 2506c3fb27SDimitry Andric #include <initializer_list> 2606c3fb27SDimitry Andric #include <string> 2706c3fb27SDimitry Andric #include <vector> 2806c3fb27SDimitry Andric 2906c3fb27SDimitry Andric namespace llvm { 3006c3fb27SDimitry Andric 3106c3fb27SDimitry Andric class raw_ostream; 3206c3fb27SDimitry Andric class Triple; 3306c3fb27SDimitry Andric 34*5f757f3fSDimitry Andric const unsigned MAX_SUBTARGET_WORDS = 5; 3506c3fb27SDimitry Andric const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64; 3606c3fb27SDimitry Andric 3706c3fb27SDimitry Andric /// Container class for subtarget features. 3806c3fb27SDimitry Andric /// This is a constexpr reimplementation of a subset of std::bitset. It would be 3906c3fb27SDimitry Andric /// nice to use std::bitset directly, but it doesn't support constant 4006c3fb27SDimitry Andric /// initialization. 4106c3fb27SDimitry Andric class FeatureBitset { 4206c3fb27SDimitry Andric static_assert((MAX_SUBTARGET_FEATURES % 64) == 0, 4306c3fb27SDimitry Andric "Should be a multiple of 64!"); 4406c3fb27SDimitry Andric std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits{}; 4506c3fb27SDimitry Andric 4606c3fb27SDimitry Andric protected: FeatureBitset(const std::array<uint64_t,MAX_SUBTARGET_WORDS> & B)4706c3fb27SDimitry Andric constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) 4806c3fb27SDimitry Andric : Bits{B} {} 4906c3fb27SDimitry Andric 5006c3fb27SDimitry Andric public: 5106c3fb27SDimitry Andric constexpr FeatureBitset() = default; FeatureBitset(std::initializer_list<unsigned> Init)5206c3fb27SDimitry Andric constexpr FeatureBitset(std::initializer_list<unsigned> Init) { 5306c3fb27SDimitry Andric for (auto I : Init) 5406c3fb27SDimitry Andric set(I); 5506c3fb27SDimitry Andric } 5606c3fb27SDimitry Andric set()5706c3fb27SDimitry Andric FeatureBitset &set() { 5806c3fb27SDimitry Andric std::fill(std::begin(Bits), std::end(Bits), -1ULL); 5906c3fb27SDimitry Andric return *this; 6006c3fb27SDimitry Andric } 6106c3fb27SDimitry Andric set(unsigned I)6206c3fb27SDimitry Andric constexpr FeatureBitset &set(unsigned I) { 63*5f757f3fSDimitry Andric Bits[I / 64] |= uint64_t(1) << (I % 64); 6406c3fb27SDimitry Andric return *this; 6506c3fb27SDimitry Andric } 6606c3fb27SDimitry Andric reset(unsigned I)6706c3fb27SDimitry Andric constexpr FeatureBitset &reset(unsigned I) { 68*5f757f3fSDimitry Andric Bits[I / 64] &= ~(uint64_t(1) << (I % 64)); 6906c3fb27SDimitry Andric return *this; 7006c3fb27SDimitry Andric } 7106c3fb27SDimitry Andric flip(unsigned I)7206c3fb27SDimitry Andric constexpr FeatureBitset &flip(unsigned I) { 73*5f757f3fSDimitry Andric Bits[I / 64] ^= uint64_t(1) << (I % 64); 7406c3fb27SDimitry Andric return *this; 7506c3fb27SDimitry Andric } 7606c3fb27SDimitry Andric 7706c3fb27SDimitry Andric constexpr bool operator[](unsigned I) const { 7806c3fb27SDimitry Andric uint64_t Mask = uint64_t(1) << (I % 64); 7906c3fb27SDimitry Andric return (Bits[I / 64] & Mask) != 0; 8006c3fb27SDimitry Andric } 8106c3fb27SDimitry Andric test(unsigned I)8206c3fb27SDimitry Andric constexpr bool test(unsigned I) const { return (*this)[I]; } 8306c3fb27SDimitry Andric size()8406c3fb27SDimitry Andric constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; } 8506c3fb27SDimitry Andric any()8606c3fb27SDimitry Andric bool any() const { 8706c3fb27SDimitry Andric return llvm::any_of(Bits, [](uint64_t I) { return I != 0; }); 8806c3fb27SDimitry Andric } none()8906c3fb27SDimitry Andric bool none() const { return !any(); } count()9006c3fb27SDimitry Andric size_t count() const { 9106c3fb27SDimitry Andric size_t Count = 0; 9206c3fb27SDimitry Andric for (auto B : Bits) 9306c3fb27SDimitry Andric Count += llvm::popcount(B); 9406c3fb27SDimitry Andric return Count; 9506c3fb27SDimitry Andric } 9606c3fb27SDimitry Andric 9706c3fb27SDimitry Andric constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) { 9806c3fb27SDimitry Andric for (unsigned I = 0, E = Bits.size(); I != E; ++I) { 9906c3fb27SDimitry Andric Bits[I] ^= RHS.Bits[I]; 10006c3fb27SDimitry Andric } 10106c3fb27SDimitry Andric return *this; 10206c3fb27SDimitry Andric } 10306c3fb27SDimitry Andric constexpr FeatureBitset operator^(const FeatureBitset &RHS) const { 10406c3fb27SDimitry Andric FeatureBitset Result = *this; 10506c3fb27SDimitry Andric Result ^= RHS; 10606c3fb27SDimitry Andric return Result; 10706c3fb27SDimitry Andric } 10806c3fb27SDimitry Andric 10906c3fb27SDimitry Andric constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) { 110*5f757f3fSDimitry Andric for (unsigned I = 0, E = Bits.size(); I != E; ++I) 11106c3fb27SDimitry Andric Bits[I] &= RHS.Bits[I]; 11206c3fb27SDimitry Andric return *this; 11306c3fb27SDimitry Andric } 11406c3fb27SDimitry Andric constexpr FeatureBitset operator&(const FeatureBitset &RHS) const { 11506c3fb27SDimitry Andric FeatureBitset Result = *this; 11606c3fb27SDimitry Andric Result &= RHS; 11706c3fb27SDimitry Andric return Result; 11806c3fb27SDimitry Andric } 11906c3fb27SDimitry Andric 12006c3fb27SDimitry Andric constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) { 12106c3fb27SDimitry Andric for (unsigned I = 0, E = Bits.size(); I != E; ++I) { 12206c3fb27SDimitry Andric Bits[I] |= RHS.Bits[I]; 12306c3fb27SDimitry Andric } 12406c3fb27SDimitry Andric return *this; 12506c3fb27SDimitry Andric } 12606c3fb27SDimitry Andric constexpr FeatureBitset operator|(const FeatureBitset &RHS) const { 12706c3fb27SDimitry Andric FeatureBitset Result = *this; 12806c3fb27SDimitry Andric Result |= RHS; 12906c3fb27SDimitry Andric return Result; 13006c3fb27SDimitry Andric } 13106c3fb27SDimitry Andric 13206c3fb27SDimitry Andric constexpr FeatureBitset operator~() const { 13306c3fb27SDimitry Andric FeatureBitset Result = *this; 13406c3fb27SDimitry Andric for (auto &B : Result.Bits) 13506c3fb27SDimitry Andric B = ~B; 13606c3fb27SDimitry Andric return Result; 13706c3fb27SDimitry Andric } 13806c3fb27SDimitry Andric 13906c3fb27SDimitry Andric bool operator==(const FeatureBitset &RHS) const { 14006c3fb27SDimitry Andric return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits)); 14106c3fb27SDimitry Andric } 14206c3fb27SDimitry Andric 14306c3fb27SDimitry Andric bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); } 14406c3fb27SDimitry Andric 14506c3fb27SDimitry Andric bool operator < (const FeatureBitset &Other) const { 14606c3fb27SDimitry Andric for (unsigned I = 0, E = size(); I != E; ++I) { 14706c3fb27SDimitry Andric bool LHS = test(I), RHS = Other.test(I); 14806c3fb27SDimitry Andric if (LHS != RHS) 14906c3fb27SDimitry Andric return LHS < RHS; 15006c3fb27SDimitry Andric } 15106c3fb27SDimitry Andric return false; 15206c3fb27SDimitry Andric } 15306c3fb27SDimitry Andric }; 15406c3fb27SDimitry Andric 15506c3fb27SDimitry Andric /// Class used to store the subtarget bits in the tables created by tablegen. 15606c3fb27SDimitry Andric class FeatureBitArray : public FeatureBitset { 15706c3fb27SDimitry Andric public: FeatureBitArray(const std::array<uint64_t,MAX_SUBTARGET_WORDS> & B)15806c3fb27SDimitry Andric constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) 15906c3fb27SDimitry Andric : FeatureBitset(B) {} 16006c3fb27SDimitry Andric getAsBitset()16106c3fb27SDimitry Andric const FeatureBitset &getAsBitset() const { return *this; } 16206c3fb27SDimitry Andric }; 16306c3fb27SDimitry Andric 16406c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 16506c3fb27SDimitry Andric 16606c3fb27SDimitry Andric /// Manages the enabling and disabling of subtarget specific features. 16706c3fb27SDimitry Andric /// 16806c3fb27SDimitry Andric /// Features are encoded as a string of the form 16906c3fb27SDimitry Andric /// "+attr1,+attr2,-attr3,...,+attrN" 17006c3fb27SDimitry Andric /// A comma separates each feature from the next (all lowercase.) 17106c3fb27SDimitry Andric /// Each of the remaining features is prefixed with + or - indicating whether 17206c3fb27SDimitry Andric /// that feature should be enabled or disabled contrary to the cpu 17306c3fb27SDimitry Andric /// specification. 17406c3fb27SDimitry Andric class SubtargetFeatures { 17506c3fb27SDimitry Andric std::vector<std::string> Features; ///< Subtarget features as a vector 17606c3fb27SDimitry Andric 17706c3fb27SDimitry Andric public: 17806c3fb27SDimitry Andric explicit SubtargetFeatures(StringRef Initial = ""); 17906c3fb27SDimitry Andric 18006c3fb27SDimitry Andric /// Returns features as a string. 18106c3fb27SDimitry Andric std::string getString() const; 18206c3fb27SDimitry Andric 18306c3fb27SDimitry Andric /// Adds Features. 18406c3fb27SDimitry Andric void AddFeature(StringRef String, bool Enable = true); 18506c3fb27SDimitry Andric 18606c3fb27SDimitry Andric void addFeaturesVector(const ArrayRef<std::string> OtherFeatures); 18706c3fb27SDimitry Andric 18806c3fb27SDimitry Andric /// Returns the vector of individual subtarget features. getFeatures()18906c3fb27SDimitry Andric const std::vector<std::string> &getFeatures() const { return Features; } 19006c3fb27SDimitry Andric 19106c3fb27SDimitry Andric /// Prints feature string. 19206c3fb27SDimitry Andric void print(raw_ostream &OS) const; 19306c3fb27SDimitry Andric 19406c3fb27SDimitry Andric // Dumps feature info. 19506c3fb27SDimitry Andric void dump() const; 19606c3fb27SDimitry Andric 19706c3fb27SDimitry Andric /// Adds the default features for the specified target triple. 19806c3fb27SDimitry Andric void getDefaultSubtargetFeatures(const Triple& Triple); 19906c3fb27SDimitry Andric 20006c3fb27SDimitry Andric /// Determine if a feature has a flag; '+' or '-' hasFlag(StringRef Feature)20106c3fb27SDimitry Andric static bool hasFlag(StringRef Feature) { 20206c3fb27SDimitry Andric assert(!Feature.empty() && "Empty string"); 20306c3fb27SDimitry Andric // Get first character 20406c3fb27SDimitry Andric char Ch = Feature[0]; 20506c3fb27SDimitry Andric // Check if first character is '+' or '-' flag 20606c3fb27SDimitry Andric return Ch == '+' || Ch =='-'; 20706c3fb27SDimitry Andric } 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric /// Return string stripped of flag. StripFlag(StringRef Feature)21006c3fb27SDimitry Andric static StringRef StripFlag(StringRef Feature) { 21106c3fb27SDimitry Andric return hasFlag(Feature) ? Feature.substr(1) : Feature; 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric /// Return true if enable flag; '+'. isEnabled(StringRef Feature)21506c3fb27SDimitry Andric static inline bool isEnabled(StringRef Feature) { 21606c3fb27SDimitry Andric assert(!Feature.empty() && "Empty string"); 21706c3fb27SDimitry Andric // Get first character 21806c3fb27SDimitry Andric char Ch = Feature[0]; 21906c3fb27SDimitry Andric // Check if first character is '+' for enabled 22006c3fb27SDimitry Andric return Ch == '+'; 22106c3fb27SDimitry Andric } 22206c3fb27SDimitry Andric 22306c3fb27SDimitry Andric /// Splits a string of comma separated items in to a vector of strings. 22406c3fb27SDimitry Andric static void Split(std::vector<std::string> &V, StringRef S); 22506c3fb27SDimitry Andric }; 22606c3fb27SDimitry Andric 22706c3fb27SDimitry Andric } // end namespace llvm 22806c3fb27SDimitry Andric 22906c3fb27SDimitry Andric #endif // LLVM_TARGETPARSER_SUBTARGETFEATURE_H 230