//========- utils/TableGen/X86InstrMappingEmitter.cpp - X86 backend-*- C++ -*-//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// This tablegen backend is responsible for emitting the X86 backend
/// instruction mapping.
///
//===----------------------------------------------------------------------===//

#include "Common/CodeGenInstruction.h"
#include "Common/CodeGenTarget.h"
#include "X86RecognizableInstr.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <map>
#include <set>

using namespace llvm;
using namespace X86Disassembler;

namespace {

class X86InstrMappingEmitter {
  const RecordKeeper &Records;
  const CodeGenTarget Target;

  // Hold all pontentially compressible EVEX instructions
  std::vector<const CodeGenInstruction *> PreCompressionInsts;
  // Hold all compressed instructions. Divided into groups with same opcodes
  // to make the search more efficient
  std::map<uint64_t, std::vector<const CodeGenInstruction *>> CompressedInsts;

  typedef std::pair<const CodeGenInstruction *, const CodeGenInstruction *>
      Entry;
  typedef std::map<StringRef, std::vector<const CodeGenInstruction *>>
      PredicateInstMap;

  // Hold all compressed instructions that need to check predicate
  PredicateInstMap PredicateInsts;

public:
  X86InstrMappingEmitter(const RecordKeeper &R) : Records(R), Target(R) {}

  // run - Output X86 EVEX compression tables.
  void run(raw_ostream &OS);

private:
  void emitCompressEVEXTable(ArrayRef<const CodeGenInstruction *> Insts,
                             raw_ostream &OS);
  void emitNFTransformTable(ArrayRef<const CodeGenInstruction *> Insts,
                            raw_ostream &OS);
  void emitND2NonNDTable(ArrayRef<const CodeGenInstruction *> Insts,
                         raw_ostream &OS);
  void emitSSE2AVXTable(ArrayRef<const CodeGenInstruction *> Insts,
                        raw_ostream &OS);

  // Prints the definition of class X86TableEntry.
  void printClassDef(raw_ostream &OS);
  // Prints the given table as a C++ array of type X86TableEntry under the guard
  // \p Macro.
  void printTable(ArrayRef<Entry> Table, StringRef Name, StringRef Macro,
                  raw_ostream &OS);
};

void X86InstrMappingEmitter::printClassDef(raw_ostream &OS) {
  OS << "struct X86TableEntry {\n"
        "  uint16_t OldOpc;\n"
        "  uint16_t NewOpc;\n"
        "  bool operator<(const X86TableEntry &RHS) const {\n"
        "    return OldOpc < RHS.OldOpc;\n"
        "  }"
        "  friend bool operator<(const X86TableEntry &TE, unsigned Opc) {\n"
        "    return TE.OldOpc < Opc;\n"
        "  }\n"
        "};";

  OS << "\n\n";
}

static void printMacroBegin(StringRef Macro, raw_ostream &OS) {
  OS << "\n#ifdef " << Macro << "\n";
}

static void printMacroEnd(StringRef Macro, raw_ostream &OS) {
  OS << "#endif // " << Macro << "\n\n";
}

void X86InstrMappingEmitter::printTable(ArrayRef<Entry> Table, StringRef Name,
                                        StringRef Macro, raw_ostream &OS) {
  printMacroBegin(Macro, OS);

  OS << "static const X86TableEntry " << Name << "[] = {\n";

  // Print all entries added to the table
  for (const auto &Pair : Table)
    OS << "  { X86::" << Pair.first->getName()
       << ", X86::" << Pair.second->getName() << " },\n";

  OS << "};\n\n";

  printMacroEnd(Macro, OS);
}

class IsMatch {
  const CodeGenInstruction *OldInst;

public:
  IsMatch(const CodeGenInstruction *OldInst) : OldInst(OldInst) {}

