; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc -mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 ; RUN: llc -mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 %va_list = type { ptr, ptr, ptr, i32, i32 } define preserve_nonecc i32 @callee(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, ...) nounwind noinline ssp { ; LA32-LABEL: callee: ; LA32: # %bb.0: # %entry ; LA32-NEXT: addi.w $sp, $sp, -48 ; LA32-NEXT: st.w $a7, $sp, 44 ; LA32-NEXT: st.w $a6, $sp, 40 ; LA32-NEXT: st.w $a5, $sp, 36 ; LA32-NEXT: ld.w $a0, $sp, 20 ; LA32-NEXT: addi.w $a1, $sp, 36 ; LA32-NEXT: st.w $a1, $sp, 8 ; LA32-NEXT: bgez $a0, .LBB0_3 ; LA32-NEXT: # %bb.1: # %maybe_reg ; LA32-NEXT: addi.w $a1, $a0, 8 ; LA32-NEXT: st.w $a1, $sp, 20 ; LA32-NEXT: bgtz $a1, .LBB0_3 ; LA32-NEXT: # %bb.2: # %in_reg ; LA32-NEXT: ld.w $a1, $sp, 12 ; LA32-NEXT: add.w $a0, $a1, $a0 ; LA32-NEXT: b .LBB0_4 ; LA32-NEXT: .LBB0_3: # %on_stack ; LA32-NEXT: ld.w $a0, $sp, 8 ; LA32-NEXT: addi.w $a1, $a0, 8 ; LA32-NEXT: st.w $a1, $sp, 8 ; LA32-NEXT: .LBB0_4: # %end ; LA32-NEXT: ld.w $a0, $a0, 0 ; LA32-NEXT: addi.w $sp, $sp, 48 ; LA32-NEXT: ret ; ; LA64-LABEL: callee: ; LA64: # %bb.0: # %entry ; LA64-NEXT: addi.d $sp, $sp, -80 ; LA64-NEXT: st.d $a7, $sp, 72 ; LA64-NEXT: st.d $a6, $sp, 64 ; LA64-NEXT: st.d $a5, $sp, 56 ; LA64-NEXT: ld.w $a0, $sp, 40 ; LA64-NEXT: addi.d $a1, $sp, 56 ; LA64-NEXT: st.d $a1, $sp, 16 ; LA64-NEXT: bgez $a0, .LBB0_3 ; LA64-NEXT: # %bb.1: # %maybe_reg ; LA64-NEXT: addi.w $a1, $a0, 8 ; LA64-NEXT: st.w $a1, $sp, 40 ; LA64-NEXT: bgtz $a1, .LBB0_3 ; LA64-NEXT: # %bb.2: # %in_reg ; LA64-NEXT: ld.d $a1, $sp, 24 ; LA64-NEXT: add.d $a0, $a1, $a0 ; LA64-NEXT: b .LBB0_4 ; LA64-NEXT: .LBB0_3: # %on_stack ; LA64-NEXT: ld.d $a0, $sp, 16 ; LA64-NEXT: addi.d $a1, $a0, 8 ; LA64-NEXT: st.d $a1, $sp, 16 ; LA64-NEXT: .LBB0_4: # %end ; LA64-NEXT: ld.w $a0, $a0, 0 ; LA64-NEXT: addi.d $sp, $sp, 80 ; LA64-NEXT: ret entry: %args = alloca %va_list, align 8 call void @llvm.va_start(ptr %args) %gr_offs_p = getelementptr inbounds %va_list, ptr %args, i32 0, i32 3 %gr_offs = load i32, ptr %gr_offs_p, align 8 %0 = icmp sge i32 %gr_offs, 0 br i1 %0, label %on_stack, label %maybe_reg maybe_reg: %new_reg_offs = add i32 %gr_offs, 8 store i32 %new_reg_offs, ptr %gr_offs_p, align 8 %inreg = icmp sle i32 %new_reg_offs, 0 br i1 %inreg, label %in_reg, label %on_stack in_reg: %reg_top_p = getelementptr inbounds %va_list, ptr %args, i32 0, i32 1 %reg_top = load ptr, ptr %reg_top_p, align 8 %reg = getelementptr inbounds i8, ptr %reg_top, i32 %gr_offs br label %end on_stack: %stack_p = getelementptr inbounds %va_list, ptr %args, i32 0, i32 0 %stack = load ptr, ptr %stack_p, align 8 %new_stack = getelementptr inbounds i8, ptr %stack, i64 8 store ptr %new_stack, ptr %stack_p, align 8 br label %end end: %p = phi ptr [ %reg, %in_reg ], [ %stack, %on_stack ] %10 = load i32, ptr %p, align 8 call void @llvm.va_end.p0(ptr %args) ret i32 %10 } declare void @llvm.va_start(ptr) nounwind declare void @llvm.va_end(ptr) nounwind define i32 @caller() nounwind ssp { ; LA32-LABEL: caller: ; LA32: # %bb.0: ; LA32-NEXT: addi.w $sp, $sp, -48 ; LA32-NEXT: st.w $ra, $sp, 44 # 4-byte Folded Spill ; LA32-NEXT: st.w $s0, $sp, 40 # 4-byte Folded Spill ; LA32-NEXT: st.w $s1, $sp, 36 # 4-byte Folded Spill ; LA32-NEXT: st.w $s2, $sp, 32 # 4-byte Folded Spill ; LA32-NEXT: st.w $s3, $sp, 28 # 4-byte Folded Spill ; LA32-NEXT: st.w $s4, $sp, 24 # 4-byte Folded Spill ; LA32-NEXT: st.w $s5, $sp, 20 # 4-byte Folded Spill ; LA32-NEXT: st.w $s6, $sp, 16 # 4-byte Folded Spill ; LA32-NEXT: st.w $s7, $sp, 12 # 4-byte Folded Spill ; LA32-NEXT: st.w $s8, $sp, 8 # 4-byte Folded Spill ; LA32-NEXT: ori $a0, $zero, 10 ; LA32-NEXT: st.w $a0, $sp, 4 ; LA32-NEXT: ori $t0, $zero, 9 ; LA32-NEXT: ori $a0, $zero, 1 ; LA32-NEXT: ori $a1, $zero, 2 ; LA32-NEXT: ori $a2, $zero, 3 ; LA32-NEXT: ori $a3, $zero, 4 ; LA32-NEXT: ori $a4, $zero, 5 ; LA32-NEXT: ori $a5, $zero, 6 ; LA32-NEXT: ori $a6, $zero, 7 ; LA32-NEXT: ori $a7, $zero, 8 ; LA32-NEXT: st.w $t0, $sp, 0 ; LA32-NEXT: bl callee ; LA32-NEXT: ld.w $s8, $sp, 8 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s7, $sp, 12 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s6, $sp, 16 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s5, $sp, 20 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s4, $sp, 24 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s3, $sp, 28 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s2, $sp, 32 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s1, $sp, 36 # 4-byte Folded Reload ; LA32-NEXT: ld.w $s0, $sp, 40 # 4-byte Folded Reload ; LA32-NEXT: ld.w $ra, $sp, 44 # 4-byte Folded Reload ; LA32-NEXT: addi.w $sp, $sp, 48 ; LA32-NEXT: ret ; ; LA64-LABEL: caller: ; LA64: # %bb.0: ; LA64-NEXT: addi.d $sp, $sp, -176 ; LA64-NEXT: st.d $ra, $sp, 168 # 8-byte Folded Spill ; LA64-NEXT: st.d $s0, $sp, 160 # 8-byte Folded Spill ; LA64-NEXT: st.d $s1, $sp, 152 # 8-byte Folded Spill ; LA64-NEXT: st.d $s2, $sp, 144 # 8-byte Folded Spill ; LA64-NEXT: st.d $s3, $sp, 136 # 8-byte Folded Spill ; LA64-NEXT: st.d $s4, $sp, 128 # 8-byte Folded Spill ; LA64-NEXT: st.d $s5, $sp, 120 # 8-byte Folded Spill ; LA64-NEXT: st.d $s6, $sp, 112 # 8-byte Folded Spill ; LA64-NEXT: st.d $s7, $sp, 104 # 8-byte Folded Spill ; LA64-NEXT: st.d $s8, $sp, 96 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs0, $sp, 88 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs1, $sp, 80 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs2, $sp, 72 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs3, $sp, 64 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs4, $sp, 56 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs5, $sp, 48 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs6, $sp, 40 # 8-byte Folded Spill ; LA64-NEXT: fst.d $fs7, $sp, 32 # 8-byte Folded Spill ; LA64-NEXT: ori $a0, $zero, 10 ; LA64-NEXT: st.d $a0, $sp, 8 ; LA64-NEXT: ori $t0, $zero, 9 ; LA64-NEXT: ori $a0, $zero, 1 ; LA64-NEXT: ori $a1, $zero, 2 ; LA64-NEXT: ori $a2, $zero, 3 ; LA64-NEXT: ori $a3, $zero, 4 ; LA64-NEXT: ori $a4, $zero, 5 ; LA64-NEXT: ori $a5, $zero, 6 ; LA64-NEXT: ori $a6, $zero, 7 ; LA64-NEXT: ori $a7, $zero, 8 ; LA64-NEXT: st.d $t0, $sp, 0 ; LA64-NEXT: pcaddu18i $ra, %call36(callee) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: fld.d $fs7, $sp, 32 # 8-byte Folded Reload ; LA64-NEXT: fld.d $fs6, $sp, 40 # 8-byte Folded Reload ; LA64-NEXT: fld.d $fs5, $sp, 48 # 8-byte Folded Reload ; LA64-NEXT: fld.d $fs4, $sp, 56 # 8-byte Folded Reload ; LA64-NEXT: fld.d $fs3, $sp, 64 # 8-byte Folded Reload ; LA64-NEXT: fld.d $fs2, $sp, 72 # 8-byte Folded Reload ; LA64-NEXT: fld.d $fs1, $sp, 80 # 8-byte Folded Reload ; LA64-NEXT: fld.d $fs0, $sp, 88 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s8, $sp, 96 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s7, $sp, 104 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s6, $sp, 112 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s5, $sp, 120 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s4, $sp, 128 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s3, $sp, 136 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s2, $sp, 144 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s1, $sp, 152 # 8-byte Folded Reload ; LA64-NEXT: ld.d $s0, $sp, 160 # 8-byte Folded Reload ; LA64-NEXT: ld.d $ra, $sp, 168 # 8-byte Folded Reload ; LA64-NEXT: addi.d $sp, $sp, 176 ; LA64-NEXT: ret %r = tail call preserve_nonecc i32 (i32, i32, i32, i32, i32, ...) @callee(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10) ret i32 %r }