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

Evan Cheng evan.cheng at apple.com
Wed Dec 7 18:00:48 PST 2005



Changes in directory llvm/utils/TableGen:

CodeGenTarget.cpp updated: 1.47 -> 1.48
CodeGenTarget.h updated: 1.21 -> 1.22
DAGISelEmitter.cpp updated: 1.85 -> 1.86
DAGISelEmitter.h updated: 1.39 -> 1.40
---
Log message:

Added support for ComplexPattern. These are patterns that require C++ pattern
matching code that is not currently auto-generated by tblgen, e.g. X86
addressing mode. Selection routines for complex patterns can return multiple operands, e.g. X86 addressing mode returns 4.


---
Diffs of the changes:  (+171 -47)

 CodeGenTarget.cpp  |    9 ++
 CodeGenTarget.h    |   17 +++++
 DAGISelEmitter.cpp |  165 ++++++++++++++++++++++++++++++++++++++++-------------
 DAGISelEmitter.h   |   27 +++++---
 4 files changed, 171 insertions(+), 47 deletions(-)


Index: llvm/utils/TableGen/CodeGenTarget.cpp
diff -u llvm/utils/TableGen/CodeGenTarget.cpp:1.47 llvm/utils/TableGen/CodeGenTarget.cpp:1.48
--- llvm/utils/TableGen/CodeGenTarget.cpp:1.47	Sun Dec  4 02:18:16 2005
+++ llvm/utils/TableGen/CodeGenTarget.cpp	Wed Dec  7 20:00:36 2005
@@ -330,3 +330,12 @@
   throw "Instruction '" + TheDef->getName() +
         "' does not have an operand named '$" + Name + "'!";
 }
+
+//===----------------------------------------------------------------------===//
+// ComplexPattern implementation
+//
+ComplexPattern::ComplexPattern(Record *R) {
+  NumOperands   = R->getValueAsInt("NumOperands");
+  SelectFunc    = R->getValueAsString("SelectFunc");
+  MatchingNodes = R->getValueAsListOfDefs("MatchingNodes");
+}


Index: llvm/utils/TableGen/CodeGenTarget.h
diff -u llvm/utils/TableGen/CodeGenTarget.h:1.21 llvm/utils/TableGen/CodeGenTarget.h:1.22
--- llvm/utils/TableGen/CodeGenTarget.h:1.21	Sun Dec  4 20:35:08 2005
+++ llvm/utils/TableGen/CodeGenTarget.h	Wed Dec  7 20:00:36 2005
@@ -157,6 +157,23 @@
   bool isLittleEndianEncoding() const;
 };
 
+/// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern
+/// tablegen class in TargetSelectionDAG.td
+class ComplexPattern {
+  unsigned NumOperands;
+  std::string SelectFunc;
+  std::vector<Record*> MatchingNodes;
+public:
+  ComplexPattern() : NumOperands(0) {};
+  ComplexPattern(Record *R);
+
+  unsigned getNumOperands() const { return NumOperands; }
+  const std::string &getSelectFunc() const { return SelectFunc; }
+  const std::vector<Record*> &getMatchingNodes() const {
+    return MatchingNodes;
+  }
+};
+
 } // End llvm namespace
 
 #endif


Index: llvm/utils/TableGen/DAGISelEmitter.cpp
diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.85 llvm/utils/TableGen/DAGISelEmitter.cpp:1.86
--- llvm/utils/TableGen/DAGISelEmitter.cpp:1.85	Mon Dec  5 17:08:55 2005
+++ llvm/utils/TableGen/DAGISelEmitter.cpp	Wed Dec  7 20:00:36 2005
@@ -477,6 +477,9 @@
   } else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
     // Using a VTSDNode or CondCodeSDNode.
     return MVT::Other;
+  } else if (R->isSubClassOf("ComplexPattern")) {
+    const CodeGenTarget &T = TP.getDAGISelEmitter().getTargetInfo();
+    return T.getPointerType();
   } else if (R->getName() == "node") {
     // Placeholder.
     return MVT::isUnknown;
@@ -609,7 +612,7 @@
   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());
@@ -833,6 +836,13 @@
   }
 }
 
+void DAGISelEmitter::ParseComplexPatterns() {
+  std::vector<Record*> AMs = Records.getAllDerivedDefinitions("ComplexPattern");
+  while (!AMs.empty()) {
+    ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back()));
+    AMs.pop_back();
+  }
+}
 
 
 /// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