  bool operator()(const CodeGenInstruction *NewInst) {
    RecognizableInstrBase NewRI(*NewInst);
    RecognizableInstrBase OldRI(*OldInst);

    // Return false if any of the following fields of does not match.
    if (std::tuple(OldRI.IsCodeGenOnly, OldRI.OpMap, NewRI.OpPrefix,
                   OldRI.HasVEX_4V, OldRI.HasVEX_L, OldRI.HasREX_W,
                   OldRI.Form) !=
        std::tuple(NewRI.IsCodeGenOnly, NewRI.OpMap, OldRI.OpPrefix,
                   NewRI.HasVEX_4V, NewRI.HasVEX_L, NewRI.HasREX_W, NewRI.Form))
      return false;

    for (unsigned I = 0, E = OldInst->Operands.size(); I < E; ++I) {
      const Record *OldOpRec = OldInst->Operands[I].Rec;
      const Record *NewOpRec = NewInst->Operands[I].Rec;

      if (OldOpRec == NewOpRec)
        continue;

      if (isRegisterOperand(OldOpRec) && isRegisterOperand(NewOpRec)) {
        if (getRegOperandSize(OldOpRec) != getRegOperandSize(NewOpRec))
          return false;
      } else if (isMemoryOperand(OldOpRec) && isMemoryOperand(NewOpRec)) {
        if (getMemOperandSize(OldOpRec) != getMemOperandSize(NewOpRec))
          return false;
      } else if (isImmediateOperand(OldOpRec) && isImmediateOperand(NewOpRec)) {
        if (OldOpRec->getValueAsDef("Type") != NewOpRec->getValueAsDef("Type"))
          return false;
      }
    }

    return true;
  }
};

static bool isInteresting(const Record *Rec) {
  // _REV instruction should not appear before encoding optimization
  return Rec->isSubClassOf("X86Inst") &&
         !Rec->getValueAsBit("isAsmParserOnly") &&
         !Rec->getName().ends_with("_REV");
}

void X86InstrMappingEmitter::emitCompressEVEXTable(
    ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {

  const std::map<StringRef, StringRef> ManualMap = {
#define ENTRY(OLD, NEW) {#OLD, #NEW},
#include "X86ManualInstrMapping.def"
  };
  const std::set<StringRef> NoCompressSet = {
#define NOCOMP(INSN) #INSN,
#include "X86ManualInstrMapping.def"
  };

  for (const CodeGenInstruction *Inst : Insts) {
    const Record *Rec = Inst->TheDef;
    StringRef Name = Rec->getName();
    if (!isInteresting(Rec))
      continue;

    // Promoted legacy instruction is in EVEX space, and has REX2-encoding
    // alternative. It's added due to HW design and never emitted by compiler.
    if (byteFromBitsInit(Rec->getValueAsBitsInit("OpMapBits")) ==
            X86Local::T_MAP4 &&
        byteFromBitsInit(Rec->getValueAsBitsInit("explicitOpPrefixBits")) ==
            X86Local::ExplicitEVEX)
      continue;

    if (NoCompressSet.find(Name) != NoCompressSet.end())
      continue;

    RecognizableInstrBase RI(*Inst);

    bool IsND = RI.OpMap == X86Local::T_MAP4 && RI.HasEVEX_B && RI.HasVEX_4V;
    // Add VEX encoded instructions to one of CompressedInsts vectors according
    // to it's opcode.
    if (RI.Encoding == X86Local::VEX)
      CompressedInsts[RI.Opcode].push_back(Inst);
    // Add relevant EVEX encoded instructions to PreCompressionInsts
    else if (RI.Encoding == X86Local::EVEX && !RI.HasEVEX_K && !RI.HasEVEX_L2 &&
             (!RI.HasEVEX_B || IsND))
      PreCompressionInsts.push_back(Inst);
  }

  std::vector<Entry> Table;
  for (const CodeGenInstruction *Inst : PreCompressionInsts) {
    const Record *Rec = Inst->TheDef;
    uint8_t Opcode = byteFromBitsInit(Rec->getValueAsBitsInit("Opcode"));
    StringRef Name = Rec->getName();
    const CodeGenInstruction *NewInst = nullptr;
    if (ManualMap.find(Name) != ManualMap.end()) {
      const Record *NewRec = Records.getDef(ManualMap.at(Rec->getName()));
      assert(NewRec && "Instruction not found!");
      NewInst = &Target.getInstruction(NewRec);
    } else if (Name.ends_with("_EVEX")) {
      if (const auto *NewRec = Records.getDef(Name.drop_back(5)))
        NewInst = &Target.getInstruction(NewRec);
    } else if (Name.ends_with("_ND"))
      // Leave it to ND2NONND table.
      continue;
    else {
      // For each pre-compression instruction look for a match in the
      // appropriate vector (instructions with the same opcode) using function
      // object IsMatch.
      const auto &Insts = CompressedInsts[Opcode];
      auto Match = llvm::find_if(Insts, IsMatch(Inst));
      if (Match != Insts.end())
        NewInst = *Match;
    }

    if (!NewInst)
      continue;

    Table.emplace_back(Inst, NewInst);
    auto Predicates = NewInst->TheDef->getValueAsListOfDefs("Predicates");
    auto It = llvm::find_if(Predicates, [](const Record *R) {
      StringRef Name = R->getName();
      return Name == "HasAVXNECONVERT" || Name == "HasAVXVNNI" ||
             Name == "HasAVXIFMA" || Name == "HasAVXVNNIINT8" ||
             Name == "HasAVXVNNIINT16";
    });
    if (It != Predicates.end())
      PredicateInsts[(*It)->getValueAsString("CondString")].push_back(NewInst);
  }

  StringRef Macro = "GET_X86_COMPRESS_EVEX_TABLE";
  printTable(Table, "X86CompressEVEXTable", Macro, OS);

  // Prints function which checks target feature for compressed instructions.
  printMacroBegin(Macro, OS);
  OS << "static bool checkPredicate(unsigned Opc, const X86Subtarget "
        "*Subtarget) {\n"
     << "  switch (Opc) {\n"
     << "  default: return true;\n";
  for (const auto &[Key, Val] : PredicateInsts) {
    for (const auto &Inst : Val)
      OS << "  case X86::" << Inst->getName() << ":\n";
    OS << "    return " << Key << ";\n";
  }
  OS << "  }\n";
  OS << "}\n\n";
  printMacroEnd(Macro, OS);
}

void X86InstrMappingEmitter::emitNFTransformTable(
    ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {
  std::vector<Entry> Table;
  for (const CodeGenInstruction *Inst : Insts) {
    const Record *Rec = Inst->TheDef;
    if (!isInteresting(Rec))
      continue;
    StringRef Name = Rec->getName();
    if (Name.contains("_NF"))
      continue;

    if (auto *NewRec = Name.consume_back("_ND")
                           ? Records.getDef(Name.str() + "_NF_ND")
                           : Records.getDef(Name.str() + "_NF")) {
#ifndef NDEBUG
      auto ClobberEFLAGS = [](const Record *R) {
        return llvm::any_of(
            R->getValueAsListOfDefs("Defs"),
            [](const Record *Def) { return Def->getName() == "EFLAGS"; });
      };
      if (ClobberEFLAGS(NewRec))
        report_fatal_error("EFLAGS should not be clobbered by " +
                           NewRec->getName());
      if (!ClobberEFLAGS(Rec))
        report_fatal_error("EFLAGS should be clobbered by " + Rec->getName());
#endif
      Table.emplace_back(Inst, &Target.getInstruction(NewRec));
    }
  }
  printTable(Table, "X86NFTransformTable", "GET_X86_NF_TRANSFORM_TABLE", OS);
}

void X86InstrMappingEmitter::emitND2NonNDTable(
    ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {

  const std::map<StringRef, StringRef> ManualMap = {
#define ENTRY_ND(OLD, NEW) {#OLD, #NEW},
#include "X86ManualInstrMapping.def"
  };
  const std::set<StringRef> NoCompressSet = {
#define NOCOMP_ND(INSN) #INSN,
#include "X86ManualInstrMapping.def"
  };

  std::vector<Entry> Table;
  for (const CodeGenInstruction *Inst : Insts) {
    const Record *Rec = Inst->TheDef;
    StringRef Name = Rec->getName();
    if (!isInteresting(Rec) || NoCompressSet.find(Name) != NoCompressSet.end())
      continue;
    if (ManualMap.find(Name) != ManualMap.end()) {
      const auto *NewRec = Records.getDef(ManualMap.at(Rec->getName()));
      assert(NewRec && "Instruction not found!");
      auto &NewInst = Target.getInstruction(NewRec);
      Table.emplace_back(Inst, &NewInst);
      continue;
    }

    if (!Name.ends_with("_ND"))
      continue;
    const auto *NewRec = Records.getDef(Name.drop_back(3));
    if (!NewRec)
      continue;
    const auto &NewInst = Target.getInstruction(NewRec);
    if (isRegisterOperand(NewInst.Operands[0].Rec))
      Table.emplace_back(Inst, &NewInst);
  }
  printTable(Table, "X86ND2NonNDTable", "GET_X86_ND2NONND_TABLE", OS);
}

void X86InstrMappingEmitter::emitSSE2AVXTable(
    ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {

  const std::map<StringRef, StringRef> ManualMap = {
#define ENTRY_SSE2AVX(OLD, NEW) {#OLD, #NEW},
#include "X86ManualInstrMapping.def"
  };

  std::vector<Entry> Table;
  for (const CodeGenInstruction *Inst : Insts) {
    const Record *Rec = Inst->TheDef;
    StringRef Name = Rec->getName();
    if (!isInteresting(Rec))
      continue;
    if (ManualMap.find(Name) != ManualMap.end()) {
      const auto *NewRec = Records.getDef(ManualMap.at(Rec->getName()));
      assert(NewRec && "Instruction not found!");
      const auto &NewInst = Target.getInstruction(NewRec);
      Table.emplace_back(Inst, &NewInst);
      continue;
    }

    std::string NewName = ("V" + Name).str();
    const auto *AVXRec = Records.getDef(NewName);
    if (!AVXRec)
      continue;
    auto &AVXInst = Target.getInstruction(AVXRec);
    Table.emplace_back(Inst, &AVXInst);
  }
  printTable(Table, "X86SSE2AVXTable", "GET_X86_SSE2AVX_TABLE", OS);
}

void X86InstrMappingEmitter::run(raw_ostream &OS) {
  emitSourceFileHeader("X86 instruction mapping", OS);

  ArrayRef<const CodeGenInstruction *> Insts = Target.getInstructions();
  printClassDef(OS);
  emitCompressEVEXTable(Insts, OS);
  emitNFTransformTable(Insts, OS);
  emitND2NonNDTable(Insts, OS);
  emitSSE2AVXTable(Insts, OS);
}
} // namespace

static TableGen::Emitter::OptClass<X86InstrMappingEmitter>
    X("gen-x86-instr-mapping", "Generate X86 instruction mapping");
