| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc -mtriple=loongarch64 -O2 < %s | FileCheck %s -check-prefix=LA64 | |
| ; RUN: llc -mtriple=loongarch32 -O2 < %s | FileCheck %s -check-prefix=LA32 | |
| ;; From llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll | |
| ;; Dynamically-sized allocation, needs a loop which can handle any size at | |
| ;; runtime. The final iteration of the loop will temporarily put SP below the | |
| ;; target address, but this doesn't break any of the ABI constraints on the | |
| ;; stack, and also doesn't probe below the target SP value. | |
| define void @dynamic(i64 %size, ptr %out) #0 { | |
| ; | |
| ; LA64-LABEL: dynamic: | |
| ; LA64: # %bb.0: | |
| ; 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: addi.d $a0, $a0, 15 | |
| ; LA64-NEXT: bstrins.d $a0, $zero, 3, 0 | |
| ; LA64-NEXT: sub.d $a0, $sp, $a0 | |
| ; LA64-NEXT: lu12i.w $a2, 1 | |
| ; LA64-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a2 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: bltu $a0, $sp, .LBB0_1 | |
| ; LA64-NEXT: # %bb.2: | |
| ; LA64-NEXT: move $sp, $a0 | |
| ; LA64-NEXT: st.d $a0, $a1, 0 | |
| ; 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: dynamic: | |
| ; LA32: # %bb.0: | |
| ; 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: 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: # =>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: | |
| ; LA32-NEXT: move $sp, $a0 | |
| ; LA32-NEXT: st.w $a0, $a2, 0 | |
| ; 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 | |
| %v = alloca i8, i64 %size, align 1 | |
| store ptr %v, ptr %out, align 8 | |
| ret void | |
| } | |
| ;; This function has a fixed-size stack slot and a dynamic one. The fixed size | |
| ;; slot isn't large enough that we would normally probe it, but we need to do so | |
| ;; here otherwise the gap between the CSR save and the first probe of the | |
| ;; dynamic allocation could be too far apart when the size of the dynamic | |
| ;; allocation is close to the guard size. | |
| define void @dynamic_fixed(i64 %size, ptr %out1, ptr %out2) #0 { | |
| ; | |
| ; LA64-LABEL: dynamic_fixed: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: addi.d $sp, $sp, -96 | |
| ; LA64-NEXT: .cfi_def_cfa_offset 96 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill | |
| ; LA64-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill | |
| ; LA64-NEXT: .cfi_offset 1, -8 | |
| ; LA64-NEXT: .cfi_offset 22, -16 | |
| ; LA64-NEXT: addi.d $fp, $sp, 96 | |
| ; LA64-NEXT: .cfi_def_cfa 22, 0 | |
| ; LA64-NEXT: addi.d $a3, $fp, -88 | |
| ; LA64-NEXT: st.d $a3, $a1, 0 | |
| ; 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: .LBB1_1: # =>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, .LBB1_1 | |
| ; LA64-NEXT: # %bb.2: | |
| ; LA64-NEXT: move $sp, $a0 | |
| ; LA64-NEXT: st.d $a0, $a2, 0 | |
| ; LA64-NEXT: addi.d $sp, $fp, -96 | |
| ; LA64-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload | |
| ; LA64-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload | |
| ; LA64-NEXT: addi.d $sp, $sp, 96 | |
| ; LA64-NEXT: ret | |
| ; | |
| ; LA32-LABEL: dynamic_fixed: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: addi.w $sp, $sp, -80 | |
| ; LA32-NEXT: .cfi_def_cfa_offset 80 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: st.w $ra, $sp, 76 # 4-byte Folded Spill | |
| ; LA32-NEXT: st.w $fp, $sp, 72 # 4-byte Folded Spill | |
| ; LA32-NEXT: .cfi_offset 1, -4 | |
| ; LA32-NEXT: .cfi_offset 22, -8 | |
| ; LA32-NEXT: addi.w $fp, $sp, 80 | |
| ; LA32-NEXT: .cfi_def_cfa 22, 0 | |
| ; LA32-NEXT: addi.w $a1, $fp, -72 | |
| ; LA32-NEXT: st.w $a1, $a2, 0 | |
| ; 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: .LBB1_1: # =>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, .LBB1_1 | |
| ; LA32-NEXT: # %bb.2: | |
| ; LA32-NEXT: move $sp, $a0 | |
| ; LA32-NEXT: st.w $a0, $a3, 0 | |
| ; LA32-NEXT: addi.w $sp, $fp, -80 | |
| ; LA32-NEXT: ld.w $fp, $sp, 72 # 4-byte Folded Reload | |
| ; LA32-NEXT: ld.w $ra, $sp, 76 # 4-byte Folded Reload | |
| ; LA32-NEXT: addi.w $sp, $sp, 80 | |
| ; LA32-NEXT: ret | |
| %v1 = alloca i8, i64 64, align 1 | |
| store ptr %v1, ptr %out1, align 8 | |
| %v2 = alloca i8, i64 %size, align 1 | |
| store ptr %v2, ptr %out2, align 8 | |
| ret void | |
| } | |
| ;; Dynamic allocation, with an alignment requirement greater than the alignment | |
| ;; of SP. Done by ANDing the target SP with a constant to align it down, then | |
| ;; doing the loop as normal. Note that we also re-align the stack in the prolog, | |
| ;; which isn't actually needed because the only aligned allocations are dynamic, | |
| ;; this is done even without stack probing. | |
| define void @dynamic_align_64(i64 %size, ptr %out) #0 { | |
| ; | |
| ; LA64-LABEL: dynamic_align_64: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: addi.d $sp, $sp, -128 | |
| ; LA64-NEXT: .cfi_def_cfa_offset 128 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: st.d $ra, $sp, 120 # 8-byte Folded Spill | |
| ; LA64-NEXT: st.d $fp, $sp, 112 # 8-byte Folded Spill | |
| ; LA64-NEXT: st.d $s8, $sp, 104 # 8-byte Folded Spill | |
| ; LA64-NEXT: .cfi_offset 1, -8 | |
| ; LA64-NEXT: .cfi_offset 22, -16 | |
| ; LA64-NEXT: .cfi_offset 31, -24 | |
| ; LA64-NEXT: addi.d $fp, $sp, 128 | |
| ; LA64-NEXT: .cfi_def_cfa 22, 0 | |
| ; LA64-NEXT: bstrins.d $sp, $zero, 5, 0 | |
| ; LA64-NEXT: move $s8, $sp | |
| ; LA64-NEXT: addi.d $a0, $a0, 15 | |
| ; LA64-NEXT: bstrins.d $a0, $zero, 3, 0 | |
| ; LA64-NEXT: sub.d $a0, $sp, $a0 | |
| ; LA64-NEXT: bstrins.d $a0, $zero, 5, 0 | |
| ; LA64-NEXT: lu12i.w $a2, 1 | |
| ; LA64-NEXT: .LBB2_1: # =>This Inner Loop Header: Depth=1 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a2 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: bltu $a0, $sp, .LBB2_1 | |
| ; LA64-NEXT: # %bb.2: | |
| ; LA64-NEXT: move $sp, $a0 | |
| ; LA64-NEXT: st.d $a0, $a1, 0 | |
| ; LA64-NEXT: addi.d $sp, $fp, -128 | |
| ; LA64-NEXT: ld.d $s8, $sp, 104 # 8-byte Folded Reload | |
| ; LA64-NEXT: ld.d $fp, $sp, 112 # 8-byte Folded Reload | |
| ; LA64-NEXT: ld.d $ra, $sp, 120 # 8-byte Folded Reload | |
| ; LA64-NEXT: addi.d $sp, $sp, 128 | |
| ; LA64-NEXT: ret | |
| ; | |
| ; LA32-LABEL: dynamic_align_64: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: addi.w $sp, $sp, -64 | |
| ; LA32-NEXT: .cfi_def_cfa_offset 64 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: st.w $ra, $sp, 60 # 4-byte Folded Spill | |
| ; LA32-NEXT: st.w $fp, $sp, 56 # 4-byte Folded Spill | |
| ; LA32-NEXT: st.w $s8, $sp, 52 # 4-byte Folded Spill | |
| ; LA32-NEXT: .cfi_offset 1, -4 | |
| ; LA32-NEXT: .cfi_offset 22, -8 | |
| ; LA32-NEXT: .cfi_offset 31, -12 | |
| ; LA32-NEXT: addi.w $fp, $sp, 64 | |
| ; LA32-NEXT: .cfi_def_cfa 22, 0 | |
| ; LA32-NEXT: bstrins.w $sp, $zero, 5, 0 | |
| ; LA32-NEXT: move $s8, $sp | |
| ; 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: addi.w $a1, $zero, -64 | |
| ; LA32-NEXT: and $a0, $a0, $a1 | |
| ; LA32-NEXT: lu12i.w $a1, 1 | |
| ; LA32-NEXT: .LBB2_1: # =>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, .LBB2_1 | |
| ; LA32-NEXT: # %bb.2: | |
| ; LA32-NEXT: move $sp, $a0 | |
| ; LA32-NEXT: st.w $a0, $a2, 0 | |
| ; LA32-NEXT: addi.w $sp, $fp, -64 | |
| ; LA32-NEXT: ld.w $s8, $sp, 52 # 4-byte Folded Reload | |
| ; LA32-NEXT: ld.w $fp, $sp, 56 # 4-byte Folded Reload | |
| ; LA32-NEXT: ld.w $ra, $sp, 60 # 4-byte Folded Reload | |
| ; LA32-NEXT: addi.w $sp, $sp, 64 | |
| ; LA32-NEXT: ret | |
| %v = alloca i8, i64 %size, align 64 | |
| store ptr %v, ptr %out, align 8 | |
| ret void | |
| } | |
| ;; Dynamic allocation, with an alignment greater than the stack guard size. The | |
| ;; only difference to the dynamic allocation is the constant used for aligning | |
| ;; the target SP, the loop will probe the whole allocation without needing to | |
| ;; know about the alignment padding. | |
| define void @dynamic_align_8192(i64 %size, ptr %out) #0 { | |
| ; | |
| ; LA64-LABEL: dynamic_align_8192: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: addi.d $sp, $sp, -2032 | |
| ; LA64-NEXT: .cfi_def_cfa_offset 2032 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill | |
| ; LA64-NEXT: st.d $fp, $sp, 2016 # 8-byte Folded Spill | |
| ; LA64-NEXT: st.d $s8, $sp, 2008 # 8-byte Folded Spill | |
| ; LA64-NEXT: .cfi_offset 1, -8 | |
| ; LA64-NEXT: .cfi_offset 22, -16 | |
| ; LA64-NEXT: .cfi_offset 31, -24 | |
| ; LA64-NEXT: addi.d $fp, $sp, 2032 | |
| ; LA64-NEXT: .cfi_def_cfa 22, 0 | |
| ; LA64-NEXT: lu12i.w $a2, 1 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a2 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a2 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a2 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: addi.d $sp, $sp, -2048 | |
| ; LA64-NEXT: addi.d $sp, $sp, -16 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: bstrins.d $sp, $zero, 12, 0 | |
| ; LA64-NEXT: move $s8, $sp | |
| ; LA64-NEXT: addi.d $a0, $a0, 15 | |
| ; LA64-NEXT: bstrins.d $a0, $zero, 3, 0 | |
| ; LA64-NEXT: sub.d $a0, $sp, $a0 | |
| ; LA64-NEXT: bstrins.d $a0, $zero, 12, 0 | |
| ; LA64-NEXT: .LBB3_1: # =>This Inner Loop Header: Depth=1 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a2 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: bltu $a0, $sp, .LBB3_1 | |
| ; LA64-NEXT: # %bb.2: | |
| ; LA64-NEXT: move $sp, $a0 | |
| ; LA64-NEXT: st.d $a0, $a1, 0 | |
| ; LA64-NEXT: lu12i.w $a0, 4 | |
| ; LA64-NEXT: sub.d $sp, $fp, $a0 | |
| ; LA64-NEXT: lu12i.w $a0, 3 | |
| ; LA64-NEXT: ori $a0, $a0, 2064 | |
| ; LA64-NEXT: add.d $sp, $sp, $a0 | |
| ; LA64-NEXT: ld.d $s8, $sp, 2008 # 8-byte Folded Reload | |
| ; LA64-NEXT: ld.d $fp, $sp, 2016 # 8-byte Folded Reload | |
| ; LA64-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload | |
| ; LA64-NEXT: addi.d $sp, $sp, 2032 | |
| ; LA64-NEXT: ret | |
| ; | |
| ; LA32-LABEL: dynamic_align_8192: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: addi.w $sp, $sp, -2032 | |
| ; LA32-NEXT: .cfi_def_cfa_offset 2032 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: st.w $ra, $sp, 2028 # 4-byte Folded Spill | |
| ; LA32-NEXT: st.w $fp, $sp, 2024 # 4-byte Folded Spill | |
| ; LA32-NEXT: st.w $s8, $sp, 2020 # 4-byte Folded Spill | |
| ; LA32-NEXT: .cfi_offset 1, -4 | |
| ; LA32-NEXT: .cfi_offset 22, -8 | |
| ; LA32-NEXT: .cfi_offset 31, -12 | |
| ; LA32-NEXT: addi.w $fp, $sp, 2032 | |
| ; LA32-NEXT: .cfi_def_cfa 22, 0 | |
| ; LA32-NEXT: lu12i.w $a1, 1 | |
| ; LA32-NEXT: sub.w $sp, $sp, $a1 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: sub.w $sp, $sp, $a1 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: sub.w $sp, $sp, $a1 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: addi.w $sp, $sp, -2048 | |
| ; LA32-NEXT: addi.w $sp, $sp, -16 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: bstrins.w $sp, $zero, 12, 0 | |
| ; LA32-NEXT: move $s8, $sp | |
| ; 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, -2 | |
| ; LA32-NEXT: and $a0, $a0, $a1 | |
| ; LA32-NEXT: lu12i.w $a1, 1 | |
| ; LA32-NEXT: .LBB3_1: # =>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, .LBB3_1 | |
| ; LA32-NEXT: # %bb.2: | |
| ; LA32-NEXT: move $sp, $a0 | |
| ; LA32-NEXT: st.w $a0, $a2, 0 | |
| ; LA32-NEXT: lu12i.w $a0, 4 | |
| ; LA32-NEXT: sub.w $sp, $fp, $a0 | |
| ; LA32-NEXT: lu12i.w $a0, 3 | |
| ; LA32-NEXT: ori $a0, $a0, 2064 | |
| ; LA32-NEXT: add.w $sp, $sp, $a0 | |
| ; LA32-NEXT: ld.w $s8, $sp, 2020 # 4-byte Folded Reload | |
| ; LA32-NEXT: ld.w $fp, $sp, 2024 # 4-byte Folded Reload | |
| ; LA32-NEXT: ld.w $ra, $sp, 2028 # 4-byte Folded Reload | |
| ; LA32-NEXT: addi.w $sp, $sp, 2032 | |
| ; LA32-NEXT: ret | |
| %v = alloca i8, i64 %size, align 8192 | |
| store ptr %v, ptr %out, align 8 | |
| ret void | |
| } | |
| ;; If a function has variable-sized stack objects, then any function calls which | |
| ;; need to pass arguments on the stack must allocate the stack space for them | |
| ;; dynamically, to ensure they are at the bottom of the frame. | |
| define void @no_reserved_call_frame(i64 %n) #0 { | |
| ; | |
| ; LA64-LABEL: no_reserved_call_frame: | |
| ; 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: .LBB4_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, .LBB4_1 | |
| ; LA64-NEXT: # %bb.2: # %entry | |
| ; LA64-NEXT: move $sp, $a0 | |
| ; LA64-NEXT: lu12i.w $a1, 1 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a1 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: pcaddu18i $ra, %call36(callee_stack_args) | |
| ; LA64-NEXT: jirl $ra, $ra, 0 | |
| ; LA64-NEXT: lu12i.w $a0, 1 | |
| ; 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: no_reserved_call_frame: | |
| ; 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: .LBB4_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, .LBB4_1 | |
| ; LA32-NEXT: # %bb.2: # %entry | |
| ; LA32-NEXT: move $sp, $a0 | |
| ; LA32-NEXT: lu12i.w $a1, 1 | |
| ; LA32-NEXT: sub.w $sp, $sp, $a1 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: addi.w $sp, $sp, -32 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: bl callee_stack_args | |
| ; LA32-NEXT: lu12i.w $a0, 1 | |
| ; LA32-NEXT: ori $a0, $a0, 32 | |
| ; 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 @callee_stack_args(ptr %v, [518 x i64] poison) | |
| ret void | |
| } | |
| ;; Same as above but without a variable-sized allocation, so the reserved call | |
| ;; frame can be folded into the fixed-size allocation in the prologue. | |
| define void @reserved_call_frame(i64 %n) #0 { | |
| ; | |
| ; LA64-LABEL: reserved_call_frame: | |
| ; LA64: # %bb.0: # %entry | |
| ; LA64-NEXT: addi.d $sp, $sp, -2032 | |
| ; LA64-NEXT: .cfi_def_cfa_offset 2032 | |
| ; LA64-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill | |
| ; LA64-NEXT: .cfi_offset 1, -8 | |
| ; LA64-NEXT: lu12i.w $a0, 1 | |
| ; LA64-NEXT: sub.d $sp, $sp, $a0 | |
| ; LA64-NEXT: st.d $zero, $sp, 0 | |
| ; LA64-NEXT: .cfi_def_cfa_offset 6128 | |
| ; LA64-NEXT: addi.d $sp, $sp, -48 | |
| ; LA64-NEXT: .cfi_def_cfa_offset 6176 | |
| ; LA64-NEXT: lu12i.w $a0, 1 | |
| ; LA64-NEXT: add.d $a0, $sp, $a0 | |
| ; LA64-NEXT: pcaddu18i $ra, %call36(callee_stack_args) | |
| ; LA64-NEXT: jirl $ra, $ra, 0 | |
| ; LA64-NEXT: lu12i.w $a0, 1 | |
| ; LA64-NEXT: ori $a0, $a0, 48 | |
| ; LA64-NEXT: add.d $sp, $sp, $a0 | |
| ; LA64-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload | |
| ; LA64-NEXT: addi.d $sp, $sp, 2032 | |
| ; LA64-NEXT: ret | |
| ; | |
| ; LA32-LABEL: reserved_call_frame: | |
| ; LA32: # %bb.0: # %entry | |
| ; LA32-NEXT: addi.w $sp, $sp, -2032 | |
| ; LA32-NEXT: .cfi_def_cfa_offset 2032 | |
| ; LA32-NEXT: st.w $ra, $sp, 2028 # 4-byte Folded Spill | |
| ; LA32-NEXT: .cfi_offset 1, -4 | |
| ; LA32-NEXT: lu12i.w $a0, 1 | |
| ; LA32-NEXT: sub.w $sp, $sp, $a0 | |
| ; LA32-NEXT: st.w $zero, $sp, 0 | |
| ; LA32-NEXT: .cfi_def_cfa_offset 6128 | |
| ; LA32-NEXT: addi.w $sp, $sp, -80 | |
| ; LA32-NEXT: .cfi_def_cfa_offset 6208 | |
| ; LA32-NEXT: lu12i.w $a0, 1 | |
| ; LA32-NEXT: ori $a0, $a0, 36 | |
| ; LA32-NEXT: add.w $a0, $sp, $a0 | |
| ; LA32-NEXT: bl callee_stack_args | |
| ; LA32-NEXT: lu12i.w $a0, 1 | |
| ; LA32-NEXT: ori $a0, $a0, 80 | |
| ; LA32-NEXT: add.w $sp, $sp, $a0 | |
| ; LA32-NEXT: ld.w $ra, $sp, 2028 # 4-byte Folded Reload | |
| ; LA32-NEXT: addi.w $sp, $sp, 2032 | |
| ; LA32-NEXT: ret | |
| entry: | |
| %v = alloca i32, i64 518 | |
| call void @callee_stack_args(ptr %v, [518 x i64] poison) | |
| ret void | |
| } | |
| declare void @callee_stack_args(ptr, [518 x i64]) | |
| attributes #0 = { uwtable(async) "probe-stack"="inline-asm" "frame-pointer"="none" } |