aboutsummaryrefslogtreecommitdiffstats
path: root/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp54
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp2
-rw-r--r--utils/TableGen/AsmWriterInst.h4
-rw-r--r--utils/TableGen/CTagsEmitter.cpp16
-rw-r--r--utils/TableGen/CallingConvEmitter.cpp58
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp26
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp106
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h29
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp18
-rw-r--r--utils/TableGen/CodeGenInstruction.h7
-rw-r--r--utils/TableGen/CodeGenIntrinsics.h4
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp16
-rw-r--r--utils/TableGen/CodeGenRegisters.h4
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp4
-rw-r--r--utils/TableGen/CodeGenSchedule.h4
-rw-r--r--utils/TableGen/CodeGenTarget.cpp3
-rw-r--r--utils/TableGen/CodeGenTarget.h4
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp4
-rw-r--r--utils/TableGen/DAGISelMatcher.h6
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp2
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp35
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp6
-rw-r--r--utils/TableGen/FastISelEmitter.cpp243
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp84
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp4
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp36
-rw-r--r--utils/TableGen/OptParserEmitter.cpp26
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.cpp9
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp27
-rw-r--r--utils/TableGen/SequenceToOffsetTable.h4
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp25
-rw-r--r--utils/TableGen/TableGenBackends.h4
-rw-r--r--utils/TableGen/X86DisassemblerShared.h4
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp26
-rw-r--r--utils/TableGen/X86DisassemblerTables.h4
-rw-r--r--utils/TableGen/X86ModRMFilters.h4
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp235
-rw-r--r--utils/TableGen/X86RecognizableInstr.h9
38 files changed, 656 insertions, 500 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 1277086..891328f 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -448,7 +448,7 @@ struct MatchableInfo {
void formTwoOperandAlias(StringRef Constraint);
void initialize(const AsmMatcherInfo &Info,
- SmallPtrSet<Record*, 16> &SingletonRegisters,
+ SmallPtrSetImpl<Record*> &SingletonRegisters,
int AsmVariantNo, std::string &RegisterPrefix);
/// validate - Return true if this matchable is a valid thing to match against
@@ -565,9 +565,9 @@ struct SubtargetFeatureInfo {
Record *TheDef;
/// \brief An unique index assigned to represent this feature.
- unsigned Index;
+ uint64_t Index;
- SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {}
+ SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {}
/// \brief The name of the enumerated constant identifying this feature.
std::string getEnumName() const {
@@ -644,7 +644,7 @@ private:
/// buildRegisterClasses - Build the ClassInfo* instances for register
/// classes.
- void buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters);
+ void buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters);
/// buildOperandClasses - Build the ClassInfo* instances for user defined
/// operand classes.
@@ -766,7 +766,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {
}
void MatchableInfo::initialize(const AsmMatcherInfo &Info,
- SmallPtrSet<Record*, 16> &SingletonRegisters,
+ SmallPtrSetImpl<Record*> &SingletonRegisters,
int AsmVariantNo, std::string &RegisterPrefix) {
AsmVariantID = AsmVariantNo;
AsmString =
@@ -1075,7 +1075,7 @@ struct LessRegisterSet {
};
void AsmMatcherInfo::
-buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
+buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
const std::vector<CodeGenRegister*> &Registers =
Target.getRegBank().getRegisters();
ArrayRef<CodeGenRegisterClass*> RegClassList =
@@ -1093,7 +1093,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
(*it)->getOrder().begin(), (*it)->getOrder().end()));
// Add any required singleton sets.
- for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
+ for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(),
ie = SingletonRegisters.end(); it != ie; ++it) {
Record *Rec = *it;
RegisterSets.insert(RegisterSet(&Rec, &Rec + 1));
@@ -1191,7 +1191,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
RegisterClasses[it->first] = RegisterSetClasses[it->second];
// Name the register classes which correspond to singleton registers.
- for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
+ for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(),
ie = SingletonRegisters.end(); it != ie; ++it) {
Record *Rec = *it;
ClassInfo *CI = RegisterClasses[Rec];
@@ -1327,10 +1327,10 @@ void AsmMatcherInfo::buildInfo() {
if (Pred->getName().empty())
PrintFatalError(Pred->getLoc(), "Predicate has no name!");
- unsigned FeatureNo = SubtargetFeatures.size();
+ uint64_t FeatureNo = SubtargetFeatures.size();
SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo);
DEBUG(SubtargetFeatures[Pred]->dump());
- assert(FeatureNo < 32 && "Too many subtarget features!");
+ assert(FeatureNo < 64 && "Too many subtarget features!");
}
// Parse the instructions; we need to do this first so that we can gather the
@@ -2205,7 +2205,9 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
}
static const char *getMinimalTypeForRange(uint64_t Range) {
- assert(Range <= 0xFFFFFFFFULL && "Enum too large");
+ assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large");
+ if (Range > 0xFFFFFFFFULL)
+ return "uint64_t";
if (Range > 0xFFFF)
return "uint32_t";
if (Range > 0xFF)
@@ -2232,7 +2234,7 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
- OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n";
+ OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n";
}
OS << " Feature_None = 0\n";
OS << "};\n\n";
@@ -2263,7 +2265,7 @@ static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) {
static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
OS << "// User-level names for subtarget features that participate in\n"
<< "// instruction matching.\n"
- << "static const char *getSubtargetFeatureName(unsigned Val) {\n";
+ << "static const char *getSubtargetFeatureName(uint64_t Val) {\n";
if (!Info.SubtargetFeatures.empty()) {
OS << " switch(Val) {\n";
typedef std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> RecFeatMap;
@@ -2290,9 +2292,9 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
std::string ClassName =
Info.AsmParser->getValueAsString("AsmParserClassName");
- OS << "unsigned " << Info.Target.getName() << ClassName << "::\n"
+ OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
<< "ComputeAvailableFeatures(uint64_t FB) const {\n";
- OS << " unsigned Features = 0;\n";
+ OS << " uint64_t Features = 0;\n";
for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
@@ -2446,7 +2448,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
if (Aliases.empty()) return false;
OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "
- "unsigned Features, unsigned VariantID) {\n";
+ "uint64_t Features, unsigned VariantID) {\n";
OS << " switch (VariantID) {\n";
unsigned VariantCount = Target.getAsmParserVariantCount();
for (unsigned VC = 0; VC != VariantCount; ++VC) {
@@ -2589,7 +2591,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit code to get the available features.
OS << " // Get the current feature set.\n";
- OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n";
+ OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the next operand index.\n";
OS << " unsigned NextOpNum = Operands.size()-1;\n";
@@ -2691,7 +2693,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 << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
+ OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const OperandVector "
@@ -2703,7 +2705,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS.indent(27);
OS << "const OperandVector &Operands,\n"
<< " MCInst &Inst,\n"
- << " unsigned &ErrorInfo,"
+ << " uint64_t &ErrorInfo,"
<< " bool matchingInlineAsm,\n"
<< " unsigned VariantID = 0);\n";
@@ -2912,7 +2914,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< "MatchInstructionImpl(const OperandVector"
<< " &Operands,\n";
OS << " MCInst &Inst,\n"
- << "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n";
+ << "uint64_t &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n";
OS << " // Eliminate obvious mismatches.\n";
OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
@@ -2922,7 +2924,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Emit code to get the available features.
OS << " // Get the current feature set.\n";
- OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n";
+ OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the instruction mnemonic, which is the first token.\n";
OS << " StringRef Mnemonic = ((" << Target.getName()
@@ -2938,7 +2940,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " bool HadMatchOtherThanFeatures = false;\n";
OS << " bool HadMatchOtherThanPredicate = false;\n";
OS << " unsigned RetCode = Match_InvalidOperand;\n";
- OS << " unsigned MissingFeatures = ~0U;\n";
+ OS << " uint64_t MissingFeatures = ~0ULL;\n";
OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
OS << " // wrong for all instances of the instruction.\n";
OS << " ErrorInfo = ~0U;\n";
@@ -3014,10 +3016,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " if ((AvailableFeatures & it->RequiredFeatures) "
<< "!= it->RequiredFeatures) {\n";
OS << " HadMatchOtherThanFeatures = true;\n";
- OS << " unsigned NewMissingFeatures = it->RequiredFeatures & "
+ OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & "
"~AvailableFeatures;\n";
- OS << " if (CountPopulation_32(NewMissingFeatures) <=\n"
- " CountPopulation_32(MissingFeatures))\n";
+ OS << " if (CountPopulation_64(NewMissingFeatures) <=\n"
+ " CountPopulation_64(MissingFeatures))\n";
OS << " MissingFeatures = NewMissingFeatures;\n";
OS << " continue;\n";
OS << " }\n";
@@ -3055,7 +3057,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n";
OS << " SMLoc Loc = ((" << Target.getName()
<< "Operand&)*Operands[0]).getStartLoc();\n";
- OS << " Parser.Warning(Loc, Info, None);\n";
+ OS << " getParser().Warning(Loc, Info, None);\n";
OS << " }\n";
}
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index c7fe9df..7ef70d3 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -424,7 +424,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Emit the string itself.
- O << " const char AsmStrs[] = {\n";
+ O << " static const char AsmStrs[] = {\n";
StringTable.emit(O, printChar);
O << " };\n\n";
diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h
index 4cee352..fd77982 100644
--- a/utils/TableGen/AsmWriterInst.h
+++ b/utils/TableGen/AsmWriterInst.h
@@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef ASMWRITER_INST_H
-#define ASMWRITER_INST_H
+#ifndef LLVM_UTILS_TABLEGEN_ASMWRITERINST_H
+#define LLVM_UTILS_TABLEGEN_ASMWRITERINST_H
#include <string>
#include <vector>
diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp
index 5d6d6da..bbed92a 100644
--- a/utils/TableGen/CTagsEmitter.cpp
+++ b/utils/TableGen/CTagsEmitter.cpp
@@ -69,19 +69,15 @@ SMLoc CTagsEmitter::locate(const Record *R) {
}
void CTagsEmitter::run(raw_ostream &OS) {
- const std::map<std::string, Record *> &Classes = Records.getClasses();
- const std::map<std::string, Record *> &Defs = Records.getDefs();
+ const auto &Classes = Records.getClasses();
+ const auto &Defs = Records.getDefs();
std::vector<Tag> Tags;
// Collect tags.
Tags.reserve(Classes.size() + Defs.size());
- for (std::map<std::string, Record *>::const_iterator I = Classes.begin(),
- E = Classes.end();
- I != E; ++I)
- Tags.push_back(Tag(I->first, locate(I->second)));
- for (std::map<std::string, Record *>::const_iterator I = Defs.begin(),
- E = Defs.end();
- I != E; ++I)
- Tags.push_back(Tag(I->first, locate(I->second)));
+ for (const auto &C : Classes)
+ Tags.push_back(Tag(C.first, locate(C.second.get())));
+ for (const auto &D : Defs)
+ Tags.push_back(Tag(D.first, locate(D.second.get())));
// Emit tags.
std::sort(Tags.begin(), Tags.end());
OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n";
diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp
index 6d43e8e..6a65e5e 100644
--- a/utils/TableGen/CallingConvEmitter.cpp
+++ b/utils/TableGen/CallingConvEmitter.cpp
@@ -35,23 +35,26 @@ private:
} // End anonymous namespace
void CallingConvEmitter::run(raw_ostream &O) {
-
std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");
-
- // Emit prototypes for all of the CC's so that they can forward ref each
- // other.
+
+ // Emit prototypes for all of the non-custom CC's so that they can forward ref
+ // each other.
+ for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
+ if (!CCs[i]->getValueAsBit("Custom")) {
+ O << "static bool " << CCs[i]->getName()
+ << "(unsigned ValNo, MVT ValVT,\n"
+ << std::string(CCs[i]->getName().size() + 13, ' ')
+ << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << std::string(CCs[i]->getName().size() + 13, ' ')
+ << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
+ }
+ }
+
+ // Emit each non-custom calling convention description in full.
for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
- O << "static bool " << CCs[i]->getName()
- << "(unsigned ValNo, MVT ValVT,\n"
- << std::string(CCs[i]->getName().size()+13, ' ')
- << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
- << std::string(CCs[i]->getName().size()+13, ' ')
- << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
+ if (!CCs[i]->getValueAsBit("Custom"))
+ EmitCallingConv(CCs[i], O);
}
-
- // Emit each calling convention description in full.
- for (unsigned i = 0, e = CCs.size(); i != e; ++i)
- EmitCallingConv(CCs[i], O);
}
@@ -178,13 +181,17 @@ void CallingConvEmitter::EmitAction(Record *Action,
if (Size)
O << Size << ", ";
else
- O << "\n" << IndentStr << " State.getTarget().getDataLayout()"
- "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), ";
+ O << "\n" << IndentStr
+ << " State.getMachineFunction().getSubtarget().getDataLayout()"
+ "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
+ " ";
if (Align)
O << Align;
else
- O << "\n" << IndentStr << " State.getTarget().getDataLayout()"
- "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))";
+ O << "\n" << IndentStr
+ << " State.getMachineFunction().getSubtarget().getDataLayout()"
+ "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
+ "))";
O << ");\n" << IndentStr
<< "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
@@ -227,6 +234,21 @@ void CallingConvEmitter::EmitAction(Record *Action,
<< IndentStr << "else\n"
<< IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
}
+ } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ MVT::SimpleValueType DestVT = getValueType(DestTy);
+ O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
+ if (MVT(DestVT).isFloatingPoint()) {
+ PrintFatalError("CCPromoteToUpperBitsInType does not handle floating "
+ "point");
+ } else {
+ O << IndentStr << "if (ArgFlags.isSExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n"
+ << IndentStr << "else if (ArgFlags.isZExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n"
+ << IndentStr << "else\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n";
+ }
} else if (Action->isSubClassOf("CCBitConvertToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 4d0c0ca..11911b6 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -24,14 +24,6 @@
#include <vector>
using namespace llvm;
-// FIXME: Somewhat hackish to use a command line option for this. There should
-// be a CodeEmitter class in the Target.td that controls this sort of thing
-// instead.
-static cl::opt<bool>
-MCEmitter("mc-emitter",
- cl::desc("Generate CodeEmitter for use with the MC library."),
- cl::init(false));
-
namespace {
class CodeEmitterGen {
@@ -134,15 +126,13 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
if (SO.second == 0) {
Case += " // op: " + VarName + "\n" +
" op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
- if (MCEmitter)
- Case += ", Fixups, STI";
+ Case += ", Fixups, STI";
Case += ");\n";
}
} else {
Case += " // op: " + VarName + "\n" +
" op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
- if (MCEmitter)
- Case += ", Fixups, STI";
+ Case += ", Fixups, STI";
Case += ");\n";
}
@@ -223,8 +213,7 @@ std::string CodeEmitterGen::getInstructionCase(Record *R,
std::string PostEmitter = R->getValueAsString("PostEncoderMethod");
if (!PostEmitter.empty()) {
Case += " Value = " + PostEmitter + "(MI, Value";
- if (MCEmitter)
- Case += ", STI";
+ Case += ", STI";
Case += ");\n";
}
@@ -243,12 +232,9 @@ void CodeEmitterGen::run(raw_ostream &o) {
// Emit function declaration
o << "uint64_t " << Target.getName();
- if (MCEmitter)
- o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
- << " SmallVectorImpl<MCFixup> &Fixups,\n"
- << " const MCSubtargetInfo &STI) const {\n";
- else
- o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n";
+ o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
+ << " SmallVectorImpl<MCFixup> &Fixups,\n"
+ << " const MCSubtargetInfo &STI) const {\n";
// Emit instruction base values
o << " static const uint64_t InstBits[] = {\n";
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 2602bbc..a750aa9 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -771,7 +771,7 @@ static unsigned getPatternSize(const TreePatternNode *P,
/// Compute the complexity metric for the input pattern. This roughly
/// corresponds to the number of nodes that are covered.
-unsigned PatternToMatch::
+int PatternToMatch::
getPatternComplexity(const CodeGenDAGPatterns &CGP) const {
return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity();
}
@@ -1387,7 +1387,7 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
if (R->isSubClassOf("SubRegIndex")) {
assert(ResNo == 0 && "SubRegisterIndices only produce one result!");
- return EEVT::TypeSet();
+ return EEVT::TypeSet(MVT::i32, TP);
}
if (R->isSubClassOf("ValueType")) {
@@ -1529,7 +1529,16 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const {
return false;
}
+static bool isOperandClass(const TreePatternNode *N, StringRef Class) {
+ if (!N->isLeaf())
+ return N->getOperator()->isSubClassOf(Class);
+ DefInit *DI = dyn_cast<DefInit>(N->getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf(Class))
+ return true;
+
+ return false;
+}
/// ApplyTypeConstraints - Apply all of the type constraints relevant to
/// this node and its children in the tree. This returns true if it makes a
/// change, false otherwise. If a type contradiction is found, flag an error.
@@ -1689,6 +1698,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled");
MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP);
MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP);
+ } else if (getOperator()->getName() == "REG_SEQUENCE") {
+ // We need to do extra, custom typechecking for REG_SEQUENCE since it is
+ // variadic.
+
+ unsigned NChild = getNumChildren();
+ if (NChild < 3) {
+ TP.error("REG_SEQUENCE requires at least 3 operands!");
+ return false;
+ }
+
+ if (NChild % 2 == 0) {
+ TP.error("REG_SEQUENCE requires an odd number of operands!");
+ return false;
+ }
+
+ if (!isOperandClass(getChild(0), "RegisterClass")) {
+ TP.error("REG_SEQUENCE requires a RegisterClass for first operand!");
+ return false;
+ }
+
+ for (unsigned I = 1; I < NChild; I += 2) {
+ TreePatternNode *SubIdxChild = getChild(I + 1);
+ if (!isOperandClass(SubIdxChild, "SubRegIndex")) {
+ TP.error("REG_SEQUENCE requires a SubRegIndex for operand " +
+ itostr(I + 1) + "!");
+ return false;
+ }
+ }
}
unsigned ChildNo = 0;
@@ -1749,7 +1786,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP);
}
- if (ChildNo != getNumChildren()) {
+ if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) {
TP.error("Instruction '" + getOperator()->getName() +
"' was provided too many operands!");
return false;
@@ -1871,7 +1908,7 @@ TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
Trees.push_back(Pat);
}
-void TreePattern::error(const std::string &Msg) {
+void TreePattern::error(const Twine &Msg) {
if (HasError)
return;
dump();
@@ -2226,13 +2263,6 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
VerifyInstructionFlags();
}
-CodeGenDAGPatterns::~CodeGenDAGPatterns() {
- for (pf_iterator I = PatternFragments.begin(),
- E = PatternFragments.end(); I != E; ++I)
- delete I->second;
-}
-
-
Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const {
Record *N = Records.getDef(Name);
if (!N || !N->isSubClassOf("SDNode")) {
@@ -2294,9 +2324,9 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");
TreePattern *P =
- new TreePattern(Fragments[i], Tree,
- !Fragments[i]->isSubClassOf("OutPatFrag"), *this);
- PatternFragments[Fragments[i]] = P;
+ (PatternFragments[Fragments[i]] = llvm::make_unique<TreePattern>(
+ Fragments[i], Tree, !Fragments[i]->isSubClassOf("OutPatFrag"),
+ *this)).get();
// Validate the argument list, converting it to set, to discard duplicates.
std::vector<std::string> &Args = P->getArgList();
@@ -2354,16 +2384,16 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag"))
continue;
- TreePattern *ThePat = PatternFragments[Fragments[i]];
- ThePat->InlinePatternFragments();
+ TreePattern &ThePat = *PatternFragments[Fragments[i]];
+ ThePat.InlinePatternFragments();
// Infer as many types as possible. Don't worry about it if we don't infer
// all of them, some may depend on the inputs of the pattern.
- ThePat->InferAllTypes();
- ThePat->resetError();
+ ThePat.InferAllTypes();
+ ThePat.resetError();
// If debugging, print out the pattern fragment result.
- DEBUG(ThePat->dump());
+ DEBUG(ThePat.dump());
}
}
@@ -3274,14 +3304,14 @@ void CodeGenDAGPatterns::ParsePatterns() {
if (LI->getSize() == 0) continue; // no pattern.
// Parse the instruction.
- TreePattern *Result = new TreePattern(CurPattern, LI, false, *this);
+ TreePattern Result(CurPattern, LI, false, *this);
// Inline pattern fragments into it.
- Result->InlinePatternFragments();
+ Result.InlinePatternFragments();
- if (Result->getNumTrees() != 1)
- Result->error("Cannot handle instructions producing instructions "
- "with temporaries yet!");
+ if (Result.getNumTrees() != 1)
+ Result.error("Cannot handle instructions producing instructions "
+ "with temporaries yet!");
bool IterateInference;
bool InferredAllPatternTypes, InferredAllResultTypes;
@@ -3294,7 +3324,7 @@ void CodeGenDAGPatterns::ParsePatterns() {
// Infer as many types as possible. If we cannot infer all of them, we
// can never do anything with this pattern: report it to the user.
InferredAllResultTypes =
- Result->InferAllTypes(&Pattern->getNamedNodesMap());
+ Result.InferAllTypes(&Pattern->getNamedNodesMap());
IterateInference = false;
@@ -3302,13 +3332,13 @@ void CodeGenDAGPatterns::ParsePatterns() {
// resolve cases where the input type is known to be a pointer type (which
// is considered resolved), but the result knows it needs to be 32- or
// 64-bits. Infer the other way for good measure.
- for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(),
+ for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(),
Pattern->getTree(0)->getNumTypes());
i != e; ++i) {
- IterateInference = Pattern->getTree(0)->
- UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result);
- IterateInference |= Result->getTree(0)->
- UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result);
+ IterateInference = Pattern->getTree(0)->UpdateNodeType(
+ i, Result.getTree(0)->getExtType(i), Result);
+ IterateInference |= Result.getTree(0)->UpdateNodeType(
+ i, Pattern->getTree(0)->getExtType(i), Result);
}
// If our iteration has converged and the input pattern's types are fully
@@ -3322,8 +3352,8 @@ void CodeGenDAGPatterns::ParsePatterns() {
// arbitrary types to the result pattern's nodes.
if (!IterateInference && InferredAllPatternTypes &&
!InferredAllResultTypes)
- IterateInference = ForceArbitraryInstResultType(Result->getTree(0),
- *Result);
+ IterateInference =
+ ForceArbitraryInstResultType(Result.getTree(0), Result);
} while (IterateInference);
// Verify that we inferred enough types that we can do something with the
@@ -3332,7 +3362,7 @@ void CodeGenDAGPatterns::ParsePatterns() {
Pattern->error("Could not infer all types in pattern!");
if (!InferredAllResultTypes) {
Pattern->dump();
- Result->error("Could not infer all types in pattern result!");
+ Result.error("Could not infer all types in pattern result!");
}
// Validate that the input pattern is correct.
@@ -3345,7 +3375,7 @@ void CodeGenDAGPatterns::ParsePatterns() {
InstImpResults);
// Promote the xform function to be an explicit node if set.
- TreePatternNode *DstPattern = Result->getOnlyTree();
+ TreePatternNode *DstPattern = Result.getOnlyTree();
std::vector<TreePatternNode*> ResultNodeOperands;
for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
TreePatternNode *OpNode = DstPattern->getChild(ii);
@@ -3357,16 +3387,16 @@ void CodeGenDAGPatterns::ParsePatterns() {
}
ResultNodeOperands.push_back(OpNode);
}
- DstPattern = Result->getOnlyTree();
+ DstPattern = Result.getOnlyTree();
if (!DstPattern->isLeaf())
DstPattern = new TreePatternNode(DstPattern->getOperator(),
ResultNodeOperands,
DstPattern->getNumTypes());
- for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i)
- DstPattern->setType(i, Result->getOnlyTree()->getExtType(i));
+ for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i)
+ DstPattern->setType(i, Result.getOnlyTree()->getExtType(i));
- TreePattern Temp(Result->getRecord(), DstPattern, false, *this);
+ TreePattern Temp(Result.getRecord(), DstPattern, false, *this);
Temp.InferAllTypes();
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index fb30cdd..c0812cf 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CODEGEN_DAGPATTERNS_H
-#define CODEGEN_DAGPATTERNS_H
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H
+#define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H
#include "CodeGenIntrinsics.h"
#include "CodeGenTarget.h"
@@ -597,7 +597,7 @@ public:
/// error - If this is the first error in the current resolution step,
/// print it and set the error flag. Otherwise, continue silently.
- void error(const std::string &Msg);
+ void error(const Twine &Msg);
bool hasError() const {
return HasError;
}
@@ -667,7 +667,7 @@ public:
PatternToMatch(Record *srcrecord, ListInit *preds,
TreePatternNode *src, TreePatternNode *dst,
const std::vector<Record*> &dstregs,
- unsigned complexity, unsigned uid)
+ int complexity, unsigned uid)
: SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst),
Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {}
@@ -676,7 +676,7 @@ public:
TreePatternNode *SrcPattern; // Source pattern to match.
TreePatternNode *DstPattern; // Resulting pattern.
std::vector<Record*> Dstregs; // Physical register defs being matched.
- unsigned AddedComplexity; // Add to matching pattern complexity.
+ int AddedComplexity; // Add to matching pattern complexity.
unsigned ID; // Unique ID for the record.
Record *getSrcRecord() const { return SrcRecord; }
@@ -684,13 +684,13 @@ public:
TreePatternNode *getSrcPattern() const { return SrcPattern; }
TreePatternNode *getDstPattern() const { return DstPattern; }
const std::vector<Record*> &getDstRegs() const { return Dstregs; }
- unsigned getAddedComplexity() const { return AddedComplexity; }
+ int getAddedComplexity() const { return AddedComplexity; }
std::string getPredicateCheck() const;
/// Compute the complexity metric for the input pattern. This roughly
/// corresponds to the number of nodes that are covered.
- unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
+ int getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
};
class CodeGenDAGPatterns {
@@ -702,7 +702,8 @@ class CodeGenDAGPatterns {
std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms;
std::map<Record*, ComplexPattern, LessRecordByID> ComplexPatterns;
- std::map<Record*, TreePattern*, LessRecordByID> PatternFragments;
+ std::map<Record *, std::unique_ptr<TreePattern>, LessRecordByID>
+ PatternFragments;
std::map<Record*, DAGDefaultOperand, LessRecordByID> DefaultOperands;
std::map<Record*, DAGInstruction, LessRecordByID> Instructions;
@@ -716,7 +717,6 @@ class CodeGenDAGPatterns {
std::vector<PatternToMatch> PatternsToMatch;
public:
CodeGenDAGPatterns(RecordKeeper &R);
- ~CodeGenDAGPatterns();
CodeGenTarget &getTargetInfo() { return Target; }
const CodeGenTarget &getTargetInfo() const { return Target; }
@@ -778,15 +778,16 @@ public:
// Pattern Fragment information.
TreePattern *getPatternFragment(Record *R) const {
assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
- return PatternFragments.find(R)->second;
+ return PatternFragments.find(R)->second.get();
}
TreePattern *getPatternFragmentIfRead(Record *R) const {
- if (!PatternFragments.count(R)) return nullptr;
- return PatternFragments.find(R)->second;
+ if (!PatternFragments.count(R))
+ return nullptr;
+ return PatternFragments.find(R)->second.get();
}
- typedef std::map<Record*, TreePattern*, LessRecordByID>::const_iterator
- pf_iterator;
+ typedef std::map<Record *, std::unique_ptr<TreePattern>,
+ LessRecordByID>::const_iterator pf_iterator;
pf_iterator pf_begin() const { return PatternFragments.begin(); }
pf_iterator pf_end() const { return PatternFragments.end(); }
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 2577ad4..d567dde 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -314,6 +314,9 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
hasPostISelHook = R->getValueAsBit("hasPostISelHook");
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
+ isRegSequence = R->getValueAsBit("isRegSequence");
+ isExtractSubreg = R->getValueAsBit("isExtractSubreg");
+ isInsertSubreg = R->getValueAsBit("isInsertSubreg");
bool Unset;
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
@@ -520,6 +523,21 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
return true;
}
+ // Bits<n> (also used for 0bxx literals)
+ if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) {
+ if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
+ return false;
+ if (!BI->isComplete())
+ return false;
+ // Convert the bits init to an integer and use that for the result.
+ IntInit *II =
+ dyn_cast_or_null<IntInit>(BI->convertInitializerTo(IntRecTy::get()));
+ if (!II)
+ return false;
+ ResOp = ResultOperand(II->getValue());
+ return true;
+ }
+
// If both are Operands with the same MVT, allow the conversion. It's
// up to the user to make sure the values are appropriate, just like
// for isel Pat's.
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index f143875..92aac5f 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CODEGEN_INSTRUCTION_H
-#define CODEGEN_INSTRUCTION_H
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
+#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineValueType.h"
@@ -253,6 +253,9 @@ namespace llvm {
bool hasExtraDefRegAllocReq : 1;
bool isCodeGenOnly : 1;
bool isPseudo : 1;
+ bool isRegSequence : 1;
+ bool isExtractSubreg : 1;
+ bool isInsertSubreg : 1;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h
index a9ece01..1f1adf1 100644
--- a/utils/TableGen/CodeGenIntrinsics.h
+++ b/utils/TableGen/CodeGenIntrinsics.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CODEGEN_INTRINSIC_H
-#define CODEGEN_INTRINSIC_H
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
+#define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
#include "llvm/CodeGen/MachineValueType.h"
#include <string>
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 8099f13..678222f 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -901,9 +901,8 @@ CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx,
FindI = SuperRegClasses.find(SubIdx);
if (FindI == SuperRegClasses.end())
return;
- for (SmallPtrSet<CodeGenRegisterClass*, 8>::const_iterator I =
- FindI->second.begin(), E = FindI->second.end(); I != E; ++I)
- Out.set((*I)->EnumValue);
+ for (CodeGenRegisterClass *RC : FindI->second)
+ Out.set(RC->EnumValue);
}
// Populate a unique sorted list of units from a register set.
@@ -967,9 +966,12 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
// Compute register name map.
for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- RegistersByName.GetOrCreateValue(
- Registers[i]->TheDef->getValueAsString("AsmName"),
- Registers[i]);
+ // FIXME: This could just be RegistersByName[name] = register, except that
+ // causes some failures in MIPS - perhaps they have duplicate register name
+ // entries? (or maybe there's a reason for it - I don't know much about this
+ // code, just drive-by refactoring)
+ RegistersByName.insert(std::make_pair(
+ Registers[i]->TheDef->getValueAsString("AsmName"), Registers[i]));
// Precompute all sub-register maps.
// This will create Composite entries for all inferred sub-register indices.
@@ -1533,7 +1535,7 @@ void CodeGenRegBank::computeRegUnitSets() {
assert(RegUnitSets.empty() && "dirty RegUnitSets");
// Compute a unique RegUnitSet for each RegClass.
- const ArrayRef<CodeGenRegisterClass*> &RegClasses = getRegClasses();
+ ArrayRef<CodeGenRegisterClass*> RegClasses = getRegClasses();
unsigned NumRegClasses = RegClasses.size();
for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) {
if (!RegClasses[RCIdx]->Allocatable)
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index 278315b..c1e37fa 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CODEGEN_REGISTERS_H
-#define CODEGEN_REGISTERS_H
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
+#define LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index 79d60ac..4cf7b5f 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -182,7 +182,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) {
// Recursively find all reachable SchedReadWrite records.
static void scanSchedRW(Record *RWDef, RecVec &RWDefs,
SmallPtrSet<Record*, 16> &RWSet) {
- if (!RWSet.insert(RWDef))
+ if (!RWSet.insert(RWDef).second)
return;
RWDefs.push_back(RWDef);
// Reads don't current have sequence records, but it can be added later.
@@ -751,7 +751,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
for (ArrayRef<Record*>::const_iterator
II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
unsigned OldSCIdx = InstrClassMap[*II];
- if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) {
+ if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) {
for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(),
RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) {
if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) {
diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h
index 3fef8ad..e5241b9 100644
--- a/utils/TableGen/CodeGenSchedule.h
+++ b/utils/TableGen/CodeGenSchedule.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CODEGEN_SCHEDULE_H
-#define CODEGEN_SCHEDULE_H
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
+#define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index d1b5711..597da68 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -301,7 +301,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
"GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG",
"IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE",
"REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START",
- "LIFETIME_END", "STACKMAP", "PATCHPOINT", nullptr};
+ "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD",
+ nullptr};
const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
for (const char *const *p = FixedInstrs; *p; ++p) {
const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index 5414310..f4e1b6a 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CODEGEN_TARGET_H
-#define CODEGEN_TARGET_H
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H
+#define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H
#include "CodeGenInstruction.h"
#include "CodeGenRegisters.h"
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 82682cd..e2e6ab1 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -94,8 +94,8 @@ struct PatternSortingPredicate {
// Otherwise, if the patterns might both match, sort based on complexity,
// which means that we prefer to match patterns that cover more nodes in the
// input over nodes that cover fewer.
- unsigned LHSSize = LHS->getPatternComplexity(CGP);
- unsigned RHSSize = RHS->getPatternComplexity(CGP);
+ int LHSSize = LHS->getPatternComplexity(CGP);
+ int RHSSize = RHS->getPatternComplexity(CGP);
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
if (LHSSize < RHSSize) return false;
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index f8f6c54..b9cb267 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -1,4 +1,4 @@
-//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===//
+//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef TBLGEN_DAGISELMATCHER_H
-#define TBLGEN_DAGISELMATCHER_H
+#ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H
+#define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index 0059570..302f27b 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -630,7 +630,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
I != E; ++I)
- PFsByName[I->first->getName()] = I->second;
+ PFsByName[I->first->getName()] = I->second.get();
if (!NodePredicates.empty()) {
OS << "bool CheckNodePredicate(SDNode *Node,\n";
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 97e37ba..4a73b00 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -718,7 +718,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
CodeGenInstruction &II = CGT.getInstruction(Op);
const DAGInstruction &Inst = CGP.getInstruction(Op);
- // If we can, get the pattern for the instruction we're generating. We derive
+ // If we can, get the pattern for the instruction we're generating. We derive
// a variety of information from this pattern, such as whether it has a chain.
//
// FIXME2: This is extremely dubious for several reasons, not the least of
@@ -755,16 +755,21 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// the "outs" list.
unsigned NumResults = Inst.getNumResults();
- // Loop over all of the operands of the instruction pattern, emitting code
- // to fill them all in. The node 'N' usually has number children equal to
- // the number of input operands of the instruction. However, in cases
- // where there are predicate operands for an instruction, we need to fill
- // in the 'execute always' values. Match up the node operands to the
- // instruction operands to do this.
+ // Number of operands we know the output instruction must have. If it is
+ // variadic, we could have more operands.
+ unsigned NumFixedOperands = II.Operands.size();
+
SmallVector<unsigned, 8> InstOps;
- for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size();
- InstOpNo != e; ++InstOpNo) {
+ // Loop over all of the fixed operands of the instruction pattern, emitting
+ // code to fill them all in. The node 'N' usually has number children equal to
+ // the number of input operands of the instruction. However, in cases where
+ // there are predicate operands for an instruction, we need to fill in the
+ // 'execute always' values. Match up the node operands to the instruction
+ // operands to do this.
+ unsigned ChildNo = 0;
+ for (unsigned InstOpNo = NumResults, e = NumFixedOperands;
+ InstOpNo != e; ++InstOpNo) {
// Determine what to emit for this operand.
Record *OperandNode = II.Operands[InstOpNo].Rec;
if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
@@ -807,6 +812,16 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
}
}
+ // If this is a variadic output instruction (i.e. REG_SEQUENCE), we can't
+ // expand suboperands, use default operands, or other features determined from
+ // the CodeGenInstruction after the fixed operands, which were handled
+ // above. Emit the remaining instructions implicitly added by the use for
+ // variable_ops.
+ if (II.Operands.isVariadic) {
+ for (unsigned I = ChildNo, E = N->getNumChildren(); I < E; ++I)
+ EmitResultOperand(N->getChild(I), InstOps);
+ }
+
// If this node has input glue or explicitly specified input physregs, we
// need to add chained and glued copyfromreg nodes and materialize the glue
// input.
@@ -852,7 +867,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// gets the excess operands from the input DAG.
int NumFixedArityOperands = -1;
if (isRoot &&
- (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP)))
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))
NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren();
// If this is the root node and multiple matched nodes in the input pattern
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index 0b117eb..7a22764 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -185,7 +185,7 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
/// Conceptually, we'd like to sink these predicates all the way to the last
/// matcher predicate in the series. However, it turns out that some
/// ComplexPatterns have side effects on the graph, so we really don't want to
-/// run a the complex pattern if the pattern predicate will fail. For this
+/// run a complex pattern if the pattern predicate will fail. For this
/// reason, we refuse to sink the pattern predicate past a ComplexPattern.
///
static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) {
@@ -400,7 +400,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
}
if (NewOptionsToMatch.empty()) {
- MatcherPtr.reset(nullptr);
+ MatcherPtr.reset();
return;
}
@@ -454,7 +454,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]);
- assert(Opcodes.insert(COM->getOpcode().getEnumName()) &&
+ assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&
"Duplicate opcodes not factored?");
Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext()));
}
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index 154f96d..748c923 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -19,6 +19,7 @@
#include "CodeGenDAGPatterns.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Error.h"
@@ -36,6 +37,7 @@ struct InstructionMemo {
const CodeGenRegisterClass *RC;
std::string SubRegNo;
std::vector<std::string>* PhysRegs;
+ std::string PredicateCheck;
};
} // End anonymous namespace
@@ -347,7 +349,7 @@ struct OperandsSignature {
// Implicit physical register operand. e.g. Instruction::Mul expect to
// select to a binary op. On x86, mul may take a single operand with
// the other operand being implicit. We must emit something that looks
- // like a binary instruction except for the very inner FastEmitInst_*
+ // like a binary instruction except for the very inner fastEmitInst_*
// call.
continue;
Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
@@ -364,7 +366,9 @@ struct OperandsSignature {
namespace {
class FastISelMap {
- typedef std::map<std::string, InstructionMemo> PredMap;
+ // A multimap is needed instead of a "plain" map because the key is
+ // the instruction's complexity (an int) and they are not unique.
+ typedef std::multimap<int, InstructionMemo> PredMap;
typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
@@ -373,6 +377,16 @@ class FastISelMap {
OperandsOpcodeTypeRetPredMap SimplePatterns;
+ // This is used to check that there are no duplicate predicates
+ typedef std::multimap<std::string, bool> PredCheckMap;
+ typedef std::map<MVT::SimpleValueType, PredCheckMap> RetPredCheckMap;
+ typedef std::map<MVT::SimpleValueType, RetPredCheckMap> TypeRetPredCheckMap;
+ typedef std::map<std::string, TypeRetPredCheckMap> OpcodeTypeRetPredCheckMap;
+ typedef std::map<OperandsSignature, OpcodeTypeRetPredCheckMap>
+ OperandsOpcodeTypeRetPredCheckMap;
+
+ OperandsOpcodeTypeRetPredCheckMap SimplePatternsCheck;
+
std::map<OperandsSignature, std::vector<OperandsSignature> >
SignaturesWithConstantForms;
@@ -384,6 +398,11 @@ public:
void collectPatterns(CodeGenDAGPatterns &CGP);
void printImmediatePredicates(raw_ostream &OS);
void printFunctionDefinitions(raw_ostream &OS);
+private:
+ void emitInstructionCode(raw_ostream &OS,
+ const OperandsSignature &Operands,
+ const PredMap &PM,
+ const std::string &RetVTName);
};
} // End anonymous namespace
@@ -541,6 +560,17 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
continue;
}
+ // Check if the operands match one of the patterns handled by FastISel.
+ std::string ManglingSuffix;
+ raw_string_ostream SuffixOS(ManglingSuffix);
+ Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);
+ SuffixOS.flush();
+ if (!StringSwitch<bool>(ManglingSuffix)
+ .Cases("", "r", "rr", "ri", "rf", true)
+ .Cases("rri", "i", "f", true)
+ .Default(false))
+ continue;
+
// Get the predicate that guards this pattern.
std::string PredicateCheck = Pattern.getPredicateCheck();
@@ -549,14 +579,24 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
Pattern.getDstPattern()->getOperator()->getName(),
DstRC,
SubRegNo,
- PhysRegInputs
+ PhysRegInputs,
+ PredicateCheck
};
+
+ int complexity = Pattern.getPatternComplexity(CGP);
- if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck))
+ if (SimplePatternsCheck[Operands][OpcodeName][VT]
+ [RetVT].count(PredicateCheck)) {
PrintFatalError(Pattern.getSrcRecord()->getLoc(),
- "Duplicate record in FastISel table!");
+ "Duplicate predicate in FastISel table!");
+ }
+ SimplePatternsCheck[Operands][OpcodeName][VT][RetVT].insert(
+ std::make_pair(PredicateCheck, true));
- SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo;
+ // Note: Instructions with the same complexity will appear in the order
+ // that they are encountered.
+ SimplePatterns[Operands][OpcodeName][VT][RetVT].insert(
+ std::make_pair(complexity, Memo));
// If any of the operands were immediates with predicates on them, strip
// them down to a signature that doesn't have predicates so that we can
@@ -582,6 +622,72 @@ void FastISelMap::printImmediatePredicates(raw_ostream &OS) {
OS << "\n\n";
}
+void FastISelMap::emitInstructionCode(raw_ostream &OS,
+ const OperandsSignature &Operands,
+ const PredMap &PM,
+ const std::string &RetVTName) {
+ // Emit code for each possible instruction. There may be
+ // multiple if there are subtarget concerns. A reverse iterator
+ // is used to produce the ones with highest complexity first.
+
+ bool OneHadNoPredicate = false;
+ for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend();
+ PI != PE; ++PI) {
+ const InstructionMemo &Memo = PI->second;
+ std::string PredicateCheck = Memo.PredicateCheck;
+
+ if (PredicateCheck.empty()) {
+ assert(!OneHadNoPredicate &&
+ "Multiple instructions match and more than one had "
+ "no predicate!");
+ OneHadNoPredicate = true;
+ } else {
+ if (OneHadNoPredicate) {
+ // FIXME: This should be a PrintError once the x86 target
+ // fixes PR21575.
+ PrintWarning("Multiple instructions match and one with no "
+ "predicate came before one with a predicate! "
+ "name:" + Memo.Name + " predicate: " +
+ PredicateCheck);
+ }
+ OS << " if (" + PredicateCheck + ") {\n";
+ OS << " ";
+ }
+
+ for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
+ if ((*Memo.PhysRegs)[i] != "")
+ OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, "
+ << "TII.get(TargetOpcode::COPY), "
+ << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
+ }
+
+ OS << " return fastEmitInst_";
+ if (Memo.SubRegNo.empty()) {
+ Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
+ ImmediatePredicates, true);
+ OS << "(" << InstNS << Memo.Name << ", ";
+ OS << "&" << InstNS << Memo.RC->getName() << "RegClass";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS, *Memo.PhysRegs);
+ OS << ");\n";
+ } else {
+ OS << "extractsubreg(" << RetVTName
+ << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n";
+ }
+
+ if (!PredicateCheck.empty()) {
+ OS << " }\n";
+ }
+ }
+ // Return 0 if all of the possibilities had predicates but none
+ // were satisfied.
+ if (!OneHadNoPredicate)
+ OS << " return 0;\n";
+ OS << "}\n";
+ OS << "\n";
+}
+
void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
// Now emit code for all the patterns that we collected.
@@ -608,9 +714,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
RI != RE; ++RI) {
MVT::SimpleValueType RetVT = RI->first;
const PredMap &PM = RI->second;
- bool HasPred = false;
- OS << "unsigned FastEmit_"
+ OS << "unsigned fastEmit_"
<< getLegalCName(Opcode)
<< "_" << getLegalCName(getName(VT))
<< "_" << getLegalCName(getName(RetVT)) << "_";
@@ -619,58 +724,11 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
Operands.PrintParameters(OS);
OS << ") {\n";
- // Emit code for each possible instruction. There may be
- // multiple if there are subtarget concerns.
- for (PredMap::const_iterator PI = PM.begin(), PE = PM.end();
- PI != PE; ++PI) {
- std::string PredicateCheck = PI->first;
- const InstructionMemo &Memo = PI->second;
-
- if (PredicateCheck.empty()) {
- assert(!HasPred &&
- "Multiple instructions match, at least one has "
- "a predicate and at least one doesn't!");
- } else {
- OS << " if (" + PredicateCheck + ") {\n";
- OS << " ";
- HasPred = true;
- }
-
- for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
- if ((*Memo.PhysRegs)[i] != "")
- OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, "
- << "TII.get(TargetOpcode::COPY), "
- << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
- }
-
- OS << " return FastEmitInst_";
- if (Memo.SubRegNo.empty()) {
- Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
- ImmediatePredicates, true);
- OS << "(" << InstNS << Memo.Name << ", ";
- OS << "&" << InstNS << Memo.RC->getName() << "RegClass";
- if (!Operands.empty())
- OS << ", ";
- Operands.PrintArguments(OS, *Memo.PhysRegs);
- OS << ");\n";
- } else {
- OS << "extractsubreg(" << getName(RetVT);
- OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n";
- }
-
- if (HasPred)
- OS << " }\n";
-
- }
- // Return 0 if none of the predicates were satisfied.
- if (HasPred)
- OS << " return 0;\n";
- OS << "}\n";
- OS << "\n";
+ emitInstructionCode(OS, Operands, PM, getName(RetVT));
}
// Emit one function for the type that demultiplexes on return type.
- OS << "unsigned FastEmit_"
+ OS << "unsigned fastEmit_"
<< getLegalCName(Opcode) << "_"
<< getLegalCName(getName(VT)) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
@@ -682,7 +740,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
RI != RE; ++RI) {
MVT::SimpleValueType RetVT = RI->first;
- OS << " case " << getName(RetVT) << ": return FastEmit_"
+ OS << " case " << getName(RetVT) << ": return fastEmit_"
<< getLegalCName(Opcode) << "_" << getLegalCName(getName(VT))
<< "_" << getLegalCName(getName(RetVT)) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
@@ -694,7 +752,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
} else {
// Non-variadic return type.
- OS << "unsigned FastEmit_"
+ OS << "unsigned fastEmit_"
<< getLegalCName(Opcode) << "_"
<< getLegalCName(getName(VT)) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
@@ -708,63 +766,13 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
<< ")\n return 0;\n";
const PredMap &PM = RM.begin()->second;
- bool HasPred = false;
-
- // Emit code for each possible instruction. There may be
- // multiple if there are subtarget concerns.
- for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE;
- ++PI) {
- std::string PredicateCheck = PI->first;
- const InstructionMemo &Memo = PI->second;
-
- if (PredicateCheck.empty()) {
- assert(!HasPred &&
- "Multiple instructions match, at least one has "
- "a predicate and at least one doesn't!");
- } else {
- OS << " if (" + PredicateCheck + ") {\n";
- OS << " ";
- HasPred = true;
- }
-
- for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
- if ((*Memo.PhysRegs)[i] != "")
- OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, "
- << "TII.get(TargetOpcode::COPY), "
- << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
- }
-
- OS << " return FastEmitInst_";
-
- if (Memo.SubRegNo.empty()) {
- Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
- ImmediatePredicates, true);
- OS << "(" << InstNS << Memo.Name << ", ";
- OS << "&" << InstNS << Memo.RC->getName() << "RegClass";
- if (!Operands.empty())
- OS << ", ";
- Operands.PrintArguments(OS, *Memo.PhysRegs);
- OS << ");\n";
- } else {
- OS << "extractsubreg(RetVT, Op0, Op0IsKill, ";
- OS << Memo.SubRegNo;
- OS << ");\n";
- }
-
- if (HasPred)
- OS << " }\n";
- }
- // Return 0 if none of the predicates were satisfied.
- if (HasPred)
- OS << " return 0;\n";
- OS << "}\n";
- OS << "\n";
+ emitInstructionCode(OS, Operands, PM, "RetVT");
}
}
// Emit one function for the opcode that demultiplexes based on the type.
- OS << "unsigned FastEmit_"
+ OS << "unsigned fastEmit_"
<< getLegalCName(Opcode) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT VT, MVT RetVT";
@@ -777,7 +785,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
TI != TE; ++TI) {
MVT::SimpleValueType VT = TI->first;
std::string TypeName = getName(VT);
- OS << " case " << TypeName << ": return FastEmit_"
+ OS << " case " << TypeName << ": return fastEmit_"
<< getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(RetVT";
@@ -797,13 +805,16 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
// Emit one function for the operand signature that demultiplexes based
// on opcode and type.
- OS << "unsigned FastEmit_";
+ OS << "unsigned fastEmit_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT VT, MVT RetVT, unsigned Opcode";
if (!Operands.empty())
OS << ", ";
Operands.PrintParameters(OS);
- OS << ") {\n";
+ OS << ") ";
+ if (!Operands.hasAnyImmediateCodes())
+ OS << "override ";
+ OS << "{\n";
// If there are any forms of this signature available that operate on
// constrained forms of the immediate (e.g., 32-bit sext immediate in a
@@ -823,7 +834,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
for (unsigned i = 0, e = MI->second.size(); i != e; ++i) {
OS << " if (";
MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates);
- OS << ")\n if (unsigned Reg = FastEmit_";
+ OS << ")\n if (unsigned Reg = fastEmit_";
MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(VT, RetVT, Opcode";
if (!MI->second[i].empty())
@@ -841,7 +852,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
I != E; ++I) {
const std::string &Opcode = I->first;
- OS << " case " << Opcode << ": return FastEmit_"
+ OS << " case " << Opcode << ": return fastEmit_"
<< getLegalCName(Opcode) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(VT, RetVT";
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index 42639cc..bd83b6c 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -230,7 +230,7 @@ protected:
std::vector<unsigned> VariableInstructions;
// Map of well-known segment value to its delegate.
- std::map<unsigned, const FilterChooser*> FilterChooserMap;
+ std::map<unsigned, std::unique_ptr<const FilterChooser>> FilterChooserMap;
// Number of instructions which fall under FilteredInstructions category.
unsigned NumFiltered;
@@ -252,7 +252,7 @@ public:
return *(FilterChooserMap.find((unsigned)-1)->second);
}
- Filter(const Filter &f);
+ Filter(Filter &&f);
Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);
~Filter();
@@ -333,13 +333,9 @@ protected:
// Parent emitter
const FixedLenDecoderEmitter *Emitter;
+ FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION;
+ void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION;
public:
- FilterChooser(const FilterChooser &FC)
- : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
- Operands(FC.Operands), Filters(FC.Filters),
- FilterBitValues(FC.FilterBitValues), Parent(FC.Parent),
- BestIndex(FC.BestIndex), BitWidth(FC.BitWidth),
- Emitter(FC.Emitter) { }
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs,
@@ -347,10 +343,8 @@ public:
unsigned BW,
const FixedLenDecoderEmitter *E)
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
- Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) {
- for (unsigned i = 0; i < BitWidth; ++i)
- FilterBitValues.push_back(BIT_UNFILTERED);
-
+ FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1),
+ BitWidth(BW), Emitter(E) {
doFilter();
}
@@ -490,11 +484,11 @@ public:
// //
///////////////////////////
-Filter::Filter(const Filter &f)
+Filter::Filter(Filter &&f)
: Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
- FilteredInstructions(f.FilteredInstructions),
- VariableInstructions(f.VariableInstructions),
- FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered),
+ FilteredInstructions(std::move(f.FilteredInstructions)),
+ VariableInstructions(std::move(f.VariableInstructions)),
+ FilterChooserMap(std::move(f.FilterChooserMap)), NumFiltered(f.NumFiltered),
LastOpcFiltered(f.LastOpcFiltered) {
}
@@ -534,12 +528,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
}
Filter::~Filter() {
- std::map<unsigned, const FilterChooser*>::iterator filterIterator;
- for (filterIterator = FilterChooserMap.begin();
- filterIterator != FilterChooserMap.end();
- filterIterator++) {
- delete filterIterator->second;
- }
}
// Divides the decoding task into sub tasks and delegates them to the
@@ -561,14 +549,10 @@ void Filter::recurse() {
// Delegates to an inferior filter chooser for further processing on this
// group of instructions whose segment values are variable.
- FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>(
- (unsigned)-1,
- new FilterChooser(Owner->AllInstructions,
- VariableInstructions,
- Owner->Operands,
- BitValueArray,
- *Owner)
- ));
+ FilterChooserMap.insert(
+ std::make_pair(-1U, llvm::make_unique<FilterChooser>(
+ Owner->AllInstructions, VariableInstructions,
+ Owner->Operands, BitValueArray, *Owner)));
}
// No need to recurse for a singleton filtered instruction.
@@ -594,14 +578,10 @@ void Filter::recurse() {
// Delegates to an inferior filter chooser for further processing on this
// category of instructions.
- FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>(
- mapIterator->first,
- new FilterChooser(Owner->AllInstructions,
- mapIterator->second,
- Owner->Operands,
- BitValueArray,
- *Owner)
- ));
+ FilterChooserMap.insert(std::make_pair(
+ mapIterator->first, llvm::make_unique<FilterChooser>(
+ Owner->AllInstructions, mapIterator->second,
+ Owner->Operands, BitValueArray, *Owner)));
}
}
@@ -636,7 +616,8 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
// A new filter entry begins a new scope for fixup resolution.
TableInfo.FixupStack.push_back(FixupList());
- std::map<unsigned, const FilterChooser*>::const_iterator filterIterator;
+ std::map<unsigned,
+ std::unique_ptr<const FilterChooser>>::const_iterator filterIterator;
DecoderTable &Table = TableInfo.Table;
@@ -1066,19 +1047,17 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
const OperandInfo &OpInfo) const {
const std::string &Decoder = OpInfo.Decoder;
- if (OpInfo.numFields() == 1) {
- OperandInfo::const_iterator OI = OpInfo.begin();
- o.indent(Indentation) << "tmp = fieldFromInstruction"
- << "(insn, " << OI->Base << ", " << OI->Width
- << ");\n";
- } else {
+ if (OpInfo.numFields() != 1)
o.indent(Indentation) << "tmp = 0;\n";
- for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end();
- OI != OE; ++OI) {
- o.indent(Indentation) << "tmp |= (fieldFromInstruction"
- << "(insn, " << OI->Base << ", " << OI->Width
- << ") << " << OI->Offset << ");\n";
- }
+
+ for (const EncodingField &EF : OpInfo) {
+ o.indent(Indentation) << "tmp ";
+ if (OpInfo.numFields() != 1) o << '|';
+ o << "= fieldFromInstruction"
+ << "(insn, " << EF.Base << ", " << EF.Width << ')';
+ if (OpInfo.numFields() != 1 || EF.Offset != 0)
+ o << " << " << EF.Offset;
+ o << ";\n";
}
if (Decoder != "")
@@ -1384,8 +1363,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit,
bool mixed) {
Filters.clear();
- Filter F(*this, startBit, numBit, true);
- Filters.push_back(F);
+ Filters.push_back(Filter(*this, startBit, numBit, true));
BestIndex = 0; // Sole Filter instance to choose from.
bestFilter().recurse();
}
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 76f05ce..6fdf22d 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -266,6 +266,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "#undef GET_INSTRINFO_NAMED_OPS\n";
OS << "namespace llvm {";
OS << "namespace " << Namespace << " {\n";
+ OS << "LLVM_READONLY\n";
OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n";
if (!Operands.empty()) {
OS << " static const int16_t OperandMap [][" << Operands.size()
@@ -504,6 +505,9 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)";
if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)";
if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)";
+ if (Inst.isRegSequence) OS << "|(1<<MCID::RegSequence)";
+ if (Inst.isExtractSubreg) OS << "|(1<<MCID::ExtractSubreg)";
+ if (Inst.isInsertSubreg) OS << "|(1<<MCID::InsertSubreg)";
// Emit all of the target-specific flags...
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 430ef32..37f6de0 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -129,8 +129,9 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
OS << " " << Ints[i].EnumName;
OS << ((i != e-1) ? ", " : " ");
- OS << std::string(40-Ints[i].EnumName.size(), ' ')
- << "// " << Ints[i].Name << "\n";
+ if (Ints[i].EnumName.size() < 40)
+ OS << std::string(40-Ints[i].EnumName.size(), ' ');
+ OS << " // " << Ints[i].Name << "\n";
}
OS << "#endif\n\n";
}
@@ -243,19 +244,20 @@ enum IIT_Info {
IIT_ARG = 15,
// Values from 16+ are only encodable with the inefficient encoding.
- IIT_MMX = 16,
- IIT_METADATA = 17,
- IIT_EMPTYSTRUCT = 18,
- IIT_STRUCT2 = 19,
- IIT_STRUCT3 = 20,
- IIT_STRUCT4 = 21,
- IIT_STRUCT5 = 22,
- IIT_EXTEND_ARG = 23,
- IIT_TRUNC_ARG = 24,
- IIT_ANYPTR = 25,
- IIT_V1 = 26,
- IIT_VARARG = 27,
- IIT_HALF_VEC_ARG = 28
+ IIT_V64 = 16,
+ IIT_MMX = 17,
+ IIT_METADATA = 18,
+ IIT_EMPTYSTRUCT = 19,
+ IIT_STRUCT2 = 20,
+ IIT_STRUCT3 = 21,
+ IIT_STRUCT4 = 22,
+ IIT_STRUCT5 = 23,
+ IIT_EXTEND_ARG = 24,
+ IIT_TRUNC_ARG = 25,
+ IIT_ANYPTR = 26,
+ IIT_V1 = 27,
+ IIT_VARARG = 28,
+ IIT_HALF_VEC_ARG = 29
};
@@ -355,6 +357,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
case 8: Sig.push_back(IIT_V8); break;
case 16: Sig.push_back(IIT_V16); break;
case 32: Sig.push_back(IIT_V32); break;
+ case 64: Sig.push_back(IIT_V64); break;
}
return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig);
@@ -679,8 +682,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << " }\n";
OS << " }\n";
- OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, "
- "NumAttrs));\n";
+ OS << " return AttributeSet::get(C, makeArrayRef(AS, NumAttrs));\n";
OS << "}\n";
OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
}
diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp
index c5fd7ee..9262d7c 100644
--- a/utils/TableGen/OptParserEmitter.cpp
+++ b/utils/TableGen/OptParserEmitter.cpp
@@ -221,9 +221,11 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
// The containing option group (if any).
OS << ", ";
- if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
+ const ListInit *GroupFlags = nullptr;
+ if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
+ GroupFlags = DI->getDef()->getValueAsListInit("Flags");
OS << getOptionName(*DI->getDef());
- else
+ } else
OS << "INVALID";
// The option alias (if any).
@@ -249,17 +251,19 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
}
// The option flags.
+ OS << ", ";
+ int NumFlags = 0;
const ListInit *LI = R.getValueAsListInit("Flags");
- if (LI->empty()) {
- OS << ", 0";
- } else {
- OS << ", ";
- for (unsigned i = 0, e = LI->size(); i != e; ++i) {
- if (i)
- OS << " | ";
- OS << cast<DefInit>(LI->getElement(i))->getDef()->getName();
- }
+ for (Init *I : *LI)
+ OS << (NumFlags++ ? " | " : "")
+ << cast<DefInit>(I)->getDef()->getName();
+ if (GroupFlags) {
+ for (Init *I : *GroupFlags)
+ OS << (NumFlags++ ? " | " : "")
+ << cast<DefInit>(I)->getDef()->getName();
}
+ if (NumFlags == 0)
+ OS << '0';
// The option parameter field.
OS << ", " << R.getValueAsInt("NumArgs");
diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp
index 3b74ac4..ebb43f0 100644
--- a/utils/TableGen/PseudoLoweringEmitter.cpp
+++ b/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -277,11 +277,10 @@ void PseudoLoweringEmitter::run(raw_ostream &o) {
assert(InstructionClass && "Instruction class definition missing!");
std::vector<Record*> Insts;
- for (std::map<std::string, Record*>::const_iterator I =
- Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) {
- if (I->second->isSubClassOf(ExpansionClass) &&
- I->second->isSubClassOf(InstructionClass))
- Insts.push_back(I->second);
+ for (const auto &D : Records.getDefs()) {
+ if (D.second->isSubClassOf(ExpansionClass) &&
+ D.second->isSubClassOf(InstructionClass))
+ Insts.push_back(D.second.get());
}
// Process the pseudo expansion definitions, validating them as we do so.
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 573c37f..79d08a9 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -379,9 +379,9 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
OS << "extern const unsigned " << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize";
if (!isCtor)
- OS << " = sizeof(" << Namespace
+ OS << " = array_lengthof(" << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
- << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n";
+ << "Dwarf2L);\n\n";
else
OS << ";\n\n";
}
@@ -427,9 +427,8 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
OS << "extern const unsigned " << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize";
if (!isCtor)
- OS << " = sizeof(" << Namespace
- << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
- << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n";
+ OS << " = array_lengthof(" << Namespace
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n";
else
OS << ";\n\n";
}
@@ -848,6 +847,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Loop over all of the register classes... emitting each one.
OS << "namespace { // Register classes...\n";
+ SequenceToOffsetTable<std::string> RegClassStrings;
+
// Emit the register enum value arrays for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
const CodeGenRegisterClass &RC = *RegisterClasses[rc];
@@ -856,6 +857,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Give the register class a legal C name if it's anonymous.
std::string Name = RC.getName();
+ RegClassStrings.add(Name);
+
// Emit the register list now.
OS << " // " << Name << " Register Class...\n"
<< " const MCPhysReg " << Name
@@ -880,6 +883,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "}\n\n";
+ RegClassStrings.layout();
+ OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
+ RegClassStrings.emit(OS, printChar);
+ OS << "};\n\n";
+
OS << "extern const MCRegisterClass " << TargetName
<< "MCRegisterClasses[] = {\n";
@@ -892,8 +900,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large.");
assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large.");
- OS << " { " << '\"' << RC.getName() << "\", "
- << RC.getName() << ", " << RC.getName() << "Bits, "
+ OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, "
+ << RegClassStrings.get(RC.getName()) << ", "
<< RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), "
<< RC.getQualifiedName() + "RegClassID" << ", "
<< RC.SpillSize/8 << ", "
@@ -934,10 +942,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
<< RegBank.getNumNativeRegUnits() << ", "
<< TargetName << "RegDiffLists, "
<< TargetName << "RegStrings, "
+ << TargetName << "RegClassStrings, "
<< TargetName << "SubRegIdxLists, "
<< (SubRegIndices.size() + 1) << ",\n"
<< TargetName << "SubRegIdxRanges, "
- << " " << TargetName << "RegEncodingTable);\n\n";
+ << TargetName << "RegEncodingTable);\n\n";
EmitRegMapping(OS, Regs, false);
@@ -1267,6 +1276,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n";
OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n";
OS << "extern const char " << TargetName << "RegStrings[];\n";
+ OS << "extern const char " << TargetName << "RegClassStrings[];\n";
OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n";
OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n";
OS << "extern const MCRegisterInfo::SubRegCoveredBits "
@@ -1289,6 +1299,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< " " << RegBank.getNumNativeRegUnits() << ",\n"
<< " " << TargetName << "RegDiffLists,\n"
<< " " << TargetName << "RegStrings,\n"
+ << " " << TargetName << "RegClassStrings,\n"
<< " " << TargetName << "SubRegIdxLists,\n"
<< " " << SubRegIndices.size() + 1 << ",\n"
<< " " << TargetName << "SubRegIdxRanges,\n"
diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h
index e6ab664..b58de4c 100644
--- a/utils/TableGen/SequenceToOffsetTable.h
+++ b/utils/TableGen/SequenceToOffsetTable.h
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H
-#define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H
+#ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H
+#define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 06f8694..9f2fc92 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -386,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
- if (!ItinsDefSet.insert(PI->ItinsDef))
+ if (!ItinsDefSet.insert(PI->ItinsDef).second)
continue;
std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
@@ -565,7 +565,7 @@ EmitItineraries(raw_ostream &OS,
PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
Record *ItinsDef = PI->ItinsDef;
- if (!ItinsDefSet.insert(ItinsDef))
+ if (!ItinsDefSet.insert(ItinsDef).second)
continue;
// Get processor itinerary name
@@ -575,12 +575,13 @@ EmitItineraries(raw_ostream &OS,
assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
+ // Empty itineraries aren't referenced anywhere in the tablegen output
+ // so don't emit them.
+ if (ItinList.empty())
+ continue;
+
OS << "\n";
OS << "static const llvm::InstrItinerary ";
- if (ItinList.empty()) {
- OS << '*' << Name << " = nullptr;\n";
- continue;
- }
// Begin processor itinerary table
OS << Name << "[] = {\n";
@@ -1192,7 +1193,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
// Begin processor itinerary properties
OS << "\n";
- OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
+ OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n";
EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ',');
EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ',');
@@ -1201,6 +1202,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
OS << " " << (bool)(PI->ModelDef ?
+ PI->ModelDef->getValueAsBit("PostRAScheduler") : 0)
+ << ", // " << "PostRAScheduler\n";
+
+ OS << " " << (bool)(PI->ModelDef ?
PI->ModelDef->getValueAsBit("CompleteModel") : 0)
<< ", // " << "CompleteModel\n";
@@ -1213,10 +1218,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
- SchedModels.schedClassBegin()) << ",\n";
else
OS << " 0, 0, 0, 0, // No instruction-level machine model.\n";
- if (SchedModels.hasItineraries())
- OS << " " << PI->ItinsDef->getName() << ");\n";
+ if (PI->hasItineraries())
+ OS << " " << PI->ItinsDef->getName() << "};\n";
else
- OS << " 0); // No Itinerary\n";
+ OS << " nullptr}; // No Itinerary\n";
}
}
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index 28b626e..2dc03ce 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -13,6 +13,8 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H
+#define LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H
// A TableGen backend is a function that looks like
//
@@ -78,3 +80,5 @@ void EmitOptParser(RecordKeeper &RK, raw_ostream &OS);
void EmitCTags(RecordKeeper &RK, raw_ostream &OS);
} // End llvm namespace
+
+#endif
diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h
index 9e79b9c..5895277 100644
--- a/utils/TableGen/X86DisassemblerShared.h
+++ b/utils/TableGen/X86DisassemblerShared.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef X86DISASSEMBLERSHARED_H
-#define X86DISASSEMBLERSHARED_H
+#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H
+#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H
#include <string.h>
#include <string>
diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp
index fbcc6f2..d7e981c 100644
--- a/utils/TableGen/X86DisassemblerTables.cpp
+++ b/utils/TableGen/X86DisassemblerTables.cpp
@@ -171,12 +171,17 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_EVEX_OPSIZE:
return inheritsFrom(child, IC_EVEX_W_OPSIZE) ||
inheritsFrom(child, IC_EVEX_L_W_OPSIZE);
+ case IC_EVEX_B:
+ return false;
case IC_EVEX_W:
case IC_EVEX_W_XS:
case IC_EVEX_W_XD:
case IC_EVEX_W_OPSIZE:
return false;
case IC_EVEX_L:
+ case IC_EVEX_L_K_B:
+ case IC_EVEX_L_KZ_B:
+ case IC_EVEX_L_B:
case IC_EVEX_L_XS:
case IC_EVEX_L_XD:
case IC_EVEX_L_OPSIZE:
@@ -205,38 +210,59 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_EVEX_XD_K:
return inheritsFrom(child, IC_EVEX_W_XD_K) ||
inheritsFrom(child, IC_EVEX_L_W_XD_K);
+ case IC_EVEX_K_B:
+ case IC_EVEX_KZ:
+ return false;
+ case IC_EVEX_XS_KZ:
+ return inheritsFrom(child, IC_EVEX_W_XS_KZ) ||
+ inheritsFrom(child, IC_EVEX_L_W_XS_KZ);
+ case IC_EVEX_XD_KZ:
+ return inheritsFrom(child, IC_EVEX_W_XD_KZ) ||
+ inheritsFrom(child, IC_EVEX_L_W_XD_KZ);
+ case IC_EVEX_KZ_B:
case IC_EVEX_OPSIZE_K:
case IC_EVEX_OPSIZE_B:
+ case IC_EVEX_OPSIZE_K_B:
+ case IC_EVEX_OPSIZE_KZ:
+ case IC_EVEX_OPSIZE_KZ_B:
return false;
case IC_EVEX_W_K:
case IC_EVEX_W_XS_K:
case IC_EVEX_W_XD_K:
case IC_EVEX_W_OPSIZE_K:
case IC_EVEX_W_OPSIZE_B:
+ case IC_EVEX_W_OPSIZE_K_B:
return false;
case IC_EVEX_L_K:
case IC_EVEX_L_XS_K:
case IC_EVEX_L_XD_K:
case IC_EVEX_L_OPSIZE_K:
+ case IC_EVEX_L_OPSIZE_B:
+ case IC_EVEX_L_OPSIZE_K_B:
return false;
case IC_EVEX_W_KZ:
case IC_EVEX_W_XS_KZ:
case IC_EVEX_W_XD_KZ:
case IC_EVEX_W_OPSIZE_KZ:
+ case IC_EVEX_W_OPSIZE_KZ_B:
return false;
case IC_EVEX_L_KZ:
case IC_EVEX_L_XS_KZ:
case IC_EVEX_L_XD_KZ:
case IC_EVEX_L_OPSIZE_KZ:
+ case IC_EVEX_L_OPSIZE_KZ_B:
return false;
case IC_EVEX_L_W_K:
case IC_EVEX_L_W_XS_K:
case IC_EVEX_L_W_XD_K:
case IC_EVEX_L_W_OPSIZE_K:
+ case IC_EVEX_L_W_OPSIZE_B:
+ case IC_EVEX_L_W_OPSIZE_K_B:
case IC_EVEX_L_W_KZ:
case IC_EVEX_L_W_XS_KZ:
case IC_EVEX_L_W_XD_KZ:
case IC_EVEX_L_W_OPSIZE_KZ:
+ case IC_EVEX_L_W_OPSIZE_KZ_B:
return false;
case IC_EVEX_L2_K:
case IC_EVEX_L2_B:
diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h
index 1327375..d86b926 100644
--- a/utils/TableGen/X86DisassemblerTables.h
+++ b/utils/TableGen/X86DisassemblerTables.h
@@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef X86DISASSEMBLERTABLES_H
-#define X86DISASSEMBLERTABLES_H
+#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H
+#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H
#include "X86DisassemblerShared.h"
#include "X86ModRMFilters.h"
diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h
index fac3838..d919c58 100644
--- a/utils/TableGen/X86ModRMFilters.h
+++ b/utils/TableGen/X86ModRMFilters.h
@@ -15,8 +15,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef X86MODRMFILTERS_H
-#define X86MODRMFILTERS_H
+#ifndef LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H
+#define LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H
#include "llvm/Support/DataTypes.h"
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index ead419e..9b8092f 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -32,48 +32,50 @@ using namespace llvm;
MAP(C9, 38) \
MAP(CA, 39) \
MAP(CB, 40) \
- MAP(D0, 41) \
- MAP(D1, 42) \
- MAP(D4, 43) \
- MAP(D5, 44) \
- MAP(D6, 45) \
- MAP(D8, 46) \
- MAP(D9, 47) \
- MAP(DA, 48) \
- MAP(DB, 49) \
- MAP(DC, 50) \
- MAP(DD, 51) \
- MAP(DE, 52) \
- MAP(DF, 53) \
- MAP(E0, 54) \
- MAP(E1, 55) \
- MAP(E2, 56) \
- MAP(E3, 57) \
- MAP(E4, 58) \
- MAP(E5, 59) \
- MAP(E8, 60) \
- MAP(E9, 61) \
- MAP(EA, 62) \
- MAP(EB, 63) \
- MAP(EC, 64) \
- MAP(ED, 65) \
- MAP(EE, 66) \
- MAP(F0, 67) \
- MAP(F1, 68) \
- MAP(F2, 69) \
- MAP(F3, 70) \
- MAP(F4, 71) \
- MAP(F5, 72) \
- MAP(F6, 73) \
- MAP(F7, 74) \
- MAP(F8, 75) \
- MAP(F9, 76) \
- MAP(FA, 77) \
- MAP(FB, 78) \
- MAP(FC, 79) \
- MAP(FD, 80) \
- MAP(FE, 81) \
- MAP(FF, 82)
+ MAP(CF, 41) \
+ MAP(D0, 42) \
+ MAP(D1, 43) \
+ MAP(D4, 44) \
+ MAP(D5, 45) \
+ MAP(D6, 46) \
+ MAP(D7, 47) \
+ MAP(D8, 48) \
+ MAP(D9, 49) \
+ MAP(DA, 50) \
+ MAP(DB, 51) \
+ MAP(DC, 52) \
+ MAP(DD, 53) \
+ MAP(DE, 54) \
+ MAP(DF, 55) \
+ MAP(E0, 56) \
+ MAP(E1, 57) \
+ MAP(E2, 58) \
+ MAP(E3, 59) \
+ MAP(E4, 60) \
+ MAP(E5, 61) \
+ MAP(E8, 62) \
+ MAP(E9, 63) \
+ MAP(EA, 64) \
+ MAP(EB, 65) \
+ MAP(EC, 66) \
+ MAP(ED, 67) \
+ MAP(EE, 68) \
+ MAP(F0, 69) \
+ MAP(F1, 70) \
+ MAP(F2, 71) \
+ MAP(F3, 72) \
+ MAP(F4, 73) \
+ MAP(F5, 74) \
+ MAP(F6, 75) \
+ MAP(F7, 76) \
+ MAP(F8, 77) \
+ MAP(F9, 78) \
+ MAP(FA, 79) \
+ MAP(FB, 80) \
+ MAP(FC, 81) \
+ MAP(FD, 82) \
+ MAP(FE, 83) \
+ MAP(FF, 84)
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
@@ -205,6 +207,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
+ CD8_Scale = byteFromRec(Rec, "CD8_Scale");
Name = Rec->getName();
AsmString = Rec->getValueAsString("AsmString");
@@ -441,6 +444,16 @@ InstructionContext RecognizableInstr::insnContext() const {
return insnContext;
}
+void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) {
+ // The scaling factor for AVX512 compressed displacement encoding is an
+ // instruction attribute. Adjust the ModRM encoding type to include the
+ // scale for compressed displacement.
+ if (encoding != ENCODING_RM || CD8_Scale == 0)
+ return;
+ encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale));
+ assert(encoding <= ENCODING_RM_CD64 && "Invalid CDisp scaling");
+}
+
void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
unsigned &physicalOperandIndex,
unsigned &numPhysicalOperands,
@@ -464,8 +477,10 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
const std::string &typeName = (*Operands)[operandIndex].Rec->getName();
- Spec->operands[operandIndex].encoding = encodingFromString(typeName,
- OpSize);
+ OperandEncoding encoding = encodingFromString(typeName, OpSize);
+ // Adjust the encoding type for an operand based on the instruction.
+ adjustOperandEncoding(encoding);
+ Spec->operands[operandIndex].encoding = encoding;
Spec->operands[operandIndex].type = typeFromString(typeName,
HasREX_WPrefix, OpSize);
@@ -526,6 +541,14 @@ void RecognizableInstr::emitInstructionSpecifier() {
// physicalOperandIndex should always be < numPhysicalOperands
unsigned physicalOperandIndex = 0;
+ // Given the set of prefix bits, how many additional operands does the
+ // instruction have?
+ unsigned additionalOperands = 0;
+ if (HasVEX_4V || HasVEX_4VOp3)
+ ++additionalOperands;
+ if (HasEVEX_K)
+ ++additionalOperands;
+
switch (Form) {
default: llvm_unreachable("Unhandled form");
case X86Local::RawFrmSrc:
@@ -560,17 +583,17 @@ void RecognizableInstr::emitInstructionSpecifier() {
break;
case X86Local::MRMDestReg:
// Operand 1 is a register operand in the R/M field.
+ // - In AVX512 there may be a mask operand here -
// Operand 2 is a register operand in the Reg/Opcode field.
// - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- if (HasVEX_4V)
- assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
- "Unexpected number of operands for MRMDestRegFrm with VEX_4V");
- else
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestRegFrm");
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 3 + additionalOperands &&
+ "Unexpected number of operands for MRMDestRegFrm");
HANDLE_OPERAND(rmRegister)
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
if (HasVEX_4V)
// FIXME: In AVX, the register below becomes the one encoded
@@ -585,12 +608,10 @@ void RecognizableInstr::emitInstructionSpecifier() {
// Operand 2 is a register operand in the Reg/Opcode field.
// - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- if (HasVEX_4V)
- assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
- "Unexpected number of operands for MRMDestMemFrm with VEX_4V");
- else
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestMemFrm");
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 3 + additionalOperands &&
+ "Unexpected number of operands for MRMDestMemFrm with VEX_4V");
+
HANDLE_OPERAND(memory)
if (HasEVEX_K)
@@ -611,12 +632,9 @@ void RecognizableInstr::emitInstructionSpecifier() {
// Operand 3 (optional) is an immediate.
// Operand 4 (optional) is an immediate.
- if (HasVEX_4V || HasVEX_4VOp3)
- assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 &&
- "Unexpected number of operands for MRMSrcRegFrm with VEX_4V");
- else
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 4 &&
- "Unexpected number of operands for MRMSrcRegFrm");
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 4 + additionalOperands &&
+ "Unexpected number of operands for MRMSrcRegFrm");
HANDLE_OPERAND(roRegister)
@@ -647,12 +665,9 @@ void RecognizableInstr::emitInstructionSpecifier() {
// - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- if (HasVEX_4V || HasVEX_4VOp3)
- assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 &&
- "Unexpected number of operands for MRMSrcMemFrm with VEX_4V");
- else
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMSrcMemFrm");
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 4 + additionalOperands &&
+ "Unexpected number of operands for MRMSrcMemFrm");
HANDLE_OPERAND(roRegister)
@@ -685,15 +700,13 @@ void RecognizableInstr::emitInstructionSpecifier() {
case X86Local::MRM5r:
case X86Local::MRM6r:
case X86Local::MRM7r:
- {
- // Operand 1 is a register operand in the R/M field.
- // Operand 2 (optional) is an immediate or relocation.
- // Operand 3 (optional) is an immediate.
- unsigned kOp = (HasEVEX_K) ? 1:0;
- unsigned Op4v = (HasVEX_4V) ? 1:0;
- if (numPhysicalOperands > 3 + kOp + Op4v)
- llvm_unreachable("Unexpected number of operands for MRMnr");
- }
+ // Operand 1 is a register operand in the R/M field.
+ // Operand 2 (optional) is an immediate or relocation.
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 0 + additionalOperands &&
+ numPhysicalOperands <= 3 + additionalOperands &&
+ "Unexpected number of operands for MRMnr");
+
if (HasVEX_4V)
HANDLE_OPERAND(vvvvRegister)
@@ -712,15 +725,12 @@ void RecognizableInstr::emitInstructionSpecifier() {
case X86Local::MRM5m:
case X86Local::MRM6m:
case X86Local::MRM7m:
- {
- // Operand 1 is a memory operand (possibly SIB-extended)
- // Operand 2 (optional) is an immediate or relocation.
- unsigned kOp = (HasEVEX_K) ? 1:0;
- unsigned Op4v = (HasVEX_4V) ? 1:0;
- if (numPhysicalOperands < 1 + kOp + Op4v ||
- numPhysicalOperands > 2 + kOp + Op4v)
- llvm_unreachable("Unexpected number of operands for MRMnm");
- }
+ // Operand 1 is a memory operand (possibly SIB-extended)
+ // Operand 2 (optional) is an immediate or relocation.
+ assert(numPhysicalOperands >= 1 + additionalOperands &&
+ numPhysicalOperands <= 2 + additionalOperands &&
+ "Unexpected number of operands for MRMnm");
+
if (HasVEX_4V)
HANDLE_OPERAND(vvvvRegister)
if (HasEVEX_K)
@@ -756,20 +766,21 @@ void RecognizableInstr::emitInstructionSpecifier() {
case X86Local::MRM_C0: case X86Local::MRM_C1: case X86Local::MRM_C2:
case X86Local::MRM_C3: case X86Local::MRM_C4: case X86Local::MRM_C8:
case X86Local::MRM_C9: case X86Local::MRM_CA: case X86Local::MRM_CB:
- case X86Local::MRM_D0: case X86Local::MRM_D1: case X86Local::MRM_D4:
- case X86Local::MRM_D5: case X86Local::MRM_D6: case X86Local::MRM_D8:
- case X86Local::MRM_D9: case X86Local::MRM_DA: case X86Local::MRM_DB:
- case X86Local::MRM_DC: case X86Local::MRM_DD: case X86Local::MRM_DE:
- case X86Local::MRM_DF: case X86Local::MRM_E0: case X86Local::MRM_E1:
- case X86Local::MRM_E2: case X86Local::MRM_E3: case X86Local::MRM_E4:
- case X86Local::MRM_E5: case X86Local::MRM_E8: case X86Local::MRM_E9:
- case X86Local::MRM_EA: case X86Local::MRM_EB: case X86Local::MRM_EC:
- case X86Local::MRM_ED: case X86Local::MRM_EE: case X86Local::MRM_F0:
- case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3:
- case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6:
- case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA:
- case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD:
- case X86Local::MRM_FE: case X86Local::MRM_FF:
+ case X86Local::MRM_CF: case X86Local::MRM_D0: case X86Local::MRM_D1:
+ case X86Local::MRM_D4: case X86Local::MRM_D5: case X86Local::MRM_D6:
+ case X86Local::MRM_D7: case X86Local::MRM_D8: case X86Local::MRM_D9:
+ case X86Local::MRM_DA: case X86Local::MRM_DB: case X86Local::MRM_DC:
+ case X86Local::MRM_DD: case X86Local::MRM_DE: case X86Local::MRM_DF:
+ case X86Local::MRM_E0: case X86Local::MRM_E1: case X86Local::MRM_E2:
+ case X86Local::MRM_E3: case X86Local::MRM_E4: case X86Local::MRM_E5:
+ case X86Local::MRM_E8: case X86Local::MRM_E9: case X86Local::MRM_EA:
+ case X86Local::MRM_EB: case X86Local::MRM_EC: case X86Local::MRM_ED:
+ case X86Local::MRM_EE: case X86Local::MRM_F0: case X86Local::MRM_F1:
+ case X86Local::MRM_F2: case X86Local::MRM_F3: case X86Local::MRM_F4:
+ case X86Local::MRM_F5: case X86Local::MRM_F6: case X86Local::MRM_F7:
+ case X86Local::MRM_F9: case X86Local::MRM_FA: case X86Local::MRM_FB:
+ case X86Local::MRM_FC: case X86Local::MRM_FD: case X86Local::MRM_FE:
+ case X86Local::MRM_FF:
// Ignored.
break;
}
@@ -896,7 +907,6 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i32mem", TYPE_Mv)
TYPE("i32imm", TYPE_IMMv)
TYPE("i32i8imm", TYPE_IMM32)
- TYPE("u32u8imm", TYPE_IMM32)
TYPE("GR32", TYPE_R32)
TYPE("GR32orGR64", TYPE_R32)
TYPE("i64mem", TYPE_Mv)
@@ -962,10 +972,18 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("VR512", TYPE_XMM512)
TYPE("VK1", TYPE_VK1)
TYPE("VK1WM", TYPE_VK1)
+ TYPE("VK2", TYPE_VK2)
+ TYPE("VK2WM", TYPE_VK2)
+ TYPE("VK4", TYPE_VK4)
+ TYPE("VK4WM", TYPE_VK4)
TYPE("VK8", TYPE_VK8)
TYPE("VK8WM", TYPE_VK8)
TYPE("VK16", TYPE_VK16)
TYPE("VK16WM", TYPE_VK16)
+ TYPE("VK32", TYPE_VK32)
+ TYPE("VK32WM", TYPE_VK32)
+ TYPE("VK64", TYPE_VK64)
+ TYPE("VK64WM", TYPE_VK64)
TYPE("GR16_NOAX", TYPE_Rv)
TYPE("GR32_NOAX", TYPE_Rv)
TYPE("GR64_NOAX", TYPE_R64)
@@ -991,7 +1009,6 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
ENCODING("i16imm", ENCODING_IW)
}
ENCODING("i32i8imm", ENCODING_IB)
- ENCODING("u32u8imm", ENCODING_IB)
ENCODING("SSECC", ENCODING_IB)
ENCODING("AVXCC", ENCODING_IB)
ENCODING("AVX512RC", ENCODING_IB)
@@ -1038,6 +1055,8 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
ENCODING("VK1", ENCODING_RM)
ENCODING("VK8", ENCODING_RM)
ENCODING("VK16", ENCODING_RM)
+ ENCODING("VK32", ENCODING_RM)
+ ENCODING("VK64", ENCODING_RM)
errs() << "Unhandled R/M register encoding " << s << "\n";
llvm_unreachable("Unhandled R/M register encoding");
}
@@ -1064,8 +1083,12 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s,
ENCODING("FR32X", ENCODING_REG)
ENCODING("VR512", ENCODING_REG)
ENCODING("VK1", ENCODING_REG)
+ ENCODING("VK2", ENCODING_REG)
+ ENCODING("VK4", ENCODING_REG)
ENCODING("VK8", ENCODING_REG)
ENCODING("VK16", ENCODING_REG)
+ ENCODING("VK32", ENCODING_REG)
+ ENCODING("VK64", ENCODING_REG)
ENCODING("VK1WM", ENCODING_REG)
ENCODING("VK8WM", ENCODING_REG)
ENCODING("VK16WM", ENCODING_REG)
@@ -1088,8 +1111,12 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s,
ENCODING("VR256X", ENCODING_VVVV)
ENCODING("VR512", ENCODING_VVVV)
ENCODING("VK1", ENCODING_VVVV)
+ ENCODING("VK2", ENCODING_VVVV)
+ ENCODING("VK4", ENCODING_VVVV)
ENCODING("VK8", ENCODING_VVVV)
ENCODING("VK16", ENCODING_VVVV)
+ ENCODING("VK32", ENCODING_VVVV)
+ ENCODING("VK64", ENCODING_VVVV)
errs() << "Unhandled VEX.vvvv register encoding " << s << "\n";
llvm_unreachable("Unhandled VEX.vvvv register encoding");
}
@@ -1098,8 +1125,12 @@ OperandEncoding
RecognizableInstr::writemaskRegisterEncodingFromString(const std::string &s,
uint8_t OpSize) {
ENCODING("VK1WM", ENCODING_WRITEMASK)
+ ENCODING("VK2WM", ENCODING_WRITEMASK)
+ ENCODING("VK4WM", ENCODING_WRITEMASK)
ENCODING("VK8WM", ENCODING_WRITEMASK)
ENCODING("VK16WM", ENCODING_WRITEMASK)
+ ENCODING("VK32WM", ENCODING_WRITEMASK)
+ ENCODING("VK64WM", ENCODING_WRITEMASK)
errs() << "Unhandled mask register encoding " << s << "\n";
llvm_unreachable("Unhandled mask register encoding");
}
diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h
index 77286bc..95d7a40 100644
--- a/utils/TableGen/X86RecognizableInstr.h
+++ b/utils/TableGen/X86RecognizableInstr.h
@@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef X86RECOGNIZABLEINSTR_H
-#define X86RECOGNIZABLEINSTR_H
+#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H
+#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H
#include "CodeGenTarget.h"
#include "X86DisassemblerTables.h"
@@ -78,6 +78,8 @@ private:
bool IsCodeGenOnly;
/// The ForceDisassemble field from the record
bool ForceDisassemble;
+ // The CD8_Scale field from the record
+ uint8_t CD8_Scale;
// Whether the instruction has the predicate "In64BitMode"
bool Is64Bit;
// Whether the instruction has the predicate "In32BitMode"
@@ -153,6 +155,9 @@ private:
static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s,
uint8_t OpSize);
+ /// \brief Adjust the encoding type for an operand based on the instruction.
+ void adjustOperandEncoding(OperandEncoding &encoding);
+
/// handleOperand - Converts a single operand from the LLVM table format to
/// the emitted table format, handling any duplicate operands it encounters
/// and then one non-duplicate.