Improve and simplify EnforceSmallerThan for vector types.
[oota-llvm.git] / utils / TableGen / CodeGenDAGPatterns.cpp
index 20bf29eb8598593a160bcf42fadbdd1044f9a294..147f6c9d29572d3d9c7129380650b1c1e0b86742 100644 (file)
@@ -389,52 +389,6 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
   else if (!Other.hasScalarTypes())
     MadeChange |= EnforceVector(TP);
 
-  // For vectors we need to ensure that smaller size doesn't produce larger
-  // vector and vice versa.
-  if (isConcrete() && isVector(getConcrete())) {
-    MVT IVT = getConcrete();
-    unsigned Size = IVT.getSizeInBits();
-
-    // Only keep types that have at least as many bits.
-    TypeSet InputSet(Other);
-
-    for (unsigned i = 0; i != Other.TypeVec.size(); ++i) {
-      assert(isVector(Other.TypeVec[i]) && "EnforceVector didn't work");
-      if (MVT(Other.TypeVec[i]).getSizeInBits() < Size) {
-        Other.TypeVec.erase(Other.TypeVec.begin()+i--);
-        MadeChange = true;
-      }
-    }
-
-    if (Other.TypeVec.empty()) {  // FIXME: Really want an SMLoc here!
-      TP.error("Type inference contradiction found, forcing '" +
-               InputSet.getName() + "' to have at least as many bits as " +
-               getName() + "'");
-      return false;
-    }
-  } else if (Other.isConcrete() && isVector(Other.getConcrete())) {
-    MVT IVT = Other.getConcrete();
-    unsigned Size = IVT.getSizeInBits();
-
-    // Only keep types with the same or fewer total bits
-    TypeSet InputSet(*this);
-
-    for (unsigned i = 0; i != TypeVec.size(); ++i) {
-      assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
-      if (MVT(TypeVec[i]).getSizeInBits() > Size) {
-        TypeVec.erase(TypeVec.begin()+i--);
-        MadeChange = true;
-      }
-    }
-
-    if (TypeVec.empty()) {  // FIXME: Really want an SMLoc here!
-      TP.error("Type inference contradiction found, forcing '" +
-               InputSet.getName() + "' to have the same or fewer bits than " +
-               Other.getName() + "'");
-      return false;
-    }
-  }
-
   // This code does not currently handle nodes which have multiple types,
   // where some types are integer, and some are fp.  Assert that this is not
   // the case.
@@ -445,12 +399,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
   if (TP.hasError())
     return false;
 
-  // Okay, find the smallest scalar type from the other set and remove
-  // anything the same or smaller from the current set.
+  // Okay, find the smallest type from current set and remove anything the
+  // same or smaller from the other set. We need to ensure that the scalar
+  // type size is smaller than the scalar size of the smallest type. For
+  // vectors, we also need to make sure that the total size is no larger than
+  // the size of the smallest type.
   TypeSet InputSet(Other);
