; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs | FileCheck %s
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs | FileCheck %s

define <vscale x 4 x i32> @different_imm_vl_with_ta(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_imm_vl_with_ta:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetivli zero, 4, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v10, v12
; CHECK-NEXT:    vadd.vv v8, v8, v10
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen 5)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a, iXLen 4)
  ret <vscale x 4 x i32> %w
}

define <vscale x 4 x i32> @vlmax_and_imm_vl_with_ta(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: vlmax_and_imm_vl_with_ta:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetivli zero, 4, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v10, v12
; CHECK-NEXT:    vadd.vv v8, v8, v10
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen -1)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a, iXLen 4)
  ret <vscale x 4 x i32> %w
}

; Not beneficial to propagate VL since VL is larger in the use side.
define <vscale x 4 x i32> @different_imm_vl_with_ta_larger_vl(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_imm_vl_with_ta_larger_vl:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetivli zero, 4, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v10, v12
; CHECK-NEXT:    vsetivli zero, 5, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v8, v10
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen 4)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a, iXLen 5)
  ret <vscale x 4 x i32> %w
}

define <vscale x 4 x i32> @different_imm_reg_vl_with_ta(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_imm_reg_vl_with_ta:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetivli zero, 4, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v10, v12
; CHECK-NEXT:    vsetvli zero, a0, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v8, v10
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen 4)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a, iXLen %vl1)
  ret <vscale x 4 x i32> %w
}

; Not beneficial to propagate VL since VL is already one.
define <vscale x 4 x i32> @different_imm_vl_with_ta_1(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_imm_vl_with_ta_1:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetivli zero, 1, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v10, v12
; CHECK-NEXT:    vsetvli zero, a0, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v8, v10
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen 1)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a, iXLen %vl1)
  ret <vscale x 4 x i32> %w
}

; Propgate %vl2 to last instruction since it is may smaller than %vl1,
; it's still safe even %vl2 is larger than %vl1, becuase rest of the vector are
; undefined value.
define <vscale x 4 x i32> @different_vl_with_ta(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_vl_with_ta:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v10, v8, v10
; CHECK-NEXT:    vsetvli zero, a1, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vv v8, v10, v8
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a,iXLen %vl2)
  ret <vscale x 4 x i32> %w
}

; We can propagate VL to a tail-undisturbed policy, provided none of its users
; are passthrus (i.e. read past VL).
define <vscale x 4 x i32> @different_vl_with_tu(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_vl_with_tu:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m2, tu, ma
; CHECK-NEXT:    vmv2r.v v14, v10
; CHECK-NEXT:    vadd.vv v14, v10, v12
; CHECK-NEXT:    vsetvli zero, a1, e32, m2, tu, ma
; CHECK-NEXT:    vadd.vv v8, v14, v10
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a, iXLen %vl2)
  ret <vscale x 4 x i32> %w
}

; We can propagate VL to a tail-undisturbed policy, provided none of its users
; are passthrus (i.e. read past VL).
define <vscale x 4 x i32> @different_imm_vl_with_tu(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_imm_vl_with_tu:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetivli zero, 4, e32, m2, tu, ma
; CHECK-NEXT:    vmv2r.v v14, v10
; CHECK-NEXT:    vadd.vv v14, v10, v12
; CHECK-NEXT:    vadd.vv v8, v14, v10
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen 5)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %passthru, <vscale x 4 x i32> %v, <vscale x 4 x i32> %a, iXLen 4)
  ret <vscale x 4 x i32> %w
}

; We can't reduce the VL as %v is used as a passthru, i.e. the elements past VL
; are demanded.
define <vscale x 4 x i32> @different_vl_as_passthru(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_vl_as_passthru:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m2, tu, ma
; CHECK-NEXT:    vmv2r.v v12, v8
; CHECK-NEXT:    vadd.vv v12, v8, v10
; CHECK-NEXT:    vsetvli zero, a1, e32, m2, tu, ma
; CHECK-NEXT:    vadd.vv v12, v8, v10
; CHECK-NEXT:    vmv2r.v v8, v12
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %v, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl2)
  ret <vscale x 4 x i32> %w
}

