1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -early-cse -earlycse-debug-hash | FileCheck %s
3; RUN: opt < %s -S -basic-aa -early-cse-memssa | FileCheck %s
4
5define void @test1(float %A, float %B, float* %PA, float* %PB) {
6; CHECK-LABEL: @test1(
7; CHECK-NEXT:    [[C:%.*]] = fadd float [[A:%.*]], [[B:%.*]]
8; CHECK-NEXT:    store float [[C]], float* [[PA:%.*]], align 4
9; CHECK-NEXT:    store float [[C]], float* [[PB:%.*]], align 4
10; CHECK-NEXT:    ret void
11;
12  %C = fadd float %A, %B
13  store float %C, float* %PA
14  %D = fadd float %B, %A
15  store float %D, float* %PB
16  ret void
17}
18
19define void @test2(float %A, float %B, i1* %PA, i1* %PB) {
20; CHECK-LABEL: @test2(
21; CHECK-NEXT:    [[C:%.*]] = fcmp oeq float [[A:%.*]], [[B:%.*]]
22; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]], align 1
23; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]], align 1
24; CHECK-NEXT:    ret void
25;
26  %C = fcmp oeq float %A, %B
27  store i1 %C, i1* %PA
28  %D = fcmp oeq float %B, %A
29  store i1 %D, i1* %PB
30  ret void
31}
32
33define void @test3(float %A, float %B, i1* %PA, i1* %PB) {
34; CHECK-LABEL: @test3(
35; CHECK-NEXT:    [[C:%.*]] = fcmp uge float [[A:%.*]], [[B:%.*]]
36; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]], align 1
37; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]], align 1
38; CHECK-NEXT:    ret void
39;
40  %C = fcmp uge float %A, %B
41  store i1 %C, i1* %PA
42  %D = fcmp ule float %B, %A
43  store i1 %D, i1* %PB
44  ret void
45}
46
47define void @test4(i32 %A, i32 %B, i1* %PA, i1* %PB) {
48; CHECK-LABEL: @test4(
49; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
50; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]], align 1
51; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]], align 1
52; CHECK-NEXT:    ret void
53;
54  %C = icmp eq i32 %A, %B
55  store i1 %C, i1* %PA
56  %D = icmp eq i32 %B, %A
57  store i1 %D, i1* %PB
58  ret void
59}
60
61define void @test5(i32 %A, i32 %B, i1* %PA, i1* %PB) {
62; CHECK-LABEL: @test5(
63; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
64; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]], align 1
65; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]], align 1
66; CHECK-NEXT:    ret void
67;
68  %C = icmp sgt i32 %A, %B
69  store i1 %C, i1* %PA
70  %D = icmp slt i32 %B, %A
71  store i1 %D, i1* %PB
72  ret void
73}
74
75; Test degenerate case of commuted compare of identical comparands.
76
77define void @test6(float %f, i1* %p1, i1* %p2) {
78; CHECK-LABEL: @test6(
79; CHECK-NEXT:    [[C1:%.*]] = fcmp ult float [[F:%.*]], [[F]]
80; CHECK-NEXT:    store i1 [[C1]], i1* [[P1:%.*]], align 1
81; CHECK-NEXT:    store i1 [[C1]], i1* [[P2:%.*]], align 1
82; CHECK-NEXT:    ret void
83;
84  %c1 = fcmp ult float %f, %f
85  %c2 = fcmp ugt float %f, %f
86  store i1 %c1, i1* %p1
87  store i1 %c2, i1* %p2
88  ret void
89}
90
91; Min/max operands may be commuted in the compare and select.
92
93define i8 @smin_commute(i8 %a, i8 %b) {
94; CHECK-LABEL: @smin_commute(
95; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
96; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[B]], [[A]]
97; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
98; CHECK-NEXT:    [[R:%.*]] = mul i8 [[M1]], [[M1]]
99; CHECK-NEXT:    ret i8 [[R]]
100;
101  %cmp1 = icmp slt i8 %a, %b
102  %cmp2 = icmp slt i8 %b, %a
103  %m1 = select i1 %cmp1, i8 %a, i8 %b
104  %m2 = select i1 %cmp2, i8 %b, i8 %a
105  %r = mul i8 %m1, %m2
106  ret i8 %r
107}
108
109; Min/max can also have a swapped predicate and select operands.
110
111define i1 @smin_swapped(i8 %a, i8 %b) {
112; CHECK-LABEL: @smin_swapped(
113; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
114; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[A]], [[B]]
115; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
116; CHECK-NEXT:    ret i1 true
117;
118  %cmp1 = icmp sgt i8 %a, %b
119  %cmp2 = icmp slt i8 %a, %b
120  %m1 = select i1 %cmp1, i8 %b, i8 %a
121  %m2 = select i1 %cmp2, i8 %a, i8 %b
122  %r = icmp eq i8 %m2, %m1
123  ret i1 %r
124}
125
126; Min/max can also have an inverted predicate and select operands.
127
128define i1 @smin_inverted(i8 %a, i8 %b) {
129; CHECK-LABEL: @smin_inverted(
130; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
131; CHECK-NEXT:    [[CMP2:%.*]] = xor i1 [[CMP1]], true
132; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
133; CHECK-NEXT:    ret i1 true
134;
135  %cmp1 = icmp slt i8 %a, %b
136  %cmp2 = xor i1 %cmp1, -1
137  %m1 = select i1 %cmp1, i8 %a, i8 %b
138  %m2 = select i1 %cmp2, i8 %b, i8 %a
139  %r = icmp eq i8 %m1, %m2
140  ret i1 %r
141}
142
143define i8 @smax_commute(i8 %a, i8 %b) {
144; CHECK-LABEL: @smax_commute(
145; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
146; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[B]], [[A]]
147; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
148; CHECK-NEXT:    ret i8 0
149;
150  %cmp1 = icmp sgt i8 %a, %b
151  %cmp2 = icmp sgt i8 %b, %a
152  %m1 = select i1 %cmp1, i8 %a, i8 %b
153  %m2 = select i1 %cmp2, i8 %b, i8 %a
154  %r = urem i8 %m2, %m1
155  ret i8 %r
156}
157
158define i8 @smax_swapped(i8 %a, i8 %b) {
159; CHECK-LABEL: @smax_swapped(
160; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
161; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[A]], [[B]]
162; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
163; CHECK-NEXT:    ret i8 1
164;
165  %cmp1 = icmp slt i8 %a, %b
166  %cmp2 = icmp sgt i8 %a, %b
167  %m1 = select i1 %cmp1, i8 %b, i8 %a
168  %m2 = select i1 %cmp2, i8 %a, i8 %b
169  %r = sdiv i8 %m1, %m2
170  ret i8 %r
171}
172
173define i1 @smax_inverted(i8 %a, i8 %b) {
174; CHECK-LABEL: @smax_inverted(
175; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
176; CHECK-NEXT:    [[CMP2:%.*]] = xor i1 [[CMP1]], true
177; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
178; CHECK-NEXT:    ret i1 true
179;
180  %cmp1 = icmp sgt i8 %a, %b
181  %cmp2 = xor i1 %cmp1, -1
182  %m1 = select i1 %cmp1, i8 %a, i8 %b
183  %m2 = select i1 %cmp2, i8 %b, i8 %a
184  %r = icmp eq i8 %m1, %m2
185  ret i1 %r
186}
187
188define i8 @umin_commute(i8 %a, i8 %b) {
189; CHECK-LABEL: @umin_commute(
190; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
191; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 [[B]], [[A]]
192; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
193; CHECK-NEXT:    ret i8 0
194;
195  %cmp1 = icmp ult i8 %a, %b
196  %cmp2 = icmp ult i8 %b, %a
197  %m1 = select i1 %cmp1, i8 %a, i8 %b
198  %m2 = select i1 %cmp2, i8 %b, i8 %a
199  %r = sub i8 %m2, %m1
200  ret i8 %r
201}
202
203; Choose a vector type just to show that works.
204
205define <2 x i8> @umin_swapped(<2 x i8> %a, <2 x i8> %b) {
206; CHECK-LABEL: @umin_swapped(
207; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt <2 x i8> [[A:%.*]], [[B:%.*]]
208; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult <2 x i8> [[A]], [[B]]
209; CHECK-NEXT:    [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> [[B]], <2 x i8> [[A]]
210; CHECK-NEXT:    ret <2 x i8> zeroinitializer
211;
212  %cmp1 = icmp ugt <2 x i8> %a, %b
213  %cmp2 = icmp ult <2 x i8> %a, %b
214  %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a
215  %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b
216  %r = sub <2 x i8> %m2, %m1
217  ret <2 x i8> %r
218}
219
220define i1 @umin_inverted(i8 %a, i8 %b) {
221; CHECK-LABEL: @umin_inverted(
222; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
223; CHECK-NEXT:    [[CMP2:%.*]] = xor i1 [[CMP1]], true
224; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
225; CHECK-NEXT:    ret i1 true
226;
227  %cmp1 = icmp ult i8 %a, %b
228  %cmp2 = xor i1 %cmp1, -1
229  %m1 = select i1 %cmp1, i8 %a, i8 %b
230  %m2 = select i1 %cmp2, i8 %b, i8 %a
231  %r = icmp eq i8 %m1, %m2
232  ret i1 %r
233}
234
235define i8 @umax_commute(i8 %a, i8 %b) {
236; CHECK-LABEL: @umax_commute(
237; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]
238; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 [[B]], [[A]]
239; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
240; CHECK-NEXT:    ret i8 1
241;
242  %cmp1 = icmp ugt i8 %a, %b
243  %cmp2 = icmp ugt i8 %b, %a
244  %m1 = select i1 %cmp1, i8 %a, i8 %b
245  %m2 = select i1 %cmp2, i8 %b, i8 %a
246  %r = udiv i8 %m1, %m2
247  ret i8 %r
248}
249
250define i8 @umax_swapped(i8 %a, i8 %b) {
251; CHECK-LABEL: @umax_swapped(
252; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
253; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 [[A]], [[B]]
254; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
255; CHECK-NEXT:    [[R:%.*]] = add i8 [[M1]], [[M1]]
256; CHECK-NEXT:    ret i8 [[R]]
257;
258  %cmp1 = icmp ult i8 %a, %b
259  %cmp2 = icmp ugt i8 %a, %b
260  %m1 = select i1 %cmp1, i8 %b, i8 %a
261  %m2 = select i1 %cmp2, i8 %a, i8 %b
262  %r = add i8 %m2, %m1
263  ret i8 %r
264}
265
266define i1 @umax_inverted(i8 %a, i8 %b) {
267; CHECK-LABEL: @umax_inverted(
268; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]
269; CHECK-NEXT:    [[CMP2:%.*]] = xor i1 [[CMP1]], true
270; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
271; CHECK-NEXT:    ret i1 true
272;
273  %cmp1 = icmp ugt i8 %a, %b
274  %cmp2 = xor i1 %cmp1, -1
275  %m1 = select i1 %cmp1, i8 %a, i8 %b
276  %m2 = select i1 %cmp2, i8 %b, i8 %a
277  %r = icmp eq i8 %m1, %m2
278  ret i1 %r
279}
280
281; Min/max may exist with non-canonical operands. Value tracking can match those.
282; But we do not use value tracking, so we expect instcombine will canonicalize
283; this code to a form that allows CSE.
284
285define i8 @smax_nsw(i8 %a, i8 %b) {
286; CHECK-LABEL: @smax_nsw(
287; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
288; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], [[B]]
289; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0
290; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]]
291; CHECK-NEXT:    [[M2:%.*]] = select i1 [[CMP2]], i8 [[SUB]], i8 0
292; CHECK-NEXT:    [[R:%.*]] = sub i8 [[M2]], [[M1]]
293; CHECK-NEXT:    ret i8 [[R]]
294;
295  %sub = sub nsw i8 %a, %b
296  %cmp1 = icmp slt i8 %a, %b
297  %cmp2 = icmp sgt i8 %sub, 0
298  %m1 = select i1 %cmp1, i8 0, i8 %sub
299  %m2 = select i1 %cmp2, i8 %sub, i8 0
300  %r = sub i8 %m2, %m1
301  ret i8 %r
302}
303
304
305define i8 @abs_swapped_sge(i8 %a) {
306; CHECK-LABEL: @abs_swapped_sge(
307; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
308; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i8 [[A]], 0
309; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[A]], 0
310; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
311; CHECK-NEXT:    ret i8 0
312;
313  %neg = sub i8 0, %a
314  %cmp1 = icmp sge i8 %a, 0
315  %cmp2 = icmp slt i8 %a, 0
316  %m1 = select i1 %cmp1, i8 %a, i8 %neg
317  %m2 = select i1 %cmp2, i8 %neg, i8 %a
318  %r = xor i8 %m2, %m1
319  ret i8 %r
320}
321
322define i8 @nabs_swapped_sge(i8 %a) {
323; CHECK-LABEL: @nabs_swapped_sge(
324; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
325; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], 0
326; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 [[A]], 0
327; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
328; CHECK-NEXT:    ret i8 0
329;
330  %neg = sub i8 0, %a
331  %cmp1 = icmp slt i8 %a, 0
332  %cmp2 = icmp sge i8 %a, 0
333  %m1 = select i1 %cmp1, i8 %a, i8 %neg
334  %m2 = select i1 %cmp2, i8 %neg, i8 %a
335  %r = xor i8 %m2, %m1
336  ret i8 %r
337}
338
339; Abs/nabs may exist with non-canonical operands. Value tracking can match those.
340; But we do not use value tracking, so we expect instcombine will canonicalize
341; this code to a form that allows CSE.
342
343define i8 @abs_swapped(i8 %a) {
344; CHECK-LABEL: @abs_swapped(
345; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
346; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A]], 0
347; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[A]], 0
348; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
349; CHECK-NEXT:    [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]
350; CHECK-NEXT:    [[R:%.*]] = or i8 [[M2]], [[M1]]
351; CHECK-NEXT:    ret i8 [[R]]
352;
353  %neg = sub i8 0, %a
354  %cmp1 = icmp sgt i8 %a, 0
355  %cmp2 = icmp slt i8 %a, 0
356  %m1 = select i1 %cmp1, i8 %a, i8 %neg
357  %m2 = select i1 %cmp2, i8 %neg, i8 %a
358  %r = or i8 %m2, %m1
359  ret i8 %r
360}
361
362define i8 @abs_inverted(i8 %a) {
363; CHECK-LABEL: @abs_inverted(
364; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
365; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A]], 0
366; CHECK-NEXT:    [[CMP2:%.*]] = xor i1 [[CMP1]], true
367; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
368; CHECK-NEXT:    ret i8 [[M1]]
369;
370  %neg = sub i8 0, %a
371  %cmp1 = icmp sgt i8 %a, 0
372  %cmp2 = xor i1 %cmp1, -1
373  %m1 = select i1 %cmp1, i8 %a, i8 %neg
374  %m2 = select i1 %cmp2, i8 %neg, i8 %a
375  %r = or i8 %m2, %m1
376  ret i8 %r
377}
378
379; Abs/nabs may exist with non-canonical operands. Value tracking can match those.
380; But we do not use value tracking, so we expect instcombine will canonicalize
381; this code to a form that allows CSE.
382
383define i8 @nabs_swapped(i8 %a) {
384; CHECK-LABEL: @nabs_swapped(
385; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
386; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], 0
387; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[A]], 0
388; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
389; CHECK-NEXT:    [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]
390; CHECK-NEXT:    [[R:%.*]] = xor i8 [[M2]], [[M1]]
391; CHECK-NEXT:    ret i8 [[R]]
392;
393  %neg = sub i8 0, %a
394  %cmp1 = icmp slt i8 %a, 0
395  %cmp2 = icmp sgt i8 %a, 0
396  %m1 = select i1 %cmp1, i8 %a, i8 %neg
397  %m2 = select i1 %cmp2, i8 %neg, i8 %a
398  %r = xor i8 %m2, %m1
399  ret i8 %r
400}
401
402define i8 @nabs_inverted(i8 %a) {
403; CHECK-LABEL: @nabs_inverted(
404; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
405; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], 0
406; CHECK-NEXT:    [[CMP2:%.*]] = xor i1 [[CMP1]], true
407; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
408; CHECK-NEXT:    ret i8 0
409;
410  %neg = sub i8 0, %a
411  %cmp1 = icmp slt i8 %a, 0
412  %cmp2 = xor i1 %cmp1, -1
413  %m1 = select i1 %cmp1, i8 %a, i8 %neg
414  %m2 = select i1 %cmp2, i8 %neg, i8 %a
415  %r = xor i8 %m2, %m1
416  ret i8 %r
417}
418
419; Abs/nabs may exist with non-canonical operands. Value tracking can match those.
420; But we do not use value tracking, so we expect instcombine will canonicalize
421; this code to a form that allows CSE.
422
423; compares are different.
424define i8 @abs_different_constants(i8 %a) {
425; CHECK-LABEL: @abs_different_constants(
426; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
427; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A]], -1
428; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[A]], 0
429; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
430; CHECK-NEXT:    [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]
431; CHECK-NEXT:    [[R:%.*]] = or i8 [[M2]], [[M1]]
432; CHECK-NEXT:    ret i8 [[R]]
433;
434  %neg = sub i8 0, %a
435  %cmp1 = icmp sgt i8 %a, -1
436  %cmp2 = icmp slt i8 %a, 0
437  %m1 = select i1 %cmp1, i8 %a, i8 %neg
438  %m2 = select i1 %cmp2, i8 %neg, i8 %a
439  %r = or i8 %m2, %m1
440  ret i8 %r
441}
442
443; Abs/nabs may exist with non-canonical operands. Value tracking can match those.
444; But we do not use value tracking, so we expect instcombine will canonicalize
445; this code to a form that allows CSE.
446
447define i8 @nabs_different_constants(i8 %a) {
448; CHECK-LABEL: @nabs_different_constants(
449; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
450; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], 0
451; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[A]], -1
452; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
453; CHECK-NEXT:    [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]
454; CHECK-NEXT:    [[R:%.*]] = xor i8 [[M2]], [[M1]]
455; CHECK-NEXT:    ret i8 [[R]]
456;
457  %neg = sub i8 0, %a
458  %cmp1 = icmp slt i8 %a, 0
459  %cmp2 = icmp sgt i8 %a, -1
460  %m1 = select i1 %cmp1, i8 %a, i8 %neg
461  %m2 = select i1 %cmp2, i8 %neg, i8 %a
462  %r = xor i8 %m2, %m1
463  ret i8 %r
464}
465
466; https://bugs.llvm.org/show_bug.cgi?id=41101
467; Detect equivalence of selects with commuted operands: 'not' cond.
468
469define i32 @select_not_cond(i1 %cond, i32 %t, i32 %f) {
470; CHECK-LABEL: @select_not_cond(
471; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[COND:%.*]], true
472; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
473; CHECK-NEXT:    ret i32 0
474;
475  %not = xor i1 %cond, -1
476  %m1 = select i1 %cond, i32 %t, i32 %f
477  %m2 = select i1 %not, i32 %f, i32 %t
478  %r = xor i32 %m2, %m1
479  ret i32 %r
480}
481
482; Detect equivalence of selects with commuted operands: 'not' cond with vector select.
483
484define <2 x double> @select_not_cond_commute_vec(<2 x i1> %cond, <2 x double> %t, <2 x double> %f) {
485; CHECK-LABEL: @select_not_cond_commute_vec(
486; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i1> [[COND:%.*]], <i1 true, i1 true>
487; CHECK-NEXT:    [[M1:%.*]] = select <2 x i1> [[COND]], <2 x double> [[T:%.*]], <2 x double> [[F:%.*]]
488; CHECK-NEXT:    ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
489;
490  %not = xor <2 x i1> %cond, <i1 -1, i1 -1>
491  %m1 = select <2 x i1> %cond, <2 x double> %t, <2 x double> %f
492  %m2 = select <2 x i1> %not, <2 x double> %f, <2 x double> %t
493  %r = fdiv nnan <2 x double> %m1, %m2
494  ret <2 x double> %r
495}
496
497; Negative test - select ops must be commuted.
498
499define i32 @select_not_cond_wrong_select_ops(i1 %cond, i32 %t, i32 %f) {
500; CHECK-LABEL: @select_not_cond_wrong_select_ops(
501; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[COND:%.*]], true
502; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
503; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T]], i32 [[F]]
504; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
505; CHECK-NEXT:    ret i32 [[R]]
506;
507  %not = xor i1 %cond, -1
508  %m1 = select i1 %cond, i32 %t, i32 %f
509  %m2 = select i1 %not, i32 %t, i32 %f
510  %r = xor i32 %m2, %m1
511  ret i32 %r
512}
513
514; Negative test - not a 'not'.
515
516define i32 @select_not_cond_wrong_cond(i1 %cond, i32 %t, i32 %f) {
517; CHECK-LABEL: @select_not_cond_wrong_cond(
518; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND:%.*]], i32 [[T:%.*]], i32 [[F:%.*]]
519; CHECK-NEXT:    [[M2:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
520; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
521; CHECK-NEXT:    ret i32 [[R]]
522;
523  %not = xor i1 %cond, -2
524  %m1 = select i1 %cond, i32 %t, i32 %f
525  %m2 = select i1 %not, i32 %f, i32 %t
526  %r = xor i32 %m2, %m1
527  ret i32 %r
528}
529
530; Detect equivalence of selects with commuted operands: inverted pred with fcmps.
531
532define i32 @select_invert_pred_cond(float %x, i32 %t, i32 %f) {
533; CHECK-LABEL: @select_invert_pred_cond(
534; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
535; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
536; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
537; CHECK-NEXT:    ret i32 0
538;
539  %cond = fcmp ueq float %x, 42.0
540  %invcond = fcmp one float %x, 42.0
541  %m1 = select i1 %cond, i32 %t, i32 %f
542  %m2 = select i1 %invcond, i32 %f, i32 %t
543  %r = xor i32 %m2, %m1
544  ret i32 %r
545}
546
547; Detect equivalence of selects with commuted operands: inverted pred with icmps and vectors.
548
549define <2 x i32> @select_invert_pred_cond_commute_vec(<2 x i8> %x, <2 x i32> %t, <2 x i32> %f) {
550; CHECK-LABEL: @select_invert_pred_cond_commute_vec(
551; CHECK-NEXT:    [[COND:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 42, i8 -1>
552; CHECK-NEXT:    [[INVCOND:%.*]] = icmp sle <2 x i8> [[X]], <i8 42, i8 -1>
553; CHECK-NEXT:    [[M1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[T:%.*]], <2 x i32> [[F:%.*]]
554; CHECK-NEXT:    ret <2 x i32> zeroinitializer
555;
556  %cond = icmp sgt <2 x i8> %x, <i8 42, i8 -1>
557  %invcond = icmp sle <2 x i8> %x, <i8 42, i8 -1>
558  %m1 = select <2 x i1> %cond, <2 x i32> %t, <2 x i32> %f
559  %m2 = select <2 x i1> %invcond, <2 x i32> %f, <2 x i32> %t
560  %r = xor <2 x i32> %m1, %m2
561  ret <2 x i32> %r
562}
563
564; Negative test - select ops must be commuted.
565
566define i32 @select_invert_pred_wrong_select_ops(float %x, i32 %t, i32 %f) {
567; CHECK-LABEL: @select_invert_pred_wrong_select_ops(
568; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
569; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
570; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[F:%.*]], i32 [[T:%.*]]
571; CHECK-NEXT:    [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
572; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
573; CHECK-NEXT:    ret i32 [[R]]
574;
575  %cond = fcmp ueq float %x, 42.0
576  %invcond = fcmp one float %x, 42.0
577  %m1 = select i1 %cond, i32 %f, i32 %t
578  %m2 = select i1 %invcond, i32 %f, i32 %t
579  %r = xor i32 %m2, %m1
580  ret i32 %r
581}
582
583; Negative test - not an inverted predicate.
584
585define i32 @select_invert_pred_wrong_cond(float %x, i32 %t, i32 %f) {
586; CHECK-LABEL: @select_invert_pred_wrong_cond(
587; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
588; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp une float [[X]], 4.200000e+01
589; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
590; CHECK-NEXT:    [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
591; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
592; CHECK-NEXT:    ret i32 [[R]]
593;
594  %cond = fcmp ueq float %x, 42.0
595  %invcond = fcmp une float %x, 42.0
596  %m1 = select i1 %cond, i32 %t, i32 %f
597  %m2 = select i1 %invcond, i32 %f, i32 %t
598  %r = xor i32 %m2, %m1
599  ret i32 %r
600}
601
602; Negative test - cmp ops must match.
603
604define i32 @select_invert_pred_wrong_cmp_ops(float %x, i32 %t, i32 %f) {
605; CHECK-LABEL: @select_invert_pred_wrong_cmp_ops(
606; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
607; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp one float [[X]], 4.300000e+01
608; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
609; CHECK-NEXT:    [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
610; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
611; CHECK-NEXT:    ret i32 [[R]]
612;
613  %cond = fcmp ueq float %x, 42.0
614  %invcond = fcmp one float %x, 43.0
615  %m1 = select i1 %cond, i32 %t, i32 %f
616  %m2 = select i1 %invcond, i32 %f, i32 %t
617  %r = xor i32 %m2, %m1
618  ret i32 %r
619}
620
621; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
622
623define i32 @select_not_invert_pred_cond(i8 %x, i32 %t, i32 %f) {
624; CHECK-LABEL: @select_not_invert_pred_cond(
625; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X:%.*]], 42
626; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X]], 42
627; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
628; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
629; CHECK-NEXT:    ret i32 0
630;
631  %cond = icmp ugt i8 %x, 42
632  %invcond = icmp ule i8 %x, 42
633  %not = xor i1 %invcond, -1
634  %m1 = select i1 %cond, i32 %t, i32 %f
635  %m2 = select i1 %not, i32 %t, i32 %f
636  %r = sub i32 %m1, %m2
637  ret i32 %r
638}
639
640; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
641
642define i32 @select_not_invert_pred_cond_commute(i8 %x, i8 %y, i32 %t, i32 %f) {
643; CHECK-LABEL: @select_not_invert_pred_cond_commute(
644; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
645; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
646; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
647; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
648; CHECK-NEXT:    ret i32 0
649;
650  %invcond = icmp ule i8 %x, %y
651  %not = xor i1 %invcond, -1
652  %m2 = select i1 %not, i32 %t, i32 %f
653  %cond = icmp ugt i8 %x, %y
654  %m1 = select i1 %cond, i32 %t, i32 %f
655  %r = sub i32 %m2, %m1
656  ret i32 %r
657}
658
659; Negative test - not an inverted predicate.
660
661define i32 @select_not_invert_pred_cond_wrong_pred(i8 %x, i8 %y, i32 %t, i32 %f) {
662; CHECK-LABEL: @select_not_invert_pred_cond_wrong_pred(
663; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
664; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
665; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
666; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
667; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
668; CHECK-NEXT:    [[R:%.*]] = sub i32 [[M2]], [[M1]]
669; CHECK-NEXT:    ret i32 [[R]]
670;
671  %invcond = icmp ult i8 %x, %y
672  %not = xor i1 %invcond, -1
673  %m2 = select i1 %not, i32 %t, i32 %f
674  %cond = icmp ugt i8 %x, %y
675  %m1 = select i1 %cond, i32 %t, i32 %f
676  %r = sub i32 %m2, %m1
677  ret i32 %r
678}
679
680; Negative test - cmp ops must match.
681
682define i32 @select_not_invert_pred_cond_wrong_cmp_op(i8 %x, i8 %y, i32 %t, i32 %f) {
683; CHECK-LABEL: @select_not_invert_pred_cond_wrong_cmp_op(
684; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], 42
685; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
686; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
687; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]]
688; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
689; CHECK-NEXT:    [[R:%.*]] = sub i32 [[M2]], [[M1]]
690; CHECK-NEXT:    ret i32 [[R]]
691;
692  %invcond = icmp ule i8 %x, 42
693  %not = xor i1 %invcond, -1
694  %m2 = select i1 %not, i32 %t, i32 %f
695  %cond = icmp ugt i8 %x, %y
696  %m1 = select i1 %cond, i32 %t, i32 %f
697  %r = sub i32 %m2, %m1
698  ret i32 %r
699}
700
701; Negative test - select ops must be same (and not commuted).
702
703define i32 @select_not_invert_pred_cond_wrong_select_op(i8 %x, i8 %y, i32 %t, i32 %f) {
704; CHECK-LABEL: @select_not_invert_pred_cond_wrong_select_op(
705; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
706; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
707; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
708; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
709; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
710; CHECK-NEXT:    [[R:%.*]] = sub i32 [[M2]], [[M1]]
711; CHECK-NEXT:    ret i32 [[R]]
712;
713  %invcond = icmp ule i8 %x, %y
714  %not = xor i1 %invcond, -1
715  %m2 = select i1 %not, i32 %t, i32 %f
716  %cond = icmp ugt i8 %x, %y
717  %m1 = select i1 %cond, i32 %f, i32 %t
718  %r = sub i32 %m2, %m1
719  ret i32 %r
720}
721
722; This test is a reproducer for a bug involving inverted min/max selects
723; hashing differently but comparing as equal.  It exhibits such a pair of
724; values, and we run this test with -earlycse-debug-hash which would catch
725; the disagreement and fail if it regressed.
726; EarlyCSE should be able to detect the 2nd redundant `select` and eliminate
727; it.
728define i32 @inverted_max(i32 %i) {
729; CHECK-LABEL: @inverted_max(
730; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 0, [[I:%.*]]
731; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP]], i32 [[I]], i32 0
732; CHECK-NEXT:    [[CMPINV:%.*]] = icmp sgt i32 0, [[I]]
733; CHECK-NEXT:    [[R:%.*]] = add i32 [[M1]], [[M1]]
734; CHECK-NEXT:    ret i32 [[R]]
735;
736  %cmp = icmp sle i32 0, %i
737  %m1 = select i1 %cmp, i32 %i, i32 0
738  %cmpinv = icmp sgt i32 0, %i
739  %m2 = select i1 %cmpinv, i32 0, i32 %i
740  %r = add i32 %m1, %m2
741  ret i32 %r
742}
743
744; This test is a reproducer for a bug involving inverted min/max selects
745; hashing differently but comparing as equal.  It exhibits such a pair of
746; values, and we run this test with -earlycse-debug-hash which would catch
747; the disagreement and fail if it regressed.  This test also includes a
748; negation of each negation to check for the same issue one level deeper.
749define void @not_not_min(i32* %px, i32* %py, i32* %pout) {
750; CHECK-LABEL: @not_not_min(
751; CHECK-NEXT:    [[X:%.*]] = load volatile i32, i32* [[PX:%.*]], align 4
752; CHECK-NEXT:    [[Y:%.*]] = load volatile i32, i32* [[PY:%.*]], align 4
753; CHECK-NEXT:    [[CMPA:%.*]] = icmp slt i32 [[X]], [[Y]]
754; CHECK-NEXT:    [[CMPB:%.*]] = xor i1 [[CMPA]], true
755; CHECK-NEXT:    [[RA:%.*]] = select i1 [[CMPA]], i32 [[X]], i32 [[Y]]
756; CHECK-NEXT:    store volatile i32 [[RA]], i32* [[POUT:%.*]], align 4
757; CHECK-NEXT:    store volatile i32 [[RA]], i32* [[POUT]], align 4
758; CHECK-NEXT:    store volatile i32 [[RA]], i32* [[POUT]], align 4
759; CHECK-NEXT:    ret void
760;
761  %x = load volatile i32, i32* %px
762  %y = load volatile i32, i32* %py
763  %cmpa = icmp slt i32 %x, %y
764  %cmpb = xor i1 %cmpa, -1
765  %cmpc = xor i1 %cmpb, -1
766  %ra = select i1 %cmpa, i32 %x, i32 %y
767  %rb = select i1 %cmpb, i32 %y, i32 %x
768  %rc = select i1 %cmpc, i32 %x, i32 %y
769  store volatile i32 %ra, i32* %pout
770  store volatile i32 %rb, i32* %pout
771  store volatile i32 %rc, i32* %pout
772
773  ret void
774}
775
776; This would cause an assert/crash because we matched
777; a ValueTracking select pattern that required 'nsw'
778; on an operand, but we remove that flag as part of
779; CSE matching/hashing.
780
781define void @PR41083_1(i32 %span_left, i32 %clip_left) {
782; CHECK-LABEL: @PR41083_1(
783; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CLIP_LEFT:%.*]], [[SPAN_LEFT:%.*]]
784; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[CLIP_LEFT]], [[SPAN_LEFT]]
785; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
786; CHECK-NEXT:    ret void
787;
788  %cmp = icmp sgt i32 %clip_left, %span_left
789  %sub = sub nsw i32 %clip_left, %span_left
790  %cond = select i1 %cmp, i32 %sub, i32 0
791  %cmp83292 = icmp slt i32 %cond, undef
792  %sub2 = sub i32 %clip_left, %span_left
793  %sel2 = select i1 %cmp, i32 %sub2, i32 0
794  ret void
795}
796
797; This would cause an assert/crash because we matched
798; a ValueTracking select pattern that required 'nsw'
799; on an operand, but we remove that flag as part of
800; CSE matching/hashing.
801
802define i32 @PR41083_2(i32 %p) {
803; CHECK-LABEL: @PR41083_2(
804; CHECK-NEXT:    [[S:%.*]] = sub i32 0, [[P:%.*]]
805; CHECK-NEXT:    [[A:%.*]] = ashr exact i32 [[S]], 2
806; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 0, [[A]]
807; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[A]]
808; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
809; CHECK-NEXT:    [[M:%.*]] = mul i32 [[SEL]], [[SUB]]
810; CHECK-NEXT:    ret i32 [[M]]
811;
812  %s = sub i32 0, %p
813  %a = ashr exact i32 %s, 2
814  %cmp = icmp sgt i32 0, %a
815  %sub = sub nsw i32 0, %a
816  %sel = select i1 %cmp, i32 %sub, i32 0
817  %s2 = sub i32 0, %a
818  %m = mul i32 %sel, %s2
819  ret i32 %m
820}
821
822define float @maxnum(float %a, float %b) {
823; CHECK-LABEL: @maxnum(
824; CHECK-NEXT:    [[X:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float [[B:%.*]])
825; CHECK-NEXT:    ret float 1.000000e+00
826;
827  %x = call float @llvm.maxnum.f32(float %a, float %b)
828  %y = call float @llvm.maxnum.f32(float %b, float %a)
829  %r = fdiv nnan float %x, %y
830  ret float %r
831}
832
833define <2 x float> @minnum(<2 x float> %a, <2 x float> %b) {
834; CHECK-LABEL: @minnum(
835; CHECK-NEXT:    [[X:%.*]] = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
836; CHECK-NEXT:    ret <2 x float> <float 1.000000e+00, float 1.000000e+00>
837;
838  %x = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> %a, <2 x float> %b)
839  %y = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> %b, <2 x float> %a)
840  %r = fdiv nnan <2 x float> %x, %y
841  ret <2 x float> %r
842}
843
844define <2 x double> @maximum(<2 x double> %a, <2 x double> %b) {
845; CHECK-LABEL: @maximum(
846; CHECK-NEXT:    [[X:%.*]] = call <2 x double> @llvm.maximum.v2f64(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]])
847; CHECK-NEXT:    ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
848;
849  %x = call fast <2 x double> @llvm.maximum.v2f64(<2 x double> %a, <2 x double> %b)
850  %y = call <2 x double> @llvm.maximum.v2f64(<2 x double> %b, <2 x double> %a)
851  %r = fdiv nnan <2 x double> %x, %y
852  ret <2 x double> %r
853}
854
855define double @minimum(double %a, double %b) {
856; CHECK-LABEL: @minimum(
857; CHECK-NEXT:    [[X:%.*]] = call double @llvm.minimum.f64(double [[A:%.*]], double [[B:%.*]])
858; CHECK-NEXT:    ret double 1.000000e+00
859;
860  %x = call nsz double @llvm.minimum.f64(double %a, double %b)
861  %y = call ninf double @llvm.minimum.f64(double %b, double %a)
862  %r = fdiv nnan double %x, %y
863  ret double %r
864}
865define i16 @sadd_ov(i16 %a, i16 %b) {
866; CHECK-LABEL: @sadd_ov(
867; CHECK-NEXT:    [[X:%.*]] = call { i16, i1 } @llvm.sadd.with.overflow.i16(i16 [[A:%.*]], i16 [[B:%.*]])
868; CHECK-NEXT:    [[X1:%.*]] = extractvalue { i16, i1 } [[X]], 0
869; CHECK-NEXT:    ret i16 [[X1]]
870;
871  %x = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)
872  %y = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %b, i16 %a)
873  %x1 = extractvalue {i16, i1} %x, 0
874  %y1 = extractvalue {i16, i1} %y, 0
875  %o = or i16 %x1, %y1
876  ret i16 %o
877}
878
879define <5 x i65> @uadd_ov(<5 x i65> %a, <5 x i65> %b) {
880; CHECK-LABEL: @uadd_ov(
881; CHECK-NEXT:    [[X:%.*]] = call { <5 x i65>, <5 x i1> } @llvm.uadd.with.overflow.v5i65(<5 x i65> [[A:%.*]], <5 x i65> [[B:%.*]])
882; CHECK-NEXT:    [[X1:%.*]] = extractvalue { <5 x i65>, <5 x i1> } [[X]], 0
883; CHECK-NEXT:    ret <5 x i65> [[X1]]
884;
885  %x = call {<5 x i65>, <5 x i1>} @llvm.uadd.with.overflow.v5i65(<5 x i65> %a, <5 x i65> %b)
886  %y = call {<5 x i65>, <5 x i1>} @llvm.uadd.with.overflow.v5i65(<5 x i65> %b, <5 x i65> %a)
887  %x1 = extractvalue {<5 x i65>, <5 x i1>} %x, 0
888  %y1 = extractvalue {<5 x i65>, <5 x i1>} %y, 0
889  %o = or <5 x i65> %x1, %y1
890  ret <5 x i65> %o
891}
892
893define i37 @smul_ov(i37 %a, i37 %b) {
894; CHECK-LABEL: @smul_ov(
895; CHECK-NEXT:    [[X:%.*]] = call { i37, i1 } @llvm.smul.with.overflow.i37(i37 [[A:%.*]], i37 [[B:%.*]])
896; CHECK-NEXT:    [[X1:%.*]] = extractvalue { i37, i1 } [[X]], 0
897; CHECK-NEXT:    ret i37 [[X1]]
898;
899  %x = call {i37, i1} @llvm.smul.with.overflow.i37(i37 %a, i37 %b)
900  %y = call {i37, i1} @llvm.smul.with.overflow.i37(i37 %b, i37 %a)
901  %x1 = extractvalue {i37, i1} %x, 0
902  %y1 = extractvalue {i37, i1} %y, 0
903  %o = or i37 %x1, %y1
904  ret i37 %o
905}
906
907define <2 x i31> @umul_ov(<2 x i31> %a, <2 x i31> %b) {
908; CHECK-LABEL: @umul_ov(
909; CHECK-NEXT:    [[X:%.*]] = call { <2 x i31>, <2 x i1> } @llvm.umul.with.overflow.v2i31(<2 x i31> [[A:%.*]], <2 x i31> [[B:%.*]])
910; CHECK-NEXT:    [[X1:%.*]] = extractvalue { <2 x i31>, <2 x i1> } [[X]], 0
911; CHECK-NEXT:    ret <2 x i31> [[X1]]
912;
913  %x = call {<2 x i31>, <2 x i1>} @llvm.umul.with.overflow.v2i31(<2 x i31> %a, <2 x i31> %b)
914  %y = call {<2 x i31>, <2 x i1>} @llvm.umul.with.overflow.v2i31(<2 x i31> %b, <2 x i31> %a)
915  %x1 = extractvalue {<2 x i31>, <2 x i1>} %x, 0
916  %y1 = extractvalue {<2 x i31>, <2 x i1>} %y, 0
917  %o = or <2 x i31> %x1, %y1
918  ret <2 x i31> %o
919}
920
921define i64 @sadd_sat(i64 %a, i64 %b) {
922; CHECK-LABEL: @sadd_sat(
923; CHECK-NEXT:    [[X:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
924; CHECK-NEXT:    ret i64 [[X]]
925;
926  %x = call i64 @llvm.sadd.sat.i64(i64 %a, i64 %b)
927  %y = call i64 @llvm.sadd.sat.i64(i64 %b, i64 %a)
928  %o = or i64 %x, %y
929  ret i64 %o
930}
931
932define <2 x i64> @uadd_sat(<2 x i64> %a, <2 x i64> %b) {
933; CHECK-LABEL: @uadd_sat(
934; CHECK-NEXT:    [[X:%.*]] = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> [[A:%.*]], <2 x i64> [[B:%.*]])
935; CHECK-NEXT:    ret <2 x i64> [[X]]
936;
937  %x = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %a, <2 x i64> %b)
938  %y = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %b, <2 x i64> %a)
939  %o = or <2 x i64> %x, %y
940  ret <2 x i64> %o
941}
942
943define <2 x i64> @smax(<2 x i64> %a, <2 x i64> %b) {
944; CHECK-LABEL: @smax(
945; CHECK-NEXT:    [[X:%.*]] = call <2 x i64> @llvm.smax.v2i64(<2 x i64> [[A:%.*]], <2 x i64> [[B:%.*]])
946; CHECK-NEXT:    ret <2 x i64> [[X]]
947;
948  %x = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %a, <2 x i64> %b)
949  %y = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %b, <2 x i64> %a)
950  %o = or <2 x i64> %x, %y
951  ret <2 x i64> %o
952}
953
954define i4 @smin(i4 %a, i4 %b) {
955; CHECK-LABEL: @smin(
956; CHECK-NEXT:    [[X:%.*]] = call i4 @llvm.smin.i4(i4 [[A:%.*]], i4 [[B:%.*]])
957; CHECK-NEXT:    ret i4 [[X]]
958;
959  %x = call i4 @llvm.smin.i4(i4 %a, i4 %b)
960  %y = call i4 @llvm.smin.i4(i4 %b, i4 %a)
961  %o = or i4 %x, %y
962  ret i4 %o
963}
964
965define i67 @umax(i67 %a, i67 %b) {
966; CHECK-LABEL: @umax(
967; CHECK-NEXT:    [[X:%.*]] = call i67 @llvm.umax.i67(i67 [[A:%.*]], i67 [[B:%.*]])
968; CHECK-NEXT:    ret i67 [[X]]
969;
970  %x = call i67 @llvm.umax.i67(i67 %a, i67 %b)
971  %y = call i67 @llvm.umax.i67(i67 %b, i67 %a)
972  %o = or i67 %x, %y
973  ret i67 %o
974}
975
976define <3 x i17> @umin(<3 x i17> %a, <3 x i17> %b) {
977; CHECK-LABEL: @umin(
978; CHECK-NEXT:    [[X:%.*]] = call <3 x i17> @llvm.umin.v3i17(<3 x i17> [[A:%.*]], <3 x i17> [[B:%.*]])
979; CHECK-NEXT:    ret <3 x i17> [[X]]
980;
981  %x = call <3 x i17> @llvm.umin.v3i17(<3 x i17> %a, <3 x i17> %b)
982  %y = call <3 x i17> @llvm.umin.v3i17(<3 x i17> %b, <3 x i17> %a)
983  %o = or <3 x i17> %x, %y
984  ret <3 x i17> %o
985}
986
987; Negative test - mismatched intrinsics
988
989define i4 @smin_umin(i4 %a, i4 %b) {
990; CHECK-LABEL: @smin_umin(
991; CHECK-NEXT:    [[X:%.*]] = call i4 @llvm.smin.i4(i4 [[A:%.*]], i4 [[B:%.*]])
992; CHECK-NEXT:    [[Y:%.*]] = call i4 @llvm.umin.i4(i4 [[B]], i4 [[A]])
993; CHECK-NEXT:    [[O:%.*]] = or i4 [[X]], [[Y]]
994; CHECK-NEXT:    ret i4 [[O]]
995;
996  %x = call i4 @llvm.smin.i4(i4 %a, i4 %b)
997  %y = call i4 @llvm.umin.i4(i4 %b, i4 %a)
998  %o = or i4 %x, %y
999  ret i4 %o
1000}
1001
1002; TODO: handle >2 args
1003
1004define i16 @smul_fix(i16 %a, i16 %b) {
1005; CHECK-LABEL: @smul_fix(
1006; CHECK-NEXT:    [[X:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 3)
1007; CHECK-NEXT:    [[Y:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[B]], i16 [[A]], i32 3)
1008; CHECK-NEXT:    [[O:%.*]] = or i16 [[X]], [[Y]]
1009; CHECK-NEXT:    ret i16 [[O]]
1010;
1011  %x = call i16 @llvm.smul.fix.i16(i16 %a, i16 %b, i32 3)
1012  %y = call i16 @llvm.smul.fix.i16(i16 %b, i16 %a, i32 3)
1013  %o = or i16 %x, %y
1014  ret i16 %o
1015}
1016
1017; TODO: handle >2 args
1018
1019define i16 @umul_fix(i16 %a, i16 %b, i32 %s) {
1020; CHECK-LABEL: @umul_fix(
1021; CHECK-NEXT:    [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1)
1022; CHECK-NEXT:    [[Y:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[B]], i16 [[A]], i32 1)
1023; CHECK-NEXT:    [[O:%.*]] = or i16 [[X]], [[Y]]
1024; CHECK-NEXT:    ret i16 [[O]]
1025;
1026  %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1)
1027  %y = call i16 @llvm.umul.fix.i16(i16 %b, i16 %a, i32 1)
1028  %o = or i16 %x, %y
1029  ret i16 %o
1030}
1031
1032; TODO: handle >2 args
1033
1034define <3 x i16> @smul_fix_sat(<3 x i16> %a, <3 x i16> %b) {
1035; CHECK-LABEL: @smul_fix_sat(
1036; CHECK-NEXT:    [[X:%.*]] = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> [[A:%.*]], <3 x i16> [[B:%.*]], i32 2)
1037; CHECK-NEXT:    [[Y:%.*]] = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> [[B]], <3 x i16> [[A]], i32 2)
1038; CHECK-NEXT:    [[O:%.*]] = or <3 x i16> [[X]], [[Y]]
1039; CHECK-NEXT:    ret <3 x i16> [[O]]
1040;
1041  %x = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> %a, <3 x i16> %b, i32 2)
1042  %y = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> %b, <3 x i16> %a, i32 2)
1043  %o = or <3 x i16> %x, %y
1044  ret <3 x i16> %o
1045}
1046
1047; TODO: handle >2 args
1048
1049define <3 x i16> @umul_fix_sat(<3 x i16> %a, <3 x i16> %b) {
1050; CHECK-LABEL: @umul_fix_sat(
1051; CHECK-NEXT:    [[X:%.*]] = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> [[A:%.*]], <3 x i16> [[B:%.*]], i32 3)
1052; CHECK-NEXT:    [[Y:%.*]] = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> [[B]], <3 x i16> [[A]], i32 3)
1053; CHECK-NEXT:    [[O:%.*]] = or <3 x i16> [[X]], [[Y]]
1054; CHECK-NEXT:    ret <3 x i16> [[O]]
1055;
1056  %x = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> %a, <3 x i16> %b, i32 3)
1057  %y = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> %b, <3 x i16> %a, i32 3)
1058  %o = or <3 x i16> %x, %y
1059  ret <3 x i16> %o
1060}
1061
1062define i16 @umul_smul_fix(i16 %a, i16 %b, i32 %s) {
1063; CHECK-LABEL: @umul_smul_fix(
1064; CHECK-NEXT:    [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1)
1065; CHECK-NEXT:    [[Y:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[B]], i16 [[A]], i32 1)
1066; CHECK-NEXT:    [[O:%.*]] = or i16 [[X]], [[Y]]
1067; CHECK-NEXT:    ret i16 [[O]]
1068;
1069  %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1)
1070  %y = call i16 @llvm.smul.fix.i16(i16 %b, i16 %a, i32 1)
1071  %o = or i16 %x, %y
1072  ret i16 %o
1073}
1074
1075define i16 @umul_fix_scale(i16 %a, i16 %b, i32 %s) {
1076; CHECK-LABEL: @umul_fix_scale(
1077; CHECK-NEXT:    [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1)
1078; CHECK-NEXT:    [[Y:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[B]], i16 [[A]], i32 2)
1079; CHECK-NEXT:    [[O:%.*]] = or i16 [[X]], [[Y]]
1080; CHECK-NEXT:    ret i16 [[O]]
1081;
1082  %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1)
1083  %y = call i16 @llvm.umul.fix.i16(i16 %b, i16 %a, i32 2)
1084  %o = or i16 %x, %y
1085  ret i16 %o
1086}
1087
1088; TODO: handle >2 args
1089
1090define float @fma(float %a, float %b, float %c) {
1091; CHECK-LABEL: @fma(
1092; CHECK-NEXT:    [[X:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[C:%.*]])
1093; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[C]])
1094; CHECK-NEXT:    [[R:%.*]] = fdiv nnan float [[X]], [[Y]]
1095; CHECK-NEXT:    ret float [[R]]
1096;
1097  %x = call float @llvm.fma.f32(float %a, float %b, float %c)
1098  %y = call float @llvm.fma.f32(float %b, float %a, float %c)
1099  %r = fdiv nnan float %x, %y
1100  ret float %r
1101}
1102
1103define float @fma_different_add_ops(float %a, float %b, float %c, float %d) {
1104; CHECK-LABEL: @fma_different_add_ops(
1105; CHECK-NEXT:    [[X:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[C:%.*]])
1106; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[D:%.*]])
1107; CHECK-NEXT:    [[R:%.*]] = fdiv nnan float [[X]], [[Y]]
1108; CHECK-NEXT:    ret float [[R]]
1109;
1110  %x = call float @llvm.fma.f32(float %a, float %b, float %c)
1111  %y = call float @llvm.fma.f32(float %b, float %a, float %d)
1112  %r = fdiv nnan float %x, %y
1113  ret float %r
1114}
1115
1116; TODO: handle >2 args
1117
1118define <2 x double> @fmuladd(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
1119; CHECK-LABEL: @fmuladd(
1120; CHECK-NEXT:    [[X:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]], <2 x double> [[C:%.*]])
1121; CHECK-NEXT:    [[Y:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[B]], <2 x double> [[A]], <2 x double> [[C]])
1122; CHECK-NEXT:    [[R:%.*]] = fdiv nnan <2 x double> [[X]], [[Y]]
1123; CHECK-NEXT:    ret <2 x double> [[R]]
1124;
1125  %x = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c)
1126  %y = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> %a, <2 x double> %c)
1127  %r = fdiv nnan <2 x double> %x, %y
1128  ret <2 x double> %r
1129}
1130
1131declare float @llvm.maxnum.f32(float, float)
1132declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>)
1133declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
1134declare double @llvm.minimum.f64(double, double)
1135
1136declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16)
1137declare {<5 x i65>, <5 x i1>} @llvm.uadd.with.overflow.v5i65(<5 x i65>, <5 x i65>)
1138declare {i37, i1} @llvm.smul.with.overflow.i37(i37, i37)
1139declare {<2 x i31>, <2 x i1>} @llvm.umul.with.overflow.v2i31(<2 x i31>, <2 x i31>)
1140declare i64 @llvm.sadd.sat.i64(i64, i64)
1141declare <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64>, <2 x i64>)
1142
1143declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>)
1144declare i4 @llvm.smin.i4(i4, i4)
1145declare i4 @llvm.umin.i4(i4, i4)
1146declare i67 @llvm.umax.i67(i67, i67)
1147declare <3 x i17> @llvm.umin.v3i17(<3 x i17>, <3 x i17>)
1148
1149declare i16 @llvm.smul.fix.i16(i16, i16, i32)
1150declare i16 @llvm.umul.fix.i16(i16, i16, i32)
1151declare <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16>, <3 x i16>, i32)
1152declare <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16>, <3 x i16>, i32)
1153
1154declare float @llvm.fma.f32(float, float, float)
1155declare <2 x double> @llvm.fmuladd.v2f64(<2 x double>, <2 x double>, <2 x double>)
1156