diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index dfb17f3ae42..555a6341c46 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -45,6 +45,87 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
   }
 }
 
+/// getOperandNum - Return the node corresponding to operand #OpNo in tree
+/// N, which has NumResults results.
+TreePatternNode *SDTypeConstraint::getOperandNum(unsigned OpNo,
+                                                 TreePatternNode *N,
+                                                 unsigned NumResults) const {
+  assert(NumResults == 1 && "We only work with single result nodes so far!");
+  
+  if (OpNo < NumResults)
+    return N;  // FIXME: need value #
+  else
+    return N->getChild(OpNo-NumResults);
+}
+
+/// ApplyTypeConstraint - Given a node in a pattern, apply this type
+/// constraint to the nodes operands.  This returns true if it makes a
+/// change, false otherwise.  If a type contradiction is found, throw an
+/// exception.
+bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
+                                           const SDNodeInfo &NodeInfo,
+                                           TreePattern &TP) const {
+  unsigned NumResults = NodeInfo.getNumResults();
+  assert(NumResults == 1 && "We only work with single result nodes so far!");
+  
+  // Check that the number of operands is sane.
+  if (NodeInfo.getNumOperands() >= 0) {
+    if (N->getNumChildren() != (unsigned)NodeInfo.getNumOperands())
+      TP.error(N->getOperator()->getName() + " node requires exactly " +
+               itostr(NodeInfo.getNumOperands()) + " operands!");
+  }
+  
+  TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NumResults);
+  
+  switch (ConstraintType) {
+  default: assert(0 && "Unknown constraint type!");
+  case SDTCisVT:
+    // Operand must be a particular type.
+    return NodeToApply->UpdateNodeType(x.SDTCisVT_Info.VT, TP);
+  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.
+    return false;
+  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.
+    return false;
+  case SDTCisSameAs: {
+    TreePatternNode *OtherNode =
+      getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults);
+    return NodeToApply->UpdateNodeType(OtherNode->getType(), TP) |
+           OtherNode->UpdateNodeType(NodeToApply->getType(), TP);
+  }
+  case SDTCisVTSmallerThanOp: {
+    // The NodeToApply must be a leaf node that is a VT.  OtherOperandNum must
+    // have an integer type that is smaller than the VT.
+    if (!NodeToApply->isLeaf() ||
+        !dynamic_cast<DefInit*>(NodeToApply->getLeafValue()) ||
+        !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()
+               ->isSubClassOf("ValueType"))
+      TP.error(N->getOperator()->getName() + " expects a VT operand!");
+    MVT::ValueType VT =
+     getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
+    if (!MVT::isInteger(VT))
+      TP.error(N->getOperator()->getName() + " VT operand must be integer!");
+    
+    TreePatternNode *OtherNode =
+      getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N,NumResults);
+    if (OtherNode->hasTypeSet() &&
+        (!MVT::isInteger(OtherNode->getType()) ||
+         OtherNode->getType() <= VT))
+      OtherNode->UpdateNodeType(MVT::Other, TP);  // Throw an error.
+    return false;
+  }
+  }  
+  return false;
+}
+
+
 //===----------------------------------------------------------------------===//
 // SDNodeInfo implementation
 //
@@ -77,6 +158,23 @@ TreePatternNode::~TreePatternNode() {
 #endif
 }
 
+/// UpdateNodeType - Set the node type of N to VT if VT contains
+/// information.  If N already contains a conflicting type, then throw an
+/// exception.  This returns true if any information was updated.
+///
+bool TreePatternNode::UpdateNodeType(MVT::ValueType VT, TreePattern &TP) {
+  if (VT == MVT::LAST_VALUETYPE || getType() == VT) return false;
+  if (getType() == MVT::LAST_VALUETYPE) {
+    setType(VT);
+    return true;
+  }
+  
+  TP.error("Type inference contradiction found in node " + 
+           getOperator()->getName() + "!");
+  return true; // unreachable
+}
+
+
 void TreePatternNode::print(std::ostream &OS) const {
   if (isLeaf()) {
     OS << *getLeafValue();
@@ -132,6 +230,8 @@ TreePatternNode *TreePatternNode::clone() const {
   return New;
 }
 
+/// SubstituteFormalArguments - Replace the formal arguments in this tree
+/// with actual values specified by ArgMap.
 void TreePatternNode::
 SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
   if (isLeaf()) return;
@@ -196,6 +296,35 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
   return FragTree;
 }
 
+/// 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;
+  
+  // 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);
+    
+    // Types of operands must match.
+    MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getType(), TP);
+    MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getType(), TP);
+    MadeChange |= UpdateNodeType(MVT::isVoid, TP);
+    return MadeChange;
+  }
+  
+  const SDNodeInfo &NI = TP.getDAGISelEmitter().getSDNodeInfo(getOperator());
+  
+  bool MadeChange = NI.ApplyTypeConstraints(this, TP);
+  for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+    MadeChange |= getChild(i)->ApplyTypeConstraints(TP);
+  return MadeChange;  
+}
+
+
 //===----------------------------------------------------------------------===//
 // TreePattern implementation
 //