@@ -1204,9 +1214,10 @@
       if (InVal->isLeaf() &&
           dynamic_cast<DefInit*>(InVal->getLeafValue())) {
         Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
-        if (CGI.OperandList[i].Rec != InRec)
+        if (CGI.OperandList[i].Rec != InRec &&
+            !InRec->isSubClassOf("ComplexPattern"))
           I->error("Operand $" + OpName +
-                 "'s register class disagrees between the operand and pattern");
+                   "'s register class disagrees between the operand and pattern");
       }
       Operands.push_back(CGI.OperandList[i].Rec);
       
@@ -1586,22 +1597,59 @@
 }
 
 
+// NodeIsComplexPattern - return true if N is a leaf node and a subclass of
+// ComplexPattern.
+static bool NodeIsComplexPattern(TreePatternNode *N)
+{
+  return (N->isLeaf() &&
+          dynamic_cast<DefInit*>(N->getLeafValue()) &&
+          static_cast<DefInit*>(N->getLeafValue())->getDef()->
+          isSubClassOf("ComplexPattern"));
+}
+
+// NodeGetComplexPattern - return the pointer to the ComplexPattern if N
+// is a leaf node and a subclass of ComplexPattern, else it returns NULL.
+static const ComplexPattern *NodeGetComplexPattern(TreePatternNode *N,
+                                                   DAGISelEmitter &ISE)
+{
+  if (N->isLeaf() &&
+      dynamic_cast<DefInit*>(N->getLeafValue()) &&
+      static_cast<DefInit*>(N->getLeafValue())->getDef()->
+      isSubClassOf("ComplexPattern")) {
+    return &ISE.getComplexPattern(static_cast<DefInit*>(N->getLeafValue())
+                                  ->getDef());
+  }
+  return NULL;
+}
+
 /// 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) {
+static unsigned getPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) {
   assert(isExtIntegerVT(P->getExtType()) || 
          isExtFloatingPointVT(P->getExtType()) ||
          P->getExtType() == MVT::isVoid && "Not a valid pattern node to size!");
   unsigned Size = 1;  // The node itself.
-  
+
+  // 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 = NodeGetComplexPattern(P, ISE);
+  if (AM)
+    Size += AM->getNumOperands();
+    
   // 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->getExtType() != MVT::Other)
-      Size += getPatternSize(Child);
-    else if (Child->isLeaf() && dynamic_cast<IntInit*>(Child->getLeafValue())) {
-      ++Size;  // Matches a ConstantSDNode.
+      Size += getPatternSize(Child, ISE);
+    else if (Child->isLeaf()) {
+      if (dynamic_cast<IntInit*>(Child->getLeafValue())) 
+        ++Size;  // Matches a ConstantSDNode.
+      else if (NodeIsComplexPattern(Child))
+        Size += getPatternSize(Child, ISE);
     }
   }
   
@@ -1624,10 +1672,13 @@
 // In particular, we want to match maximal patterns first and lowest cost within
 // a particular complexity first.
 struct PatternSortingPredicate {
+  PatternSortingPredicate(DAGISelEmitter &ise) : ISE(ise) {};
+  DAGISelEmitter &ISE;
+
   bool operator()(DAGISelEmitter::PatternToMatch *LHS,
                   DAGISelEmitter::PatternToMatch *RHS) {
-    unsigned LHSSize = getPatternSize(LHS->first);
-    unsigned RHSSize = getPatternSize(RHS->first);
+    unsigned LHSSize = getPatternSize(LHS->first, ISE);
+    unsigned RHSSize = getPatternSize(RHS->first, ISE);
     if (LHSSize > RHSSize) return true;   // LHS -> bigger -> less cost
     if (LHSSize < RHSSize) return false;
     
@@ -1649,9 +1700,10 @@
          << ")->getSignExtended() != " << II->getValue() << ")\n"
          << "        goto P" << PatternNo << "Fail;\n";
       return;
+    } else if (!NodeIsComplexPattern(N)) {
+      assert(0 && "Cannot match this as a leaf value!");
+      abort();
     }
-    assert(0 && "Cannot match this as a leaf value!");
-    abort();
   }
   
   // If this node has a name associated with it, capture it in VarMap.  If
@@ -1710,6 +1762,8 @@
         if (LeafRec->isSubClassOf("RegisterClass") ||
             LeafRec->isSubClassOf("Register")) {
           // Handle register references.  Nothing to do here.
+        } else if (LeafRec->isSubClassOf("ComplexPattern")) {
+          // Handle complex pattern. Nothing to do here.
         } else if (LeafRec->isSubClassOf("ValueType")) {
           // Make sure this is the specified value type.
           OS << "      if (cast<VTSDNode>(" << RootName << OpNo << ")->getVT() != "
@@ -1819,9 +1873,10 @@
 
 /// CodeGenPatternResult - Emit the action for a pattern.  Now that it has
 /// matched, we actually have to build a DAG!
-unsigned DAGISelEmitter::
+std::pair<unsigned, unsigned> DAGISelEmitter::
 CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
                      std::map<std::string,std::string> &VariableMap, 
+                     unsigned PatternNo,
                      std::ostream &OS, bool &HasChain, bool InFlag,
                      bool isRoot) {
   // This is something selected from the pattern we matched.
@@ -1832,10 +1887,12 @@
            "Variable referenced but not defined and not caught earlier!");
     if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
       // Already selected this operand, just return the tmpval.
-      return atoi(Val.c_str()+3);
+      return std::make_pair(1, atoi(Val.c_str()+3));
     }
