xref: /llvm-project/llvm/test/CodeGen/SystemZ/fp-cmp-04.ll (revision 1d1893097a6319a6402331a54a588b1a5d961808)
1; Test that floating-point compares are omitted if CC already has the
2; right value.
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as | 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, ptr %dest) {
10; CHECK-LABEL: f1:
11; CHECK: aebr %f0, %f2
12; CHECK-NEXT: ber %r14
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, ptr %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, ptr %dest) {
29; CHECK-LABEL: f2:
30; CHECK: aebr %f0, %f2
31; CHECK-NEXT: blr %r14
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, ptr %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, ptr %dest) {
48; CHECK-LABEL: f3:
49; CHECK: aebr %f0, %f2
50; CHECK-NEXT: bhr %r14
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, ptr %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, ptr %dest) {
67; CHECK-LABEL: f4:
68; CHECK: aebr %f0, %f2
69; CHECK-NEXT: bnlhr %r14
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, ptr %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, ptr %dest) {
86; CHECK-LABEL: f5:
87; CHECK: seb %f0, 0(%r2)
88; CHECK-NEXT: bnher %r14
89; CHECK: br %r14
90entry:
91  %cur = load float, ptr %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, ptr %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, ptr %dest) {
106; CHECK-LABEL: f6:
107; CHECK: lpebr %f0, %f2
108; CHECK-NEXT: bhr %r14
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, ptr %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, ptr %dest) {
125; CHECK-LABEL: f7:
126; CHECK: lnebr %f0, %f2
127; CHECK-NEXT: blr %r14
128; CHECK: br %r14
129entry:
130  %abs = call float @llvm.fabs.f32(float %a)
131  %res = fneg float %abs
132  %cmp = fcmp olt float %res, 0.0
133  br i1 %cmp, label %exit, label %store
134
135store:
136  store float %res, ptr %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, ptr %dest) {
145; CHECK-LABEL: f8:
146; CHECK: lcebr %f0, %f2
147; CHECK-NEXT: bler %r14
148; CHECK: br %r14
149entry:
150  %res = fneg float %a
151  %cmp = fcmp ole float %res, 0.0
152  br i1 %cmp, label %exit, label %store
153
154store:
155  store float %res, ptr %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, ptr %dest) {
164; CHECK-LABEL: f9:
165; CHECK: meebr %f0, %f2
166; CHECK-NEXT: ltebr %f1, %f0
167; CHECK-NEXT: blhr %r14
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, ptr %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, ptr %dest) {
185; CHECK-LABEL: f10:
186; CHECK: aebr %f0, %f2
187; CHECK-NEXT: debr %f0, %f4
188; CHECK-NEXT: ltebr %f1, %f0
189; CHECK-NEXT: bner %r14
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, ptr %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, ptr %dest1, ptr %dest2) {
208; CHECK-LABEL: f11:
209; CHECK: aebr %f0, %f2
210; CHECK-NEXT: sebr %f4, %f0
211; CHECK-DAG: ste %f4, 0(%r2)
212; CHECK-DAG: ltebr %f1, %f0
213; CHECK-NEXT: ber %r14
214; CHECK: br %r14
215entry:
216  %add = fadd float %a, %b
217  %sub = fsub float %c, %add
218  store float %sub, ptr %dest1
219  %cmp = fcmp oeq float %add, 0.0
220  br i1 %cmp, label %exit, label %store
221
222store:
223  store float %sub, ptr %dest2
224  br label %exit
225
226exit:
227  ret float %add
228}
229
230; %val in %f2 must be preserved during comparison and also copied to %f0.
231define float @f12(float %dummy, float %val, ptr %dest) {
232; CHECK-LABEL: f12:
233; CHECK: ler %f0, %f2
234; CHECK-NEXT: ltebr %f1, %f2
235; CHECK-NEXT: #APP
236; CHECK-NEXT: blah %f0
237; CHECK-NEXT: #NO_APP
238; CHECK-NEXT: blr %r14
239; CHECK: br %r14
240entry:
241  call void asm sideeffect "blah $0", "{f0}"(float %val)
242  %cmp = fcmp olt float %val, 0.0
243  br i1 %cmp, label %exit, label %store
244
245store:
246  store float %val, ptr %dest
247  br label %exit
248
249exit:
250  ret float %val
251}
252
253; Same for double.
254define double @f13(double %dummy, double %val, ptr %dest) {
255; CHECK-LABEL: f13:
256; CHECK: ldr %f0, %f2
257; CHECK-NEXT: ltdbr %f1, %f2
258; CHECK-NEXT: #APP
259; CHECK-NEXT: blah %f0
260; CHECK-NEXT: #NO_APP
261; CHECK-NEXT: blr %r14
262; CHECK: br %r14
263entry:
264  call void asm sideeffect "blah $0", "{f0}"(double %val)
265  %cmp = fcmp olt double %val, 0.0
266  br i1 %cmp, label %exit, label %store
267
268store:
269  store double %val, ptr %dest
270  br label %exit
271
272exit:
273  ret double %val
274}
275
276; LXR cannot be converted to LTXBR as its input is live after it.
277define void @f14(ptr %ptr1, ptr %ptr2) {
278; CHECK-LABEL: f14:
279; CHECK: lxr
280; CHECK-NEXT: dxbr
281; CHECK-NEXT: std
282; CHECK-NEXT: std
283; CHECK-NEXT: mxbr
284; CHECK-NEXT: ltxbr
285; CHECK-NEXT: std
286; CHECK-NEXT: std
287; CHECK-NEXT: blr %r14
288; CHECK: br %r14
289entry:
290  %val1 = load fp128, ptr %ptr1
291  %val2 = load fp128, ptr %ptr2
292  %div = fdiv fp128 %val1, %val2
293  store fp128 %div, ptr %ptr1
294  %mul = fmul fp128 %val1, %val2
295  store fp128 %mul, ptr %ptr2
296  %cmp = fcmp olt fp128 %val1, 0xL00000000000000000000000000000000
297  br i1 %cmp, label %exit, label %store
298
299store:
300  call void asm sideeffect "blah", ""()
301  br label %exit
302
303exit:
304  ret void
305}
306
307define float @f15(float %val, float %dummy, ptr %dest) {
308; CHECK-LABEL: f15:
309; CHECK: ltebr %f1, %f0
310; CHECK-NEXT: ler %f2, %f0
311; CHECK-NEXT: #APP
312; CHECK-NEXT: blah %f2
313; CHECK-NEXT: #NO_APP
314; CHECK-NEXT: blr %r14
315; CHECK: br %r14
316entry:
317  call void asm sideeffect "blah $0", "{f2}"(float %val)
318  %cmp = fcmp olt float %val, 0.0
319  br i1 %cmp, label %exit, label %store
320
321store:
322  store float %val, ptr %dest
323  br label %exit
324
325exit:
326  ret float %val
327}
328
329define double @f16(double %val, double %dummy, ptr %dest) {
330; CHECK-LABEL: f16:
331; CHECK: ltdbr %f1, %f0
332; CHECK: ldr %f2, %f0
333; CHECK-NEXT: #APP
334; CHECK-NEXT: blah %f2
335; CHECK-NEXT: #NO_APP
336; CHECK-NEXT: blr %r14
337; CHECK: br %r14
338entry:
339  call void asm sideeffect "blah $0", "{f2}"(double %val)
340  %cmp = fcmp olt double %val, 0.0
341  br i1 %cmp, label %exit, label %store
342
343store:
344  store double %val, ptr %dest
345  br label %exit
346
347exit:
348  ret double %val
349}
350
351; Repeat f2 with a comparison against -0.
352define float @f17(float %a, float %b, ptr %dest) {
353; CHECK-LABEL: f17:
354; CHECK: aebr %f0, %f2
355; CHECK-NEXT: blr %r14
356; CHECK: br %r14
357entry:
358  %res = fadd float %a, %b
359  %cmp = fcmp olt float %res, -0.0
360  br i1 %cmp, label %exit, label %store
361
362store:
363  store float %b, ptr %dest
364  br label %exit
365
366exit:
367  ret float %res
368}
369
370; Test another form of f7 in which the condition is based on the unnegated
371; result.  This is what InstCombine would produce.
372define float @f18(float %dummy, float %a, ptr %dest) {
373; CHECK-LABEL: f18:
374; CHECK:       # %bb.0: # %entry
375; CHECK-NEXT:    lnebr %f0, %f2
376; CHECK-NEXT:    blr %r14
377; CHECK-NEXT:  .LBB17_1: # %store
378; CHECK-NEXT:    ste %f0, 0(%r2)
379; CHECK-NEXT:    br %r14
380entry:
381  %abs = call float @llvm.fabs.f32(float %a)
382  %res = fneg float %abs
383  %cmp = fcmp ogt float %abs, 0.0
384  br i1 %cmp, label %exit, label %store
385
386store:
387  store float %res, ptr %dest
388  br label %exit
389
390exit:
391  ret float %res
392}
393
394; Similarly for f8.
395define float @f19(float %dummy, float %a, ptr %dest) {
396; CHECK-LABEL: f19:
397; CHECK:       # %bb.0: # %entry
398; CHECK-NEXT:    lcebr %f0, %f2
399; CHECK-NEXT:    bler %r14
400; CHECK-NEXT:  .LBB18_1: # %store
401; CHECK-NEXT:    ste %f0, 0(%r2)
402; CHECK-NEXT:    br %r14
403entry:
404  %res = fneg float %a
405  %cmp = fcmp oge float %a, 0.0
406  br i1 %cmp, label %exit, label %store
407
408store:
409  store float %res, ptr %dest
410  br label %exit
411
412exit:
413  ret float %res
414}
415