xref: /llvm-project/llvm/utils/TableGen/X86InstrMappingEmitter.cpp (revision 4e8c9d28132039a98feb97cec2759cddeb37d934)
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