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

Chris Lattner lattner at cs.uiuc.edu
Thu Oct 13 21:11:25 PDT 2005



Changes in directory llvm/utils/TableGen:

DAGISelEmitter.cpp updated: 1.51 -> 1.52
DAGISelEmitter.h updated: 1.29 -> 1.30
---
Log message:

Implement a couple of new (important) features.

1. If an operation has to be int or fp and the target only supports one
   int or fp type, relize that the op has to have that type.
2. If a target has operations on multiple types, do not emit matching code
   for patterns involving those operators, since we do not emit the code to
   check for them yet.  This prevents PPC from generating FP ops currently.

Also move some code around into more logical places.



---
Diffs of the changes:  (+128 -50)

 DAGISelEmitter.cpp |  173 ++++++++++++++++++++++++++++++++++++++---------------
 DAGISelEmitter.h   |    5 -
 2 files changed, 128 insertions(+), 50 deletions(-)


Index: llvm/utils/TableGen/DAGISelEmitter.cpp
diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.51 llvm/utils/TableGen/DAGISelEmitter.cpp:1.52
--- llvm/utils/TableGen/DAGISelEmitter.cpp:1.51	Thu Sep 29 17:36:54 2005
+++ llvm/utils/TableGen/DAGISelEmitter.cpp	Thu Oct 13 23:11:13 2005
@@ -75,6 +75,8 @@
       TP.error(N->getOperator()->getName() + " node requires exactly " +
                itostr(NodeInfo.getNumOperands()) + " operands!");
   }
+
+  const CodeGenTarget &CGT = TP.getDAGISelEmitter().getTargetInfo();
   
   TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NumResults);
   
@@ -83,18 +85,51 @@
   case SDTCisVT:
     // Operand must be a particular type.
     return NodeToApply->UpdateNodeType(x.SDTCisVT_Info.VT, TP);
-  case SDTCisInt:
+  case SDTCisInt: {
     if (NodeToApply->hasTypeSet() && !MVT::isInteger(NodeToApply->getType()))
       NodeToApply->UpdateNodeType(MVT::i1, TP);  // throw an error.
 
-    // FIXME: can tell from the target if there is only one Int type supported.
+    // If there is only one integer type supported, this must be it.
+    const std::vector<MVT::ValueType> &VTs = CGT.getLegalValueTypes();
+    MVT::ValueType VT = MVT::LAST_VALUETYPE;
+    for (unsigned i = 0, e = VTs.size(); i != e; ++i)
+      if (MVT::isInteger(VTs[i])) {
+        if (VT == MVT::LAST_VALUETYPE)
+          VT = VTs[i];  // First integer type we've found.
+        else {
+          VT = MVT::LAST_VALUETYPE;
+          break;
+        }
+      }
+
+    // If we found exactly one supported integer type, apply it.
+    if (VT != MVT::LAST_VALUETYPE)
+      return NodeToApply->UpdateNodeType(VT, TP);
     return false;
-  case SDTCisFP:
+  }
+  case SDTCisFP: {
     if (NodeToApply->hasTypeSet() &&
         !MVT::isFloatingPoint(NodeToApply->getType()))
       NodeToApply->UpdateNodeType(MVT::f32, TP);  // throw an error.
-    // FIXME: can tell from the target if there is only one FP type supported.
+
+    // If there is only one FP type supported, this must be it.
+    const std::vector<MVT::ValueType> &VTs = CGT.getLegalValueTypes();
+    MVT::ValueType VT = MVT::LAST_VALUETYPE;
+    for (unsigned i = 0, e = VTs.size(); i != e; ++i)
+      if (MVT::isFloatingPoint(VTs[i])) {
+        if (VT == MVT::LAST_VALUETYPE)
+          VT = VTs[i];  // First integer type we've found.
+        else {
+          VT = MVT::LAST_VALUETYPE;
+          break;
+        }
+      }
+        
+    // If we found exactly one supported FP type, apply it.
+    if (VT != MVT::LAST_VALUETYPE)
+      return NodeToApply->UpdateNodeType(VT, TP);
     return false;
+  }
   case SDTCisSameAs: {
     TreePatternNode *OtherNode =
       getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults);
@@ -344,18 +379,51 @@
   return FragTree;
 }
 
