blob: 781a3beb4d4d8ac04be30d675a4faf691cce4813 [file] [log] [blame]
Alp Tokercb402912014-01-24 17:20:08 +00001; Test that floating-point compares are omitted if CC already has the
Richard Sandiford0897fce2013-08-07 11:10:06 +00002; right value.
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
5
6declare float @llvm.fabs.f32(float %f)
7
8; Test addition followed by EQ, which can use the CC result of the addition.
9define float @f1(float %a, float %b, float *%dest) {
10; CHECK-LABEL: f1:
11; CHECK: aebr %f0, %f2
12; CHECK-NEXT: je .L{{.*}}
13; CHECK: br %r14
14entry:
15 %res = fadd float %a, %b
16 %cmp = fcmp oeq float %res, 0.0
17 br i1 %cmp, label %exit, label %store
18
19store:
20 store float %b, float *%dest
21 br label %exit
22
23exit:
24 ret float %res
25}
26
27; ...and again with LT.
28define float @f2(float %a, float %b, float *%dest) {
29; CHECK-LABEL: f2:
30; CHECK: aebr %f0, %f2
31; CHECK-NEXT: jl .L{{.*}}
32; CHECK: br %r14
33entry:
34 %res = fadd float %a, %b
35 %cmp = fcmp olt float %res, 0.0
36 br i1 %cmp, label %exit, label %store
37
38store:
39 store float %b, float *%dest
40 br label %exit
41
42exit:
43 ret float %res
44}
45
46; ...and again with GT.
47define float @f3(float %a, float %b, float *%dest) {
48; CHECK-LABEL: f3:
49; CHECK: aebr %f0, %f2
50; CHECK-NEXT: jh .L{{.*}}
51; CHECK: br %r14
52entry:
53 %res = fadd float %a, %b
54 %cmp = fcmp ogt float %res, 0.0
55 br i1 %cmp, label %exit, label %store
56
57store:
58 store float %b, float *%dest
59 br label %exit
60
61exit:
62 ret float %res
63}
64
65; ...and again with UEQ.
66define float @f4(float %a, float %b, float *%dest) {
67; CHECK-LABEL: f4:
68; CHECK: aebr %f0, %f2
69; CHECK-NEXT: jnlh .L{{.*}}
70; CHECK: br %r14
71entry:
72 %res = fadd float %a, %b
73 %cmp = fcmp ueq float %res, 0.0
74 br i1 %cmp, label %exit, label %store
75
76store:
77 store float %b, float *%dest
78 br label %exit
79
80exit:
81 ret float %res
82}
83
84; Subtraction also provides a zero-based CC value.
85define float @f5(float %a, float %b, float *%dest) {
86; CHECK-LABEL: f5:
87; CHECK: seb %f0, 0(%r2)
88; CHECK-NEXT: jnhe .L{{.*}}
89; CHECK: br %r14
90entry:
91 %cur = load float *%dest
92 %res = fsub float %a, %cur
93 %cmp = fcmp ult float %res, 0.0
94 br i1 %cmp, label %exit, label %store
95
96store:
97 store float %b, float *%dest
98 br label %exit
99
100exit:
101 ret float %res
102}
103
104; Test the result of LOAD POSITIVE.
105define float @f6(float %dummy, float %a, float *%dest) {
106; CHECK-LABEL: f6:
107; CHECK: lpebr %f0, %f2
108; CHECK-NEXT: jh .L{{.*}}
109; CHECK: br %r14
110entry:
111 %res = call float @llvm.fabs.f32(float %a)
112 %cmp = fcmp ogt float %res, 0.0
113 br i1 %cmp, label %exit, label %store
114
115store:
116 store float %res, float *%dest
117 br label %exit
118
119exit:
120 ret float %res
121}
122
123; Test the result of LOAD NEGATIVE.
124define float @f7(float %dummy, float %a, float *%dest) {
125; CHECK-LABEL: f7:
126; CHECK: lnebr %f0, %f2
127; CHECK-NEXT: jl .L{{.*}}
128; CHECK: br %r14
129entry:
130 %abs = call float @llvm.fabs.f32(float %a)
131 %res = fsub float -0.0, %abs
132 %cmp = fcmp olt float %res, 0.0
133 br i1 %cmp, label %exit, label %store
134
135store:
136 store float %res, float *%dest
137 br label %exit
138
139exit:
140 ret float %res
141}
142
143; Test the result of LOAD COMPLEMENT.
144define float @f8(float %dummy, float %a, float *%dest) {
145; CHECK-LABEL: f8:
146; CHECK: lcebr %f0, %f2
147; CHECK-NEXT: jle .L{{.*}}
148; CHECK: br %r14
149entry:
150 %res = fsub float -0.0, %a
151 %cmp = fcmp ole float %res, 0.0
152 br i1 %cmp, label %exit, label %store
153
154store:
155 store float %res, float *%dest
156 br label %exit
157
158exit:
159 ret float %res
160}
161
162; Multiplication (for example) does not modify CC.
163define float @f9(float %a, float %b, float *%dest) {
164; CHECK-LABEL: f9:
165; CHECK: meebr %f0, %f2
166; CHECK-NEXT: ltebr %f0, %f0
167; CHECK-NEXT: jlh .L{{.*}}
168; CHECK: br %r14
169entry:
170 %res = fmul float %a, %b
171 %cmp = fcmp one float %res, 0.0
172 br i1 %cmp, label %exit, label %store
173
174store:
175 store float %b, float *%dest
176 br label %exit
177
178exit:
179 ret float %res
180}
181
182; Test a combination involving a CC-setting instruction followed by
183; a non-CC-setting instruction.
184define float @f10(float %a, float %b, float %c, float *%dest) {
185; CHECK-LABEL: f10:
186; CHECK: aebr %f0, %f2
187; CHECK-NEXT: debr %f0, %f4
188; CHECK-NEXT: ltebr %f0, %f0
189; CHECK-NEXT: jne .L{{.*}}
190; CHECK: br %r14
191entry:
192 %add = fadd float %a, %b
193 %res = fdiv float %add, %c
194 %cmp = fcmp une float %res, 0.0
195 br i1 %cmp, label %exit, label %store
196
197store:
198 store float %b, float *%dest
199 br label %exit
200
201exit:
202 ret float %res
203}
204
205; Test a case where CC is set based on a different register from the
206; compare input.
207define float @f11(float %a, float %b, float %c, float *%dest1, float *%dest2) {
208; CHECK-LABEL: f11:
209; CHECK: aebr %f0, %f2
210; CHECK-NEXT: sebr %f4, %f0
211; CHECK-NEXT: ste %f4, 0(%r2)
212; CHECK-NEXT: ltebr %f0, %f0
213; CHECK-NEXT: je .L{{.*}}
214; CHECK: br %r14
215entry:
216 %add = fadd float %a, %b
217 %sub = fsub float %c, %add
218 store float %sub, float *%dest1
219 %cmp = fcmp oeq float %add, 0.0
220 br i1 %cmp, label %exit, label %store
221
222store:
223 store float %sub, float *%dest2
224 br label %exit
225
226exit:
227 ret float %add
228}
229
230; Test that LER gets converted to LTEBR where useful.
231define float @f12(float %dummy, float %val, float *%dest) {
232; CHECK-LABEL: f12:
233; CHECK: ltebr %f0, %f2
234; CHECK-NEXT: #APP
235; CHECK-NEXT: blah %f0
236; CHECK-NEXT: #NO_APP
237; CHECK-NEXT: jl .L{{.*}}
238; CHECK: br %r14
239entry:
240 call void asm sideeffect "blah $0", "{f0}"(float %val)
241 %cmp = fcmp olt float %val, 0.0
242 br i1 %cmp, label %exit, label %store
243
244store:
245 store float %val, float *%dest
246 br label %exit
247
248exit:
249 ret float %val
250}
251
252; Test that LDR gets converted to LTDBR where useful.
253define double @f13(double %dummy, double %val, double *%dest) {
254; CHECK-LABEL: f13:
255; CHECK: ltdbr %f0, %f2
256; CHECK-NEXT: #APP
257; CHECK-NEXT: blah %f0
258; CHECK-NEXT: #NO_APP
259; CHECK-NEXT: jl .L{{.*}}
260; CHECK: br %r14
261entry:
262 call void asm sideeffect "blah $0", "{f0}"(double %val)
263 %cmp = fcmp olt double %val, 0.0
264 br i1 %cmp, label %exit, label %store
265
266store:
267 store double %val, double *%dest
268 br label %exit
269
270exit:
271 ret double %val
272}
273
274; Test that LXR gets converted to LTXBR where useful.
275define void @f14(fp128 *%ptr1, fp128 *%ptr2) {
276; CHECK-LABEL: f14:
277; CHECK: ltxbr
278; CHECK-NEXT: dxbr
279; CHECK-NEXT: std
280; CHECK-NEXT: std
281; CHECK-NEXT: mxbr
282; CHECK-NEXT: std
283; CHECK-NEXT: std
284; CHECK-NEXT: jl .L{{.*}}
285; CHECK: br %r14
286entry:
287 %val1 = load fp128 *%ptr1
288 %val2 = load fp128 *%ptr2
289 %div = fdiv fp128 %val1, %val2
290 store fp128 %div, fp128 *%ptr1
291 %mul = fmul fp128 %val1, %val2
292 store fp128 %mul, fp128 *%ptr2
293 %cmp = fcmp olt fp128 %val1, 0xL00000000000000000000000000000000
294 br i1 %cmp, label %exit, label %store
295
296store:
297 call void asm sideeffect "blah", ""()
298 br label %exit
299
300exit:
301 ret void
302}
303
304; Test a case where it is the source rather than destination of LER that
305; we need.
306define float @f15(float %val, float %dummy, float *%dest) {
307; CHECK-LABEL: f15:
308; CHECK: ltebr %f2, %f0
309; CHECK-NEXT: #APP
310; CHECK-NEXT: blah %f2
311; CHECK-NEXT: #NO_APP
312; CHECK-NEXT: jl .L{{.*}}
313; CHECK: br %r14
314entry:
315 call void asm sideeffect "blah $0", "{f2}"(float %val)
316 %cmp = fcmp olt float %val, 0.0
317 br i1 %cmp, label %exit, label %store
318
319store:
320 store float %val, float *%dest
321 br label %exit
322
323exit:
324 ret float %val
325}
326
327; Test a case where it is the source rather than destination of LDR that
328; we need.
329define double @f16(double %val, double %dummy, double *%dest) {
330; CHECK-LABEL: f16:
331; CHECK: ltdbr %f2, %f0
332; CHECK-NEXT: #APP
333; CHECK-NEXT: blah %f2
334; CHECK-NEXT: #NO_APP
335; CHECK-NEXT: jl .L{{.*}}
336; CHECK: br %r14
337entry:
338 call void asm sideeffect "blah $0", "{f2}"(double %val)
339 %cmp = fcmp olt double %val, 0.0
340 br i1 %cmp, label %exit, label %store
341
342store:
343 store double %val, double *%dest
344 br label %exit
345
346exit:
347 ret double %val
348}
Richard Sandiford198ddf82013-12-06 09:59:12 +0000349
350; Repeat f2 with a comparison against -0.
351define float @f17(float %a, float %b, float *%dest) {
352; CHECK-LABEL: f17:
353; CHECK: aebr %f0, %f2
354; CHECK-NEXT: jl .L{{.*}}
355; CHECK: br %r14
356entry:
357 %res = fadd float %a, %b
358 %cmp = fcmp olt float %res, -0.0
359 br i1 %cmp, label %exit, label %store
360
361store:
362 store float %b, float *%dest
363 br label %exit
364
365exit:
366 ret float %res
367}
Richard Sandiford73170f82013-12-11 11:45:08 +0000368
369; Test another form of f7 in which the condition is based on the unnegated
370; result. This is what InstCombine would produce.
371define float @f18(float %dummy, float %a, float *%dest) {
372; CHECK-LABEL: f18:
373; CHECK: lnebr %f0, %f2
374; CHECK-NEXT: jl .L{{.*}}
375; CHECK: br %r14
376entry:
377 %abs = call float @llvm.fabs.f32(float %a)
378 %res = fsub float -0.0, %abs
379 %cmp = fcmp ogt float %abs, 0.0
380 br i1 %cmp, label %exit, label %store
381
382store:
383 store float %res, float *%dest
384 br label %exit
385
386exit:
387 ret float %res
388}
389
390; Similarly for f8.
391define float @f19(float %dummy, float %a, float *%dest) {
392; CHECK-LABEL: f19:
393; CHECK: lcebr %f0, %f2
394; CHECK-NEXT: jle .L{{.*}}
395; CHECK: br %r14
396entry:
397 %res = fsub float -0.0, %a
398 %cmp = fcmp oge float %a, 0.0
399 br i1 %cmp, label %exit, label %store
400
401store:
402 store float %res, float *%dest
403 br label %exit
404
405exit:
406 ret float %res
407}