First steps to getting PredicateOperand's to work. This handles instruction
[oota-llvm.git] / utils / TableGen / DAGISelEmitter.cpp
index 9deb43514bf66c6c18d5679023cc9047a79f8c0b..3d79ea09b3e1743880fee52c46d98d8d4e6e10b0 100644 (file)
@@ -759,27 +759,40 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
       MadeChange = UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
     }
 
-    if (getNumChildren() != Inst.getNumOperands())
-      TP.error("Instruction '" + getOperator()->getName() + " expects " +
-               utostr(Inst.getNumOperands()) + " operands, not " +
-               utostr(getNumChildren()) + " operands!");
-    for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+    unsigned ChildNo = 0;
+    for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
       Record *OperandNode = Inst.getOperand(i);
+      
+      // If the instruction expects a predicate operand, we codegen this by
+      // setting the predicate to it's "execute always" value.
+      if (OperandNode->isSubClassOf("PredicateOperand"))
+        continue;
+       
+      // Verify that we didn't run out of provided operands.
+      if (ChildNo >= getNumChildren())
+        TP.error("Instruction '" + getOperator()->getName() +
+                 "' expects more operands than were provided.");
+      
       MVT::ValueType VT;
+      TreePatternNode *Child = getChild(ChildNo++);
       if (OperandNode->isSubClassOf("RegisterClass")) {
         const CodeGenRegisterClass &RC = 
           ISE.getTargetInfo().getRegisterClass(OperandNode);
-        MadeChange |=getChild(i)->UpdateNodeType(ConvertVTs(RC.getValueTypes()),
-                                                 TP);
+        MadeChange |= Child->UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
       } else if (OperandNode->isSubClassOf("Operand")) {
         VT = getValueType(OperandNode->getValueAsDef("Type"));
-        MadeChange |= getChild(i)->UpdateNodeType(VT, TP);
+        MadeChange |= Child->UpdateNodeType(VT, TP);
       } else {
         assert(0 && "Unknown operand type!");
         abort();
       }
-      MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+      MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
     }
