Skip to content

Commit e2452f5

Browse files
committed
[AMDGPU][MC] Added detection of unsupported instructions
Implemented identification of unsupported instructions; improved errors reporting. See bug 42590. Reviewers: rampitec Differential Revision: https://reviews.llvm.org/D88211
1 parent d8ee28b commit e2452f5

35 files changed

+8193
-947
lines changed

llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp

Lines changed: 98 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
12461246
bool isForcedDPP() const { return ForcedDPP; }
12471247
bool isForcedSDWA() const { return ForcedSDWA; }
12481248
ArrayRef<unsigned> getMatchedVariants() const;
1249+
StringRef getMatchedVariantName() const;
12491250

12501251
std::unique_ptr<AMDGPUOperand> parseRegister(bool RestoreOnFailure = false);
12511252
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
@@ -1369,6 +1370,13 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
13691370
bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
13701371
unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
13711372

1373+
bool isSupportedMnemo(StringRef Mnemo,
1374+
const FeatureBitset &FBS);
1375+
bool isSupportedMnemo(StringRef Mnemo,
1376+
const FeatureBitset &FBS,
1377+
ArrayRef<unsigned> Variants);
1378+
bool checkUnsupportedInstruction(StringRef Name, const SMLoc &IDLoc);
1379+
13721380
bool isId(const StringRef Id) const;
13731381
bool isId(const AsmToken &Token, const StringRef Id) const;
13741382
bool isToken(const AsmToken::TokenKind Kind) const;
@@ -2837,6 +2845,15 @@ unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
28372845
return Match_Success;
28382846
}
28392847

2848+
static ArrayRef<unsigned> getAllVariants() {
2849+
static const unsigned Variants[] = {
2850+
AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2851+
AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2852+
};
2853+
2854+
return makeArrayRef(Variants);
2855+
}
2856+
28402857
// What asm variants we should check
28412858
ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
28422859
if (getForcedEncodingSize() == 32) {
@@ -2860,12 +2877,23 @@ ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
28602877
return makeArrayRef(Variants);
28612878
}
28622879

2863-
static const unsigned Variants[] = {
2864-
AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2865-
AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2866-
};
2880+
return getAllVariants();
2881+
}
28672882

2868-
return makeArrayRef(Variants);
2883+
StringRef AMDGPUAsmParser::getMatchedVariantName() const {
2884+
if (getForcedEncodingSize() == 32)
2885+
return "e32";
2886+
2887+
if (isForcedVOP3())
2888+
return "e64";
2889+
2890+
if (isForcedSDWA())
2891+
return "sdwa";
2892+
2893+
if (isForcedDPP())
2894+
return "dpp";
2895+
2896+
return "";
28692897
}
28702898

28712899
unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
@@ -3753,6 +3781,57 @@ static std::string AMDGPUMnemonicSpellCheck(StringRef S,
37533781
const FeatureBitset &FBS,
37543782
unsigned VariantID = 0);
37553783

3784+
static bool AMDGPUCheckMnemonic(StringRef Mnemonic,
3785+
const FeatureBitset &AvailableFeatures,
3786+
unsigned VariantID);
3787+
3788+
bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo,
3789+
const FeatureBitset &FBS) {
3790+
return isSupportedMnemo(Mnemo, FBS, getAllVariants());
3791+
}
3792+
3793+
bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo,
3794+
const FeatureBitset &FBS,
3795+
ArrayRef<unsigned> Variants) {
3796+
for (auto Variant : Variants) {
3797+
if (AMDGPUCheckMnemonic(Mnemo, FBS, Variant))
3798+
return true;
3799+
}
3800+
3801+
return false;
3802+
}
3803+
3804+
bool AMDGPUAsmParser::checkUnsupportedInstruction(StringRef Mnemo,
3805+
const SMLoc &IDLoc) {
3806+
FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
3807+
3808+
// Check if requested instruction variant is supported.
3809+
if (isSupportedMnemo(Mnemo, FBS, getMatchedVariants()))
3810+
return false;
3811+
3812+
// This instruction is not supported.
3813+
// Clear any other pending errors because they are no longer relevant.
3814+
getParser().clearPendingErrors();
3815+
3816+
// Requested instruction variant is not supported.
3817+
// Check if any other variants are supported.
3818+
StringRef VariantName = getMatchedVariantName();
3819+
if (!VariantName.empty() && isSupportedMnemo(Mnemo, FBS)) {
3820+
return Error(IDLoc,
3821+
Twine(VariantName,
3822+
" variant of this instruction is not supported"));
3823+
}
3824+
3825+
// Finally check if this instruction is supported on any other GPU.
3826+
if (isSupportedMnemo(Mnemo, FeatureBitset().set())) {
3827+
return Error(IDLoc, "instruction not supported on this GPU");
3828+
}
3829+
3830+
// Instruction not supported on any GPU. Probably a typo.
3831+
std::string Suggestion = AMDGPUMnemonicSpellCheck(Mnemo, FBS);
3832+
return Error(IDLoc, "invalid instruction" + Suggestion);
3833+
}
3834+
37563835
bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
37573836
OperandVector &Operands,
37583837
MCStreamer &Out,
@@ -3782,27 +3861,26 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
37823861
break;
37833862
}
37843863

