mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-13 17:38:39 +00:00
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:
parent
1166bf3f4c
commit
b73628b5ab
@ -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),
|
def LVX : XForm_1<31, 103, (ops VRRC:$vD, memrr:$src),
|
||||||
"lvx $vD, $src", LdStGeneral,
|
"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),
|
def LVSL : XForm_1<31, 6, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
|
||||||
"lvsl $vD, $base, $rA", LdStGeneral,
|
"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),
|
def STVX : XForm_8<31, 231, (ops VRRC:$rS, memrr:$dst),
|
||||||
"stvx $rS, $dst", LdStGeneral,
|
"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),
|
def SRAWI : XForm_10<31, 824, (ops GPRC:$rA, GPRC:$rS, u5imm:$SH),
|
||||||
"srawi $rA, $rS, $SH", IntShift,
|
"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),
|
def VADDFP : VXForm_1<10, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||||
"vaddfp $vD, $vA, $vB", VecFP,
|
"vaddfp $vD, $vA, $vB", VecFP,
|
||||||
[(set VRRC:$vD, (fadd VRRC:$vA, VRRC:$vB))]>;
|
[(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),
|
def VCFSX : VXForm_1<842, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
||||||
"vcfsx $vD, $vB, $UIMM", VecFP,
|
"vcfsx $vD, $vB, $UIMM", VecFP,
|
||||||
[]>;
|
[]>;
|
||||||
@ -1060,6 +1063,11 @@ def : Pat<(f64 (extload iaddr:$src, f32)),
|
|||||||
def : Pat<(f64 (extload xaddr:$src, f32)),
|
def : Pat<(f64 (extload xaddr:$src, f32)),
|
||||||
(FMRSD (LFSX xaddr:$src))>;
|
(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)>;
|
def : Pat<(retflag), (BLR)>;
|
||||||
|
|
||||||
// Same as above, but using a temporary. FIXME: implement temporaries :)
|
// Same as above, but using a temporary. FIXME: implement temporaries :)
|
||||||
|
@ -41,7 +41,7 @@ namespace llvm {
|
|||||||
std::string MethodProtos, MethodBodies;
|
std::string MethodProtos, MethodBodies;
|
||||||
|
|
||||||
const std::string &getName() const;
|
const std::string &getName() const;
|
||||||
|
const std::vector<MVT::ValueType> &getValueTypes() const { return VTs; }
|
||||||
unsigned getNumValueTypes() const { return VTs.size(); }
|
unsigned getNumValueTypes() const { return VTs.size(); }
|
||||||
|
|
||||||
const MVT::ValueType getValueTypeNum(unsigned VTNum) const {
|
const MVT::ValueType getValueTypeNum(unsigned VTNum) const {
|
||||||
|
@ -34,18 +34,45 @@ FilterVTs(const std::vector<MVT::ValueType> &InVTs, T Filter) {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isExtIntegerVT - Return true if the specified extended value type is
|
template<typename T>
|
||||||
/// integer, or isInt.
|
static std::vector<unsigned char>
|
||||||
static bool isExtIntegerVT(unsigned char VT) {
|
FilterEVTs(const std::vector<unsigned char> &InVTs, T Filter) {
|
||||||
return VT == MVT::isInt ||
|
std::vector<unsigned char> Result;
|
||||||
(VT < MVT::LAST_VALUETYPE && MVT::isInteger((MVT::ValueType)VT));
|
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
|
static std::vector<unsigned char>
|
||||||
/// floating point, or isFP.
|
ConvertVTs(const std::vector<MVT::ValueType> &InVTs) {
|
||||||
static bool isExtFloatingPointVT(unsigned char VT) {
|
std::vector<unsigned char> Result;
|
||||||
return VT == MVT::isFP ||
|
for (unsigned i = 0, e = InVTs.size(); i != e; ++i)
|
||||||
(VT < MVT::LAST_VALUETYPE && MVT::isFloatingPoint((MVT::ValueType)VT));
|
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: {
|
case SDTCisSameAs: {
|
||||||
TreePatternNode *OtherNode =
|
TreePatternNode *OtherNode =
|
||||||
getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults);
|
getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults);
|
||||||
return NodeToApply->UpdateNodeType(OtherNode->getExtType(), TP) |
|
return NodeToApply->UpdateNodeType(OtherNode->getExtTypes(), TP) |
|
||||||
OtherNode->UpdateNodeType(NodeToApply->getExtType(), TP);
|
OtherNode->UpdateNodeType(NodeToApply->getExtTypes(), TP);
|
||||||
}
|
}
|
||||||
case SDTCisVTSmallerThanOp: {
|
case SDTCisVTSmallerThanOp: {
|
||||||
// The NodeToApply must be a leaf node that is a VT. OtherOperandNum must
|
// 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;
|
bool MadeChange = false;
|
||||||
MadeChange |= OtherNode->UpdateNodeType(MVT::isInt, TP);
|
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.
|
OtherNode->UpdateNodeType(MVT::Other, TP); // Throw an error.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -183,20 +214,28 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
|
|||||||
// Both operands must be integer or FP, but we don't care which.
|
// Both operands must be integer or FP, but we don't care which.
|
||||||
bool MadeChange = false;
|
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);
|
MadeChange |= BigOperand->UpdateNodeType(MVT::isInt, TP);
|
||||||
else if (isExtFloatingPointVT(NodeToApply->getExtType()))
|
else if (isExtFloatingPointInVTs(NodeToApply->getExtTypes()))
|
||||||
MadeChange |= BigOperand->UpdateNodeType(MVT::isFP, TP);
|
MadeChange |= BigOperand->UpdateNodeType(MVT::isFP, TP);
|
||||||
if (isExtIntegerVT(BigOperand->getExtType()))
|
if (isExtIntegerInVTs(BigOperand->getExtTypes()))
|
||||||
MadeChange |= NodeToApply->UpdateNodeType(MVT::isInt, TP);
|
MadeChange |= NodeToApply->UpdateNodeType(MVT::isInt, TP);
|
||||||
else if (isExtFloatingPointVT(BigOperand->getExtType()))
|
else if (isExtFloatingPointInVTs(BigOperand->getExtTypes()))
|
||||||
MadeChange |= NodeToApply->UpdateNodeType(MVT::isFP, TP);
|
MadeChange |= NodeToApply->UpdateNodeType(MVT::isFP, TP);
|
||||||
|
|
||||||
std::vector<MVT::ValueType> VTs = CGT.getLegalValueTypes();
|
std::vector<MVT::ValueType> VTs = CGT.getLegalValueTypes();
|
||||||
|
|
||||||
if (isExtIntegerVT(NodeToApply->getExtType())) {
|
if (isExtIntegerInVTs(NodeToApply->getExtTypes())) {
|
||||||
VTs = FilterVTs(VTs, MVT::isInteger);
|
VTs = FilterVTs(VTs, MVT::isInteger);
|
||||||
} else if (isExtFloatingPointVT(NodeToApply->getExtType())) {
|
} else if (isExtFloatingPointInVTs(NodeToApply->getExtTypes())) {
|
||||||
VTs = FilterVTs(VTs, MVT::isFloatingPoint);
|
VTs = FilterVTs(VTs, MVT::isFloatingPoint);
|
||||||
} else {
|
} else {
|
||||||
VTs.clear();
|
VTs.clear();
|
||||||
@ -273,24 +312,42 @@ TreePatternNode::~TreePatternNode() {
|
|||||||
/// information. If N already contains a conflicting type, then throw an
|
/// information. If N already contains a conflicting type, then throw an
|
||||||
/// exception. This returns true if any information was updated.
|
/// exception. This returns true if any information was updated.
|
||||||
///
|
///
|
||||||
bool TreePatternNode::UpdateNodeType(unsigned char VT, TreePattern &TP) {
|
bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
|
||||||
if (VT == MVT::isUnknown || getExtType() == VT) return false;
|
TreePattern &TP) {
|
||||||
if (getExtType() == MVT::isUnknown) {
|
assert(!ExtVTs.empty() && "Cannot update node type with empty type vector!");
|
||||||
setType(VT);
|
|
||||||
|
if (ExtVTs[0] == MVT::isUnknown || LHSIsSubsetOfRHS(getExtTypes(), ExtVTs))
|
||||||
|
return false;
|
||||||
|
if (isTypeCompletelyUnknown() || LHSIsSubsetOfRHS(ExtVTs, getExtTypes())) {
|
||||||
|
setTypes(ExtVTs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are told this is to be an int or FP type, and it already is, ignore
|
if (ExtVTs[0] == MVT::isInt && isExtIntegerInVTs(getExtTypes())) {
|
||||||
// the advice.
|
assert(hasTypeSet() && "should be handled above!");
|
||||||
if ((VT == MVT::isInt && isExtIntegerVT(getExtType())) ||
|
std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), MVT::isInteger);
|
||||||
(VT == MVT::isFP && isExtFloatingPointVT(getExtType())))
|
if (getExtTypes() == FVTs)
|
||||||
return false;
|
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,
|
// If we know this is an int or fp type, and we are told it is a specific one,
|
||||||
// take the advice.
|
// take the advice.
|
||||||
if ((getExtType() == MVT::isInt && isExtIntegerVT(VT)) ||
|
//
|
||||||
(getExtType() == MVT::isFP && isExtFloatingPointVT(VT))) {
|
// Similarly, we should probably set the type here to the intersection of
|
||||||
setType(VT);
|
// {isInt|isFP} and ExtVTs
|
||||||
|
if ((getExtTypeNum(0) == MVT::isInt && isExtIntegerInVTs(ExtVTs)) ||
|
||||||
|
(getExtTypeNum(0) == MVT::isFP && isExtFloatingPointInVTs(ExtVTs))) {
|
||||||
|
setTypes(ExtVTs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,12 +370,14 @@ void TreePatternNode::print(std::ostream &OS) const {
|
|||||||
OS << "(" << getOperator()->getName();
|
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::Other: OS << ":Other"; break;
|
||||||
case MVT::isInt: OS << ":isInt"; break;
|
case MVT::isInt: OS << ":isInt"; break;
|
||||||
case MVT::isFP : OS << ":isFP"; break;
|
case MVT::isFP : OS << ":isFP"; break;
|
||||||
case MVT::isUnknown: ; /*OS << ":?";*/ break;
|
case MVT::isUnknown: ; /*OS << ":?";*/ break;
|
||||||
default: OS << ":" << getType(); break;
|
default: OS << ":" << getTypeNum(0); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isLeaf()) {
|
if (!isLeaf()) {
|
||||||
@ -351,7 +410,7 @@ void TreePatternNode::dump() const {
|
|||||||
/// that are otherwise identical are considered isomorphic.
|
/// that are otherwise identical are considered isomorphic.
|
||||||
bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N) const {
|
bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N) const {
|
||||||
if (N == this) return true;
|
if (N == this) return true;
|
||||||
if (N->isLeaf() != isLeaf() || getExtType() != N->getExtType() ||
|
if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
|
||||||
getPredicateFn() != N->getPredicateFn() ||
|
getPredicateFn() != N->getPredicateFn() ||
|
||||||
getTransformFn() != N->getTransformFn())
|
getTransformFn() != N->getTransformFn())
|
||||||
return false;
|
return false;
|
||||||
@ -385,7 +444,7 @@ TreePatternNode *TreePatternNode::clone() const {
|
|||||||
New = new TreePatternNode(getOperator(), CChildren);
|
New = new TreePatternNode(getOperator(), CChildren);
|
||||||
}
|
}
|
||||||
New->setName(getName());
|
New->setName(getName());
|
||||||
New->setType(getExtType());
|
New->setTypes(getExtTypes());
|
||||||
New->setPredicateFn(getPredicateFn());
|
New->setPredicateFn(getPredicateFn());
|
||||||
New->setTransformFn(getTransformFn());
|
New->setTransformFn(getTransformFn());
|
||||||
return New;
|
return New;
|
||||||
@ -451,7 +510,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FragTree->setName(getName());
|
FragTree->setName(getName());
|
||||||
FragTree->UpdateNodeType(getExtType(), TP);
|
FragTree->UpdateNodeType(getExtTypes(), TP);
|
||||||
|
|
||||||
// Get a new copy of this fragment to stitch into here.
|
// Get a new copy of this fragment to stitch into here.
|
||||||
//delete this; // FIXME: implement refcounting!
|
//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
|
/// type which should be applied to it. This infer the type of register
|
||||||
/// references from the register file information, for example.
|
/// 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) {
|
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...
|
// Check to see if this is a register or a register class...
|
||||||
if (R->isSubClassOf("RegisterClass")) {
|
if (R->isSubClassOf("RegisterClass")) {
|
||||||
if (NotRegisters) return MVT::isUnknown;
|
if (NotRegisters)
|
||||||
|
return Unknown;
|
||||||
const CodeGenRegisterClass &RC =
|
const CodeGenRegisterClass &RC =
|
||||||
TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(R);
|
TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(R);
|
||||||
return RC.getValueTypeNum(0);
|
return ConvertVTs(RC.getValueTypes());
|
||||||
} else if (R->isSubClassOf("PatFrag")) {
|
} else if (R->isSubClassOf("PatFrag")) {
|
||||||
// Pattern fragment types will be resolved when they are inlined.
|
// Pattern fragment types will be resolved when they are inlined.
|
||||||
return MVT::isUnknown;
|
return Unknown;
|
||||||
} else if (R->isSubClassOf("Register")) {
|
} else if (R->isSubClassOf("Register")) {
|
||||||
// If the register appears in exactly one regclass, and the regclass has one
|
// If the register appears in exactly one regclass, and the regclass has one
|
||||||
// value type, use it as the known type.
|
// value type, use it as the known type.
|
||||||
const CodeGenTarget &T = TP.getDAGISelEmitter().getTargetInfo();
|
const CodeGenTarget &T = TP.getDAGISelEmitter().getTargetInfo();
|
||||||
if (const CodeGenRegisterClass *RC = T.getRegisterClassForRegister(R))
|
if (const CodeGenRegisterClass *RC = T.getRegisterClassForRegister(R))
|
||||||
if (RC->getNumValueTypes() == 1)
|
return ConvertVTs(RC->getValueTypes());
|
||||||
return RC->getValueTypeNum(0);
|
return Unknown;
|
||||||
return MVT::isUnknown;
|
|
||||||
} else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
|
} else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
|
||||||
// Using a VTSDNode or CondCodeSDNode.
|
// Using a VTSDNode or CondCodeSDNode.
|
||||||
return MVT::Other;
|
return Other;
|
||||||
} else if (R->isSubClassOf("ComplexPattern")) {
|
} 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") {
|
} else if (R->getName() == "node" || R->getName() == "srcvalue") {
|
||||||
// Placeholder.
|
// Placeholder.
|
||||||
return MVT::isUnknown;
|
return Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
TP.error("Unknown node flavor used in pattern: " + R->getName());
|
TP.error("Unknown node flavor used in pattern: " + R->getName());
|
||||||
return MVT::Other;
|
return Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ApplyTypeConstraints - Apply all of the type constraints relevent to
|
/// 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);
|
bool MadeChange = UpdateNodeType(MVT::isInt, TP);
|
||||||
|
|
||||||
if (hasTypeSet()) {
|
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.
|
// Make sure that the value is representable for this type.
|
||||||
if (Size < 32) {
|
if (Size < 32) {
|
||||||
int Val = (II->getValue() << (32-Size)) >> (32-Size);
|
int Val = (II->getValue() << (32-Size)) >> (32-Size);
|
||||||
if (Val != II->getValue())
|
if (Val != II->getValue())
|
||||||
TP.error("Sign-extended integer value '" + itostr(II->getValue()) +
|
TP.error("Sign-extended integer value '" + itostr(II->getValue()) +
|
||||||
"' is out of range for type 'MVT::" +
|
"' 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);
|
MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
|
||||||
|
|
||||||
// Types of operands must match.
|
// Types of operands must match.
|
||||||
MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getExtType(), TP);
|
MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getExtTypes(), TP);
|
||||||
MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getExtType(), TP);
|
MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getExtTypes(), TP);
|
||||||
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
|
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
|
||||||
return MadeChange;
|
return MadeChange;
|
||||||
} else if (getOperator()->isSubClassOf("SDNode")) {
|
} else if (getOperator()->isSubClassOf("SDNode")) {
|
||||||
@ -566,9 +636,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||||||
|
|
||||||
const CodeGenRegisterClass &RC =
|
const CodeGenRegisterClass &RC =
|
||||||
TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(ResultNode);
|
TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(ResultNode);
|
||||||
|
MadeChange = UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
|
||||||
// Get the first ValueType in the RegClass, it's as good as any.
|
|
||||||
MadeChange = UpdateNodeType(RC.getValueTypeNum(0), TP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getNumChildren() != Inst.getNumOperands())
|
if (getNumChildren() != Inst.getNumOperands())
|
||||||
@ -581,15 +649,16 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||||||
if (OperandNode->isSubClassOf("RegisterClass")) {
|
if (OperandNode->isSubClassOf("RegisterClass")) {
|
||||||
const CodeGenRegisterClass &RC =
|
const CodeGenRegisterClass &RC =
|
||||||
TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(OperandNode);
|
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")) {
|
} else if (OperandNode->isSubClassOf("Operand")) {
|
||||||
VT = getValueType(OperandNode->getValueAsDef("Type"));
|
VT = getValueType(OperandNode->getValueAsDef("Type"));
|
||||||
|
MadeChange |= getChild(i)->UpdateNodeType(VT, TP);
|
||||||
} else {
|
} else {
|
||||||
assert(0 && "Unknown operand type!");
|
assert(0 && "Unknown operand type!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
MadeChange |= getChild(i)->UpdateNodeType(VT, TP);
|
|
||||||
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
|
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
|
||||||
}
|
}
|
||||||
return MadeChange;
|
return MadeChange;
|
||||||
@ -601,8 +670,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||||||
if (getNumChildren() != 1)
|
if (getNumChildren() != 1)
|
||||||
TP.error("Node transform '" + getOperator()->getName() +
|
TP.error("Node transform '" + getOperator()->getName() +
|
||||||
"' requires one operand!");
|
"' requires one operand!");
|
||||||
bool MadeChange = UpdateNodeType(getChild(0)->getExtType(), TP);
|
bool MadeChange = UpdateNodeType(getChild(0)->getExtTypes(), TP);
|
||||||
MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP);
|
MadeChange |= getChild(0)->UpdateNodeType(getExtTypes(), TP);
|
||||||
return MadeChange;
|
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.
|
// Ensure that the inputs agree if we've already seen this input.
|
||||||
if (Rec != SlotRec)
|
if (Rec != SlotRec)
|
||||||
I->error("All $" + Pat->getName() + " inputs must agree with each other");
|
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");
|
I->error("All $" + Pat->getName() + " inputs must agree with each other");
|
||||||
}
|
}
|
||||||
return true;
|
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,
|
// If this is not a set, verify that the children nodes are not void typed,
|
||||||
// and recurse.
|
// and recurse.
|
||||||
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
|
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!");
|
I->error("Cannot have void nodes inside of patterns!");
|
||||||
FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,
|
FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,
|
||||||
InstImpInputs, InstImpResults);
|
InstImpInputs, InstImpResults);
|
||||||
@ -1146,7 +1215,7 @@ void DAGISelEmitter::ParseInstructions() {
|
|||||||
// fill in the InstResults map.
|
// fill in the InstResults map.
|
||||||
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
|
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
|
||||||
TreePatternNode *Pat = I->getTree(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"
|
I->error("Top-level forms in instruction pattern should have"
|
||||||
" void types");
|
" void types");
|
||||||
|
|
||||||
@ -1372,7 +1441,7 @@ static void CombineChildVariants(TreePatternNode *Orig,
|
|||||||
R->setName(Orig->getName());
|
R->setName(Orig->getName());
|
||||||
R->setPredicateFn(Orig->getPredicateFn());
|
R->setPredicateFn(Orig->getPredicateFn());
|
||||||
R->setTransformFn(Orig->getTransformFn());
|
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.
|
// If this pattern cannot every match, do not include it as a variant.
|
||||||
std::string ErrString;
|
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
|
/// patterns before small ones. This is used to determine the size of a
|
||||||
/// pattern.
|
/// pattern.
|
||||||
static unsigned getPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) {
|
static unsigned getPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) {
|
||||||
assert(isExtIntegerVT(P->getExtType()) ||
|
assert(isExtIntegerInVTs(P->getExtTypes()) ||
|
||||||
isExtFloatingPointVT(P->getExtType()) ||
|
isExtFloatingPointInVTs(P->getExtTypes()) ||
|
||||||
P->getExtType() == MVT::isVoid ||
|
P->getExtTypeNum(0) == MVT::isVoid ||
|
||||||
P->getExtType() == MVT::Flag && "Not a valid pattern node to size!");
|
P->getExtTypeNum(0) == MVT::Flag &&
|
||||||
|
"Not a valid pattern node to size!");
|
||||||
unsigned Size = 1; // The node itself.
|
unsigned Size = 1; // The node itself.
|
||||||
|
|
||||||
// FIXME: This is a hack to statically increase the priority of patterns
|
// 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.
|
// Count children in the count if they are also nodes.
|
||||||
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
|
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
|
||||||
TreePatternNode *Child = P->getChild(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);
|
Size += getPatternSize(Child, ISE);
|
||||||
else if (Child->isLeaf()) {
|
else if (Child->isLeaf()) {
|
||||||
if (dynamic_cast<IntInit*>(Child->getLeafValue()))
|
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
|
/// RemoveAllTypes - A quick recursive walk over a pattern which removes all
|
||||||
/// type information from it.
|
/// type information from it.
|
||||||
static void RemoveAllTypes(TreePatternNode *N) {
|
static void RemoveAllTypes(TreePatternNode *N) {
|
||||||
N->setType(MVT::isUnknown);
|
N->removeTypes();
|
||||||
if (!N->isLeaf())
|
if (!N->isLeaf())
|
||||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
||||||
RemoveAllTypes(N->getChild(i));
|
RemoveAllTypes(N->getChild(i));
|
||||||
@ -1959,7 +2029,8 @@ public:
|
|||||||
unsigned ResNo = TmpNo++;
|
unsigned ResNo = TmpNo++;
|
||||||
unsigned NumRes = 1;
|
unsigned NumRes = 1;
|
||||||
if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
|
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!");
|
default: assert(0 && "Unknown type for constant node!");
|
||||||
case MVT::i1: OS << " bool Tmp"; break;
|
case MVT::i1: OS << " bool Tmp"; break;
|
||||||
case MVT::i8: OS << " unsigned char Tmp"; break;
|
case MVT::i8: OS << " unsigned char Tmp"; break;
|
||||||
@ -1971,7 +2042,7 @@ public:
|
|||||||
OS << " ";
|
OS << " ";
|
||||||
DeclareSDOperand("Tmp"+utostr(ResNo));
|
DeclareSDOperand("Tmp"+utostr(ResNo));
|
||||||
OS << " = CurDAG->getTargetConstant(Tmp"
|
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") {
|
} else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
|
||||||
OS << " ";
|
OS << " ";
|
||||||
DeclareSDOperand("Tmp"+utostr(ResNo));
|
DeclareSDOperand("Tmp"+utostr(ResNo));
|
||||||
@ -2019,7 +2090,7 @@ public:
|
|||||||
DeclareSDOperand("Tmp"+utostr(ResNo));
|
DeclareSDOperand("Tmp"+utostr(ResNo));
|
||||||
OS << " = CurDAG->getRegister("
|
OS << " = CurDAG->getRegister("
|
||||||
<< ISE.getQualifiedName(DI->getDef()) << ", MVT::"
|
<< ISE.getQualifiedName(DI->getDef()) << ", MVT::"
|
||||||
<< getEnumName(N->getType())
|
<< getEnumName(N->getTypeNum(0))
|
||||||
<< ");\n";
|
<< ");\n";
|
||||||
return std::make_pair(1, ResNo);
|
return std::make_pair(1, ResNo);
|
||||||
}
|
}
|
||||||
@ -2027,9 +2098,10 @@ public:
|
|||||||
unsigned ResNo = TmpNo++;
|
unsigned ResNo = TmpNo++;
|
||||||
OS << " ";
|
OS << " ";
|
||||||
DeclareSDOperand("Tmp"+utostr(ResNo));
|
DeclareSDOperand("Tmp"+utostr(ResNo));
|
||||||
|
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
|
||||||
OS << " = CurDAG->getTargetConstant("
|
OS << " = CurDAG->getTargetConstant("
|
||||||
<< II->getValue() << ", MVT::"
|
<< II->getValue() << ", MVT::"
|
||||||
<< getEnumName(N->getType())
|
<< getEnumName(N->getTypeNum(0))
|
||||||
<< ");\n";
|
<< ");\n";
|
||||||
return std::make_pair(1, ResNo);
|
return std::make_pair(1, ResNo);
|
||||||
}
|
}
|
||||||
@ -2099,8 +2171,8 @@ public:
|
|||||||
DeclareSDOperand("Tmp"+utostr(ResNo));
|
DeclareSDOperand("Tmp"+utostr(ResNo));
|
||||||
OS << " = CurDAG->getTargetNode("
|
OS << " = CurDAG->getTargetNode("
|
||||||
<< II.Namespace << "::" << II.TheDef->getName();
|
<< II.Namespace << "::" << II.TheDef->getName();
|
||||||
if (N->getType() != MVT::isVoid)
|
if (N->getTypeNum(0) != MVT::isVoid)
|
||||||
OS << ", MVT::" << getEnumName(N->getType());
|
OS << ", MVT::" << getEnumName(N->getTypeNum(0));
|
||||||
if (HasOutFlag)
|
if (HasOutFlag)
|
||||||
OS << ", MVT::Flag";
|
OS << ", MVT::Flag";
|
||||||
|
|
||||||
@ -2122,9 +2194,8 @@ public:
|
|||||||
// Output order: results, chain, flags
|
// Output order: results, chain, flags
|
||||||
// Result types.
|
// Result types.
|
||||||
if (NumResults > 0) {
|
if (NumResults > 0) {
|
||||||
// TODO: multiple results?
|
if (N->getTypeNum(0) != MVT::isVoid)
|
||||||
if (N->getType() != MVT::isVoid)
|
OS << ", MVT::" << getEnumName(N->getTypeNum(0));
|
||||||
OS << ", MVT::" << getEnumName(N->getType());
|
|
||||||
}
|
}
|
||||||
if (HasChain)
|
if (HasChain)
|
||||||
OS << ", MVT::Other";
|
OS << ", MVT::Other";
|
||||||
@ -2195,8 +2266,8 @@ public:
|
|||||||
OS << " if (N.Val->hasOneUse()) {\n";
|
OS << " if (N.Val->hasOneUse()) {\n";
|
||||||
OS << " return CurDAG->SelectNodeTo(N.Val, "
|
OS << " return CurDAG->SelectNodeTo(N.Val, "
|
||||||
<< II.Namespace << "::" << II.TheDef->getName();
|
<< II.Namespace << "::" << II.TheDef->getName();
|
||||||
if (N->getType() != MVT::isVoid)
|
if (N->getTypeNum(0) != MVT::isVoid)
|
||||||
OS << ", MVT::" << getEnumName(N->getType());
|
OS << ", MVT::" << getEnumName(N->getTypeNum(0));
|
||||||
if (HasOutFlag)
|
if (HasOutFlag)
|
||||||
OS << ", MVT::Flag";
|
OS << ", MVT::Flag";
|
||||||
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
||||||
@ -2207,8 +2278,8 @@ public:
|
|||||||
OS << " } else {\n";
|
OS << " } else {\n";
|
||||||
OS << " return CodeGenMap[N] = CurDAG->getTargetNode("
|
OS << " return CodeGenMap[N] = CurDAG->getTargetNode("
|
||||||
<< II.Namespace << "::" << II.TheDef->getName();
|
<< II.Namespace << "::" << II.TheDef->getName();
|
||||||
if (N->getType() != MVT::isVoid)
|
if (N->getTypeNum(0) != MVT::isVoid)
|
||||||
OS << ", MVT::" << getEnumName(N->getType());
|
OS << ", MVT::" << getEnumName(N->getTypeNum(0));
|
||||||
if (HasOutFlag)
|
if (HasOutFlag)
|
||||||
OS << ", MVT::Flag";
|
OS << ", MVT::Flag";
|
||||||
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
||||||
@ -2249,9 +2320,9 @@ public:
|
|||||||
// Did we find one?
|
// Did we find one?
|
||||||
if (!Pat->hasTypeSet()) {
|
if (!Pat->hasTypeSet()) {
|
||||||
// Move a type over from 'other' to 'pat'.
|
// Move a type over from 'other' to 'pat'.
|
||||||
Pat->setType(Other->getType());
|
Pat->setTypes(Other->getExtTypes());
|
||||||
OS << " if (" << Prefix << ".Val->getValueType(0) != MVT::"
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,9 +124,9 @@ namespace llvm {
|
|||||||
/// patterns), and as such should be ref counted. We currently just leak all
|
/// patterns), and as such should be ref counted. We currently just leak all
|
||||||
/// TreePatternNode objects!
|
/// TreePatternNode objects!
|
||||||
class TreePatternNode {
|
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.
|
/// been determined yet.
|
||||||
unsigned char Ty;
|
std::vector<unsigned char> Types;
|
||||||
|
|
||||||
/// Operator - The Record for the operator if this is an interior node (not
|
/// Operator - The Record for the operator if this is an interior node (not
|
||||||
/// a leaf).
|
/// a leaf).
|
||||||
@ -151,26 +151,32 @@ namespace llvm {
|
|||||||
std::vector<TreePatternNode*> Children;
|
std::vector<TreePatternNode*> Children;
|
||||||
public:
|
public:
|
||||||
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch)
|
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch)
|
||||||
: Ty(MVT::isUnknown), Operator(Op), Val(0), TransformFn(0),
|
: Types(), Operator(Op), Val(0), TransformFn(0),
|
||||||
Children(Ch) {}
|
Children(Ch) { Types.push_back(MVT::isUnknown); }
|
||||||
TreePatternNode(Init *val) // leaf ctor
|
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();
|
~TreePatternNode();
|
||||||
|
|
||||||
const std::string &getName() const { return Name; }
|
const std::string &getName() const { return Name; }
|
||||||
void setName(const std::string &N) { Name = N; }
|
void setName(const std::string &N) { Name = N; }
|
||||||
|
|
||||||
bool isLeaf() const { return Val != 0; }
|
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 {
|
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!");
|
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; }
|
unsigned char getExtTypeNum(unsigned Num) const {
|
||||||
void setType(unsigned char VT) { Ty = VT; }
|
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; }
|
Init *getLeafValue() const { assert(isLeaf()); return Val; }
|
||||||
Record *getOperator() const { assert(!isLeaf()); return Operator; }
|
Record *getOperator() const { assert(!isLeaf()); return Operator; }
|
||||||
@ -181,6 +187,7 @@ namespace llvm {
|
|||||||
Children[i] = N;
|
Children[i] = N;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string &getPredicateFn() const { return PredicateFn; }
|
const std::string &getPredicateFn() const { return PredicateFn; }
|
||||||
void setPredicateFn(const std::string &Fn) { PredicateFn = Fn; }
|
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
|
/// information. If N already contains a conflicting type, then throw an
|
||||||
/// exception. This returns true if any information was updated.
|
/// 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
|
/// ContainsUnresolvedType - Return true if this tree contains any
|
||||||
/// unresolved types.
|
/// unresolved types.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user