; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -mattr=+sme-i16i64 -mattr=+sme-f64f64 -verify-machineinstrs < %s | FileCheck %s

;
; SUB Multi-Single x2
;

define void @multi_vector_sub_write_single_za_vg1x2_i32(i32 %slice, <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,  <vscale x 4 x i32> %zm) {
; CHECK-LABEL: multi_vector_sub_write_single_za_vg1x2_i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    sub za.s[w8, 0, vgx2], { z0.s, z1.s }, z2.s
; CHECK-NEXT:    sub za.s[w8, 7, vgx2], { z0.s, z1.s }, z2.s
; CHECK-NEXT:    ret
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x2.nxv4i32(i32 %slice,
                                                       <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                       <vscale x 4 x i32> %zm)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x2.nxv4i32(i32 %slice.7,
                                                       <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                       <vscale x 4 x i32> %zm)
  ret void
}

define void @multi_vector_sub_write_single_za_vg1x2_i64(i32 %slice, <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,  <vscale x 2 x i64> %zm) {
; CHECK-LABEL: multi_vector_sub_write_single_za_vg1x2_i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    sub za.d[w8, 0, vgx2], { z0.d, z1.d }, z2.d
; CHECK-NEXT:    sub za.d[w8, 7, vgx2], { z0.d, z1.d }, z2.d
; CHECK-NEXT:    ret
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x2.nxv2i64(i32 %slice,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zm)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x2.nxv2i64(i32 %slice.7,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zm)
  ret void
}

;
; SUB Multi-Single x4
;

define void @multi_vector_sub_write_single_za_vg1x4_i32(i32 %slice, <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
; CHECK-LABEL: multi_vector_sub_write_single_za_vg1x4_i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    sub za.s[w8, 0, vgx4], { z0.s - z3.s }, z4.s
; CHECK-NEXT:    sub za.s[w8, 7, vgx4], { z0.s - z3.s }, z4.s
; CHECK-NEXT:    ret
                                               <vscale x 4 x i32> %zn2, <vscale x 4 x i32> %zn3,
                                               <vscale x 4 x i32> %zm) {
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x4.nxv4i32(i32 %slice,
                                                       <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                       <vscale x 4 x i32> %zn2, <vscale x 4 x i32> %zn3,
                                                       <vscale x 4 x i32> %zm)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x4.nxv4i32(i32 %slice.7,
                                                       <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                       <vscale x 4 x i32> %zn2, <vscale x 4 x i32> %zn3,
                                                       <vscale x 4 x i32> %zm)
  ret void
}

define void @multi_vector_sub_write_single_za_vg1x4_i64(i32 %slice,
; CHECK-LABEL: multi_vector_sub_write_single_za_vg1x4_i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    sub za.d[w8, 0, vgx4], { z0.d - z3.d }, z4.d
; CHECK-NEXT:    sub za.d[w8, 7, vgx4], { z0.d - z3.d }, z4.d
; CHECK-NEXT:    ret
                                               <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                               <vscale x 2 x i64> %zn2, <vscale x 2 x i64> %zn3,
                                               <vscale x 2 x i64> %zm) {
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x4.nxv2i64(i32 %slice,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zn2, <vscale x 2 x i64> %zn3,
                                                       <vscale x 2 x i64> %zm)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.single.za.vg1x4.nxv2i64(i32 %slice.7,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zn2, <vscale x 2 x i64> %zn3,
                                                       <vscale x 2 x i64> %zm)
  ret void
}

;
; SUB Multi-Multi x2
;

define void @multi_vector_sub_write_za_vg1x2_i32(i32 %slice, <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
; CHECK-LABEL: multi_vector_sub_write_za_vg1x2_i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z3 killed $z3 killed $z2_z3 def $z2_z3
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    // kill: def $z2 killed $z2 killed $z2_z3 def $z2_z3
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    sub za.s[w8, 0, vgx2], { z0.s, z1.s }, { z2.s, z3.s }
; CHECK-NEXT:    sub za.s[w8, 7, vgx2], { z0.s, z1.s }, { z2.s, z3.s }
; CHECK-NEXT:    ret
                                        <vscale x 4 x i32> %zm1, <vscale x 4 x i32> %zm2) {
  call void @llvm.aarch64.sme.sub.write.za.vg1x2.nxv4i32(i32 %slice,
                                                       <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                       <vscale x 4 x i32> %zm1, <vscale x 4 x i32> %zm2)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.za.vg1x2.nxv4i32(i32 %slice.7,
                                                       <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                       <vscale x 4 x i32> %zm1, <vscale x 4 x i32> %zm2)
  ret void
}


define void @multi_vector_sub_write_za_vg1x2_i64(i32 %slice, <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
; CHECK-LABEL: multi_vector_sub_write_za_vg1x2_i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z3 killed $z3 killed $z2_z3 def $z2_z3
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    // kill: def $z2 killed $z2 killed $z2_z3 def $z2_z3
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1
; CHECK-NEXT:    sub za.d[w8, 0, vgx2], { z0.d, z1.d }, { z2.d, z3.d }
; CHECK-NEXT:    sub za.d[w8, 7, vgx2], { z0.d, z1.d }, { z2.d, z3.d }
; CHECK-NEXT:    ret
                                        <vscale x 2 x i64> %zm1, <vscale x 2 x i64> %zm2) {
  call void @llvm.aarch64.sme.sub.write.za.vg1x2.nxv2i64(i32 %slice,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zm1, <vscale x 2 x i64> %zm2)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.za.vg1x2.nxv2i64(i32 %slice.7,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zm1, <vscale x 2 x i64> %zm2)
  ret void
}