3785-
switch (Result) {
3786-
default: break;
3787-
case Match_Success:
3864+
if (Result == Match_Success) {
37883865
if (!validateInstruction(Inst, IDLoc, Operands)) {
37893866
return true;
37903867
}
37913868
Inst.setLoc(IDLoc);
37923869
Out.emitInstruction(Inst, getSTI());
37933870
return false;
3871+
}
3872+
3873+
StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
3874+
if (checkUnsupportedInstruction(Mnemo, IDLoc)) {
3875+
return true;
3876+
}
37943877

3878+
switch (Result) {
3879+
default: break;
37953880
case Match_MissingFeature:
3881+
// FIXME: this case should be analyzed and error message corrected.
37963882
return Error(IDLoc, "instruction not supported on this GPU");
37973883

3798-
case Match_MnemonicFail: {
3799-
FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
3800-
std::string Suggestion = AMDGPUMnemonicSpellCheck(
3801-
((AMDGPUOperand &)*Operands[0]).getToken(), FBS);
3802-
return Error(IDLoc, "invalid instruction" + Suggestion,
3803-
((AMDGPUOperand &)*Operands[0]).getLocRange());
3804-
}
3805-
38063884
case Match_InvalidOperand: {
38073885
SMLoc ErrorLoc = IDLoc;
38083886
if (ErrorInfo != ~0ULL) {
@@ -3819,6 +3897,8 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
38193897
case Match_PreferE32:
38203898
return Error(IDLoc, "internal error: instruction without _e64 suffix "
38213899
"should be encoded as e32");
3900+
case Match_MnemonicFail:
3901+
llvm_unreachable("Invalid instructions should have been handled already");
38223902
}
38233903
llvm_unreachable("Implement any new match types added!");
38243904
}
@@ -4771,6 +4851,7 @@ bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
47714851
Parser.Lex();
47724852

47734853
if (Res != MatchOperand_Success) {
4854+
checkUnsupportedInstruction(Name, NameLoc);
47744855
if (!Parser.hasPendingError()) {
47754856
// FIXME: use real operand location rather than the current location.
47764857
StringRef Msg =
@@ -7469,6 +7550,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmParser() {
74697550
#define GET_REGISTER_MATCHER
74707551
#define GET_MATCHER_IMPLEMENTATION
74717552
#define GET_MNEMONIC_SPELL_CHECKER
7553+
#define GET_MNEMONIC_CHECKER
74727554
#include "AMDGPUGenAsmMatcher.inc"
74737555

74747556
// This fuction should be defined after auto-generated include so that we have

llvm/test/MC/AMDGPU/dpp-err.s

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@ v_mov_b32_dpp v0, v1 row_xmask:1 row_mask:0x1 bank_mask:0x1
1414
// GFX10: v_mov_b32_dpp v0, v1 row_xmask:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x61,0x01,0x11]
1515

1616
v_mov_b32_dpp v0, v1 wave_shl:1 row_mask:0x1 bank_mask:0x1
17-
// GFX89: v0, v1 wave_shl:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x30,0x01,0x11]
17+
// GFX89: v_mov_b32_dpp v0, v1 wave_shl:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x30,0x01,0x11]
1818
// GFX10-ERR: error: not a valid operand.
1919

2020
v_mov_b32_dpp v0, v1 wave_shr:1 row_mask:0x1 bank_mask:0x1
21-
// GFX89: v0, v1 wave_shr:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x38,0x01,0x11]
21+
// GFX89: v_mov_b32_dpp v0, v1 wave_shr:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x38,0x01,0x11]
2222
// GFX10-ERR: error: not a valid operand.
2323

2424
v_mov_b32_dpp v0, v1 wave_rol:1 row_mask:0x1 bank_mask:0x1
25-
// GFX89: v0, v1 wave_rol:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x34,0x01,0x11]
25+
// GFX89: v_mov_b32_dpp v0, v1 wave_rol:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x34,0x01,0x11]
2626
// GFX10-ERR: error: not a valid operand.
2727

2828
v_mov_b32_dpp v0, v1 wave_ror:1 row_mask:0x1 bank_mask:0x1
29-
// GFX89: v0, v1 wave_ror:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x3c,0x01,0x11]
29+
// GFX89: v_mov_b32_dpp v0, v1 wave_ror:1 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x3c,0x01,0x11]
3030
// GFX10-ERR: error: not a valid operand.
3131

3232
v_mov_b32_dpp v0, v1 row_bcast:15 row_mask:0x1 bank_mask:0x1
33-
// GFX89: v0, v1 row_bcast:15 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x42,0x01,0x11]
33+
// GFX89: v_mov_b32_dpp v0, v1 row_bcast:15 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x42,0x01,0x11]
3434
// GFX10-ERR: error: not a valid operand.
3535

3636
v_mov_b32_dpp v0, v1 row_bcast:31 row_mask:0x1 bank_mask:0x1
37-
// GFX89: v0, v1 row_bcast:31 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x43,0x01,0x11]
37+
// GFX89: v_mov_b32_dpp v0, v1 row_bcast:31 row_mask:0x1 bank_mask:0x1 ; encoding: [0xfa,0x02,0x00,0x7e,0x01,0x43,0x01,0x11]
3838
// GFX10-ERR: error: not a valid operand.

llvm/test/MC/AMDGPU/ds.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ ds_add_u32 v2, v4 offset:16
1616
// VI: ds_add_u32 v2, v4 offset:16 ; encoding: [0x10,0x00,0x00,0xd8,0x02,0x04,0x00,0x00]
1717

1818
ds_add_src2_f32 v255 offset:65535
19-
// NOSICI: error: not a valid operand.
19+
// NOSICI: error: instruction not supported on this GPU
2020
// VI: ds_add_src2_f32 v255 offset:65535 ; encoding: [0xff,0xff,0x2a,0xd9,0xff,0x00,0x00,0x00]
2121

2222
ds_add_src2_f32 v0 offset:4 gds
23-
// NOSICI: error: not a valid operand.
23+
// NOSICI: error: instruction not supported on this GPU
2424
// VI: ds_add_src2_f32 v0 offset:4 gds ; encoding: [0x04,0x00,0x2b,0xd9,0x00,0x00,0x00,0x00]
2525

2626
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)