1 ; RUN: llc < %s -march=x86-64 -asm-verbose=false | FileCheck %s
3 ; Some of these patterns can be matched as SSE min or max. Some of
4 ; then can be matched provided that the operands are swapped.
5 ; Some of them can't be matched at all and require a comparison
6 ; and a conditional branch.
8 ; The naming convention is {,x_}{o,u}{gt,lt,ge,le}{,_inverse}
9 ; x_ : use 0.0 instead of %y
10 ; _inverse : swap the arms of the select.
13 ; CHECK-NEXT: maxsd %xmm1, %xmm0
15 define double @ogt(double %x, double %y) nounwind {
16 %c = fcmp ogt double %x, %y
17 %d = select i1 %c, double %x, double %y
22 ; CHECK-NEXT: minsd %xmm1, %xmm0
24 define double @olt(double %x, double %y) nounwind {
25 %c = fcmp olt double %x, %y
26 %d = select i1 %c, double %x, double %y
31 ; CHECK-NEXT: minsd %xmm0, %xmm1
32 ; CHECK-NEXT: movapd %xmm1, %xmm0
34 define double @ogt_inverse(double %x, double %y) nounwind {
35 %c = fcmp ogt double %x, %y
36 %d = select i1 %c, double %y, double %x
41 ; CHECK-NEXT: maxsd %xmm0, %xmm1
42 ; CHECK-NEXT: movapd %xmm1, %xmm0
44 define double @olt_inverse(double %x, double %y) nounwind {
45 %c = fcmp olt double %x, %y
46 %d = select i1 %c, double %y, double %x
51 ; CHECK-NEXT: ucomisd %xmm1, %xmm0
52 define double @oge(double %x, double %y) nounwind {
53 %c = fcmp oge double %x, %y
54 %d = select i1 %c, double %x, double %y
59 ; CHECK-NEXT: ucomisd %xmm0, %xmm1
60 define double @ole(double %x, double %y) nounwind {
61 %c = fcmp ole double %x, %y
62 %d = select i1 %c, double %x, double %y
67 ; CHECK-NEXT: ucomisd %xmm1, %xmm0
68 define double @oge_inverse(double %x, double %y) nounwind {
69 %c = fcmp oge double %x, %y
70 %d = select i1 %c, double %y, double %x
75 ; CHECK-NEXT: ucomisd %xmm0, %xmm1
76 define double @ole_inverse(double %x, double %y) nounwind {
77 %c = fcmp ole double %x, %y
78 %d = select i1 %c, double %y, double %x
83 ; CHECK-NEXT: pxor %xmm1, %xmm1
84 ; CHECK-NEXT: maxsd %xmm1, %xmm0
86 define double @x_ogt(double %x) nounwind {
87 %c = fcmp ogt double %x, 0.000000e+00
88 %d = select i1 %c, double %x, double 0.000000e+00
93 ; CHECK-NEXT: pxor %xmm1, %xmm1
94 ; CHECK-NEXT: minsd %xmm1, %xmm0
96 define double @x_olt(double %x) nounwind {
97 %c = fcmp olt double %x, 0.000000e+00
98 %d = select i1 %c, double %x, double 0.000000e+00
102 ; CHECK: x_ogt_inverse:
103 ; CHECK-NEXT: pxor %xmm1, %xmm1
104 ; CHECK-NEXT: minsd %xmm0, %xmm1
105 ; CHECK-NEXT: movapd %xmm1, %xmm0
107 define double @x_ogt_inverse(double %x) nounwind {
108 %c = fcmp ogt double %x, 0.000000e+00
109 %d = select i1 %c, double 0.000000e+00, double %x
113 ; CHECK: x_olt_inverse:
114 ; CHECK-NEXT: pxor %xmm1, %xmm1
115 ; CHECK-NEXT: maxsd %xmm0, %xmm1
116 ; CHECK-NEXT: movapd %xmm1, %xmm0
118 define double @x_olt_inverse(double %x) nounwind {
119 %c = fcmp olt double %x, 0.000000e+00
120 %d = select i1 %c, double 0.000000e+00, double %x
125 ; CHECK-NEXT: pxor %xmm1, %xmm1
126 ; CHECK-NEXT: maxsd %xmm1, %xmm0
128 define double @x_oge(double %x) nounwind {
129 %c = fcmp oge double %x, 0.000000e+00
130 %d = select i1 %c, double %x, double 0.000000e+00
135 ; CHECK-NEXT: pxor %xmm1, %xmm1
136 ; CHECK-NEXT: minsd %xmm1, %xmm0
138 define double @x_ole(double %x) nounwind {
139 %c = fcmp ole double %x, 0.000000e+00
140 %d = select i1 %c, double %x, double 0.000000e+00
144 ; CHECK: x_oge_inverse:
145 ; CHECK-NEXT: pxor %xmm1, %xmm1
146 ; CHECK-NEXT: minsd %xmm0, %xmm1
147 ; CHECK-NEXT: movapd %xmm1, %xmm0
149 define double @x_oge_inverse(double %x) nounwind {
150 %c = fcmp oge double %x, 0.000000e+00
151 %d = select i1 %c, double 0.000000e+00, double %x
155 ; CHECK: x_ole_inverse:
156 ; CHECK-NEXT: pxor %xmm1, %xmm1
157 ; CHECK-NEXT: maxsd %xmm0, %xmm1
158 ; CHECK-NEXT: movapd %xmm1, %xmm0
160 define double @x_ole_inverse(double %x) nounwind {
161 %c = fcmp ole double %x, 0.000000e+00
162 %d = select i1 %c, double 0.000000e+00, double %x
167 ; CHECK-NEXT: ucomisd %xmm0, %xmm1
168 define double @ugt(double %x, double %y) nounwind {
169 %c = fcmp ugt double %x, %y
170 %d = select i1 %c, double %x, double %y
175 ; CHECK-NEXT: ucomisd %xmm1, %xmm0
176 define double @ult(double %x, double %y) nounwind {
177 %c = fcmp ult double %x, %y
178 %d = select i1 %c, double %x, double %y
182 ; CHECK: ugt_inverse:
183 ; CHECK-NEXT: ucomisd %xmm0, %xmm1
184 define double @ugt_inverse(double %x, double %y) nounwind {
185 %c = fcmp ugt double %x, %y
186 %d = select i1 %c, double %y, double %x
190 ; CHECK: ult_inverse:
191 ; CHECK-NEXT: ucomisd %xmm1, %xmm0
192 define double @ult_inverse(double %x, double %y) nounwind {
193 %c = fcmp ult double %x, %y
194 %d = select i1 %c, double %y, double %x
199 ; CHECK-NEXT: maxsd %xmm0, %xmm1
200 ; CHECK-NEXT: movapd %xmm1, %xmm0
202 define double @uge(double %x, double %y) nounwind {
203 %c = fcmp uge double %x, %y
204 %d = select i1 %c, double %x, double %y
209 ; CHECK-NEXT: minsd %xmm0, %xmm1
210 ; CHECK-NEXT: movapd %xmm1, %xmm0
212 define double @ule(double %x, double %y) nounwind {
213 %c = fcmp ule double %x, %y
214 %d = select i1 %c, double %x, double %y
218 ; CHECK: uge_inverse:
219 ; CHECK-NEXT: minsd %xmm1, %xmm0
221 define double @uge_inverse(double %x, double %y) nounwind {
222 %c = fcmp uge double %x, %y
223 %d = select i1 %c, double %y, double %x
227 ; CHECK: ule_inverse:
228 ; CHECK-NEXT: maxsd %xmm1, %xmm0
230 define double @ule_inverse(double %x, double %y) nounwind {
231 %c = fcmp ule double %x, %y
232 %d = select i1 %c, double %y, double %x
237 ; CHECK-NEXT: pxor %xmm1, %xmm1
238 ; CHECK-NEXT: maxsd %xmm0, %xmm1
239 ; CHECK-NEXT: movapd %xmm1, %xmm0
241 define double @x_ugt(double %x) nounwind {
242 %c = fcmp ugt double %x, 0.000000e+00
243 %d = select i1 %c, double %x, double 0.000000e+00
248 ; CHECK-NEXT: pxor %xmm1, %xmm1
249 ; CHECK-NEXT: minsd %xmm0, %xmm1
250 ; CHECK-NEXT: movapd %xmm1, %xmm0
252 define double @x_ult(double %x) nounwind {
253 %c = fcmp ult double %x, 0.000000e+00
254 %d = select i1 %c, double %x, double 0.000000e+00
258 ; CHECK: x_ugt_inverse:
259 ; CHECK-NEXT: pxor %xmm1, %xmm1
260 ; CHECK-NEXT: minsd %xmm1, %xmm0
262 define double @x_ugt_inverse(double %x) nounwind {
263 %c = fcmp ugt double %x, 0.000000e+00
264 %d = select i1 %c, double 0.000000e+00, double %x
268 ; CHECK: x_ult_inverse:
269 ; CHECK-NEXT: pxor %xmm1, %xmm1
270 ; CHECK-NEXT: maxsd %xmm1, %xmm0
272 define double @x_ult_inverse(double %x) nounwind {
273 %c = fcmp ult double %x, 0.000000e+00
274 %d = select i1 %c, double 0.000000e+00, double %x
279 ; CHECK-NEXT: pxor %xmm1, %xmm1
280 ; CHECK-NEXT: maxsd %xmm0, %xmm1
281 ; CHECK-NEXT: movapd %xmm1, %xmm0
283 define double @x_uge(double %x) nounwind {
284 %c = fcmp uge double %x, 0.000000e+00
285 %d = select i1 %c, double %x, double 0.000000e+00
290 ; CHECK-NEXT: pxor %xmm1, %xmm1
291 ; CHECK-NEXT: minsd %xmm0, %xmm1
292 ; CHECK-NEXT: movapd %xmm1, %xmm0
294 define double @x_ule(double %x) nounwind {
295 %c = fcmp ule double %x, 0.000000e+00
296 %d = select i1 %c, double %x, double 0.000000e+00
300 ; CHECK: x_uge_inverse:
301 ; CHECK-NEXT: pxor %xmm1, %xmm1
302 ; CHECK-NEXT: minsd %xmm1, %xmm0
304 define double @x_uge_inverse(double %x) nounwind {
305 %c = fcmp uge double %x, 0.000000e+00
306 %d = select i1 %c, double 0.000000e+00, double %x
310 ; CHECK: x_ule_inverse:
311 ; CHECK-NEXT: pxor %xmm1, %xmm1
312 ; CHECK-NEXT: maxsd %xmm1, %xmm0
314 define double @x_ule_inverse(double %x) nounwind {
315 %c = fcmp ule double %x, 0.000000e+00
316 %d = select i1 %c, double 0.000000e+00, double %x
320 ; Test a few more misc. cases.
322 ; CHECK: clampTo3k_a:
324 define double @clampTo3k_a(double %x) nounwind readnone {
326 %0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1]
327 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
331 ; CHECK: clampTo3k_b:
333 define double @clampTo3k_b(double %x) nounwind readnone {
335 %0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1]
336 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
340 ; CHECK: clampTo3k_c:
342 define double @clampTo3k_c(double %x) nounwind readnone {
344 %0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1]
345 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
349 ; CHECK: clampTo3k_d:
351 define double @clampTo3k_d(double %x) nounwind readnone {
353 %0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1]
354 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
358 ; CHECK: clampTo3k_e:
360 define double @clampTo3k_e(double %x) nounwind readnone {
362 %0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1]
363 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
367 ; CHECK: clampTo3k_f:
369 define double @clampTo3k_f(double %x) nounwind readnone {
371 %0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1]
372 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
376 ; CHECK: clampTo3k_g:
378 define double @clampTo3k_g(double %x) nounwind readnone {
380 %0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1]
381 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
385 ; CHECK: clampTo3k_h:
387 define double @clampTo3k_h(double %x) nounwind readnone {
389 %0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1]
390 %x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]