From 8d3af5e7d082dbd029c3987ceadbdcf9e49af6d7 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 15 Jun 2006 07:22:16 +0000 Subject: [PATCH] Instructions with variable operands (variable_ops) can have a number required 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 | 15 ++++++++++++++- lib/CodeGen/MachineInstr.cpp | 3 ++- lib/CodeGen/SelectionDAG/ScheduleDAG.cpp | 3 ++- utils/TableGen/InstrInfoEmitter.cpp | 17 +++++++---------- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 9e49a975bc1..6fb3274e801 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -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, diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 8003afa0ba5..480364a2821 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -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; } diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp index 1d154017f51..5d404f0766f 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp @@ -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 diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 66d17cb86bb..f91babcf860 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -64,9 +64,6 @@ void InstrInfoEmitter::printDefList(const std::vector &Uses, static std::vector GetOperandInfo(const CodeGenInstruction &Inst) { std::vector 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, unsigned> &EmittedLists, std::map, 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... -- 2.34.1