Add support for generating v4i32 altivec code

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25046 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2005-12-30 00:12:56 +00:00
parent 1166bf3f4c
commit b73628b5ab
4 changed files with 190 additions and 99 deletions

View File

@ -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 :)

View File

@ -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 {

View File

@ -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;
}
/// 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 @@ 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;
}

View File

@ -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.