Index: llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1084,6 +1084,7 @@ 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 @@ 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)"); Index: llvm/trunk/lib/Target/AMDGPU/SOPInstructions.td =================================================================== --- llvm/trunk/lib/Target/AMDGPU/SOPInstructions.td +++ llvm/trunk/lib/Target/AMDGPU/SOPInstructions.td @@ -302,6 +302,8 @@ // 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; Index: llvm/trunk/test/MC/AMDGPU/sop2-err.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/sop2-err.s +++ llvm/trunk/test/MC/AMDGPU/sop2-err.s @@ -5,3 +5,9 @@ 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 Index: llvm/trunk/test/MC/AMDGPU/sop2.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/sop2.s +++ llvm/trunk/test/MC/AMDGPU/sop2.s @@ -50,6 +50,14 @@ // 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 @@ // 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] Index: llvm/trunk/test/MC/AMDGPU/sopc-err.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/sopc-err.s +++ llvm/trunk/test/MC/AMDGPU/sopc-err.s @@ -8,3 +8,9 @@ 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 Index: llvm/trunk/test/MC/AMDGPU/sopc.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/sopc.s +++ llvm/trunk/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]