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