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