; We can't reduce the VL as %v is used as a passthru, i.e. the elements past VL
; are demanded.
define <vscale x 4 x i32> @different_imm_vl_as_passthru(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen %vl1, iXLen %vl2) {
; CHECK-LABEL: different_imm_vl_as_passthru:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetivli zero, 5, e32, m2, tu, ma
; CHECK-NEXT:    vmv2r.v v12, v8
; CHECK-NEXT:    vadd.vv v12, v8, v10
; CHECK-NEXT:    vsetivli zero, 4, e32, m2, tu, ma
; CHECK-NEXT:    vadd.vv v12, v8, v10
; CHECK-NEXT:    vmv2r.v v8, v12
; CHECK-NEXT:    ret
  %v = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen 5)
  %w = call <vscale x 4 x i32> @llvm.riscv.vadd.nxv4i32.nxv4i32(<vscale x 4 x i32> %v, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b, iXLen 4)
  ret <vscale x 4 x i32> %w
}

define <vscale x 4 x i32> @dont_optimize_tied_def(<vscale x 4 x i32> %a, <vscale x 4 x i16> %b, <vscale x 4 x i16> %c, iXLen %vl) {
; CHECK-LABEL: dont_optimize_tied_def:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli a1, zero, e16, m1, tu, ma
; CHECK-NEXT:    vwmacc.vv v8, v10, v11
; CHECK-NEXT:    vsetvli zero, a0, e16, m1, tu, ma
; CHECK-NEXT:    vwmacc.vv v8, v10, v11
; CHECK-NEXT:    ret
  %1 = call <vscale x 4 x i32> @llvm.riscv.vwmacc.nxv4i32.nxv4i16(<vscale x 4 x i32> %a, <vscale x 4 x i16> %b, <vscale x 4 x i16> %c, iXLen -1, iXLen 0)
  %2 = call <vscale x 4 x i32> @llvm.riscv.vwmacc.nxv4i32.nxv4i16(<vscale x 4 x i32> %1, <vscale x 4 x i16> %b, <vscale x 4 x i16> %c, iXLen %vl, iXLen 0)
  ret <vscale x 4 x i32> %2
}

define void @optimize_ternary_use(<vscale x 4 x i16> %a, <vscale x 4 x i32> %b, <vscale x 4 x i32> %c, ptr %p, iXLen %vl) {
; CHECK-LABEL: optimize_ternary_use:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a1, e32, m2, ta, ma
; CHECK-NEXT:    vzext.vf2 v14, v8
; CHECK-NEXT:    vmadd.vv v14, v10, v12
; CHECK-NEXT:    vse32.v v14, (a0)
; CHECK-NEXT:    ret
  %1 = zext <vscale x 4 x i16> %a to <vscale x 4 x i32>
  %2 = mul <vscale x 4 x i32> %b, %1
  %3 = add <vscale x 4 x i32> %2, %c
  call void @llvm.riscv.vse(<vscale x 4 x i32> %3, ptr %p, iXLen %vl)
  ret void
}

; This function has a copy between two vrm2 virtual registers, make sure we can
; reduce vl between it.
define void @fadd_fcmp_select_copy(<vscale x 4 x float> %v, <vscale x 4 x i1> %c, ptr %p, iXLen %vl) {
; CHECK-LABEL: fadd_fcmp_select_copy:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a1, e32, m2, ta, ma
; CHECK-NEXT:    vfadd.vv v8, v8, v8
; CHECK-NEXT:    fmv.w.x fa5, zero
; CHECK-NEXT:    vmflt.vf v10, v8, fa5
; CHECK-NEXT:    vmand.mm v10, v0, v10
; CHECK-NEXT:    vse32.v v8, (a0)
; CHECK-NEXT:    vsm.v v10, (a0)
; CHECK-NEXT:    ret
  %fadd = fadd <vscale x 4 x float> %v, %v
  %fcmp = fcmp olt <vscale x 4 x float> %fadd, zeroinitializer
  %select = select <vscale x 4 x i1> %c, <vscale x 4 x i1> %fcmp, <vscale x 4 x i1> zeroinitializer
  call void @llvm.riscv.vse(<vscale x 4 x float> %fadd, ptr %p, iXLen %vl)
  call void @llvm.riscv.vsm(<vscale x 4 x i1> %select, ptr %p, iXLen %vl)
  ret void
}

define <vscale x 8 x i32> @vcompress_cmp(<vscale x 8 x i32> %a, <vscale x 8 x i32> %b, <vscale x 8 x i32> %c, iXLen %vl) {
; CHECK-LABEL: vcompress_cmp:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m4, ta, ma
; CHECK-NEXT:    vmseq.vv v20, v8, v12
; CHECK-NEXT:    vcompress.vm v8, v16, v20
; CHECK-NEXT:    ret
  %cmp = icmp eq <vscale x 8 x i32> %a, %b
  %compress = call <vscale x 8 x i32> @llvm.riscv.vcompress.nxv8i32(<vscale x 8 x i32> poison, <vscale x 8 x i32> %c, <vscale x 8 x i1> %cmp, iXLen %vl)
  ret <vscale x 8 x i32> %compress
}

