Teach the DAGISelEmitter to not compute the variable_ops operand
authorDan Gohman <gohman@apple.com>
Sat, 31 May 2008 02:11:25 +0000 (02:11 +0000)
committerDan Gohman <gohman@apple.com>
Sat, 31 May 2008 02:11:25 +0000 (02:11 +0000)
index for the input pattern in terms of the output pattern. Instead
keep track of how many fixed operands the input pattern actually
has, and have the input matching code pass the output-emitting
function that index value. This simplifies the code, disentangles
variables_ops from the support for predication operations, and
makes variable_ops more robust.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51808 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Target.td
lib/Target/TargetSelectionDAG.td
lib/Target/X86/X86InstrInfo.td
utils/TableGen/CodeGenDAGPatterns.cpp
utils/TableGen/CodeGenInstruction.cpp
utils/TableGen/DAGISelEmitter.cpp
utils/TableGen/DAGISelEmitter.h
utils/TableGen/InstrInfoEmitter.cpp

index 92c40570af3e8f51fc1d07527c7a9104f3d44dfa..a268e164107f2f745aa2e2c1bba9a29ba77966e9 100644 (file)
@@ -259,12 +259,6 @@ def ins;
 /// of operands.
 def variable_ops;
 
-/// discard definition - Mark this operand as being matched in the input
-/// but omitted from the output. This is necessary in some situations
-/// involving variable_ops to help the pattern matcher determine which
-/// input nodes to forward on to the variable_ops portion of the output.
-def discard;
-
 /// ptr_rc definition - Mark this operand as being a pointer value whose
 /// register class is resolved dynamically via a callback to TargetInstrInfo.
 /// FIXME: We should probably change this to a class which contain a list of
index 9def220337fb47c3c0d663d80ef8f73b3df104a2..474f9100263704a3209c98980ebcf247689ac90f 100644 (file)
@@ -62,7 +62,7 @@ class SDTCisIntVectorOfSameSize<int ThisOp, int OtherOp>
 
 /// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same
 /// type as the element type of OtherOp, which is a vector type.
-class  SDTCisEltOfVec<int ThisOp, int OtherOp>
+class SDTCisEltOfVec<int ThisOp, int OtherOp>
   : SDTypeConstraint<ThisOp> {
   int OtherOpNum = OtherOp;
 }
@@ -470,7 +470,6 @@ class PatLeaf<dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm>
 def vtInt      : PatLeaf<(vt),  [{ return MVT::isInteger(N->getVT()); }]>;
 def vtFP       : PatLeaf<(vt),  [{ return MVT::isFloatingPoint(N->getVT()); }]>;
 
-def immAllZeros : PatLeaf<(imm), [{ return N->isNullValue(); }]>;
 def immAllOnes : PatLeaf<(imm), [{ return N->isAllOnesValue(); }]>;
 def immAllOnesV: PatLeaf<(build_vector), [{
   return ISD::isBuildVectorAllOnes(N);
index 4ffc303c3725dc59018a2e7042d86c408810bdfb..4b8dc100b9e7c781f1138060b46087e0677e7ccd 100644 (file)
@@ -322,9 +322,9 @@ let neverHasSideEffects = 1, isNotDuplicable = 1 in
 // Return instructions.
 let isTerminator = 1, isReturn = 1, isBarrier = 1,
     hasCtrlDep = 1, FPForm = SpecialFP, FPFormBits = SpecialFP.Value in {
-  def RET    : I   <0xC3, RawFrm, (outs), (ins discard:$amt, variable_ops),
+  def RET    : I   <0xC3, RawFrm, (outs), (ins variable_ops),
                     "ret",
-                    [(X86retflag immAllZeros:$amt)]>;
+                    [(X86retflag 0)]>;
   def RETI   : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
                     "ret\t$amt",
                     [(X86retflag imm:$amt)]>;
index 006c067e8fd15c574c54a1521c35701747e4f564..8c46b35fa19fbab2bbf25cdb2eaca06a0f5f2497 100644 (file)
@@ -916,8 +916,6 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
         MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP);
       } else if (OperandNode->getName() == "unknown") {
         MadeChange |= Child->UpdateNodeType(MVT::isUnknown, TP);
-      } else if (OperandNode->getName() == "discard") {
-        MadeChange |= Child->UpdateNodeType(MVT::isUnknown, TP);
       } else {
         assert(0 && "Unknown operand type!");
         abort();
index d52037823f67857c07e171438a64ac4097f47881..37c2069ec7279e3b8af3d4b8b75f5d963cc981af 100644 (file)
@@ -163,8 +163,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
       isVariadic = true;
       continue;
     } else if (!Rec->isSubClassOf("RegisterClass") && 
-               Rec->getName() != "ptr_rc" && Rec->getName() != "unknown" &&
-               Rec->getName() != "discard")
+               Rec->getName() != "ptr_rc" && Rec->getName() != "unknown")
       throw "Unknown operand class '" + Rec->getName() +
             "' in instruction '" + R->getName() + "' instruction!";
 
index cf8c6272baccb501a624167bebaf52365a66fe59..29fec09515f5b98889495375e71b61f4db4fbef7 100644 (file)
@@ -331,6 +331,15 @@ private:
   /// instructions.
   std::vector<std::string> &TargetOpcodes;
   std::vector<std::string> &TargetVTs;
+  /// OutputIsVariadic - Records whether the instruction output pattern uses
+  /// variable_ops.  This requires that the Emit function be passed an
+  /// additional argument to indicate where the input varargs operands
+  /// begin.
+  bool &OutputIsVariadic;
+  /// NumInputRootOps - Records the number of operands the root node of the
+  /// input pattern has.  This information is used in the generated code to
+  /// pass to Emit functions when variable_ops processing is needed.
+  unsigned &NumInputRootOps;
 
   std::string ChainName;
   unsigned TmpNo;
@@ -367,10 +376,13 @@ public:
                      std::vector<std::pair<unsigned, std::string> > &gc,
                      std::set<std::string> &gd,
                      std::vector<std::string> &to,
-                     std::vector<std::string> &tv)
+                     std::vector<std::string> &tv,
+                     bool &oiv,
+                     unsigned &niro)
   : CGP(cgp), Predicates(preds), Pattern(pattern), Instruction(instr),
     GeneratedCode(gc), GeneratedDecl(gd),
     TargetOpcodes(to), TargetVTs(tv),
+    OutputIsVariadic(oiv), NumInputRootOps(niro),
     TmpNo(0), OpcNo(0), VTNo(0) {}
 
   /// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo
