Emit an error if instructions or patterns are defined but can never match.
authorChris Lattner <sabre@nondot.org>
Wed, 28 Sep 2005 19:27:25 +0000 (19:27 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 28 Sep 2005 19:27:25 +0000 (19:27 +0000)
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
utils/TableGen/DAGISelEmitter.h

index dde7f6770dfdda3a931e9edf09c1b580dc5a0b79..bac99ebbc2ae3ced7a0c902d2ad572782b68adf9 100644 (file)
@@ -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(),
index 48f941d859346700c481aa16e1c287b17b057c5b..d169acfecc1e49b157e0c70a14f0a6ffa5a95946 100644 (file)
@@ -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,