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