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