-  MVT::SimpleValueType Smallest = TypeVec[0];
+  MVT Smallest = TypeVec[0];
   for (unsigned i = 0; i != Other.TypeVec.size(); ++i) {
-    if (Other.TypeVec[i] <= Smallest) {
+    MVT OtherVT = Other.TypeVec[i];
+    // Don't compare vector and non-vector types.
+    if (OtherVT.isVector() != Smallest.isVector())
+      continue;
+    // The getSizeInBits() check here is only needed for vectors, but is
+    // a subset of the scalar check for scalars so no need to qualify.
+    if (OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() ||
+        OtherVT.getSizeInBits() < Smallest.getSizeInBits()) {
       Other.TypeVec.erase(Other.TypeVec.begin()+i--);
       MadeChange = true;
     }
@@ -462,12 +426,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
     return false;
   }
 
-  // Okay, find the largest scalar type from the other set and remove
-  // anything the same or larger from the current set.
+  // Okay, find the largest type from the other set and remove anything the
+  // same or smaller from the current set. We need to ensure that the scalar
+  // type size is larger than the scalar size of the largest type. For
+  // vectors, we also need to make sure that the total size is no smaller than
+  // the size of the largest type.
   InputSet = TypeSet(*this);
-  MVT::SimpleValueType Largest = Other.TypeVec[Other.TypeVec.size()-1];
+  MVT Largest = Other.TypeVec[Other.TypeVec.size()-1];
   for (unsigned i = 0; i != TypeVec.size(); ++i) {
-    if (TypeVec[i] >= Largest) {
+    MVT OtherVT = TypeVec[i];
+    // Don't compare vector and non-vector types.
+    if (OtherVT.isVector() != Largest.isVector())
+      continue;
+    // The getSizeInBits() check here is only needed for vectors, but is
+    // a subset of the scalar check for scalars so no need to qualify.
+    if (OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
+         OtherVT.getSizeInBits() > Largest.getSizeInBits()) {
       TypeVec.erase(TypeVec.begin()+i--);
       MadeChange = true;
     }
@@ -482,6 +456,34 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
   return MadeChange;
 }
 
+/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+/// whose element is specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
+                                           TreePattern &TP) {
+  bool MadeChange = false;
+
+  MadeChange |= EnforceVector(TP);
+
+  TypeSet InputSet(*this);
+
+  // Filter out all the types which don't have the right element type.
+  for (unsigned i = 0; i != TypeVec.size(); ++i) {
+    assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+    if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) {
+      TypeVec.erase(TypeVec.begin()+i--);
+      MadeChange = true;
+    }
+  }
+
+  if (TypeVec.empty()) {  // FIXME: Really want an SMLoc here!
+    TP.error("Type inference contradiction found, forcing '" +
+             InputSet.getName() + "' to have a vector element");
+    return false;
+  }
+
+  return MadeChange;
+}
+
 /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
 /// whose element is specified by VTOperand.
 bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
@@ -609,6 +611,64 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
   return MadeChange;
 }
 
+/// EnforceVectorSameNumElts - 'this' is now constrainted to
+/// be a vector with same num elements as VTOperand.
+bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
+                                             TreePattern &TP) {
+  if (TP.hasError())
+    return false;
+
+  // "This" must be a vector and "VTOperand" must be a vector.
+  bool MadeChange = false;
+  MadeChange |= EnforceVector(TP);
+  MadeChange |= VTOperand.EnforceVector(TP);
+
+  // If we know one of the vector types, it forces the other type to agree.
+  if (isConcrete()) {
+    MVT IVT = getConcrete();
+    unsigned NumElems = IVT.getVectorNumElements();
+
+    // Only keep types that have same elements as VTOperand.
+    TypeSet InputSet(VTOperand);
+
+    for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) {
+      assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work");
+      if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() != NumElems) {
+        VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--);
+        MadeChange = true;
+      }
+    }
+    if (VTOperand.TypeVec.empty()) {  // FIXME: Really want an SMLoc here!
+      TP.error("Type inference contradiction found, forcing '" +
+               InputSet.getName() + "' to have same number elements as '" +
+               getName() + "'");
+      return false;
+    }
+  } else if (VTOperand.isConcrete()) {
+    MVT IVT = VTOperand.getConcrete();
+    unsigned NumElems = IVT.getVectorNumElements();
+
+    // Only keep types that have same elements as 'this'.
+    TypeSet InputSet(*this);
+
+    for (unsigned i = 0; i != TypeVec.size(); ++i) {
+      assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+      if (MVT(TypeVec[i]).getVectorNumElements() != NumElems) {
+        TypeVec.erase(TypeVec.begin()+i--);
+        MadeChange = true;
+      }
+    }
+    if (TypeVec.empty()) {  // FIXME: Really want an SMLoc here!
+      TP.error("Type inference contradiction found, forcing '" +
+               InputSet.getName() + "' to have same number elements than '" +
+               VTOperand.getName() + "'");
+      return false;
+    }
+  }
+
+  return MadeChange;
+}
+
 //===----------------------------------------------------------------------===//
 // Helpers for working with extended types.
 
@@ -839,6 +899,19 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
     ConstraintType = SDTCisSubVecOfVec;
     x.SDTCisSubVecOfVec_Info.OtherOperandNum =
       R->getValueAsInt("OtherOpNum");
