142 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			LLVM
		
	
	
	
| ; RUN: llc < %s -mtriple=i386-linux | FileCheck %s -check-prefix=X86-32
 | |
| ; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=X86-64
 | |
| 
 | |
| declare i32 @get_val()
 | |
| declare void @use_val(i32)
 | |
| declare i1 @setjmp()
 | |
| declare void @longjmp()
 | |
| declare void @personality()
 | |
| 
 | |
| 
 | |
| ; Test that llc avoids reusing spill slots in functions that call
 | |
| ; setjmp(), whether they use "call" or "invoke" for calling setjmp()
 | |
| ; (PR18244).
 | |
| 
 | |
| define void @setjmp_caller() {
 | |
| ; X86-32-LABEL: setjmp_caller:
 | |
| ; X86-64-LABEL: setjmp_caller:
 | |
| ; This code keeps enough variables live across the setjmp() call that
 | |
| ; they don't all fit in registers and the compiler will allocate a
 | |
| ; spill slot.
 | |
|   %a1 = call i32 @get_val()
 | |
|   %a2 = call i32 @get_val()
 | |
|   %a3 = call i32 @get_val()
 | |
|   %a4 = call i32 @get_val()
 | |
|   %a5 = call i32 @get_val()
 | |
|   %a6 = call i32 @get_val()
 | |
|   %a7 = call i32 @get_val()
 | |
|   %a8 = call i32 @get_val()
 | |
| ; X86-32: movl %eax, [[SPILL_SLOT:[0-9]+]](%esp)
 | |
| ; X86-32: calll get_val
 | |
| ; X86-64: movl %eax, [[SPILL_SLOT:[0-9]+]](%rsp)
 | |
| ; X86-64: callq get_val
 | |
| 
 | |
|   %setjmp_result = call i1 @setjmp() returns_twice
 | |
|   br i1 %setjmp_result, label %second, label %first
 | |
| ; X86-32: calll setjmp
 | |
| ; X86-64: callq setjmp
 | |
| 
 | |
| ; Again, keep enough variables live that they need spill slots.  Since
 | |
| ; this function calls a returns_twice function (setjmp()), the
 | |
| ; compiler should not reuse the spill slots.  longjmp() can return to
 | |
| ; where the first spill slots were still live.
 | |
| first:
 | |
|   %b1 = call i32 @get_val()
 | |
|   %b2 = call i32 @get_val()
 | |
|   %b3 = call i32 @get_val()
 | |
|   %b4 = call i32 @get_val()
 | |
|   %b5 = call i32 @get_val()
 | |
|   %b6 = call i32 @get_val()
 | |
|   %b7 = call i32 @get_val()
 | |
|   %b8 = call i32 @get_val()
 | |
|   call void @use_val(i32 %b1)
 | |
|   call void @use_val(i32 %b2)
 | |
|   call void @use_val(i32 %b3)
 | |
|   call void @use_val(i32 %b4)
 | |
|   call void @use_val(i32 %b5)
 | |
|   call void @use_val(i32 %b6)
 | |
|   call void @use_val(i32 %b7)
 | |
|   call void @use_val(i32 %b8)
 | |
|   call void @longjmp()
 | |
|   unreachable
 | |
| ; X86-32-NOT: movl {{.*}}, [[SPILL_SLOT]](%esp)
 | |
| ; X86-64-NOT: movl {{.*}}, [[SPILL_SLOT]](%rsp)
 | |
| 
 | |
| second:
 | |
|   call void @use_val(i32 %a1)
 | |
|   call void @use_val(i32 %a2)
 | |
|   call void @use_val(i32 %a3)
 | |
|   call void @use_val(i32 %a4)
 | |
|   call void @use_val(i32 %a5)
 | |
|   call void @use_val(i32 %a6)
 | |
|   call void @use_val(i32 %a7)
 | |
|   call void @use_val(i32 %a8)
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| 
 | |
| ; This is the same as above, but using "invoke" rather than "call" to
 | |
| ; call setjmp().
 | |
| 
 | |
| define void @setjmp_invoker() personality void ()* @personality {
 | |
| ; X86-32-LABEL: setjmp_invoker:
 | |
| ; X86-64-LABEL: setjmp_invoker:
 | |
|   %a1 = call i32 @get_val()
 | |
|   %a2 = call i32 @get_val()
 | |
|   %a3 = call i32 @get_val()
 | |
|   %a4 = call i32 @get_val()
 | |
|   %a5 = call i32 @get_val()
 | |
|   %a6 = call i32 @get_val()
 | |
|   %a7 = call i32 @get_val()
 | |
|   %a8 = call i32 @get_val()
 | |
| ; X86-32: movl %eax, [[SPILL_SLOT:[0-9]+]](%esp)
 | |
| ; X86-32: calll get_val
 | |
| ; X86-64: movl %eax, [[SPILL_SLOT:[0-9]+]](%rsp)
 | |
| ; X86-64: callq get_val
 | |
| 
 | |
|   %setjmp_result = invoke i1 @setjmp() returns_twice
 | |
|       to label %cont unwind label %lpad
 | |
| ; X86-32: calll setjmp
 | |
| ; X86-64: callq setjmp
 | |
| 
 | |
| cont:
 | |
|   br i1 %setjmp_result, label %second, label %first
 | |
| 
 | |
| lpad:
 | |
|   %lp = landingpad { i8*, i32 } cleanup
 | |
|   unreachable
 | |
| 
 | |
| first:
 | |
|   %b1 = call i32 @get_val()
 | |
|   %b2 = call i32 @get_val()
 | |
|   %b3 = call i32 @get_val()
 | |
|   %b4 = call i32 @get_val()
 | |
|   %b5 = call i32 @get_val()
 | |
|   %b6 = call i32 @get_val()
 | |
|   %b7 = call i32 @get_val()
 | |
|   %b8 = call i32 @get_val()
 | |
|   call void @use_val(i32 %b1)
 | |
|   call void @use_val(i32 %b2)
 | |
|   call void @use_val(i32 %b3)
 | |
|   call void @use_val(i32 %b4)
 | |
|   call void @use_val(i32 %b5)
 | |
|   call void @use_val(i32 %b6)
 | |
|   call void @use_val(i32 %b7)
 | |
|   call void @use_val(i32 %b8)
 | |
|   call void @longjmp()
 | |
|   unreachable
 | |
| ; X86-32-NOT: movl {{.*}}, [[SPILL_SLOT]](%esp)
 | |
| ; X86-64-NOT: movl {{.*}}, [[SPILL_SLOT]](%rsp)
 | |
| 
 | |
| second:
 | |
|   call void @use_val(i32 %a1)
 | |
|   call void @use_val(i32 %a2)
 | |
|   call void @use_val(i32 %a3)
 | |
|   call void @use_val(i32 %a4)
 | |
|   call void @use_val(i32 %a5)
 | |
|   call void @use_val(i32 %a6)
 | |
|   call void @use_val(i32 %a7)
 | |
|   call void @use_val(i32 %a8)
 | |
|   ret void
 | |
| }
 |