177 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s -check-prefix=X64
 | 
						|
; RUN: llc < %s -mtriple=i686-unknown-linux-gnu | FileCheck %s -check-prefix=X32
 | 
						|
 | 
						|
; CHECK-LABEL: foo
 | 
						|
 | 
						|
; Check the functionality of the local stack symbol table ordering
 | 
						|
; heuristics.
 | 
						|
; The test has a bunch of locals of various sizes that are referenced a
 | 
						|
; different number of times.
 | 
						|
;
 | 
						|
; a   : 120B, 9 uses,   density = 0.075
 | 
						|
; aa  : 4000B, 1 use,   density = 0.00025
 | 
						|
; b   : 4B, 1 use,      density = 0.25
 | 
						|
; cc  : 4000B, 2 uses   density = 0.0005
 | 
						|
; d   : 4B, 2 uses      density = 0.5
 | 
						|
; e   : 4B, 3 uses      density = 0.75
 | 
						|
; f   : 4B, 4 uses      density = 1
 | 
						|
;
 | 
						|
; Given the size, number of uses and calculated density (uses / size), we're
 | 
						|
; going to hope that f gets allocated closest to the stack pointer,
 | 
						|
; followed by e, d, b, then a (to check for just a few).
 | 
						|
; We use gnu-inline asm between calls to prevent registerization of addresses
 | 
						|
; so that we get exact counts.
 | 
						|
;
 | 
						|
; The test is taken from something like this:
 | 
						|
; void foo()
 | 
						|
; {
 | 
						|
;   int f; // 4 uses.          4 / 4 = 1
 | 
						|
;   int a[30]; // 9 uses.      8 / 120 = 0.06
 | 
						|
;   int aa[1000]; // 1 use.    1 / 4000 =
 | 
						|
;   int e; // 3 uses.          3 / 4 = 0.75
 | 
						|
;   int cc[1000]; // 2 uses.   2 / 4000 = 
 | 
						|
;   int b; // 1 use.           1 / 4 = 0.25
 | 
						|
;   int d; // 2 uses.          2 / 4 = 0.5
 | 
						|
;   int aaa[1000]; // 2 uses.  2 / 4000
 | 
						|
;
 | 
						|
; 
 | 
						|
;   check_a(&a);
 | 
						|
;   bar1(&aaa);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar1(&a);
 | 
						|
;   check_f(&f);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar1(&a);
 | 
						|
;   bar3(&aa, &aaa, &cc);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar2(&a,&cc);
 | 
						|
;   check_b(&b);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar1(&a);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar2(&a, &f);
 | 
						|
;   check_e(&e);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar1(&a);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar2(&e, &f);
 | 
						|
;   check_d(&d);
 | 
						|
;   bar1(&a);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar3(&d, &e, &f);
 | 
						|
;   asm ("":::"esi","edi","ebp","ebx","rbx","r12","r13","r14","r15","rbp");
 | 
						|
;   bar1(&a);
 | 
						|
; }
 | 
						|
;
 | 
						|
; X64: leaq 16(%rsp), %rdi
 | 
						|
; X64: callq check_a
 | 
						|
; X64: callq bar1
 | 
						|
; X64: callq bar1
 | 
						|
; X64: movq %rsp, %rdi
 | 
						|
; X64: callq check_f
 | 
						|
; X64: callq bar1
 | 
						|
; X64: callq bar3
 | 
						|
; X64: callq bar2
 | 
						|
; X64: leaq 12(%rsp), %rdi
 | 
						|
; X64: callq check_b
 | 
						|
; X64: callq bar1
 | 
						|
; X64: callq bar2
 | 
						|
; X64: leaq 4(%rsp), %rdi
 | 
						|
; X64: callq check_e
 | 
						|
; X64: callq bar1
 | 
						|
; X64: callq bar2
 | 
						|
; X64: leaq 8(%rsp), %rdi
 | 
						|
; X64: callq check_d
 | 
						|
 | 
						|
; X32: leal 32(%esp)
 | 
						|
; X32: calll check_a
 | 
						|
; X32: calll bar1
 | 
						|
; X32: calll bar1
 | 
						|
; X32: leal 16(%esp)
 | 
						|
; X32: calll check_f
 | 
						|
; X32: calll bar1
 | 
						|
; X32: calll bar3
 | 
						|
; X32: calll bar2
 | 
						|
; X32: leal 28(%esp)
 | 
						|
; X32: calll check_b
 | 
						|
; X32: calll bar1
 | 
						|
; X32: calll bar2
 | 
						|
; X32: leal 20(%esp)
 | 
						|
; X32: calll check_e
 | 
						|
; X32: calll bar1
 | 
						|
; X32: calll bar2
 | 
						|
