Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down Expand Up @@ -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

//===----------------------------------------------------------------------===//
Expand Down
22 changes: 15 additions & 7 deletions llvm/lib/Target/AArch64/SVEInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -10050,18 +10050,19 @@ multiclass sve2p1_multi_vec_extract_narrow<string mnemonic, bits<2> opc, SDPatte
}

// SVE2 multi-vec shift narrow
class sve2p1_multi_vec_shift_narrow<string mnemonic, bits<3> 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<string mnemonic, ZPRRegOp ZdRC, RegisterOperand ZSrcOp,
Operand immtype, bits<3> 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;
Expand All @@ -10072,12 +10073,19 @@ class sve2p1_multi_vec_shift_narrow<string mnemonic, bits<3> opc, bits<2> tsz>
let hasSideEffects = 0;
}

multiclass sve2p1_multi_vec_shift_narrow<string mnemonic, bits<3> opc, SDPatternOperator intrinsic> {
def NAME : sve2p1_multi_vec_shift_narrow<mnemonic, opc, 0b01>;
multiclass sve_multi_vec_shift_narrow<string mnemonic, bits<3> opc, SDPatternOperator intrinsic> {
def NAME : sve2p1_multi_vec_shift_narrow<mnemonic, ZPR16, ZZ_s_mul_r, vecshiftR16, opc, 0b01> {
let Inst{19} = imm{3}; // imm4
}

def : SVE2p1_Sat_Shift_VG2_Pat<NAME, intrinsic, nxv8i16, nxv4i32, vecshiftR16>;
}

multiclass sve_multi_vec_round_shift_narrow<string mnemonic, bits<3> opc> {
def NAME : sve2p1_multi_vec_shift_narrow<mnemonic, ZPR8, ZZ_h_mul_r, vecshiftR8, opc, 0b00> {
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<string mnemonic, bits<2> msz, bit n,
Expand Down
266 changes: 266 additions & 0 deletions llvm/test/MC/AArch64/SVE2p3/qshrn-diagnostics.s
Original file line number Diff line number Diff line change
@@ -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]+}}:
Loading
Loading