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

Tom Stellard tom at stellard.net
Thu Jun 6 18:39:54 PDT 2013


Ping

On Mon, Jun 03, 2013 at 02:23:22PM -0700, Tom Stellard wrote:
> 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
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list