X86EVEX2VEXTablesEmitter.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. //===- utils/TableGen/X86EVEX2VEXTablesEmitter.cpp - X86 backend-*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// This tablegen backend is responsible for emitting the X86 backend EVEX2VEX
  10. /// compression tables.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13. #include "CodeGenTarget.h"
  14. #include "llvm/TableGen/Error.h"
  15. #include "llvm/TableGen/TableGenBackend.h"
  16. using namespace llvm;
  17. namespace {
  18. class X86EVEX2VEXTablesEmitter {
  19. RecordKeeper &Records;
  20. CodeGenTarget Target;
  21. // Hold all non-masked & non-broadcasted EVEX encoded instructions
  22. std::vector<const CodeGenInstruction *> EVEXInsts;
  23. // Hold all VEX encoded instructions. Divided into groups with same opcodes
  24. // to make the search more efficient
  25. std::map<uint64_t, std::vector<const CodeGenInstruction *>> VEXInsts;
  26. typedef std::pair<const CodeGenInstruction *, const CodeGenInstruction *> Entry;
  27. typedef std::pair<StringRef, StringRef> Predicate;
  28. // Represent both compress tables
  29. std::vector<Entry> EVEX2VEX128;
  30. std::vector<Entry> EVEX2VEX256;
  31. // Represent predicates of VEX instructions.
  32. std::vector<Predicate> EVEX2VEXPredicates;
  33. public:
  34. X86EVEX2VEXTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {}
  35. // run - Output X86 EVEX2VEX tables.
  36. void run(raw_ostream &OS);
  37. private:
  38. // Prints the given table as a C++ array of type
  39. // X86EvexToVexCompressTableEntry
  40. void printTable(const std::vector<Entry> &Table, raw_ostream &OS);
  41. // Prints function which checks target feature specific predicate.
  42. void printCheckPredicate(const std::vector<Predicate> &Predicates,
  43. raw_ostream &OS);
  44. };
  45. void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table,
  46. raw_ostream &OS) {
  47. StringRef Size = (Table == EVEX2VEX128) ? "128" : "256";
  48. OS << "// X86 EVEX encoded instructions that have a VEX " << Size
  49. << " encoding\n"
  50. << "// (table format: <EVEX opcode, VEX-" << Size << " opcode>).\n"
  51. << "static const X86EvexToVexCompressTableEntry X86EvexToVex" << Size
  52. << "CompressTable[] = {\n"
  53. << " // EVEX scalar with corresponding VEX.\n";
  54. // Print all entries added to the table
  55. for (const auto &Pair : Table) {
  56. OS << " { X86::" << Pair.first->TheDef->getName()
  57. << ", X86::" << Pair.second->TheDef->getName() << " },\n";
  58. }
  59. OS << "};\n\n";
  60. }
  61. void X86EVEX2VEXTablesEmitter::printCheckPredicate(
  62. const std::vector<Predicate> &Predicates, raw_ostream &OS) {
  63. OS << "static bool CheckVEXInstPredicate"
  64. << "(MachineInstr &MI, const X86Subtarget *Subtarget) {\n"
  65. << " unsigned Opc = MI.getOpcode();\n"
  66. << " switch (Opc) {\n"
  67. << " default: return true;\n";
  68. for (const auto &Pair : Predicates)
  69. OS << " case X86::" << Pair.first << ": return " << Pair.second << ";\n";
  70. OS << " }\n"
  71. << "}\n\n";
  72. }
  73. // Return true if the 2 BitsInits are equal
  74. // Calculates the integer value residing BitsInit object
  75. static inline uint64_t getValueFromBitsInit(const BitsInit *B) {
  76. uint64_t Value = 0;
  77. for (unsigned i = 0, e = B->getNumBits(); i != e; ++i) {
  78. if (BitInit *Bit = dyn_cast<BitInit>(B->getBit(i)))
  79. Value |= uint64_t(Bit->getValue()) << i;
  80. else
  81. PrintFatalError("Invalid VectSize bit");
  82. }
  83. return Value;
  84. }
  85. // Function object - Operator() returns true if the given VEX instruction
  86. // matches the EVEX instruction of this object.
  87. class IsMatch {
  88. const CodeGenInstruction *EVEXInst;
  89. public:
  90. IsMatch(const CodeGenInstruction *EVEXInst) : EVEXInst(EVEXInst) {}
  91. bool operator()(const CodeGenInstruction *VEXInst) {
  92. Record *RecE = EVEXInst->TheDef;
  93. Record *RecV = VEXInst->TheDef;
  94. bool EVEX_W = RecE->getValueAsBit("HasVEX_W");
  95. bool VEX_W = RecV->getValueAsBit("HasVEX_W");
  96. bool VEX_WIG = RecV->getValueAsBit("IgnoresVEX_W");
  97. bool EVEX_WIG = RecE->getValueAsBit("IgnoresVEX_W");
  98. bool EVEX_W1_VEX_W0 = RecE->getValueAsBit("EVEX_W1_VEX_W0");
  99. if (RecV->getValueAsDef("OpEnc")->getName().str() != "EncVEX" ||
  100. RecV->getValueAsBit("isCodeGenOnly") != RecE->getValueAsBit("isCodeGenOnly") ||
  101. // VEX/EVEX fields
  102. RecV->getValueAsDef("OpPrefix") != RecE->getValueAsDef("OpPrefix") ||
  103. RecV->getValueAsDef("OpMap") != RecE->getValueAsDef("OpMap") ||
  104. RecV->getValueAsBit("hasVEX_4V") != RecE->getValueAsBit("hasVEX_4V") ||
  105. RecV->getValueAsBit("hasEVEX_L2") != RecE->getValueAsBit("hasEVEX_L2") ||
  106. RecV->getValueAsBit("hasVEX_L") != RecE->getValueAsBit("hasVEX_L") ||
  107. // Match is allowed if either is VEX_WIG, or they match, or EVEX
  108. // is VEX_W1X and VEX is VEX_W0.
  109. (!(VEX_WIG || (!EVEX_WIG && EVEX_W == VEX_W) ||
  110. (EVEX_W1_VEX_W0 && EVEX_W && !VEX_W))) ||
  111. // Instruction's format
  112. RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form"))
  113. return false;
  114. // This is needed for instructions with intrinsic version (_Int).
  115. // Where the only difference is the size of the operands.
  116. // For example: VUCOMISDZrm and Int_VUCOMISDrm
  117. // Also for instructions that their EVEX version was upgraded to work with
  118. // k-registers. For example VPCMPEQBrm (xmm output register) and
  119. // VPCMPEQBZ128rm (k register output register).
  120. for (unsigned i = 0, e = EVEXInst->Operands.size(); i < e; i++) {
  121. Record *OpRec1 = EVEXInst->Operands[i].Rec;
  122. Record *OpRec2 = VEXInst->Operands[i].Rec;
  123. if (OpRec1 == OpRec2)
  124. continue;
  125. if (isRegisterOperand(OpRec1) && isRegisterOperand(OpRec2)) {
  126. if (getRegOperandSize(OpRec1) != getRegOperandSize(OpRec2))
  127. return false;
  128. } else if (isMemoryOperand(OpRec1) && isMemoryOperand(OpRec2)) {
  129. return false;
  130. } else if (isImmediateOperand(OpRec1) && isImmediateOperand(OpRec2)) {
  131. if (OpRec1->getValueAsDef("Type") != OpRec2->getValueAsDef("Type")) {
  132. return false;
  133. }
  134. } else
  135. return false;
  136. }
  137. return true;
  138. }
  139. private:
  140. static inline bool isRegisterOperand(const Record *Rec) {
  141. return Rec->isSubClassOf("RegisterClass") ||
  142. Rec->isSubClassOf("RegisterOperand");
  143. }
  144. static inline bool isMemoryOperand(const Record *Rec) {
  145. return Rec->isSubClassOf("Operand") &&
  146. Rec->getValueAsString("OperandType") == "OPERAND_MEMORY";
  147. }
  148. static inline bool isImmediateOperand(const Record *Rec) {
  149. return Rec->isSubClassOf("Operand") &&
  150. Rec->getValueAsString("OperandType") == "OPERAND_IMMEDIATE";
  151. }
  152. static inline unsigned int getRegOperandSize(const Record *RegRec) {
  153. if (RegRec->isSubClassOf("RegisterClass"))
  154. return RegRec->getValueAsInt("Alignment");
  155. if (RegRec->isSubClassOf("RegisterOperand"))
  156. return RegRec->getValueAsDef("RegClass")->getValueAsInt("Alignment");
  157. llvm_unreachable("Register operand's size not known!");
  158. }
  159. };
  160. void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
  161. auto getPredicates = [&](const CodeGenInstruction *Inst) {
  162. std::vector<Record *> PredicatesRecords =
  163. Inst->TheDef->getValueAsListOfDefs("Predicates");
  164. // Currently we only do AVX related checks and assume each instruction
  165. // has one and only one AVX related predicates.
  166. for (unsigned i = 0, e = PredicatesRecords.size(); i != e; ++i)
  167. if (PredicatesRecords[i]->getName().startswith("HasAVX"))
  168. return PredicatesRecords[i]->getValueAsString("CondString");
  169. llvm_unreachable(
  170. "Instruction with checkPredicate set must have one predicate!");
  171. };
  172. emitSourceFileHeader("X86 EVEX2VEX tables", OS);
  173. ArrayRef<const CodeGenInstruction *> NumberedInstructions =
  174. Target.getInstructionsByEnumValue();
  175. for (const CodeGenInstruction *Inst : NumberedInstructions) {
  176. // Filter non-X86 instructions.
  177. if (!Inst->TheDef->isSubClassOf("X86Inst"))
  178. continue;
  179. // Add VEX encoded instructions to one of VEXInsts vectors according to
  180. // it's opcode.
  181. if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncVEX") {
  182. uint64_t Opcode = getValueFromBitsInit(Inst->TheDef->
  183. getValueAsBitsInit("Opcode"));
  184. VEXInsts[Opcode].push_back(Inst);
  185. }
  186. // Add relevant EVEX encoded instructions to EVEXInsts
  187. else if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncEVEX" &&
  188. !Inst->TheDef->getValueAsBit("hasEVEX_K") &&
  189. !Inst->TheDef->getValueAsBit("hasEVEX_B") &&
  190. !Inst->TheDef->getValueAsBit("hasEVEX_L2") &&
  191. !Inst->TheDef->getValueAsBit("notEVEX2VEXConvertible"))
  192. EVEXInsts.push_back(Inst);
  193. }
  194. for (const CodeGenInstruction *EVEXInst : EVEXInsts) {
  195. uint64_t Opcode = getValueFromBitsInit(EVEXInst->TheDef->
  196. getValueAsBitsInit("Opcode"));
  197. // For each EVEX instruction look for a VEX match in the appropriate vector
  198. // (instructions with the same opcode) using function object IsMatch.
  199. // Allow EVEX2VEXOverride to explicitly specify a match.
  200. const CodeGenInstruction *VEXInst = nullptr;
  201. if (!EVEXInst->TheDef->isValueUnset("EVEX2VEXOverride")) {
  202. StringRef AltInstStr =
  203. EVEXInst->TheDef->getValueAsString("EVEX2VEXOverride");
  204. Record *AltInstRec = Records.getDef(AltInstStr);
  205. assert(AltInstRec && "EVEX2VEXOverride instruction not found!");
  206. VEXInst = &Target.getInstruction(AltInstRec);
  207. } else {
  208. auto Match = llvm::find_if(VEXInsts[Opcode], IsMatch(EVEXInst));
  209. if (Match != VEXInsts[Opcode].end())
  210. VEXInst = *Match;
  211. }
  212. if (!VEXInst)
  213. continue;
  214. // In case a match is found add new entry to the appropriate table
  215. if (EVEXInst->TheDef->getValueAsBit("hasVEX_L"))
  216. EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1}
  217. else
  218. EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0}
  219. // Adding predicate check to EVEX2VEXPredicates table when needed.
  220. if (VEXInst->TheDef->getValueAsBit("checkVEXPredicate"))
  221. EVEX2VEXPredicates.push_back(
  222. std::make_pair(EVEXInst->TheDef->getName(), getPredicates(VEXInst)));
  223. }
  224. // Print both tables
  225. printTable(EVEX2VEX128, OS);
  226. printTable(EVEX2VEX256, OS);
  227. // Print CheckVEXInstPredicate function.
  228. printCheckPredicate(EVEX2VEXPredicates, OS);
  229. }
  230. }
  231. namespace llvm {
  232. void EmitX86EVEX2VEXTables(RecordKeeper &RK, raw_ostream &OS) {
  233. X86EVEX2VEXTablesEmitter(RK).run(OS);
  234. }
  235. }