[AMDGPU][MC] Refactored exp tgt handling

Summary:
- Separated tgt encoding from parsing;
- Separated tgt decoding from printing;
- Improved errors handling;
- Disabled leading zeroes in index. The following code is no longer accepted: exp pos00 v3, v2, v1, v0

Reviewers: arsenm, rampitec, foad

Differential Revision: https://reviews.llvm.org/D95216
This commit is contained in:
Dmitry Preobrazhensky 2021-01-26 14:52:24 +03:00
parent 25f80e16d1
commit 745064e36b
11 changed files with 125 additions and 86 deletions

View File

@ -32,7 +32,7 @@ static bool isExport(const SUnit &SU) {
static bool isPositionExport(const SIInstrInfo *TII, SUnit *SU) {
const MachineInstr *MI = SU->getInstr();
int Imm = TII->getNamedOperand(*MI, AMDGPU::OpName::tgt)->getImm();
unsigned Imm = TII->getNamedOperand(*MI, AMDGPU::OpName::tgt)->getImm();
return Imm >= AMDGPU::Exp::ET_POS0 && Imm <= AMDGPU::Exp::ET_POS_LAST;
}

View File

@ -1355,7 +1355,6 @@ private:
const OperandInfoTy &Offset,
const OperandInfoTy &Width);
OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
SMLoc getFlatOffsetLoc(const OperandVector &Operands) const;
SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const;
@ -5884,76 +5883,24 @@ OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
// exp
//===----------------------------------------------------------------------===//
OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
uint8_t &Val) {
if (Str == "null") {
Val = Exp::ET_NULL;
return MatchOperand_Success;
}
if (Str.startswith("mrt")) {
Str = Str.drop_front(3);
if (Str == "z") { // == mrtz
Val = Exp::ET_MRTZ;
return MatchOperand_Success;
}
if (Str.getAsInteger(10, Val))
return MatchOperand_ParseFail;
if (Val > Exp::ET_MRT7)
return MatchOperand_ParseFail;
return MatchOperand_Success;
}
if (Str.startswith("pos")) {
Str = Str.drop_front(3);
if (Str.getAsInteger(10, Val))
return MatchOperand_ParseFail;
if (Val > (isGFX10Plus() ? 4 : 3))
return MatchOperand_ParseFail;
Val += Exp::ET_POS0;
return MatchOperand_Success;
}
if (isGFX10Plus() && Str == "prim") {
Val = Exp::ET_PRIM;
return MatchOperand_Success;
}
if (Str.startswith("param")) {
Str = Str.drop_front(5);
if (Str.getAsInteger(10, Val))
return MatchOperand_ParseFail;
if (Val >= 32)
return MatchOperand_ParseFail;
Val += Exp::ET_PARAM0;
return MatchOperand_Success;
}
return MatchOperand_ParseFail;
}
OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
using namespace llvm::AMDGPU::Exp;
StringRef Str;
SMLoc S = getLoc();
if (!parseId(Str))
return MatchOperand_NoMatch;
uint8_t Val;
auto Res = parseExpTgtImpl(Str, Val);
if (Res != MatchOperand_Success) {
Error(S, "invalid exp target");
return Res;
unsigned Id = getTgtId(Str);
if (Id == ET_INVALID || !isSupportedTgtId(Id, getSTI())) {
Error(S, (Id == ET_INVALID) ?
"invalid exp target" :
"exp target is not supported on this GPU");
return MatchOperand_ParseFail;
}
Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
Operands.push_back(AMDGPUOperand::CreateImm(this, Id, S,
AMDGPUOperand::ImmTyExpTgt));
return MatchOperand_Success;
}

View File

