| ; 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 |
| } |