Changes in directory llvm/utils/TableGen:
CodeEmitterGen.cpp updated: 1.41 -> 1.41.2.1 CodeGenTarget.cpp updated: 1.40 -> 1.40.2.1 DAGISelEmitter.cpp updated: 1.59 -> 1.59.2.1 DAGISelEmitter.h updated: 1.33 -> 1.33.2.1 InstrInfoEmitter.cpp updated: 1.28 -> 1.28.2.1 InstrInfoEmitter.h updated: 1.10 -> 1.10.2.1 InstrSelectorEmitter.cpp (r1.45) removed InstrSelectorEmitter.h (r1.27) removed Record.cpp updated: 1.45 -> 1.45.2.1 Record.h updated: 1.52 -> 1.52.2.1 RegisterInfoEmitter.cpp updated: 1.36 -> 1.36.2.1 SubtargetEmitter.cpp added (r1.14.2.2) SubtargetEmitter.h added (r1.7.2.2) TableGen.cpp updated: 1.39 -> 1.39.2.1 --- Log message: Merged mainline into Vector LLVM branch --- Diffs of the changes: (+894 -122) CodeEmitterGen.cpp | 3 CodeGenTarget.cpp | 28 -- DAGISelEmitter.cpp | 242 ++++++++++++++++++---- DAGISelEmitter.h | 17 + InstrInfoEmitter.cpp | 80 ++++--- InstrInfoEmitter.h | 9 Record.cpp | 19 + Record.h | 6 RegisterInfoEmitter.cpp | 19 - SubtargetEmitter.cpp | 516 ++++++++++++++++++++++++++++++++++++++++++++++++ SubtargetEmitter.h | 62 +++++ TableGen.cpp | 15 - 12 files changed, 894 insertions(+), 122 deletions(-) Index: llvm/utils/TableGen/CodeEmitterGen.cpp diff -u llvm/utils/TableGen/CodeEmitterGen.cpp:1.41 llvm/utils/TableGen/CodeEmitterGen.cpp:1.41.2.1 --- llvm/utils/TableGen/CodeEmitterGen.cpp:1.41 Thu Aug 18 20:04:33 2005 +++ llvm/utils/TableGen/CodeEmitterGen.cpp Wed Nov 16 12:33:45 2005 @@ -76,7 +76,6 @@ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); EmitSourceFileHeader("Machine Code Emitter", o); - o << "namespace llvm {\n\n"; std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::"; // Emit function declaration @@ -255,6 +254,4 @@ << " }\n" << " return Value;\n" << "}\n\n"; - - o << "} // End llvm namespace \n"; } Index: llvm/utils/TableGen/CodeGenTarget.cpp diff -u llvm/utils/TableGen/CodeGenTarget.cpp:1.40 llvm/utils/TableGen/CodeGenTarget.cpp:1.40.2.1 --- llvm/utils/TableGen/CodeGenTarget.cpp:1.40 Thu Oct 13 22:54:49 2005 +++ llvm/utils/TableGen/CodeGenTarget.cpp Wed Nov 16 12:33:45 2005 @@ -84,15 +84,8 @@ throw std::string("ERROR: Multiple subclasses of Target defined!"); TargetRec = Targets[0]; - // Read in all of the CalleeSavedRegisters... - ListInit *LI = TargetRec->getValueAsListInit("CalleeSavedRegisters"); - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i))) - CalleeSavedRegisters.push_back(DI->getDef()); - else - throw "Target: " + TargetRec->getName() + - " expected register definition in CalleeSavedRegisters list!"; - + // Read in all of the CalleeSavedRegisters. + CalleeSavedRegisters =TargetRec->getValueAsListOfDefs("CalleeSavedRegisters"); PointerType = getValueType(TargetRec->getValueAsDef("PointerType")); } @@ -108,12 +101,10 @@ /// getAsmWriter - Return the AssemblyWriter definition for this target. /// Record *CodeGenTarget::getAsmWriter() const { - ListInit *LI = TargetRec->getValueAsListInit("AssemblyWriters"); - if (AsmWriterNum >= LI->getSize()) + std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); + if (AsmWriterNum >= LI.size()) throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!"; - DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(AsmWriterNum)); - if (!DI) throw std::string("AssemblyWriter list should be a list of defs!"); - return DI->getDef(); + return LI[AsmWriterNum]; } void CodeGenTarget::ReadRegisters() const { @@ -159,12 +150,9 @@ MethodBodies = R->getValueAsCode("MethodBodies"); MethodProtos = R->getValueAsCode("MethodProtos"); - ListInit *RegList = R->getValueAsListInit("MemberList"); - for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { - DefInit *RegDef = dynamic_cast<DefInit*>(RegList->getElement(i)); - if (!RegDef) throw "Register class member is not a record!"; - Record *Reg = RegDef->getDef(); - + std::vector<Record*> RegList = R->getValueAsListOfDefs("MemberList"); + for (unsigned i = 0, e = RegList.size(); i != e; ++i) { + Record *Reg = RegList[i]; if (!Reg->isSubClassOf("Register")) throw "Register Class member '" + Reg->getName() + "' does not derive from the Register class!"; Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.59 llvm/utils/TableGen/DAGISelEmitter.cpp:1.59.2.1 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.59 Mon Oct 17 23:41:01 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Nov 16 12:33:45 2005 @@ -228,16 +228,14 @@ // Parse the properties. Properties = 0; - ListInit *LI = R->getValueAsListInit("Properties"); - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) { - DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i)); - assert(DI && "Properties list must be list of defs!"); - if (DI->getDef()->getName() == "SDNPCommutative") { + std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); + for (unsigned i = 0, e = PropList.size(); i != e; ++i) { + if (PropList[i]->getName() == "SDNPCommutative") { Properties |= 1 << SDNPCommutative; - } else if (DI->getDef()->getName() == "SDNPAssociative") { + } else if (PropList[i]->getName() == "SDNPAssociative") { Properties |= 1 << SDNPAssociative; } else { - std::cerr << "Unknown SD Node property '" << DI->getDef()->getName() + std::cerr << "Unknown SD Node property '" << PropList[i]->getName() << "' on node '" << R->getName() << "'!\n"; exit(1); } @@ -245,14 +243,9 @@ // Parse the type constraints. - ListInit *Constraints = TypeProfile->getValueAsListInit("Constraints"); - for (unsigned i = 0, e = Constraints->getSize(); i != e; ++i) { - assert(dynamic_cast<DefInit*>(Constraints->getElement(i)) && - "Constraints list should contain constraint definitions!"); - Record *Constraint = - static_cast<DefInit*>(Constraints->getElement(i))->getDef(); - TypeConstraints.push_back(Constraint); - } + std::vector<Record*> ConstraintList = + TypeProfile->getValueAsListOfDefs("Constraints"); + TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end()); } //===----------------------------------------------------------------------===// @@ -291,8 +284,13 @@ return true; } - TP.error("Type inference contradiction found in node " + - getOperator()->getName() + "!"); + if (isLeaf()) { + dump(); + TP.error("Type inference contradiction found in node!"); + } else { + TP.error("Type inference contradiction found in node " + + getOperator()->getName() + "!"); + } return true; // unreachable } @@ -462,10 +460,12 @@ // Pattern fragment types will be resolved when they are inlined. return MVT::isUnknown; } else if (R->isSubClassOf("Register")) { - assert(0 && "Explicit registers not handled here yet!\n"); + //const CodeGenTarget &T = TP.getDAGISelEmitter().getTargetInfo(); + // TODO: if a register appears in exactly one regclass, we could use that + // type info. return MVT::isUnknown; - } else if (R->isSubClassOf("ValueType")) { - // Using a VTSDNode. + } else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { + // Using a VTSDNode or CondCodeSDNode. return MVT::Other; } else if (R->getName() == "node") { // Placeholder. @@ -482,10 +482,28 @@ /// exception. bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (isLeaf()) { - if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) + if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) { // If it's a regclass or something else known, include the type. return UpdateNodeType(getIntrinsicType(DI->getDef(), NotRegisters, TP), TP); + } else if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) { + // Int inits are always integers. :) + bool MadeChange = UpdateNodeType(MVT::isInt, TP); + + if (hasTypeSet()) { + unsigned Size = MVT::getSizeInBits(getType()); + // Make sure that the value is representable for this type. + if (Size < 32) { + int Val = (II->getValue() << (32-Size)) >> (32-Size); + if (Val != II->getValue()) + TP.error("Sign-extended integer value '" + itostr(II->getValue()) + + "' is out of range for type 'MVT::" + + getEnumName(getType()) + "'!"); + } + } + + return MadeChange; + } return false; } @@ -571,19 +589,22 @@ // TreePattern implementation // -TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, +TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + isInputPattern = isInput; for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) Trees.push_back(ParseTreePattern((DagInit*)RawPat->getElement(i))); } -TreePattern::TreePattern(Record *TheRec, DagInit *Pat, +TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + isInputPattern = isInput; Trees.push_back(ParseTreePattern(Pat)); } -TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, +TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + isInputPattern = isInput; Trees.push_back(Pat); } @@ -618,6 +639,10 @@ New = new TreePatternNode(DI); } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { New = ParseTreePattern(DI); + } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { + New = new TreePatternNode(II); + if (!Dag->getArgName(0).empty()) + error("Constant int argument should not have a name!"); } else { Arg->dump(); error("Unknown leaf value for tree pattern!"); @@ -636,6 +661,11 @@ Operator->getName() != "set") error("Unrecognized node '" + Operator->getName() + "'!"); + // Check to see if this is something that is illegal in an input pattern. + if (isInputPattern && (Operator->isSubClassOf("Instruction") || + Operator->isSubClassOf("SDNodeXForm"))) + error("Cannot use '" + Operator->getName() + "' in an input pattern!"); + std::vector<TreePatternNode*> Children; for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { @@ -663,8 +693,15 @@ Args.push_back(Dag->getArgName(i)); } } + } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { + TreePatternNode *Node = new TreePatternNode(II); + if (!Dag->getArgName(i).empty()) + error("Constant int argument should not have a name!"); + Children.push_back(Node); } else { + std::cerr << '"'; Arg->dump(); + std::cerr << "\": "; error("Unknown leaf value for tree pattern!"); } } @@ -771,7 +808,7 @@ OS << "\n// Predicate functions.\n"; for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); - TreePattern *P = new TreePattern(Fragments[i], Tree, *this); + TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this); PatternFragments[Fragments[i]] = P; // Validate the argument list, converting it to map, to discard duplicates. @@ -975,14 +1012,39 @@ std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction"); for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { - if (!dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern"))) - continue; // no pattern yet, ignore it. + ListInit *LI = 0; - ListInit *LI = Instrs[i]->getValueAsListInit("Pattern"); - if (LI->getSize() == 0) continue; // no pattern. + if (dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern"))) + LI = Instrs[i]->getValueAsListInit("Pattern"); + + // 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) { + std::vector<MVT::ValueType> ResultTypes; + std::vector<MVT::ValueType> OperandTypes; + + CodeGenInstruction &InstInfo =Target.getInstruction(Instrs[i]->getName()); + + // Doesn't even define a result? + if (InstInfo.OperandList.size() == 0) + continue; + + // Assume the first operand is the result. + ResultTypes.push_back(InstInfo.OperandList[0].Ty); + + // The rest are inputs. + for (unsigned j = 1, e = InstInfo.OperandList.size(); j != e; ++j) + OperandTypes.push_back(InstInfo.OperandList[j].Ty); + + // Create and insert the instruction. + Instructions.insert(std::make_pair(Instrs[i], + DAGInstruction(0, ResultTypes, OperandTypes))); + continue; // no pattern. + } // Parse the instruction. - TreePattern *I = new TreePattern(Instrs[i], LI, *this); + TreePattern *I = new TreePattern(Instrs[i], LI, true, *this); // Inline pattern fragments into it. I->InlinePatternFragments(); @@ -1099,7 +1161,7 @@ // Use a temporary tree pattern to infer all types and make sure that the // constructed result is correct. This depends on the instruction already // being inserted into the Instructions map. - TreePattern Temp(I->getRecord(), ResultPattern, *this); + TreePattern Temp(I->getRecord(), ResultPattern, false, *this); Temp.InferAllTypes(); DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second; @@ -1112,6 +1174,7 @@ for (std::map<Record*, DAGInstruction>::iterator II = Instructions.begin(), E = Instructions.end(); II != E; ++II) { TreePattern *I = II->second.getPattern(); + if (I == 0) continue; // No pattern. if (I->getNumTrees() != 1) { std::cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!"; @@ -1140,7 +1203,7 @@ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { DagInit *Tree = Patterns[i]->getValueAsDag("PatternToMatch"); - TreePattern *Pattern = new TreePattern(Patterns[i], Tree, *this); + TreePattern *Pattern = new TreePattern(Patterns[i], Tree, true, *this); // Inline pattern fragments into it. Pattern->InlinePatternFragments(); @@ -1154,7 +1217,7 @@ if (LI->getSize() == 0) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(Patterns[i], LI, *this); + TreePattern *Result = new TreePattern(Patterns[i], LI, false, *this); // Inline pattern fragments into it. Result->InlinePatternFragments(); @@ -1437,6 +1500,9 @@ TreePatternNode *Child = P->getChild(i); if (!Child->isLeaf() && Child->getExtType() != MVT::Other) Size += getPatternSize(Child); + else if (Child->isLeaf() && dynamic_cast<IntInit*>(Child->getLeafValue())) { + ++Size; // Matches a ConstantSDNode. + } } return Size; @@ -1477,7 +1543,16 @@ const std::string &RootName, std::map<std::string,std::string> &VarMap, unsigned PatternNo, std::ostream &OS) { - assert(!N->isLeaf() && "Cannot match against a leaf!"); + if (N->isLeaf()) { + if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { + OS << " if (cast<ConstantSDNode>(" << RootName + << ")->getSignExtended() != " << II->getValue() << ")\n" + << " goto P" << PatternNo << "Fail;\n"; + return; + } + assert(0 && "Cannot match this as a leaf value!"); + abort(); + } // If this node has a name associated with it, capture it in VarMap. If // we already saw this in the pattern, emit code to verify dagness. @@ -1527,15 +1602,29 @@ } // Handle leaves of various types. - Init *LeafVal = Child->getLeafValue(); - Record *LeafRec = dynamic_cast<DefInit*>(LeafVal)->getDef(); - if (LeafRec->isSubClassOf("RegisterClass")) { - // Handle register references. Nothing to do here. - } else if (LeafRec->isSubClassOf("ValueType")) { - // Make sure this is the specified value type. - OS << " if (cast<VTSDNode>(" << RootName << i << ")->getVT() != " - << "MVT::" << LeafRec->getName() << ") goto P" << PatternNo - << "Fail;\n"; + if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) { + Record *LeafRec = DI->getDef(); + if (LeafRec->isSubClassOf("RegisterClass")) { + // Handle register references. Nothing to do here. + } else if (LeafRec->isSubClassOf("ValueType")) { + // Make sure this is the specified value type. + OS << " if (cast<VTSDNode>(" << RootName << i << ")->getVT() != " + << "MVT::" << LeafRec->getName() << ") goto P" << PatternNo + << "Fail;\n"; + } else if (LeafRec->isSubClassOf("CondCode")) { + // Make sure this is the specified cond code. + OS << " if (cast<CondCodeSDNode>(" << RootName << i + << ")->get() != " << "ISD::" << LeafRec->getName() + << ") goto P" << PatternNo << "Fail;\n"; + } else { + Child->dump(); + assert(0 && "Unknown leaf type!"); + } + } else if (IntInit *II = dynamic_cast<IntInit*>(Child->getLeafValue())) { + OS << " if (!isa<ConstantSDNode>(" << RootName << i << ") ||\n" + << " cast<ConstantSDNode>(" << RootName << i + << ")->getSignExtended() != " << II->getValue() << ")\n" + << " goto P" << PatternNo << "Fail;\n"; } else { Child->dump(); assert(0 && "Unknown leaf type!"); @@ -1589,6 +1678,25 @@ } if (N->isLeaf()) { + // If this is an explicit register reference, handle it. + if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { + unsigned ResNo = Ctr++; + if (DI->getDef()->isSubClassOf("Register")) { + OS << " SDOperand Tmp" << ResNo << " = CurDAG->getRegister(" + << getQualifiedName(DI->getDef()) << ", MVT::" + << getEnumName(N->getType()) + << ");\n"; + return ResNo; + } + } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { + unsigned ResNo = Ctr++; + OS << " SDOperand Tmp" << ResNo << " = CurDAG->getTargetConstant(" + << II->getValue() << ", MVT::" + << getEnumName(N->getType()) + << ");\n"; + return ResNo; + } + N->dump(); assert(0 && "Unknown leaf type!"); return ~0U; @@ -1685,6 +1793,12 @@ return false; } +Record *DAGISelEmitter::getSDNodeNamed(const std::string &Name) const { + Record *N = Records.getDef(Name); + assert(N && N->isSubClassOf("SDNode") && "Bad argument"); + return N; +} + /// EmitCodeForPattern - Given a pattern to match, emit code to the specified /// stream to match the pattern, and generate the code for the match if it /// succeeds. @@ -1785,14 +1899,52 @@ << " SDOperand Tmp0 = Select(N.getOperand(0));\n" << " if (!N.Val->hasOneUse()) CodeGenMap[N] = Tmp0;\n" << " return Tmp0;\n" + << " }\n" + << " case ISD::TokenFactor:\n" + << " if (N.getNumOperands() == 2) {\n" + << " SDOperand Op0 = Select(N.getOperand(0));\n" + << " SDOperand Op1 = Select(N.getOperand(1));\n" + << " return CodeGenMap[N] =\n" + << " CurDAG->getNode(ISD::TokenFactor, MVT::Other, Op0, Op1);\n" + << " } else {\n" + << " std::vector<SDOperand> Ops;\n" + << " for (unsigned i = 0, e = N.getNumOperands(); i != e; ++i)\n" + << " Ops.push_back(Select(N.getOperand(i)));\n" + << " return CodeGenMap[N] = \n" + << " CurDAG->getNode(ISD::TokenFactor, MVT::Other, Ops);\n" + << " }\n" + << " case ISD::CopyFromReg: {\n" + << " SDOperand Chain = Select(N.getOperand(0));\n" + << " if (Chain == N.getOperand(0)) return N; // No change\n" + << " SDOperand New = CurDAG->getCopyFromReg(Chain,\n" + << " cast<RegisterSDNode>(N.getOperand(1))->getReg(),\n" + << " N.Val->getValueType(0));\n" + << " return New.getValue(N.ResNo);\n" + << " }\n" + << " case ISD::CopyToReg: {\n" + << " SDOperand Chain = Select(N.getOperand(0));\n" + << " SDOperand Reg = N.getOperand(1);\n" + << " SDOperand Val = Select(N.getOperand(2));\n" + << " return CodeGenMap[N] = \n" + << " CurDAG->getNode(ISD::CopyToReg, MVT::Other,\n" + << " Chain, Reg, Val);\n" << " }\n"; // Group the patterns by their top-level opcodes. std::map<Record*, std::vector<PatternToMatch*>, CompareByRecordName> PatternsByOpcode; for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) - PatternsByOpcode[PatternsToMatch[i].first->getOperator()] - .push_back(&PatternsToMatch[i]); + if (!PatternsToMatch[i].first->isLeaf()) { + PatternsByOpcode[PatternsToMatch[i].first->getOperator()] + .push_back(&PatternsToMatch[i]); + } else { + if (IntInit *II = + dynamic_cast<IntInit*>(PatternsToMatch[i].first->getLeafValue())) { + PatternsByOpcode[getSDNodeNamed("imm")].push_back(&PatternsToMatch[i]); + } else { + assert(0 && "Unknown leaf value"); + } + } // Loop over all of the case statements. for (std::map<Record*, std::vector<PatternToMatch*>, Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.33 llvm/utils/TableGen/DAGISelEmitter.h:1.33.2.1 --- llvm/utils/TableGen/DAGISelEmitter.h:1.33 Sat Oct 15 20:41:58 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Wed Nov 16 12:33:45 2005 @@ -226,7 +226,7 @@ /// ContainsUnresolvedType - Return true if this tree contains any /// unresolved types. bool ContainsUnresolvedType() const { - if (Ty == MVT::LAST_VALUETYPE) return true; + if (!hasTypeSet()) return true; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) if (getChild(i)->ContainsUnresolvedType()) return true; return false; @@ -258,13 +258,20 @@ /// ISE - the DAG isel emitter coordinating this madness. /// DAGISelEmitter &ISE; + + /// isInputPattern - True if this is an input pattern, something to match. + /// False if this is an output pattern, something to emit. + bool isInputPattern; public: /// TreePattern constructor - Parse the specified DagInits into the /// current record. - TreePattern(Record *TheRec, ListInit *RawPat, DAGISelEmitter &ise); - TreePattern(Record *TheRec, DagInit *Pat, DAGISelEmitter &ise); - TreePattern(Record *TheRec, TreePatternNode *Pat, DAGISelEmitter &ise); + TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, + DAGISelEmitter &ise); + TreePattern(Record *TheRec, DagInit *Pat, bool isInput, + DAGISelEmitter &ise); + TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, + DAGISelEmitter &ise); /// getTrees - Return the tree patterns which corresponds to this pattern. /// @@ -375,6 +382,8 @@ const CodeGenTarget &getTargetInfo() const { return Target; } + Record *getSDNodeNamed(const std::string &Name) const; + const SDNodeInfo &getSDNodeInfo(Record *R) const { assert(SDNodes.count(R) && "Unknown node!"); return SDNodes.find(R)->second; Index: llvm/utils/TableGen/InstrInfoEmitter.cpp diff -u llvm/utils/TableGen/InstrInfoEmitter.cpp:1.28 llvm/utils/TableGen/InstrInfoEmitter.cpp:1.28.2.1 --- llvm/utils/TableGen/InstrInfoEmitter.cpp:1.28 Fri Aug 26 15:42:52 2005 +++ llvm/utils/TableGen/InstrInfoEmitter.cpp Wed Nov 16 12:33:45 2005 @@ -15,6 +15,7 @@ #include "InstrInfoEmitter.h" #include "CodeGenTarget.h" #include "Record.h" +#include <algorithm> using namespace llvm; // runEnums - Print out enum values for all of the instructions. @@ -47,16 +48,6 @@ OS << "} // End llvm namespace \n"; } -static std::vector<Record*> GetDefList(ListInit *LI, const std::string &Name) { - std::vector<Record*> Result; - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i))) - Result.push_back(DI->getDef()); - else - throw "Illegal value in '" + Name + "' list!"; - return Result; -} - void InstrInfoEmitter::printDefList(const std::vector<Record*> &Uses, unsigned Num, std::ostream &OS) const { OS << "static const unsigned ImplicitList" << Num << "[] = { "; @@ -86,6 +77,8 @@ // run - Emit the main instruction description records for the target... void InstrInfoEmitter::run(std::ostream &OS) { + GatherItinClasses(); + EmitSourceFileHeader("Target Instruction Descriptors", OS); OS << "namespace llvm {\n\n"; @@ -99,26 +92,21 @@ // Keep track of all of the def lists we have emitted already. std::map<std::vector<Record*>, unsigned> EmittedLists; - std::map<ListInit*, unsigned> ListNumbers; unsigned ListNumber = 0; // Emit all of the instruction's implicit uses and defs. for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) { Record *Inst = II->second.TheDef; - ListInit *LI = Inst->getValueAsListInit("Uses"); - if (LI->getSize()) { - std::vector<Record*> Uses = GetDefList(LI, Inst->getName()); + std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); + if (!Uses.empty()) { unsigned &IL = EmittedLists[Uses]; if (!IL) printDefList(Uses, IL = ++ListNumber, OS); - ListNumbers[LI] = IL; } - LI = Inst->getValueAsListInit("Defs"); - if (LI->getSize()) { - std::vector<Record*> Uses = GetDefList(LI, Inst->getName()); - unsigned &IL = EmittedLists[Uses]; - if (!IL) printDefList(Uses, IL = ++ListNumber, OS); - ListNumbers[LI] = IL; + std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs"); + if (!Defs.empty()) { + unsigned &IL = EmittedLists[Defs]; + if (!IL) printDefList(Defs, IL = ++ListNumber, OS); } } @@ -150,14 +138,14 @@ // OS << "\nstatic const TargetInstrDescriptor " << TargetName << "Insts[] = {\n"; - emitRecord(Target.getPHIInstruction(), 0, InstrInfo, ListNumbers, + emitRecord(Target.getPHIInstruction(), 0, InstrInfo, EmittedLists, OperandInfosEmitted, OS); unsigned i = 0; for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) if (II->second.TheDef != PHI) - emitRecord(II->second, ++i, InstrInfo, ListNumbers, + emitRecord(II->second, ++i, InstrInfo, EmittedLists, OperandInfosEmitted, OS); OS << "};\n"; OS << "} // End llvm namespace \n"; @@ -165,7 +153,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, - std::map<ListInit*, unsigned> &ListNumbers, + std::map<std::vector<Record*>, unsigned> &EmittedLists, std::map<std::vector<Record*>, unsigned> &OpInfo, std::ostream &OS) { int NumOperands; @@ -183,7 +171,13 @@ OS << Inst.TheDef->getName(); else OS << Inst.Name; - OS << "\",\t" << NumOperands << ", -1, 0, false, 0, 0, 0, 0"; + + unsigned ItinClass = !IsItineraries ? 0 : + ItinClassNumber(Inst.TheDef->getValueAsDef("Itinerary")->getName()); + + OS << "\",\t" << NumOperands << ", -1, 0, false, 0, 0, " + << ItinClass + << ", 0"; // Emit all of the target indepedent flags... if (Inst.isReturn) OS << "|M_RET_FLAG"; @@ -215,17 +209,17 @@ OS << ", "; // Emit the implicit uses and defs lists... - LI = Inst.TheDef->getValueAsListInit("Uses"); - if (!LI->getSize()) + std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); + if (UseList.empty()) OS << "EmptyImpList, "; else - OS << "ImplicitList" << ListNumbers[LI] << ", "; + OS << "ImplicitList" << EmittedLists[UseList] << ", "; - LI = Inst.TheDef->getValueAsListInit("Defs"); - if (!LI->getSize()) + std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); + if (DefList.empty()) OS << "EmptyImpList, "; else - OS << "ImplicitList" << ListNumbers[LI] << ", "; + OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. std::vector<Record*> OperandInfo = GetOperandInfo(Inst); @@ -237,6 +231,30 @@ OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } +struct LessRecord { + bool operator()(const Record *Rec1, const Record *Rec2) const { + return Rec1->getName() < Rec2->getName(); + } +}; +void InstrInfoEmitter::GatherItinClasses() { + std::vector<Record*> DefList = + Records.getAllDerivedDefinitions("InstrItinClass"); + IsItineraries = !DefList.empty(); + + if (!IsItineraries) return; + + sort(DefList.begin(), DefList.end(), LessRecord()); + + for (unsigned i = 0, N = DefList.size(); i < N; i++) { + Record *Def = DefList[i]; + ItinClassMap[Def->getName()] = i; + } +} + +unsigned InstrInfoEmitter::ItinClassNumber(std::string ItinName) { + return ItinClassMap[ItinName]; +} + void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, IntInit *ShiftInt, std::ostream &OS) { if (Val == 0 || ShiftInt == 0) Index: llvm/utils/TableGen/InstrInfoEmitter.h diff -u llvm/utils/TableGen/InstrInfoEmitter.h:1.10 llvm/utils/TableGen/InstrInfoEmitter.h:1.10.2.1 --- llvm/utils/TableGen/InstrInfoEmitter.h:1.10 Fri Aug 19 13:46:26 2005 +++ llvm/utils/TableGen/InstrInfoEmitter.h Wed Nov 16 12:33:45 2005 @@ -28,8 +28,11 @@ class InstrInfoEmitter : public TableGenBackend { RecordKeeper &Records; + bool IsItineraries; + std::map<std::string, unsigned> ItinClassMap; + public: - InstrInfoEmitter(RecordKeeper &R) : Records(R) {} + InstrInfoEmitter(RecordKeeper &R) : Records(R), IsItineraries(false) {} // run - Output the instruction set description, returning true on failure. void run(std::ostream &OS); @@ -41,9 +44,11 @@ std::ostream &OS) const; void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, - std::map<ListInit*, unsigned> &ListNumbers, + std::map<std::vector<Record*>, unsigned> &EL, std::map<std::vector<Record*>, unsigned> &OpInfo, std::ostream &OS); + void GatherItinClasses(); + unsigned ItinClassNumber(std::string ItinName); void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift, std::ostream &OS); }; Index: llvm/utils/TableGen/Record.cpp diff -u llvm/utils/TableGen/Record.cpp:1.45 llvm/utils/TableGen/Record.cpp:1.45.2.1 --- llvm/utils/TableGen/Record.cpp:1.45 Tue Sep 13 16:44:28 2005 +++ llvm/utils/TableGen/Record.cpp Wed Nov 16 12:33:45 2005 @@ -709,6 +709,25 @@ "' does not have a list initializer!"; } +/// getValueAsListOfDefs - This method looks up the specified field and returns +/// its value as a vector of records, throwing an exception if the field does +/// not exist or if the value is not the right type. +/// +std::vector<Record*> +Record::getValueAsListOfDefs(const std::string &FieldName) const { + ListInit *List = getValueAsListInit(FieldName); + std::vector<Record*> Defs; + for (unsigned i = 0; i < List->getSize(); i++) { + if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i))) { + Defs.push_back(DI->getDef()); + } else { + throw "Record `" + getName() + "', field `" + FieldName + + "' list is not entirely DefInit!"; + } + } + return Defs; +} + /// getValueAsInt - This method looks up the specified field and returns its /// value as an int, throwing an exception if the field does not exist or if /// the value is not the right type. Index: llvm/utils/TableGen/Record.h diff -u llvm/utils/TableGen/Record.h:1.52 llvm/utils/TableGen/Record.h:1.52.2.1 --- llvm/utils/TableGen/Record.h:1.52 Tue Sep 13 16:44:28 2005 +++ llvm/utils/TableGen/Record.h Wed Nov 16 12:33:45 2005 @@ -1000,6 +1000,12 @@ /// ListInit *getValueAsListInit(const std::string &FieldName) const; + /// getValueAsListOfDefs - This method looks up the specified field and + /// returnsits value as a vector of records, throwing an exception if the + /// field does not exist or if the value is not the right type. + /// + std::vector<Record*> getValueAsListOfDefs(const std::string &FieldName) const; + /// getValueAsDef - This method looks up the specified field and returns its /// value as a Record, throwing an exception if the field does not exist or if /// the value is not the right type. Index: llvm/utils/TableGen/RegisterInfoEmitter.cpp diff -u llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.36 llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.36.2.1 --- llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.36 Sun Oct 2 01:23:37 2005 +++ llvm/utils/TableGen/RegisterInfoEmitter.cpp Wed Nov 16 12:33:45 2005 @@ -163,23 +163,22 @@ for (unsigned i = 0, e = Regs.size(); i != e; ++i) { Record *R = Regs[i].TheDef; - ListInit *LI = Regs[i].TheDef->getValueAsListInit("Aliases"); + std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("Aliases"); // Add information that R aliases all of the elements in the list... and // that everything in the list aliases R. - for (unsigned j = 0, e = LI->getSize(); j != e; ++j) { - DefInit *Reg = dynamic_cast<DefInit*>(LI->getElement(j)); - if (!Reg) throw "ERROR: Alias list element is not a def!"; - if (RegisterAliases[R].count(Reg->getDef())) + for (unsigned j = 0, e = LI.size(); j != e; ++j) { + Record *Reg = LI[j]; + if (RegisterAliases[R].count(Reg)) std::cerr << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg->getDef()) + << " and " << getQualifiedName(Reg) << " specified multiple times!\n"; - RegisterAliases[R].insert(Reg->getDef()); + RegisterAliases[R].insert(Reg); - if (RegisterAliases[Reg->getDef()].count(R)) + if (RegisterAliases[Reg].count(R)) std::cerr << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg->getDef()) + << " and " << getQualifiedName(Reg) << " specified multiple times!\n"; - RegisterAliases[Reg->getDef()].insert(R); + RegisterAliases[Reg].insert(R); } } Index: llvm/utils/TableGen/SubtargetEmitter.cpp diff -c /dev/null llvm/utils/TableGen/SubtargetEmitter.cpp:1.14.2.2 *** /dev/null Wed Nov 16 12:33:56 2005 --- llvm/utils/TableGen/SubtargetEmitter.cpp Wed Nov 16 12:33:45 2005 *************** *** 0 **** --- 1,516 ---- + //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by James M. Laskey and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This tablegen backend emits subtarget enumerations. The format is in a state + // flux and will be tightened up when integration to scheduling is complete. + // + //===----------------------------------------------------------------------===// + + #include "SubtargetEmitter.h" + #include "CodeGenTarget.h" + #include "Record.h" + #include "llvm/ADT/StringExtras.h" + #include "llvm/Support/Debug.h" + #include <algorithm> + using namespace llvm; + + // + // Record sort by name function. + // + struct LessRecord { + bool operator()(const Record *Rec1, const Record *Rec2) const { + return Rec1->getName() < Rec2->getName(); + } + }; + + // + // Record sort by field "Name" function. + // + struct LessRecordFieldName { + bool operator()(const Record *Rec1, const Record *Rec2) const { + return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name"); + } + }; + + // + // Enumeration - Emit the specified class as an enumeration. + // + void SubtargetEmitter::Enumeration(std::ostream &OS, + const char *ClassName, + bool isBits) { + // Get all records of class and sort + std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName); + sort(DefList.begin(), DefList.end(), LessRecord()); + + // Open enumeration + OS << "enum {\n"; + + // For each record + for (unsigned i = 0, N = DefList.size(); i < N;) { + // Next record + Record *Def = DefList[i]; + + // Get and emit name + std::string Name = Def->getName(); + OS << " " << Name; + + // If bit flags then emit expression (1 << i) + if (isBits) OS << " = " << " 1 << " << i; + + // Depending on 'if more in the list' emit comma + if (++i < N) OS << ","; + + OS << "\n"; + } + + // Close enumeration + OS << "};\n"; + } + + // + // FeatureKeyValues - Emit data of all the subtarget features. Used by command + // line. + // + void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) { + // Gather and sort all the features + std::vector<Record*> FeatureList = + Records.getAllDerivedDefinitions("SubtargetFeature"); + sort(FeatureList.begin(), FeatureList.end(), LessRecord()); + + // Begin feature table + OS << "// Sorted (by key) array of values for CPU features.\n" + << "static llvm::SubtargetFeatureKV FeatureKV[] = {\n"; + + // For each feature + for (unsigned i = 0, N = FeatureList.size(); i < N;) { + // Next feature + Record *Feature = FeatureList[i]; + + std::string Name = Feature->getName(); + std::string CommandLineName = Feature->getValueAsString("Name"); + std::string Desc = Feature->getValueAsString("Desc"); + + // Emit as { "feature", "decription", feactureEnum } + OS << " { " + << "\"" << CommandLineName << "\", " + << "\"" << Desc << "\", " + << Name + << " }"; + + // Depending on 'if more in the list' emit comma + if (++i < N) OS << ","; + + OS << "\n"; + } + + // End feature table + OS << "};\n"; + + // Emit size of table + OS<<"\nenum {\n"; + OS<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n"; + OS<<"};\n"; + } + + // + // CPUKeyValues - Emit data of all the subtarget processors. Used by command + // line. + // + void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { + // Gather and sort processor information + std::vector<Record*> ProcessorList = + Records.getAllDerivedDefinitions("Processor"); + sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); + + // Begin processor table + OS << "// Sorted (by key) array of values for CPU subtype.\n" + << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n"; + + // For each processor + for (unsigned i = 0, N = ProcessorList.size(); i < N;) { + // Next processor + Record *Processor = ProcessorList[i]; + + std::string Name = Processor->getValueAsString("Name"); + std::vector<Record*> FeatureList = + Processor->getValueAsListOfDefs("Features"); + + // Emit as { "cpu", "description", f1 | f2 | ... fn }, + OS << " { " + << "\"" << Name << "\", " + << "\"Select the " << Name << " processor\", "; + + if (FeatureList.empty()) { + OS << "0"; + } else { + for (unsigned j = 0, M = FeatureList.size(); j < M;) { + Record *Feature = FeatureList[j]; + std::string Name = Feature->getName(); + OS << Name; + if (++j < M) OS << " | "; + } + } + + OS << " }"; + + // Depending on 'if more in the list' emit comma + if (++i < N) OS << ","; + + OS << "\n"; + } + + // End processor table + OS << "};\n"; + + // Emit size of table + OS<<"\nenum {\n"; + OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n"; + OS<<"};\n"; + } + + // + // CollectAllItinClasses - Gathers and enumerates all the itinerary classes. + // Returns itinerary class count. + // + unsigned SubtargetEmitter::CollectAllItinClasses(std::ostream &OS, + std::map<std::string, unsigned> &ItinClassesMap) { + // Gather and sort all itinerary classes + std::vector<Record*> ItinClassList = + Records.getAllDerivedDefinitions("InstrItinClass"); + sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); + + // For each itinerary class + unsigned N = ItinClassList.size(); + for (unsigned i = 0; i < N; i++) { + // Next itinerary class + Record *ItinClass = ItinClassList[i]; + // Get name of itinerary class + std::string Name = ItinClass->getName(); + // Assign itinerary class a unique number + ItinClassesMap[Name] = i; + } + + // Emit size of table + OS<<"\nenum {\n"; + OS<<" ItinClassesSize = " << N << "\n"; + OS<<"};\n"; + + // Return itinerary class count + return N; + } + + // + // FormItineraryString - Compose a string containing the data initialization + // for the specified itinerary. N is the number of stages. + // + void SubtargetEmitter::FormItineraryString(Record *ItinData, + std::string &ItinString, + unsigned &NStages) { + // Get states list + std::vector<Record*> StageList = ItinData->getValueAsListOfDefs("Stages"); + + // For each stage + unsigned N = NStages = StageList.size(); + for (unsigned i = 0; i < N; i++) { + // Next stage + Record *Stage = StageList[i]; + + // Form string as ,{ cycles, u1 | u2 | ... | un } + int Cycles = Stage->getValueAsInt("Cycles"); + ItinString += " { " + itostr(Cycles) + ", "; + + // Get unit list + std::vector<Record*> UnitList = Stage->getValueAsListOfDefs("Units"); + + // For each unit + for (unsigned j = 0, M = UnitList.size(); j < M;) { + // Next unit + Record *Unit = UnitList[j]; + + // Add name and bitwise or + ItinString += Unit->getName(); + if (++j < M) ItinString += " | "; + } + + // Close off stage + ItinString += " }"; + } + } + + // + // EmitStageData - Generate unique itinerary stages. Record itineraries for + // processors. + // + void SubtargetEmitter::EmitStageData(std::ostream &OS, + unsigned NItinClasses, + std::map<std::string, unsigned> &ItinClassesMap, + std::vector<std::vector<InstrItinerary> > &ProcList) { + // Gather processor iteraries + std::vector<Record*> ProcItinList = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + + // If just no itinerary then don't bother + if (ProcItinList.size() < 2) return; + + // Begin stages table + OS << "static llvm::InstrStage Stages[] = {\n" + " { 0, 0 }, // No itinerary\n"; + + unsigned ItinEnum = 1; + std::map<std::string, unsigned> ItinMap; + for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { + // Next record + Record *Proc = ProcItinList[i]; + + // Get processor itinerary name + std::string Name = Proc->getName(); + + // Skip default + if (Name == "NoItineraries") continue; + + // Create and expand processor itinerary to cover all itinerary classes + std::vector<InstrItinerary> ItinList; + ItinList.resize(NItinClasses); + + // Get itinerary data list + std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); + + // For each itinerary data + for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { + // Next itinerary data + Record *ItinData = ItinDataList[j]; + + // Get string and stage count + std::string ItinString; + unsigned NStages; + FormItineraryString(ItinData, ItinString, NStages); + + // Check to see if it already exists + unsigned Find = ItinMap[ItinString]; + + // If new itinerary + if (Find == 0) { + // Emit as { cycles, u1 | u2 | ... | un }, // index + OS << ItinString << ", // " << ItinEnum << "\n"; + // Record Itin class number + ItinMap[ItinString] = Find = ItinEnum++; + } + + // Set up itinerary as location and location + stage count + InstrItinerary Intinerary = { Find, Find + NStages }; + + // Locate where to inject into processor itinerary table + std::string Name = ItinData->getValueAsDef("TheClass")->getName(); + Find = ItinClassesMap[Name]; + + // Inject - empty slots will be 0, 0 + ItinList[Find] = Intinerary; + } + + // Add process itinerary to list + ProcList.push_back(ItinList); + } + + // Closing stage + OS << " { 0, 0 } // End itinerary\n"; + // End stages table + OS << "};\n"; + + // Emit size of table + OS<<"\nenum {\n"; + OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage)\n"; + OS<<"};\n"; + } + + // + // EmitProcessorData - Generate data for processor itineraries. + // + void SubtargetEmitter::EmitProcessorData(std::ostream &OS, + std::vector<std::vector<InstrItinerary> > &ProcList) { + // Get an iterator for processor itinerary stages + std::vector<std::vector<InstrItinerary> >::iterator + ProcListIter = ProcList.begin(); + + // For each processor itinerary + std::vector<Record*> Itins = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + for (unsigned i = 0, N = Itins.size(); i < N; i++) { + // Next record + Record *Itin = Itins[i]; + + // Get processor itinerary name + std::string Name = Itin->getName(); + + // Skip default + if (Name == "NoItineraries") continue; + + // Begin processor itinerary table + OS << "\n"; + OS << "static llvm::InstrItinerary " << Name << "[] = {\n"; + + // For each itinerary class + std::vector<InstrItinerary> &ItinList = *ProcListIter++; + unsigned ItinIndex = 0; + for (unsigned j = 0, M = ItinList.size(); j < M;) { + InstrItinerary &Intinerary = ItinList[j]; + + // Emit in the form of { first, last } // index + if (Intinerary.First == 0) { + OS << " { 0, 0 }"; + } else { + OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }"; + } + + // If more in list add comma + if (++j < M) OS << ","; + + OS << " // " << (j - 1) << "\n"; + } + + // End processor itinerary table + OS << "};\n"; + } + + OS << "\n"; + OS << "static llvm::InstrItinerary NoItineraries[] = {};\n"; + } + + // + // EmitProcessorLookup - generate cpu name to itinerary lookup table. + // + void SubtargetEmitter::EmitProcessorLookup(std::ostream &OS) { + // Gather and sort processor information + std::vector<Record*> ProcessorList = + Records.getAllDerivedDefinitions("Processor"); + sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); + + // Begin processor table + OS << "\n"; + OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" + << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n"; + + // For each processor + for (unsigned i = 0, N = ProcessorList.size(); i < N;) { + // Next processor + Record *Processor = ProcessorList[i]; + + std::string Name = Processor->getValueAsString("Name"); + std::string ProcItin = Processor->getValueAsDef("ProcItin")->getName(); + + // Emit as { "cpu", procinit }, + OS << " { " + << "\"" << Name << "\", " + << "(void *)&" << ProcItin; + + OS << " }"; + + // Depending on ''if more in the list'' emit comma + if (++i < N) OS << ","; + + OS << "\n"; + } + + // End processor table + OS << "};\n"; + + // Emit size of table + OS<<"\nenum {\n"; + OS<<" ProcItinKVSize = sizeof(ProcItinKV)/" + "sizeof(llvm::SubtargetInfoKV)\n"; + OS<<"};\n"; + } + + // + // EmitData - Emits all stages and itineries, folding common patterns. + // + void SubtargetEmitter::EmitData(std::ostream &OS) { + std::map<std::string, unsigned> ItinClassesMap; + std::vector<std::vector<InstrItinerary> > ProcList; + + // Enumerate all the itinerary classes + unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap); + // Make sure the rest is worth the effort + HasItineraries = NItinClasses != 0; + + if (HasItineraries) { + // Emit the stage data + EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList); + // Emit the processor itinerary data + EmitProcessorData(OS, ProcList); + // Emit the processor lookup data + EmitProcessorLookup(OS); + } + } + + // + // ParseFeaturesFunction - Produces a subtarget specific function for parsing + // the subtarget features string. + // + void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) { + std::vector<Record*> Features = + Records.getAllDerivedDefinitions("SubtargetFeature"); + sort(Features.begin(), Features.end(), LessRecord()); + + OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" + "// subtarget options.\n" + "void llvm::"; + OS << Target; + OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" + " const std::string &CPU) {\n" + " SubtargetFeatures Features(FS);\n" + " Features.setCPUIfNone(CPU);\n" + " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" + " FeatureKV, FeatureKVSize);\n"; + + for (unsigned i = 0; i < Features.size(); i++) { + // Next record + Record *R = Features[i]; + std::string Instance = R->getName(); + std::string Name = R->getValueAsString("Name"); + std::string Type = R->getValueAsString("Type"); + std::string Attribute = R->getValueAsString("Attribute"); + + OS << " " << Attribute << " = (Bits & " << Instance << ") != 0;\n"; + } + + if (HasItineraries) { + OS << "\n" + << " InstrItinerary *Itinerary = (InstrItinerary *)" + "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" + " InstrItins = InstrItineraryData(Stages, Itinerary);\n"; + } + + OS << "}\n"; + } + + // + // SubtargetEmitter::run - Main subtarget enumeration emitter. + // + void SubtargetEmitter::run(std::ostream &OS) { + Target = CodeGenTarget().getName(); + + EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); + + OS << "#include \"llvm/Target/SubtargetFeature.h\"\n"; + OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n"; + + Enumeration(OS, "FuncUnit", true); + OS<<"\n"; + // Enumeration(OS, "InstrItinClass", false); + // OS<<"\n"; + Enumeration(OS, "SubtargetFeature", true); + OS<<"\n"; + FeatureKeyValues(OS); + OS<<"\n"; + CPUKeyValues(OS); + OS<<"\n"; + EmitData(OS); + OS<<"\n"; + ParseFeaturesFunction(OS); + } Index: llvm/utils/TableGen/SubtargetEmitter.h diff -c /dev/null llvm/utils/TableGen/SubtargetEmitter.h:1.7.2.2 *** /dev/null Wed Nov 16 12:33:56 2005 --- llvm/utils/TableGen/SubtargetEmitter.h Wed Nov 16 12:33:45 2005 *************** *** 0 **** --- 1,62 ---- + //===- SubtargetEmitter.h - Generate subtarget enumerations -----*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by James M. Laskey and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This tablegen backend emits subtarget enumerations. + // + //===----------------------------------------------------------------------===// + + #ifndef SUBTARGET_EMITTER_H + #define SUBTARGET_EMITTER_H + + #include "TableGenBackend.h" + #include "llvm/Target/TargetInstrItineraries.h" + #include <vector> + #include <map> + #include <string> + + + namespace llvm { + + class SubtargetEmitter : public TableGenBackend { + + RecordKeeper &Records; + std::string Target; + bool HasItineraries; + + void Enumeration(std::ostream &OS, const char *ClassName, bool isBits); + void FeatureKeyValues(std::ostream &OS); + void CPUKeyValues(std::ostream &OS); + unsigned CollectAllItinClasses(std::ostream &OS, + std::map<std::string, unsigned> &ItinClassesMap); + void FormItineraryString(Record *ItinData, std::string &ItinString, + unsigned &NStages); + void EmitStageData(std::ostream &OS, unsigned NItinClasses, + std::map<std::string, unsigned> &ItinClassesMap, + std::vector<std::vector<InstrItinerary> > &ProcList); + void EmitProcessorData(std::ostream &OS, + std::vector<std::vector<InstrItinerary> > &ProcList); + void EmitProcessorLookup(std::ostream &OS); + void EmitData(std::ostream &OS); + void ParseFeaturesFunction(std::ostream &OS); + + public: + SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {} + + // run - Output the subtarget enumerations, returning true on failure. + void run(std::ostream &o); + + }; + + + } // End llvm namespace + + #endif + + + Index: llvm/utils/TableGen/TableGen.cpp diff -u llvm/utils/TableGen/TableGen.cpp:1.39 llvm/utils/TableGen/TableGen.cpp:1.39.2.1 --- llvm/utils/TableGen/TableGen.cpp:1.39 Fri Sep 2 20:14:03 2005 +++ llvm/utils/TableGen/TableGen.cpp Wed Nov 16 12:33:45 2005 @@ -23,8 +23,8 @@ #include "RegisterInfoEmitter.h" #include "InstrInfoEmitter.h" #include "AsmWriterEmitter.h" -#include "InstrSelectorEmitter.h" #include "DAGISelEmitter.h" +#include "SubtargetEmitter.h" #include <algorithm> #include <cstdio> #include <fstream> @@ -34,8 +34,9 @@ PrintRecords, GenEmitter, GenRegisterEnums, GenRegister, GenRegisterHeader, - GenInstrEnums, GenInstrs, GenAsmWriter, GenInstrSelector, + GenInstrEnums, GenInstrs, GenAsmWriter, GenDAGISel, + GenSubtarget, PrintEnums, Parse }; @@ -59,10 +60,10 @@ "Generate instruction descriptions"), clEnumValN(GenAsmWriter, "gen-asm-writer", "Generate assembly writer"), - clEnumValN(GenInstrSelector, "gen-instr-selector", - "Generate an instruction selector"), clEnumValN(GenDAGISel, "gen-dag-isel", "Generate a DAG instruction selector"), + clEnumValN(GenSubtarget, "gen-subtarget", + "Generate subtarget enumerations"), clEnumValN(PrintEnums, "print-enums", "Print enum values for a class"), clEnumValN(Parse, "parse", @@ -466,12 +467,12 @@ AsmWriterEmitter(Records).run(*Out); break; - case GenInstrSelector: - InstrSelectorEmitter(Records).run(*Out); - break; case GenDAGISel: DAGISelEmitter(Records).run(*Out); break; + case GenSubtarget: + SubtargetEmitter(Records).run(*Out); + break; case PrintEnums: { std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits