diff options
| author | Craig Topper <craig.topper@intel.com> | 2019-04-09 18:45:15 +0000 |
|---|---|---|
| committer | Craig Topper <craig.topper@intel.com> | 2019-04-09 18:45:15 +0000 |
| commit | 8e2871cd2c2e6d9e2dc74ac25a86d28219596534 (patch) | |
| tree | 6e456de8f4fcb144cb1cc29096c949848a9cac24 /llvm/lib/Target | |
| parent | f7433f9623533d7901fa1f0eb3bf0aaebbbbd73d (diff) | |
| download | bcm5719-llvm-8e2871cd2c2e6d9e2dc74ac25a86d28219596534.tar.gz bcm5719-llvm-8e2871cd2c2e6d9e2dc74ac25a86d28219596534.zip | |
[X86] Add support for {vex2}, {vex3}, and {evex} to the assembler to match gas. Use {evex} to improve the one our 32-bit AVX512 tests.
These can be used to force the encoding used for instructions.
{vex2} will fail if the instruction is not VEX encoded, but otherwise won't do anything since we prefer vex2 when possible. Might need to skip use of the _REV MOV instructions for this too, but I haven't done that yet.
{vex3} will force the instruction to use the 3 byte VEX encoding or fail if there is no VEX form.
{evex} will force the instruction to use the EVEX version or fail if there is no EVEX version.
Differential Revision: https://reviews.llvm.org/D59266
llvm-svn: 358029
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 114 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 3 |
3 files changed, 111 insertions, 9 deletions
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 50d2d195a3f..362e57ddefd 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -71,6 +71,15 @@ class X86AsmParser : public MCTargetAsmParser { ParseInstructionInfo *InstInfo; bool Code16GCC; + enum VEXEncoding { + VEXEncoding_Default, + VEXEncoding_VEX2, + VEXEncoding_VEX3, + VEXEncoding_EVEX, + }; + + VEXEncoding ForcedVEXEncoding = VEXEncoding_Default; + private: SMLoc consumeToken() { MCAsmParser &Parser = getParser(); @@ -858,6 +867,8 @@ private: bool parseDirectiveFPOEndProc(SMLoc L); bool parseDirectiveFPOData(SMLoc L); + unsigned checkTargetMatchPredicate(MCInst &Inst) override; + bool validateInstruction(MCInst &Inst, const OperandVector &Ops); bool processInstruction(MCInst &Inst, const OperandVector &Ops); @@ -939,6 +950,9 @@ private: /// } public: + enum X86MatchResultTy { + Match_Unsupported = FIRST_TARGET_MATCH_RESULT_TY, + }; X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser, const MCInstrInfo &mii, const MCTargetOptions &Options) @@ -2296,6 +2310,48 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { MCAsmParser &Parser = getParser(); InstInfo = &Info; + std::string TempName; // Used when we parse a pseudo prefix. + + // Reset the forced VEX encoding. + ForcedVEXEncoding = VEXEncoding_Default; + + // Parse pseudo prefixes. + while (1) { + if (Name == "{") { + if (getLexer().isNot(AsmToken::Identifier)) + return Error(Parser.getTok().getLoc(), "Unexpected token after '{'"); + std::string Prefix = Parser.getTok().getString().lower(); + Parser.Lex(); // Eat identifier. + if (getLexer().isNot(AsmToken::RCurly)) + return Error(Parser.getTok().getLoc(), "Expected '}'"); + Parser.Lex(); // Eat curly. + + if (Prefix == "vex2") + ForcedVEXEncoding = VEXEncoding_VEX2; + else if (Prefix == "vex3") + ForcedVEXEncoding = VEXEncoding_VEX3; + else if (Prefix == "evex") + ForcedVEXEncoding = VEXEncoding_EVEX; + else + return Error(NameLoc, "unknown prefix"); + + NameLoc = Parser.getTok().getLoc(); + if (getLexer().is(AsmToken::LCurly)) { + Parser.Lex(); + Name = "{"; + } else { + if (getLexer().isNot(AsmToken::Identifier)) + return Error(Parser.getTok().getLoc(), "Expected identifier"); + TempName = Parser.getTok().getString().lower(); + Name = TempName; + Parser.Lex(); + } + continue; + } + + break; + } + StringRef PatchedName = Name; if ((Name.equals("jmp") || Name.equals("jc") || Name.equals("jz")) && @@ -2943,6 +2999,22 @@ static unsigned getPrefixes(OperandVector &Operands) { return Result; } +unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) { + unsigned Opc = Inst.getOpcode(); + const MCInstrDesc &MCID = MII.get(Opc); + + if (ForcedVEXEncoding == VEXEncoding_EVEX && + (MCID.TSFlags & X86II::EncodingMask) != X86II::EVEX) + return Match_Unsupported; + + if ((ForcedVEXEncoding == VEXEncoding_VEX2 || + ForcedVEXEncoding == VEXEncoding_VEX3) && + (MCID.TSFlags & X86II::EncodingMask) != X86II::VEX) + return Match_Unsupported; + + return Match_Success; +} + bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -2956,18 +3028,24 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, MatchFPUWaitAlias(IDLoc, static_cast<X86Operand &>(*Operands[0]), Operands, Out, MatchingInlineAsm); X86Operand &Op = static_cast<X86Operand &>(*Operands[0]); - bool WasOriginallyInvalidOperand = false; unsigned Prefixes = getPrefixes(Operands); MCInst Inst; + // If VEX3 encoding is forced, we need to pass the USE_VEX3 flag to the + // encoder. + if (ForcedVEXEncoding == VEXEncoding_VEX3) + Prefixes |= X86::IP_USE_VEX3; + if (Prefixes) Inst.setFlags(Prefixes); // First, try a direct match. FeatureBitset MissingFeatures; - switch (MatchInstruction(Operands, Inst, ErrorInfo, MissingFeatures, - MatchingInlineAsm, isParsingIntelSyntax())) { + unsigned OriginalError = MatchInstruction(Operands, Inst, ErrorInfo, + MissingFeatures, MatchingInlineAsm, + isParsingIntelSyntax()); + switch (OriginalError) { default: llvm_unreachable("Unexpected match result!"); case Match_Success: if (!MatchingInlineAsm && validateInstruction(Inst, Operands)) @@ -2987,9 +3065,8 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_MissingFeature: return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm); case Match_InvalidOperand: - WasOriginallyInvalidOperand = true; - break; case Match_MnemonicFail: + case Match_Unsupported: break; } if (Op.getToken().empty()) { @@ -3080,11 +3157,15 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, // If all of the instructions reported an invalid mnemonic, then the original // mnemonic was invalid. if (std::count(std::begin(Match), std::end(Match), Match_MnemonicFail) == 4) { - if (!WasOriginallyInvalidOperand) { + if (OriginalError == Match_MnemonicFail) return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'", Op.getLocRange(), MatchingInlineAsm); - } + if (OriginalError == Match_Unsupported) + return Error(IDLoc, "unsupported instruction", EmptyRange, + MatchingInlineAsm); + + assert(OriginalError == Match_InvalidOperand && "Unexpected error"); // Recover location info for the operand if we know which was the problem. if (ErrorInfo != ~0ULL) { if (ErrorInfo >= Operands.size()) @@ -3103,6 +3184,13 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, MatchingInlineAsm); } + // If one instruction matched as unsupported, report this as unsupported. + if (std::count(std::begin(Match), std::end(Match), + Match_Unsupported) == 1) { + return Error(IDLoc, "unsupported instruction", EmptyRange, + MatchingInlineAsm); + } + // If one instruction matched with a missing feature, report this as a // missing feature. if (std::count(std::begin(Match), std::end(Match), @@ -3144,6 +3232,11 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst Inst; + // If VEX3 encoding is forced, we need to pass the USE_VEX3 flag to the + // encoder. + if (ForcedVEXEncoding == VEXEncoding_VEX3) + Prefixes |= X86::IP_USE_VEX3; + if (Prefixes) Inst.setFlags(Prefixes); @@ -3292,6 +3385,13 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, UnsizedMemOp->getLocRange()); } + // If one instruction matched as unsupported, report this as unsupported. + if (std::count(std::begin(Match), std::end(Match), + Match_Unsupported) == 1) { + return Error(IDLoc, "unsupported instruction", EmptyRange, + MatchingInlineAsm); + } + // If one instruction matched with a missing feature, report this as a // missing feature. if (std::count(std::begin(Match), std::end(Match), diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 1c4eff22d85..a56d64ce296 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -60,7 +60,8 @@ namespace X86 { IP_HAS_REPEAT_NE = 4, IP_HAS_REPEAT = 8, IP_HAS_LOCK = 16, - IP_HAS_NOTRACK = 32 + IP_HAS_NOTRACK = 32, + IP_USE_VEX3 = 64, }; enum OperandType : unsigned { diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index d063c4e5a86..8eb48fcb0bb 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -979,7 +979,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, uint8_t LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3); // Can we use the 2 byte VEX prefix? - if (Encoding == X86II::VEX && VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { + if (!(MI.getFlags() & X86::IP_USE_VEX3) && + Encoding == X86II::VEX && VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { EmitByte(0xC5, CurByte, OS); EmitByte(LastByte | (VEX_R << 7), CurByte, OS); return; |

