aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-09-28 19:27:25 +0000
committerChris Lattner <sabre@nondot.org>2005-09-28 19:27:25 +0000
commite97603f1bd569c8f51e2e132a25d050ab71012db (patch)
treeb5c5b9c43687d1017ff9904778bfec7908d3f389
parent645992f595193a651f291c661502ed3df0841ca0 (diff)
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative operators. Defining ORI like this, for example: def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2), "ori $dst, $src1, $src2", [(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>; results in: tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp50
-rw-r--r--utils/TableGen/DAGISelEmitter.h5
2 files changed, 52 insertions, 3 deletions
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index dde7f6770d..bac99ebbc2 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -372,6 +372,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP) {
}
}
+/// canPatternMatch - If it is impossible for this pattern to match on this
+/// target, fill in Reason and return false. Otherwise, return true. This is
+/// used as a santity check for .td files (to prevent people from writing stuff
+/// that can never possibly work), and to prevent the pattern permuter from
+/// generating stuff that is useless.
+bool TreePatternNode::canPatternMatch(std::string &Reason, DAGISelEmitter &ISE) {
+ if (isLeaf()) return true;
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (!getChild(i)->canPatternMatch(Reason, ISE))
+ return false;
+
+ // If this node is a commutative operator, check that the LHS isn't an
+ // immediate.
+ const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(getOperator());
+ if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+ // Scan all of the operands of the node and make sure that only the last one
+ // is a constant node.
+ for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i)
+ if (!getChild(i)->isLeaf() &&
+ getChild(i)->getOperator()->getName() == "imm") {
+ Reason = "Immediate value must be on the RHS of commutative operators!";
+ return false;
+ }
+ }
+
+ return true;
+}
//===----------------------------------------------------------------------===//
// TreePattern implementation
@@ -962,6 +990,11 @@ void DAGISelEmitter::ParseInstructions() {
continue; // Not a set of a single value (not handled so far)
TreePatternNode *SrcPattern = Pattern->getChild(1)->clone();
+
+ std::string Reason;
+ if (!SrcPattern->canPatternMatch(Reason, *this))
+ I->error("Instruction can never match: " + Reason);
+
TreePatternNode *DstPattern = II->second.getResultPattern();
PatternsToMatch.push_back(std::make_pair(SrcPattern, DstPattern));
}
@@ -999,6 +1032,11 @@ void DAGISelEmitter::ParsePatterns() {
if (Result->getNumTrees() != 1)
Result->error("Cannot handle instructions producing instructions "
"with temporaries yet!");
+
+ std::string Reason;
+ if (!Pattern->getOnlyTree()->canPatternMatch(Reason, *this))
+ Pattern->error("Pattern can never match: " + Reason);
+
PatternsToMatch.push_back(std::make_pair(Pattern->getOnlyTree(),
Result->getOnlyTree()));
}
@@ -1011,6 +1049,12 @@ void DAGISelEmitter::ParsePatterns() {
});
}
+// GenerateVariants - Generate variants. For example, commutative patterns can
+// match multiple ways. Add them to PatternsToMatch as well.
+void DAGISelEmitter::GenerateVariants() {
+
+}
+
/// 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.
@@ -1331,13 +1375,13 @@ void DAGISelEmitter::run(std::ostream &OS) {
ParseInstructions();
ParsePatterns();
- // FIXME: Generate variants. For example, commutative patterns can match
+ // Generate variants. For example, commutative patterns can match
// multiple ways. Add them to PatternsToMatch as well.
+ GenerateVariants();
// At this point, we have full information about the 'Patterns' we need to
// parse, both implicitly from instructions as well as from explicit pattern
- // definitions.
-
+ // definitions. Emit the resultant instruction selector.
EmitInstructionSelector(OS);
for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h
index 48f941d859..d169acfecc 100644
--- a/utils/TableGen/DAGISelEmitter.h
+++ b/utils/TableGen/DAGISelEmitter.h
@@ -204,6 +204,10 @@ namespace llvm {
if (getChild(i)->ContainsUnresolvedType()) return true;
return false;
}
+
+ /// canPatternMatch - Return false if it is impossible for this pattern to
+ /// match on this target.
+ bool canPatternMatch(std::string &Reason, DAGISelEmitter &ISE);
};
@@ -369,6 +373,7 @@ private:
void ParsePatternFragments(std::ostream &OS);
void ParseInstructions();
void ParsePatterns();
+ void GenerateVariants();
void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
std::map<std::string,
TreePatternNode*> &InstInputs,