From d7349194650386d97a1d779369cb46f20ba9f252 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 19 Mar 2010 21:37:09 +0000 Subject: [PATCH] major surgery on tblgen: generalize TreePatternNode to maintain a list of types (one for each result of the node) instead of a single type. There are liberal hacks added to emulate the old behavior in various situations, but they can start disolving now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98999 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/CodeGenDAGPatterns.cpp | 350 +++++++++++++++++--------- utils/TableGen/CodeGenDAGPatterns.h | 61 +++-- utils/TableGen/DAGISelEmitter.cpp | 4 +- utils/TableGen/DAGISelMatcherGen.cpp | 25 +- utils/TableGen/FastISelEmitter.cpp | 21 +- 5 files changed, 301 insertions(+), 160 deletions(-) diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 2ade4e32d35..2c9b8fd6f8d 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -566,6 +566,7 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const { unsigned NumResults = NodeInfo.getNumResults(); + unsigned ResNo = 0; // TODO: Set to the result # we're working with. assert(NumResults <= 1 && "We only work with nodes with zero or one result so far!"); @@ -582,24 +583,25 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, default: assert(0 && "Unknown constraint type!"); case SDTCisVT: // Operand must be a particular type. - return NodeToApply->UpdateNodeType(x.SDTCisVT_Info.VT, TP); + return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP); case SDTCisPtrTy: // Operand must be same as target pointer type. - return NodeToApply->UpdateNodeType(MVT::iPTR, TP); + return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP); case SDTCisInt: // Require it to be one of the legal integer VTs. - return NodeToApply->getExtType().EnforceInteger(TP); + return NodeToApply->getExtType(ResNo).EnforceInteger(TP); case SDTCisFP: // Require it to be one of the legal fp VTs. - return NodeToApply->getExtType().EnforceFloatingPoint(TP); + return NodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP); case SDTCisVec: // Require it to be one of the legal vector VTs. - return NodeToApply->getExtType().EnforceVector(TP); + return NodeToApply->getExtType(ResNo).EnforceVector(TP); case SDTCisSameAs: { + unsigned OResNo = 0; // FIXME: getOperandNum should return pair. TreePatternNode *OtherNode = getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults); - return NodeToApply->UpdateNodeType(OtherNode->getExtType(), TP) | - OtherNode->UpdateNodeType(NodeToApply->getExtType(), TP); + return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)| + OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP); } case SDTCisVTSmallerThanOp: { // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must @@ -614,40 +616,44 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, if (!isInteger(VT)) TP.error(N->getOperator()->getName() + " VT operand must be integer!"); + unsigned OResNo = 0; // FIXME: getOperandNum should return pair. TreePatternNode *OtherNode = getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N,NumResults); // It must be integer. - bool MadeChange = OtherNode->getExtType().EnforceInteger(TP); + bool MadeChange = OtherNode->getExtType(OResNo).EnforceInteger(TP); // This doesn't try to enforce any information on the OtherNode, it just // validates it when information is determined. - if (OtherNode->hasTypeSet() && OtherNode->getType() <= VT) - OtherNode->UpdateNodeType(MVT::Other, TP); // Throw an error. + if (OtherNode->hasTypeSet(OResNo) && OtherNode->getType(OResNo) <= VT) + OtherNode->UpdateNodeType(OResNo, MVT::Other, TP); // Throw an error. return MadeChange; } case SDTCisOpSmallerThanOp: { + unsigned BResNo = 0; // FIXME: getOperandNum should return pair. TreePatternNode *BigOperand = getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NumResults); - return NodeToApply->getExtType(). - EnforceSmallerThan(BigOperand->getExtType(), TP); + return NodeToApply->getExtType(ResNo). + EnforceSmallerThan(BigOperand->getExtType(BResNo), TP); } case SDTCisEltOfVec: { + unsigned VResNo = 0; // FIXME: getOperandNum should return pair. TreePatternNode *VecOperand = getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NumResults); - if (VecOperand->hasTypeSet()) { - if (!isVector(VecOperand->getType())) + if (VecOperand->hasTypeSet(VResNo)) { + if (!isVector(VecOperand->getType(VResNo))) TP.error(N->getOperator()->getName() + " VT operand must be a vector!"); - EVT IVT = VecOperand->getType(); + EVT IVT = VecOperand->getType(VResNo); IVT = IVT.getVectorElementType(); - return NodeToApply->UpdateNodeType(IVT.getSimpleVT().SimpleTy, TP); + return NodeToApply->UpdateNodeType(ResNo, IVT.getSimpleVT().SimpleTy, TP); } - if (NodeToApply->hasTypeSet() && VecOperand->getExtType().hasVectorTypes()){ + if (NodeToApply->hasTypeSet(ResNo) && + VecOperand->getExtType(VResNo).hasVectorTypes()){ // Filter vector types out of VecOperand that don't have the right element // type. - return VecOperand->getExtType(). - EnforceVectorEltTypeIs(NodeToApply->getType(), TP); + return VecOperand->getExtType(VResNo). + EnforceVectorEltTypeIs(NodeToApply->getType(ResNo), TP); } return false; } @@ -740,17 +746,73 @@ TreePatternNode::~TreePatternNode() { #endif } - +static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { + if (Operator->getName() == "set" || + Operator->getName() == "implicit" || + Operator->getName() == "parallel") + return 0; // All return nothing. + + if (Operator->isSubClassOf("Intrinsic")) { + unsigned NumRes = CDP.getIntrinsic(Operator).IS.RetVTs.size(); + if (NumRes == 1 && CDP.getIntrinsic(Operator).IS.RetVTs[0] == MVT::isVoid) + return 0; + return NumRes; + } + + if (Operator->isSubClassOf("SDNode")) + return CDP.getSDNodeInfo(Operator).getNumResults(); + + if (Operator->isSubClassOf("PatFrag")) { + // If we've already parsed this pattern fragment, get it. Otherwise, handle + // the forward reference case where one pattern fragment references another + // before it is processed. + if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) + return PFRec->getOnlyTree()->getNumTypes(); + + // Get the result tree. + DagInit *Tree = Operator->getValueAsDag("Fragment"); + Record *Op = 0; + if (Tree && dynamic_cast(Tree->getOperator())) + Op = dynamic_cast(Tree->getOperator())->getDef(); + assert(Op && "Invalid Fragment"); + return GetNumNodeResults(Op, CDP); + } + + if (Operator->isSubClassOf("Instruction")) { + CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); + + // FIXME: Handle implicit defs right. + if (InstInfo.NumDefs != 0) + return 1; // FIXME: Handle inst results right! + + if (!InstInfo.ImplicitDefs.empty()) { + // Add on one implicit def if it has a resolvable type. + Record *FirstImplicitDef = InstInfo.ImplicitDefs[0]; + assert(FirstImplicitDef->isSubClassOf("Register")); + const std::vector &RegVTs = + CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); + if (RegVTs.size() == 1) + return 1; + } + return 0; + } + + if (Operator->isSubClassOf("SDNodeXForm")) + return 1; // FIXME: Generalize SDNodeXForm + + Operator->dump(); + errs() << "Unhandled node in GetNumNodeResults\n"; + exit(1); +} void TreePatternNode::print(raw_ostream &OS) const { - if (isLeaf()) { + if (isLeaf()) OS << *getLeafValue(); - } else { + else OS << '(' << getOperator()->getName(); - } - - if (!isTypeCompletelyUnknown()) - OS << ':' << getExtType().getName(); + + for (unsigned i = 0, e = Types.size(); i != e; ++i) + OS << ':' << getExtType(i).getName(); if (!isLeaf()) { if (getNumChildren() != 0) { @@ -786,7 +848,7 @@ void TreePatternNode::dump() const { bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, const MultipleUseVarSet &DepVars) const { if (N == this) return true; - if (N->isLeaf() != isLeaf() || getExtType() != N->getExtType() || + if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() || getPredicateFns() != N->getPredicateFns() || getTransformFn() != N->getTransformFn()) return false; @@ -815,16 +877,16 @@ bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, TreePatternNode *TreePatternNode::clone() const { TreePatternNode *New; if (isLeaf()) { - New = new TreePatternNode(getLeafValue()); + New = new TreePatternNode(getLeafValue(), getNumTypes()); } else { std::vector CChildren; CChildren.reserve(Children.size()); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) CChildren.push_back(getChild(i)->clone()); - New = new TreePatternNode(getOperator(), CChildren); + New = new TreePatternNode(getOperator(), CChildren, getNumTypes()); } New->setName(getName()); - New->setType(getExtType()); + New->Types = Types; New->setPredicateFns(getPredicateFns()); New->setTransformFn(getTransformFn()); return New; @@ -832,7 +894,8 @@ TreePatternNode *TreePatternNode::clone() const { /// RemoveAllTypes - Recursively strip all the types of this tree. void TreePatternNode::RemoveAllTypes() { - setType(EEVT::TypeSet()); // Reset to unknown type. + for (unsigned i = 0, e = Types.size(); i != e; ++i) + Types[i] = EEVT::TypeSet(); // Reset to unknown type. if (isLeaf()) return; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) getChild(i)->RemoveAllTypes(); @@ -914,7 +977,8 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { } FragTree->setName(getName()); - FragTree->UpdateNodeType(getExtType(), TP); + for (unsigned i = 0, e = Types.size(); i != e; ++i) + FragTree->UpdateNodeType(i, getExtType(i), TP); // Transfer in the old predicates. for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i) @@ -932,8 +996,10 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { /// type which should be applied to it. This will infer the type of register /// references from the register file information, for example. /// -static EEVT::TypeSet getImplicitType(Record *R, bool NotRegisters, - TreePattern &TP) { +static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, + bool NotRegisters, TreePattern &TP) { + assert(ResNo == 0 && "FIXME: Unhandled result number"); + // Check to see if this is a register or a register class. if (R->isSubClassOf("RegisterClass")) { if (NotRegisters) @@ -1044,17 +1110,23 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (isLeaf()) { if (DefInit *DI = dynamic_cast(getLeafValue())) { // If it's a regclass or something else known, include the type. - return UpdateNodeType(getImplicitType(DI->getDef(), NotRegisters, TP),TP); + bool MadeChange = false; + for (unsigned i = 0, e = Types.size(); i != e; ++i) + MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i, + NotRegisters, TP), TP); + return MadeChange; } if (IntInit *II = dynamic_cast(getLeafValue())) { + assert(Types.size() == 1 && "Invalid IntInit"); + // Int inits are always integers. :) - bool MadeChange = Type.EnforceInteger(TP); + bool MadeChange = Types[0].EnforceInteger(TP); - if (!hasTypeSet()) + if (!Types[0].isConcrete()) return MadeChange; - MVT::SimpleValueType VT = getType(); + MVT::SimpleValueType VT = getType(0); if (VT == MVT::iPTR || VT == MVT::iPTRAny) return MadeChange; @@ -1075,7 +1147,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return MadeChange; TP.error("Integer value '" + itostr(II->getValue())+ - "' is out of range for type '" + getEnumName(getType()) + "'!"); + "' is out of range for type '" + getEnumName(getType(0)) + "'!"); return MadeChange; } return false; @@ -1083,27 +1155,31 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // special handling for set, which isn't really an SDNode. if (getOperator()->getName() == "set") { - assert (getNumChildren() >= 2 && "Missing RHS of a set?"); + assert(getNumTypes() == 0 && "Set doesn't produce a value"); + assert(getNumChildren() >= 2 && "Missing RHS of a set?"); unsigned NC = getNumChildren(); - bool MadeChange = false; + + TreePatternNode *SetVal = getChild(NC-1); + bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters); + for (unsigned i = 0; i < NC-1; ++i) { - MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters); - MadeChange |= getChild(NC-1)->ApplyTypeConstraints(TP, NotRegisters); + TreePatternNode *Child = getChild(i); + MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); // Types of operands must match. - MadeChange |=getChild(i)->UpdateNodeType(getChild(NC-1)->getExtType(),TP); - MadeChange |=getChild(NC-1)->UpdateNodeType(getChild(i)->getExtType(),TP); - MadeChange |=UpdateNodeType(MVT::isVoid, TP); + MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP); + MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP); } return MadeChange; } if (getOperator()->getName() == "implicit" || getOperator()->getName() == "parallel") { + assert(getNumTypes() == 0 && "Node doesn't produce a value"); + bool MadeChange = false; for (unsigned i = 0; i < getNumChildren(); ++i) MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters); - MadeChange |= UpdateNodeType(MVT::isVoid, TP); return MadeChange; } @@ -1112,13 +1188,16 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters); MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters); + assert(getChild(0)->getNumTypes() == 1 && + getChild(1)->getNumTypes() == 1 && "Unhandled case"); + // child #1 of COPY_TO_REGCLASS should be a register class. We don't care // what type it gets, so if it didn't get a concrete type just give it the // first viable type from the reg class. - if (!getChild(1)->hasTypeSet() && - !getChild(1)->getExtType().isCompletelyUnknown()) { - MVT::SimpleValueType RCVT = getChild(1)->getExtType().getTypeList()[0]; - MadeChange |= getChild(1)->UpdateNodeType(RCVT, TP); + if (!getChild(1)->hasTypeSet(0) && + !getChild(1)->getExtType(0).isCompletelyUnknown()) { + MVT::SimpleValueType RCVT = getChild(1)->getExtType(0).getTypeList()[0]; + MadeChange |= getChild(1)->UpdateNodeType(0, RCVT, TP); } return MadeChange; } @@ -1129,22 +1208,26 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Apply the result type to the node. unsigned NumRetVTs = Int->IS.RetVTs.size(); unsigned NumParamVTs = Int->IS.ParamVTs.size(); - + if (NumRetVTs == 1 && Int->IS.RetVTs[0] == MVT::isVoid) + NumRetVTs = 0; + for (unsigned i = 0, e = NumRetVTs; i != e; ++i) - MadeChange |= UpdateNodeType(Int->IS.RetVTs[i], TP); + MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); - if (getNumChildren() != NumParamVTs + NumRetVTs) + if (getNumChildren() != NumParamVTs + 1) TP.error("Intrinsic '" + Int->Name + "' expects " + - utostr(NumParamVTs + NumRetVTs - 1) + " operands, not " + + utostr(NumParamVTs) + " operands, not " + utostr(getNumChildren() - 1) + " operands!"); // Apply type info to the intrinsic ID. - MadeChange |= getChild(0)->UpdateNodeType(MVT::iPTR, TP); + MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); - for (unsigned i = NumRetVTs, e = getNumChildren(); i != e; ++i) { - MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i - NumRetVTs]; - MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP); - MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); + for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) { + MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters); + + MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i]; + assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case"); + MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP); } return MadeChange; } @@ -1155,18 +1238,14 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { bool MadeChange = NI.ApplyTypeConstraints(this, TP); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); - // Branch, etc. do not produce results and top-level forms in instr pattern - // must have void types. - if (NI.getNumResults() == 0) - MadeChange |= UpdateNodeType(MVT::isVoid, TP); - - return MadeChange; + return MadeChange; } if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = CDP.getInstruction(getOperator()); + unsigned ResNo = 0; assert(Inst.getNumResults() <= 1 && - "Only supports zero or one result instrs!"); + "FIXME: Only supports zero or one result instrs!"); CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(getOperator()); @@ -1195,23 +1274,23 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(FirstImplicitDef->isSubClassOf("Register")); const std::vector &RegVTs = CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); - if (RegVTs.size() == 1) + if (RegVTs.size() == 1) // FIXME: Generalize. ResultType = EEVT::TypeSet(RegVTs); - else - ResultType = EEVT::TypeSet(MVT::isVoid, TP); } else { // Otherwise, the instruction produces no value result. - // FIXME: Model "no result" different than "one result that is void" - ResultType = EEVT::TypeSet(MVT::isVoid, TP); } - bool MadeChange = UpdateNodeType(ResultType, TP); + bool MadeChange = false; + + if (!ResultType.isCompletelyUnknown()) + MadeChange |= UpdateNodeType(ResNo, ResultType, TP); // If this is an INSERT_SUBREG, constrain the source and destination VTs to // be the same. if (getOperator()->getName() == "INSERT_SUBREG") { - MadeChange |= UpdateNodeType(getChild(0)->getExtType(), TP); - MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP); + assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); + MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); + MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); } unsigned ChildNo = 0; @@ -1233,15 +1312,17 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MVT::SimpleValueType VT; TreePatternNode *Child = getChild(ChildNo++); + assert(Child->getNumTypes() == 1 && "Unknown case?"); + if (OperandNode->isSubClassOf("RegisterClass")) { const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(OperandNode); - MadeChange |= Child->UpdateNodeType(RC.getValueTypes(), TP); + MadeChange |= Child->UpdateNodeType(0, RC.getValueTypes(), TP); } else if (OperandNode->isSubClassOf("Operand")) { VT = getValueType(OperandNode->getValueAsDef("Type")); - MadeChange |= Child->UpdateNodeType(VT, TP); + MadeChange |= Child->UpdateNodeType(0, VT, TP); } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP); + MadeChange |= Child->UpdateNodeType(0, MVT::iPTR, TP); } else if (OperandNode->getName() == "unknown") { // Nothing to do. } else { @@ -1373,6 +1454,7 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) { ComputeNamedNodes(N->getChild(i)); } + TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { DefInit *OpDef = dynamic_cast(Dag->getOperator()); if (!OpDef) error("Pattern has unexpected operator type!"); @@ -1401,11 +1483,11 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { Args.push_back(Dag->getArgName(0)); } - New = new TreePatternNode(DI); + New = new TreePatternNode(DI, 1); } else if (DagInit *DI = dynamic_cast(Arg)) { New = ParseTreePattern(DI); } else if (IntInit *II = dynamic_cast(Arg)) { - New = new TreePatternNode(II); + New = new TreePatternNode(II, 1); if (!Dag->getArgName(0).empty()) error("Constant int argument should not have a name!"); } else if (BitsInit *BI = dynamic_cast(Arg)) { @@ -1414,7 +1496,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { if (II == 0 || !dynamic_cast(II)) error("Bits value must be constants!"); - New = new TreePatternNode(dynamic_cast(II)); + New = new TreePatternNode(dynamic_cast(II), 1); if (!Dag->getArgName(0).empty()) error("Constant int argument should not have a name!"); } else { @@ -1424,7 +1506,8 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { } // Apply the type cast. - New->UpdateNodeType(getValueType(Operator), *this); + assert(New->getNumTypes() == 1 && "FIXME: Unhandled"); + New->UpdateNodeType(0, getValueType(Operator), *this); if (New->getNumChildren() == 0) New->setName(Dag->getArgName(0)); return New; @@ -1463,7 +1546,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { std::vector >())); --i; // Revisit this node... } else { - TreePatternNode *Node = new TreePatternNode(DefI); + TreePatternNode *Node = new TreePatternNode(DefI, 1); Node->setName(Dag->getArgName(i)); Children.push_back(Node); @@ -1475,7 +1558,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { } } } else if (IntInit *II = dynamic_cast(Arg)) { - TreePatternNode *Node = new TreePatternNode(II); + TreePatternNode *Node = new TreePatternNode(II, 1); if (!Dag->getArgName(i).empty()) error("Constant int argument should not have a name!"); Children.push_back(Node); @@ -1485,7 +1568,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { if (II == 0 || !dynamic_cast(II)) error("Bits value must be constants!"); - TreePatternNode *Node = new TreePatternNode(dynamic_cast(II)); + TreePatternNode *Node = new TreePatternNode(dynamic_cast(II),1); if (!Dag->getArgName(i).empty()) error("Constant int argument should not have a name!"); Children.push_back(Node); @@ -1516,11 +1599,12 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); } - TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID)); + TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1); Children.insert(Children.begin(), IIDNode); } - TreePatternNode *Result = new TreePatternNode(Operator, Children); + unsigned NumResults = GetNumNodeResults(Operator, CDP); + TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); Result->setName(Dag->getName()); return Result; } @@ -1567,7 +1651,11 @@ InferAllTypes(const StringMap > *InNamedTypes) { continue; } - MadeChange |=Nodes[i]->UpdateNodeType(InNodes[0]->getExtType(),*this); + assert(Nodes[i]->getNumTypes() == 1 & + InNodes[0]->getNumTypes() == 1 && + "FIXME: cannot name multiple result nodes yet"); + MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0), + *this); } } @@ -1575,8 +1663,12 @@ InferAllTypes(const StringMap > *InNamedTypes) { // same type. if (I->second.size() > 1) { for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) { - MadeChange |=Nodes[i]->UpdateNodeType(Nodes[i+1]->getExtType(),*this); - MadeChange |=Nodes[i+1]->UpdateNodeType(Nodes[i]->getExtType(),*this); + TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1]; + assert(N1->getNumTypes() == 1 & N2->getNumTypes() == 1 && + "FIXME: cannot name multiple result nodes yet"); + + MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this); + MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this); } } } @@ -1874,7 +1966,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, // Ensure that the inputs agree if we've already seen this input. if (Rec != SlotRec) I->error("All $" + Pat->getName() + " inputs must agree with each other"); - if (Slot->getExtType() != Pat->getExtType()) + if (Slot->getExtTypes() != Pat->getExtTypes()) I->error("All $" + Pat->getName() + " inputs must agree with each other"); return true; } @@ -1913,7 +2005,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, // If this is not a set, verify that the children nodes are not void typed, // and recurse. for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { - if (Pat->getChild(i)->getType() == MVT::isVoid) + if (Pat->getChild(i)->getNumTypes() == 0) I->error("Cannot have void nodes inside of patterns!"); FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults, InstImpInputs, InstImpResults); @@ -2168,7 +2260,7 @@ void CodeGenDAGPatterns::ParseInstructions() { // fill in the InstResults map. for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { TreePatternNode *Pat = I->getTree(j); - if (!Pat->hasTypeSet() || Pat->getType() != MVT::isVoid) + if (Pat->getNumTypes() != 0) I->error("Top-level forms in instruction pattern should have" " void types"); @@ -2188,7 +2280,7 @@ void CodeGenDAGPatterns::ParseInstructions() { // Check that all of the results occur first in the list. std::vector Results; - TreePatternNode *Res0Node = NULL; + TreePatternNode *Res0Node = 0; for (unsigned i = 0; i != NumResults; ++i) { if (i == CGI.OperandList.size()) I->error("'" + InstResults.begin()->first + @@ -2266,7 +2358,7 @@ void CodeGenDAGPatterns::ParseInstructions() { OpNode->setTransformFn(0); std::vector Children; Children.push_back(OpNode); - OpNode = new TreePatternNode(Xform, Children); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } ResultNodeOperands.push_back(OpNode); @@ -2277,10 +2369,11 @@ void CodeGenDAGPatterns::ParseInstructions() { " occurs in pattern but not in operands list!"); TreePatternNode *ResultPattern = - new TreePatternNode(I->getRecord(), ResultNodeOperands); + new TreePatternNode(I->getRecord(), ResultNodeOperands, + GetNumNodeResults(I->getRecord(), *this)); // Copy fully inferred output node type to instruction result pattern. - if (NumResults > 0) - ResultPattern->setType(Res0Node->getExtType()); + for (unsigned i = 0; i != NumResults; ++i) + ResultPattern->setType(i, Res0Node->getExtType(i)); // Create and insert the instruction. // FIXME: InstImpResults and InstImpInputs should not be part of @@ -2341,7 +2434,7 @@ static void FindNames(const TreePatternNode *P, // If this is the first instance of the name, remember the node. if (Rec.second++ == 0) Rec.first = P; - else if (Rec.first->getType() != P->getType()) + else if (Rec.first->getExtTypes() != P->getExtTypes()) PatternTop->error("repetition of value: $" + P->getName() + " where different uses have different types!"); } @@ -2429,23 +2522,29 @@ static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { // If this type is already concrete or completely unknown we can't do // anything. - if (N->getExtType().isCompletelyUnknown() || N->getExtType().isConcrete()) - return false; + for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) { + if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete()) + continue; + + // Otherwise, force its type to the first possibility (an arbitrary choice). + if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP)) + return true; + } - // Otherwise, force its type to the first possibility (an arbitrary choice). - return N->getExtType().MergeInTypeInfo(N->getExtType().getTypeList()[0], TP); + return false; } void CodeGenDAGPatterns::ParsePatterns() { std::vector Patterns = Records.getAllDerivedDefinitions("Pattern"); for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - DagInit *Tree = Patterns[i]->getValueAsDag("PatternToMatch"); + Record *CurPattern = Patterns[i]; + DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); DefInit *OpDef = dynamic_cast(Tree->getOperator()); Record *Operator = OpDef->getDef(); TreePattern *Pattern; if (Operator->getName() != "parallel") - Pattern = new TreePattern(Patterns[i], Tree, true, *this); + Pattern = new TreePattern(CurPattern, Tree, true, *this); else { std::vector Values; RecTy *ListTy = 0; @@ -2470,17 +2569,17 @@ void CodeGenDAGPatterns::ParsePatterns() { } } ListInit *LI = new ListInit(Values, new ListRecTy(ListTy)); - Pattern = new TreePattern(Patterns[i], LI, true, *this); + Pattern = new TreePattern(CurPattern, LI, true, *this); } // Inline pattern fragments into it. Pattern->InlinePatternFragments(); - ListInit *LI = Patterns[i]->getValueAsListInit("ResultInstrs"); + ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); if (LI->getSize() == 0) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(Patterns[i], LI, false, *this); + TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); // Inline pattern fragments into it. Result->InlinePatternFragments(); @@ -2508,12 +2607,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. - if (!Result->getTree(0)->getExtType().isVoid() && - !Pattern->getTree(0)->getExtType().isVoid()) { + for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + Pattern->getTree(0)->getNumTypes()); + i != e; ++i) { IterateInference = Pattern->getTree(0)-> - UpdateNodeType(Result->getTree(0)->getExtType(), *Result); + UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); IterateInference |= Result->getTree(0)-> - UpdateNodeType(Pattern->getTree(0)->getExtType(), *Result); + UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); } // If our iteration has converged and the input pattern's types are fully @@ -2559,25 +2659,29 @@ void CodeGenDAGPatterns::ParsePatterns() { OpNode->setTransformFn(0); std::vector Children; Children.push_back(OpNode); - OpNode = new TreePatternNode(Xform, Children); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } ResultNodeOperands.push_back(OpNode); } DstPattern = Result->getOnlyTree(); if (!DstPattern->isLeaf()) DstPattern = new TreePatternNode(DstPattern->getOperator(), - ResultNodeOperands); - DstPattern->setType(Result->getOnlyTree()->getExtType()); + ResultNodeOperands, + DstPattern->getNumTypes()); + + 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); Temp.InferAllTypes(); AddPatternToMatch(Pattern, - PatternToMatch(Patterns[i]->getValueAsListInit("Predicates"), - Pattern->getTree(0), - Temp.getOnlyTree(), InstImpResults, - Patterns[i]->getValueAsInt("AddedComplexity"), - Patterns[i]->getID())); + PatternToMatch(CurPattern->getValueAsListInit("Predicates"), + Pattern->getTree(0), + Temp.getOnlyTree(), InstImpResults, + CurPattern->getValueAsInt("AddedComplexity"), + CurPattern->getID())); } } @@ -2611,13 +2715,15 @@ static void CombineChildVariants(TreePatternNode *Orig, std::vector NewChildren; for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) NewChildren.push_back(ChildVariants[i][Idxs[i]]); - TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren); + TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren, + Orig->getNumTypes()); // Copy over properties. R->setName(Orig->getName()); R->setPredicateFns(Orig->getPredicateFns()); R->setTransformFn(Orig->getTransformFn()); - R->setType(Orig->getExtType()); + for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) + R->setType(i, Orig->getExtType(i)); // If this pattern cannot match, do not include it as a variant. std::string ErrString; diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 947cfe7f6dd..34fdb595c39 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -238,10 +238,10 @@ public: /// patterns), and as such should be ref counted. We currently just leak all /// TreePatternNode objects! class TreePatternNode { - /// The type of this node. Before and during type inference, this may be a - /// set of possible types. After (successful) type inference, this is a - /// single type. - EEVT::TypeSet Type; + /// The type of each node result. Before and during type inference, each + /// result may be a set of possible types. After (successful) type inference, + /// each is a single concrete type. + SmallVector Types; /// Operator - The Record for the operator if this is an interior node (not /// a leaf). @@ -265,10 +265,14 @@ class TreePatternNode { std::vector Children; public: - TreePatternNode(Record *Op, const std::vector &Ch) - : Operator(Op), Val(0), TransformFn(0), Children(Ch) { } - TreePatternNode(Init *val) // leaf ctor + TreePatternNode(Record *Op, const std::vector &Ch, + unsigned NumResults) + : Operator(Op), Val(0), TransformFn(0), Children(Ch) { + Types.resize(NumResults); + } + TreePatternNode(Init *val, unsigned NumResults) // leaf ctor : Operator(0), Val(val), TransformFn(0) { + Types.resize(NumResults); } ~TreePatternNode(); @@ -278,14 +282,24 @@ public: bool isLeaf() const { return Val != 0; } // Type accessors. - MVT::SimpleValueType getType() const { return Type.getConcrete(); } - const EEVT::TypeSet &getExtType() const { return Type; } - EEVT::TypeSet &getExtType() { return Type; } - void setType(const EEVT::TypeSet &T) { Type = T; } + unsigned getNumTypes() const { return Types.size(); } + MVT::SimpleValueType getType(unsigned ResNo) const { + return Types[ResNo].getConcrete(); + } + const SmallVectorImpl &getExtTypes() const { return Types; } + const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; } + EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; } + void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; } - bool hasTypeSet() const { return Type.isConcrete(); } - bool isTypeCompletelyUnknown() const { return Type.isCompletelyUnknown(); } - bool isTypeDynamicallyResolved() const { return Type.isDynamicallyResolved();} + bool hasTypeSet(unsigned ResNo) const { + return Types[ResNo].isConcrete(); + } + bool isTypeCompletelyUnknown(unsigned ResNo) const { + return Types[ResNo].isCompletelyUnknown(); + } + bool isTypeDynamicallyResolved(unsigned ResNo) const { + return Types[ResNo].isDynamicallyResolved(); + } Init *getLeafValue() const { assert(isLeaf()); return Val; } Record *getOperator() const { assert(!isLeaf()); return Operator; } @@ -378,18 +392,22 @@ public: // Higher level manipulation routines. /// information. If N already contains a conflicting type, then throw an /// exception. This returns true if any information was updated. /// - bool UpdateNodeType(const EEVT::TypeSet &InTy, TreePattern &TP) { - return Type.MergeInTypeInfo(InTy, TP); + bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy, + TreePattern &TP) { + return Types[ResNo].MergeInTypeInfo(InTy, TP); } - bool UpdateNodeType(MVT::SimpleValueType InTy, TreePattern &TP) { - return Type.MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP); + bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy, + TreePattern &TP) { + return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP); } /// ContainsUnresolvedType - Return true if this tree contains any /// unresolved types. bool ContainsUnresolvedType() const { - if (!hasTypeSet()) return true; + for (unsigned i = 0, e = Types.size(); i != e; ++i) + if (!Types[i].isConcrete()) return true; + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) if (getChild(i)->ContainsUnresolvedType()) return true; return false; @@ -679,6 +697,11 @@ public: assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); return PatternFragments.find(R)->second; } + TreePattern *getPatternFragmentIfRead(Record *R) const { + if (!PatternFragments.count(R)) return 0; + return PatternFragments.find(R)->second; + } + typedef std::map::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index ef9b7345115..044086add5b 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -25,7 +25,6 @@ using namespace llvm; /// patterns before small ones. This is used to determine the size of a /// pattern. static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) { - assert(P->hasTypeSet() && "Not a valid pattern node to size!"); unsigned Size = 3; // The node itself. // If the root node is a ConstantSDNode, increases its size. // e.g. (set R32:$dst, 0). @@ -49,7 +48,8 @@ static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) { // Count children in the count if they are also nodes. for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) { TreePatternNode *Child = P->getChild(i); - if (!Child->isLeaf() && Child->getType() != MVT::Other) + if (!Child->isLeaf() && Child->getNumTypes() && + Child->getType(0) != MVT::Other) Size += getPatternSize(Child, CGP); else if (Child->isLeaf()) { if (dynamic_cast(Child->getLeafValue())) diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 0c0b7265e5f..da6f6afd82d 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -409,8 +409,10 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and // reinfer any correlated types. bool DoTypeCheck = false; - if (NodeNoTypes->getExtType() != N->getExtType()) { - NodeNoTypes->setType(N->getExtType()); + if (NodeNoTypes->getNumTypes() != 0 && + NodeNoTypes->getExtType(0) != N->getExtType(0)) { + assert(NodeNoTypes->getNumTypes() == 1 && "FIXME: Handle multiple results"); + NodeNoTypes->setType(0, N->getExtType(0)); InferPossibleTypes(); DoTypeCheck = true; } @@ -442,8 +444,10 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i])); - if (DoTypeCheck) - AddMatcher(new CheckTypeMatcher(N->getType())); + if (DoTypeCheck) { + assert(N->getNumTypes() == 1); + AddMatcher(new CheckTypeMatcher(N->getType(0))); + } } /// EmitMatcherCode - Generate the code that matches the predicate of this @@ -567,7 +571,7 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, assert(N->isLeaf() && "Must be a leaf"); if (IntInit *II = dynamic_cast(N->getLeafValue())) { - AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType())); + AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } @@ -575,13 +579,13 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, // If this is an explicit register reference, handle it. if (DefInit *DI = dynamic_cast(N->getLeafValue())) { if (DI->getDef()->isSubClassOf("Register")) { - AddMatcher(new EmitRegisterMatcher(DI->getDef(), N->getType())); + AddMatcher(new EmitRegisterMatcher(DI->getDef(), N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } if (DI->getDef()->getName() == "zero_reg") { - AddMatcher(new EmitRegisterMatcher(0, N->getType())); + AddMatcher(new EmitRegisterMatcher(0, N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } @@ -708,10 +712,11 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // Determine the result types. SmallVector ResultVTs; - if (N->getType() != MVT::isVoid) { + if (N->getNumTypes()) { // FIXME2: If the node has multiple results, we should add them. For now, // preserve existing behavior?! - ResultVTs.push_back(N->getType()); + assert(N->getNumTypes() == 1); + ResultVTs.push_back(N->getType(0)); } // If this is the root instruction of a pattern that has physical registers in @@ -723,7 +728,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // If the root came from an implicit def in the instruction handling stuff, // don't re-add it. Record *HandledReg = 0; - if (NumResults == 0 && N->getType() != MVT::isVoid && + if (NumResults == 0 && N->getNumTypes() != 0 && !II.ImplicitDefs.empty()) HandledReg = II.ImplicitDefs[0]; diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 52f9563ec72..23f09a5bd31 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -70,13 +70,16 @@ struct OperandsSignature { for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { TreePatternNode *Op = InstPatNode->getChild(i); // For now, filter out any operand with a predicate. - if (!Op->getPredicateFns().empty()) - return false; // For now, filter out any operand with multiple values. - assert(Op->hasTypeSet() && "Type infererence not done?"); + if (!Op->getPredicateFns().empty() || + Op->getNumTypes() != 1) + return false; + + assert(Op->hasTypeSet(0) && "Type infererence not done?"); // For now, all the operands must have the same type. - if (Op->getType() != VT) + if (Op->getType(0) != VT) return false; + if (!Op->isLeaf()) { if (Op->getOperator()->getName() == "imm") { Operands.push_back("i"); @@ -295,10 +298,14 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { Record *InstPatOp = InstPatNode->getOperator(); std::string OpcodeName = getOpcodeName(InstPatOp, CGP); - MVT::SimpleValueType RetVT = InstPatNode->getType(); + assert(InstPatNode->getNumTypes() <= 1); + MVT::SimpleValueType RetVT = MVT::isVoid; + if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getType(0); MVT::SimpleValueType VT = RetVT; - if (InstPatNode->getNumChildren()) - VT = InstPatNode->getChild(0)->getType(); + if (InstPatNode->getNumChildren()) { + assert(InstPatNode->getChild(0)->getNumTypes() == 1); + VT = InstPatNode->getChild(0)->getType(0); + } // For now, filter out instructions which just set a register to // an Operand or an immediate, like MOV32ri. -- 2.34.1