From 486c34b48d07ca34e8c4af71a01de01fb53267ba Mon Sep 17 00:00:00 2001 From: Jonathan Thackray Date: Fri, 5 Sep 2025 23:50:38 +0100 Subject: [PATCH] [AArch64][llvm] Armv9.7-A: Add support for SVE2p3 shift operations Add instructions for SVE2p3 shift operations: - SQRSHRN - SQRSHRUN - SQSHRN - SQSHRUN - UQRSHRN - UQSHRN as documented here: * https://developer.arm.com/documentation/ddi0602/2025-09/ * https://developer.arm.com/documentation/109697/2025_09/2025-Architecture-Extensions --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 17 +- llvm/lib/Target/AArch64/SVEInstrFormats.td | 22 +- .../MC/AArch64/SVE2p3/qshrn-diagnostics.s | 266 ++++++++++++++++++ llvm/test/MC/AArch64/SVE2p3/qshrn.s | 255 +++++++++++++++++ 4 files changed, 550 insertions(+), 10 deletions(-) create mode 100644 llvm/test/MC/AArch64/SVE2p3/qshrn-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2p3/qshrn.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 992b143f16fba..7af4e9c0d7972 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -4272,9 +4272,9 @@ def : Pat<(nxv4i32 (partial_reduce_smla nxv4i32:$Acc, nxv8i16:$MulLHS, nxv8i16:$ defm SQCVTN_Z2Z_StoH : sve2p1_multi_vec_extract_narrow<"sqcvtn", 0b00, int_aarch64_sve_sqcvtn_x2>; defm UQCVTN_Z2Z_StoH : sve2p1_multi_vec_extract_narrow<"uqcvtn", 0b01, int_aarch64_sve_uqcvtn_x2>; defm SQCVTUN_Z2Z_StoH : sve2p1_multi_vec_extract_narrow<"sqcvtun", 0b10, int_aarch64_sve_sqcvtun_x2>; -defm SQRSHRN_Z2ZI_StoH : sve2p1_multi_vec_shift_narrow<"sqrshrn", 0b101, int_aarch64_sve_sqrshrn_x2>; -defm UQRSHRN_Z2ZI_StoH : sve2p1_multi_vec_shift_narrow<"uqrshrn", 0b111, int_aarch64_sve_uqrshrn_x2>; -defm SQRSHRUN_Z2ZI_StoH : sve2p1_multi_vec_shift_narrow<"sqrshrun", 0b001, int_aarch64_sve_sqrshrun_x2>; +defm SQRSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqrshrn", 0b101, int_aarch64_sve_sqrshrn_x2>; +defm UQRSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"uqrshrn", 0b111, int_aarch64_sve_uqrshrn_x2>; +defm SQRSHRUN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqrshrun", 0b001, int_aarch64_sve_sqrshrun_x2>; defm WHILEGE_2PXX : sve2p1_int_while_rr_pair<"whilege", 0b000>; defm WHILEGT_2PXX : sve2p1_int_while_rr_pair<"whilegt", 0b001>; @@ -4648,6 +4648,17 @@ let Predicates = [HasSVE2p3_or_SME2p3] in { defm SCVTFLT_ZZ : sve2_int_to_fp_upcvt<"scvtflt", 0b10>; defm UCVTF_ZZ : sve2_int_to_fp_upcvt<"ucvtf", 0b01>; defm UCVTFLT_ZZ : sve2_int_to_fp_upcvt<"ucvtflt", 0b11>; + + // SVE2 saturating shift right narrow by immediate and interleave + defm SQRSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqrshrn", 0b101>; + defm SQRSHRUN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqrshrun", 0b001>; + defm SQSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqshrn", 0b000>; + defm SQSHRUN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqshrun", 0b100>; + defm UQRSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"uqrshrn", 0b111>; + defm UQSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"uqshrn", 0b010>; + defm SQSHRUN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqshrun", 0b100, null_frag>; + defm SQSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqshrn", 0b000, null_frag>; + defm UQSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"uqshrn", 0b010, null_frag>; } // End HasSME2p3orSVE2p3 //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 3255d8e6cbe74..68ca454357adf 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -10050,18 +10050,19 @@ multiclass sve2p1_multi_vec_extract_narrow opc, SDPatte } // SVE2 multi-vec shift narrow -class sve2p1_multi_vec_shift_narrow opc, bits<2> tsz> - : I<(outs ZPR16:$Zd), (ins ZZ_s_mul_r:$Zn, vecshiftR16:$imm4), - mnemonic, "\t$Zd, $Zn, $imm4", +class sve2p1_multi_vec_shift_narrow opc, bits<2> tsz> + : I<(outs ZdRC:$Zd), (ins ZSrcOp:$Zn, immtype:$imm), + mnemonic, "\t$Zd, $Zn, $imm", "", []>, Sched<[]> { bits<5> Zd; bits<4> Zn; - bits<4> imm4; + bits<4> imm; let Inst{31-23} = 0b010001011; let Inst{22} = tsz{1}; let Inst{21} = 0b1; let Inst{20} = tsz{0}; - let Inst{19-16} = imm4; + let Inst{18-16} = imm{2-0}; // imm3 let Inst{15-14} = 0b00; let Inst{13-11} = opc; let Inst{10} = 0b0; @@ -10072,12 +10073,19 @@ class sve2p1_multi_vec_shift_narrow opc, bits<2> tsz> let hasSideEffects = 0; } -multiclass sve2p1_multi_vec_shift_narrow opc, SDPatternOperator intrinsic> { - def NAME : sve2p1_multi_vec_shift_narrow; +multiclass sve_multi_vec_shift_narrow opc, SDPatternOperator intrinsic> { + def NAME : sve2p1_multi_vec_shift_narrow { + let Inst{19} = imm{3}; // imm4 + } def : SVE2p1_Sat_Shift_VG2_Pat; } +multiclass sve_multi_vec_round_shift_narrow opc> { + def NAME : sve2p1_multi_vec_shift_narrow { + let Inst{19} = 0b1; // always 1 for imm3 version + } +} // SME2 multi-vec contiguous load (scalar plus scalar, two registers) class sve2p1_mem_cld_ss_2z msz, bit n, diff --git a/llvm/test/MC/AArch64/SVE2p3/qshrn-diagnostics.s b/llvm/test/MC/AArch64/SVE2p3/qshrn-diagnostics.s new file mode 100644 index 0000000000000..85add58429237 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p3/qshrn-diagnostics.s @@ -0,0 +1,266 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Invalid element width + +sqrshrn z10.s, { z0.s, z1.s }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrn z10.s, { z0.s, z1.s }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrn z10.d, { z0.d, z1.d }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrn z10.d, { z0.d, z1.d }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid operand for instruction + +sqrshrn z10.h, { z0.b, z1.b }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqrshrn z10.h, { z0.b, z1.b }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Intermediate out of range + +sqrshrn z10.b, { z0.h, z1.h }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqrshrn z10.b, { z0.h, z1.h }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrn z10.b, { z0.h, z1.h }, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqrshrn z10.b, { z0.h, z1.h }, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqrshrn z10.b, { z0.h, z1.h }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqrshrn z10.b, { z0.h, z1.h }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +sqrshrun z10.s, { z0.s, z1.s }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrun z10.s, { z0.s, z1.s }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrun z10.d, { z0.d, z1.d }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrun z10.d, { z0.d, z1.d }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid operand for instruction + +sqrshrun z10.h, { z0.b, z1.b }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqrshrun z10.h, { z0.b, z1.b }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Intermediate out of range + +sqrshrun z10.b, { z0.h, z1.h }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqrshrun z10.b, { z0.h, z1.h }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrun z10.b, { z0.h, z1.h }, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqrshrun z10.b, { z0.h, z1.h }, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqrshrun z10.b, { z0.h, z1.h }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqrshrun z10.b, { z0.h, z1.h }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +sqshrn z10.s, { z0.s, z1.s }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrn z10.s, { z0.s, z1.s }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrn z10.d, { z0.d, z1.d }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrn z10.d, { z0.d, z1.d }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Intermediate out of range + +sqshrn z10.b, { z0.h, z1.h }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqshrn z10.b, { z0.h, z1.h }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrn z10.b, { z0.h, z1.h }, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqshrn z10.b, { z0.h, z1.h }, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrn z0.h, { z0.s, z1.s }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]. +// CHECK-NEXT: sqshrn z0.h, { z0.s, z1.s }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrn z0.h, { z0.s, z1.s }, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]. +// CHECK-NEXT: sqshrn z0.h, { z0.s, z1.s }, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqshrn z10.b, { z0.h, z1.h }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqshrn z10.b, { z0.h, z1.h }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +sqshrun z10.s, { z0.s, z1.s }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrun z10.s, { z0.s, z1.s }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrun z10.d, { z0.d, z1.d }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrun z10.d, { z0.d, z1.d }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Intermediate out of range + +sqshrun z10.b, { z0.h, z1.h }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqshrun z10.b, { z0.h, z1.h }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrun z10.b, { z0.h, z1.h }, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: sqshrun z10.b, { z0.h, z1.h }, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrun z10.h, { z0.s, z1.s }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]. +// CHECK-NEXT: sqshrun z10.h, { z0.s, z1.s }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrun z10.h, { z0.s, z1.s }, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]. +// CHECK-NEXT: sqshrun z10.h, { z0.s, z1.s }, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqshrun z10.b, { z0.h, z1.h }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqshrun z10.b, { z0.h, z1.h }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +uqrshrn z10.s, { z0.s, z1.s }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrn z10.s, { z0.s, z1.s }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrn z10.d, { z0.d, z1.d }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrn z10.d, { z0.d, z1.d }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid operand for instruction + +uqrshrn z10.h, { z0.b, z1.b }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqrshrn z10.h, { z0.b, z1.b }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Intermediate out of range + +uqrshrn z10.b, { z0.h, z1.h }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: uqrshrn z10.b, { z0.h, z1.h }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrn z10.b, { z0.h, z1.h }, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: uqrshrn z10.b, { z0.h, z1.h }, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +uqrshrn z10.b, { z0.h, z1.h }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqrshrn z10.b, { z0.h, z1.h }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +uqshrn z10.s, { z0.s, z1.s }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrn z10.s, { z0.s, z1.s }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrn z10.d, { z0.d, z1.d }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrn z10.d, { z0.d, z1.d }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Intermediate out of range + +uqshrn z10.b, { z0.h, z1.h }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: uqshrn z10.b, { z0.h, z1.h }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrn z10.b, { z0.h, z1.h }, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8]. +// CHECK-NEXT: uqshrn z10.b, { z0.h, z1.h }, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrn z0.h, { z0.s, z1.s }, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]. +// CHECK-NEXT: uqshrn z0.h, { z0.s, z1.s }, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrn z0.h, { z0.s, z1.s }, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]. +// CHECK-NEXT: uqshrn z0.h, { z0.s, z1.s }, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +uqshrn z10.b, { z0.h, z1.h }, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqshrn z10.b, { z0.h, z1.h }, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2p3/qshrn.s b/llvm/test/MC/AArch64/SVE2p3/qshrn.s new file mode 100644 index 0000000000000..31c87cf342671 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p3/qshrn.s @@ -0,0 +1,255 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p3 < %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=+sve2p3 < %s \ +// RUN: | llvm-objdump -d --mattr=+sve2p3 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2p3 < %s \ +// RUN: | llvm-objdump -d --mattr=-sve2p3 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// Disassemble encoding and check the re-encoding (-show-encoding) matches. +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 < %s \ +// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \ +// RUN: | llvm-mc -triple=aarch64 -mattr=+sve2p3 -disassemble -show-encoding \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST + +// ----------------------------------------------------------------- +// Signed saturating rounding shift right narrow by immediate and interleave + +sqrshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-INST: sqrshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-ENCODING: encoding: [0x00,0x28,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af2800 + +sqrshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-INST: sqrshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x2b,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af2bdf + +sqrshrn z0.b, { z0.h, z1.h }, #8 +// CHECK-INST: sqrshrn z0.b, { z0.h, z1.h }, #8 +// CHECK-ENCODING: encoding: [0x00,0x28,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a82800 + +sqrshrn z31.b, { z30.h, z31.h }, #3 +// CHECK-INST: sqrshrn z31.b, { z30.h, z31.h }, #3 +// CHECK-ENCODING: encoding: [0xdf,0x2b,0xad,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45ad2bdf + +// ----------------------------------------------------------------- +// Signed saturating rounding shift right unsigned narrow by immediate and interleave + +sqrshrun z0.b, { z0.h, z1.h }, #1 +// CHECK-INST: sqrshrun z0.b, { z0.h, z1.h }, #1 +// CHECK-ENCODING: encoding: [0x00,0x08,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af0800 + +sqrshrun z31.b, { z30.h, z31.h }, #1 +// CHECK-INST: sqrshrun z31.b, { z30.h, z31.h }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x0b,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af0bdf + +sqrshrun z0.b, { z0.h, z1.h }, #8 +// CHECK-INST: sqrshrun z0.b, { z0.h, z1.h }, #8 +// CHECK-ENCODING: encoding: [0x00,0x08,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a80800 + +sqrshrun z31.b, { z30.h, z31.h }, #8 +// CHECK-INST: sqrshrun z31.b, { z30.h, z31.h }, #8 +// CHECK-ENCODING: encoding: [0xdf,0x0b,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a80bdf + +// ----------------------------------------------------------------- +// Signed saturating shift right narrow by immediate and interleave + +sqshrn z21.b, { z30.h, z31.h }, #1 +// CHECK-INST: sqshrn z21.b, { z30.h, z31.h }, #1 +// CHECK-ENCODING: encoding: [0xd5,0x03,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af03d5 + +sqshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-INST: sqshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x03,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af03df + +sqshrn z10.b, { z0.h, z1.h }, #8 +// CHECK-INST: sqshrn z10.b, { z0.h, z1.h }, #8 +// CHECK-ENCODING: encoding: [0x0a,0x00,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a8000a + +sqshrn z31.b, { z30.h, z31.h }, #8 +// CHECK-INST: sqshrn z31.b, { z30.h, z31.h }, #8 +// CHECK-ENCODING: encoding: [0xdf,0x03,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a803df + +sqshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-INST: sqshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-ENCODING: encoding: [0x00,0x00,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af0000 + +sqshrn z0.h, { z0.s, z1.s }, #1 +// CHECK-INST: sqshrn z0.h, { z0.s, z1.s }, #1 +// CHECK-ENCODING: encoding: [0x00,0x00,0xbf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45bf0000 + +sqshrn z31.h, { z30.s, z31.s }, #1 +// CHECK-INST: sqshrn z31.h, { z30.s, z31.s }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x03,0xbf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45bf03df + +sqshrn z0.h, { z0.s, z1.s }, #16 +// CHECK-INST: sqshrn z0.h, { z0.s, z1.s }, #16 +// CHECK-ENCODING: encoding: [0x00,0x00,0xb0,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45b00000 + +sqshrn z31.h, { z30.s, z31.s }, #16 +// CHECK-INST: sqshrn z31.h, { z30.s, z31.s }, #16 +// CHECK-ENCODING: encoding: [0xdf,0x03,0xb0,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45b003df + +// ----------------------------------------------------------------- +// Signed saturating shift right unsigned narrow by immediate and interleave + +sqshrun z0.b, { z0.h, z1.h }, #1 +// CHECK-INST: sqshrun z0.b, { z0.h, z1.h }, #1 +// CHECK-ENCODING: encoding: [0x00,0x20,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af2000 + +sqshrun z31.b, { z30.h, z31.h }, #1 +// CHECK-INST: sqshrun z31.b, { z30.h, z31.h }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x23,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af23df + +sqshrun z0.b, { z0.h, z1.h }, #8 +// CHECK-INST: sqshrun z0.b, { z0.h, z1.h }, #8 +// CHECK-ENCODING: encoding: [0x00,0x20,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a82000 + +sqshrun z31.b, { z30.h, z31.h }, #8 +// CHECK-INST: sqshrun z31.b, { z30.h, z31.h }, #8 +// CHECK-ENCODING: encoding: [0xdf,0x23,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a823df + +sqshrun z0.h, { z0.s, z1.s }, #1 +// CHECK-INST: sqshrun z0.h, { z0.s, z1.s }, #1 +// CHECK-ENCODING: encoding: [0x00,0x20,0xbf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45bf2000 + +sqshrun z31.h, { z30.s, z31.s }, #1 +// CHECK-INST: sqshrun z31.h, { z30.s, z31.s }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x23,0xbf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45bf23df + +sqshrun z0.h, { z0.s, z1.s }, #16 +// CHECK-INST: sqshrun z0.h, { z0.s, z1.s }, #16 +// CHECK-ENCODING: encoding: [0x00,0x20,0xb0,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45b02000 + +sqshrun z31.h, { z30.s, z31.s }, #16 +// CHECK-INST: sqshrun z31.h, { z30.s, z31.s }, #16 +// CHECK-ENCODING: encoding: [0xdf,0x23,0xb0,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45b023df + +// ----------------------------------------------------------------- +// Unsigned saturating rounding shift right narrow by immediate and interleave + +uqrshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-INST: uqrshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-ENCODING: encoding: [0x00,0x38,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af3800 + +uqrshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-INST: uqrshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x3b,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af3bdf + +uqrshrn z0.b, { z0.h, z1.h }, #8 +// CHECK-INST: uqrshrn z0.b, { z0.h, z1.h }, #8 +// CHECK-ENCODING: encoding: [0x00,0x38,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a83800 + +uqrshrn z31.b, { z30.h, z31.h }, #8 +// CHECK-INST: uqrshrn z31.b, { z30.h, z31.h }, #8 +// CHECK-ENCODING: encoding: [0xdf,0x3b,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a83bdf + +// ----------------------------------------------------------------- +// Unsigned saturating shift right narrow by immediate and interleave + +uqshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-INST: uqshrn z0.b, { z0.h, z1.h }, #1 +// CHECK-ENCODING: encoding: [0x00,0x10,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af1000 + +uqshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-INST: uqshrn z31.b, { z30.h, z31.h }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x13,0xaf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45af13df + +uqshrn z0.b, { z0.h, z1.h }, #8 +// CHECK-INST: uqshrn z0.b, { z0.h, z1.h }, #8 +// CHECK-ENCODING: encoding: [0x00,0x10,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a81000 + +uqshrn z31.b, { z30.h, z31.h }, #8 +// CHECK-INST: uqshrn z31.b, { z30.h, z31.h }, #8 +// CHECK-ENCODING: encoding: [0xdf,0x13,0xa8,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45a813df + +uqshrn z0.h, { z0.s, z1.s }, #1 +// CHECK-INST: uqshrn z0.h, { z0.s, z1.s }, #1 +// CHECK-ENCODING: encoding: [0x00,0x10,0xbf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45bf1000 + +uqshrn z31.h, { z30.s, z31.s }, #1 +// CHECK-INST: uqshrn z31.h, { z30.s, z31.s }, #1 +// CHECK-ENCODING: encoding: [0xdf,0x13,0xbf,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45bf13df + +uqshrn z0.h, { z0.s, z1.s }, #16 +// CHECK-INST: uqshrn z0.h, { z0.s, z1.s }, #16 +// CHECK-ENCODING: encoding: [0x00,0x10,0xb0,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45b01000 + +uqshrn z31.h, { z30.s, z31.s }, #16 +// CHECK-INST: uqshrn z31.h, { z30.s, z31.s }, #16 +// CHECK-ENCODING: encoding: [0xdf,0x13,0xb0,0x45] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 45b013df