; X32: leal 24(%esp)
 | 
						|
; X32: calll check_d
 | 
						|
 | 
						|
 | 
						|
define void @foo() nounwind uwtable {
 | 
						|
entry:
 | 
						|
  %f = alloca i32, align 4
 | 
						|
  %a = alloca [30 x i32], align 16
 | 
						|
  %aa = alloca [1000 x i32], align 16
 | 
						|
  %e = alloca i32, align 4
 | 
						|
  %cc = alloca [1000 x i32], align 16
 | 
						|
  %b = alloca i32, align 4
 | 
						|
  %d = alloca i32, align 4
 | 
						|
  %aaa = alloca [1000 x i32], align 16
 | 
						|
  call void @llvm.lifetime.start.p0(i64 4, ptr %f) #1
 | 
						|
  call void @llvm.lifetime.start.p0(i64 120, ptr %a) #1
 | 
						|
  call void @llvm.lifetime.start.p0(i64 4000, ptr %aa) #1
 | 
						|
  call void @llvm.lifetime.start.p0(i64 4, ptr %e) #1
 | 
						|
  call void @llvm.lifetime.start.p0(i64 4000, ptr %cc) #1
 | 
						|
  call void @llvm.lifetime.start.p0(i64 4, ptr %b) #1
 | 
						|
  call void @llvm.lifetime.start.p0(i64 4, ptr %d) #1
 | 
						|
  call void @llvm.lifetime.start.p0(i64 4000, ptr %aaa) #1
 | 
						|
  %call = call i32 (ptr, ...) @check_a(ptr %a)
 | 
						|
  %call1 = call i32 (ptr, ...) @bar1(ptr %aaa)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call2 = call i32 (ptr, ...) @bar1(ptr %a)
 | 
						|
  %call3 = call i32 (ptr, ...) @check_f(ptr %f)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call4 = call i32 (ptr, ...) @bar1(ptr %a)
 | 
						|
  %call5 = call i32 (ptr, ptr, ptr, ...) @bar3(ptr %aa, ptr %aaa, ptr %cc)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call6 = call i32 (ptr, ptr, ...) @bar2(ptr %a, ptr %cc)
 | 
						|
  %call7 = call i32 (ptr, ...) @check_b(ptr %b)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call8 = call i32 (ptr, ...) @bar1(ptr %a)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call9 = call i32 (ptr, ptr, ...) @bar2(ptr %a, ptr %f)
 | 
						|
  %call10 = call i32 (ptr, ...) @check_e(ptr %e)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call11 = call i32 (ptr, ...) @bar1(ptr %a)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call12 = call i32 (ptr, ptr, ...) @bar2(ptr %e, ptr %f)
 | 
						|
  %call13 = call i32 (ptr, ...) @check_d(ptr %d)
 | 
						|
  %call14 = call i32 (ptr, ...) @bar1(ptr %a)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call15 = call i32 (ptr, ptr, ptr, ...) @bar3(ptr %d, ptr %e, ptr %f)
 | 
						|
  call void asm sideeffect "", "~{esi},~{edi},~{ebp},~{ebx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{rbp},~{dirflag},~{fpsr},~{flags}"() #1
 | 
						|
  %call16 = call i32 (ptr, ...) @bar1(ptr %a)
 | 
						|
  call void @llvm.lifetime.end.p0(i64 4000, ptr %aaa) #1
 | 
						|
  call void @llvm.lifetime.end.p0(i64 4, ptr %d) #1
 | 
						|
  call void @llvm.lifetime.end.p0(i64 4, ptr %b) #1
 | 
						|
  call void @llvm.lifetime.end.p0(i64 4000, ptr %cc) #1
 | 
						|
  call void @llvm.lifetime.end.p0(i64 4, ptr %e) #1
 | 
						|
  call void @llvm.lifetime.end.p0(i64 4000, ptr %aa) #1
 | 
						|
  call void @llvm.lifetime.end.p0(i64 120, ptr %a) #1
 | 
						|
  call void @llvm.lifetime.end.p0(i64 4, ptr %f) #1
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; Function Attrs: nounwind
 | 
						|
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #1
 | 
						|
 | 
						|
declare i32 @check_a(...) #2
 | 
						|
declare i32 @bar1(...) #2
 | 
						|
declare i32 @check_f(...) #2
 | 
						|
declare i32 @bar3(...) #2
 | 
						|
declare i32 @bar2(...) #2
 | 
						|
declare i32 @check_b(...) #2
 | 
						|
declare i32 @check_e(...) #2
 | 
						|
declare i32 @check_d(...) #2
 | 
						|
 | 
						|
; Function Attrs: nounwind
 | 
						|
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #1
 | 
						|
 |