diff --git a/llvm/lib/Target/AMDGPU/AMDGPUExportClustering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUExportClustering.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUExportClustering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUExportClustering.cpp @@ -32,7 +32,7 @@ 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; } 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 @@ -1355,7 +1355,6 @@ 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 @@ // 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; } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp @@ -1004,25 +1004,19 @@ void AMDGPUInstPrinter::printExpTgt(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O) { + using namespace llvm::AMDGPU::Exp; + // This is really a 6 bit field. - uint32_t Tgt = MI->getOperand(OpNo).getImm() & ((1 << 6) - 1); - - 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; + 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; } } diff --git a/llvm/lib/Target/AMDGPU/SIDefines.h b/llvm/lib/Target/AMDGPU/SIDefines.h --- a/llvm/lib/Target/AMDGPU/SIDefines.h +++ b/llvm/lib/Target/AMDGPU/SIDefines.h @@ -692,7 +692,7 @@ namespace Exp { -enum Target { +enum Target : unsigned { ET_MRT0 = 0, ET_MRT7 = 7, ET_MRTZ = 8, @@ -704,6 +704,15 @@ 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 diff --git a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp --- a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp +++ b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp @@ -1298,7 +1298,7 @@ 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) diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -486,6 +486,18 @@ } // 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 diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -788,6 +788,67 @@ } // 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 //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AMDGPU/exp-err.s b/llvm/test/MC/AMDGPU/exp-err.s --- a/llvm/test/MC/AMDGPU/exp-err.s +++ b/llvm/test/MC/AMDGPU/exp-err.s @@ -5,6 +5,9 @@ // 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 diff --git a/llvm/test/MC/AMDGPU/exp-gfx10.s b/llvm/test/MC/AMDGPU/exp-gfx10.s --- a/llvm/test/MC/AMDGPU/exp-gfx10.s +++ b/llvm/test/MC/AMDGPU/exp-gfx10.s @@ -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] 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 @@ -665,6 +665,11 @@ // 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 diff --git a/llvm/test/MC/AMDGPU/gfx9_err_pos.s b/llvm/test/MC/AMDGPU/gfx9_err_pos.s --- a/llvm/test/MC/AMDGPU/gfx9_err_pos.s +++ b/llvm/test/MC/AMDGPU/gfx9_err_pos.s @@ -24,6 +24,14 @@ // 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