117ecd23fSShengchen Kan //========- utils/TableGen/X86InstrMappingEmitter.cpp - X86 backend-*- C++ -*-// 217ecd23fSShengchen Kan // 317ecd23fSShengchen Kan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 417ecd23fSShengchen Kan // See https://llvm.org/LICENSE.txt for license information. 517ecd23fSShengchen Kan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 617ecd23fSShengchen Kan // 717ecd23fSShengchen Kan //===----------------------------------------------------------------------===// 817ecd23fSShengchen Kan /// 917ecd23fSShengchen Kan /// This tablegen backend is responsible for emitting the X86 backend 1017ecd23fSShengchen Kan /// instruction mapping. 1117ecd23fSShengchen Kan /// 1217ecd23fSShengchen Kan //===----------------------------------------------------------------------===// 1317ecd23fSShengchen Kan 1417ecd23fSShengchen Kan #include "Common/CodeGenInstruction.h" 1517ecd23fSShengchen Kan #include "Common/CodeGenTarget.h" 1617ecd23fSShengchen Kan #include "X86RecognizableInstr.h" 1717ecd23fSShengchen Kan #include "llvm/TableGen/Error.h" 1817ecd23fSShengchen Kan #include "llvm/TableGen/Record.h" 1917ecd23fSShengchen Kan #include "llvm/TableGen/TableGenBackend.h" 2017ecd23fSShengchen Kan #include <map> 2117ecd23fSShengchen Kan #include <set> 2217ecd23fSShengchen Kan 2317ecd23fSShengchen Kan using namespace llvm; 2417ecd23fSShengchen Kan using namespace X86Disassembler; 2517ecd23fSShengchen Kan 2617ecd23fSShengchen Kan namespace { 2717ecd23fSShengchen Kan 2817ecd23fSShengchen Kan class X86InstrMappingEmitter { 291a793a8cSRahul Joshi const RecordKeeper &Records; 301a793a8cSRahul Joshi const CodeGenTarget Target; 3117ecd23fSShengchen Kan 3217ecd23fSShengchen Kan // Hold all pontentially compressible EVEX instructions 3317ecd23fSShengchen Kan std::vector<const CodeGenInstruction *> PreCompressionInsts; 3417ecd23fSShengchen Kan // Hold all compressed instructions. Divided into groups with same opcodes 3517ecd23fSShengchen Kan // to make the search more efficient 3617ecd23fSShengchen Kan std::map<uint64_t, std::vector<const CodeGenInstruction *>> CompressedInsts; 3717ecd23fSShengchen Kan 3817ecd23fSShengchen Kan typedef std::pair<const CodeGenInstruction *, const CodeGenInstruction *> 3917ecd23fSShengchen Kan Entry; 4017ecd23fSShengchen Kan typedef std::map<StringRef, std::vector<const CodeGenInstruction *>> 4117ecd23fSShengchen Kan PredicateInstMap; 4217ecd23fSShengchen Kan 4317ecd23fSShengchen Kan // Hold all compressed instructions that need to check predicate 4417ecd23fSShengchen Kan PredicateInstMap PredicateInsts; 4517ecd23fSShengchen Kan 4617ecd23fSShengchen Kan public: 471a793a8cSRahul Joshi X86InstrMappingEmitter(const RecordKeeper &R) : Records(R), Target(R) {} 4817ecd23fSShengchen Kan 4917ecd23fSShengchen Kan // run - Output X86 EVEX compression tables. 5017ecd23fSShengchen Kan void run(raw_ostream &OS); 5117ecd23fSShengchen Kan 5217ecd23fSShengchen Kan private: 5317ecd23fSShengchen Kan void emitCompressEVEXTable(ArrayRef<const CodeGenInstruction *> Insts, 5417ecd23fSShengchen Kan raw_ostream &OS); 5517ecd23fSShengchen Kan void emitNFTransformTable(ArrayRef<const CodeGenInstruction *> Insts, 5617ecd23fSShengchen Kan raw_ostream &OS); 5722c572eaSShengchen Kan void emitND2NonNDTable(ArrayRef<const CodeGenInstruction *> Insts, 5822c572eaSShengchen Kan raw_ostream &OS); 59bddab518SJaydeepChauhan14 void emitSSE2AVXTable(ArrayRef<const CodeGenInstruction *> Insts, 60bddab518SJaydeepChauhan14 raw_ostream &OS); 6117ecd23fSShengchen Kan 6217ecd23fSShengchen Kan // Prints the definition of class X86TableEntry. 6317ecd23fSShengchen Kan void printClassDef(raw_ostream &OS); 6417ecd23fSShengchen Kan // Prints the given table as a C++ array of type X86TableEntry under the guard 6517ecd23fSShengchen Kan // \p Macro. 661a793a8cSRahul Joshi void printTable(ArrayRef<Entry> Table, StringRef Name, StringRef Macro, 671a793a8cSRahul Joshi raw_ostream &OS); 6817ecd23fSShengchen Kan }; 6917ecd23fSShengchen Kan 7017ecd23fSShengchen Kan void X86InstrMappingEmitter::printClassDef(raw_ostream &OS) { 7117ecd23fSShengchen Kan OS << "struct X86TableEntry {\n" 7217ecd23fSShengchen Kan " uint16_t OldOpc;\n" 7317ecd23fSShengchen Kan " uint16_t NewOpc;\n" 7417ecd23fSShengchen Kan " bool operator<(const X86TableEntry &RHS) const {\n" 7517ecd23fSShengchen Kan " return OldOpc < RHS.OldOpc;\n" 7617ecd23fSShengchen Kan " }" 7717ecd23fSShengchen Kan " friend bool operator<(const X86TableEntry &TE, unsigned Opc) {\n" 7817ecd23fSShengchen Kan " return TE.OldOpc < Opc;\n" 7917ecd23fSShengchen Kan " }\n" 8017ecd23fSShengchen Kan "};"; 8117ecd23fSShengchen Kan 8217ecd23fSShengchen Kan OS << "\n\n"; 8317ecd23fSShengchen Kan } 8417ecd23fSShengchen Kan 8517ecd23fSShengchen Kan static void printMacroBegin(StringRef Macro, raw_ostream &OS) { 8617ecd23fSShengchen Kan OS << "\n#ifdef " << Macro << "\n"; 8717ecd23fSShengchen Kan } 8817ecd23fSShengchen Kan 8917ecd23fSShengchen Kan static void printMacroEnd(StringRef Macro, raw_ostream &OS) { 9017ecd23fSShengchen Kan OS << "#endif // " << Macro << "\n\n"; 9117ecd23fSShengchen Kan } 9217ecd23fSShengchen Kan 931a793a8cSRahul Joshi void X86InstrMappingEmitter::printTable(ArrayRef<Entry> Table, StringRef Name, 941a793a8cSRahul Joshi StringRef Macro, raw_ostream &OS) { 9517ecd23fSShengchen Kan printMacroBegin(Macro, OS); 9617ecd23fSShengchen Kan 9717ecd23fSShengchen Kan OS << "static const X86TableEntry " << Name << "[] = {\n"; 9817ecd23fSShengchen Kan 9917ecd23fSShengchen Kan // Print all entries added to the table 10017ecd23fSShengchen Kan for (const auto &Pair : Table) 10117ecd23fSShengchen Kan OS << " { X86::" << Pair.first->TheDef->getName() 10217ecd23fSShengchen Kan << ", X86::" << Pair.second->TheDef->getName() << " },\n"; 10317ecd23fSShengchen Kan 10417ecd23fSShengchen Kan OS << "};\n\n"; 10517ecd23fSShengchen Kan 10617ecd23fSShengchen Kan printMacroEnd(Macro, OS); 10717ecd23fSShengchen Kan } 10817ecd23fSShengchen Kan 10917ecd23fSShengchen Kan static uint8_t byteFromBitsInit(const BitsInit *B) { 11017ecd23fSShengchen Kan unsigned N = B->getNumBits(); 11117ecd23fSShengchen Kan assert(N <= 8 && "Field is too large for uint8_t!"); 11217ecd23fSShengchen Kan 11317ecd23fSShengchen Kan uint8_t Value = 0; 11417ecd23fSShengchen Kan for (unsigned I = 0; I != N; ++I) { 11562e2c7fbSRahul Joshi const BitInit *Bit = cast<BitInit>(B->getBit(I)); 11617ecd23fSShengchen Kan Value |= Bit->getValue() << I; 11717ecd23fSShengchen Kan } 11817ecd23fSShengchen Kan return Value; 11917ecd23fSShengchen Kan } 12017ecd23fSShengchen Kan 12117ecd23fSShengchen Kan class IsMatch { 12217ecd23fSShengchen Kan const CodeGenInstruction *OldInst; 12317ecd23fSShengchen Kan 12417ecd23fSShengchen Kan public: 12517ecd23fSShengchen Kan IsMatch(const CodeGenInstruction *OldInst) : OldInst(OldInst) {} 12617ecd23fSShengchen Kan 12717ecd23fSShengchen Kan bool operator()(const CodeGenInstruction *NewInst) { 12817ecd23fSShengchen Kan RecognizableInstrBase NewRI(*NewInst); 12917ecd23fSShengchen Kan RecognizableInstrBase OldRI(*OldInst); 13017ecd23fSShengchen Kan 13117ecd23fSShengchen Kan // Return false if any of the following fields of does not match. 13217ecd23fSShengchen Kan if (std::tuple(OldRI.IsCodeGenOnly, OldRI.OpMap, NewRI.OpPrefix, 13317ecd23fSShengchen Kan OldRI.HasVEX_4V, OldRI.HasVEX_L, OldRI.HasREX_W, 13417ecd23fSShengchen Kan OldRI.Form) != 13517ecd23fSShengchen Kan std::tuple(NewRI.IsCodeGenOnly, NewRI.OpMap, OldRI.OpPrefix, 13617ecd23fSShengchen Kan NewRI.HasVEX_4V, NewRI.HasVEX_L, NewRI.HasREX_W, NewRI.Form)) 13717ecd23fSShengchen Kan return false; 13817ecd23fSShengchen Kan 13917ecd23fSShengchen Kan for (unsigned I = 0, E = OldInst->Operands.size(); I < E; ++I) { 140bdf02249SRahul Joshi const Record *OldOpRec = OldInst->Operands[I].Rec; 141bdf02249SRahul Joshi const Record *NewOpRec = NewInst->Operands[I].Rec; 14217ecd23fSShengchen Kan 14317ecd23fSShengchen Kan if (OldOpRec == NewOpRec) 14417ecd23fSShengchen Kan continue; 14517ecd23fSShengchen Kan 14617ecd23fSShengchen Kan if (isRegisterOperand(OldOpRec) && isRegisterOperand(NewOpRec)) { 14717ecd23fSShengchen Kan if (getRegOperandSize(OldOpRec) != getRegOperandSize(NewOpRec)) 14817ecd23fSShengchen Kan return false; 14917ecd23fSShengchen Kan } else if (isMemoryOperand(OldOpRec) && isMemoryOperand(NewOpRec)) { 15017ecd23fSShengchen Kan if (getMemOperandSize(OldOpRec) != getMemOperandSize(NewOpRec)) 15117ecd23fSShengchen Kan return false; 15217ecd23fSShengchen Kan } else if (isImmediateOperand(OldOpRec) && isImmediateOperand(NewOpRec)) { 15317ecd23fSShengchen Kan if (OldOpRec->getValueAsDef("Type") != NewOpRec->getValueAsDef("Type")) 15417ecd23fSShengchen Kan return false; 15517ecd23fSShengchen Kan } 15617ecd23fSShengchen Kan } 15717ecd23fSShengchen Kan 15817ecd23fSShengchen Kan return true; 15917ecd23fSShengchen Kan } 16017ecd23fSShengchen Kan }; 16117ecd23fSShengchen Kan 16217ecd23fSShengchen Kan static bool isInteresting(const Record *Rec) { 16317ecd23fSShengchen Kan // _REV instruction should not appear before encoding optimization 16417ecd23fSShengchen Kan return Rec->isSubClassOf("X86Inst") && 16517ecd23fSShengchen Kan !Rec->getValueAsBit("isAsmParserOnly") && 16617ecd23fSShengchen Kan !Rec->getName().ends_with("_REV"); 16717ecd23fSShengchen Kan } 16817ecd23fSShengchen Kan 16917ecd23fSShengchen Kan void X86InstrMappingEmitter::emitCompressEVEXTable( 17017ecd23fSShengchen Kan ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) { 171bdc7840cSShengchen Kan 172bdc7840cSShengchen Kan const std::map<StringRef, StringRef> ManualMap = { 173bdc7840cSShengchen Kan #define ENTRY(OLD, NEW) {#OLD, #NEW}, 174bdc7840cSShengchen Kan #include "X86ManualInstrMapping.def" 175bdc7840cSShengchen Kan }; 176bdc7840cSShengchen Kan const std::set<StringRef> NoCompressSet = { 177bdc7840cSShengchen Kan #define NOCOMP(INSN) #INSN, 178bdc7840cSShengchen Kan #include "X86ManualInstrMapping.def" 179bdc7840cSShengchen Kan }; 180bdc7840cSShengchen Kan 18117ecd23fSShengchen Kan for (const CodeGenInstruction *Inst : Insts) { 18217ecd23fSShengchen Kan const Record *Rec = Inst->TheDef; 18317ecd23fSShengchen Kan StringRef Name = Rec->getName(); 18417ecd23fSShengchen Kan if (!isInteresting(Rec)) 18517ecd23fSShengchen Kan continue; 18617ecd23fSShengchen Kan 18717ecd23fSShengchen Kan // Promoted legacy instruction is in EVEX space, and has REX2-encoding 18817ecd23fSShengchen Kan // alternative. It's added due to HW design and never emitted by compiler. 18917ecd23fSShengchen Kan if (byteFromBitsInit(Rec->getValueAsBitsInit("OpMapBits")) == 19017ecd23fSShengchen Kan X86Local::T_MAP4 && 19117ecd23fSShengchen Kan byteFromBitsInit(Rec->getValueAsBitsInit("explicitOpPrefixBits")) == 19217ecd23fSShengchen Kan X86Local::ExplicitEVEX) 19317ecd23fSShengchen Kan continue; 19417ecd23fSShengchen Kan 19517ecd23fSShengchen Kan if (NoCompressSet.find(Name) != NoCompressSet.end()) 19617ecd23fSShengchen Kan continue; 19717ecd23fSShengchen Kan 19817ecd23fSShengchen Kan RecognizableInstrBase RI(*Inst); 19917ecd23fSShengchen Kan 20017ecd23fSShengchen Kan bool IsND = RI.OpMap == X86Local::T_MAP4 && RI.HasEVEX_B && RI.HasVEX_4V; 20117ecd23fSShengchen Kan // Add VEX encoded instructions to one of CompressedInsts vectors according 20217ecd23fSShengchen Kan // to it's opcode. 20317ecd23fSShengchen Kan if (RI.Encoding == X86Local::VEX) 20417ecd23fSShengchen Kan CompressedInsts[RI.Opcode].push_back(Inst); 20517ecd23fSShengchen Kan // Add relevant EVEX encoded instructions to PreCompressionInsts 20617ecd23fSShengchen Kan else if (RI.Encoding == X86Local::EVEX && !RI.HasEVEX_K && !RI.HasEVEX_L2 && 20717ecd23fSShengchen Kan (!RI.HasEVEX_B || IsND)) 20817ecd23fSShengchen Kan PreCompressionInsts.push_back(Inst); 20917ecd23fSShengchen Kan } 21017ecd23fSShengchen Kan 21117ecd23fSShengchen Kan std::vector<Entry> Table; 21217ecd23fSShengchen Kan for (const CodeGenInstruction *Inst : PreCompressionInsts) { 21317ecd23fSShengchen Kan const Record *Rec = Inst->TheDef; 21417ecd23fSShengchen Kan uint8_t Opcode = byteFromBitsInit(Rec->getValueAsBitsInit("Opcode")); 21517ecd23fSShengchen Kan StringRef Name = Rec->getName(); 21617ecd23fSShengchen Kan const CodeGenInstruction *NewInst = nullptr; 21717ecd23fSShengchen Kan if (ManualMap.find(Name) != ManualMap.end()) { 21832719c48SRahul Joshi const Record *NewRec = Records.getDef(ManualMap.at(Rec->getName())); 21917ecd23fSShengchen Kan assert(NewRec && "Instruction not found!"); 22017ecd23fSShengchen Kan NewInst = &Target.getInstruction(NewRec); 22117ecd23fSShengchen Kan } else if (Name.ends_with("_EVEX")) { 2221a793a8cSRahul Joshi if (const auto *NewRec = Records.getDef(Name.drop_back(5))) 22317ecd23fSShengchen Kan NewInst = &Target.getInstruction(NewRec); 224bdc7840cSShengchen Kan } else if (Name.ends_with("_ND")) 225bdc7840cSShengchen Kan // Leave it to ND2NONND table. 226bdc7840cSShengchen Kan continue; 227bdc7840cSShengchen Kan else { 22817ecd23fSShengchen Kan // For each pre-compression instruction look for a match in the 22917ecd23fSShengchen Kan // appropriate vector (instructions with the same opcode) using function 23017ecd23fSShengchen Kan // object IsMatch. 23117ecd23fSShengchen Kan auto Match = llvm::find_if(CompressedInsts[Opcode], IsMatch(Inst)); 23217ecd23fSShengchen Kan if (Match != CompressedInsts[Opcode].end()) 23317ecd23fSShengchen Kan NewInst = *Match; 23417ecd23fSShengchen Kan } 23517ecd23fSShengchen Kan 23617ecd23fSShengchen Kan if (!NewInst) 23717ecd23fSShengchen Kan continue; 23817ecd23fSShengchen Kan 239*4e8c9d28SJay Foad Table.emplace_back(Inst, NewInst); 24017ecd23fSShengchen Kan auto Predicates = NewInst->TheDef->getValueAsListOfDefs("Predicates"); 24117ecd23fSShengchen Kan auto It = llvm::find_if(Predicates, [](const Record *R) { 24217ecd23fSShengchen Kan StringRef Name = R->getName(); 24317ecd23fSShengchen Kan return Name == "HasAVXNECONVERT" || Name == "HasAVXVNNI" || 244b0329206SPhoebe Wang Name == "HasAVXIFMA" || Name == "HasAVXVNNIINT8" || 245b0329206SPhoebe Wang Name == "HasAVXVNNIINT16"; 24617ecd23fSShengchen Kan }); 24717ecd23fSShengchen Kan if (It != Predicates.end()) 24817ecd23fSShengchen Kan PredicateInsts[(*It)->getValueAsString("CondString")].push_back(NewInst); 24917ecd23fSShengchen Kan } 25017ecd23fSShengchen Kan 25117ecd23fSShengchen Kan StringRef Macro = "GET_X86_COMPRESS_EVEX_TABLE"; 25217ecd23fSShengchen Kan printTable(Table, "X86CompressEVEXTable", Macro, OS); 25317ecd23fSShengchen Kan 25417ecd23fSShengchen Kan // Prints function which checks target feature for compressed instructions. 25517ecd23fSShengchen Kan printMacroBegin(Macro, OS); 25617ecd23fSShengchen Kan OS << "static bool checkPredicate(unsigned Opc, const X86Subtarget " 25717ecd23fSShengchen Kan "*Subtarget) {\n" 25817ecd23fSShengchen Kan << " switch (Opc) {\n" 25917ecd23fSShengchen Kan << " default: return true;\n"; 26017ecd23fSShengchen Kan for (const auto &[Key, Val] : PredicateInsts) { 26117ecd23fSShengchen Kan for (const auto &Inst : Val) 26217ecd23fSShengchen Kan OS << " case X86::" << Inst->TheDef->getName() << ":\n"; 26317ecd23fSShengchen Kan OS << " return " << Key << ";\n"; 26417ecd23fSShengchen Kan } 26517ecd23fSShengchen Kan OS << " }\n"; 26617ecd23fSShengchen Kan OS << "}\n\n"; 26717ecd23fSShengchen Kan printMacroEnd(Macro, OS); 26817ecd23fSShengchen Kan } 26917ecd23fSShengchen Kan 27017ecd23fSShengchen Kan void X86InstrMappingEmitter::emitNFTransformTable( 27117ecd23fSShengchen Kan ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) { 27217ecd23fSShengchen Kan std::vector<Entry> Table; 27317ecd23fSShengchen Kan for (const CodeGenInstruction *Inst : Insts) { 27417ecd23fSShengchen Kan const Record *Rec = Inst->TheDef; 27517ecd23fSShengchen Kan if (!isInteresting(Rec)) 27617ecd23fSShengchen Kan continue; 27717ecd23fSShengchen Kan std::string Name = Rec->getName().str(); 27817ecd23fSShengchen Kan auto Pos = Name.find("_NF"); 27917ecd23fSShengchen Kan if (Pos == std::string::npos) 28017ecd23fSShengchen Kan continue; 28117ecd23fSShengchen Kan 2825988c798SShengchen Kan if (auto *NewRec = Records.getDef(Name.erase(Pos, 3))) { 2835988c798SShengchen Kan #ifndef NDEBUG 2845988c798SShengchen Kan auto ClobberEFLAGS = [](const Record *R) { 2855988c798SShengchen Kan return llvm::any_of( 2865988c798SShengchen Kan R->getValueAsListOfDefs("Defs"), 2875988c798SShengchen Kan [](const Record *Def) { return Def->getName() == "EFLAGS"; }); 2885988c798SShengchen Kan }; 2895988c798SShengchen Kan if (ClobberEFLAGS(Rec)) 2905988c798SShengchen Kan report_fatal_error("EFLAGS should not be clobbered by " + 2915988c798SShengchen Kan Rec->getName()); 2925988c798SShengchen Kan if (!ClobberEFLAGS(NewRec)) 2935988c798SShengchen Kan report_fatal_error("EFLAGS should be clobbered by " + 2945988c798SShengchen Kan NewRec->getName()); 2955988c798SShengchen Kan #endif 296*4e8c9d28SJay Foad Table.emplace_back(&Target.getInstruction(NewRec), Inst); 29717ecd23fSShengchen Kan } 2985988c798SShengchen Kan } 29917ecd23fSShengchen Kan printTable(Table, "X86NFTransformTable", "GET_X86_NF_TRANSFORM_TABLE", OS); 30017ecd23fSShengchen Kan } 30117ecd23fSShengchen Kan 30222c572eaSShengchen Kan void X86InstrMappingEmitter::emitND2NonNDTable( 30322c572eaSShengchen Kan ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) { 304bdc7840cSShengchen Kan 305bdc7840cSShengchen Kan const std::map<StringRef, StringRef> ManualMap = { 306bdc7840cSShengchen Kan #define ENTRY_ND(OLD, NEW) {#OLD, #NEW}, 307bdc7840cSShengchen Kan #include "X86ManualInstrMapping.def" 308bdc7840cSShengchen Kan }; 309bdc7840cSShengchen Kan const std::set<StringRef> NoCompressSet = { 310bdc7840cSShengchen Kan #define NOCOMP_ND(INSN) #INSN, 311bdc7840cSShengchen Kan #include "X86ManualInstrMapping.def" 312bdc7840cSShengchen Kan }; 313bdc7840cSShengchen Kan 31422c572eaSShengchen Kan std::vector<Entry> Table; 31522c572eaSShengchen Kan for (const CodeGenInstruction *Inst : Insts) { 31622c572eaSShengchen Kan const Record *Rec = Inst->TheDef; 31722c572eaSShengchen Kan StringRef Name = Rec->getName(); 318bdc7840cSShengchen Kan if (!isInteresting(Rec) || NoCompressSet.find(Name) != NoCompressSet.end()) 319bdc7840cSShengchen Kan continue; 320bdc7840cSShengchen Kan if (ManualMap.find(Name) != ManualMap.end()) { 3211a793a8cSRahul Joshi const auto *NewRec = Records.getDef(ManualMap.at(Rec->getName())); 322bdc7840cSShengchen Kan assert(NewRec && "Instruction not found!"); 323bdc7840cSShengchen Kan auto &NewInst = Target.getInstruction(NewRec); 324*4e8c9d28SJay Foad Table.emplace_back(Inst, &NewInst); 325bdc7840cSShengchen Kan continue; 326bdc7840cSShengchen Kan } 327bdc7840cSShengchen Kan 328bdc7840cSShengchen Kan if (!Name.ends_with("_ND")) 32922c572eaSShengchen Kan continue; 3301a793a8cSRahul Joshi const auto *NewRec = Records.getDef(Name.drop_back(3)); 33122c572eaSShengchen Kan if (!NewRec) 33222c572eaSShengchen Kan continue; 3331a793a8cSRahul Joshi const auto &NewInst = Target.getInstruction(NewRec); 33422c572eaSShengchen Kan if (isRegisterOperand(NewInst.Operands[0].Rec)) 335*4e8c9d28SJay Foad Table.emplace_back(Inst, &NewInst); 33622c572eaSShengchen Kan } 33722c572eaSShengchen Kan printTable(Table, "X86ND2NonNDTable", "GET_X86_ND2NONND_TABLE", OS); 33822c572eaSShengchen Kan } 33922c572eaSShengchen Kan 340bddab518SJaydeepChauhan14 void X86InstrMappingEmitter::emitSSE2AVXTable( 341bddab518SJaydeepChauhan14 ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) { 342bddab518SJaydeepChauhan14 343bddab518SJaydeepChauhan14 const std::map<StringRef, StringRef> ManualMap = { 344bddab518SJaydeepChauhan14 #define ENTRY_SSE2AVX(OLD, NEW) {#OLD, #NEW}, 345bddab518SJaydeepChauhan14 #include "X86ManualInstrMapping.def" 346bddab518SJaydeepChauhan14 }; 347bddab518SJaydeepChauhan14 348bddab518SJaydeepChauhan14 std::vector<Entry> Table; 349bddab518SJaydeepChauhan14 for (const CodeGenInstruction *Inst : Insts) { 350bddab518SJaydeepChauhan14 const Record *Rec = Inst->TheDef; 351bddab518SJaydeepChauhan14 StringRef Name = Rec->getName(); 352bddab518SJaydeepChauhan14 if (!isInteresting(Rec)) 353bddab518SJaydeepChauhan14 continue; 354bddab518SJaydeepChauhan14 if (ManualMap.find(Name) != ManualMap.end()) { 3551a793a8cSRahul Joshi const auto *NewRec = Records.getDef(ManualMap.at(Rec->getName())); 356bddab518SJaydeepChauhan14 assert(NewRec && "Instruction not found!"); 3571a793a8cSRahul Joshi const auto &NewInst = Target.getInstruction(NewRec); 358*4e8c9d28SJay Foad Table.emplace_back(Inst, &NewInst); 359bddab518SJaydeepChauhan14 continue; 360bddab518SJaydeepChauhan14 } 361bddab518SJaydeepChauhan14 362bddab518SJaydeepChauhan14 std::string NewName = ("V" + Name).str(); 3631a793a8cSRahul Joshi const auto *AVXRec = Records.getDef(NewName); 364bddab518SJaydeepChauhan14 if (!AVXRec) 365bddab518SJaydeepChauhan14 continue; 366bddab518SJaydeepChauhan14 auto &AVXInst = Target.getInstruction(AVXRec); 367*4e8c9d28SJay Foad Table.emplace_back(Inst, &AVXInst); 368bddab518SJaydeepChauhan14 } 369bddab518SJaydeepChauhan14 printTable(Table, "X86SSE2AVXTable", "GET_X86_SSE2AVX_TABLE", OS); 370bddab518SJaydeepChauhan14 } 371bddab518SJaydeepChauhan14 37217ecd23fSShengchen Kan void X86InstrMappingEmitter::run(raw_ostream &OS) { 37317ecd23fSShengchen Kan emitSourceFileHeader("X86 instruction mapping", OS); 37417ecd23fSShengchen Kan 37517ecd23fSShengchen Kan ArrayRef<const CodeGenInstruction *> Insts = 37617ecd23fSShengchen Kan Target.getInstructionsByEnumValue(); 37717ecd23fSShengchen Kan printClassDef(OS); 37817ecd23fSShengchen Kan emitCompressEVEXTable(Insts, OS); 37917ecd23fSShengchen Kan emitNFTransformTable(Insts, OS); 38022c572eaSShengchen Kan emitND2NonNDTable(Insts, OS); 381bddab518SJaydeepChauhan14 emitSSE2AVXTable(Insts, OS); 38217ecd23fSShengchen Kan } 38317ecd23fSShengchen Kan } // namespace 38417ecd23fSShengchen Kan 38517ecd23fSShengchen Kan static TableGen::Emitter::OptClass<X86InstrMappingEmitter> 38617ecd23fSShengchen Kan X("gen-x86-instr-mapping", "Generate X86 instruction mapping"); 387