diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1241,12 +1241,15 @@ def _timm : AsmVectorIndexOpnd, TImmLeaf; } +def VectorIndex0Operand : AsmVectorIndex<0, 0>; def VectorIndex1Operand : AsmVectorIndex<1, 1>; def VectorIndexBOperand : AsmVectorIndex<0, 15>; def VectorIndexHOperand : AsmVectorIndex<0, 7>; def VectorIndexSOperand : AsmVectorIndex<0, 3>; def VectorIndexDOperand : AsmVectorIndex<0, 1>; +defm VectorIndex0 : VectorIndex; defm VectorIndex1 : VectorIndex; defm VectorIndexB : VectorIndex; multiclass SMov { + // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME) + // streaming mode. + let Predicates = [HasNEONorStreamingSVE] in { + def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> { + let Inst{20-16} = 0b00001; + } + def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> { + let Inst{20-16} = 0b00001; + } + def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> { + let Inst{20-16} = 0b00010; + } + def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> { + let Inst{20-16} = 0b00010; + } + def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> { + let Inst{20-16} = 0b00100; + } + } def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> { bits<4> idx; let Inst{20-17} = idx; @@ -7331,6 +7353,28 @@ } multiclass UMov { + // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME) + // streaming mode. + let Predicates = [HasNEONorStreamingSVE] in { + def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> { + let Inst{20-16} = 0b00001; + } + def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> { + let Inst{20-16} = 0b00010; + } + def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> { + let Inst{20-16} = 0b00100; + } + def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> { + let Inst{20-16} = 0b01000; + } + def : SIMDMovAlias<"mov", ".s", + !cast(NAME # vi32_idx0), + GPR32, VectorIndex0>; + def : SIMDMovAlias<"mov", ".d", + !cast(NAME # vi64_idx0), + GPR64, VectorIndex0>; + } def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> { bits<4> idx; let Inst{20-17} = idx; diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -5102,6 +5102,8 @@ case Match_InvalidSVECpyImm64: return Error(Loc, "immediate must be an integer in range [-128, 127] or a " "multiple of 256 in range [-32768, 32512]"); + case Match_InvalidIndexRange0_0: + return Error(Loc, "expected lane specifier '[0]'"); case Match_InvalidIndexRange1_1: return Error(Loc, "expected lane specifier '[1]'"); case Match_InvalidIndexRange0_15: @@ -5711,6 +5713,7 @@ case Match_InvalidSVECpyImm16: case Match_InvalidSVECpyImm32: case Match_InvalidSVECpyImm64: + case Match_InvalidIndexRange0_0: case Match_InvalidIndexRange1_1: case Match_InvalidIndexRange0_15: case Match_InvalidIndexRange0_7: diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -323,6 +323,17 @@ // ^ insert implicit 8-bit element tile MI.insert(MI.begin()+2, MCOperand::createReg(AArch64::ZAB0)); break; + case AArch64::SMOVvi8to32_idx0: + case AArch64::SMOVvi8to64_idx0: + case AArch64::SMOVvi16to32_idx0: + case AArch64::SMOVvi16to64_idx0: + case AArch64::SMOVvi32to64_idx0: + case AArch64::UMOVvi8_idx0: + case AArch64::UMOVvi16_idx0: + case AArch64::UMOVvi32_idx0: + case AArch64::UMOVvi64_idx0: + MI.addOperand(MCOperand::createImm(0)); + break; } if (Result != MCDisassembler::Fail) diff --git a/llvm/test/MC/AArch64/SME/streaming-mode-neon-negative.s b/llvm/test/MC/AArch64/SME/streaming-mode-neon-negative.s --- a/llvm/test/MC/AArch64/SME/streaming-mode-neon-negative.s +++ b/llvm/test/MC/AArch64/SME/streaming-mode-neon-negative.s @@ -15,3 +15,158 @@ // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon // CHECK-NEXT: bfcvtn v5.4h, v5.4s // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// Check non-zero index is illegal in streaming mode +// ------------------------------------------------------------------------- // +// SMOV 8-bit to 32-bit + +smov w0, v0.b[1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov w0, v0.b[1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov w0, v0.b[7] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov w0, v0.b[7] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov w0, v0.b[15] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov w0, v0.b[15] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// SMOV 8-bit to 64-bit + +smov x0, v0.b[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.b[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov x0, v0.b[6] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.b[6] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov x0, v0.b[12] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.b[12] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// SMOV 16-bit to 32-bit + +smov w0, v0.h[1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov w0, v0.h[1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov w0, v0.h[3] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov w0, v0.h[3] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov w0, v0.h[7] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov w0, v0.h[7] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// SMOV 16-bit to 64-bit + +smov x0, v0.h[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.h[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov x0, v0.h[4] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.h[4] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov x0, v0.h[6] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.h[6] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// SMOV 32-bit to 64-bit + +smov x0, v0.s[1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.s[1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov x0, v0.s[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.s[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +smov x0, v0.s[3] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: smov x0, v0.s[3] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// UMOV 8-bit to 32-bit + +umov w0, v0.b[1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.b[1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +umov w0, v0.b[7] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.b[7] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +umov w0, v0.b[15] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.b[15] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// UMOV 16-bit to 32-bit + +umov w0, v0.h[1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.h[1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +umov w0, v0.h[3] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.h[3] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +umov w0, v0.h[7] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.h[7] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// ------------------------------------------------------------------------- // +// UMOV 32-bit to 32-bit + +umov w0, v0.s[1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.s[1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +umov w0, v0.s[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.s[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +umov w0, v0.s[3] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov w0, v0.s[3] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// ------------------------------------------------------------------------- // +// UMOV 64-bit to 64-bit + +umov x0, v0.d[1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: neon +// CHECK-NEXT: umov x0, v0.d[1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SME/streaming-mode-neon.s b/llvm/test/MC/AArch64/SME/streaming-mode-neon.s --- a/llvm/test/MC/AArch64/SME/streaming-mode-neon.s +++ b/llvm/test/MC/AArch64/SME/streaming-mode-neon.s @@ -71,3 +71,62 @@ // CHECK-INST: frsqrte d0, d1 // CHECK-ENCODING: [0x20,0xd8,0xe1,0x7e] // CHECK-ERROR: instruction requires: streaming-sve or neon + +// Vector to GPR integer move instructions + +smov w0, v0.b[0] +// CHECK-INST: smov w0, v0.b[0] +// CHECK-ENCODING: [0x00,0x2c,0x01,0x0e] +// CHECK-ERROR: instruction requires: neon + +smov x0, v0.b[0] +// CHECK-INST: smov x0, v0.b[0] +// CHECK-ENCODING: [0x00,0x2c,0x01,0x4e] +// CHECK-ERROR: instruction requires: neon + +smov w0, v0.h[0] +// CHECK-INST: smov w0, v0.h[0] +// CHECK-ENCODING: [0x00,0x2c,0x02,0x0e] +// CHECK-ERROR: instruction requires: neon + +smov x0, v0.h[0] +// CHECK-INST: smov x0, v0.h[0] +// CHECK-ENCODING: [0x00,0x2c,0x02,0x4e] +// CHECK-ERROR: instruction requires: neon + +smov x0, v0.s[0] +// CHECK-INST: smov x0, v0.s[0] +// CHECK-ENCODING: [0x00,0x2c,0x04,0x4e] +// CHECK-ERROR: instruction requires: neon + +umov w0, v0.b[0] +// CHECK-INST: umov w0, v0.b[0] +// CHECK-ENCODING: [0x00,0x3c,0x01,0x0e] +// CHECK-ERROR: instruction requires: neon + +umov w0, v0.h[0] +// CHECK-INST: umov w0, v0.h[0] +// CHECK-ENCODING: [0x00,0x3c,0x02,0x0e] +// CHECK-ERROR: instruction requires: neon + +umov w0, v0.s[0] +// CHECK-INST: mov w0, v0.s[0] +// CHECK-ENCODING: [0x00,0x3c,0x04,0x0e] +// CHECK-ERROR: instruction requires: neon + +umov x0, v0.d[0] +// CHECK-INST: mov x0, v0.d[0] +// CHECK-ENCODING: [0x00,0x3c,0x08,0x4e] +// CHECK-ERROR: instruction requires: neon + +// Aliases + +mov w0, v0.s[0] +// CHECK-INST: mov w0, v0.s[0] +// CHECK-ENCODING: [0x00,0x3c,0x04,0x0e] +// CHECK-ERROR: instruction requires: neon + +mov x0, v0.d[0] +// CHECK-INST: mov x0, v0.d[0] +// CHECK-ENCODING: [0x00,0x3c,0x08,0x4e] +// CHECK-ERROR: instruction requires: neon