diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -3759,4 +3759,7 @@ defm FMINNMQV : sve2p1_fp_reduction_q<0b101, "fminnmqv">; defm FMAXQV : sve2p1_fp_reduction_q<0b110, "fmaxqv">; defm FMINQV : sve2p1_fp_reduction_q<0b111, "fminqv">; -} + +defm DUPQ_ZZI : sve2p1_dupq<"dupq">; +def EXTQ_ZZI : sve2p1_extq<"extq">; +} // End HasSVE2p1_or_HasSME2p1 diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -9309,3 +9309,57 @@ def _S : sve2p1_fp_reduction_q<0b10, opc, mnemonic, ZPR32, "4s">; def _D : sve2p1_fp_reduction_q<0b11, opc, mnemonic, ZPR64, "2d">; } + + +// SVE Permute Vector - Quadwords (DUPQ) +class sve2p1_dupq ind_tsz, string mnemonic, ZPRRegOp zprty, Operand itype> + : I<(outs zprty:$Zd), (ins zprty:$Zn, itype:$index), + mnemonic, "\t$Zd, $Zn$index", + "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + let Inst{31-21} = 0b00000101001; + let Inst{20-16} = ind_tsz; + let Inst{15-10} = 0b001001; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve2p1_dupq { + def _B : sve2p1_dupq<{?, ?, ?, ?, 1}, mnemonic, ZPR8, VectorIndexB32b> { + bits<4> index; + let Inst{20-17} = index; + } + def _H : sve2p1_dupq<{?, ?, ?, 1, 0}, mnemonic, ZPR16, VectorIndexH32b> { + bits<3> index; + let Inst{20-18} = index; + } + def _S : sve2p1_dupq<{?, ?, 1, 0, 0}, mnemonic, ZPR32, VectorIndexS32b> { + bits<2> index; + let Inst{20-19} = index; + } + def _D : sve2p1_dupq<{?, 1, 0, 0, 0}, mnemonic, ZPR64, VectorIndexD32b> { + bits<1> index; + let Inst{20} = index; + } +} + + +// SVE Permute Vector - Quadwords (EXTQ) +class sve2p1_extq + : I<(outs ZPR8:$Zdn), (ins ZPR8:$_Zdn, ZPR8:$Zm, imm0_15:$imm4), + mnemonic, "\t$Zdn, $_Zdn, $Zm, $imm4", + "", []>, Sched<[]> { + bits<5> Zdn; + bits<5> Zm; + bits<4> imm4; + let Inst{31-20} = 0b000001010110; + let Inst{19-16} = imm4; + let Inst{15-10} = 0b001001; + let Inst{9-5} = Zm; + let Inst{4-0} = Zdn; + + let Constraints = "$Zdn = $_Zdn"; + let DestructiveInstType = DestructiveOther; + let ElementSize = ZPR8.ElementSize; +} diff --git a/llvm/test/MC/AArch64/SVE2p1/dupq-diagnostics.s b/llvm/test/MC/AArch64/SVE2p1/dupq-diagnostics.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/dupq-diagnostics.s @@ -0,0 +1,52 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 2>&1 < %s | FileCheck %s + +// --------------------------------------------------------------------------// +// Invalid vector lane index + +dupq z0.b, z0.b[16] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15]. +// CHECK-NEXT: dupq z0.b, z0.b[16] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dupq z0.b, z0.b[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15]. +// CHECK-NEXT: dupq z0.b, z0.b[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dupq z0.h, z0.h[8] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7]. +// CHECK-NEXT: dupq z0.h, z0.h[8] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dupq z0.h, z0.h[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7]. +// CHECK-NEXT: dupq z0.h, z0.h[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dupq z0.s, z0.s[4] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: dupq z0.s, z0.s[4] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dupq z0.s, z0.s[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: dupq z0.s, z0.s[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dupq z0.d, z0.d[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1]. +// CHECK-NEXT: dupq z0.d, z0.d[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dupq z0.d, z0.d[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1]. +// CHECK-NEXT: dupq z0.d, z0.d[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid vector suffix + +dupq z0.s, z0.h[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: dupq z0.s, z0.h[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2p1/dupq.s b/llvm/test/MC/AArch64/SVE2p1/dupq.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/dupq.s @@ -0,0 +1,115 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p1 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2p1 < %s \ +// RUN: | llvm-objdump -d --no-print-imm-hex --mattr=+sme2p1 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2p1 < %s \ +// RUN: | llvm-objdump -d --mattr=-sme2p1,-sve2p1 - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p1 < %s \ +// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \ +// RUN: | llvm-mc -triple=aarch64 -mattr=+sme2p1 -disassemble -show-encoding \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST + + +dupq z0.h, z0.h[0] // 00000101-00100010-00100100-00000000 +// CHECK-INST: dupq z0.h, z0.h[0] +// CHECK-ENCODING: [0x00,0x24,0x22,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05222400 + +dupq z21.h, z10.h[5] // 00000101-00110110-00100101-01010101 +// CHECK-INST: dupq z21.h, z10.h[5] +// CHECK-ENCODING: [0x55,0x25,0x36,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05362555 + +dupq z23.h, z13.h[2] // 00000101-00101010-00100101-10110111 +// CHECK-INST: dupq z23.h, z13.h[2] +// CHECK-ENCODING: [0xb7,0x25,0x2a,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 052a25b7 + +dupq z31.h, z31.h[7] // 00000101-00111110-00100111-11111111 +// CHECK-INST: dupq z31.h, z31.h[7] +// CHECK-ENCODING: [0xff,0x27,0x3e,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 053e27ff + + +dupq z0.s, z0.s[0] // 00000101-00100100-00100100-00000000 +// CHECK-INST: dupq z0.s, z0.s[0] +// CHECK-ENCODING: [0x00,0x24,0x24,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05242400 + +dupq z21.s, z10.s[2] // 00000101-00110100-00100101-01010101 +// CHECK-INST: dupq z21.s, z10.s[2] +// CHECK-ENCODING: [0x55,0x25,0x34,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05342555 + +dupq z23.s, z13.s[1] // 00000101-00101100-00100101-10110111 +// CHECK-INST: dupq z23.s, z13.s[1] +// CHECK-ENCODING: [0xb7,0x25,0x2c,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 052c25b7 + +dupq z31.s, z31.s[3] // 00000101-00111100-00100111-11111111 +// CHECK-INST: dupq z31.s, z31.s[3] +// CHECK-ENCODING: [0xff,0x27,0x3c,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 053c27ff + + +dupq z0.d, z0.d[0] // 00000101-00101000-00100100-00000000 +// CHECK-INST: dupq z0.d, z0.d[0] +// CHECK-ENCODING: [0x00,0x24,0x28,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05282400 + +dupq z21.d, z10.d[1] // 00000101-00111000-00100101-01010101 +// CHECK-INST: dupq z21.d, z10.d[1] +// CHECK-ENCODING: [0x55,0x25,0x38,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05382555 + +dupq z23.d, z13.d[0] // 00000101-00101000-00100101-10110111 +// CHECK-INST: dupq z23.d, z13.d[0] +// CHECK-ENCODING: [0xb7,0x25,0x28,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 052825b7 + +dupq z31.d, z31.d[1] // 00000101-00111000-00100111-11111111 +// CHECK-INST: dupq z31.d, z31.d[1] +// CHECK-ENCODING: [0xff,0x27,0x38,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 053827ff + + +dupq z0.b, z0.b[0] // 00000101-00100001-00100100-00000000 +// CHECK-INST: dupq z0.b, z0.b[0] +// CHECK-ENCODING: [0x00,0x24,0x21,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05212400 + +dupq z21.b, z10.b[10] // 00000101-00110101-00100101-01010101 +// CHECK-INST: dupq z21.b, z10.b[10] +// CHECK-ENCODING: [0x55,0x25,0x35,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05352555 + +dupq z23.b, z13.b[4] // 00000101-00101001-00100101-10110111 +// CHECK-INST: dupq z23.b, z13.b[4] +// CHECK-ENCODING: [0xb7,0x25,0x29,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 052925b7 + +dupq z31.b, z31.b[15] // 00000101-00111111-00100111-11111111 +// CHECK-INST: dupq z31.b, z31.b[15] +// CHECK-ENCODING: [0xff,0x27,0x3f,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 053f27ff + diff --git a/llvm/test/MC/AArch64/SVE2p1/extq-diagnostics.s b/llvm/test/MC/AArch64/SVE2p1/extq-diagnostics.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/extq-diagnostics.s @@ -0,0 +1,22 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 2>&1 < %s | FileCheck %s + +// --------------------------------------------------------------------------// +// Invalid immediate + +extq z23.b, z23.b, z13.b, #16 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15]. +// CHECK-NEXT: extq z23.b, z23.b, z13.b, #16 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +extq z23.b, z23.b, z13.b, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15]. +// CHECK-NEXT: extq z23.b, z23.b, z13.b, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid vector suffix + +extq z23.h, z23.h, z13.h, #7 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: extq z23.h, z23.h, z13.h, #7 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2p1/extq.s b/llvm/test/MC/AArch64/SVE2p1/extq.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/extq.s @@ -0,0 +1,48 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p1 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2p1 < %s \ +// RUN: | llvm-objdump -d --no-print-imm-hex --mattr=+sme2p1 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2p1 < %s \ +// RUN: | llvm-objdump -d --mattr=-sme2p1,-sve2p1 - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p1 < %s \ +// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \ +// RUN: | llvm-mc -triple=aarch64 -mattr=+sme2p1 -disassemble -show-encoding \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST + + +movprfx z23, z31 +extq z23.b, z23.b, z13.b, #8 // 00000101-01101000-00100101-10110111 +// CHECK-INST: movprfx z23, z31 +// CHECK-INST: extq z23.b, z23.b, z13.b, #8 +// CHECK-ENCODING: [0xb7,0x25,0x68,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 056825b7 + +extq z0.b, z0.b, z0.b, #0 // 00000101-01100000-00100100-00000000 +// CHECK-INST: extq z0.b, z0.b, z0.b, #0 +// CHECK-ENCODING: [0x00,0x24,0x60,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05602400 + +extq z21.b, z21.b, z10.b, #5 // 00000101-01100101-00100101-01010101 +// CHECK-INST: extq z21.b, z21.b, z10.b, #5 +// CHECK-ENCODING: [0x55,0x25,0x65,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 05652555 + +extq z23.b, z23.b, z13.b, #8 // 00000101-01101000-00100101-10110111 +// CHECK-INST: extq z23.b, z23.b, z13.b, #8 +// CHECK-ENCODING: [0xb7,0x25,0x68,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 056825b7 + +extq z31.b, z31.b, z31.b, #15 // 00000101-01101111-00100111-11111111 +// CHECK-INST: extq z31.b, z31.b, z31.b, #15 +// CHECK-ENCODING: [0xff,0x27,0x6f,0x05] +// CHECK-ERROR: instruction requires: sme2p1 or sve2p1 +// CHECK-UNKNOWN: 056f27ff +