X86FoldTablesEmitter.cpp revision 360784
1114902Sscottl//===- utils/TableGen/X86FoldTablesEmitter.cpp - X86 backend-*- C++ -*-===//
2114902Sscottl//
3114902Sscottl// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4114902Sscottl// See https://llvm.org/LICENSE.txt for license information.
5114902Sscottl// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6114902Sscottl//
7114902Sscottl//===----------------------------------------------------------------------===//
8114902Sscottl//
9114902Sscottl// This tablegen backend is responsible for emitting the memory fold tables of
10114902Sscottl// the X86 backend instructions.
11114902Sscottl//
12114902Sscottl//===----------------------------------------------------------------------===//
13114902Sscottl
14114902Sscottl#include "CodeGenTarget.h"
15114902Sscottl#include "X86RecognizableInstr.h"
16114902Sscottl#include "llvm/Support/FormattedStream.h"
17114902Sscottl#include "llvm/TableGen/Error.h"
18114902Sscottl#include "llvm/TableGen/TableGenBackend.h"
19114902Sscottl
20114902Sscottlusing namespace llvm;
21114902Sscottl
22114902Sscottlnamespace {
23114902Sscottl
24114902Sscottl// 3 possible strategies for the unfolding flag (TB_NO_REVERSE) of the
25114902Sscottl// manual added entries.
26114902Sscottlenum UnfoldStrategy {
27114902Sscottl  UNFOLD,     // Allow unfolding
28114902Sscottl  NO_UNFOLD,  // Prevent unfolding
29114902Sscottl  NO_STRATEGY // Make decision according to operands' sizes
30152919Sscottl};
31152919Sscottl
32114902Sscottl// Represents an entry in the manual mapped instructions set.
33152919Sscottlstruct ManualMapEntry {
34114902Sscottl  const char *RegInstStr;
35114902Sscottl  const char *MemInstStr;
36114902Sscottl  UnfoldStrategy Strategy;
37114902Sscottl
38129879Sphk  ManualMapEntry(const char *RegInstStr, const char *MemInstStr,
39114902Sscottl                 UnfoldStrategy Strategy = NO_STRATEGY)
40114902Sscottl      : RegInstStr(RegInstStr), MemInstStr(MemInstStr), Strategy(Strategy) {}
41114902Sscottl};
42114902Sscottl
43114902Sscottlclass IsMatch;
44114902Sscottl
45114902Sscottl// List of instructions requiring explicitly aligned memory.
46126364Sscottlconst char *ExplicitAlign[] = {"MOVDQA",  "MOVAPS",  "MOVAPD",  "MOVNTPS",
47122999Smbr                               "MOVNTPD", "MOVNTDQ", "MOVNTDQA"};
48114902Sscottl
49114902Sscottl// List of instructions NOT requiring explicit memory alignment.
50114902Sscottlconst char *ExplicitUnalign[] = {"MOVDQU", "MOVUPS", "MOVUPD",
51114902Sscottl                                 "PCMPESTRM", "PCMPESTRI",
52114902Sscottl                                 "PCMPISTRM", "PCMPISTRI" };
53129859Sscottl
54129859Sscottl// For manually mapping instructions that do not match by their encoding.
55114902Sscottlconst ManualMapEntry ManualMapSet[] = {
56114902Sscottl    { "ADD16ri_DB",       "ADD16mi",         NO_UNFOLD  },
57114902Sscottl    { "ADD16ri8_DB",      "ADD16mi8",        NO_UNFOLD  },
58114902Sscottl    { "ADD16rr_DB",       "ADD16mr",         NO_UNFOLD  },
59114902Sscottl    { "ADD32ri_DB",       "ADD32mi",         NO_UNFOLD  },
60114902Sscottl    { "ADD32ri8_DB",      "ADD32mi8",        NO_UNFOLD  },
61114902Sscottl    { "ADD32rr_DB",       "ADD32mr",         NO_UNFOLD  },
62114902Sscottl    { "ADD64ri32_DB",     "ADD64mi32",       NO_UNFOLD  },
63114902Sscottl    { "ADD64ri8_DB",      "ADD64mi8",        NO_UNFOLD  },
64114902Sscottl    { "ADD64rr_DB",       "ADD64mr",         NO_UNFOLD  },
65114902Sscottl    { "ADD8ri_DB",        "ADD8mi",          NO_UNFOLD  },
66114902Sscottl    { "ADD8rr_DB",        "ADD8mr",          NO_UNFOLD  },
67114902Sscottl    { "ADD16rr_DB",       "ADD16rm",         NO_UNFOLD  },
68114902Sscottl    { "ADD32rr_DB",       "ADD32rm",         NO_UNFOLD  },
69114902Sscottl    { "ADD64rr_DB",       "ADD64rm",         NO_UNFOLD  },
70114902Sscottl    { "ADD8rr_DB",        "ADD8rm",          NO_UNFOLD  },
71114902Sscottl    { "PUSH16r",          "PUSH16rmm",       UNFOLD },
72150535Sscottl    { "PUSH32r",          "PUSH32rmm",       UNFOLD },
73114902Sscottl    { "PUSH64r",          "PUSH64rmm",       UNFOLD },
74150535Sscottl    { "TAILJMPr",         "TAILJMPm",        UNFOLD },
75150535Sscottl    { "TAILJMPr64",       "TAILJMPm64",      UNFOLD },
76150535Sscottl    { "TAILJMPr64_REX",   "TAILJMPm64_REX",  UNFOLD },
77161425Simp};
78150535Sscottl
79114902Sscottl
80114902Sscottlstatic bool isExplicitAlign(const CodeGenInstruction *Inst) {
81114902Sscottl  return any_of(ExplicitAlign, [Inst](const char *InstStr) {
82114902Sscottl    return Inst->TheDef->getName().find(InstStr) != StringRef::npos;
83114902Sscottl  });
84114902Sscottl}
85114902Sscottl
86150535Sscottlstatic bool isExplicitUnalign(const CodeGenInstruction *Inst) {
87114902Sscottl  return any_of(ExplicitUnalign, [Inst](const char *InstStr) {
88114902Sscottl    return Inst->TheDef->getName().find(InstStr) != StringRef::npos;
89114902Sscottl  });
90114902Sscottl}
91114902Sscottl
92114902Sscottlclass X86FoldTablesEmitter {
93114902Sscottl  RecordKeeper &Records;
94114902Sscottl  CodeGenTarget Target;
95114902Sscottl
96114902Sscottl  // Represents an entry in the folding table
97114902Sscottl  class X86FoldTableEntry {
98114902Sscottl    const CodeGenInstruction *RegInst;
99114902Sscottl    const CodeGenInstruction *MemInst;
100114902Sscottl
101114902Sscottl  public:
102114902Sscottl    bool CannotUnfold = false;
103140923Sscottl    bool IsLoad = false;
104140923Sscottl    bool IsStore = false;
105114902Sscottl    bool IsAligned = false;
106114902Sscottl    unsigned int Alignment = 0;
107114902Sscottl
108114902Sscottl    X86FoldTableEntry(const CodeGenInstruction *RegInst,
109114902Sscottl                      const CodeGenInstruction *MemInst)
110114902Sscottl        : RegInst(RegInst), MemInst(MemInst) {}
111140923Sscottl
112114902Sscottl    void print(formatted_raw_ostream &OS) const {
113114902Sscottl      OS.indent(2);
114114902Sscottl      OS << "{ X86::" << RegInst->TheDef->getName() << ",";
115114902Sscottl      OS.PadToColumn(40);
116114902Sscottl      OS  << "X86::" << MemInst->TheDef->getName() << ",";
117114902Sscottl      OS.PadToColumn(75);
118119997Sps
119116852Sscottl      if (IsLoad)
120116852Sscottl        OS << "TB_FOLDED_LOAD | ";
121114902Sscottl      if (IsStore)
122114902Sscottl        OS << "TB_FOLDED_STORE | ";
123114902Sscottl      if (CannotUnfold)
124114902Sscottl        OS << "TB_NO_REVERSE | ";
125114902Sscottl      if (IsAligned)
126114902Sscottl        OS << "TB_ALIGN_" << Alignment << " | ";
127114902Sscottl
128114902Sscottl      OS << "0 },\n";
129114902Sscottl    }
130114902Sscottl  };
131130585Sphk
132114902Sscottl  typedef std::vector<X86FoldTableEntry> FoldTable;
133122999Smbr  // std::vector for each folding table.
134114902Sscottl  // Table2Addr - Holds instructions which their memory form performs load+store
135114902Sscottl  // Table#i - Holds instructions which the their memory form perform a load OR
136114902Sscottl  //           a store,  and their #i'th operand is folded.
137114902Sscottl  FoldTable Table2Addr;
138122999Smbr  FoldTable Table0;
139122999Smbr  FoldTable Table1;
140114902Sscottl  FoldTable Table2;
141114902Sscottl  FoldTable Table3;
142114902Sscottl  FoldTable Table4;
143140923Sscottl
144140923Sscottlpublic:
145114902Sscottl  X86FoldTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {}
146114902Sscottl
147114902Sscottl  // run - Generate the 6 X86 memory fold tables.
148114902Sscottl  void run(formatted_raw_ostream &OS);
149114902Sscottl
150141062Sscottlprivate:
151114902Sscottl  // Decides to which table to add the entry with the given instructions.
152126364Sscottl  // S sets the strategy of adding the TB_NO_REVERSE flag.
153126364Sscottl  void updateTables(const CodeGenInstruction *RegInstr,
154140923Sscottl                    const CodeGenInstruction *MemInstr,
155126364Sscottl                    const UnfoldStrategy S = NO_STRATEGY);
156114902Sscottl
157114902Sscottl  // Generates X86FoldTableEntry with the given instructions and fill it with
158114902Sscottl  // the appropriate flags - then adds it to Table.
159114902Sscottl  void addEntryWithFlags(FoldTable &Table, const CodeGenInstruction *RegInstr,
160114902Sscottl                         const CodeGenInstruction *MemInstr,
161114902Sscottl                         const UnfoldStrategy S, const unsigned int FoldedInd);
162114902Sscottl
163114902Sscottl  // Print the given table as a static const C++ array of type
164114902Sscottl  // X86MemoryFoldTableEntry.
165114902Sscottl  void printTable(const FoldTable &Table, StringRef TableName,
166126364Sscottl                  formatted_raw_ostream &OS) {
167114902Sscottl    OS << "static const X86MemoryFoldTableEntry MemoryFold" << TableName
168114902Sscottl       << "[] = {\n";
169122999Smbr
170114902Sscottl    for (const X86FoldTableEntry &E : Table)
171114902Sscottl      E.print(OS);
172114902Sscottl
173114902Sscottl    OS << "};\n\n";
174140923Sscottl  }
175114902Sscottl};
176114902Sscottl
177114902Sscottl// Return true if one of the instruction's operands is a RST register class
178114902Sscottlstatic bool hasRSTRegClass(const CodeGenInstruction *Inst) {
179114902Sscottl  return any_of(Inst->Operands, [](const CGIOperandList::OperandInfo &OpIn) {
180114902Sscottl    return OpIn.Rec->getName() == "RST" || OpIn.Rec->getName() == "RSTi";
181141062Sscottl  });
182114902Sscottl}
183114902Sscottl
184114902Sscottl// Return true if one of the instruction's operands is a ptr_rc_tailcall
185141062Sscottlstatic bool hasPtrTailcallRegClass(const CodeGenInstruction *Inst) {
186114902Sscottl  return any_of(Inst->Operands, [](const CGIOperandList::OperandInfo &OpIn) {
187152919Sscottl    return OpIn.Rec->getName() == "ptr_rc_tailcall";
188152919Sscottl  });
189}
190
191// Calculates the integer value representing the BitsInit object
192static 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
204static 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
218static 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
228static inline unsigned int
229getMemOperandSize(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.
260static 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.
269static 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
277static inline bool isNOREXRegClass(const Record *Op) {
278  return Op->getName().find("_NOREX") != StringRef::npos;
279}
280
281static inline bool isRegisterOperand(const Record *Rec) {
282  return Rec->isSubClassOf("RegisterClass") ||
283         Rec->isSubClassOf("RegisterOperand") ||
284         Rec->isSubClassOf("PointerLikeRegClass");
285}
286
287static inline bool isMemoryOperand(const Record *Rec) {
288  return Rec->isSubClassOf("Operand") &&
289         Rec->getValueAsString("OperandType") == "OPERAND_MEMORY";
290}
291
292static 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.
298static inline const CodeGenInstruction *
299getAltRegInst(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.
312class IsMatch {
313  const CodeGenInstruction *MemInst;
314
315public:
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
419private:
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
454void 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
513void 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
575void 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
665namespace llvm {
666
667void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &o) {
668  formatted_raw_ostream OS(o);
669  X86FoldTablesEmitter(RK).run(OS);
670}
671} // namespace llvm
672