[llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h

Chris Lattner lattner at cs.uiuc.edu
Thu Sep 29 12:28:22 PDT 2005



Changes in directory llvm/utils/TableGen:

DAGISelEmitter.cpp updated: 1.49 -> 1.50
DAGISelEmitter.h updated: 1.28 -> 1.29
---
Log message:

Teach tblgen to build permutations of instructions, so that the target author
doesn't have to specify them manually.  It currently handles associativity,
e.g. knowing that (X*Y)+Z  also matches  X+(Y*Z)  and will be extended in
the future.

It is smart enough to not introduce duplicate patterns or patterns that can
never match.



---
Diffs of the changes:  (+193 -6)

 DAGISelEmitter.cpp |  193 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 DAGISelEmitter.h   |    6 +
 2 files changed, 193 insertions(+), 6 deletions(-)


Index: llvm/utils/TableGen/DAGISelEmitter.cpp
diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.49 llvm/utils/TableGen/DAGISelEmitter.cpp:1.50
--- llvm/utils/TableGen/DAGISelEmitter.cpp:1.49	Wed Sep 28 15:58:06 2005
+++ llvm/utils/TableGen/DAGISelEmitter.cpp	Thu Sep 29 14:28:10 2005
@@ -232,6 +232,32 @@
   print(std::cerr);
 }
 
+/// isIsomorphicTo - Return true if this node is recursively isomorphic to
+/// the specified node.  For this comparison, all of the state of the node
+/// is considered, except for the assigned name.  Nodes with differing names
+/// 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() ||
+      getPredicateFn() != N->getPredicateFn() ||
+      getTransformFn() != N->getTransformFn())
+    return false;
+
+  if (isLeaf()) {
+    if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue()))
+      if (DefInit *NDI = dynamic_cast<DefInit*>(N->getLeafValue()))
+        return DI->getDef() == NDI->getDef();
+    return getLeafValue() == N->getLeafValue();
+  }
+  
+  if (N->getOperator() != getOperator() ||
+      N->getNumChildren() != getNumChildren()) return false;
+  for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+    if (!getChild(i)->isIsomorphicTo(N->getChild(i)))
+      return false;
+  return true;
+}
+
 /// clone - Make a copy of this tree and all of its children.
 ///
 TreePatternNode *TreePatternNode::clone() const {
@@ -1042,18 +1068,165 @@
     PatternsToMatch.push_back(std::make_pair(Pattern->getOnlyTree(),
                                              Result->getOnlyTree()));
   }
+}
 
-  DEBUG(std::cerr << "\n\nPARSED PATTERNS TO MATCH:\n\n";
-        for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
-          std::cerr << "PATTERN: ";  PatternsToMatch[i].first->dump();
-          std::cerr << "\nRESULT:  ";PatternsToMatch[i].second->dump();
-          std::cerr << "\n";
-        });
+/// CombineChildVariants - Given a bunch of permutations of each child of the
+/// 'operator' node, put them together in all possible ways.
+static void CombineChildVariants(TreePatternNode *Orig, 
+                  std::vector<std::vector<TreePatternNode*> > &ChildVariants,
+                                 std::vector<TreePatternNode*> &OutVariants,
+                                 DAGISelEmitter &ISE) {
+  // The end result is an all-pairs construction of the resultant pattern.
+  std::vector<unsigned> Idxs;
+  Idxs.resize(ChildVariants.size());
+  bool NotDone = true;
+  while (NotDone) {
+    // Create the variant and add it to the output list.
+    std::vector<TreePatternNode*> NewChildren;
+    for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
+      NewChildren.push_back(ChildVariants[i][Idxs[i]]);
+    TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren);
+    
+    // Copy over properties.
+    R->setName(Orig->getName());
+    R->setPredicateFn(Orig->getPredicateFn());
+    R->setTransformFn(Orig->getTransformFn());
+    R->setType(Orig->getType());
+    
+    // If this pattern cannot every match, do not include it as a variant.
+    std::string ErrString;
+    if (!R->canPatternMatch(ErrString, ISE)) {
+      delete R;
+    } else {
+      bool AlreadyExists = false;
+      
+      // Scan to see if this pattern has already been emitted.  We can get
+      // duplication due to things like commuting:
+      //   (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
+      // which are the same pattern.  Ignore the dups.
+      for (unsigned i = 0, e = OutVariants.size(); i != e; ++i)
+        if (R->isIsomorphicTo(OutVariants[i])) {
+          AlreadyExists = true;
+          break;
+        }
+      
+      if (AlreadyExists)
+        delete R;
+      else
+        OutVariants.push_back(R);
+    }
+    
+    // Increment indices to the next permutation.
+    NotDone = false;
+    // Look for something we can increment without causing a wrap-around.
+    for (unsigned IdxsIdx = 0; IdxsIdx != Idxs.size(); ++IdxsIdx) {
+      if (++Idxs[IdxsIdx] < ChildVariants[IdxsIdx].size()) {
+        NotDone = true;   // Found something to increment.
+        break;
+      }
+      Idxs[IdxsIdx] = 0;
+    }
+  }
 }
 
