Re-implement the main strength-reduction portion of LoopStrengthReduction.
[oota-llvm.git] / test / CodeGen / X86 / sse-minmax.ll
1 ; RUN: llc < %s -march=x86-64 -asm-verbose=false | FileCheck %s
2
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.
7
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.
11
12 ; CHECK:      ogt:
13 ; CHECK-NEXT: maxsd %xmm1, %xmm0
14 ; CHECK-NEXT: ret
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
18   ret double %d
19 }
20
21 ; CHECK:      olt:
22 ; CHECK-NEXT: minsd %xmm1, %xmm0
23 ; CHECK-NEXT: ret
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
27   ret double %d
28 }
29
30 ; CHECK:      ogt_inverse:
31 ; CHECK-NEXT: minsd  %xmm0, %xmm1
32 ; CHECK-NEXT: movapd %xmm1, %xmm0
33 ; CHECK-NEXT: ret
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
37   ret double %d
38 }
39
40 ; CHECK:      olt_inverse:
41 ; CHECK-NEXT: maxsd  %xmm0, %xmm1
42 ; CHECK-NEXT: movapd %xmm1, %xmm0
43 ; CHECK-NEXT: ret
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
47   ret double %d
48 }
49
50 ; CHECK:      oge:
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
55   ret double %d
56 }
57
58 ; CHECK:      ole:
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
63   ret double %d
64 }
65
66 ; CHECK:      oge_inverse:
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
71   ret double %d
72 }
73
74 ; CHECK:      ole_inverse:
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
79   ret double %d
80 }
81
82 ; CHECK:      x_ogt:
83 ; CHECK-NEXT: pxor  %xmm1, %xmm1
84 ; CHECK-NEXT: maxsd %xmm1, %xmm0
85 ; CHECK-NEXT: ret
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
89   ret double %d
90 }
91
92 ; CHECK:      x_olt:
93 ; CHECK-NEXT: pxor  %xmm1, %xmm1
94 ; CHECK-NEXT: minsd %xmm1, %xmm0
95 ; CHECK-NEXT: ret
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
99   ret double %d
100 }
101
102 ; CHECK:      x_ogt_inverse:
103 ; CHECK-NEXT: pxor   %xmm1, %xmm1
104 ; CHECK-NEXT: minsd  %xmm0, %xmm1
105 ; CHECK-NEXT: movapd %xmm1, %xmm0
106 ; CHECK-NEXT: ret
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
110   ret double %d
111 }
112
113 ; CHECK:      x_olt_inverse:
114 ; CHECK-NEXT: pxor   %xmm1, %xmm1
115 ; CHECK-NEXT: maxsd  %xmm0, %xmm1
116 ; CHECK-NEXT: movapd %xmm1, %xmm0
117 ; CHECK-NEXT: ret
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
121   ret double %d
122 }
123
124 ; CHECK:      x_oge:
125 ; CHECK-NEXT: pxor  %xmm1, %xmm1
126 ; CHECK-NEXT: maxsd %xmm1, %xmm0
127 ; CHECK-NEXT: ret
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
131   ret double %d
132 }
133
134 ; CHECK:      x_ole:
135 ; CHECK-NEXT: pxor  %xmm1, %xmm1
136 ; CHECK-NEXT: minsd %xmm1, %xmm0
137 ; CHECK-NEXT: ret
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
141   ret double %d
142 }
143
144 ; CHECK:      x_oge_inverse:
145 ; CHECK-NEXT: pxor   %xmm1, %xmm1
146 ; CHECK-NEXT: minsd  %xmm0, %xmm1
147 ; CHECK-NEXT: movapd %xmm1, %xmm0
148 ; CHECK-NEXT: ret
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
152   ret double %d
153 }
154
155 ; CHECK:      x_ole_inverse:
156 ; CHECK-NEXT: pxor   %xmm1, %xmm1
157 ; CHECK-NEXT: maxsd  %xmm0, %xmm1
158 ; CHECK-NEXT: movapd %xmm1, %xmm0
159 ; CHECK-NEXT: ret
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
163   ret double %d
164 }
165
166 ; CHECK:      ugt:
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
171   ret double %d
172 }
173
174 ; CHECK:      ult:
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
179   ret double %d
180 }
181
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
187   ret double %d
188 }
189
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
195   ret double %d
196 }
197
198 ; CHECK:      uge:
199 ; CHECK-NEXT: maxsd  %xmm0, %xmm1
200 ; CHECK-NEXT: movapd %xmm1, %xmm0
201 ; CHECK-NEXT: ret
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
205   ret double %d
206 }
207
208 ; CHECK:      ule:
209 ; CHECK-NEXT: minsd  %xmm0, %xmm1
210 ; CHECK-NEXT: movapd %xmm1, %xmm0
211 ; CHECK-NEXT: ret
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
215   ret double %d
216 }
217
218 ; CHECK:      uge_inverse:
219 ; CHECK-NEXT: minsd %xmm1, %xmm0
220 ; CHECK-NEXT: ret
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
224   ret double %d
225 }
226
227 ; CHECK:      ule_inverse:
228 ; CHECK-NEXT: maxsd %xmm1, %xmm0
229 ; CHECK-NEXT: ret
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
233   ret double %d
234 }
235
236 ; CHECK:      x_ugt:
237 ; CHECK-NEXT: pxor   %xmm1, %xmm1
238 ; CHECK-NEXT: maxsd  %xmm0, %xmm1
239 ; CHECK-NEXT: movapd %xmm1, %xmm0
240 ; CHECK-NEXT: ret
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
244   ret double %d
245 }
246
247 ; CHECK:      x_ult:
248 ; CHECK-NEXT: pxor   %xmm1, %xmm1
249 ; CHECK-NEXT: minsd  %xmm0, %xmm1
250 ; CHECK-NEXT: movapd %xmm1, %xmm0
251 ; CHECK-NEXT: ret
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
255   ret double %d
256 }
257
258 ; CHECK:      x_ugt_inverse:
259 ; CHECK-NEXT: pxor  %xmm1, %xmm1
260 ; CHECK-NEXT: minsd %xmm1, %xmm0
261 ; CHECK-NEXT: ret
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
265   ret double %d
266 }
267
268 ; CHECK:      x_ult_inverse:
269 ; CHECK-NEXT: pxor  %xmm1, %xmm1
270 ; CHECK-NEXT: maxsd %xmm1, %xmm0
271 ; CHECK-NEXT: ret
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
275   ret double %d
276 }
277
278 ; CHECK:      x_uge:
279 ; CHECK-NEXT: pxor   %xmm1, %xmm1
280 ; CHECK-NEXT: maxsd  %xmm0, %xmm1
281 ; CHECK-NEXT: movapd %xmm1, %xmm0
282 ; CHECK-NEXT: ret
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
286   ret double %d
287 }
288
289 ; CHECK:      x_ule:
290 ; CHECK-NEXT: pxor   %xmm1, %xmm1
291 ; CHECK-NEXT: minsd  %xmm0, %xmm1
292 ; CHECK-NEXT: movapd %xmm1, %xmm0
293 ; CHECK-NEXT: ret
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
297   ret double %d
298 }
299
300 ; CHECK:      x_uge_inverse:
301 ; CHECK-NEXT: pxor  %xmm1, %xmm1
302 ; CHECK-NEXT: minsd %xmm1, %xmm0
303 ; CHECK-NEXT: ret
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
307   ret double %d
308 }
309
310 ; CHECK:      x_ule_inverse:
311 ; CHECK-NEXT: pxor  %xmm1, %xmm1
312 ; CHECK-NEXT: maxsd %xmm1, %xmm0
313 ; CHECK-NEXT: ret
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
317   ret double %d
318 }
319
320 ; Test a few more misc. cases.
321
322 ; CHECK: clampTo3k_a:
323 ; CHECK: minsd
324 define double @clampTo3k_a(double %x) nounwind readnone {
325 entry:
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]
328   ret double %x_addr.0
329 }
330
331 ; CHECK: clampTo3k_b:
332 ; CHECK: minsd
333 define double @clampTo3k_b(double %x) nounwind readnone {
334 entry:
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]
337   ret double %x_addr.0
338 }
339
340 ; CHECK: clampTo3k_c:
341 ; CHECK: maxsd
342 define double @clampTo3k_c(double %x) nounwind readnone {
343 entry:
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]
346   ret double %x_addr.0
347 }
348
349 ; CHECK: clampTo3k_d:
350 ; CHECK: maxsd
351 define double @clampTo3k_d(double %x) nounwind readnone {
352 entry:
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]
355   ret double %x_addr.0
356 }
357
358 ; CHECK: clampTo3k_e:
359 ; CHECK: maxsd
360 define double @clampTo3k_e(double %x) nounwind readnone {
361 entry:
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]
364   ret double %x_addr.0
365 }
366
367 ; CHECK: clampTo3k_f:
368 ; CHECK: maxsd
369 define double @clampTo3k_f(double %x) nounwind readnone {
370 entry:
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]
373   ret double %x_addr.0
374 }
375
376 ; CHECK: clampTo3k_g:
377 ; CHECK: minsd
378 define double @clampTo3k_g(double %x) nounwind readnone {
379 entry:
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]
382   ret double %x_addr.0
383 }
384
385 ; CHECK: clampTo3k_h:
386 ; CHECK: minsd
387 define double @clampTo3k_h(double %x) nounwind readnone {
388 entry:
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]
391   ret double %x_addr.0
392 }