@@ -311,9 +440,8 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
       return 0;
     }
     
-    // Apply the type cast...
-    assert(0 && "unimp yet");
-    //New->updateNodeType(getValueType(Operator), TheRecord->getName());
+    // Apply the type cast.
+    New->UpdateNodeType(getValueType(Operator), *this);
     return New;
   }
   
@@ -361,6 +489,23 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
   return new TreePatternNode(Operator, Children);
 }
 
+/// InferAllTypes - Infer/propagate as many types throughout the expression
+/// patterns as possible.  Return true if all types are infered, false
+/// otherwise.  Throw an exception if a type contradiction is found.
+bool TreePattern::InferAllTypes() {
+  bool MadeChange = true;
+  while (MadeChange) {
+    MadeChange = false;
+    for (unsigned i = 0, e = Trees.size(); i != e; ++i)
+      MadeChange |= Trees[i]->ApplyTypeConstraints(*this);
+  }
+  
+  bool HasUnresolvedTypes = false;
+  for (unsigned i = 0, e = Trees.size(); i != e; ++i)
+    HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();
+  return !HasUnresolvedTypes;
+}
+
 void TreePattern::print(std::ostream &OS) const {
   switch (getPatternType()) {
   case TreePattern::PatFrag:     OS << "PatFrag pattern "; break;
@@ -449,9 +594,22 @@ void DAGISelEmitter::ParseAndResolvePatternFragments(std::ostream &OS) {
   // that there are not references to PatFrags left inside of them.
   for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
        E = PatternFragments.end(); I != E; ++I) {
-    I->second->InlinePatternFragments();
+    TreePattern *ThePat = I->second;
+    ThePat->InlinePatternFragments();
+    
+    // Infer as many types as possible.  Don't worry about it if we don't infer
+    // all of them, some may depend on the inputs of the pattern.
+    try {
+      ThePat->InferAllTypes();
+    } catch (...) {
+      // If this pattern fragment is not supported by this target (no types can
+      // satisfy its constraints), just ignore it.  If the bogus pattern is
+      // actually used by instructions, the type consistency error will be
+      // reported there.
+    }
+    
     // If debugging, print out the pattern fragment result.
-    DEBUG(I->second->dump());
+    DEBUG(ThePat->dump());
   }
 }
 
@@ -473,12 +631,21 @@ void DAGISelEmitter::ParseAndResolveInstructions() {
       Trees.push_back((DagInit*)LI->getElement(j));
 
     // Parse the instruction.
-    Instructions.push_back(new TreePattern(TreePattern::Instruction, Instrs[i],
-                                           Trees, *this));
+    TreePattern *I = new TreePattern(TreePattern::Instruction, Instrs[i],
+                                     Trees, *this);
     // Inline pattern fragments into it.
-    Instructions.back()->InlinePatternFragments();
+    I->InlinePatternFragments();
     
-    DEBUG(Instructions.back()->dump());
+    // Infer as many types as possible.  Don't worry about it if we don't infer
+    // all of them, some may depend on the inputs of the pattern.
+    if (!I->InferAllTypes()) {
+      I->dump();
+      I->error("Could not infer all types in pattern!");
+    }
+
+    DEBUG(I->dump());
+    
+    Instructions.push_back(I);
   }
 }
 
diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h
index e2fade99171..20d24fb9752 100644
--- a/utils/TableGen/DAGISelEmitter.h
+++ b/utils/TableGen/DAGISelEmitter.h
@@ -21,7 +21,9 @@ namespace llvm {
   class Record;
   class Init;
   class DagInit;
+  class SDNodeInfo;
   class TreePattern;
+  class TreePatternNode;
   class DAGISelEmitter;
   
   /// SDTypeConstraint - This is a discriminated union of constraints,
@@ -45,6 +47,18 @@ namespace llvm {
         unsigned OtherOperandNum;
       } SDTCisVTSmallerThanOp_Info;
     } x;
+
+    /// ApplyTypeConstraint - Given a node in a pattern, apply this type
+    /// constraint to the nodes operands.  This returns true if it makes a
+    /// change, false otherwise.  If a type contradiction is found, throw an
+    /// exception.
+    bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo,
+                             TreePattern &TP) const;
+    
+    /// getOperandNum - Return the node corresponding to operand #OpNo in tree
+    /// N, which has NumResults results.
+    TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N,
+                                   unsigned NumResults) const;
   };
   
   /// SDNodeInfo - One of these records is created for each SDNode instance in
@@ -54,20 +68,32 @@ namespace llvm {
     Record *Def;
     std::string EnumName;
     std::string SDClassName;
-    int NumResults, NumOperands;
+    unsigned NumResults;
+    int NumOperands;
     std::vector<SDTypeConstraint> TypeConstraints;
   public:
     SDNodeInfo(Record *R);  // Parse the specified record.
     
-    int getNumResults() const { return NumResults; }
+    unsigned getNumResults() const { return NumResults; }
     int getNumOperands() const { return NumOperands; }
     Record *getRecord() const { return Def; }
     const std::string &getEnumName() const { return EnumName; }
     const std::string &getSDClassName() const { return SDClassName; }
     
-    const std::vector<SDTypeConstraint> &getTypeConstraints() {
+    const std::vector<SDTypeConstraint> &getTypeConstraints() const {
       return TypeConstraints;
     }
+
+    /// ApplyTypeConstraints - Given a node in a pattern, apply the type
+    /// constraints for this node to the operands of the node.  This returns
+    /// true if it makes a change, false otherwise.  If a type contradiction is
+    /// found, throw an exception.
+    bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const {
+      bool MadeChange = false;
+      for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
+        MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
+      return MadeChange;
+    }
   };
 
   /// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped
@@ -106,6 +132,7 @@ namespace llvm {
     void setName(const std::string &N) { Name = N; }
     
     bool isLeaf() const { return Val != 0; }
+    bool hasTypeSet() const { return Ty != MVT::LAST_VALUETYPE; }
     MVT::ValueType getType() const { return Ty; }
     void setType(MVT::ValueType VT) { Ty = VT; }
     
@@ -130,6 +157,8 @@ namespace llvm {
     ///
     TreePatternNode *clone() const;
     
+    /// SubstituteFormalArguments - Replace the formal arguments in this tree
+    /// with actual values specified by ArgMap.
     void SubstituteFormalArguments(std::map<std::string,
                                             TreePatternNode*> &ArgMap);
 
@@ -137,7 +166,27 @@ namespace llvm {
     /// fragments, inline them into place, giving us a pattern without any
     /// PatFrag references.
     TreePatternNode *InlinePatternFragments(TreePattern &TP);
-        
+    
+    /// 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 ApplyTypeConstraints(TreePattern &TP);
+    
+    /// UpdateNodeType - Set the node type of N to VT if VT contains
+    /// information.  If N already contains a conflicting type, then throw an
+    /// exception.  This returns true if any information was updated.
+    ///
+    bool UpdateNodeType(MVT::ValueType VT, TreePattern &TP);
+    
+    /// ContainsUnresolvedType - Return true if this tree contains any
+    /// unresolved types.
+    bool ContainsUnresolvedType() const {
+      if (Ty == MVT::LAST_VALUETYPE) return true;
+      for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+        if (getChild(i)->ContainsUnresolvedType()) return true;
+      return false;
+    }
   };
   
   
@@ -206,6 +255,11 @@ namespace llvm {
         Trees[i] = Trees[i]->InlinePatternFragments(*this);
     }
     
+    /// InferAllTypes - Infer/propagate as many types throughout the expression
+    /// patterns as possible.  Return true if all types are infered, false
+    /// otherwise.  Throw an exception if a type contradiction is found.
+    bool InferAllTypes();
+    
     /// error - Throw an exception, prefixing it with information about this
     /// pattern.
     void error(const std::string &Msg) const;