xref: /llvm-project/llvm/test/Transforms/InstCombine/fabs.ll (revision d18ab0e1bd5032d213acb94ef70564d221f63fa7)
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)
18declare void @usebool(i1)
19
20define float @replace_fabs_call_f32(float %x) {
21; CHECK-LABEL: @replace_fabs_call_f32(
22; CHECK-NEXT:    [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[X:%.*]])
23; CHECK-NEXT:    ret float [[FABSF]]
24;
25  %fabsf = tail call float @fabsf(float %x)
26  ret float %fabsf
27}
28
29define double @replace_fabs_call_f64(double %x) {
30; CHECK-LABEL: @replace_fabs_call_f64(
31; CHECK-NEXT:    [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
32; CHECK-NEXT:    ret double [[FABS]]
33;
34  %fabs = tail call double @fabs(double %x)
35  ret double %fabs
36}
37
38define fp128 @replace_fabs_call_f128(fp128 %x) {
39; CHECK-LABEL: @replace_fabs_call_f128(
40; CHECK-NEXT:    [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
41; CHECK-NEXT:    ret fp128 [[FABSL]]
42;
43  %fabsl = tail call fp128 @fabsl(fp128 %x)
44  ret fp128 %fabsl
45}
46
47; Make sure fast math flags are preserved when replacing the libcall.
48define float @fmf_replace_fabs_call_f32(float %x) {
49; CHECK-LABEL: @fmf_replace_fabs_call_f32(
50; CHECK-NEXT:    [[FABSF:%.*]] = tail call nnan float @llvm.fabs.f32(float [[X:%.*]])
51; CHECK-NEXT:    ret float [[FABSF]]
52;
53  %fabsf = tail call nnan float @fabsf(float %x)
54  ret float %fabsf
55}
56
57; Make sure all intrinsic calls are eliminated when the input is known
58; positive.
59
60; The fabs cannot be eliminated because %x may be a NaN
61
62define float @square_fabs_intrinsic_f32(float %x) {
63; CHECK-LABEL: @square_fabs_intrinsic_f32(
64; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[X]]
65; CHECK-NEXT:    [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[MUL]])
66; CHECK-NEXT:    ret float [[FABSF]]
67;
68  %mul = fmul float %x, %x
69  %fabsf = tail call float @llvm.fabs.f32(float %mul)
70  ret float %fabsf
71}
72
73define double @square_fabs_intrinsic_f64(double %x) {
74; CHECK-LABEL: @square_fabs_intrinsic_f64(
75; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[X:%.*]], [[X]]
76; CHECK-NEXT:    [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[MUL]])
77; CHECK-NEXT:    ret double [[FABS]]
78;
79  %mul = fmul double %x, %x
80  %fabs = tail call double @llvm.fabs.f64(double %mul)
81  ret double %fabs
82}
83
84define fp128 @square_fabs_intrinsic_f128(fp128 %x) {
85; CHECK-LABEL: @square_fabs_intrinsic_f128(
86; CHECK-NEXT:    [[MUL:%.*]] = fmul fp128 [[X:%.*]], [[X]]
87; CHECK-NEXT:    [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[MUL]])
88; CHECK-NEXT:    ret fp128 [[FABSL]]
89;
90  %mul = fmul fp128 %x, %x
91  %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul)
92  ret fp128 %fabsl
93}
94
95define float @square_nnan_fabs_intrinsic_f32(float %x) {
96; CHECK-LABEL: @square_nnan_fabs_intrinsic_f32(
97; CHECK-NEXT:    [[MUL:%.*]] = fmul nnan float [[X:%.*]], [[X]]
98; CHECK-NEXT:    ret float [[MUL]]
99;
100  %mul = fmul nnan float %x, %x
101  %fabsf = call float @llvm.fabs.f32(float %mul)
102  ret float %fabsf
103}
104
105; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization.
106
107define float @square_fabs_shrink_call1(float %x) {
108; CHECK-LABEL: @square_fabs_shrink_call1(
109; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[X]]
110; CHECK-NEXT:    [[TRUNC:%.*]] = call float @llvm.fabs.f32(float [[TMP1]])
111; CHECK-NEXT:    ret float [[TRUNC]]
112;
113  %ext = fpext float %x to double
114  %sq = fmul double %ext, %ext
115  %fabs = call double @fabs(double %sq)
116  %trunc = fptrunc double %fabs to float
117  ret float %trunc
118}
119
120define float @square_fabs_shrink_call2(float %x) {
121; CHECK-LABEL: @square_fabs_shrink_call2(
122; CHECK-NEXT:    [[SQ:%.*]] = fmul float [[X:%.*]], [[X]]
123; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SQ]])
124; CHECK-NEXT:    ret float [[TMP1]]
125;
126  %sq = fmul float %x, %x
127  %ext = fpext float %sq to double
128  %fabs = call double @fabs(double %ext)
129  %trunc = fptrunc double %fabs to float
130  ret float %trunc
131}
132
133define float @fabs_select_constant_negative_positive(i32 %c) {
134; CHECK-LABEL: @fabs_select_constant_negative_positive(
135; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
136; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
137; CHECK-NEXT:    ret float [[FABS]]
138;
139  %cmp = icmp eq i32 %c, 0
140  %select = select i1 %cmp, float -1.0, float 2.0
141  %fabs = call float @llvm.fabs.f32(float %select)
142  ret float %fabs
143}
144
145define float @fabs_select_constant_positive_negative(i32 %c) {
146; CHECK-LABEL: @fabs_select_constant_positive_negative(
147; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
148; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
149; CHECK-NEXT:    ret float [[FABS]]
150;
151  %cmp = icmp eq i32 %c, 0
152  %select = select i1 %cmp, float 1.0, float -2.0
153  %fabs = call float @llvm.fabs.f32(float %select)
154  ret float %fabs
155}
156
157define float @fabs_select_constant_negative_negative(i32 %c) {
158; CHECK-LABEL: @fabs_select_constant_negative_negative(
159; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
160; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
161; CHECK-NEXT:    ret float [[FABS]]
162;
163  %cmp = icmp eq i32 %c, 0
164  %select = select i1 %cmp, float -1.0, float -2.0
165  %fabs = call float @llvm.fabs.f32(float %select)
166  ret float %fabs
167}
168
169define float @fabs_select_constant_neg0(i32 %c) {
170; CHECK-LABEL: @fabs_select_constant_neg0(
171; CHECK-NEXT:    ret float 0.000000e+00
172;
173  %cmp = icmp eq i32 %c, 0
174  %select = select i1 %cmp, float -0.0, float 0.0
175  %fabs = call float @llvm.fabs.f32(float %select)
176  ret float %fabs
177}
178
179define float @fabs_select_var_constant_negative(i32 %c, float %x) {
180; CHECK-LABEL: @fabs_select_var_constant_negative(
181; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
182; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT:%.*]])
183; CHECK-NEXT:    [[FABS1:%.*]] = select i1 [[CMP]], float [[FABS]], float 1.000000e+00
184; CHECK-NEXT:    ret float [[FABS1]]
185;
186  %cmp = icmp eq i32 %c, 0
187  %select = select i1 %cmp, float %x, float -1.0
188  %fabs = call float @llvm.fabs.f32(float %select)
189  ret float %fabs
190}
191
192; The fabs cannot be eliminated because %x may be a NaN
193
194define float @square_fma_fabs_intrinsic_f32(float %x) {
195; CHECK-LABEL: @square_fma_fabs_intrinsic_f32(
196; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
197; CHECK-NEXT:    [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMA]])
198; CHECK-NEXT:    ret float [[FABSF]]
199;
200  %fma = call float @llvm.fma.f32(float %x, float %x, float 1.0)
201  %fabsf = call float @llvm.fabs.f32(float %fma)
202  ret float %fabsf
203}
204
205; The fabs cannot be eliminated because %x may be a NaN
206
207define float @square_nnan_fma_fabs_intrinsic_f32(float %x) {
208; CHECK-LABEL: @square_nnan_fma_fabs_intrinsic_f32(
209; CHECK-NEXT:    [[FMA:%.*]] = call nnan float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
210; CHECK-NEXT:    ret float [[FMA]]
211;
212  %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.0)
213  %fabsf = call float @llvm.fabs.f32(float %fma)
214  ret float %fabsf
215}
216
217define float @square_fmuladd_fabs_intrinsic_f32(float %x) {
218; CHECK-LABEL: @square_fmuladd_fabs_intrinsic_f32(
219; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
220; CHECK-NEXT:    [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMULADD]])
221; CHECK-NEXT:    ret float [[FABSF]]
222;
223  %fmuladd = call float @llvm.fmuladd.f32(float %x, float %x, float 1.0)
224  %fabsf = call float @llvm.fabs.f32(float %fmuladd)
225  ret float %fabsf
226}
227
228define float @square_nnan_fmuladd_fabs_intrinsic_f32(float %x) {
229; CHECK-LABEL: @square_nnan_fmuladd_fabs_intrinsic_f32(
230; CHECK-NEXT:    [[FMULADD:%.*]] = call nnan float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00)
231; CHECK-NEXT:    ret float [[FMULADD]]
232;
233  %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.0)
234  %fabsf = call float @llvm.fabs.f32(float %fmuladd)
235  ret float %fabsf
236}
237
238; Don't introduce a second fpext
239
240define double @multi_use_fabs_fpext(float %x) {
241; CHECK-LABEL: @multi_use_fabs_fpext(
242; CHECK-NEXT:    [[FPEXT:%.*]] = fpext float [[X:%.*]] to double
243; CHECK-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[FPEXT]])
244; CHECK-NEXT:    store volatile double [[FPEXT]], ptr undef, align 8
245; CHECK-NEXT:    ret double [[FABS]]
246;
247  %fpext = fpext float %x to double
248  %fabs = call double @llvm.fabs.f64(double %fpext)
249  store volatile double %fpext, ptr undef
250  ret double %fabs
251}
252
253; X <= 0.0 ? (0.0 - X) : X --> fabs(X)
254
255define double @select_fcmp_ole_zero(double %x) {
256; CHECK-LABEL: @select_fcmp_ole_zero(
257; CHECK-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
258; CHECK-NEXT:    ret double [[FABS]]
259;
260  %lezero = fcmp ole double %x, 0.0
261  %negx = fsub double 0.0, %x
262  %fabs = select i1 %lezero, double %negx, double %x
263  ret double %fabs
264}
265
266define double @select_fcmp_nnan_ole_zero(double %x) {
267; CHECK-LABEL: @select_fcmp_nnan_ole_zero(
268; CHECK-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
269; CHECK-NEXT:    ret double [[FABS]]
270;
271  %lezero = fcmp ole double %x, 0.0
272  %negx = fsub nnan double 0.0, %x
273  %fabs = select i1 %lezero, double %negx, double %x
274  ret double %fabs
275}
276
277define double @select_nnan_fcmp_nnan_ole_zero(double %x) {
278; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_zero(
279; CHECK-NEXT:    [[FABS:%.*]] = call nnan double @llvm.fabs.f64(double [[X:%.*]])
280; CHECK-NEXT:    ret double [[FABS]]
281;
282  %lezero = fcmp ole double %x, 0.0
283  %negx = fsub nnan double 0.0, %x
284  %fabs = select nnan i1 %lezero, double %negx, double %x
285  ret double %fabs
286}
287
288; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
289
290define double @select_fcmp_nnan_ule_zero(double %x) {
291; CHECK-LABEL: @select_fcmp_nnan_ule_zero(
292; CHECK-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
293; CHECK-NEXT:    ret double [[FABS]]
294;
295  %lezero = fcmp ule double %x, 0.0
296  %negx = fsub nnan double 0.0, %x
297  %fabs = select i1 %lezero, double %negx, double %x
298  ret double %fabs
299}
300
301; Negative test - wrong predicate.
302
303define double @select_fcmp_nnan_olt_zero(double %x) {
304; CHECK-LABEL: @select_fcmp_nnan_olt_zero(
305; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00
306; CHECK-NEXT:    [[NEGX:%.*]] = fsub nnan double 0.000000e+00, [[X]]
307; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]]
308; CHECK-NEXT:    ret double [[FABS]]
309;
310  %lezero = fcmp olt double %x, 0.0
311  %negx = fsub nnan double 0.0, %x
312  %fabs = select i1 %lezero, double %negx, double %x
313  ret double %fabs
314}
315
316; X <= -0.0 ? (0.0 - X) : X --> fabs(X)
317
318define <2 x float> @select_fcmp_nnan_ole_negzero(<2 x float> %x) {
319; CHECK-LABEL: @select_fcmp_nnan_ole_negzero(
320; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
321; CHECK-NEXT:    ret <2 x float> [[FABS]]
322;
323  %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0>
324  %negx = fsub nnan <2 x float> <float 0.0, float poison>, %x
325  %fabs = select <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x
326  ret <2 x float> %fabs
327}
328
329define <2 x float> @select_nnan_fcmp_nnan_ole_negzero(<2 x float> %x) {
330; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_negzero(
331; CHECK-NEXT:    [[FABS:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
332; CHECK-NEXT:    ret <2 x float> [[FABS]]
333;
334  %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0>
335  %negx = fsub nnan <2 x float> <float 0.0, float poison>, %x
336  %fabs = select nnan <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x
337  ret <2 x float> %fabs
338}
339
340; X > 0.0 ? X : (0.0 - X) --> fabs(X)
341
342define fp128 @select_fcmp_ogt_zero(fp128 %x) {
343; CHECK-LABEL: @select_fcmp_ogt_zero(
344; CHECK-NEXT:    [[FABS:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
345; CHECK-NEXT:    ret fp128 [[FABS]]
346;
347  %gtzero = fcmp ogt fp128 %x, zeroinitializer
348  %negx = fsub fp128 zeroinitializer, %x
349  %fabs = select i1 %gtzero, fp128 %x, fp128 %negx
350  ret fp128 %fabs
351}
352
353; This is not fabs because that could produce a different signbit for a NAN input.
354; PR59279
355
356define float @select_nsz_fcmp_ogt_fneg(float %a) {
357; CHECK-LABEL: @select_nsz_fcmp_ogt_fneg(
358; CHECK-NEXT:    [[FNEG:%.*]] = fneg float [[A:%.*]]
359; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[A]], 0.000000e+00
360; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[CMP]], float [[A]], float [[FNEG]]
361; CHECK-NEXT:    ret float [[R]]
362;
363  %fneg = fneg float %a
364  %cmp = fcmp ogt float %a, %fneg
365  %r = select nsz i1 %cmp, float %a, float %fneg
366  ret float %r
367}
368
369define float @select_nsz_nnan_fcmp_ogt_fneg(float %a) {
370; CHECK-LABEL: @select_nsz_nnan_fcmp_ogt_fneg(
371; CHECK-NEXT:    [[R:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[A:%.*]])
372; CHECK-NEXT:    ret float [[R]]
373;
374  %fneg = fneg float %a
375  %cmp = fcmp ogt float %a, %fneg
376  %r = select nsz nnan i1 %cmp, float %a, float %fneg
377  ret float %r
378}
379
380define fp128 @select_fcmp_nnan_ogt_zero(fp128 %x) {
381; CHECK-LABEL: @select_fcmp_nnan_ogt_zero(
382; CHECK-NEXT:    [[FABS:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
383; CHECK-NEXT:    ret fp128 [[FABS]]
384;
385  %gtzero = fcmp ogt fp128 %x, zeroinitializer
386  %negx = fsub nnan fp128 zeroinitializer, %x
387  %fabs = select i1 %gtzero, fp128 %x, fp128 %negx
388  ret fp128 %fabs
389}
390
391define fp128 @select_nnan_fcmp_nnan_ogt_zero(fp128 %x) {
392; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_zero(
393; CHECK-NEXT:    [[FABS:%.*]] = call nnan fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
394; CHECK-NEXT:    ret fp128 [[FABS]]
395;
396  %gtzero = fcmp ogt fp128 %x, zeroinitializer
397  %negx = fsub nnan fp128 zeroinitializer, %x
398  %fabs = select nnan i1 %gtzero, fp128 %x, fp128 %negx
399  ret fp128 %fabs
400}
401
402; X > -0.0 ? X : (0.0 - X) --> fabs(X)
403
404define half @select_fcmp_nnan_ogt_negzero(half %x) {
405; CHECK-LABEL: @select_fcmp_nnan_ogt_negzero(
406; CHECK-NEXT:    [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
407; CHECK-NEXT:    ret half [[FABS]]
408;
409  %gtzero = fcmp ogt half %x, -0.0
410  %negx = fsub nnan half 0.0, %x
411  %fabs = select i1 %gtzero, half %x, half %negx
412  ret half %fabs
413}
414
415define half @select_nnan_fcmp_nnan_ogt_negzero(half %x) {
416; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_negzero(
417; CHECK-NEXT:    [[FABS:%.*]] = call nnan half @llvm.fabs.f16(half [[X:%.*]])
418; CHECK-NEXT:    ret half [[FABS]]
419;
420  %gtzero = fcmp ogt half %x, -0.0
421  %negx = fsub nnan half 0.0, %x
422  %fabs = select nnan i1 %gtzero, half %x, half %negx
423  ret half %fabs
424}
425
426; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
427
428define half @select_fcmp_nnan_ugt_negzero(half %x) {
429; CHECK-LABEL: @select_fcmp_nnan_ugt_negzero(
430; CHECK-NEXT:    [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
431; CHECK-NEXT:    ret half [[FABS]]
432;
433  %gtzero = fcmp ugt half %x, -0.0
434  %negx = fsub nnan half 0.0, %x
435  %fabs = select i1 %gtzero, half %x, half %negx
436  ret half %fabs
437}
438
439; Negative test - wrong predicate.
440
441define half @select_fcmp_nnan_oge_negzero(half %x) {
442; CHECK-LABEL: @select_fcmp_nnan_oge_negzero(
443; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
444; CHECK-NEXT:    [[NEGX:%.*]] = fsub nnan half 0xH0000, [[X]]
445; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]]
446; CHECK-NEXT:    ret half [[FABS]]
447;
448  %gtzero = fcmp oge half %x, -0.0
449  %negx = fsub nnan half 0.0, %x
450  %fabs = select i1 %gtzero, half %x, half %negx
451  ret half %fabs
452}
453
454; This is not fabs because that could produce a different signbit for a NAN input.
455; PR59279
456
457define double @select_nsz_fcmp_olt_zero_unary_fneg(double %x) {
458; CHECK-LABEL: @select_nsz_fcmp_olt_zero_unary_fneg(
459; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00
460; CHECK-NEXT:    [[NEGX:%.*]] = fneg double [[X]]
461; CHECK-NEXT:    [[FABS:%.*]] = select nsz i1 [[LTZERO]], double [[NEGX]], double [[X]]
462; CHECK-NEXT:    ret double [[FABS]]
463;
464  %ltzero = fcmp olt double %x, 0.0
465  %negx = fneg double %x
466  %fabs = select nsz i1 %ltzero, double %negx, double %x
467  ret double %fabs
468}
469
470; X < 0.0 ? -X : X --> fabs(X)
471
472define double @select_nsz_nnan_fcmp_olt_zero_unary_fneg(double %x) {
473; CHECK-LABEL: @select_nsz_nnan_fcmp_olt_zero_unary_fneg(
474; CHECK-NEXT:    [[FABS:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]])
475; CHECK-NEXT:    ret double [[FABS]]
476;
477  %ltzero = fcmp olt double %x, 0.0
478  %negx = fneg double %x
479  %fabs = select nsz nnan i1 %ltzero, double %negx, double %x
480  ret double %fabs
481}
482
483define double @select_fcmp_nnan_nsz_olt_zero(double %x) {
484; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero(
485; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00
486; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
487; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]]
488; CHECK-NEXT:    ret double [[FABS]]
489;
490  %ltzero = fcmp olt double %x, 0.0
491  %negx = fsub nnan nsz double -0.0, %x
492  %fabs = select i1 %ltzero, double %negx, double %x
493  ret double %fabs
494}
495
496define double @select_nnan_nsz_fcmp_nnan_nsz_olt_zero(double %x) {
497; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_olt_zero(
498; CHECK-NEXT:    [[FABS:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]])
499; CHECK-NEXT:    ret double [[FABS]]
500;
501  %ltzero = fcmp olt double %x, 0.0
502  %negx = fsub nnan nsz double -0.0, %x
503  %fabs = select nnan nsz i1 %ltzero, double %negx, double %x
504  ret double %fabs
505}
506
507; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
508
509define double @select_fcmp_nnan_nsz_ult_zero(double %x) {
510; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero(
511; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00
512; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
513; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]]
514; CHECK-NEXT:    ret double [[FABS]]
515;
516  %ltzero = fcmp ult double %x, 0.0
517  %negx = fsub nnan nsz double -0.0, %x
518  %fabs = select i1 %ltzero, double %negx, double %x
519  ret double %fabs
520}
521
522define double @select_fcmp_nnan_nsz_olt_zero_unary_fneg(double %x) {
523; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero_unary_fneg(
524; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00
525; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
526; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]]
527; CHECK-NEXT:    ret double [[FABS]]
528;
529  %ltzero = fcmp olt double %x, 0.0
530  %negx = fneg nnan nsz double %x
531  %fabs = select i1 %ltzero, double %negx, double %x
532  ret double %fabs
533}
534
535; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
536
537define double @select_fcmp_nnan_nsz_ult_zero_unary_fneg(double %x) {
538; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero_unary_fneg(
539; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00
540; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz double [[X]]
541; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]]
542; CHECK-NEXT:    ret double [[FABS]]
543;
544  %ltzero = fcmp ult double %x, 0.0
545  %negx = fneg nnan nsz double %x
546  %fabs = select i1 %ltzero, double %negx, double %x
547  ret double %fabs
548}
549
550; X < -0.0 ? -X : X --> fabs(X)
551
552define float @select_fcmp_nnan_nsz_olt_negzero(float %x) {
553; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero(
554; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
555; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
556; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]]
557; CHECK-NEXT:    ret float [[FABS]]
558;
559  %ltzero = fcmp olt float %x, -0.0
560  %negx = fsub nnan ninf nsz float -0.0, %x
561  %fabs = select i1 %ltzero, float %negx, float %x
562  ret float %fabs
563}
564
565define float @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero(float %x) {
566; CHECK-LABEL: @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero(
567; CHECK-NEXT:    [[FABS:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[X:%.*]])
568; CHECK-NEXT:    ret float [[FABS]]
569;
570  %ltzero = fcmp olt float %x, -0.0
571  %negx = fsub nnan nsz float -0.0, %x
572  %fabs = select nnan ninf nsz i1 %ltzero, float %negx, float %x
573  ret float %fabs
574}
575
576; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
577
578define float @select_fcmp_nnan_nsz_ult_negzero(float %x) {
579; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero(
580; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00
581; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
582; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]]
583; CHECK-NEXT:    ret float [[FABS]]
584;
585  %ltzero = fcmp ult float %x, -0.0
586  %negx = fsub nnan ninf nsz float -0.0, %x
587  %fabs = select i1 %ltzero, float %negx, float %x
588  ret float %fabs
589}
590
591define float @select_fcmp_nnan_nsz_olt_negzero_unary_fneg(float %x) {
592; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero_unary_fneg(
593; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
594; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
595; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]]
596; CHECK-NEXT:    ret float [[FABS]]
597;
598  %ltzero = fcmp olt float %x, -0.0
599  %negx = fneg nnan ninf nsz float %x
600  %fabs = select i1 %ltzero, float %negx, float %x
601  ret float %fabs
602}
603
604; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
605
606define float @select_fcmp_nnan_nsz_ult_negzero_unary_fneg(float %x) {
607; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero_unary_fneg(
608; CHECK-NEXT:    [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00
609; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]]
610; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]]
611; CHECK-NEXT:    ret float [[FABS]]
612;
613  %ltzero = fcmp ult float %x, -0.0
614  %negx = fneg nnan ninf nsz float %x
615  %fabs = select i1 %ltzero, float %negx, float %x
616  ret float %fabs
617}
618
619; X <= 0.0 ? -X : X --> fabs(X)
620
621define double @select_fcmp_nnan_nsz_ole_zero(double %x) {
622; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero(
623; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00
624; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
625; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]]
626; CHECK-NEXT:    ret double [[FABS]]
627;
628  %lezero = fcmp ole double %x, 0.0
629  %negx = fsub fast double -0.0, %x
630  %fabs = select i1 %lezero, double %negx, double %x
631  ret double %fabs
632}
633
634define double @select_fast_fcmp_nnan_nsz_ole_zero(double %x) {
635; CHECK-LABEL: @select_fast_fcmp_nnan_nsz_ole_zero(
636; CHECK-NEXT:    [[FABS:%.*]] = call fast double @llvm.fabs.f64(double [[X:%.*]])
637; CHECK-NEXT:    ret double [[FABS]]
638;
639  %lezero = fcmp ole double %x, 0.0
640  %negx = fsub nnan nsz double -0.0, %x
641  %fabs = select fast i1 %lezero, double %negx, double %x
642  ret double %fabs
643}
644
645; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
646
647define double @select_fcmp_nnan_nsz_ule_zero(double %x) {
648; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero(
649; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00
650; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
651; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]]
652; CHECK-NEXT:    ret double [[FABS]]
653;
654  %lezero = fcmp ule double %x, 0.0
655  %negx = fsub fast double -0.0, %x
656  %fabs = select i1 %lezero, double %negx, double %x
657  ret double %fabs
658}
659
660define double @select_fcmp_nnan_nsz_ole_zero_unary_fneg(double %x) {
661; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero_unary_fneg(
662; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00
663; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
664; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]]
665; CHECK-NEXT:    ret double [[FABS]]
666;
667  %lezero = fcmp ole double %x, 0.0
668  %negx = fneg fast double %x
669  %fabs = select i1 %lezero, double %negx, double %x
670  ret double %fabs
671}
672
673; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
674
675define double @select_fcmp_nnan_nsz_ule_zero_unary_fneg(double %x) {
676; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero_unary_fneg(
677; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00
678; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast double [[X]]
679; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]]
680; CHECK-NEXT:    ret double [[FABS]]
681;
682  %lezero = fcmp ule double %x, 0.0
683  %negx = fneg fast double %x
684  %fabs = select i1 %lezero, double %negx, double %x
685  ret double %fabs
686}
687
688; X <= -0.0 ? -X : X --> fabs(X)
689
690define float @select_fcmp_nnan_nsz_ole_negzero(float %x) {
691; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero(
692; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00
693; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
694; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]]
695; CHECK-NEXT:    ret float [[FABS]]
696;
697  %lezero = fcmp ole float %x, -0.0
698  %negx = fsub nnan nsz float -0.0, %x
699  %fabs = select i1 %lezero, float %negx, float %x
700  ret float %fabs
701}
702
703define float @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero(float %x) {
704; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero(
705; CHECK-NEXT:    [[FABS:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X:%.*]])
706; CHECK-NEXT:    ret float [[FABS]]
707;
708  %lezero = fcmp ole float %x, -0.0
709  %negx = fsub nnan nsz float -0.0, %x
710  %fabs = select nnan nsz i1 %lezero, float %negx, float %x
711  ret float %fabs
712}
713
714; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
715
716define float @select_fcmp_nnan_nsz_ule_negzero(float %x) {
717; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero(
718; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00
719; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
720; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]]
721; CHECK-NEXT:    ret float [[FABS]]
722;
723  %lezero = fcmp ule float %x, -0.0
724  %negx = fsub nnan nsz float -0.0, %x
725  %fabs = select i1 %lezero, float %negx, float %x
726  ret float %fabs
727}
728
729define float @select_fcmp_nnan_nsz_ole_negzero_unary_fneg(float %x) {
730; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero_unary_fneg(
731; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00
732; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
733; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]]
734; CHECK-NEXT:    ret float [[FABS]]
735;
736  %lezero = fcmp ole float %x, -0.0
737  %negx = fneg nnan nsz float %x
738  %fabs = select i1 %lezero, float %negx, float %x
739  ret float %fabs
740}
741
742; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
743
744define float @select_fcmp_nnan_nsz_ule_negzero_unary_fneg(float %x) {
745; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero_unary_fneg(
746; CHECK-NEXT:    [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00
747; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz float [[X]]
748; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]]
749; CHECK-NEXT:    ret float [[FABS]]
750;
751  %lezero = fcmp ule float %x, -0.0
752  %negx = fneg nnan nsz float %x
753  %fabs = select i1 %lezero, float %negx, float %x
754  ret float %fabs
755}
756
757; This is not fabs because that could produce a different signbit for a NAN input.
758; PR59279
759
760define <2 x float> @select_nsz_fcmp_ogt_zero_unary_fneg(<2 x float> %x) {
761; CHECK-LABEL: @select_nsz_fcmp_ogt_zero_unary_fneg(
762; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer
763; CHECK-NEXT:    [[NEGX:%.*]] = fneg <2 x float> [[X]]
764; CHECK-NEXT:    [[FABS:%.*]] = select nsz <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
765; CHECK-NEXT:    ret <2 x float> [[FABS]]
766;
767  %gtzero = fcmp ogt <2 x float> %x, zeroinitializer
768  %negx = fneg <2 x float> %x
769  %fabs = select nsz <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
770  ret <2 x float> %fabs
771}
772
773; X > 0.0 ? X : (-X) --> fabs(X)
774
775define <2 x float> @select_nsz_nnan_fcmp_ogt_zero_unary_fneg(<2 x float> %x) {
776; CHECK-LABEL: @select_nsz_nnan_fcmp_ogt_zero_unary_fneg(
777; CHECK-NEXT:    [[FABS:%.*]] = call nnan nsz <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
778; CHECK-NEXT:    ret <2 x float> [[FABS]]
779;
780  %gtzero = fcmp ogt <2 x float> %x, zeroinitializer
781  %negx = fneg <2 x float> %x
782  %fabs = select nsz nnan <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
783  ret <2 x float> %fabs
784}
785
786define <2 x float> @select_fcmp_nnan_nsz_ogt_zero(<2 x float> %x) {
787; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero(
788; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer
789; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
790; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
791; CHECK-NEXT:    ret <2 x float> [[FABS]]
792;
793  %gtzero = fcmp ogt <2 x float> %x, zeroinitializer
794  %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x
795  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
796  ret <2 x float> %fabs
797}
798
799; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
800
801define <2 x float> @select_fcmp_nnan_nsz_ugt_zero(<2 x float> %x) {
802; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero(
803; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer
804; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
805; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
806; CHECK-NEXT:    ret <2 x float> [[FABS]]
807;
808  %gtzero = fcmp ugt <2 x float> %x, zeroinitializer
809  %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x
810  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
811  ret <2 x float> %fabs
812}
813
814define <2 x float> @select_fcmp_nnan_nsz_ogt_zero_unary_fneg(<2 x float> %x) {
815; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero_unary_fneg(
816; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer
817; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
818; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
819; CHECK-NEXT:    ret <2 x float> [[FABS]]
820;
821  %gtzero = fcmp ogt <2 x float> %x, zeroinitializer
822  %negx = fneg nnan nsz arcp <2 x float> %x
823  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
824  ret <2 x float> %fabs
825}
826
827; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
828
829define <2 x float> @select_fcmp_nnan_nsz_ugt_zero_unary_fneg(<2 x float> %x) {
830; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero_unary_fneg(
831; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer
832; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]]
833; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]]
834; CHECK-NEXT:    ret <2 x float> [[FABS]]
835;
836  %gtzero = fcmp ugt <2 x float> %x, zeroinitializer
837  %negx = fneg nnan nsz arcp <2 x float> %x
838  %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx
839  ret <2 x float> %fabs
840}
841
842; X > -0.0 ? X : (0.0 - X) --> fabs(X)
843
844define half @select_fcmp_nnan_nsz_ogt_negzero(half %x) {
845; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_negzero(
846; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ogt half [[X:%.*]], 0xH0000
847; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast half [[X]]
848; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[GTZERO]], half [[X]], half [[NEGX]]
849; CHECK-NEXT:    ret half [[FABS]]
850;
851  %gtzero = fcmp ogt half %x, -0.0
852  %negx = fsub fast half 0.0, %x
853  %fabs = select i1 %gtzero, half %x, half %negx
854  ret half %fabs
855}
856
857; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
858
859define half @select_fcmp_nnan_nsz_ugt_negzero(half %x) {
860; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_negzero(
861; CHECK-NEXT:    [[GTZERO:%.*]] = fcmp ugt half [[X:%.*]], 0xH0000
862; CHECK-NEXT:    [[NEGX:%.*]] = fneg fast half [[X]]
863; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[GTZERO]], half [[X]], half [[NEGX]]
864; CHECK-NEXT:    ret half [[FABS]]
865;
866  %gtzero = fcmp ugt half %x, -0.0
867  %negx = fsub fast half 0.0, %x
868  %fabs = select i1 %gtzero, half %x, half %negx
869  ret half %fabs
870}
871
872; X > 0.0 ? X : (0.0 - X) --> fabs(X)
873
874define <2 x double> @select_fcmp_nnan_nsz_oge_zero(<2 x double> %x) {
875; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero(
876; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer
877; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
878; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
879; CHECK-NEXT:    ret <2 x double> [[FABS]]
880;
881  %gezero = fcmp oge <2 x double> %x, zeroinitializer
882  %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x
883  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
884  ret <2 x double> %fabs
885}
886
887; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
888
889define <2 x double> @select_fcmp_nnan_nsz_uge_zero(<2 x double> %x) {
890; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero(
891; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer
892; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
893; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
894; CHECK-NEXT:    ret <2 x double> [[FABS]]
895;
896  %gezero = fcmp uge <2 x double> %x, zeroinitializer
897  %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x
898  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
899  ret <2 x double> %fabs
900}
901
902define <2 x double> @select_fcmp_nnan_nsz_oge_zero_unary_fneg(<2 x double> %x) {
903; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero_unary_fneg(
904; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer
905; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
906; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
907; CHECK-NEXT:    ret <2 x double> [[FABS]]
908;
909  %gezero = fcmp oge <2 x double> %x, zeroinitializer
910  %negx = fneg nnan nsz reassoc <2 x double> %x
911  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
912  ret <2 x double> %fabs
913}
914
915; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
916
917define <2 x double> @select_fcmp_nnan_nsz_uge_zero_unary_fneg(<2 x double> %x) {
918; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero_unary_fneg(
919; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer
920; CHECK-NEXT:    [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]]
921; CHECK-NEXT:    [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]]
922; CHECK-NEXT:    ret <2 x double> [[FABS]]
923;
924  %gezero = fcmp uge <2 x double> %x, zeroinitializer
925  %negx = fneg nnan nsz reassoc <2 x double> %x
926  %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx
927  ret <2 x double> %fabs
928}
929
930; X > -0.0 ? X : (0.0 - X) --> fabs(X)
931
932define half @select_fcmp_nnan_nsz_oge_negzero(half %x) {
933; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero(
934; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
935; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
936; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]]
937; CHECK-NEXT:    ret half [[FABS]]
938;
939  %gezero = fcmp oge half %x, -0.0
940  %negx = fsub nnan nsz half -0.0, %x
941  %fabs = select i1 %gezero, half %x, half %negx
942  ret half %fabs
943}
944
945; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
946
947define half @select_fcmp_nnan_nsz_uge_negzero(half %x) {
948; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero(
949; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000
950; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
951; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]]
952; CHECK-NEXT:    ret half [[FABS]]
953;
954  %gezero = fcmp uge half %x, -0.0
955  %negx = fsub nnan nsz half -0.0, %x
956  %fabs = select i1 %gezero, half %x, half %negx
957  ret half %fabs
958}
959
960define half @select_fcmp_nnan_nsz_oge_negzero_unary_fneg(half %x) {
961; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero_unary_fneg(
962; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
963; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
964; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]]
965; CHECK-NEXT:    ret half [[FABS]]
966;
967  %gezero = fcmp oge half %x, -0.0
968  %negx = fneg nnan nsz half %x
969  %fabs = select i1 %gezero, half %x, half %negx
970  ret half %fabs
971}
972
973; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
974
975define half @select_fcmp_nnan_nsz_uge_negzero_unary_fneg(half %x) {
976; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero_unary_fneg(
977; CHECK-NEXT:    [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000
978; CHECK-NEXT:    [[NEGX:%.*]] = fneg nnan nsz half [[X]]
979; CHECK-NEXT:    [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]]
980; CHECK-NEXT:    ret half [[FABS]]
981;
982  %gezero = fcmp uge half %x, -0.0
983  %negx = fneg nnan nsz half %x
984  %fabs = select i1 %gezero, half %x, half %negx
985  ret half %fabs
986}
987
988define float @select_fneg(i1 %c, float %x) {
989; CHECK-LABEL: @select_fneg(
990; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
991; CHECK-NEXT:    ret float [[FABS]]
992;
993  %n = fneg float %x
994  %s = select i1 %c, float %n, float %x
995  %fabs = call float @llvm.fabs.f32(float %s)
996  ret float %fabs
997}
998
999define float @select_fneg_use1(i1 %c, float %x) {
1000; CHECK-LABEL: @select_fneg_use1(
1001; CHECK-NEXT:    [[N:%.*]] = fneg float [[X:%.*]]
1002; CHECK-NEXT:    call void @use(float [[N]])
1003; CHECK-NEXT:    [[FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]])
1004; CHECK-NEXT:    ret float [[FABS]]
1005;
1006  %n = fneg float %x
1007  call void @use(float %n)
1008  %s = select i1 %c, float %x, float %n
1009  %fabs = call fast float @llvm.fabs.f32(float %s)
1010  ret float %fabs
1011}
1012
1013define float @select_fneg_use2(i1 %c, float %x) {
1014; CHECK-LABEL: @select_fneg_use2(
1015; CHECK-NEXT:    [[N:%.*]] = fneg arcp float [[X:%.*]]
1016; CHECK-NEXT:    [[S:%.*]] = select i1 [[C:%.*]], float [[N]], float [[X]]
1017; CHECK-NEXT:    call void @use(float [[S]])
1018; CHECK-NEXT:    [[FABS:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X]])
1019; CHECK-NEXT:    ret float [[FABS]]
1020;
1021  %n = fneg arcp float %x
1022  %s = select i1 %c, float %n, float %x
1023  call void @use(float %s)
1024  %fabs = call nnan nsz float @llvm.fabs.f32(float %s)
1025  ret float %fabs
1026}
1027
1028define <2 x float> @select_fneg_vec(<2 x i1> %c, <2 x float> %x) {
1029; CHECK-LABEL: @select_fneg_vec(
1030; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
1031; CHECK-NEXT:    ret <2 x float> [[FABS]]
1032;
1033  %n = fneg <2 x float> %x
1034  %s = select fast <2 x i1> %c, <2 x float> %x, <2 x float> %n
1035  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %s)
1036  ret <2 x float> %fabs
1037}
1038
1039define float @test_select_neg_negx_x(float %value) {
1040; CHECK-LABEL: @test_select_neg_negx_x(
1041; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]])
1042; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1043;
1044  %a0 = bitcast float %value to i32
1045  %a1 = icmp slt i32 %a0, 0
1046  %fneg.i = fneg float %value
1047  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1048  ret float %value.addr.0.i
1049}
1050
1051define float @test_select_nneg_negx_x(float %value) {
1052; CHECK-LABEL: @test_select_nneg_negx_x(
1053; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]])
1054; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = fneg float [[TMP1]]
1055; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1056;
1057  %a0 = bitcast float %value to i32
1058  %a1 = icmp sgt i32 %a0, -1
1059  %fneg.i = fneg float %value
1060  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1061  ret float %value.addr.0.i
1062}
1063
1064define float @test_select_neg_x_negx(float %value) {
1065; CHECK-LABEL: @test_select_neg_x_negx(
1066; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]])
1067; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = fneg float [[TMP1]]
1068; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1069;
1070  %a0 = bitcast float %value to i32
1071  %a1 = icmp slt i32 %a0, 0
1072  %fneg.i = fneg float %value
1073  %value.addr.0.i = select i1 %a1, float %value, float %fneg.i
1074  ret float %value.addr.0.i
1075}
1076
1077define float @test_select_nneg_x_negx(float %value) {
1078; CHECK-LABEL: @test_select_nneg_x_negx(
1079; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]])
1080; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1081;
1082  %a0 = bitcast float %value to i32
1083  %a1 = icmp sgt i32 %a0, -1
1084  %fneg.i = fneg float %value
1085  %value.addr.0.i = select i1 %a1, float %value, float %fneg.i
1086  ret float %value.addr.0.i
1087}
1088
1089define float @test_select_neg_negx_x_multiuse1(float %value) {
1090; CHECK-LABEL: @test_select_neg_negx_x_multiuse1(
1091; CHECK-NEXT:    [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32
1092; CHECK-NEXT:    [[A1:%.*]] = icmp slt i32 [[A0]], 0
1093; CHECK-NEXT:    call void @usebool(i1 [[A1]])
1094; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE]])
1095; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1096;
1097  %a0 = bitcast float %value to i32
1098  %a1 = icmp slt i32 %a0, 0
1099  call void @usebool(i1 %a1)
1100  %fneg.i = fneg float %value
1101  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1102  ret float %value.addr.0.i
1103}
1104
1105define float @test_select_neg_negx_x_multiuse2(float %value) {
1106; CHECK-LABEL: @test_select_neg_negx_x_multiuse2(
1107; CHECK-NEXT:    [[FNEG_I:%.*]] = fneg float [[VALUE:%.*]]
1108; CHECK-NEXT:    call void @use(float [[FNEG_I]])
1109; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE]])
1110; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1111;
1112  %a0 = bitcast float %value to i32
1113  %a1 = icmp slt i32 %a0, 0
1114  %fneg.i = fneg float %value
1115  call void @use(float %fneg.i)
1116  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1117  ret float %value.addr.0.i
1118}
1119
1120define float @test_select_neg_negx_x_multiuse3(float %value) {
1121; CHECK-LABEL: @test_select_neg_negx_x_multiuse3(
1122; CHECK-NEXT:    [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32
1123; CHECK-NEXT:    [[A1:%.*]] = icmp slt i32 [[A0]], 0
1124; CHECK-NEXT:    call void @usebool(i1 [[A1]])
1125; CHECK-NEXT:    [[FNEG_I:%.*]] = fneg float [[VALUE]]
1126; CHECK-NEXT:    call void @use(float [[FNEG_I]])
1127; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE]])
1128; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1129;
1130  %a0 = bitcast float %value to i32
1131  %a1 = icmp slt i32 %a0, 0
1132  call void @usebool(i1 %a1)
1133  %fneg.i = fneg float %value
1134  call void @use(float %fneg.i)
1135  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1136  ret float %value.addr.0.i
1137}
1138
1139define float @test_select_neg_negx_x_fmf(float %value) {
1140; CHECK-LABEL: @test_select_neg_negx_x_fmf(
1141; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[VALUE:%.*]])
1142; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1143;
1144  %a0 = bitcast float %value to i32
1145  %a1 = icmp slt i32 %a0, 0
1146  %fneg.i = fneg float %value
1147  %value.addr.0.i = select nsz nnan ninf i1 %a1, float %fneg.i, float %value
1148  ret float %value.addr.0.i
1149}
1150
1151define float @test_select_nneg_negx_x_fmf(float %value) {
1152; CHECK-LABEL: @test_select_nneg_negx_x_fmf(
1153; CHECK-NEXT:    [[TMP1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[VALUE:%.*]])
1154; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = fneg nnan ninf nsz float [[TMP1]]
1155; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1156;
1157  %a0 = bitcast float %value to i32
1158  %a1 = icmp sgt i32 %a0, -1
1159  %fneg.i = fneg float %value
1160  %value.addr.0.i = select nsz nnan ninf i1 %a1, float %fneg.i, float %value
1161  ret float %value.addr.0.i
1162}
1163
1164; Negative tests
1165
1166define float @test_select_nneg_negx_x_multiuse4(float %value) {
1167; CHECK-LABEL: @test_select_nneg_negx_x_multiuse4(
1168; CHECK-NEXT:    [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32
1169; CHECK-NEXT:    [[A1:%.*]] = icmp sgt i32 [[A0]], -1
1170; CHECK-NEXT:    call void @usebool(i1 [[A1]])
1171; CHECK-NEXT:    [[FNEG_I:%.*]] = fneg float [[VALUE]]
1172; CHECK-NEXT:    call void @use(float [[FNEG_I]])
1173; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[VALUE]]
1174; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1175;
1176  %a0 = bitcast float %value to i32
1177  %a1 = icmp sgt i32 %a0, -1
1178  call void @usebool(i1 %a1)
1179  %fneg.i = fneg float %value
1180  call void @use(float %fneg.i)
1181  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1182  ret float %value.addr.0.i
1183}
1184
1185define float @test_select_neg_negx_x_mismatched1(float %value, float %y) {
1186; CHECK-LABEL: @test_select_neg_negx_x_mismatched1(
1187; CHECK-NEXT:    [[A0:%.*]] = bitcast float [[Y:%.*]] to i32
1188; CHECK-NEXT:    [[A1:%.*]] = icmp slt i32 [[A0]], 0
1189; CHECK-NEXT:    [[FNEG_I:%.*]] = fneg float [[VALUE:%.*]]
1190; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[VALUE]]
1191; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1192;
1193  %a0 = bitcast float %y to i32
1194  %a1 = icmp slt i32 %a0, 0
1195  %fneg.i = fneg float %value
1196  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1197  ret float %value.addr.0.i
1198}
1199
1200define float @test_select_neg_negx_x_mismatched2(float %value, float %y) {
1201; CHECK-LABEL: @test_select_neg_negx_x_mismatched2(
1202; CHECK-NEXT:    [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32
1203; CHECK-NEXT:    [[A1:%.*]] = icmp slt i32 [[A0]], 0
1204; CHECK-NEXT:    [[FNEG_I:%.*]] = fneg float [[Y:%.*]]
1205; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[VALUE]]
1206; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1207;
1208  %a0 = bitcast float %value to i32
1209  %a1 = icmp slt i32 %a0, 0
1210  %fneg.i = fneg float %y
1211  %value.addr.0.i = select i1 %a1, float %fneg.i, float %value
1212  ret float %value.addr.0.i
1213}
1214
1215define float @test_select_neg_negx_x_mismatched3(float %value, float %y) {
1216; CHECK-LABEL: @test_select_neg_negx_x_mismatched3(
1217; CHECK-NEXT:    [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32
1218; CHECK-NEXT:    [[A1:%.*]] = icmp slt i32 [[A0]], 0
1219; CHECK-NEXT:    [[FNEG_I:%.*]] = fneg float [[VALUE]]
1220; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[Y:%.*]]
1221; CHECK-NEXT:    ret float [[VALUE_ADDR_0_I]]
1222;
1223  %a0 = bitcast float %value to i32
1224  %a1 = icmp slt i32 %a0, 0
1225  %fneg.i = fneg float %value
1226  %value.addr.0.i = select i1 %a1, float %fneg.i, float %y
1227  ret float %value.addr.0.i
1228}
1229
1230define <2 x float> @test_select_neg_negx_x_wrong_type(<2 x float> %value) {
1231; CHECK-LABEL: @test_select_neg_negx_x_wrong_type(
1232; CHECK-NEXT:    [[A0:%.*]] = bitcast <2 x float> [[VALUE:%.*]] to i64
1233; CHECK-NEXT:    [[A1:%.*]] = icmp slt i64 [[A0]], 0
1234; CHECK-NEXT:    [[FNEG_I:%.*]] = fneg <2 x float> [[VALUE]]
1235; CHECK-NEXT:    [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], <2 x float> [[FNEG_I]], <2 x float> [[VALUE]]
1236; CHECK-NEXT:    ret <2 x float> [[VALUE_ADDR_0_I]]
1237;
1238  %a0 = bitcast <2 x float> %value to i64
1239  %a1 = icmp slt i64 %a0, 0
1240  %fneg.i = fneg <2 x float> %value
1241  %value.addr.0.i = select i1 %a1, <2 x float> %fneg.i, <2 x float> %value
1242  ret <2 x float> %value.addr.0.i
1243}
1244