Modify getRegisterValueType() to allow for a register being in mutliple
[oota-llvm.git] / utils / TableGen / DAGISelEmitter.cpp
index 299612977a1f381f8cb5ea7c6dfb114a28387177..aad21fe19bc0f865dd5a52f4b8393f729a4759a0 100644 (file)
 #include "DAGISelEmitter.h"
 #include "Record.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/Streams.h"
 #include <algorithm>
 #include <deque>
 using namespace llvm;
 
+namespace {
+  cl::opt<bool>
+  GenDebug("gen-debug", cl::desc("Generate debug code"),
+              cl::init(false));
+}
+
 //===----------------------------------------------------------------------===//
 // DAGISelEmitter Helper methods
 //
@@ -167,12 +175,33 @@ struct PatternSortingPredicate {
   }
 };
 
-/// getRegisterValueType - Look up and return the first ValueType of specified 
-/// RegisterClass record
+/// getRegisterValueType - Look up and return the ValueType of the specified
+/// register. If the register is a member of multiple register classes which
+/// have different associated types, return MVT::Other.
 static MVT::SimpleValueType getRegisterValueType(Record *R, const CodeGenTarget &T) {
-  if (const CodeGenRegisterClass *RC = T.getRegisterClassForRegister(R))
-    return RC->getValueTypeNum(0);
-  return MVT::Other;
+  int FoundRC = 0;
+  MVT::SimpleValueType VT = MVT::Other;
+  const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
+  std::vector<CodeGenRegisterClass>::const_iterator RC;
+  std::vector<Record*>::const_iterator Element;
+
+  for (RC = RCs.begin() ; RC != RCs.end() ; RC++) {
+    Element = find((*RC).Elements.begin(), (*RC).Elements.end(), R);
+    if (Element != (*RC).Elements.end()) {
+      if (!FoundRC) {
+        FoundRC = 1;
+        VT = (*RC).getValueTypeNum(0);
+      } else {
+        // In multiple RC's
+        if (VT != (*RC).getValueTypeNum(0)) {
+          // Types of the RC's do not agree. Return MVT::Other. The
+          // target is responsible for handling this.
+          return MVT::Other;
+        }
+      }
+    }
+  }
+  return VT;
 }
 
 
@@ -514,8 +543,8 @@ public:
 
           if (NeedCheck) {
             std::string ParentName(RootName.begin(), RootName.end()-1);
-            emitCheck("CanBeFoldedBy(" + RootName + ".getNode(), " + ParentName +
-                      ".getNode(), N.getNode())");
+            emitCheck("IsLegalAndProfitableToFold(" + RootName +
+                      ".getNode(), " + ParentName + ".getNode(), N.getNode())");
           }
         }
       }
@@ -575,11 +604,14 @@ public:
           emitInit("SDValue " + RootName + "1" + " = " +
                    RootName + ".getOperand(" + utostr(1) + ");");
 
-          emitCheck("isa<ConstantSDNode>(" + RootName + "1)");
+          unsigned NTmp = TmpNo++;
+          emitCode("ConstantSDNode *Tmp" + utostr(NTmp) +
+                   " = dyn_cast<ConstantSDNode>(" + RootName + "1);");
+          emitCheck("Tmp" + utostr(NTmp));
           const char *MaskPredicate = N->getOperator()->getName() == "or"
             ? "CheckOrMask(" : "CheckAndMask(";
-          emitCheck(MaskPredicate + RootName + "0, cast<ConstantSDNode>(" +
-                    RootName + "1), INT64_C(" + itostr(II->getValue()) + "))");
+          emitCheck(MaskPredicate + RootName + "0, Tmp" + utostr(NTmp) +
+                    ", INT64_C(" + itostr(II->getValue()) + "))");
           
           EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0), RootName,
                              ChainSuffix + utostr(0), FoundChain);
