diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 3f9af27a2e5e..4a3f4d6e9155 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1084,6 +1084,7 @@ private: OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc); + bool validateSOPLiteral(const MCInst &Inst) const; bool validateConstantBusLimitations(const MCInst &Inst); bool validateEarlyClobberLimitations(const MCInst &Inst); bool validateIntClampSupported(const MCInst &Inst); @@ -2461,8 +2462,46 @@ bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) { return true; } +bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const { + unsigned Opcode = Inst.getOpcode(); + const MCInstrDesc &Desc = MII.get(Opcode); + if (!(Desc.TSFlags & (SIInstrFlags::SOP2 | SIInstrFlags::SOPC))) + return true; + + const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); + const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); + + const int OpIndices[] = { Src0Idx, Src1Idx }; + + unsigned NumLiterals = 0; + uint32_t LiteralValue; + + for (int OpIdx : OpIndices) { + if (OpIdx == -1) break; + + const MCOperand &MO = Inst.getOperand(OpIdx); + if (MO.isImm() && + // Exclude special imm operands (like that used by s_set_gpr_idx_on) + AMDGPU::isSISrcOperand(Desc, OpIdx) && + !isInlineConstant(Inst, OpIdx)) { + uint32_t Value = static_cast(MO.getImm()); + if (NumLiterals == 0 || LiteralValue != Value) { + LiteralValue = Value; + ++NumLiterals; + } + } + } + + return NumLiterals <= 1; +} + bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, const SMLoc &IDLoc) { + if (!validateSOPLiteral(Inst)) { + Error(IDLoc, + "only one literal operand is allowed"); + return false; + } if (!validateConstantBusLimitations(Inst)) { Error(IDLoc, "invalid operand (violates constant bus restrictions)"); diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td index ca5e981ac5c2..ee72d28dd6c3 100644 --- a/llvm/lib/Target/AMDGPU/SOPInstructions.td +++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td @@ -302,6 +302,8 @@ class SOP2_Real op, SOP_Pseudo ps> : // copy relevant pseudo op flags let SubtargetPredicate = ps.SubtargetPredicate; let AsmMatchConverter = ps.AsmMatchConverter; + let UseNamedOperandTable = ps.UseNamedOperandTable; + let TSFlags = ps.TSFlags; // encoding bits<7> sdst; diff --git a/llvm/test/MC/AMDGPU/sop2-err.s b/llvm/test/MC/AMDGPU/sop2-err.s index 5115489a7f27..128a3d7b33ce 100644 --- a/llvm/test/MC/AMDGPU/sop2-err.s +++ b/llvm/test/MC/AMDGPU/sop2-err.s @@ -5,3 +5,9 @@ s_cbranch_g_fork 100, s[6:7] s_cbranch_g_fork s[6:7], 100 // GCN: error: invalid operand for instruction + +s_and_b32 s2, 0x12345678, 0x12345679 +// GCN: error: only one literal operand is allowed + +s_and_b64 s[2:3], 0x12345678, 0x12345679 +// GCN: error: only one literal operand is allowed diff --git a/llvm/test/MC/AMDGPU/sop2.s b/llvm/test/MC/AMDGPU/sop2.s index 7bcbb9720574..8102b0d7f331 100644 --- a/llvm/test/MC/AMDGPU/sop2.s +++ b/llvm/test/MC/AMDGPU/sop2.s @@ -50,6 +50,14 @@ s_and_b32 s2, s4, s6 // SICI: s_and_b32 s2, s4, s6 ; encoding: [0x04,0x06,0x02,0x87] // GFX89: s_and_b32 s2, s4, s6 ; encoding: [0x04,0x06,0x02,0x86] +s_and_b32 s2, 1234, 1234 +// SICI: s_and_b32 s2, 0x4d2, 0x4d2 ; encoding: [0xff,0xff,0x02,0x87,0xd2,0x04,0x00,0x00] +// GFX89: s_and_b32 s2, 0x4d2, 0x4d2 ; encoding: [0xff,0xff,0x02,0x86,0xd2,0x04,0x00,0x00] + +s_and_b32 s2, 0xFFFF0000, -65536 +// SICI: s_and_b32 s2, 0xffff0000, 0xffff0000 ; encoding: [0xff,0xff,0x02,0x87,0x00,0x00,0xff,0xff] +// GFX89: s_and_b32 s2, 0xffff0000, 0xffff0000 ; encoding: [0xff,0xff,0x02,0x86,0x00,0x00,0xff,0xff] + s_and_b64 s[2:3], s[4:5], s[6:7] // SICI: s_and_b64 s[2:3], s[4:5], s[6:7] ; encoding: [0x04,0x06,0x82,0x87] // GFX89: s_and_b64 s[2:3], s[4:5], s[6:7] ; encoding: [0x04,0x06,0x82,0x86] @@ -134,6 +142,10 @@ s_ashr_i64 s[2:3], s[4:5], s6 // SICI: s_ashr_i64 s[2:3], s[4:5], s6 ; encoding: [0x04,0x06,0x82,0x91] // GFX89: s_ashr_i64 s[2:3], s[4:5], s6 ; encoding: [0x04,0x06,0x82,0x90] +s_ashr_i64 s[2:3], -65536, 0xFFFF0000 +// SICI: s_ashr_i64 s[2:3], 0xffff0000, 0xffff0000 ; encoding: [0xff,0xff,0x82,0x91,0x00,0x00,0xff,0xff] +// GFX89: s_ashr_i64 s[2:3], 0xffff0000, 0xffff0000 ; encoding: [0xff,0xff,0x82,0x90,0x00,0x00,0xff,0xff] + s_bfm_b32 s2, s4, s6 // SICI: s_bfm_b32 s2, s4, s6 ; encoding: [0x04,0x06,0x02,0x92] // GFX89: s_bfm_b32 s2, s4, s6 ; encoding: [0x04,0x06,0x02,0x91] diff --git a/llvm/test/MC/AMDGPU/sopc-err.s b/llvm/test/MC/AMDGPU/sopc-err.s index b6d954271d34..10b25445376b 100644 --- a/llvm/test/MC/AMDGPU/sopc-err.s +++ b/llvm/test/MC/AMDGPU/sopc-err.s @@ -8,3 +8,9 @@ s_set_gpr_idx_on s0, 16 s_set_gpr_idx_on s0, -1 // GCN: error: invalid operand for instruction + +s_cmp_eq_i32 0x12345678, 0x12345679 +// GCN: error: only one literal operand is allowed + +s_cmp_eq_u64 0x12345678, 0x12345679 +// GCN: error: only one literal operand is allowed diff --git a/llvm/test/MC/AMDGPU/sopc.s b/llvm/test/MC/AMDGPU/sopc.s index dc922b65a6e9..c7b337d75a53 100644 --- a/llvm/test/MC/AMDGPU/sopc.s +++ b/llvm/test/MC/AMDGPU/sopc.s @@ -9,6 +9,12 @@ s_cmp_eq_i32 s1, s2 // GCN: s_cmp_eq_i32 s1, s2 ; encoding: [0x01,0x02,0x00,0xbf] +s_cmp_eq_i32 0xabcd1234, 0xabcd1234 +// GCN: s_cmp_eq_i32 0xabcd1234, 0xabcd1234 ; encoding: [0xff,0xff,0x00,0xbf,0x34,0x12,0xcd,0xab] + +s_cmp_eq_i32 0xFFFF0000, -65536 +// GCN: s_cmp_eq_i32 0xffff0000, 0xffff0000 ; encoding: [0xff,0xff,0x00,0xbf,0x00,0x00,0xff,0xff] + s_cmp_lg_i32 s1, s2 // GCN: s_cmp_lg_i32 s1, s2 ; encoding: [0x01,0x02,0x01,0xbf]