1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instsimplify -S | FileCheck %s
3
4; fneg (fneg X) ==> X
5define float @fneg_fneg_var(float %a) {
6; CHECK-LABEL: @fneg_fneg_var(
7; CHECK-NEXT:    ret float [[A:%.*]]
8;
9  %r  = fneg float %a
10  %r1 = fneg float %r
11  ret float %r1
12}
13
14; fneg (fsub -0.0, X) ==> X
15define float @fsub_-0_x(float %a) {
16; CHECK-LABEL: @fsub_-0_x(
17; CHECK-NEXT:    ret float [[A:%.*]]
18;
19  %t1 = fsub float -0.0, %a
20  %ret = fneg float %t1
21  ret float %ret
22}
23
24define <2 x float> @fsub_-0_x_vec(<2 x float> %a) {
25; CHECK-LABEL: @fsub_-0_x_vec(
26; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
27;
28  %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
29  %ret = fneg <2 x float> %t1
30  ret <2 x float> %ret
31}
32
33define <2 x float> @fsub_-0_x_vec_undef_elts(<2 x float> %a) {
34; CHECK-LABEL: @fsub_-0_x_vec_undef_elts(
35; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
36;
37  %t1 = fsub <2 x float> <float -0.0, float undef>, %a
38  %ret = fneg <2 x float> %t1
39  ret <2 x float> %ret
40}
41
42define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) {
43; CHECK-LABEL: @fsub_negzero_vec_undef_elts(
44; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
45;
46  %r = fsub nsz <2 x float> %x, <float undef, float -0.0>
47  ret <2 x float> %r
48}
49
50; fsub -0.0, (fsub -0.0, X) ==> X
51define float @fsub_-0_-0_x(float %a) {
52; CHECK-LABEL: @fsub_-0_-0_x(
53; CHECK-NEXT:    ret float [[A:%.*]]
54;
55  %t1 = fsub float -0.0, %a
56  %ret = fsub float -0.0, %t1
57  ret float %ret
58}
59
60; fsub -0.0, (fneg X) ==> X
61define float @fneg_x(float %a) {
62; CHECK-LABEL: @fneg_x(
63; CHECK-NEXT:    ret float [[A:%.*]]
64;
65  %t1 = fneg float %a
66  %ret = fsub float -0.0, %t1
67  ret float %ret
68}
69
70define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) {
71; CHECK-LABEL: @fsub_-0_-0_x_vec(
72; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
73;
74  %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
75  %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
76  ret <2 x float> %ret
77}
78
79define <2 x float> @fneg_x_vec(<2 x float> %a) {
80; CHECK-LABEL: @fneg_x_vec(
81; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
82;
83  %t1 = fneg <2 x float> %a
84  %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
85  ret <2 x float> %ret
86}
87
88define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) {
89; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts(
90; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
91;
92  %t1 = fsub <2 x float> <float undef, float -0.0>, %a
93  %ret = fsub <2 x float> <float -0.0, float undef>, %t1
94  ret <2 x float> %ret
95}
96
97define <2 x float> @fneg_x_vec_undef_elts(<2 x float> %a) {
98; CHECK-LABEL: @fneg_x_vec_undef_elts(
99; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
100;
101  %t1 = fneg <2 x float> %a
102  %ret = fsub <2 x float> <float -0.0, float undef>, %t1
103  ret <2 x float> %ret
104}
105
106; fsub -0.0, (fsub 0.0, X) != X
107define float @fsub_-0_0_x(float %a) {
108; CHECK-LABEL: @fsub_-0_0_x(
109; CHECK-NEXT:    [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]]
110; CHECK-NEXT:    [[RET:%.*]] = fsub float -0.000000e+00, [[T1]]
111; CHECK-NEXT:    ret float [[RET]]
112;
113  %t1 = fsub float 0.0, %a
114  %ret = fsub float -0.0, %t1
115  ret float %ret
116}
117
118; fsub 0.0, (fsub -0.0, X) != X
119define float @fsub_0_-0_x(float %a) {
120; CHECK-LABEL: @fsub_0_-0_x(
121; CHECK-NEXT:    [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]]
122; CHECK-NEXT:    [[RET:%.*]] = fsub float 0.000000e+00, [[T1]]
123; CHECK-NEXT:    ret float [[RET]]
124;
125  %t1 = fsub float -0.0, %a
126  %ret = fsub float 0.0, %t1
127  ret float %ret
128}
129
130; fsub X, 0 ==> X
131define float @fsub_x_0(float %x) {
132; CHECK-LABEL: @fsub_x_0(
133; CHECK-NEXT:    ret float [[X:%.*]]
134;
135  %r = fsub float %x, 0.0
136  ret float %r
137}
138
139define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) {
140; CHECK-LABEL: @fsub_x_0_vec_undef(
141; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
142;
143  %r = fsub <2 x float> %x, <float undef, float 0.0>
144  ret <2 x float> %r
145}
146
147; fadd X, -0 ==> X
148define float @fadd_x_n0(float %a) {
149; CHECK-LABEL: @fadd_x_n0(
150; CHECK-NEXT:    ret float [[A:%.*]]
151;
152  %ret = fadd float %a, -0.0
153  ret float %ret
154}
155
156define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) {
157; CHECK-LABEL: @fadd_x_n0_vec_undef_elt(
158; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
159;
160  %ret = fadd <2 x float> %a, <float -0.0, float undef>
161  ret <2 x float> %ret
162}
163
164; fmul X, 1.0 ==> X
165define double @fmul_X_1(double %a) {
166; CHECK-LABEL: @fmul_X_1(
167; CHECK-NEXT:    ret double [[A:%.*]]
168;
169  %b = fmul double 1.0, %a
170  ret double %b
171}
172
173; PR2642
174define <4 x float> @fmul_X_1_vec(<4 x float> %x) {
175; CHECK-LABEL: @fmul_X_1_vec(
176; CHECK-NEXT:    ret <4 x float> [[X:%.*]]
177;
178  %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
179  ret <4 x float> %m
180}
181
182; fdiv X, 1.0 ==> X
183define float @fdiv_x_1(float %a) {
184; CHECK-LABEL: @fdiv_x_1(
185; CHECK-NEXT:    ret float [[A:%.*]]
186;
187  %ret = fdiv float %a, 1.0
188  ret float %ret
189}
190
191; We can't optimize away the fadd in this test because the input
192; value to the function and subsequently to the fadd may be -0.0.
193; In that one special case, the result of the fadd should be +0.0
194; rather than the first parameter of the fadd.
195
196; Fragile test warning: We need 6 sqrt calls to trigger the bug
197; because the internal logic has a magic recursion limit of 6.
198; This is presented without any explanation or ability to customize.
199
200declare float @sqrtf(float)
201
202define float @PR22688(float %x) {
203; CHECK-LABEL: @PR22688(
204; CHECK-NEXT:    [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]])
205; CHECK-NEXT:    [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]])
206; CHECK-NEXT:    [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]])
207; CHECK-NEXT:    [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]])
208; CHECK-NEXT:    [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]])
209; CHECK-NEXT:    [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]])
210; CHECK-NEXT:    [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00
211; CHECK-NEXT:    ret float [[TMP7]]
212;
213  %1 = call float @sqrtf(float %x)
214  %2 = call float @sqrtf(float %1)
215  %3 = call float @sqrtf(float %2)
216  %4 = call float @sqrtf(float %3)
217  %5 = call float @sqrtf(float %4)
218  %6 = call float @sqrtf(float %5)
219  %7 = fadd float %6, 0.0
220  ret float %7
221}
222
223declare float @llvm.fabs.f32(float)
224declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
225declare float @llvm.sqrt.f32(float)
226declare float @llvm.maxnum.f32(float, float)
227
228define float @fabs_select_positive_constants(i32 %c) {
229; CHECK-LABEL: @fabs_select_positive_constants(
230; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
231; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
232; CHECK-NEXT:    ret float [[SELECT]]
233;
234  %cmp = icmp eq i32 %c, 0
235  %select = select i1 %cmp, float 1.0, float 2.0
236  %fabs = call float @llvm.fabs.f32(float %select)
237  ret float %fabs
238}
239
240define <2 x float> @fabs_select_positive_constants_vector(i32 %c) {
241; CHECK-LABEL: @fabs_select_positive_constants_vector(
242; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
243; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
244; CHECK-NEXT:    ret <2 x float> [[SELECT]]
245;
246  %cmp = icmp eq i32 %c, 0
247  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
248  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
249  ret <2 x float> %fabs
250}
251
252define float @fabs_select_constant_variable(i32 %c, float %x) {
253; CHECK-LABEL: @fabs_select_constant_variable(
254; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
255; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]]
256; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
257; CHECK-NEXT:    ret float [[FABS]]
258;
259  %cmp = icmp eq i32 %c, 0
260  %select = select i1 %cmp, float 1.0, float %x
261  %fabs = call float @llvm.fabs.f32(float %select)
262  ret float %fabs
263}
264
265define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) {
266; CHECK-LABEL: @fabs_select_constant_variable_vector(
267; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
268; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]]
269; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
270; CHECK-NEXT:    ret <2 x float> [[FABS]]
271;
272  %cmp = icmp eq i32 %c, 0
273  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x
274  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
275  ret <2 x float> %fabs
276}
277
278define float @fabs_select_neg0_pos0(i32 %c) {
279; CHECK-LABEL: @fabs_select_neg0_pos0(
280; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
281; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00
282; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
283; CHECK-NEXT:    ret float [[FABS]]
284;
285  %cmp = icmp eq i32 %c, 0
286  %select = select i1 %cmp, float -0.0, float 0.0
287  %fabs = call float @llvm.fabs.f32(float %select)
288  ret float %fabs
289}
290
291define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) {
292; CHECK-LABEL: @fabs_select_neg0_pos0_vector(
293; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
294; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer
295; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
296; CHECK-NEXT:    ret <2 x float> [[FABS]]
297;
298  %cmp = icmp eq i32 %c, 0
299  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0>
300  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
301  ret <2 x float> %fabs
302}
303
304define float @fabs_select_neg0_neg1(i32 %c) {
305; CHECK-LABEL: @fabs_select_neg0_neg1(
306; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
307; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00
308; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
309; CHECK-NEXT:    ret float [[FABS]]
310;
311  %cmp = icmp eq i32 %c, 0
312  %select = select i1 %cmp, float -0.0, float -1.0
313  %fabs = call float @llvm.fabs.f32(float %select)
314  ret float %fabs
315}
316
317define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) {
318; CHECK-LABEL: @fabs_select_neg0_neg1_vector(
319; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
320; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> <float -1.000000e+00, float -1.000000e+00>
321; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
322; CHECK-NEXT:    ret <2 x float> [[FABS]]
323;
324  %cmp = icmp eq i32 %c, 0
325  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0>
326  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
327  ret <2 x float> %fabs
328}
329
330define float @fabs_select_nan_nan(i32 %c) {
331; CHECK-LABEL: @fabs_select_nan_nan(
332; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
333; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000
334; CHECK-NEXT:    ret float [[SELECT]]
335;
336  %cmp = icmp eq i32 %c, 0
337  %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000
338  %fabs = call float @llvm.fabs.f32(float %select)
339  ret float %fabs
340}
341
342define <2 x float> @fabs_select_nan_nan_vector(i32 %c) {
343; CHECK-LABEL: @fabs_select_nan_nan_vector(
344; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
345; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
346; CHECK-NEXT:    ret <2 x float> [[SELECT]]
347;
348  %cmp = icmp eq i32 %c, 0
349  %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
350  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
351  ret <2 x float> %fabs
352}
353
354define float @fabs_select_negnan_nan(i32 %c) {
355; CHECK-LABEL: @fabs_select_negnan_nan(
356; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
357; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000
358; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
359; CHECK-NEXT:    ret float [[FABS]]
360;
361  %cmp = icmp eq i32 %c, 0
362  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000
363  %fabs = call float @llvm.fabs.f32(float %select)
364  ret float %fabs
365}
366
367define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) {
368; CHECK-LABEL: @fabs_select_negnan_nan_vector(
369; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
370; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
371; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
372; CHECK-NEXT:    ret <2 x float> [[FABS]]
373;
374  %cmp = icmp eq i32 %c, 0
375  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
376  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
377  ret <2 x float> %fabs
378}
379
380define float @fabs_select_negnan_negnan(i32 %c) {
381; CHECK-LABEL: @fabs_select_negnan_negnan(
382; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
383; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000
384; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
385; CHECK-NEXT:    ret float [[FABS]]
386;
387  %cmp = icmp eq i32 %c, 0
388  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000
389  %fabs = call float @llvm.fabs.f32(float %select)
390  ret float %fabs
391}
392
393define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) {
394; CHECK-LABEL: @fabs_select_negnan_negnan_vector(
395; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
396; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
397; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
398; CHECK-NEXT:    ret <2 x float> [[FABS]]
399;
400  %cmp = icmp eq i32 %c, 0
401  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
402  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
403  ret <2 x float> %fabs
404}
405
406define float @fabs_select_negnan_negzero(i32 %c) {
407; CHECK-LABEL: @fabs_select_negnan_negzero(
408; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
409; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00
410; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
411; CHECK-NEXT:    ret float [[FABS]]
412;
413  %cmp = icmp eq i32 %c, 0
414  %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0
415  %fabs = call float @llvm.fabs.f32(float %select)
416  ret float %fabs
417}
418
419define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) {
420; CHECK-LABEL: @fabs_select_negnan_negzero_vector(
421; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
422; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00>
423; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
424; CHECK-NEXT:    ret <2 x float> [[FABS]]
425;
426  %cmp = icmp eq i32 %c, 0
427  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0>
428  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
429  ret <2 x float> %fabs
430}
431
432define float @fabs_select_negnan_zero(i32 %c) {
433; CHECK-LABEL: @fabs_select_negnan_zero(
434; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
435; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00
436; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
437; CHECK-NEXT:    ret float [[FABS]]
438;
439  %cmp = icmp eq i32 %c, 0
440  %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0
441  %fabs = call float @llvm.fabs.f32(float %select)
442  ret float %fabs
443}
444
445define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) {
446; CHECK-LABEL: @fabs_select_negnan_zero_vector(
447; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
448; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer
449; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
450; CHECK-NEXT:    ret <2 x float> [[FABS]]
451;
452  %cmp = icmp eq i32 %c, 0
453  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0>
454  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
455  ret <2 x float> %fabs
456}
457
458; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
459; an arbitrary sign bit.
460define float @fabs_sqrt(float %a) {
461; CHECK-LABEL: @fabs_sqrt(
462; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
463; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
464; CHECK-NEXT:    ret float [[FABS]]
465;
466  %sqrt = call float @llvm.sqrt.f32(float %a)
467  %fabs = call float @llvm.fabs.f32(float %sqrt)
468  ret float %fabs
469}
470
471; The fabs can't be eliminated because the nnan sqrt may still return -0.
472define float @fabs_sqrt_nnan(float %a) {
473; CHECK-LABEL: @fabs_sqrt_nnan(
474; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
475; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
476; CHECK-NEXT:    ret float [[FABS]]
477;
478  %sqrt = call nnan float @llvm.sqrt.f32(float %a)
479  %fabs = call float @llvm.fabs.f32(float %sqrt)
480  ret float %fabs
481}
482
483; The fabs can't be eliminated because the nsz sqrt may still return NaN.
484define float @fabs_sqrt_nsz(float %a) {
485; CHECK-LABEL: @fabs_sqrt_nsz(
486; CHECK-NEXT:    [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]])
487; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
488; CHECK-NEXT:    ret float [[FABS]]
489;
490  %sqrt = call nsz float @llvm.sqrt.f32(float %a)
491  %fabs = call float @llvm.fabs.f32(float %sqrt)
492  ret float %fabs
493}
494
495; The fabs can be eliminated because we're nsz and nnan.
496define float @fabs_sqrt_nnan_nsz(float %a) {
497; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
498; CHECK-NEXT:    [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]])
499; CHECK-NEXT:    ret float [[SQRT]]
500;
501  %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
502  %fabs = call float @llvm.fabs.f32(float %sqrt)
503  ret float %fabs
504}
505
506; The second fabs can be eliminated because the operand to sqrt cannot be -0.
507define float @fabs_sqrt_nnan_fabs(float %a) {
508; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
509; CHECK-NEXT:    [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
510; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]])
511; CHECK-NEXT:    ret float [[SQRT]]
512;
513  %b = call float @llvm.fabs.f32(float %a)
514  %sqrt = call nnan float @llvm.sqrt.f32(float %b)
515  %fabs = call float @llvm.fabs.f32(float %sqrt)
516  ret float %fabs
517}
518
519define float @fabs_select_positive_constants_vector_extract(i32 %c) {
520; CHECK-LABEL: @fabs_select_positive_constants_vector_extract(
521; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
522; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
523; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0
524; CHECK-NEXT:    ret float [[EXTRACT]]
525;
526  %cmp = icmp eq i32 %c, 0
527  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
528  %extract = extractelement <2 x float> %select, i32 0
529  %fabs = call float @llvm.fabs.f32(float %extract)
530  ret float %fabs
531}
532
533; Y - (Y - X) --> X
534
535define float @fsub_fsub_common_op(float %x, float %y) {
536; CHECK-LABEL: @fsub_fsub_common_op(
537; CHECK-NEXT:    ret float [[X:%.*]]
538;
539  %s = fsub float %y, %x
540  %r = fsub reassoc nsz float %y, %s
541  ret float %r
542}
543
544define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) {
545; CHECK-LABEL: @fsub_fsub_common_op_vec(
546; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
547;
548  %s = fsub <2 x float> %y, %x
549  %r = fsub reassoc nsz <2 x float> %y, %s
550  ret <2 x float> %r
551}
552
553; Negative test - fsub is not commutative.
554; Y - (X - Y) --> (Y - X) + Y (canonicalized)
555
556define float @fsub_fsub_wrong_common_op(float %x, float %y) {
557; CHECK-LABEL: @fsub_fsub_wrong_common_op(
558; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
559; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]]
560; CHECK-NEXT:    ret float [[R]]
561;
562  %s = fsub float %x, %y
563  %r = fsub reassoc nsz float %y, %s
564  ret float %r
565}
566
567; Negative test - negated operand needed.
568; (Y - X) - Y --> -X
569
570define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) {
571; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
572; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
573; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
574; CHECK-NEXT:    ret float [[R]]
575;
576  %s = fsub float %y, %x
577  %r = fsub reassoc nsz float %s, %y
578  ret float %r
579}
580
581; Negative test - fsub is not commutative.
582; (X - Y) - Y --> ?
583
584define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) {
585; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
586; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
587; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
588; CHECK-NEXT:    ret float [[R]]
589;
590  %s = fsub float %x, %y
591  %r = fsub reassoc nsz float %s, %y
592  ret float %r
593}
594
595; (Y + X) - Y --> X
596
597define float @fadd_fsub_common_op(float %x, float %y) {
598; CHECK-LABEL: @fadd_fsub_common_op(
599; CHECK-NEXT:    ret float [[X:%.*]]
600;
601  %a = fadd float %y, %x
602  %r = fsub reassoc nsz float %a, %y
603  ret float %r
604}
605
606; (X + Y) - Y --> X
607
608define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) {
609; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
610; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
611;
612  %a = fadd <2 x float> %x, %y
613  %r = fsub reassoc nsz <2 x float> %a, %y
614  ret <2 x float> %r
615}
616
617; Negative test - negated operand needed.
618; Y - (Y + X) --> -X
619
620define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) {
621; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
622; CHECK-NEXT:    [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]]
623; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
624; CHECK-NEXT:    ret float [[R]]
625;
626  %a = fadd float %y, %x
627  %r = fsub reassoc nsz float %y, %a
628  ret float %r
629}
630
631; Negative test - negated operand needed.
632; Y - (X + Y) --> -X
633
634define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) {
635; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
636; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
637; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
638; CHECK-NEXT:    ret float [[R]]
639;
640  %a = fadd float %x, %y
641  %r = fsub reassoc nsz float %y, %a
642  ret float %r
643}
644
645; Y + (X - Y) --> X
646
647define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) {
648; CHECK-LABEL: @fsub_fadd_common_op_vec(
649; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
650;
651  %s = fsub <2 x float> %x, %y
652  %r = fadd reassoc nsz <2 x float> %y, %s
653  ret <2 x float> %r
654}
655
656; (X - Y) + Y --> X
657
658define float @fsub_fadd_common_op_commute(float %x, float %y) {
659; CHECK-LABEL: @fsub_fadd_common_op_commute(
660; CHECK-NEXT:    ret float [[X:%.*]]
661;
662  %s = fsub float %x, %y
663  %r = fadd reassoc nsz float %s, %y
664  ret float %r
665}
666
667; Negative test.
668; Y + (Y - X) --> ?
669
670define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) {
671; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
672; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
673; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]]
674; CHECK-NEXT:    ret float [[R]]
675;
676  %s = fsub float %y, %x
677  %r = fadd reassoc nsz float %y, %s
678  ret float %r
679}
680
681; Negative test.
682; (Y - X) + Y --> ?
683
684define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) {
685; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
686; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
687; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]]
688; CHECK-NEXT:    ret float [[R]]
689;
690  %s = fsub float %y, %x
691  %r = fadd reassoc nsz float %s, %y
692  ret float %r
693}
694
695; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627
696
697define float @maxnum_with_poszero_op(float %a) {
698; CHECK-LABEL: @maxnum_with_poszero_op(
699; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00)
700; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
701; CHECK-NEXT:    ret float [[FABS]]
702;
703  %max = call float @llvm.maxnum.f32(float %a, float 0.0)
704  %fabs = call float @llvm.fabs.f32(float %max)
705  ret float %fabs
706}
707
708define float @maxnum_with_poszero_op_commute(float %a) {
709; CHECK-LABEL: @maxnum_with_poszero_op_commute(
710; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
711; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]])
712; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
713; CHECK-NEXT:    ret float [[FABS]]
714;
715  %sqrt = call float @llvm.sqrt.f32(float %a)
716  %max = call float @llvm.maxnum.f32(float 0.0, float %sqrt)
717  %fabs = call float @llvm.fabs.f32(float %max)
718  ret float %fabs
719}
720
721define float @maxnum_with_negzero_op(float %a) {
722; CHECK-LABEL: @maxnum_with_negzero_op(
723; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
724; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
725; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]])
726; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
727; CHECK-NEXT:    ret float [[FABS]]
728;
729  %nnan = call nnan float @llvm.sqrt.f32(float %a)
730  %fabsa = call float @llvm.fabs.f32(float %nnan)
731  %max = call float @llvm.maxnum.f32(float -0.0, float %fabsa)
732  %fabs = call float @llvm.fabs.f32(float %max)
733  ret float %fabs
734}
735
736define float @maxnum_with_negzero_op_commute(float %a) {
737; CHECK-LABEL: @maxnum_with_negzero_op_commute(
738; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
739; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
740; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00)
741; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
742; CHECK-NEXT:    ret float [[FABS]]
743;
744  %nnan = call nnan float @llvm.sqrt.f32(float %a)
745  %fabsa = call float @llvm.fabs.f32(float %nnan)
746  %max = call float @llvm.maxnum.f32(float %fabsa, float -0.0)
747  %fabs = call float @llvm.fabs.f32(float %max)
748  ret float %fabs
749}
750
751; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum.
752
753define float @maxnum_with_pos_one_op(float %a) {
754; CHECK-LABEL: @maxnum_with_pos_one_op(
755; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00)
756; CHECK-NEXT:    ret float [[MAX]]
757;
758  %max = call float @llvm.maxnum.f32(float %a, float 1.0)
759  %fabs = call float @llvm.fabs.f32(float %max)
760  ret float %fabs
761}
762