diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 529 | ||||
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.h | 15 | ||||
-rw-r--r-- | utils/TableGen/CodeGenInstruction.cpp | 20 | ||||
-rw-r--r-- | utils/TableGen/CodeGenInstruction.h | 7 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 25 | ||||
-rw-r--r-- | utils/TableGen/DAGISelEmitter.cpp | 74 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcher.cpp | 14 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcher.h | 8 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherEmitter.cpp | 57 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherGen.cpp | 97 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherOpt.cpp | 11 | ||||
-rw-r--r-- | utils/TableGen/FastISelEmitter.cpp | 4 | ||||
-rw-r--r-- | utils/TableGen/InstrInfoEmitter.cpp | 2 | ||||
-rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 13 | ||||
-rw-r--r-- | utils/TableGen/Record.cpp | 30 | ||||
-rw-r--r-- | utils/TableGen/Record.h | 12 | ||||
-rw-r--r-- | utils/TableGen/TableGen.cpp | 1 | ||||
-rwxr-xr-x | utils/buildit/build_llvm | 2 | ||||
-rw-r--r-- | utils/lit/lit/LitTestCase.py | 30 | ||||
-rw-r--r-- | utils/lit/lit/TestFormats.py | 5 | ||||
-rw-r--r-- | utils/lit/lit/TestRunner.py | 10 | ||||
-rwxr-xr-x | utils/lit/lit/lit.py | 42 |
22 files changed, 598 insertions, 410 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 4cc9b79..d2c0195 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -61,9 +61,9 @@ EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) { assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny && VTList[0] != MVT::fAny); - // Remove duplicates. + // Verify no duplicates. array_pod_sort(TypeVec.begin(), TypeVec.end()); - TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end()); + assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end()); } /// FillWithPossibleTypes - Set to all legal types and return true, only valid @@ -394,24 +394,39 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { } /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type -/// whose element is VT. -bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, +/// whose element is specified by VTOperand. +bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { - TypeSet InputSet(*this); + // "This" must be a vector and "VTOperand" must be a scalar. bool MadeChange = false; + MadeChange |= EnforceVector(TP); + MadeChange |= VTOperand.EnforceScalar(TP); + + // If we know the vector type, it forces the scalar to agree. + if (isConcrete()) { + EVT IVT = getConcrete(); + IVT = IVT.getVectorElementType(); + return MadeChange | + VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP); + } + + // If the scalar type is known, filter out vector types whose element types + // disagree. + if (!VTOperand.isConcrete()) + return MadeChange; - // If we know nothing, then get the full set. - if (TypeVec.empty()) - MadeChange = FillWithPossibleTypes(TP, isVector, "vector"); + MVT::SimpleValueType VT = VTOperand.getConcrete(); - // Filter out all the non-vector types and types which don't have the right - // element type. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isVector(TypeVec[i]) || - EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) { + TypeSet InputSet(*this); + + // Filter out all the types which don't have the right element type. + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) { TypeVec.erase(TypeVec.begin()+i--); MadeChange = true; } + } if (TypeVec.empty()) // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + @@ -476,6 +491,59 @@ void DumpDepVars(MultipleUseVarSet &DepVars) { // PatternToMatch implementation // + +/// getPatternSize - Return the 'size' of this pattern. We want to match large +/// patterns before small ones. This is used to determine the size of a +/// pattern. +static unsigned getPatternSize(const TreePatternNode *P, + const CodeGenDAGPatterns &CGP) { + unsigned Size = 3; // The node itself. + // If the root node is a ConstantSDNode, increases its size. + // e.g. (set R32:$dst, 0). + if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue())) + Size += 2; + + // FIXME: This is a hack to statically increase the priority of patterns + // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. + // Later we can allow complexity / cost for each pattern to be (optionally) + // specified. To get best possible pattern match we'll need to dynamically + // calculate the complexity of all patterns a dag can potentially map to. + const ComplexPattern *AM = P->getComplexPatternInfo(CGP); + if (AM) + Size += AM->getNumOperands() * 3; + + // If this node has some predicate function that must match, it adds to the + // complexity of this node. + if (!P->getPredicateFns().empty()) + ++Size; + + // 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->getNumTypes() && + Child->getType(0) != MVT::Other) + Size += getPatternSize(Child, CGP); + else if (Child->isLeaf()) { + if (dynamic_cast<IntInit*>(Child->getLeafValue())) + Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). + else if (Child->getComplexPatternInfo(CGP)) + Size += getPatternSize(Child, CGP); + else if (!Child->getPredicateFns().empty()) + ++Size; + } + } + + return Size; +} + +/// Compute the complexity metric for the input pattern. This roughly +/// corresponds to the number of nodes that are covered. +unsigned PatternToMatch:: +getPatternComplexity(const CodeGenDAGPatterns &CGP) const { + return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); +} + + /// getPredicateCheck - Return a single string containing all of this /// pattern's predicates concatenated with "&&" operators. /// @@ -509,6 +577,9 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { if (R->isSubClassOf("SDTCisVT")) { ConstraintType = SDTCisVT; x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT")); + if (x.SDTCisVT_Info.VT == MVT::isVoid) + throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); + } else if (R->isSubClassOf("SDTCisPtrTy")) { ConstraintType = SDTCisPtrTy; } else if (R->isSubClassOf("SDTCisInt")) { @@ -568,13 +639,6 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const { - // Check that the number of operands is sane. Negative operands -> varargs. - if (NodeInfo.getNumOperands() >= 0) { - if (N->getNumChildren() != (unsigned)NodeInfo.getNumOperands()) - TP.error(N->getOperator()->getName() + " node requires exactly " + - itostr(NodeInfo.getNumOperands()) + " operands!"); - } - unsigned ResNo = 0; // The result number being referenced. TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); @@ -612,22 +676,15 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, TP.error(N->getOperator()->getName() + " expects a VT operand!"); MVT::SimpleValueType VT = getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()); - if (!isInteger(VT)) - TP.error(N->getOperator()->getName() + " VT operand must be integer!"); + + EEVT::TypeSet TypeListTmp(VT, TP); unsigned OResNo = 0; TreePatternNode *OtherNode = getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, OResNo); - - // It must be integer. - 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(OResNo) && OtherNode->getType(OResNo) <= VT) - OtherNode->UpdateNodeType(OResNo, MVT::Other, TP); // Throw an error. - return MadeChange; + return TypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP); } case SDTCisOpSmallerThanOp: { unsigned BResNo = 0; @@ -642,22 +699,11 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, TreePatternNode *VecOperand = getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo); - if (VecOperand->hasTypeSet(VResNo)) { - if (!isVector(VecOperand->getType(VResNo))) - TP.error(N->getOperator()->getName() + " VT operand must be a vector!"); - EVT IVT = VecOperand->getType(VResNo); - IVT = IVT.getVectorElementType(); - return NodeToApply->UpdateNodeType(ResNo, IVT.getSimpleVT().SimpleTy, TP); - } - 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(VResNo). - EnforceVectorEltTypeIs(NodeToApply->getType(ResNo), TP); - } - return false; + // Filter vector types out of VecOperand that don't have the right element + // type. + return VecOperand->getExtType(VResNo). + EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP); } } return false; @@ -716,10 +762,11 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { /// getKnownType - If the type constraints on this node imply a fixed type /// (e.g. all stores return void, etc), then return it as an /// MVT::SimpleValueType. Otherwise, return EEVT::Other. -MVT::SimpleValueType SDNodeInfo::getKnownType() const { +MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { unsigned NumResults = getNumResults(); assert(NumResults <= 1 && "We only work with nodes with zero or one result so far!"); + assert(ResNo == 0 && "Only handles single result nodes so far"); for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) { // Make sure that this applies to the correct node result. @@ -750,16 +797,11 @@ TreePatternNode::~TreePatternNode() { static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->getName() == "set" || - Operator->getName() == "implicit" || - Operator->getName() == "parallel") + Operator->getName() == "implicit") 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("Intrinsic")) + return CDP.getIntrinsic(Operator).IS.RetVTs.size(); if (Operator->isSubClassOf("SDNode")) return CDP.getSDNodeInfo(Operator).getNumResults(); @@ -782,21 +824,14 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->isSubClassOf("Instruction")) { CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); + + // FIXME: Should allow access to all the results here. + unsigned NumDefsToAdd = InstInfo.NumDefs ? 1 : 0; - // 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<MVT::SimpleValueType> &RegVTs = - CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); - if (RegVTs.size() == 1) - return 1; - } - return 0; + // Add on one implicit def if it has a resolvable type. + if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) + ++NumDefsToAdd; + return NumDefsToAdd; } if (Operator->isSubClassOf("SDNodeXForm")) @@ -1000,34 +1035,49 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(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")) { + assert(ResNo == 0 && "Regclass ref only has one result!"); if (NotRegisters) return EEVT::TypeSet(); // Unknown. const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes()); - } else if (R->isSubClassOf("PatFrag")) { + } + + if (R->isSubClassOf("PatFrag")) { + assert(ResNo == 0 && "FIXME: PatFrag with multiple results?"); // Pattern fragment types will be resolved when they are inlined. return EEVT::TypeSet(); // Unknown. - } else if (R->isSubClassOf("Register")) { + } + + if (R->isSubClassOf("Register")) { + assert(ResNo == 0 && "Registers only produce one result!"); if (NotRegisters) return EEVT::TypeSet(); // Unknown. const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); return EEVT::TypeSet(T.getRegisterVTs(R)); - } else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { + } + + if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { + assert(ResNo == 0 && "This node only has one result!"); // Using a VTSDNode or CondCodeSDNode. return EEVT::TypeSet(MVT::Other, TP); - } else if (R->isSubClassOf("ComplexPattern")) { + } + + if (R->isSubClassOf("ComplexPattern")) { + assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?"); if (NotRegisters) return EEVT::TypeSet(); // Unknown. return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(), TP); - } else if (R->isSubClassOf("PointerLikeRegClass")) { + } + if (R->isSubClassOf("PointerLikeRegClass")) { + assert(ResNo == 0 && "Regclass can only have one result!"); return EEVT::TypeSet(MVT::iPTR, TP); - } else if (R->getName() == "node" || R->getName() == "srcvalue" || - R->getName() == "zero_reg") { + } + + if (R->getName() == "node" || R->getName() == "srcvalue" || + R->getName() == "zero_reg") { // Placeholder. return EEVT::TypeSet(); // Unknown. } @@ -1175,8 +1225,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return MadeChange; } - if (getOperator()->getName() == "implicit" || - getOperator()->getName() == "parallel") { + if (getOperator()->getName() == "implicit") { assert(getNumTypes() == 0 && "Node doesn't produce a value"); bool MadeChange = false; @@ -1210,8 +1259,6 @@ 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(i, Int->IS.RetVTs[i], TP); @@ -1237,6 +1284,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (getOperator()->isSubClassOf("SDNode")) { const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator()); + // Check that the number of operands is sane. Negative operands -> varargs. + if (NI.getNumOperands() >= 0 && + getNumChildren() != (unsigned)NI.getNumOperands()) + TP.error(getOperator()->getName() + " node requires exactly " + + itostr(NI.getNumOperands()) + " operands!"); + bool MadeChange = NI.ApplyTypeConstraints(this, TP); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); @@ -1245,21 +1298,20 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = CDP.getInstruction(getOperator()); - unsigned ResNo = 0; - assert(Inst.getNumResults() <= 1 && - "FIXME: Only supports zero or one result instrs!"); - CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(getOperator()); - EEVT::TypeSet ResultType; - - // Apply the result type to the node - if (InstInfo.NumDefs != 0) { // # of elements in (outs) list - Record *ResultNode = Inst.getResult(0); + bool MadeChange = false; + + // Apply the result types to the node, these come from the things in the + // (outs) list of the instruction. + // FIXME: Cap at one result so far. + unsigned NumResultsToAdd = InstInfo.NumDefs ? 1 : 0; + for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) { + Record *ResultNode = Inst.getResult(ResNo); if (ResultNode->isSubClassOf("PointerLikeRegClass")) { - ResultType = EEVT::TypeSet(MVT::iPTR, TP); + MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP); } else if (ResultNode->getName() == "unknown") { // Nothing to do. } else { @@ -1267,25 +1319,23 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { "Operands should be register classes!"); const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(ResultNode); - ResultType = RC.getValueTypes(); + MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); } - } else if (!InstInfo.ImplicitDefs.empty()) { - // If the instruction has implicit defs, the first one defines the result - // type. - Record *FirstImplicitDef = InstInfo.ImplicitDefs[0]; - assert(FirstImplicitDef->isSubClassOf("Register")); - const std::vector<MVT::SimpleValueType> &RegVTs = - CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); - if (RegVTs.size() == 1) // FIXME: Generalize. - ResultType = EEVT::TypeSet(RegVTs); - } else { - // Otherwise, the instruction produces no value result. } - bool MadeChange = false; - - if (!ResultType.isCompletelyUnknown()) - MadeChange |= UpdateNodeType(ResNo, ResultType, TP); + // If the instruction has implicit defs, we apply the first one as a result. + // FIXME: This sucks, it should apply all implicit defs. + if (!InstInfo.ImplicitDefs.empty()) { + unsigned ResNo = NumResultsToAdd; + + // FIXME: Generalize to multiple possible types and multiple possible + // ImplicitDefs. + MVT::SimpleValueType VT = + InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()); + + if (VT != MVT::Other) + MadeChange |= UpdateNodeType(ResNo, VT, TP); + } // If this is an INSERT_SUBREG, constrain the source and destination VTs to // be the same. @@ -1314,17 +1364,17 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MVT::SimpleValueType VT; TreePatternNode *Child = getChild(ChildNo++); - assert(Child->getNumTypes() == 1 && "Unknown case?"); + unsigned ChildResNo = 0; // Instructions always use res #0 of their op. if (OperandNode->isSubClassOf("RegisterClass")) { const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(OperandNode); - MadeChange |= Child->UpdateNodeType(0, RC.getValueTypes(), TP); + MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); } else if (OperandNode->isSubClassOf("Operand")) { VT = getValueType(OperandNode->getValueAsDef("Type")); - MadeChange |= Child->UpdateNodeType(0, VT, TP); + MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP); } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange |= Child->UpdateNodeType(0, MVT::iPTR, TP); + MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP); } else if (OperandNode->getName() == "unknown") { // Nothing to do. } else { @@ -1423,13 +1473,13 @@ TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ isInputPattern = isInput; for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) - Trees.push_back(ParseTreePattern((DagInit*)RawPat->getElement(i))); + Trees.push_back(ParseTreePattern(RawPat->getElement(i), "")); } TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ isInputPattern = isInput; - Trees.push_back(ParseTreePattern(Pat)); + Trees.push_back(ParseTreePattern(Pat, "")); } TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, @@ -1457,7 +1507,49 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) { } -TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { +TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ + if (DefInit *DI = dynamic_cast<DefInit*>(TheInit)) { + Record *R = DI->getDef(); + + // Direct reference to a leaf DagNode or PatFrag? Turn it into a + // TreePatternNode if its own. For example: + /// (foo GPR, imm) -> (foo GPR, (imm)) + if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) + return ParseTreePattern(new DagInit(DI, "", + std::vector<std::pair<Init*, std::string> >()), + OpName); + + // Input argument? + TreePatternNode *Res = new TreePatternNode(DI, 1); + if (R->getName() == "node" && !OpName.empty()) { + if (OpName.empty()) + error("'node' argument requires a name to match with operand list"); + Args.push_back(OpName); + } + + Res->setName(OpName); + return Res; + } + + if (IntInit *II = dynamic_cast<IntInit*>(TheInit)) { + if (!OpName.empty()) + error("Constant int argument should not have a name!"); + return new TreePatternNode(II, 1); + } + + if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) { + // Turn this into an IntInit. + Init *II = BI->convertInitializerTo(new IntRecTy()); + if (II == 0 || !dynamic_cast<IntInit*>(II)) + error("Bits value must be constants!"); + return ParseTreePattern(II, OpName); + } + + DagInit *Dag = dynamic_cast<DagInit*>(TheInit); + if (!Dag) { + TheInit->dump(); + error("Pattern has unexpected init kind!"); + } DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); if (!OpDef) error("Pattern has unexpected operator type!"); Record *Operator = OpDef->getDef(); @@ -1468,50 +1560,14 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { if (Dag->getNumArgs() != 1) error("Type cast only takes one operand!"); - Init *Arg = Dag->getArg(0); - TreePatternNode *New; - if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) { - Record *R = DI->getDef(); - if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) { - Dag->setArg(0, new DagInit(DI, "", - std::vector<std::pair<Init*, std::string> >())); - return ParseTreePattern(Dag); - } - - // Input argument? - if (R->getName() == "node") { - if (Dag->getArgName(0).empty()) - error("'node' argument requires a name to match with operand list"); - Args.push_back(Dag->getArgName(0)); - } - - New = new TreePatternNode(DI, 1); - } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { - New = ParseTreePattern(DI); - } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { - 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<BitsInit*>(Arg)) { - // Turn this into an IntInit. - Init *II = BI->convertInitializerTo(new IntRecTy()); - if (II == 0 || !dynamic_cast<IntInit*>(II)) - error("Bits value must be constants!"); - - New = new TreePatternNode(dynamic_cast<IntInit*>(II), 1); - if (!Dag->getArgName(0).empty()) - error("Constant int argument should not have a name!"); - } else { - Arg->dump(); - error("Unknown leaf value for tree pattern!"); - return 0; - } + TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0)); // Apply the type cast. assert(New->getNumTypes() == 1 && "FIXME: Unhandled"); New->UpdateNodeType(0, getValueType(Operator), *this); - if (New->getNumChildren() == 0) - New->setName(Dag->getArgName(0)); + + if (!OpName.empty()) + error("ValueType cast should not have a name!"); return New; } @@ -1522,65 +1578,38 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { !Operator->isSubClassOf("SDNodeXForm") && !Operator->isSubClassOf("Intrinsic") && Operator->getName() != "set" && - Operator->getName() != "implicit" && - Operator->getName() != "parallel") + Operator->getName() != "implicit") 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!"); + if (isInputPattern) { + if (Operator->isSubClassOf("Instruction") || + Operator->isSubClassOf("SDNodeXForm")) + error("Cannot use '" + Operator->getName() + "' in an input pattern!"); + } else { + if (Operator->isSubClassOf("Intrinsic")) + error("Cannot use '" + Operator->getName() + "' in an output pattern!"); + + if (Operator->isSubClassOf("SDNode") && + Operator->getName() != "imm" && + Operator->getName() != "fpimm" && + Operator->getName() != "tglobaltlsaddr" && + Operator->getName() != "tconstpool" && + Operator->getName() != "tjumptable" && + Operator->getName() != "tframeindex" && + Operator->getName() != "texternalsym" && + Operator->getName() != "tblockaddress" && + Operator->getName() != "tglobaladdr" && + Operator->getName() != "bb" && + Operator->getName() != "vt") + error("Cannot use '" + Operator->getName() + "' in an output pattern!"); + } std::vector<TreePatternNode*> Children; - - for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { - Init *Arg = Dag->getArg(i); - if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { - Children.push_back(ParseTreePattern(DI)); - if (Children.back()->getName().empty()) - Children.back()->setName(Dag->getArgName(i)); - } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) { - Record *R = DefI->getDef(); - // Direct reference to a leaf DagNode or PatFrag? Turn it into a - // TreePatternNode if its own. - if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) { - Dag->setArg(i, new DagInit(DefI, "", - std::vector<std::pair<Init*, std::string> >())); - --i; // Revisit this node... - } else { - TreePatternNode *Node = new TreePatternNode(DefI, 1); - Node->setName(Dag->getArgName(i)); - Children.push_back(Node); - - // Input argument? - if (R->getName() == "node") { - if (Dag->getArgName(i).empty()) - error("'node' argument requires a name to match with operand list"); - Args.push_back(Dag->getArgName(i)); - } - } - } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { - TreePatternNode *Node = new TreePatternNode(II, 1); - if (!Dag->getArgName(i).empty()) - error("Constant int argument should not have a name!"); - Children.push_back(Node); - } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Arg)) { - // Turn this into an IntInit. - Init *II = BI->convertInitializerTo(new IntRecTy()); - if (II == 0 || !dynamic_cast<IntInit*>(II)) - error("Bits value must be constants!"); - - TreePatternNode *Node = new TreePatternNode(dynamic_cast<IntInit*>(II),1); - if (!Dag->getArgName(i).empty()) - error("Constant int argument should not have a name!"); - Children.push_back(Node); - } else { - errs() << '"'; - Arg->dump(); - errs() << "\": "; - error("Unknown leaf value for tree pattern!"); - } - } + + // Parse all the operands. + for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) + Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i))); // If the operator is an intrinsic, then this is just syntactic sugar for for // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and @@ -1591,15 +1620,13 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { // If this intrinsic returns void, it must have side-effects and thus a // chain. - if (Int.IS.RetVTs[0] == MVT::isVoid) { + if (Int.IS.RetVTs.empty()) Operator = getDAGPatterns().get_intrinsic_void_sdnode(); - } else if (Int.ModRef != CodeGenIntrinsic::NoMem) { + else if (Int.ModRef != CodeGenIntrinsic::NoMem) // Has side-effects, requires chain. Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); - } else { - // Otherwise, no chain. + else // Otherwise, no chain. Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); - } TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1); Children.insert(Children.begin(), IIDNode); @@ -1607,10 +1634,48 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { unsigned NumResults = GetNumNodeResults(Operator, CDP); TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); - Result->setName(Dag->getName()); + Result->setName(OpName); + + if (!Dag->getName().empty()) { + assert(Result->getName().empty()); + Result->setName(Dag->getName()); + } return Result; } +/// SimplifyTree - See if we can simplify this tree to eliminate something that +/// will never match in favor of something obvious that will. This is here +/// strictly as a convenience to target authors because it allows them to write +/// more type generic things and have useless type casts fold away. +/// +/// This returns true if any change is made. +static bool SimplifyTree(TreePatternNode *&N) { + if (N->isLeaf()) + return false; + + // If we have a bitconvert with a resolved type and if the source and + // destination types are the same, then the bitconvert is useless, remove it. + if (N->getOperator()->getName() == "bitconvert" && + N->getExtType(0).isConcrete() && + N->getExtType(0) == N->getChild(0)->getExtType(0) && + N->getName().empty()) { + N = N->getChild(0); + SimplifyTree(N); + return true; + } + + // Walk all children. + bool MadeChange = false; + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { + TreePatternNode *Child = N->getChild(i); + MadeChange |= SimplifyTree(Child); + N->setChild(i, Child); + } + return MadeChange; +} + + + /// InferAllTypes - Infer/propagate as many types throughout the expression /// patterns as possible. Return true if all types are inferred, false /// otherwise. Throw an exception if a type contradiction is found. @@ -1622,8 +1687,10 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { bool MadeChange = true; while (MadeChange) { MadeChange = false; - for (unsigned i = 0, e = Trees.size(); i != e; ++i) + for (unsigned i = 0, e = Trees.size(); i != e; ++i) { MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false); + MadeChange |= SimplifyTree(Trees[i]); + } // If there are constraints on our named nodes, apply them. for (StringMap<SmallVector<TreePatternNode*,1> >::iterator @@ -2542,37 +2609,7 @@ void CodeGenDAGPatterns::ParsePatterns() { for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { Record *CurPattern = Patterns[i]; DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); - DefInit *OpDef = dynamic_cast<DefInit*>(Tree->getOperator()); - Record *Operator = OpDef->getDef(); - TreePattern *Pattern; - if (Operator->getName() != "parallel") - Pattern = new TreePattern(CurPattern, Tree, true, *this); - else { - std::vector<Init*> Values; - RecTy *ListTy = 0; - for (unsigned j = 0, ee = Tree->getNumArgs(); j != ee; ++j) { - Values.push_back(Tree->getArg(j)); - TypedInit *TArg = dynamic_cast<TypedInit*>(Tree->getArg(j)); - if (TArg == 0) { - errs() << "In dag: " << Tree->getAsString(); - errs() << " -- Untyped argument in pattern\n"; - assert(0 && "Untyped argument in pattern"); - } - if (ListTy != 0) { - ListTy = resolveTypes(ListTy, TArg->getType()); - if (ListTy == 0) { - errs() << "In dag: " << Tree->getAsString(); - errs() << " -- Incompatible types in pattern arguments\n"; - assert(0 && "Incompatible types in pattern arguments"); - } - } - else { - ListTy = TArg->getType(); - } - } - ListInit *LI = new ListInit(Values, new ListRecTy(ListTy)); - Pattern = new TreePattern(CurPattern, LI, true, *this); - } + TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this); // Inline pattern fragments into it. Pattern->InlinePatternFragments(); diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index f583f29..5480513 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -129,7 +129,7 @@ namespace EEVT { /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type /// whose element is VT. - bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP); + bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP); bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; } bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; } @@ -199,6 +199,9 @@ public: SDNodeInfo(Record *R); // Parse the specified record. unsigned getNumResults() const { return NumResults; } + + /// getNumOperands - This is the number of operands required or -1 if + /// variadic. int getNumOperands() const { return NumOperands; } Record *getRecord() const { return Def; } const std::string &getEnumName() const { return EnumName; } @@ -211,7 +214,7 @@ public: /// getKnownType - If the type constraints on this node imply a fixed type /// (e.g. all stores return void, etc), then return it as an /// MVT::SimpleValueType. Otherwise, return MVT::Other. - MVT::SimpleValueType getKnownType() const; + MVT::SimpleValueType getKnownType(unsigned ResNo) const; /// hasProperty - Return true if this node has the specified property. /// @@ -272,7 +275,7 @@ public: ~TreePatternNode(); const std::string &getName() const { return Name; } - void setName(const std::string &N) { Name = N; } + void setName(StringRef N) { Name.assign(N.begin(), N.end()); } bool isLeaf() const { return Val != 0; } @@ -510,7 +513,7 @@ public: void dump() const; private: - TreePatternNode *ParseTreePattern(DagInit *DI); + TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName); void ComputeNamedNodes(); void ComputeNamedNodes(TreePatternNode *N); }; @@ -595,6 +598,10 @@ public: unsigned getAddedComplexity() const { return AddedComplexity; } std::string getPredicateCheck() const; + + /// Compute the complexity metric for the input pattern. This roughly + /// corresponds to the number of nodes that are covered. + unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const; }; // Deterministic comparison of Record*. diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index eea5561..99d196c 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenInstruction.h" +#include "CodeGenTarget.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" @@ -294,3 +295,22 @@ CodeGenInstruction::ParseOperandName(const std::string &Op, // Otherwise, didn't find it! throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; } + + +/// HasOneImplicitDefWithKnownVT - If the instruction has at least one +/// implicit def and it has a known VT, return the VT, otherwise return +/// MVT::Other. +MVT::SimpleValueType CodeGenInstruction:: +HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const { + if (ImplicitDefs.empty()) return MVT::Other; + + // Check to see if the first implicit def has a resolvable type. + Record *FirstImplicitDef = ImplicitDefs[0]; + assert(FirstImplicitDef->isSubClassOf("Register")); + const std::vector<MVT::SimpleValueType> &RegVTs = + TargetInfo.getRegisterVTs(FirstImplicitDef); + if (RegVTs.size() == 1) + return RegVTs[0]; + return MVT::Other; +} + diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index c369123..946c2d0 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -22,6 +22,7 @@ namespace llvm { class Record; class DagInit; + class CodeGenTarget; class CodeGenInstruction { public: @@ -183,6 +184,12 @@ namespace llvm { /// non-empty name. If the instruction does not have an operand with the /// specified name, throw an exception. unsigned getOperandNamed(const std::string &Name) const; + + /// HasOneImplicitDefWithKnownVT - If the instruction has at least one + /// implicit def and it has a known VT, return the VT, otherwise return + /// MVT::Other. + MVT::SimpleValueType + HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const; }; } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 79bc30d..0392895 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -18,6 +18,7 @@ #include "CodeGenIntrinsics.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/CommandLine.h" #include <algorithm> using namespace llvm; @@ -194,6 +195,10 @@ getRegisterVTs(Record *R) const { } } } + + // Remove duplicates. + array_pod_sort(Result.begin(), Result.end()); + Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); return Result; } @@ -488,15 +493,17 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { } if (EVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); - isOverloaded |= true; + isOverloaded = true; } + + // Reject invalid types. + if (VT == MVT::isVoid) + throw "Intrinsic '" + DefName + " has void in result type list!"; + IS.RetVTs.push_back(VT); IS.RetTypeDefs.push_back(TyEl); } - - if (IS.RetVTs.size() == 0) - throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!"; - + // Parse the list of parameter types. TypeList = R->getValueAsListInit("ParamTypes"); for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { @@ -517,10 +524,16 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { "Expected iAny or vAny type"); } else VT = getValueType(TyEl->getValueAsDef("VT")); + if (EVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); - isOverloaded |= true; + isOverloaded = true; } + + // Reject invalid types. + if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) + throw "Intrinsic '" + DefName + " has void in result type list!"; + IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); } diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 044086a..04c7710 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -21,49 +21,6 @@ using namespace llvm; // DAGISelEmitter Helper methods // -/// getPatternSize - Return the 'size' of this pattern. We want to match large -/// patterns before small ones. This is used to determine the size of a -/// pattern. -static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) { - unsigned Size = 3; // The node itself. - // If the root node is a ConstantSDNode, increases its size. - // e.g. (set R32:$dst, 0). - if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue())) - Size += 2; - - // FIXME: This is a hack to statically increase the priority of patterns - // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. - // Later we can allow complexity / cost for each pattern to be (optionally) - // specified. To get best possible pattern match we'll need to dynamically - // calculate the complexity of all patterns a dag can potentially map to. - const ComplexPattern *AM = P->getComplexPatternInfo(CGP); - if (AM) - Size += AM->getNumOperands() * 3; - - // If this node has some predicate function that must match, it adds to the - // complexity of this node. - if (!P->getPredicateFns().empty()) - ++Size; - - // 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->getNumTypes() && - Child->getType(0) != MVT::Other) - Size += getPatternSize(Child, CGP); - else if (Child->isLeaf()) { - if (dynamic_cast<IntInit*>(Child->getLeafValue())) - Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). - else if (Child->getComplexPatternInfo(CGP)) - Size += getPatternSize(Child, CGP); - else if (!Child->getPredicateFns().empty()) - ++Size; - } - } - - return Size; -} - /// getResultPatternCost - Compute the number of instructions for this pattern. /// This is a temporary hack. We should really include the instruction /// latencies in this calculation. @@ -153,12 +110,25 @@ struct PatternSortingPredicate { PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {} CodeGenDAGPatterns &CGP; - bool operator()(const PatternToMatch *LHS, - const PatternToMatch *RHS) { - unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), CGP); - unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), CGP); - LHSSize += LHS->getAddedComplexity(); - RHSSize += RHS->getAddedComplexity(); + bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) { + const TreePatternNode *LHSSrc = LHS->getSrcPattern(); + const TreePatternNode *RHSSrc = RHS->getSrcPattern(); + + if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 && + LHSSrc->getType(0) != RHSSrc->getType(0)) { + MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0); + if (MVT(V1).isVector() != MVT(V2).isVector()) + return MVT(V2).isVector(); + + if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint()) + return MVT(V2).isFloatingPoint(); + } + + // Otherwise, if the patterns might both match, sort based on complexity, + // which means that we prefer to match patterns that cover more nodes in the + // input over nodes that cover fewer. + unsigned LHSSize = LHS->getPatternComplexity(CGP); + unsigned RHSSize = RHS->getPatternComplexity(CGP); if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost if (LHSSize < RHSSize) return false; @@ -173,7 +143,8 @@ struct PatternSortingPredicate { if (LHSPatSize < RHSPatSize) return true; if (LHSPatSize > RHSPatSize) return false; - // Sort based on the UID of the pattern, giving us a deterministic ordering. + // Sort based on the UID of the pattern, giving us a deterministic ordering + // if all other sorting conditions fail. assert(LHS == RHS || LHS->ID != RHS->ID); return LHS->ID < RHS->ID; } @@ -208,8 +179,7 @@ void DAGISelEmitter::run(raw_ostream &OS) { // We want to process the matches in order of minimal cost. Sort the patterns // so the least cost one is at the start. - std::stable_sort(Patterns.begin(), Patterns.end(), - PatternSortingPredicate(CGP)); + std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP)); // Convert each variant of each pattern into a Matcher. diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index cd3fad1..9f12a68 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -147,7 +147,8 @@ void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "CheckType " << getEnumName(Type) << '\n'; + OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo=" + << ResNo << '\n'; } void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { @@ -356,12 +357,11 @@ bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const { // different, then we know they contradict. For example, a check for // ISD::STORE will never be true at the same time a check for Type i32 is. if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) { - // FIXME: What result is this referring to? - MVT::SimpleValueType NodeType; - if (getOpcode().getNumResults() == 0) - NodeType = MVT::isVoid; - else - NodeType = getOpcode().getKnownType(); + // If checking for a result the opcode doesn't have, it can't match. + if (CT->getResNo() >= getOpcode().getNumResults()) + return true; + + MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo()); if (NodeType != MVT::Other) return TypesAreContradictory(NodeType, CT->getType()); } diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index ef7ecf4..d9b25d5 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -492,14 +492,16 @@ private: }; /// CheckTypeMatcher - This checks to see if the current node has the -/// specified type, if not it fails to match. +/// specified type at the specified result, if not it fails to match. class CheckTypeMatcher : public Matcher { MVT::SimpleValueType Type; + unsigned ResNo; public: - CheckTypeMatcher(MVT::SimpleValueType type) - : Matcher(CheckType), Type(type) {} + CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno) + : Matcher(CheckType), Type(type), ResNo(resno) {} MVT::SimpleValueType getType() const { return Type; } + unsigned getResNo() const { return ResNo; } static inline bool classof(const Matcher *N) { return N->getKind() == CheckType; diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index cabf2d4..4473f0d 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -32,6 +32,7 @@ OmitComments("omit-comments", cl::desc("Do not generate comments"), namespace { class MatcherTableEmitter { + const CodeGenDAGPatterns &CGP; StringMap<unsigned> NodePredicateMap, PatternPredicateMap; std::vector<std::string> NodePredicates, PatternPredicates; @@ -43,13 +44,12 @@ class MatcherTableEmitter { std::vector<Record*> NodeXForms; public: - MatcherTableEmitter() {} + MatcherTableEmitter(const CodeGenDAGPatterns &cgp) : CGP(cgp) {} unsigned EmitMatcherList(const Matcher *N, unsigned Indent, unsigned StartIdx, formatted_raw_ostream &OS); - void EmitPredicateFunctions(const CodeGenDAGPatterns &CGP, - formatted_raw_ostream &OS); + void EmitPredicateFunctions(formatted_raw_ostream &OS); void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS); private: @@ -255,9 +255,9 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, } case Matcher::CheckOpcode: - OS << "OPC_CheckOpcode, " - << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << ",\n"; - return 2; + OS << "OPC_CheckOpcode, TARGET_OPCODE(" + << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n"; + return 3; case Matcher::SwitchOpcode: case Matcher::SwitchType: { @@ -280,10 +280,14 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, // For each case we emit the size, then the opcode, then the matcher. for (unsigned i = 0, e = NumCases; i != e; ++i) { const Matcher *Child; - if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) + unsigned IdxSize; + if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) { Child = SOM->getCaseMatcher(i); - else + IdxSize = 2; // size of opcode in table is 2 bytes. + } else { Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i); + IdxSize = 1; // size of type in table is 1 byte. + } // We need to encode the opcode and the offset of the case code before // emitting the case code. Handle this by buffering the output into a @@ -299,7 +303,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, TmpBuf.clear(); raw_svector_ostream OS(TmpBuf); formatted_raw_ostream FOS(OS); - ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+1, FOS); + ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize, + FOS); } while (GetVBRSize(ChildSize) != VBRSize); assert(ChildSize != 0 && "Should not have a zero-sized child!"); @@ -316,15 +321,15 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << ' '; if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) - OS << SOM->getCaseOpcode(i).getEnumName(); + OS << "TARGET_OPCODE(" << SOM->getCaseOpcode(i).getEnumName() << "),"; else - OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)); - OS << ','; - + OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ','; + + CurrentIdx += IdxSize; + if (!OmitComments) - OS << "// ->" << CurrentIdx+ChildSize+1; + OS << "// ->" << CurrentIdx+ChildSize; OS << '\n'; - ++CurrentIdx; OS << TmpBuf.str(); CurrentIdx += ChildSize; } @@ -341,6 +346,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, } case Matcher::CheckType: + assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 && + "FIXME: Add support for CheckType of resno != 0"); OS << "OPC_CheckType, " << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n"; return 2; @@ -442,6 +449,13 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, case Matcher::EmitMergeInputChains: { const EmitMergeInputChainsMatcher *MN = cast<EmitMergeInputChainsMatcher>(N); + + // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1. + if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) { + OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n"; + return 1; + } + OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", "; for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i) OS << MN->getNode(i) << ", "; @@ -507,7 +521,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) { OS.PadToColumn(Indent*2) << "// Src: " - << *SNT->getPattern().getSrcPattern() << '\n'; + << *SNT->getPattern().getSrcPattern() << " - Complexity = " + << SNT->getPattern().getPatternComplexity(CGP) << '\n'; OS.PadToColumn(Indent*2) << "// Dst: " << *SNT->getPattern().getDstPattern() << '\n'; } @@ -534,7 +549,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << '\n'; if (!OmitComments) { OS.PadToColumn(Indent*2) << "// Src: " - << *CM->getPattern().getSrcPattern() << '\n'; + << *CM->getPattern().getSrcPattern() << " - Complexity = " + << CM->getPattern().getPatternComplexity(CGP) << '\n'; OS.PadToColumn(Indent*2) << "// Dst: " << *CM->getPattern().getDstPattern(); } @@ -565,8 +581,7 @@ EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx, return Size; } -void MatcherTableEmitter::EmitPredicateFunctions(const CodeGenDAGPatterns &CGP, - formatted_raw_ostream &OS) { +void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { // Emit pattern predicates. if (!PatternPredicates.empty()) { OS << "bool CheckPatternPredicate(unsigned PredNo) const {\n"; @@ -760,7 +775,7 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher, OS << "// The main instruction selector code.\n"; OS << "SDNode *SelectCode(SDNode *N) {\n"; - MatcherTableEmitter MatcherEmitter; + MatcherTableEmitter MatcherEmitter(CGP); OS << " // Opcodes are emitted as 2 bytes, TARGET_OPCODE handles this.\n"; OS << " #define TARGET_OPCODE(X) X & 255, unsigned(X) >> 8\n"; @@ -775,5 +790,5 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher, OS << '\n'; // Next up, emit the function for node and pattern predicates: - MatcherEmitter.EmitPredicateFunctions(CGP, OS); + MatcherEmitter.EmitPredicateFunctions(OS); } diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index da6f6af..9d469a9 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -408,13 +408,13 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, // If N and NodeNoTypes don't agree on a type, then this is a case where we // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and // reinfer any correlated types. - bool DoTypeCheck = false; - if (NodeNoTypes->getNumTypes() != 0 && - NodeNoTypes->getExtType(0) != N->getExtType(0)) { - assert(NodeNoTypes->getNumTypes() == 1 && "FIXME: Handle multiple results"); - NodeNoTypes->setType(0, N->getExtType(0)); + SmallVector<unsigned, 2> ResultsToTypeCheck; + + for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) { + if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue; + NodeNoTypes->setType(i, N->getExtType(i)); InferPossibleTypes(); - DoTypeCheck = true; + ResultsToTypeCheck.push_back(i); } // If this node has a name associated with it, capture it in VariableMap. If @@ -444,10 +444,9 @@ 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) { - assert(N->getNumTypes() == 1); - AddMatcher(new CheckTypeMatcher(N->getType(0))); - } + for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i) + AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]), + ResultsToTypeCheck[i])); } /// EmitMatcherCode - Generate the code that matches the predicate of this @@ -688,9 +687,19 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, continue; } + const TreePatternNode *Child = N->getChild(ChildNo); + // Otherwise this is a normal operand or a predicate operand without // 'execute always'; emit it. - EmitResultOperand(N->getChild(ChildNo), InstOps); + unsigned BeforeAddingNumOps = InstOps.size(); + EmitResultOperand(Child, InstOps); + assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands"); + + // If the operand is an instruction and it produced multiple results, just + // take the first one. + if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction")) + InstOps.resize(BeforeAddingNumOps+1); + ++ChildNo; } @@ -712,24 +721,19 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // Determine the result types. SmallVector<MVT::SimpleValueType, 4> ResultVTs; - if (N->getNumTypes()) { - // FIXME2: If the node has multiple results, we should add them. For now, - // preserve existing behavior?! - assert(N->getNumTypes() == 1); - ResultVTs.push_back(N->getType(0)); - } + for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) + ResultVTs.push_back(N->getType(i)); // If this is the root instruction of a pattern that has physical registers in // its result pattern, add output VTs for them. For example, X86 has: // (set AL, (mul ...)) // This also handles implicit results like: // (implicit EFLAGS) - if (isRoot && Pattern.getDstRegs().size() != 0) { + if (isRoot && !Pattern.getDstRegs().empty()) { // 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->getNumTypes() != 0 && - !II.ImplicitDefs.empty()) + if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) HandledReg = II.ImplicitDefs[0]; for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { @@ -763,6 +767,9 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, bool NodeHasMemRefs = isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP); + assert((!ResultVTs.empty() || TreeHasOutFlag || NodeHasChain) && + "Node has no result"); + AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(), ResultVTs.data(), ResultVTs.size(), InstOps.data(), InstOps.size(), @@ -830,33 +837,35 @@ void MatcherGen::EmitResultCode() { // At this point, we have however many values the result pattern produces. // However, the input pattern might not need all of these. If there are - // excess values at the end (such as condition codes etc) just lop them off. - // This doesn't need to worry about flags or chains, just explicit results. - // - // FIXME2: This doesn't work because there is currently no way to get an - // accurate count of the # results the source pattern sets. This is because - // of the "parallel" construct in X86 land, which looks like this: - // - //def : Pat<(parallel (X86and_flag GR8:$src1, GR8:$src2), - // (implicit EFLAGS)), - // (AND8rr GR8:$src1, GR8:$src2)>; + // excess values at the end (such as implicit defs of condition codes etc) + // just lop them off. This doesn't need to worry about flags or chains, just + // explicit results. // - // This idiom means to match the two-result node X86and_flag (which is - // declared as returning a single result, because we can't match multi-result - // nodes yet). In this case, we would have to know that the input has two - // results. However, mul8r is modelled exactly the same way, but without - // implicit defs included. The fix is to support multiple results directly - // and eliminate 'parallel'. - // - // FIXME2: When this is fixed, we should revert the terrible hack in the - // OPC_EmitNode code in the interpreter. -#if 0 - const TreePatternNode *Src = Pattern.getSrcPattern(); - unsigned NumSrcResults = Src->getTypeNum(0) != MVT::isVoid ? 1 : 0; - NumSrcResults += Pattern.getDstRegs().size(); + unsigned NumSrcResults = Pattern.getSrcPattern()->getNumTypes(); + + // If the pattern also has (implicit) results, count them as well. + if (!Pattern.getDstRegs().empty()) { + // If the root came from an implicit def in the instruction handling stuff, + // don't re-add it. + Record *HandledReg = 0; + const TreePatternNode *DstPat = Pattern.getDstPattern(); + if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){ + const CodeGenTarget &CGT = CGP.getTargetInfo(); + CodeGenInstruction &II = CGT.getInstruction(DstPat->getOperator()); + + if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) + HandledReg = II.ImplicitDefs[0]; + } + + for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { + Record *Reg = Pattern.getDstRegs()[i]; + if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; + ++NumSrcResults; + } + } + assert(Ops.size() >= NumSrcResults && "Didn't provide enough results"); Ops.resize(NumSrcResults); -#endif // If the matched pattern covers nodes which define a flag result, emit a node // that tells the matcher about them so that it can update their results. diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 820ab63..c73bdb9 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -48,8 +48,9 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(), RM->getResultNo()); - if (CheckTypeMatcher *CT= dyn_cast<CheckTypeMatcher>(MC->getNext())) - if (MC->getChildNo() < 8) // Only have CheckChildType0...7 + if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext())) + if (MC->getChildNo() < 8 && // Only have CheckChildType0...7 + CT->getResNo() == 0) // CheckChildType checks res #0 New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType()); if (New) { @@ -420,10 +421,12 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { CheckTypeMatcher *CTM = cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i], Matcher::CheckType)); - if (CTM == 0 || + if (CTM == 0 || // iPTR checks could alias any other case without us knowing, don't // bother with them. CTM->getType() == MVT::iPTR || + // SwitchType only works for result #0. + CTM->getResNo() != 0 || // If the CheckType isn't at the start of the list, see if we can move // it there. !CTM->canMoveBefore(NewOptionsToMatch[i])) { @@ -488,7 +491,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size())); } else { // If we factored and ended up with one case, create it now. - MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first)); + MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0)); MatcherPtr->setNext(Cases[0].second); } return; diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 23f09a5..ba59e50 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -296,9 +296,11 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { if (!InstPatNode) continue; if (InstPatNode->isLeaf()) continue; + // Ignore multiple result nodes for now. + if (InstPatNode->getNumTypes() > 1) continue; + Record *InstPatOp = InstPatNode->getOperator(); std::string OpcodeName = getOpcodeName(InstPatOp, CGP); - assert(InstPatNode->getNumTypes() <= 1); MVT::SimpleValueType RetVT = MVT::isVoid; if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getType(0); MVT::SimpleValueType VT = RetVT; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 8f7550b..9bc5459 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -337,7 +337,7 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, IntInit *ShiftInt, raw_ostream &OS) { if (Val == 0 || ShiftInt == 0) throw std::string("Illegal value or shift amount in TargetInfo*!"); - RecordVal *RV = R->getValue(Val->getValue()); + RecordVal *RV = R->getDottedValue(Val->getValue()); int Shift = ShiftInt->getValue(); if (RV == 0 || RV->getValue() == 0) { diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index c5df9e4..417aca7 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -172,10 +172,11 @@ static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, static void EmitTypeGenerate(raw_ostream &OS, const std::vector<Record*> &ArgTypes, unsigned &ArgNo) { - if (ArgTypes.size() == 1) { - EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); - return; - } + if (ArgTypes.empty()) + return EmitTypeForValueType(OS, MVT::isVoid); + + if (ArgTypes.size() == 1) + return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); OS << "StructType::get(Context, "; @@ -251,11 +252,11 @@ namespace { unsigned RHSSize = RHSVec->size(); unsigned LHSSize = LHSVec->size(); - do { + for (; i != LHSSize; ++i) { if (i == RHSSize) return false; // RHS is shorter than LHS. if ((*LHSVec)[i] != (*RHSVec)[i]) return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); - } while (++i != LHSSize); + } if (i != RHSSize) return true; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index b9facb4..55c9989 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -1108,12 +1108,15 @@ RecTy *VarInit::getFieldType(const std::string &FieldName) const { return 0; } -Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const { +Init *VarInit::getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { if (dynamic_cast<RecordRecTy*>(getType())) - if (const RecordVal *RV = R.getValue(VarName)) { - Init *TheInit = RV->getValue(); + if (const RecordVal *Val = R.getValue(VarName)) { + if (RV != Val && (RV || dynamic_cast<UnsetInit*>(Val->getValue()))) + return 0; + Init *TheInit = Val->getValue(); assert(TheInit != this && "Infinite loop detected!"); - if (Init *I = TheInit->getFieldInit(R, FieldName)) + if (Init *I = TheInit->getFieldInit(R, RV, FieldName)) return I; else return 0; @@ -1174,7 +1177,8 @@ RecTy *DefInit::getFieldType(const std::string &FieldName) const { return 0; } -Init *DefInit::getFieldInit(Record &R, const std::string &FieldName) const { +Init *DefInit::getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { return Def->getValue(FieldName)->getValue(); } @@ -1185,7 +1189,7 @@ std::string DefInit::getAsString() const { Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, unsigned Bit) { - if (Init *BitsVal = Rec->getFieldInit(R, FieldName)) + if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName)) if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) { assert(Bit < BI->getNumBits() && "Bit reference out of range!"); Init *B = BI->getBit(Bit); @@ -1198,7 +1202,7 @@ Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, unsigned Elt) { - if (Init *ListVal = Rec->getFieldInit(R, FieldName)) + if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName)) if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) { if (Elt >= LI->getSize()) return 0; Init *E = LI->getElement(Elt); @@ -1215,7 +1219,7 @@ Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) { Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec; - Init *BitsVal = NewRec->getFieldInit(R, FieldName); + Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName); if (BitsVal) { Init *BVR = BitsVal->resolveReferences(R, RV); return BVR->isComplete() ? BVR : this; @@ -1303,6 +1307,16 @@ void Record::resolveReferencesTo(const RecordVal *RV) { } } +RecordVal *Record::getDottedValue(StringRef Name) { + size_t pos = Name.find('.'); + if (pos == StringRef::npos) + return getValue(Name); + RecordVal *RV = getValue(Name.substr(0, pos)); + if (!RV) return 0; + DefInit *DI = dynamic_cast<DefInit*>(RV->getValue()); + if (!DI) return 0; + return DI->getDef()->getDottedValue(Name.substr(pos+1)); +} void Record::dump() const { errs() << *this; } diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 90096e9..41373c7 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -503,7 +503,8 @@ struct Init { /// initializer for the specified field. If getFieldType returns non-null /// this method should return non-null, otherwise it returns null. /// - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const { + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { return 0; } @@ -950,7 +951,8 @@ public: unsigned Elt); virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const; /// resolveReferences - This method is used by classes that refer to other /// variables which may not be defined at the time they expression is formed. @@ -1035,7 +1037,8 @@ public: //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const; virtual std::string getAsString() const; @@ -1259,6 +1262,9 @@ public: return 0; } + // Like getValue, but allow dotting into members: X.Y + RecordVal *getDottedValue(StringRef Name); + void addTemplateArg(StringRef Name) { assert(!isTemplateArg(Name) && "Template arg already defined!"); TemplateArgs.push_back(Name); diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index f20ec00..1326ebc 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -34,7 +34,6 @@ #include "SubtargetEmitter.h" #include "TGParser.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileUtilities.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index f67794e..33f471d 100755 --- a/utils/buildit/build_llvm +++ b/utils/buildit/build_llvm @@ -203,6 +203,7 @@ fi make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$TARGETS" \ UNIVERSAL_SDK_PATH=$HOST_SDKROOT \ NO_RUNTIME_LIBS=1 \ + DISABLE_EDIS=1 \ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ CXXFLAGS="-DLLVM_VERSION_INFO='\" Apple Build #$LLVM_VERSION\"'" \ @@ -227,6 +228,7 @@ cd $DIR/obj-llvm || exit 1 # Install the tree into the destination directory. make $LOCAL_MAKEFLAGS $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$TARGETS" \ NO_RUNTIME_LIBS=1 \ + DISABLE_EDIS=1 \ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ OPTIMIZE_OPTION='-O3' VERBOSE=1 install diff --git a/utils/lit/lit/LitTestCase.py b/utils/lit/lit/LitTestCase.py new file mode 100644 index 0000000..8951185 --- /dev/null +++ b/utils/lit/lit/LitTestCase.py @@ -0,0 +1,30 @@ +import unittest +import Test + +""" +TestCase adaptor for providing a 'unittest' compatible interface to 'lit' tests. +""" + +class UnresolvedError(RuntimeError): + pass + +class LitTestCase(unittest.TestCase): + def __init__(self, test, lit_config): + unittest.TestCase.__init__(self) + self._test = test + self._lit_config = lit_config + + def id(self): + return self._test.getFullName() + + def shortDescription(self): + return self._test.getFullName() + + def runTest(self): + tr, output = self._test.config.test_format.execute( + self._test, self._lit_config) + + if tr is Test.UNRESOLVED: + raise UnresolvedError(output) + elif tr.isFailure: + self.fail(output) diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py index 433e39a..7ab9bb6 100644 --- a/utils/lit/lit/TestFormats.py +++ b/utils/lit/lit/TestFormats.py @@ -90,8 +90,9 @@ class FileBasedTest(object): litConfig, localConfig): source_path = testSuite.getSourcePath(path_in_suite) for filename in os.listdir(source_path): - # Ignore dot files. - if filename.startswith('.'): + # Ignore dot files and excluded tests. + if (filename.startswith('.') or + filename in localConfig.excludes): continue filepath = os.path.join(source_path, filename) diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index 29adff2..d10e4b0 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -63,6 +63,7 @@ def executeShCmd(cmd, cfg, cwd, results): procs = [] input = subprocess.PIPE stderrTempFiles = [] + opened_files = [] # To avoid deadlock, we use a single stderr stream for piped # output. This is null until we have seen some output using # stderr. @@ -113,8 +114,11 @@ def executeShCmd(cmd, cfg, cwd, results): else: r[2] = open(r[0], r[1]) # Workaround a Win32 and/or subprocess bug when appending. + # + # FIXME: Actually, this is probably an instance of PR6753. if r[1] == 'a': r[2].seek(0, 2) + opened_files.append(r[2]) result = r[2] final_redirects.append(result) @@ -176,7 +180,7 @@ def executeShCmd(cmd, cfg, cwd, results): else: err = '' procData[i] = (out,err) - + # Read stderr out of the temp files. for i,f in stderrTempFiles: f.seek(0, 0) @@ -199,6 +203,10 @@ def executeShCmd(cmd, cfg, cwd, results): else: exitCode = res + # Explicitly close any redirected files. + for f in opened_files: + f.close() + if cmd.negate: exitCode = not exitCode diff --git a/utils/lit/lit/lit.py b/utils/lit/lit/lit.py index e800754..a29fa42 100755 --- a/utils/lit/lit/lit.py +++ b/utils/lit/lit/lit.py @@ -315,6 +315,48 @@ def runTests(numThreads, litConfig, provider, display): except KeyboardInterrupt: sys.exit(2) +def load_test_suite(inputs): + import unittest + + # Create the global config object. + litConfig = LitConfig.LitConfig(progname = 'lit', + path = [], + quiet = False, + useValgrind = False, + valgrindLeakCheck = False, + valgrindArgs = [], + useTclAsSh = False, + noExecute = False, + debug = False, + isWindows = (platform.system()=='Windows'), + params = {}) + + # Load the tests from the inputs. + tests = [] + testSuiteCache = {} + localConfigCache = {} + for input in inputs: + prev = len(tests) + tests.extend(getTests(input, litConfig, + testSuiteCache, localConfigCache)[1]) + if prev == len(tests): + litConfig.warning('input %r contained no tests' % input) + + # If there were any errors during test discovery, exit now. + if litConfig.numErrors: + print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors + sys.exit(2) + + # Return a unittest test suite which just runs the tests in order. + def get_test_fn(test): + return unittest.FunctionTestCase( + lambda: test.config.test_format.execute( + test, litConfig), + description = test.getFullName()) + + from LitTestCase import LitTestCase + return unittest.TestSuite([LitTestCase(test, litConfig) for test in tests]) + def main(): # Bump the GIL check interval, its more important to get any one thread to a # blocking operation (hopefully exec) than to try and unblock other threads. |