1,415 changes: 708 additions & 707 deletions llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp

Large diffs are not rendered by default.

28 changes: 19 additions & 9 deletions llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "MCTargetDesc/AArch64MCTargetDesc.h" // For AArch64::X0 and friends.
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/ErrorHandling.h"

namespace llvm {
Expand Down Expand Up @@ -280,16 +281,22 @@ struct AArch64NamedImmMapper {
struct Mapping {
const char *Name;
uint32_t Value;
uint64_t FeatureBitSet; // Set of features this mapping is available for
// Set of features this mapping is available for
// Zero value of FeatureBitSet means the mapping is always available
FeatureBitset FeatureBitSet;

bool isNameEqual(std::string Other, uint64_t FeatureBits=~0ULL) const {
if (FeatureBitSet && !(FeatureBitSet & FeatureBits))
bool isNameEqual(std::string Other,
const FeatureBitset& FeatureBits) const {
if (FeatureBitSet.any() &&
(FeatureBitSet & FeatureBits).none())
return false;
return Name == Other;
}
bool isValueEqual(uint32_t Other, uint64_t FeatureBits=~0ULL) const {
if (FeatureBitSet && !(FeatureBitSet & FeatureBits))

bool isValueEqual(uint32_t Other,
const FeatureBitset& FeatureBits) const {
if (FeatureBitSet.any() &&
(FeatureBitSet & FeatureBits).none())
return false;
return Value == Other;
}
Expand All @@ -300,9 +307,11 @@ struct AArch64NamedImmMapper {
: Mappings(&Mappings[0]), NumMappings(N), TooBigImm(TooBigImm) {}

// Maps value to string, depending on availability for FeatureBits given
StringRef toString(uint32_t Value, uint64_t FeatureBits, bool &Valid) const;
StringRef toString(uint32_t Value, const FeatureBitset& FeatureBits,
bool &Valid) const;
// Maps string to value, depending on availability for FeatureBits given
uint32_t fromString(StringRef Name, uint64_t FeatureBits, bool &Valid) const;
uint32_t fromString(StringRef Name, const FeatureBitset& FeatureBits,
bool &Valid) const;

/// Many of the instructions allow an alternative assembly form consisting of
/// a simple immediate. Currently the only valid forms are ranges [0, N) where
Expand Down Expand Up @@ -1195,8 +1204,9 @@ namespace AArch64SysReg {
size_t NumInstMappings;

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

struct MSRMapper : SysRegMapper {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/ARM/ARMAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,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
Original file line number Diff line number Diff line change
Expand Up @@ -4538,7 +4538,7 @@ breakPartialRegDependency(MachineBasicBlock::iterator MI,
}

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

bool ARMBaseInstrInfo::isSwiftFastImmShift(const MachineInstr *MI) const {
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/ARM/ARMSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,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
156 changes: 79 additions & 77 deletions llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,48 +243,48 @@ class ARMAsmParser : public MCTargetAsmParser {

bool isThumb() const {
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
return STI.getFeatureBits()[ARM::ModeThumb];
}
bool isThumbOne() const {
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
return isThumb() && !STI.getFeatureBits()[ARM::FeatureThumb2];
}
bool isThumbTwo() const {
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
return isThumb() && STI.getFeatureBits()[ARM::FeatureThumb2];
}
bool hasThumb() const {
return STI.getFeatureBits() & ARM::HasV4TOps;
return STI.getFeatureBits()[ARM::HasV4TOps];
}
bool hasV6Ops() const {
return STI.getFeatureBits() & ARM::HasV6Ops;
return STI.getFeatureBits()[ARM::HasV6Ops];
}
bool hasV6MOps() const {
return STI.getFeatureBits() & ARM::HasV6MOps;
return STI.getFeatureBits()[ARM::HasV6MOps];
}
bool hasV7Ops() const {
return STI.getFeatureBits() & ARM::HasV7Ops;
return STI.getFeatureBits()[ARM::HasV7Ops];
}
bool hasV8Ops() const {
return STI.getFeatureBits() & ARM::HasV8Ops;
return STI.getFeatureBits()[ARM::HasV8Ops];
}
bool hasARM() const {
return !(STI.getFeatureBits() & ARM::FeatureNoARM);
return !STI.getFeatureBits()[ARM::FeatureNoARM];
}
bool hasThumb2DSP() const {
return STI.getFeatureBits() & ARM::FeatureDSPThumb2;
return STI.getFeatureBits()[ARM::FeatureDSPThumb2];
}
bool hasD16() const {
return STI.getFeatureBits() & ARM::FeatureD16;
return STI.getFeatureBits()[ARM::FeatureD16];
}
bool hasV8_1aOps() const {
return STI.getFeatureBits() & ARM::HasV8_1aOps;
return STI.getFeatureBits()[ARM::HasV8_1aOps];
}

void SwitchMode() {
uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
setAvailableFeatures(FB);
}
bool isMClass() const {
return STI.getFeatureBits() & ARM::FeatureMClass;
return STI.getFeatureBits()[ARM::FeatureMClass];
}

/// @name Auto-generated Match Functions
Expand Down Expand Up @@ -9187,52 +9187,53 @@ bool ARMAsmParser::parseDirectiveCPU(SMLoc L) {
// tools/clang/lib/Driver/Tools.cpp
static const struct {
const unsigned ID;
const uint64_t Enabled;
const uint64_t Disabled;
const FeatureBitset Enabled;
const FeatureBitset Disabled;
} FPUs[] = {
{/* ID */ ARM::FK_VFP,
/* Enabled */ ARM::FeatureVFP2,
/* Disabled */ ARM::FeatureNEON},
{/* ID */ ARM::FK_VFPV2,
/* Enabled */ ARM::FeatureVFP2,
/* Disabled */ ARM::FeatureNEON},
{/* ID */ ARM::FK_VFPV3,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3,
/* Disabled */ ARM::FeatureNEON | ARM::FeatureD16},
{/* ID */ ARM::FK_VFPV3_D16,
/* Enable */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureD16,
/* Disabled */ ARM::FeatureNEON},
{/* ID */ ARM::FK_VFPV4,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4,
/* Disabled */ ARM::FeatureNEON | ARM::FeatureD16},
{/* ID */ ARM::FK_VFPV4_D16,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureD16,
/* Disabled */ ARM::FeatureNEON},
{/* ID */ ARM::FK_FPV5_D16,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8 | ARM::FeatureD16,
/* Disabled */ ARM::FeatureNEON | ARM::FeatureCrypto},
{/* ID */ ARM::FK_FP_ARMV8,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8,
/* Disabled */ ARM::FeatureNEON | ARM::FeatureCrypto | ARM::FeatureD16},
{/* ID */ ARM::FK_NEON,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureNEON,
/* Disabled */ ARM::FeatureD16},
{/* ID */ ARM::FK_NEON_VFPV4,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureNEON,
/* Disabled */ ARM::FeatureD16},
{/* ID */ ARM::FK_NEON_FP_ARMV8,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8 | ARM::FeatureNEON,
/* Disabled */ ARM::FeatureCrypto | ARM::FeatureD16},
{/* ID */ ARM::FK_VFP,
/* Enabled */ {ARM::FeatureVFP2},
/* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_VFPV2,
/* Enabled */ {ARM::FeatureVFP2},
/* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_VFPV3,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3},
/* Disabled */ {ARM::FeatureNEON, ARM::FeatureD16}},
{/* ID */ ARM::FK_VFPV3_D16,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureD16},
/* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_VFPV4,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4},
/* Disabled */ {ARM::FeatureNEON, ARM::FeatureD16}},
{/* ID */ ARM::FK_VFPV4_D16,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureD16},
/* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_FPV5_D16,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8, ARM::FeatureD16},
/* Disabled */ {ARM::FeatureNEON, ARM::FeatureCrypto}},
{/* ID */ ARM::FK_FP_ARMV8,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8},
/* Disabled */ {ARM::FeatureNEON, ARM::FeatureCrypto, ARM::FeatureD16}},
{/* ID */ ARM::FK_NEON,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureNEON},
/* Disabled */ {ARM::FeatureD16}},
{/* ID */ ARM::FK_NEON_VFPV4,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureNEON},
/* Disabled */ {ARM::FeatureD16}},
{/* ID */ ARM::FK_NEON_FP_ARMV8,
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8, ARM::FeatureNEON},
/* Disabled */ {ARM::FeatureCrypto, ARM::FeatureD16}},
{/* ID */ ARM::FK_CRYPTO_NEON_FP_ARMV8,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8 | ARM::FeatureNEON | ARM::FeatureCrypto,
/* Disabled */ ARM::FeatureD16},
{ARM::FK_SOFTVFP, 0, 0},
/* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8, ARM::FeatureNEON,
ARM::FeatureCrypto},
/* Disabled */ {ARM::FeatureD16}},
{ARM::FK_SOFTVFP, {}, {}},
};

/// parseDirectiveFPU
Expand All @@ -9254,8 +9255,8 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {

// Need to toggle features that should be on but are off and that
// should off but are on.
uint64_t Toggle = (Entry.Enabled & ~STI.getFeatureBits()) |
(Entry.Disabled & STI.getFeatureBits());
FeatureBitset Toggle = (Entry.Enabled & ~STI.getFeatureBits()) |
(Entry.Disabled & STI.getFeatureBits());
setAvailableFeatures(ComputeAvailableFeatures(STI.ToggleFeature(Toggle)));
break;
}
Expand Down Expand Up @@ -9984,30 +9985,30 @@ extern "C" void LLVMInitializeARMAsmParser() {
static const struct {
const char *Name;
const unsigned ArchCheck;
const uint64_t Features;
const FeatureBitset Features;
} Extensions[] = {
{ "crc", Feature_HasV8, ARM::FeatureCRC },
{ "crc", Feature_HasV8, {ARM::FeatureCRC} },
{ "crypto", Feature_HasV8,
ARM::FeatureCrypto | ARM::FeatureNEON | ARM::FeatureFPARMv8 },
{ "fp", Feature_HasV8, ARM::FeatureFPARMv8 },
{ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} },
{ "fp", Feature_HasV8, {ARM::FeatureFPARMv8} },
{ "idiv", Feature_HasV7 | Feature_IsNotMClass,
ARM::FeatureHWDiv | ARM::FeatureHWDivARM },
{ARM::FeatureHWDiv, ARM::FeatureHWDivARM} },
// FIXME: iWMMXT not supported
{ "iwmmxt", Feature_None, 0 },
{ "iwmmxt", Feature_None, {} },
// FIXME: iWMMXT2 not supported
{ "iwmmxt2", Feature_None, 0 },
{ "iwmmxt2", Feature_None, {} },
// FIXME: Maverick not supported
{ "maverick", Feature_None, 0 },
{ "mp", Feature_HasV7 | Feature_IsNotMClass, ARM::FeatureMP },
{ "maverick", Feature_None, {} },
{ "mp", Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureMP} },
// FIXME: ARMv6-m OS Extensions feature not checked
{ "os", Feature_None, 0 },
{ "os", Feature_None, {} },
// FIXME: Also available in ARMv6-K
{ "sec", Feature_HasV7, ARM::FeatureTrustZone },
{ "simd", Feature_HasV8, ARM::FeatureNEON | ARM::FeatureFPARMv8 },
{ "sec", Feature_HasV7, {ARM::FeatureTrustZone} },
{ "simd", Feature_HasV8, {ARM::FeatureNEON, ARM::FeatureFPARMv8} },
// FIXME: Only available in A-class, isel not predicated
{ "virt", Feature_HasV7, ARM::FeatureVirtualization },
{ "virt", Feature_HasV7, {ARM::FeatureVirtualization} },
// FIXME: xscale not supported
{ "xscale", Feature_None, 0 },
{ "xscale", Feature_None, {} },
};

/// parseDirectiveArchExtension
Expand Down Expand Up @@ -10035,7 +10036,7 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
if (Extension.Name != Name)
continue;

if (!Extension.Features)
if (Extension.Features.none())
report_fatal_error("unsupported architectural extension: " + Name);

if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) {
Expand All @@ -10044,9 +10045,10 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
return false;
}

uint64_t ToggleFeatures = EnableFeature
? (~STI.getFeatureBits() & Extension.Features)
: ( STI.getFeatureBits() & Extension.Features);
FeatureBitset ToggleFeatures = EnableFeature
? (~STI.getFeatureBits() & Extension.Features)
: ( STI.getFeatureBits() & Extension.Features);

uint64_t Features =
ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
setAvailableFeatures(Features);
Expand Down
78 changes: 43 additions & 35 deletions llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
raw_ostream &CS) const {
CommentStream = &CS;

assert(!(STI.getFeatureBits() & ARM::ModeThumb) &&
assert(!STI.getFeatureBits()[ARM::ModeThumb] &&
"Asked to disassemble an ARM instruction but Subtarget is in Thumb "
"mode!");

Expand Down Expand Up @@ -700,7 +700,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
raw_ostream &CS) const {
CommentStream = &CS;

assert((STI.getFeatureBits() & ARM::ModeThumb) &&
assert(STI.getFeatureBits()[ARM::ModeThumb] &&
"Asked to disassemble in Thumb mode but Subtarget is in ARM mode!");

// We want to read exactly 2 bytes of data.
Expand Down Expand Up @@ -1026,9 +1026,10 @@ static const uint16_t DPRDecoderTable[] = {

static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
bool hasD16 = featureBits & ARM::FeatureD16;
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();

bool hasD16 = featureBits[ARM::FeatureD16];

if (RegNo > 31 || (hasD16 && RegNo > 15))
return MCDisassembler::Fail;
Expand Down Expand Up @@ -1373,9 +1374,9 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
break;
}

uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
if ((featureBits & ARM::HasV8Ops) && (coproc != 14))
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
if (featureBits[ARM::HasV8Ops] && (coproc != 14))
return MCDisassembler::Fail;

Inst.addOperand(MCOperand::createImm(coproc));
Expand Down Expand Up @@ -2151,9 +2152,10 @@ static DecodeStatus DecodeSETPANInstruction(MCInst &Inst, unsigned Insn,
unsigned Imm = fieldFromInstruction(Insn, 9, 1);

const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
uint64_t FeatureBits = Dis->getSubtargetInfo().getFeatureBits();
if ((FeatureBits & ARM::HasV8_1aOps) == 0 ||
(FeatureBits & ARM::HasV8Ops) == 0 )
const FeatureBitset &FeatureBits = Dis->getSubtargetInfo().getFeatureBits();

if (!FeatureBits[ARM::HasV8_1aOps] ||
!FeatureBits[ARM::HasV8Ops])
return MCDisassembler::Fail;

// Decoder can be called from DecodeTST, which does not check the full
Expand Down Expand Up @@ -3319,10 +3321,11 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
unsigned Rn = fieldFromInstruction(Insn, 16, 4);

uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
bool hasMP = featureBits & ARM::FeatureMP;
bool hasV7Ops = featureBits & ARM::HasV7Ops;
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();

bool hasMP = featureBits[ARM::FeatureMP];
bool hasV7Ops = featureBits[ARM::HasV7Ops];

if (Rn == 15) {
switch (Inst.getOpcode()) {
Expand Down Expand Up @@ -3405,10 +3408,11 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
imm |= (Rn << 9);
unsigned add = fieldFromInstruction(Insn, 9, 1);

uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
bool hasMP = featureBits & ARM::FeatureMP;
bool hasV7Ops = featureBits & ARM::HasV7Ops;
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();

bool hasMP = featureBits[ARM::FeatureMP];
bool hasV7Ops = featureBits[ARM::HasV7Ops];

if (Rn == 15) {
switch (Inst.getOpcode()) {
Expand Down Expand Up @@ -3485,10 +3489,11 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
unsigned imm = fieldFromInstruction(Insn, 0, 12);
imm |= (Rn << 13);

uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
bool hasMP = (featureBits & ARM::FeatureMP);
bool hasV7Ops = (featureBits & ARM::HasV7Ops);
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();

bool hasMP = featureBits[ARM::FeatureMP];
bool hasV7Ops = featureBits[ARM::HasV7Ops];

if (Rn == 15) {
switch (Inst.getOpcode()) {
Expand Down Expand Up @@ -3602,9 +3607,10 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
unsigned U = fieldFromInstruction(Insn, 23, 1);
int imm = fieldFromInstruction(Insn, 0, 12);

uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
bool hasV7Ops = (featureBits & ARM::HasV7Ops);
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();

bool hasV7Ops = featureBits[ARM::HasV7Ops];

if (Rt == 15) {
switch (Inst.getOpcode()) {
Expand Down Expand Up @@ -3925,9 +3931,10 @@ static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Val,
if (Val == 0xA || Val == 0xB)
return MCDisassembler::Fail;

uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
if ((featureBits & ARM::HasV8Ops) && !(Val == 14 || Val == 15))
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();

if (featureBits[ARM::HasV8Ops] && !(Val == 14 || Val == 15))
return MCDisassembler::Fail;

Inst.addOperand(MCOperand::createImm(Val));
Expand Down Expand Up @@ -4077,9 +4084,10 @@ static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Val,
static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
uint64_t FeatureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
if (FeatureBits & ARM::FeatureMClass) {
const FeatureBitset &FeatureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();

if (FeatureBits[ARM::FeatureMClass]) {
unsigned ValLow = Val & 0xff;

// Validate the SYSm value first.
Expand All @@ -4099,7 +4107,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
case 17: // basepri
case 18: // basepri_max
case 19: // faultmask
if (!(FeatureBits & ARM::HasV7Ops))
if (!(FeatureBits[ARM::HasV7Ops]))
// Values basepri, basepri_max and faultmask are only valid for v7m.
return MCDisassembler::Fail;
break;
Expand All @@ -4109,7 +4117,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,

if (Inst.getOpcode() == ARM::t2MSR_M) {
unsigned Mask = fieldFromInstruction(Val, 10, 2);
if (!(FeatureBits & ARM::HasV7Ops)) {
if (!(FeatureBits[ARM::HasV7Ops])) {
// The ARMv6-M MSR bits {11-10} can be only 0b10, other values are
// unpredictable.
if (Mask != 2)
Expand All @@ -4123,7 +4131,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
// indicates the move for the GE{3:0} bits, the mask{0} bit can be set
// only if the processor includes the DSP extension.
if (Mask == 0 || (Mask != 2 && ValLow > 3) ||
(!(FeatureBits & ARM::FeatureDSPThumb2) && (Mask & 1)))
(!(FeatureBits[ARM::FeatureDSPThumb2]) && (Mask & 1)))
S = MCDisassembler::SoftFail;
}
}
Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
O << "\tsev";
break;
case 5:
if ((STI.getFeatureBits() & ARM::HasV8Ops)) {
if (STI.getFeatureBits()[ARM::HasV8Ops]) {
O << "\tsevl";
break;
} // Fallthrough for non-v8
Expand Down Expand Up @@ -302,7 +302,7 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
case ARM::t2SUBS_PC_LR: {
if (MI->getNumOperands() == 3 && MI->getOperand(0).isImm() &&
MI->getOperand(0).getImm() == 0 &&
(STI.getFeatureBits() & ARM::FeatureVirtualization)) {
STI.getFeatureBits()[ARM::FeatureVirtualization]) {
O << "\teret";
printPredicateOperand(MI, 1, STI, O);
printAnnotation(O, Annot);
Expand Down Expand Up @@ -695,7 +695,7 @@ void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
unsigned val = MI->getOperand(OpNum).getImm();
O << ARM_MB::MemBOptToString(val, (STI.getFeatureBits() & ARM::HasV8Ops));
O << ARM_MB::MemBOptToString(val, STI.getFeatureBits()[ARM::HasV8Ops]);
}

void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
Expand Down Expand Up @@ -795,14 +795,14 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
const MCOperand &Op = MI->getOperand(OpNum);
unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf;
uint64_t FeatureBits = STI.getFeatureBits();
const FeatureBitset &FeatureBits = STI.getFeatureBits();

if (FeatureBits & ARM::FeatureMClass) {
if (FeatureBits[ARM::FeatureMClass]) {
unsigned SYSm = Op.getImm();
unsigned Opcode = MI->getOpcode();

// For writes, handle extended mask bits if the DSP extension is present.
if (Opcode == ARM::t2MSR_M && (FeatureBits & ARM::FeatureDSPThumb2)) {
if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSPThumb2]) {
switch (SYSm) {
case 0x400:
O << "apsr_g";
Expand Down Expand Up @@ -834,7 +834,7 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
// Handle the basic 8-bit mask.
SYSm &= 0xff;

if (Opcode == ARM::t2MSR_M && (FeatureBits & ARM::HasV7Ops)) {
if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
// ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
// alias for MSR APSR_nzcvq.
switch (SYSm) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void ARMAsmBackend::handleAssemblerFlag(MCAssemblerFlag Flag) {
} // end anonymous namespace

unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op) const {
bool HasThumb2 = STI->getFeatureBits() & ARM::FeatureThumb2;
bool HasThumb2 = STI->getFeatureBits()[ARM::FeatureThumb2];

switch (Op) {
default:
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class ARMAsmBackend : public MCAsmBackend {
return ARM::NumTargetFixupKinds;
}

bool hasNOP() const { return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; }
bool hasNOP() const { return STI->getFeatureBits()[ARM::HasV6T2Ops]; }

const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ class ARMMCCodeEmitter : public MCCodeEmitter {
~ARMMCCodeEmitter() override {}

bool isThumb(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
return STI.getFeatureBits()[ARM::ModeThumb];
}
bool isThumb2(const MCSubtargetInfo &STI) const {
return isThumb(STI) && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0;
return isThumb(STI) && STI.getFeatureBits()[ARM::FeatureThumb2];
}
bool isTargetMachO(const MCSubtargetInfo &STI) const {
Triple TT(STI.getTargetTriple());
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ using namespace llvm;

static bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) {
if (STI.getFeatureBits() & llvm::ARM::HasV7Ops &&
if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
(MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
(MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
// Checks for the deprecated CP15ISB encoding:
Expand Down Expand Up @@ -65,7 +65,7 @@ static bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,

static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) {
if (STI.getFeatureBits() & llvm::ARM::HasV8Ops && MI.getOperand(1).isImm() &&
if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() != 8) {
Info = "applying IT instruction to more than one subsequent instruction is "
"deprecated";
Expand All @@ -77,7 +77,7 @@ static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,

static bool getARMStoreDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) {
assert((~STI.getFeatureBits() & llvm::ARM::ModeThumb) &&
assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
"cannot predicate thumb instructions");

assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
Expand All @@ -94,7 +94,7 @@ static bool getARMStoreDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,

static bool getARMLoadDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) {
assert((~STI.getFeatureBits() & llvm::ARM::ModeThumb) &&
assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
"cannot predicate thumb instructions");

assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
Expand Down
80 changes: 42 additions & 38 deletions llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,7 @@ class MipsAssemblerOptions {
// The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
// The reason we need this mask is explained in the selectArch function.
// FIXME: Ideally we would like TableGen to generate this information.
static const uint64_t AllArchRelatedMask =
Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
static const FeatureBitset AllArchRelatedMask;

private:
unsigned ATReg;
Expand All @@ -96,6 +88,17 @@ class MipsAssemblerOptions {
};
}

const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
};

namespace {
class MipsAsmParser : public MCTargetAsmParser {
MipsTargetStreamer &getTargetStreamer() {
Expand Down Expand Up @@ -317,7 +320,7 @@ class MipsAsmParser : public MCTargetAsmParser {
// FeatureMipsGP64 | FeatureMips1)
// Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
void selectArch(StringRef ArchFeature) {
uint64_t FeatureBits = STI.getFeatureBits();
FeatureBitset FeatureBits = STI.getFeatureBits();
FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
STI.setFeatureBits(FeatureBits);
setAvailableFeatures(
Expand All @@ -326,15 +329,15 @@ class MipsAsmParser : public MCTargetAsmParser {
}

void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
if (!(STI.getFeatureBits() & Feature)) {
if (!(STI.getFeatureBits()[Feature])) {
setAvailableFeatures(
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
}
AssemblerOptions.back()->setFeatures(getAvailableFeatures());
}

void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
if (STI.getFeatureBits() & Feature) {
if (STI.getFeatureBits()[Feature]) {
setAvailableFeatures(
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
}
Expand Down Expand Up @@ -381,69 +384,70 @@ class MipsAsmParser : public MCTargetAsmParser {
/// True if all of $fcc0 - $fcc7 exist for the current ISA.
bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }

bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
const MipsABIInfo &getABI() const { return ABI; }
bool isABI_N32() const { return ABI.IsN32(); }
bool isABI_N64() const { return ABI.IsN64(); }
bool isABI_O32() const { return ABI.IsO32(); }
bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }

bool useOddSPReg() const {
return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
}

bool inMicroMipsMode() const {
return STI.getFeatureBits() & Mips::FeatureMicroMips;
return STI.getFeatureBits()[Mips::FeatureMicroMips];
}
bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
bool hasMips32() const {
return (STI.getFeatureBits() & Mips::FeatureMips32);
return STI.getFeatureBits()[Mips::FeatureMips32];
}
bool hasMips64() const {
return (STI.getFeatureBits() & Mips::FeatureMips64);
return STI.getFeatureBits()[Mips::FeatureMips64];
}
bool hasMips32r2() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r2);
return STI.getFeatureBits()[Mips::FeatureMips32r2];
}
bool hasMips64r2() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r2);
return STI.getFeatureBits()[Mips::FeatureMips64r2];
}
bool hasMips32r3() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r3);
return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
}
bool hasMips64r3() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r3);
return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
}
bool hasMips32r5() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r5);
return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
}
bool hasMips64r5() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r5);
return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
}
bool hasMips32r6() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r6);
return STI.getFeatureBits()[Mips::FeatureMips32r6];
}
bool hasMips64r6() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r6);
return STI.getFeatureBits()[Mips::FeatureMips64r6];
}

bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
bool hasCnMips() const {
return (STI.getFeatureBits() & Mips::FeatureCnMips);
return (STI.getFeatureBits()[Mips::FeatureCnMips]);
}
bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }

bool inMips16Mode() const {
return STI.getFeatureBits() & Mips::FeatureMips16;
return STI.getFeatureBits()[Mips::FeatureMips16];
}

bool useSoftFloat() const {
return (STI.getFeatureBits() & Mips::FeatureSoftFloat);
return STI.getFeatureBits()[Mips::FeatureSoftFloat];
}

/// Warn if RegIndex is the same as the current AT.
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ class MipsDisassembler : public MCDisassembler {
public:
MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian)
: MCDisassembler(STI, Ctx),
IsMicroMips(STI.getFeatureBits() & Mips::FeatureMicroMips),
IsMicroMips(STI.getFeatureBits()[Mips::FeatureMicroMips]),
IsBigEndian(IsBigEndian) {}

bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; }
bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; }
bool hasMips32r6() const {
return STI.getFeatureBits() & Mips::FeatureMips32r6;
return STI.getFeatureBits()[Mips::FeatureMips32r6];
}

bool isGP64() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }

bool hasCOP3() const {
// Only present in MIPS-I and MIPS-II
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ static void LowerDextDins(MCInst& InstIn) {
}

bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
return STI.getFeatureBits() & Mips::FeatureMicroMips;
return STI.getFeatureBits()[Mips::FeatureMicroMips];
}

bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {
return STI.getFeatureBits() & Mips::FeatureMips32r6;
return STI.getFeatureBits()[Mips::FeatureMips32r6];
}

void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {
Expand Down
38 changes: 19 additions & 19 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
MCAssembler &MCA = getStreamer().getAssembler();
Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;

uint64_t Features = STI.getFeatureBits();
const FeatureBitset &Features = STI.getFeatureBits();

// Set the header flags that we can in the constructor.
// FIXME: This is a fairly terrible hack. We set the rest
Expand All @@ -402,35 +402,35 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
unsigned EFlags = MCA.getELFHeaderEFlags();

// Architecture
if (Features & Mips::FeatureMips64r6)
if (Features[Mips::FeatureMips64r6])
EFlags |= ELF::EF_MIPS_ARCH_64R6;
else if (Features & Mips::FeatureMips64r2 ||
Features & Mips::FeatureMips64r3 ||
Features & Mips::FeatureMips64r5)
else if (Features[Mips::FeatureMips64r2] ||
Features[Mips::FeatureMips64r3] ||
Features[Mips::FeatureMips64r5])
EFlags |= ELF::EF_MIPS_ARCH_64R2;
else if (Features & Mips::FeatureMips64)
else if (Features[Mips::FeatureMips64])
EFlags |= ELF::EF_MIPS_ARCH_64;
else if (Features & Mips::FeatureMips5)
else if (Features[Mips::FeatureMips5])
EFlags |= ELF::EF_MIPS_ARCH_5;
else if (Features & Mips::FeatureMips4)
else if (Features[Mips::FeatureMips4])
EFlags |= ELF::EF_MIPS_ARCH_4;
else if (Features & Mips::FeatureMips3)
else if (Features[Mips::FeatureMips3])
EFlags |= ELF::EF_MIPS_ARCH_3;
else if (Features & Mips::FeatureMips32r6)
else if (Features[Mips::FeatureMips32r6])
EFlags |= ELF::EF_MIPS_ARCH_32R6;
else if (Features & Mips::FeatureMips32r2 ||
Features & Mips::FeatureMips32r3 ||
Features & Mips::FeatureMips32r5)
else if (Features[Mips::FeatureMips32r2] ||
Features[Mips::FeatureMips32r3] ||
Features[Mips::FeatureMips32r5])
EFlags |= ELF::EF_MIPS_ARCH_32R2;
else if (Features & Mips::FeatureMips32)
else if (Features[Mips::FeatureMips32])
EFlags |= ELF::EF_MIPS_ARCH_32;
else if (Features & Mips::FeatureMips2)
else if (Features[Mips::FeatureMips2])
EFlags |= ELF::EF_MIPS_ARCH_2;
else
EFlags |= ELF::EF_MIPS_ARCH_1;

// Other options.
if (Features & Mips::FeatureNaN2008)
if (Features[Mips::FeatureNaN2008])
EFlags |= ELF::EF_MIPS_NAN2008;

// -mabicalls and -mplt are not implemented but we should act as if they were
Expand Down Expand Up @@ -470,7 +470,7 @@ void MipsTargetELFStreamer::finish() {
DataSection.setAlignment(std::max(16u, DataSection.getAlignment()));
BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment()));

uint64_t Features = STI.getFeatureBits();
const FeatureBitset &Features = STI.getFeatureBits();

// Update e_header flags. See the FIXME and comment above in
// the constructor for a full rundown on this.
Expand All @@ -483,10 +483,10 @@ void MipsTargetELFStreamer::finish() {
else if (getABI().IsN32())
EFlags |= ELF::EF_MIPS_ABI2;

if (Features & Mips::FeatureGP64Bit) {
if (Features[Mips::FeatureGP64Bit]) {
if (getABI().IsO32())
EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */
} else if (Features & Mips::FeatureMips64r2 || Features & Mips::FeatureMips64)
} else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])
EFlags |= ELF::EF_MIPS_32BITMODE;

// If we've set the cpic eflag and we're n64, go ahead and set the pic
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1682,7 +1682,7 @@ bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
// where th can be omitted when it is 0. dcbtst is the same. We take the
// server form to be the default, so swap the operands if we're parsing for
// an embedded core (they'll be swapped again upon printing).
if ((STI.getFeatureBits() & PPC::FeatureBookE) != 0 &&
if (STI.getFeatureBits()[PPC::FeatureBookE] &&
Operands.size() == 4 &&
(Name == "dcbt" || Name == "dcbtst")) {
std::swap(Operands[1], Operands[3]);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
uint32_t Inst =
(Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);

if ((STI.getFeatureBits() & PPC::FeatureQPX) != 0) {
if (STI.getFeatureBits()[PPC::FeatureQPX]) {
DecodeStatus result =
decodeInstruction(DecoderTableQPX32, MI, Inst, Address, this, STI);
if (result != MCDisassembler::Fail)
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
O << "t";
O << " ";

bool IsBookE = (STI.getFeatureBits() & PPC::FeatureBookE) != 0;
bool IsBookE = STI.getFeatureBits()[PPC::FeatureBookE];
if (IsBookE && TH != 0 && TH != 16)
O << (unsigned int) TH << ", ";

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
: MCTargetAsmParser(), STI(STI), MII(MII), Parser(_Parser),
ForcedEncodingSize(0){

if (!STI.getFeatureBits()) {
if (STI.getFeatureBits().none()) {
// Set default features.
STI.ToggleFeature("SOUTHERN_ISLANDS");
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/R600/MCTargetDesc/R600MCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
} else if (IS_VTX(Desc)) {
uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
if (!(STI.getFeatureBits() & AMDGPU::FeatureCaymanISA)) {
if (!(STI.getFeatureBits()[AMDGPU::FeatureCaymanISA])) {
InstWord2 |= 1 << 19; // Mega-Fetch bit
}

Expand Down Expand Up @@ -132,7 +132,7 @@ void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
Emit((uint32_t) 0, OS);
} else {
uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
if ((STI.getFeatureBits() & AMDGPU::FeatureR600ALUInst) &&
if ((STI.getFeatureBits()[AMDGPU::FeatureR600ALUInst]) &&
((Desc.TSFlags & R600_InstFlag::OP1) ||
Desc.TSFlags & R600_InstFlag::OP2)) {
uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace Sparc {
#include "SparcGenAsmWriter.inc"

bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & Sparc::FeatureV9) != 0;
return (STI.getFeatureBits()[Sparc::FeatureV9]) != 0;
}

void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,13 @@ class X86AddressSanitizer : public X86AsmInstrumentation {
MCContext &Ctx, int64_t *Residue);

bool is64BitMode() const {
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
return STI.getFeatureBits()[X86::Mode64Bit];
}
bool is32BitMode() const {
return (STI.getFeatureBits() & X86::Mode32Bit) != 0;
return STI.getFeatureBits()[X86::Mode32Bit];
}
bool is16BitMode() const {
return (STI.getFeatureBits() & X86::Mode16Bit) != 0;
return STI.getFeatureBits()[X86::Mode16Bit];
}

unsigned getPointerWidth() {
Expand Down Expand Up @@ -1072,9 +1072,9 @@ CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
const bool hasCompilerRTSupport = T.isOSLinux();
if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
MCOptions.SanitizeAddress) {
if ((STI.getFeatureBits() & X86::Mode32Bit) != 0)
if (STI.getFeatureBits()[X86::Mode32Bit] != 0)
return new X86AddressSanitizer32(STI);
if ((STI.getFeatureBits() & X86::Mode64Bit) != 0)
if (STI.getFeatureBits()[X86::Mode64Bit] != 0)
return new X86AddressSanitizer64(STI);
}
return new X86AsmInstrumentation(STI);
Expand Down
25 changes: 13 additions & 12 deletions llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,23 +729,24 @@ class X86AsmParser : public MCTargetAsmParser {

bool is64BitMode() const {
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
return STI.getFeatureBits()[X86::Mode64Bit];
}
bool is32BitMode() const {
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode32Bit) != 0;
return STI.getFeatureBits()[X86::Mode32Bit];
}
bool is16BitMode() const {
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode16Bit) != 0;
return STI.getFeatureBits()[X86::Mode16Bit];
}
void SwitchMode(uint64_t mode) {
uint64_t oldMode = STI.getFeatureBits() &
(X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit);
unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(oldMode | mode));
void SwitchMode(unsigned mode) {
FeatureBitset AllModes({X86::Mode64Bit, X86::Mode32Bit, X86::Mode16Bit});
FeatureBitset OldMode = STI.getFeatureBits() & AllModes;
unsigned FB = ComputeAvailableFeatures(
STI.ToggleFeature(OldMode.flip(mode)));
setAvailableFeatures(FB);
assert(mode == (STI.getFeatureBits() &
(X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit)));

assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes));
}

unsigned getPointerWidth() {
Expand Down Expand Up @@ -1696,7 +1697,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
}

// rounding mode token
if (STI.getFeatureBits() & X86::FeatureAVX512 &&
if (STI.getFeatureBits()[X86::FeatureAVX512] &&
getLexer().is(AsmToken::LCurly))
return ParseRoundingModeOp(Start, End);

Expand Down Expand Up @@ -1754,7 +1755,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
}
case AsmToken::LCurly:{
SMLoc Start = Parser.getTok().getLoc(), End;
if (STI.getFeatureBits() & X86::FeatureAVX512)
if (STI.getFeatureBits()[X86::FeatureAVX512])
return ParseRoundingModeOp(Start, End);
return ErrorOperand(Start, "unknown token in expression");
}
Expand All @@ -1764,7 +1765,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands,
const MCParsedAsmOperand &Op) {
MCAsmParser &Parser = getParser();
if(STI.getFeatureBits() & X86::FeatureAVX512) {
if(STI.getFeatureBits()[X86::FeatureAVX512]) {
if (getLexer().is(AsmToken::LCurly)) {
// Eat "{" and mark the current place.
const SMLoc consumedToken = consumeToken();
Expand Down
19 changes: 9 additions & 10 deletions llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,19 @@ X86GenericDisassembler::X86GenericDisassembler(
MCContext &Ctx,
std::unique_ptr<const MCInstrInfo> MII)
: MCDisassembler(STI, Ctx), MII(std::move(MII)) {
switch (STI.getFeatureBits() &
(X86::Mode16Bit | X86::Mode32Bit | X86::Mode64Bit)) {
case X86::Mode16Bit:
const FeatureBitset &FB = STI.getFeatureBits();
if (FB[X86::Mode16Bit]) {
fMode = MODE_16BIT;
break;
case X86::Mode32Bit:
return;
} else if (FB[X86::Mode32Bit]) {
fMode = MODE_32BIT;
break;
case X86::Mode64Bit:
return;
} else if (FB[X86::Mode64Bit]) {
fMode = MODE_64BIT;
break;
default:
llvm_unreachable("Invalid CPU mode");
return;
}

llvm_unreachable("Invalid CPU mode");
}

struct Region {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
// InstrInfo.td as soon as Requires clause is supported properly
// for InstAlias.
if (MI->getOpcode() == X86::CALLpcrel32 &&
(STI.getFeatureBits() & X86::Mode64Bit) != 0) {
(STI.getFeatureBits()[X86::Mode64Bit])) {
OS << "\tcallq\t";
printPCRelImm(MI, 0, OS);
}
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ class X86MCCodeEmitter : public MCCodeEmitter {
~X86MCCodeEmitter() override {}

bool is64BitMode(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
return STI.getFeatureBits()[X86::Mode64Bit];
}

bool is32BitMode(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & X86::Mode32Bit) != 0;
return STI.getFeatureBits()[X86::Mode32Bit];
}

bool is16BitMode(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & X86::Mode16Bit) != 0;
return STI.getFeatureBits()[X86::Mode16Bit];
}

/// Is16BitMemOperand - Return true if the specified instruction has
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/TableGen/AsmPredicateCondsEmission.td
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ def foo : Instruction {
let Predicates = [Pred1, Pred2];
}

// CHECK: return ((Bits & arch::AssemblerCondition2));
// CHECK: return (Bits[arch::AssemblerCondition2]);
12 changes: 5 additions & 7 deletions llvm/utils/TableGen/AsmMatcherEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2248,7 +2248,7 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
Info.AsmParser->getValueAsString("AsmParserClassName");

OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
<< "ComputeAvailableFeatures(uint64_t FB) const {\n";
<< "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n";
OS << " uint64_t Features = 0;\n";
for (const auto &SF : Info.SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second;
Expand All @@ -2270,12 +2270,10 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
Cond = Cond.substr(1);
}

OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")";
OS << "(";
if (Neg)
OS << " == 0";
else
OS << " != 0";
OS << ")";
OS << "!";
OS << "FB[" << Info.Target.getName() << "::" << Cond << "])";

if (Comma.second.empty())
break;
Expand Down Expand Up @@ -2645,7 +2643,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of MCTargetAsmParser.\n";
OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const OperandVector "
Expand Down
10 changes: 5 additions & 5 deletions llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
// The predicate function is just a big switch statement based on the
// input predicate index.
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
<< "uint64_t Bits) {\n";
<< "const FeatureBitset& Bits) {\n";
Indentation += 2;
if (!Predicates.empty()) {
OS.indent(Indentation) << "switch (Idx) {\n";
Expand Down Expand Up @@ -1102,10 +1102,10 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
const std::string &PredicateNamespace) {
if (str[0] == '!')
o << "!(Bits & " << PredicateNamespace << "::"
<< str.slice(1,str.size()) << ")";
o << "!Bits[" << PredicateNamespace << "::"
<< str.slice(1,str.size()) << "]";
else
o << "(Bits & " << PredicateNamespace << "::" << str << ")";
o << "Bits[" << PredicateNamespace << "::" << str << "]";
}

bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
Expand Down Expand Up @@ -2012,7 +2012,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " InsnType insn, uint64_t Address,\n"
<< " const void *DisAsm,\n"
<< " const MCSubtargetInfo &STI) {\n"
<< " uint64_t Bits = STI.getFeatureBits();\n"
<< " const FeatureBitset& Bits = STI.getFeatureBits();\n"
<< "\n"
<< " const uint8_t *Ptr = DecodeTable;\n"
<< " uint32_t CurFieldValue = 0;\n"
Expand Down
8 changes: 4 additions & 4 deletions llvm/utils/TableGen/InstrInfoEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,15 +549,15 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
CodeGenTarget &Target = CDP.getTargetInfo();
if (Inst.HasComplexDeprecationPredicate)
// Emit a function pointer to the complex predicate method.
OS << ",0"
OS << ", -1 "
<< ",&get" << Inst.DeprecatedReason << "DeprecationInfo";
else if (!Inst.DeprecatedReason.empty())
// Emit the Subtarget feature.
OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
<< ",nullptr";
OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
<< " ,nullptr";
else
// Instruction isn't deprecated.
OS << ",0,nullptr";
OS << ", -1 ,nullptr";

OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}
Expand Down
57 changes: 27 additions & 30 deletions llvm/utils/TableGen/SubtargetEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/TableGen/Error.h"
Expand Down Expand Up @@ -62,7 +63,7 @@ class SubtargetEmitter {
CodeGenSchedModels &SchedModels;
std::string Target;

void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
void Enumeration(raw_ostream &OS, const char *ClassName);
unsigned FeatureKeyValues(raw_ostream &OS);
unsigned CPUKeyValues(raw_ostream &OS);
void FormItineraryStageString(const std::string &Names,
Expand Down Expand Up @@ -112,17 +113,16 @@ class SubtargetEmitter {
// Enumeration - Emit the specified class as an enumeration.
//
void SubtargetEmitter::Enumeration(raw_ostream &OS,
const char *ClassName,
bool isBits) {
const char *ClassName) {
// Get all records of class and sort
std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
std::sort(DefList.begin(), DefList.end(), LessRecord());

unsigned N = DefList.size();
if (N == 0)
return;
if (N > 64)
PrintFatalError("Too many (> 64) subtarget features!");
if (N > MAX_SUBTARGET_FEATURES)
PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");

OS << "namespace " << Target << " {\n";

Expand All @@ -135,21 +135,14 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS,
Record *Def = DefList[i];

// Get and emit name
OS << " " << Def->getName();

// If bit flags then emit expression (1 << i)
if (isBits) OS << " = " << " 1ULL << " << i;

// Depending on 'if more in the list' emit comma
OS << " " << Def->getName() << " = " << i;
if (++i < N) OS << ",";

OS << "\n";
}

// Close enumeration
OS << "};\n";

OS << "}\n";
// Close enumeration and namespace
OS << "};\n}\n";
}

//
Expand Down Expand Up @@ -183,22 +176,24 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {

if (CommandLineName.empty()) continue;

// Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
// Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }
OS << " { "
<< "\"" << CommandLineName << "\", "
<< "\"" << Desc << "\", "
<< Target << "::" << Name << ", ";
<< "{ " << Target << "::" << Name << " }, ";

const std::vector<Record*> &ImpliesList =
Feature->getValueAsListOfDefs("Implies");

if (ImpliesList.empty()) {
OS << "0ULL";
OS << "{ }";
} else {
OS << "{ ";
for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
OS << Target << "::" << ImpliesList[j]->getName();
if (++j < M) OS << " | ";
if (++j < M) OS << ", ";
}
OS << " }";
}

OS << " }";
Expand Down Expand Up @@ -240,22 +235,24 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
const std::vector<Record*> &FeatureList =
Processor->getValueAsListOfDefs("Features");

// Emit as { "cpu", "description", f1 | f2 | ... fn },
// Emit as { "cpu", "description", { f1 , f2 , ... fn } },
OS << " { "
<< "\"" << Name << "\", "
<< "\"Select the " << Name << " processor\", ";

if (FeatureList.empty()) {
OS << "0ULL";
OS << "{ }";
} else {
OS << "{ ";
for (unsigned j = 0, M = FeatureList.size(); j < M;) {
OS << Target << "::" << FeatureList[j]->getName();
if (++j < M) OS << " | ";
if (++j < M) OS << ", ";
}
OS << " }";
}

// The "0" is for the "implies" section of this data structure.
OS << ", 0ULL }";
// The { } is for the "implies" section of this data structure.
OS << ", { } }";

// Depending on 'if more in the list' emit comma
if (++i < N) OS << ",";
Expand Down Expand Up @@ -1383,7 +1380,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
}

OS << " InitMCProcessorInfo(CPU, FS);\n"
<< " uint64_t Bits = getFeatureBits();\n";
<< " const FeatureBitset& Bits = getFeatureBits();\n";

for (unsigned i = 0; i < Features.size(); i++) {
// Next record
Expand All @@ -1393,12 +1390,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
const std::string &Attribute = R->getValueAsString("Attribute");

if (Value=="true" || Value=="false")
OS << " if ((Bits & " << Target << "::"
<< Instance << ") != 0) "
OS << " if (Bits[" << Target << "::"
<< Instance << "]) "
<< Attribute << " = " << Value << ";\n";
else
OS << " if ((Bits & " << Target << "::"
<< Instance << ") != 0 && "
OS << " if (Bits[" << Target << "::"
<< Instance << "] && "
<< Attribute << " < " << Value << ") "
<< Attribute << " = " << Value << ";\n";
}
Expand All @@ -1416,7 +1413,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "#undef GET_SUBTARGETINFO_ENUM\n";

OS << "namespace llvm {\n";
Enumeration(OS, "SubtargetFeature", true);
Enumeration(OS, "SubtargetFeature");
OS << "} // End llvm namespace \n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";

Expand Down