; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc -mtriple=riscv32 -mattr=+m,+v %s -o - | FileCheck %s --check-prefixes=CHECK,RV32 ; RUN: llc -mtriple=riscv64 -mattr=+m,+v %s -o - | FileCheck %s --check-prefixes=CHECK,RV64 ; Companion to musttail-indirect-args.ll for scalable vector args. ; is too large to fit in v8-v23, so it is split into ; multiple parts and the callee receives a pointer to the parts via ; CCValAssign::Indirect. The musttail computed-arg path must scale per-part ; offsets by VSCALE -- mirrors the non-musttail spill path validated by ; calling-conv.ll's caller_scalable_vector_split_indirect. declare @callee_musttail_scalable( %x, %y) ; Forwarded: both args are caller formals passed straight through. The ; incoming indirect pointers are forwarded zero-copy; no per-part offset ; computation happens in the caller, so VSCALE does not enter here. define @caller_musttail_scalable_forwarded( %x, %y) nounwind { ; CHECK-LABEL: caller_musttail_scalable_forwarded: ; CHECK: # %bb.0: ; CHECK-NEXT: tail callee_musttail_scalable %r = musttail call @callee_musttail_scalable( %x, %y) ret %r } ; Computed: both args are arithmetic on the formals, so dyn_cast ; fails and we go through the store-into-incoming-pointer path. The ; second part's store must use VSCALE * PartOffset relative to ; IncomingPtr, otherwise the part lands at a fixed byte offset that ; differs from what the callee expects (vlenb * 8 above). define @caller_musttail_scalable_computed( %x, %y) nounwind { ; CHECK-LABEL: caller_musttail_scalable_computed: ; CHECK: # %bb.0: ; CHECK-NEXT: csrr a1, vlenb ; CHECK-NEXT: slli a1, a1, 3 ; CHECK-NEXT: vl8re32.v v24, (a0) ; CHECK-NEXT: add a1, a0, a1 ; CHECK-NEXT: vl8re32.v v0, (a1) ; CHECK-NEXT: vsetvli a2, zero, e32, m8, ta, ma ; CHECK-NEXT: vadd.vv v8, v8, v24 ; CHECK-NEXT: vs8r.v v8, (a0) ; CHECK-NEXT: vadd.vv v16, v16, v0 ; CHECK-NEXT: vs8r.v v16, (a1) ; CHECK-NEXT: tail callee_musttail_scalable %s = add %x, %y %r = musttail call @callee_musttail_scalable( %s, %s) ret %r } ; Mixed: first arg forwarded, second arg computed. Exercises both branches ; of the formal-arg-vs-computed path on the same call. define @caller_musttail_scalable_mixed( %x, %y) nounwind { ; CHECK-LABEL: caller_musttail_scalable_mixed: ; CHECK: # %bb.0: ; CHECK-NEXT: csrr a1, vlenb ; CHECK-NEXT: slli a1, a1, 3 ; CHECK-NEXT: vl8re32.v v24, (a0) ; CHECK-NEXT: add a1, a0, a1 ; CHECK-NEXT: vl8re32.v v0, (a1) ; CHECK-NEXT: vsetvli a2, zero, e32, m8, ta, ma ; CHECK-NEXT: vadd.vv v24, v8, v24 ; CHECK-NEXT: vs8r.v v24, (a0) ; CHECK-NEXT: vadd.vv v24, v16, v0 ; CHECK-NEXT: vs8r.v v24, (a1) ; CHECK-NEXT: tail callee_musttail_scalable %s = add %x, %y %r = musttail call @callee_musttail_scalable( %x, %s) ret %r } ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; RV32: {{.*}} ; RV64: {{.*}}