X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=utils%2FTableGen%2FCodeGenDAGPatterns.cpp;h=a91ed1854617ed7f1e7a449d963436998a207bfd;hp=20bf29eb8598593a160bcf42fadbdd1044f9a294;hb=e80e5583701de7a73ba50b705cbf1106980c0c85;hpb=230796b2783ef67f305f94fb880e272cdc4fe4a3 diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 20bf29eb859..a91ed185461 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -350,7 +350,7 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { /// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors -/// this shoud be based on the element type. Update this and other based on +/// this should be based on the element type. Update this and other based on /// this information. bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { if (TP.hasError()) @@ -389,52 +389,6 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { else if (!Other.hasScalarTypes()) MadeChange |= EnforceVector(TP); - // For vectors we need to ensure that smaller size doesn't produce larger - // vector and vice versa. - if (isConcrete() && isVector(getConcrete())) { - MVT IVT = getConcrete(); - unsigned Size = IVT.getSizeInBits(); - - // Only keep types that have at least as many bits. - TypeSet InputSet(Other); - - for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { - assert(isVector(Other.TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(Other.TypeVec[i]).getSizeInBits() < Size) { - Other.TypeVec.erase(Other.TypeVec.begin()+i--); - MadeChange = true; - } - } - - if (Other.TypeVec.empty()) { // FIXME: Really want an SMLoc here! - TP.error("Type inference contradiction found, forcing '" + - InputSet.getName() + "' to have at least as many bits as " + - getName() + "'"); - return false; - } - } else if (Other.isConcrete() && isVector(Other.getConcrete())) { - MVT IVT = Other.getConcrete(); - unsigned Size = IVT.getSizeInBits(); - - // Only keep types with the same or fewer total bits - TypeSet InputSet(*this); - - for (unsigned i = 0; i != TypeVec.size(); ++i) { - assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(TypeVec[i]).getSizeInBits() > Size) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } - } - - if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! - TP.error("Type inference contradiction found, forcing '" + - InputSet.getName() + "' to have the same or fewer bits than " + - Other.getName() + "'"); - return false; - } - } - // This code does not currently handle nodes which have multiple types, // where some types are integer, and some are fp. Assert that this is not // the case. @@ -445,12 +399,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { if (TP.hasError()) return false; - // Okay, find the smallest scalar type from the other set and remove - // anything the same or smaller from the current set. + // Okay, find the smallest type from current set and remove anything the + // same or smaller from the other set. We need to ensure that the scalar + // type size is smaller than the scalar size of the smallest type. For + // vectors, we also need to make sure that the total size is no larger than + // the size of the smallest type. TypeSet InputSet(Other); - MVT::SimpleValueType Smallest = TypeVec[0]; + MVT Smallest = TypeVec[0]; for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { - if (Other.TypeVec[i] <= Smallest) { + MVT OtherVT = Other.TypeVec[i]; + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Smallest.isVector()) + continue; + // The getSizeInBits() check here is only needed for vectors, but is + // a subset of the scalar check for scalars so no need to qualify. + if (OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() || + OtherVT.getSizeInBits() < Smallest.getSizeInBits()) { Other.TypeVec.erase(Other.TypeVec.begin()+i--); MadeChange = true; } @@ -462,12 +426,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { return false; } - // Okay, find the largest scalar type from the other set and remove - // anything the same or larger from the current set. + // Okay, find the largest type from the other set and remove anything the + // same or smaller from the current set. We need to ensure that the scalar + // type size is larger than the scalar size of the largest type. For + // vectors, we also need to make sure that the total size is no smaller than + // the size of the largest type. InputSet = TypeSet(*this); - MVT::SimpleValueType Largest = Other.TypeVec[Other.TypeVec.size()-1]; + MVT Largest = Other.TypeVec[Other.TypeVec.size()-1]; for (unsigned i = 0; i != TypeVec.size(); ++i) { - if (TypeVec[i] >= Largest) { + MVT OtherVT = TypeVec[i]; + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Largest.isVector()) + continue; + // The getSizeInBits() check here is only needed for vectors, but is + // a subset of the scalar check for scalars so no need to qualify. + if (OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() || + OtherVT.getSizeInBits() > Largest.getSizeInBits()) { TypeVec.erase(TypeVec.begin()+i--); MadeChange = true; } @@ -482,7 +456,35 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { return MadeChange; } -/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type +/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type +/// whose element is specified by VTOperand. +bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, + TreePattern &TP) { + bool MadeChange = false; + + MadeChange |= EnforceVector(TP); + + 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 (MVT(TypeVec[i]).getVectorElementType().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 '" + + InputSet.getName() + "' to have a vector element"); + return false; + } + + return MadeChange; +} + +/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type /// whose element is specified by VTOperand. bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { @@ -528,7 +530,7 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, return MadeChange; } -/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to be a +/// EnforceVectorSubVectorTypeIs - 'this' is now constrained to be a /// vector type specified by VTOperand. bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { @@ -609,6 +611,64 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, return MadeChange; } +/// EnforceVectorSameNumElts - 'this' is now constrained to +/// be a vector with same num elements as VTOperand. +bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, + TreePattern &TP) { + if (TP.hasError()) + return false; + + // "This" must be a vector and "VTOperand" must be a vector. + bool MadeChange = false; + MadeChange |= EnforceVector(TP); + MadeChange |= VTOperand.EnforceVector(TP); + + // If we know one of the vector types, it forces the other type to agree. + if (isConcrete()) { + MVT IVT = getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); + + // Only keep types that have same elements as VTOperand. + TypeSet InputSet(VTOperand); + + for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) { + assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() != NumElems) { + VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--); + MadeChange = true; + } + } + if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have same number elements as '" + + getName() + "'"); + return false; + } + } else if (VTOperand.isConcrete()) { + MVT IVT = VTOperand.getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); + + // Only keep types that have same elements as 'this'. + TypeSet InputSet(*this); + + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(TypeVec[i]).getVectorNumElements() != NumElems) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } + } + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have same number elements than '" + + VTOperand.getName() + "'"); + return false; + } + } + + return MadeChange; +} + //===----------------------------------------------------------------------===// // Helpers for working with extended types. @@ -711,7 +771,7 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const { if (ClassName == "SDNode") Result = " SDNode *N = Node;\n"; else - Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n"; + Result = " auto *N = cast<" + ClassName + ">(Node);\n"; return Result + getPredCode(); } @@ -782,8 +842,8 @@ getPatternComplexity(const CodeGenDAGPatterns &CGP) const { /// std::string PatternToMatch::getPredicateCheck() const { std::string PredicateCheck; - for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) { - if (DefInit *Pred = dyn_cast(Predicates->getElement(i))) { + for (Init *I : Predicates->getValues()) { + if (DefInit *Pred = dyn_cast(I)) { Record *Def = Pred->getDef(); if (!Def->isSubClassOf("Predicate")) { #ifndef NDEBUG @@ -839,9 +899,21 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { ConstraintType = SDTCisSubVecOfVec; x.SDTCisSubVecOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); + } else if (R->isSubClassOf("SDTCVecEltisVT")) { + ConstraintType = SDTCVecEltisVT; + x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT")); + if (MVT(x.SDTCVecEltisVT_Info.VT).isVector()) + PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT"); + if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() && + !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint()) + PrintFatalError(R->getLoc(), "Must use integer or floating point type " + "as SDTCVecEltisVT"); + } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) { + ConstraintType = SDTCisSameNumEltsAs; + x.SDTCisSameNumEltsAs_Info.OtherOperandNum = + R->getValueAsInt("OtherOperandNum"); } else { - errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n"; - exit(1); + PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); } } @@ -859,11 +931,12 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, OpNo -= NumResults; if (OpNo >= N->getNumChildren()) { - errs() << "Invalid operand number in type constraint " + std::string S; + raw_string_ostream OS(S); + OS << "Invalid operand number in type constraint " << (OpNo+NumResults) << " "; - N->dump(); - errs() << '\n'; - exit(1); + N->print(OS); + PrintFatalError(OS.str()); } return N->getChild(OpNo); @@ -901,8 +974,8 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, unsigned OResNo = 0; TreePatternNode *OtherNode = getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); - return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)| - OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP); + return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)| + OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP); } case SDTCisVTSmallerThanOp: { // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must @@ -956,6 +1029,18 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, return BigVecOperand->getExtType(VResNo). EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP); } + case SDTCVecEltisVT: { + return NodeToApply->getExtType(ResNo). + EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP); + } + case SDTCisSameNumEltsAs: { + unsigned OResNo = 0; + TreePatternNode *OtherNode = + getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum, + N, NodeInfo, OResNo); + return OtherNode->getExtType(OResNo). + EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP); + } } llvm_unreachable("Invalid ConstraintType!"); } @@ -1031,9 +1116,9 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { } else if (PropList[i]->getName() == "SDNPVariadic") { Properties |= 1 << SDNPVariadic; } else { - errs() << "Unknown SD Node property '" << PropList[i]->getName() - << "' on node '" << R->getName() << "'!\n"; - exit(1); + PrintFatalError("Unknown SD Node property '" + + PropList[i]->getName() + "' on node '" + + R->getName() + "'!"); } } @@ -1111,8 +1196,16 @@ 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.Operands.NumDefs ? 1 : 0; + unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; + + // Subtract any defaulted outputs. + for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { + Record *OperandNode = InstInfo.Operands[i].Rec; + + if (OperandNode->isSubClassOf("OperandWithDefaultOps") && + !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + --NumDefsToAdd; + } // Add on one implicit def if it has a resolvable type. if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) @@ -1130,8 +1223,7 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { return 1; Operator->dump(); - errs() << "Unhandled node in GetNumNodeResults\n"; - exit(1); + PrintFatalError("Unhandled node in GetNumNodeResults"); } void TreePatternNode::print(raw_ostream &OS) const { @@ -1689,8 +1781,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // 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.Operands.NumDefs ? 1 : 0; + unsigned NumResultsToAdd = std::min(InstInfo.Operands.NumDefs, + Inst.getNumResults()); for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP); @@ -1907,8 +1999,8 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false) { - for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) - Trees.push_back(ParseTreePattern(RawPat->getElement(i), "")); + for (Init *I : RawPat->getValues()) + Trees.push_back(ParseTreePattern(I, "")); } TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, @@ -1971,7 +2063,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ } // ?:$name or just $name. - if (TheInit == UnsetInit::get()) { + if (isa(TheInit)) { if (OpName.empty()) error("'?' argument requires a name to match with operand list"); TreePatternNode *Res = new TreePatternNode(TheInit, 1); @@ -2051,7 +2143,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Operator->getName() != "tblockaddress" && Operator->getName() != "tglobaladdr" && Operator->getName() != "bb" && - Operator->getName() != "vt") + Operator->getName() != "vt" && + Operator->getName() != "mcsym") error("Cannot use '" + Operator->getName() + "' in an output pattern!"); } @@ -2280,10 +2373,9 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { Record *N = Records.getDef(Name); - if (!N || !N->isSubClassOf("SDNode")) { - errs() << "Error getting SDNode '" << Name << "'!\n"; - exit(1); - } + if (!N || !N->isSubClassOf("SDNode")) + PrintFatalError("Error getting SDNode '" + Name + "'!"); + return N; } @@ -2723,7 +2815,7 @@ static bool InferFromPattern(CodeGenInstruction &InstInfo, if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) { // Allow explicitly setting mayLoad = 1, even when the pattern has no loads. - // Some targets translate imediates to loads. + // Some targets translate immediates to loads. if (!InstInfo.mayLoad) { Error = true; PrintError(PatDef->getLoc(), "Pattern doesn't match mayLoad = " + @@ -2769,8 +2861,8 @@ static bool hasNullFragReference(DagInit *DI) { /// hasNullFragReference - Return true if any DAG in the list references /// the null_frag operator. static bool hasNullFragReference(ListInit *LI) { - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) { - DagInit *DI = dyn_cast(LI->getElement(i)); + for (Init *I : LI->getValues()) { + DagInit *DI = dyn_cast(I); assert(DI && "non-dag in an instruction Pattern list?!"); if (hasNullFragReference(DI)) return true; @@ -2811,159 +2903,161 @@ static bool checkOperandClass(CGIOperandList::OperandInfo &OI, const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) { - assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); + assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); - // Parse the instruction. - TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this); - // Inline pattern fragments into it. - I->InlinePatternFragments(); + // Parse the instruction. + TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this); + // Inline pattern fragments into it. + I->InlinePatternFragments(); - // Infer as many types as possible. If we cannot infer all of them, we can - // never do anything with this instruction pattern: report it to the user. - if (!I->InferAllTypes()) - I->error("Could not infer all types in pattern!"); + // Infer as many types as possible. If we cannot infer all of them, we can + // never do anything with this instruction pattern: report it to the user. + if (!I->InferAllTypes()) + I->error("Could not infer all types in pattern!"); - // InstInputs - Keep track of all of the inputs of the instruction, along - // with the record they are declared as. - std::map InstInputs; + // InstInputs - Keep track of all of the inputs of the instruction, along + // with the record they are declared as. + std::map InstInputs; - // InstResults - Keep track of all the virtual registers that are 'set' - // in the instruction, including what reg class they are. - std::map InstResults; + // InstResults - Keep track of all the virtual registers that are 'set' + // in the instruction, including what reg class they are. + std::map InstResults; - std::vector InstImpResults; + std::vector InstImpResults; - // Verify that the top-level forms in the instruction are of void type, and - // fill in the InstResults map. - for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { - TreePatternNode *Pat = I->getTree(j); - if (Pat->getNumTypes() != 0) - I->error("Top-level forms in instruction pattern should have" - " void types"); + // Verify that the top-level forms in the instruction are of void type, and + // fill in the InstResults map. + for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { + TreePatternNode *Pat = I->getTree(j); + if (Pat->getNumTypes() != 0) + I->error("Top-level forms in instruction pattern should have" + " void types"); - // Find inputs and outputs, and verify the structure of the uses/defs. - FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, - InstImpResults); - } + // Find inputs and outputs, and verify the structure of the uses/defs. + FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, + InstImpResults); + } - // Now that we have inputs and outputs of the pattern, inspect the operands - // list for the instruction. This determines the order that operands are - // added to the machine instruction the node corresponds to. - unsigned NumResults = InstResults.size(); + // Now that we have inputs and outputs of the pattern, inspect the operands + // list for the instruction. This determines the order that operands are + // added to the machine instruction the node corresponds to. + unsigned NumResults = InstResults.size(); - // Parse the operands list from the (ops) list, validating it. - assert(I->getArgList().empty() && "Args list should still be empty here!"); + // Parse the operands list from the (ops) list, validating it. + assert(I->getArgList().empty() && "Args list should still be empty here!"); - // Check that all of the results occur first in the list. - std::vector Results; - TreePatternNode *Res0Node = nullptr; - for (unsigned i = 0; i != NumResults; ++i) { - if (i == CGI.Operands.size()) - I->error("'" + InstResults.begin()->first + - "' set but does not appear in operand list!"); - const std::string &OpName = CGI.Operands[i].Name; + // Check that all of the results occur first in the list. + std::vector Results; + SmallVector ResNodes; + for (unsigned i = 0; i != NumResults; ++i) { + if (i == CGI.Operands.size()) + I->error("'" + InstResults.begin()->first + + "' set but does not appear in operand list!"); + const std::string &OpName = CGI.Operands[i].Name; - // Check that it exists in InstResults. - TreePatternNode *RNode = InstResults[OpName]; - if (!RNode) - I->error("Operand $" + OpName + " does not exist in operand list!"); + // Check that it exists in InstResults. + TreePatternNode *RNode = InstResults[OpName]; + if (!RNode) + I->error("Operand $" + OpName + " does not exist in operand list!"); - if (i == 0) - Res0Node = RNode; - Record *R = cast(RNode->getLeafValue())->getDef(); - if (!R) - I->error("Operand $" + OpName + " should be a set destination: all " - "outputs must occur before inputs in operand list!"); + ResNodes.push_back(RNode); - if (!checkOperandClass(CGI.Operands[i], R)) - I->error("Operand $" + OpName + " class mismatch!"); + Record *R = cast(RNode->getLeafValue())->getDef(); + if (!R) + I->error("Operand $" + OpName + " should be a set destination: all " + "outputs must occur before inputs in operand list!"); - // Remember the return type. - Results.push_back(CGI.Operands[i].Rec); + if (!checkOperandClass(CGI.Operands[i], R)) + I->error("Operand $" + OpName + " class mismatch!"); - // Okay, this one checks out. - InstResults.erase(OpName); - } + // Remember the return type. + Results.push_back(CGI.Operands[i].Rec); - // Loop over the inputs next. Make a copy of InstInputs so we can destroy - // the copy while we're checking the inputs. - std::map InstInputsCheck(InstInputs); + // Okay, this one checks out. + InstResults.erase(OpName); + } - std::vector ResultNodeOperands; - std::vector Operands; - for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { - CGIOperandList::OperandInfo &Op = CGI.Operands[i]; - const std::string &OpName = Op.Name; - if (OpName.empty()) - I->error("Operand #" + utostr(i) + " in operands list has no name!"); - - if (!InstInputsCheck.count(OpName)) { - // If this is an operand with a DefaultOps set filled in, we can ignore - // this. When we codegen it, we will do so as always executed. - if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { - // Does it have a non-empty DefaultOps field? If so, ignore this - // operand. - if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) - continue; - } - I->error("Operand $" + OpName + - " does not appear in the instruction pattern"); - } - TreePatternNode *InVal = InstInputsCheck[OpName]; - InstInputsCheck.erase(OpName); // It occurred, remove from map. - - if (InVal->isLeaf() && isa(InVal->getLeafValue())) { - Record *InRec = static_cast(InVal->getLeafValue())->getDef(); - if (!checkOperandClass(Op, InRec)) - I->error("Operand $" + OpName + "'s register class disagrees" - " between the operand and pattern"); + // Loop over the inputs next. Make a copy of InstInputs so we can destroy + // the copy while we're checking the inputs. + std::map InstInputsCheck(InstInputs); + + std::vector ResultNodeOperands; + std::vector Operands; + for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { + CGIOperandList::OperandInfo &Op = CGI.Operands[i]; + const std::string &OpName = Op.Name; + if (OpName.empty()) + I->error("Operand #" + utostr(i) + " in operands list has no name!"); + + if (!InstInputsCheck.count(OpName)) { + // If this is an operand with a DefaultOps set filled in, we can ignore + // this. When we codegen it, we will do so as always executed. + if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { + // Does it have a non-empty DefaultOps field? If so, ignore this + // operand. + if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) + continue; } - Operands.push_back(Op.Rec); + I->error("Operand $" + OpName + + " does not appear in the instruction pattern"); + } + TreePatternNode *InVal = InstInputsCheck[OpName]; + InstInputsCheck.erase(OpName); // It occurred, remove from map. - // Construct the result for the dest-pattern operand list. - TreePatternNode *OpNode = InVal->clone(); + if (InVal->isLeaf() && isa(InVal->getLeafValue())) { + Record *InRec = static_cast(InVal->getLeafValue())->getDef(); + if (!checkOperandClass(Op, InRec)) + I->error("Operand $" + OpName + "'s register class disagrees" + " between the operand and pattern"); + } + Operands.push_back(Op.Rec); - // No predicate is useful on the result. - OpNode->clearPredicateFns(); + // Construct the result for the dest-pattern operand list. + TreePatternNode *OpNode = InVal->clone(); - // Promote the xform function to be an explicit node if set. - if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(nullptr); - std::vector Children; - Children.push_back(OpNode); - OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); - } + // No predicate is useful on the result. + OpNode->clearPredicateFns(); - ResultNodeOperands.push_back(OpNode); + // Promote the xform function to be an explicit node if set. + if (Record *Xform = OpNode->getTransformFn()) { + OpNode->setTransformFn(nullptr); + std::vector Children; + Children.push_back(OpNode); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } - if (!InstInputsCheck.empty()) - I->error("Input operand $" + InstInputsCheck.begin()->first + - " occurs in pattern but not in operands list!"); + ResultNodeOperands.push_back(OpNode); + } - TreePatternNode *ResultPattern = - new TreePatternNode(I->getRecord(), ResultNodeOperands, - GetNumNodeResults(I->getRecord(), *this)); - // Copy fully inferred output node type to instruction result pattern. - for (unsigned i = 0; i != NumResults; ++i) - ResultPattern->setType(i, Res0Node->getExtType(i)); + if (!InstInputsCheck.empty()) + I->error("Input operand $" + InstInputsCheck.begin()->first + + " occurs in pattern but not in operands list!"); - // Create and insert the instruction. - // FIXME: InstImpResults should not be part of DAGInstruction. - DAGInstruction TheInst(I, Results, Operands, InstImpResults); - DAGInsts.insert(std::make_pair(I->getRecord(), TheInst)); + TreePatternNode *ResultPattern = + new TreePatternNode(I->getRecord(), ResultNodeOperands, + GetNumNodeResults(I->getRecord(), *this)); + // Copy fully inferred output node types to instruction result pattern. + for (unsigned i = 0; i != NumResults; ++i) { + assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); + ResultPattern->setType(i, ResNodes[i]->getExtType(0)); + } - // Use a temporary tree pattern to infer all types and make sure that the - // constructed result is correct. This depends on the instruction already - // being inserted into the DAGInsts map. - TreePattern Temp(I->getRecord(), ResultPattern, false, *this); - Temp.InferAllTypes(&I->getNamedNodesMap()); + // Create and insert the instruction. + // FIXME: InstImpResults should not be part of DAGInstruction. + DAGInstruction TheInst(I, Results, Operands, InstImpResults); + DAGInsts.insert(std::make_pair(I->getRecord(), TheInst)); - DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second; - TheInsertedInst.setResultPattern(Temp.getOnlyTree()); + // Use a temporary tree pattern to infer all types and make sure that the + // constructed result is correct. This depends on the instruction already + // being inserted into the DAGInsts map. + TreePattern Temp(I->getRecord(), ResultPattern, false, *this); + Temp.InferAllTypes(&I->getNamedNodesMap()); - return TheInsertedInst; - } + DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second; + TheInsertedInst.setResultPattern(Temp.getOnlyTree()); + + return TheInsertedInst; +} /// ParseInstructions - Parse all of the instructions, inlining and resolving /// any fragments involved. This populates the Instructions list with fully @@ -2983,25 +3077,20 @@ void CodeGenDAGPatterns::ParseInstructions() { // null_frag operator is as-if no pattern were specified. Normally this // is from a multiclass expansion w/ a SDPatternOperator passed in as // null_frag. - if (!LI || LI->getSize() == 0 || hasNullFragReference(LI)) { + if (!LI || LI->empty() || hasNullFragReference(LI)) { std::vector Results; std::vector Operands; CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); if (InstInfo.Operands.size() != 0) { - if (InstInfo.Operands.NumDefs == 0) { - // These produce no results - for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j) - Operands.push_back(InstInfo.Operands[j].Rec); - } else { - // Assume the first operand is the result. - Results.push_back(InstInfo.Operands[0].Rec); - - // The rest are inputs. - for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j) - Operands.push_back(InstInfo.Operands[j].Rec); - } + for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j) + Results.push_back(InstInfo.Operands[j].Rec); + + // The rest are inputs. + for (unsigned j = InstInfo.Operands.NumDefs, + e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); } // Create and insert the instruction. @@ -3258,7 +3347,7 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() { if (InstInfo.InferredFrom && InstInfo.InferredFrom != InstInfo.TheDef && InstInfo.InferredFrom != PTM.getSrcRecord()) - PrintError(InstInfo.InferredFrom->getLoc(), "inferred from patttern"); + PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern"); } } if (Errors) @@ -3311,7 +3400,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->InlinePatternFragments(); ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); - if (LI->getSize() == 0) continue; // no pattern. + if (LI->empty()) continue; // no pattern. // Parse the instruction. TreePattern Result(CurPattern, LI, false, *this); @@ -3484,7 +3573,7 @@ static void CombineChildVariants(TreePatternNode *Orig, } // Increment indices to the next permutation by incrementing the - // indicies from last index backward, e.g., generate the sequence + // indices from last index backward, e.g., generate the sequence // [0, 0], [0, 1], [1, 0], [1, 1]. int IdxsIdx; for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { @@ -3635,7 +3724,7 @@ static void GenerateVariantsOf(TreePatternNode *N, // operands are the commutative operands, and there might be more operands // after those. assert(NC >= 3 && - "Commutative intrinsic should have at least 3 childrean!"); + "Commutative intrinsic should have at least 3 children!"); std::vector > Variants; Variants.push_back(ChildVariants[0]); // Intrinsic id. Variants.push_back(ChildVariants[2]); @@ -3710,13 +3799,11 @@ void CodeGenDAGPatterns::GenerateVariants() { if (AlreadyExists) continue; // Otherwise, add it to the list of patterns we have. - PatternsToMatch. - push_back(PatternToMatch(PatternsToMatch[i].getSrcRecord(), - PatternsToMatch[i].getPredicates(), - Variant, PatternsToMatch[i].getDstPattern(), - PatternsToMatch[i].getDstRegs(), - PatternsToMatch[i].getAddedComplexity(), - Record::getNewUID())); + PatternsToMatch.emplace_back( + PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(), + Variant, PatternsToMatch[i].getDstPattern(), + PatternsToMatch[i].getDstRegs(), + PatternsToMatch[i].getAddedComplexity(), Record::getNewUID()); } DEBUG(errs() << "\n");