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)
226
227define float @fabs_select_positive_constants(i32 %c) {
228; CHECK-LABEL: @fabs_select_positive_constants(
229; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
230; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
231; CHECK-NEXT:    ret float [[SELECT]]
232;
233  %cmp = icmp eq i32 %c, 0
234  %select = select i1 %cmp, float 1.0, float 2.0
235  %fabs = call float @llvm.fabs.f32(float %select)
236  ret float %fabs
237}
238
239define <2 x float> @fabs_select_positive_constants_vector(i32 %c) {
240; CHECK-LABEL: @fabs_select_positive_constants_vector(
241; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
242; 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>
243; CHECK-NEXT:    ret <2 x float> [[SELECT]]
244;
245  %cmp = icmp eq i32 %c, 0
246  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
247  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
248  ret <2 x float> %fabs
249}
250
251define float @fabs_select_constant_variable(i32 %c, float %x) {
252; CHECK-LABEL: @fabs_select_constant_variable(
253; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
254; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]]
255; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
256; CHECK-NEXT:    ret float [[FABS]]
257;
258  %cmp = icmp eq i32 %c, 0
259  %select = select i1 %cmp, float 1.0, float %x
260  %fabs = call float @llvm.fabs.f32(float %select)
261  ret float %fabs
262}
263
264define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) {
265; CHECK-LABEL: @fabs_select_constant_variable_vector(
266; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
267; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]]
268; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
269; CHECK-NEXT:    ret <2 x float> [[FABS]]
270;
271  %cmp = icmp eq i32 %c, 0
272  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x
273  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
274  ret <2 x float> %fabs
275}
276
277define float @fabs_select_neg0_pos0(i32 %c) {
278; CHECK-LABEL: @fabs_select_neg0_pos0(
279; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
280; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00
281; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
282; CHECK-NEXT:    ret float [[FABS]]
283;
284  %cmp = icmp eq i32 %c, 0
285  %select = select i1 %cmp, float -0.0, float 0.0
286  %fabs = call float @llvm.fabs.f32(float %select)
287  ret float %fabs
288}
289
290define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) {
291; CHECK-LABEL: @fabs_select_neg0_pos0_vector(
292; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
293; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer
294; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
295; CHECK-NEXT:    ret <2 x float> [[FABS]]
296;
297  %cmp = icmp eq i32 %c, 0
298  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0>
299  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
300  ret <2 x float> %fabs
301}
302
303define float @fabs_select_neg0_neg1(i32 %c) {
304; CHECK-LABEL: @fabs_select_neg0_neg1(
305; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
306; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00
307; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
308; CHECK-NEXT:    ret float [[FABS]]
309;
310  %cmp = icmp eq i32 %c, 0
311  %select = select i1 %cmp, float -0.0, float -1.0
312  %fabs = call float @llvm.fabs.f32(float %select)
313  ret float %fabs
314}
315
316define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) {
317; CHECK-LABEL: @fabs_select_neg0_neg1_vector(
318; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
319; 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>
320; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
321; CHECK-NEXT:    ret <2 x float> [[FABS]]
322;
323  %cmp = icmp eq i32 %c, 0
324  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0>
325  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
326  ret <2 x float> %fabs
327}
328
329define float @fabs_select_nan_nan(i32 %c) {
330; CHECK-LABEL: @fabs_select_nan_nan(
331; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
332; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000
333; CHECK-NEXT:    ret float [[SELECT]]
334;
335  %cmp = icmp eq i32 %c, 0
336  %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000
337  %fabs = call float @llvm.fabs.f32(float %select)
338  ret float %fabs
339}
340
341define <2 x float> @fabs_select_nan_nan_vector(i32 %c) {
342; CHECK-LABEL: @fabs_select_nan_nan_vector(
343; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
344; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
345; CHECK-NEXT:    ret <2 x float> [[SELECT]]
346;
347  %cmp = icmp eq i32 %c, 0
348  %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
349  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
350  ret <2 x float> %fabs
351}
352
353define float @fabs_select_negnan_nan(i32 %c) {
354; CHECK-LABEL: @fabs_select_negnan_nan(
355; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
356; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000
357; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
358; CHECK-NEXT:    ret float [[FABS]]
359;
360  %cmp = icmp eq i32 %c, 0
361  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000
362  %fabs = call float @llvm.fabs.f32(float %select)
363  ret float %fabs
364}
365
366define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) {
367; CHECK-LABEL: @fabs_select_negnan_nan_vector(
368; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
369; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
370; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
371; CHECK-NEXT:    ret <2 x float> [[FABS]]
372;
373  %cmp = icmp eq i32 %c, 0
374  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
375  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
376  ret <2 x float> %fabs
377}
378
379define float @fabs_select_negnan_negnan(i32 %c) {
380; CHECK-LABEL: @fabs_select_negnan_negnan(
381; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
382; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000
383; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
384; CHECK-NEXT:    ret float [[FABS]]
385;
386  %cmp = icmp eq i32 %c, 0
387  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000
388  %fabs = call float @llvm.fabs.f32(float %select)
389  ret float %fabs
390}
391
392define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) {
393; CHECK-LABEL: @fabs_select_negnan_negnan_vector(
394; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
395; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
396; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
397; CHECK-NEXT:    ret <2 x float> [[FABS]]
398;
399  %cmp = icmp eq i32 %c, 0
400  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
401  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
402  ret <2 x float> %fabs
403}
404
405define float @fabs_select_negnan_negzero(i32 %c) {
406; CHECK-LABEL: @fabs_select_negnan_negzero(
407; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
408; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00
409; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
410; CHECK-NEXT:    ret float [[FABS]]
411;
412  %cmp = icmp eq i32 %c, 0
413  %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0
414  %fabs = call float @llvm.fabs.f32(float %select)
415  ret float %fabs
416}
417
418define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) {
419; CHECK-LABEL: @fabs_select_negnan_negzero_vector(
420; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
421; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00>
422; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
423; CHECK-NEXT:    ret <2 x float> [[FABS]]
424;
425  %cmp = icmp eq i32 %c, 0
426  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0>
427  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
428  ret <2 x float> %fabs
429}
430
431define float @fabs_select_negnan_zero(i32 %c) {
432; CHECK-LABEL: @fabs_select_negnan_zero(
433; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
434; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00
435; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
436; CHECK-NEXT:    ret float [[FABS]]
437;
438  %cmp = icmp eq i32 %c, 0
439  %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0
440  %fabs = call float @llvm.fabs.f32(float %select)
441  ret float %fabs
442}
443
444define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) {
445; CHECK-LABEL: @fabs_select_negnan_zero_vector(
446; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
447; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer
448; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
449; CHECK-NEXT:    ret <2 x float> [[FABS]]
450;
451  %cmp = icmp eq i32 %c, 0
452  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0>
453  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
454  ret <2 x float> %fabs
455}
456
457; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
458; an arbitrary sign bit.
459define float @fabs_sqrt(float %a) {
460; CHECK-LABEL: @fabs_sqrt(
461; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
462; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
463; CHECK-NEXT:    ret float [[FABS]]
464;
465  %sqrt = call float @llvm.sqrt.f32(float %a)
466  %fabs = call float @llvm.fabs.f32(float %sqrt)
467  ret float %fabs
468}
469
470; The fabs can't be eliminated because the nnan sqrt may still return -0.
471define float @fabs_sqrt_nnan(float %a) {
472; CHECK-LABEL: @fabs_sqrt_nnan(
473; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
474; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
475; CHECK-NEXT:    ret float [[FABS]]
476;
477  %sqrt = call nnan float @llvm.sqrt.f32(float %a)
478  %fabs = call float @llvm.fabs.f32(float %sqrt)
479  ret float %fabs
480}
481
482; The fabs can't be eliminated because the nsz sqrt may still return NaN.
483define float @fabs_sqrt_nsz(float %a) {
484; CHECK-LABEL: @fabs_sqrt_nsz(
485; CHECK-NEXT:    [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]])
486; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
487; CHECK-NEXT:    ret float [[FABS]]
488;
489  %sqrt = call nsz float @llvm.sqrt.f32(float %a)
490  %fabs = call float @llvm.fabs.f32(float %sqrt)
491  ret float %fabs
492}
493
494; The fabs can be eliminated because we're nsz and nnan.
495define float @fabs_sqrt_nnan_nsz(float %a) {
496; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
497; CHECK-NEXT:    [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]])
498; CHECK-NEXT:    ret float [[SQRT]]
499;
500  %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
501  %fabs = call float @llvm.fabs.f32(float %sqrt)
502  ret float %fabs
503}
504
505; The second fabs can be eliminated because the operand to sqrt cannot be -0.
506define float @fabs_sqrt_nnan_fabs(float %a) {
507; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
508; CHECK-NEXT:    [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
509; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]])
510; CHECK-NEXT:    ret float [[SQRT]]
511;
512  %b = call float @llvm.fabs.f32(float %a)
513  %sqrt = call nnan float @llvm.sqrt.f32(float %b)
514  %fabs = call float @llvm.fabs.f32(float %sqrt)
515  ret float %fabs
516}
517
518define float @fabs_select_positive_constants_vector_extract(i32 %c) {
519; CHECK-LABEL: @fabs_select_positive_constants_vector_extract(
520; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
521; 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>
522; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0
523; CHECK-NEXT:    ret float [[EXTRACT]]
524;
525  %cmp = icmp eq i32 %c, 0
526  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
527  %extract = extractelement <2 x float> %select, i32 0
528  %fabs = call float @llvm.fabs.f32(float %extract)
529  ret float %fabs
530}
531
532declare float @llvm.minnum.f32(float, float)
533declare float @llvm.maxnum.f32(float, float)
534declare double @llvm.minnum.f64(double, double)
535declare double @llvm.maxnum.f64(double, double)
536declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
537declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
538
539; From the LangRef for minnum/maxnum:
540; "If either operand is a NaN, returns the other non-NaN operand."
541
542define double @maxnum_nan_op0(double %x) {
543; CHECK-LABEL: @maxnum_nan_op0(
544; CHECK-NEXT:    ret double [[X:%.*]]
545;
546  %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x)
547  ret double %r
548}
549
550define double @maxnum_nan_op1(double %x) {
551; CHECK-LABEL: @maxnum_nan_op1(
552; CHECK-NEXT:    ret double [[X:%.*]]
553;
554  %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead)
555  ret double %r
556}
557
558define double @minnum_nan_op0(double %x) {
559; CHECK-LABEL: @minnum_nan_op0(
560; CHECK-NEXT:    ret double [[X:%.*]]
561;
562  %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x)
563  ret double %r
564}
565
566define double @minnum_nan_op1(double %x) {
567; CHECK-LABEL: @minnum_nan_op1(
568; CHECK-NEXT:    ret double [[X:%.*]]
569;
570  %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead)
571  ret double %r
572}
573
574define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) {
575; CHECK-LABEL: @maxnum_nan_op0_vec(
576; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
577;
578  %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x)
579  ret <2 x double> %r
580}
581
582define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) {
583; CHECK-LABEL: @maxnum_nan_op1_vec(
584; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
585;
586  %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
587  ret <2 x double> %r
588}
589
590define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) {
591; CHECK-LABEL: @minnum_nan_op0_vec(
592; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
593;
594  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x)
595  ret <2 x double> %r
596}
597
598define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) {
599; CHECK-LABEL: @minnum_nan_op1_vec(
600; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
601;
602  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
603  ret <2 x double> %r
604}
605
606define float @maxnum_undef_op1(float %x) {
607; CHECK-LABEL: @maxnum_undef_op1(
608; CHECK-NEXT:    ret float [[X:%.*]]
609;
610  %val = call float @llvm.maxnum.f32(float %x, float undef)
611  ret float %val
612}
613
614define float @maxnum_undef_op0(float %x) {
615; CHECK-LABEL: @maxnum_undef_op0(
616; CHECK-NEXT:    ret float [[X:%.*]]
617;
618  %val = call float @llvm.maxnum.f32(float undef, float %x)
619  ret float %val
620}
621
622define float @minnum_undef_op1(float %x) {
623; CHECK-LABEL: @minnum_undef_op1(
624; CHECK-NEXT:    ret float [[X:%.*]]
625;
626  %val = call float @llvm.minnum.f32(float %x, float undef)
627  ret float %val
628}
629
630define float @minnum_undef_op0(float %x) {
631; CHECK-LABEL: @minnum_undef_op0(
632; CHECK-NEXT:    ret float [[X:%.*]]
633;
634  %val = call float @llvm.minnum.f32(float undef, float %x)
635  ret float %val
636}
637
638define float @minnum_undef_undef(float %x) {
639; CHECK-LABEL: @minnum_undef_undef(
640; CHECK-NEXT:    ret float undef
641;
642  %val = call float @llvm.minnum.f32(float undef, float undef)
643  ret float %val
644}
645
646define float @maxnum_undef_undef(float %x) {
647; CHECK-LABEL: @maxnum_undef_undef(
648; CHECK-NEXT:    ret float undef
649;
650  %val = call float @llvm.maxnum.f32(float undef, float undef)
651  ret float %val
652}
653
654define float @minnum_same_args(float %x) {
655; CHECK-LABEL: @minnum_same_args(
656; CHECK-NEXT:    ret float [[X:%.*]]
657;
658  %y = call float @llvm.minnum.f32(float %x, float %x)
659  ret float %y
660}
661
662define float @maxnum_same_args(float %x) {
663; CHECK-LABEL: @maxnum_same_args(
664; CHECK-NEXT:    ret float [[X:%.*]]
665;
666  %y = call float @llvm.maxnum.f32(float %x, float %x)
667  ret float %y
668}
669
670define float @minnum_x_minnum_x_y(float %x, float %y) {
671; CHECK-LABEL: @minnum_x_minnum_x_y(
672; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
673; CHECK-NEXT:    ret float [[A]]
674;
675  %a = call float @llvm.minnum.f32(float %x, float %y)
676  %b = call float @llvm.minnum.f32(float %x, float %a)
677  ret float %b
678}
679
680define float @minnum_y_minnum_x_y(float %x, float %y) {
681; CHECK-LABEL: @minnum_y_minnum_x_y(
682; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
683; CHECK-NEXT:    ret float [[A]]
684;
685  %a = call float @llvm.minnum.f32(float %x, float %y)
686  %b = call float @llvm.minnum.f32(float %y, float %a)
687  ret float %b
688}
689
690define float @minnum_x_y_minnum_x(float %x, float %y) {
691; CHECK-LABEL: @minnum_x_y_minnum_x(
692; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
693; CHECK-NEXT:    ret float [[A]]
694;
695  %a = call float @llvm.minnum.f32(float %x, float %y)
696  %b = call float @llvm.minnum.f32(float %a, float %x)
697  ret float %b
698}
699
700define float @minnum_x_y_minnum_y(float %x, float %y) {
701; CHECK-LABEL: @minnum_x_y_minnum_y(
702; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
703; CHECK-NEXT:    ret float [[A]]
704;
705  %a = call float @llvm.minnum.f32(float %x, float %y)
706  %b = call float @llvm.minnum.f32(float %a, float %y)
707  ret float %b
708}
709
710; negative test
711
712define float @minnum_z_minnum_x_y(float %x, float %y, float %z) {
713; CHECK-LABEL: @minnum_z_minnum_x_y(
714; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
715; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[A]])
716; CHECK-NEXT:    ret float [[B]]
717;
718  %a = call float @llvm.minnum.f32(float %x, float %y)
719  %b = call float @llvm.minnum.f32(float %z, float %a)
720  ret float %b
721}
722
723; negative test
724
725define float @minnum_x_y_minnum_z(float %x, float %y, float %z) {
726; CHECK-LABEL: @minnum_x_y_minnum_z(
727; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
728; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minnum.f32(float [[A]], float [[Z:%.*]])
729; CHECK-NEXT:    ret float [[B]]
730;
731  %a = call float @llvm.minnum.f32(float %x, float %y)
732  %b = call float @llvm.minnum.f32(float %a, float %z)
733  ret float %b
734}
735
736; minnum(X, -INF) --> -INF
737
738define float @minnum_neginf(float %x) {
739; CHECK-LABEL: @minnum_neginf(
740; CHECK-NEXT:    ret float 0xFFF0000000000000
741;
742  %val = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
743  ret float %val
744}
745
746define <2 x double> @minnum_neginf_commute_vec(<2 x double> %x) {
747; CHECK-LABEL: @minnum_neginf_commute_vec(
748; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>
749;
750  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
751  ret <2 x double> %r
752}
753
754; negative test
755
756define float @minnum_inf(float %x) {
757; CHECK-LABEL: @minnum_inf(
758; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.minnum.f32(float 0x7FF0000000000000, float [[X:%.*]])
759; CHECK-NEXT:    ret float [[VAL]]
760;
761  %val = call float @llvm.minnum.f32(float 0x7FF0000000000000, float %x)
762  ret float %val
763}
764define float @maxnum_x_maxnum_x_y(float %x, float %y) {
765; CHECK-LABEL: @maxnum_x_maxnum_x_y(
766; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
767; CHECK-NEXT:    ret float [[A]]
768;
769  %a = call float @llvm.maxnum.f32(float %x, float %y)
770  %b = call float @llvm.maxnum.f32(float %x, float %a)
771  ret float %b
772}
773
774define float @maxnum_y_maxnum_x_y(float %x, float %y) {
775; CHECK-LABEL: @maxnum_y_maxnum_x_y(
776; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
777; CHECK-NEXT:    ret float [[A]]
778;
779  %a = call float @llvm.maxnum.f32(float %x, float %y)
780  %b = call float @llvm.maxnum.f32(float %y, float %a)
781  ret float %b
782}
783
784define float @maxnum_x_y_maxnum_x(float %x, float %y) {
785; CHECK-LABEL: @maxnum_x_y_maxnum_x(
786; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
787; CHECK-NEXT:    ret float [[A]]
788;
789  %a = call float @llvm.maxnum.f32(float %x, float %y)
790  %b = call float @llvm.maxnum.f32(float %a, float %x)
791  ret float %b
792}
793
794define float @maxnum_x_y_maxnum_y(float %x, float %y) {
795; CHECK-LABEL: @maxnum_x_y_maxnum_y(
796; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
797; CHECK-NEXT:    ret float [[A]]
798;
799  %a = call float @llvm.maxnum.f32(float %x, float %y)
800  %b = call float @llvm.maxnum.f32(float %a, float %y)
801  ret float %b
802}
803
804; negative test
805
806define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) {
807; CHECK-LABEL: @maxnum_z_maxnum_x_y(
808; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
809; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[A]])
810; CHECK-NEXT:    ret float [[B]]
811;
812  %a = call float @llvm.maxnum.f32(float %x, float %y)
813  %b = call float @llvm.maxnum.f32(float %z, float %a)
814  ret float %b
815}
816
817; negative test
818
819define float @maxnum_x_y_maxnum_z(float %x, float %y, float %z) {
820; CHECK-LABEL: @maxnum_x_y_maxnum_z(
821; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
822; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[Z:%.*]])
823; CHECK-NEXT:    ret float [[B]]
824;
825  %a = call float @llvm.maxnum.f32(float %x, float %y)
826  %b = call float @llvm.maxnum.f32(float %a, float %z)
827  ret float %b
828}
829
830; maxnum(X, INF) --> INF
831
832define <2 x double> @maxnum_inf(<2 x double> %x) {
833; CHECK-LABEL: @maxnum_inf(
834; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>
835;
836  %val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
837  ret <2 x double> %val
838}
839
840define float @maxnum_inf_commute(float %x) {
841; CHECK-LABEL: @maxnum_inf_commute(
842; CHECK-NEXT:    ret float 0x7FF0000000000000
843;
844  %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x)
845  ret float %val
846}
847
848; negative test
849
850define float @maxnum_neginf(float %x) {
851; CHECK-LABEL: @maxnum_neginf(
852; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float [[X:%.*]])
853; CHECK-NEXT:    ret float [[VAL]]
854;
855  %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x)
856  ret float %val
857}
858
859declare float @llvm.minimum.f32(float, float)
860declare float @llvm.maximum.f32(float, float)
861declare double @llvm.minimum.f64(double, double)
862declare double @llvm.maximum.f64(double, double)
863declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
864declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
865
866; From the LangRef for minimum/maximum:
867; "If either operand is a NaN, returns NaN."
868
869define double @maximum_nan_op0(double %x) {
870; CHECK-LABEL: @maximum_nan_op0(
871; CHECK-NEXT:    ret double 0x7FF8000000000000
872;
873  %r = call double @llvm.maximum.f64(double 0x7ff8000000000000, double %x)
874  ret double %r
875}
876
877define double @maximum_nan_op1(double %x) {
878; CHECK-LABEL: @maximum_nan_op1(
879; CHECK-NEXT:    ret double 0x7FF800000000DEAD
880;
881  %r = call double @llvm.maximum.f64(double %x, double 0x7ff800000000dead)
882  ret double %r
883}
884
885define double @minimum_nan_op0(double %x) {
886; CHECK-LABEL: @minimum_nan_op0(
887; CHECK-NEXT:    ret double 0x7FF8000DEAD00000
888;
889  %r = call double @llvm.minimum.f64(double 0x7ff8000dead00000, double %x)
890  ret double %r
891}
892
893define double @minimum_nan_op1(double %x) {
894; CHECK-LABEL: @minimum_nan_op1(
895; CHECK-NEXT:    ret double 0x7FF800DEAD00DEAD
896;
897  %r = call double @llvm.minimum.f64(double %x, double 0x7ff800dead00dead)
898  ret double %r
899}
900
901define <2 x double> @maximum_nan_op0_vec(<2 x double> %x) {
902; CHECK-LABEL: @maximum_nan_op0_vec(
903; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
904;
905  %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x)
906  ret <2 x double> %r
907}
908
909define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) {
910; CHECK-LABEL: @maximum_nan_op1_vec(
911; CHECK-NEXT:    ret <2 x double> <double 0x7FF800000000DEAD, double 0x7FF8FFFFFFFFFFFF>
912;
913  %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
914  ret <2 x double> %r
915}
916
917define <2 x double> @minimum_nan_op0_vec(<2 x double> %x) {
918; CHECK-LABEL: @minimum_nan_op0_vec(
919; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000DEAD00000>
920;
921  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x)
922  ret <2 x double> %r
923}
924
925define <2 x double> @minimum_nan_op1_vec(<2 x double> %x) {
926; CHECK-LABEL: @minimum_nan_op1_vec(
927; CHECK-NEXT:    ret <2 x double> <double 0x7FF800DEAD00DEAD, double 0x7FF800DEAD00DEAD>
928;
929  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
930  ret <2 x double> %r
931}
932
933define float @maximum_undef_op1(float %x) {
934; CHECK-LABEL: @maximum_undef_op1(
935; CHECK-NEXT:    ret float [[X:%.*]]
936;
937  %val = call float @llvm.maximum.f32(float %x, float undef)
938  ret float %val
939}
940
941define float @maximum_undef_op0(float %x) {
942; CHECK-LABEL: @maximum_undef_op0(
943; CHECK-NEXT:    ret float [[X:%.*]]
944;
945  %val = call float @llvm.maximum.f32(float undef, float %x)
946  ret float %val
947}
948
949define float @minimum_undef_op1(float %x) {
950; CHECK-LABEL: @minimum_undef_op1(
951; CHECK-NEXT:    ret float [[X:%.*]]
952;
953  %val = call float @llvm.minimum.f32(float %x, float undef)
954  ret float %val
955}
956
957define float @minimum_undef_op0(float %x) {
958; CHECK-LABEL: @minimum_undef_op0(
959; CHECK-NEXT:    ret float [[X:%.*]]
960;
961  %val = call float @llvm.minimum.f32(float undef, float %x)
962  ret float %val
963}
964
965define float @minimum_undef_undef(float %x) {
966; CHECK-LABEL: @minimum_undef_undef(
967; CHECK-NEXT:    ret float undef
968;
969  %val = call float @llvm.minimum.f32(float undef, float undef)
970  ret float %val
971}
972
973define float @maximum_undef_undef(float %x) {
974; CHECK-LABEL: @maximum_undef_undef(
975; CHECK-NEXT:    ret float undef
976;
977  %val = call float @llvm.maximum.f32(float undef, float undef)
978  ret float %val
979}
980
981define float @minimum_same_args(float %x) {
982; CHECK-LABEL: @minimum_same_args(
983; CHECK-NEXT:    ret float [[X:%.*]]
984;
985  %y = call float @llvm.minimum.f32(float %x, float %x)
986  ret float %y
987}
988
989define float @maximum_same_args(float %x) {
990; CHECK-LABEL: @maximum_same_args(
991; CHECK-NEXT:    ret float [[X:%.*]]
992;
993  %y = call float @llvm.maximum.f32(float %x, float %x)
994  ret float %y
995}
996
997define float @minimum_x_minimum_x_y(float %x, float %y) {
998; CHECK-LABEL: @minimum_x_minimum_x_y(
999; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
1000; CHECK-NEXT:    ret float [[A]]
1001;
1002  %a = call float @llvm.minimum.f32(float %x, float %y)
1003  %b = call float @llvm.minimum.f32(float %x, float %a)
1004  ret float %b
1005}
1006
1007define float @minimum_y_minimum_x_y(float %x, float %y) {
1008; CHECK-LABEL: @minimum_y_minimum_x_y(
1009; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
1010; CHECK-NEXT:    ret float [[A]]
1011;
1012  %a = call float @llvm.minimum.f32(float %x, float %y)
1013  %b = call float @llvm.minimum.f32(float %y, float %a)
1014  ret float %b
1015}
1016
1017define float @minimum_x_y_minimum_x(float %x, float %y) {
1018; CHECK-LABEL: @minimum_x_y_minimum_x(
1019; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
1020; CHECK-NEXT:    ret float [[A]]
1021;
1022  %a = call float @llvm.minimum.f32(float %x, float %y)
1023  %b = call float @llvm.minimum.f32(float %a, float %x)
1024  ret float %b
1025}
1026
1027define float @minimum_x_y_minimum_y(float %x, float %y) {
1028; CHECK-LABEL: @minimum_x_y_minimum_y(
1029; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
1030; CHECK-NEXT:    ret float [[A]]
1031;
1032  %a = call float @llvm.minimum.f32(float %x, float %y)
1033  %b = call float @llvm.minimum.f32(float %a, float %y)
1034  ret float %b
1035}
1036
1037; negative test
1038
1039define float @minimum_z_minimum_x_y(float %x, float %y, float %z) {
1040; CHECK-LABEL: @minimum_z_minimum_x_y(
1041; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
1042; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[A]])
1043; CHECK-NEXT:    ret float [[B]]
1044;
1045  %a = call float @llvm.minimum.f32(float %x, float %y)
1046  %b = call float @llvm.minimum.f32(float %z, float %a)
1047  ret float %b
1048}
1049
1050; negative test
1051
1052define float @minimum_x_y_minimum_z(float %x, float %y, float %z) {
1053; CHECK-LABEL: @minimum_x_y_minimum_z(
1054; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
1055; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minimum.f32(float [[A]], float [[Z:%.*]])
1056; CHECK-NEXT:    ret float [[B]]
1057;
1058  %a = call float @llvm.minimum.f32(float %x, float %y)
1059  %b = call float @llvm.minimum.f32(float %a, float %z)
1060  ret float %b
1061}
1062
1063; minimum(X, -INF) --> -INF
1064
1065define float @minimum_neginf(float %x) {
1066; CHECK-LABEL: @minimum_neginf(
1067; CHECK-NEXT:    ret float 0xFFF0000000000000
1068;
1069  %val = call float @llvm.minimum.f32(float %x, float 0xFFF0000000000000)
1070  ret float %val
1071}
1072
1073define <2 x double> @minimum_neginf_commute_vec(<2 x double> %x) {
1074; CHECK-LABEL: @minimum_neginf_commute_vec(
1075; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>
1076;
1077  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
1078  ret <2 x double> %r
1079}
1080
1081; negative test
1082
1083define float @minimum_inf(float %x) {
1084; CHECK-LABEL: @minimum_inf(
1085; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.minimum.f32(float 0x7FF0000000000000, float [[X:%.*]])
1086; CHECK-NEXT:    ret float [[VAL]]
1087;
1088  %val = call float @llvm.minimum.f32(float 0x7FF0000000000000, float %x)
1089  ret float %val
1090}
1091define float @maximum_x_maximum_x_y(float %x, float %y) {
1092; CHECK-LABEL: @maximum_x_maximum_x_y(
1093; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1094; CHECK-NEXT:    ret float [[A]]
1095;
1096  %a = call float @llvm.maximum.f32(float %x, float %y)
1097  %b = call float @llvm.maximum.f32(float %x, float %a)
1098  ret float %b
1099}
1100
1101define float @maximum_y_maximum_x_y(float %x, float %y) {
1102; CHECK-LABEL: @maximum_y_maximum_x_y(
1103; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1104; CHECK-NEXT:    ret float [[A]]
1105;
1106  %a = call float @llvm.maximum.f32(float %x, float %y)
1107  %b = call float @llvm.maximum.f32(float %y, float %a)
1108  ret float %b
1109}
1110
1111define float @maximum_x_y_maximum_x(float %x, float %y) {
1112; CHECK-LABEL: @maximum_x_y_maximum_x(
1113; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1114; CHECK-NEXT:    ret float [[A]]
1115;
1116  %a = call float @llvm.maximum.f32(float %x, float %y)
1117  %b = call float @llvm.maximum.f32(float %a, float %x)
1118  ret float %b
1119}
1120
1121define float @maximum_x_y_maximum_y(float %x, float %y) {
1122; CHECK-LABEL: @maximum_x_y_maximum_y(
1123; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1124; CHECK-NEXT:    ret float [[A]]
1125;
1126  %a = call float @llvm.maximum.f32(float %x, float %y)
1127  %b = call float @llvm.maximum.f32(float %a, float %y)
1128  ret float %b
1129}
1130
1131; negative test
1132
1133define float @maximum_z_maximum_x_y(float %x, float %y, float %z) {
1134; CHECK-LABEL: @maximum_z_maximum_x_y(
1135; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1136; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[A]])
1137; CHECK-NEXT:    ret float [[B]]
1138;
1139  %a = call float @llvm.maximum.f32(float %x, float %y)
1140  %b = call float @llvm.maximum.f32(float %z, float %a)
1141  ret float %b
1142}
1143
1144; negative test
1145
1146define float @maximum_x_y_maximum_z(float %x, float %y, float %z) {
1147; CHECK-LABEL: @maximum_x_y_maximum_z(
1148; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1149; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[Z:%.*]])
1150; CHECK-NEXT:    ret float [[B]]
1151;
1152  %a = call float @llvm.maximum.f32(float %x, float %y)
1153  %b = call float @llvm.maximum.f32(float %a, float %z)
1154  ret float %b
1155}
1156
1157; maximum(X, INF) --> INF
1158
1159define <2 x double> @maximum_inf(<2 x double> %x) {
1160; CHECK-LABEL: @maximum_inf(
1161; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>
1162;
1163  %val = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
1164  ret <2 x double> %val
1165}
1166
1167define float @maximum_inf_commute(float %x) {
1168; CHECK-LABEL: @maximum_inf_commute(
1169; CHECK-NEXT:    ret float 0x7FF0000000000000
1170;
1171  %val = call float @llvm.maximum.f32(float 0x7FF0000000000000, float %x)
1172  ret float %val
1173}
1174
1175; Y - (Y - X) --> X
1176
1177define float @fsub_fsub_common_op(float %x, float %y) {
1178; CHECK-LABEL: @fsub_fsub_common_op(
1179; CHECK-NEXT:    ret float [[X:%.*]]
1180;
1181  %s = fsub float %y, %x
1182  %r = fsub reassoc nsz float %y, %s
1183  ret float %r
1184}
1185
1186define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) {
1187; CHECK-LABEL: @fsub_fsub_common_op_vec(
1188; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
1189;
1190  %s = fsub <2 x float> %y, %x
1191  %r = fsub reassoc nsz <2 x float> %y, %s
1192  ret <2 x float> %r
1193}
1194
1195; Negative test - fsub is not commutative.
1196; Y - (X - Y) --> (Y - X) + Y (canonicalized)
1197
1198define float @fsub_fsub_wrong_common_op(float %x, float %y) {
1199; CHECK-LABEL: @fsub_fsub_wrong_common_op(
1200; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
1201; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]]
1202; CHECK-NEXT:    ret float [[R]]
1203;
1204  %s = fsub float %x, %y
1205  %r = fsub reassoc nsz float %y, %s
1206  ret float %r
1207}
1208
1209; Negative test - negated operand needed.
1210; (Y - X) - Y --> -X
1211
1212define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) {
1213; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
1214; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
1215; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
1216; CHECK-NEXT:    ret float [[R]]
1217;
1218  %s = fsub float %y, %x
1219  %r = fsub reassoc nsz float %s, %y
1220  ret float %r
1221}
1222
1223; Negative test - fsub is not commutative.
1224; (X - Y) - Y --> ?
1225
1226define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) {
1227; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
1228; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
1229; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
1230; CHECK-NEXT:    ret float [[R]]
1231;
1232  %s = fsub float %x, %y
1233  %r = fsub reassoc nsz float %s, %y
1234  ret float %r
1235}
1236
1237; (Y + X) - Y --> X
1238
1239define float @fadd_fsub_common_op(float %x, float %y) {
1240; CHECK-LABEL: @fadd_fsub_common_op(
1241; CHECK-NEXT:    ret float [[X:%.*]]
1242;
1243  %a = fadd float %y, %x
1244  %r = fsub reassoc nsz float %a, %y
1245  ret float %r
1246}
1247
1248; (X + Y) - Y --> X
1249
1250define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) {
1251; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
1252; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
1253;
1254  %a = fadd <2 x float> %x, %y
1255  %r = fsub reassoc nsz <2 x float> %a, %y
1256  ret <2 x float> %r
1257}
1258
1259; Negative test - negated operand needed.
1260; Y - (Y + X) --> -X
1261
1262define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) {
1263; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
1264; CHECK-NEXT:    [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]]
1265; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
1266; CHECK-NEXT:    ret float [[R]]
1267;
1268  %a = fadd float %y, %x
1269  %r = fsub reassoc nsz float %y, %a
1270  ret float %r
1271}
1272
1273; Negative test - negated operand needed.
1274; Y - (X + Y) --> -X
1275
1276define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) {
1277; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
1278; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
1279; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
1280; CHECK-NEXT:    ret float [[R]]
1281;
1282  %a = fadd float %x, %y
1283  %r = fsub reassoc nsz float %y, %a
1284  ret float %r
1285}
1286
1287; Y + (X - Y) --> X
1288
1289define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) {
1290; CHECK-LABEL: @fsub_fadd_common_op_vec(
1291; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
1292;
1293  %s = fsub <2 x float> %x, %y
1294  %r = fadd reassoc nsz <2 x float> %y, %s
1295  ret <2 x float> %r
1296}
1297
1298; (X - Y) + Y --> X
1299
1300define float @fsub_fadd_common_op_commute(float %x, float %y) {
1301; CHECK-LABEL: @fsub_fadd_common_op_commute(
1302; CHECK-NEXT:    ret float [[X:%.*]]
1303;
1304  %s = fsub float %x, %y
1305  %r = fadd reassoc nsz float %s, %y
1306  ret float %r
1307}
1308
1309; Negative test.
1310; Y + (Y - X) --> ?
1311
1312define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) {
1313; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
1314; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
1315; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]]
1316; CHECK-NEXT:    ret float [[R]]
1317;
1318  %s = fsub float %y, %x
1319  %r = fadd reassoc nsz float %y, %s
1320  ret float %r
1321}
1322
1323; Negative test.
1324; (Y - X) + Y --> ?
1325
1326define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) {
1327; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
1328; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
1329; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]]
1330; CHECK-NEXT:    ret float [[R]]
1331;
1332  %s = fsub float %y, %x
1333  %r = fadd reassoc nsz float %s, %y
1334  ret float %r
1335}
1336
1337; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627
1338
1339define float @maxnum_with_poszero_op(float %a) {
1340; CHECK-LABEL: @maxnum_with_poszero_op(
1341; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00)
1342; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
1343; CHECK-NEXT:    ret float [[FABS]]
1344;
1345  %max = call float @llvm.maxnum.f32(float %a, float 0.0)
1346  %fabs = call float @llvm.fabs.f32(float %max)
1347  ret float %fabs
1348}
1349
1350define float @maxnum_with_poszero_op_commute(float %a) {
1351; CHECK-LABEL: @maxnum_with_poszero_op_commute(
1352; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
1353; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]])
1354; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
1355; CHECK-NEXT:    ret float [[FABS]]
1356;
1357  %sqrt = call float @llvm.sqrt.f32(float %a)
1358  %max = call float @llvm.maxnum.f32(float 0.0, float %sqrt)
1359  %fabs = call float @llvm.fabs.f32(float %max)
1360  ret float %fabs
1361}
1362
1363define float @maxnum_with_negzero_op(float %a) {
1364; CHECK-LABEL: @maxnum_with_negzero_op(
1365; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
1366; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
1367; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]])
1368; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
1369; CHECK-NEXT:    ret float [[FABS]]
1370;
1371  %nnan = call nnan float @llvm.sqrt.f32(float %a)
1372  %fabsa = call float @llvm.fabs.f32(float %nnan)
1373  %max = call float @llvm.maxnum.f32(float -0.0, float %fabsa)
1374  %fabs = call float @llvm.fabs.f32(float %max)
1375  ret float %fabs
1376}
1377
1378define float @maxnum_with_negzero_op_commute(float %a) {
1379; CHECK-LABEL: @maxnum_with_negzero_op_commute(
1380; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
1381; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
1382; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00)
1383; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
1384; CHECK-NEXT:    ret float [[FABS]]
1385;
1386  %nnan = call nnan float @llvm.sqrt.f32(float %a)
1387  %fabsa = call float @llvm.fabs.f32(float %nnan)
1388  %max = call float @llvm.maxnum.f32(float %fabsa, float -0.0)
1389  %fabs = call float @llvm.fabs.f32(float %max)
1390  ret float %fabs
1391}
1392
1393; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum.
1394
1395define float @maxnum_with_pos_one_op(float %a) {
1396; CHECK-LABEL: @maxnum_with_pos_one_op(
1397; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00)
1398; CHECK-NEXT:    ret float [[MAX]]
1399;
1400  %max = call float @llvm.maxnum.f32(float %a, float 1.0)
1401  %fabs = call float @llvm.fabs.f32(float %max)
1402  ret float %fabs
1403}
1404