+  } else if (R->isSubClassOf("SDTCVecEltisVT")) {
+    ConstraintType = SDTCVecEltisVT;
+    x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
+    if (MVT(x.SDTCVecEltisVT_Info.VT).isVector())
+      PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT");
+    if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() &&
+        !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint())
+      PrintFatalError(R->getLoc(), "Must use integer or floating point type "
+                                   "as SDTCVecEltisVT");
+  } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) {
+    ConstraintType = SDTCisSameNumEltsAs;
+    x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
+      R->getValueAsInt("OtherOperandNum");
   } else {
     errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
     exit(1);
@@ -901,8 +974,8 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
     unsigned OResNo = 0;
     TreePatternNode *OtherNode =
       getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
-    return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)|
-           OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP);
+    return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)|
+           OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP);
   }
   case SDTCisVTSmallerThanOp: {
     // The NodeToApply must be a leaf node that is a VT.  OtherOperandNum must
@@ -956,6 +1029,18 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
     return BigVecOperand->getExtType(VResNo).
       EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP);
   }
+  case SDTCVecEltisVT: {
+    return NodeToApply->getExtType(ResNo).
+      EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP);
+  }
+  case SDTCisSameNumEltsAs: {
+    unsigned OResNo = 0;
+    TreePatternNode *OtherNode =
+      getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum,
+                    N, NodeInfo, OResNo);
+    return OtherNode->getExtType(OResNo).
+      EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP);
+  }
   }
   llvm_unreachable("Invalid ConstraintType!");
 }
@@ -2811,159 +2896,159 @@ static bool checkOperandClass(CGIOperandList::OperandInfo &OI,
 const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
     CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) {
 
-    assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");
-
-    // Parse the instruction.
-    TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this);
-    // Inline pattern fragments into it.
-    I->InlinePatternFragments();
-
-    // Infer as many types as possible.  If we cannot infer all of them, we can
-    // never do anything with this instruction pattern: report it to the user.
-    if (!I->InferAllTypes())
-      I->error("Could not infer all types in pattern!");
-
-    // InstInputs - Keep track of all of the inputs of the instruction, along
-    // with the record they are declared as.
-    std::map<std::string, TreePatternNode*> InstInputs;
-
-    // InstResults - Keep track of all the virtual registers that are 'set'
-    // in the instruction, including what reg class they are.
-    std::map<std::string, TreePatternNode*> InstResults;
-
-    std::vector<Record*> InstImpResults;
-
-    // Verify that the top-level forms in the instruction are of void type, and
-    // fill in the InstResults map.
-    for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
-      TreePatternNode *Pat = I->getTree(j);
-      if (Pat->getNumTypes() != 0)
-        I->error("Top-level forms in instruction pattern should have"
-                 " void types");
-
-      // Find inputs and outputs, and verify the structure of the uses/defs.
-      FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
-                                  InstImpResults);
+  assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");
+
+  // Parse the instruction.
+  TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this);
+  // Inline pattern fragments into it.
+  I->InlinePatternFragments();
+
+  // Infer as many types as possible.  If we cannot infer all of them, we can
+  // never do anything with this instruction pattern: report it to the user.
+  if (!I->InferAllTypes())
+    I->error("Could not infer all types in pattern!");
+
+  // InstInputs - Keep track of all of the inputs of the instruction, along
+  // with the record they are declared as.
+  std::map<std::string, TreePatternNode*> InstInputs;
+
+  // InstResults - Keep track of all the virtual registers that are 'set'
+  // in the instruction, including what reg class they are.
+  std::map<std::string, TreePatternNode*> InstResults;
+
+  std::vector<Record*> InstImpResults;
+
+  // Verify that the top-level forms in the instruction are of void type, and
+  // fill in the InstResults map.
+  for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
+    TreePatternNode *Pat = I->getTree(j);
+    if (Pat->getNumTypes() != 0)
+      I->error("Top-level forms in instruction pattern should have"
+               " void types");
+
+    // Find inputs and outputs, and verify the structure of the uses/defs.
+    FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
+                                InstImpResults);
+  }
+
+  // Now that we have inputs and outputs of the pattern, inspect the operands
+  // list for the instruction.  This determines the order that operands are
+  // added to the machine instruction the node corresponds to.
+  unsigned NumResults = InstResults.size();
+
+  // Parse the operands list from the (ops) list, validating it.
+  assert(I->getArgList().empty() && "Args list should still be empty here!");
+
+  // Check that all of the results occur first in the list.
+  std::vector<Record*> Results;
+  TreePatternNode *Res0Node = nullptr;
+  for (unsigned i = 0; i != NumResults; ++i) {
+    if (i == CGI.Operands.size())
+      I->error("'" + InstResults.begin()->first +
+               "' set but does not appear in operand list!");
+    const std::string &OpName = CGI.Operands[i].Name;
+
+    // Check that it exists in InstResults.
+    TreePatternNode *RNode = InstResults[OpName];
+    if (!RNode)
+      I->error("Operand $" + OpName + " does not exist in operand list!");
+
+    if (i == 0)
+      Res0Node = RNode;
+    Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
+    if (!R)
+      I->error("Operand $" + OpName + " should be a set destination: all "
+               "outputs must occur before inputs in operand list!");
+
+    if (!checkOperandClass(CGI.Operands[i], R))
+      I->error("Operand $" + OpName + " class mismatch!");
+
+    // Remember the return type.
+    Results.push_back(CGI.Operands[i].Rec);
+
+    // Okay, this one checks out.
+    InstResults.erase(OpName);
+  }
+
+  // Loop over the inputs next.  Make a copy of InstInputs so we can destroy
+  // the copy while we're checking the inputs.
+  std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
+
+  std::vector<TreePatternNode*> ResultNodeOperands;
+  std::vector<Record*> Operands;
+  for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
+    CGIOperandList::OperandInfo &Op = CGI.Operands[i];
+    const std::string &OpName = Op.Name;
+    if (OpName.empty())
+      I->error("Operand #" + utostr(i) + " in operands list has no name!");
+
+    if (!InstInputsCheck.count(OpName)) {
+      // If this is an operand with a DefaultOps set filled in, we can ignore
+      // this.  When we codegen it, we will do so as always executed.
+      if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {
+        // Does it have a non-empty DefaultOps field?  If so, ignore this
+        // operand.
+        if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
+          continue;
+      }
+      I->error("Operand $" + OpName +
+               " does not appear in the instruction pattern");
     }