-    
+
+    const ComplexPattern *CP;
     unsigned ResNo = Ctr++;
+    unsigned NumRes = 1;
     if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
       switch (N->getType()) {
       default: assert(0 && "Unknown type for constant node!");
@@ -1850,13 +1907,27 @@
          << ResNo << "C, MVT::" << getEnumName(N->getType()) << ");\n";
     } else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
       OS << "      SDOperand Tmp" << ResNo << " = " << Val << ";\n";
+    } else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, *this))) {
+      std::string Fn = CP->getSelectFunc();
+      NumRes = CP->getNumOperands();
+      OS << "      SDOperand ";
+      for (unsigned i = 0; i < NumRes; i++) {
+        if (i != 0) OS << ", ";
+        OS << "Tmp" << i + ResNo;
+      }
+      OS << ";\n";
+      OS << "      if (!" << Fn << "(" << Val;
+      for (unsigned i = 0; i < NumRes; i++)
+        OS << " , Tmp" << i + ResNo;
+      OS << ")) goto P" << PatternNo << "Fail;\n";
+      Ctr = ResNo + NumRes;
     } else {
       OS << "      SDOperand Tmp" << ResNo << " = Select(" << Val << ");\n";
     }
     // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
     // value if used multiple times by this pattern result.
     Val = "Tmp"+utostr(ResNo);
-    return ResNo;
+    return std::make_pair(NumRes, ResNo);
   }
   
   if (N->isLeaf()) {
@@ -1868,7 +1939,7 @@
            << getQualifiedName(DI->getDef()) << ", MVT::"
            << getEnumName(N->getType())
            << ");\n";
-        return ResNo;
+        return std::make_pair(1, ResNo);
       }
     } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
       unsigned ResNo = Ctr++;
@@ -1876,21 +1947,26 @@
          << II->getValue() << ", MVT::"
         << getEnumName(N->getType())
         << ");\n";
-      return ResNo;
+      return std::make_pair(1, ResNo);
     }
     
     N->dump();
     assert(0 && "Unknown leaf type!");
-    return ~0U;
+    return std::make_pair(1, ~0U);
   }
 
   Record *Op = N->getOperator();
   if (Op->isSubClassOf("Instruction")) {
     // Emit all of the operands.
     std::vector<unsigned> Ops;
-    for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
-      Ops.push_back(CodeGenPatternResult(N->getChild(i), Ctr,
-                                         VariableMap, OS, HasChain, InFlag));
+    for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+      TreePatternNode *Child = N->getChild(i);
+      std::pair<unsigned, unsigned> NOPair = 
+        CodeGenPatternResult(Child, Ctr,
+                             VariableMap, PatternNo, OS, HasChain, InFlag);
+      for (unsigned j = 0; j < NOPair.first; j++)
+        Ops.push_back(NOPair.second + j);
+    }
 
     CodeGenInstruction &II = Target.getInstruction(Op->getName());
     bool HasCtrlDep = II.hasCtrlDep;
@@ -1934,12 +2010,12 @@
         OS << "      CodeGenMap[N.getValue(0)] = Result;\n";
         OS << "      CodeGenMap[N.getValue(" << NumResults
            << ")] = Result.getValue(" << NumResults << ");\n";
