1; RUN: llc < %s -mtriple=i386-linux | FileCheck %s -check-prefix=X86-32
2; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=X86-64
3
4declare i32 @get_val()
5declare void @use_val(i32)
6declare i1 @setjmp()
7declare void @longjmp()
8declare void @personality()
9
10
11; Test that llc avoids reusing spill slots in functions that call
12; setjmp(), whether they use "call" or "invoke" for calling setjmp()
13; (PR18244).
14
15define void @setjmp_caller() {
16; X86-32-LABEL: setjmp_caller:
17; X86-64-LABEL: setjmp_caller:
18; This code keeps enough variables live across the setjmp() call that
19; they don't all fit in registers and the compiler will allocate a
20; spill slot.
21  %a1 = call i32 @get_val()
22  %a2 = call i32 @get_val()
23  %a3 = call i32 @get_val()
24  %a4 = call i32 @get_val()
25  %a5 = call i32 @get_val()
26  %a6 = call i32 @get_val()
27  %a7 = call i32 @get_val()
28  %a8 = call i32 @get_val()
29; X86-32: movl %eax, [[SPILL_SLOT:[0-9]+]](%esp)
30; X86-32: calll get_val
31; X86-64: movl %eax, [[SPILL_SLOT:[0-9]+]](%rsp)
32; X86-64: callq get_val
33
34  %setjmp_result = call i1 @setjmp() returns_twice
35  br i1 %setjmp_result, label %second, label %first
36; X86-32: calll setjmp
37; X86-64: callq setjmp
38
39; Again, keep enough variables live that they need spill slots.  Since
40; this function calls a returns_twice function (setjmp()), the
41; compiler should not reuse the spill slots.  longjmp() can return to
42; where the first spill slots were still live.
43first:
44  %b1 = call i32 @get_val()
45  %b2 = call i32 @get_val()
46  %b3 = call i32 @get_val()
47  %b4 = call i32 @get_val()
48  %b5 = call i32 @get_val()
49  %b6 = call i32 @get_val()
50  %b7 = call i32 @get_val()
51  %b8 = call i32 @get_val()
52  call void @use_val(i32 %b1)
53  call void @use_val(i32 %b2)
54  call void @use_val(i32 %b3)
55  call void @use_val(i32 %b4)
56  call void @use_val(i32 %b5)
57  call void @use_val(i32 %b6)
58  call void @use_val(i32 %b7)
59  call void @use_val(i32 %b8)
60  call void @longjmp()
61  unreachable
62; X86-32-NOT: movl {{.*}}, [[SPILL_SLOT]](%esp)
63; X86-64-NOT: movl {{.*}}, [[SPILL_SLOT]](%rsp)
64
65second:
66  call void @use_val(i32 %a1)
67  call void @use_val(i32 %a2)
68  call void @use_val(i32 %a3)
69  call void @use_val(i32 %a4)
70  call void @use_val(i32 %a5)
71  call void @use_val(i32 %a6)
72  call void @use_val(i32 %a7)
73  call void @use_val(i32 %a8)
74  ret void
75}
76
77
78; This is the same as above, but using "invoke" rather than "call" to
79; call setjmp().
80
81define void @setjmp_invoker() {
82; X86-32-LABEL: setjmp_invoker:
83; X86-64-LABEL: setjmp_invoker:
84  %a1 = call i32 @get_val()
85  %a2 = call i32 @get_val()
86  %a3 = call i32 @get_val()
87  %a4 = call i32 @get_val()
88  %a5 = call i32 @get_val()
89  %a6 = call i32 @get_val()
90  %a7 = call i32 @get_val()
91  %a8 = call i32 @get_val()
92; X86-32: movl %eax, [[SPILL_SLOT:[0-9]+]](%esp)
93; X86-32: calll get_val
94; X86-64: movl %eax, [[SPILL_SLOT:[0-9]+]](%rsp)
95; X86-64: callq get_val
96
97  %setjmp_result = invoke i1 @setjmp() returns_twice
98      to label %cont unwind label %lpad
99; X86-32: calll setjmp
100; X86-64: callq setjmp
101
102cont:
103  br i1 %setjmp_result, label %second, label %first
104
105lpad:
106  %lp = landingpad { i8*, i32 } personality void ()* @personality cleanup
107  unreachable
108
109first:
110  %b1 = call i32 @get_val()
111  %b2 = call i32 @get_val()
112  %b3 = call i32 @get_val()
113  %b4 = call i32 @get_val()
114  %b5 = call i32 @get_val()
115  %b6 = call i32 @get_val()
116  %b7 = call i32 @get_val()
117  %b8 = call i32 @get_val()
118  call void @use_val(i32 %b1)
119  call void @use_val(i32 %b2)
120  call void @use_val(i32 %b3)
121  call void @use_val(i32 %b4)
122  call void @use_val(i32 %b5)
123  call void @use_val(i32 %b6)
124  call void @use_val(i32 %b7)
125  call void @use_val(i32 %b8)
126  call void @longjmp()
127  unreachable
128; X86-32-NOT: movl {{.*}}, [[SPILL_SLOT]](%esp)
129; X86-64-NOT: movl {{.*}}, [[SPILL_SLOT]](%rsp)
130
131second:
132  call void @use_val(i32 %a1)
133  call void @use_val(i32 %a2)
134  call void @use_val(i32 %a3)
135  call void @use_val(i32 %a4)
136  call void @use_val(i32 %a5)
137  call void @use_val(i32 %a6)
138  call void @use_val(i32 %a7)
139  call void @use_val(i32 %a8)
140  ret void
141}
142