[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / fabs.ll
blobcccf0f4457b6ab54211457550914899c362bec52
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
4 ; Make sure libcalls are replaced with intrinsic calls.
6 declare float @llvm.fabs.f32(float)
7 declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
8 declare double @llvm.fabs.f64(double)
9 declare fp128 @llvm.fabs.f128(fp128)
11 declare float @fabsf(float)
12 declare double @fabs(double)
13 declare fp128 @fabsl(fp128)
14 declare float @llvm.fma.f32(float, float, float)
15 declare float @llvm.fmuladd.f32(float, float, float)
17 declare void @use(float)
18 declare void @usebool(i1)
20 define 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]]
25   %fabsf = tail call float @fabsf(float %x)
26   ret float %fabsf
29 define 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]]
34   %fabs = tail call double @fabs(double %x)
35   ret double %fabs
38 define 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]]
43   %fabsl = tail call fp128 @fabsl(fp128 %x)
44   ret fp128 %fabsl
47 ; Make sure fast math flags are preserved when replacing the libcall.
48 define 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]]
53   %fabsf = tail call nnan float @fabsf(float %x)
54   ret float %fabsf
57 ; Make sure all intrinsic calls are eliminated when the input is known
58 ; positive.
60 ; The fabs cannot be eliminated because %x may be a NaN
62 define 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]]
68   %mul = fmul float %x, %x
69   %fabsf = tail call float @llvm.fabs.f32(float %mul)
70   ret float %fabsf
73 define 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]]
79   %mul = fmul double %x, %x
80   %fabs = tail call double @llvm.fabs.f64(double %mul)
81   ret double %fabs
84 define 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]]
90   %mul = fmul fp128 %x, %x
91   %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul)
92   ret fp128 %fabsl
95 define 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]]
100   %mul = fmul nnan float %x, %x
101   %fabsf = call float @llvm.fabs.f32(float %mul)
102   ret float %fabsf
105 ; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization.
107 define 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]]
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
120 define 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]]
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
133 define 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]]
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
145 define 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]]
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
157 define 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]]
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
169 define float @fabs_select_constant_neg0(i32 %c) {
170 ; CHECK-LABEL: @fabs_select_constant_neg0(
171 ; CHECK-NEXT:    ret float 0.000000e+00
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
179 define 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]]
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
192 ; The fabs cannot be eliminated because %x may be a NaN
194 define 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]]
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
205 ; The fabs cannot be eliminated because %x may be a NaN
207 define 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]]
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
217 define 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]]
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
228 define 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]]
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
238 ; Don't introduce a second fpext
240 define 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]]
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
253 ; X <= 0.0 ? (0.0 - X) : X --> fabs(X)
255 define 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]]
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
266 define 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]]
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
277 define 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]]
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
288 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
290 define 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]]
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
301 ; Negative test - wrong predicate.
303 define 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]]
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
316 ; X <= -0.0 ? (0.0 - X) : X --> fabs(X)
318 define <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]]
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
329 define <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]]
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
340 ; X > 0.0 ? X : (0.0 - X) --> fabs(X)
342 define 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]]
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
353 ; This is not fabs because that could produce a different signbit for a NAN input.
354 ; PR59279
356 define 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]]
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
369 define 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]]
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
380 define 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]]
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
391 define 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]]
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
402 ; X > -0.0 ? X : (0.0 - X) --> fabs(X)
404 define 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]]
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
415 define 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]]
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
426 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
428 define 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]]
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
439 ; Negative test - wrong predicate.
441 define 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]]
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
454 ; This is not fabs because that could produce a different signbit for a NAN input.
455 ; PR59279
457 define 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]]
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
470 ; X < 0.0 ? -X : X --> fabs(X)
472 define 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]]
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
483 define 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]]
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
496 define 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]]
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
507 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
509 define 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]]
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
522 define 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]]
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
535 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
537 define 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]]
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
550 ; X < -0.0 ? -X : X --> fabs(X)
552 define 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]]
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
565 define 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]]
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
576 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
578 define 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]]
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
591 define 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]]
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
604 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
606 define 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]]
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
619 ; X <= 0.0 ? -X : X --> fabs(X)
621 define 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]]
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
634 define 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]]
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
645 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
647 define 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]]
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
660 define 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]]
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
673 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
675 define 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]]
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
688 ; X <= -0.0 ? -X : X --> fabs(X)
690 define 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]]
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
703 define 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]]
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
714 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
716 define 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]]
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
729 define 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]]
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
742 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
744 define 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]]
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
757 ; This is not fabs because that could produce a different signbit for a NAN input.
758 ; PR59279
760 define <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]]
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
773 ; X > 0.0 ? X : (-X) --> fabs(X)
775 define <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]]
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
786 define <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]]
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
799 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
801 define <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]]
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
814 define <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]]
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
827 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
829 define <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]]
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
842 ; X > -0.0 ? X : (0.0 - X) --> fabs(X)
844 define 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]]
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
857 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
859 define 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]]
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
872 ; X > 0.0 ? X : (0.0 - X) --> fabs(X)
874 define <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]]
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
887 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
889 define <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]]
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
902 define <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]]
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
915 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
917 define <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]]
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
930 ; X > -0.0 ? X : (0.0 - X) --> fabs(X)
932 define 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]]
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
945 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
947 define 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]]
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
960 define 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]]
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
973 ; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically.
975 define 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]]
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
988 define 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]]
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
999 define 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]]
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
1013 define 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]]
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
1028 define <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]]
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
1039 define 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]]
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
1051 define 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]]
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
1064 define 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]]
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
1077 define 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]]
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
1089 define 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]]
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
1105 define 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]]
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
1120 define 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]]
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
1139 define 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]]
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
1151 define 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]]
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
1164 ; Negative tests
1166 define 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]]
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
1185 define 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]]
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
1200 define 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]]
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
1215 define 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]]
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
1230 define <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]]
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