Parse intrinsics correctly and perform type propagation.  This doesn't currently
emit the code to select intrinsics, but that is next :)


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27082 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 4aa6f7f..8dd9eba 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -691,6 +691,25 @@
       MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
     }
     return MadeChange;
+  } else if (getOperator()->isSubClassOf("Intrinsic")) {
+    const CodeGenIntrinsic &Int = 
+      TP.getDAGISelEmitter().getIntrinsic(getOperator());
+    // FIXME: get type information! 
+    bool MadeChange = false;
+
+    // Apply the result type to the node.
+    MadeChange = UpdateNodeType(Int.ArgVTs[0], TP);
+    
+    if (getNumChildren() != Int.ArgVTs.size()-1)
+      TP.error("Intrinsic '" + getOperator()->getName() + " expects " +
+               utostr(Int.ArgVTs.size()-1) + " operands, not " +
+               utostr(getNumChildren()) + " operands!");
+    for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+      MVT::ValueType OpVT = Int.ArgVTs[i+1];
+      MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP);
+      MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+    }
+    return MadeChange;
   } else {
     assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
     
@@ -723,6 +742,13 @@
     if (!getChild(i)->canPatternMatch(Reason, ISE))
       return false;
 
+  // If this is an intrinsic, handle cases that would make it not match.  For
+  // example, if an operand is required to be an immediate.
+  if (getOperator()->isSubClassOf("Intrinsic")) {
+    // TODO:
+    return true;
+  }
+  
   // If this node is a commutative operator, check that the LHS isn't an
   // immediate.
   const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(getOperator());
@@ -811,6 +837,7 @@
   if (!Operator->isSubClassOf("PatFrag") && !Operator->isSubClassOf("SDNode") &&
       !Operator->isSubClassOf("Instruction") && 
       !Operator->isSubClassOf("SDNodeXForm") &&
+      !Operator->isSubClassOf("Intrinsic") &&
       Operator->getName() != "set")
     error("Unrecognized node '" + Operator->getName() + "'!");
   
@@ -1592,10 +1619,13 @@
   }
 
   // Look up interesting info about the node.
-  const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(N->getOperator());
+  const SDNodeInfo *NodeInfo = 0;
+  
+  if (!N->getOperator()->isSubClassOf("Intrinsic"))
+    NodeInfo = &ISE.getSDNodeInfo(N->getOperator());
 
   // If this node is associative, reassociate.
-  if (NodeInfo.hasProperty(SDNodeInfo::SDNPAssociative)) {
+  if (NodeInfo && NodeInfo->hasProperty(SDNodeInfo::SDNPAssociative)) {
     // Reassociate by pulling together all of the linked operators 
     std::vector<TreePatternNode*> MaximalChildren;
     GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
@@ -1656,7 +1686,7 @@
   CombineChildVariants(N, ChildVariants, OutVariants, ISE);
 
   // If this node is commutative, consider the commuted order.
-  if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+  if (NodeInfo && NodeInfo->hasProperty(SDNodeInfo::SDNPCommutative)) {
     assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!");
     // Consider the commuted order.
     CombineChildVariants(N, ChildVariants[1], ChildVariants[0],
@@ -2955,6 +2985,9 @@
   for (std::map<Record*, std::vector<PatternToMatch*>,
        CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
        E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
+    if (PBOI->first->isSubClassOf("Intrinsic"))
+      continue;   // Skip intrinsics here.
+    
     const std::string &OpName = PBOI->first->getName();
     OS << "void Select_" << OpName << "(SDOperand &Result, SDOperand N) {\n";
     
@@ -3201,6 +3234,9 @@
   for (std::map<Record*, std::vector<PatternToMatch*>,
                 CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
        E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
+    if (PBOI->first->isSubClassOf("Intrinsic"))
+      continue;
+    
     const SDNodeInfo &OpcodeInfo = getSDNodeInfo(PBOI->first);
     OS << "  case " << OpcodeInfo.getEnumName() << ": "
        << std::string(std::max(0, int(24-OpcodeInfo.getEnumName().size())), ' ')
@@ -3363,6 +3399,7 @@
   OS << "  return ResNode;\n";
   OS << "}\n";
   
+  Intrinsics = LoadIntrinsics(Records);
   ParseNodeInfo();
   ParseNodeTransforms(OS);
   ParseComplexPatterns();
diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h
index 35606f7..10b997d 100644
--- a/utils/TableGen/DAGISelEmitter.h
+++ b/utils/TableGen/DAGISelEmitter.h
@@ -16,6 +16,7 @@
 
 #include "TableGenBackend.h"
 #include "CodeGenTarget.h"
+#include "CodeGenIntrinsics.h"
 #include <set>
 
 namespace llvm {
@@ -412,6 +413,7 @@
 private:
   RecordKeeper &Records;
   CodeGenTarget Target;
+  std::vector<CodeGenIntrinsic> Intrinsics;
   
   std::map<Record*, SDNodeInfo> SDNodes;
   std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
@@ -448,6 +450,13 @@
     return ComplexPatterns.find(R)->second;
   }
   
+  const CodeGenIntrinsic &getIntrinsic(Record *R) const {
+    for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
+      if (Intrinsics[i].TheDef == R) return Intrinsics[i];
+    assert(0 && "Unknown intrinsic!");
+    abort();
+  }
+  
   TreePattern *getPatternFragment(Record *R) const {
     assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
     return PatternFragments.find(R)->second;