@@ -602,8 +634,8 @@ public:
       std::string Fn = CP->getSelectFunc();
       unsigned NumOps = CP->getNumOperands();
       for (unsigned i = 0; i < NumOps; ++i) {
-        emitDecl("CPTmp" + utostr(i));
-        emitCode("SDValue CPTmp" + utostr(i) + ";");
+        emitDecl("CPTmp" + RootName + "_" + utostr(i));
+        emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
       }
       if (CP->hasProperty(SDNPHasChain)) {
         emitDecl("CPInChain");
@@ -614,7 +646,7 @@ public:
 
       std::string Code = Fn + "(" + RootName + ", " + RootName;
       for (unsigned i = 0; i < NumOps; i++)
-        Code += ", CPTmp" + utostr(i);
+        Code += ", CPTmp" + RootName + "_" + utostr(i);
       if (CP->hasProperty(SDNPHasChain)) {
         ChainName = "Chain" + ChainSuffix;
         Code += ", CPInChain, Chain" + ChainSuffix;
@@ -676,8 +708,8 @@ public:
           std::string Fn = CP->getSelectFunc();
           unsigned NumOps = CP->getNumOperands();
           for (unsigned i = 0; i < NumOps; ++i) {
-            emitDecl("CPTmp" + utostr(i));
-            emitCode("SDValue CPTmp" + utostr(i) + ";");
+            emitDecl("CPTmp" + RootName + "_" + utostr(i));
+            emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
           }
           if (CP->hasProperty(SDNPHasChain)) {
             const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Parent->getOperator());
@@ -702,7 +734,7 @@ public:
           }
           Code += RootName;
           for (unsigned i = 0; i < NumOps; i++)
-            Code += ", CPTmp" + utostr(i);
+            Code += ", CPTmp" + RootName + "_" + utostr(i);
           if (CP->hasProperty(SDNPHasChain))
             Code += ", CPInChain, Chain" + ChainSuffix;
           emitCheck(Code + ")");
@@ -730,11 +762,14 @@ public:
                     ".getNode())");
       } else if (IntInit *II =
                  dynamic_cast<IntInit*>(Child->getLeafValue())) {
-        emitCheck("isa<ConstantSDNode>(" + RootName + ")");
+        unsigned NTmp = TmpNo++;
+        emitCode("ConstantSDNode *Tmp"+ utostr(NTmp) +
+                 " = dyn_cast<ConstantSDNode>("+
+                 RootName + ");");
+        emitCheck("Tmp" + utostr(NTmp));
         unsigned CTmp = TmpNo++;
-        emitCode("int64_t CN"+utostr(CTmp)+" = cast<ConstantSDNode>("+
-                 RootName + ")->getSExtValue();");
-        
+        emitCode("int64_t CN"+ utostr(CTmp) +
+                 " = Tmp" + utostr(NTmp) + "->getSExtValue();");
         emitCheck("CN" + utostr(CTmp) + " == "
                   "INT64_C(" +itostr(II->getValue()) + ")");
       } else {
@@ -848,14 +883,12 @@ public:
         NodeOps.push_back(Val);
       } else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
         for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
-          emitCode("AddToISelQueue(CPTmp" + utostr(i) + ");");
-          NodeOps.push_back("CPTmp" + utostr(i));
+          NodeOps.push_back("CPTmp" + Val + "_" + utostr(i));
         }
       } else {
         // This node, probably wrapped in a SDNodeXForm, behaves like a leaf
         // node even if it isn't one. Don't select it.
         if (!LikeLeaf) {
-          emitCode("AddToISelQueue(" + Val + ");");
           if (isRoot && N->isLeaf()) {
             emitCode("ReplaceUses(N, " + Val + ");");
             emitCode("return NULL;");
@@ -913,7 +946,8 @@ public:
       TreePatternNode *InstPatNode =
         isRoot ? (InstPat ? InstPat->getTree(0) : Pattern)
                : (InstPat ? InstPat->getTree(0) : NULL);
-      if (InstPatNode && InstPatNode->getOperator()->getName() == "set") {
+      if (InstPatNode && !InstPatNode->isLeaf() &&
+          InstPatNode->getOperator()->getName() == "set") {
         InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
       }
       bool IsVariadic = isRoot && II.isVariadic;
@@ -961,14 +995,17 @@ public:
         for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
           emitCode("if (" + OrigChains[i].first + ".getNode() != " +
                    OrigChains[i].second + ".getNode()) {");
-          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, "
+        emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, "
+                 "N.getDebugLoc(), MVT::Other, "
                  "&InChains[0], InChains.size());");
+        if (GenDebug) {
+          emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"yellow\");");
+          emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"black\");");
+        }
       }
 
       // Loop over all of the operands of the instruction pattern, emitting code