;
; SUB Multi-Multi x4
;

define void @multi_vector_sub_write_za_vg1x4_i32(i32 %slice, <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
; CHECK-LABEL: multi_vector_sub_write_za_vg1x4_i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $z7 killed $z7 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z6 killed $z6 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z5 killed $z5 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z4 killed $z4 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    sub za.s[w8, 0, vgx4], { z0.s - z3.s }, { z4.s - z7.s }
; CHECK-NEXT:    sub za.s[w8, 7, vgx4], { z0.s - z3.s }, { z4.s - z7.s }
; CHECK-NEXT:    ret
                                        <vscale x 4 x i32> %zn2, <vscale x 4 x i32> %zn3,
                                        <vscale x 4 x i32> %zm0, <vscale x 4 x i32> %zm1,
                                        <vscale x 4 x i32> %zm2, <vscale x 4 x i32> %zm3) {
  call void @llvm.aarch64.sme.sub.write.za.vg1x4.nxv4i32(i32 %slice,
                                                      <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                      <vscale x 4 x i32> %zn2, <vscale x 4 x i32> %zn3,
                                                      <vscale x 4 x i32> %zm0, <vscale x 4 x i32> %zm1,
                                                      <vscale x 4 x i32> %zm2, <vscale x 4 x i32> %zm3)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.za.vg1x4.nxv4i32(i32 %slice.7,
                                                       <vscale x 4 x i32> %zn0, <vscale x 4 x i32> %zn1,
                                                      <vscale x 4 x i32> %zn2, <vscale x 4 x i32> %zn3,
                                                       <vscale x 4 x i32> %zm0, <vscale x 4 x i32> %zm1,
                                                      <vscale x 4 x i32> %zm2, <vscale x 4 x i32> %zm3)
  ret void
}

define void @multi_vector_sub_write_za_vg1x4_i64(i32 %slice, <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
; CHECK-LABEL: multi_vector_sub_write_za_vg1x4_i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $z7 killed $z7 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    mov w8, w0
; CHECK-NEXT:    // kill: def $z6 killed $z6 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z5 killed $z5 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    // kill: def $z4 killed $z4 killed $z4_z5_z6_z7 def $z4_z5_z6_z7
; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3
; CHECK-NEXT:    sub za.d[w8, 0, vgx4], { z0.d - z3.d }, { z4.d - z7.d }
; CHECK-NEXT:    sub za.d[w8, 7, vgx4], { z0.d - z3.d }, { z4.d - z7.d }
; CHECK-NEXT:    ret
                                        <vscale x 2 x i64> %zn2, <vscale x 2 x i64> %zn3,
                                        <vscale x 2 x i64> %zm0, <vscale x 2 x i64> %zm1,
                                        <vscale x 2 x i64> %zm2, <vscale x 2 x i64> %zm3) {
  call void @llvm.aarch64.sme.sub.write.za.vg1x4.nxv2i64(i32 %slice,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zn2, <vscale x 2 x i64> %zn3,
                                                       <vscale x 2 x i64> %zm0, <vscale x 2 x i64> %zm1,
                                                       <vscale x 2 x i64> %zm2, <vscale x 2 x i64> %zm3)
  %slice.7 = add i32 %slice, 7
  call void @llvm.aarch64.sme.sub.write.za.vg1x4.nxv2i64(i32 %slice.7,
                                                       <vscale x 2 x i64> %zn0, <vscale x 2 x i64> %zn1,
                                                       <vscale x 2 x i64> %zn2, <vscale x 2 x i64> %zn3,
                                                       <vscale x 2 x i64> %zm0, <vscale x 2 x i64> %zm1,
                                                       <vscale x 2 x i64> %zm2, <vscale x 2 x i64> %zm3)
  ret void
}

declare void@llvm.aarch64.sme.sub.write.single.za.vg1x2.nxv4i32(i32, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>)
declare void@llvm.aarch64.sme.sub.write.single.za.vg1x2.nxv2i64(i32, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>)
declare void@llvm.aarch64.sme.sub.write.single.za.vg1x4.nxv4i32(i32, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>,
<vscale x 4 x i32>, <vscale x 4 x i32>)
declare void@llvm.aarch64.sme.sub.write.single.za.vg1x4.nxv2i64(i32, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>,
<vscale x 2 x i64>, <vscale x 2 x i64>)
declare void@llvm.aarch64.sme.sub.write.za.vg1x2.nxv4i32(i32, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>)
declare void@llvm.aarch64.sme.sub.write.za.vg1x2.nxv2i64(i32, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>)
declare void@llvm.aarch64.sme.sub.write.za.vg1x4.nxv4i32(i32, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>)
declare void@llvm.aarch64.sme.sub.write.za.vg1x4.nxv2i64(i32, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>)