+    
+    if (ChildNo != getNumChildren())
+      TP.error("Instruction '" + getOperator()->getName() +
+               "' was provided too many operands!");
+    
     return MadeChange;
   } else {
     assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
@@ -1471,25 +1484,35 @@ void DAGISelEmitter::ParseInstructions() {
     std::vector<TreePatternNode*> ResultNodeOperands;
     std::vector<Record*> Operands;
     for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) {
-      const std::string &OpName = CGI.OperandList[i].Name;
+      CodeGenInstruction::OperandInfo &Op = CGI.OperandList[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 (!InstInputsCheck.count(OpName)) {
+        // If this is an predicate operand with an ExecuteAlways set filled in,
+        // we can ignore this.  When we codegen it, we will do so as always
+        // executed.
+        if (Op.Rec->isSubClassOf("PredicateOperand")) {
+          // Does it have a non-empty ExecuteAlways field?  If so, ignore this
+          // operand.
+          if (Op.Rec->getValueAsDag("ExecuteAlways")->getNumArgs())
+            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() &&
           dynamic_cast<DefInit*>(InVal->getLeafValue())) {
         Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
-        if (CGI.OperandList[i].Rec != InRec &&
-            !InRec->isSubClassOf("ComplexPattern"))
+        if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern"))
           I->error("Operand $" + OpName + "'s register class disagrees"
                    " between the operand and pattern");
       }
-      Operands.push_back(CGI.OperandList[i].Rec);
+      Operands.push_back(Op.Rec);
       
       // Construct the result for the dest-pattern operand list.
       TreePatternNode *OpNode = InVal->clone();
@@ -2138,6 +2161,8 @@ private:
   std::map<std::string, Record*> OperatorMap;
   // Names of all the folded nodes which produce chains.
   std::vector<std::pair<std::string, unsigned> > FoldedChains;
+  // Original input chain(s).
+  std::vector<std::pair<std::string, std::string> > OrigChains;
   std::set<std::string> Duplicates;
 
   /// GeneratedCode - This is the buffer that we emit code to.  The first int
@@ -2198,8 +2223,8 @@ public:
   /// if the match fails. At this point, we already know that the opcode for N
   /// matches, and the SDNode for the result has the RootName specified name.
   void EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
-                     const std::string &RootName,
-                     const std::string &ChainSuffix, bool &FoundChain) {
+                     const std::string &RootName, const std::string &ChainSuffix,
+                     bool &FoundChain) {
     bool isRoot = (P == NULL);
     // Emit instruction predicates. Each predicate is just a string for now.
     if (isRoot) {
@@ -2257,13 +2282,11 @@ public:
     unsigned OpNo = 0;
     bool NodeHasChain = NodeHasProperty   (N, SDNPHasChain, ISE);
     bool HasChain     = PatternHasProperty(N, SDNPHasChain, ISE);
-    bool HasOutFlag   = PatternHasProperty(N, SDNPOutFlag,  ISE);
     bool EmittedUseCheck = false;
     if (HasChain) {
       if (NodeHasChain)
         OpNo = 1;
       if (!isRoot) {
-        const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
         // Multiple uses of actual result?
         emitCheck(RootName + ".hasOneUse()");
         EmittedUseCheck = true;
@@ -2281,22 +2304,36 @@ public:
           //      /        [YY]
           //      |         ^
           //     [XX]-------|
-          const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator());
-          if (PInfo.getNumOperands() > 1 ||
+          bool NeedCheck = false;
+          if (P != Pattern)
+            NeedCheck = true;
+          else {
+            const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator());
+            NeedCheck =
+              P->getOperator() == ISE.get_intrinsic_void_sdnode() ||
+              P->getOperator() == ISE.get_intrinsic_w_chain_sdnode() ||
+              P->getOperator() == ISE.get_intrinsic_wo_chain_sdnode() ||
+              PInfo.getNumOperands() > 1 ||
               PInfo.hasProperty(SDNPHasChain) ||
               PInfo.hasProperty(SDNPInFlag) ||
-              PInfo.hasProperty(SDNPOptInFlag)) {
+              PInfo.hasProperty(SDNPOptInFlag);
+          }
+
+          if (NeedCheck) {
             std::string ParentName(RootName.begin(), RootName.end()-1);
             emitCheck("CanBeFoldedBy(" + RootName + ".Val, " + ParentName +
-                      ".Val)");
+                      ".Val, N.Val)");
           }
         }
       }
 
       if (NodeHasChain) {
-        if (FoundChain)
-          emitCheck("Chain.Val == " + RootName + ".Val");
-        else
+        if (FoundChain) {
+          emitCheck("(" + ChainName + ".Val == " + RootName + ".Val || "
+                    "IsChainCompatible(" + ChainName + ".Val, " +
+                    RootName + ".Val))");
+          OrigChains.push_back(std::make_pair(ChainName, RootName));
+        } else
           FoundChain = true;
         ChainName = "Chain" + ChainSuffix;
         emitInit("SDOperand " + ChainName + " = " + RootName +
@@ -2313,7 +2350,6 @@ public:
         (PatternHasProperty(N, SDNPInFlag, ISE) ||
          PatternHasProperty(N, SDNPOptInFlag, ISE) ||
          PatternHasProperty(N, SDNPOutFlag, ISE))) {
-      const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
       if (!EmittedUseCheck) {
         // Multiple uses of actual result?
         emitCheck(RootName + ".hasOneUse()");
@@ -2451,7 +2487,12 @@ public:
             emitCode("SDOperand " + ChainName + ";");
           }
           
-          std::string Code = Fn + "(" + RootName;
+          std::string Code = Fn + "(";
+          if (CP->hasProperty(SDNPHasChain)) {
+            std::string ParentName(RootName.begin(), RootName.end()-1);
+            Code += "N, " + ParentName + ", ";
+          }
+          Code += RootName;
           for (unsigned i = 0; i < NumOps; i++)
             Code += ", CPTmp" + utostr(i);
           if (CP->hasProperty(SDNPHasChain))
@@ -2665,6 +2706,26 @@ public:
           PatResults++;
       }
 
+      if (OrigChains.size() > 0) {
+        // The original input chain is being ignored. If it is not just
+        // pointing to the op that's being folded, we should create a
+        // TokenFactor with it and the chain of the folded op as the new chain.
+        // We could potentially be doing multiple levels of folding, in that
+        // case, the TokenFactor can have more operands.
+        emitCode("SmallVector<SDOperand, 8> InChains;");
+        for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
+          emitCode("if (" + OrigChains[i].first + ".Val != " +
+                   OrigChains[i].second + ".Val) {");
+          emitCode("  AddToISelQueue(" + OrigChains[i].first + ");");
+          emitCode("  InChains.push_back(" + OrigChains[i].first + ");");
+          emitCode("}");
+        }
+        emitCode("AddToISelQueue(" + ChainName + ");");
+        emitCode("InChains.push_back(" + ChainName + ");");
+        emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, MVT::Other, "
+                 "&InChains[0], InChains.size());");
+      }
+
       std::vector<std::string> AllOps;
       for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
         std::vector<std::string> Ops = EmitResultCode(N->getChild(i),
@@ -3277,8 +3338,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
       PatternsByOpcode[Node->getOperator()].push_back(&PatternsToMatch[i]);
     } else {
       const ComplexPattern *CP;
-      if (IntInit *II = 
-          dynamic_cast<IntInit*>(Node->getLeafValue())) {
+      if (dynamic_cast<IntInit*>(Node->getLeafValue())) {
         PatternsByOpcode[getSDNodeNamed("imm")].push_back(&PatternsToMatch[i]);
       } else if ((CP = NodeGetComplexPattern(Node, *this))) {
         std::vector<Record*> OpNodes = CP->getRootNodes();
@@ -3647,6 +3707,21 @@ void DAGISelEmitter::run(std::ostream &OS) {
   OS << "/// Dummy parameter to ReplaceAllUsesOfValueWith().\n"
      << "std::vector<SDNode*> ISelKilled;\n\n";
 
+  OS << "/// IsChainCompatible - Returns true if Chain is Op or Chain does\n";
+  OS << "/// not reach Op.\n";
+  OS << "static bool IsChainCompatible(SDNode *Chain, SDNode *Op) {\n";
+  OS << "  if (Chain->getOpcode() == ISD::EntryToken)\n";
+  OS << "    return true;\n";
+  OS << "  else if (Chain->getOpcode() == ISD::TokenFactor)\n";
+  OS << "    return false;\n";
+  OS << "  else if (Chain->getNumOperands() > 0) {\n";
+  OS << "    SDOperand C0 = Chain->getOperand(0);\n";
+  OS << "    if (C0.getValueType() == MVT::Other)\n";
+  OS << "      return C0.Val != Op && IsChainCompatible(C0.Val, Op);\n";
+  OS << "  }\n";
+  OS << "  return true;\n";
+  OS << "}\n";
+
   OS << "/// Sorting functions for the selection queue.\n"
      << "struct isel_sort : public std::binary_function"
      << "<SDNode*, SDNode*, bool> {\n"
@@ -3683,7 +3758,8 @@ OS << "  unsigned NumKilled = ISelKilled.size();\n";
   OS << "  if (NumKilled) {\n";
   OS << "    for (unsigned i = 0; i != NumKilled; ++i) {\n";
   OS << "      SDNode *Temp = ISelKilled[i];\n";
-  OS << "      std::remove(ISelQueue.begin(), ISelQueue.end(), Temp);\n";
+  OS << "      ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(), "
+     << "Temp), ISelQueue.end());\n";
   OS << "    };\n";
  OS << "    std::make_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
   OS << "    ISelKilled.clear();\n";
@@ -3701,16 +3777,6 @@ OS << "  unsigned NumKilled = ISelKilled.size();\n";
   OS << "  RemoveKilled();\n";
   OS << "}\n\n";
 
-  OS << "void DeleteNode(SDNode *N) {\n";
-  OS << "  CurDAG->DeleteNode(N);\n";
-  OS << "  for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); "
-     << "I != E; ++I) {\n";
-  OS << "    SDNode *Operand = I->Val;\n";
-  OS << "    if (Operand->use_empty())\n";
-  OS << "      DeleteNode(Operand);\n";
-  OS << "  }\n";
-  OS << "}\n";
-
   OS << "// SelectRoot - Top level entry to DAG isel.\n";
   OS << "SDOperand SelectRoot(SDOperand Root) {\n";
   OS << "  SelectRootInit();\n";
@@ -3734,8 +3800,10 @@ OS << "  unsigned NumKilled = ISelKilled.size();\n";
   OS << "      if (ResNode != Node) {\n";
   OS << "        if (ResNode)\n";
   OS << "          ReplaceUses(Node, ResNode);\n";
-  OS << "        if (Node->use_empty()) // Don't delete EntryToken, etc.\n";
-  OS << "          DeleteNode(Node);\n";
+  OS << "        if (Node->use_empty()) { // Don't delete EntryToken, etc.\n";
+  OS << "          CurDAG->RemoveDeadNode(Node, ISelKilled);\n";
+  OS << "          RemoveKilled();\n";
+  OS << "        }\n";
   OS << "      }\n";
   OS << "    }\n";
   OS << "  }\n";