[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