summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp529
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h15
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp20
-rw-r--r--utils/TableGen/CodeGenInstruction.h7
-rw-r--r--utils/TableGen/CodeGenTarget.cpp25
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp74
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp14
-rw-r--r--utils/TableGen/DAGISelMatcher.h8
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp57
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp97
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp11
-rw-r--r--utils/TableGen/FastISelEmitter.cpp4
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp2
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp13
-rw-r--r--utils/TableGen/Record.cpp30
-rw-r--r--utils/TableGen/Record.h12
-rw-r--r--utils/TableGen/TableGen.cpp1
-rwxr-xr-xutils/buildit/build_llvm2
-rw-r--r--utils/lit/lit/LitTestCase.py30
-rw-r--r--utils/lit/lit/TestFormats.py5
-rw-r--r--utils/lit/lit/TestRunner.py10
-rwxr-xr-xutils/lit/lit/lit.py42
22 files changed, 598 insertions, 410 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 4cc9b79..d2c0195 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -61,9 +61,9 @@ EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) {
assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny &&
VTList[0] != MVT::fAny);
- // Remove duplicates.
+ // Verify no duplicates.
array_pod_sort(TypeVec.begin(), TypeVec.end());
- TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end());
+ assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end());
}
/// FillWithPossibleTypes - Set to all legal types and return true, only valid
@@ -394,24 +394,39 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
}
/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
-/// whose element is VT.
-bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
+/// whose element is specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
TreePattern &TP) {
- TypeSet InputSet(*this);
+ // "This" must be a vector and "VTOperand" must be a scalar.
bool MadeChange = false;
+ MadeChange |= EnforceVector(TP);
+ MadeChange |= VTOperand.EnforceScalar(TP);
+
+ // If we know the vector type, it forces the scalar to agree.
+ if (isConcrete()) {
+ EVT IVT = getConcrete();
+ IVT = IVT.getVectorElementType();
+ return MadeChange |
+ VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP);
+ }
+
+ // If the scalar type is known, filter out vector types whose element types
+ // disagree.
+ if (!VTOperand.isConcrete())
+ return MadeChange;
- // If we know nothing, then get the full set.
- if (TypeVec.empty())
- MadeChange = FillWithPossibleTypes(TP, isVector, "vector");
+ MVT::SimpleValueType VT = VTOperand.getConcrete();
- // Filter out all the non-vector types and types which don't have the right
- // element type.
- for (unsigned i = 0; i != TypeVec.size(); ++i)
- if (!isVector(TypeVec[i]) ||
- EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) {
+ TypeSet InputSet(*this);
+
+ // Filter out all the types which don't have the right element type.
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+ if (EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) {
TypeVec.erase(TypeVec.begin()+i--);
MadeChange = true;
}
+ }
if (TypeVec.empty()) // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, forcing '" +
@@ -476,6 +491,59 @@ void DumpDepVars(MultipleUseVarSet &DepVars) {
// PatternToMatch implementation
//
+
+/// getPatternSize - Return the 'size' of this pattern. We want to match large
+/// patterns before small ones. This is used to determine the size of a
+/// pattern.
+static unsigned getPatternSize(const TreePatternNode *P,
+ const CodeGenDAGPatterns &CGP) {
+ unsigned Size = 3; // The node itself.
+ // If the root node is a ConstantSDNode, increases its size.
+ // e.g. (set R32:$dst, 0).
+ if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue()))
+ Size += 2;
+
+ // FIXME: This is a hack to statically increase the priority of patterns
+ // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
+ // Later we can allow complexity / cost for each pattern to be (optionally)
+ // specified. To get best possible pattern match we'll need to dynamically
+ // calculate the complexity of all patterns a dag can potentially map to.
+ const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
+ if (AM)
+ Size += AM->getNumOperands() * 3;
+
+ // If this node has some predicate function that must match, it adds to the
+ // complexity of this node.
+ if (!P->getPredicateFns().empty())
+ ++Size;
+
+ // 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->getNumTypes() &&
+ Child->getType(0) != MVT::Other)
+ Size += getPatternSize(Child, CGP);
+ else if (Child->isLeaf()) {
+ if (dynamic_cast<IntInit*>(Child->getLeafValue()))
+ Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
+ else if (Child->getComplexPatternInfo(CGP))
+ Size += getPatternSize(Child, CGP);
+ else if (!Child->getPredicateFns().empty())
+ ++Size;
+ }
+ }
+
+ return Size;
+}
+
+/// Compute the complexity metric for the input pattern. This roughly
+/// corresponds to the number of nodes that are covered.
+unsigned PatternToMatch::
+getPatternComplexity(const CodeGenDAGPatterns &CGP) const {
+ return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity();
+}
+
+
/// getPredicateCheck - Return a single string containing all of this
/// pattern's predicates concatenated with "&&" operators.
///
@@ -509,6 +577,9 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
if (R->isSubClassOf("SDTCisVT")) {
ConstraintType = SDTCisVT;
x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
+ if (x.SDTCisVT_Info.VT == MVT::isVoid)
+ throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
+
} else if (R->isSubClassOf("SDTCisPtrTy")) {
ConstraintType = SDTCisPtrTy;
} else if (R->isSubClassOf("SDTCisInt")) {
@@ -568,13 +639,6 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N,
bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
const SDNodeInfo &NodeInfo,
TreePattern &TP) const {
- // Check that the number of operands is sane. Negative operands -> varargs.
- if (NodeInfo.getNumOperands() >= 0) {
- if (N->getNumChildren() != (unsigned)NodeInfo.getNumOperands())
- TP.error(N->getOperator()->getName() + " node requires exactly " +
- itostr(NodeInfo.getNumOperands()) + " operands!");
- }
-
unsigned ResNo = 0; // The result number being referenced.
TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);
@@ -612,22 +676,15 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
TP.error(N->getOperator()->getName() + " expects a VT operand!");
MVT::SimpleValueType VT =
getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
- if (!isInteger(VT))
- TP.error(N->getOperator()->getName() + " VT operand must be integer!");
+
+ EEVT::TypeSet TypeListTmp(VT, TP);
unsigned OResNo = 0;
TreePatternNode *OtherNode =
getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo,
OResNo);
-
- // It must be integer.
- bool MadeChange = OtherNode->getExtType(OResNo).EnforceInteger(TP);
- // This doesn't try to enforce any information on the OtherNode, it just
- // validates it when information is determined.
- if (OtherNode->hasTypeSet(OResNo) && OtherNode->getType(OResNo) <= VT)
- OtherNode->UpdateNodeType(OResNo, MVT::Other, TP); // Throw an error.
- return MadeChange;
+ return TypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP);
}
case SDTCisOpSmallerThanOp: {
unsigned BResNo = 0;
@@ -642,22 +699,11 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
TreePatternNode *VecOperand =
getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo,
VResNo);
- if (VecOperand->hasTypeSet(VResNo)) {
- if (!isVector(VecOperand->getType(VResNo)))
- TP.error(N->getOperator()->getName() + " VT operand must be a vector!");
- EVT IVT = VecOperand->getType(VResNo);
- IVT = IVT.getVectorElementType();
- return NodeToApply->UpdateNodeType(ResNo, IVT.getSimpleVT().SimpleTy, TP);
- }
- if (NodeToApply->hasTypeSet(ResNo) &&
- VecOperand->getExtType(VResNo).hasVectorTypes()){
- // Filter vector types out of VecOperand that don't have the right element
- // type.
- return VecOperand->getExtType(VResNo).
- EnforceVectorEltTypeIs(NodeToApply->getType(ResNo), TP);
- }
- return false;
+ // Filter vector types out of VecOperand that don't have the right element
+ // type.
+ return VecOperand->getExtType(VResNo).
+ EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP);
}
}
return false;
@@ -716,10 +762,11 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
/// getKnownType - If the type constraints on this node imply a fixed type
/// (e.g. all stores return void, etc), then return it as an
/// MVT::SimpleValueType. Otherwise, return EEVT::Other.
-MVT::SimpleValueType SDNodeInfo::getKnownType() const {
+MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const {
unsigned NumResults = getNumResults();
assert(NumResults <= 1 &&
"We only work with nodes with zero or one result so far!");
+ assert(ResNo == 0 && "Only handles single result nodes so far");
for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) {
// Make sure that this applies to the correct node result.
@@ -750,16 +797,11 @@ TreePatternNode::~TreePatternNode() {
static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
if (Operator->getName() == "set" ||
- Operator->getName() == "implicit" ||
- Operator->getName() == "parallel")
+ Operator->getName() == "implicit")
return 0; // All return nothing.
- if (Operator->isSubClassOf("Intrinsic")) {
- unsigned NumRes = CDP.getIntrinsic(Operator).IS.RetVTs.size();
- if (NumRes == 1 && CDP.getIntrinsic(Operator).IS.RetVTs[0] == MVT::isVoid)
- return 0;
- return NumRes;
- }
+ if (Operator->isSubClassOf("Intrinsic"))
+ return CDP.getIntrinsic(Operator).IS.RetVTs.size();
if (Operator->isSubClassOf("SDNode"))
return CDP.getSDNodeInfo(Operator).getNumResults();
@@ -782,21 +824,14 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
if (Operator->isSubClassOf("Instruction")) {
CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator);
+
+ // FIXME: Should allow access to all the results here.
+ unsigned NumDefsToAdd = InstInfo.NumDefs ? 1 : 0;
- // FIXME: Handle implicit defs right.
- if (InstInfo.NumDefs != 0)
- return 1; // FIXME: Handle inst results right!
-
- if (!InstInfo.ImplicitDefs.empty()) {
- // Add on one implicit def if it has a resolvable type.
- Record *FirstImplicitDef = InstInfo.ImplicitDefs[0];
- assert(FirstImplicitDef->isSubClassOf("Register"));
- const std::vector<MVT::SimpleValueType> &RegVTs =
- CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef);
- if (RegVTs.size() == 1)
- return 1;
- }
- return 0;
+ // Add on one implicit def if it has a resolvable type.
+ if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
+ ++NumDefsToAdd;
+ return NumDefsToAdd;
}
if (Operator->isSubClassOf("SDNodeXForm"))
@@ -1000,34 +1035,49 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
///
static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
bool NotRegisters, TreePattern &TP) {
- assert(ResNo == 0 && "FIXME: Unhandled result number");
-
// Check to see if this is a register or a register class.
if (R->isSubClassOf("RegisterClass")) {
+ assert(ResNo == 0 && "Regclass ref only has one result!");
if (NotRegisters)
return EEVT::TypeSet(); // Unknown.
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes());
- } else if (R->isSubClassOf("PatFrag")) {
+ }
+
+ if (R->isSubClassOf("PatFrag")) {
+ assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");
// Pattern fragment types will be resolved when they are inlined.
return EEVT::TypeSet(); // Unknown.
- } else if (R->isSubClassOf("Register")) {
+ }
+
+ if (R->isSubClassOf("Register")) {
+ assert(ResNo == 0 && "Registers only produce one result!");
if (NotRegisters)
return EEVT::TypeSet(); // Unknown.
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
return EEVT::TypeSet(T.getRegisterVTs(R));
- } else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
+ }
+
+ if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
+ assert(ResNo == 0 && "This node only has one result!");
// Using a VTSDNode or CondCodeSDNode.
return EEVT::TypeSet(MVT::Other, TP);
- } else if (R->isSubClassOf("ComplexPattern")) {
+ }
+
+ if (R->isSubClassOf("ComplexPattern")) {
+ assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?");
if (NotRegisters)
return EEVT::TypeSet(); // Unknown.
return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(),
TP);
- } else if (R->isSubClassOf("PointerLikeRegClass")) {
+ }
+ if (R->isSubClassOf("PointerLikeRegClass")) {
+ assert(ResNo == 0 && "Regclass can only have one result!");
return EEVT::TypeSet(MVT::iPTR, TP);
- } else if (R->getName() == "node" || R->getName() == "srcvalue" ||
- R->getName() == "zero_reg") {
+ }
+
+ if (R->getName() == "node" || R->getName() == "srcvalue" ||
+ R->getName() == "zero_reg") {
// Placeholder.
return EEVT::TypeSet(); // Unknown.
}
@@ -1175,8 +1225,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
return MadeChange;
}
- if (getOperator()->getName() == "implicit" ||
- getOperator()->getName() == "parallel") {
+ if (getOperator()->getName() == "implicit") {
assert(getNumTypes() == 0 && "Node doesn't produce a value");
bool MadeChange = false;
@@ -1210,8 +1259,6 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
// Apply the result type to the node.
unsigned NumRetVTs = Int->IS.RetVTs.size();
unsigned NumParamVTs = Int->IS.ParamVTs.size();
- if (NumRetVTs == 1 && Int->IS.RetVTs[0] == MVT::isVoid)
- NumRetVTs = 0;
for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP);
@@ -1237,6 +1284,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (getOperator()->isSubClassOf("SDNode")) {
const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());
+ // Check that the number of operands is sane. Negative operands -> varargs.
+ if (NI.getNumOperands() >= 0 &&
+ getNumChildren() != (unsigned)NI.getNumOperands())
+ TP.error(getOperator()->getName() + " node requires exactly " +
+ itostr(NI.getNumOperands()) + " operands!");
+
bool MadeChange = NI.ApplyTypeConstraints(this, TP);
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
@@ -1245,21 +1298,20 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (getOperator()->isSubClassOf("Instruction")) {
const DAGInstruction &Inst = CDP.getInstruction(getOperator());
- unsigned ResNo = 0;
- assert(Inst.getNumResults() <= 1 &&
- "FIXME: Only supports zero or one result instrs!");
-
CodeGenInstruction &InstInfo =
CDP.getTargetInfo().getInstruction(getOperator());
- EEVT::TypeSet ResultType;
-
- // Apply the result type to the node
- if (InstInfo.NumDefs != 0) { // # of elements in (outs) list
- Record *ResultNode = Inst.getResult(0);
+ bool MadeChange = false;
+
+ // Apply the result types to the node, these come from the things in the
+ // (outs) list of the instruction.
+ // FIXME: Cap at one result so far.
+ unsigned NumResultsToAdd = InstInfo.NumDefs ? 1 : 0;
+ for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) {
+ Record *ResultNode = Inst.getResult(ResNo);
if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
- ResultType = EEVT::TypeSet(MVT::iPTR, TP);
+ MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP);
} else if (ResultNode->getName() == "unknown") {
// Nothing to do.
} else {
@@ -1267,25 +1319,23 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
"Operands should be register classes!");
const CodeGenRegisterClass &RC =
CDP.getTargetInfo().getRegisterClass(ResultNode);
- ResultType = RC.getValueTypes();
+ MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP);
}
- } else if (!InstInfo.ImplicitDefs.empty()) {
- // If the instruction has implicit defs, the first one defines the result
- // type.
- Record *FirstImplicitDef = InstInfo.ImplicitDefs[0];
- assert(FirstImplicitDef->isSubClassOf("Register"));
- const std::vector<MVT::SimpleValueType> &RegVTs =
- CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef);
- if (RegVTs.size() == 1) // FIXME: Generalize.
- ResultType = EEVT::TypeSet(RegVTs);
- } else {
- // Otherwise, the instruction produces no value result.
}
- bool MadeChange = false;
-
- if (!ResultType.isCompletelyUnknown())
- MadeChange |= UpdateNodeType(ResNo, ResultType, TP);
+ // If the instruction has implicit defs, we apply the first one as a result.
+ // FIXME: This sucks, it should apply all implicit defs.
+ if (!InstInfo.ImplicitDefs.empty()) {
+ unsigned ResNo = NumResultsToAdd;
+
+ // FIXME: Generalize to multiple possible types and multiple possible
+ // ImplicitDefs.
+ MVT::SimpleValueType VT =
+ InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo());
+
+ if (VT != MVT::Other)
+ MadeChange |= UpdateNodeType(ResNo, VT, TP);
+ }
// If this is an INSERT_SUBREG, constrain the source and destination VTs to
// be the same.
@@ -1314,17 +1364,17 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MVT::SimpleValueType VT;
TreePatternNode *Child = getChild(ChildNo++);
- assert(Child->getNumTypes() == 1 && "Unknown case?");
+ unsigned ChildResNo = 0; // Instructions always use res #0 of their op.
if (OperandNode->isSubClassOf("RegisterClass")) {
const CodeGenRegisterClass &RC =
CDP.getTargetInfo().getRegisterClass(OperandNode);
- MadeChange |= Child->UpdateNodeType(0, RC.getValueTypes(), TP);
+ MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
} else if (OperandNode->isSubClassOf("Operand")) {
VT = getValueType(OperandNode->getValueAsDef("Type"));
- MadeChange |= Child->UpdateNodeType(0, VT, TP);
+ MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP);
} else if (OperandNode->isSubClassOf("PointerLikeRegClass")) {
- MadeChange |= Child->UpdateNodeType(0, MVT::iPTR, TP);
+ MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP);
} else if (OperandNode->getName() == "unknown") {
// Nothing to do.
} else {
@@ -1423,13 +1473,13 @@ TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){
isInputPattern = isInput;
for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i)
- Trees.push_back(ParseTreePattern((DagInit*)RawPat->getElement(i)));
+ Trees.push_back(ParseTreePattern(RawPat->getElement(i), ""));
}
TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){
isInputPattern = isInput;
- Trees.push_back(ParseTreePattern(Pat));
+ Trees.push_back(ParseTreePattern(Pat, ""));
}
TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
@@ -1457,7 +1507,49 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
}
-TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
+TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
+ if (DefInit *DI = dynamic_cast<DefInit*>(TheInit)) {
+ Record *R = DI->getDef();
+
+ // Direct reference to a leaf DagNode or PatFrag? Turn it into a
+ // TreePatternNode if its own. For example:
+ /// (foo GPR, imm) -> (foo GPR, (imm))
+ if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
+ return ParseTreePattern(new DagInit(DI, "",
+ std::vector<std::pair<Init*, std::string> >()),
+ OpName);
+
+ // Input argument?
+ TreePatternNode *Res = new TreePatternNode(DI, 1);
+ if (R->getName() == "node" && !OpName.empty()) {
+ if (OpName.empty())
+ error("'node' argument requires a name to match with operand list");
+ Args.push_back(OpName);
+ }
+
+ Res->setName(OpName);
+ return Res;
+ }
+
+ if (IntInit *II = dynamic_cast<IntInit*>(TheInit)) {
+ if (!OpName.empty())
+ error("Constant int argument should not have a name!");
+ return new TreePatternNode(II, 1);
+ }
+
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) {
+ // Turn this into an IntInit.
+ Init *II = BI->convertInitializerTo(new IntRecTy());
+ if (II == 0 || !dynamic_cast<IntInit*>(II))
+ error("Bits value must be constants!");
+ return ParseTreePattern(II, OpName);
+ }
+
+ DagInit *Dag = dynamic_cast<DagInit*>(TheInit);
+ if (!Dag) {
+ TheInit->dump();
+ error("Pattern has unexpected init kind!");
+ }
DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
if (!OpDef) error("Pattern has unexpected operator type!");
Record *Operator = OpDef->getDef();
@@ -1468,50 +1560,14 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
if (Dag->getNumArgs() != 1)
error("Type cast only takes one operand!");
- Init *Arg = Dag->getArg(0);
- TreePatternNode *New;
- if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
- Record *R = DI->getDef();
- if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
- Dag->setArg(0, new DagInit(DI, "",
- std::vector<std::pair<Init*, std::string> >()));
- return ParseTreePattern(Dag);
- }
-
- // Input argument?
- if (R->getName() == "node") {
- if (Dag->getArgName(0).empty())
- error("'node' argument requires a name to match with operand list");
- Args.push_back(Dag->getArgName(0));
- }
-
- New = new TreePatternNode(DI, 1);
- } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
- New = ParseTreePattern(DI);
- } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
- New = new TreePatternNode(II, 1);
- if (!Dag->getArgName(0).empty())
- error("Constant int argument should not have a name!");
- } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Arg)) {
- // Turn this into an IntInit.
- Init *II = BI->convertInitializerTo(new IntRecTy());
- if (II == 0 || !dynamic_cast<IntInit*>(II))
- error("Bits value must be constants!");
-
- New = new TreePatternNode(dynamic_cast<IntInit*>(II), 1);
- if (!Dag->getArgName(0).empty())
- error("Constant int argument should not have a name!");
- } else {
- Arg->dump();
- error("Unknown leaf value for tree pattern!");
- return 0;
- }
+ TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0));
// Apply the type cast.
assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
New->UpdateNodeType(0, getValueType(Operator), *this);
- if (New->getNumChildren() == 0)
- New->setName(Dag->getArgName(0));
+
+ if (!OpName.empty())
+ error("ValueType cast should not have a name!");
return New;
}
@@ -1522,65 +1578,38 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
!Operator->isSubClassOf("SDNodeXForm") &&
!Operator->isSubClassOf("Intrinsic") &&
Operator->getName() != "set" &&
- Operator->getName() != "implicit" &&
- Operator->getName() != "parallel")
+ Operator->getName() != "implicit")
error("Unrecognized node '" + Operator->getName() + "'!");
// Check to see if this is something that is illegal in an input pattern.
- if (isInputPattern && (Operator->isSubClassOf("Instruction") ||
- Operator->isSubClassOf("SDNodeXForm")))
- error("Cannot use '" + Operator->getName() + "' in an input pattern!");
+ if (isInputPattern) {
+ if (Operator->isSubClassOf("Instruction") ||
+ Operator->isSubClassOf("SDNodeXForm"))
+ error("Cannot use '" + Operator->getName() + "' in an input pattern!");
+ } else {
+ if (Operator->isSubClassOf("Intrinsic"))
+ error("Cannot use '" + Operator->getName() + "' in an output pattern!");
+
+ if (Operator->isSubClassOf("SDNode") &&
+ Operator->getName() != "imm" &&
+ Operator->getName() != "fpimm" &&
+ Operator->getName() != "tglobaltlsaddr" &&
+ Operator->getName() != "tconstpool" &&
+ Operator->getName() != "tjumptable" &&
+ Operator->getName() != "tframeindex" &&
+ Operator->getName() != "texternalsym" &&
+ Operator->getName() != "tblockaddress" &&
+ Operator->getName() != "tglobaladdr" &&
+ Operator->getName() != "bb" &&
+ Operator->getName() != "vt")
+ error("Cannot use '" + Operator->getName() + "' in an output pattern!");
+ }
std::vector<TreePatternNode*> Children;
-
- for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
- Init *Arg = Dag->getArg(i);
- if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
- Children.push_back(ParseTreePattern(DI));
- if (Children.back()->getName().empty())
- Children.back()->setName(Dag->getArgName(i));
- } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
- Record *R = DefI->getDef();
- // Direct reference to a leaf DagNode or PatFrag? Turn it into a
- // TreePatternNode if its own.
- if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
- Dag->setArg(i, new DagInit(DefI, "",
- std::vector<std::pair<Init*, std::string> >()));
- --i; // Revisit this node...
- } else {
- TreePatternNode *Node = new TreePatternNode(DefI, 1);
- Node->setName(Dag->getArgName(i));
- Children.push_back(Node);
-
- // Input argument?
- if (R->getName() == "node") {
- if (Dag->getArgName(i).empty())
- error("'node' argument requires a name to match with operand list");
- Args.push_back(Dag->getArgName(i));
- }
- }
- } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
- TreePatternNode *Node = new TreePatternNode(II, 1);
- if (!Dag->getArgName(i).empty())
- error("Constant int argument should not have a name!");
- Children.push_back(Node);
- } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Arg)) {
- // Turn this into an IntInit.
- Init *II = BI->convertInitializerTo(new IntRecTy());
- if (II == 0 || !dynamic_cast<IntInit*>(II))
- error("Bits value must be constants!");
-
- TreePatternNode *Node = new TreePatternNode(dynamic_cast<IntInit*>(II),1);
- if (!Dag->getArgName(i).empty())
- error("Constant int argument should not have a name!");
- Children.push_back(Node);
- } else {
- errs() << '"';
- Arg->dump();
- errs() << "\": ";
- error("Unknown leaf value for tree pattern!");
- }
- }
+
+ // Parse all the operands.
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
+ Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i)));
// If the operator is an intrinsic, then this is just syntactic sugar for for
// (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
@@ -1591,15 +1620,13 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
// If this intrinsic returns void, it must have side-effects and thus a
// chain.
- if (Int.IS.RetVTs[0] == MVT::isVoid) {
+ if (Int.IS.RetVTs.empty())
Operator = getDAGPatterns().get_intrinsic_void_sdnode();
- } else if (Int.ModRef != CodeGenIntrinsic::NoMem) {
+ else if (Int.ModRef != CodeGenIntrinsic::NoMem)
// Has side-effects, requires chain.
Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();
- } else {
- // Otherwise, no chain.
+ else // Otherwise, no chain.
Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
- }
TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1);
Children.insert(Children.begin(), IIDNode);
@@ -1607,10 +1634,48 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
unsigned NumResults = GetNumNodeResults(Operator, CDP);
TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults);
- Result->setName(Dag->getName());
+ Result->setName(OpName);
+
+ if (!Dag->getName().empty()) {
+ assert(Result->getName().empty());
+ Result->setName(Dag->getName());
+ }
return Result;
}
+/// SimplifyTree - See if we can simplify this tree to eliminate something that
+/// will never match in favor of something obvious that will. This is here
+/// strictly as a convenience to target authors because it allows them to write
+/// more type generic things and have useless type casts fold away.
+///
+/// This returns true if any change is made.
+static bool SimplifyTree(TreePatternNode *&N) {
+ if (N->isLeaf())
+ return false;
+
+ // If we have a bitconvert with a resolved type and if the source and
+ // destination types are the same, then the bitconvert is useless, remove it.
+ if (N->getOperator()->getName() == "bitconvert" &&
+ N->getExtType(0).isConcrete() &&
+ N->getExtType(0) == N->getChild(0)->getExtType(0) &&
+ N->getName().empty()) {
+ N = N->getChild(0);
+ SimplifyTree(N);
+ return true;
+ }
+
+ // Walk all children.
+ bool MadeChange = false;
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ MadeChange |= SimplifyTree(Child);
+ N->setChild(i, Child);
+ }
+ return MadeChange;
+}
+
+
+
/// InferAllTypes - Infer/propagate as many types throughout the expression
/// patterns as possible. Return true if all types are inferred, false
/// otherwise. Throw an exception if a type contradiction is found.
@@ -1622,8 +1687,10 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
bool MadeChange = true;
while (MadeChange) {
MadeChange = false;
- for (unsigned i = 0, e = Trees.size(); i != e; ++i)
+ for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false);
+ MadeChange |= SimplifyTree(Trees[i]);
+ }
// If there are constraints on our named nodes, apply them.
for (StringMap<SmallVector<TreePatternNode*,1> >::iterator
@@ -2542,37 +2609,7 @@ void CodeGenDAGPatterns::ParsePatterns() {
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
Record *CurPattern = Patterns[i];
DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch");
- DefInit *OpDef = dynamic_cast<DefInit*>(Tree->getOperator());
- Record *Operator = OpDef->getDef();
- TreePattern *Pattern;
- if (Operator->getName() != "parallel")
- Pattern = new TreePattern(CurPattern, Tree, true, *this);
- else {
- std::vector<Init*> Values;
- RecTy *ListTy = 0;
- for (unsigned j = 0, ee = Tree->getNumArgs(); j != ee; ++j) {
- Values.push_back(Tree->getArg(j));
- TypedInit *TArg = dynamic_cast<TypedInit*>(Tree->getArg(j));
- if (TArg == 0) {
- errs() << "In dag: " << Tree->getAsString();
- errs() << " -- Untyped argument in pattern\n";
- assert(0 && "Untyped argument in pattern");
- }
- if (ListTy != 0) {
- ListTy = resolveTypes(ListTy, TArg->getType());
- if (ListTy == 0) {
- errs() << "In dag: " << Tree->getAsString();
- errs() << " -- Incompatible types in pattern arguments\n";
- assert(0 && "Incompatible types in pattern arguments");
- }
- }
- else {
- ListTy = TArg->getType();
- }
- }
- ListInit *LI = new ListInit(Values, new ListRecTy(ListTy));
- Pattern = new TreePattern(CurPattern, LI, true, *this);
- }
+ TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this);
// Inline pattern fragments into it.
Pattern->InlinePatternFragments();
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index f583f29..5480513 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -129,7 +129,7 @@ namespace EEVT {
/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
/// whose element is VT.
- bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP);
+ bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
@@ -199,6 +199,9 @@ public:
SDNodeInfo(Record *R); // Parse the specified record.
unsigned getNumResults() const { return NumResults; }
+
+ /// getNumOperands - This is the number of operands required or -1 if
+ /// variadic.
int getNumOperands() const { return NumOperands; }
Record *getRecord() const { return Def; }
const std::string &getEnumName() const { return EnumName; }
@@ -211,7 +214,7 @@ public:
/// getKnownType - If the type constraints on this node imply a fixed type
/// (e.g. all stores return void, etc), then return it as an
/// MVT::SimpleValueType. Otherwise, return MVT::Other.
- MVT::SimpleValueType getKnownType() const;
+ MVT::SimpleValueType getKnownType(unsigned ResNo) const;
/// hasProperty - Return true if this node has the specified property.
///
@@ -272,7 +275,7 @@ public:
~TreePatternNode();
const std::string &getName() const { return Name; }
- void setName(const std::string &N) { Name = N; }
+ void setName(StringRef N) { Name.assign(N.begin(), N.end()); }
bool isLeaf() const { return Val != 0; }
@@ -510,7 +513,7 @@ public:
void dump() const;
private:
- TreePatternNode *ParseTreePattern(DagInit *DI);
+ TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName);
void ComputeNamedNodes();
void ComputeNamedNodes(TreePatternNode *N);
};
@@ -595,6 +598,10 @@ public:
unsigned getAddedComplexity() const { return AddedComplexity; }
std::string getPredicateCheck() const;
+
+ /// Compute the complexity metric for the input pattern. This roughly
+ /// corresponds to the number of nodes that are covered.
+ unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
};
// Deterministic comparison of Record*.
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index eea5561..99d196c 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
@@ -294,3 +295,22 @@ CodeGenInstruction::ParseOperandName(const std::string &Op,
// Otherwise, didn't find it!
throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
}
+
+
+/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
+/// implicit def and it has a known VT, return the VT, otherwise return
+/// MVT::Other.
+MVT::SimpleValueType CodeGenInstruction::
+HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
+ if (ImplicitDefs.empty()) return MVT::Other;
+
+ // Check to see if the first implicit def has a resolvable type.
+ Record *FirstImplicitDef = ImplicitDefs[0];
+ assert(FirstImplicitDef->isSubClassOf("Register"));
+ const std::vector<MVT::SimpleValueType> &RegVTs =
+ TargetInfo.getRegisterVTs(FirstImplicitDef);
+ if (RegVTs.size() == 1)
+ return RegVTs[0];
+ return MVT::Other;
+}
+
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index c369123..946c2d0 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -22,6 +22,7 @@
namespace llvm {
class Record;
class DagInit;
+ class CodeGenTarget;
class CodeGenInstruction {
public:
@@ -183,6 +184,12 @@ namespace llvm {
/// non-empty name. If the instruction does not have an operand with the
/// specified name, throw an exception.
unsigned getOperandNamed(const std::string &Name) const;
+
+ /// HasOneImplicitDefWithKnownVT - If the instruction has at least one
+ /// implicit def and it has a known VT, return the VT, otherwise return
+ /// MVT::Other.
+ MVT::SimpleValueType
+ HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const;
};
}
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 79bc30d..0392895 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -18,6 +18,7 @@
#include "CodeGenIntrinsics.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
using namespace llvm;
@@ -194,6 +195,10 @@ getRegisterVTs(Record *R) const {
}
}
}
+
+ // Remove duplicates.
+ array_pod_sort(Result.begin(), Result.end());
+ Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
return Result;
}
@@ -488,15 +493,17 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
}
if (EVT(VT).isOverloaded()) {
OverloadedVTs.push_back(VT);
- isOverloaded |= true;
+ isOverloaded = true;
}
+
+ // Reject invalid types.
+ if (VT == MVT::isVoid)
+ throw "Intrinsic '" + DefName + " has void in result type list!";
+
IS.RetVTs.push_back(VT);
IS.RetTypeDefs.push_back(TyEl);
}
-
- if (IS.RetVTs.size() == 0)
- throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!";
-
+
// Parse the list of parameter types.
TypeList = R->getValueAsListInit("ParamTypes");
for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
@@ -517,10 +524,16 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
"Expected iAny or vAny type");
} else
VT = getValueType(TyEl->getValueAsDef("VT"));
+
if (EVT(VT).isOverloaded()) {
OverloadedVTs.push_back(VT);
- isOverloaded |= true;
+ isOverloaded = true;
}
+
+ // Reject invalid types.
+ if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
+ throw "Intrinsic '" + DefName + " has void in result type list!";
+
IS.ParamVTs.push_back(VT);
IS.ParamTypeDefs.push_back(TyEl);
}
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 044086a..04c7710 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -21,49 +21,6 @@ using namespace llvm;
// DAGISelEmitter Helper methods
//
-/// getPatternSize - Return the 'size' of this pattern. We want to match large
-/// patterns before small ones. This is used to determine the size of a
-/// pattern.
-static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
- unsigned Size = 3; // The node itself.
- // If the root node is a ConstantSDNode, increases its size.
- // e.g. (set R32:$dst, 0).
- if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue()))
- Size += 2;
-
- // FIXME: This is a hack to statically increase the priority of patterns
- // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
- // Later we can allow complexity / cost for each pattern to be (optionally)
- // specified. To get best possible pattern match we'll need to dynamically
- // calculate the complexity of all patterns a dag can potentially map to.
- const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
- if (AM)
- Size += AM->getNumOperands() * 3;
-
- // If this node has some predicate function that must match, it adds to the
- // complexity of this node.
- if (!P->getPredicateFns().empty())
- ++Size;
-
- // 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->getNumTypes() &&
- Child->getType(0) != MVT::Other)
- Size += getPatternSize(Child, CGP);
- else if (Child->isLeaf()) {
- if (dynamic_cast<IntInit*>(Child->getLeafValue()))
- Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
- else if (Child->getComplexPatternInfo(CGP))
- Size += getPatternSize(Child, CGP);
- else if (!Child->getPredicateFns().empty())
- ++Size;
- }
- }
-
- return Size;
-}
-
/// getResultPatternCost - Compute the number of instructions for this pattern.
/// This is a temporary hack. We should really include the instruction
/// latencies in this calculation.
@@ -153,12 +110,25 @@ struct PatternSortingPredicate {
PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
CodeGenDAGPatterns &CGP;
- bool operator()(const PatternToMatch *LHS,
- const PatternToMatch *RHS) {
- unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), CGP);
- unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), CGP);
- LHSSize += LHS->getAddedComplexity();
- RHSSize += RHS->getAddedComplexity();
+ bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) {
+ const TreePatternNode *LHSSrc = LHS->getSrcPattern();
+ const TreePatternNode *RHSSrc = RHS->getSrcPattern();
+
+ if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 &&
+ LHSSrc->getType(0) != RHSSrc->getType(0)) {
+ MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0);
+ if (MVT(V1).isVector() != MVT(V2).isVector())
+ return MVT(V2).isVector();
+
+ if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint())
+ return MVT(V2).isFloatingPoint();
+ }
+
+ // Otherwise, if the patterns might both match, sort based on complexity,
+ // which means that we prefer to match patterns that cover more nodes in the
+ // input over nodes that cover fewer.
+ unsigned LHSSize = LHS->getPatternComplexity(CGP);
+ unsigned RHSSize = RHS->getPatternComplexity(CGP);
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
if (LHSSize < RHSSize) return false;
@@ -173,7 +143,8 @@ struct PatternSortingPredicate {
if (LHSPatSize < RHSPatSize) return true;
if (LHSPatSize > RHSPatSize) return false;
- // Sort based on the UID of the pattern, giving us a deterministic ordering.
+ // Sort based on the UID of the pattern, giving us a deterministic ordering
+ // if all other sorting conditions fail.
assert(LHS == RHS || LHS->ID != RHS->ID);
return LHS->ID < RHS->ID;
}
@@ -208,8 +179,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
// We want to process the matches in order of minimal cost. Sort the patterns
// so the least cost one is at the start.
- std::stable_sort(Patterns.begin(), Patterns.end(),
- PatternSortingPredicate(CGP));
+ std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP));
// Convert each variant of each pattern into a Matcher.
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index cd3fad1..9f12a68 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -147,7 +147,8 @@ void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
- OS.indent(indent) << "CheckType " << getEnumName(Type) << '\n';
+ OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo="
+ << ResNo << '\n';
}
void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@@ -356,12 +357,11 @@ bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const {
// different, then we know they contradict. For example, a check for
// ISD::STORE will never be true at the same time a check for Type i32 is.
if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) {
- // FIXME: What result is this referring to?
- MVT::SimpleValueType NodeType;
- if (getOpcode().getNumResults() == 0)
- NodeType = MVT::isVoid;
- else
- NodeType = getOpcode().getKnownType();
+ // If checking for a result the opcode doesn't have, it can't match.
+ if (CT->getResNo() >= getOpcode().getNumResults())
+ return true;
+
+ MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo());
if (NodeType != MVT::Other)
return TypesAreContradictory(NodeType, CT->getType());
}
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index ef7ecf4..d9b25d5 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -492,14 +492,16 @@ private:
};
/// CheckTypeMatcher - This checks to see if the current node has the
-/// specified type, if not it fails to match.
+/// specified type at the specified result, if not it fails to match.
class CheckTypeMatcher : public Matcher {
MVT::SimpleValueType Type;
+ unsigned ResNo;
public:
- CheckTypeMatcher(MVT::SimpleValueType type)
- : Matcher(CheckType), Type(type) {}
+ CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno)
+ : Matcher(CheckType), Type(type), ResNo(resno) {}
MVT::SimpleValueType getType() const { return Type; }
+ unsigned getResNo() const { return ResNo; }
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckType;
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index cabf2d4..4473f0d 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -32,6 +32,7 @@ OmitComments("omit-comments", cl::desc("Do not generate comments"),
namespace {
class MatcherTableEmitter {
+ const CodeGenDAGPatterns &CGP;
StringMap<unsigned> NodePredicateMap, PatternPredicateMap;
std::vector<std::string> NodePredicates, PatternPredicates;
@@ -43,13 +44,12 @@ class MatcherTableEmitter {
std::vector<Record*> NodeXForms;
public:
- MatcherTableEmitter() {}
+ MatcherTableEmitter(const CodeGenDAGPatterns &cgp) : CGP(cgp) {}
unsigned EmitMatcherList(const Matcher *N, unsigned Indent,
unsigned StartIdx, formatted_raw_ostream &OS);
- void EmitPredicateFunctions(const CodeGenDAGPatterns &CGP,
- formatted_raw_ostream &OS);
+ void EmitPredicateFunctions(formatted_raw_ostream &OS);
void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS);
private:
@@ -255,9 +255,9 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
}
case Matcher::CheckOpcode:
- OS << "OPC_CheckOpcode, "
- << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << ",\n";
- return 2;
+ OS << "OPC_CheckOpcode, TARGET_OPCODE("
+ << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n";
+ return 3;
case Matcher::SwitchOpcode:
case Matcher::SwitchType: {
@@ -280,10 +280,14 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
// For each case we emit the size, then the opcode, then the matcher.
for (unsigned i = 0, e = NumCases; i != e; ++i) {
const Matcher *Child;
- if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
+ unsigned IdxSize;
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
Child = SOM->getCaseMatcher(i);
- else
+ IdxSize = 2; // size of opcode in table is 2 bytes.
+ } else {
Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
+ IdxSize = 1; // size of type in table is 1 byte.
+ }
// We need to encode the opcode and the offset of the case code before
// emitting the case code. Handle this by buffering the output into a
@@ -299,7 +303,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
TmpBuf.clear();
raw_svector_ostream OS(TmpBuf);
formatted_raw_ostream FOS(OS);
- ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+1, FOS);
+ ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize,
+ FOS);
} while (GetVBRSize(ChildSize) != VBRSize);
assert(ChildSize != 0 && "Should not have a zero-sized child!");
@@ -316,15 +321,15 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
OS << ' ';
if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
- OS << SOM->getCaseOpcode(i).getEnumName();
+ OS << "TARGET_OPCODE(" << SOM->getCaseOpcode(i).getEnumName() << "),";
else
- OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i));
- OS << ',';
-
+ OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ',';
+
+ CurrentIdx += IdxSize;
+
if (!OmitComments)
- OS << "// ->" << CurrentIdx+ChildSize+1;
+ OS << "// ->" << CurrentIdx+ChildSize;
OS << '\n';
- ++CurrentIdx;
OS << TmpBuf.str();
CurrentIdx += ChildSize;
}
@@ -341,6 +346,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
}
case Matcher::CheckType:
+ assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 &&
+ "FIXME: Add support for CheckType of resno != 0");
OS << "OPC_CheckType, "
<< getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";
return 2;
@@ -442,6 +449,13 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
case Matcher::EmitMergeInputChains: {
const EmitMergeInputChainsMatcher *MN =
cast<EmitMergeInputChainsMatcher>(N);
+
+ // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1.
+ if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) {
+ OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n";
+ return 1;
+ }
+
OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";
for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
OS << MN->getNode(i) << ", ";
@@ -507,7 +521,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
OS.PadToColumn(Indent*2) << "// Src: "
- << *SNT->getPattern().getSrcPattern() << '\n';
+ << *SNT->getPattern().getSrcPattern() << " - Complexity = "
+ << SNT->getPattern().getPatternComplexity(CGP) << '\n';
OS.PadToColumn(Indent*2) << "// Dst: "
<< *SNT->getPattern().getDstPattern() << '\n';
}
@@ -534,7 +549,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
OS << '\n';
if (!OmitComments) {
OS.PadToColumn(Indent*2) << "// Src: "
- << *CM->getPattern().getSrcPattern() << '\n';
+ << *CM->getPattern().getSrcPattern() << " - Complexity = "
+ << CM->getPattern().getPatternComplexity(CGP) << '\n';
OS.PadToColumn(Indent*2) << "// Dst: "
<< *CM->getPattern().getDstPattern();
}
@@ -565,8 +581,7 @@ EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
return Size;
}
-void MatcherTableEmitter::EmitPredicateFunctions(const CodeGenDAGPatterns &CGP,
- formatted_raw_ostream &OS) {
+void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
// Emit pattern predicates.
if (!PatternPredicates.empty()) {
OS << "bool CheckPatternPredicate(unsigned PredNo) const {\n";
@@ -760,7 +775,7 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher,
OS << "// The main instruction selector code.\n";
OS << "SDNode *SelectCode(SDNode *N) {\n";
- MatcherTableEmitter MatcherEmitter;
+ MatcherTableEmitter MatcherEmitter(CGP);
OS << " // Opcodes are emitted as 2 bytes, TARGET_OPCODE handles this.\n";
OS << " #define TARGET_OPCODE(X) X & 255, unsigned(X) >> 8\n";
@@ -775,5 +790,5 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher,
OS << '\n';
// Next up, emit the function for node and pattern predicates:
- MatcherEmitter.EmitPredicateFunctions(CGP, OS);
+ MatcherEmitter.EmitPredicateFunctions(OS);
}
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index da6f6af..9d469a9 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -408,13 +408,13 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N,
// If N and NodeNoTypes don't agree on a type, then this is a case where we
// need to do a type check. Emit the check, apply the tyep to NodeNoTypes and
// reinfer any correlated types.
- bool DoTypeCheck = false;
- if (NodeNoTypes->getNumTypes() != 0 &&
- NodeNoTypes->getExtType(0) != N->getExtType(0)) {
- assert(NodeNoTypes->getNumTypes() == 1 && "FIXME: Handle multiple results");
- NodeNoTypes->setType(0, N->getExtType(0));
+ SmallVector<unsigned, 2> ResultsToTypeCheck;
+
+ for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) {
+ if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue;
+ NodeNoTypes->setType(i, N->getExtType(i));
InferPossibleTypes();
- DoTypeCheck = true;
+ ResultsToTypeCheck.push_back(i);
}
// If this node has a name associated with it, capture it in VariableMap. If
@@ -444,10 +444,9 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N,
for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
- if (DoTypeCheck) {
- assert(N->getNumTypes() == 1);
- AddMatcher(new CheckTypeMatcher(N->getType(0)));
- }
+ for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i)
+ AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]),
+ ResultsToTypeCheck[i]));
}
/// EmitMatcherCode - Generate the code that matches the predicate of this
@@ -688,9 +687,19 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
continue;
}
+ const TreePatternNode *Child = N->getChild(ChildNo);
+
// Otherwise this is a normal operand or a predicate operand without
// 'execute always'; emit it.
- EmitResultOperand(N->getChild(ChildNo), InstOps);
+ unsigned BeforeAddingNumOps = InstOps.size();
+ EmitResultOperand(Child, InstOps);
+ assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands");
+
+ // If the operand is an instruction and it produced multiple results, just
+ // take the first one.
+ if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction"))
+ InstOps.resize(BeforeAddingNumOps+1);
+
++ChildNo;
}
@@ -712,24 +721,19 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// Determine the result types.
SmallVector<MVT::SimpleValueType, 4> ResultVTs;
- if (N->getNumTypes()) {
- // FIXME2: If the node has multiple results, we should add them. For now,
- // preserve existing behavior?!
- assert(N->getNumTypes() == 1);
- ResultVTs.push_back(N->getType(0));
- }
+ for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i)
+ ResultVTs.push_back(N->getType(i));
// If this is the root instruction of a pattern that has physical registers in
// its result pattern, add output VTs for them. For example, X86 has:
// (set AL, (mul ...))
// This also handles implicit results like:
// (implicit EFLAGS)
- if (isRoot && Pattern.getDstRegs().size() != 0) {
+ if (isRoot && !Pattern.getDstRegs().empty()) {
// If the root came from an implicit def in the instruction handling stuff,
// don't re-add it.
Record *HandledReg = 0;
- if (NumResults == 0 && N->getNumTypes() != 0 &&
- !II.ImplicitDefs.empty())
+ if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
HandledReg = II.ImplicitDefs[0];
for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
@@ -763,6 +767,9 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
bool NodeHasMemRefs =
isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
+ assert((!ResultVTs.empty() || TreeHasOutFlag || NodeHasChain) &&
+ "Node has no result");
+
AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(),
ResultVTs.data(), ResultVTs.size(),
InstOps.data(), InstOps.size(),
@@ -830,33 +837,35 @@ void MatcherGen::EmitResultCode() {
// At this point, we have however many values the result pattern produces.
// However, the input pattern might not need all of these. If there are
- // excess values at the end (such as condition codes etc) just lop them off.
- // This doesn't need to worry about flags or chains, just explicit results.
- //
- // FIXME2: This doesn't work because there is currently no way to get an
- // accurate count of the # results the source pattern sets. This is because
- // of the "parallel" construct in X86 land, which looks like this:
- //
- //def : Pat<(parallel (X86and_flag GR8:$src1, GR8:$src2),
- // (implicit EFLAGS)),
- // (AND8rr GR8:$src1, GR8:$src2)>;
+ // excess values at the end (such as implicit defs of condition codes etc)
+ // just lop them off. This doesn't need to worry about flags or chains, just
+ // explicit results.
//
- // This idiom means to match the two-result node X86and_flag (which is
- // declared as returning a single result, because we can't match multi-result
- // nodes yet). In this case, we would have to know that the input has two
- // results. However, mul8r is modelled exactly the same way, but without
- // implicit defs included. The fix is to support multiple results directly
- // and eliminate 'parallel'.
- //
- // FIXME2: When this is fixed, we should revert the terrible hack in the
- // OPC_EmitNode code in the interpreter.
-#if 0
- const TreePatternNode *Src = Pattern.getSrcPattern();
- unsigned NumSrcResults = Src->getTypeNum(0) != MVT::isVoid ? 1 : 0;
- NumSrcResults += Pattern.getDstRegs().size();
+ unsigned NumSrcResults = Pattern.getSrcPattern()->getNumTypes();
+
+ // If the pattern also has (implicit) results, count them as well.
+ if (!Pattern.getDstRegs().empty()) {
+ // If the root came from an implicit def in the instruction handling stuff,
+ // don't re-add it.
+ Record *HandledReg = 0;
+ const TreePatternNode *DstPat = Pattern.getDstPattern();
+ if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(DstPat->getOperator());
+
+ if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
+ HandledReg = II.ImplicitDefs[0];
+ }
+
+ for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
+ Record *Reg = Pattern.getDstRegs()[i];
+ if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
+ ++NumSrcResults;
+ }
+ }
+
assert(Ops.size() >= NumSrcResults && "Didn't provide enough results");
Ops.resize(NumSrcResults);
-#endif
// If the matched pattern covers nodes which define a flag result, emit a node
// that tells the matcher about them so that it can update their results.
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index 820ab63..c73bdb9 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -48,8 +48,9 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr,
New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
RM->getResultNo());
- if (CheckTypeMatcher *CT= dyn_cast<CheckTypeMatcher>(MC->getNext()))
- if (MC->getChildNo() < 8) // Only have CheckChildType0...7
+ if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 8 && // Only have CheckChildType0...7
+ CT->getResNo() == 0) // CheckChildType checks res #0
New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
if (New) {
@@ -420,10 +421,12 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
CheckTypeMatcher *CTM =
cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
Matcher::CheckType));
- if (CTM == 0 ||
+ if (CTM == 0 ||
// iPTR checks could alias any other case without us knowing, don't
// bother with them.
CTM->getType() == MVT::iPTR ||
+ // SwitchType only works for result #0.
+ CTM->getResNo() != 0 ||
// If the CheckType isn't at the start of the list, see if we can move
// it there.
!CTM->canMoveBefore(NewOptionsToMatch[i])) {
@@ -488,7 +491,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size()));
} else {
// If we factored and ended up with one case, create it now.
- MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first));
+ MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0));
MatcherPtr->setNext(Cases[0].second);
}
return;
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index 23f09a5..ba59e50 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -296,9 +296,11 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) {
if (!InstPatNode) continue;
if (InstPatNode->isLeaf()) continue;
+ // Ignore multiple result nodes for now.
+ if (InstPatNode->getNumTypes() > 1) continue;
+
Record *InstPatOp = InstPatNode->getOperator();
std::string OpcodeName = getOpcodeName(InstPatOp, CGP);
- assert(InstPatNode->getNumTypes() <= 1);
MVT::SimpleValueType RetVT = MVT::isVoid;
if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getType(0);
MVT::SimpleValueType VT = RetVT;
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 8f7550b..9bc5459 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -337,7 +337,7 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
IntInit *ShiftInt, raw_ostream &OS) {
if (Val == 0 || ShiftInt == 0)
throw std::string("Illegal value or shift amount in TargetInfo*!");
- RecordVal *RV = R->getValue(Val->getValue());
+ RecordVal *RV = R->getDottedValue(Val->getValue());
int Shift = ShiftInt->getValue();
if (RV == 0 || RV->getValue() == 0) {
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index c5df9e4..417aca7 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -172,10 +172,11 @@ static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
static void EmitTypeGenerate(raw_ostream &OS,
const std::vector<Record*> &ArgTypes,
unsigned &ArgNo) {
- if (ArgTypes.size() == 1) {
- EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
- return;
- }
+ if (ArgTypes.empty())
+ return EmitTypeForValueType(OS, MVT::isVoid);
+
+ if (ArgTypes.size() == 1)
+ return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
OS << "StructType::get(Context, ";
@@ -251,11 +252,11 @@ namespace {
unsigned RHSSize = RHSVec->size();
unsigned LHSSize = LHSVec->size();
- do {
+ for (; i != LHSSize; ++i) {
if (i == RHSSize) return false; // RHS is shorter than LHS.
if ((*LHSVec)[i] != (*RHSVec)[i])
return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
- } while (++i != LHSSize);
+ }
if (i != RHSSize) return true;
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index b9facb4..55c9989 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -1108,12 +1108,15 @@ RecTy *VarInit::getFieldType(const std::string &FieldName) const {
return 0;
}
-Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const {
+Init *VarInit::getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
if (dynamic_cast<RecordRecTy*>(getType()))
- if (const RecordVal *RV = R.getValue(VarName)) {
- Init *TheInit = RV->getValue();
+ if (const RecordVal *Val = R.getValue(VarName)) {
+ if (RV != Val && (RV || dynamic_cast<UnsetInit*>(Val->getValue())))
+ return 0;
+ Init *TheInit = Val->getValue();
assert(TheInit != this && "Infinite loop detected!");
- if (Init *I = TheInit->getFieldInit(R, FieldName))
+ if (Init *I = TheInit->getFieldInit(R, RV, FieldName))
return I;
else
return 0;
@@ -1174,7 +1177,8 @@ RecTy *DefInit::getFieldType(const std::string &FieldName) const {
return 0;
}
-Init *DefInit::getFieldInit(Record &R, const std::string &FieldName) const {
+Init *DefInit::getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
return Def->getValue(FieldName)->getValue();
}
@@ -1185,7 +1189,7 @@ std::string DefInit::getAsString() const {
Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV,
unsigned Bit) {
- if (Init *BitsVal = Rec->getFieldInit(R, FieldName))
+ if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName))
if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
assert(Bit < BI->getNumBits() && "Bit reference out of range!");
Init *B = BI->getBit(Bit);
@@ -1198,7 +1202,7 @@ Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV,
Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt) {
- if (Init *ListVal = Rec->getFieldInit(R, FieldName))
+ if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName))
if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) {
if (Elt >= LI->getSize()) return 0;
Init *E = LI->getElement(Elt);
@@ -1215,7 +1219,7 @@ Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) {
Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec;
- Init *BitsVal = NewRec->getFieldInit(R, FieldName);
+ Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName);
if (BitsVal) {
Init *BVR = BitsVal->resolveReferences(R, RV);
return BVR->isComplete() ? BVR : this;
@@ -1303,6 +1307,16 @@ void Record::resolveReferencesTo(const RecordVal *RV) {
}
}
+RecordVal *Record::getDottedValue(StringRef Name) {
+ size_t pos = Name.find('.');
+ if (pos == StringRef::npos)
+ return getValue(Name);
+ RecordVal *RV = getValue(Name.substr(0, pos));
+ if (!RV) return 0;
+ DefInit *DI = dynamic_cast<DefInit*>(RV->getValue());
+ if (!DI) return 0;
+ return DI->getDef()->getDottedValue(Name.substr(pos+1));
+}
void Record::dump() const { errs() << *this; }
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index 90096e9..41373c7 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -503,7 +503,8 @@ struct Init {
/// initializer for the specified field. If getFieldType returns non-null
/// this method should return non-null, otherwise it returns null.
///
- virtual Init *getFieldInit(Record &R, const std::string &FieldName) const {
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
return 0;
}
@@ -950,7 +951,8 @@ public:
unsigned Elt);
virtual RecTy *getFieldType(const std::string &FieldName) const;
- virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const;
/// resolveReferences - This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed.
@@ -1035,7 +1037,8 @@ public:
//virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
virtual RecTy *getFieldType(const std::string &FieldName) const;
- virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const;
virtual std::string getAsString() const;
@@ -1259,6 +1262,9 @@ public:
return 0;
}
+ // Like getValue, but allow dotting into members: X.Y
+ RecordVal *getDottedValue(StringRef Name);
+
void addTemplateArg(StringRef Name) {
assert(!isTemplateArg(Name) && "Template arg already defined!");
TemplateArgs.push_back(Name);
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index f20ec00..1326ebc 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -34,7 +34,6 @@
#include "SubtargetEmitter.h"
#include "TGParser.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm
index f67794e..33f471d 100755
--- a/utils/buildit/build_llvm
+++ b/utils/buildit/build_llvm
@@ -203,6 +203,7 @@ fi
make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$TARGETS" \
UNIVERSAL_SDK_PATH=$HOST_SDKROOT \
NO_RUNTIME_LIBS=1 \
+ DISABLE_EDIS=1 \
LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \
LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \
CXXFLAGS="-DLLVM_VERSION_INFO='\" Apple Build #$LLVM_VERSION\"'" \
@@ -227,6 +228,7 @@ cd $DIR/obj-llvm || exit 1
# Install the tree into the destination directory.
make $LOCAL_MAKEFLAGS $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$TARGETS" \
NO_RUNTIME_LIBS=1 \
+ DISABLE_EDIS=1 \
LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \
LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \
OPTIMIZE_OPTION='-O3' VERBOSE=1 install
diff --git a/utils/lit/lit/LitTestCase.py b/utils/lit/lit/LitTestCase.py
new file mode 100644
index 0000000..8951185
--- /dev/null
+++ b/utils/lit/lit/LitTestCase.py
@@ -0,0 +1,30 @@
+import unittest
+import Test
+
+"""
+TestCase adaptor for providing a 'unittest' compatible interface to 'lit' tests.
+"""
+
+class UnresolvedError(RuntimeError):
+ pass
+
+class LitTestCase(unittest.TestCase):
+ def __init__(self, test, lit_config):
+ unittest.TestCase.__init__(self)
+ self._test = test
+ self._lit_config = lit_config
+
+ def id(self):
+ return self._test.getFullName()
+
+ def shortDescription(self):
+ return self._test.getFullName()
+
+ def runTest(self):
+ tr, output = self._test.config.test_format.execute(
+ self._test, self._lit_config)
+
+ if tr is Test.UNRESOLVED:
+ raise UnresolvedError(output)
+ elif tr.isFailure:
+ self.fail(output)
diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py
index 433e39a..7ab9bb6 100644
--- a/utils/lit/lit/TestFormats.py
+++ b/utils/lit/lit/TestFormats.py
@@ -90,8 +90,9 @@ class FileBasedTest(object):
litConfig, localConfig):
source_path = testSuite.getSourcePath(path_in_suite)
for filename in os.listdir(source_path):
- # Ignore dot files.
- if filename.startswith('.'):
+ # Ignore dot files and excluded tests.
+ if (filename.startswith('.') or
+ filename in localConfig.excludes):
continue
filepath = os.path.join(source_path, filename)
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py
index 29adff2..d10e4b0 100644
--- a/utils/lit/lit/TestRunner.py
+++ b/utils/lit/lit/TestRunner.py
@@ -63,6 +63,7 @@ def executeShCmd(cmd, cfg, cwd, results):
procs = []
input = subprocess.PIPE
stderrTempFiles = []
+ opened_files = []
# To avoid deadlock, we use a single stderr stream for piped
# output. This is null until we have seen some output using
# stderr.
@@ -113,8 +114,11 @@ def executeShCmd(cmd, cfg, cwd, results):
else:
r[2] = open(r[0], r[1])
# Workaround a Win32 and/or subprocess bug when appending.
+ #
+ # FIXME: Actually, this is probably an instance of PR6753.
if r[1] == 'a':
r[2].seek(0, 2)
+ opened_files.append(r[2])
result = r[2]
final_redirects.append(result)
@@ -176,7 +180,7 @@ def executeShCmd(cmd, cfg, cwd, results):
else:
err = ''
procData[i] = (out,err)
-
+
# Read stderr out of the temp files.
for i,f in stderrTempFiles:
f.seek(0, 0)
@@ -199,6 +203,10 @@ def executeShCmd(cmd, cfg, cwd, results):
else:
exitCode = res
+ # Explicitly close any redirected files.
+ for f in opened_files:
+ f.close()
+
if cmd.negate:
exitCode = not exitCode
diff --git a/utils/lit/lit/lit.py b/utils/lit/lit/lit.py
index e800754..a29fa42 100755
--- a/utils/lit/lit/lit.py
+++ b/utils/lit/lit/lit.py
@@ -315,6 +315,48 @@ def runTests(numThreads, litConfig, provider, display):
except KeyboardInterrupt:
sys.exit(2)
+def load_test_suite(inputs):
+ import unittest
+
+ # Create the global config object.
+ litConfig = LitConfig.LitConfig(progname = 'lit',
+ path = [],
+ quiet = False,
+ useValgrind = False,
+ valgrindLeakCheck = False,
+ valgrindArgs = [],
+ useTclAsSh = False,
+ noExecute = False,
+ debug = False,
+ isWindows = (platform.system()=='Windows'),
+ params = {})
+
+ # Load the tests from the inputs.
+ tests = []
+ testSuiteCache = {}
+ localConfigCache = {}
+ for input in inputs:
+ prev = len(tests)
+ tests.extend(getTests(input, litConfig,
+ testSuiteCache, localConfigCache)[1])
+ if prev == len(tests):
+ litConfig.warning('input %r contained no tests' % input)
+
+ # If there were any errors during test discovery, exit now.
+ if litConfig.numErrors:
+ print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors
+ sys.exit(2)
+
+ # Return a unittest test suite which just runs the tests in order.
+ def get_test_fn(test):
+ return unittest.FunctionTestCase(
+ lambda: test.config.test_format.execute(
+ test, litConfig),
+ description = test.getFullName())
+
+ from LitTestCase import LitTestCase
+ return unittest.TestSuite([LitTestCase(test, litConfig) for test in tests])
+
def main():
# Bump the GIL check interval, its more important to get any one thread to a
# blocking operation (hopefully exec) than to try and unblock other threads.
OpenPOWER on IntegriCloud