[PATCH 1/2] TableGen: Generate a function for getting operand indices based on their defined names

Tom Stellard tom at stellard.net
Mon Jun 3 14:23:22 PDT 2013


From: Tom Stellard <thomas.stellard at amd.com>

This patch modifies TableGen to generate a function in
${TARGET}GenInstrInfo.inc called getNamedOperandIdx(), which can be used
to look up indices for operands based on their names.

For example, if you have an instruction like:

def ADD : TargetInstr <(outs GPR:$dst), (ins GPR:$src0, GPR:$src1)>;

You can look up the operand indices using the new function, like this:

Target::getNamedOperandIdx(Target::ADD, Target::OpName::DST)  => 0
Target::getNamedOperandIdx(Target::ADD, Target::OpName::SRC0) => 1
Target::getNamedOperandIdx(Target::ADD, Target::OpName::SRC1) => 2

The operand names are case insensitive, so $dst is equivalent to $DST.

This change is useful for R600 which has instructions with a large number
of operands, many of which model single bit instruction configuration
values.  These configuration bits are common across most instructions,
but may have a different operand index depending on the instruction type.
It is useful to have a convenient way to look up the operand indices,
so these bits can be generically set on any instruction.
---
 utils/TableGen/InstrInfoEmitter.cpp | 76 +++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index d6020a8..884cce7 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -45,6 +45,8 @@ private:
   void emitEnums(raw_ostream &OS);
 
   typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
+  typedef std::map<std::vector<std::pair<std::string, unsigned> >,
+                   std::vector<std::string> > OpNameMapTy;
   void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
                   Record *InstrInfo,
                   std::map<std::vector<Record*>, unsigned> &EL,
@@ -293,6 +295,80 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
   OS << "} // End llvm namespace \n";
 
   OS << "#endif // GET_INSTRINFO_CTOR\n\n";
+
+  std::string Namespace = Target.getInstNamespace();
+  std::string OpNameNS = "OpName";
+  std::map<std::string, bool> OperandNames;
+  OpNameMapTy OperandMap;
+  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+    const CodeGenInstruction *Inst = NumberedInstructions[i];
+    std::vector<std::pair<std::string, unsigned> > OpList;
+    for (unsigned j = 0, je = Inst->Operands.size(); j != je; ++j) {
+      CGIOperandList::OperandInfo Info = Inst->Operands[j];
+      std::string Name =  Info.Name;
+      std::transform(Name.begin(), Name.end(), Name.begin(), ::toupper);
+      OperandNames[Name] = true;
+      Name = OpNameNS + "::" + Name;
+      OpList.push_back(
+                      std::pair<std::string, unsigned>(Name, Info.MIOperandNo));
+    }
+    OperandMap[OpList].push_back(Namespace + "::" + Inst->TheDef->getName());
+  }
+
+  OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n";
+  OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n";
+  OS << "namespace llvm {";
+  OS << "namespace " << Namespace << " {\n";
+  OS << "namespace " << OpNameNS << " { \n";
+  OS << "enum {\n";
+  OS << "NO_OPERAND";
+  for (std::map<std::string, bool>::iterator i = OperandNames.begin(),
+                                             e = OperandNames.end();
+                                             i != e; ++i) {
+    OS << ",\n" << i->first;
+  }
+  OS << "\n};\n";
+  OS << "} // End namespace OpName\n";
+  OS << "} // End namespace " << Namespace << "\n";
+  OS << "} // End namespace llvm\n";
+  OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n";
+
+  OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n";
+  OS << "#undef GET_INSTRINFO_NAMED_OPS\n";
+  OS << "namespace llvm {";
+  OS << "namespace " << Namespace << " {\n";
+  OS << "int getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n";
+  OS << "  switch(Opcode) {\n";
+  for (OpNameMapTy::iterator i = OperandMap.begin(), e = OperandMap.end();
+                                                     i != e; ++i) {
+    std::vector<std::pair<std::string, unsigned> > OpList = i->first;
+    std::vector<std::string> OpcodeList = i->second;
+
+    for (std::vector<std::string>::iterator ii = OpcodeList.begin(),
+                                            ie = OpcodeList.end();
+                                            ii != ie; ++ii) {
+      std::string OpName = *ii;
+      OS << "  case " << OpName << ":\n";
+    }
+    OS << "    switch(NamedIdx) {\n";
+
+    for (std::vector<std::pair<std::string, unsigned> >::iterator
+                                                   oi = OpList.begin(),
+                                                   oe = OpList.end();
+                                                   oi != oe; ++oi) {
+      std::pair<std::string, unsigned> OpPair = *oi;
+      OS << "    case " << OpPair.first << ": return "
+                                        << OpPair.second << ";\n";
+    }
+    OS << "    default: return -1;\n";
+    OS << "    }\n";
+  }
+  OS << "    default: return -1;\n";
+  OS << "  }\n";
+  OS << "}\n";
+  OS << "} // End namespace " << Namespace << "\n";
+  OS << "} // End namespace llvm\n";
+  OS << "#endif //GET_INSTRINFO_NAMED_OPS\n";
 }
 
 void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
-- 
1.7.11.4




More information about the llvm-commits mailing list