Skip to content

Commit

Permalink
Use std::bitset for SubtargetFeatures
Browse files Browse the repository at this point in the history
Previously, subtarget features were a bitfield with the underlying type being uint64_t. 
Since several targets (X86 and ARM, in particular) have hit or were very close to hitting this bound, switching the features to use a bitset.

No functional change.

Differential Revision: http://reviews.llvm.org/D7065

llvm-svn: 229831
  • Loading branch information
Michael Kuperstein committed Feb 19, 2015
1 parent 36f974d commit ba5b04c
Show file tree
Hide file tree
Showing 33 changed files with 356 additions and 328 deletions.
9 changes: 5 additions & 4 deletions llvm/include/llvm/MC/MCInstPrinter.h
Expand Up @@ -10,6 +10,7 @@
#ifndef LLVM_MC_MCINSTPRINTER_H
#define LLVM_MC_MCINSTPRINTER_H

#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Format.h"

Expand Down Expand Up @@ -41,7 +42,7 @@ class MCInstPrinter {
const MCRegisterInfo &MRI;

/// The current set of available features.
uint64_t AvailableFeatures;
FeatureBitset AvailableFeatures;

/// True if we are printing marked up assembly.
bool UseMarkup;
Expand All @@ -58,7 +59,7 @@ class MCInstPrinter {
MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii,
const MCRegisterInfo &mri)
: CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri),
AvailableFeatures(0), UseMarkup(0), PrintImmHex(0),
AvailableFeatures(), UseMarkup(0), PrintImmHex(0),
PrintHexStyle(HexStyle::C) {}

virtual ~MCInstPrinter();
Expand All @@ -78,8 +79,8 @@ class MCInstPrinter {
/// printRegName - Print the assembler register name.
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;

uint64_t getAvailableFeatures() const { return AvailableFeatures; }
void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; }
const FeatureBitset& getAvailableFeatures() const { return AvailableFeatures; }
void setAvailableFeatures(const FeatureBitset& Value) { AvailableFeatures = Value; }