define <vscale x 8 x i32> @vcompress_add(<vscale x 8 x i32> %a, <vscale x 8 x i32> %b, <vscale x 8 x i1> %c, iXLen %vl) {
; CHECK-LABEL: vcompress_add:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m4, ta, ma
; CHECK-NEXT:    vadd.vv v12, v8, v12
; CHECK-NEXT:    vcompress.vm v8, v12, v0
; CHECK-NEXT:    ret
  %add = add <vscale x 8 x i32> %a, %b
  %compress = call <vscale x 8 x i32> @llvm.riscv.vcompress.nxv8i32(<vscale x 8 x i32> poison, <vscale x 8 x i32> %add, <vscale x 8 x i1> %c, iXLen %vl)
  ret <vscale x 8 x i32> %compress
}

; Make sure we peek through INSERT_SUBREG of tuple registers.
define void @segmented_store_insert_subreg(<vscale x 4 x float> %v0, <vscale x 4 x float> %v1, <vscale x 4 x float> %v2, ptr %p, iXLen %vl) {
; CHECK-LABEL: segmented_store_insert_subreg:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a1, e32, m2, ta, ma
; CHECK-NEXT:    vfadd.vv v10, v8, v10
; CHECK-NEXT:    vsseg3e32.v v8, (a0)
; CHECK-NEXT:    ret
  %fadd = fadd <vscale x 4 x float> %v0, %v1
  %t0 = call target("riscv.vector.tuple", <vscale x 16 x i8>, 3) @llvm.riscv.tuple.insert(target("riscv.vector.tuple", <vscale x 16 x i8>, 3) poison, <vscale x 4 x float> %v0, i32 0)
  %t1 = call target("riscv.vector.tuple", <vscale x 16 x i8>, 3) @llvm.riscv.tuple.insert(target("riscv.vector.tuple", <vscale x 16 x i8>, 3) %t0, <vscale x 4 x float> %fadd, i32 1)
  %t2 = call target("riscv.vector.tuple", <vscale x 16 x i8>, 3) @llvm.riscv.tuple.insert(target("riscv.vector.tuple", <vscale x 16 x i8>, 3) %t1, <vscale x 4 x float> %v2, i32 2)
  call void @llvm.riscv.vsseg3(target("riscv.vector.tuple", <vscale x 16 x i8>, 3) %t2, ptr %p, iXLen %vl, iXLen 5)
  ret void
}

define void @recurrence(<vscale x 4 x i32> %v, ptr %p, iXLen %n, iXLen %vl) {
; CHECK-LABEL: recurrence:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    vsetvli zero, a2, e32, m2, ta, ma
; CHECK-NEXT:    vmv.v.i v10, 0
; CHECK-NEXT:  .LBB16_1: # %loop
; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    addi a1, a1, -1
; CHECK-NEXT:    vadd.vv v10, v10, v8
; CHECK-NEXT:    bnez a1, .LBB16_1
; CHECK-NEXT:  # %bb.2: # %exit
; CHECK-NEXT:    vse32.v v10, (a0)
; CHECK-NEXT:    ret
entry:
  br label %loop
loop:
  %iv = phi iXLen [ 0, %entry ], [ %iv.next, %loop ]
  %phi = phi <vscale x 4 x i32> [ zeroinitializer, %entry ], [ %x, %loop ]
  %x = add <vscale x 4 x i32> %phi, %v
  %iv.next = add iXLen %iv, 1
  %done = icmp eq iXLen %iv.next, %n
  br i1 %done, label %exit, label %loop
exit:
  call void @llvm.riscv.vse(<vscale x 4 x i32> %x, ptr %p, iXLen %vl)
  ret void
}

