[AsmParser] Match mandatory operands following optional operands.

Currently, the asm parser stops matching instruction operands as soon as the first optional operand is encountered. This leads to the need for custom checks on missing mandatory operands that come after optional operands.

The patch changes the parser to always match all optional and mandatory instruction operands, thus making the custom checks unnecessary. This is particularly useful for the AMDGPU backend where we have numerous optional instruction modifiers.

Reviewed By: dp

Differential Revision: https://reviews.llvm.org/D137549
This commit is contained in:
Ivan Kosarev 2022-11-10 12:19:53 +00:00
parent 30498cf7c4
commit af6b1f797f
7 changed files with 63 additions and 41 deletions

View File

@ -1,10 +1,10 @@
// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx1010 -mattr=+WavefrontSize32,-WavefrontSize64 %s 2>&1 | FileCheck %s --implicit-check-not=error: --strict-whitespace
//==============================================================================
// dim modifier is required on this GPU
// operands are not valid for this GPU or mode
image_atomic_add v252, v2, s[8:15]
// CHECK: error: dim modifier is required on this GPU
// CHECK: error: operands are not valid for this GPU or mode
// CHECK-NEXT:{{^}}image_atomic_add v252, v2, s[8:15]
// CHECK-NEXT:{{^}}^
@ -966,19 +966,6 @@ s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP, 0)
// CHECK-NEXT:{{^}}s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP, 0)
// CHECK-NEXT:{{^}} ^
//==============================================================================
// missing dst operand or lds modifier
buffer_load_dword off, s[8:11], s3
// CHECK: error: missing dst operand or lds modifier
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3
// CHECK-NEXT:{{^}}^
buffer_load_dword off, s[8:11], s3 offset:1
// CHECK: error: missing dst operand or lds modifier
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3 offset:1
// CHECK-NEXT:{{^}}^
//==============================================================================
// missing message operation
@ -1191,6 +1178,16 @@ v_add_f32_e64 v0, v1
// CHECK-NEXT:{{^}}v_add_f32_e64 v0, v1
// CHECK-NEXT:{{^}}^
buffer_load_dword off, s[8:11], s3
// CHECK: error: too few operands for instruction
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3
// CHECK-NEXT:{{^}}^
buffer_load_dword off, s[8:11], s3 offset:1
// CHECK: error: too few operands for instruction
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3 offset:1
// CHECK-NEXT:{{^}}^
//==============================================================================
// too large value for expcnt

View File

@ -37,7 +37,7 @@ global_load_lds_dword v[2:3], off
// GFX9ERR: error: instruction not supported on this GPU
global_load_dword v[2:3], off
// GFX9ERR: error: missing dst operand or lds modifier
// GFX9ERR: error: too few operands for instruction
scratch_load_dword v2, off, offset:256
// GFX9ERR: error: missing dst operand or lds modifier
// GFX9ERR: error: too few operands for instruction

View File

@ -179,15 +179,15 @@ v_add_i16 v5, 0.5, v2
// CHECK-NEXT:{{^}} ^
//==============================================================================
// missing dst operand or lds modifier
// too few operands for instruction
buffer_load_dword off, s[8:11], s3
// CHECK: error: missing dst operand or lds modifier
// CHECK: error: too few operands for instruction
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3
// CHECK-NEXT:{{^}}^
buffer_load_dword off, s[8:11], s3 offset:1
// CHECK: error: missing dst operand or lds modifier
// CHECK: error: too few operands for instruction
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3 offset:1
// CHECK-NEXT:{{^}}^

View File

@ -862,7 +862,7 @@ buffer_store_lds_dword s[4:7], s8 offset:4 tfe lds
// NOVI: error: invalid operand for instruction
buffer_load_dword off, s[8:11], s3
// NOSICIVI: error: missing dst operand or lds modifier
// NOSICIVI: error: too few operands for instruction
buffer_load_dword off, s[8:11], s3 offset:1
// NOSICIVI: error: missing dst operand or lds modifier
// NOSICIVI: error: too few operands for instruction

View File

