1; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s -check-prefix=X64
2; RUN: llc < %s -mtriple=i686-unknown-linux-gnu | FileCheck %s -check-prefix=X32
3
4; CHECK-LABEL: foo
5
6; Check the functionality of the local stack symbol table ordering
7; heuristics.
8; The test has a bunch of locals of various sizes that are referenced a
9; different number of times.
10;
11; a   : 120B, 9 uses,   density = 0.075
12; aa  : 4000B, 1 use,   density = 0.00025
13; b   : 4B, 1 use,      density = 0.25
14; cc  : 4000B, 2 uses   density = 0.0005
15; d   : 4B, 2 uses      density = 0.5
16; e   : 4B, 3 uses      density = 0.75
17; f   : 4B, 4 uses      density = 1
18;
19; Given the size, number of uses and calculated density (uses / size), we're
20; going to hope that f gets allocated closest to the stack pointer,
21; followed by e, d, b, then a (to check for just a few).
22; We use gnu-inline asm between calls to prevent registerization of addresses
23; so that we get exact counts.
24;
25; The test is taken from something like this:
26; void foo()
27; {
28;   int f; // 4 uses.          4 / 4 = 1
29;   int a[30]; // 9 uses.      8 / 120 = 0.06
30;   int aa[1000]; // 1 use.    1 / 4000 =
31;   int e; // 3 uses.          3 / 4 = 0.75
32;   int cc[1000]; // 2 uses.   2 / 4000 =
33;   int b; // 1 use.           1 / 4 = 0.25
34;   int d; // 2 uses.          2 / 4 = 0.5
35;   int aaa[1000]; // 2 uses.  2 / 4000
36;
37;
38;   check_a(&a);
39;   bar1(&aaa);
40;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
41;   bar1(&a);
42;   check_f(&f);
43;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
44;   bar1(&a);
45;   bar3(&aa, &aaa, &cc);
46;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
47;   bar2(&a,&cc);
48;   check_b(&b);
49;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
50;   bar1(&a);
51;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
52;   bar2(&a, &f);
53;   check_e(&e);
54;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
55;   bar1(&a);
56;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
57;   bar2(&e, &f);
58;   check_d(&d);
59;   bar1(&a);
60;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
61;   bar3(&d, &e, &f);
62;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
63;   bar1(&a);
64; }
65;
66; X64: leaq 16(%rsp), %rdi
67; X64: callq check_a
68; X64: callq bar1
69; X64: callq bar1
70; X64: leaq (%rsp), %rdi
71; X64: callq check_f
72; X64: callq bar1
73; X64: callq bar3
74; X64: callq bar2
75; X64: leaq 12(%rsp), %rdi
76; X64: callq check_b
77; X64: callq bar1
78; X64: callq bar2
79; X64: leaq 4(%rsp), %rdi
80; X64: callq check_e
81; X64: callq bar1
82; X64: callq bar2
83; X64: leaq 8(%rsp), %rdi
84; X64: callq check_d
85
86; X32: leal 32(%esp)
87; X32: calll check_a
88; X32: calll bar1
89; X32: calll bar1
90; X32: leal 16(%esp)
91; X32: calll check_f
92; X32: calll bar1
93; X32: calll bar3
94; X32: calll bar2
95; X32: leal 28(%esp)
96; X32: calll check_b
97; X32: calll bar1
98; X32: calll bar2
99; X32: leal 20(%esp)
100; X32: calll check_e
101; X32: calll bar1
102; X32: calll bar2
103; X32: leal 24(%esp)
104; X32: calll check_d
105
106
107define void @foo() nounwind uwtable {
108entry:
109  %f = alloca i32, align 4
110  %a = alloca [30 x i32], align 16
111  %aa = alloca [1000 x i32], align 16
112  %e = alloca i32, align 4
113  %cc = alloca [1000 x i32], align 16
114  %b = alloca i32, align 4
115  %d = alloca i32, align 4
116  %aaa = alloca [1000 x i32], align 16
117  %0 = bitcast i32* %f to i8*
118  call void @llvm.lifetime.start(i64 4, i8* %0) #1
119  %1 = bitcast [30 x i32]* %a to i8*
120  call void @llvm.lifetime.start(i64 120, i8* %1) #1
121  %2 = bitcast [1000 x i32]* %aa to i8*
122  call void @llvm.lifetime.start(i64 4000, i8* %2) #1
123  %3 = bitcast i32* %e to i8*
124  call void @llvm.lifetime.start(i64 4, i8* %3) #1
125  %4 = bitcast [1000 x i32]* %cc to i8*
126  call void @llvm.lifetime.start(i64 4000, i8* %4) #1
127  %5 = bitcast i32* %b to i8*
128  call void @llvm.lifetime.start(i64 4, i8* %5) #1
129  %6 = bitcast i32* %d to i8*
130  call void @llvm.lifetime.start(i64 4, i8* %6) #1
131  %7 = bitcast [1000 x i32]* %aaa to i8*
132  call void @llvm.lifetime.start(i64 4000, i8* %7) #1
133  %call = call i32 ([30 x i32]*, ...) bitcast (i32 (...)* @check_a to i32 ([30 x i32]*, ...)*)([30 x i32]* %a)
134  %call1 = call i32 ([1000 x i32]*, ...) bitcast (i32 (...)* @bar1 to i32 ([1000 x i32]*, ...)*)([1000 x i32]* %aaa)
135  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
136  %call2 = call i32 ([30 x i32]*, ...) bitcast (i32 (...)* @bar1 to i32 ([30 x i32]*, ...)*)([30 x i32]* %a)
137  %call3 = call i32 (i32*, ...) bitcast (i32 (...)* @check_f to i32 (i32*, ...)*)(i32* %f)
138  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
139  %call4 = call i32 ([30 x i32]*, ...) bitcast (i32 (...)* @bar1 to i32 ([30 x i32]*, ...)*)([30 x i32]* %a)
140  %call5 = call i32 ([1000 x i32]*, [1000 x i32]*, [1000 x i32]*, ...) bitcast (i32 (...)* @bar3 to i32 ([1000 x i32]*, [1000 x i32]*, [1000 x i32]*, ...)*)([1000 x i32]* %aa, [1000 x i32]* %aaa, [1000 x i32]* %cc)
141  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
142  %call6 = call i32 ([30 x i32]*, [1000 x i32]*, ...) bitcast (i32 (...)* @bar2 to i32 ([30 x i32]*, [1000 x i32]*, ...)*)([30 x i32]* %a, [1000 x i32]* %cc)
143  %call7 = call i32 (i32*, ...) bitcast (i32 (...)* @check_b to i32 (i32*, ...)*)(i32* %b)
144  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
145  %call8 = call i32 ([30 x i32]*, ...) bitcast (i32 (...)* @bar1 to i32 ([30 x i32]*, ...)*)([30 x i32]* %a)
146  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
147  %call9 = call i32 ([30 x i32]*, i32*, ...) bitcast (i32 (...)* @bar2 to i32 ([30 x i32]*, i32*, ...)*)([30 x i32]* %a, i32* %f)
148  %call10 = call i32 (i32*, ...) bitcast (i32 (...)* @check_e to i32 (i32*, ...)*)(i32* %e)
149  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
150  %call11 = call i32 ([30 x i32]*, ...) bitcast (i32 (...)* @bar1 to i32 ([30 x i32]*, ...)*)([30 x i32]* %a)
151  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
152  %call12 = call i32 (i32*, i32*, ...) bitcast (i32 (...)* @bar2 to i32 (i32*, i32*, ...)*)(i32* %e, i32* %f)
153  %call13 = call i32 (i32*, ...) bitcast (i32 (...)* @check_d to i32 (i32*, ...)*)(i32* %d)
154  %call14 = call i32 ([30 x i32]*, ...) bitcast (i32 (...)* @bar1 to i32 ([30 x i32]*, ...)*)([30 x i32]* %a)
155  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
156  %call15 = call i32 (i32*, i32*, i32*, ...) bitcast (i32 (...)* @bar3 to i32 (i32*, i32*, i32*, ...)*)(i32* %d, i32* %e, i32* %f)
157  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
158  %call16 = call i32 ([30 x i32]*, ...) bitcast (i32 (...)* @bar1 to i32 ([30 x i32]*, ...)*)([30 x i32]* %a)
159  call void @llvm.lifetime.end(i64 4000, i8* %7) #1
160  call void @llvm.lifetime.end(i64 4, i8* %6) #1
161  call void @llvm.lifetime.end(i64 4, i8* %5) #1
162  call void @llvm.lifetime.end(i64 4000, i8* %4) #1
163  call void @llvm.lifetime.end(i64 4, i8* %3) #1
164  call void @llvm.lifetime.end(i64 4000, i8* %2) #1
165  call void @llvm.lifetime.end(i64 120, i8* %1) #1
166  call void @llvm.lifetime.end(i64 4, i8* %0) #1
167  ret void
168}
169
170; Function Attrs: nounwind
171declare void @llvm.lifetime.start(i64, i8* nocapture) #1
172
173declare i32 @check_a(...) #2
174declare i32 @bar1(...) #2
175declare i32 @check_f(...) #2
176declare i32 @bar3(...) #2
177declare i32 @bar2(...) #2
178declare i32 @check_b(...) #2
179declare i32 @check_e(...) #2
180declare i32 @check_d(...) #2
181
182; Function Attrs: nounwind
183declare void @llvm.lifetime.end(i64, i8* nocapture) #1
184
185