[llvm] e122eba - [AMDGPU][MC] Corrected MTBUF parsing and decoding
Dmitry Preobrazhensky via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 15 09:50:40 PDT 2020
Author: Dmitry Preobrazhensky
Date: 2020-07-15T19:46:00+03:00
New Revision: e122eba185055fb848cc7efc578035716dc1fec4
URL: https://github.com/llvm/llvm-project/commit/e122eba185055fb848cc7efc578035716dc1fec4
DIFF: https://github.com/llvm/llvm-project/commit/e122eba185055fb848cc7efc578035716dc1fec4.diff
LOG: [AMDGPU][MC] Corrected MTBUF parsing and decoding
MTBUF implementation has many issues and this change addresses most of these:
- refactored duplicated code;
- hardcoded constants moved out of high-level code;
- fixed a decoding error when nfmt or dfmt are zero (bug 36932);
- corrected parsing of operand separators (bug 46403);
- corrected handling of missing operands (bug 46404);
- corrected handling of out-of-range modifiers (bug 46421);
- corrected default value (bug 46467).
Reviewers: arsenm, rampitec, vpykhtin, artem.tamazov, kzhuravl
Differential Revision: https://reviews.llvm.org/D83760
Added:
Modified:
llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
llvm/lib/Target/AMDGPU/BUFInstructions.td
llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
llvm/lib/Target/AMDGPU/SIDefines.h
llvm/lib/Target/AMDGPU/SIInstrInfo.td
llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
llvm/test/MC/AMDGPU/mtbuf-gfx10.s
llvm/test/MC/AMDGPU/mtbuf.s
llvm/test/MC/Disassembler/AMDGPU/mtbuf_gfx10.txt
llvm/test/MC/Disassembler/AMDGPU/mtbuf_vi.txt
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 013b7a0cf25d..57f3546f4da5 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -339,7 +339,7 @@ class AMDGPUOperand : public MCParsedAsmOperand {
bool isSWZ() const { return isImmTy(ImmTySWZ); }
bool isTFE() const { return isImmTy(ImmTyTFE); }
bool isD16() const { return isImmTy(ImmTyD16); }
- bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<8>(getImm()); }
+ bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<7>(getImm()); }
bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
@@ -1295,7 +1295,10 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
- OperandMatchResultTy parseDfmtNfmt(OperandVector &Operands);
+ OperandMatchResultTy parseDfmtNfmt(int64_t &Format);
+ OperandMatchResultTy parseUfmt(int64_t &Format);
+ OperandMatchResultTy parseFORMAT(OperandVector &Operands);
+ bool tryParseFmt(const char *Pref, int64_t MaxVal, int64_t &Val);
void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
@@ -4870,50 +4873,96 @@ AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
return MatchOperand_Success;
}
+//===----------------------------------------------------------------------===//
+// MTBUF format
+//===----------------------------------------------------------------------===//
+
+bool AMDGPUAsmParser::tryParseFmt(const char *Pref,
+ int64_t MaxVal,
+ int64_t &Fmt) {
+ int64_t Val;
+ SMLoc Loc = getLoc();
+
+ auto Res = parseIntWithPrefix(Pref, Val);
+ if (Res == MatchOperand_ParseFail)
+ return false;
+ if (Res == MatchOperand_NoMatch)
+ return true;
+
+ if (Val < 0 || Val > MaxVal) {
+ Error(Loc, Twine("out of range ", StringRef(Pref)));
+ return false;
+ }
+
+ Fmt = Val;
+ return true;
+}
+
// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
// values to live in a joint format operand in the MCInst encoding.
OperandMatchResultTy
-AMDGPUAsmParser::parseDfmtNfmt(OperandVector &Operands) {
- SMLoc S = Parser.getTok().getLoc();
- int64_t Dfmt = 0, Nfmt = 0;
+AMDGPUAsmParser::parseDfmtNfmt(int64_t &Format) {
+ using namespace llvm::AMDGPU::MTBUFFormat;
+
+ int64_t Dfmt = DFMT_UNDEF;
+ int64_t Nfmt = NFMT_UNDEF;
+
// dfmt and nfmt can appear in either order, and each is optional.
- bool GotDfmt = false, GotNfmt = false;
- while (!GotDfmt || !GotNfmt) {
- if (!GotDfmt) {
- auto Res = parseIntWithPrefix("dfmt", Dfmt);
- if (Res != MatchOperand_NoMatch) {
- if (Res != MatchOperand_Success)
- return Res;
- if (Dfmt >= 16) {
- Error(Parser.getTok().getLoc(), "out of range dfmt");
- return MatchOperand_ParseFail;
- }
- GotDfmt = true;
- Parser.Lex();
- continue;
- }
+ for (int I = 0; I < 2; ++I) {
+ if (Dfmt == DFMT_UNDEF && !tryParseFmt("dfmt", DFMT_MAX, Dfmt))
+ return MatchOperand_ParseFail;
+
+ if (Nfmt == NFMT_UNDEF && !tryParseFmt("nfmt", NFMT_MAX, Nfmt)) {
+ return MatchOperand_ParseFail;
}
- if (!GotNfmt) {
- auto Res = parseIntWithPrefix("nfmt", Nfmt);
- if (Res != MatchOperand_NoMatch) {
- if (Res != MatchOperand_Success)
- return Res;
- if (Nfmt >= 8) {
- Error(Parser.getTok().getLoc(), "out of range nfmt");
- return MatchOperand_ParseFail;
- }
- GotNfmt = true;
- Parser.Lex();
- continue;
- }
+ // Skip optional comma between dfmt/nfmt
+ // but guard against 2 commas following each other.
+ if ((Dfmt == DFMT_UNDEF) != (Nfmt == NFMT_UNDEF) &&
+ !peekToken().is(AsmToken::Comma)) {
+ trySkipToken(AsmToken::Comma);
}
- break;
}
- if (!GotDfmt && !GotNfmt)
+
+ if (Dfmt == DFMT_UNDEF && Nfmt == NFMT_UNDEF)
return MatchOperand_NoMatch;
- auto Format = Dfmt | Nfmt << 4;
+
+ Dfmt = (Dfmt == DFMT_UNDEF)? DFMT_DEFAULT : Dfmt;
+ Nfmt = (Nfmt == NFMT_UNDEF)? NFMT_DEFAULT : Nfmt;
+
+ Format = encodeDfmtNfmt(Dfmt, Nfmt);
+ return MatchOperand_Success;
+}
+
+OperandMatchResultTy
+AMDGPUAsmParser::parseUfmt(int64_t &Format) {
+ using namespace llvm::AMDGPU::MTBUFFormat;
+
+ int64_t Fmt = UFMT_UNDEF;
+
+ if (!tryParseFmt("format", UFMT_MAX, Fmt))
+ return MatchOperand_ParseFail;
+
+ if (Fmt == UFMT_UNDEF)
+ return MatchOperand_NoMatch;
+
+ Format = Fmt;
+ return MatchOperand_Success;
+}
+
+OperandMatchResultTy
+AMDGPUAsmParser::parseFORMAT(OperandVector &Operands) {
+ using namespace llvm::AMDGPU::MTBUFFormat;
+
+ int64_t Format = isGFX10() ? UFMT_DEFAULT : DFMT_NFMT_DEFAULT;
+ OperandMatchResultTy Res;
+ SMLoc Loc = getLoc();
+
+ Res = isGFX10() ? parseUfmt(Format) : parseDfmtNfmt(Format);
+ if (Res == MatchOperand_ParseFail)
+ return Res;
+
Operands.push_back(
- AMDGPUOperand::CreateImm(this, Format, S, AMDGPUOperand::ImmTyFORMAT));
+ AMDGPUOperand::CreateImm(this, Format, Loc, AMDGPUOperand::ImmTyFORMAT));
return MatchOperand_Success;
}
@@ -6242,7 +6291,6 @@ static const OptionalOperand AMDGPUOptionalOperandTable[] = {
{"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
{"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr},
{"dlc", AMDGPUOperand::ImmTyDLC, true, nullptr},
- {"format", AMDGPUOperand::ImmTyFORMAT, false, nullptr},
{"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
{"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
{"swz", AMDGPUOperand::ImmTySWZ, true, nullptr},
@@ -6327,8 +6375,6 @@ OperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands)
Op.ConvertResult);
} else if (Op.Type == AMDGPUOperand::ImmTyDim) {
res = parseDim(Operands);
- } else if (Op.Type == AMDGPUOperand::ImmTyFORMAT && !isGFX10()) {
- res = parseDfmtNfmt(Operands);
} else {
res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
}
diff --git a/llvm/lib/Target/AMDGPU/BUFInstructions.td b/llvm/lib/Target/AMDGPU/BUFInstructions.td
index fa42ddc54b56..370e9db9e83e 100644
--- a/llvm/lib/Target/AMDGPU/BUFInstructions.td
+++ b/llvm/lib/Target/AMDGPU/BUFInstructions.td
@@ -168,15 +168,15 @@ class getMTBUFIns<int addrKind, list<RegisterClass> vdataList=[]> {
class getMTBUFAsmOps<int addrKind> {
string Pfx =
- !if(!eq(addrKind, BUFAddrKind.Offset), "off, $srsrc, $format, $soffset",
+ !if(!eq(addrKind, BUFAddrKind.Offset), "off, $srsrc,$format $soffset",
!if(!eq(addrKind, BUFAddrKind.OffEn),
- "$vaddr, $srsrc, $format, $soffset offen",
+ "$vaddr, $srsrc,$format $soffset offen",
!if(!eq(addrKind, BUFAddrKind.IdxEn),
- "$vaddr, $srsrc, $format, $soffset idxen",
+ "$vaddr, $srsrc,$format $soffset idxen",
!if(!eq(addrKind, BUFAddrKind.BothEn),
- "$vaddr, $srsrc, $format, $soffset idxen offen",
+ "$vaddr, $srsrc,$format $soffset idxen offen",
!if(!eq(addrKind, BUFAddrKind.Addr64),
- "$vaddr, $srsrc, $format, $soffset addr64",
+ "$vaddr, $srsrc,$format $soffset addr64",
"")))));
string ret = Pfx # "$offset";
}
diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
index fe063d33ea3e..00bf404dea27 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
@@ -299,14 +299,23 @@ void AMDGPUInstPrinter::printExpVM(const MCInst *MI, unsigned OpNo,
void AMDGPUInstPrinter::printFORMAT(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
- if (unsigned Val = MI->getOperand(OpNo).getImm()) {
- if (AMDGPU::isGFX10(STI))
- O << " format:" << Val;
- else {
- O << " dfmt:" << (Val & 15);
- O << ", nfmt:" << (Val >> 4);
- }
+ using namespace llvm::AMDGPU::MTBUFFormat;
+
+ unsigned Val = MI->getOperand(OpNo).getImm();
+ if (AMDGPU::isGFX10(STI)) {
+ if (Val == UFMT_DEFAULT)
+ return;
+ O << " format:" << Val;
+ } else {
+ if (Val == DFMT_NFMT_DEFAULT)
+ return;
+ unsigned Dfmt;
+ unsigned Nfmt;
+ decodeDfmtNfmt(Val, Dfmt, Nfmt);
+ O << " dfmt:" << Dfmt;
+ O << ", nfmt:" << Nfmt;
}
+ O << ',';
}
void AMDGPUInstPrinter::printRegOperand(unsigned RegNo, raw_ostream &O,
diff --git a/llvm/lib/Target/AMDGPU/SIDefines.h b/llvm/lib/Target/AMDGPU/SIDefines.h
index 4f7d255eb450..9c9dd66a4a79 100644
--- a/llvm/lib/Target/AMDGPU/SIDefines.h
+++ b/llvm/lib/Target/AMDGPU/SIDefines.h
@@ -392,6 +392,48 @@ enum ModeRegisterMasks : uint32_t {
} // namespace Hwreg
+namespace MTBUFFormat {
+
+enum DataFormat {
+ DFMT_MAX = 15,
+
+ DFMT_UNDEF = -1,
+ DFMT_DEFAULT = 1,
+
+ DFMT_SHIFT = 0,
+ DFMT_MASK = DFMT_MAX
+};
+
+enum NumFormat {
+ NFMT_MAX = 7,
+
+ NFMT_UNDEF = -1,
+ NFMT_DEFAULT = 0,
+
+ NFMT_SHIFT = 4,
+ NFMT_MASK = NFMT_MAX
+};
+
+enum MergedFormat {
+ DFMT_NFMT_UNDEF = -1,
+ DFMT_NFMT_DEFAULT = ((DFMT_DEFAULT & DFMT_MASK) << DFMT_SHIFT) |
+ ((NFMT_DEFAULT & NFMT_MASK) << NFMT_SHIFT),
+
+
+ DFMT_NFMT_MASK = (DFMT_MASK << DFMT_SHIFT) | (NFMT_MASK << NFMT_SHIFT),
+
+ DFMT_NFMT_MAX = DFMT_NFMT_MASK
+};
+
+enum UnifiedFormat {
+ UFMT_MAX = 127,
+
+ UFMT_UNDEF = -1,
+ UFMT_DEFAULT = 1
+};
+
+} // namespace MTBUFFormat
+
namespace Swizzle { // Encoding of swizzle macro used in ds_swizzle_b32.
enum Id : unsigned { // id of symbolic names
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.td b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
index 7aee52f91360..72feff80ac81 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.td
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
@@ -1115,7 +1115,7 @@ def LWE : NamedOperandBit<"LWE", NamedMatchClass<"LWE">>;
def exp_compr : NamedOperandBit<"ExpCompr", NamedMatchClass<"ExpCompr">>;
def exp_vm : NamedOperandBit<"ExpVM", NamedMatchClass<"ExpVM">>;
-def FORMAT : NamedOperandU8<"FORMAT", NamedMatchClass<"FORMAT">>;
+def FORMAT : NamedOperandU8<"FORMAT", NamedMatchClass<"FORMAT", 0>>;
def DMask : NamedOperandU16<"DMask", NamedMatchClass<"DMask">>;
def Dim : NamedOperandU8<"Dim", NamedMatchClass<"Dim", 0>>;
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
index 00e6d517bde5..b89e34e4c99c 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
@@ -783,6 +783,23 @@ void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width)
} // namespace Hwreg
+//===----------------------------------------------------------------------===//
+// MTBUF Format
+//===----------------------------------------------------------------------===//
+
+namespace MTBUFFormat {
+
+int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt) {
+ return (Dfmt << DFMT_SHIFT) | (Nfmt << NFMT_SHIFT);
+}
+
+void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt) {
+ Dfmt = (Format >> DFMT_SHIFT) & DFMT_MASK;
+ Nfmt = (Format >> NFMT_SHIFT) & NFMT_MASK;
+}
+
+} // namespace MTBUFFormat
+
//===----------------------------------------------------------------------===//
// SendMsg
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
index e71554575f6a..a9ea05755a67 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
@@ -482,6 +482,15 @@ void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width);
} // namespace Hwreg
+namespace MTBUFFormat {
+
+LLVM_READNONE
+int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt);
+
+void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt);
+
+} // namespace MTBUFFormat
+
namespace SendMsg {
LLVM_READONLY
diff --git a/llvm/test/MC/AMDGPU/mtbuf-gfx10.s b/llvm/test/MC/AMDGPU/mtbuf-gfx10.s
index ea3f9df9bb5e..40f082d02ebc 100644
--- a/llvm/test/MC/AMDGPU/mtbuf-gfx10.s
+++ b/llvm/test/MC/AMDGPU/mtbuf-gfx10.s
@@ -1,4 +1,5 @@
-// RUN: llvm-mc -arch=amdgcn -mcpu=gfx1010 -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=GFX10 %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx1010 -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=GFX10 %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx1010 -show-encoding %s 2>&1 | FileCheck -check-prefix=GFX10-ERR %s
// GFX10: tbuffer_load_format_d16_x v0, off, s[0:3], format:22, 0 ; encoding: [0x00,0x00,0xb0,0xe8,0x00,0x00,0x20,0x80]
tbuffer_load_format_d16_x v0, off, s[0:3], format:22, 0
@@ -66,3 +67,49 @@ tbuffer_store_format_xyzw v[0:3], v6, s[0:3], format:46, 0 idxen
tbuffer_store_format_x v0, v1, s[0:3], format:125, 0 idxen
// GFX10: tbuffer_store_format_xy v[0:1], v2, s[0:3], format:33, 0 idxen ; encoding: [0x00,0x20,0x0d,0xe9,0x02,0x00,0x00,0x80]
tbuffer_store_format_xy v[0:1], v2, s[0:3], format:33, 0 idxen
+
+// GFX10: tbuffer_store_format_x v0, v1, s[0:3], format:127, 0 idxen ; encoding: [0x00,0x20,0xfc,0xeb,0x01,0x00,0x00,0x80]
+tbuffer_store_format_x v0, v1, s[0:3], format:127, 0 idxen
+
+// GFX10: tbuffer_store_format_x v0, v1, s[0:3], format:127, 0 idxen ; encoding: [0x00,0x20,0xfc,0xeb,0x01,0x00,0x00,0x80]
+tbuffer_store_format_x v0, v1, s[0:3] format:127 0 idxen
+
+// GFX10: tbuffer_store_format_x v0, v1, s[0:3], format:0, s0 idxen ; encoding: [0x00,0x20,0x04,0xe8,0x01,0x00,0x00,0x00]
+tbuffer_store_format_x v0, v1, s[0:3] format:0 s0 idxen
+
+// GFX10: tbuffer_store_format_x v0, v1, s[0:3], s0 idxen ; encoding: [0x00,0x20,0x0c,0xe8,0x01,0x00,0x00,0x00]
+tbuffer_store_format_x v0, v1, s[0:3] format:1 s0 idxen
+
+// GFX10: tbuffer_store_format_x v0, v1, s[0:3], 0 idxen ; encoding: [0x00,0x20,0x0c,0xe8,0x01,0x00,0x00,0x80]
+tbuffer_store_format_x v0, v1, s[0:3], 0 idxen
+
+// GFX10: tbuffer_load_format_d16_x v0, off, s[0:3], s0 ; encoding: [0x00,0x00,0x08,0xe8,0x00,0x00,0x20,0x00]
+tbuffer_load_format_d16_x v0, off, s[0:3] s0
+
+//===----------------------------------------------------------------------===//
+// Errors handling.
+//===----------------------------------------------------------------------===//
+
+// GFX10-ERR: error: out of range format
+tbuffer_load_format_d16_x v0, off, s[0:3], format:-1, 0
+
+// GFX10-ERR: error: out of range format
+tbuffer_load_format_d16_x v0, off, s[0:3], format:128, s0
+
+// GFX10-ERR: error: too few operands for instruction
+tbuffer_load_format_d16_x v0, off, s[0:3], format:127
+
+// GFX10-ERR: error: too few operands for instruction
+tbuffer_load_format_d16_x v0, off, s[0:3]
+
+// GFX10-ERR: error: invalid operand for instruction
+tbuffer_load_format_d16_x v0, off, s[0:3] idxen
+
+// GFX10-ERR: error: unknown token in expression
+tbuffer_load_format_d16_x v0, off, s[0:3], format:1,, s0
+
+// GFX10-ERR: error: unknown token in expression
+tbuffer_load_format_d16_x v0, off, s[0:3], format:1:, s0
+
+// GFX10-ERR: error: not a valid operand
+tbuffer_load_format_d16_x v0, off, s[0:3],, format:1, s0
diff --git a/llvm/test/MC/AMDGPU/mtbuf.s b/llvm/test/MC/AMDGPU/mtbuf.s
index bfffb67bd762..9d207ff32606 100644
--- a/llvm/test/MC/AMDGPU/mtbuf.s
+++ b/llvm/test/MC/AMDGPU/mtbuf.s
@@ -1,6 +1,10 @@
-// RUN: llvm-mc -arch=amdgcn -mcpu=tahiti -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=SI -check-prefix=SICI %s
-// RUN: llvm-mc -arch=amdgcn -mcpu=bonaire -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=CI -check-prefix=SICI %s
-// RUN: llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=VI %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=tahiti -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=SI -check-prefix=SICI %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=bonaire -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=CI -check-prefix=SICI %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding %s | FileCheck -check-prefix=GCN -check-prefix=VI %s
+
+// RUN: not llvm-mc -arch=amdgcn -mcpu=tahiti -show-encoding %s 2>&1 | FileCheck -check-prefix=GCN-ERR %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=bonaire -show-encoding %s 2>&1 | FileCheck -check-prefix=GCN-ERR %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding %s 2>&1 | FileCheck -check-prefix=GCN-ERR %s
//===----------------------------------------------------------------------===//
// Test for dfmt and nfmt (tbuffer only)
@@ -45,11 +49,81 @@ tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, ttmp1
// dfmt is optional:
tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], nfmt:2, ttmp1
-// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:0, nfmt:2, ttmp1 ; encoding: [0x00,0x00,0x07,0xe9,0x00,0x01,0x1d,0x71]
-// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:0, nfmt:2, ttmp1 ; encoding: [0x00,0x80,0x03,0xe9,0x00,0x01,0x1d,0x71]
+// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:1, nfmt:2, ttmp1 ; encoding: [0x00,0x00,0x0f,0xe9,0x00,0x01,0x1d,0x71]
+// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:1, nfmt:2, ttmp1 ; encoding: [0x00,0x80,0x0b,0xe9,0x00,0x01,0x1d,0x71]
// nfmt and dfmt can be in either order:
tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], nfmt:2, dfmt:15, ttmp1
// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:2, ttmp1 ; encoding: [0x00,0x00,0x7f,0xe9,0x00,0x01,0x1d,0x71]
// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:2, ttmp1 ; encoding: [0x00,0x80,0x7b,0xe9,0x00,0x01,0x1d,0x71]
+// nfmt and dfmt may be omitted:
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], ttmp1
+// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], ttmp1 ; encoding: [0x00,0x00,0x0f,0xe8,0x00,0x01,0x1d,0x71]
+// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], ttmp1 ; encoding: [0x00,0x80,0x0b,0xe8,0x00,0x01,0x1d,0x71]
+
+// Check dfmt/nfmt min values
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:0, nfmt:0, ttmp1
+// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:0, nfmt:0, ttmp1 ; encoding: [0x00,0x00,0x07,0xe8,0x00,0x01,0x1d,0x71]
+// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:0, nfmt:0, ttmp1 ; encoding: [0x00,0x80,0x03,0xe8,0x00,0x01,0x1d,0x71]
+
+// Check dfmt/nfmt max values
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:7, ttmp1
+// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:7, ttmp1 ; encoding: [0x00,0x00,0xff,0xeb,0x00,0x01,0x1d,0x71]
+// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:7, ttmp1 ; encoding: [0x00,0x80,0xfb,0xeb,0x00,0x01,0x1d,0x71]
+
+// Check default dfmt/nfmt values
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:1, nfmt:0, ttmp1
+// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], ttmp1 ; encoding: [0x00,0x00,0x0f,0xe8,0x00,0x01,0x1d,0x71]
+// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], ttmp1 ; encoding: [0x00,0x80,0x0b,0xe8,0x00,0x01,0x1d,0x71]
+
+// Check that comma separators are optional
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:15 nfmt:7 ttmp1
+// SICI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:7, ttmp1 ; encoding: [0x00,0x00,0xff,0xeb,0x00,0x01,0x1d,0x71]
+// VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:7, ttmp1 ; encoding: [0x00,0x80,0xfb,0xeb,0x00,0x01,0x1d,0x71]
+
+//===----------------------------------------------------------------------===//
+// Errors handling.
+//===----------------------------------------------------------------------===//
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:-1 nfmt:1 s0
+// GCN-ERR: error: out of range dfmt
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:16 nfmt:1 s0
+// GCN-ERR: error: out of range dfmt
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1 nfmt:-1 s0
+// GCN-ERR: error: out of range nfmt
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1 nfmt:8 s0
+// GCN-ERR: error: out of range nfmt
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7]
+// GCN-ERR: error: too few operands for instruction
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7],, dfmt:1 nfmt:1 s0
+// GCN-ERR: error: not a valid operand
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1,, nfmt:1 s0
+// GCN-ERR: error: unknown token in expression
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1 nfmt:1,, s0
+// GCN-ERR: error: unknown token in expression
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1 dfmt:1 s0
+// GCN-ERR: error: not a valid operand
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] nfmt:1 nfmt:1 s0
+// GCN-ERR: error: not a valid operand
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1 nfmt:1 dfmt:1 s0
+// GCN-ERR: error: not a valid operand
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] nfmt:1 dfmt:1 nfmt:1 s0
+// GCN-ERR: error: not a valid operand
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1: nfmt:1 s0
+// GCN-ERR: error: unknown token in expression
+
+tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7] dfmt:1 nfmt:1: s0
+// GCN-ERR: error: unknown token in expression
diff --git a/llvm/test/MC/Disassembler/AMDGPU/mtbuf_gfx10.txt b/llvm/test/MC/Disassembler/AMDGPU/mtbuf_gfx10.txt
index 86fcdfc3d6b1..10d92d9990dc 100644
--- a/llvm/test/MC/Disassembler/AMDGPU/mtbuf_gfx10.txt
+++ b/llvm/test/MC/Disassembler/AMDGPU/mtbuf_gfx10.txt
@@ -67,3 +67,20 @@
# GFX10: tbuffer_store_format_xy v[0:1], v2, s[0:3], format:33, 0 idxen
0x00,0x20,0x0d,0xe9,0x02,0x00,0x00,0x80
+# GFX10: tbuffer_store_format_x v0, v1, s[0:3], format:127, 0 idxen ; encoding: [0x00,0x20,0xfc,0xeb,0x01,0x00,0x00,0x80]
+0x00,0x20,0xfc,0xeb,0x01,0x00,0x00,0x80
+
+# GFX10: tbuffer_store_format_x v0, v1, s[0:3], format:0, 0 idxen ; encoding: [0x00,0x20,0x04,0xe8,0x01,0x00,0x00,0x80]
+0x00,0x20,0x04,0xe8,0x01,0x00,0x00,0x80
+
+# GFX10: tbuffer_load_format_d16_x v0, off, s[0:3], format:0, s0 ; encoding: [0x00,0x00,0x00,0xe8,0x00,0x00,0x20,0x00]
+0x00,0x00,0x00,0xe8,0x00,0x00,0x20,0x00
+
+# GFX10: tbuffer_store_format_x v0, v1, s[0:3], 0 idxen ; encoding: [0x00,0x20,0x0c,0xe8,0x01,0x00,0x00,0x80]
+0x00,0x20,0x0c,0xe8,0x01,0x00,0x00,0x80
+
+# GFX10: tbuffer_load_format_d16_x v0, off, s[0:3], s0 ; encoding: [0x00,0x00,0x08,0xe8,0x00,0x00,0x20,0x00]
+0x00,0x00,0x08,0xe8,0x00,0x00,0x20,0x00
+
+# GFX10: tbuffer_store_format_x v0, v1, s[0:3], format:2, s0 idxen ; encoding: [0x00,0x20,0x14,0xe8,0x01,0x00,0x00,0x00]
+0x00,0x20,0x14,0xe8,0x01,0x00,0x00,0x00
diff --git a/llvm/test/MC/Disassembler/AMDGPU/mtbuf_vi.txt b/llvm/test/MC/Disassembler/AMDGPU/mtbuf_vi.txt
index 519e03ede69e..35f9d3bfd18f 100644
--- a/llvm/test/MC/Disassembler/AMDGPU/mtbuf_vi.txt
+++ b/llvm/test/MC/Disassembler/AMDGPU/mtbuf_vi.txt
@@ -20,3 +20,21 @@
# VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:2, ttmp1 ; encoding: [0x00,0x80,0x7b,0xe9,0x00,0x01,0x1d,0x71]
0x00 0x80 0x7b 0xe9 0x00 0x01 0x1d 0x71
+
+# VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:0, nfmt:2, ttmp1 ; encoding: [0x00,0x80,0x03,0xe9,0x00,0x01,0x1d,0x71]
+0x00,0x80,0x03,0xe9,0x00,0x01,0x1d,0x71
+
+# VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:0, ttmp1 ; encoding: [0x00,0x80,0x7b,0xe8,0x00,0x01,0x1d,0x71]
+0x00,0x80,0x7b,0xe8,0x00,0x01,0x1d,0x71
+
+# VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], ttmp1 ; encoding: [0x00,0x80,0x0b,0xe8,0x00,0x01,0x1d,0x71]
+0x00,0x80,0x0b,0xe8,0x00,0x01,0x1d,0x71
+
+# VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:0, nfmt:0, ttmp1 ; encoding: [0x00,0x80,0x03,0xe8,0x00,0x01,0x1d,0x71]
+0x00,0x80,0x03,0xe8,0x00,0x01,0x1d,0x71
+
+# VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:1, nfmt:1, ttmp1 ; encoding: [0x00,0x80,0x8b,0xe8,0x00,0x01,0x1d,0x71]
+0x00,0x80,0x8b,0xe8,0x00,0x01,0x1d,0x71
+
+# VI: tbuffer_store_format_xyzw v[1:4], off, ttmp[4:7], dfmt:15, nfmt:7, ttmp1 ; encoding: [0x00,0x80,0xfb,0xeb,0x00,0x01,0x1d,0x71]
+0x00,0x80,0xfb,0xeb,0x00,0x01,0x1d,0x71
More information about the llvm-commits
mailing list