+/// getIntrinsicType - Check to see if the specified record has an intrinsic
+/// type which should be applied to it.  This infer the type of register
+/// references from the register file information, for example.
+///
+static MVT::ValueType getIntrinsicType(Record *R, bool NotRegisters, TreePattern &TP) {
+  // Check to see if this is a register or a register class...
+  if (R->isSubClassOf("RegisterClass")) {
+    if (NotRegisters) return MVT::LAST_VALUETYPE;
+    return getValueType(R->getValueAsDef("RegType"));
+  } else if (R->isSubClassOf("PatFrag")) {
+    // Pattern fragment types will be resolved when they are inlined.
+    return MVT::LAST_VALUETYPE;
+  } else if (R->isSubClassOf("Register")) {
+    assert(0 && "Explicit registers not handled here yet!\n");
+    return MVT::LAST_VALUETYPE;
+  } else if (R->isSubClassOf("ValueType")) {
+    // Using a VTSDNode.
+    return MVT::Other;
+  } else if (R->getName() == "node") {
+    // Placeholder.
+    return MVT::LAST_VALUETYPE;
+  }
+  
+  TP.error("Unknown node flavor used in pattern: " + R->getName());
+  return MVT::Other;
+}
+
 /// ApplyTypeConstraints - Apply all of the type constraints relevent to
 /// this node and its children in the tree.  This returns true if it makes a
 /// change, false otherwise.  If a type contradiction is found, throw an
 /// exception.
-bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP) {
-  if (isLeaf()) return false;
+bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
+  if (isLeaf()) {
+    if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue()))
+      // If it's a regclass or something else known, include the type.
+      return UpdateNodeType(getIntrinsicType(DI->getDef(), NotRegisters, TP),
+                            TP);
+    return false;
+  }
   
   // special handling for set, which isn't really an SDNode.
   if (getOperator()->getName() == "set") {
     assert (getNumChildren() == 2 && "Only handle 2 operand set's for now!");
-    bool MadeChange = getChild(0)->ApplyTypeConstraints(TP);
-    MadeChange |= getChild(1)->ApplyTypeConstraints(TP);
+    bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
+    MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
     
     // Types of operands must match.
     MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getType(), TP);
@@ -367,7 +435,7 @@
     
     bool MadeChange = NI.ApplyTypeConstraints(this, TP);
     for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
-      MadeChange |= getChild(i)->ApplyTypeConstraints(TP);
+      MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
     return MadeChange;  
   } else if (getOperator()->isSubClassOf("Instruction")) {
     const DAGInstruction &Inst =
@@ -383,7 +451,7 @@
                utostr(getNumChildren()) + " operands!");
     for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
       MadeChange |= getChild(i)->UpdateNodeType(Inst.getOperandType(i), TP);
-      MadeChange |= getChild(i)->ApplyTypeConstraints(TP);
+      MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
     }
     return MadeChange;
   } else {
@@ -456,32 +524,6 @@
   throw "In " + TheRecord->getName() + ": " + Msg;
 }
 
-/// getIntrinsicType - Check to see if the specified record has an intrinsic
-/// type which should be applied to it.  This infer the type of register
-/// references from the register file information, for example.
-///
-MVT::ValueType TreePattern::getIntrinsicType(Record *R) const {
-  // Check to see if this is a register or a register class...
-  if (R->isSubClassOf("RegisterClass"))
-    return getValueType(R->getValueAsDef("RegType"));
-  else if (R->isSubClassOf("PatFrag")) {
-    // Pattern fragment types will be resolved when they are inlined.
-    return MVT::LAST_VALUETYPE;
-  } else if (R->isSubClassOf("Register")) {
-    assert(0 && "Explicit registers not handled here yet!\n");
-    return MVT::LAST_VALUETYPE;
-  } else if (R->isSubClassOf("ValueType")) {
-    // Using a VTSDNode.
-    return MVT::Other;
-  } else if (R->getName() == "node") {
-    // Placeholder.
-    return MVT::LAST_VALUETYPE;
-  }
-  
-  error("Unknown node flavor used in pattern: " + R->getName());
-  return MVT::Other;
-}
-
 TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
   Record *Operator = Dag->getNodeType();
   
@@ -489,7 +531,7 @@
     // If the operator is a ValueType, then this must be "type cast" of a leaf
     // node.
     if (Dag->getNumArgs() != 1)
-      error("Type cast only valid for a leaf node!");
+      error("Type cast only takes one operand!");
     
     Init *Arg = Dag->getArg(0);
     TreePatternNode *New;
@@ -504,8 +546,6 @@
       }   
       
       New = new TreePatternNode(DI);