+/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of
+/// the (potentially recursive) pattern by using algebraic laws.
+///
+static void GenerateVariantsOf(TreePatternNode *N,
+                               std::vector<TreePatternNode*> &OutVariants,
+                               DAGISelEmitter &ISE) {
+  // We cannot permute leaves.
+  if (N->isLeaf()) {
+    OutVariants.push_back(N);
+    return;
+  }
+
+  // Look up interesting info about the node.
+  const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(N->getOperator());
+
+  // If this node is associative, reassociate.
+  // TODO!
+  
+  // Compute permutations of all children.
+  std::vector<std::vector<TreePatternNode*> > ChildVariants;
+  ChildVariants.resize(N->getNumChildren());
+  for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+    GenerateVariantsOf(N->getChild(i), ChildVariants[i], ISE);
+
+  // Build all permutations based on how the children were formed.
+  CombineChildVariants(N, ChildVariants, OutVariants, ISE);
+
+  // If this node is commutative, consider the commuted order.
+  if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+    assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!");
+    std::vector<std::vector<TreePatternNode*> > CommChildVariants;
+    CommChildVariants.push_back(ChildVariants[1]);
+    CommChildVariants.push_back(ChildVariants[0]);
+
+    // Consider all commuted orders.
+    CombineChildVariants(N, CommChildVariants, OutVariants, ISE);
+  }
+}
+
+
 // GenerateVariants - Generate variants.  For example, commutative patterns can
 // match multiple ways.  Add them to PatternsToMatch as well.
 void DAGISelEmitter::GenerateVariants() {
+  
+  DEBUG(std::cerr << "Generating instruction variants.\n");
+  
+  // Loop over all of the patterns we've collected, checking to see if we can
+  // generate variants of the instruction, through the exploitation of
+  // identities.  This permits the target to provide agressive matching without
+  // the .td file having to contain tons of variants of instructions.
+  //
+  // Note that this loop adds new patterns to the PatternsToMatch list, but we
+  // intentionally do not reconsider these.  Any variants of added patterns have
+  // already been added.
+  //
+  for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+    std::vector<TreePatternNode*> Variants;
+    GenerateVariantsOf(PatternsToMatch[i].first, Variants, *this);
+
+    assert(!Variants.empty() && "Must create at least original variant!");
+    assert(Variants[0]->isIsomorphicTo(PatternsToMatch[i].first) &&
+           "Input pattern should be first variant!");
+    Variants.erase(Variants.begin());  // Remove the original pattern.
+
+    if (Variants.empty())  // No variants for this pattern.
+      continue;
+
+    DEBUG(std::cerr << "FOUND VARIANTS OF: ";
+          PatternsToMatch[i].first->dump();
+          std::cerr << "\n");
+
+    for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
+      TreePatternNode *Variant = Variants[v];
+
+      DEBUG(std::cerr << "  VAR#" << v <<  ": ";
+            Variant->dump();
+            std::cerr << "\n");
+      
+      // Scan to see if an instruction or explicit pattern already matches this.
+      bool AlreadyExists = false;
+      for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
+        // Check to see if this variant already exists.
+        if (Variant->isIsomorphicTo(PatternsToMatch[p].first)) {
+          DEBUG(std::cerr << "  *** ALREADY EXISTS, ignoring variant.\n");
+          AlreadyExists = true;
+          break;
+        }
+      }
+      // If we already have it, ignore the variant.
+      if (AlreadyExists) continue;
+
+      // Otherwise, add it to the list of patterns we have.
+      PatternsToMatch.push_back(std::make_pair(Variant, 
+                                               PatternsToMatch[i].second));
+    }
+
+    DEBUG(std::cerr << "\n");
+  }
 }
 
 
@@ -1381,6 +1554,14 @@
   // multiple ways.  Add them to PatternsToMatch as well.
   GenerateVariants();
 
+  
+  DEBUG(std::cerr << "\n\nALL PATTERNS TO MATCH:\n\n";
+        for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+          std::cerr << "PATTERN: ";  PatternsToMatch[i].first->dump();
+          std::cerr << "\nRESULT:  ";PatternsToMatch[i].second->dump();
+          std::cerr << "\n";
+        });
+  
   // 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.  Emit the resultant instruction selector.


Index: llvm/utils/TableGen/DAGISelEmitter.h
diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.28 llvm/utils/TableGen/DAGISelEmitter.h:1.29
--- llvm/utils/TableGen/DAGISelEmitter.h:1.28	Wed Sep 28 15:58:06 2005
+++ llvm/utils/TableGen/DAGISelEmitter.h	Thu Sep 29 14:28:10 2005
@@ -174,6 +174,12 @@
     ///
     TreePatternNode *clone() const;
     
+    /// isIsomorphicTo - Return true if this node is recursively isomorphic to
+    /// the specified node.  For this comparison, all of the state of the node
+    /// is considered, except for the assigned name.  Nodes with differing names
+    /// that are otherwise identical are considered isomorphic.
+    bool isIsomorphicTo(const TreePatternNode *N) const;
+    
     /// SubstituteFormalArguments - Replace the formal arguments in this tree
     /// with actual values specified by ArgMap.
     void SubstituteFormalArguments(std::map<std::string,






More information about the llvm-commits mailing list