-        OS << "      Chain = CodeGenMap[N].getValue(" << NumResults << ");\n";
+        OS << "      Chain = Result.getValue(" << NumResults << ");\n";
       }
       if (NumResults == 0)
         OS << "      return Chain;\n";
       else
-        OS << "      return (N.ResNo) ? Chain : CodeGenMap[N];\n";
+        OS << "      return (N.ResNo) ? Chain : Result.getValue(0);\n";
     } else {
       // If this instruction is the root, and if there is only one use of it,
       // use SelectNodeTo instead of getTargetNode to avoid an allocation.
@@ -1963,11 +2039,12 @@
       OS << ");\n";
       OS << "      }\n";
     }
-    return ResNo;
+    return std::make_pair(1, ResNo);
   } else if (Op->isSubClassOf("SDNodeXForm")) {
     assert(N->getNumChildren() == 1 && "node xform should have one child!");
     unsigned OpVal = CodeGenPatternResult(N->getChild(0), Ctr,
-                                          VariableMap, OS, HasChain, InFlag);
+                                          VariableMap, PatternNo, OS, HasChain, InFlag)
+      .second;
     
     unsigned ResNo = Ctr++;
     OS << "      SDOperand Tmp" << ResNo << " = Transform_" << Op->getName()
@@ -1976,11 +2053,11 @@
       OS << "      CodeGenMap[N] = Tmp" << ResNo << ";\n";
       OS << "      return Tmp" << ResNo << ";\n";
     }
-    return ResNo;
+    return std::make_pair(1, ResNo);
   } else {
     N->dump();
     assert(0 && "Unknown node in result pattern!");
-    return ~0U;
+    return std::make_pair(1, ~0U);
   }
 }
 
@@ -2005,10 +2082,13 @@
   if (!Pat->hasTypeSet()) {
     // Move a type over from 'other' to 'pat'.
     Pat->setType(Other->getType());
-    OS << "      if (" << Prefix << ".getValueType() != MVT::"
+    OS << "      if (" << Prefix << ".Val->getValueType(0) != MVT::"
        << getName(Pat->getType()) << ") goto P" << PatternNo << "Fail;\n";
     return true;
   } else if (Pat->isLeaf()) {
+    if (NodeIsComplexPattern(Pat))
+      OS << "      if (" << Prefix << ".Val->getValueType(0) != MVT::"
+         << getName(Pat->getType()) << ") goto P" << PatternNo << "Fail;\n";
     return false;
   }
   
@@ -2038,7 +2118,7 @@
   OS << "\n      // Emits: ";
   Pattern.second->print(OS);
   OS << "\n";
-  OS << "      // Pattern complexity = " << getPatternSize(Pattern.first)
+  OS << "      // Pattern complexity = " << getPatternSize(Pattern.first, *this)
      << "  cost = " << getResultPatternCost(Pattern.second) << "\n";
 
   // Emit the matcher, capturing named arguments in VariableMap.
@@ -2088,7 +2168,7 @@
   
   unsigned TmpNo = 0;
   CodeGenPatternResult(Pattern.second,
-                       TmpNo, VariableMap, OS, HasChain, InFlag, true /*the root*/);
+                       TmpNo, VariableMap, PatternNo, OS, HasChain, InFlag, true /*the root*/);
   delete Pat;
   
   OS << "    }\n  P" << PatternNo << "Fail:\n";
@@ -2166,23 +2246,31 @@
   // Group the patterns by their top-level opcodes.
   std::map<Record*, std::vector<PatternToMatch*>,
            CompareByRecordName> PatternsByOpcode;
