X86FoldTablesEmitter.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. //===- utils/TableGen/X86FoldTablesEmitter.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 memory fold tables of
  10. // the X86 backend instructions.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "CodeGenTarget.h"
  14. #include "X86RecognizableInstr.h"
  15. #include "llvm/Support/FormattedStream.h"
  16. #include "llvm/TableGen/Error.h"
  17. #include "llvm/TableGen/TableGenBackend.h"
  18. using namespace llvm;
  19. using namespace X86Disassembler;
  20. namespace {
  21. // 3 possible strategies for the unfolding flag (TB_NO_REVERSE) of the
  22. // manual added entries.
  23. enum UnfoldStrategy {
  24. UNFOLD, // Allow unfolding
  25. NO_UNFOLD, // Prevent unfolding
  26. NO_STRATEGY // Make decision according to operands' sizes
  27. };
  28. // Represents an entry in the manual mapped instructions set.
  29. struct ManualMapEntry {
  30. const char *RegInstStr;
  31. const char *MemInstStr;
  32. UnfoldStrategy Strategy;
  33. ManualMapEntry(const char *RegInstStr, const char *MemInstStr,
  34. UnfoldStrategy Strategy = NO_STRATEGY)
  35. : RegInstStr(RegInstStr), MemInstStr(MemInstStr), Strategy(Strategy) {}
  36. };
  37. // List of instructions requiring explicitly aligned memory.
  38. const char *ExplicitAlign[] = {"MOVDQA", "MOVAPS", "MOVAPD", "MOVNTPS",
  39. "MOVNTPD", "MOVNTDQ", "MOVNTDQA"};
  40. // List of instructions NOT requiring explicit memory alignment.
  41. const char *ExplicitUnalign[] = {"MOVDQU", "MOVUPS", "MOVUPD",
  42. "PCMPESTRM", "PCMPESTRI",
  43. "PCMPISTRM", "PCMPISTRI" };
  44. // For manually mapping instructions that do not match by their encoding.
  45. const ManualMapEntry ManualMapSet[] = {
  46. { "ADD16ri_DB", "ADD16mi", NO_UNFOLD },
  47. { "ADD16ri8_DB", "ADD16mi8", NO_UNFOLD },
  48. { "ADD16rr_DB", "ADD16mr", NO_UNFOLD },
  49. { "ADD32ri_DB", "ADD32mi", NO_UNFOLD },
  50. { "ADD32ri8_DB", "ADD32mi8", NO_UNFOLD },
  51. { "ADD32rr_DB", "ADD32mr", NO_UNFOLD },
  52. { "ADD64ri32_DB", "ADD64mi32", NO_UNFOLD },
  53. { "ADD64ri8_DB", "ADD64mi8", NO_UNFOLD },
  54. { "ADD64rr_DB", "ADD64mr", NO_UNFOLD },
  55. { "ADD8ri_DB", "ADD8mi", NO_UNFOLD },
  56. { "ADD8rr_DB", "ADD8mr", NO_UNFOLD },
  57. { "ADD16rr_DB", "ADD16rm", NO_UNFOLD },
  58. { "ADD32rr_DB", "ADD32rm", NO_UNFOLD },
  59. { "ADD64rr_DB", "ADD64rm", NO_UNFOLD },
  60. { "ADD8rr_DB", "ADD8rm", NO_UNFOLD },
  61. { "MMX_MOVD64from64rr", "MMX_MOVQ64mr", UNFOLD },
  62. { "MMX_MOVD64grr", "MMX_MOVD64mr", UNFOLD },
  63. { "MOVLHPSrr", "MOVHPSrm", NO_UNFOLD },
  64. { "PUSH16r", "PUSH16rmm", UNFOLD },
  65. { "PUSH32r", "PUSH32rmm", UNFOLD },
  66. { "PUSH64r", "PUSH64rmm", UNFOLD },
  67. { "TAILJMPr", "TAILJMPm", UNFOLD },
  68. { "TAILJMPr64", "TAILJMPm64", UNFOLD },
  69. { "TAILJMPr64_REX", "TAILJMPm64_REX", UNFOLD },
  70. { "VMOVLHPSZrr", "VMOVHPSZ128rm", NO_UNFOLD },
  71. { "VMOVLHPSrr", "VMOVHPSrm", NO_UNFOLD },
  72. };
  73. static bool isExplicitAlign(const CodeGenInstruction *Inst) {
  74. return any_of(ExplicitAlign, [Inst](const char *InstStr) {
  75. return Inst->TheDef->getName().contains(InstStr);
  76. });
  77. }
  78. static bool isExplicitUnalign(const CodeGenInstruction *Inst) {
  79. return any_of(ExplicitUnalign, [Inst](const char *InstStr) {
  80. return Inst->TheDef->getName().contains(InstStr);
  81. });
  82. }
  83. class X86FoldTablesEmitter {
  84. RecordKeeper &Records;
  85. CodeGenTarget Target;
  86. // Represents an entry in the folding table
  87. class X86FoldTableEntry {
  88. const CodeGenInstruction *RegInst;
  89. const CodeGenInstruction *MemInst;
  90. public:
  91. bool CannotUnfold = false;
  92. bool IsLoad = false;
  93. bool IsStore = false;
  94. bool IsAligned = false;
  95. unsigned int Alignment = 0;
  96. X86FoldTableEntry(const CodeGenInstruction *RegInst,
  97. const CodeGenInstruction *MemInst)
  98. : RegInst(RegInst), MemInst(MemInst) {}
  99. void print(formatted_raw_ostream &OS) const {
  100. OS.indent(2);
  101. OS << "{ X86::" << RegInst->TheDef->getName() << ",";
  102. OS.PadToColumn(40);
  103. OS << "X86::" << MemInst->TheDef->getName() << ",";
  104. OS.PadToColumn(75);
  105. std::string Attrs;
  106. if (IsLoad)
  107. Attrs += "TB_FOLDED_LOAD | ";
  108. if (IsStore)
  109. Attrs += "TB_FOLDED_STORE | ";
  110. if (CannotUnfold)
  111. Attrs += "TB_NO_REVERSE | ";
  112. if (IsAligned)
  113. Attrs += "TB_ALIGN_" + std::to_string(Alignment) + " | ";
  114. StringRef SimplifiedAttrs = StringRef(Attrs).rtrim("| ");
  115. if (SimplifiedAttrs.empty())
  116. SimplifiedAttrs = "0";
  117. OS << SimplifiedAttrs << " },\n";
  118. }
  119. bool operator<(const X86FoldTableEntry &RHS) const {
  120. bool LHSpseudo = RegInst->TheDef->getValueAsBit("isPseudo");
  121. bool RHSpseudo = RHS.RegInst->TheDef->getValueAsBit("isPseudo");
  122. if (LHSpseudo != RHSpseudo)
  123. return LHSpseudo;
  124. return RegInst->TheDef->getName() < RHS.RegInst->TheDef->getName();
  125. }
  126. };
  127. typedef std::vector<X86FoldTableEntry> FoldTable;
  128. // std::vector for each folding table.
  129. // Table2Addr - Holds instructions which their memory form performs load+store
  130. // Table#i - Holds instructions which the their memory form perform a load OR
  131. // a store, and their #i'th operand is folded.
  132. FoldTable Table2Addr;
  133. FoldTable Table0;
  134. FoldTable Table1;
  135. FoldTable Table2;
  136. FoldTable Table3;
  137. FoldTable Table4;
  138. public:
  139. X86FoldTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {}
  140. // run - Generate the 6 X86 memory fold tables.
  141. void run(formatted_raw_ostream &OS);
  142. private:
  143. // Decides to which table to add the entry with the given instructions.
  144. // S sets the strategy of adding the TB_NO_REVERSE flag.
  145. void updateTables(const CodeGenInstruction *RegInstr,
  146. const CodeGenInstruction *MemInstr,
  147. const UnfoldStrategy S = NO_STRATEGY);
  148. // Generates X86FoldTableEntry with the given instructions and fill it with
  149. // the appropriate flags - then adds it to Table.
  150. void addEntryWithFlags(FoldTable &Table, const CodeGenInstruction *RegInstr,
  151. const CodeGenInstruction *MemInstr,
  152. const UnfoldStrategy S, const unsigned int FoldedInd);
  153. // Print the given table as a static const C++ array of type
  154. // X86MemoryFoldTableEntry.
  155. void printTable(const FoldTable &Table, StringRef TableName,
  156. formatted_raw_ostream &OS) {
  157. OS << "static const X86MemoryFoldTableEntry MemoryFold" << TableName
  158. << "[] = {\n";
  159. for (const X86FoldTableEntry &E : Table)
  160. E.print(OS);
  161. OS << "};\n\n";
  162. }
  163. };
  164. // Return true if one of the instruction's operands is a RST register class
  165. static bool hasRSTRegClass(const CodeGenInstruction *Inst) {
  166. return any_of(Inst->Operands, [](const CGIOperandList::OperandInfo &OpIn) {
  167. return OpIn.Rec->getName() == "RST" || OpIn.Rec->getName() == "RSTi";
  168. });
  169. }
  170. // Return true if one of the instruction's operands is a ptr_rc_tailcall
  171. static bool hasPtrTailcallRegClass(const CodeGenInstruction *Inst) {
  172. return any_of(Inst->Operands, [](const CGIOperandList::OperandInfo &OpIn) {
  173. return OpIn.Rec->getName() == "ptr_rc_tailcall";
  174. });
  175. }
  176. // Calculates the integer value representing the BitsInit object
  177. static inline uint64_t getValueFromBitsInit(const BitsInit *B) {
  178. assert(B->getNumBits() <= sizeof(uint64_t) * 8 && "BitInits' too long!");
  179. uint64_t Value = 0;
  180. for (unsigned i = 0, e = B->getNumBits(); i != e; ++i) {
  181. BitInit *Bit = cast<BitInit>(B->getBit(i));
  182. Value |= uint64_t(Bit->getValue()) << i;
  183. }
  184. return Value;
  185. }
  186. // Return true if the instruction defined as a register flavor.
  187. static inline bool hasRegisterFormat(const Record *Inst) {
  188. const BitsInit *FormBits = Inst->getValueAsBitsInit("FormBits");
  189. uint64_t FormBitsNum = getValueFromBitsInit(FormBits);
  190. // Values from X86Local namespace defined in X86RecognizableInstr.cpp
  191. return FormBitsNum >= X86Local::MRMDestReg && FormBitsNum <= X86Local::MRM7r;
  192. }
  193. // Return true if the instruction defined as a memory flavor.
  194. static inline bool hasMemoryFormat(const Record *Inst) {
  195. const BitsInit *FormBits = Inst->getValueAsBitsInit("FormBits");
  196. uint64_t FormBitsNum = getValueFromBitsInit(FormBits);
  197. // Values from X86Local namespace defined in X86RecognizableInstr.cpp
  198. return FormBitsNum >= X86Local::MRMDestMem && FormBitsNum <= X86Local::MRM7m;
  199. }
  200. static inline bool isNOREXRegClass(const Record *Op) {
  201. return Op->getName().contains("_NOREX");
  202. }
  203. // Get the alternative instruction pointed by "FoldGenRegForm" field.
  204. static inline const CodeGenInstruction *
  205. getAltRegInst(const CodeGenInstruction *I, const RecordKeeper &Records,
  206. const CodeGenTarget &Target) {
  207. StringRef AltRegInstStr = I->TheDef->getValueAsString("FoldGenRegForm");
  208. Record *AltRegInstRec = Records.getDef(AltRegInstStr);
  209. assert(AltRegInstRec &&
  210. "Alternative register form instruction def not found");
  211. CodeGenInstruction &AltRegInst = Target.getInstruction(AltRegInstRec);
  212. return &AltRegInst;
  213. }
  214. // Function object - Operator() returns true if the given VEX instruction
  215. // matches the EVEX instruction of this object.
  216. class IsMatch {
  217. const CodeGenInstruction *MemInst;
  218. unsigned Variant;
  219. public:
  220. IsMatch(const CodeGenInstruction *Inst, unsigned V)
  221. : MemInst(Inst), Variant(V) {}
  222. bool operator()(const CodeGenInstruction *RegInst) {
  223. X86Disassembler::RecognizableInstrBase RegRI(*RegInst);
  224. X86Disassembler::RecognizableInstrBase MemRI(*MemInst);
  225. const Record *RegRec = RegInst->TheDef;
  226. const Record *MemRec = MemInst->TheDef;
  227. // EVEX_B means different things for memory and register forms.
  228. if (RegRI.HasEVEX_B != 0 || MemRI.HasEVEX_B != 0)
  229. return false;
  230. // Instruction's format - The register form's "Form" field should be
  231. // the opposite of the memory form's "Form" field.
  232. if (!areOppositeForms(RegRI.Form, MemRI.Form))
  233. return false;
  234. // X86 encoding is crazy, e.g
  235. //
  236. // f3 0f c7 30 vmxon (%rax)
  237. // f3 0f c7 f0 senduipi %rax
  238. //
  239. // This two instruction have similiar encoding fields but are unrelated
  240. if (X86Disassembler::getMnemonic(MemInst, Variant) !=
  241. X86Disassembler::getMnemonic(RegInst, Variant))
  242. return false;
  243. // Return false if one (at least) of the encoding fields of both
  244. // instructions do not match.
  245. if (RegRI.Encoding != MemRI.Encoding || RegRI.Opcode != MemRI.Opcode ||
  246. RegRI.OpPrefix != MemRI.OpPrefix || RegRI.OpMap != MemRI.OpMap ||
  247. RegRI.OpSize != MemRI.OpSize || RegRI.AdSize != MemRI.AdSize ||
  248. RegRI.HasREX_W != MemRI.HasREX_W ||
  249. RegRI.HasVEX_4V != MemRI.HasVEX_4V ||
  250. RegRI.HasVEX_L != MemRI.HasVEX_L ||
  251. RegRI.HasVEX_W != MemRI.HasVEX_W ||
  252. RegRI.IgnoresVEX_L != MemRI.IgnoresVEX_L ||
  253. RegRI.IgnoresVEX_W != MemRI.IgnoresVEX_W ||
  254. RegRI.HasEVEX_K != MemRI.HasEVEX_K ||
  255. RegRI.HasEVEX_KZ != MemRI.HasEVEX_KZ ||
  256. RegRI.HasEVEX_L2 != MemRI.HasEVEX_L2 ||
  257. RegRec->getValueAsBit("hasEVEX_RC") !=
  258. MemRec->getValueAsBit("hasEVEX_RC") ||
  259. RegRec->getValueAsBit("hasLockPrefix") !=
  260. MemRec->getValueAsBit("hasLockPrefix") ||
  261. RegRec->getValueAsBit("hasNoTrackPrefix") !=
  262. MemRec->getValueAsBit("hasNoTrackPrefix") ||
  263. RegRec->getValueAsBit("EVEX_W1_VEX_W0") !=
  264. MemRec->getValueAsBit("EVEX_W1_VEX_W0"))
  265. return false;
  266. // Make sure the sizes of the operands of both instructions suit each other.
  267. // This is needed for instructions with intrinsic version (_Int).
  268. // Where the only difference is the size of the operands.
  269. // For example: VUCOMISDZrm and Int_VUCOMISDrm
  270. // Also for instructions that their EVEX version was upgraded to work with
  271. // k-registers. For example VPCMPEQBrm (xmm output register) and
  272. // VPCMPEQBZ128rm (k register output register).
  273. bool ArgFolded = false;
  274. unsigned MemOutSize = MemRec->getValueAsDag("OutOperandList")->getNumArgs();
  275. unsigned RegOutSize = RegRec->getValueAsDag("OutOperandList")->getNumArgs();
  276. unsigned MemInSize = MemRec->getValueAsDag("InOperandList")->getNumArgs();
  277. unsigned RegInSize = RegRec->getValueAsDag("InOperandList")->getNumArgs();
  278. // Instructions with one output in their memory form use the memory folded
  279. // operand as source and destination (Read-Modify-Write).
  280. unsigned RegStartIdx =
  281. (MemOutSize + 1 == RegOutSize) && (MemInSize == RegInSize) ? 1 : 0;
  282. for (unsigned i = 0, e = MemInst->Operands.size(); i < e; i++) {
  283. Record *MemOpRec = MemInst->Operands[i].Rec;
  284. Record *RegOpRec = RegInst->Operands[i + RegStartIdx].Rec;
  285. if (MemOpRec == RegOpRec)
  286. continue;
  287. if (isRegisterOperand(MemOpRec) && isRegisterOperand(RegOpRec)) {
  288. if (getRegOperandSize(MemOpRec) != getRegOperandSize(RegOpRec) ||
  289. isNOREXRegClass(MemOpRec) != isNOREXRegClass(RegOpRec))
  290. return false;
  291. } else if (isMemoryOperand(MemOpRec) && isMemoryOperand(RegOpRec)) {
  292. if (getMemOperandSize(MemOpRec) != getMemOperandSize(RegOpRec))
  293. return false;
  294. } else if (isImmediateOperand(MemOpRec) && isImmediateOperand(RegOpRec)) {
  295. if (MemOpRec->getValueAsDef("Type") != RegOpRec->getValueAsDef("Type"))
  296. return false;
  297. } else {
  298. // Only one operand can be folded.
  299. if (ArgFolded)
  300. return false;
  301. assert(isRegisterOperand(RegOpRec) && isMemoryOperand(MemOpRec));
  302. ArgFolded = true;
  303. }
  304. }
  305. return true;
  306. }
  307. private:
  308. // Return true of the 2 given forms are the opposite of each other.
  309. bool areOppositeForms(unsigned RegForm, unsigned MemForm) {
  310. if ((MemForm == X86Local::MRM0m && RegForm == X86Local::MRM0r) ||
  311. (MemForm == X86Local::MRM1m && RegForm == X86Local::MRM1r) ||
  312. (MemForm == X86Local::MRM2m && RegForm == X86Local::MRM2r) ||
  313. (MemForm == X86Local::MRM3m && RegForm == X86Local::MRM3r) ||
  314. (MemForm == X86Local::MRM4m && RegForm == X86Local::MRM4r) ||
  315. (MemForm == X86Local::MRM5m && RegForm == X86Local::MRM5r) ||
  316. (MemForm == X86Local::MRM6m && RegForm == X86Local::MRM6r) ||
  317. (MemForm == X86Local::MRM7m && RegForm == X86Local::MRM7r) ||
  318. (MemForm == X86Local::MRMXm && RegForm == X86Local::MRMXr) ||
  319. (MemForm == X86Local::MRMXmCC && RegForm == X86Local::MRMXrCC) ||
  320. (MemForm == X86Local::MRMDestMem && RegForm == X86Local::MRMDestReg) ||
  321. (MemForm == X86Local::MRMSrcMem && RegForm == X86Local::MRMSrcReg) ||
  322. (MemForm == X86Local::MRMSrcMem4VOp3 &&
  323. RegForm == X86Local::MRMSrcReg4VOp3) ||
  324. (MemForm == X86Local::MRMSrcMemOp4 &&
  325. RegForm == X86Local::MRMSrcRegOp4) ||
  326. (MemForm == X86Local::MRMSrcMemCC && RegForm == X86Local::MRMSrcRegCC))
  327. return true;
  328. return false;
  329. }
  330. };
  331. } // end anonymous namespace
  332. void X86FoldTablesEmitter::addEntryWithFlags(FoldTable &Table,
  333. const CodeGenInstruction *RegInstr,
  334. const CodeGenInstruction *MemInstr,
  335. const UnfoldStrategy S,
  336. const unsigned int FoldedInd) {
  337. X86FoldTableEntry Result = X86FoldTableEntry(RegInstr, MemInstr);
  338. Record *RegRec = RegInstr->TheDef;
  339. Record *MemRec = MemInstr->TheDef;
  340. // Only table0 entries should explicitly specify a load or store flag.
  341. if (&Table == &Table0) {
  342. unsigned MemInOpsNum = MemRec->getValueAsDag("InOperandList")->getNumArgs();
  343. unsigned RegInOpsNum = RegRec->getValueAsDag("InOperandList")->getNumArgs();
  344. // If the instruction writes to the folded operand, it will appear as an
  345. // output in the register form instruction and as an input in the memory
  346. // form instruction.
  347. // If the instruction reads from the folded operand, it well appear as in
  348. // input in both forms.
  349. if (MemInOpsNum == RegInOpsNum)
  350. Result.IsLoad = true;
  351. else
  352. Result.IsStore = true;
  353. }
  354. Record *RegOpRec = RegInstr->Operands[FoldedInd].Rec;
  355. Record *MemOpRec = MemInstr->Operands[FoldedInd].Rec;
  356. // Unfolding code generates a load/store instruction according to the size of
  357. // the register in the register form instruction.
  358. // If the register's size is greater than the memory's operand size, do not
  359. // allow unfolding.
  360. if (S == UNFOLD)
  361. Result.CannotUnfold = false;
  362. else if (S == NO_UNFOLD)
  363. Result.CannotUnfold = true;
  364. else if (getRegOperandSize(RegOpRec) > getMemOperandSize(MemOpRec))
  365. Result.CannotUnfold = true; // S == NO_STRATEGY
  366. uint64_t Enc = getValueFromBitsInit(RegRec->getValueAsBitsInit("OpEncBits"));
  367. if (isExplicitAlign(RegInstr)) {
  368. // The instruction require explicitly aligned memory.
  369. BitsInit *VectSize = RegRec->getValueAsBitsInit("VectSize");
  370. uint64_t Value = getValueFromBitsInit(VectSize);
  371. Result.IsAligned = true;
  372. Result.Alignment = Value;
  373. } else if (Enc != X86Local::XOP && Enc != X86Local::VEX &&
  374. Enc != X86Local::EVEX) {
  375. // Instructions with VEX encoding do not require alignment.
  376. if (!isExplicitUnalign(RegInstr) && getMemOperandSize(MemOpRec) > 64) {
  377. // SSE packed vector instructions require a 16 byte alignment.
  378. Result.IsAligned = true;
  379. Result.Alignment = 16;
  380. }
  381. }
  382. Table.push_back(Result);
  383. }
  384. void X86FoldTablesEmitter::updateTables(const CodeGenInstruction *RegInstr,
  385. const CodeGenInstruction *MemInstr,
  386. const UnfoldStrategy S) {
  387. Record *RegRec = RegInstr->TheDef;
  388. Record *MemRec = MemInstr->TheDef;
  389. unsigned MemOutSize = MemRec->getValueAsDag("OutOperandList")->getNumArgs();
  390. unsigned RegOutSize = RegRec->getValueAsDag("OutOperandList")->getNumArgs();
  391. unsigned MemInSize = MemRec->getValueAsDag("InOperandList")->getNumArgs();
  392. unsigned RegInSize = RegRec->getValueAsDag("InOperandList")->getNumArgs();
  393. // Instructions which Read-Modify-Write should be added to Table2Addr.
  394. if (MemOutSize != RegOutSize && MemInSize == RegInSize) {
  395. addEntryWithFlags(Table2Addr, RegInstr, MemInstr, S, 0);
  396. return;
  397. }
  398. if (MemInSize == RegInSize && MemOutSize == RegOutSize) {
  399. // Load-Folding cases.
  400. // If the i'th register form operand is a register and the i'th memory form
  401. // operand is a memory operand, add instructions to Table#i.
  402. for (unsigned i = RegOutSize, e = RegInstr->Operands.size(); i < e; i++) {
  403. Record *RegOpRec = RegInstr->Operands[i].Rec;
  404. Record *MemOpRec = MemInstr->Operands[i].Rec;
  405. // PointerLikeRegClass: For instructions like TAILJMPr, TAILJMPr64, TAILJMPr64_REX
  406. if ((isRegisterOperand(RegOpRec) ||
  407. RegOpRec->isSubClassOf("PointerLikeRegClass")) &&
  408. isMemoryOperand(MemOpRec)) {
  409. switch (i) {
  410. case 0:
  411. addEntryWithFlags(Table0, RegInstr, MemInstr, S, 0);
  412. return;
  413. case 1:
  414. addEntryWithFlags(Table1, RegInstr, MemInstr, S, 1);
  415. return;
  416. case 2:
  417. addEntryWithFlags(Table2, RegInstr, MemInstr, S, 2);
  418. return;
  419. case 3:
  420. addEntryWithFlags(Table3, RegInstr, MemInstr, S, 3);
  421. return;
  422. case 4:
  423. addEntryWithFlags(Table4, RegInstr, MemInstr, S, 4);
  424. return;
  425. }
  426. }
  427. }
  428. } else if (MemInSize == RegInSize + 1 && MemOutSize + 1 == RegOutSize) {
  429. // Store-Folding cases.
  430. // If the memory form instruction performs a store, the *output*
  431. // register of the register form instructions disappear and instead a
  432. // memory *input* operand appears in the memory form instruction.
  433. // For example:
  434. // MOVAPSrr => (outs VR128:$dst), (ins VR128:$src)
  435. // MOVAPSmr => (outs), (ins f128mem:$dst, VR128:$src)
  436. Record *RegOpRec = RegInstr->Operands[RegOutSize - 1].Rec;
  437. Record *MemOpRec = MemInstr->Operands[RegOutSize - 1].Rec;
  438. if (isRegisterOperand(RegOpRec) && isMemoryOperand(MemOpRec) &&
  439. getRegOperandSize(RegOpRec) == getMemOperandSize(MemOpRec))
  440. addEntryWithFlags(Table0, RegInstr, MemInstr, S, 0);
  441. }
  442. }
  443. void X86FoldTablesEmitter::run(formatted_raw_ostream &OS) {
  444. emitSourceFileHeader("X86 fold tables", OS);
  445. // Holds all memory instructions
  446. std::vector<const CodeGenInstruction *> MemInsts;
  447. // Holds all register instructions - divided according to opcode.
  448. std::map<uint8_t, std::vector<const CodeGenInstruction *>> RegInsts;
  449. ArrayRef<const CodeGenInstruction *> NumberedInstructions =
  450. Target.getInstructionsByEnumValue();
  451. for (const CodeGenInstruction *Inst : NumberedInstructions) {
  452. const Record *Rec = Inst->TheDef;
  453. if (!Rec->isSubClassOf("X86Inst") || Rec->getValueAsBit("isAsmParserOnly"))
  454. continue;
  455. // - Do not proceed if the instruction is marked as notMemoryFoldable.
  456. // - Instructions including RST register class operands are not relevant
  457. // for memory folding (for further details check the explanation in
  458. // lib/Target/X86/X86InstrFPStack.td file).
  459. // - Some instructions (listed in the manual map above) use the register
  460. // class ptr_rc_tailcall, which can be of a size 32 or 64, to ensure
  461. // safe mapping of these instruction we manually map them and exclude
  462. // them from the automation.
  463. if (Rec->getValueAsBit("isMemoryFoldable") == false ||
  464. hasRSTRegClass(Inst) || hasPtrTailcallRegClass(Inst))
  465. continue;
  466. // Add all the memory form instructions to MemInsts, and all the register
  467. // form instructions to RegInsts[Opc], where Opc in the opcode of each
  468. // instructions. this helps reducing the runtime of the backend.
  469. if (hasMemoryFormat(Rec))
  470. MemInsts.push_back(Inst);
  471. else if (hasRegisterFormat(Rec)) {
  472. uint8_t Opc = getValueFromBitsInit(Rec->getValueAsBitsInit("Opcode"));
  473. RegInsts[Opc].push_back(Inst);
  474. }
  475. }
  476. Record *AsmWriter = Target.getAsmWriter();
  477. unsigned Variant = AsmWriter->getValueAsInt("Variant");
  478. // For each memory form instruction, try to find its register form
  479. // instruction.
  480. for (const CodeGenInstruction *MemInst : MemInsts) {
  481. uint8_t Opc =
  482. getValueFromBitsInit(MemInst->TheDef->getValueAsBitsInit("Opcode"));
  483. auto RegInstsIt = RegInsts.find(Opc);
  484. if (RegInstsIt == RegInsts.end())
  485. continue;
  486. // Two forms (memory & register) of the same instruction must have the same
  487. // opcode. try matching only with register form instructions with the same
  488. // opcode.
  489. std::vector<const CodeGenInstruction *> &OpcRegInsts = RegInstsIt->second;
  490. auto Match = find_if(OpcRegInsts, IsMatch(MemInst, Variant));
  491. if (Match != OpcRegInsts.end()) {
  492. const CodeGenInstruction *RegInst = *Match;
  493. // If the matched instruction has it's "FoldGenRegForm" set, map the
  494. // memory form instruction to the register form instruction pointed by
  495. // this field
  496. if (RegInst->TheDef->isValueUnset("FoldGenRegForm")) {
  497. updateTables(RegInst, MemInst);
  498. } else {
  499. const CodeGenInstruction *AltRegInst =
  500. getAltRegInst(RegInst, Records, Target);
  501. updateTables(AltRegInst, MemInst);
  502. }
  503. OpcRegInsts.erase(Match);
  504. }
  505. }
  506. // Add the manually mapped instructions listed above.
  507. for (const ManualMapEntry &Entry : ManualMapSet) {
  508. Record *RegInstIter = Records.getDef(Entry.RegInstStr);
  509. Record *MemInstIter = Records.getDef(Entry.MemInstStr);
  510. updateTables(&(Target.getInstruction(RegInstIter)),
  511. &(Target.getInstruction(MemInstIter)), Entry.Strategy);
  512. }
  513. // Sort the tables before printing.
  514. llvm::sort(Table2Addr);
  515. llvm::sort(Table0);
  516. llvm::sort(Table1);
  517. llvm::sort(Table2);
  518. llvm::sort(Table3);
  519. llvm::sort(Table4);
  520. // Print all tables.
  521. printTable(Table2Addr, "Table2Addr", OS);
  522. printTable(Table0, "Table0", OS);
  523. printTable(Table1, "Table1", OS);
  524. printTable(Table2, "Table2", OS);
  525. printTable(Table3, "Table3", OS);
  526. printTable(Table4, "Table4", OS);
  527. }
  528. namespace llvm {
  529. void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &o) {
  530. formatted_raw_ostream OS(o);
  531. X86FoldTablesEmitter(RK).run(OS);
  532. }
  533. } // namespace llvm