237 lines
7.1 KiB
C
237 lines
7.1 KiB
C
|
//===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- C++ -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
/// \file Defines and manages user or tool specified CPU characteristics.
|
||
|
/// The intent is to be able to package specific features that should or should
|
||
|
/// not be used on a specific target processor. A tool, such as llc, could, as
|
||
|
/// as example, gather chip info from the command line, a long with features
|
||
|
/// that should be used on that chip.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#ifndef LLVM_MC_SUBTARGETFEATURE_H
|
||
|
#define LLVM_MC_SUBTARGETFEATURE_H
|
||
|
|
||
|
#include "llvm/ADT/StringRef.h"
|
||
|
#include "llvm/Support/MathExtras.h"
|
||
|
#include <array>
|
||
|
#include <bitset>
|
||
|
#include <initializer_list>
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace llvm {
|
||
|
|
||
|
class raw_ostream;
|
||
|
class Triple;
|
||
|
|
||
|
const unsigned MAX_SUBTARGET_WORDS = 4;
|
||
|
const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
|
||
|
|
||
|
/// Container class for subtarget features.
|
||
|
/// This is a constexpr reimplementation of a subset of std::bitset. It would be
|
||
|
/// nice to use std::bitset directly, but it doesn't support constant
|
||
|
/// initialization.
|
||
|
class FeatureBitset {
|
||
|
static_assert((MAX_SUBTARGET_FEATURES % 64) == 0,
|
||
|
"Should be a multiple of 64!");
|
||
|
// This cannot be a std::array, operator[] is not constexpr until C++17.
|
||
|
uint64_t Bits[MAX_SUBTARGET_WORDS] = {};
|
||
|
|
||
|
protected:
|
||
|
constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) {
|
||
|
for (unsigned I = 0; I != B.size(); ++I)
|
||
|
Bits[I] = B[I];
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
constexpr FeatureBitset() = default;
|
||
|
constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
|
||
|
for (auto I : Init)
|
||
|
set(I);
|
||
|
}
|
||
|
|
||
|
FeatureBitset &set() {
|
||
|
std::fill(std::begin(Bits), std::end(Bits), -1ULL);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
constexpr FeatureBitset &set(unsigned I) {
|
||
|
// GCC <6.2 crashes if this is written in a single statement.
|
||
|
uint64_t NewBits = Bits[I / 64] | (uint64_t(1) << (I % 64));
|
||
|
Bits[I / 64] = NewBits;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
constexpr FeatureBitset &reset(unsigned I) {
|
||
|
// GCC <6.2 crashes if this is written in a single statement.
|
||
|
uint64_t NewBits = Bits[I / 64] & ~(uint64_t(1) << (I % 64));
|
||
|
Bits[I / 64] = NewBits;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
constexpr FeatureBitset &flip(unsigned I) {
|
||
|
// GCC <6.2 crashes if this is written in a single statement.
|
||
|
uint64_t NewBits = Bits[I / 64] ^ (uint64_t(1) << (I % 64));
|
||
|
Bits[I / 64] = NewBits;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
constexpr bool operator[](unsigned I) const {
|
||
|
uint64_t Mask = uint64_t(1) << (I % 64);
|
||
|
return (Bits[I / 64] & Mask) != 0;
|
||
|
}
|
||
|
|
||
|
constexpr bool test(unsigned I) const { return (*this)[I]; }
|
||
|
|
||
|
constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
|
||
|
|
||
|
bool any() const {
|
||
|
return llvm::any_of(Bits, [](uint64_t I) { return I != 0; });
|
||
|
}
|
||
|
bool none() const { return !any(); }
|
||
|
size_t count() const {
|
||
|
size_t Count = 0;
|
||
|
for (auto B : Bits)
|
||
|
Count += countPopulation(B);
|
||
|
return Count;
|
||
|
}
|
||
|
|
||
|
constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) {
|
||
|
for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
|
||
|
Bits[I] ^= RHS.Bits[I];
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
constexpr FeatureBitset operator^(const FeatureBitset &RHS) const {
|
||
|
FeatureBitset Result = *this;
|
||
|
Result ^= RHS;
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
|
||
|
for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
|
||
|
Bits[I] &= RHS.Bits[I];
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
|
||
|
FeatureBitset Result = *this;
|
||
|
Result &= RHS;
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
|
||
|
for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
|
||
|
Bits[I] |= RHS.Bits[I];
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
|
||
|
FeatureBitset Result = *this;
|
||
|
Result |= RHS;
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
constexpr FeatureBitset operator~() const {
|
||
|
FeatureBitset Result = *this;
|
||
|
for (auto &B : Result.Bits)
|
||
|
B = ~B;
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
bool operator==(const FeatureBitset &RHS) const {
|
||
|
return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits));
|
||
|
}
|
||
|
|
||
|
bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); }
|
||
|
|
||
|
bool operator < (const FeatureBitset &Other) const {
|
||
|
for (unsigned I = 0, E = size(); I != E; ++I) {
|
||
|
bool LHS = test(I), RHS = Other.test(I);
|
||
|
if (LHS != RHS)
|
||
|
return LHS < RHS;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// Class used to store the subtarget bits in the tables created by tablegen.
|
||
|
class FeatureBitArray : public FeatureBitset {
|
||
|
public:
|
||
|
constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
|
||
|
: FeatureBitset(B) {}
|
||
|
|
||
|
const FeatureBitset &getAsBitset() const { return *this; }
|
||
|
};
|
||
|
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
/// Manages the enabling and disabling of subtarget specific features.
|
||
|
///
|
||
|
/// Features are encoded as a string of the form
|
||
|
/// "+attr1,+attr2,-attr3,...,+attrN"
|
||
|
/// A comma separates each feature from the next (all lowercase.)
|
||
|
/// Each of the remaining features is prefixed with + or - indicating whether
|
||
|
/// that feature should be enabled or disabled contrary to the cpu
|
||
|
/// specification.
|
||
|
class SubtargetFeatures {
|
||
|
std::vector<std::string> Features; ///< Subtarget features as a vector
|
||
|
|
||
|
public:
|
||
|
explicit SubtargetFeatures(StringRef Initial = "");
|
||
|
|
||
|
/// Returns features as a string.
|
||
|
std::string getString() const;
|
||
|
|
||
|
/// Adds Features.
|
||
|
void AddFeature(StringRef String, bool Enable = true);
|
||
|
|
||
|
/// Returns the vector of individual subtarget features.
|
||
|
const std::vector<std::string> &getFeatures() const { return Features; }
|
||
|
|
||
|
/// Prints feature string.
|
||
|
void print(raw_ostream &OS) const;
|
||
|
|
||
|
// Dumps feature info.
|
||
|
void dump() const;
|
||
|
|
||
|
/// Adds the default features for the specified target triple.
|
||
|
void getDefaultSubtargetFeatures(const Triple& Triple);
|
||
|
|
||
|
/// Determine if a feature has a flag; '+' or '-'
|
||
|
static bool hasFlag(StringRef Feature) {
|
||
|
assert(!Feature.empty() && "Empty string");
|
||
|
// Get first character
|
||
|
char Ch = Feature[0];
|
||
|
// Check if first character is '+' or '-' flag
|
||
|
return Ch == '+' || Ch =='-';
|
||
|
}
|
||
|
|
||
|
/// Return string stripped of flag.
|
||
|
static StringRef StripFlag(StringRef Feature) {
|
||
|
return hasFlag(Feature) ? Feature.substr(1) : Feature;
|
||
|
}
|
||
|
|
||
|
/// Return true if enable flag; '+'.
|
||
|
static inline bool isEnabled(StringRef Feature) {
|
||
|
assert(!Feature.empty() && "Empty string");
|
||
|
// Get first character
|
||
|
char Ch = Feature[0];
|
||
|
// Check if first character is '+' for enabled
|
||
|
return Ch == '+';
|
||
|
}
|
||
|
|
||
|
/// Splits a string of comma separated items in to a vector of strings.
|
||
|
static void Split(std::vector<std::string> &V, StringRef S);
|
||
|
};
|
||
|
|
||
|
} // end namespace llvm
|
||
|
|
||
|
#endif // LLVM_MC_SUBTARGETFEATURE_H
|