diff --git a/contrib/llvm-project/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp b/contrib/llvm-project/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp index fef8dc7236f5..ee0a96ee5b53 100644 --- a/contrib/llvm-project/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp +++ b/contrib/llvm-project/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp @@ -1,238 +1,238 @@ //==- utils/TableGen/X86CompressEVEXTablesEmitter.cpp - X86 backend-*- C++ -*-// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// This tablegen backend is responsible for emitting the X86 backend EVEX /// compression tables. /// //===----------------------------------------------------------------------===// #include "CodeGenInstruction.h" #include "CodeGenTarget.h" #include "X86RecognizableInstr.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include #include using namespace llvm; using namespace X86Disassembler; namespace { const std::map ManualMap = { #define ENTRY(OLD, NEW) {#OLD, #NEW}, #include "X86ManualCompressEVEXTables.def" }; const std::set NoCompressSet = { #define NOCOMP(INSN) #INSN, #include "X86ManualCompressEVEXTables.def" }; class X86CompressEVEXTablesEmitter { RecordKeeper &Records; CodeGenTarget Target; // Hold all pontentially compressible EVEX instructions std::vector PreCompressionInsts; // Hold all compressed instructions. Divided into groups with same opcodes // to make the search more efficient std::map> CompressedInsts; typedef std::pair Entry; - typedef std::map> + typedef std::map> PredicateInstMap; std::vector Table; // Hold all compressed instructions that need to check predicate PredicateInstMap PredicateInsts; public: X86CompressEVEXTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {} // run - Output X86 EVEX compression tables. void run(raw_ostream &OS); private: // Prints the given table as a C++ array of type X86CompressEVEXTableEntry void printTable(const std::vector &Table, raw_ostream &OS); // Prints function which checks target feature for compressed instructions. void printCheckPredicate(const PredicateInstMap &PredicateInsts, raw_ostream &OS); }; void X86CompressEVEXTablesEmitter::printTable(const std::vector &Table, raw_ostream &OS) { OS << "static const X86CompressEVEXTableEntry X86CompressEVEXTable[] = {\n"; // Print all entries added to the table for (const auto &Pair : Table) OS << " { X86::" << Pair.first->TheDef->getName() << ", X86::" << Pair.second->TheDef->getName() << " },\n"; OS << "};\n\n"; } void X86CompressEVEXTablesEmitter::printCheckPredicate( const PredicateInstMap &PredicateInsts, raw_ostream &OS) { OS << "static bool checkPredicate(unsigned Opc, const X86Subtarget *Subtarget) {\n" << " switch (Opc) {\n" << " default: return true;\n"; for (const auto &[Key, Val] : PredicateInsts) { for (const auto &Inst : Val) OS << " case X86::" << Inst->TheDef->getName() << ":\n"; - OS << " return " << Key->getValueAsString("CondString") << ";\n"; + OS << " return " << Key << ";\n"; } OS << " }\n"; OS << "}\n\n"; } static uint8_t byteFromBitsInit(const BitsInit *B) { unsigned N = B->getNumBits(); assert(N <= 8 && "Field is too large for uint8_t!"); uint8_t Value = 0; for (unsigned I = 0; I != N; ++I) { BitInit *Bit = cast(B->getBit(I)); Value |= Bit->getValue() << I; } return Value; } class IsMatch { const CodeGenInstruction *OldInst; public: IsMatch(const CodeGenInstruction *OldInst) : OldInst(OldInst) {} bool operator()(const CodeGenInstruction *NewInst) { RecognizableInstrBase NewRI(*NewInst); RecognizableInstrBase OldRI(*OldInst); // Return false if any of the following fields of does not match. if (std::make_tuple(OldRI.IsCodeGenOnly, OldRI.OpMap, NewRI.OpPrefix, OldRI.HasVEX_4V, OldRI.HasVEX_L, OldRI.HasREX_W, OldRI.Form) != std::make_tuple(NewRI.IsCodeGenOnly, NewRI.OpMap, OldRI.OpPrefix, NewRI.HasVEX_4V, NewRI.HasVEX_L, NewRI.HasREX_W, NewRI.Form)) return false; for (unsigned I = 0, E = OldInst->Operands.size(); I < E; ++I) { Record *OldOpRec = OldInst->Operands[I].Rec; Record *NewOpRec = NewInst->Operands[I].Rec; if (OldOpRec == NewOpRec) continue; if (isRegisterOperand(OldOpRec) && isRegisterOperand(NewOpRec)) { if (getRegOperandSize(OldOpRec) != getRegOperandSize(NewOpRec)) return false; } else if (isMemoryOperand(OldOpRec) && isMemoryOperand(NewOpRec)) { if (getMemOperandSize(OldOpRec) != getMemOperandSize(NewOpRec)) return false; } else if (isImmediateOperand(OldOpRec) && isImmediateOperand(NewOpRec)) { if (OldOpRec->getValueAsDef("Type") != NewOpRec->getValueAsDef("Type")) return false; } } return true; } }; void X86CompressEVEXTablesEmitter::run(raw_ostream &OS) { emitSourceFileHeader("X86 EVEX compression tables", OS); ArrayRef NumberedInstructions = Target.getInstructionsByEnumValue(); for (const CodeGenInstruction *Inst : NumberedInstructions) { const Record *Rec = Inst->TheDef; StringRef Name = Rec->getName(); // _REV instruction should not appear before encoding optimization if (!Rec->isSubClassOf("X86Inst") || Rec->getValueAsBit("isAsmParserOnly") || Name.ends_with("_REV")) continue; // Promoted legacy instruction is in EVEX space, and has REX2-encoding // alternative. It's added due to HW design and never emitted by compiler. if (byteFromBitsInit(Rec->getValueAsBitsInit("OpMapBits")) == X86Local::T_MAP4 && byteFromBitsInit(Rec->getValueAsBitsInit("explicitOpPrefixBits")) == X86Local::ExplicitEVEX) continue; if (NoCompressSet.find(Name) != NoCompressSet.end()) continue; RecognizableInstrBase RI(*Inst); bool IsND = RI.OpMap == X86Local::T_MAP4 && RI.HasEVEX_B && RI.HasVEX_4V; // Add VEX encoded instructions to one of CompressedInsts vectors according // to it's opcode. if (RI.Encoding == X86Local::VEX) CompressedInsts[RI.Opcode].push_back(Inst); // Add relevant EVEX encoded instructions to PreCompressionInsts else if (RI.Encoding == X86Local::EVEX && !RI.HasEVEX_K && !RI.HasEVEX_L2 && (!RI.HasEVEX_B || IsND)) PreCompressionInsts.push_back(Inst); } for (const CodeGenInstruction *Inst : PreCompressionInsts) { const Record *Rec = Inst->TheDef; uint8_t Opcode = byteFromBitsInit(Rec->getValueAsBitsInit("Opcode")); StringRef Name = Rec->getName(); const CodeGenInstruction *NewInst = nullptr; if (ManualMap.find(Name) != ManualMap.end()) { Record *NewRec = Records.getDef(ManualMap.at(Rec->getName())); assert(NewRec && "Instruction not found!"); NewInst = &Target.getInstruction(NewRec); } else if (Name.ends_with("_EVEX")) { if (auto *NewRec = Records.getDef(Name.drop_back(5))) NewInst = &Target.getInstruction(NewRec); } else if (Name.ends_with("_ND")) { if (auto *NewRec = Records.getDef(Name.drop_back(3))) { auto &TempInst = Target.getInstruction(NewRec); if (isRegisterOperand(TempInst.Operands[0].Rec)) NewInst = &TempInst; } } else { // For each pre-compression instruction look for a match in the appropriate // vector (instructions with the same opcode) using function object // IsMatch. auto Match = llvm::find_if(CompressedInsts[Opcode], IsMatch(Inst)); if (Match != CompressedInsts[Opcode].end()) NewInst = *Match; } if (!NewInst) continue; Table.push_back(std::make_pair(Inst, NewInst)); auto Predicates = NewInst->TheDef->getValueAsListOfDefs("Predicates"); auto It = llvm::find_if(Predicates, [](const Record *R) { StringRef Name = R->getName(); return Name == "HasAVXNECONVERT" || Name == "HasAVXVNNI" || Name == "HasAVXIFMA"; }); if(It!= Predicates.end()) - PredicateInsts[*It].push_back(NewInst); + PredicateInsts[(*It)->getValueAsString("CondString")].push_back(NewInst); } printTable(Table, OS); printCheckPredicate(PredicateInsts, OS); } } // namespace static TableGen::Emitter::OptClass X("gen-x86-compress-evex-tables", "Generate X86 EVEX compression tables");