Home | History | Annotate | Line # | Download | only in MC
      1 //===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 /// \file Defines and manages user or tool specified CPU characteristics.
     10 /// The intent is to be able to package specific features that should or should
     11 /// not be used on a specific target processor.  A tool, such as llc, could, as
     12 /// as example, gather chip info from the command line, a long with features
     13 /// that should be used on that chip.
     14 //
     15 //===----------------------------------------------------------------------===//
     16 
     17 #ifndef LLVM_MC_SUBTARGETFEATURE_H
     18 #define LLVM_MC_SUBTARGETFEATURE_H
     19 
     20 #include "llvm/ADT/StringRef.h"
     21 #include "llvm/Support/MathExtras.h"
     22 #include <array>
     23 #include <bitset>
     24 #include <initializer_list>
     25 #include <string>
     26 #include <vector>
     27 
     28 namespace llvm {
     29 
     30 class raw_ostream;
     31 class Triple;
     32 
     33 const unsigned MAX_SUBTARGET_WORDS = 4;
     34 const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
     35 
     36 /// Container class for subtarget features.
     37 /// This is a constexpr reimplementation of a subset of std::bitset. It would be
     38 /// nice to use std::bitset directly, but it doesn't support constant
     39 /// initialization.
     40 class FeatureBitset {
     41   static_assert((MAX_SUBTARGET_FEATURES % 64) == 0,
     42                 "Should be a multiple of 64!");
     43   // This cannot be a std::array, operator[] is not constexpr until C++17.
     44   uint64_t Bits[MAX_SUBTARGET_WORDS] = {};
     45 
     46 protected:
     47   constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) {
     48     for (unsigned I = 0; I != B.size(); ++I)
     49       Bits[I] = B[I];
     50   }
     51 
     52 public:
     53   constexpr FeatureBitset() = default;
     54   constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
     55     for (auto I : Init)
     56       set(I);
     57   }
     58 
     59   FeatureBitset &set() {
     60     std::fill(std::begin(Bits), std::end(Bits), -1ULL);
     61     return *this;
     62   }
     63 
     64   constexpr FeatureBitset &set(unsigned I) {
     65     // GCC <6.2 crashes if this is written in a single statement.
     66     uint64_t NewBits = Bits[I / 64] | (uint64_t(1) << (I % 64));
     67     Bits[I / 64] = NewBits;
     68     return *this;
     69   }
     70 
     71   constexpr FeatureBitset &reset(unsigned I) {
     72     // GCC <6.2 crashes if this is written in a single statement.
     73     uint64_t NewBits = Bits[I / 64] & ~(uint64_t(1) << (I % 64));
     74     Bits[I / 64] = NewBits;
     75     return *this;
     76   }
     77 
     78   constexpr FeatureBitset &flip(unsigned I) {
     79     // GCC <6.2 crashes if this is written in a single statement.
     80     uint64_t NewBits = Bits[I / 64] ^ (uint64_t(1) << (I % 64));
     81     Bits[I / 64] = NewBits;
     82     return *this;
     83   }
     84 
     85   constexpr bool operator[](unsigned I) const {
     86     uint64_t Mask = uint64_t(1) << (I % 64);
     87     return (Bits[I / 64] & Mask) != 0;
     88   }
     89 
     90   constexpr bool test(unsigned I) const { return (*this)[I]; }
     91 
     92   constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
     93 
     94   bool any() const {
     95     return llvm::any_of(Bits, [](uint64_t I) { return I != 0; });
     96   }
     97   bool none() const { return !any(); }
     98   size_t count() const {
     99     size_t Count = 0;
    100     for (auto B : Bits)
    101       Count += countPopulation(B);
    102     return Count;
    103   }
    104 
    105   constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) {
    106     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
    107       Bits[I] ^= RHS.Bits[I];
    108     }
    109     return *this;
    110   }
    111   constexpr FeatureBitset operator^(const FeatureBitset &RHS) const {
    112     FeatureBitset Result = *this;
    113     Result ^= RHS;
    114     return Result;
    115   }
    116 
    117   constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
    118     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
    119       Bits[I] &= RHS.Bits[I];
    120     }
    121     return *this;
    122   }
    123   constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
    124     FeatureBitset Result = *this;
    125     Result &= RHS;
    126     return Result;
    127   }
    128 
    129   constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
    130     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
    131       Bits[I] |= RHS.Bits[I];
    132     }
    133     return *this;
    134   }
    135   constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
    136     FeatureBitset Result = *this;
    137     Result |= RHS;
    138     return Result;
    139   }
    140 
    141   constexpr FeatureBitset operator~() const {
    142     FeatureBitset Result = *this;
    143     for (auto &B : Result.Bits)
    144       B = ~B;
    145     return Result;
    146   }
    147 
    148   bool operator==(const FeatureBitset &RHS) const {
    149     return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits));
    150   }
    151 
    152   bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); }
    153 
    154   bool operator < (const FeatureBitset &Other) const {
    155     for (unsigned I = 0, E = size(); I != E; ++I) {
    156       bool LHS = test(I), RHS = Other.test(I);
    157       if (LHS != RHS)
    158         return LHS < RHS;
    159     }
    160     return false;
    161   }
    162 };
    163 
    164 /// Class used to store the subtarget bits in the tables created by tablegen.
    165 class FeatureBitArray : public FeatureBitset {
    166 public:
    167   constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
    168       : FeatureBitset(B) {}
    169 
    170   const FeatureBitset &getAsBitset() const { return *this; }
    171 };
    172 
    173 //===----------------------------------------------------------------------===//
    174 
    175 /// Manages the enabling and disabling of subtarget specific features.
    176 ///
    177 /// Features are encoded as a string of the form
    178 ///   "+attr1,+attr2,-attr3,...,+attrN"
    179 /// A comma separates each feature from the next (all lowercase.)
    180 /// Each of the remaining features is prefixed with + or - indicating whether
    181 /// that feature should be enabled or disabled contrary to the cpu
    182 /// specification.
    183 class SubtargetFeatures {
    184   std::vector<std::string> Features;    ///< Subtarget features as a vector
    185 
    186 public:
    187   explicit SubtargetFeatures(StringRef Initial = "");
    188 
    189   /// Returns features as a string.
    190   std::string getString() const;
    191 
    192   /// Adds Features.
    193   void AddFeature(StringRef String, bool Enable = true);
    194 
    195   /// Returns the vector of individual subtarget features.
    196   const std::vector<std::string> &getFeatures() const { return Features; }
    197 
    198   /// Prints feature string.
    199   void print(raw_ostream &OS) const;
    200 
    201   // Dumps feature info.
    202   void dump() const;
    203 
    204   /// Adds the default features for the specified target triple.
    205   void getDefaultSubtargetFeatures(const Triple& Triple);
    206 
    207   /// Determine if a feature has a flag; '+' or '-'
    208   static bool hasFlag(StringRef Feature) {
    209     assert(!Feature.empty() && "Empty string");
    210     // Get first character
    211     char Ch = Feature[0];
    212     // Check if first character is '+' or '-' flag
    213     return Ch == '+' || Ch =='-';
    214   }
    215 
    216   /// Return string stripped of flag.
    217   static StringRef StripFlag(StringRef Feature) {
    218     return hasFlag(Feature) ? Feature.substr(1) : Feature;
    219   }
    220 
    221   /// Return true if enable flag; '+'.
    222   static inline bool isEnabled(StringRef Feature) {
    223     assert(!Feature.empty() && "Empty string");
    224     // Get first character
    225     char Ch = Feature[0];
    226     // Check if first character is '+' for enabled
    227     return Ch == '+';
    228   }
    229 
    230   /// Splits a string of comma separated items in to a vector of strings.
    231   static void Split(std::vector<std::string> &V, StringRef S);
    232 };
    233 
    234 } // end namespace llvm
    235 
    236 #endif // LLVM_MC_SUBTARGETFEATURE_H
    237