1321369Sdim//===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- C++ -*-===// 2224133Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6224133Sdim// 7224133Sdim//===----------------------------------------------------------------------===// 8224133Sdim// 9321369Sdim/// \file Defines and manages user or tool specified CPU characteristics. 10321369Sdim/// The intent is to be able to package specific features that should or should 11321369Sdim/// not be used on a specific target processor. A tool, such as llc, could, as 12321369Sdim/// as example, gather chip info from the command line, a long with features 13321369Sdim/// that should be used on that chip. 14224133Sdim// 15224133Sdim//===----------------------------------------------------------------------===// 16224133Sdim 17224133Sdim#ifndef LLVM_MC_SUBTARGETFEATURE_H 18224133Sdim#define LLVM_MC_SUBTARGETFEATURE_H 19224133Sdim 20321369Sdim#include "llvm/ADT/StringRef.h" 21360784Sdim#include "llvm/Support/MathExtras.h" 22353358Sdim#include <array> 23288943Sdim#include <bitset> 24321369Sdim#include <initializer_list> 25321369Sdim#include <string> 26309124Sdim#include <vector> 27224133Sdim 28224133Sdimnamespace llvm { 29321369Sdim 30321369Sdimclass raw_ostream; 31321369Sdimclass Triple; 32239462Sdim 33353358Sdimconst unsigned MAX_SUBTARGET_WORDS = 3; 34353358Sdimconst unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64; 35353358Sdim 36321369Sdim/// Container class for subtarget features. 37360784Sdim/// This is a constexpr reimplementation of a subset of std::bitset. It would be 38360784Sdim/// nice to use std::bitset directly, but it doesn't support constant 39360784Sdim/// initialization. 40360784Sdimclass FeatureBitset { 41360784Sdim static_assert((MAX_SUBTARGET_FEATURES % 64) == 0, 42360784Sdim "Should be a multiple of 64!"); 43360784Sdim // This cannot be a std::array, operator[] is not constexpr until C++17. 44360784Sdim uint64_t Bits[MAX_SUBTARGET_WORDS] = {}; 45288943Sdim 46360784Sdimprotected: 47360784Sdim constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) { 48360784Sdim for (unsigned I = 0; I != B.size(); ++I) 49360784Sdim Bits[I] = B[I]; 50360784Sdim } 51288943Sdim 52360784Sdimpublic: 53360784Sdim constexpr FeatureBitset() = default; 54360784Sdim constexpr FeatureBitset(std::initializer_list<unsigned> Init) { 55296417Sdim for (auto I : Init) 56296417Sdim set(I); 57288943Sdim } 58353358Sdim 59360784Sdim FeatureBitset &set() { 60360784Sdim std::fill(std::begin(Bits), std::end(Bits), -1ULL); 61360784Sdim return *this; 62360784Sdim } 63360784Sdim 64360784Sdim constexpr FeatureBitset &set(unsigned I) { 65360784Sdim // GCC <6.2 crashes if this is written in a single statement. 66360784Sdim uint64_t NewBits = Bits[I / 64] | (uint64_t(1) << (I % 64)); 67360784Sdim Bits[I / 64] = NewBits; 68360784Sdim return *this; 69360784Sdim } 70360784Sdim 71360784Sdim constexpr FeatureBitset &reset(unsigned I) { 72360784Sdim // GCC <6.2 crashes if this is written in a single statement. 73360784Sdim uint64_t NewBits = Bits[I / 64] & ~(uint64_t(1) << (I % 64)); 74360784Sdim Bits[I / 64] = NewBits; 75360784Sdim return *this; 76360784Sdim } 77360784Sdim 78360784Sdim constexpr FeatureBitset &flip(unsigned I) { 79360784Sdim // GCC <6.2 crashes if this is written in a single statement. 80360784Sdim uint64_t NewBits = Bits[I / 64] ^ (uint64_t(1) << (I % 64)); 81360784Sdim Bits[I / 64] = NewBits; 82360784Sdim return *this; 83360784Sdim } 84360784Sdim 85360784Sdim constexpr bool operator[](unsigned I) const { 86360784Sdim uint64_t Mask = uint64_t(1) << (I % 64); 87360784Sdim return (Bits[I / 64] & Mask) != 0; 88360784Sdim } 89360784Sdim 90360784Sdim constexpr bool test(unsigned I) const { return (*this)[I]; } 91360784Sdim 92360784Sdim constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; } 93360784Sdim 94360784Sdim bool any() const { 95360784Sdim return llvm::any_of(Bits, [](uint64_t I) { return I != 0; }); 96360784Sdim } 97360784Sdim bool none() const { return !any(); } 98360784Sdim size_t count() const { 99360784Sdim size_t Count = 0; 100360784Sdim for (auto B : Bits) 101360784Sdim Count += countPopulation(B); 102360784Sdim return Count; 103360784Sdim } 104360784Sdim 105360784Sdim constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) { 106360784Sdim for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) { 107360784Sdim Bits[I] ^= RHS.Bits[I]; 108360784Sdim } 109360784Sdim return *this; 110360784Sdim } 111360784Sdim constexpr FeatureBitset operator^(const FeatureBitset &RHS) const { 112360784Sdim FeatureBitset Result = *this; 113360784Sdim Result ^= RHS; 114360784Sdim return Result; 115360784Sdim } 116360784Sdim 117360784Sdim constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) { 118360784Sdim for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) { 119360784Sdim Bits[I] &= RHS.Bits[I]; 120360784Sdim } 121360784Sdim return *this; 122360784Sdim } 123360784Sdim constexpr FeatureBitset operator&(const FeatureBitset &RHS) const { 124360784Sdim FeatureBitset Result = *this; 125360784Sdim Result &= RHS; 126360784Sdim return Result; 127360784Sdim } 128360784Sdim 129360784Sdim constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) { 130360784Sdim for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) { 131360784Sdim Bits[I] |= RHS.Bits[I]; 132360784Sdim } 133360784Sdim return *this; 134360784Sdim } 135360784Sdim constexpr FeatureBitset operator|(const FeatureBitset &RHS) const { 136360784Sdim FeatureBitset Result = *this; 137360784Sdim Result |= RHS; 138360784Sdim return Result; 139360784Sdim } 140360784Sdim 141360784Sdim constexpr FeatureBitset operator~() const { 142360784Sdim FeatureBitset Result = *this; 143360784Sdim for (auto &B : Result.Bits) 144360784Sdim B = ~B; 145360784Sdim return Result; 146360784Sdim } 147360784Sdim 148360784Sdim bool operator==(const FeatureBitset &RHS) const { 149360784Sdim return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits)); 150360784Sdim } 151360784Sdim 152360784Sdim bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); } 153360784Sdim 154353358Sdim bool operator < (const FeatureBitset &Other) const { 155353358Sdim for (unsigned I = 0, E = size(); I != E; ++I) { 156353358Sdim bool LHS = test(I), RHS = Other.test(I); 157353358Sdim if (LHS != RHS) 158353358Sdim return LHS < RHS; 159353358Sdim } 160353358Sdim return false; 161353358Sdim } 162288943Sdim}; 163288943Sdim 164353358Sdim/// Class used to store the subtarget bits in the tables created by tablegen. 165360784Sdimclass FeatureBitArray : public FeatureBitset { 166353358Sdimpublic: 167353358Sdim constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) 168360784Sdim : FeatureBitset(B) {} 169239462Sdim 170360784Sdim const FeatureBitset &getAsBitset() const { return *this; } 171224133Sdim}; 172239462Sdim 173224133Sdim//===----------------------------------------------------------------------===// 174321369Sdim 175321369Sdim/// Manages the enabling and disabling of subtarget specific features. 176224133Sdim/// 177321369Sdim/// Features are encoded as a string of the form 178251662Sdim/// "+attr1,+attr2,-attr3,...,+attrN" 179224133Sdim/// A comma separates each feature from the next (all lowercase.) 180224133Sdim/// Each of the remaining features is prefixed with + or - indicating whether 181224133Sdim/// that feature should be enabled or disabled contrary to the cpu 182224133Sdim/// specification. 183321369Sdimclass SubtargetFeatures { 184321369Sdim std::vector<std::string> Features; ///< Subtarget features as a vector 185224133Sdim 186224133Sdimpublic: 187280031Sdim explicit SubtargetFeatures(StringRef Initial = ""); 188224133Sdim 189321369Sdim /// Returns features as a string. 190224133Sdim std::string getString() const; 191224133Sdim 192321369Sdim /// Adds Features. 193288943Sdim void AddFeature(StringRef String, bool Enable = true); 194239462Sdim 195327952Sdim /// Returns the vector of individual subtarget features. 196327952Sdim const std::vector<std::string> &getFeatures() const { return Features; } 197327952Sdim 198321369Sdim /// Prints feature string. 199224133Sdim void print(raw_ostream &OS) const; 200239462Sdim 201321369Sdim // Dumps feature info. 202224133Sdim void dump() const; 203224133Sdim 204261991Sdim /// Adds the default features for the specified target triple. 205224133Sdim void getDefaultSubtargetFeatures(const Triple& Triple); 206353358Sdim 207353358Sdim /// Determine if a feature has a flag; '+' or '-' 208353358Sdim static bool hasFlag(StringRef Feature) { 209353358Sdim assert(!Feature.empty() && "Empty string"); 210353358Sdim // Get first character 211353358Sdim char Ch = Feature[0]; 212353358Sdim // Check if first character is '+' or '-' flag 213353358Sdim return Ch == '+' || Ch =='-'; 214353358Sdim } 215353358Sdim 216353358Sdim /// Return string stripped of flag. 217353358Sdim static std::string StripFlag(StringRef Feature) { 218353358Sdim return hasFlag(Feature) ? Feature.substr(1) : Feature; 219353358Sdim } 220353358Sdim 221353358Sdim /// Return true if enable flag; '+'. 222353358Sdim static inline bool isEnabled(StringRef Feature) { 223353358Sdim assert(!Feature.empty() && "Empty string"); 224353358Sdim // Get first character 225353358Sdim char Ch = Feature[0]; 226353358Sdim // Check if first character is '+' for enabled 227353358Sdim return Ch == '+'; 228353358Sdim } 229353358Sdim 230353358Sdim /// Splits a string of comma separated items in to a vector of strings. 231353358Sdim static void Split(std::vector<std::string> &V, StringRef S); 232224133Sdim}; 233224133Sdim 234321369Sdim} // end namespace llvm 235224133Sdim 236321369Sdim#endif // LLVM_MC_SUBTARGETFEATURE_H 237