X86FoldTablesEmitter.cpp 26 KB

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