Fairly serious rework of the typing code to add new int/fp lattice values.

Overall, no functionality change yet though.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23729 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2005-10-14 06:12:03 +00:00
parent e0583b1b92
commit 3c7e18d690
2 changed files with 109 additions and 60 deletions

View File

@ -19,6 +19,35 @@
#include <set>
using namespace llvm;
//===----------------------------------------------------------------------===//
// Helpers for working with extended types.
/// FilterVTs - Filter a list of VT's according to a predicate.
///
template<typename T>
static std::vector<MVT::ValueType>
FilterVTs(const std::vector<MVT::ValueType> &InVTs, T Filter) {
std::vector<MVT::ValueType> Result;
for (unsigned i = 0, e = InVTs.size(); i != e; ++i)
if (Filter(InVTs[i]))
Result.push_back(InVTs[i]);
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));
}
/// 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));
}
//===----------------------------------------------------------------------===//
// SDTypeConstraint implementation
//
@ -63,16 +92,6 @@ TreePatternNode *SDTypeConstraint::getOperandNum(unsigned OpNo,
return N->getChild(OpNo-NumResults);
}
template<typename T>
static std::vector<MVT::ValueType>
FilterVTs(const std::vector<MVT::ValueType> &InVTs, T Filter) {
std::vector<MVT::ValueType> Result;
for (unsigned i = 0, e = InVTs.size(); i != e; ++i)
if (Filter(InVTs[i]))
Result.push_back(InVTs[i]);
return Result;
}
/// ApplyTypeConstraint - Given a node in a pattern, apply this type
/// constraint to the nodes operands. This returns true if it makes a
/// change, false otherwise. If a type contradiction is found, throw an
@ -100,9 +119,6 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
// Operand must be a particular type.
return NodeToApply->UpdateNodeType(x.SDTCisVT_Info.VT, TP);
case SDTCisInt: {
if (NodeToApply->hasTypeSet() && !MVT::isInteger(NodeToApply->getType()))
NodeToApply->UpdateNodeType(MVT::i1, TP); // throw an error.
// If there is only one integer type supported, this must be it.
std::vector<MVT::ValueType> IntVTs =
FilterVTs(CGT.getLegalValueTypes(), MVT::isInteger);
@ -110,13 +126,9 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
// If we found exactly one supported integer type, apply it.
if (IntVTs.size() == 1)
return NodeToApply->UpdateNodeType(IntVTs[0], TP);
return false;
return NodeToApply->UpdateNodeType(MVT::isInt, TP);
}
case SDTCisFP: {
if (NodeToApply->hasTypeSet() &&
!MVT::isFloatingPoint(NodeToApply->getType()))
NodeToApply->UpdateNodeType(MVT::f32, TP); // throw an error.
// If there is only one FP type supported, this must be it.
std::vector<MVT::ValueType> FPVTs =
FilterVTs(CGT.getLegalValueTypes(), MVT::isFloatingPoint);
@ -124,13 +136,13 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
// If we found exactly one supported FP type, apply it.
if (FPVTs.size() == 1)
return NodeToApply->UpdateNodeType(FPVTs[0], TP);
return false;
return NodeToApply->UpdateNodeType(MVT::isFP, TP);
}
case SDTCisSameAs: {
TreePatternNode *OtherNode =
getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults);
return NodeToApply->UpdateNodeType(OtherNode->getType(), TP) |
OtherNode->UpdateNodeType(NodeToApply->getType(), TP);
return NodeToApply->UpdateNodeType(OtherNode->getExtType(), TP) |
OtherNode->UpdateNodeType(NodeToApply->getExtType(), TP);
}
case SDTCisVTSmallerThanOp: {
// The NodeToApply must be a leaf node that is a VT. OtherOperandNum must
@ -147,9 +159,12 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
TreePatternNode *OtherNode =
getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N,NumResults);
if (OtherNode->hasTypeSet() &&
(!MVT::isInteger(OtherNode->getType()) ||
OtherNode->getType() <= VT))
// It must be integer.
bool MadeChange = false;
MadeChange |= OtherNode->UpdateNodeType(MVT::isInt, TP);
if (OtherNode->hasTypeSet() && OtherNode->getType() <= VT)
OtherNode->UpdateNodeType(MVT::Other, TP); // Throw an error.
return false;
}
@ -216,13 +231,27 @@ 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(MVT::ValueType VT, TreePattern &TP) {
if (VT == MVT::LAST_VALUETYPE || getType() == VT) return false;
if (getType() == MVT::LAST_VALUETYPE) {
bool TreePatternNode::UpdateNodeType(unsigned char VT, TreePattern &TP) {
if (VT == MVT::isUnknown || getExtType() == VT) return false;
if (getExtType() == MVT::isUnknown) {
setType(VT);
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 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);
return true;
}
TP.error("Type inference contradiction found in node " +
getOperator()->getName() + "!");
return true; // unreachable
@ -236,12 +265,13 @@ void TreePatternNode::print(std::ostream &OS) const {
OS << "(" << getOperator()->getName();
}
if (getType() == MVT::Other)
OS << ":Other";
else if (getType() == MVT::LAST_VALUETYPE)
;//OS << ":?";
else
OS << ":" << getType();
switch (getExtType()) {
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;
}
if (!isLeaf()) {
if (getNumChildren() != 0) {
@ -273,7 +303,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() || getType() != N->getType() ||
if (N->isLeaf() != isLeaf() || getExtType() != N->getExtType() ||
getPredicateFn() != N->getPredicateFn() ||
getTransformFn() != N->getTransformFn())
return false;
@ -307,7 +337,7 @@ TreePatternNode *TreePatternNode::clone() const {
New = new TreePatternNode(getOperator(), CChildren);
}
New->setName(getName());
New->setType(getType());
New->setType(getExtType());
New->setPredicateFn(getPredicateFn());
New->setTransformFn(getTransformFn());
return New;
@ -383,23 +413,24 @@ 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 MVT::ValueType getIntrinsicType(Record *R, bool NotRegisters, TreePattern &TP) {
static unsigned char getIntrinsicType(Record *R, bool NotRegisters,
TreePattern &TP) {
// Check to see if this is a register or a register class...
if (R->isSubClassOf("RegisterClass")) {
if (NotRegisters) return MVT::LAST_VALUETYPE;
if (NotRegisters) return MVT::isUnknown;
return getValueType(R->getValueAsDef("RegType"));
} else if (R->isSubClassOf("PatFrag")) {
// Pattern fragment types will be resolved when they are inlined.
return MVT::LAST_VALUETYPE;
return MVT::isUnknown;
} else if (R->isSubClassOf("Register")) {
assert(0 && "Explicit registers not handled here yet!\n");
return MVT::LAST_VALUETYPE;
return MVT::isUnknown;
} else if (R->isSubClassOf("ValueType")) {
// Using a VTSDNode.
return MVT::Other;
} else if (R->getName() == "node") {
// Placeholder.
return MVT::LAST_VALUETYPE;
return MVT::isUnknown;
}
TP.error("Unknown node flavor used in pattern: " + R->getName());
@ -426,8 +457,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)->getType(), TP);
MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getType(), TP);
MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getExtType(), TP);
MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getExtType(), TP);
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
return MadeChange;
} else if (getOperator()->isSubClassOf("SDNode")) {
@ -462,8 +493,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)->getType(), TP);
MadeChange |= getChild(0)->UpdateNodeType(getType(), TP);
bool MadeChange = UpdateNodeType(getChild(0)->getExtType(), TP);
MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP);
return MadeChange;
}
}
@ -825,7 +856,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->getType() != Pat->getType())
if (Slot->getExtType() != Pat->getExtType())
I->error("All $" + Pat->getName() + " inputs must agree with each other");
}
return true;
@ -847,7 +878,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)->getType() == MVT::isVoid)
if (Pat->getChild(i)->getExtType() == MVT::isVoid)
I->error("Cannot have void nodes inside of patterns!");
FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults);
}
@ -933,7 +964,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->getType() != MVT::isVoid) {
if (Pat->getExtType() != MVT::isVoid) {
I->dump();
I->error("Top-level forms in instruction pattern should have"
" void types");
@ -993,7 +1024,7 @@ void DAGISelEmitter::ParseInstructions() {
" does not appear in the instruction pattern");
TreePatternNode *InVal = InstInputsCheck[OpName];
InstInputsCheck.erase(OpName); // It occurred, remove from map.
if (CGI.OperandList[i].Ty != InVal->getType())
if (CGI.OperandList[i].Ty != InVal->getExtType())
I->error("Operand $" + OpName +
"'s type disagrees between the operand and pattern");
OperandTypes.push_back(InVal->getType());
@ -1133,7 +1164,7 @@ static void CombineChildVariants(TreePatternNode *Orig,
R->setName(Orig->getName());
R->setPredicateFn(Orig->getPredicateFn());
R->setTransformFn(Orig->getTransformFn());
R->setType(Orig->getType());
R->setType(Orig->getExtType());
// If this pattern cannot every match, do not include it as a variant.
std::string ErrString;
@ -1357,14 +1388,15 @@ void DAGISelEmitter::GenerateVariants() {
/// patterns before small ones. This is used to determine the size of a
/// pattern.
static unsigned getPatternSize(TreePatternNode *P) {
assert(MVT::isInteger(P->getType()) || MVT::isFloatingPoint(P->getType()) &&
assert(isExtIntegerVT(P->getExtType()) ||
isExtFloatingPointVT(P->getExtType()) &&
"Not a valid pattern node to size!");
unsigned Size = 1; // The node itself.
// 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->getType() != MVT::Other)
if (!Child->isLeaf() && Child->getExtType() != MVT::Other)
Size += getPatternSize(Child);
}
@ -1557,7 +1589,7 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
/// RemoveAllTypes - A quick recursive walk over a pattern which removes all
/// type information from it.
static void RemoveAllTypes(TreePatternNode *N) {
N->setType(MVT::LAST_VALUETYPE);
N->setType(MVT::isUnknown);
if (!N->isLeaf())
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
RemoveAllTypes(N->getChild(i));

View File

@ -27,6 +27,16 @@ namespace llvm {
class TreePatternNode;
class DAGISelEmitter;
/// MVT::DAGISelGenValueType - These are some extended forms of MVT::ValueType
/// that we use as lattice values during type inferrence.
namespace MVT {
enum DAGISelGenValueType {
isFP = MVT::LAST_VALUETYPE,
isInt,
isUnknown
};
}
/// SDTypeConstraint - This is a discriminated union of constraints,
/// corresponding to the SDTypeConstraint tablegen class in Target.td.
struct SDTypeConstraint {
@ -115,8 +125,8 @@ namespace llvm {
class TreePatternNode {
/// The inferred type for this node, or MVT::LAST_VALUETYPE if it hasn't
/// been determined yet.
MVT::ValueType Ty;
unsigned char Ty;
/// Operator - The Record for the operator if this is an interior node (not
/// a leaf).
Record *Operator;
@ -140,19 +150,26 @@ namespace llvm {
std::vector<TreePatternNode*> Children;
public:
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch)
: Ty(MVT::LAST_VALUETYPE), Operator(Op), Val(0), TransformFn(0),
: Ty(MVT::isUnknown), Operator(Op), Val(0), TransformFn(0),
Children(Ch) {}
TreePatternNode(Init *val) // leaf ctor
: Ty(MVT::LAST_VALUETYPE), Operator(0), Val(val), TransformFn(0) {}
: Ty(MVT::isUnknown), Operator(0), Val(val), TransformFn(0) {}
~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; }
MVT::ValueType getType() const { return Ty; }
void setType(MVT::ValueType VT) { Ty = VT; }
bool hasTypeSet() const { return Ty < MVT::LAST_VALUETYPE; }
bool isTypeCompletelyUnknown() const {
return Ty == MVT::isUnknown;
}
MVT::ValueType getType() const {
assert(hasTypeSet() && "Doesn't have a type yet!");
return (MVT::ValueType)Ty;
}
unsigned char getExtType() const { return Ty; }
void setType(unsigned char VT) { Ty = VT; }
Init *getLeafValue() const { assert(isLeaf()); return Val; }
Record *getOperator() const { assert(!isLeaf()); return Operator; }
@ -204,7 +221,7 @@ namespace llvm {
/// information. If N already contains a conflicting type, then throw an
/// exception. This returns true if any information was updated.
///
bool UpdateNodeType(MVT::ValueType VT, TreePattern &TP);
bool UpdateNodeType(unsigned char EVT, TreePattern &TP);
/// ContainsUnresolvedType - Return true if this tree contains any
/// unresolved types.