-  for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i)
-    if (!PatternsToMatch[i].first->isLeaf()) {
-      PatternsByOpcode[PatternsToMatch[i].first->getOperator()]
-         .push_back(&PatternsToMatch[i]);
+  for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+    TreePatternNode *Node = PatternsToMatch[i].first;
+    if (!Node->isLeaf()) {
+      PatternsByOpcode[Node->getOperator()].push_back(&PatternsToMatch[i]);
     } else {
+      const ComplexPattern *CP;
       if (IntInit *II = 
-             dynamic_cast<IntInit*>(PatternsToMatch[i].first->getLeafValue())) {
+             dynamic_cast<IntInit*>(Node->getLeafValue())) {
         PatternsByOpcode[getSDNodeNamed("imm")].push_back(&PatternsToMatch[i]);
+      } else if ((CP = NodeGetComplexPattern(Node, *this))) {
+        std::vector<Record*> OpNodes = CP->getMatchingNodes();
+        for (unsigned j = 0, e = OpNodes.size(); j != e; j++) {
+          PatternsByOpcode[OpNodes[j]].insert(PatternsByOpcode[OpNodes[j]].begin(),
+                                              &PatternsToMatch[i]);
+        }
       } else {
         std::cerr << "Unrecognized opcode '";
-        PatternsToMatch[i].first->dump();
+        Node->dump();
         std::cerr << "' on tree pattern '";
         std::cerr << PatternsToMatch[i].second->getOperator()->getName();
         std::cerr << "'!\n";
         exit(1);
       }
     }
+  }
   
   // Loop over all of the case statements.
   for (std::map<Record*, std::vector<PatternToMatch*>,
@@ -2197,7 +2285,7 @@
     // 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());
+                     PatternSortingPredicate(*this));
     
     for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
       EmitCodeForPattern(*Patterns[i], OS);
@@ -2227,6 +2315,7 @@
   
   ParseNodeInfo();
   ParseNodeTransforms(OS);
+  ParseComplexPatterns();
   ParsePatternFragments(OS);
   ParseInstructions();
   ParsePatterns();


Index: llvm/utils/TableGen/DAGISelEmitter.h
diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.39 llvm/utils/TableGen/DAGISelEmitter.h:1.40
--- llvm/utils/TableGen/DAGISelEmitter.h:1.39	Sun Dec  4 02:18:16 2005
+++ llvm/utils/TableGen/DAGISelEmitter.h	Wed Dec  7 20:00:36 2005
@@ -26,6 +26,7 @@
   class TreePattern;
   class TreePatternNode;
   class DAGISelEmitter;
+  class ComplexPattern;
   
   /// MVT::DAGISelGenValueType - These are some extended forms of MVT::ValueType
   /// that we use as lattice values during type inferrence.
@@ -365,6 +366,7 @@
 
   std::map<Record*, SDNodeInfo> SDNodes;
   std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
+  std::map<Record*, ComplexPattern> ComplexPatterns;
   std::map<Record*, TreePattern*> PatternFragments;
   std::map<Record*, DAGInstruction> Instructions;
   
@@ -387,15 +389,20 @@
     return SDNodes.find(R)->second;
   }
 
-  TreePattern *getPatternFragment(Record *R) const {
-    assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
-    return PatternFragments.find(R)->second;
-  }
-  
   const std::pair<Record*, std::string> &getSDNodeTransform(Record *R) const {
     assert(SDNodeXForms.count(R) && "Invalid transform!");
     return SDNodeXForms.find(R)->second;
   }
+
+  const ComplexPattern &getComplexPattern(Record *R) const {
+    assert(ComplexPatterns.count(R) && "Unknown addressing mode!");
+    return ComplexPatterns.find(R)->second;
+  }
+  
+  TreePattern *getPatternFragment(Record *R) const {
+    assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
+    return PatternFragments.find(R)->second;
+  }
   
   const DAGInstruction &getInstruction(Record *R) const {
     assert(Instructions.count(R) && "Unknown instruction!");
@@ -405,6 +412,7 @@
 private:
   void ParseNodeInfo();
   void ParseNodeTransforms(std::ostream &OS);
+  void ParseComplexPatterns();
   void ParsePatternFragments(std::ostream &OS);
   void ParseInstructions();
   void ParsePatterns();
@@ -420,10 +428,11 @@
                                std::ostream &OS, bool &HasChain);
   void EmitCopyToRegsForPattern(TreePatternNode *N, const std::string &RootName,
                                 std::ostream &OS, bool &HasChain, bool &InFlag);
-  unsigned CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
-                                std::map<std::string,std::string> &VariableMap, 
-                                std::ostream &OS, bool &HasChain, bool InFlag,
-                                bool isRoot = false);
+  std::pair<unsigned, unsigned>
+  CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
+                       std::map<std::string,std::string> &VariableMap, 
+                       unsigned PatternNo, std::ostream &OS, bool &HasChain,
+                       bool InFlag, bool isRoot = false);
   void EmitCodeForPattern(PatternToMatch &Pattern, std::ostream &OS);
   void EmitInstructionSelector(std::ostream &OS);
 };






More information about the llvm-commits mailing list