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: movq %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 call void @llvm.lifetime.start.p0(i64 4, ptr %f) #1 118 call void @llvm.lifetime.start.p0(i64 120, ptr %a) #1 119 call void @llvm.lifetime.start.p0(i64 4000, ptr %aa) #1 120 call void @llvm.lifetime.start.p0(i64 4, ptr %e) #1 121 call void @llvm.lifetime.start.p0(i64 4000, ptr %cc) #1 122 call void @llvm.lifetime.start.p0(i64 4, ptr %b) #1 123 call void @llvm.lifetime.start.p0(i64 4, ptr %d) #1 124 call void @llvm.lifetime.start.p0(i64 4000, ptr %aaa) #1 125 %call = call i32 (ptr, ...) @check_a(ptr %a) 126 %call1 = call i32 (ptr, ...) @bar1(ptr %aaa) 127 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 128 %call2 = call i32 (ptr, ...) @bar1(ptr %a) 129 %call3 = call i32 (ptr, ...) @check_f(ptr %f) 130 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 131 %call4 = call i32 (ptr, ...) @bar1(ptr %a) 132 %call5 = call i32 (ptr, ptr, ptr, ...) @bar3(ptr %aa, ptr %aaa, ptr %cc) 133 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 134 %call6 = call i32 (ptr, ptr, ...) @bar2(ptr %a, ptr %cc) 135 %call7 = call i32 (ptr, ...) @check_b(ptr %b) 136 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 137 %call8 = call i32 (ptr, ...) @bar1(ptr %a) 138 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 139 %call9 = call i32 (ptr, ptr, ...) @bar2(ptr %a, ptr %f) 140 %call10 = call i32 (ptr, ...) @check_e(ptr %e) 141 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 142 %call11 = call i32 (ptr, ...) @bar1(ptr %a) 143 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 144 %call12 = call i32 (ptr, ptr, ...) @bar2(ptr %e, ptr %f) 145 %call13 = call i32 (ptr, ...) @check_d(ptr %d) 146 %call14 = call i32 (ptr, ...) @bar1(ptr %a) 147 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 148 %call15 = call i32 (ptr, ptr, ptr, ...) @bar3(ptr %d, ptr %e, ptr %f) 149 call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1 150 %call16 = call i32 (ptr, ...) @bar1(ptr %a) 151 call void @llvm.lifetime.end.p0(i64 4000, ptr %aaa) #1 152 call void @llvm.lifetime.end.p0(i64 4, ptr %d) #1 153 call void @llvm.lifetime.end.p0(i64 4, ptr %b) #1 154 call void @llvm.lifetime.end.p0(i64 4000, ptr %cc) #1 155 call void @llvm.lifetime.end.p0(i64 4, ptr %e) #1 156 call void @llvm.lifetime.end.p0(i64 4000, ptr %aa) #1 157 call void @llvm.lifetime.end.p0(i64 120, ptr %a) #1 158 call void @llvm.lifetime.end.p0(i64 4, ptr %f) #1 159 ret void 160} 161 162; Function Attrs: nounwind 163declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #1 164 165declare i32 @check_a(...) #2 166declare i32 @bar1(...) #2 167declare i32 @check_f(...) #2 168declare i32 @bar3(...) #2 169declare i32 @bar2(...) #2 170declare i32 @check_b(...) #2 171declare i32 @check_e(...) #2 172declare i32 @check_d(...) #2 173 174; Function Attrs: nounwind 175declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #1 176 177