define void @recurrence_vleff(<vscale x 4 x i32> %v, ptr %p, iXLen %n, iXLen %vl) {
; CHECK-LABEL: recurrence_vleff:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    vsetvli zero, a2, e32, m2, ta, ma
; CHECK-NEXT:    vmv.v.i v8, 0
; CHECK-NEXT:    mv a3, a0
; CHECK-NEXT:  .LBB17_1: # %loop
; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    vsetvli zero, a2, e32, m2, ta, ma
; CHECK-NEXT:    vle32ff.v v10, (a3)
; CHECK-NEXT:    addi a1, a1, -1
; CHECK-NEXT:    vadd.vv v8, v8, v10
; CHECK-NEXT:    vse32.v v8, (a0)
; CHECK-NEXT:    addi a3, a3, 4
; CHECK-NEXT:    bnez a1, .LBB17_1
; CHECK-NEXT:  # %bb.2: # %exit
; CHECK-NEXT:    ret
entry:
  br label %loop
loop:
  %iv = phi iXLen [ 0, %entry ], [ %iv.next, %loop ]
  %phi = phi <vscale x 4 x i32> [ zeroinitializer, %entry ], [ %y, %loop ]
  %gep = getelementptr i32, ptr %p, iXLen %iv
  %vleff = call { <vscale x 4 x i32>, iXLen } @llvm.riscv.vleff(<vscale x 4 x i32> poison, ptr %gep, iXLen %vl)
  %vleff.x = extractvalue { <vscale x 4 x i32>, iXLen } %vleff, 0
  %vleff.vl = extractvalue { <vscale x 4 x i32>, iXLen } %vleff, 1
  %y = add <vscale x 4 x i32> %phi, %vleff.x
  call void @llvm.riscv.vse(<vscale x 4 x i32> %y, ptr %p, iXLen %vleff.vl)
  %iv.next = add iXLen %iv, 1
  %done = icmp eq iXLen %iv.next, %n
  br i1 %done, label %exit, label %loop
exit:
  ret void
}

define <vscale x 4 x i32> @join(<vscale x 4 x i32> %v, i1 %cond, iXLen %vl) {
; CHECK-LABEL: join:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    andi a0, a0, 1
; CHECK-NEXT:    vsetivli zero, 2, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vi v8, v8, 1
; CHECK-NEXT:    beqz a0, .LBB18_2
; CHECK-NEXT:  # %bb.1: # %foo
; CHECK-NEXT:    vsetivli zero, 1, e32, m2, ta, ma
; CHECK-NEXT:    vadd.vi v8, v8, 1
; CHECK-NEXT:    ret
; CHECK-NEXT:  .LBB18_2: # %bar
; CHECK-NEXT:    vadd.vi v8, v8, 2
; CHECK-NEXT:    ret
entry:
  %a = call <vscale x 4 x i32> @llvm.riscv.vadd(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, iXLen 1, iXLen -1)
  br i1 %cond, label %foo, label %bar
foo:
  %b = call <vscale x 4 x i32> @llvm.riscv.vadd(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, iXLen 1, iXLen 1)
  ret <vscale x 4 x i32> %b
bar:
  %c = call <vscale x 4 x i32> @llvm.riscv.vadd(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, iXLen 2, iXLen 2)
  ret <vscale x 4 x i32> %c
}

; The vsmul.vx ends up dead, but doesn't get deleted before RISCVVLOptimizer. Make
; sure we don't crash when we handle it.
; TODO: DeadMachineInstructionElim should remove the dead vsmul.vx.
define <vscale x 2 x i64> @dead_vsmul() {
; CHECK-LABEL: dead_vsmul:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    vsetivli zero, 0, e16, mf2, ta, ma
; CHECK-NEXT:    vmv.v.i v10, 0
; CHECK-NEXT:    csrwi vxrm, 0
; CHECK-NEXT:    vsetvli a0, zero, e64, m2, ta, ma
; CHECK-NEXT:    vmv.v.i v8, 0
; CHECK-NEXT:    vsetivli zero, 0, e64, m2, tu, ma
; CHECK-NEXT:    vmv.v.v v8, v8
; CHECK-NEXT:    vsetvli zero, zero, e16, mf2, tu, ma
; CHECK-NEXT:    vsmul.vx v10, v10, zero
; CHECK-NEXT:    ret
entry:
  %0 = call <vscale x 2 x i16> @llvm.riscv.vsmul(<vscale x 2 x i16> zeroinitializer, <vscale x 2 x i16> zeroinitializer, i16 0, iXLen 0, iXLen 0)
  %1 = call <vscale x 2 x i32> @llvm.riscv.vwmacc(<vscale x 2 x i32> zeroinitializer, i16 0, <vscale x 2 x i16> %0, iXLen 0, iXLen 0)
  %2 = call <vscale x 2 x i64> @llvm.riscv.vwmul(<vscale x 2 x i64> zeroinitializer, <vscale x 2 x i32> %1, <vscale x 2 x i32> zeroinitializer, iXLen 0)
  %3 = call <vscale x 2 x i64> @llvm.riscv.vmerge(<vscale x 2 x i64> zeroinitializer, <vscale x 2 x i64> %2, <vscale x 2 x i64> zeroinitializer, <vscale x 2 x i1> splat (i1 true), iXLen 0)

  ret <vscale x 2 x i64> %3
}
