[SystemZ] Make more use of TMHH
[oota-llvm.git] / test / CodeGen / SystemZ / frame-05.ll
1 ; Test saving and restoring of call-saved GPRs.
2 ;
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5 ; This function should require all GPRs, but no other spill slots.  The caller
6 ; allocates room for the GPR save slots, so we shouldn't need to allocate any
7 ; extra space.
8 ;
9 ; The function only modifies the low 32 bits of each register, which in
10 ; itself would allow STM and LM to be used instead of STMG and LMG.
11 ; However, the ABI defines the offset of each register, so we always
12 ; use the 64-bit form.
13 ;
14 ; Use a different address for the final store, so that we can check that
15 ; %r15 isn't referenced again until after that.
16 define void @f1(i32 *%ptr) {
17 ; CHECK-LABEL: f1:
18 ; CHECK: stmg %r6, %r15, 48(%r15)
19 ; CHECK-NOT: %r15
20 ; CHECK: .cfi_offset %r6, -112
21 ; CHECK: .cfi_offset %r7, -104
22 ; CHECK: .cfi_offset %r8, -96
23 ; CHECK: .cfi_offset %r9, -88
24 ; CHECK: .cfi_offset %r10, -80
25 ; CHECK: .cfi_offset %r11, -72
26 ; CHECK: .cfi_offset %r12, -64
27 ; CHECK: .cfi_offset %r13, -56
28 ; CHECK: .cfi_offset %r14, -48
29 ; CHECK: .cfi_offset %r15, -40
30 ; ...main function body...
31 ; CHECK-NOT: %r15
32 ; CHECK: st {{.*}}, 4(%r2)
33 ; CHECK: lmg %r6, %r15, 48(%r15)
34 ; CHECK: br %r14
35   %l0 = load volatile i32 *%ptr
36   %l1 = load volatile i32 *%ptr
37   %l3 = load volatile i32 *%ptr
38   %l4 = load volatile i32 *%ptr
39   %l5 = load volatile i32 *%ptr
40   %l6 = load volatile i32 *%ptr
41   %l7 = load volatile i32 *%ptr
42   %l8 = load volatile i32 *%ptr
43   %l9 = load volatile i32 *%ptr
44   %l10 = load volatile i32 *%ptr
45   %l11 = load volatile i32 *%ptr
46   %l12 = load volatile i32 *%ptr
47   %l13 = load volatile i32 *%ptr
48   %l14 = load volatile i32 *%ptr
49   %add0 = add i32 %l0, %l0
50   %add1 = add i32 %l1, %add0
51   %add3 = add i32 %l3, %add1
52   %add4 = add i32 %l4, %add3
53   %add5 = add i32 %l5, %add4
54   %add6 = add i32 %l6, %add5
55   %add7 = add i32 %l7, %add6
56   %add8 = add i32 %l8, %add7
57   %add9 = add i32 %l9, %add8
58   %add10 = add i32 %l10, %add9
59   %add11 = add i32 %l11, %add10
60   %add12 = add i32 %l12, %add11
61   %add13 = add i32 %l13, %add12
62   %add14 = add i32 %l14, %add13
63   store volatile i32 %add0, i32 *%ptr
64   store volatile i32 %add1, i32 *%ptr
65   store volatile i32 %add3, i32 *%ptr
66   store volatile i32 %add4, i32 *%ptr
67   store volatile i32 %add5, i32 *%ptr
68   store volatile i32 %add6, i32 *%ptr
69   store volatile i32 %add7, i32 *%ptr
70   store volatile i32 %add8, i32 *%ptr
71   store volatile i32 %add9, i32 *%ptr
72   store volatile i32 %add10, i32 *%ptr
73   store volatile i32 %add11, i32 *%ptr
74   store volatile i32 %add12, i32 *%ptr
75   store volatile i32 %add13, i32 *%ptr
76   %final = getelementptr i32 *%ptr, i32 1
77   store volatile i32 %add14, i32 *%final
78   ret void
79 }
80
81 ; Like f1, but requires one fewer GPR.  We allocate the call-saved GPRs
82 ; from %r14 down, so that the STMG/LMG sequences aren't any longer than
83 ; they need to be.
84 define void @f2(i32 *%ptr) {
85 ; CHECK-LABEL: f2:
86 ; CHECK: stmg %r7, %r15, 56(%r15)
87 ; CHECK-NOT: %r15
88 ; CHECK: .cfi_offset %r7, -104
89 ; CHECK: .cfi_offset %r8, -96
90 ; CHECK: .cfi_offset %r9, -88
91 ; CHECK: .cfi_offset %r10, -80
92 ; CHECK: .cfi_offset %r11, -72
93 ; CHECK: .cfi_offset %r12, -64
94 ; CHECK: .cfi_offset %r13, -56
95 ; CHECK: .cfi_offset %r14, -48
96 ; CHECK: .cfi_offset %r15, -40
97 ; ...main function body...
98 ; CHECK-NOT: %r15
99 ; CHECK-NOT: %r6
100 ; CHECK: st {{.*}}, 4(%r2)
101 ; CHECK: lmg %r7, %r15, 56(%r15)
102 ; CHECK: br %r14
103   %l0 = load volatile i32 *%ptr
104   %l1 = load volatile i32 *%ptr
105   %l3 = load volatile i32 *%ptr
106   %l4 = load volatile i32 *%ptr
107   %l5 = load volatile i32 *%ptr
108   %l7 = load volatile i32 *%ptr
109   %l8 = load volatile i32 *%ptr
110   %l9 = load volatile i32 *%ptr
111   %l10 = load volatile i32 *%ptr
112   %l11 = load volatile i32 *%ptr
113   %l12 = load volatile i32 *%ptr
114   %l13 = load volatile i32 *%ptr
115   %l14 = load volatile i32 *%ptr
116   %add0 = add i32 %l0, %l0
117   %add1 = add i32 %l1, %add0
118   %add3 = add i32 %l3, %add1
119   %add4 = add i32 %l4, %add3
120   %add5 = add i32 %l5, %add4
121   %add7 = add i32 %l7, %add5
122   %add8 = add i32 %l8, %add7
123   %add9 = add i32 %l9, %add8
124   %add10 = add i32 %l10, %add9
125   %add11 = add i32 %l11, %add10
126   %add12 = add i32 %l12, %add11
127   %add13 = add i32 %l13, %add12
128   %add14 = add i32 %l14, %add13
129   store volatile i32 %add0, i32 *%ptr
130   store volatile i32 %add1, i32 *%ptr
131   store volatile i32 %add3, i32 *%ptr
132   store volatile i32 %add4, i32 *%ptr
133   store volatile i32 %add5, i32 *%ptr
134   store volatile i32 %add7, i32 *%ptr
135   store volatile i32 %add8, i32 *%ptr
136   store volatile i32 %add9, i32 *%ptr
137   store volatile i32 %add10, i32 *%ptr
138   store volatile i32 %add11, i32 *%ptr
139   store volatile i32 %add12, i32 *%ptr
140   store volatile i32 %add13, i32 *%ptr
141   %final = getelementptr i32 *%ptr, i32 1
142   store volatile i32 %add14, i32 *%final
143   ret void
144 }
145
146 ; Like f1, but only needs one call-saved GPR, which ought to be %r14.
147 define void @f3(i32 *%ptr) {
148 ; CHECK-LABEL: f3:
149 ; CHECK: stmg %r14, %r15, 112(%r15)
150 ; CHECK-NOT: %r15
151 ; CHECK: .cfi_offset %r14, -48
152 ; CHECK: .cfi_offset %r15, -40
153 ; ...main function body...
154 ; CHECK-NOT: %r15
155 ; CHECK-NOT: %r6
156 ; CHECK-NOT: %r7
157 ; CHECK-NOT: %r8
158 ; CHECK-NOT: %r9
159 ; CHECK-NOT: %r10
160 ; CHECK-NOT: %r11
161 ; CHECK-NOT: %r12
162 ; CHECK-NOT: %r13
163 ; CHECK: st {{.*}}, 4(%r2)
164 ; CHECK: lmg %r14, %r15, 112(%r15)
165 ; CHECK: br %r14
166   %l0 = load volatile i32 *%ptr
167   %l1 = load volatile i32 *%ptr
168   %l3 = load volatile i32 *%ptr
169   %l4 = load volatile i32 *%ptr
170   %l5 = load volatile i32 *%ptr
171   %l14 = load volatile i32 *%ptr
172   %add0 = add i32 %l0, %l0
173   %add1 = add i32 %l1, %add0
174   %add3 = add i32 %l3, %add1
175   %add4 = add i32 %l4, %add3
176   %add5 = add i32 %l5, %add4
177   %add14 = add i32 %l14, %add5
178   store volatile i32 %add0, i32 *%ptr
179   store volatile i32 %add1, i32 *%ptr
180   store volatile i32 %add3, i32 *%ptr
181   store volatile i32 %add4, i32 *%ptr
182   store volatile i32 %add5, i32 *%ptr
183   %final = getelementptr i32 *%ptr, i32 1
184   store volatile i32 %add14, i32 *%final
185   ret void
186 }
187
188 ; This function should use all call-clobbered GPRs but no call-saved ones.
189 ; It shouldn't need to touch the stack at all.
190 define void @f4(i32 *%ptr) {
191 ; CHECK-LABEL: f4:
192 ; CHECK-NOT: %r15
193 ; CHECK-NOT: %r6
194 ; CHECK-NOT: %r7
195 ; CHECK-NOT: %r8
196 ; CHECK-NOT: %r9
197 ; CHECK-NOT: %r10
198 ; CHECK-NOT: %r11
199 ; CHECK-NOT: %r12
200 ; CHECK-NOT: %r13
201 ; CHECK: br %r14
202   %l0 = load volatile i32 *%ptr
203   %l1 = load volatile i32 *%ptr
204   %l3 = load volatile i32 *%ptr
205   %l4 = load volatile i32 *%ptr
206   %l5 = load volatile i32 *%ptr
207   %add0 = add i32 %l0, %l0
208   %add1 = add i32 %l1, %add0
209   %add3 = add i32 %l3, %add1
210   %add4 = add i32 %l4, %add3
211   %add5 = add i32 %l5, %add4
212   store volatile i32 %add0, i32 *%ptr
213   store volatile i32 %add1, i32 *%ptr
214   store volatile i32 %add3, i32 *%ptr
215   store volatile i32 %add4, i32 *%ptr
216   %final = getelementptr i32 *%ptr, i32 1
217   store volatile i32 %add5, i32 *%final
218   ret void
219 }