summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td12
-rw-r--r--utils/TableGen/CodeGenRegisters.h2
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp239
-rw-r--r--utils/TableGen/DAGISelEmitter.h36
4 files changed, 190 insertions, 99 deletions
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 2830964c6a..395eab678d 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 fbbec9a32a..8e9008c74a 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<MVT::ValueType> &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 85ebfdece9..fc75cb5a82 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -34,18 +34,45 @@ FilterVTs(const std::vector<MVT::ValueType> &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<typename T>
+static std::vector<unsigned char>
+FilterEVTs(const std::vector<unsigned char> &InVTs, T Filter) {
+ std::vector<unsigned char> 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<unsigned char>
+ConvertVTs(const std::vector<MVT::ValueType> &InVTs) {
+ std::vector<unsigned char> Result;
+ for (unsigned i = 0, e = InVTs.size(); i != e; ++i)
+ Result.push_back(InVTs[i]);
+ return Result;
+}
+
+static bool LHSIsSubsetOfRHS(const std::vector<unsigned char> &LHS,
+ const std::vector<unsigned char> &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<unsigned char> 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<unsigned char> 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<MVT::ValueType> 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<unsigned char> &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<unsigned char> 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<unsigned char> 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<unsigned char> getIntrinsicType(Record *R, bool NotRegisters,
TreePattern &TP) {
+ // Some common return values
+ std::vector<unsigned char> Unknown(1, MVT::isUnknown);
+ std::vector<unsigned char> 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<unsigned char>
+ 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<IntInit*>(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 5b3aa6313f..9bf7c205bb 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<unsigned char> Types;
/// Operator - The Record for the operator if this is an interior node (not
/// a leaf).
@@ -151,26 +151,32 @@ namespace llvm {
std::vector<TreePatternNode*> Children;
public:
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &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<unsigned char> &getExtTypes() const { return Types; }
+ void setTypes(const std::vector<unsigned char> &T) { Types = T; }
+ void removeTypes() { Types = std::vector<unsigned char>(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<unsigned char> &ExtVTs,
+ TreePattern &TP);
+ bool UpdateNodeType(unsigned char ExtVT, TreePattern &TP) {
+ std::vector<unsigned char> ExtVTs(1, ExtVT);
+ return UpdateNodeType(ExtVTs, TP);
+ }
/// ContainsUnresolvedType - Return true if this tree contains any
/// unresolved types.