Add support for generating v4i32 altivec code
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25046 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 85ebfde..fc75cb5 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -34,18 +34,45 @@
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;
}
-/// 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));
+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
+/// 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 @@
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 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 @@
// 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 @@
/// 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 @@
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 @@
/// 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 @@
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 @@
}
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 @@
/// 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 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
/// 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 @@
// 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 @@
/// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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;
}