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 @@ -3236,6 +3236,7 @@ const int OpIndices[] = { Src0Idx, Src1Idx }; + unsigned NumExprs = 0; unsigned NumLiterals = 0; uint32_t LiteralValue; @@ -3243,19 +3244,21 @@ 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; + // Exclude special imm operands (like that used by s_set_gpr_idx_on) + if (AMDGPU::isSISrcOperand(Desc, OpIdx)) { + if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { + uint32_t Value = static_cast(MO.getImm()); + if (NumLiterals == 0 || LiteralValue != Value) { + LiteralValue = Value; + ++NumLiterals; + } + } else if (MO.isExpr()) { + ++NumExprs; } } } - return NumLiterals <= 1; + return NumLiterals + NumExprs <= 1; } bool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) { @@ -3291,6 +3294,7 @@ const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx }; + unsigned NumExprs = 0; unsigned NumLiterals = 0; uint32_t LiteralValue; @@ -3298,21 +3302,26 @@ if (OpIdx == -1) break; const MCOperand &MO = Inst.getOperand(OpIdx); - if (!MO.isImm() || !AMDGPU::isSISrcOperand(Desc, OpIdx)) + if (!MO.isImm() && !MO.isExpr()) + continue; + if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) continue; if (OpIdx == Src2Idx && (Desc.TSFlags & SIInstrFlags::IsMAI) && getFeatureBits()[AMDGPU::FeatureMFMAInlineLiteralBug]) return false; - if (!isInlineConstant(Inst, OpIdx)) { + if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { uint32_t Value = static_cast(MO.getImm()); if (NumLiterals == 0 || LiteralValue != Value) { LiteralValue = Value; ++NumLiterals; } + } else if (MO.isExpr()) { + ++NumExprs; } } + NumLiterals += NumExprs; return !NumLiterals || (NumLiterals == 1 && getFeatureBits()[AMDGPU::FeatureVOP3Literal]); Index: llvm/trunk/test/MC/AMDGPU/expressions-gfx10.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/expressions-gfx10.s +++ llvm/trunk/test/MC/AMDGPU/expressions-gfx10.s @@ -1,4 +1,5 @@ -// RUN: llvm-mc -arch=amdgcn -mcpu=gfx1010 -mattr=-WavefrontSize32,+WavefrontSize64 -show-encoding %s | FileCheck %s --check-prefix=GFX10 +// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx1010 -mattr=-WavefrontSize32,+WavefrontSize64 -show-encoding %s | FileCheck %s --check-prefix=GFX10 +// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx1010 -mattr=-WavefrontSize32,+WavefrontSize64 %s 2>&1 | FileCheck -check-prefix=NOGFX10 %s i1=1 @@ -47,3 +48,26 @@ v_lshlrev_b64 v[5:6], u-1, v[2:3] // GFX10: v_lshlrev_b64 v[5:6], u-1, v[2:3] ; encoding: [0x05,0x00,0xff,0xd6,0xff,0x04,0x02,0x00,A,A,A,A] // GFX10-NEXT: ; fixup A - offset: 8, value: u-1, kind: FK_Data_4 + +//===----------------------------------------------------------------------===// +// Instructions can use only one literal. +// Relocatable expressions are counted as literals. +//===----------------------------------------------------------------------===// + +s_sub_u32 s0, 123, u +// NOGFX10: error: only one literal operand is allowed + +s_sub_u32 s0, u, u +// NOGFX10: error: only one literal operand is allowed + +s_sub_u32 s0, u, u1 +// NOGFX10: error: only one literal operand is allowed + +v_bfe_u32 v0, v2, 123, u +// NOGFX10: error: invalid literal operand + +v_bfe_u32 v0, v2, u, u +// NOGFX10: error: invalid literal operand + +v_bfe_u32 v0, v2, u, u1 +// NOGFX10: error: invalid literal operand Index: llvm/trunk/test/MC/AMDGPU/expressions-gfx9.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/expressions-gfx9.s +++ llvm/trunk/test/MC/AMDGPU/expressions-gfx9.s @@ -9,6 +9,23 @@ // NOGFX9: error: expected an absolute expression //===----------------------------------------------------------------------===// +// Instructions can use only one literal. +// Relocatable expressions are counted as literals. +//===----------------------------------------------------------------------===// + +s_sub_u32 s0, 123, u +// NOGFX9: error: only one literal operand is allowed + +s_sub_u32 s0, u, u +// NOGFX9: error: only one literal operand is allowed + +s_sub_u32 s0, u, u1 +// NOGFX9: error: only one literal operand is allowed + +v_bfe_u32 v0, v2, v3, u +// NOGFX9: error: invalid literal operand + +//===----------------------------------------------------------------------===// // Constant expressions may be used with 'sext' modifier //===----------------------------------------------------------------------===//