@@ -1008,8 +1045,6 @@ public:
 
       // Emit all the chain and CopyToReg stuff.
       bool ChainEmitted = NodeHasChain;
-      if (NodeHasChain)
-        emitCode("AddToISelQueue(" + ChainName + ");");
       if (NodeHasInFlag || HasImpInputs)
         EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
                              InFlagDecled, ResNodeDecled, true);
@@ -1021,7 +1056,6 @@ public:
         if (NodeHasOptInFlag) {
           emitCode("if (HasInFlag) {");
           emitCode("  InFlag = N.getOperand(N.getNumOperands()-1);");
-          emitCode("  AddToISelQueue(InFlag);");
           emitCode("}");
         }
       }
@@ -1047,6 +1081,10 @@ public:
 
       std::string Code = "Opc" + utostr(OpcNo);
 
+      if (!isRoot || (InputHasChain && !NodeHasChain))
+        // For call to "getTargetNode()".
+        Code += ", N.getDebugLoc()";
+
       emitOpcode(II.Namespace + "::" + II.TheDef->getName());
 
       // Output order: results, chain, flags
@@ -1086,23 +1124,27 @@ public:
         emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
                  ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
 
-        emitCode("  AddToISelQueue(N.getOperand(i));");
         emitCode("  Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
         emitCode("}");
       }
 
       // Generate MemOperandSDNodes nodes for each memory accesses covered by 
       // this pattern.
-      if (II.isSimpleLoad | II.mayLoad | II.mayStore) {
+      if (II.mayLoad | II.mayStore) {
         std::vector<std::string>::const_iterator mi, mie;
         for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
-          emitCode("SDValue LSI_" + *mi + " = "
+          std::string LSIName = "LSI_" + *mi;
+          emitCode("SDValue " + LSIName + " = "
                    "CurDAG->getMemOperand(cast<MemSDNode>(" +
                    *mi + ")->getMemOperand());");
+          if (GenDebug) {
+            emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"yellow\");");
+            emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"black\");");
+          }
           if (IsVariadic)
-            emitCode("Ops" + utostr(OpsNo) + ".push_back(LSI_" + *mi + ");");
+            emitCode("Ops" + utostr(OpsNo) + ".push_back(" + LSIName + ");");
           else
-            AllOps.push_back("LSI_" + *mi);
+            AllOps.push_back(LSIName);
         }
       }
 
@@ -1168,16 +1210,13 @@ public:
                           ");");
       }
 
-      if (FoldedChains.size() > 0) {
-        std::string Code;
-        for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) {
-          ReplaceFroms.push_back("SDValue(" +
-                                 FoldedChains[j].first + ".getNode(), " +
-                                 utostr(FoldedChains[j].second) +
-                                 ")");
-          ReplaceTos.push_back("SDValue(ResNode, " +
-                               utostr(NumResults+NumDstRegs) + ")");
-        }
+      for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) {
+        ReplaceFroms.push_back("SDValue(" +
+                               FoldedChains[j].first + ".getNode(), " +
+                               utostr(FoldedChains[j].second) +
+                               ")");
+        ReplaceTos.push_back("SDValue(ResNode, " +
+                             utostr(NumResults+NumDstRegs) + ")");
       }
 
       if (NodeHasOutFlag) {
@@ -1269,6 +1308,18 @@ public:
       }
 
       emitCode(CodePrefix + Code + ");");
+
+      if (GenDebug) {
+        if (!isRoot) {
+          emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"yellow\");");
+          emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"black\");");
+        }
+        else {
+          emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"yellow\");");
+          emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"black\");");
+        }
+      }
+
       for (unsigned i = 0, e = After.size(); i != e; ++i)
         emitCode(After[i]);
 
@@ -1354,20 +1405,19 @@ private:
                 InFlagDecled = true;
               } else
                 emitCode("InFlag = " + RootName + utostr(OpNo) + ";");
