1 //===- utils/TableGen/X86FoldTablesEmitter.cpp - X86 backend-*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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/Support/FormattedStream.h"
17 #include "llvm/TableGen/Error.h"
18 #include "llvm/TableGen/TableGenBackend.h"
24 // 3 possible strategies for the unfolding flag (TB_NO_REVERSE) of the
25 // manual added entries.
27 UNFOLD
, // Allow unfolding
28 NO_UNFOLD
, // Prevent unfolding
29 NO_STRATEGY
// Make decision according to operands' sizes
32 // Represents an entry in the manual mapped instructions set.
33 struct ManualMapEntry
{
34 const char *RegInstStr
;
35 const char *MemInstStr
;
36 UnfoldStrategy Strategy
;
38 ManualMapEntry(const char *RegInstStr
, const char *MemInstStr
,
39 UnfoldStrategy Strategy
= NO_STRATEGY
)
40 : RegInstStr(RegInstStr
), MemInstStr(MemInstStr
), Strategy(Strategy
) {}
45 // List of instructions requiring explicitly aligned memory.
46 const char *ExplicitAlign
[] = {"MOVDQA", "MOVAPS", "MOVAPD", "MOVNTPS",
47 "MOVNTPD", "MOVNTDQ", "MOVNTDQA"};
49 // List of instructions NOT requiring explicit memory alignment.
50 const char *ExplicitUnalign
[] = {"MOVDQU", "MOVUPS", "MOVUPD",
51 "PCMPESTRM", "PCMPESTRI",
52 "PCMPISTRM", "PCMPISTRI" };
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
},
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
;
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
;
92 class X86FoldTablesEmitter
{
93 RecordKeeper
&Records
;
96 // Represents an entry in the folding table
97 class X86FoldTableEntry
{
98 const CodeGenInstruction
*RegInst
;
99 const CodeGenInstruction
*MemInst
;
102 bool CannotUnfold
= false;
104 bool IsStore
= false;
105 bool IsAligned
= false;
106 unsigned int Alignment
= 0;
108 X86FoldTableEntry(const CodeGenInstruction
*RegInst
,
109 const CodeGenInstruction
*MemInst
)
110 : RegInst(RegInst
), MemInst(MemInst
) {}
112 void print(formatted_raw_ostream
&OS
) const {
114 OS
<< "{ X86::" << RegInst
->TheDef
->getName() << ",";
116 OS
<< "X86::" << MemInst
->TheDef
->getName() << ",";
120 OS
<< "TB_FOLDED_LOAD | ";
122 OS
<< "TB_FOLDED_STORE | ";
124 OS
<< "TB_NO_REVERSE | ";
126 OS
<< "TB_ALIGN_" << Alignment
<< " | ";
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
;
145 X86FoldTablesEmitter(RecordKeeper
&R
) : Records(R
), Target(R
) {}
147 // run - Generate the 6 X86 memory fold tables.
148 void run(formatted_raw_ostream
&OS
);
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
);
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
);
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
170 for (const X86FoldTableEntry
&E
: Table
)
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";
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";
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!");
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
;
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!");
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())
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");
224 llvm_unreachable("Register operand's size not known!");
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"))
237 MemRec
->getValueAsDef("ParserMatchClass")->getValueAsString("Name");
248 if (Name
== "Mem128")
250 if (Name
== "Mem256")
252 if (Name
== "Mem512")
256 llvm_unreachable("Memory operand's size not known!");
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
);
264 // Values from X86Local namespace defined in X86RecognizableInstr.cpp
265 return FormBitsNum
>= X86Local::MRMDestReg
&& FormBitsNum
<= X86Local::MRM7r
;
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
);
273 // Values from X86Local namespace defined in X86RecognizableInstr.cpp
274 return FormBitsNum
>= X86Local::MRMDestMem
&& FormBitsNum
<= X86Local::MRM7m
;
277 static inline bool isNOREXRegClass(const Record
*Op
) {
278 return Op
->getName().find("_NOREX") != StringRef::npos
;
281 static inline bool isRegisterOperand(const Record
*Rec
) {
282 return Rec
->isSubClassOf("RegisterClass") ||
283 Rec
->isSubClassOf("RegisterOperand") ||
284 Rec
->isSubClassOf("PointerLikeRegClass");
287 static inline bool isMemoryOperand(const Record
*Rec
) {
288 return Rec
->isSubClassOf("Operand") &&
289 Rec
->getValueAsString("OperandType") == "OPERAND_MEMORY";
292 static inline bool isImmediateOperand(const Record
*Rec
) {
293 return Rec
->isSubClassOf("Operand") &&
294 Rec
->getValueAsString("OperandType") == "OPERAND_IMMEDIATE";
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
) {
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
);
310 // Function object - Operator() returns true if the given VEX instruction
311 // matches the EVEX instruction of this object.
313 const CodeGenInstruction
*MemInst
;
316 IsMatch(const CodeGenInstruction
*Inst
, const RecordKeeper
&Records
)
319 bool operator()(const CodeGenInstruction
*RegInst
) {
320 Record
*MemRec
= MemInst
->TheDef
;
321 Record
*RegRec
= RegInst
->TheDef
;
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")) ||
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"))
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();
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;
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
;
393 if (MemOpRec
== RegOpRec
)
396 if (isRegisterOperand(MemOpRec
) && isRegisterOperand(RegOpRec
)) {
397 if (getRegOperandSize(MemOpRec
) != getRegOperandSize(RegOpRec
) ||
398 isNOREXRegClass(MemOpRec
) != isNOREXRegClass(RegOpRec
))
400 } else if (isMemoryOperand(MemOpRec
) && isMemoryOperand(RegOpRec
)) {
401 if (getMemOperandSize(MemOpRec
) != getMemOperandSize(RegOpRec
))
403 } else if (isImmediateOperand(MemOpRec
) && isImmediateOperand(RegOpRec
)) {
404 if (MemOpRec
->getValueAsDef("Type") != RegOpRec
->getValueAsDef("Type"))
407 // Only one operand can be folded.
411 assert(isRegisterOperand(RegOpRec
) && isMemoryOperand(MemOpRec
));
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
);
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
))
452 } // end anonymous namespace
454 void X86FoldTablesEmitter::addEntryWithFlags(FoldTable
&Table
,
455 const CodeGenInstruction
*RegInstr
,
456 const CodeGenInstruction
*MemInstr
,
457 const UnfoldStrategy S
,
458 const unsigned int FoldedInd
) {
460 X86FoldTableEntry Result
= X86FoldTableEntry(RegInstr
, MemInstr
);
461 Record
*RegRec
= RegInstr
->TheDef
;
462 Record
*MemRec
= MemInstr
->TheDef
;
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
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;
476 Result
.IsStore
= true;
479 Record
*RegOpRec
= RegInstr
->Operands
[FoldedInd
].Rec
;
480 Record
*MemOpRec
= MemInstr
->Operands
[FoldedInd
].Rec
;
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
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
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;
510 Table
.push_back(Result
);
513 void X86FoldTablesEmitter::updateTables(const CodeGenInstruction
*RegInstr
,
514 const CodeGenInstruction
*MemInstr
,
515 const UnfoldStrategy S
) {
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();
524 // Instructions which Read-Modify-Write should be added to Table2Addr.
525 if (MemOutSize
!= RegOutSize
&& MemInSize
== RegInSize
) {
526 addEntryWithFlags(Table2Addr
, RegInstr
, MemInstr
, S
, 0);
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
)) {
540 addEntryWithFlags(Table0
, RegInstr
, MemInstr
, S
, 0);
543 addEntryWithFlags(Table1
, RegInstr
, MemInstr
, S
, 1);
546 addEntryWithFlags(Table2
, RegInstr
, MemInstr
, S
, 2);
549 addEntryWithFlags(Table3
, RegInstr
, MemInstr
, S
, 3);
552 addEntryWithFlags(Table4
, RegInstr
, MemInstr
, S
, 4);
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.
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);
575 void X86FoldTablesEmitter::run(formatted_raw_ostream
&OS
) {
576 emitSourceFileHeader("X86 fold tables", OS
);
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
;
583 ArrayRef
<const CodeGenInstruction
*> NumberedInstructions
=
584 Target
.getInstructionsByEnumValue();
586 for (const CodeGenInstruction
*Inst
: NumberedInstructions
) {
587 if (!Inst
->TheDef
->getNameInit() || !Inst
->TheDef
->isSubClassOf("X86Inst"))
590 const Record
*Rec
= Inst
->TheDef
;
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
))
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
);
615 // For each memory form instruction, try to find its register form
617 for (const CodeGenInstruction
*MemInst
: MemInsts
) {
619 getValueFromBitsInit(MemInst
->TheDef
->getValueAsBitsInit("Opcode"));
621 if (RegInsts
.count(Opc
) == 0)
624 // Two forms (memory & register) of the same instruction must have the same
625 // opcode. try matching only with register form instructions with the same
627 std::vector
<const CodeGenInstruction
*> &OpcRegInsts
=
628 RegInsts
.find(Opc
)->second
;
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
636 if (RegInst
->TheDef
->isValueUnset("FoldGenRegForm")) {
637 updateTables(RegInst
, MemInst
);
639 const CodeGenInstruction
*AltRegInst
=
640 getAltRegInst(RegInst
, Records
, Target
);
641 updateTables(AltRegInst
, MemInst
);
643 OpcRegInsts
.erase(Match
);
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
);
652 updateTables(&(Target
.getInstruction(RegInstIter
)),
653 &(Target
.getInstruction(MemInstIter
)), Entry
.Strategy
);
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
);
667 void EmitX86FoldTables(RecordKeeper
&RK
, raw_ostream
&o
) {
668 formatted_raw_ostream
OS(o
);
669 X86FoldTablesEmitter(RK
).run(OS
);