bool getUseMarkup() const { return UseMarkup; }
void setUseMarkup(bool Value) { UseMarkup = Value; }
Expand Down
4 changes: 2 additions & 2 deletions llvm/include/llvm/MC/MCInstrDesc.h
Expand Up @@ -150,7 +150,7 @@ class MCInstrDesc {
const uint16_t *ImplicitUses; // Registers implicitly read by this instr
const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr
const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands
uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any
FeatureBitset DeprecatedFeatureMask; // Feature bits that this is deprecated on, if any
// A complex method to determine is a certain is deprecated or not, and return
// the reason for deprecation.
bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &);
Expand All @@ -173,7 +173,7 @@ class MCInstrDesc {
std::string &Info) const {
if (ComplexDeprecationInfo)
return ComplexDeprecationInfo(MI, STI, Info);
if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) {
if ((STI.getFeatureBits() & DeprecatedFeatureMask).any()) {
// FIXME: it would be nice to include the subtarget feature here.
Info = "deprecated";
return true;
Expand Down
16 changes: 10 additions & 6 deletions llvm/include/llvm/MC/MCSubtargetInfo.h
Expand Up @@ -42,7 +42,7 @@ class MCSubtargetInfo {
const InstrStage *Stages; // Instruction itinerary stages
const unsigned *OperandCycles; // Itinerary operand cycles
const unsigned *ForwardingPaths; // Forwarding paths
uint64_t FeatureBits; // Feature bits for current CPU + FS
FeatureBitset FeatureBits; // Feature bits for current CPU + FS

public:
void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS,
Expand All @@ -67,13 +67,13 @@ class MCSubtargetInfo {

/// getFeatureBits - Return the feature bits.
///
uint64_t getFeatureBits() const {
const FeatureBitset& getFeatureBits() const {
return FeatureBits;
}

/// setFeatureBits - Set the feature bits.
///
void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; }
void setFeatureBits(FeatureBitset& FeatureBits_) { FeatureBits = FeatureBits_; }

/// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with
/// feature string). Recompute feature bits and scheduling model.
Expand All @@ -84,11 +84,15 @@ class MCSubtargetInfo {

/// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version does not change the implied bits.
uint64_t ToggleFeature(uint64_t FB);
FeatureBitset ToggleFeature(uint64_t FB);

/// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version will also change all implied bits.
uint64_t ToggleFeature(StringRef FS);
/// bits. This version does not change the implied bits.
FeatureBitset ToggleFeature(const FeatureBitset& FB);

/// ToggleFeature - Toggle a set of features and returns the re-computed
/// feature bits. This version will also change all implied bits.
FeatureBitset ToggleFeature(StringRef FS);

/// getSchedModelForCPU - Get the machine model of a CPU.
///
Expand Down
26 changes: 22 additions & 4 deletions llvm/include/llvm/MC/SubtargetFeature.h
Expand Up @@ -21,11 +21,29 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/DataTypes.h"
#include <bitset>

namespace llvm {
class raw_ostream;
class StringRef;

// A container class for subtarget features.
// This is convenient because std::bitset does not have a constructor
// with an initializer list of set bits.
const unsigned MAX_SUBTARGET_FEATURES = 64;
class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> {
public:
// Cannot inherit constructors because it's not supported by VC++..
FeatureBitset() : bitset() {}

FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}

FeatureBitset(std::initializer_list<unsigned> Init) : bitset() {
for (auto I = Init.begin() , E = Init.end(); I != E; ++I)
set(*I);
}
};

//===----------------------------------------------------------------------===//
///
/// SubtargetFeatureKV - Used to provide key value pairs for feature and
Expand All @@ -34,8 +52,8 @@ namespace llvm {
struct SubtargetFeatureKV {
const char *Key; // K-V key string
const char *Desc; // Help descriptor
uint64_t Value; // K-V integer value
uint64_t Implies; // K-V bit mask
FeatureBitset Value; // K-V integer value
FeatureBitset Implies; // K-V bit mask

// Compare routine for std::lower_bound
bool operator<(StringRef S) const {
Expand Down Expand Up @@ -82,11 +100,11 @@ class SubtargetFeatures {

/// ToggleFeature - Toggle a feature and returns the newly updated feature
/// bits.
uint64_t ToggleFeature(uint64_t Bits, StringRef String,
FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String,
ArrayRef<SubtargetFeatureKV> FeatureTable);

/// Get feature bits of a CPU.
uint64_t getFeatureBits(StringRef CPU,
FeatureBitset getFeatureBits(StringRef CPU,
ArrayRef<SubtargetFeatureKV> CPUTable,
ArrayRef<SubtargetFeatureKV> FeatureTable);

Expand Down
9 changes: 7 additions & 2 deletions llvm/lib/MC/MCSubtargetInfo.cpp
Expand Up @@ -63,14 +63,19 @@ MCSubtargetInfo::InitMCSubtargetInfo(StringRef TT, StringRef C, StringRef FS,

/// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version does not change the implied bits.
uint64_t MCSubtargetInfo::ToggleFeature(uint64_t FB) {
FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
FeatureBits.flip(FB);
return FeatureBits;
}

FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
FeatureBits ^= FB;
return FeatureBits;
}

/// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version will also change all implied bits.
uint64_t MCSubtargetInfo::ToggleFeature(StringRef FS) {
FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef FS) {
SubtargetFeatures Features;
FeatureBits = Features.ToggleFeature(FeatureBits, FS, ProcFeatures);
return FeatureBits;
Expand Down
23 changes: 12 additions & 11 deletions llvm/lib/MC/SubtargetFeature.cpp
Expand Up @@ -150,12 +150,12 @@ std::string SubtargetFeatures::getString() const {
/// feature, set it.
///
static
void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV *FeatureEntry,
ArrayRef<SubtargetFeatureKV> FeatureTable) {
for (auto &FE : FeatureTable) {
if (FeatureEntry->Value == FE.Value) continue;

if (FeatureEntry->Implies & FE.Value) {
if ((FeatureEntry->Implies & FE.Value).any()) {
Bits |= FE.Value;
SetImpliedBits(Bits, &FE, FeatureTable);
}
Expand All @@ -166,12 +166,13 @@ void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
/// feature, clear it.
///
static
void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
void ClearImpliedBits(FeatureBitset &Bits,
const SubtargetFeatureKV *FeatureEntry,
ArrayRef<SubtargetFeatureKV> FeatureTable) {
for (auto &FE : FeatureTable) {
if (FeatureEntry->Value == FE.Value) continue;

if (FE.Implies & FeatureEntry->Value) {
if ((FE.Implies & FeatureEntry->Value).any()) {
Bits &= ~FE.Value;
ClearImpliedBits(Bits, &FE, FeatureTable);
}
Expand All @@ -180,8 +181,8 @@ void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,

/// ToggleFeature - Toggle a feature and returns the newly updated feature
/// bits.
uint64_t
SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature,
FeatureBitset
SubtargetFeatures::ToggleFeature(FeatureBitset Bits, StringRef Feature,
ArrayRef<SubtargetFeatureKV> FeatureTable) {

// Find feature in table.
Expand All @@ -191,7 +192,6 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature,
if (FeatureEntry) {
if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
Bits &= ~FeatureEntry->Value;

// For each feature that implies this, clear it.
ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
} else {
Expand All @@ -212,13 +212,13 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature,

/// getFeatureBits - Get feature bits a CPU.
///
uint64_t
FeatureBitset
SubtargetFeatures::getFeatureBits(StringRef CPU,
ArrayRef<SubtargetFeatureKV> CPUTable,
ArrayRef<SubtargetFeatureKV> FeatureTable) {

if (CPUTable.empty() || FeatureTable.empty())
return 0;
return FeatureBitset();

#ifndef NDEBUG
for (size_t i = 1, e = CPUTable.size(); i != e; ++i) {
Expand All @@ -230,7 +230,8 @@ SubtargetFeatures::getFeatureBits(StringRef CPU,
"CPU features table is not sorted");
}
#endif
uint64_t Bits = 0; // Resulting bits
// Resulting bits
FeatureBitset Bits;

// Check if help is needed
if (CPU == "help")
Expand All @@ -247,7 +248,7 @@ SubtargetFeatures::getFeatureBits(StringRef CPU,

// Set the feature implied by this CPU feature, if any.
for (auto &FE : FeatureTable) {
if (CPUEntry->Value & FE.Value)
if ((CPUEntry->Value & FE.Value).any())
SetImpliedBits(Bits, &FE, FeatureTable);
}
} else {
Expand Down
9 changes: 5 additions & 4 deletions llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
Expand Up @@ -14,6 +14,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Regex.h"

using namespace llvm;
Expand Down Expand Up @@ -245,7 +246,7 @@ const AArch64NamedImmMapper::Mapping AArch64SysReg::MRSMapper::MRSPairs[] = {
{"ich_elsr_el2", ICH_ELSR_EL2}
};

AArch64SysReg::MRSMapper::MRSMapper(uint64_t FeatureBits)
AArch64SysReg::MRSMapper::MRSMapper(const FeatureBitset &FeatureBits)
: SysRegMapper(FeatureBits) {
InstPairs = &MRSPairs[0];
NumInstPairs = llvm::array_lengthof(MRSPairs);
Expand All @@ -269,7 +270,7 @@ const AArch64NamedImmMapper::Mapping AArch64SysReg::MSRMapper::MSRPairs[] = {
{"icc_sgi0r_el1", ICC_SGI0R_EL1}
};

AArch64SysReg::MSRMapper::MSRMapper(uint64_t FeatureBits)
AArch64SysReg::MSRMapper::MSRMapper(const FeatureBitset &FeatureBits)
: SysRegMapper(FeatureBits) {
InstPairs = &MSRPairs[0];
NumInstPairs = llvm::array_lengthof(MSRPairs);
Expand Down Expand Up @@ -773,7 +774,7 @@ AArch64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const {
}

// Next search for target specific registers
if (FeatureBits & AArch64::ProcCyclone) {
if (FeatureBits[AArch64::ProcCyclone]) {
for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) {
if (CycloneSysRegPairs[i].Name == NameLower) {
Valid = true;
Expand Down Expand Up @@ -823,7 +824,7 @@ AArch64SysReg::SysRegMapper::toString(uint32_t Bits) const {
}

// Next search for target specific registers
if (FeatureBits & AArch64::ProcCyclone) {
if (FeatureBits[AArch64::ProcCyclone]) {
for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) {
if (CycloneSysRegPairs[i].Value == Bits) {
return CycloneSysRegPairs[i].Name;
Expand Down
10 changes: 6 additions & 4 deletions llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
Expand Up @@ -26,6 +26,8 @@

namespace llvm {

class FeatureBitset;

inline static unsigned getWRegFromXReg(unsigned Reg) {
switch (Reg) {
case AArch64::X0: return AArch64::W0;
Expand Down Expand Up @@ -1139,21 +1141,21 @@ namespace AArch64SysReg {

const AArch64NamedImmMapper::Mapping *InstPairs;
size_t NumInstPairs;
uint64_t FeatureBits;
const FeatureBitset &FeatureBits;

SysRegMapper(uint64_t FeatureBits) : FeatureBits(FeatureBits) { }
SysRegMapper(const FeatureBitset &FeatureBits) : FeatureBits(FeatureBits) { }
uint32_t fromString(StringRef Name, bool &Valid) const;
std::string toString(uint32_t Bits) const;
};

struct MSRMapper : SysRegMapper {
static const AArch64NamedImmMapper::Mapping MSRPairs[];
MSRMapper(uint64_t FeatureBits);
MSRMapper(const FeatureBitset &FeatureBits);
};

struct MRSMapper : SysRegMapper {
static const AArch64NamedImmMapper::Mapping MRSPairs[];
MRSMapper(uint64_t FeatureBits);
MRSMapper(const FeatureBitset &FeatureBits);
};

uint32_t ParseGenericRegister(StringRef Name, bool &Valid);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/ARM/ARMAsmPrinter.cpp
Expand Up @@ -422,7 +422,7 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
}

static bool isThumb(const MCSubtargetInfo& STI) {
return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
return STI.getFeatureBits()[ARM::ModeThumb];
}

void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
Expand Up @@ -4507,7 +4507,7 @@ breakPartialRegDependency(MachineBasicBlock::iterator MI,
}

bool ARMBaseInstrInfo::hasNOP() const {
return (Subtarget.getFeatureBits() & ARM::HasV6T2Ops) != 0;
return Subtarget.getFeatureBits()[ARM::HasV6T2Ops];
}

bool ARMBaseInstrInfo::isSwiftFastImmShift(const MachineInstr *MI) const {
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/ARM/ARMSubtarget.cpp
Expand Up @@ -262,8 +262,8 @@ void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
}

// NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
uint64_t Bits = getFeatureBits();
if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters
const FeatureBitset &Bits = getFeatureBits();
if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters
(Options.UnsafeFPMath || isTargetDarwin()))
UseNEONForSinglePrecisionFP = true;
}
Expand Down

0 comments on commit ba5b04c

Please sign in to comment.