1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -passes=instcombine -S | FileCheck %s
3
4; Make sure libcalls are replaced with intrinsic calls.
5
6declare float @llvm.fabs.f32(float)
7declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
8declare double @llvm.fabs.f64(double)
9declare fp128 @llvm.fabs.f128(fp128)
10
11declare float @fabsf(float)
12declare double @fabs(double)
13declare fp128 @fabsl(fp128)
14declare float @llvm.fma.f32(float, float, float)
15declare float @llvm.fmuladd.f32(float, float, float)
16
17declare void @use(float)
18
19define float @replace_fabs_call_f32(float %x) {
20; CHECK-LABEL: @replace_fabs_call_f32(
21; CHECK-NEXT:    [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[X:%.*]])
22; CHECK-NEXT:    ret float [[FABSF]]
23;
24  %fabsf = tail call float @fabsf(float %x)
25  ret float %fabsf
26}
27
28define double @replace_fabs_call_f64(double %x) {
29; CHECK-LABEL: @replace_fabs_call_f64(
30; CHECK-NEXT:    [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
31; CHECK-NEXT:    ret double [[FABS]]
32;
33  %fabs = tail call double @fabs(double %x)
34  ret double %fabs
35}
36
37define fp128 @replace_fabs_call_f128(fp128 %x) {
38; CHECK-LABEL: @replace_fabs_call_f128(
39; CHECK-NEXT:    [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
40; CHECK-NEXT:    ret fp128 [[FABSL]]
41;
42  %fabsl = tail call fp128 @fabsl(fp128 %x)
43  ret fp128 %fabsl
44}
45
46; Make sure fast math flags are preserved when replacing the libcall.
47define float @fmf_replace_fabs_call_f32(float %x) {
48; CHECK-LABEL: @fmf_replace_fabs_call_f32(
49; CHECK-NEXT:    [[FABSF:%.*]] = tail call nnan float @llvm.fabs.f32(float [[X:%.*]])
50; CHECK-NEXT:    ret float [[FABSF]]
51;
52  %fabsf = tail call nnan float @fabsf(float %x)
53  ret float %fabsf
54}
55
56; Make sure all intrinsic calls are eliminated when the input is known
57; positive.
58
59; The fabs cannot be eliminated because %x may be a NaN
60
61define float @square_fabs_intrinsic_f32(float %x) {
62; CHECK-LABEL: @square_fabs_intrinsic_f32(
63; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[X]]
64; CHECK-NEXT:    [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[MUL]])
65; CHECK-NEXT:    ret float [[FABSF]]
66;
67  %mul = fmul float %x, %x
68  %fabsf = tail call float @llvm.fabs.f32(float %mul)
69  ret float %fabsf
70}
71
72define double @square_fabs_intrinsic_f64(double %x) {
73; CHECK-LABEL: @square_fabs_intrinsic_f64(
74; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[X:%.*]], [[X]]
75; CHECK-NEXT:    [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[MUL]])
76; CHECK-NEXT:    ret double [[FABS]]
77;
78  %mul = fmul double %x, %x
79  %fabs = tail call double @llvm.fabs.f64(double %mul)
80  ret double %fabs
81}
82
83define fp128 @square_fabs_intrinsic_f128(fp128 %x) {
84; CHECK-LABEL: @square_fabs_intrinsic_f128(
85; CHECK-NEXT:    [[MUL:%.*]] = fmul fp128 [[X:%.*]], [[X]]
86; CHECK-NEXT:    [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[MUL]])
87; CHECK-NEXT:    ret fp128 [[FABSL]]
88;
89  %mul = fmul fp128 %x, %x
90  %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul)
91  ret fp128 %fabsl
92}
93
94define float @square_nnan_fabs_intrinsic_f32(float %x) {
95; CHECK-LABEL: @square_nnan_fabs_intrinsic_f32(
96; CHECK-NEXT:    [[MUL:%.*]] = fmul nnan float [[X:%.*]], [[X]]
97; CHECK-NEXT:    ret float [[MUL]]
98;
99  %mul = fmul nnan float %x, %x
100  %fabsf = call float @llvm.fabs.f32(float %mul)
101  ret float %fabsf
102}
103
104; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization.
105
106define float @square_fabs_shrink_call1(float %x) {
107; CHECK-LABEL: @square_fabs_shrink_call1(
108; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[X]]
109; CHECK-NEXT:    [[TRUNC:%.*]] = call float @llvm.fabs.f32(float [[TMP1]])
110; CHECK-NEXT:    ret float [[TRUNC]]
111;
112  %ext = fpext float %x to double
113  %sq = fmul double %ext, %ext
114  %fabs = call double @fabs(double %sq)
115  %trunc = fptrunc double %fabs to float
116  ret float %trunc
117}
118
119define float @square_fabs_shrink_call2(float %x) {
120; CHECK-LABEL: @square_fabs_shrink_call2(
121; CHECK-NEXT:    [[SQ:%.*]] = fmul float [[X:%.*]], [[X]]
122; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SQ]])
123; CHECK-NEXT:    ret float [[TMP1]]
124;
125  %sq = fmul float %x, %x
126  %ext = fpext float %sq to double
127  %fabs = call double @fabs(double %ext)
128  %trunc = fptrunc double %fabs to float
129  ret float %trunc
130}
131
132define float @fabs_select_constant_negative_positive(i32 %c) {
133; CHECK-LABEL: @fabs_select_constant_negative_positive(
134; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
135; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
136; CHECK-NEXT:    ret float [[FABS]]
137;
138  %cmp = icmp eq i32 %c, 0
139  %select = select i1 %cmp, float -1.0, float 2.0
140  %fabs = call float @llvm.fabs.f32(float %select)
141  ret float %fabs
142}
143
144define float @fabs_select_constant_positive_negative(i32 %c) {
145; CHECK-LABEL: @fabs_select_constant_positive_negative(
146; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
147; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
148; CHECK-NEXT:    ret float [[FABS]]
149;
150  %cmp = icmp eq i32 %c, 0
151  %select = select i1 %cmp, float 1.0, float -2.0
152  %fabs = call float @llvm.fabs.f32(float %select)
153  ret float %fabs
154}
155
156define float @fabs_select_constant_negative_negative(i32 %c) {
157; CHECK-LABEL: @fabs_select_constant_negative_negative(
158; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
159; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
160; CHECK-NEXT:    ret float [[FABS]]
161;
162  %cmp = icmp eq i32 %c, 0
163  %select = select i1 %cmp, float -1.0, float -2.0
164  %fabs = call float @llvm.fabs.f32(float %select)
165  ret float %fabs
166}
167
168define float @fabs_select_constant_neg0(i32 %c) {
169; CHECK-LABEL: @fabs_select_constant_neg0(
170; CHECK-NEXT:    ret float 0.000000e+00
171;
172  %cmp = icmp eq i32 %c, 0
173  %select = select i1 %cmp, float -0.0, float 0.0
174  %fabs = call float @llvm.fabs.f32(float %select)
175  ret float %fabs
176}
177
178define float @fabs_select_var_constant_negative(i32 %c, float %x) {
179; CHECK-LABEL: @fabs_select_var_constant_negative(
180; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
181; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float [[X:%.*]], float -1.000000e+00
182; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
183; CHECK-NEXT:    ret float [[FABS]]
184;
185  %cmp = icmp eq i32 %c, 0
186  %select = select i1 %cmp, float %x, float -1.0
187  %fabs = call float @llvm.fabs.f32(float %select)
188  ret float %fabs
189}
190
191; The fabs cannot be eliminated because %x may be a NaN
192
193define float @square_fma_fabs_intrinsic_f32(float %x) {
194; CHECK-LABEL: @square_fma_fabs_intrinsic_f32(
195; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
196; CHECK-NEXT:    [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMA]])
197; CHECK-NEXT:    ret float [[FABSF]]
198;
199  %fma = call float @llvm.fma.f32(float %x, float %x, float 1.0)
200  %fabsf = call float @llvm.fabs.f32(float %fma)
201  ret float %fabsf
202}
203
204; The fabs cannot be eliminated because %x may be a NaN
205
206define float @square_nnan_fma_fabs_intrinsic_f32(float %x) {
207; CHECK-LABEL: @square_nnan_fma_fabs_intrinsic_f32(
208; CHECK-NEXT:    [[FMA:%.*]] = call nnan float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
209; CHECK-NEXT:    ret float [[FMA]]
210;
211  %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.0)
212  %fabsf = call float @llvm.fabs.f32(float %fma)
213  ret float %fabsf
214}
215
216define float @square_fmuladd_fabs_intrinsic_f32(float %x) {
217; CHECK-LABEL: @square_fmuladd_fabs_intrinsic_f32(
218; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
219; CHECK-NEXT:    [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMULADD]])
220; CHECK-NEXT:    ret float [[FABSF]]
221;
222  %fmuladd = call float @llvm.fmuladd.f32(float %x, float %x, float 1.0)
223  %fabsf = call float @llvm.fabs.f32(float %fmuladd)
224  ret float %fabsf
225}
226
227define float @square_nnan_fmuladd_fabs_intrinsic_f32(float %x) {
228; CHECK-LABEL: @square_nnan_fmuladd_fabs_intrinsic_f32(
229; CHECK-NEXT:    [[FMULADD:%.*]] = call nnan float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
230; CHECK-NEXT:    ret float [[FMULADD]]
231;
232  %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.0)
233  %fabsf = call float @llvm.fabs.f32(float %fmuladd)
234  ret float %fabsf
235}
236
237; Don't introduce a second fpext
238
239define double @multi_use_fabs_fpext(float %x) {
240; CHECK-LABEL: @multi_use_fabs_fpext(
241; CHECK-NEXT:    [[FPEXT:%.*]] = fpext float [[X:%.*]] to double
242; CHECK-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[FPEXT]])
243; CHECK-NEXT:    store volatile double [[FPEXT]], double* undef, align 8
244; CHECK-NEXT:    ret double [[FABS]]
245;
246  %fpext = fpext float %x to double
247  %fabs = call double @llvm.fabs.f64(double %fpext)
248  store volatile double %fpext, double* undef
249  ret double %fabs
250}
251
252; X <= 0.0 ? (0.0 - X) : X --> fabs(X)
253
254define double @select_fcmp_ole_zero(double %x) {
255; CHECK-LABEL: @select_fcmp_ole_zero(
256; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
257; CHECK-NEXT:    ret double [[TMP1]]
258;
259  %lezero = fcmp ole double %x, 0.0
260  %negx = fsub double 0.0, %x
261  %fabs = select i1 %lezero, double %negx, double %x
262  ret double %fabs
263}
264
265define double @select_fcmp_nnan_ole_zero(double %x) {
266; CHECK-LABEL: @select_fcmp_nnan_ole_zero(
267; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
268; CHECK-NEXT:    ret double [[TMP1]]
269;
270  %lezero = fcmp ole double %x, 0.0
271  %negx = fsub nnan double 0.0, %x
272  %fabs = select i1 %lezero, double %negx, double %x
273  ret double %fabs
274}
275
276define double @select_nnan_fcmp_nnan_ole_zero(double %x) {
277; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_zero(
278; CHECK-NEXT:    [[TMP1:%.*]] = call nnan double @llvm.fabs.f64(double [[X:%.*]])
279; CHECK-NEXT:    ret double [[TMP1]]
280;
281  %lezero = fcmp ole double %x, 0.0
282  %negx = fsub nnan double 0.0, %x
283  %fabs = select nnan i1 %lezero, double %negx, double %x
284  ret double %fabs
285}
286
287; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
288
289define double @select_fcmp_nnan_ule_zero(double %x) {
290; CHECK-LABEL: @select_fcmp_nnan_ule_zero(
291; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
292; CHECK-NEXT:    ret double [[TMP1]]
293;
294  %lezero = fcmp ule double %x, 0.0
295  %negx = fsub nnan double 0.0, %x
296  %fabs = select i1 %lezero, double %negx, double %x
297  ret double %fabs
298}
299
300; Negative test - wrong predicate.
301
302define double @select_fcmp_nnan_olt_zero(double %x) {
303; CHECK-LABEL: @select_fcmp_nnan_olt_zero(
304; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00
305; CHECK-NEXT:    [[NEGX:%.*]] = fsub nnan double 0.000000e+00, [[X]]
306; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]]
307; CHECK-NEXT:    ret double [[FABS]]
308;
309  %lezero = fcmp olt double %x, 0.0
310  %negx = fsub nnan double 0.0, %x
311  %fabs = select i1 %lezero, double %negx, double %x
312  ret double %fabs
313}
314
315; X <= -0.0 ? (0.0 - X) : X --> fabs(X)
316
317define <2 x float> @select_fcmp_nnan_ole_negzero(<2 x float> %x) {
318; CHECK-LABEL: @select_fcmp_nnan_ole_negzero(
319; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
320; CHECK-NEXT:    ret <2 x float> [[TMP1]]
321;
322  %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0>
323  %negx = fsub nnan <2 x float> <float 0.0, float undef>, %x
324  %fabs = select <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x
325  ret <2 x float> %fabs
326}
327
328define <2 x float> @select_nnan_fcmp_nnan_ole_negzero(<2 x float> %x) {
329; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_negzero(
330; CHECK-NEXT:    [[TMP1:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
331; CHECK-NEXT:    ret <2 x float> [[TMP1]]
332;
333  %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0>
334  %negx = fsub nnan <2 x float> <float 0.0, float undef>, %x
335  %fabs = select nnan <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x
336  ret <2 x float> %fabs
337}
338
339; X > 0.0 ? X : (0.0 - X) --> fabs(X)
340
341define fp128 @select_fcmp_ogt_zero(fp128 %x) {
342; CHECK-LABEL: @select_fcmp_ogt_zero(
343; CHECK-NEXT:    [[TMP1:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
344; CHECK-NEXT:    ret fp128 [[TMP1]]
345;
346  %gtzero = fcmp ogt fp128 %x, zeroinitializer
347  %negx = fsub fp128 zeroinitializer, %x
348  %fabs = select i1 %gtzero, fp128 %x, fp128 %negx
349  ret fp128 %fabs
350}
351
352define float @select_fcmp_ogt_fneg(float %a) {
353; CHECK-LABEL: @select_fcmp_ogt_fneg(
354; CHECK-NEXT:    [[TMP1:%.*]] = call nsz float @llvm.fabs.f32(float [[A:%.*]])
355; CHECK-NEXT:    ret float [[TMP1]]
356;
357  %fneg = fneg float %a
358  %cmp = fcmp ogt float %a, %fneg
359  %r = select nsz i1 %cmp, float %a, float %fneg
360  ret float %r
361}
362
363define fp128 @select_fcmp_nnan_ogt_zero(fp128 %x) {
364; CHECK-LABEL: @select_fcmp_nnan_ogt_zero(
365; CHECK-NEXT:    [[TMP1:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
366; CHECK-NEXT:    ret fp128 [[TMP1]]
367;
368  %gtzero = fcmp ogt fp128 %x, zeroinitializer
369  %negx = fsub nnan fp128 zeroinitializer, %x
370  %fabs = select i1 %gtzero, fp128 %x, fp128 %negx
371  ret fp128 %fabs
372}
373
374define fp128 @select_nnan_fcmp_nnan_ogt_zero(fp128 %x) {
375; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_zero(
376; CHECK-NEXT:    [[TMP1:%.*]] = call nnan fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
377; CHECK-NEXT:    ret fp128 [[TMP1]]
378;
379  %gtzero = fcmp ogt fp128 %x, zeroinitializer
380  %negx = fsub nnan fp128 zeroinitializer, %x
381  %fabs = select nnan i1 %gtzero, fp128 %x, fp128 %negx
382  ret fp128 %fabs
383}
384
385; X > -0.0 ? X : (0.0 - X) --> fabs(X)
386
387define half @select_fcmp_nnan_ogt_negzero(half %x) {
388; CHECK-LABEL: @select_fcmp_nnan_ogt_negzero(
389; CHECK-NEXT:    [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
390; CHECK-NEXT:    ret half [[TMP1]]
391;
392  %gtzero = fcmp ogt half %x, -0.0
393  %negx = fsub nnan half 0.0, %x
394  %fabs = select i1 %gtzero, half %x, half %negx
395  ret half %fabs
396}
397
398define half @select_nnan_fcmp_nnan_ogt_negzero(half %x) {
399; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_negzero(
400; CHECK-NEXT:    [[TMP1:%.*]] = call nnan half @llvm.fabs.f16(half [[X:%.*]])
401; CHECK-NEXT:    ret half [[TMP1]]
402;
403  %gtzero = fcmp ogt half %x, -0.0
404  %negx = fsub nnan half 0.0, %x
405  %fabs = select nnan i1 %gtzero, half %x, half %negx
406  ret half %fabs
407}
408
409; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
410
411define half @select_fcmp_nnan_ugt_negzero(half %x) {
412; CHECK-LABEL: @select_fcmp_nnan_ugt_negzero(
413; CHECK-NEXT:    [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
414; CHECK-NEXT:    ret half [[TMP1]]
415;
416  %gtzero = fcmp ugt half %x, -0.0
417  %negx = fsub nnan half 0.0, %x
418  %fabs = select i1 %gtzero, half %x, half %negx
419  ret half %fabs
420}
421
422; Negative test - wrong predicate.
423
424define half @select_fcmp_nnan_oge_negzero(half %x) {
425; CHECK-LABEL: @select_fcmp_nnan_oge_negzero(
426; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
427; CHECK-NEXT:    [[NEGX:%.*]] = fsub nnan half 0xH0000, [[X]]
428; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]]
429; CHECK-NEXT:    ret half [[FABS]]
430;
431  %gtzero = fcmp oge half %x, -0.0
432  %negx = fsub nnan half 0.0, %x
433  %fabs = select i1 %gtzero, half %x, half %negx
434  ret half %fabs
435}
436
437; X < 0.0 ? -X : X --> fabs(X)
438
439define double @select_fcmp_olt_zero_unary_fneg(double %x) {
440; CHECK-LABEL: @select_fcmp_olt_zero_unary_fneg(
441; CHECK-NEXT:    [[TMP1:%.*]] = call nsz double @llvm.fabs.f64(double [[X:%.*]])
442; CHECK-NEXT:    ret double [[TMP1]]
443;
444  %ltzero = fcmp olt double %x, 0.0
445  %negx = fneg double %x
446  %fabs = select nsz i1 %ltzero, double %negx, double %x
447  ret double %fabs
448}
449
450define double @select_fcmp_nnan_nsz_olt_zero(double %x) {
451; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero(
452; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00
453; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
454; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]]
455; CHECK-NEXT:    ret double [[FABS]]
456;
457  %ltzero = fcmp olt double %x, 0.0
458  %negx = fsub nnan nsz double -0.0, %x
459  %fabs = select i1 %ltzero, double %negx, double %x
460  ret double %fabs
461}
462
463define double @select_nnan_nsz_fcmp_nnan_nsz_olt_zero(double %x) {
464; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_olt_zero(
465; CHECK-NEXT:    [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]])
466; CHECK-NEXT:    ret double [[TMP1]]
467;
468  %ltzero = fcmp olt double %x, 0.0
469  %negx = fsub nnan nsz double -0.0, %x
470  %fabs = select nnan nsz i1 %ltzero, double %negx, double %x
471  ret double %fabs
472}
473
474; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
475
476define double @select_fcmp_nnan_nsz_ult_zero(double %x) {
477; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero(
478; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00
479; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
480; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]]
481; CHECK-NEXT:    ret double [[FABS]]
482;
483  %ltzero = fcmp ult double %x, 0.0
484  %negx = fsub nnan nsz double -0.0, %x
485  %fabs = select i1 %ltzero, double %negx, double %x
486  ret double %fabs
487}
488
489define double @select_fcmp_nnan_nsz_olt_zero_unary_fneg(double %x) {
490; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero_unary_fneg(
491; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00
492; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
493; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]]
494; CHECK-NEXT:    ret double [[FABS]]
495;
496  %ltzero = fcmp olt double %x, 0.0
497  %negx = fneg nnan nsz double %x
498  %fabs = select i1 %ltzero, double %negx, double %x
499  ret double %fabs
500}
501
502; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
503
504define double @select_fcmp_nnan_nsz_ult_zero_unary_fneg(double %x) {
505; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero_unary_fneg(
506; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00
507; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
508; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]]
509; CHECK-NEXT:    ret double [[FABS]]
510;
511  %ltzero = fcmp ult double %x, 0.0
512  %negx = fneg nnan nsz double %x
513  %fabs = select i1 %ltzero, double %negx, double %x
514  ret double %fabs
515}
516
517; X < -0.0 ? -X : X --> fabs(X)
518
519define float @select_fcmp_nnan_nsz_olt_negzero(float %x) {
520; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero(
521; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
522; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
523; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]]
524; CHECK-NEXT:    ret float [[FABS]]
525;
526  %ltzero = fcmp olt float %x, -0.0
527  %negx = fsub nnan ninf nsz float -0.0, %x
528  %fabs = select i1 %ltzero, float %negx, float %x
529  ret float %fabs
530}
531
532define float @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero(float %x) {
533; CHECK-LABEL: @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero(
534; CHECK-NEXT:    [[TMP1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[X:%.*]])
535; CHECK-NEXT:    ret float [[TMP1]]
536;
537  %ltzero = fcmp olt float %x, -0.0
538  %negx = fsub nnan nsz float -0.0, %x
539  %fabs = select nnan ninf nsz i1 %ltzero, float %negx, float %x
540  ret float %fabs
541}
542
543; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
544
545define float @select_fcmp_nnan_nsz_ult_negzero(float %x) {
546; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero(
547; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00
548; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
549; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]]
550; CHECK-NEXT:    ret float [[FABS]]
551;
552  %ltzero = fcmp ult float %x, -0.0
553  %negx = fsub nnan ninf nsz float -0.0, %x
554  %fabs = select i1 %ltzero, float %negx, float %x
555  ret float %fabs
556}
557
558define float @select_fcmp_nnan_nsz_olt_negzero_unary_fneg(float %x) {
559; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero_unary_fneg(
560; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
561; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
562; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]]
563; CHECK-NEXT:    ret float [[FABS]]
564;
565  %ltzero = fcmp olt float %x, -0.0
566  %negx = fneg nnan ninf nsz float %x
567  %fabs = select i1 %ltzero, float %negx, float %x
568  ret float %fabs
569}
570
571; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
572
573define float @select_fcmp_nnan_nsz_ult_negzero_unary_fneg(float %x) {
574; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero_unary_fneg(
575; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00
576; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
577; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]]
578; CHECK-NEXT:    ret float [[FABS]]
579;
580  %ltzero = fcmp ult float %x, -0.0
581  %negx = fneg nnan ninf nsz float %x
582  %fabs = select i1 %ltzero, float %negx, float %x
583  ret float %fabs
584}
585
586; X <= 0.0 ? -X : X --> fabs(X)
587
588define double @select_fcmp_nnan_nsz_ole_zero(double %x) {
589; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero(
590; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00
591; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
592; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]]
593; CHECK-NEXT:    ret double [[FABS]]
594;
595  %lezero = fcmp ole double %x, 0.0
596  %negx = fsub fast double -0.0, %x
597  %fabs = select i1 %lezero, double %negx, double %x
598  ret double %fabs
599}
600
601define double @select_fast_fcmp_nnan_nsz_ole_zero(double %x) {
602; CHECK-LABEL: @select_fast_fcmp_nnan_nsz_ole_zero(
603; CHECK-NEXT:    [[TMP1:%.*]] = call fast double @llvm.fabs.f64(double [[X:%.*]])
604; CHECK-NEXT:    ret double [[TMP1]]
605;
606  %lezero = fcmp ole double %x, 0.0
607  %negx = fsub nnan nsz double -0.0, %x
608  %fabs = select fast i1 %lezero, double %negx, double %x
609  ret double %fabs
610}
611
612; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
613
614define double @select_fcmp_nnan_nsz_ule_zero(double %x) {
615; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero(
616; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00
617; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
618; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]]
619; CHECK-NEXT:    ret double [[FABS]]
620;
621  %lezero = fcmp ule double %x, 0.0
622  %negx = fsub fast double -0.0, %x
623  %fabs = select i1 %lezero, double %negx, double %x
624  ret double %fabs
625}
626
627define double @select_fcmp_nnan_nsz_ole_zero_unary_fneg(double %x) {
628; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero_unary_fneg(
629; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00
630; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
631; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]]
632; CHECK-NEXT:    ret double [[FABS]]
633;
634  %lezero = fcmp ole double %x, 0.0
635  %negx = fneg fast double %x
636  %fabs = select i1 %lezero, double %negx, double %x
637  ret double %fabs
638}
639
640; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
641
642define double @select_fcmp_nnan_nsz_ule_zero_unary_fneg(double %x) {
643; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero_unary_fneg(
644; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00
645; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
646; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]]
647; CHECK-NEXT:    ret double [[FABS]]
648;
649  %lezero = fcmp ule double %x, 0.0
650  %negx = fneg fast double %x
651  %fabs = select i1 %lezero, double %negx, double %x
652  ret double %fabs
653}
654
655; X <= -0.0 ? -X : X --> fabs(X)
656
657define float @select_fcmp_nnan_nsz_ole_negzero(float %x) {
658; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero(
659; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00
660; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
661; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]]
662; CHECK-NEXT:    ret float [[FABS]]
663;
664  %lezero = fcmp ole float %x, -0.0
665  %negx = fsub nnan nsz float -0.0, %x
666  %fabs = select i1 %lezero, float %negx, float %x
667  ret float %fabs
668}
669
670define float @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero(float %x) {
671; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero(
672; CHECK-NEXT:    [[TMP1:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X:%.*]])
673; CHECK-NEXT:    ret float [[TMP1]]
674;
675  %lezero = fcmp ole float %x, -0.0
676  %negx = fsub nnan nsz float -0.0, %x
677  %fabs = select nnan nsz i1 %lezero, float %negx, float %x
678  ret float %fabs
679}
680
681; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
682
683define float @select_fcmp_nnan_nsz_ule_negzero(float %x) {
684; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero(
685; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00
686; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
687; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]]
688; CHECK-NEXT:    ret float [[FABS]]
689;
690  %lezero = fcmp ule float %x, -0.0
691  %negx = fsub nnan nsz float -0.0, %x
692  %fabs = select i1 %lezero, float %negx, float %x
693  ret float %fabs
694}
695
696define float @select_fcmp_nnan_nsz_ole_negzero_unary_fneg(float %x) {
697; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero_unary_fneg(
698; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00
699; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
700; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]]
701; CHECK-NEXT:    ret float [[FABS]]
702;
703  %lezero = fcmp ole float %x, -0.0
704  %negx = fneg nnan nsz float %x
705  %fabs = select i1 %lezero, float %negx, float %x
706  ret float %fabs
707}
708
709; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
710
711define float @select_fcmp_nnan_nsz_ule_negzero_unary_fneg(float %x) {
712; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero_unary_fneg(
713; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00
714; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
715; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]]
716; CHECK-NEXT:    ret float [[FABS]]
717;
718  %lezero = fcmp ule float %x, -0.0
719  %negx = fneg nnan nsz float %x
720  %fabs = select i1 %lezero, float %negx, float %x
721  ret float %fabs
722}
723
724; X > 0.0 ? X : (0.0 - X) --> fabs(X)
725
726define <2 x float> @select_fcmp_ogt_zero_unary_fneg(<2 x float> %x) {
727; CHECK-LABEL: @select_fcmp_ogt_zero_unary_fneg(
728; CHECK-NEXT:    [[TMP1:%.*]] = call nsz <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
729; CHECK-NEXT:    ret <2 x float> [[TMP1]]
730;
731  %gtzero = fcmp ogt <2 x float> %x, zeroinitializer
732  %negx = fneg <2 x float> %x
733  %fabs = select nsz <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
734  ret <2 x float> %fabs
735}
736
737define <2 x float> @select_fcmp_nnan_nsz_ogt_zero(<2 x float> %x) {
738; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero(
739; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer
740; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
741; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
742; CHECK-NEXT:    ret <2 x float> [[FABS]]
743;
744  %gtzero = fcmp ogt <2 x float> %x, zeroinitializer
745  %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x
746  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
747  ret <2 x float> %fabs
748}
749
750; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
751
752define <2 x float> @select_fcmp_nnan_nsz_ugt_zero(<2 x float> %x) {
753; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero(
754; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer
755; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
756; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
757; CHECK-NEXT:    ret <2 x float> [[FABS]]
758;
759  %gtzero = fcmp ugt <2 x float> %x, zeroinitializer
760  %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x
761  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
762  ret <2 x float> %fabs
763}
764
765define <2 x float> @select_fcmp_nnan_nsz_ogt_zero_unary_fneg(<2 x float> %x) {
766; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero_unary_fneg(
767; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer
768; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
769; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
770; CHECK-NEXT:    ret <2 x float> [[FABS]]
771;
772  %gtzero = fcmp ogt <2 x float> %x, zeroinitializer
773  %negx = fneg nnan nsz arcp <2 x float> %x
774  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
775  ret <2 x float> %fabs
776}
777
778; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
779
780define <2 x float> @select_fcmp_nnan_nsz_ugt_zero_unary_fneg(<2 x float> %x) {
781; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero_unary_fneg(
782; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer
783; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
784; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
785; CHECK-NEXT:    ret <2 x float> [[FABS]]
786;
787  %gtzero = fcmp ugt <2 x float> %x, zeroinitializer
788  %negx = fneg nnan nsz arcp <2 x float> %x
789  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
790  ret <2 x float> %fabs
791}
792
793; X > -0.0 ? X : (0.0 - X) --> fabs(X)
794
795define half @select_fcmp_nnan_nsz_ogt_negzero(half %x) {
796; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_negzero(
797; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ogt half [[X:%.*]], 0xH0000
798; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast half [[X]]
799; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]]
800; CHECK-NEXT:    ret half [[FABS]]
801;
802  %gtzero = fcmp ogt half %x, -0.0
803  %negx = fsub fast half 0.0, %x
804  %fabs = select i1 %gtzero, half %x, half %negx
805  ret half %fabs
806}
807
808; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
809
810define half @select_fcmp_nnan_nsz_ugt_negzero(half %x) {
811; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_negzero(
812; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ugt half [[X:%.*]], 0xH0000
813; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast half [[X]]
814; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]]
815; CHECK-NEXT:    ret half [[FABS]]
816;
817  %gtzero = fcmp ugt half %x, -0.0
818  %negx = fsub fast half 0.0, %x
819  %fabs = select i1 %gtzero, half %x, half %negx
820  ret half %fabs
821}
822
823; X > 0.0 ? X : (0.0 - X) --> fabs(X)
824
825define <2 x double> @select_fcmp_nnan_nsz_oge_zero(<2 x double> %x) {
826; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero(
827; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer
828; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
829; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
830; CHECK-NEXT:    ret <2 x double> [[FABS]]
831;
832  %gezero = fcmp oge <2 x double> %x, zeroinitializer
833  %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x
834  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
835  ret <2 x double> %fabs
836}
837
838; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
839
840define <2 x double> @select_fcmp_nnan_nsz_uge_zero(<2 x double> %x) {
841; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero(
842; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer
843; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
844; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
845; CHECK-NEXT:    ret <2 x double> [[FABS]]
846;
847  %gezero = fcmp uge <2 x double> %x, zeroinitializer
848  %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x
849  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
850  ret <2 x double> %fabs
851}
852
853define <2 x double> @select_fcmp_nnan_nsz_oge_zero_unary_fneg(<2 x double> %x) {
854; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero_unary_fneg(
855; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer
856; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
857; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
858; CHECK-NEXT:    ret <2 x double> [[FABS]]
859;
860  %gezero = fcmp oge <2 x double> %x, zeroinitializer
861  %negx = fneg nnan nsz reassoc <2 x double> %x
862  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
863  ret <2 x double> %fabs
864}
865
866; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
867
868define <2 x double> @select_fcmp_nnan_nsz_uge_zero_unary_fneg(<2 x double> %x) {
869; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero_unary_fneg(
870; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer
871; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
872; CHECK-NEXT:    [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
873; CHECK-NEXT:    ret <2 x double> [[FABS]]
874;
875  %gezero = fcmp uge <2 x double> %x, zeroinitializer
876  %negx = fneg nnan nsz reassoc <2 x double> %x
877  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
878  ret <2 x double> %fabs
879}
880
881; X > -0.0 ? X : (0.0 - X) --> fabs(X)
882
883define half @select_fcmp_nnan_nsz_oge_negzero(half %x) {
884; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero(
885; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
886; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
887; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]]
888; CHECK-NEXT:    ret half [[FABS]]
889;
890  %gezero = fcmp oge half %x, -0.0
891  %negx = fsub nnan nsz half -0.0, %x
892  %fabs = select i1 %gezero, half %x, half %negx
893  ret half %fabs
894}
895
896; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
897
898define half @select_fcmp_nnan_nsz_uge_negzero(half %x) {
899; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero(
900; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000
901; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
902; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]]
903; CHECK-NEXT:    ret half [[FABS]]
904;
905  %gezero = fcmp uge half %x, -0.0
906  %negx = fsub nnan nsz half -0.0, %x
907  %fabs = select i1 %gezero, half %x, half %negx
908  ret half %fabs
909}
910
911define half @select_fcmp_nnan_nsz_oge_negzero_unary_fneg(half %x) {
912; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero_unary_fneg(
913; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
914; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
915; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]]
916; CHECK-NEXT:    ret half [[FABS]]
917;
918  %gezero = fcmp oge half %x, -0.0
919  %negx = fneg nnan nsz half %x
920  %fabs = select i1 %gezero, half %x, half %negx
921  ret half %fabs
922}
923
924; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
925
926define half @select_fcmp_nnan_nsz_uge_negzero_unary_fneg(half %x) {
927; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero_unary_fneg(
928; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000
929; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
930; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]]
931; CHECK-NEXT:    ret half [[FABS]]
932;
933  %gezero = fcmp uge half %x, -0.0
934  %negx = fneg nnan nsz half %x
935  %fabs = select i1 %gezero, half %x, half %negx
936  ret half %fabs
937}
938
939define float @select_fneg(i1 %c, float %x) {
940; CHECK-LABEL: @select_fneg(
941; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
942; CHECK-NEXT:    ret float [[FABS]]
943;
944  %n = fneg float %x
945  %s = select i1 %c, float %n, float %x
946  %fabs = call float @llvm.fabs.f32(float %s)
947  ret float %fabs
948}
949
950define float @select_fneg_use1(i1 %c, float %x) {
951; CHECK-LABEL: @select_fneg_use1(
952; CHECK-NEXT:    [[N:%.*]] = fneg float [[X:%.*]]
953; CHECK-NEXT:    call void @use(float [[N]])
954; CHECK-NEXT:    [[FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]])
955; CHECK-NEXT:    ret float [[FABS]]
956;
957  %n = fneg float %x
958  call void @use(float %n)
959  %s = select i1 %c, float %x, float %n
960  %fabs = call fast float @llvm.fabs.f32(float %s)
961  ret float %fabs
962}
963
964define float @select_fneg_use2(i1 %c, float %x) {
965; CHECK-LABEL: @select_fneg_use2(
966; CHECK-NEXT:    [[N:%.*]] = fneg arcp float [[X:%.*]]
967; CHECK-NEXT:    [[S:%.*]] = select i1 [[C:%.*]], float [[N]], float [[X]]
968; CHECK-NEXT:    call void @use(float [[S]])
969; CHECK-NEXT:    [[FABS:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X]])
970; CHECK-NEXT:    ret float [[FABS]]
971;
972  %n = fneg arcp float %x
973  %s = select i1 %c, float %n, float %x
974  call void @use(float %s)
975  %fabs = call nnan nsz float @llvm.fabs.f32(float %s)
976  ret float %fabs
977}
978
979define <2 x float> @select_fneg_vec(<2 x i1> %c, <2 x float> %x) {
980; CHECK-LABEL: @select_fneg_vec(
981; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
982; CHECK-NEXT:    ret <2 x float> [[FABS]]
983;
984  %n = fneg <2 x float> %x
985  %s = select fast <2 x i1> %c, <2 x float> %x, <2 x float> %n
986  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %s)
987  ret <2 x float> %fabs
988}
989