-              emitCode("AddToISelQueue(InFlag);");
             } else {
               if (!ChainEmitted) {
                 emitCode("SDValue Chain = CurDAG->getEntryNode();");
                 ChainName = "Chain";
                 ChainEmitted = true;
               }
-              emitCode("AddToISelQueue(" + RootName + utostr(OpNo) + ");");
               if (!InFlagDecled) {
                 emitCode("SDValue InFlag(0, 0);");
                 InFlagDecled = true;
               }
               std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
               emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
+                       ", " + RootName + ".getDebugLoc()" +
                        ", " + getQualifiedName(RR) +
                        ", " +  RootName + utostr(OpNo) + ", InFlag).getNode();");
               ResNodeDecled = true;
@@ -1387,7 +1437,6 @@ private:
       } else
         emitCode("InFlag = " + RootName +
                ".getOperand(" + utostr(OpNo) + ");");
-      emitCode("AddToISelQueue(InFlag);");
     }
   }
 };
@@ -1766,8 +1815,19 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
 
         // Replace the emission code within selection routines with calls to the
         // emission functions.
-        CallerCode = "return Emit_" + utostr(EmitFuncNum) + CallerCode;
-        GeneratedCode.push_back(std::make_pair(false, CallerCode));
+        if (GenDebug) {
+          GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N.getNode(), \"red\");"));
+        }
+        CallerCode = "SDNode *Result = Emit_" + utostr(EmitFuncNum) + CallerCode;
+        GeneratedCode.push_back(std::make_pair(3, CallerCode));
+        if (GenDebug) {
+          GeneratedCode.push_back(std::make_pair(0, "if(Result) {"));
+          GeneratedCode.push_back(std::make_pair(0, "  CurDAG->setSubgraphColor(Result, \"yellow\");"));
+          GeneratedCode.push_back(std::make_pair(0, "  CurDAG->setSubgraphColor(Result, \"black\");"));
+          GeneratedCode.push_back(std::make_pair(0, "}"));
+          //GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N.getNode(), \"black\");"));
+        }
+        GeneratedCode.push_back(std::make_pair(0, "return Result;"));
       }
 
       // Print function.
@@ -1792,9 +1852,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
       } else
         OpVTI->second.push_back(OpVTStr);
 
-      OS << "SDNode *Select_" << getLegalCName(OpName)
-         << OpVTStr << "(const SDValue &N) {\n";    
-
       // We want to emit all of the matching code now.  However, we want to emit
       // the matches in order of minimal cost.  Sort the patterns so the least
       // cost one is at the start.
@@ -1836,6 +1893,9 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
       // Next, reverse the list of patterns itself for the same reason.
       std::reverse(CodeForPatterns.begin(), CodeForPatterns.end());
     
+      OS << "SDNode *Select_" << getLegalCName(OpName)
+         << OpVTStr << "(const SDValue &N) {\n";    
+
       // Emit all of the patterns now, grouped together to share code.
       EmitPatterns(CodeForPatterns, 2, OS);
     
@@ -1861,15 +1921,11 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  std::vector<SDValue> Ops(N.getNode()->op_begin(), N.getNode()->op_end());\n"
      << "  SelectInlineAsmMemoryOperands(Ops);\n\n"
     
-     << "  // Ensure that the asm operands are themselves selected.\n"
-     << "  for (unsigned j = 0, e = Ops.size(); j != e; ++j)\n"
-     << "    AddToISelQueue(Ops[j]);\n\n"
-    
      << "  std::vector<MVT> VTs;\n"
      << "  VTs.push_back(MVT::Other);\n"
      << "  VTs.push_back(MVT::Flag);\n"
-     << "  SDValue New = CurDAG->getNode(ISD::INLINEASM, VTs, &Ops[0], "
-                 "Ops.size());\n"
+     << "  SDValue New = CurDAG->getNode(ISD::INLINEASM, N.getDebugLoc(), "
+                 "VTs, &Ops[0], Ops.size());\n"
      << "  return New.getNode();\n"
      << "}\n\n";
 
@@ -1882,7 +1938,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  SDValue Chain = N.getOperand(0);\n"
      << "  unsigned C = cast<LabelSDNode>(N)->getLabelID();\n"
      << "  SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
