From a28aec1da7c0dccb80d9ccb484b968850dd4c7dc Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 15 Sep 2005 22:23:50 +0000 Subject: [PATCH] teach the type inference code how to infer types for instructions and node xforms. Run type inference on result patterns, so we always have fully typed results (and to catch errors in .td files). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23369 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/DAGISelEmitter.cpp | 88 +++++++++++++++++++++---------- utils/TableGen/DAGISelEmitter.h | 13 +++-- 2 files changed, 67 insertions(+), 34 deletions(-) diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index e5a436bb133..79ef2311c3d 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -324,14 +324,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP) { for (unsigned i = 0, e = getNumChildren(); i != e; ++i) MadeChange |= getChild(i)->ApplyTypeConstraints(TP); return MadeChange; - } else { - assert(getOperator()->isSubClassOf("Instruction") && "Unknown node type!"); - + } else if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = TP.getDAGISelEmitter().getInstruction(getOperator()); - // TODO: type inference for instructions. - return false; + assert(Inst.getNumResults() == 1 && "Only supports one result instrs!"); + // Apply the result type to the node + bool MadeChange = UpdateNodeType(Inst.getResultType(0), TP); + + if (getNumChildren() != Inst.getNumOperands()) + TP.error("Instruction '" + getOperator()->getName() + " expects " + + utostr(Inst.getNumOperands()) + " operands, not " + + utostr(getNumChildren()) + " operands!"); + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { + MadeChange |= getChild(i)->UpdateNodeType(Inst.getOperandType(i), TP); + MadeChange |= getChild(i)->ApplyTypeConstraints(TP); + } + return MadeChange; + } else { + assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); + + // Node transforms always take one operand, and take and return the same + // type. + if (getNumChildren() != 1) + TP.error("Node transform '" + getOperator()->getName() + + "' requires one operand!"); + bool MadeChange = UpdateNodeType(getChild(0)->getType(), TP); + MadeChange |= getChild(0)->UpdateNodeType(getType(), TP); + return MadeChange; } } @@ -340,13 +360,24 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP) { // TreePattern implementation // -TreePattern::TreePattern(Record *TheRec, const std::vector &RawPat, +TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { - - for (unsigned i = 0, e = RawPat.size(); i != e; ++i) - Trees.push_back(ParseTreePattern(RawPat[i])); + for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) + Trees.push_back(ParseTreePattern((DagInit*)RawPat->getElement(i))); } +TreePattern::TreePattern(Record *TheRec, DagInit *Pat, + DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + Trees.push_back(ParseTreePattern(Pat)); +} + +TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, + DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + Trees.push_back(Pat); +} + + + void TreePattern::error(const std::string &Msg) const { dump(); throw "In " + TheRecord->getName() + ": " + Msg; @@ -550,9 +581,8 @@ void DAGISelEmitter::ParsePatternFragments(std::ostream &OS) { // First step, parse all of the fragments and emit predicate functions. OS << "\n// Predicate functions.\n"; for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { - std::vector Trees; - Trees.push_back(Fragments[i]->getValueAsDag("Fragment")); - TreePattern *P = new TreePattern(Fragments[i], Trees, *this); + DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); + TreePattern *P = new TreePattern(Fragments[i], Tree, *this); PatternFragments[Fragments[i]] = P; // Validate the argument list, converting it to map, to discard duplicates. @@ -762,12 +792,8 @@ void DAGISelEmitter::ParseInstructions() { ListInit *LI = Instrs[i]->getValueAsListInit("Pattern"); if (LI->getSize() == 0) continue; // no pattern. - std::vector Trees; - for (unsigned j = 0, e = LI->getSize(); j != e; ++j) - Trees.push_back((DagInit*)LI->getElement(j)); - // Parse the instruction. - TreePattern *I = new TreePattern(Instrs[i], Trees, *this); + TreePattern *I = new TreePattern(Instrs[i], LI, *this); // Inline pattern fragments into it. I->InlinePatternFragments(); @@ -876,11 +902,21 @@ void DAGISelEmitter::ParseInstructions() { TreePatternNode *ResultPattern = new TreePatternNode(I->getRecord(), ResultNodeOperands); + + // Create and insert the instruction. + DAGInstruction TheInst(I, ResultTypes, OperandTypes); + Instructions.insert(std::make_pair(I->getRecord(), TheInst)); + + // 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); + Temp.InferAllTypes(); + + DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second; + TheInsertedInst.setResultPattern(Temp.getOnlyTree()); DEBUG(I->dump()); - Instructions.insert(std::make_pair(I->getRecord(), - DAGInstruction(I, ResultTypes, - OperandTypes, ResultPattern))); } // If we can, convert the instructions to be patterns that are matched! @@ -909,10 +945,8 @@ void DAGISelEmitter::ParsePatterns() { std::vector Patterns = Records.getAllDerivedDefinitions("Pattern"); for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - std::vector Trees; - Trees.push_back(Patterns[i]->getValueAsDag("PatternToMatch")); - TreePattern *Pattern = new TreePattern(Patterns[i], Trees, *this); - Trees.clear(); + DagInit *Tree = Patterns[i]->getValueAsDag("PatternToMatch"); + TreePattern *Pattern = new TreePattern(Patterns[i], Tree, *this); // Inline pattern fragments into it. Pattern->InlinePatternFragments(); @@ -924,21 +958,17 @@ void DAGISelEmitter::ParsePatterns() { ListInit *LI = Patterns[i]->getValueAsListInit("ResultInstrs"); if (LI->getSize() == 0) continue; // no pattern. - for (unsigned j = 0, e = LI->getSize(); j != e; ++j) - Trees.push_back((DagInit*)LI->getElement(j)); // Parse the instruction. - TreePattern *Result = new TreePattern(Patterns[i], Trees, *this); + TreePattern *Result = new TreePattern(Patterns[i], LI, *this); // Inline pattern fragments into it. Result->InlinePatternFragments(); // 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. -#if 0 // FIXME: ENABLE when we can infer though instructions! if (!Result->InferAllTypes()) Result->error("Could not infer all types in pattern result!"); -#endif if (Result->getNumTrees() != 1) Result->error("Cannot handle instructions producing instructions " diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index bd1018b5312..de223b1cb6b 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -20,6 +20,7 @@ namespace llvm { class Record; struct Init; + class ListInit; class DagInit; class SDNodeInfo; class TreePattern; @@ -222,8 +223,9 @@ namespace llvm { /// TreePattern constructor - Parse the specified DagInits into the /// current record. - TreePattern(Record *TheRec, - const std::vector &RawPat, DAGISelEmitter &ise); + TreePattern(Record *TheRec, ListInit *RawPat, DAGISelEmitter &ise); + TreePattern(Record *TheRec, DagInit *Pat, DAGISelEmitter &ise); + TreePattern(Record *TheRec, TreePatternNode *Pat, DAGISelEmitter &ise); /// getTrees - Return the tree patterns which corresponds to this pattern. /// @@ -285,15 +287,16 @@ namespace llvm { public: DAGInstruction(TreePattern *TP, const std::vector &resultTypes, - const std::vector &operandTypes, - TreePatternNode *resultPattern) + const std::vector &operandTypes) : Pattern(TP), ResultTypes(resultTypes), OperandTypes(operandTypes), - ResultPattern(resultPattern) {} + ResultPattern(0) {} TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return ResultTypes.size(); } unsigned getNumOperands() const { return OperandTypes.size(); } + void setResultPattern(TreePatternNode *R) { ResultPattern = R; } + MVT::ValueType getResultType(unsigned RN) const { assert(RN < ResultTypes.size()); return ResultTypes[RN];