+    TreePatternNode *InVal = InstInputsCheck[OpName];
+    InstInputsCheck.erase(OpName);   // It occurred, remove from map.
 
-    // Now that we have inputs and outputs of the pattern, inspect the operands
-    // list for the instruction.  This determines the order that operands are
-    // added to the machine instruction the node corresponds to.
-    unsigned NumResults = InstResults.size();
-
-    // Parse the operands list from the (ops) list, validating it.
-    assert(I->getArgList().empty() && "Args list should still be empty here!");
-
-    // Check that all of the results occur first in the list.
-    std::vector<Record*> Results;
-    TreePatternNode *Res0Node = nullptr;
-    for (unsigned i = 0; i != NumResults; ++i) {
-      if (i == CGI.Operands.size())
-        I->error("'" + InstResults.begin()->first +
-                 "' set but does not appear in operand list!");
-      const std::string &OpName = CGI.Operands[i].Name;
-
-      // Check that it exists in InstResults.
-      TreePatternNode *RNode = InstResults[OpName];
-      if (!RNode)
-        I->error("Operand $" + OpName + " does not exist in operand list!");
-
-      if (i == 0)
-        Res0Node = RNode;
-      Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
-      if (!R)
-        I->error("Operand $" + OpName + " should be a set destination: all "
-                 "outputs must occur before inputs in operand list!");
-
-      if (!checkOperandClass(CGI.Operands[i], R))
-        I->error("Operand $" + OpName + " class mismatch!");
-
-      // Remember the return type.
-      Results.push_back(CGI.Operands[i].Rec);
-
-      // Okay, this one checks out.
-      InstResults.erase(OpName);
+    if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
+      Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
+      if (!checkOperandClass(Op, InRec))
+        I->error("Operand $" + OpName + "'s register class disagrees"
+                 " between the operand and pattern");
     }
+    Operands.push_back(Op.Rec);
 