-     << "  AddToISelQueue(Chain);\n"
      << "  return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::DBG_LABEL,\n"
      << "                              MVT::Other, Tmp, Chain);\n"
      << "}\n\n";
@@ -1891,7 +1946,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  SDValue Chain = N.getOperand(0);\n"
      << "  unsigned C = cast<LabelSDNode>(N)->getLabelID();\n"
      << "  SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
-     << "  AddToISelQueue(Chain);\n"
      << "  return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::EH_LABEL,\n"
      << "                              MVT::Other, Tmp, Chain);\n"
      << "}\n\n";
@@ -1909,7 +1963,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());\n"
      << "  SDValue Tmp2 = "
      << "CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy());\n"
-     << "  AddToISelQueue(Chain);\n"
      << "  return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::DECLARE,\n"
      << "                              MVT::Other, Tmp1, Tmp2, Chain);\n"
      << "}\n\n";
@@ -1919,7 +1972,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  SDValue N1 = N.getOperand(1);\n"
      << "  unsigned C = cast<ConstantSDNode>(N1)->getZExtValue();\n"
      << "  SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
-     << "  AddToISelQueue(N0);\n"
      << "  return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::EXTRACT_SUBREG,\n"
      << "                              N.getValueType(), N0, Tmp);\n"
      << "}\n\n";
@@ -1930,21 +1982,19 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  SDValue N2 = N.getOperand(2);\n"
      << "  unsigned C = cast<ConstantSDNode>(N2)->getZExtValue();\n"
      << "  SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
-     << "  AddToISelQueue(N1);\n"
-     << "  AddToISelQueue(N0);\n"
      << "  return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::INSERT_SUBREG,\n"
      << "                              N.getValueType(), N0, N1, Tmp);\n"
      << "}\n\n";
 
   OS << "// The main instruction selector code.\n"
      << "SDNode *SelectCode(SDValue N) {\n"
-     << "  if (N.isMachineOpcode()) {\n"
-     << "    return NULL;   // Already selected.\n"
-     << "  }\n\n"
      << "  MVT::SimpleValueType NVT = N.getNode()->getValueType(0).getSimpleVT();\n"
      << "  switch (N.getOpcode()) {\n"
-     << "  default: break;\n"
-     << "  case ISD::EntryToken:       // These leaves remain the same.\n"
+     << "  default:\n"
+     << "    assert(!N.isMachineOpcode() && \"Node already selected!\");\n"
+     << "    break;\n"
+     << "  case ISD::EntryToken:       // These nodes remain the same.\n"
+     << "  case ISD::MEMOPERAND:\n"
      << "  case ISD::BasicBlock:\n"
      << "  case ISD::Register:\n"
      << "  case ISD::HANDLENODE:\n"
@@ -1955,22 +2005,17 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  case ISD::TargetExternalSymbol:\n"
      << "  case ISD::TargetJumpTable:\n"
      << "  case ISD::TargetGlobalTLSAddress:\n"
-     << "  case ISD::TargetGlobalAddress: {\n"
+     << "  case ISD::TargetGlobalAddress:\n"
+     << "  case ISD::TokenFactor:\n"
+     << "  case ISD::CopyFromReg:\n"
+     << "  case ISD::CopyToReg: {\n"
      << "    return NULL;\n"
      << "  }\n"
      << "  case ISD::AssertSext:\n"
      << "  case ISD::AssertZext: {\n"
-     << "    AddToISelQueue(N.getOperand(0));\n"
      << "    ReplaceUses(N, N.getOperand(0));\n"
      << "    return NULL;\n"
      << "  }\n"
-     << "  case ISD::TokenFactor:\n"
-     << "  case ISD::CopyFromReg:\n"
-     << "  case ISD::CopyToReg: {\n"
-     << "    for (unsigned i = 0, e = N.getNumOperands(); i != e; ++i)\n"
-     << "      AddToISelQueue(N.getOperand(i));\n"
-     << "    return NULL;\n"
-     << "  }\n"
      << "  case ISD::INLINEASM: return Select_INLINEASM(N);\n"
      << "  case ISD::DBG_LABEL: return Select_DBG_LABEL(N);\n"
      << "  case ISD::EH_LABEL: return Select_EH_LABEL(N);\n"