@ -8,53 +8,63 @@
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r3): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 2 (Reg:r0): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr32Disp20 against actual operand at index 3 (Mem:3): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'llill'
// CHECK: Trying to match opcode LLILL
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r0): match success using generic matcher
// CHECK: Matching formal operand class MCK_U16Imm against actual operand at index 2 (Imm:0): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'lgr'
// CHECK: Trying to match opcode LGR
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r1): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 2 (Reg:r0): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'lg'
// CHECK: Trying to match opcode LG
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r1): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDXAddr64Disp20 against actual operand at index 2 (Mem:16(r2)): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'lg'
// CHECK: Trying to match opcode LG
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r1): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDXAddr64Disp20 against actual operand at index 2 (Mem:16(r2,r3)): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'stmg'
// CHECK: Trying to match opcode STMG
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r13): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 2 (Reg:r15): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr64Disp20 against actual operand at index 3 (Mem:104(r15)): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'mvc'
// CHECK: Trying to match opcode MVC
// CHECK: Matching formal operand class MCK_BDLAddr64Disp12Len8 against actual operand at index 1 (Mem:184(8,r15)): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr64Disp12 against actual operand at index 2 (Mem:8(r2)): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'mvck'
// CHECK: Trying to match opcode MVCK
// CHECK: Matching formal operand class MCK_BDRAddr64Disp12 against actual operand at index 1 (Mem:0(r0,r1)): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr64Disp12 against actual operand at index 2 (Mem:4095(r15)): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 3 (Reg:r2): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'j'
// CHECK: Trying to match opcode J
// CHECK: Matching formal operand class MCK_PCRel16 against actual operand at index 1 (Imm:.Ltmp0+2): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 2: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 2: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'brasl'
// CHECK: Trying to match opcode BRASL
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r14): match success using generic matcher
// CHECK: Matching formal operand class MCK_PCRelTLS32 against actual operand at index 2 (ImmTLS:fun): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: .text
// CHECK: sllg %r3, %r0, 3
// CHECK: llill %r0, 0

View File

@ -9,13 +9,15 @@
// CHECK: Trying to match opcode PSHUFBrm
// CHECK: Matching formal operand class MCK_Mem128 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rip,Scale=1,Disp=CPI1_0): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 2 (Reg:xmm1): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 2 encodings with mnemonic 'sha1rnds4'
// CHECK: Trying to match opcode SHA1RNDS4rri
// CHECK: Matching formal operand class MCK_ImmUnsignedi8 against actual operand at index 1 (Imm:1): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 2 (Reg:xmm1): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 3 (Reg:xmm2): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 4 encodings with mnemonic 'pinsrw'
// CHECK: Trying to match opcode MMX_PINSRWrr
// CHECK: Matching formal operand class MCK_ImmUnsignedi8 against actual operand at index 1 (Imm:3): match success using generic matcher
@ -25,14 +27,16 @@
// CHECK: Matching formal operand class MCK_ImmUnsignedi8 against actual operand at index 1 (Imm:3): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR32orGR64 against actual operand at index 2 (Reg:ecx): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 3 (Reg:xmm5): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 2 encodings with mnemonic 'crc32l'
// CHECK: Trying to match opcode CRC32r32r32
// CHECK: Matching formal operand class MCK_GR32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=3735928559,SegReg=gs): Opcode result: multiple operand mismatches, ignoring this opcode
// CHECK: Trying to match opcode CRC32r32m32
// CHECK: Matching formal operand class MCK_Mem32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=3735928559,SegReg=gs): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR32 against actual operand at index 2 (Reg:ecx): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 4 encodings with mnemonic 'punpcklbw'
// CHECK: Trying to match opcode MMX_PUNPCKLBWrr
// CHECK: Matching formal operand class MCK_VR64 against actual operand at index 1 (Reg:mm0): match success using generic matcher
@ -40,7 +44,8 @@
// CHECK: Trying to match opcode MMX_PUNPCKLBWrm
// CHECK: Matching formal operand class MCK_VR64 against actual operand at index 1 (Reg:mm0): match success using generic matcher
// CHECK: Matching formal operand class MCK_Mem32 against actual operand at index 2 (Memory: ModeSize=64,Size=32,BaseReg=rsp,Scale=1): match success using generic matcher
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
// CHECK: Opcode result: complete match, selecting this opcode
pshufb CPI1_0(%rip), %xmm1
sha1rnds4 $1, %xmm1, %xmm2

View File

@ -3666,7 +3666,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " else\n";
OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \": \");\n";
OS << " if (ActualIdx >= Operands.size()) {\n";
OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"actual operand index out of range \");\n";
OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"actual operand "
"index out of range\\n\");\n";
if (ReportMultipleNearMisses) {
OS << " bool ThisOperandValid = (Formal == " <<"InvalidMatchClass) || "
"isSubclass(Formal, OptionalMatchClass);\n";
@ -3690,12 +3691,21 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n";
OS << " continue;\n";
} else {
OS << " OperandsValid = (Formal == InvalidMatchClass) || isSubclass(Formal, OptionalMatchClass);\n";
OS << " if (!OperandsValid) ErrorInfo = ActualIdx;\n";
OS << " if (Formal == InvalidMatchClass) {\n";
if (HasOptionalOperands) {
OS << " OptionalOperandsMask.set(FormalIdx, " << MaxNumOperands
OS << " OptionalOperandsMask.set(FormalIdx, " << MaxNumOperands
<< ");\n";
}
OS << " break;\n";
OS << " }\n";
OS << " if (isSubclass(Formal, OptionalMatchClass)) {\n";
if (HasOptionalOperands) {
OS << " OptionalOperandsMask.set(FormalIdx);\n";
}
OS << " continue;\n";
OS << " }\n";
OS << " OperandsValid = false;\n";
OS << " ErrorInfo = ActualIdx;\n";
OS << " break;\n";
}
OS << " }\n";