@ -1004,25 +1004,19 @@ void AMDGPUInstPrinter::printExpSrc3(const MCInst *MI, unsigned OpNo,
void AMDGPUInstPrinter::printExpTgt(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
// This is really a 6 bit field.
uint32_t Tgt = MI->getOperand(OpNo).getImm() & ((1 << 6) - 1);
using namespace llvm::AMDGPU::Exp;
if (Tgt <= Exp::ET_MRT7)
O << " mrt" << Tgt - Exp::ET_MRT0;
else if (Tgt == Exp::ET_MRTZ)
O << " mrtz";
else if (Tgt == Exp::ET_NULL)
O << " null";
else if (Tgt >= Exp::ET_POS0 &&
Tgt <= uint32_t(isGFX10Plus(STI) ? Exp::ET_POS4 : Exp::ET_POS3))
O << " pos" << Tgt - Exp::ET_POS0;
else if (isGFX10Plus(STI) && Tgt == Exp::ET_PRIM)
O << " prim";
else if (Tgt >= Exp::ET_PARAM0 && Tgt <= Exp::ET_PARAM31)
O << " param" << Tgt - Exp::ET_PARAM0;
else {
// Reserved values 10, 11
O << " invalid_target_" << Tgt;
// This is really a 6 bit field.
unsigned Id = MI->getOperand(OpNo).getImm() & ((1 << 6) - 1);
int Index;
StringRef TgtName;
if (getTgtName(Id, TgtName, Index) && isSupportedTgtId(Id, STI)) {
O << ' ' << TgtName;
if (Index >= 0)
O << Index;
} else {
O << " invalid_target_" << Id;
}
}

View File

@ -692,7 +692,7 @@ enum DppFiMode {
namespace Exp {
enum Target {
enum Target : unsigned {
ET_MRT0 = 0,
ET_MRT7 = 7,
ET_MRTZ = 8,
@ -704,6 +704,15 @@ enum Target {
ET_PRIM = 20, // GFX10+
ET_PARAM0 = 32,
ET_PARAM31 = 63,
ET_NULL_MAX_IDX = 0,
ET_MRTZ_MAX_IDX = 0,
ET_PRIM_MAX_IDX = 0,
ET_MRT_MAX_IDX = 7,
ET_POS_MAX_IDX = 4,
ET_PARAM_MAX_IDX = 31,
ET_INVALID = 255,
};
} // namespace Exp

View File

@ -1298,7 +1298,7 @@ void SIInsertWaitcnts::updateEventWaitcntAfter(MachineInstr &Inst,
ScoreBrackets->applyWaitcnt(AMDGPU::Waitcnt());
}
} else if (SIInstrInfo::isEXP(Inst)) {
int Imm = TII->getNamedOperand(Inst, AMDGPU::OpName::tgt)->getImm();
unsigned Imm = TII->getNamedOperand(Inst, AMDGPU::OpName::tgt)->getImm();
if (Imm >= AMDGPU::Exp::ET_PARAM0 && Imm <= AMDGPU::Exp::ET_PARAM31)
ScoreBrackets->updateByEvent(TII, TRI, MRI, EXP_PARAM_ACCESS, Inst);
else if (Imm >= AMDGPU::Exp::ET_POS0 && Imm <= AMDGPU::Exp::ET_POS_LAST)

View File

@ -788,6 +788,67 @@ void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width)
} // namespace Hwreg
//===----------------------------------------------------------------------===//
// exp tgt
//===----------------------------------------------------------------------===//
namespace Exp {
struct ExpTgt {
StringLiteral Name;
unsigned Tgt;
unsigned MaxIndex;
};
static constexpr ExpTgt ExpTgtInfo[] = {
{{"null"}, ET_NULL, ET_NULL_MAX_IDX},
{{"mrtz"}, ET_MRTZ, ET_MRTZ_MAX_IDX},
{{"prim"}, ET_PRIM, ET_PRIM_MAX_IDX},
{{"mrt"}, ET_MRT0, ET_MRT_MAX_IDX},
{{"pos"}, ET_POS0, ET_POS_MAX_IDX},
{{"param"}, ET_PARAM0, ET_PARAM_MAX_IDX},
};
bool getTgtName(unsigned Id, StringRef &Name, int &Index) {
for (const ExpTgt &Val : ExpTgtInfo) {
if (Val.Tgt <= Id && Id <= Val.Tgt + Val.MaxIndex) {
Index = (Val.MaxIndex == 0) ? -1 : (Id - Val.Tgt);
Name = Val.Name;
return true;
}
}
return false;
}
unsigned getTgtId(const StringRef Name) {
for (const ExpTgt &Val : ExpTgtInfo) {
if (Val.MaxIndex == 0 && Name == Val.Name)
return Val.Tgt;
if (Val.MaxIndex > 0 && Name.startswith(Val.Name)) {
StringRef Suffix = Name.drop_front(Val.Name.size());
unsigned Id;
if (Suffix.getAsInteger(10, Id) || Id > Val.MaxIndex)
return ET_INVALID;
// Disable leading zeroes
if (Suffix.size() > 1 && Suffix[0] == '0')
return ET_INVALID;
return Val.Tgt + Id;
}
}
return ET_INVALID;
}
bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI) {
return (Id != ET_POS4 && Id != ET_PRIM) || isGFX10Plus(STI);
}
} // namespace Exp
//===----------------------------------------------------------------------===//
// MTBUF Format
//===----------------------------------------------------------------------===//

View File

@ -486,6 +486,18 @@ void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width);
} // namespace Hwreg
namespace Exp {
bool getTgtName(unsigned Id, StringRef &Name, int &Index);
LLVM_READONLY
unsigned getTgtId(const StringRef Name);
LLVM_READNONE
bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI);
} // namespace Exp
namespace MTBUFFormat {
LLVM_READNONE

View File

@ -5,6 +5,9 @@ exp mrt8 v3, v2, v1, v0
// GCN: :5: error: invalid exp target
exp pos4 v3, v2, v1, v0
// GCN: :5: error: exp target is not supported on this GPU
exp pos5 v3, v2, v1, v0
// GCN: :5: error: invalid exp target
exp param32 v3, v2, v1, v0

View File

@ -3,13 +3,13 @@
// RUN: llvm-mc -arch=amdgcn -mcpu=gfx1010 -show-encoding %s | FileCheck -check-prefix=GFX10 %s
exp prim v1, off, off, off
// SIVI: :5: error: invalid exp target
// SIVI: :5: error: exp target is not supported on this GPU
// GFX10: exp prim v1, off, off, off ; encoding: [0x41,0x01,0x00,0xf8,0x01,0x00,0x00,0x00]
exp prim v2, v3, off, off
// SIVI: :5: error: invalid exp target
// SIVI: :5: error: exp target is not supported on this GPU
// GFX10: exp prim v2, v3, off, off ; encoding: [0x43,0x01,0x00,0xf8,0x02,0x03,0x00,0x00]
exp pos4 v4, v3, v2, v1
// SIVI: error: invalid exp target
// SIVI: error: exp target is not supported on this GPU
// GFX10: exp pos4 v4, v3, v2, v1 ; encoding: [0x0f,0x01,0x00,0xf8,0x04,0x03,0x02,0x01]

View File

@ -665,6 +665,11 @@ exp invalid_target_10 v3, v2, v1, v0
// CHECK-NEXT:{{^}}exp invalid_target_10 v3, v2, v1, v0
// CHECK-NEXT:{{^}} ^
exp pos00 v3, v2, v1, v0
// CHECK: error: invalid exp target
// CHECK-NEXT:{{^}}exp pos00 v3, v2, v1, v0
// CHECK-NEXT:{{^}} ^
//==============================================================================
// invalid immediate: only 16-bit values are legal

View File

@ -24,6 +24,14 @@ s_set_gpr_idx_on s0, gpr_idx(SRC0,DST,SRC1,DST)
// CHECK-NEXT:{{^}}s_set_gpr_idx_on s0, gpr_idx(SRC0,DST,SRC1,DST)
// CHECK-NEXT:{{^}} ^
//==============================================================================
// exp target is not supported on this GPU
exp pos4 v4, v3, v2, v1
// CHECK: error: exp target is not supported on this GPU
// CHECK-NEXT:{{^}}exp pos4 v4, v3, v2, v1
// CHECK-NEXT:{{^}} ^
//==============================================================================
// expected a 12-bit unsigned offset