@@ -392,6 +404,9 @@ public:
     bool isRoot = (P == NULL);
     // Emit instruction predicates. Each predicate is just a string for now.
     if (isRoot) {
+      // Record input varargs info.
+      NumInputRootOps = N->getNumChildren();
+
       std::string PredicateCheck;
       for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
         if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
@@ -887,7 +902,7 @@ public:
       if (InstPatNode && InstPatNode->getOperator()->getName() == "set") {
         InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
       }
-      bool HasVarOps     = isRoot && II.isVariadic;
+      bool IsVariadic = isRoot && II.isVariadic;
       // FIXME: fix how we deal with physical register operands.
       bool HasImpInputs  = isRoot && Inst.getNumImpOperands() > 0;
       bool HasImpResults = isRoot && DstRegs.size() > 0;
@@ -904,11 +919,14 @@ public:
       unsigned NumResults = Inst.getNumResults();    
       unsigned NumDstRegs = HasImpResults ? DstRegs.size() : 0;
 
+      // Record output varargs info.
+      OutputIsVariadic = IsVariadic;
+
       if (NodeHasOptInFlag) {
         emitCode("bool HasInFlag = "
            "(N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag);");
       }
-      if (HasVarOps)
+      if (IsVariadic)
         emitCode("SmallVector<SDOperand, 8> Ops" + utostr(OpcNo) + ";");
 
       // How many results is this pattern expected to produce?
@@ -946,20 +964,15 @@ public:
       // in the 'execute always' values.  Match up the node operands to the
       // instruction operands to do this.
       std::vector<std::string> AllOps;
-      unsigned NumEAInputs = 0; // # of synthesized 'execute always' inputs.
-      unsigned InputIndex = 0;
       for (unsigned ChildNo = 0, InstOpNo = NumResults;
            InstOpNo != II.OperandList.size(); ++InstOpNo) {
         std::vector<std::string> Ops;
         
         // Determine what to emit for this operand.
         Record *OperandNode = II.OperandList[InstOpNo].Rec;
-        if (OperandNode->getName() == "discard") {
-          // This is a "discard" operand; emit nothing. Just note it.
-          ++InputIndex;
-        } else if ((OperandNode->isSubClassOf("PredicateOperand") ||
-                    OperandNode->isSubClassOf("OptionalDefOperand")) &&
-                   !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
+        if ((OperandNode->isSubClassOf("PredicateOperand") ||
+             OperandNode->isSubClassOf("OptionalDefOperand")) &&
+            !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
           // This is a predicate or optional def operand; emit the
           // 'default ops' operands.
           const DAGDefaultOperand &DefaultOp =
@@ -968,9 +981,7 @@ public:
             Ops = EmitResultCode(DefaultOp.DefaultOps[i], DstRegs,
                                  InFlagDecled, ResNodeDecled);
             AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
-            NumEAInputs += Ops.size();
           }
-          ++InputIndex;
         } else {
           // Otherwise this is a normal operand or a predicate operand without
           // 'execute always'; emit it.
@@ -978,7 +989,6 @@ public:
                                InFlagDecled, ResNodeDecled);
           AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
           ++ChildNo;
-          ++InputIndex;
         }
       }
 
@@ -1057,15 +1067,7 @@ public:
           Code += ", MVT::Flag";
 
         // Inputs.
-        if (HasVarOps) {
-          // Figure out how many fixed inputs the node has.  This is important
-          // to know which inputs are the variable ones if present. Include
-          // the 'discard' and chain inputs in the count, and adjust for the
-          // number of operands that are 'execute always'. This is the index
-          // where we should start copying operands into the 'variable_ops'
-          // portion of the output.
-          InputIndex += NodeHasChain - NumEAInputs;
-        
+        if (IsVariadic) {
           for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
             emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
           AllOps.clear();
@@ -1078,7 +1080,7 @@ public:
           else if (NodeHasOptInFlag)
             EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
 
-          emitCode("for (unsigned i = " + utostr(InputIndex) +
+          emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
                    ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
 
           emitCode("  AddToISelQueue(N.getOperand(i));");
@@ -1087,13 +1089,13 @@ public:
         }
 
         if (NodeHasChain) {
-          if (HasVarOps)
+          if (IsVariadic)
             emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
           else
             AllOps.push_back(ChainName);
         }
 
-        if (HasVarOps) {
+        if (IsVariadic) {
           if (NodeHasInFlag || HasImpInputs)
             emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
           else if (NodeHasOptInFlag) {
@@ -1358,11 +1360,17 @@ void DAGISelEmitter::GenerateCodeForPattern(const PatternToMatch &Pattern,
                   std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
                                            std::set<std::string> &GeneratedDecl,
                                         std::vector<std::string> &TargetOpcodes,
-                                          std::vector<std::string> &TargetVTs) {
+                                            std::vector<std::string> &TargetVTs,
+                                            bool &OutputIsVariadic,
+                                            unsigned &NumInputRootOps) {
+  OutputIsVariadic = false;
+  NumInputRootOps = 0;
+
   PatternCodeEmitter Emitter(CGP, Pattern.getPredicates(),
                              Pattern.getSrcPattern(), Pattern.getDstPattern(),
                              GeneratedCode, GeneratedDecl,
-                             TargetOpcodes, TargetVTs);
+                             TargetOpcodes, TargetVTs,
+                             OutputIsVariadic, NumInputRootOps);
 
   // Emit the matcher, capturing named arguments in VariableMap.
   bool FoundChain = false;
@@ -1652,17 +1660,24 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
       std::vector<std::vector<std::string> > PatternOpcodes;
       std::vector<std::vector<std::string> > PatternVTs;
       std::vector<std::set<std::string> > PatternDecls;
+      std::vector<bool> OutputIsVariadicFlags;
+      std::vector<unsigned> NumInputRootOpsCounts;
       for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
         CodeList GeneratedCode;
         std::set<std::string> GeneratedDecl;
         std::vector<std::string> TargetOpcodes;
         std::vector<std::string> TargetVTs;
+        bool OutputIsVariadic;
+        unsigned NumInputRootOps;
         GenerateCodeForPattern(*Patterns[i], GeneratedCode, GeneratedDecl,
-                               TargetOpcodes, TargetVTs);
+                               TargetOpcodes, TargetVTs,
+                               OutputIsVariadic, NumInputRootOps);
         CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode));
         PatternDecls.push_back(GeneratedDecl);
         PatternOpcodes.push_back(TargetOpcodes);
         PatternVTs.push_back(TargetVTs);
+        OutputIsVariadicFlags.push_back(OutputIsVariadic);
+        NumInputRootOpsCounts.push_back(NumInputRootOps);
       }
     
       // Scan the code to see if all of the patterns are reachable and if it is
@@ -1697,6 +1712,8 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
         std::vector<std::string> &TargetOpcodes = PatternOpcodes[i];
         std::vector<std::string> &TargetVTs = PatternVTs[i];
         std::set<std::string> Decls = PatternDecls[i];
+        bool OutputIsVariadic = OutputIsVariadicFlags[i];
+        unsigned NumInputRootOps = NumInputRootOpsCounts[i];
         std::vector<std::string> AddedInits;
         int CodeSize = (int)GeneratedCode.size();
         int LastPred = -1;
@@ -1723,6 +1740,12 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
           CalleeCode += ", SDOperand &" + Name;
           CallerCode += ", " + Name;
         }
