diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1539,7 +1539,6 @@ bool validateMIMGD16(const MCInst &Inst); bool validateMIMGDim(const MCInst &Inst); bool validateMIMGMSAA(const MCInst &Inst); - bool validateLdsDirect(const MCInst &Inst); bool validateOpSel(const MCInst &Inst); bool validateVccOperand(unsigned Reg) const; bool validateVOP3Literal(const MCInst &Inst, const OperandVector &Operands); @@ -1549,6 +1548,7 @@ bool validateDivScale(const MCInst &Inst); bool validateCoherencyBits(const MCInst &Inst, const OperandVector &Operands, const SMLoc &IDLoc); + Optional validateLdsDirect(const MCInst &Inst); unsigned getConstantBusLimit(unsigned Opcode) const; bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; @@ -3768,7 +3768,7 @@ } } -bool AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) { +Optional AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) { using namespace SIInstrFlags; const unsigned Opcode = Inst.getOpcode(); @@ -3776,33 +3776,29 @@ // lds_direct register is defined so that it can be used // with 9-bit operands only. Ignore encodings which do not accept these. - if ((Desc.TSFlags & (VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA)) == 0) - return true; + const auto Enc = VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA; + if ((Desc.TSFlags & Enc) == 0) + return None; - const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); - const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); - const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); + for (auto SrcName : {OpName::src0, OpName::src1, OpName::src2}) { + auto SrcIdx = getNamedOperandIdx(Opcode, SrcName); + if (SrcIdx == -1) + break; + const auto &Src = Inst.getOperand(SrcIdx); + if (Src.isReg() && Src.getReg() == LDS_DIRECT) { - const int SrcIndices[] = { Src1Idx, Src2Idx }; + if (isGFX90A()) + return StringRef("lds_direct is not supported on this GPU"); - // lds_direct cannot be specified as either src1 or src2. - for (int SrcIdx : SrcIndices) { - if (SrcIdx == -1) break; - const MCOperand &Src = Inst.getOperand(SrcIdx); - if (Src.isReg() && Src.getReg() == LDS_DIRECT) { - return false; + if (IsRevOpcode(Opcode) || (Desc.TSFlags & SIInstrFlags::SDWA)) + return StringRef("lds_direct cannot be used with this instruction"); + + if (SrcName != OpName::src0) + return StringRef("lds_direct may be used as src0 only"); } } - if (Src0Idx == -1) - return true; - - const MCOperand &Src = Inst.getOperand(Src0Idx); - if (!Src.isReg() || Src.getReg() != LDS_DIRECT) - return true; - - // lds_direct is specified as src0. Check additional limitations. - return (Desc.TSFlags & SIInstrFlags::SDWA) == 0 && !IsRevOpcode(Opcode); + return None; } SMLoc AMDGPUAsmParser::getFlatOffsetLoc(const OperandVector &Operands) const { @@ -4133,9 +4129,8 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands) { - if (!validateLdsDirect(Inst)) { - Error(getRegLoc(AMDGPU::LDS_DIRECT, Operands), - "invalid use of lds_direct"); + if (auto ErrMsg = validateLdsDirect(Inst)) { + Error(getRegLoc(LDS_DIRECT, Operands), *ErrMsg); return false; } if (!validateSOPLiteral(Inst)) { diff --git a/llvm/test/MC/AMDGPU/gfx10_err_pos.s b/llvm/test/MC/AMDGPU/gfx10_err_pos.s --- a/llvm/test/MC/AMDGPU/gfx10_err_pos.s +++ b/llvm/test/MC/AMDGPU/gfx10_err_pos.s @@ -935,20 +935,43 @@ // CHECK-NEXT:{{^}} ^ //============================================================================== -// invalid use of lds_direct +// lane id must be in the interval [0,group size - 1] + +ds_swizzle_b32 v8, v2 offset:swizzle(BROADCAST,2,-1) +// CHECK: error: lane id must be in the interval [0,group size - 1] +// CHECK-NEXT:{{^}}ds_swizzle_b32 v8, v2 offset:swizzle(BROADCAST,2,-1) +// CHECK-NEXT:{{^}} ^ + +//============================================================================== +// lds_direct cannot be used with this instruction v_ashrrev_i16 v0, lds_direct, v0 -// CHECK: error: invalid use of lds_direct +// CHECK: error: lds_direct cannot be used with this instruction // CHECK-NEXT:{{^}}v_ashrrev_i16 v0, lds_direct, v0 // CHECK-NEXT:{{^}} ^ +v_ashrrev_i16 v0, v1, lds_direct +// CHECK: error: lds_direct cannot be used with this instruction +// CHECK-NEXT:{{^}}v_ashrrev_i16 v0, v1, lds_direct +// CHECK-NEXT:{{^}} ^ + +v_mov_b32_sdwa v1, src_lds_direct dst_sel:DWORD +// CHECK: error: lds_direct cannot be used with this instruction +// CHECK-NEXT:{{^}}v_mov_b32_sdwa v1, src_lds_direct dst_sel:DWORD +// CHECK-NEXT:{{^}} ^ + +v_add_f32_sdwa v5, v1, lds_direct dst_sel:DWORD +// CHECK: error: lds_direct cannot be used with this instruction +// CHECK-NEXT:{{^}}v_add_f32_sdwa v5, v1, lds_direct dst_sel:DWORD +// CHECK-NEXT:{{^}} ^ + //============================================================================== -// lane id must be in the interval [0,group size - 1] +// lds_direct may be used as src0 only -ds_swizzle_b32 v8, v2 offset:swizzle(BROADCAST,2,-1) -// CHECK: error: lane id must be in the interval [0,group size - 1] -// CHECK-NEXT:{{^}}ds_swizzle_b32 v8, v2 offset:swizzle(BROADCAST,2,-1) -// CHECK-NEXT:{{^}} ^ +v_add_f32 v5, v1, lds_direct +// CHECK: error: lds_direct may be used as src0 only +// CHECK-NEXT:{{^}}v_add_f32 v5, v1, lds_direct +// CHECK-NEXT:{{^}} ^ //============================================================================== // message does not support operations diff --git a/llvm/test/MC/AMDGPU/gfx90a_err.s b/llvm/test/MC/AMDGPU/gfx90a_err.s --- a/llvm/test/MC/AMDGPU/gfx90a_err.s +++ b/llvm/test/MC/AMDGPU/gfx90a_err.s @@ -230,3 +230,15 @@ global_atomic_max_f64 v[0:1], v[2:3], off scc // GFX90A: error: instruction must not use scc + +v_mov_b32_sdwa v1, src_lds_direct dst_sel:DWORD +// GFX90A: error: lds_direct is not supported on this GPU + +v_add_f32_sdwa v5, v1, lds_direct dst_sel:DWORD +// GFX90A: error: lds_direct is not supported on this GPU + +v_ashrrev_i16 v0, lds_direct, v0 +// GFX90A: error: lds_direct is not supported on this GPU + +v_add_f32 v5, v1, lds_direct +// GFX90A: error: lds_direct is not supported on this GPU diff --git a/llvm/test/MC/AMDGPU/lds_direct-err.s b/llvm/test/MC/AMDGPU/lds_direct-err.s --- a/llvm/test/MC/AMDGPU/lds_direct-err.s +++ b/llvm/test/MC/AMDGPU/lds_direct-err.s @@ -12,46 +12,46 @@ //---------------------------------------------------------------------------// v_ashrrev_i16 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_ashrrev_i32 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_lshlrev_b16 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_lshlrev_b32 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_lshrrev_b16 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_lshrrev_b32 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_pk_ashrrev_i16 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_pk_lshlrev_b16 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_pk_lshrrev_b16 v0, lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_subbrev_co_u32 v0, vcc, src_lds_direct, v0, vcc -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_subrev_co_u32 v0, vcc, src_lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_subrev_f16 v0, src_lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_subrev_u16 v0, src_lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction v_subrev_u32 v0, src_lds_direct, v0 -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct cannot be used with this instruction //---------------------------------------------------------------------------// // lds_direct may not be used with v_writelane_b32 for VI/GFX9 @@ -72,10 +72,10 @@ //---------------------------------------------------------------------------// v_add_i32 v0, v0, lds_direct -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct may be used as src0 only v_add_i32 lds_direct, v0, v0 // NOGFX9: error: invalid operand for instruction v_fma_f32 v0, v0, v0, lds_direct -// NOGFX9: error: invalid use of lds_direct +// NOGFX9: error: lds_direct may be used as src0 only diff --git a/llvm/test/MC/AMDGPU/lds_direct-gfx10.s b/llvm/test/MC/AMDGPU/lds_direct-gfx10.s --- a/llvm/test/MC/AMDGPU/lds_direct-gfx10.s +++ b/llvm/test/MC/AMDGPU/lds_direct-gfx10.s @@ -17,43 +17,43 @@ // NOGFX10: error: invalid operand for instruction v_ashrrev_i16 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_ashrrev_i32 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_lshlrev_b16 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_lshlrev_b32 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_lshrrev_b16 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_lshrrev_b32 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_pk_ashrrev_i16 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_pk_lshlrev_b16 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_pk_lshrrev_b16 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_subrev_co_ci_u32 v0, vcc_lo, src_lds_direct, v0, vcc_lo -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_subrev_co_u32 v0, s0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_subrev_f16 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_subrev_f32 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction v_subrev_nc_u32 v0, src_lds_direct, v0 -// NOGFX10: error: invalid use of lds_direct +// NOGFX10: error: lds_direct cannot be used with this instruction