diff options
author | Craig Topper <craig.topper@intel.com> | 2018-06-19 04:24:44 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2018-06-19 04:24:44 +0000 |
commit | c2965214efbd35ed54e08cce042e8eed778646aa (patch) | |
tree | a6ffdedbcc558cc1ea19cad92b1491a691093612 /llvm/utils | |
parent | 0a5e90cc2a6d954ee0c2fae99e0f5d0cb82b3168 (diff) | |
download | bcm5719-llvm-c2965214efbd35ed54e08cce042e8eed778646aa.tar.gz bcm5719-llvm-c2965214efbd35ed54e08cce042e8eed778646aa.zip |
[X86] Add the ability to force an EVEX2VEX mapping table entry from the .td files. Remove remaining manual table entries from the tablegen emitter.
This adds an EVEX2VEXOverride string to the X86 instruction class in X86InstrFormats.td. If this field is set it will add manual entry in the EVEX->VEX tables that doesn't check the encoding information.
Then use this mechanism to map VMOVDU/A8/16, 128-bit VALIGN, and VPSHUFF/I instructions to VEX instructions.
Finally, remove the manual table from the emitter.
This has the bonus of fully sorting the autogenerated EVEX->VEX tables by their EVEX instruction enum value. We may be able to use this to do a binary search for the conversion and get rid of the need to create a DenseMap.
llvm-svn: 335018
Diffstat (limited to 'llvm/utils')
-rw-r--r-- | llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp | 101 |
1 files changed, 30 insertions, 71 deletions
diff --git a/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp b/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp index a3ec380a4bc..d5dc10ecad2 100644 --- a/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp +++ b/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp @@ -21,6 +21,7 @@ using namespace llvm; namespace { class X86EVEX2VEXTablesEmitter { + RecordKeeper &Records; CodeGenTarget Target; // Hold all non-masked & non-broadcasted EVEX encoded instructions @@ -35,15 +36,8 @@ class X86EVEX2VEXTablesEmitter { std::vector<Entry> EVEX2VEX128; std::vector<Entry> EVEX2VEX256; - // Represents a manually added entry to the tables - struct ManualEntry { - const char *EVEXInstStr; - const char *VEXInstStr; - bool Is128Bit; - }; - public: - X86EVEX2VEXTablesEmitter(RecordKeeper &R) : Target(R) {} + X86EVEX2VEXTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {} // run - Output X86 EVEX2VEX tables. void run(raw_ostream &OS); @@ -71,53 +65,6 @@ void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table, << ", X86::" << Pair.second->TheDef->getName() << " },\n"; } - // Some VEX instructions were duplicated to multiple EVEX versions due the - // introduction of mask variants, and thus some of the EVEX versions have - // different encoding than the VEX instruction. In order to maximize the - // compression we add these entries manually. - static constexpr ManualEntry ManuallyAddedEntries[] = { - // EVEX-Inst VEX-Inst Is128-bit - {"VMOVDQU8Z128mr", "VMOVDQUmr", true}, - {"VMOVDQU8Z128rm", "VMOVDQUrm", true}, - {"VMOVDQU8Z128rr", "VMOVDQUrr", true}, - {"VMOVDQU8Z128rr_REV", "VMOVDQUrr_REV", true}, - {"VMOVDQU16Z128mr", "VMOVDQUmr", true}, - {"VMOVDQU16Z128rm", "VMOVDQUrm", true}, - {"VMOVDQU16Z128rr", "VMOVDQUrr", true}, - {"VMOVDQU16Z128rr_REV", "VMOVDQUrr_REV", true}, - {"VMOVDQU8Z256mr", "VMOVDQUYmr", false}, - {"VMOVDQU8Z256rm", "VMOVDQUYrm", false}, - {"VMOVDQU8Z256rr", "VMOVDQUYrr", false}, - {"VMOVDQU8Z256rr_REV", "VMOVDQUYrr_REV", false}, - {"VMOVDQU16Z256mr", "VMOVDQUYmr", false}, - {"VMOVDQU16Z256rm", "VMOVDQUYrm", false}, - {"VMOVDQU16Z256rr", "VMOVDQUYrr", false}, - {"VMOVDQU16Z256rr_REV", "VMOVDQUYrr_REV", false}, - - // These will require some custom adjustment in the conversion pass. - {"VALIGNDZ128rri", "VPALIGNRrri", true}, - {"VALIGNQZ128rri", "VPALIGNRrri", true}, - {"VALIGNDZ128rmi", "VPALIGNRrmi", true}, - {"VALIGNQZ128rmi", "VPALIGNRrmi", true}, - {"VSHUFF32X4Z256rmi", "VPERM2F128rm", false}, - {"VSHUFF32X4Z256rri", "VPERM2F128rr", false}, - {"VSHUFF64X2Z256rmi", "VPERM2F128rm", false}, - {"VSHUFF64X2Z256rri", "VPERM2F128rr", false}, - {"VSHUFI32X4Z256rmi", "VPERM2I128rm", false}, - {"VSHUFI32X4Z256rri", "VPERM2I128rr", false}, - {"VSHUFI64X2Z256rmi", "VPERM2I128rm", false}, - {"VSHUFI64X2Z256rri", "VPERM2I128rr", false}, - }; - - // Print the manually added entries - for (const ManualEntry &Entry : ManuallyAddedEntries) { - if ((Table == EVEX2VEX128 && Entry.Is128Bit) || - (Table == EVEX2VEX256 && !Entry.Is128Bit)) { - OS << " { X86::" << Entry.EVEXInstStr << ", X86::" << Entry.VEXInstStr - << " },\n"; - } - } - OS << "};\n\n"; } @@ -271,22 +218,34 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) { getValueAsBitsInit("Opcode")); // For each EVEX instruction look for a VEX match in the appropriate vector // (instructions with the same opcode) using function object IsMatch. - auto Match = llvm::find_if(VEXInsts[Opcode], IsMatch(EVEXInst)); - if (Match != VEXInsts[Opcode].end()) { - const CodeGenInstruction *VEXInst = *Match; - - // In case a match is found add new entry to the appropriate table - switch (getValueFromBitsInit( - EVEXInst->TheDef->getValueAsBitsInit("EVEX_LL"))) { - case 0: - EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0} - break; - case 1: - EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1} - break; - default: - llvm_unreachable("Instruction's size not fit for the mapping!"); - } + // Allow EVEX2VEXOverride to explicitly specify a match. + const CodeGenInstruction *VEXInst = nullptr; + if (!EVEXInst->TheDef->isValueUnset("EVEX2VEXOverride")) { + StringRef AltInstStr = + EVEXInst->TheDef->getValueAsString("EVEX2VEXOverride"); + Record *AltInstRec = Records.getDef(AltInstStr); + assert(AltInstRec && "EVEX2VEXOverride instruction not found!"); + VEXInst = &Target.getInstruction(AltInstRec); + } else { + auto Match = llvm::find_if(VEXInsts[Opcode], IsMatch(EVEXInst)); + if (Match != VEXInsts[Opcode].end()) + VEXInst = *Match; + } + + if (!VEXInst) + continue; + + // In case a match is found add new entry to the appropriate table + switch (getValueFromBitsInit( + EVEXInst->TheDef->getValueAsBitsInit("EVEX_LL"))) { + case 0: + EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0} + break; + case 1: + EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1} + break; + default: + llvm_unreachable("Instruction's size not fit for the mapping!"); } } |