+
+        if (OutputIsVariadic) {
+          CalleeCode += ", unsigned NumInputRootOps";
+          CallerCode += ", " + utostr(NumInputRootOps);
+        }
+
         CallerCode += ");";
         CalleeCode += ") ";
         // Prevent emission routines from being inlined to reduce selection
index 1b47bcc156e69471206dc97750a0a0a68546529d..2f626f6b866bd446e64fc6add07bab70dce7452f 100644 (file)
@@ -41,7 +41,9 @@ private:
                   std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
                               std::set<std::string> &GeneratedDecl,
                               std::vector<std::string> &TargetOpcodes,
-                              std::vector<std::string> &TargetVTs);
+                              std::vector<std::string> &TargetVTs,
+                              bool &OutputIsVariadic,
+                              unsigned &NumInputRootOps);
   void EmitPatterns(std::vector<std::pair<const PatternToMatch*, 
                   std::vector<std::pair<unsigned, std::string> > > > &Patterns, 
                     unsigned Indent, std::ostream &OS);
index 8390c90660426bbb3b5517ac00b4572ca48781c9..fb8dd371efd11265399059eb30097b7f56d3180e 100644 (file)
@@ -85,10 +85,6 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
       Record *OpR = OperandList[j].Rec;
       std::string Res;
       
-      // Discard "discard" operands.
-      if (OpR->getName() == "discard")
-        continue;
-
       if (OpR->isSubClassOf("RegisterClass"))
         Res += getQualifiedName(OpR) + "RegClassID, ";
       else
@@ -206,14 +202,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
     MinOperands = Inst.OperandList.back().MIOperandNo +
                   Inst.OperandList.back().MINumOperands;
 
-  // Subtract the number of "discard" operands, which we'll be skipping
-  // when emitting OperandInfo records.
-  for (unsigned j = 0, e = Inst.OperandList.size(); j != e; ++j) {
-    Record *OpR = Inst.OperandList[j].Rec;
-    if (OpR->getName() == "discard")
-      --MinOperands;
-  }
-  
   OS << "  { ";
   OS << Num << ",\t" << MinOperands << ",\t"
      << Inst.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef)