diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index fa5e05ae880125..4f05ba5ab576f1 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1396,8 +1396,8 @@ class AMDGPUAsmParser : public MCTargetAsmParser { bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands); bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands); bool validateSOPLiteral(const MCInst &Inst) const; - bool validateConstantBusLimitations(const MCInst &Inst); - bool validateEarlyClobberLimitations(const MCInst &Inst); + bool validateConstantBusLimitations(const MCInst &Inst, const OperandVector &Operands); + bool validateEarlyClobberLimitations(const MCInst &Inst, const OperandVector &Operands); bool validateIntClampSupported(const MCInst &Inst); bool validateMIMGAtomicDMask(const MCInst &Inst); bool validateMIMGGatherDMask(const MCInst &Inst); @@ -1410,7 +1410,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser { bool validateOpSel(const MCInst &Inst); bool validateVccOperand(unsigned Reg) const; bool validateVOP3Literal(const MCInst &Inst, const OperandVector &Operands); - bool validateMAIAccWrite(const MCInst &Inst); + bool validateMAIAccWrite(const MCInst &Inst, const OperandVector &Operands); bool validateDivScale(const MCInst &Inst); bool validateCoherencyBits(const MCInst &Inst, const OperandVector &Operands, const SMLoc &IDLoc); @@ -3062,9 +3062,12 @@ bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) { } } -bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) { +bool +AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst, + const OperandVector &Operands) { const unsigned Opcode = Inst.getOpcode(); const MCInstrDesc &Desc = MII.get(Opcode); + unsigned LastSGPR = AMDGPU::NoRegister; unsigned ConstantBusUseCount = 0; unsigned NumLiterals = 0; unsigned LiteralSize; @@ -3098,15 +3101,15 @@ bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) { const MCOperand &MO = Inst.getOperand(OpIdx); if (usesConstantBus(Inst, OpIdx)) { if (MO.isReg()) { - const unsigned Reg = mc2PseudoReg(MO.getReg()); + LastSGPR = mc2PseudoReg(MO.getReg()); // Pairs of registers with a partial intersections like these // s0, s[0:1] // flat_scratch_lo, flat_scratch // flat_scratch_lo, flat_scratch_hi // are theoretically valid but they are disabled anyway. // Note that this code mimics SIInstrInfo::verifyInstruction - if (!SGPRsUsed.count(Reg)) { - SGPRsUsed.insert(Reg); + if (!SGPRsUsed.count(LastSGPR)) { + SGPRsUsed.insert(LastSGPR); ++ConstantBusUseCount; } } else { // Expression or a literal @@ -3138,10 +3141,19 @@ bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) { } ConstantBusUseCount += NumLiterals; - return ConstantBusUseCount <= getConstantBusLimit(Opcode); + if (ConstantBusUseCount <= getConstantBusLimit(Opcode)) + return true; + + SMLoc LitLoc = getLitLoc(Operands); + SMLoc RegLoc = getRegLoc(LastSGPR, Operands); + SMLoc Loc = (LitLoc.getPointer() < RegLoc.getPointer()) ? RegLoc : LitLoc; + Error(Loc, "invalid operand (violates constant bus restrictions)"); + return false; } -bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) { +bool +AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst, + const OperandVector &Operands) { const unsigned Opcode = Inst.getOpcode(); const MCInstrDesc &Desc = MII.get(Opcode); @@ -3170,6 +3182,8 @@ bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) { if (Src.isReg()) { const unsigned SrcReg = mc2PseudoReg(Src.getReg()); if (isRegIntersect(DstReg, SrcReg, TRI)) { + Error(getRegLoc(SrcReg, Operands), + "destination must be different than all sources"); return false; } } @@ -3343,7 +3357,8 @@ bool AMDGPUAsmParser::validateMovrels(const MCInst &Inst) { return !isSGPR(mc2PseudoReg(Reg), TRI); } -bool AMDGPUAsmParser::validateMAIAccWrite(const MCInst &Inst) { +bool AMDGPUAsmParser::validateMAIAccWrite(const MCInst &Inst, + const OperandVector &Operands) { const unsigned Opc = Inst.getOpcode(); @@ -3357,10 +3372,11 @@ bool AMDGPUAsmParser::validateMAIAccWrite(const MCInst &Inst) { if (!Src0.isReg()) return true; - auto Reg = Src0.getReg(); + auto Reg = mc2PseudoReg(Src0.getReg()); const MCRegisterInfo *TRI = getContext().getRegisterInfo(); - if (isSGPR(mc2PseudoReg(Reg), TRI)) { - Error(getLoc(), "source operand must be either a VGPR or an inline constant"); + if (isSGPR(Reg, TRI)) { + Error(getRegLoc(Reg, Operands), + "source operand must be either a VGPR or an inline constant"); return false; } @@ -3837,14 +3853,10 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, if (!validateVOP3Literal(Inst, Operands)) { return false; } - if (!validateConstantBusLimitations(Inst)) { - Error(IDLoc, - "invalid operand (violates constant bus restrictions)"); + if (!validateConstantBusLimitations(Inst, Operands)) { return false; } - if (!validateEarlyClobberLimitations(Inst)) { - Error(IDLoc, - "destination must be different than all sources"); + if (!validateEarlyClobberLimitations(Inst, Operands)) { return false; } if (!validateIntClampSupported(Inst)) { @@ -3897,7 +3909,7 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, if (!validateSMEMOffset(Inst, Operands)) { return false; } - if (!validateMAIAccWrite(Inst)) { + if (!validateMAIAccWrite(Inst, Operands)) { return false; } if (!validateDivScale(Inst)) { diff --git a/llvm/test/MC/AMDGPU/gfx10_err_pos.s b/llvm/test/MC/AMDGPU/gfx10_err_pos.s index 519f056f654320..c1aa9f860b5cae 100644 --- a/llvm/test/MC/AMDGPU/gfx10_err_pos.s +++ b/llvm/test/MC/AMDGPU/gfx10_err_pos.s @@ -6,7 +6,22 @@ v_mqsad_pk_u16_u8 v[0:1], v[1:2], v9, v[4:5] // CHECK: error: destination must be different than all sources // CHECK-NEXT:{{^}}v_mqsad_pk_u16_u8 v[0:1], v[1:2], v9, v[4:5] -// CHECK-NEXT:{{^}}^ +// CHECK-NEXT:{{^}} ^ + +v_mqsad_pk_u16_u8 v[0:1], v[2:3], v0, v[4:5] +// CHECK: error: destination must be different than all sources +// CHECK-NEXT:{{^}}v_mqsad_pk_u16_u8 v[0:1], v[2:3], v0, v[4:5] +// CHECK-NEXT:{{^}} ^ + +v_mqsad_pk_u16_u8 v[0:1], v[2:3], v1, v[4:5] +// CHECK: error: destination must be different than all sources +// CHECK-NEXT:{{^}}v_mqsad_pk_u16_u8 v[0:1], v[2:3], v1, v[4:5] +// CHECK-NEXT:{{^}} ^ + +v_mqsad_pk_u16_u8 v[0:1], v[2:3], v9, v[0:1] +// CHECK: error: destination must be different than all sources +// CHECK-NEXT:{{^}}v_mqsad_pk_u16_u8 v[0:1], v[2:3], v9, v[0:1] +// CHECK-NEXT:{{^}} ^ //============================================================================== // dim modifier is required on this GPU @@ -604,17 +619,42 @@ v_pk_add_u16 v1, v2, v3 op_sel:[-1,0] v_ashrrev_i64 v[0:1], 0x100, s[0:1] // CHECK: error: invalid operand (violates constant bus restrictions) // CHECK-NEXT:{{^}}v_ashrrev_i64 v[0:1], 0x100, s[0:1] -// CHECK-NEXT:{{^}}^ +// CHECK-NEXT:{{^}} ^ + +v_ashrrev_i64 v[0:1], s3, s[0:1] +// CHECK: error: invalid operand (violates constant bus restrictions) +// CHECK-NEXT:{{^}}v_ashrrev_i64 v[0:1], s3, s[0:1] +// CHECK-NEXT:{{^}} ^ v_bfe_u32 v0, s1, 0x3039, s2 // CHECK: error: invalid operand (violates constant bus restrictions) // CHECK-NEXT:{{^}}v_bfe_u32 v0, s1, 0x3039, s2 -// CHECK-NEXT:{{^}}^ +// CHECK-NEXT:{{^}} ^ + +v_bfe_u32 v0, s1, s2, s3 +// CHECK: error: invalid operand (violates constant bus restrictions) +// CHECK-NEXT:{{^}}v_bfe_u32 v0, s1, s2, s3 +// CHECK-NEXT:{{^}} ^ v_div_fmas_f32 v5, s3, 0x123, v3 // CHECK: error: invalid operand (violates constant bus restrictions) // CHECK-NEXT:{{^}}v_div_fmas_f32 v5, s3, 0x123, v3 -// CHECK-NEXT:{{^}}^ +// CHECK-NEXT:{{^}} ^ + +v_div_fmas_f32 v5, s3, v3, 0x123 +// CHECK: error: invalid operand (violates constant bus restrictions) +// CHECK-NEXT:{{^}}v_div_fmas_f32 v5, s3, v3, 0x123 +// CHECK-NEXT:{{^}} ^ + +v_div_fmas_f32 v5, 0x123, v3, s3 +// CHECK: error: invalid operand (violates constant bus restrictions) +// CHECK-NEXT:{{^}}v_div_fmas_f32 v5, 0x123, v3, s3 +// CHECK-NEXT:{{^}} ^ + +v_div_fmas_f32 v5, s3, s4, v3 +// CHECK: error: invalid operand (violates constant bus restrictions) +// CHECK-NEXT:{{^}}v_div_fmas_f32 v5, s3, s4, v3 +// CHECK-NEXT:{{^}} ^ //============================================================================== // invalid operand for instruction diff --git a/llvm/test/MC/AMDGPU/gfx908_err_pos.s b/llvm/test/MC/AMDGPU/gfx908_err_pos.s index 8923e62b52fceb..3fa641b176fedc 100644 --- a/llvm/test/MC/AMDGPU/gfx908_err_pos.s +++ b/llvm/test/MC/AMDGPU/gfx908_err_pos.s @@ -38,4 +38,4 @@ v_dot2_f32_f16 v0, v1, v2, v3 op_sel_hi:[2,0] v_accvgpr_write a2, execz // CHECK: error: source operand must be either a VGPR or an inline constant // CHECK-NEXT:{{^}}v_accvgpr_write a2, execz -// CHECK-NEXT:{{^}} ^ +// CHECK-NEXT:{{^}} ^ diff --git a/llvm/test/MC/AMDGPU/gfx9_err_pos.s b/llvm/test/MC/AMDGPU/gfx9_err_pos.s index 1b55ac2a8cf4f2..6b83ce2af9dd14 100644 --- a/llvm/test/MC/AMDGPU/gfx9_err_pos.s +++ b/llvm/test/MC/AMDGPU/gfx9_err_pos.s @@ -122,7 +122,17 @@ s_set_gpr_idx_on s0, 16 v_add_f32_e64 v0, flat_scratch_hi, m0 // CHECK: error: invalid operand (violates constant bus restrictions) // CHECK-NEXT:{{^}}v_add_f32_e64 v0, flat_scratch_hi, m0 -// CHECK-NEXT:{{^}}^ +// CHECK-NEXT:{{^}} ^ + +v_madak_f32 v5, s1, v2, 0xa1b1c1d1 +// CHECK: error: invalid operand (violates constant bus restrictions) +// CHECK-NEXT:{{^}}v_madak_f32 v5, s1, v2, 0xa1b1c1d1 +// CHECK-NEXT:{{^}} ^ + +v_madmk_f32 v5, s1, 0x11213141, v255 +// CHECK: error: invalid operand (violates constant bus restrictions) +// CHECK-NEXT:{{^}}v_madmk_f32 v5, s1, 0x11213141, v255 +// CHECK-NEXT:{{^}} ^ //============================================================================== // literal operands are not supported