From b73628b5abee86ef76e1ed8c7f9eaed85bea61a8 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Fri, 30 Dec 2005 00:12:56 +0000 Subject: [PATCH] Add support for generating v4i32 altivec code git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25046 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCInstrInfo.td | 12 +- utils/TableGen/CodeGenRegisters.h | 2 +- utils/TableGen/DAGISelEmitter.cpp | 239 +++++++++++++++++++---------- utils/TableGen/DAGISelEmitter.h | 36 +++-- 4 files changed, 190 insertions(+), 99 deletions(-) diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 2830964c6a9..395eab678d5 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -447,7 +447,7 @@ def LVEWX: XForm_1<31, 71, (ops VRRC:$vD, GPRC:$base, GPRC:$rA), []>; def LVX : XForm_1<31, 103, (ops VRRC:$vD, memrr:$src), "lvx $vD, $src", LdStGeneral, - [(set VRRC:$vD, (load xoaddr:$src))]>; + [(set VRRC:$vD, (v4f32 (load xoaddr:$src)))]>; } def LVSL : XForm_1<31, 6, (ops VRRC:$vD, GPRC:$base, GPRC:$rA), "lvsl $vD, $base, $rA", LdStGeneral, @@ -542,7 +542,7 @@ def STVEWX: XForm_8<31, 199, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB), []>; def STVX : XForm_8<31, 231, (ops VRRC:$rS, memrr:$dst), "stvx $rS, $dst", LdStGeneral, - [(store VRRC:$rS, xoaddr:$dst)]>; + [(store (v4f32 VRRC:$rS), xoaddr:$dst)]>; } def SRAWI : XForm_10<31, 824, (ops GPRC:$rA, GPRC:$rS, u5imm:$SH), "srawi $rA, $rS, $SH", IntShift, @@ -892,6 +892,9 @@ def VNMSUBFP: VAForm_1<47, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB, VRRC:$vC), def VADDFP : VXForm_1<10, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vaddfp $vD, $vA, $vB", VecFP, [(set VRRC:$vD, (fadd VRRC:$vA, VRRC:$vB))]>; +def VADDUWM : VXForm_1<128, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), + "vadduwm $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (add VRRC:$vA, VRRC:$vB))]>; def VCFSX : VXForm_1<842, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB), "vcfsx $vD, $vB, $UIMM", VecFP, []>; @@ -1060,6 +1063,11 @@ def : Pat<(f64 (extload iaddr:$src, f32)), def : Pat<(f64 (extload xaddr:$src, f32)), (FMRSD (LFSX xaddr:$src))>; +def : Pat<(v4i32 (load xoaddr:$src)), + (v4i32 (LVX xoaddr:$src))>; +def : Pat<(store (v4i32 VRRC:$rS), xoaddr:$dst), + (STVX (v4i32 VRRC:$rS), xoaddr:$dst)>; + def : Pat<(retflag), (BLR)>; // Same as above, but using a temporary. FIXME: implement temporaries :) diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index fbbec9a32a2..8e9008c74aa 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -41,7 +41,7 @@ namespace llvm { std::string MethodProtos, MethodBodies; const std::string &getName() const; - + const std::vector &getValueTypes() const { return VTs; } unsigned getNumValueTypes() const { return VTs.size(); } const MVT::ValueType getValueTypeNum(unsigned VTNum) const { diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 85ebfdece9a..fc75cb5a824 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -34,18 +34,45 @@ FilterVTs(const std::vector &InVTs, T Filter) { return Result; } -/// isExtIntegerVT - Return true if the specified extended value type is -/// integer, or isInt. -static bool isExtIntegerVT(unsigned char VT) { - return VT == MVT::isInt || - (VT < MVT::LAST_VALUETYPE && MVT::isInteger((MVT::ValueType)VT)); +template +static std::vector +FilterEVTs(const std::vector &InVTs, T Filter) { + std::vector Result; + for (unsigned i = 0, e = InVTs.size(); i != e; ++i) + if (Filter((MVT::ValueType)InVTs[i])) + Result.push_back(InVTs[i]); + return Result; +} + +static std::vector +ConvertVTs(const std::vector &InVTs) { + std::vector Result; + for (unsigned i = 0, e = InVTs.size(); i != e; ++i) + Result.push_back(InVTs[i]); + return Result; +} + +static bool LHSIsSubsetOfRHS(const std::vector &LHS, + const std::vector &RHS) { + if (LHS.size() > RHS.size()) return false; + for (unsigned i = 0, e = LHS.size(); i != e; ++i) + if (find(RHS.begin(), RHS.end(), LHS[i]) == RHS.end()) + return false; + return true; +} + +/// isExtIntegerVT - Return true if the specified extended value type vector +/// contains isInt or an integer value type. +static bool isExtIntegerInVTs(std::vector EVTs) { + assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!"); + return EVTs[0] == MVT::isInt || !(FilterEVTs(EVTs, MVT::isInteger).empty()); } -/// isExtFloatingPointVT - Return true if the specified extended value type is -/// floating point, or isFP. -static bool isExtFloatingPointVT(unsigned char VT) { - return VT == MVT::isFP || - (VT < MVT::LAST_VALUETYPE && MVT::isFloatingPoint((MVT::ValueType)VT)); +/// isExtFloatingPointVT - Return true if the specified extended value type +/// vector contains isFP or a FP value type. +static bool isExtFloatingPointInVTs(std::vector EVTs) { + assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!"); + return EVTs[0] == MVT::isFP || !(FilterEVTs(EVTs, MVT::isFloatingPoint).empty()); } //===----------------------------------------------------------------------===// @@ -149,8 +176,8 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, case SDTCisSameAs: { TreePatternNode *OtherNode = getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults); - return NodeToApply->UpdateNodeType(OtherNode->getExtType(), TP) | - OtherNode->UpdateNodeType(NodeToApply->getExtType(), TP); + return NodeToApply->UpdateNodeType(OtherNode->getExtTypes(), TP) | + OtherNode->UpdateNodeType(NodeToApply->getExtTypes(), TP); } case SDTCisVTSmallerThanOp: { // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must @@ -172,7 +199,11 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, bool MadeChange = false; MadeChange |= OtherNode->UpdateNodeType(MVT::isInt, TP); - if (OtherNode->hasTypeSet() && OtherNode->getType() <= VT) + // This code only handles nodes that have one type set. Assert here so + // that we can change this if we ever need to deal with multiple value + // types at this point. + assert(OtherNode->getExtTypes().size() == 1 && "Node has too many types!"); + if (OtherNode->hasTypeSet() && OtherNode->getTypeNum(0) <= VT) OtherNode->UpdateNodeType(MVT::Other, TP); // Throw an error. return false; } @@ -183,20 +214,28 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, // Both operands must be integer or FP, but we don't care which. bool MadeChange = false; - if (isExtIntegerVT(NodeToApply->getExtType())) + // 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. + assert(!(isExtIntegerInVTs(NodeToApply->getExtTypes()) && + isExtFloatingPointInVTs(NodeToApply->getExtTypes())) && + !(isExtIntegerInVTs(BigOperand->getExtTypes()) && + isExtFloatingPointInVTs(BigOperand->getExtTypes())) && + "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); + if (isExtIntegerInVTs(NodeToApply->getExtTypes())) MadeChange |= BigOperand->UpdateNodeType(MVT::isInt, TP); - else if (isExtFloatingPointVT(NodeToApply->getExtType())) + else if (isExtFloatingPointInVTs(NodeToApply->getExtTypes())) MadeChange |= BigOperand->UpdateNodeType(MVT::isFP, TP); - if (isExtIntegerVT(BigOperand->getExtType())) + if (isExtIntegerInVTs(BigOperand->getExtTypes())) MadeChange |= NodeToApply->UpdateNodeType(MVT::isInt, TP); - else if (isExtFloatingPointVT(BigOperand->getExtType())) + else if (isExtFloatingPointInVTs(BigOperand->getExtTypes())) MadeChange |= NodeToApply->UpdateNodeType(MVT::isFP, TP); std::vector VTs = CGT.getLegalValueTypes(); - if (isExtIntegerVT(NodeToApply->getExtType())) { + if (isExtIntegerInVTs(NodeToApply->getExtTypes())) { VTs = FilterVTs(VTs, MVT::isInteger); - } else if (isExtFloatingPointVT(NodeToApply->getExtType())) { + } else if (isExtFloatingPointInVTs(NodeToApply->getExtTypes())) { VTs = FilterVTs(VTs, MVT::isFloatingPoint); } else { VTs.clear(); @@ -273,24 +312,42 @@ TreePatternNode::~TreePatternNode() { /// information. If N already contains a conflicting type, then throw an /// exception. This returns true if any information was updated. /// -bool TreePatternNode::UpdateNodeType(unsigned char VT, TreePattern &TP) { - if (VT == MVT::isUnknown || getExtType() == VT) return false; - if (getExtType() == MVT::isUnknown) { - setType(VT); +bool TreePatternNode::UpdateNodeType(const std::vector &ExtVTs, + TreePattern &TP) { + assert(!ExtVTs.empty() && "Cannot update node type with empty type vector!"); + + if (ExtVTs[0] == MVT::isUnknown || LHSIsSubsetOfRHS(getExtTypes(), ExtVTs)) + return false; + if (isTypeCompletelyUnknown() || LHSIsSubsetOfRHS(ExtVTs, getExtTypes())) { + setTypes(ExtVTs); return true; } - // If we are told this is to be an int or FP type, and it already is, ignore - // the advice. - if ((VT == MVT::isInt && isExtIntegerVT(getExtType())) || - (VT == MVT::isFP && isExtFloatingPointVT(getExtType()))) - return false; + if (ExtVTs[0] == MVT::isInt && isExtIntegerInVTs(getExtTypes())) { + assert(hasTypeSet() && "should be handled above!"); + std::vector FVTs = FilterEVTs(getExtTypes(), MVT::isInteger); + if (getExtTypes() == FVTs) + return false; + setTypes(FVTs); + return true; + } + if (ExtVTs[0] == MVT::isFP && isExtFloatingPointInVTs(getExtTypes())) { + assert(hasTypeSet() && "should be handled above!"); + std::vector FVTs = FilterEVTs(getExtTypes(), MVT::isFloatingPoint); + if (getExtTypes() == FVTs) + return false; + setTypes(FVTs); + return true; + } // If we know this is an int or fp type, and we are told it is a specific one, // take the advice. - if ((getExtType() == MVT::isInt && isExtIntegerVT(VT)) || - (getExtType() == MVT::isFP && isExtFloatingPointVT(VT))) { - setType(VT); + // + // Similarly, we should probably set the type here to the intersection of + // {isInt|isFP} and ExtVTs + if ((getExtTypeNum(0) == MVT::isInt && isExtIntegerInVTs(ExtVTs)) || + (getExtTypeNum(0) == MVT::isFP && isExtFloatingPointInVTs(ExtVTs))) { + setTypes(ExtVTs); return true; } @@ -313,12 +370,14 @@ void TreePatternNode::print(std::ostream &OS) const { OS << "(" << getOperator()->getName(); } - switch (getExtType()) { + // FIXME: At some point we should handle printing all the value types for + // nodes that are multiply typed. + switch (getExtTypeNum(0)) { case MVT::Other: OS << ":Other"; break; case MVT::isInt: OS << ":isInt"; break; case MVT::isFP : OS << ":isFP"; break; case MVT::isUnknown: ; /*OS << ":?";*/ break; - default: OS << ":" << getType(); break; + default: OS << ":" << getTypeNum(0); break; } if (!isLeaf()) { @@ -351,7 +410,7 @@ void TreePatternNode::dump() const { /// that are otherwise identical are considered isomorphic. bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N) const { if (N == this) return true; - if (N->isLeaf() != isLeaf() || getExtType() != N->getExtType() || + if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() || getPredicateFn() != N->getPredicateFn() || getTransformFn() != N->getTransformFn()) return false; @@ -385,7 +444,7 @@ TreePatternNode *TreePatternNode::clone() const { New = new TreePatternNode(getOperator(), CChildren); } New->setName(getName()); - New->setType(getExtType()); + New->setTypes(getExtTypes()); New->setPredicateFn(getPredicateFn()); New->setTransformFn(getTransformFn()); return New; @@ -451,7 +510,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { } FragTree->setName(getName()); - FragTree->UpdateNodeType(getExtType(), TP); + FragTree->UpdateNodeType(getExtTypes(), TP); // Get a new copy of this fragment to stitch into here. //delete this; // FIXME: implement refcounting! @@ -462,37 +521,43 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { /// type which should be applied to it. This infer the type of register /// references from the register file information, for example. /// -static unsigned char getIntrinsicType(Record *R, bool NotRegisters, +static std::vector getIntrinsicType(Record *R, bool NotRegisters, TreePattern &TP) { + // Some common return values + std::vector Unknown(1, MVT::isUnknown); + std::vector Other(1, MVT::Other); + // Check to see if this is a register or a register class... if (R->isSubClassOf("RegisterClass")) { - if (NotRegisters) return MVT::isUnknown; + if (NotRegisters) + return Unknown; const CodeGenRegisterClass &RC = TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(R); - return RC.getValueTypeNum(0); + return ConvertVTs(RC.getValueTypes()); } else if (R->isSubClassOf("PatFrag")) { // Pattern fragment types will be resolved when they are inlined. - return MVT::isUnknown; + return Unknown; } else if (R->isSubClassOf("Register")) { // If the register appears in exactly one regclass, and the regclass has one // value type, use it as the known type. const CodeGenTarget &T = TP.getDAGISelEmitter().getTargetInfo(); if (const CodeGenRegisterClass *RC = T.getRegisterClassForRegister(R)) - if (RC->getNumValueTypes() == 1) - return RC->getValueTypeNum(0); - return MVT::isUnknown; + return ConvertVTs(RC->getValueTypes()); + return Unknown; } else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { // Using a VTSDNode or CondCodeSDNode. - return MVT::Other; + return Other; } else if (R->isSubClassOf("ComplexPattern")) { - return TP.getDAGISelEmitter().getComplexPattern(R).getValueType(); + std::vector + ComplexPat(1, TP.getDAGISelEmitter().getComplexPattern(R).getValueType()); + return ComplexPat; } else if (R->getName() == "node" || R->getName() == "srcvalue") { // Placeholder. - return MVT::isUnknown; + return Unknown; } TP.error("Unknown node flavor used in pattern: " + R->getName()); - return MVT::Other; + return Other; } /// ApplyTypeConstraints - Apply all of the type constraints relevent to @@ -510,14 +575,19 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { bool MadeChange = UpdateNodeType(MVT::isInt, TP); if (hasTypeSet()) { - unsigned Size = MVT::getSizeInBits(getType()); + // At some point, it may make sense for this tree pattern to have + // multiple types. Assert here that it does not, so we revisit this + // code when appropriate. + assert(getExtTypes().size() == 1 && "TreePattern has too many types!"); + + unsigned Size = MVT::getSizeInBits(getTypeNum(0)); // Make sure that the value is representable for this type. if (Size < 32) { int Val = (II->getValue() << (32-Size)) >> (32-Size); if (Val != II->getValue()) TP.error("Sign-extended integer value '" + itostr(II->getValue()) + "' is out of range for type 'MVT::" + - getEnumName(getType()) + "'!"); + getEnumName(getTypeNum(0)) + "'!"); } } @@ -533,8 +603,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters); // Types of operands must match. - MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getExtType(), TP); - MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getExtType(), TP); + MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getExtTypes(), TP); + MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getExtTypes(), TP); MadeChange |= UpdateNodeType(MVT::isVoid, TP); return MadeChange; } else if (getOperator()->isSubClassOf("SDNode")) { @@ -566,9 +636,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { const CodeGenRegisterClass &RC = TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(ResultNode); - - // Get the first ValueType in the RegClass, it's as good as any. - MadeChange = UpdateNodeType(RC.getValueTypeNum(0), TP); + MadeChange = UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP); } if (getNumChildren() != Inst.getNumOperands()) @@ -581,15 +649,16 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (OperandNode->isSubClassOf("RegisterClass")) { const CodeGenRegisterClass &RC = TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(OperandNode); - VT = RC.getValueTypeNum(0); + //VT = RC.getValueTypeNum(0); + MadeChange |=getChild(i)->UpdateNodeType(ConvertVTs(RC.getValueTypes()), + TP); } else if (OperandNode->isSubClassOf("Operand")) { VT = getValueType(OperandNode->getValueAsDef("Type")); + MadeChange |= getChild(i)->UpdateNodeType(VT, TP); } else { assert(0 && "Unknown operand type!"); abort(); } - - MadeChange |= getChild(i)->UpdateNodeType(VT, TP); MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); } return MadeChange; @@ -601,8 +670,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (getNumChildren() != 1) TP.error("Node transform '" + getOperator()->getName() + "' requires one operand!"); - bool MadeChange = UpdateNodeType(getChild(0)->getExtType(), TP); - MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP); + bool MadeChange = UpdateNodeType(getChild(0)->getExtTypes(), TP); + MadeChange |= getChild(0)->UpdateNodeType(getExtTypes(), TP); return MadeChange; } } @@ -995,7 +1064,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, // Ensure that the inputs agree if we've already seen this input. if (Rec != SlotRec) I->error("All $" + Pat->getName() + " inputs must agree with each other"); - if (Slot->getExtType() != Pat->getExtType()) + if (Slot->getExtTypes() != Pat->getExtTypes()) I->error("All $" + Pat->getName() + " inputs must agree with each other"); } return true; @@ -1019,7 +1088,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, // If this is not a set, verify that the children nodes are not void typed, // and recurse. for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { - if (Pat->getChild(i)->getExtType() == MVT::isVoid) + if (Pat->getChild(i)->getExtTypeNum(0) == MVT::isVoid) I->error("Cannot have void nodes inside of patterns!"); FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults, InstImpInputs, InstImpResults); @@ -1146,7 +1215,7 @@ void DAGISelEmitter::ParseInstructions() { // fill in the InstResults map. for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { TreePatternNode *Pat = I->getTree(j); - if (Pat->getExtType() != MVT::isVoid) + if (Pat->getExtTypeNum(0) != MVT::isVoid) I->error("Top-level forms in instruction pattern should have" " void types"); @@ -1372,7 +1441,7 @@ static void CombineChildVariants(TreePatternNode *Orig, R->setName(Orig->getName()); R->setPredicateFn(Orig->getPredicateFn()); R->setTransformFn(Orig->getTransformFn()); - R->setType(Orig->getExtType()); + R->setTypes(Orig->getExtTypes()); // If this pattern cannot every match, do not include it as a variant. std::string ErrString; @@ -1622,10 +1691,11 @@ static const ComplexPattern *NodeGetComplexPattern(TreePatternNode *N, /// patterns before small ones. This is used to determine the size of a /// pattern. static unsigned getPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) { - assert(isExtIntegerVT(P->getExtType()) || - isExtFloatingPointVT(P->getExtType()) || - P->getExtType() == MVT::isVoid || - P->getExtType() == MVT::Flag && "Not a valid pattern node to size!"); + assert(isExtIntegerInVTs(P->getExtTypes()) || + isExtFloatingPointInVTs(P->getExtTypes()) || + P->getExtTypeNum(0) == MVT::isVoid || + P->getExtTypeNum(0) == MVT::Flag && + "Not a valid pattern node to size!"); unsigned Size = 1; // The node itself. // FIXME: This is a hack to statically increase the priority of patterns @@ -1640,7 +1710,7 @@ static unsigned getPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) { // 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->getExtType() != MVT::Other) + if (!Child->isLeaf() && Child->getExtTypeNum(0) != MVT::Other) Size += getPatternSize(Child, ISE); else if (Child->isLeaf()) { if (dynamic_cast(Child->getLeafValue())) @@ -1697,7 +1767,7 @@ static MVT::ValueType getRegisterValueType(Record *R, const CodeGenTarget &T) { /// RemoveAllTypes - A quick recursive walk over a pattern which removes all /// type information from it. static void RemoveAllTypes(TreePatternNode *N) { - N->setType(MVT::isUnknown); + N->removeTypes(); if (!N->isLeaf()) for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) RemoveAllTypes(N->getChild(i)); @@ -1959,7 +2029,8 @@ public: unsigned ResNo = TmpNo++; unsigned NumRes = 1; if (!N->isLeaf() && N->getOperator()->getName() == "imm") { - switch (N->getType()) { + assert(N->getExtTypes().size() == 1 && "Multiple types not handled!"); + switch (N->getTypeNum(0)) { default: assert(0 && "Unknown type for constant node!"); case MVT::i1: OS << " bool Tmp"; break; case MVT::i8: OS << " unsigned char Tmp"; break; @@ -1971,7 +2042,7 @@ public: OS << " "; DeclareSDOperand("Tmp"+utostr(ResNo)); OS << " = CurDAG->getTargetConstant(Tmp" - << ResNo << "C, MVT::" << getEnumName(N->getType()) << ");\n"; + << ResNo << "C, MVT::" << getEnumName(N->getTypeNum(0)) << ");\n"; } else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") { OS << " "; DeclareSDOperand("Tmp"+utostr(ResNo)); @@ -2019,7 +2090,7 @@ public: DeclareSDOperand("Tmp"+utostr(ResNo)); OS << " = CurDAG->getRegister(" << ISE.getQualifiedName(DI->getDef()) << ", MVT::" - << getEnumName(N->getType()) + << getEnumName(N->getTypeNum(0)) << ");\n"; return std::make_pair(1, ResNo); } @@ -2027,9 +2098,10 @@ public: unsigned ResNo = TmpNo++; OS << " "; DeclareSDOperand("Tmp"+utostr(ResNo)); + assert(N->getExtTypes().size() == 1 && "Multiple types not handled!"); OS << " = CurDAG->getTargetConstant(" << II->getValue() << ", MVT::" - << getEnumName(N->getType()) + << getEnumName(N->getTypeNum(0)) << ");\n"; return std::make_pair(1, ResNo); } @@ -2099,8 +2171,8 @@ public: DeclareSDOperand("Tmp"+utostr(ResNo)); OS << " = CurDAG->getTargetNode(" << II.Namespace << "::" << II.TheDef->getName(); - if (N->getType() != MVT::isVoid) - OS << ", MVT::" << getEnumName(N->getType()); + if (N->getTypeNum(0) != MVT::isVoid) + OS << ", MVT::" << getEnumName(N->getTypeNum(0)); if (HasOutFlag) OS << ", MVT::Flag"; @@ -2122,9 +2194,8 @@ public: // Output order: results, chain, flags // Result types. if (NumResults > 0) { - // TODO: multiple results? - if (N->getType() != MVT::isVoid) - OS << ", MVT::" << getEnumName(N->getType()); + if (N->getTypeNum(0) != MVT::isVoid) + OS << ", MVT::" << getEnumName(N->getTypeNum(0)); } if (HasChain) OS << ", MVT::Other"; @@ -2195,8 +2266,8 @@ public: OS << " if (N.Val->hasOneUse()) {\n"; OS << " return CurDAG->SelectNodeTo(N.Val, " << II.Namespace << "::" << II.TheDef->getName(); - if (N->getType() != MVT::isVoid) - OS << ", MVT::" << getEnumName(N->getType()); + if (N->getTypeNum(0) != MVT::isVoid) + OS << ", MVT::" << getEnumName(N->getTypeNum(0)); if (HasOutFlag) OS << ", MVT::Flag"; for (unsigned i = 0, e = Ops.size(); i != e; ++i) @@ -2207,8 +2278,8 @@ public: OS << " } else {\n"; OS << " return CodeGenMap[N] = CurDAG->getTargetNode(" << II.Namespace << "::" << II.TheDef->getName(); - if (N->getType() != MVT::isVoid) - OS << ", MVT::" << getEnumName(N->getType()); + if (N->getTypeNum(0) != MVT::isVoid) + OS << ", MVT::" << getEnumName(N->getTypeNum(0)); if (HasOutFlag) OS << ", MVT::Flag"; for (unsigned i = 0, e = Ops.size(); i != e; ++i) @@ -2249,9 +2320,9 @@ public: // Did we find one? if (!Pat->hasTypeSet()) { // Move a type over from 'other' to 'pat'. - Pat->setType(Other->getType()); + Pat->setTypes(Other->getExtTypes()); OS << " if (" << Prefix << ".Val->getValueType(0) != MVT::" - << getName(Pat->getType()) << ") goto P" << PatternNo << "Fail;\n"; + << getName(Pat->getTypeNum(0)) << ") goto P" << PatternNo << "Fail;\n"; return true; } diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 5b3aa6313fc..9bf7c205bb3 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -124,9 +124,9 @@ namespace llvm { /// patterns), and as such should be ref counted. We currently just leak all /// TreePatternNode objects! class TreePatternNode { - /// The inferred type for this node, or MVT::LAST_VALUETYPE if it hasn't + /// The inferred type for this node, or MVT::isUnknown if it hasn't /// been determined yet. - unsigned char Ty; + std::vector Types; /// Operator - The Record for the operator if this is an interior node (not /// a leaf). @@ -151,26 +151,32 @@ namespace llvm { std::vector Children; public: TreePatternNode(Record *Op, const std::vector &Ch) - : Ty(MVT::isUnknown), Operator(Op), Val(0), TransformFn(0), - Children(Ch) {} + : Types(), Operator(Op), Val(0), TransformFn(0), + Children(Ch) { Types.push_back(MVT::isUnknown); } TreePatternNode(Init *val) // leaf ctor - : Ty(MVT::isUnknown), Operator(0), Val(val), TransformFn(0) {} + : Types(), Operator(0), Val(val), TransformFn(0) { Types.push_back(MVT::isUnknown); } ~TreePatternNode(); const std::string &getName() const { return Name; } void setName(const std::string &N) { Name = N; } bool isLeaf() const { return Val != 0; } - bool hasTypeSet() const { return Ty < MVT::LAST_VALUETYPE; } + bool hasTypeSet() const { return Types[0] < MVT::LAST_VALUETYPE; } bool isTypeCompletelyUnknown() const { - return Ty == MVT::isUnknown; + return Types[0] == MVT::isUnknown; } - MVT::ValueType getType() const { + MVT::ValueType getTypeNum(unsigned Num) const { assert(hasTypeSet() && "Doesn't have a type yet!"); - return (MVT::ValueType)Ty; + assert(Types.size() > Num && "Type num out of range!"); + return (MVT::ValueType)Types[Num]; } - unsigned char getExtType() const { return Ty; } - void setType(unsigned char VT) { Ty = VT; } + unsigned char getExtTypeNum(unsigned Num) const { + assert(Types.size() > Num && "Extended type num out of range!"); + return Types[Num]; + } + const std::vector &getExtTypes() const { return Types; } + void setTypes(const std::vector &T) { Types = T; } + void removeTypes() { Types = std::vector(1,MVT::isUnknown); } Init *getLeafValue() const { assert(isLeaf()); return Val; } Record *getOperator() const { assert(!isLeaf()); return Operator; } @@ -181,6 +187,7 @@ namespace llvm { Children[i] = N; } + const std::string &getPredicateFn() const { return PredicateFn; } void setPredicateFn(const std::string &Fn) { PredicateFn = Fn; } @@ -222,7 +229,12 @@ namespace llvm { /// information. If N already contains a conflicting type, then throw an /// exception. This returns true if any information was updated. /// - bool UpdateNodeType(unsigned char EVT, TreePattern &TP); + bool UpdateNodeType(const std::vector &ExtVTs, + TreePattern &TP); + bool UpdateNodeType(unsigned char ExtVT, TreePattern &TP) { + std::vector ExtVTs(1, ExtVT); + return UpdateNodeType(ExtVTs, TP); + } /// ContainsUnresolvedType - Return true if this tree contains any /// unresolved types. -- 2.34.1