From e97603f1bd569c8f51e2e132a25d050ab71012db Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 28 Sep 2005 19:27:25 +0000 Subject: [PATCH] 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 --- utils/TableGen/DAGISelEmitter.cpp | 50 +++++++++++++++++++++++++++++-- utils/TableGen/DAGISelEmitter.h | 5 ++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index dde7f6770df..bac99ebbc2a 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::iterator I = PatternFragments.begin(), diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 48f941d8593..d169acfecc1 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 &InstInputs, -- 2.34.1