Instructions with variable operands (variable_ops) can have a number required
authorEvan Cheng <evan.cheng@apple.com>
Thu, 15 Jun 2006 07:22:16 +0000 (07:22 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 15 Jun 2006 07:22:16 +0000 (07:22 +0000)
operands. e.g.
def CALL32r : I<0xFF, MRM2r, (ops GR32:$dst, variable_ops),
                "call {*}$dst", [(X86call GR32:$dst)]>;
TableGen should emit operand informations for the "required" operands.

Added a target instruction info flag M_VARIABLE_OPS to indicate the target
instruction may have more operands in addition to the minimum required
operands.

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

include/llvm/Target/TargetInstrInfo.h
lib/CodeGen/MachineInstr.cpp
lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
utils/TableGen/InstrInfoEmitter.cpp

index 9e49a975bc11d3a24f36ba61763bbd354e4ee285..6fb3274e8018d982a44d50627c924298c0a88adb 100644 (file)
@@ -76,6 +76,10 @@ const unsigned M_TERMINATOR_FLAG       = 1 << 10;
 // block.
 const unsigned M_USES_CUSTOM_DAG_SCHED_INSERTION = 1 << 11;
 
+// M_VARIABLE_OPS - Set if this instruction can have a variable number of extra
+// operands in addition to the minimum number operands specified.
+const unsigned M_VARIABLE_OPS = 1 << 12;
+
 // Machine operand flags
 // M_LOOK_UP_PTR_REG_CLASS - Set if this operand is a pointer value and it
 // requires a callback to look up its register class.
@@ -97,7 +101,7 @@ public:
 class TargetInstrDescriptor {
 public:
   const char *    Name;          // Assembly language mnemonic for the opcode.
-  int             numOperands;   // Number of args; -1 if variable #args
+  unsigned        numOperands;   // Num of args (may be more if variable_ops).
   InstrSchedClass schedClass;    // enum  identifying instr sched class
   unsigned        Flags;         // flags identifying machine instr class
   unsigned        TSFlags;       // Target Specific Flag values
@@ -144,6 +148,11 @@ public:
 
   const TargetRegisterClass
   *getInstrOperandRegClass(const TargetInstrDescriptor *II, unsigned Op) const {
+    if (Op >= II->numOperands) {
+      if (II->Flags & M_VARIABLE_OPS)
+        return NULL;
+      assert(false && "Invalid operand # of instruction");
+    }
     const TargetOperandInfo &toi = II->OpInfo[Op];
     return (toi.Flags & M_LOOK_UP_PTR_REG_CLASS)
            ? getPointerRegClass() : toi.RegClass;
@@ -212,6 +221,10 @@ public:
     return get(Opcode).Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION;
   }
 
+  bool hasVariableOperands(MachineOpCode Opcode) const {
+    return get(Opcode).Flags & M_VARIABLE_OPS;
+  }
+
   /// Return true if the instruction is a register to register move
   /// and leave the source and dest operands in the passed parameters.
   virtual bool isMoveInstr(const MachineInstr& MI,
index 8003afa0ba5ae238f9ca557cb267ff71b72228ed..480364a282196790a5b39779dd987db707b37489 100644 (file)
@@ -91,7 +91,8 @@ MachineInstr *MachineInstr::removeFromParent() {
 ///
 bool MachineInstr::OperandsComplete() const {
   int NumOperands = TargetInstrDescriptors[Opcode].numOperands;
-  if (NumOperands >= 0 && getNumOperands() >= (unsigned)NumOperands)
+  if ((TargetInstrDescriptors[Opcode].Flags & M_VARIABLE_OPS) == 0 &&
+      getNumOperands() >= (unsigned)NumOperands)
     return true;  // Broken: we have all the operands of this instruction!
   return false;
 }
index 1d154017f51eb592b04ebb97879d3f553c11a6f7..5d404f0766fe4112ba5c7d64cc788a495677f597 100644 (file)
@@ -358,7 +358,8 @@ void ScheduleDAG::EmitNode(SDNode *Node,
     unsigned NodeOperands = CountOperands(Node);
     unsigned NumMIOperands = NodeOperands + NumResults;
 #ifndef NDEBUG
-    assert((unsigned(II.numOperands) == NumMIOperands || II.numOperands == -1)&&
+    assert((unsigned(II.numOperands) == NumMIOperands ||
+            (II.Flags & M_VARIABLE_OPS)) &&
            "#operands for dag node doesn't match .td file!"); 
 #endif
 
index 66d17cb86bb8cdbaf29eba682034ad291cfc7c51..f91babcf860bccc03baea8e0a5af9ee6acacc109 100644 (file)
@@ -64,9 +64,6 @@ void InstrInfoEmitter::printDefList(const std::vector<Record*> &Uses,
 
 static std::vector<Record*> GetOperandInfo(const CodeGenInstruction &Inst) {
   std::vector<Record*> Result;
-  if (Inst.hasVariableNumberOfOperands)
-    return Result;  // No info for variable operand instrs.
-
   for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) {
     if (Inst.OperandList[i].Rec->isSubClassOf("RegisterClass")) {
       Result.push_back(Inst.OperandList[i].Rec);
@@ -170,15 +167,13 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
                          std::map<std::vector<Record*>, unsigned> &EmittedLists,
                                std::map<std::vector<Record*>, unsigned> &OpInfo,
                                   std::ostream &OS) {
-  int NumOperands;
-  if (Inst.hasVariableNumberOfOperands)
-    NumOperands = -1;
-  else if (!Inst.OperandList.empty())
+  int MinOperands;
+  if (!Inst.OperandList.empty())
     // Each logical operand can be multiple MI operands.
-    NumOperands = Inst.OperandList.back().MIOperandNo +
+    MinOperands = Inst.OperandList.back().MIOperandNo +
                   Inst.OperandList.back().MINumOperands;
   else
-    NumOperands = 0;
+    MinOperands = 0;
   
   OS << "  { \"";
   if (Inst.Name.empty())
@@ -189,7 +184,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
   unsigned ItinClass = !IsItineraries ? 0 :
             ItinClassNumber(Inst.TheDef->getValueAsDef("Itinerary")->getName());
   
-  OS << "\",\t" << NumOperands << ", " << ItinClass
+  OS << "\",\t" << MinOperands << ", " << ItinClass
      << ", 0";
 
   // Try to determine (from the pattern), if the instruction is a store.
@@ -224,6 +219,8 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
   if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
   if (Inst.usesCustomDAGSchedInserter)
     OS << "|M_USES_CUSTOM_DAG_SCHED_INSERTION";
+  if (Inst.hasVariableNumberOfOperands)
+    OS << "|M_VARIABLE_OPS";
   OS << ", 0";
 
   // Emit all of the target-specific flags...