diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt --- a/llvm/lib/Target/X86/CMakeLists.txt +++ b/llvm/lib/Target/X86/CMakeLists.txt @@ -19,7 +19,7 @@ tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget) if (X86_GEN_FOLD_TABLES) - tablegen(LLVM X86GenFoldTables.inc -gen-x86-fold-tables) + tablegen(LLVM X86GenFoldTables.inc -gen-x86-fold-tables -asmwriternum=1) endif() add_public_tablegen_target(X86CommonTableGen) diff --git a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp --- a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp +++ b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp @@ -317,15 +317,26 @@ // matches the EVEX instruction of this object. class IsMatch { const CodeGenInstruction *MemInst; + unsigned Variant; public: - IsMatch(const CodeGenInstruction *Inst, const RecordKeeper &Records) - : MemInst(Inst) {} + IsMatch(const CodeGenInstruction *Inst, unsigned V) + : MemInst(Inst), Variant(V) {} bool operator()(const CodeGenInstruction *RegInst) { Record *MemRec = MemInst->TheDef; Record *RegRec = RegInst->TheDef; + // X86 encoding is crazy, e.g + // + // f3 0f c7 30 vmxon (%rax) + // f3 0f c7 f0 senduipi %rax + // + // This two instruction have similiar encoding fileds but are unrelated + if (X86Disassembler::getMnemonic(MemInst, Variant) != + X86Disassembler::getMnemonic(RegInst, Variant)) + return false; + // Return false if one (at least) of the encoding fields of both // instructions do not match. if (RegRec->getValueAsDef("OpEnc") != MemRec->getValueAsDef("OpEnc") || @@ -616,6 +627,8 @@ } } + Record *AsmWriter = Target.getAsmWriter(); + unsigned Variant = AsmWriter->getValueAsInt("Variant"); // For each memory form instruction, try to find its register form // instruction. for (const CodeGenInstruction *MemInst : MemInsts) { @@ -631,7 +644,7 @@ // opcode. std::vector &OpcRegInsts = RegInstsIt->second; - auto Match = find_if(OpcRegInsts, IsMatch(MemInst, Records)); + auto Match = find_if(OpcRegInsts, IsMatch(MemInst, Variant)); if (Match != OpcRegInsts.end()) { const CodeGenInstruction *RegInst = *Match; // If the matched instruction has it's "FoldGenRegForm" set, map the diff --git a/llvm/utils/TableGen/X86MnemonicTables.cpp b/llvm/utils/TableGen/X86MnemonicTables.cpp --- a/llvm/utils/TableGen/X86MnemonicTables.cpp +++ b/llvm/utils/TableGen/X86MnemonicTables.cpp @@ -59,21 +59,8 @@ // Skip CodeGenInstructions that are not real standalone instructions RI.Form == X86Local::PrefixByte || RI.Form == X86Local::Pseudo) continue; - // Flatten an instruction assembly string. - std::string AsmString = I->FlattenAsmStringVariants(I->AsmString, Variant); - StringRef Mnemonic(AsmString); - // Extract a mnemonic assuming it's separated by \t - Mnemonic = Mnemonic.take_until([](char C) { return C == '\t'; }); - - // Special case: CMOVCC, JCC, SETCC have "${cond}" in mnemonic. - // Replace it with "CC" in-place. - size_t CondPos = Mnemonic.find("${cond}"); - if (CondPos != StringRef::npos) - Mnemonic = AsmString.replace(CondPos, StringRef::npos, "CC"); - - // It's intentional that we put a std::string to the map (StringRef::upper - // returns a string) as AsmString is deallocated at the end of the iteration - MnemonicToCGInstrMap[Mnemonic.upper()].push_back(I); + std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant); + MnemonicToCGInstrMap[Mnemonic].push_back(I); } OS << "#ifdef GET_X86_MNEMONIC_TABLES_H\n"; diff --git a/llvm/utils/TableGen/X86RecognizableInstr.h b/llvm/utils/TableGen/X86RecognizableInstr.h --- a/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/llvm/utils/TableGen/X86RecognizableInstr.h @@ -363,6 +363,7 @@ InstrUID uid); }; +std::string getMnemonic(const CodeGenInstruction *I, unsigned Variant); } // namespace X86Disassembler } // namespace llvm diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp --- a/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -24,6 +24,20 @@ using namespace llvm; using namespace X86Disassembler; +std::string X86Disassembler::getMnemonic(const CodeGenInstruction *I, unsigned Variant) { + std::string AsmString = I->FlattenAsmStringVariants(I->AsmString, Variant); + StringRef Mnemonic(AsmString); + // Extract a mnemonic assuming it's separated by \t + Mnemonic = Mnemonic.take_until([](char C) { return C == '\t'; }); + + // Special case: CMOVCC, JCC, SETCC have "${cond}" in mnemonic. + // Replace it with "CC" in-place. + size_t CondPos = Mnemonic.find("${cond}"); + if (CondPos != StringRef::npos) + Mnemonic = AsmString.replace(CondPos, StringRef::npos, "CC"); + return Mnemonic.upper(); +} + /// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit. /// Useful for switch statements and the like. ///