-      // If it's a regclass or something else known, set the type.
-      New->setType(getIntrinsicType(DI->getDef()));
     } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
       New = ParseTreePattern(DI);
     } else {
@@ -546,9 +586,6 @@
         Node->setName(Dag->getArgName(i));
         Children.push_back(Node);
         
-        // If it's a regclass or something else known, set the type.
-        Node->setType(getIntrinsicType(R));
-        
         // Input argument?
         if (R->getName() == "node") {
           if (Dag->getArgName(i).empty())
@@ -573,7 +610,7 @@
   while (MadeChange) {
     MadeChange = false;
     for (unsigned i = 0, e = Trees.size(); i != e; ++i)
-      MadeChange |= Trees[i]->ApplyTypeConstraints(*this);
+      MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false);
   }
   
   bool HasUnresolvedTypes = false;
@@ -1517,6 +1554,14 @@
   }
 }
 
+/// RemoveAllTypes - A quick recursive walk over a pattern which removes all
+/// type information from it.
+static void RemoveAllTypes(TreePatternNode *N) {
+  N->setType(MVT::LAST_VALUETYPE);
+  if (!N->isLeaf())
+    for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+      RemoveAllTypes(N->getChild(i));
+}
 
 /// EmitCodeForPattern - Given a pattern to match, emit code to the specified
 /// stream to match the pattern, and generate the code for the match if it
@@ -1537,12 +1582,44 @@
   std::map<std::string,std::string> VariableMap;
   EmitMatchForPattern(Pattern.first, "N", VariableMap, PatternNo, OS);
   
-  unsigned TmpNo = 0;
-  unsigned Res = CodeGenPatternResult(Pattern.second, TmpNo, VariableMap, OS);
+  // TP - Get *SOME* tree pattern, we don't care which.
+  TreePattern &TP = *PatternFragments.begin()->second;
+  
+  // At this point, we know that we structurally match the pattern, but the
+  // types of the nodes may not match.  Figure out the fewest number of type 
+  // comparisons we need to emit.  For example, if there is only one integer
+  // type supported by a target, there should be no type comparisons at all for
+  // integer patterns!
+  //
+  // To figure out the fewest number of type checks needed, clone the pattern,
+  // remove the types, then perform type inference on the pattern as a whole.
+  // If there are unresolved types, emit an explicit check for those types,
+  // apply the type to the tree, then rerun type inference.  Iterate until all
+  // types are resolved.
+  //
+  TreePatternNode *Pat = Pattern.first->clone();
+  RemoveAllTypes(Pat);
+  bool MadeChange = true;
+  try {
+    while (MadeChange)
+      MadeChange = Pat->ApplyTypeConstraints(TP,true/*Ignore reg constraints*/);
+  } catch (...) {
+    assert(0 && "Error: could not find consistent types for something we"
+           " already decided was ok!");
+    abort();
+  }
+
+  if (!Pat->ContainsUnresolvedType()) {
+    unsigned TmpNo = 0;
+    unsigned Res = CodeGenPatternResult(Pattern.second, TmpNo, VariableMap, OS);
+  
+    // Add the result to the map if it has multiple uses.
+    OS << "      if (!N.Val->hasOneUse()) CodeGenMap[N] = Tmp" << Res << ";\n";
+    OS << "      return Tmp" << Res << ";\n";
+  }
+  
+  delete Pat;
   
-  // Add the result to the map if it has multiple uses.
-  OS << "      if (!N.Val->hasOneUse()) CodeGenMap[N] = Tmp" << Res << ";\n";
-  OS << "      return Tmp" << Res << ";\n";
   OS << "    }\n  P" << PatternNo << "Fail:\n";
 }
 


Index: llvm/utils/TableGen/DAGISelEmitter.h
diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.29 llvm/utils/TableGen/DAGISelEmitter.h:1.30
--- llvm/utils/TableGen/DAGISelEmitter.h:1.29	Thu Sep 29 14:28:10 2005
+++ llvm/utils/TableGen/DAGISelEmitter.h	Thu Oct 13 23:11:13 2005
@@ -194,7 +194,7 @@
     /// this node and its children in the tree.  This returns true if it makes a
     /// change, false otherwise.  If a type contradiction is found, throw an
     /// exception.
-    bool ApplyTypeConstraints(TreePattern &TP);
+    bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters);
     
     /// UpdateNodeType - Set the node type of N to VT if VT contains
     /// information.  If N already contains a conflicting type, then throw an
@@ -290,7 +290,6 @@
     void dump() const;
     
   private:
-    MVT::ValueType getIntrinsicType(Record *R) const;
     TreePatternNode *ParseTreePattern(DagInit *DI);
   };
 
@@ -353,6 +352,8 @@
   // run - Output the isel, returning true on failure.
   void run(std::ostream &OS);
   
+  const CodeGenTarget &getTargetInfo() const { return Target; }
+  
   const SDNodeInfo &getSDNodeInfo(Record *R) const {
     assert(SDNodes.count(R) && "Unknown node!");
     return SDNodes.find(R)->second;






More information about the llvm-commits mailing list