; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 ; RUN: llc -mtriple=loongarch64 -O2 < %s -verify-machineinstrs | FileCheck %s -check-prefix=LA64 ; RUN: llc -mtriple=loongarch32 -O2 < %s -verify-machineinstrs | FileCheck %s -check-prefix=LA32 ;; Test that very large outgoing call frames in functions with variable-sized ;; objects get proper stack probing. The outgoing args are large enough to force ;; the PROBED_STACKALLOC path, which must be expanded in a non-entry block. define void @f(i64 %n) #0 { ; LA64-LABEL: f: ; LA64: # %bb.0: # %entry ; LA64-NEXT: addi.d $sp, $sp, -16 ; LA64-NEXT: .cfi_def_cfa_offset 16 ; LA64-NEXT: st.d $zero, $sp, 0 ; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ; LA64-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill ; LA64-NEXT: .cfi_offset 1, -8 ; LA64-NEXT: .cfi_offset 22, -16 ; LA64-NEXT: addi.d $fp, $sp, 16 ; LA64-NEXT: .cfi_def_cfa 22, 0 ; LA64-NEXT: slli.d $a0, $a0, 2 ; LA64-NEXT: addi.d $a0, $a0, 15 ; LA64-NEXT: bstrins.d $a0, $zero, 3, 0 ; LA64-NEXT: sub.d $a0, $sp, $a0 ; LA64-NEXT: lu12i.w $a1, 1 ; LA64-NEXT: .LBB0_1: # %entry ; LA64-NEXT: # =>This Inner Loop Header: Depth=1 ; LA64-NEXT: sub.d $sp, $sp, $a1 ; LA64-NEXT: st.d $zero, $sp, 0 ; LA64-NEXT: bltu $a0, $sp, .LBB0_1 ; LA64-NEXT: # %bb.2: # %entry ; LA64-NEXT: move $sp, $a0 ; LA64-NEXT: lu12i.w $a1, 5 ; LA64-NEXT: sub.d $t1, $sp, $a1 ; LA64-NEXT: lu12i.w $t2, 1 ; LA64-NEXT: .LBB0_3: # %entry ; LA64-NEXT: # =>This Inner Loop Header: Depth=1 ; LA64-NEXT: sub.d $sp, $sp, $t2 ; LA64-NEXT: st.d $zero, $sp, 0 ; LA64-NEXT: bne $sp, $t1, .LBB0_3 ; LA64-NEXT: # %bb.4: # %entry ; LA64-NEXT: addi.d $sp, $sp, -2048 ; LA64-NEXT: addi.d $sp, $sp, -1424 ; LA64-NEXT: st.d $zero, $sp, 0 ; LA64-NEXT: pcaddu18i $ra, %call36(g) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: lu12i.w $a0, 5 ; LA64-NEXT: ori $a0, $a0, 3472 ; LA64-NEXT: add.d $sp, $sp, $a0 ; LA64-NEXT: addi.d $sp, $fp, -16 ; LA64-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload ; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ; LA64-NEXT: addi.d $sp, $sp, 16 ; LA64-NEXT: ret ; ; LA32-LABEL: f: ; LA32: # %bb.0: # %entry ; LA32-NEXT: addi.w $sp, $sp, -16 ; LA32-NEXT: .cfi_def_cfa_offset 16 ; LA32-NEXT: st.w $zero, $sp, 0 ; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill ; LA32-NEXT: st.w $fp, $sp, 8 # 4-byte Folded Spill ; LA32-NEXT: .cfi_offset 1, -4 ; LA32-NEXT: .cfi_offset 22, -8 ; LA32-NEXT: addi.w $fp, $sp, 16 ; LA32-NEXT: .cfi_def_cfa 22, 0 ; LA32-NEXT: slli.w $a0, $a0, 2 ; LA32-NEXT: addi.w $a0, $a0, 15 ; LA32-NEXT: addi.w $a1, $zero, -16 ; LA32-NEXT: and $a0, $a0, $a1 ; LA32-NEXT: sub.w $a0, $sp, $a0 ; LA32-NEXT: lu12i.w $a1, 1 ; LA32-NEXT: .LBB0_1: # %entry ; LA32-NEXT: # =>This Inner Loop Header: Depth=1 ; LA32-NEXT: sub.w $sp, $sp, $a1 ; LA32-NEXT: st.w $zero, $sp, 0 ; LA32-NEXT: bltu $a0, $sp, .LBB0_1 ; LA32-NEXT: # %bb.2: # %entry ; LA32-NEXT: move $sp, $a0 ; LA32-NEXT: lu12i.w $a1, 5 ; LA32-NEXT: sub.w $t1, $sp, $a1 ; LA32-NEXT: lu12i.w $t2, 1 ; LA32-NEXT: .LBB0_3: # %entry ; LA32-NEXT: # =>This Inner Loop Header: Depth=1 ; LA32-NEXT: sub.w $sp, $sp, $t2 ; LA32-NEXT: st.w $zero, $sp, 0 ; LA32-NEXT: bne $sp, $t1, .LBB0_3 ; LA32-NEXT: # %bb.4: # %entry ; LA32-NEXT: addi.w $sp, $sp, -2048 ; LA32-NEXT: addi.w $sp, $sp, -1456 ; LA32-NEXT: st.w $zero, $sp, 0 ; LA32-NEXT: bl g ; LA32-NEXT: lu12i.w $a0, 5 ; LA32-NEXT: ori $a0, $a0, 3504 ; LA32-NEXT: add.w $sp, $sp, $a0 ; LA32-NEXT: addi.w $sp, $fp, -16 ; LA32-NEXT: ld.w $fp, $sp, 8 # 4-byte Folded Reload ; LA32-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload ; LA32-NEXT: addi.w $sp, $sp, 16 ; LA32-NEXT: ret entry: %v = alloca i32, i64 %n call void @g(ptr %v, [3000 x i64] poison) ret void } declare void @g(ptr, [3000 x i64]) attributes #0 = { "probe-stack"="inline-asm" }