• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; This is a basic test of the alloca instruction.
2
3; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \
4; RUN:   --target x8632 -i %s --args -O2 -allow-externally-defined-symbols \
5; RUN:   | %if --need=target_X8632 --command FileCheck %s
6
7; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \
8; RUN:   --target x8632 -i %s --args -Om1 -allow-externally-defined-symbols \
9; RUN:   | %if --need=target_X8632 --command FileCheck \
10; RUN:   --check-prefix CHECK-OPTM1 %s
11
12; RUN: %if --need=target_ARM32 \
13; RUN:   --command %p2i --filetype=obj \
14; RUN:   --disassemble --target arm32 -i %s --args -O2 \
15; RUN:   -allow-externally-defined-symbols \
16; RUN:   | %if --need=target_ARM32 \
17; RUN:   --command FileCheck --check-prefix ARM32 --check-prefix=ARM-OPT2 %s
18
19; RUN: %if --need=target_ARM32 \
20; RUN:   --command %p2i --filetype=obj \
21; RUN:   --disassemble --target arm32 -i %s --args -Om1 \
22; RUN:   -allow-externally-defined-symbols \
23; RUN:   | %if --need=target_ARM32 \
24; RUN:   --command FileCheck --check-prefix ARM32 --check-prefix=ARM-OPTM1 %s
25
26; RUN: %if --need=target_MIPS32 --need=allow_dump \
27; RUN:   --command %p2i --filetype=asm --assemble \
28; RUN:   --disassemble --target mips32 -i %s --args -O2 \
29; RUN:   -allow-externally-defined-symbols \
30; RUN:   | %if --need=target_MIPS32 --need=allow_dump \
31; RUN:   --command FileCheck --check-prefix MIPS32 --check-prefix=MIPS32-OPT2 %s
32
33; RUN: %if --need=target_MIPS32 --need=allow_dump \
34; RUN:   --command %p2i --filetype=asm --assemble \
35; RUN:   --disassemble --target mips32 -i %s --args -Om1 \
36; RUN:   -allow-externally-defined-symbols \
37; RUN:   | %if --need=target_MIPS32 --need=allow_dump \
38; RUN:   --command FileCheck --check-prefix MIPS32 --check-prefix=MIPS32-OPTM1 %s
39
40define internal void @fixed_416_align_16(i32 %n) {
41entry:
42  %array = alloca i8, i32 416, align 16
43  %__2 = ptrtoint i8* %array to i32
44  call void @f1(i32 %__2)
45  ret void
46}
47; CHECK-LABEL: fixed_416_align_16
48; CHECK:      sub     esp,0x1bc
49; CHECK:      lea     eax,[esp+0x10]
50; CHECK:      mov     DWORD PTR [esp],eax
51; CHECK:      call {{.*}} R_{{.*}}    f1
52
53; CHECK-OPTM1-LABEL: fixed_416_align_16
54; CHECK-OPTM1:      sub     esp,0x18
55; CHECK-OPTM1:      sub     esp,0x1a0
56; CHECK-OPTM1:      mov     DWORD PTR [esp],eax
57; CHECK-OPTM1:      call {{.*}} R_{{.*}}    f1
58
59; ARM32-LABEL: fixed_416_align_16
60; ARM32-OPT2:  sub sp, sp, #428
61; ARM32-OPTM1: sub sp, sp, #416
62; ARM32:       bl {{.*}} R_{{.*}}    f1
63
64; MIPS32-LABEL: fixed_416_align_16
65; MIPS32-OPT2: addiu sp,sp,-448
66; MIPS32-OPT2: addiu a0,sp,16
67; MIPS32-OPTM1: addiu sp,sp,-464
68; MIPS32-OPTM1: addiu [[REG:.*]],sp,16
69; MIPS32-OPTM1: sw [[REG]],{{.*}}
70; MIPS32-OPTM1: lw a0,{{.*}}
71; MIPS32: jal {{.*}} R_{{.*}} f1
72
73define internal void @fixed_416_align_32(i32 %n) {
74entry:
75  %array = alloca i8, i32 400, align 32
76  %__2 = ptrtoint i8* %array to i32
77  call void @f1(i32 %__2)
78  ret void
79}
80; CHECK-LABEL: fixed_416_align_32
81; CHECK:      push    ebp
82; CHECK-NEXT: mov     ebp,esp
83; CHECK:      sub     esp,0x1d8
84; CHECK:      and     esp,0xffffffe0
85; CHECK:      lea     eax,[esp+0x10]
86; CHECK:      mov     DWORD PTR [esp],eax
87; CHECK:      call {{.*}} R_{{.*}}    f1
88
89; ARM32-LABEL: fixed_416_align_32
90; ARM32-OPT2:  sub sp, sp, #424
91; ARM32-OPTM1: sub sp, sp, #416
92; ARM32:       bic sp, sp, #31
93; ARM32:       bl {{.*}} R_{{.*}}    f1
94
95; MIPS32-LABEL: fixed_416_align_32
96; MIPS32-OPT2: addiu sp,sp,-448
97; MIPS32-OPT2: addiu a0,sp,16
98; MIPS32-OPTM1: addiu sp,sp,-464
99; MIPS32-OPTM1: addiu [[REG:.*]],sp,32
100; MIPS32-OPTM1: sw [[REG]],{{.*}}
101; MIPS32-OPTM1: lw a0,{{.*}}
102; MIPS32: jal {{.*}} R_{{.*}} f1
103
104; Show that the amount to allocate will be rounded up.
105define internal void @fixed_351_align_16(i32 %n) {
106entry:
107  %array = alloca i8, i32 351, align 16
108  %__2 = ptrtoint i8* %array to i32
109  call void @f1(i32 %__2)
110  ret void
111}
112; CHECK-LABEL: fixed_351_align_16
113; CHECK:      sub     esp,0x17c
114; CHECK:      lea     eax,[esp+0x10]
115; CHECK:      mov     DWORD PTR [esp],eax
116; CHECK:      call {{.*}} R_{{.*}}    f1
117
118; CHECK-OPTM1-LABEL: fixed_351_align_16
119; CHECK-OPTM1:      sub     esp,0x18
120; CHECK-OPTM1:      sub     esp,0x160
121; CHECK-OPTM1:      mov     DWORD PTR [esp],eax
122; CHECK-OPTM1:      call {{.*}} R_{{.*}}    f1
123
124; ARM32-LABEL: fixed_351_align_16
125; ARM32-OPT2:  sub sp, sp, #364
126; ARM32-OPTM1: sub sp, sp, #352
127; ARM32:       bl {{.*}} R_{{.*}}    f1
128
129; MIPS32-LABEL: fixed_351_align_16
130; MIPS32-OPT2: addiu sp,sp,-384
131; MIPS32-OPT2: addiu a0,sp,16
132; MIPS32-OPTM1: addiu sp,sp,-400
133; MIPS32-OPTM1: addiu [[REG:.*]],sp,16
134; MIPS32-OPTM1: sw [[REG]],{{.*}}
135; MIPS32-OPTM1: lw a0,{{.*}}
136; MIPS32: jal {{.*}} R_{{.*}} f1
137
138define internal void @fixed_351_align_32(i32 %n) {
139entry:
140  %array = alloca i8, i32 351, align 32
141  %__2 = ptrtoint i8* %array to i32
142  call void @f1(i32 %__2)
143  ret void
144}
145; CHECK-LABEL: fixed_351_align_32
146; CHECK:      push    ebp
147; CHECK-NEXT: mov     ebp,esp
148; CHECK:      sub     esp,0x198
149; CHECK:      and     esp,0xffffffe0
150; CHECK:      lea     eax,[esp+0x10]
151; CHECK:      mov     DWORD PTR [esp],eax
152; CHECK:      call {{.*}} R_{{.*}}    f1
153
154; ARM32-LABEL: fixed_351_align_32
155; ARM32-OPT2:  sub sp, sp, #360
156; ARM32-OPTM1: sub sp, sp, #352
157; ARM32:       bic sp, sp, #31
158; ARM32:       bl {{.*}} R_{{.*}}    f1
159
160; MIPS32-LABEL: fixed_351_align_32
161; MIPS32-OPT2: addiu sp,sp,-384
162; MIPS32-OPT2: addiu a0,sp,16
163; MIPS32-OPTM1: addiu sp,sp,-400
164; MIPS32-OPTM1: addiu [[REG:.*]],sp,32
165; MIPS32-OPTM1: sw [[REG]],{{.*}}
166; MIPS32-OPTM1: lw a0,{{.*}}
167; MIPS32: jal {{.*}} R_{{.*}} f1
168
169declare void @f1(i32 %ignored)
170
171declare void @f2(i32 %ignored)
172
173define internal void @variable_n_align_16(i32 %n) {
174entry:
175  %array = alloca i8, i32 %n, align 16
176  %__2 = ptrtoint i8* %array to i32
177  call void @f2(i32 %__2)
178  ret void
179}
180; CHECK-LABEL: variable_n_align_16
181; CHECK:      sub     esp,0x18
182; CHECK:      mov     eax,DWORD PTR [ebp+0x8]
183; CHECK:      add     eax,0xf
184; CHECK:      and     eax,0xfffffff0
185; CHECK:      sub     esp,eax
186; CHECK:      lea     eax,[esp+0x10]
187; CHECK:      mov     DWORD PTR [esp],eax
188; CHECK:      call {{.*}} R_{{.*}}    f2
189
190; ARM32-LABEL: variable_n_align_16
191; ARM32:      add r0, r0, #15
192; ARM32:      bic r0, r0, #15
193; ARM32:      sub sp, sp, r0
194; ARM32:      bl {{.*}} R_{{.*}}    f2
195
196; MIPS32-LABEL: variable_n_align_16
197; MIPS32: addiu	[[REG:.*]],{{.*}},15
198; MIPS32: li	[[REG1:.*]],-16
199; MIPS32: and	[[REG2:.*]],[[REG]],[[REG1]]
200; MIPS32: subu	[[REG3:.*]],sp,[[REG2:.*]]
201; MIPS32: li	[[REG4:.*]],-16
202; MIPS32: and	{{.*}},[[REG3]],[[REG4]]
203; MIPS32: addiu	sp,sp,-16
204; MIPS32: jal	{{.*}} R_{{.*}} f2
205; MIPS32: addiu	sp,sp,16
206
207define internal void @variable_n_align_32(i32 %n) {
208entry:
209  %array = alloca i8, i32 %n, align 32
210  %__2 = ptrtoint i8* %array to i32
211  call void @f2(i32 %__2)
212  ret void
213}
214; In -O2, the order of the CHECK-DAG lines in the output is switched.
215; CHECK-LABEL: variable_n_align_32
216; CHECK:      push    ebp
217; CHECK:      mov     ebp,esp
218; CHECK:      sub     esp,0x18
219; CHECK-DAG:  and     esp,0xffffffe0
220; CHECK-DAG:  mov     eax,DWORD PTR [ebp+0x8]
221; CHECK:      add     eax,0x1f
222; CHECK:      and     eax,0xffffffe0
223; CHECK:      sub     esp,eax
224; CHECK:      lea     eax,[esp+0x10]
225; CHECK:      mov     DWORD PTR [esp],eax
226; CHECK:      call {{.*}} R_{{.*}}    f2
227; CHECK:      mov     esp,ebp
228; CHECK:      pop     ebp
229
230; ARM32-LABEL: variable_n_align_32
231; ARM32:      push {fp, lr}
232; ARM32:      mov fp, sp
233; ARM32:      bic sp, sp, #31
234; ARM32:      add r0, r0, #31
235; ARM32:      bic r0, r0, #31
236; ARM32:      sub sp, sp, r0
237; ARM32:      bl {{.*}} R_{{.*}}    f2
238; ARM32:      mov sp, fp
239; ARM32:      pop {fp, lr}
240
241; MIPS32-LABEL: variable_n_align_32
242; MIPS32: addiu	[[REG:.*]],{{.*}},15
243; MIPS32: li 	[[REG1:.*]],-16
244; MIPS32: and 	[[REG2:.*]],[[REG]],[[REG1]]
245; MIPS32: subu 	[[REG3:.*]],sp,[[REG2]]
246; MIPS32: li 	[[REG4:.*]],-32
247; MIPS32: and 	{{.*}},[[REG3]],[[REG4]]
248; MIPS32: addiu	sp,sp,-16
249; MIPS32: jal 	{{.*}} R_{{.*}} f2
250; MIPS32: addiu	sp,sp,16
251
252; Test alloca with default (0) alignment.
253define internal void @align0(i32 %n) {
254entry:
255  %array = alloca i8, i32 %n
256  %__2 = ptrtoint i8* %array to i32
257  call void @f2(i32 %__2)
258  ret void
259}
260; CHECK-LABEL: align0
261; CHECK: add [[REG:.*]],0xf
262; CHECK: and [[REG]],0xfffffff0
263; CHECK: sub esp,[[REG]]
264
265; ARM32-LABEL: align0
266; ARM32: add r0, r0, #15
267; ARM32: bic r0, r0, #15
268; ARM32: sub sp, sp, r0
269
270; MIPS32-LABEL: align0
271; MIPS32: addiu	[[REG:.*]],{{.*}},15
272; MIPS32: li	[[REG1:.*]],-16
273; MIPS32: and	[[REG2:.*]],[[REG]],[[REG1]]
274; MIPS32: subu	{{.*}},sp,[[REG2]]
275; MIPS32: addiu	sp,sp,-16
276; MIPS32: jal	{{.*}} R_{{.*}} f2
277; MIPS32: addiu	sp,sp,16
278
279; Test a large alignment where a mask might not fit in an immediate
280; field of an instruction for some architectures.
281define internal void @align1MB(i32 %n) {
282entry:
283  %array = alloca i8, i32 %n, align 1048576
284  %__2 = ptrtoint i8* %array to i32
285  call void @f2(i32 %__2)
286  ret void
287}
288; CHECK-LABEL: align1MB
289; CHECK: push ebp
290; CHECK-NEXT: mov ebp,esp
291; CHECK: and esp,0xfff00000
292; CHECK: add [[REG:.*]],0xfffff
293; CHECK: and [[REG]],0xfff00000
294; CHECK: sub esp,[[REG]]
295
296; ARM32-LABEL: align1MB
297; ARM32: movw [[REG:.*]], #0
298; ARM32: movt [[REG]], #65520 ; 0xfff0
299; ARM32: and sp, sp, [[REG]]
300; ARM32: movw [[REG2:.*]], #65535 ; 0xffff
301; ARM32: movt [[REG2]], #15
302; ARM32: add r0, r0, [[REG2]]
303; ARM32: movw [[REG3:.*]], #0
304; ARM32: movt [[REG3]], #65520 ; 0xfff0
305; ARM32: and r0, r0, [[REG3]]
306; ARM32: sub sp, sp, r0
307
308; MIPS32-LABEL: align1MB
309; MIPS32: addiu	[[REG:.*]],{{.*}},15
310; MIPS32: li	[[REG1:.*]],-16
311; MIPS32: and	[[REG2:.*]],[[REG]],[[REG1]]
312; MIPS32: subu	[[REG3:.*]],sp,[[REG2]]
313; MIPS32: lui	[[REG4:.*]],0xfff0
314; MIPS32: and	{{.*}},[[REG3]],[[REG4]]
315; MIPS32: addiu	sp,sp,-16
316; MIPS32: jal   {{.*}} R_{{.*}} f2
317; MIPS32: addiu	sp,sp,16
318
319; Test a large alignment where a mask might still fit in an immediate
320; field of an instruction for some architectures.
321define internal void @align512MB(i32 %n) {
322entry:
323  %array = alloca i8, i32 %n, align 536870912
324  %__2 = ptrtoint i8* %array to i32
325  call void @f2(i32 %__2)
326  ret void
327}
328; CHECK-LABEL: align512MB
329; CHECK: push ebp
330; CHECK-NEXT: mov ebp,esp
331; CHECK: and esp,0xe0000000
332; CHECK: add [[REG:.*]],0x1fffffff
333; CHECK: and [[REG]],0xe0000000
334; CHECK: sub esp,[[REG]]
335
336; ARM32-LABEL: align512MB
337; ARM32: and sp, sp, #-536870912 ; 0xe0000000
338; ARM32: mvn [[REG:.*]], #-536870912 ; 0xe0000000
339; ARM32: add r0, r0, [[REG]]
340; ARM32: and r0, r0, #-536870912 ; 0xe0000000
341; ARM32: sub sp, sp, r0
342
343; MIPS32-LABEL: align512MB
344; MIPS32: addiu	[[REG:.*]],{{.*}},15
345; MIPS32: li	[[REG2:.*]],-16
346; MIPS32: and	[[REG3:.*]],[[REG]],[[REG2]]
347; MIPS32: subu	[[REG4:.*]],sp,[[REG3]]
348; MIPS32: lui	[[REG5:.*]],0xe000
349; MIPS32: and	{{.*}},[[REG4]],[[REG5]]
350; MIPS32: addiu	sp,sp,-16
351; MIPS32: jal	{{.*}} R_{{.*}} f2
352; MIPS32: addiu	sp,sp,16
353
354; Test that a simple alloca sequence doesn't trigger a frame pointer.
355define internal void @fixed_no_frameptr(i32 %arg) {
356entry:
357  %a1 = alloca i8, i32 8, align 4
358  %a2 = alloca i8, i32 12, align 4
359  %a3 = alloca i8, i32 16, align 4
360  %p1 = bitcast i8* %a1 to i32*
361  %p2 = bitcast i8* %a2 to i32*
362  %p3 = bitcast i8* %a3 to i32*
363  store i32 %arg, i32* %p1, align 1
364  store i32 %arg, i32* %p2, align 1
365  store i32 %arg, i32* %p3, align 1
366  ret void
367}
368; CHECK-LABEL: fixed_no_frameptr
369; CHECK-NOT:      mov     ebp,esp
370
371; Test that a simple alloca sequence with at least one large alignment does
372; trigger a frame pointer.
373define internal void @fixed_bigalign_with_frameptr(i32 %arg) {
374entry:
375  %a1 = alloca i8, i32 8, align 4
376  %a2 = alloca i8, i32 12, align 4
377  %a3 = alloca i8, i32 16, align 64
378  %p1 = bitcast i8* %a1 to i32*
379  %p2 = bitcast i8* %a2 to i32*
380  %p3 = bitcast i8* %a3 to i32*
381  store i32 %arg, i32* %p1, align 1
382  store i32 %arg, i32* %p2, align 1
383  store i32 %arg, i32* %p3, align 1
384  ret void
385}
386; CHECK-LABEL: fixed_bigalign_with_frameptr
387; CHECK:      mov     ebp,esp
388
389; Test that a more complex alloca sequence does trigger a frame pointer.
390define internal void @var_with_frameptr(i32 %arg) {
391entry:
392  %a1 = alloca i8, i32 8, align 4
393  %a2 = alloca i8, i32 12, align 4
394  %a3 = alloca i8, i32 %arg, align 4
395  %p1 = bitcast i8* %a1 to i32*
396  %p2 = bitcast i8* %a2 to i32*
397  %p3 = bitcast i8* %a3 to i32*
398  store i32 %arg, i32* %p1, align 1
399  store i32 %arg, i32* %p2, align 1
400  store i32 %arg, i32* %p3, align 1
401  ret void
402}
403; CHECK-LABEL: var_with_frameptr
404; CHECK:      mov     ebp,esp
405