-    // Loop over the inputs next.  Make a copy of InstInputs so we can destroy
-    // the copy while we're checking the inputs.
-    std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
-
-    std::vector<TreePatternNode*> ResultNodeOperands;
-    std::vector<Record*> Operands;
-    for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
-      CGIOperandList::OperandInfo &Op = CGI.Operands[i];
-      const std::string &OpName = Op.Name;
-      if (OpName.empty())
-        I->error("Operand #" + utostr(i) + " in operands list has no name!");
-
-      if (!InstInputsCheck.count(OpName)) {
-        // If this is an operand with a DefaultOps set filled in, we can ignore
-        // this.  When we codegen it, we will do so as always executed.
-        if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {
-          // Does it have a non-empty DefaultOps field?  If so, ignore this
-          // operand.
-          if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
-            continue;
-        }
-        I->error("Operand $" + OpName +
-                 " does not appear in the instruction pattern");
-      }
-      TreePatternNode *InVal = InstInputsCheck[OpName];
-      InstInputsCheck.erase(OpName);   // It occurred, remove from map.
-
-      if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
-        Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
-        if (!checkOperandClass(Op, InRec))
-          I->error("Operand $" + OpName + "'s register class disagrees"
-                   " between the operand and pattern");
-      }
-      Operands.push_back(Op.Rec);
-
-      // Construct the result for the dest-pattern operand list.
-      TreePatternNode *OpNode = InVal->clone();
+    // Construct the result for the dest-pattern operand list.
+    TreePatternNode *OpNode = InVal->clone();
 
-      // No predicate is useful on the result.
-      OpNode->clearPredicateFns();
+    // No predicate is useful on the result.
+    OpNode->clearPredicateFns();
 
-      // Promote the xform function to be an explicit node if set.
-      if (Record *Xform = OpNode->getTransformFn()) {
-        OpNode->setTransformFn(nullptr);
-        std::vector<TreePatternNode*> Children;
-        Children.push_back(OpNode);
-        OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
-      }
-
-      ResultNodeOperands.push_back(OpNode);
+    // Promote the xform function to be an explicit node if set.
+    if (Record *Xform = OpNode->getTransformFn()) {
+      OpNode->setTransformFn(nullptr);
+      std::vector<TreePatternNode*> Children;
+      Children.push_back(OpNode);
+      OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
     }
 
-    if (!InstInputsCheck.empty())
-      I->error("Input operand $" + InstInputsCheck.begin()->first +
-               " occurs in pattern but not in operands list!");
+    ResultNodeOperands.push_back(OpNode);
+  }
 
-    TreePatternNode *ResultPattern =
-      new TreePatternNode(I->getRecord(), ResultNodeOperands,
-                          GetNumNodeResults(I->getRecord(), *this));
-    // Copy fully inferred output node type to instruction result pattern.
-    for (unsigned i = 0; i != NumResults; ++i)
-      ResultPattern->setType(i, Res0Node->getExtType(i));
+  if (!InstInputsCheck.empty())
+    I->error("Input operand $" + InstInputsCheck.begin()->first +
+             " occurs in pattern but not in operands list!");
 
-    // Create and insert the instruction.
-    // FIXME: InstImpResults should not be part of DAGInstruction.
-    DAGInstruction TheInst(I, Results, Operands, InstImpResults);
-    DAGInsts.insert(std::make_pair(I->getRecord(), TheInst));
+  TreePatternNode *ResultPattern =
+    new TreePatternNode(I->getRecord(), ResultNodeOperands,
+                        GetNumNodeResults(I->getRecord(), *this));
+  // Copy fully inferred output node type to instruction result pattern.
+  for (unsigned i = 0; i != NumResults; ++i)
+    ResultPattern->setType(i, Res0Node->getExtType(i));
 
-    // Use a temporary tree pattern to infer all types and make sure that the
-    // constructed result is correct.  This depends on the instruction already
-    // being inserted into the DAGInsts map.
-    TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
-    Temp.InferAllTypes(&I->getNamedNodesMap());
+  // Create and insert the instruction.
+  // FIXME: InstImpResults should not be part of DAGInstruction.
+  DAGInstruction TheInst(I, Results, Operands, InstImpResults);
+  DAGInsts.insert(std::make_pair(I->getRecord(), TheInst));
 
-    DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second;
-    TheInsertedInst.setResultPattern(Temp.getOnlyTree());
+  // Use a temporary tree pattern to infer all types and make sure that the
+  // constructed result is correct.  This depends on the instruction already
+  // being inserted into the DAGInsts map.
+  TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
+  Temp.InferAllTypes(&I->getNamedNodesMap());
 
-    return TheInsertedInst;
-  }
+  DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second;
+  TheInsertedInst.setResultPattern(Temp.getOnlyTree());
+
+  return TheInsertedInst;
+}
 
 /// ParseInstructions - Parse all of the instructions, inlining and resolving
 /// any fragments involved.  This populates the Instructions list with fully