Index: lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64SVEInstrInfo.td +++ lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1348,6 +1348,9 @@ defm LDNT1W_ZZR_D : sve2_mem_cldnt_vs<0b11010, "ldnt1w", Z_d, ZPR64>; defm LDNT1D_ZZR_D : sve2_mem_cldnt_vs<0b11110, "ldnt1d", Z_d, ZPR64>; + // SVE2 vector splice (constructive) + defm SPLICE_ZPZZ : sve2_int_perm_splice_cons<"splice">; + // Predicated shifts defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; defm UQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0111, "uqshl">; Index: lib/Target/AArch64/SVEInstrFormats.td =================================================================== --- lib/Target/AArch64/SVEInstrFormats.td +++ lib/Target/AArch64/SVEInstrFormats.td @@ -4275,6 +4275,30 @@ def _D : sve_int_perm_splice<0b11, asm, ZPR64>; } +class sve2_int_perm_splice_cons sz8_64, string asm, + ZPRRegOp zprty, RegisterOperand VecList> +: I<(outs zprty:$Zd), (ins PPR3bAny:$Pg, VecList:$Zn), + asm, "\t$Zd, $Pg, $Zn", + "", + []>, Sched<[]> { + bits<3> Pg; + bits<5> Zn; + bits<5> Zd; + let Inst{31-24} = 0b00000101; + let Inst{23-22} = sz8_64; + let Inst{21-13} = 0b101101100; + let Inst{12-10} = Pg; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve2_int_perm_splice_cons { + def _B : sve2_int_perm_splice_cons<0b00, asm, ZPR8, ZZ_b>; + def _H : sve2_int_perm_splice_cons<0b01, asm, ZPR16, ZZ_h>; + def _S : sve2_int_perm_splice_cons<0b10, asm, ZPR32, ZZ_s>; + def _D : sve2_int_perm_splice_cons<0b11, asm, ZPR64, ZZ_d>; +} + class sve_int_perm_rev sz8_64, bits<2> opc, string asm, ZPRRegOp zprty> : I<(outs zprty:$Zd), (ins zprty:$_Zd, PPR3bAny:$Pg, zprty:$Zn), Index: test/MC/AArch64/SVE2/splice-diagnostics.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE2/splice-diagnostics.s @@ -0,0 +1,83 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element widths. + +splice z0.b, p0, { z1.h, z2.h } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: splice z0.b, p0, { z1.h, z2.h } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +splice z0.b, p0, { } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: splice z0.b, p0, { } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +splice z0.b, p0, { z1.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: splice z0.b, p0, { z1.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +splice z0.b, p0, { z1.b, z2.b, z3.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: splice z0.b, p0, { z1.b, z2.b, z3.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +splice z0.b, p0, { z1.b, z2.h } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: splice z0.b, p0, { z1.b, z2.h } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +splice z0.b, p0, { z1.b, z31.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: splice z0.b, p0, { z1.b, z31.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +splice z0.b, p0, { v0.4b, v1.4b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: splice z0.b, p0, { v0.4b, v1.4b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate operation + +splice z0.b, p0/z, { z1.b, z2.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: splice z0.b, p0/z, { z1.b, z2.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +splice z0.b, p0/m, { z1.b, z2.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: splice z0.b, p0/m, { z1.b, z2.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Predicate not in restricted predicate range + +splice z0.b, p8, { z1.b, z2.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7] +// CHECK-NEXT: splice z0.b, p8, { z1.b, z2.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +splice z31.b, p0, { z30.b, z31.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: splice z31.b, p0, { z30.b, z31.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31.b, p0/z, z6.b +splice z31.b, p0, { z30.b, z31.b } +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: splice z31.b, p0, { z30.b, z31.b } +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE2/splice.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE2/splice.s @@ -0,0 +1,32 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %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=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +splice z29.b, p7, { z30.b, z31.b } +// CHECK-INST: splice z29.b, p7, { z30.b, z31.b } +// CHECK-ENCODING: [0xdd,0x9f,0x2d,0x05] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 2d 05 + +splice z29.h, p7, { z30.h, z31.h } +// CHECK-INST: splice z29.h, p7, { z30.h, z31.h } +// CHECK-ENCODING: [0xdd,0x9f,0x6d,0x05] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 6d 05 + +splice z29.s, p7, { z30.s, z31.s } +// CHECK-INST: splice z29.s, p7, { z30.s, z31.s } +// CHECK-ENCODING: [0xdd,0x9f,0xad,0x05] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f ad 05 + +splice z29.d, p7, { z30.d, z31.d } +// CHECK-INST: splice z29.d, p7, { z30.d, z31.d } +// CHECK-ENCODING: [0xdd,0x9f,0xed,0x05] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f ed 05