xref: /llvm-project/llvm/test/CodeGen/LoongArch/alloca.ll (revision 9d4f7f44b64d87d1068859906f43b7ce03a7388b)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \
3; RUN:   | FileCheck %s --check-prefix=LA32
4; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \
5; RUN:   | FileCheck %s --check-prefix=LA64
6
7declare void @notdead(ptr)
8
9;; These tests must ensure the stack pointer is restored using the frame
10;; pointer
11
12define void @simple_alloca(i32 %n) nounwind {
13; LA32-LABEL: simple_alloca:
14; LA32:       # %bb.0:
15; LA32-NEXT:    addi.w $sp, $sp, -16
16; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
17; LA32-NEXT:    st.w $fp, $sp, 8 # 4-byte Folded Spill
18; LA32-NEXT:    addi.w $fp, $sp, 16
19; LA32-NEXT:    addi.w $a0, $a0, 15
20; LA32-NEXT:    bstrins.w $a0, $zero, 3, 0
21; LA32-NEXT:    sub.w $a0, $sp, $a0
22; LA32-NEXT:    move $sp, $a0
23; LA32-NEXT:    bl %plt(notdead)
24; LA32-NEXT:    addi.w $sp, $fp, -16
25; LA32-NEXT:    ld.w $fp, $sp, 8 # 4-byte Folded Reload
26; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
27; LA32-NEXT:    addi.w $sp, $sp, 16
28; LA32-NEXT:    ret
29;
30; LA64-LABEL: simple_alloca:
31; LA64:       # %bb.0:
32; LA64-NEXT:    addi.d $sp, $sp, -16
33; LA64-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
34; LA64-NEXT:    st.d $fp, $sp, 0 # 8-byte Folded Spill
35; LA64-NEXT:    addi.d $fp, $sp, 16
36; LA64-NEXT:    bstrpick.d $a0, $a0, 31, 0
37; LA64-NEXT:    addi.d $a0, $a0, 15
38; LA64-NEXT:    bstrpick.d $a0, $a0, 32, 4
39; LA64-NEXT:    slli.d $a0, $a0, 4
40; LA64-NEXT:    sub.d $a0, $sp, $a0
41; LA64-NEXT:    move $sp, $a0
42; LA64-NEXT:    bl %plt(notdead)
43; LA64-NEXT:    addi.d $sp, $fp, -16
44; LA64-NEXT:    ld.d $fp, $sp, 0 # 8-byte Folded Reload
45; LA64-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload
46; LA64-NEXT:    addi.d $sp, $sp, 16
47; LA64-NEXT:    ret
48  %1 = alloca i8, i32 %n
49  call void @notdead(ptr %1)
50  ret void
51}
52
53declare ptr @llvm.stacksave()
54declare void @llvm.stackrestore(ptr)
55
56define void @scoped_alloca(i32 %n) nounwind {
57; LA32-LABEL: scoped_alloca:
58; LA32:       # %bb.0:
59; LA32-NEXT:    addi.w $sp, $sp, -16
60; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
61; LA32-NEXT:    st.w $fp, $sp, 8 # 4-byte Folded Spill
62; LA32-NEXT:    st.w $s0, $sp, 4 # 4-byte Folded Spill
63; LA32-NEXT:    addi.w $fp, $sp, 16
64; LA32-NEXT:    move $s0, $sp
65; LA32-NEXT:    addi.w $a0, $a0, 15
66; LA32-NEXT:    bstrins.w $a0, $zero, 3, 0
67; LA32-NEXT:    sub.w $a0, $sp, $a0
68; LA32-NEXT:    move $sp, $a0
69; LA32-NEXT:    bl %plt(notdead)
70; LA32-NEXT:    move $sp, $s0
71; LA32-NEXT:    addi.w $sp, $fp, -16
72; LA32-NEXT:    ld.w $s0, $sp, 4 # 4-byte Folded Reload
73; LA32-NEXT:    ld.w $fp, $sp, 8 # 4-byte Folded Reload
74; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
75; LA32-NEXT:    addi.w $sp, $sp, 16
76; LA32-NEXT:    ret
77;
78; LA64-LABEL: scoped_alloca:
79; LA64:       # %bb.0:
80; LA64-NEXT:    addi.d $sp, $sp, -32
81; LA64-NEXT:    st.d $ra, $sp, 24 # 8-byte Folded Spill
82; LA64-NEXT:    st.d $fp, $sp, 16 # 8-byte Folded Spill
83; LA64-NEXT:    st.d $s0, $sp, 8 # 8-byte Folded Spill
84; LA64-NEXT:    addi.d $fp, $sp, 32
85; LA64-NEXT:    move $s0, $sp
86; LA64-NEXT:    bstrpick.d $a0, $a0, 31, 0
87; LA64-NEXT:    addi.d $a0, $a0, 15
88; LA64-NEXT:    bstrpick.d $a0, $a0, 32, 4
89; LA64-NEXT:    slli.d $a0, $a0, 4
90; LA64-NEXT:    sub.d $a0, $sp, $a0
91; LA64-NEXT:    move $sp, $a0
92; LA64-NEXT:    bl %plt(notdead)
93; LA64-NEXT:    move $sp, $s0
94; LA64-NEXT:    addi.d $sp, $fp, -32
95; LA64-NEXT:    ld.d $s0, $sp, 8 # 8-byte Folded Reload
96; LA64-NEXT:    ld.d $fp, $sp, 16 # 8-byte Folded Reload
97; LA64-NEXT:    ld.d $ra, $sp, 24 # 8-byte Folded Reload
98; LA64-NEXT:    addi.d $sp, $sp, 32
99; LA64-NEXT:    ret
100  %sp = call ptr @llvm.stacksave()
101  %addr = alloca i8, i32 %n
102  call void @notdead(ptr %addr)
103  call void @llvm.stackrestore(ptr %sp)
104  ret void
105}
106
107declare void @func(ptr, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)
108
109;; Check that outgoing arguments passed on the stack do not corrupt a
110;; variable-sized stack object.
111define void @alloca_callframe(i32 %n) nounwind {
112; LA32-LABEL: alloca_callframe:
113; LA32:       # %bb.0:
114; LA32-NEXT:    addi.w $sp, $sp, -16
115; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
116; LA32-NEXT:    st.w $fp, $sp, 8 # 4-byte Folded Spill
117; LA32-NEXT:    addi.w $fp, $sp, 16
118; LA32-NEXT:    addi.w $a0, $a0, 15
119; LA32-NEXT:    bstrins.w $a0, $zero, 3, 0
120; LA32-NEXT:    sub.w $a0, $sp, $a0
121; LA32-NEXT:    move $sp, $a0
122; LA32-NEXT:    addi.w $sp, $sp, -16
123; LA32-NEXT:    ori $a1, $zero, 12
124; LA32-NEXT:    st.w $a1, $sp, 12
125; LA32-NEXT:    ori $a1, $zero, 11
126; LA32-NEXT:    st.w $a1, $sp, 8
127; LA32-NEXT:    ori $a1, $zero, 10
128; LA32-NEXT:    st.w $a1, $sp, 4
129; LA32-NEXT:    ori $t0, $zero, 9
130; LA32-NEXT:    ori $a1, $zero, 2
131; LA32-NEXT:    ori $a2, $zero, 3
132; LA32-NEXT:    ori $a3, $zero, 4
133; LA32-NEXT:    ori $a4, $zero, 5
134; LA32-NEXT:    ori $a5, $zero, 6
135; LA32-NEXT:    ori $a6, $zero, 7
136; LA32-NEXT:    ori $a7, $zero, 8
137; LA32-NEXT:    st.w $t0, $sp, 0
138; LA32-NEXT:    bl %plt(func)
139; LA32-NEXT:    addi.w $sp, $sp, 16
140; LA32-NEXT:    addi.w $sp, $fp, -16
141; LA32-NEXT:    ld.w $fp, $sp, 8 # 4-byte Folded Reload
142; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
143; LA32-NEXT:    addi.w $sp, $sp, 16
144; LA32-NEXT:    ret
145;
146; LA64-LABEL: alloca_callframe:
147; LA64:       # %bb.0:
148; LA64-NEXT:    addi.d $sp, $sp, -16
149; LA64-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
150; LA64-NEXT:    st.d $fp, $sp, 0 # 8-byte Folded Spill
151; LA64-NEXT:    addi.d $fp, $sp, 16
152; LA64-NEXT:    bstrpick.d $a0, $a0, 31, 0
153; LA64-NEXT:    addi.d $a0, $a0, 15
154; LA64-NEXT:    bstrpick.d $a0, $a0, 32, 4
155; LA64-NEXT:    slli.d $a0, $a0, 4
156; LA64-NEXT:    sub.d $a0, $sp, $a0
157; LA64-NEXT:    move $sp, $a0
158; LA64-NEXT:    addi.d $sp, $sp, -32
159; LA64-NEXT:    ori $a1, $zero, 12
160; LA64-NEXT:    st.d $a1, $sp, 24
161; LA64-NEXT:    ori $a1, $zero, 11
162; LA64-NEXT:    st.d $a1, $sp, 16
163; LA64-NEXT:    ori $a1, $zero, 10
164; LA64-NEXT:    st.d $a1, $sp, 8
165; LA64-NEXT:    ori $t0, $zero, 9
166; LA64-NEXT:    ori $a1, $zero, 2
167; LA64-NEXT:    ori $a2, $zero, 3
168; LA64-NEXT:    ori $a3, $zero, 4
169; LA64-NEXT:    ori $a4, $zero, 5
170; LA64-NEXT:    ori $a5, $zero, 6
171; LA64-NEXT:    ori $a6, $zero, 7
172; LA64-NEXT:    ori $a7, $zero, 8
173; LA64-NEXT:    st.d $t0, $sp, 0
174; LA64-NEXT:    bl %plt(func)
175; LA64-NEXT:    addi.d $sp, $sp, 32
176; LA64-NEXT:    addi.d $sp, $fp, -16
177; LA64-NEXT:    ld.d $fp, $sp, 0 # 8-byte Folded Reload
178; LA64-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload
179; LA64-NEXT:    addi.d $sp, $sp, 16
180; LA64-NEXT:    ret
181  %1 = alloca i8, i32 %n
182  call void @func(ptr %1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8,
183                  i32 9, i32 10, i32 11, i32 12)
184  ret void
185}
186