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/TableGen/Error.h"
17 #include "llvm/TableGen/TableGenBackend.h"
23 // 3 possible strategies for the unfolding flag (TB_NO_REVERSE) of the
24 // manual added entries.
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
) {}
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
;
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
;
88 class X86FoldTablesEmitter
{
89 RecordKeeper
&Records
;
92 // Represents an entry in the folding table
93 class X86FoldTableEntry
{
94 const CodeGenInstruction
*RegInst
;
95 const CodeGenInstruction
*MemInst
;
98 bool CannotUnfold
= 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() << ", ";
114 OS
<< "TB_FOLDED_LOAD | ";
116 OS
<< "TB_FOLDED_STORE | ";
118 OS
<< "TB_NO_REVERSE | ";
120 OS
<< "TB_ALIGN_" << E
.Alignment
<< " | ";
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
;
141 X86FoldTablesEmitter(RecordKeeper
&R
) : Records(R
), Target(R
) {}
143 // run - Generate the 6 X86 memory fold tables.
144 void run(raw_ostream
&OS
);
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
,
163 OS
<< "static const X86MemoryFoldTableEntry MemoryFold" << TableName
166 for (const X86FoldTableEntry
&E
: Table
)
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!");
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
;
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())
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"))
233 MemRec
->getValueAsDef("ParserMatchClass")->getValueAsString("Name");
244 if (Name
== "Mem128")
246 if (Name
== "Mem256")
248 if (Name
== "Mem512")
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
);
306 // Function object - Operator() returns true if the given VEX instruction
307 // matches the EVEX instruction of this object.
309 const CodeGenInstruction
*MemInst
;
312 IsMatch(const CodeGenInstruction
*Inst
, const RecordKeeper
&Records
)
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")) ||
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"))
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
)
384 if (isRegisterOperand(MemOpRec
) && isRegisterOperand(RegOpRec
)) {
385 if (getRegOperandSize(MemOpRec
) != getRegOperandSize(RegOpRec
) ||
386 isNOREXRegClass(MemOpRec
) != isNOREXRegClass(RegOpRec
))
388 } else if (isMemoryOperand(MemOpRec
) && isMemoryOperand(RegOpRec
)) {
389 if (getMemOperandSize(MemOpRec
) != getMemOperandSize(RegOpRec
))
391 } else if (isImmediateOperand(MemOpRec
) && isImmediateOperand(RegOpRec
)) {
392 if (MemOpRec
->getValueAsDef("Type") != RegOpRec
->getValueAsDef("Type"))
395 // Only one operand can be folded.
399 assert(isRegisterOperand(RegOpRec
) && isMemoryOperand(MemOpRec
));
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
))
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
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;
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
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);
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
)) {
525 addEntryWithFlags(Table0
, RegInstr
, MemInstr
, S
, 0);
528 addEntryWithFlags(Table1
, RegInstr
, MemInstr
, S
, 1);
531 addEntryWithFlags(Table2
, RegInstr
, MemInstr
, S
, 2);
534 addEntryWithFlags(Table3
, RegInstr
, MemInstr
, S
, 3);
537 addEntryWithFlags(Table4
, RegInstr
, MemInstr
, S
, 4);
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.
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);
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"))
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
))
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
602 for (const CodeGenInstruction
*MemInst
: MemInsts
) {
604 getValueFromBitsInit(MemInst
->TheDef
->getValueAsBitsInit("Opcode"));
606 if (RegInsts
.count(Opc
) == 0)
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
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
621 if (RegInst
->TheDef
->isValueUnset("FoldGenRegForm")) {
622 updateTables(RegInst
, MemInst
);
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
);
652 void EmitX86FoldTables(RecordKeeper
&RK
, raw_ostream
&OS
) {
653 X86FoldTablesEmitter(RK
).run(OS
);