[AMDGPU][MC] Disabled use of 2 different literals with SOP2/SOPC instructions
See bug 39319: https://bugs.llvm.org/show_bug.cgi?id=39319
Reviewers: artem.tamazov, arsenm, rampitec
Differential Revision: https://reviews.llvm.org/D56847
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351549 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 3f9af27..4a3f4d6 100644
--- a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/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<uint32_t>(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/lib/Target/AMDGPU/SOPInstructions.td b/lib/Target/AMDGPU/SOPInstructions.td
index ca5e981..ee72d28 100644
--- a/lib/Target/AMDGPU/SOPInstructions.td
+++ b/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;
diff --git a/test/MC/AMDGPU/sop2-err.s b/test/MC/AMDGPU/sop2-err.s
index 5115489..128a3d7 100644
--- a/test/MC/AMDGPU/sop2-err.s
+++ b/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
diff --git a/test/MC/AMDGPU/sop2.s b/test/MC/AMDGPU/sop2.s
index 7bcbb97..8102b0d 100644
--- a/test/MC/AMDGPU/sop2.s
+++ b/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]
diff --git a/test/MC/AMDGPU/sopc-err.s b/test/MC/AMDGPU/sopc-err.s
index b6d9542..10b2544 100644
--- a/test/MC/AMDGPU/sopc-err.s
+++ b/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
diff --git a/test/MC/AMDGPU/sopc.s b/test/MC/AMDGPU/sopc.s
index dc922b6..c7b337d 100644
--- a/test/MC/AMDGPU/sopc.s
+++ b/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]