1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instsimplify -S | FileCheck %s
3
4define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) {
5; CHECK-LABEL: @fsub_negzero_vec_undef_elts(
6; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
7;
8  %r = fsub nsz <2 x float> %x, <float undef, float -0.0>
9  ret <2 x float> %r
10}
11
12; fsub -0.0, (fsub -0.0, X) ==> X
13define float @fsub_-0_-0_x(float %a) {
14; CHECK-LABEL: @fsub_-0_-0_x(
15; CHECK-NEXT:    ret float [[A:%.*]]
16;
17  %t1 = fsub float -0.0, %a
18  %ret = fsub float -0.0, %t1
19  ret float %ret
20}
21
22define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) {
23; CHECK-LABEL: @fsub_-0_-0_x_vec(
24; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
25;
26  %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
27  %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
28  ret <2 x float> %ret
29}
30
31define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) {
32; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts(
33; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
34;
35  %t1 = fsub <2 x float> <float undef, float -0.0>, %a
36  %ret = fsub <2 x float> <float -0.0, float undef>, %t1
37  ret <2 x float> %ret
38}
39
40; fsub 0.0, (fsub -0.0, X) != X
41define float @fsub_0_-0_x(float %a) {
42; CHECK-LABEL: @fsub_0_-0_x(
43; CHECK-NEXT:    [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]]
44; CHECK-NEXT:    [[RET:%.*]] = fsub float -0.000000e+00, [[T1]]
45; CHECK-NEXT:    ret float [[RET]]
46;
47  %t1 = fsub float 0.0, %a
48  %ret = fsub float -0.0, %t1
49  ret float %ret
50}
51
52; fsub -0.0, (fsub 0.0, X) != X
53define float @fsub_-0_0_x(float %a) {
54; CHECK-LABEL: @fsub_-0_0_x(
55; CHECK-NEXT:    [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]]
56; CHECK-NEXT:    [[RET:%.*]] = fsub float 0.000000e+00, [[T1]]
57; CHECK-NEXT:    ret float [[RET]]
58;
59  %t1 = fsub float -0.0, %a
60  %ret = fsub float 0.0, %t1
61  ret float %ret
62}
63
64; fsub X, 0 ==> X
65define float @fsub_x_0(float %x) {
66; CHECK-LABEL: @fsub_x_0(
67; CHECK-NEXT:    ret float [[X:%.*]]
68;
69  %r = fsub float %x, 0.0
70  ret float %r
71}
72
73define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) {
74; CHECK-LABEL: @fsub_x_0_vec_undef(
75; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
76;
77  %r = fsub <2 x float> %x, <float undef, float 0.0>
78  ret <2 x float> %r
79}
80
81; fadd X, -0 ==> X
82define float @fadd_x_n0(float %a) {
83; CHECK-LABEL: @fadd_x_n0(
84; CHECK-NEXT:    ret float [[A:%.*]]
85;
86  %ret = fadd float %a, -0.0
87  ret float %ret
88}
89
90define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) {
91; CHECK-LABEL: @fadd_x_n0_vec_undef_elt(
92; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
93;
94  %ret = fadd <2 x float> %a, <float -0.0, float undef>
95  ret <2 x float> %ret
96}
97
98; fmul X, 1.0 ==> X
99define double @fmul_X_1(double %a) {
100; CHECK-LABEL: @fmul_X_1(
101; CHECK-NEXT:    ret double [[A:%.*]]
102;
103  %b = fmul double 1.0, %a
104  ret double %b
105}
106
107; PR2642
108define <4 x float> @fmul_X_1_vec(<4 x float> %x) {
109; CHECK-LABEL: @fmul_X_1_vec(
110; CHECK-NEXT:    ret <4 x float> [[X:%.*]]
111;
112  %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
113  ret <4 x float> %m
114}
115
116; fdiv X, 1.0 ==> X
117define float @fdiv_x_1(float %a) {
118; CHECK-LABEL: @fdiv_x_1(
119; CHECK-NEXT:    ret float [[A:%.*]]
120;
121  %ret = fdiv float %a, 1.0
122  ret float %ret
123}
124
125; We can't optimize away the fadd in this test because the input
126; value to the function and subsequently to the fadd may be -0.0.
127; In that one special case, the result of the fadd should be +0.0
128; rather than the first parameter of the fadd.
129
130; Fragile test warning: We need 6 sqrt calls to trigger the bug
131; because the internal logic has a magic recursion limit of 6.
132; This is presented without any explanation or ability to customize.
133
134declare float @sqrtf(float)
135
136define float @PR22688(float %x) {
137; CHECK-LABEL: @PR22688(
138; CHECK-NEXT:    [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]])
139; CHECK-NEXT:    [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]])
140; CHECK-NEXT:    [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]])
141; CHECK-NEXT:    [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]])
142; CHECK-NEXT:    [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]])
143; CHECK-NEXT:    [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]])
144; CHECK-NEXT:    [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00
145; CHECK-NEXT:    ret float [[TMP7]]
146;
147  %1 = call float @sqrtf(float %x)
148  %2 = call float @sqrtf(float %1)
149  %3 = call float @sqrtf(float %2)
150  %4 = call float @sqrtf(float %3)
151  %5 = call float @sqrtf(float %4)
152  %6 = call float @sqrtf(float %5)
153  %7 = fadd float %6, 0.0
154  ret float %7
155}
156
157declare float @llvm.fabs.f32(float)
158declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
159declare float @llvm.sqrt.f32(float)
160
161define float @fabs_select_positive_constants(i32 %c) {
162; CHECK-LABEL: @fabs_select_positive_constants(
163; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
164; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
165; CHECK-NEXT:    ret float [[SELECT]]
166;
167  %cmp = icmp eq i32 %c, 0
168  %select = select i1 %cmp, float 1.0, float 2.0
169  %fabs = call float @llvm.fabs.f32(float %select)
170  ret float %fabs
171}
172
173define <2 x float> @fabs_select_positive_constants_vector(i32 %c) {
174; CHECK-LABEL: @fabs_select_positive_constants_vector(
175; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
176; 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>
177; CHECK-NEXT:    ret <2 x float> [[SELECT]]
178;
179  %cmp = icmp eq i32 %c, 0
180  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
181  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
182  ret <2 x float> %fabs
183}
184
185define float @fabs_select_constant_variable(i32 %c, float %x) {
186; CHECK-LABEL: @fabs_select_constant_variable(
187; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
188; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]]
189; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
190; CHECK-NEXT:    ret float [[FABS]]
191;
192  %cmp = icmp eq i32 %c, 0
193  %select = select i1 %cmp, float 1.0, float %x
194  %fabs = call float @llvm.fabs.f32(float %select)
195  ret float %fabs
196}
197
198define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) {
199; CHECK-LABEL: @fabs_select_constant_variable_vector(
200; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
201; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]]
202; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
203; CHECK-NEXT:    ret <2 x float> [[FABS]]
204;
205  %cmp = icmp eq i32 %c, 0
206  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x
207  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
208  ret <2 x float> %fabs
209}
210
211define float @fabs_select_neg0_pos0(i32 %c) {
212; CHECK-LABEL: @fabs_select_neg0_pos0(
213; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
214; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00
215; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
216; CHECK-NEXT:    ret float [[FABS]]
217;
218  %cmp = icmp eq i32 %c, 0
219  %select = select i1 %cmp, float -0.0, float 0.0
220  %fabs = call float @llvm.fabs.f32(float %select)
221  ret float %fabs
222}
223
224define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) {
225; CHECK-LABEL: @fabs_select_neg0_pos0_vector(
226; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
227; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer
228; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
229; CHECK-NEXT:    ret <2 x float> [[FABS]]
230;
231  %cmp = icmp eq i32 %c, 0
232  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0>
233  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
234  ret <2 x float> %fabs
235}
236
237define float @fabs_select_neg0_neg1(i32 %c) {
238; CHECK-LABEL: @fabs_select_neg0_neg1(
239; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
240; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00
241; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
242; CHECK-NEXT:    ret float [[FABS]]
243;
244  %cmp = icmp eq i32 %c, 0
245  %select = select i1 %cmp, float -0.0, float -1.0
246  %fabs = call float @llvm.fabs.f32(float %select)
247  ret float %fabs
248}
249
250define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) {
251; CHECK-LABEL: @fabs_select_neg0_neg1_vector(
252; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
253; 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>
254; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
255; CHECK-NEXT:    ret <2 x float> [[FABS]]
256;
257  %cmp = icmp eq i32 %c, 0
258  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0>
259  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
260  ret <2 x float> %fabs
261}
262
263define float @fabs_select_nan_nan(i32 %c) {
264; CHECK-LABEL: @fabs_select_nan_nan(
265; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
266; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000
267; CHECK-NEXT:    ret float [[SELECT]]
268;
269  %cmp = icmp eq i32 %c, 0
270  %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000
271  %fabs = call float @llvm.fabs.f32(float %select)
272  ret float %fabs
273}
274
275define <2 x float> @fabs_select_nan_nan_vector(i32 %c) {
276; CHECK-LABEL: @fabs_select_nan_nan_vector(
277; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
278; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
279; CHECK-NEXT:    ret <2 x float> [[SELECT]]
280;
281  %cmp = icmp eq i32 %c, 0
282  %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
283  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
284  ret <2 x float> %fabs
285}
286
287define float @fabs_select_negnan_nan(i32 %c) {
288; CHECK-LABEL: @fabs_select_negnan_nan(
289; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
290; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000
291; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
292; CHECK-NEXT:    ret float [[FABS]]
293;
294  %cmp = icmp eq i32 %c, 0
295  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000
296  %fabs = call float @llvm.fabs.f32(float %select)
297  ret float %fabs
298}
299
300define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) {
301; CHECK-LABEL: @fabs_select_negnan_nan_vector(
302; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
303; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
304; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
305; CHECK-NEXT:    ret <2 x float> [[FABS]]
306;
307  %cmp = icmp eq i32 %c, 0
308  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
309  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
310  ret <2 x float> %fabs
311}
312
313define float @fabs_select_negnan_negnan(i32 %c) {
314; CHECK-LABEL: @fabs_select_negnan_negnan(
315; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
316; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000
317; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
318; CHECK-NEXT:    ret float [[FABS]]
319;
320  %cmp = icmp eq i32 %c, 0
321  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000
322  %fabs = call float @llvm.fabs.f32(float %select)
323  ret float %fabs
324}
325
326define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) {
327; CHECK-LABEL: @fabs_select_negnan_negnan_vector(
328; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
329; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
330; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
331; CHECK-NEXT:    ret <2 x float> [[FABS]]
332;
333  %cmp = icmp eq i32 %c, 0
334  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
335  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
336  ret <2 x float> %fabs
337}
338
339define float @fabs_select_negnan_negzero(i32 %c) {
340; CHECK-LABEL: @fabs_select_negnan_negzero(
341; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
342; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00
343; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
344; CHECK-NEXT:    ret float [[FABS]]
345;
346  %cmp = icmp eq i32 %c, 0
347  %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0
348  %fabs = call float @llvm.fabs.f32(float %select)
349  ret float %fabs
350}
351
352define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) {
353; CHECK-LABEL: @fabs_select_negnan_negzero_vector(
354; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
355; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00>
356; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
357; CHECK-NEXT:    ret <2 x float> [[FABS]]
358;
359  %cmp = icmp eq i32 %c, 0
360  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0>
361  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
362  ret <2 x float> %fabs
363}
364
365define float @fabs_select_negnan_zero(i32 %c) {
366; CHECK-LABEL: @fabs_select_negnan_zero(
367; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
368; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00
369; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
370; CHECK-NEXT:    ret float [[FABS]]
371;
372  %cmp = icmp eq i32 %c, 0
373  %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0
374  %fabs = call float @llvm.fabs.f32(float %select)
375  ret float %fabs
376}
377
378define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) {
379; CHECK-LABEL: @fabs_select_negnan_zero_vector(
380; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
381; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer
382; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
383; CHECK-NEXT:    ret <2 x float> [[FABS]]
384;
385  %cmp = icmp eq i32 %c, 0
386  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0>
387  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
388  ret <2 x float> %fabs
389}
390
391; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
392; an arbitrary sign bit.
393define float @fabs_sqrt(float %a) {
394; CHECK-LABEL: @fabs_sqrt(
395; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
396; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
397; CHECK-NEXT:    ret float [[FABS]]
398;
399  %sqrt = call float @llvm.sqrt.f32(float %a)
400  %fabs = call float @llvm.fabs.f32(float %sqrt)
401  ret float %fabs
402}
403
404; The fabs can't be eliminated because the nnan sqrt may still return -0.
405define float @fabs_sqrt_nnan(float %a) {
406; CHECK-LABEL: @fabs_sqrt_nnan(
407; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
408; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
409; CHECK-NEXT:    ret float [[FABS]]
410;
411  %sqrt = call nnan float @llvm.sqrt.f32(float %a)
412  %fabs = call float @llvm.fabs.f32(float %sqrt)
413  ret float %fabs
414}
415
416; The fabs can't be eliminated because the nsz sqrt may still return NaN.
417define float @fabs_sqrt_nsz(float %a) {
418; CHECK-LABEL: @fabs_sqrt_nsz(
419; CHECK-NEXT:    [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]])
420; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
421; CHECK-NEXT:    ret float [[FABS]]
422;
423  %sqrt = call nsz float @llvm.sqrt.f32(float %a)
424  %fabs = call float @llvm.fabs.f32(float %sqrt)
425  ret float %fabs
426}
427
428; The fabs can be eliminated because we're nsz and nnan.
429define float @fabs_sqrt_nnan_nsz(float %a) {
430; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
431; CHECK-NEXT:    [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]])
432; CHECK-NEXT:    ret float [[SQRT]]
433;
434  %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
435  %fabs = call float @llvm.fabs.f32(float %sqrt)
436  ret float %fabs
437}
438
439; The second fabs can be eliminated because the operand to sqrt cannot be -0.
440define float @fabs_sqrt_nnan_fabs(float %a) {
441; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
442; CHECK-NEXT:    [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
443; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]])
444; CHECK-NEXT:    ret float [[SQRT]]
445;
446  %b = call float @llvm.fabs.f32(float %a)
447  %sqrt = call nnan float @llvm.sqrt.f32(float %b)
448  %fabs = call float @llvm.fabs.f32(float %sqrt)
449  ret float %fabs
450}
451
452define float @fabs_select_positive_constants_vector_extract(i32 %c) {
453; CHECK-LABEL: @fabs_select_positive_constants_vector_extract(
454; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
455; 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>
456; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0
457; CHECK-NEXT:    ret float [[EXTRACT]]
458;
459  %cmp = icmp eq i32 %c, 0
460  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
461  %extract = extractelement <2 x float> %select, i32 0
462  %fabs = call float @llvm.fabs.f32(float %extract)
463  ret float %fabs
464}
465
466declare float @llvm.minnum.f32(float, float)
467declare float @llvm.maxnum.f32(float, float)
468declare double @llvm.minnum.f64(double, double)
469declare double @llvm.maxnum.f64(double, double)
470declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
471declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
472
473; From the LangRef for minnum/maxnum:
474; "If either operand is a NaN, returns the other non-NaN operand."
475
476define double @maxnum_nan_op0(double %x) {
477; CHECK-LABEL: @maxnum_nan_op0(
478; CHECK-NEXT:    ret double [[X:%.*]]
479;
480  %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x)
481  ret double %r
482}
483
484define double @maxnum_nan_op1(double %x) {
485; CHECK-LABEL: @maxnum_nan_op1(
486; CHECK-NEXT:    ret double [[X:%.*]]
487;
488  %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead)
489  ret double %r
490}
491
492define double @minnum_nan_op0(double %x) {
493; CHECK-LABEL: @minnum_nan_op0(
494; CHECK-NEXT:    ret double [[X:%.*]]
495;
496  %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x)
497  ret double %r
498}
499
500define double @minnum_nan_op1(double %x) {
501; CHECK-LABEL: @minnum_nan_op1(
502; CHECK-NEXT:    ret double [[X:%.*]]
503;
504  %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead)
505  ret double %r
506}
507
508define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) {
509; CHECK-LABEL: @maxnum_nan_op0_vec(
510; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
511;
512  %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x)
513  ret <2 x double> %r
514}
515
516define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) {
517; CHECK-LABEL: @maxnum_nan_op1_vec(
518; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
519;
520  %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
521  ret <2 x double> %r
522}
523
524define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) {
525; CHECK-LABEL: @minnum_nan_op0_vec(
526; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
527;
528  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x)
529  ret <2 x double> %r
530}
531
532define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) {
533; CHECK-LABEL: @minnum_nan_op1_vec(
534; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
535;
536  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
537  ret <2 x double> %r
538}
539
540define float @maxnum_undef_op1(float %x) {
541; CHECK-LABEL: @maxnum_undef_op1(
542; CHECK-NEXT:    ret float [[X:%.*]]
543;
544  %val = call float @llvm.maxnum.f32(float %x, float undef)
545  ret float %val
546}
547
548define float @maxnum_undef_op0(float %x) {
549; CHECK-LABEL: @maxnum_undef_op0(
550; CHECK-NEXT:    ret float [[X:%.*]]
551;
552  %val = call float @llvm.maxnum.f32(float undef, float %x)
553  ret float %val
554}
555
556define float @minnum_undef_op1(float %x) {
557; CHECK-LABEL: @minnum_undef_op1(
558; CHECK-NEXT:    ret float [[X:%.*]]
559;
560  %val = call float @llvm.minnum.f32(float %x, float undef)
561  ret float %val
562}
563
564define float @minnum_undef_op0(float %x) {
565; CHECK-LABEL: @minnum_undef_op0(
566; CHECK-NEXT:    ret float [[X:%.*]]
567;
568  %val = call float @llvm.minnum.f32(float undef, float %x)
569  ret float %val
570}
571
572define float @minnum_undef_undef(float %x) {
573; CHECK-LABEL: @minnum_undef_undef(
574; CHECK-NEXT:    ret float undef
575;
576  %val = call float @llvm.minnum.f32(float undef, float undef)
577  ret float %val
578}
579
580define float @maxnum_undef_undef(float %x) {
581; CHECK-LABEL: @maxnum_undef_undef(
582; CHECK-NEXT:    ret float undef
583;
584  %val = call float @llvm.maxnum.f32(float undef, float undef)
585  ret float %val
586}
587
588define float @minnum_same_args(float %x) {
589; CHECK-LABEL: @minnum_same_args(
590; CHECK-NEXT:    ret float [[X:%.*]]
591;
592  %y = call float @llvm.minnum.f32(float %x, float %x)
593  ret float %y
594}
595
596define float @maxnum_same_args(float %x) {
597; CHECK-LABEL: @maxnum_same_args(
598; CHECK-NEXT:    ret float [[X:%.*]]
599;
600  %y = call float @llvm.maxnum.f32(float %x, float %x)
601  ret float %y
602}
603
604define float @minnum_x_minnum_x_y(float %x, float %y) {
605; CHECK-LABEL: @minnum_x_minnum_x_y(
606; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
607; CHECK-NEXT:    ret float [[A]]
608;
609  %a = call float @llvm.minnum.f32(float %x, float %y)
610  %b = call float @llvm.minnum.f32(float %x, float %a)
611  ret float %b
612}
613
614define float @minnum_y_minnum_x_y(float %x, float %y) {
615; CHECK-LABEL: @minnum_y_minnum_x_y(
616; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
617; CHECK-NEXT:    ret float [[A]]
618;
619  %a = call float @llvm.minnum.f32(float %x, float %y)
620  %b = call float @llvm.minnum.f32(float %y, float %a)
621  ret float %b
622}
623
624define float @minnum_x_y_minnum_x(float %x, float %y) {
625; CHECK-LABEL: @minnum_x_y_minnum_x(
626; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
627; CHECK-NEXT:    ret float [[A]]
628;
629  %a = call float @llvm.minnum.f32(float %x, float %y)
630  %b = call float @llvm.minnum.f32(float %a, float %x)
631  ret float %b
632}
633
634define float @minnum_x_y_minnum_y(float %x, float %y) {
635; CHECK-LABEL: @minnum_x_y_minnum_y(
636; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
637; CHECK-NEXT:    ret float [[A]]
638;
639  %a = call float @llvm.minnum.f32(float %x, float %y)
640  %b = call float @llvm.minnum.f32(float %a, float %y)
641  ret float %b
642}
643
644; negative test
645
646define float @minnum_z_minnum_x_y(float %x, float %y, float %z) {
647; CHECK-LABEL: @minnum_z_minnum_x_y(
648; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
649; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[A]])
650; CHECK-NEXT:    ret float [[B]]
651;
652  %a = call float @llvm.minnum.f32(float %x, float %y)
653  %b = call float @llvm.minnum.f32(float %z, float %a)
654  ret float %b
655}
656
657; negative test
658
659define float @minnum_x_y_minnum_z(float %x, float %y, float %z) {
660; CHECK-LABEL: @minnum_x_y_minnum_z(
661; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
662; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minnum.f32(float [[A]], float [[Z:%.*]])
663; CHECK-NEXT:    ret float [[B]]
664;
665  %a = call float @llvm.minnum.f32(float %x, float %y)
666  %b = call float @llvm.minnum.f32(float %a, float %z)
667  ret float %b
668}
669
670; minnum(X, -INF) --> -INF
671
672define float @minnum_neginf(float %x) {
673; CHECK-LABEL: @minnum_neginf(
674; CHECK-NEXT:    ret float 0xFFF0000000000000
675;
676  %val = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
677  ret float %val
678}
679
680define <2 x double> @minnum_neginf_commute_vec(<2 x double> %x) {
681; CHECK-LABEL: @minnum_neginf_commute_vec(
682; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>
683;
684  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
685  ret <2 x double> %r
686}
687
688; negative test
689
690define float @minnum_inf(float %x) {
691; CHECK-LABEL: @minnum_inf(
692; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.minnum.f32(float 0x7FF0000000000000, float [[X:%.*]])
693; CHECK-NEXT:    ret float [[VAL]]
694;
695  %val = call float @llvm.minnum.f32(float 0x7FF0000000000000, float %x)
696  ret float %val
697}
698define float @maxnum_x_maxnum_x_y(float %x, float %y) {
699; CHECK-LABEL: @maxnum_x_maxnum_x_y(
700; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
701; CHECK-NEXT:    ret float [[A]]
702;
703  %a = call float @llvm.maxnum.f32(float %x, float %y)
704  %b = call float @llvm.maxnum.f32(float %x, float %a)
705  ret float %b
706}
707
708define float @maxnum_y_maxnum_x_y(float %x, float %y) {
709; CHECK-LABEL: @maxnum_y_maxnum_x_y(
710; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
711; CHECK-NEXT:    ret float [[A]]
712;
713  %a = call float @llvm.maxnum.f32(float %x, float %y)
714  %b = call float @llvm.maxnum.f32(float %y, float %a)
715  ret float %b
716}
717
718define float @maxnum_x_y_maxnum_x(float %x, float %y) {
719; CHECK-LABEL: @maxnum_x_y_maxnum_x(
720; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
721; CHECK-NEXT:    ret float [[A]]
722;
723  %a = call float @llvm.maxnum.f32(float %x, float %y)
724  %b = call float @llvm.maxnum.f32(float %a, float %x)
725  ret float %b
726}
727
728define float @maxnum_x_y_maxnum_y(float %x, float %y) {
729; CHECK-LABEL: @maxnum_x_y_maxnum_y(
730; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
731; CHECK-NEXT:    ret float [[A]]
732;
733  %a = call float @llvm.maxnum.f32(float %x, float %y)
734  %b = call float @llvm.maxnum.f32(float %a, float %y)
735  ret float %b
736}
737
738; negative test
739
740define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) {
741; CHECK-LABEL: @maxnum_z_maxnum_x_y(
742; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
743; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[A]])
744; CHECK-NEXT:    ret float [[B]]
745;
746  %a = call float @llvm.maxnum.f32(float %x, float %y)
747  %b = call float @llvm.maxnum.f32(float %z, float %a)
748  ret float %b
749}
750
751; negative test
752
753define float @maxnum_x_y_maxnum_z(float %x, float %y, float %z) {
754; CHECK-LABEL: @maxnum_x_y_maxnum_z(
755; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
756; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[Z:%.*]])
757; CHECK-NEXT:    ret float [[B]]
758;
759  %a = call float @llvm.maxnum.f32(float %x, float %y)
760  %b = call float @llvm.maxnum.f32(float %a, float %z)
761  ret float %b
762}
763
764; maxnum(X, INF) --> INF
765
766define <2 x double> @maxnum_inf(<2 x double> %x) {
767; CHECK-LABEL: @maxnum_inf(
768; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>
769;
770  %val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
771  ret <2 x double> %val
772}
773
774define float @maxnum_inf_commute(float %x) {
775; CHECK-LABEL: @maxnum_inf_commute(
776; CHECK-NEXT:    ret float 0x7FF0000000000000
777;
778  %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x)
779  ret float %val
780}
781
782; negative test
783
784define float @maxnum_neginf(float %x) {
785; CHECK-LABEL: @maxnum_neginf(
786; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float [[X:%.*]])
787; CHECK-NEXT:    ret float [[VAL]]
788;
789  %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x)
790  ret float %val
791}
792
793declare float @llvm.minimum.f32(float, float)
794declare float @llvm.maximum.f32(float, float)
795declare double @llvm.minimum.f64(double, double)
796declare double @llvm.maximum.f64(double, double)
797declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
798declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
799
800; From the LangRef for minimum/maximum:
801; "If either operand is a NaN, returns NaN."
802
803define double @maximum_nan_op0(double %x) {
804; CHECK-LABEL: @maximum_nan_op0(
805; CHECK-NEXT:    ret double 0x7FF8000000000000
806;
807  %r = call double @llvm.maximum.f64(double 0x7ff8000000000000, double %x)
808  ret double %r
809}
810
811define double @maximum_nan_op1(double %x) {
812; CHECK-LABEL: @maximum_nan_op1(
813; CHECK-NEXT:    ret double 0x7FF800000000DEAD
814;
815  %r = call double @llvm.maximum.f64(double %x, double 0x7ff800000000dead)
816  ret double %r
817}
818
819define double @minimum_nan_op0(double %x) {
820; CHECK-LABEL: @minimum_nan_op0(
821; CHECK-NEXT:    ret double 0x7FF8000DEAD00000
822;
823  %r = call double @llvm.minimum.f64(double 0x7ff8000dead00000, double %x)
824  ret double %r
825}
826
827define double @minimum_nan_op1(double %x) {
828; CHECK-LABEL: @minimum_nan_op1(
829; CHECK-NEXT:    ret double 0x7FF800DEAD00DEAD
830;
831  %r = call double @llvm.minimum.f64(double %x, double 0x7ff800dead00dead)
832  ret double %r
833}
834
835define <2 x double> @maximum_nan_op0_vec(<2 x double> %x) {
836; CHECK-LABEL: @maximum_nan_op0_vec(
837; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
838;
839  %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x)
840  ret <2 x double> %r
841}
842
843define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) {
844; CHECK-LABEL: @maximum_nan_op1_vec(
845; CHECK-NEXT:    ret <2 x double> <double 0x7FF800000000DEAD, double 0x7FF8FFFFFFFFFFFF>
846;
847  %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
848  ret <2 x double> %r
849}
850
851define <2 x double> @minimum_nan_op0_vec(<2 x double> %x) {
852; CHECK-LABEL: @minimum_nan_op0_vec(
853; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000DEAD00000>
854;
855  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x)
856  ret <2 x double> %r
857}
858
859define <2 x double> @minimum_nan_op1_vec(<2 x double> %x) {
860; CHECK-LABEL: @minimum_nan_op1_vec(
861; CHECK-NEXT:    ret <2 x double> <double 0x7FF800DEAD00DEAD, double 0x7FF800DEAD00DEAD>
862;
863  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
864  ret <2 x double> %r
865}
866
867define float @maximum_undef_op1(float %x) {
868; CHECK-LABEL: @maximum_undef_op1(
869; CHECK-NEXT:    ret float [[X:%.*]]
870;
871  %val = call float @llvm.maximum.f32(float %x, float undef)
872  ret float %val
873}
874
875define float @maximum_undef_op0(float %x) {
876; CHECK-LABEL: @maximum_undef_op0(
877; CHECK-NEXT:    ret float [[X:%.*]]
878;
879  %val = call float @llvm.maximum.f32(float undef, float %x)
880  ret float %val
881}
882
883define float @minimum_undef_op1(float %x) {
884; CHECK-LABEL: @minimum_undef_op1(
885; CHECK-NEXT:    ret float [[X:%.*]]
886;
887  %val = call float @llvm.minimum.f32(float %x, float undef)
888  ret float %val
889}
890
891define float @minimum_undef_op0(float %x) {
892; CHECK-LABEL: @minimum_undef_op0(
893; CHECK-NEXT:    ret float [[X:%.*]]
894;
895  %val = call float @llvm.minimum.f32(float undef, float %x)
896  ret float %val
897}
898
899define float @minimum_undef_undef(float %x) {
900; CHECK-LABEL: @minimum_undef_undef(
901; CHECK-NEXT:    ret float undef
902;
903  %val = call float @llvm.minimum.f32(float undef, float undef)
904  ret float %val
905}
906
907define float @maximum_undef_undef(float %x) {
908; CHECK-LABEL: @maximum_undef_undef(
909; CHECK-NEXT:    ret float undef
910;
911  %val = call float @llvm.maximum.f32(float undef, float undef)
912  ret float %val
913}
914
915define float @minimum_same_args(float %x) {
916; CHECK-LABEL: @minimum_same_args(
917; CHECK-NEXT:    ret float [[X:%.*]]
918;
919  %y = call float @llvm.minimum.f32(float %x, float %x)
920  ret float %y
921}
922
923define float @maximum_same_args(float %x) {
924; CHECK-LABEL: @maximum_same_args(
925; CHECK-NEXT:    ret float [[X:%.*]]
926;
927  %y = call float @llvm.maximum.f32(float %x, float %x)
928  ret float %y
929}
930
931define float @minimum_x_minimum_x_y(float %x, float %y) {
932; CHECK-LABEL: @minimum_x_minimum_x_y(
933; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
934; CHECK-NEXT:    ret float [[A]]
935;
936  %a = call float @llvm.minimum.f32(float %x, float %y)
937  %b = call float @llvm.minimum.f32(float %x, float %a)
938  ret float %b
939}
940
941define float @minimum_y_minimum_x_y(float %x, float %y) {
942; CHECK-LABEL: @minimum_y_minimum_x_y(
943; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
944; CHECK-NEXT:    ret float [[A]]
945;
946  %a = call float @llvm.minimum.f32(float %x, float %y)
947  %b = call float @llvm.minimum.f32(float %y, float %a)
948  ret float %b
949}
950
951define float @minimum_x_y_minimum_x(float %x, float %y) {
952; CHECK-LABEL: @minimum_x_y_minimum_x(
953; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
954; CHECK-NEXT:    ret float [[A]]
955;
956  %a = call float @llvm.minimum.f32(float %x, float %y)
957  %b = call float @llvm.minimum.f32(float %a, float %x)
958  ret float %b
959}
960
961define float @minimum_x_y_minimum_y(float %x, float %y) {
962; CHECK-LABEL: @minimum_x_y_minimum_y(
963; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
964; CHECK-NEXT:    ret float [[A]]
965;
966  %a = call float @llvm.minimum.f32(float %x, float %y)
967  %b = call float @llvm.minimum.f32(float %a, float %y)
968  ret float %b
969}
970
971; negative test
972
973define float @minimum_z_minimum_x_y(float %x, float %y, float %z) {
974; CHECK-LABEL: @minimum_z_minimum_x_y(
975; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
976; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[A]])
977; CHECK-NEXT:    ret float [[B]]
978;
979  %a = call float @llvm.minimum.f32(float %x, float %y)
980  %b = call float @llvm.minimum.f32(float %z, float %a)
981  ret float %b
982}
983
984; negative test
985
986define float @minimum_x_y_minimum_z(float %x, float %y, float %z) {
987; CHECK-LABEL: @minimum_x_y_minimum_z(
988; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
989; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minimum.f32(float [[A]], float [[Z:%.*]])
990; CHECK-NEXT:    ret float [[B]]
991;
992  %a = call float @llvm.minimum.f32(float %x, float %y)
993  %b = call float @llvm.minimum.f32(float %a, float %z)
994  ret float %b
995}
996
997; minimum(X, -INF) --> -INF
998
999define float @minimum_neginf(float %x) {
1000; CHECK-LABEL: @minimum_neginf(
1001; CHECK-NEXT:    ret float 0xFFF0000000000000
1002;
1003  %val = call float @llvm.minimum.f32(float %x, float 0xFFF0000000000000)
1004  ret float %val
1005}
1006
1007define <2 x double> @minimum_neginf_commute_vec(<2 x double> %x) {
1008; CHECK-LABEL: @minimum_neginf_commute_vec(
1009; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>
1010;
1011  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
1012  ret <2 x double> %r
1013}
1014
1015; negative test
1016
1017define float @minimum_inf(float %x) {
1018; CHECK-LABEL: @minimum_inf(
1019; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.minimum.f32(float 0x7FF0000000000000, float [[X:%.*]])
1020; CHECK-NEXT:    ret float [[VAL]]
1021;
1022  %val = call float @llvm.minimum.f32(float 0x7FF0000000000000, float %x)
1023  ret float %val
1024}
1025define float @maximum_x_maximum_x_y(float %x, float %y) {
1026; CHECK-LABEL: @maximum_x_maximum_x_y(
1027; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1028; CHECK-NEXT:    ret float [[A]]
1029;
1030  %a = call float @llvm.maximum.f32(float %x, float %y)
1031  %b = call float @llvm.maximum.f32(float %x, float %a)
1032  ret float %b
1033}
1034
1035define float @maximum_y_maximum_x_y(float %x, float %y) {
1036; CHECK-LABEL: @maximum_y_maximum_x_y(
1037; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1038; CHECK-NEXT:    ret float [[A]]
1039;
1040  %a = call float @llvm.maximum.f32(float %x, float %y)
1041  %b = call float @llvm.maximum.f32(float %y, float %a)
1042  ret float %b
1043}
1044
1045define float @maximum_x_y_maximum_x(float %x, float %y) {
1046; CHECK-LABEL: @maximum_x_y_maximum_x(
1047; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1048; CHECK-NEXT:    ret float [[A]]
1049;
1050  %a = call float @llvm.maximum.f32(float %x, float %y)
1051  %b = call float @llvm.maximum.f32(float %a, float %x)
1052  ret float %b
1053}
1054
1055define float @maximum_x_y_maximum_y(float %x, float %y) {
1056; CHECK-LABEL: @maximum_x_y_maximum_y(
1057; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1058; CHECK-NEXT:    ret float [[A]]
1059;
1060  %a = call float @llvm.maximum.f32(float %x, float %y)
1061  %b = call float @llvm.maximum.f32(float %a, float %y)
1062  ret float %b
1063}
1064
1065; negative test
1066
1067define float @maximum_z_maximum_x_y(float %x, float %y, float %z) {
1068; CHECK-LABEL: @maximum_z_maximum_x_y(
1069; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1070; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[A]])
1071; CHECK-NEXT:    ret float [[B]]
1072;
1073  %a = call float @llvm.maximum.f32(float %x, float %y)
1074  %b = call float @llvm.maximum.f32(float %z, float %a)
1075  ret float %b
1076}
1077
1078; negative test
1079
1080define float @maximum_x_y_maximum_z(float %x, float %y, float %z) {
1081; CHECK-LABEL: @maximum_x_y_maximum_z(
1082; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
1083; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[Z:%.*]])
1084; CHECK-NEXT:    ret float [[B]]
1085;
1086  %a = call float @llvm.maximum.f32(float %x, float %y)
1087  %b = call float @llvm.maximum.f32(float %a, float %z)
1088  ret float %b
1089}
1090
1091; maximum(X, INF) --> INF
1092
1093define <2 x double> @maximum_inf(<2 x double> %x) {
1094; CHECK-LABEL: @maximum_inf(
1095; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>
1096;
1097  %val = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
1098  ret <2 x double> %val
1099}
1100
1101define float @maximum_inf_commute(float %x) {
1102; CHECK-LABEL: @maximum_inf_commute(
1103; CHECK-NEXT:    ret float 0x7FF0000000000000
1104;
1105  %val = call float @llvm.maximum.f32(float 0x7FF0000000000000, float %x)
1106  ret float %val
1107}
1108
1109; Y - (Y - X) --> X
1110
1111define float @fsub_fsub_common_op(float %x, float %y) {
1112; CHECK-LABEL: @fsub_fsub_common_op(
1113; CHECK-NEXT:    ret float [[X:%.*]]
1114;
1115  %s = fsub float %y, %x
1116  %r = fsub reassoc nsz float %y, %s
1117  ret float %r
1118}
1119
1120define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) {
1121; CHECK-LABEL: @fsub_fsub_common_op_vec(
1122; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
1123;
1124  %s = fsub <2 x float> %y, %x
1125  %r = fsub reassoc nsz <2 x float> %y, %s
1126  ret <2 x float> %r
1127}
1128
1129; Negative test - fsub is not commutative.
1130; Y - (X - Y) --> (Y - X) + Y (canonicalized)
1131
1132define float @fsub_fsub_wrong_common_op(float %x, float %y) {
1133; CHECK-LABEL: @fsub_fsub_wrong_common_op(
1134; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
1135; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]]
1136; CHECK-NEXT:    ret float [[R]]
1137;
1138  %s = fsub float %x, %y
1139  %r = fsub reassoc nsz float %y, %s
1140  ret float %r
1141}
1142
1143; Negative test - negated operand needed.
1144; (Y - X) - Y --> -X
1145
1146define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) {
1147; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
1148; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
1149; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
1150; CHECK-NEXT:    ret float [[R]]
1151;
1152  %s = fsub float %y, %x
1153  %r = fsub reassoc nsz float %s, %y
1154  ret float %r
1155}
1156
1157; Negative test - fsub is not commutative.
1158; (X - Y) - Y --> ?
1159
1160define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) {
1161; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
1162; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
1163; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
1164; CHECK-NEXT:    ret float [[R]]
1165;
1166  %s = fsub float %x, %y
1167  %r = fsub reassoc nsz float %s, %y
1168  ret float %r
1169}
1170
1171; (Y + X) - Y --> X
1172
1173define float @fadd_fsub_common_op(float %x, float %y) {
1174; CHECK-LABEL: @fadd_fsub_common_op(
1175; CHECK-NEXT:    ret float [[X:%.*]]
1176;
1177  %a = fadd float %y, %x
1178  %r = fsub reassoc nsz float %a, %y
1179  ret float %r
1180}
1181
1182; (X + Y) - Y --> X
1183
1184define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) {
1185; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
1186; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
1187;
1188  %a = fadd <2 x float> %x, %y
1189  %r = fsub reassoc nsz <2 x float> %a, %y
1190  ret <2 x float> %r
1191}
1192
1193; Negative test - negated operand needed.
1194; Y - (Y + X) --> -X
1195
1196define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) {
1197; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
1198; CHECK-NEXT:    [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]]
1199; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
1200; CHECK-NEXT:    ret float [[R]]
1201;
1202  %a = fadd float %y, %x
1203  %r = fsub reassoc nsz float %y, %a
1204  ret float %r
1205}
1206
1207; Negative test - negated operand needed.
1208; Y - (X + Y) --> -X
1209
1210define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) {
1211; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
1212; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
1213; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
1214; CHECK-NEXT:    ret float [[R]]
1215;
1216  %a = fadd float %x, %y
1217  %r = fsub reassoc nsz float %y, %a
1218  ret float %r
1219}
1220
1221; Y + (X - Y) --> X
1222
1223define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) {
1224; CHECK-LABEL: @fsub_fadd_common_op_vec(
1225; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
1226;
1227  %s = fsub <2 x float> %x, %y
1228  %r = fadd reassoc nsz <2 x float> %y, %s
1229  ret <2 x float> %r
1230}
1231
1232; (X - Y) + Y --> X
1233
1234define float @fsub_fadd_common_op_commute(float %x, float %y) {
1235; CHECK-LABEL: @fsub_fadd_common_op_commute(
1236; CHECK-NEXT:    ret float [[X:%.*]]
1237;
1238  %s = fsub float %x, %y
1239  %r = fadd reassoc nsz float %s, %y
1240  ret float %r
1241}
1242
1243; Negative test.
1244; Y + (Y - X) --> ?
1245
1246define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) {
1247; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
1248; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
1249; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]]
1250; CHECK-NEXT:    ret float [[R]]
1251;
1252  %s = fsub float %y, %x
1253  %r = fadd reassoc nsz float %y, %s
1254  ret float %r
1255}
1256
1257; Negative test.
1258; (Y - X) + Y --> ?
1259
1260define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) {
1261; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
1262; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
1263; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]]
1264; CHECK-NEXT:    ret float [[R]]
1265;
1266  %s = fsub float %y, %x
1267  %r = fadd reassoc nsz float %s, %y
1268  ret float %r
1269}
1270