Index: lib/Target/AMDGPU/AMDGPU.td =================================================================== --- lib/Target/AMDGPU/AMDGPU.td +++ lib/Target/AMDGPU/AMDGPU.td @@ -349,10 +349,45 @@ let ShouldEmitMatchRegisterName = 0; } +def AMDGPUAsmVariants { + string Default = "Default"; + int Default_ID = 0; + string VOP3 = "VOP3"; + int VOP3_ID = 1; + string SDWA = "SDWA"; + int SDWA_ID = 2; + string DPP = "DPP"; + int DPP_ID = 3; +} + +def DefaultAMDGPUAsmParserVariant : AsmParserVariant { + let Variant = AMDGPUAsmVariants.Default_ID; + let Name = AMDGPUAsmVariants.Default; +} + +def VOP3AsmParserVariant : AsmParserVariant { + let Variant = AMDGPUAsmVariants.VOP3_ID; + let Name = AMDGPUAsmVariants.VOP3; +} + +def SDWAAsmParserVariant : AsmParserVariant { + let Variant = AMDGPUAsmVariants.SDWA_ID; + let Name = AMDGPUAsmVariants.SDWA; +} + +def DPPAsmParserVariant : AsmParserVariant { + let Variant = AMDGPUAsmVariants.DPP_ID; + let Name = AMDGPUAsmVariants.DPP; +} + def AMDGPU : Target { // Pull in Instruction Info: let InstructionSet = AMDGPUInstrInfo; let AssemblyParsers = [AMDGPUAsmParser]; + let AssemblyParserVariants = [DefaultAMDGPUAsmParserVariant, + VOP3AsmParserVariant, + SDWAAsmParserVariant, + DPPAsmParserVariant]; } // Dummy Instruction itineraries for pseudo instructions Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1147,35 +1147,76 @@ MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) { + // What asm variants we should check + std::vector MatchedVariants; + if (getForcedEncodingSize() == 32) { + MatchedVariants = {AMDGPUAsmVariants::DEFAULT}; + } else if (isForcedVOP3()) { + MatchedVariants = {AMDGPUAsmVariants::VOP3}; + } else if (isForcedSDWA()) { + MatchedVariants = {AMDGPUAsmVariants::SDWA}; + } else if (isForcedDPP()) { + MatchedVariants = {AMDGPUAsmVariants::DPP}; + } else { + MatchedVariants = {AMDGPUAsmVariants::DEFAULT, + AMDGPUAsmVariants::VOP3, + AMDGPUAsmVariants::SDWA, + AMDGPUAsmVariants::DPP}; + } + MCInst Inst; + unsigned Result = Match_Success; + for (auto Variant : MatchedVariants) { + uint64_t EI; + auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, + Variant); + // We order match statuses from least to most specific. We use most specific + // status as resulting + // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32 + if ((R == Match_Success) || + (R == Match_PreferE32) || + (R == Match_MissingFeature && Result != Match_PreferE32) || + (R == Match_InvalidOperand && Result != Match_MissingFeature + && Result != Match_PreferE32) || + (R == Match_MnemonicFail && Result != Match_InvalidOperand + && Result != Match_MissingFeature + && Result != Match_PreferE32)) { + Result = R; + ErrorInfo = EI; + } + if (R == Match_Success) + break; + } - switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { - default: break; - case Match_Success: - Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst, getSTI()); - return false; - case Match_MissingFeature: - return Error(IDLoc, "instruction not supported on this GPU"); + switch (Result) { + default: break; + case Match_Success: + Inst.setLoc(IDLoc); + Out.EmitInstruction(Inst, getSTI()); + return false; - case Match_MnemonicFail: - return Error(IDLoc, "unrecognized instruction mnemonic"); + case Match_MissingFeature: + return Error(IDLoc, "instruction not supported on this GPU"); - case Match_InvalidOperand: { - SMLoc ErrorLoc = IDLoc; - if (ErrorInfo != ~0ULL) { - if (ErrorInfo >= Operands.size()) { - return Error(IDLoc, "too few operands for instruction"); - } - ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); - if (ErrorLoc == SMLoc()) - ErrorLoc = IDLoc; + case Match_MnemonicFail: + return Error(IDLoc, "unrecognized instruction mnemonic"); + + case Match_InvalidOperand: { + SMLoc ErrorLoc = IDLoc; + if (ErrorInfo != ~0ULL) { + if (ErrorInfo >= Operands.size()) { + return Error(IDLoc, "too few operands for instruction"); } - return Error(ErrorLoc, "invalid operand for instruction"); + ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; } - case Match_PreferE32: - return Error(IDLoc, "internal error: instruction without _e64 suffix " - "should be encoded as e32"); + return Error(ErrorLoc, "invalid operand for instruction"); + } + + case Match_PreferE32: + return Error(IDLoc, "internal error: instruction without _e64 suffix " + "should be encoded as e32"); } llvm_unreachable("Implement any new match types added!"); } Index: lib/Target/AMDGPU/SIDefines.h =================================================================== --- lib/Target/AMDGPU/SIDefines.h +++ lib/Target/AMDGPU/SIDefines.h @@ -105,6 +105,15 @@ }; } +namespace AMDGPUAsmVariants { + enum { + DEFAULT = 0, + VOP3 = 1, + SDWA = 2, + DPP = 3 + }; +} + namespace llvm { namespace AMDGPU { namespace EncValues { // Encoding values of enum9/8/7 operands Index: lib/Target/AMDGPU/SIInstrFormats.td =================================================================== --- lib/Target/AMDGPU/SIInstrFormats.td +++ lib/Target/AMDGPU/SIInstrFormats.td @@ -95,6 +95,7 @@ field bits<1> DisableDecoder = 0; let isAsmParserOnly = !if(!eq(DisableDecoder{0}, {0}), 0, 1); + let AsmVariantName = AMDGPUAsmVariants.Default; } class PseudoInstSI pattern = []> @@ -187,6 +188,8 @@ "cvtVOP3", !if(!eq(HasMods,1), "cvtVOP3_2_mod", "")); + let AsmVariantName = AMDGPUAsmVariants.VOP3; + let isCodeGenOnly = 0; int Size = 8; Index: lib/Target/AMDGPU/SIInstrInfo.td =================================================================== --- lib/Target/AMDGPU/SIInstrInfo.td +++ lib/Target/AMDGPU/SIInstrInfo.td @@ -1110,7 +1110,8 @@ def VOP_I64_I64_I32_I64 : VOPProfile <[i64, i64, i32, i64]>; // This class is used only with VOPC instructions. Use $sdst for out operand -class SIInstAlias : +class SIInstAlias : InstAlias , PredicateControl { field bit isCompare; @@ -1139,23 +1140,25 @@ // else // 0 dst, 0 src (inst)))); + + let AsmVariantName = VariantName; } -class SIInstAliasSI : - SIInstAlias (op_name#"_e32_si"), p> { +class SIInstAliasSI : + SIInstAlias (op_name#"_e32_si"), p, VariantName> { let AssemblerPredicate = SIAssemblerPredicate; } -class SIInstAliasVI : - SIInstAlias (op_name#"_e32_vi"), p> { +class SIInstAliasVI : + SIInstAlias (op_name#"_e32_vi"), p, VariantName> { let AssemblerPredicates = [isVI]; } -multiclass SIInstAliasBuilder { +multiclass SIInstAliasBuilder { - def : SIInstAliasSI ; + def : SIInstAliasSI ; - def : SIInstAliasVI ; + def : SIInstAliasVI ; } class VOP { @@ -1818,7 +1821,7 @@ } // End AssemblerPredicates = [isVI] - defm : SIInstAliasBuilder; + defm : SIInstAliasBuilder; } multiclass VOPC_Helper pat32, Index: lib/Target/AMDGPU/VIInstrFormats.td =================================================================== --- lib/Target/AMDGPU/VIInstrFormats.td +++ lib/Target/AMDGPU/VIInstrFormats.td @@ -140,6 +140,7 @@ let Size = 8; let AsmMatchConverter = !if(!eq(HasMods,1), "cvtDPP", ""); + let AsmVariantName = AMDGPUAsmVariants.DPP; } class VOP_DPPe : Enc64 { @@ -186,6 +187,7 @@ VOPAnyCommon { let SDWA = 1; let Size = 8; + let AsmVariantName = AMDGPUAsmVariants.SDWA; } class VOP_SDWAe : Enc64 { Index: lib/Target/AMDGPU/VIInstructions.td =================================================================== --- lib/Target/AMDGPU/VIInstructions.td +++ lib/Target/AMDGPU/VIInstructions.td @@ -93,6 +93,7 @@ (inst VGPR_32:$dst, 0, VCSrc_32:$src0, 0, VCSrc_32:$src1, 0, 0) >, PredicateControl { let UseInstAsmMatchConverter = 0; + let AsmVariantName = AMDGPUAsmVariants.VOP3; } def : SI2_VI3Alias <"v_ldexp_f32", V_LDEXP_F32_e64_vi>;