Revert r300964 + r300970 - [globalisel][tablegen] Import SelectionDAG's rule predicates and support the equivalent in GIRule.

It's causing llvm-clang-x86_64-expensive-checks-win to fail to compile and I
haven't worked out why. Reverting to make it green while I figure it out.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300978 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Sanders 2017-04-21 14:09:20 +00:00
parent bd1b03d467
commit 9eb6db17b6
12 changed files with 39 additions and 257 deletions

View File

@ -18,50 +18,20 @@
#include "llvm/ADT/Optional.h"
#include <cstdint>
#include <bitset>
namespace llvm {
class MachineInstr;
class MachineFunction;
class MachineOperand;
class MachineRegisterInfo;
class RegisterBankInfo;
class TargetInstrInfo;
class TargetRegisterInfo;
/// Container class for CodeGen predicate results.
/// This is convenient because std::bitset does not have a constructor
/// with an initializer list of set bits.
///
/// Each InstructionSelector subclass should define a PredicateBitset class with:
/// const unsigned MAX_SUBTARGET_PREDICATES = 192;
/// using PredicateBitset = PredicateBitsetImpl<MAX_SUBTARGET_PREDICATES>;
/// and updating the constant to suit the target. Tablegen provides a suitable
/// definition for the predicates in use in <Target>GenGlobalISel.inc when
/// GET_GLOBALISEL_PREDICATE_BITSET is defined.
template <std::size_t MaxPredicates>
class PredicateBitsetImpl : public std::bitset<MaxPredicates> {
public:
// Cannot inherit constructors because it's not supported by VC++..
PredicateBitsetImpl() = default;
PredicateBitsetImpl(const std::bitset<MaxPredicates> &B)
: std::bitset<MaxPredicates>(B) {}
PredicateBitsetImpl(std::initializer_list<unsigned> Init) {
for (auto I : Init)
std::bitset<MaxPredicates>::set(I);
}
};
/// Provides the logic to select generic machine instructions.
class InstructionSelector {
public:
virtual ~InstructionSelector() {}
/// This is executed before selecting a function.
virtual void beginFunction(const MachineFunction &MF) {}
/// Select the (possibly generic) instruction \p I to only use target-specific
/// opcodes. It is OK to insert multiple instructions, but they cannot be
/// generic pre-isel instructions.

View File

@ -41,17 +41,12 @@ using namespace llvm;
namespace {
#define GET_GLOBALISEL_PREDICATE_BITSET
#include "AArch64GenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATE_BITSET
class AArch64InstructionSelector : public InstructionSelector {
public:
AArch64InstructionSelector(const AArch64TargetMachine &TM,
const AArch64Subtarget &STI,
const AArch64RegisterBankInfo &RBI);
void beginFunction(const MachineFunction &MF) override;
bool select(MachineInstr &I) const override;
private:
@ -75,12 +70,6 @@ private:
const AArch64InstrInfo &TII;
const AArch64RegisterInfo &TRI;
const AArch64RegisterBankInfo &RBI;
bool ForCodeSize;
PredicateBitset AvailableFeatures;
PredicateBitset
computeAvailableFeatures(const MachineFunction *MF,
const AArch64Subtarget *Subtarget) const;
// We declare the temporaries used by selectImpl() in the class to minimize the
// cost of constructing placeholder values.
@ -99,7 +88,7 @@ AArch64InstructionSelector::AArch64InstructionSelector(
const AArch64TargetMachine &TM, const AArch64Subtarget &STI,
const AArch64RegisterBankInfo &RBI)
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI), ForCodeSize(), AvailableFeatures()
TRI(*STI.getRegisterInfo()), RBI(RBI)
#define GET_GLOBALISEL_TEMPORARIES_INIT
#include "AArch64GenGlobalISel.inc"
#undef GET_GLOBALISEL_TEMPORARIES_INIT
@ -578,12 +567,6 @@ bool AArch64InstructionSelector::selectVaStartDarwin(
return true;
}
void AArch64InstructionSelector::beginFunction(
const MachineFunction &MF) {
ForCodeSize = MF.getFunction()->optForSize();
AvailableFeatures = computeAvailableFeatures(&MF, &STI);
}
bool AArch64InstructionSelector::select(MachineInstr &I) const {
assert(I.getParent() && "Instruction should be in a basic block!");
assert(I.getParent()->getParent() && "Instruction should be in a function!");

View File

@ -95,8 +95,7 @@ void initializeFixupBWInstPassPass(PassRegistry &);
/// encoding when possible in order to reduce code size.
FunctionPass *createX86EvexToVexInsts();
InstructionSelector *createX86InstructionSelector(const X86TargetMachine &TM,
X86Subtarget &,
InstructionSelector *createX86InstructionSelector(X86Subtarget &,
X86RegisterBankInfo &);
void initializeEvexToVexInstPassPass(PassRegistry &);

View File

@ -39,16 +39,11 @@ using namespace llvm;
namespace {
#define GET_GLOBALISEL_PREDICATE_BITSET
#include "X86GenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATE_BITSET
class X86InstructionSelector : public InstructionSelector {
public:
X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
X86InstructionSelector(const X86Subtarget &STI,
const X86RegisterBankInfo &RBI);
void beginFunction(const MachineFunction &MF) override;
bool select(MachineInstr &I) const override;
private:
@ -75,17 +70,10 @@ private:
bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
const X86TargetMachine &TM;
const X86Subtarget &STI;
const X86InstrInfo &TII;
const X86RegisterInfo &TRI;
const X86RegisterBankInfo &RBI;
bool OptForSize;
bool OptForMinSize;
PredicateBitset AvailableFeatures;
PredicateBitset computeAvailableFeatures(const MachineFunction *MF,
const X86Subtarget *Subtarget) const;
#define GET_GLOBALISEL_TEMPORARIES_DECL
#include "X86GenGlobalISel.inc"
@ -98,12 +86,10 @@ private:
#include "X86GenGlobalISel.inc"
#undef GET_GLOBALISEL_IMPL
X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
const X86Subtarget &STI,
X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI,
const X86RegisterBankInfo &RBI)
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI), OptForSize(false),
OptForMinSize(false), AvailableFeatures()
: InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI)
#define GET_GLOBALISEL_TEMPORARIES_INIT
#include "X86GenGlobalISel.inc"
#undef GET_GLOBALISEL_TEMPORARIES_INIT
@ -195,12 +181,6 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
return true;
}
void X86InstructionSelector::beginFunction(const MachineFunction &MF) {
OptForSize = MF.getFunction()->optForSize();
OptForMinSize = MF.getFunction()->optForMinSize();
AvailableFeatures = computeAvailableFeatures(&MF, &STI);
}
bool X86InstructionSelector::select(MachineInstr &I) const {
assert(I.getParent() && "Instruction should be in a basic block!");
assert(I.getParent()->getParent() && "Instruction should be in a function!");
@ -591,8 +571,7 @@ bool X86InstructionSelector::selectTrunc(MachineInstr &I,
}
InstructionSelector *
llvm::createX86InstructionSelector(const X86TargetMachine &TM,
X86Subtarget &Subtarget,
llvm::createX86InstructionSelector(X86Subtarget &Subtarget,
X86RegisterBankInfo &RBI) {
return new X86InstructionSelector(TM, Subtarget, RBI);
return new X86InstructionSelector(Subtarget, RBI);
}

View File

@ -286,7 +286,7 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const {
auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo());
GISel->RegBankInfo.reset(RBI);
GISel->InstSelector.reset(createX86InstructionSelector(*this, *I, *RBI));
GISel->InstSelector.reset(createX86InstructionSelector(*I, *RBI));
#endif
I->setGISelAccessor(*GISel);
}

View File

@ -29,31 +29,7 @@ def m1 : OperandWithDefaultOps <i32, (ops (i32 -1))>;
def Z : OperandWithDefaultOps <i32, (ops R0)>;
def m1Z : OperandWithDefaultOps <i32, (ops (i32 -1), R0)>;
def HasA : Predicate<"Subtarget->hasA()">;
def HasB : Predicate<"Subtarget->hasB()">;
//===- Test the function boilerplate. -------------------------------------===//
// CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
// CHECK-NEXT: Feature_HasABit = 0,
// CHECK-NEXT: Feature_HasBBit = 1,
// CHECK-NEXT: };
// CHECK-LABEL: static const char *SubtargetFeatureNames[] = {
// CHECK-NEXT: "Feature_HasA",
// CHECK-NEXT: "Feature_HasB",
// CHECK-NEXT: nullptr
// CHECK-NEXT: };
// CHECK-LABEL: PredicateBitset MyTargetInstructionSelector::
// CHECK-NEXT: computeAvailableFeatures(const MachineFunction *MF, const MyTargetSubtarget *Subtarget) const {
// CHECK-NEXT: PredicateBitset Features;
// CHECK-NEXT: if (Subtarget->hasA())
// CHECK-NEXT: Features[Feature_HasABit] = 1;
// CHECK-NEXT: if (Subtarget->hasB())
// CHECK-NEXT: Features[Feature_HasBBit] = 1;
// CHECK-NEXT: return Features;
// CHECK-NEXT: }
//===- Test the function definition boilerplate. --------------------------===//
// CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I) const {
// CHECK: MachineFunction &MF = *I.getParent()->getParent();
@ -127,9 +103,6 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
//===- Test a nested instruction match. -----------------------------------===//
// CHECK-LABEL: if ([&]() {
// CHECK-NEXT: PredicateBitset ExpectedFeatures = {Feature_HasABit};
// CHECK-NEXT: if ((AvailableFeatures & ExpectedFeatures) != ExpectedFeatures)
// CHECK-NEXT: return false;
// CHECK-NEXT: MachineInstr &MI0 = I;
// CHECK-NEXT: if (MI0.getNumOperands() < 3)
// CHECK-NEXT: return false;
@ -169,9 +142,6 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
// We also get a second rule by commutativity.
// CHECK-LABEL: if ([&]() {
// CHECK-NEXT: PredicateBitset ExpectedFeatures = {Feature_HasABit};
// CHECK-NEXT: if ((AvailableFeatures & ExpectedFeatures) != ExpectedFeatures)
// CHECK-NEXT: return false;
// CHECK-NEXT: MachineInstr &MI0 = I;
// CHECK-NEXT: if (MI0.getNumOperands() < 3)
// CHECK-NEXT: return false;
@ -211,15 +181,11 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
[(set GPR32:$dst,
(mul (add GPR32:$src1, GPR32:$src2), GPR32:$src3))]>,
Requires<[HasA]>;
(mul (add GPR32:$src1, GPR32:$src2), GPR32:$src3))]>;
//===- Test another simple pattern with regclass operands. ----------------===//
// CHECK-LABEL: if ([&]() {
// CHECK-NEXT: PredicateBitset ExpectedFeatures = {Feature_HasABit, Feature_HasBBit};
// CHECK-NEXT: if ((AvailableFeatures & ExpectedFeatures) != ExpectedFeatures)
// CHECK-NEXT: return false;
// CHECK-NEXT: MachineInstr &MI0 = I;
// CHECK-NEXT: if (MI0.getNumOperands() < 3)
// CHECK-NEXT: return false;
@ -247,8 +213,7 @@ def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
// CHECK-NEXT: }()) { return true; }
def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
[(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>,
Requires<[HasA, HasB]>;
[(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>;
//===- Test a pattern with ComplexPattern operands. -----------------------===//
//

View File

@ -2861,7 +2861,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
emitValidateOperandClass(Info, OS);
// Emit the available features compute function.
SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
SubtargetFeatureInfo::emitComputeAvailableFeatures(
Info.Target.getName(), ClassName, "ComputeAvailableFeatures",
Info.SubtargetFeatures, OS);

View File

@ -336,7 +336,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
o << "#endif // NDEBUG\n";
// Emit the available features compute function.
SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
SubtargetFeatureInfo::emitComputeAvailableFeatures(
Target.getName(), "MCCodeEmitter", "computeAvailableFeatures",
SubtargetFeatures, o);

View File

@ -31,7 +31,6 @@
//===----------------------------------------------------------------------===//
#include "CodeGenDAGPatterns.h"
#include "SubtargetFeatureInfo.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
@ -162,6 +161,20 @@ static std::string explainPredicates(const TreePatternNode *N) {
return Explanation;
}
static std::string explainRulePredicates(const ArrayRef<Init *> Predicates) {
std::string Explanation = "";
StringRef Separator = "";
for (const auto *P : Predicates) {
Explanation += Separator;
if (const DefInit *PDef = dyn_cast<DefInit>(P)) {
Explanation += PDef->getDef()->getName();
} else
Explanation += "<unknown>";
}
return Explanation;
}
std::string explainOperator(Record *Operator) {
if (Operator->isSubClassOf("SDNode"))
return " (" + Operator->getValueAsString("Opcode") + ")";
@ -225,8 +238,6 @@ class RuleMatcher {
/// ID for the next instruction variable defined with defineInsnVar()
unsigned NextInsnVarID;
std::vector<Record *> RequiredFeatures;
public:
RuleMatcher()
: Matchers(), Actions(), InsnVariableNames(), NextInsnVarID(0) {}
@ -234,7 +245,6 @@ public:
RuleMatcher &operator=(RuleMatcher &&Other) = default;
InstructionMatcher &addInstructionMatcher();
void addRequiredFeature(Record *Feature);
template <class Kind, class... Args> Kind &addAction(Args &&... args);
@ -245,9 +255,7 @@ public:
void emitCxxCapturedInsnList(raw_ostream &OS);
void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr);
void emit(raw_ostream &OS,
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
SubtargetFeatures);
void emit(raw_ostream &OS);
/// Compare the priority of this object and B.
///
@ -1084,10 +1092,6 @@ InstructionMatcher &RuleMatcher::addInstructionMatcher() {
return *Matchers.back();
}
void RuleMatcher::addRequiredFeature(Record *Feature) {
RequiredFeatures.push_back(Feature);
}
template <class Kind, class... Args>
Kind &RuleMatcher::addAction(Args &&... args) {
Actions.emplace_back(llvm::make_unique<Kind>(std::forward<Args>(args)...));
@ -1131,9 +1135,7 @@ void RuleMatcher::emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr) {
Matchers.front()->emitCxxCaptureStmts(OS, *this, InsnVarName);
}
void RuleMatcher::emit(raw_ostream &OS,
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
SubtargetFeatures) {
void RuleMatcher::emit(raw_ostream &OS) {
if (Matchers.empty())
llvm_unreachable("Unexpected empty matcher!");
@ -1147,22 +1149,7 @@ void RuleMatcher::emit(raw_ostream &OS,
// %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr
// on some targets but we don't need to make use of that yet.
assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet");
OS << "if (";
OS << "[&]() {\n";
if (!RequiredFeatures.empty()) {
OS << " PredicateBitset ExpectedFeatures = {";
StringRef Separator = "";
for (const auto &Predicate : RequiredFeatures) {
const auto &I = SubtargetFeatures.find(Predicate);
assert(I != SubtargetFeatures.end() && "Didn't import predicate?");
OS << Separator << I->second.getEnumBitName();
Separator = ", ";
}
OS << "};\n";
OS << "if ((AvailableFeatures & ExpectedFeatures) != ExpectedFeatures)\n"
<< " return false;\n";
}
OS << "if ([&]() {\n";
emitCxxCaptureStmts(OS, "I");
@ -1277,13 +1264,10 @@ private:
/// GIComplexPatternEquiv.
DenseMap<const Record *, const Record *> ComplexPatternEquivs;
// Map of predicates to their subtarget features.
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
void gatherNodeEquivs();
const CodeGenInstruction *findNodeEquiv(Record *N) const;
Error importRulePredicates(RuleMatcher &M, ArrayRef<Init *> Predicates);
Error importRulePredicates(RuleMatcher &M, ArrayRef<Init *> Predicates) const;
Expected<InstructionMatcher &>
createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher,
const TreePatternNode *Src) const;
@ -1303,8 +1287,6 @@ private:
/// Analyze pattern \p P, returning a matcher for it if possible.
/// Otherwise, return an Error explaining why we don't support it.
Expected<RuleMatcher> runOnPattern(const PatternToMatch &P);
void declareSubtargetFeature(Record *Predicate);
};
void GlobalISelEmitter::gatherNodeEquivs() {
@ -1333,13 +1315,10 @@ GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
Error
GlobalISelEmitter::importRulePredicates(RuleMatcher &M,
ArrayRef<Init *> Predicates) {
for (const Init *Predicate : Predicates) {
const DefInit *PredicateDef = static_cast<const DefInit *>(Predicate);
declareSubtargetFeature(PredicateDef->getDef());
M.addRequiredFeature(PredicateDef->getDef());
}
ArrayRef<Init *> Predicates) const {
if (!Predicates.empty())
return failedImport("Pattern has a rule predicate (" +
explainRulePredicates(Predicates) + ")");
return Error::success();
}
@ -1746,13 +1725,6 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
for (const auto &Rule : Rules)
MaxTemporaries = std::max(MaxTemporaries, Rule.countTemporaryOperands());
OS << "#ifdef GET_GLOBALISEL_PREDICATE_BITSET\n"
<< "const unsigned MAX_SUBTARGET_PREDICATES = " << SubtargetFeatures.size()
<< ";\n"
<< "using PredicateBitset = "
"llvm::PredicateBitsetImpl<MAX_SUBTARGET_PREDICATES>;\n"
<< "#endif // ifdef GET_GLOBALISEL_PREDICATE_BITSET\n\n";
OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_DECL\n";
for (unsigned I = 0; I < MaxTemporaries; ++I)
OS << " mutable MachineOperand TempOp" << I << ";\n";
@ -1763,21 +1735,14 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
OS << ", TempOp" << I << "(MachineOperand::CreatePlaceholder())\n";
OS << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n\n";
OS << "#ifdef GET_GLOBALISEL_IMPL\n";
SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
OS);
SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS);
SubtargetFeatureInfo::emitComputeAvailableFeatures(
Target.getName(), "InstructionSelector", "computeAvailableFeatures",
SubtargetFeatures, OS);
OS << "bool " << Target.getName()
OS << "#ifdef GET_GLOBALISEL_IMPL\n"
<< "bool " << Target.getName()
<< "InstructionSelector::selectImpl(MachineInstr &I) const {\n"
<< " MachineFunction &MF = *I.getParent()->getParent();\n"
<< " const MachineRegisterInfo &MRI = MF.getRegInfo();\n";
for (auto &Rule : Rules) {
Rule.emit(OS, SubtargetFeatures);
Rule.emit(OS);
++NumPatternEmitted;
}
@ -1786,12 +1751,6 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
<< "#endif // ifdef GET_GLOBALISEL_IMPL\n";
}
void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) {
if (SubtargetFeatures.count(Predicate) == 0)
SubtargetFeatures.emplace(
Predicate, SubtargetFeatureInfo(Predicate, SubtargetFeatures.size()));
}
} // end anonymous namespace
//===----------------------------------------------------------------------===//

View File

@ -59,20 +59,6 @@ void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
OS << "};\n\n";
}
void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
raw_ostream &OS) {
OS << "// Bits for subtarget features that participate in "
<< "instruction matching.\n";
OS << "enum SubtargetFeatureBits : "
<< getMinimalTypeForRange(SubtargetFeatures.size()) << " {\n";
for (const auto &SF : SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second;
OS << " " << SFI.getEnumBitName() << " = " << SFI.Index << ",\n";
}
OS << "};\n\n";
}
void SubtargetFeatureInfo::emitNameTable(
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
raw_ostream &OS) {
@ -104,24 +90,6 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures(
StringRef TargetName, StringRef ClassName, StringRef FuncName,
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
raw_ostream &OS) {
OS << "PredicateBitset " << TargetName << ClassName << "::\n"
<< FuncName << "(const MachineFunction *MF, const " << TargetName
<< "Subtarget *Subtarget) const {\n";
OS << " PredicateBitset Features;\n";
for (const auto &SF : SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second;
OS << " if (" << SFI.TheDef->getValueAsString("CondString") << ")\n";
OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
}
OS << " return Features;\n";
OS << "}\n\n";
}
void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
StringRef TargetName, StringRef ClassName, StringRef FuncName,
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
raw_ostream &OS) {
OS << "uint64_t " << TargetName << ClassName << "::\n"
<< FuncName << "(const FeatureBitset& FB) const {\n";
OS << " uint64_t Features = 0;\n";

View File

@ -37,34 +37,16 @@ struct SubtargetFeatureInfo {
return "Feature_" + TheDef->getName().str();
}
/// \brief The name of the enumerated constant identifying the bitnumber for
/// this feature.
std::string getEnumBitName() const {
return "Feature_" + TheDef->getName().str() + "Bit";
}
void dump() const;
static std::vector<std::pair<Record *, SubtargetFeatureInfo>>
getAll(const RecordKeeper &Records);
/// Emit the subtarget feature flag definitions.
///
/// This version emits the bit value for the feature and is therefore limited
/// to 64 feature bits.
static void emitSubtargetFeatureFlagEnumeration(
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
&SubtargetFeatures,
raw_ostream &OS);
/// Emit the subtarget feature flag definitions.
///
/// This version emits the bit index for the feature and can therefore support
/// more than 64 feature bits.
static void emitSubtargetFeatureBitEnumeration(
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
&SubtargetFeatures,
raw_ostream &OS);
static void emitNameTable(std::map<Record *, SubtargetFeatureInfo,
LessRecordByID> &SubtargetFeatures,
raw_ostream &OS);
@ -72,9 +54,6 @@ struct SubtargetFeatureInfo {
/// Emit the function to compute the list of available features given a
/// subtarget.
///
/// This version is used for subtarget features defined using Predicate<>
/// and supports more than 64 feature bits.
///
/// \param TargetName The name of the target as used in class prefixes (e.g.
/// <TargetName>Subtarget)
/// \param ClassName The name of the class (without the <Target> prefix)
@ -87,25 +66,6 @@ struct SubtargetFeatureInfo {
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
&SubtargetFeatures,
raw_ostream &OS);
/// Emit the function to compute the list of available features given a
/// subtarget.
///
/// This version is used for subtarget features defined using
/// AssemblerPredicate<> and supports up to 64 feature bits.
///
/// \param TargetName The name of the target as used in class prefixes (e.g.
/// <TargetName>Subtarget)
/// \param ClassName The name of the class (without the <Target> prefix)
/// that will contain the generated functions.
/// \param FuncName The name of the function to emit.
/// \param SubtargetFeatures A map of TableGen records to the
/// SubtargetFeatureInfo equivalent.
static void emitComputeAssemblerAvailableFeatures(
StringRef TargetName, StringRef ClassName, StringRef FuncName,
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
&SubtargetFeatures,
raw_ostream &OS);
};
} // end namespace llvm

View File

@ -40,6 +40,5 @@ const char *llvm::getMinimalTypeForEnumBitfield(uint64_t Size) {
uint64_t MaxIndex = Size;
if (MaxIndex > 0)
MaxIndex--;
assert(MaxIndex <= 64 && "Too many bits");
return getMinimalTypeForRange(1ULL << MaxIndex);
}