aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp41
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp2
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp43
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp1
-rw-r--r--utils/TableGen/CodeGenInstruction.h1
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp138
-rw-r--r--utils/TableGen/CodeGenRegisters.h12
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp151
-rw-r--r--utils/TableGen/CodeGenSchedule.h172
-rw-r--r--utils/TableGen/CodeGenTarget.cpp18
-rw-r--r--utils/TableGen/CodeGenTarget.h8
-rw-r--r--utils/TableGen/DAGISelMatcher.h2
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp4
-rw-r--r--utils/TableGen/EDEmitter.cpp7
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp1036
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp33
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp173
-rw-r--r--utils/TableGen/StringToOffsetTable.h1
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp380
-rw-r--r--utils/TableGen/X86DisassemblerShared.h1
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp237
-rw-r--r--utils/TableGen/X86DisassemblerTables.h50
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp237
-rw-r--r--utils/TableGen/X86RecognizableInstr.h2
25 files changed, 1717 insertions, 1034 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index f5e094e486..abcec8fe94 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -1829,22 +1829,6 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
<< " MCTargetAsmParser::Match_Success :\n"
<< " MCTargetAsmParser::Match_InvalidOperand;\n\n";
- // Check for register operands, including sub-classes.
- OS << " if (Operand.isReg()) {\n";
- OS << " MatchClassKind OpKind;\n";
- OS << " switch (Operand.getReg()) {\n";
- OS << " default: OpKind = InvalidMatchClass; break;\n";
- for (std::map<Record*, ClassInfo*>::iterator
- it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
- it != ie; ++it)
- OS << " case " << Info.Target.getName() << "::"
- << it->first->getName() << ": OpKind = " << it->second->Name
- << "; break;\n";
- OS << " }\n";
- OS << " return isSubclass(OpKind, Kind) ? "
- << "MCTargetAsmParser::Match_Success :\n "
- << " MCTargetAsmParser::Match_InvalidOperand;\n }\n\n";
-
// Check the user classes. We don't care what order since we're only
// actually matching against one of them.
for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
@@ -1864,6 +1848,22 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
OS << " }\n\n";
}
+ // Check for register operands, including sub-classes.
+ OS << " if (Operand.isReg()) {\n";
+ OS << " MatchClassKind OpKind;\n";
+ OS << " switch (Operand.getReg()) {\n";
+ OS << " default: OpKind = InvalidMatchClass; break;\n";
+ for (std::map<Record*, ClassInfo*>::iterator
+ it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
+ it != ie; ++it)
+ OS << " case " << Info.Target.getName() << "::"
+ << it->first->getName() << ": OpKind = " << it->second->Name
+ << "; break;\n";
+ OS << " }\n";
+ OS << " return isSubclass(OpKind, Kind) ? "
+ << "MCTargetAsmParser::Match_Success :\n "
+ << " MCTargetAsmParser::Match_InvalidOperand;\n }\n\n";
+
// Generic fallthrough match failure case for operands that don't have
// specialized diagnostic types.
OS << " return MCTargetAsmParser::Match_InvalidOperand;\n";
@@ -2447,7 +2447,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
emitSubtargetFeatureFlagEnumeration(Info, OS);
// Emit the function to match a register name to number.
- emitMatchRegisterName(Target, AsmParser, OS);
+ // This should be omitted for Mips target
+ if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName"))
+ emitMatchRegisterName(Target, AsmParser, OS);
OS << "#endif // GET_REGISTER_MATCHER\n\n";
@@ -2649,6 +2651,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n";
OS << " if (i + 1 >= Operands.size()) {\n";
OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n";
+ OS << " if (!OperandsValid) ErrorInfo = i + 1;\n";
OS << " break;\n";
OS << " }\n";
OS << " unsigned Diag = validateOperandClass(Operands[i+1],\n";
@@ -2715,8 +2718,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
OS << " // Okay, we had no match. Try to return a useful error code.\n";
- OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)";
- OS << " return RetCode;\n";
+ OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n";
+ OS << " return RetCode;\n\n";
OS << " // Missing feature matches return which features were missing\n";
OS << " ErrorInfo = MissingFeatures;\n";
OS << " return Match_MissingFeature;\n";
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index bd153a855c..57979b3e6d 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -14,8 +14,8 @@
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "StringToOffsetTable.h"
#include "SequenceToOffsetTable.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index c5585f5eaa..0e14cbae38 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -11,6 +11,7 @@ add_tablegen(llvm-tblgen LLVM
CodeGenDAGPatterns.cpp
CodeGenInstruction.cpp
CodeGenRegisters.cpp
+ CodeGenSchedule.cpp
CodeGenTarget.cpp
DAGISelEmitter.cpp
DAGISelMatcherEmitter.cpp
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index d4b02fbd2f..34f8a34e7a 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -2520,6 +2520,37 @@ static void InferFromPattern(const CodeGenInstruction &Inst,
IsVariadic = true; // Can warn if we want.
}
+/// hasNullFragReference - Return true if the DAG has any reference to the
+/// null_frag operator.
+static bool hasNullFragReference(DagInit *DI) {
+ DefInit *OpDef = dynamic_cast<DefInit*>(DI->getOperator());
+ if (!OpDef) return false;
+ Record *Operator = OpDef->getDef();
+
+ // If this is the null fragment, return true.
+ if (Operator->getName() == "null_frag") return true;
+ // If any of the arguments reference the null fragment, return true.
+ for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
+ DagInit *Arg = dynamic_cast<DagInit*>(DI->getArg(i));
+ if (Arg && hasNullFragReference(Arg))
+ return true;
+ }
+
+ return false;
+}
+
+/// hasNullFragReference - Return true if any DAG in the list references
+/// the null_frag operator.
+static bool hasNullFragReference(ListInit *LI) {
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i) {
+ DagInit *DI = dynamic_cast<DagInit*>(LI->getElement(i));
+ assert(DI && "non-dag in an instruction Pattern list?!");
+ if (hasNullFragReference(DI))
+ return true;
+ }
+ return false;
+}
+
/// ParseInstructions - Parse all of the instructions, inlining and resolving
/// any fragments involved. This populates the Instructions list with fully
/// resolved instructions.
@@ -2534,8 +2565,11 @@ void CodeGenDAGPatterns::ParseInstructions() {
// If there is no pattern, only collect minimal information about the
// instruction for its operand list. We have to assume that there is one
- // result, as we have no detailed info.
- if (!LI || LI->getSize() == 0) {
+ // result, as we have no detailed info. A pattern which references the
+ // null_frag operator is as-if no pattern were specified. Normally this
+ // is from a multiclass expansion w/ a SDPatternOperator passed in as
+ // null_frag.
+ if (!LI || LI->getSize() == 0 || hasNullFragReference(LI)) {
std::vector<Record*> Results;
std::vector<Record*> Operands;
@@ -2874,6 +2908,11 @@ void CodeGenDAGPatterns::ParsePatterns() {
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
Record *CurPattern = Patterns[i];
DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch");
+
+ // If the pattern references the null_frag, there's nothing to do.
+ if (hasNullFragReference(Tree))
+ continue;
+
TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this);
// Inline pattern fragments into it.
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 33381e9569..12e153a665 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -297,6 +297,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) {
isCompare = R->getValueAsBit("isCompare");
isMoveImm = R->getValueAsBit("isMoveImm");
isBitcast = R->getValueAsBit("isBitcast");
+ isSelect = R->getValueAsBit("isSelect");
isBarrier = R->getValueAsBit("isBarrier");
isCall = R->getValueAsBit("isCall");
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 3ba9f24daa..95b572d2d0 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -222,6 +222,7 @@ namespace llvm {
bool isCompare;
bool isMoveImm;
bool isBitcast;
+ bool isSelect;
bool isBarrier;
bool isCall;
bool canFoldAsLoad;
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 81bf9edad6..011f4b7938 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -28,19 +28,15 @@ using namespace llvm;
//===----------------------------------------------------------------------===//
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
- : TheDef(R),
- EnumValue(Enum)
-{}
-
-std::string CodeGenSubRegIndex::getNamespace() const {
- if (TheDef->getValue("Namespace"))
- return TheDef->getValueAsString("Namespace");
- else
- return "";
+ : TheDef(R), EnumValue(Enum) {
+ Name = R->getName();
+ if (R->getValue("Namespace"))
+ Namespace = R->getValueAsString("Namespace");
}
-const std::string &CodeGenSubRegIndex::getName() const {
- return TheDef->getName();
+CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
+ unsigned Enum)
+ : TheDef(0), Name(N), Namespace(Nspace), EnumValue(Enum) {
}
std::string CodeGenSubRegIndex::getQualifiedName() const {
@@ -52,16 +48,31 @@ std::string CodeGenSubRegIndex::getQualifiedName() const {
}
void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
- std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf");
- if (Comps.empty())
+ if (!TheDef)
return;
- if (Comps.size() != 2)
- throw TGError(TheDef->getLoc(), "ComposedOf must have exactly two entries");
- CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
- CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
- CodeGenSubRegIndex *X = A->addComposite(B, this);
- if (X)
- throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
+
+ std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf");
+ if (!Comps.empty()) {
+ if (Comps.size() != 2)
+ throw TGError(TheDef->getLoc(), "ComposedOf must have exactly two entries");
+ CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
+ CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
+ CodeGenSubRegIndex *X = A->addComposite(B, this);
+ if (X)
+ throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
+ }
+
+ std::vector<Record*> Parts =
+ TheDef->getValueAsListOfDefs("CoveringSubRegIndices");
+ if (!Parts.empty()) {
+ if (Parts.size() < 2)
+ throw TGError(TheDef->getLoc(),
+ "CoveredBySubRegs must have two or more entries");
+ SmallVector<CodeGenSubRegIndex*, 8> IdxParts;
+ for (unsigned i = 0, e = Parts.size(); i != e; ++i)
+ IdxParts.push_back(RegBank.getSubRegIdx(Parts[i]));
+ RegBank.addConcatSubRegIndex(IdxParts, this);
+ }
}
void CodeGenSubRegIndex::cleanComposites() {
@@ -187,10 +198,7 @@ bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) {
unsigned OldNumUnits = RegUnits.size();
for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
I != E; ++I) {
- // Strangely a register may have itself as a subreg (self-cycle) e.g. XMM.
CodeGenRegister *SR = I->second;
- if (SR == this)
- continue;
// Merge the subregister's units into this register's RegUnits.
mergeRegUnits(RegUnits, SR->RegUnits);
}
@@ -260,44 +268,6 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
}
}
- // Process the composites.
- ListInit *Comps = TheDef->getValueAsListInit("CompositeIndices");
- for (unsigned i = 0, e = Comps->size(); i != e; ++i) {
- DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i));
- if (!Pat)
- throw TGError(TheDef->getLoc(), "Invalid dag '" +
- Comps->getElement(i)->getAsString() +
- "' in CompositeIndices");
- DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator());
- if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex"))
- throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " +
- Pat->getAsString());
- CodeGenSubRegIndex *BaseIdx = RegBank.getSubRegIdx(BaseIdxInit->getDef());
-
- // Resolve list of subreg indices into R2.
- CodeGenRegister *R2 = this;
- for (DagInit::const_arg_iterator di = Pat->arg_begin(),
- de = Pat->arg_end(); di != de; ++di) {
- DefInit *IdxInit = dynamic_cast<DefInit*>(*di);
- if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex"))
- throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " +
- Pat->getAsString());
- CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(IdxInit->getDef());
- const SubRegMap &R2Subs = R2->computeSubRegs(RegBank);
- SubRegMap::const_iterator ni = R2Subs.find(Idx);
- if (ni == R2Subs.end())
- throw TGError(TheDef->getLoc(), "Composite " + Pat->getAsString() +
- " refers to bad index in " + R2->getName());
- R2 = ni->second;
- }
-
- // Insert composite index. Allow overriding inherited indices etc.
- SubRegs[BaseIdx] = R2;
-
- // R2 is no longer an orphan.
- Orphans.erase(R2);
- }
-
// Now Orphans contains the inherited subregisters without a direct index.
// Create inferred indexes for all missing entries.
// Work backwards in the Indices vector in order to compose subregs bottom-up.
@@ -327,14 +297,25 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
// Compute the inverse SubReg -> Idx map.
for (SubRegMap::const_iterator SI = SubRegs.begin(), SE = SubRegs.end();
SI != SE; ++SI) {
- // Ignore idempotent sub-register indices.
- if (SI->second == this)
+ if (SI->second == this) {
+ SMLoc Loc;
+ if (TheDef)
+ Loc = TheDef->getLoc();
+ throw TGError(Loc, "Register " + getName() +
+ " has itself as a sub-register");
+ }
+ // Ensure that every sub-register has a unique name.
+ DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*>::iterator Ins =
+ SubReg2Idx.insert(std::make_pair(SI->second, SI->first)).first;
+ if (Ins->second == SI->first)
continue;
- // Is is possible to have multiple names for the same sub-register.
- // For example, XMM0 appears as sub_xmm, sub_sd, and sub_ss in YMM0.
- // Eventually, this degeneration should go away, but for now we simply give
- // precedence to the explicit sub-register index over the inherited ones.
- SubReg2Idx.insert(std::make_pair(SI->second, SI->first));
+ // Trouble: Two different names for SI->second.
+ SMLoc Loc;
+ if (TheDef)
+ Loc = TheDef->getLoc();
+ throw TGError(Loc, "Sub-register can't have two names: " +
+ SI->second->getName() + " available as " +
+ SI->first->getName() + " and " + Ins->second->getName());
}
// Derive possible names for sub-register concatenations from any explicit
@@ -508,8 +489,6 @@ void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
Id.push_back(I->first->EnumValue);
Id.push_back(I->second->TopoSig);
- if (I->second == this)
- continue;
// Don't add duplicate entries.
if (!I->second->SuperRegs.empty() && I->second->SuperRegs.back() == this)
continue;
@@ -530,8 +509,7 @@ CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
// Add any secondary sub-registers that weren't part of the explicit tree.
for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
I != E; ++I)
- if (I->second != this)
- OSet.insert(I->second);
+ OSet.insert(I->second);
}
// Compute overlapping registers.
@@ -970,7 +948,7 @@ void CodeGenRegisterClass::buildRegUnitSet(
// CodeGenRegBank
//===----------------------------------------------------------------------===//
-CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) {
+CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
// Configure register Sets to understand register classes and tuples.
Sets.addFieldExpander("RegisterClass", "MemberList");
Sets.addFieldExpander("CalleeSavedRegs", "SaveList");
@@ -980,7 +958,6 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) {
// More indices will be synthesized later.
std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex");
std::sort(SRIs.begin(), SRIs.end(), LessRecord());
- NumNamedIndices = SRIs.size();
for (unsigned i = 0, e = SRIs.size(); i != e; ++i)
getSubRegIdx(SRIs[i]);
// Build composite maps from ComposedOf fields.
@@ -1048,6 +1025,15 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) {
CodeGenRegisterClass::computeSubClasses(*this);
}
+// Create a synthetic CodeGenSubRegIndex without a corresponding Record.
+CodeGenSubRegIndex*
+CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) {
+ CodeGenSubRegIndex *Idx = new CodeGenSubRegIndex(Name, Namespace,
+ SubRegIndices.size() + 1);
+ SubRegIndices.push_back(Idx);
+ return Idx;
+}
+
CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
if (Idx)
@@ -1112,7 +1098,7 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
// None exists, synthesize one.
std::string Name = A->getName() + "_then_" + B->getName();
- Comp = getSubRegIdx(new Record(Name, SMLoc(), Records));
+ Comp = createSubRegIndex(Name, A->getNamespace());
A->addComposite(B, Comp);
return Comp;
}
@@ -1132,7 +1118,7 @@ getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex*, 8> &Parts) {
Name += '_';
Name += Parts[i]->getName();
}
- return Idx = getSubRegIdx(new Record(Name, SMLoc(), Records));
+ return Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
}
void CodeGenRegBank::computeComposites() {
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index eb6724ea1a..827063e470 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -35,14 +35,17 @@ namespace llvm {
/// CodeGenSubRegIndex - Represents a sub-register index.
class CodeGenSubRegIndex {
Record *const TheDef;
+ std::string Name;
+ std::string Namespace;
public:
const unsigned EnumValue;
CodeGenSubRegIndex(Record *R, unsigned Enum);
+ CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
- const std::string &getName() const;
- std::string getNamespace() const;
+ const std::string &getName() const { return Name; }
+ const std::string &getNamespace() const { return Namespace; }
std::string getQualifiedName() const;
// Order CodeGenSubRegIndex pointers by EnumValue.
@@ -422,13 +425,13 @@ namespace llvm {
// CodeGenRegBank - Represent a target's registers and the relations between
// them.
class CodeGenRegBank {
- RecordKeeper &Records;
SetTheory Sets;
// SubRegIndices.
std::vector<CodeGenSubRegIndex*> SubRegIndices;
DenseMap<Record*, CodeGenSubRegIndex*> Def2SubRegIdx;
- unsigned NumNamedIndices;
+
+ CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace);
typedef std::map<SmallVector<CodeGenSubRegIndex*, 8>,
CodeGenSubRegIndex*> ConcatIdxMap;
@@ -495,7 +498,6 @@ namespace llvm {
// in the .td files. The rest are synthesized such that all sub-registers
// have a unique name.
ArrayRef<CodeGenSubRegIndex*> getSubRegIndices() { return SubRegIndices; }
- unsigned getNumNamedIndices() { return NumNamedIndices; }
// Find a SubRegIndex form its Record def.
CodeGenSubRegIndex *getSubRegIdx(Record*);
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
new file mode 100644
index 0000000000..f57fd182ea
--- /dev/null
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -0,0 +1,151 @@
+//===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate the machine model as decribed in
+// the target description.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "subtarget-emitter"
+
+#include "CodeGenSchedule.h"
+#include "CodeGenTarget.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+// CodeGenModels ctor interprets machine model records and populates maps.
+CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
+ const CodeGenTarget &TGT):
+ Records(RK), Target(TGT), NumItineraryClasses(0), HasProcItineraries(false) {
+
+ // Populate SchedClassIdxMap and set NumItineraryClasses.
+ CollectSchedClasses();
+
+ // Populate ProcModelMap.
+ CollectProcModels();
+}
+
+// Visit all the instruction definitions for this target to gather and enumerate
+// the itinerary classes. These are the explicitly specified SchedClasses. More
+// SchedClasses may be inferred.
+void CodeGenSchedModels::CollectSchedClasses() {
+
+ // NoItinerary is always the first class at Index=0
+ SchedClasses.resize(1);
+ SchedClasses.back().Name = "NoItinerary";
+ SchedClassIdxMap[SchedClasses.back().Name] = 0;
+
+ // Gather and sort all itinerary classes used by instruction descriptions.
+ std::vector<Record*> ItinClassList;
+ for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
+ E = Target.inst_end(); I != E; ++I) {
+ Record *SchedDef = (*I)->TheDef->getValueAsDef("Itinerary");
+ // Map a new SchedClass with no index.
+ if (!SchedClassIdxMap.count(SchedDef->getName())) {
+ SchedClassIdxMap[SchedDef->getName()] = 0;
+ ItinClassList.push_back(SchedDef);
+ }
+ }
+ // Assign each itinerary class unique number, skipping NoItinerary==0
+ NumItineraryClasses = ItinClassList.size();
+ std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
+ for (unsigned i = 0, N = NumItineraryClasses; i < N; i++) {
+ Record *ItinDef = ItinClassList[i];
+ SchedClassIdxMap[ItinDef->getName()] = SchedClasses.size();
+ SchedClasses.push_back(CodeGenSchedClass(ItinDef));
+ }
+
+ // TODO: Infer classes from non-itinerary scheduler resources.
+}
+
+// Gather all processor models.
+void CodeGenSchedModels::CollectProcModels() {
+ std::vector<Record*> ProcRecords =
+ Records.getAllDerivedDefinitions("Processor");
+ std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName());
+
+ // Reserve space because we can. Reallocation would be ok.
+ ProcModels.reserve(ProcRecords.size());
+
+ // For each processor, find a unique machine model.
+ for (unsigned i = 0, N = ProcRecords.size(); i < N; ++i)
+ addProcModel(ProcRecords[i]);
+}
+
+// Get a unique processor model based on the defined MachineModel and
+// ProcessorItineraries.
+void CodeGenSchedModels::addProcModel(Record *ProcDef) {
+ unsigned Idx = getProcModelIdx(ProcDef);
+ if (Idx < ProcModels.size())
+ return;
+
+ Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
+ Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
+
+ std::string ModelName = ModelDef->getName();
+ const std::string &ItinName = ItinsDef->getName();
+
+ bool NoModel = ModelDef->getValueAsBit("NoModel");
+ bool hasTopLevelItin = !ItinsDef->getValueAsListOfDefs("IID").empty();
+ if (NoModel) {
+ // If an itinerary is defined without a machine model, infer a new model.
+ if (NoModel && hasTopLevelItin) {
+ ModelName = ItinName + "Model";
+ ModelDef = NULL;
+ }
+ }
+ else {
+ // If a machine model is defined, the itinerary must be defined within it
+ // rather than in the Processor definition itself.
+ assert(!hasTopLevelItin && "Itinerary must be defined in SchedModel");
+ ItinsDef = ModelDef->getValueAsDef("Itineraries");
+ }
+
+ ProcModelMap[getProcModelKey(ProcDef)]= ProcModels.size();
+
+ ProcModels.push_back(CodeGenProcModel(ModelName, ModelDef, ItinsDef));
+
+ std::vector<Record*> ItinRecords = ItinsDef->getValueAsListOfDefs("IID");
+ CollectProcItin(ProcModels.back(), ItinRecords);
+}
+
+// Gather the processor itineraries.
+void CodeGenSchedModels::CollectProcItin(CodeGenProcModel &ProcModel,
+ std::vector<Record*> ItinRecords) {
+ // Skip empty itinerary.
+ if (ItinRecords.empty())
+ return;
+
+ HasProcItineraries = true;
+
+ ProcModel.ItinDefList.resize(NumItineraryClasses+1);
+
+ // Insert each itinerary data record in the correct position within
+ // the processor model's ItinDefList.
+ for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) {
+ Record *ItinData = ItinRecords[i];
+ Record *ItinDef = ItinData->getValueAsDef("TheClass");
+ if (!SchedClassIdxMap.count(ItinDef->getName())) {
+ DEBUG(dbgs() << ProcModel.ItinsDef->getName()
+ << " has unused itinerary class " << ItinDef->getName() << '\n');
+ continue;
+ }
+ ProcModel.ItinDefList[getItinClassIdx(ItinDef)] = ItinData;
+ }
+#ifndef NDEBUG
+ // Check for missing itinerary entries.
+ assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec");
+ for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) {
+ if (!ProcModel.ItinDefList[i])
+ DEBUG(dbgs() << ProcModel.ItinsDef->getName()
+ << " missing itinerary for class " << SchedClasses[i].Name << '\n');
+ }
+#endif
+}
diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h
new file mode 100644
index 0000000000..9da0145732
--- /dev/null
+++ b/utils/TableGen/CodeGenSchedule.h
@@ -0,0 +1,172 @@
+//===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate the machine model as decribed in
+// the target description.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_SCHEDULE_H
+#define CODEGEN_SCHEDULE_H
+
+#include "llvm/TableGen/Record.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace llvm {
+
+class CodeGenTarget;
+
+// Scheduling class.
+//
+// Each instruction description will be mapped to a scheduling class. It may be
+// an explicitly defined itinerary class, or an inferred class in which case
+// ItinClassDef == NULL.
+struct CodeGenSchedClass {
+ std::string Name;
+ unsigned Index;
+ Record *ItinClassDef;
+
+ CodeGenSchedClass(): Index(0), ItinClassDef(0) {}
+ CodeGenSchedClass(Record *rec): Index(0), ItinClassDef(rec) {
+ Name = rec->getName();
+ }
+};
+
+// Processor model.
+//
+// ModelName is a unique name used to name an instantiation of MCSchedModel.
+//
+// ModelDef is NULL for inferred Models. This happens when a processor defines
+// an itinerary but no machine model. If the processer defines neither a machine
+// model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
+// the special "NoModel" field set to true.
+//
+// ItinsDef always points to a valid record definition, but may point to the
+// default NoItineraries. NoItineraries has an empty list of InstrItinData
+// records.
+//
+// ItinDefList orders this processor's InstrItinData records by SchedClass idx.
+struct CodeGenProcModel {
+ std::string ModelName;
+ Record *ModelDef;
+ Record *ItinsDef;
+
+ // Array of InstrItinData records indexed by CodeGenSchedClass::Index.
+ // The list is empty if the subtarget has no itineraries.
+ std::vector<Record *> ItinDefList;
+
+ CodeGenProcModel(const std::string &Name, Record *MDef, Record *IDef):
+ ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}
+};
+
+// Top level container for machine model data.
+class CodeGenSchedModels {
+ RecordKeeper &Records;
+ const CodeGenTarget &Target;
+
+ // List of unique SchedClasses.
+ std::vector<CodeGenSchedClass> SchedClasses;
+
+ // Map SchedClass name to itinerary index.
+ // These are either explicit itinerary classes or inferred classes.
+ StringMap<unsigned> SchedClassIdxMap;
+
+ // SchedClass indices 1 up to and including NumItineraryClasses identify
+ // itinerary classes that are explicitly used for this target's instruction
+ // definitions. NoItinerary always has index 0 regardless of whether it is
+ // explicitly referenced.
+ //
+ // Any inferred SchedClass have a index greater than NumItineraryClasses.
+ unsigned NumItineraryClasses;
+
+ // List of unique processor models.
+ std::vector<CodeGenProcModel> ProcModels;
+
+ // Map Processor's MachineModel + ProcItin fields to a CodeGenProcModel index.
+ typedef DenseMap<std::pair<Record*, Record*>, unsigned> ProcModelMapTy;
+ ProcModelMapTy ProcModelMap;
+
+ // True if any processors have nonempty itineraries.
+ bool HasProcItineraries;
+
+public:
+ CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
+
+ // Check if any instructions are assigned to an explicit itinerary class other
+ // than NoItinerary.
+ bool hasItineraryClasses() const { return NumItineraryClasses > 0; }
+
+ // Return the number of itinerary classes in use by this target's instruction
+ // descriptions, not including "NoItinerary".
+ unsigned numItineraryClasses() const {
+ return NumItineraryClasses;
+ }
+
+ // Get a SchedClass from its index.
+ const CodeGenSchedClass &getSchedClass(unsigned Idx) {
+ asse