xref: /llvm-project/llvm/test/Transforms/InstCombine/max-of-nots.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4define <2 x i32> @umin_of_nots(<2 x i32> %x, <2 x i32> %y) {
5; CHECK-LABEL: @umin_of_nots(
6; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
7; CHECK-NEXT:    [[MIN:%.*]] = xor <2 x i32> [[TMP1]], splat (i32 -1)
8; CHECK-NEXT:    ret <2 x i32> [[MIN]]
9;
10  %notx = xor <2 x i32> %x, <i32 -1, i32 -1>
11  %noty = xor <2 x i32> %y, <i32 -1, i32 -1>
12  %cmp = icmp ult <2 x i32> %notx, %noty
13  %min = select <2 x i1> %cmp, <2 x i32> %notx, <2 x i32> %noty
14  ret <2 x i32> %min
15}
16
17define <2 x i32> @smin_of_nots(<2 x i32> %x, <2 x i32> %y) {
18; CHECK-LABEL: @smin_of_nots(
19; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
20; CHECK-NEXT:    [[MIN:%.*]] = xor <2 x i32> [[TMP1]], splat (i32 -1)
21; CHECK-NEXT:    ret <2 x i32> [[MIN]]
22;
23  %notx = xor <2 x i32> %x, <i32 -1, i32 -1>
24  %noty = xor <2 x i32> %y, <i32 -1, i32 -1>
25  %cmp = icmp sle <2 x i32> %notx, %noty
26  %min = select <2 x i1> %cmp, <2 x i32> %notx, <2 x i32> %noty
27  ret <2 x i32> %min
28}
29
30define i32 @compute_min_2(i32 %x, i32 %y) {
31; CHECK-LABEL: @compute_min_2(
32; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
33; CHECK-NEXT:    ret i32 [[TMP1]]
34;
35  %not_x = sub i32 -1, %x
36  %not_y = sub i32 -1, %y
37  %cmp = icmp sgt i32 %not_x, %not_y
38  %not_min = select i1 %cmp, i32 %not_x, i32 %not_y
39  %min = sub i32 -1, %not_min
40  ret i32 %min
41}
42
43declare void @extra_use(i8)
44define i8 @umin_not_1_extra_use(i8 %x, i8 %y) {
45; CHECK-LABEL: @umin_not_1_extra_use(
46; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
47; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X]])
48; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP1]], -1
49; CHECK-NEXT:    call void @extra_use(i8 [[NX]])
50; CHECK-NEXT:    ret i8 [[MINXY]]
51;
52  %nx = xor i8 %x, -1
53  %ny = xor i8 %y, -1
54  %cmpxy = icmp ult i8 %nx, %ny
55  %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
56  call void @extra_use(i8 %nx)
57  ret i8 %minxy
58}
59
60define i8 @umin_not_2_extra_use(i8 %x, i8 %y) {
61; CHECK-LABEL: @umin_not_2_extra_use(
62; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
63; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
64; CHECK-NEXT:    [[MINXY:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])
65; CHECK-NEXT:    call void @extra_use(i8 [[NX]])
66; CHECK-NEXT:    call void @extra_use(i8 [[NY]])
67; CHECK-NEXT:    ret i8 [[MINXY]]
68;
69  %nx = xor i8 %x, -1
70  %ny = xor i8 %y, -1
71  %cmpxy = icmp ult i8 %nx, %ny
72  %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
73  call void @extra_use(i8 %nx)
74  call void @extra_use(i8 %ny)
75  ret i8 %minxy
76}
77
78; PR35834 - https://bugs.llvm.org/show_bug.cgi?id=35834
79
80define i8 @umin3_not(i8 %x, i8 %y, i8 %z) {
81; CHECK-LABEL: @umin3_not(
82; CHECK-NEXT:    [[MINMAXOP:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
83; CHECK-NEXT:    [[R_V:%.*]] = call i8 @llvm.umax.i8(i8 [[MINMAXOP]], i8 [[Z:%.*]])
84; CHECK-NEXT:    [[R:%.*]] = xor i8 [[R_V]], -1
85; CHECK-NEXT:    ret i8 [[R]]
86;
87  %nx = xor i8 %x, -1
88  %ny = xor i8 %y, -1
89  %nz = xor i8 %z, -1
90  %cmpyx = icmp ult i8 %y, %x
91  %cmpxz = icmp ult i8 %nx, %nz
92  %minxz = select i1 %cmpxz, i8 %nx, i8 %nz
93  %cmpyz = icmp ult i8 %ny, %nz
94  %minyz = select i1 %cmpyz, i8 %ny, i8 %nz
95  %r = select i1 %cmpyx, i8 %minxz, i8 %minyz
96  ret i8 %r
97}
98
99; PR35875 - https://bugs.llvm.org/show_bug.cgi?id=35875
100
101define i8 @umin3_not_more_uses(i8 %x, i8 %y, i8 %z) {
102; CHECK-LABEL: @umin3_not_more_uses(
103; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
104; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
105; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])
106; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[Z:%.*]], i8 [[TMP1]])
107; CHECK-NEXT:    [[R:%.*]] = xor i8 [[TMP2]], -1
108; CHECK-NEXT:    call void @extra_use(i8 [[NX]])
109; CHECK-NEXT:    call void @extra_use(i8 [[NY]])
110; CHECK-NEXT:    ret i8 [[R]]
111;
112  %nx = xor i8 %x, -1
113  %ny = xor i8 %y, -1
114  %nz = xor i8 %z, -1
115  %cmpxz = icmp ult i8 %nx, %nz
116  %minxz = select i1 %cmpxz, i8 %nx, i8 %nz
117  %cmpyz = icmp ult i8 %ny, %nz
118  %minyz = select i1 %cmpyz, i8 %ny, i8 %nz
119  %cmpyx = icmp ult i8 %y, %x
120  %r = select i1 %cmpyx, i8 %minxz, i8 %minyz
121  call void @extra_use(i8 %nx)
122  call void @extra_use(i8 %ny)
123  ret i8 %r
124}
125
126declare void @use8(i8)
127
128define i8 @umin3_not_all_ops_extra_uses(i8 %x, i8 %y, i8 %z) {
129; CHECK-LABEL: @umin3_not_all_ops_extra_uses(
130; CHECK-NEXT:    [[XN:%.*]] = xor i8 [[X:%.*]], -1
131; CHECK-NEXT:    [[YN:%.*]] = xor i8 [[Y:%.*]], -1
132; CHECK-NEXT:    [[ZN:%.*]] = xor i8 [[Z:%.*]], -1
133; CHECK-NEXT:    [[MINXZ:%.*]] = call i8 @llvm.umin.i8(i8 [[XN]], i8 [[ZN]])
134; CHECK-NEXT:    [[MINXYZ:%.*]] = call i8 @llvm.umin.i8(i8 [[MINXZ]], i8 [[YN]])
135; CHECK-NEXT:    call void @use8(i8 [[XN]])
136; CHECK-NEXT:    call void @use8(i8 [[YN]])
137; CHECK-NEXT:    call void @use8(i8 [[ZN]])
138; CHECK-NEXT:    ret i8 [[MINXYZ]]
139;
140  %xn = xor i8 %x, -1
141  %yn = xor i8 %y, -1
142  %zn = xor i8 %z, -1
143  %cmpxz = icmp ult i8 %xn, %zn
144  %minxz = select i1 %cmpxz, i8 %xn, i8 %zn
145  %cmpxyz = icmp ult i8 %minxz, %yn
146  %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn
147  call void @use8(i8 %xn)
148  call void @use8(i8 %yn)
149  call void @use8(i8 %zn)
150  ret i8 %minxyz
151}
152
153define i32 @compute_min_3(i32 %x, i32 %y, i32 %z) {
154; CHECK-LABEL: @compute_min_3(
155; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
156; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP1]], i32 [[Z:%.*]])
157; CHECK-NEXT:    ret i32 [[TMP2]]
158;
159  %not_x = sub i32 -1, %x
160  %not_y = sub i32 -1, %y
161  %not_z = sub i32 -1, %z
162  %cmp_1 = icmp sgt i32 %not_x, %not_y
163  %not_min_1 = select i1 %cmp_1, i32 %not_x, i32 %not_y
164  %cmp_2 = icmp sgt i32 %not_min_1, %not_z
165  %not_min_2 = select i1 %cmp_2, i32 %not_min_1, i32 %not_z
166  %min = sub i32 -1, %not_min_2
167  ret i32 %min
168}
169
170; Don't increase the critical path by moving the 'not' op after the 'select'.
171
172define i32 @compute_min_arithmetic(i32 %x, i32 %y) {
173; CHECK-LABEL: @compute_min_arithmetic(
174; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -4
175; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[TMP1]])
176; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor i32 [[TMP2]], -1
177; CHECK-NEXT:    ret i32 [[NOT_MIN]]
178;
179  %not_value = sub i32 3, %x
180  %not_y = sub i32 -1, %y
181  %cmp = icmp sgt i32 %not_value, %not_y
182  %not_min = select i1 %cmp, i32 %not_value, i32 %not_y
183  ret i32 %not_min
184}
185
186declare void @fake_use(i32)
187
188define i32 @compute_min_pessimization(i32 %x, i32 %y) {
189; CHECK-LABEL: @compute_min_pessimization(
190; CHECK-NEXT:    [[NOT_VALUE:%.*]] = sub i32 3, [[X:%.*]]
191; CHECK-NEXT:    call void @fake_use(i32 [[NOT_VALUE]])
192; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X]], -4
193; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[TMP1]])
194; CHECK-NEXT:    ret i32 [[MIN]]
195;
196  %not_value = sub i32 3, %x
197  call void @fake_use(i32 %not_value)
198  %not_y = sub i32 -1, %y
199  %cmp = icmp sgt i32 %not_value, %not_y
200  %not_min = select i1 %cmp, i32 %not_value, i32 %not_y
201  %min = sub i32 -1, %not_min
202  ret i32 %min
203}
204
205define i32 @max_of_nots(i32 %x, i32 %y) {
206; CHECK-LABEL: @max_of_nots(
207; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 0)
208; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP1]], i32 [[X:%.*]])
209; CHECK-NEXT:    [[SMAX96:%.*]] = xor i32 [[TMP2]], -1
210; CHECK-NEXT:    ret i32 [[SMAX96]]
211;
212  %c0 = icmp sgt i32 %y, 0
213  %xor_y = xor i32 %y, -1
214  %s0 = select i1 %c0, i32 %xor_y, i32 -1
215  %xor_x = xor i32 %x, -1
216  %c1 = icmp slt i32 %s0, %xor_x
217  %smax96 = select i1 %c1, i32 %xor_x, i32 %s0
218  ret i32 %smax96
219}
220
221  ; negative test case (i.e. can not simplify) : ABS(MIN(NOT x,y))
222define i32 @abs_of_min_of_not(i32 %x, i32 %y) {
223; CHECK-LABEL: @abs_of_min_of_not(
224; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 -3, [[Y:%.*]]
225; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 [[TMP1]])
226; CHECK-NEXT:    [[MIN:%.*]] = xor i32 [[TMP2]], -1
227; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[MIN]], i1 false)
228; CHECK-NEXT:    ret i32 [[ABS]]
229;
230
231  %xord = xor i32 %x, -1
232  %yadd = add i32 %y, 2
233  %cond.i = icmp sge i32 %yadd, %xord
234  %min = select i1 %cond.i, i32 %xord, i32 %yadd
235  %cmp2 = icmp sgt i32 %min, -1
236  %sub = sub i32 0, %min
237  %abs = select i1 %cmp2, i32 %min, i32 %sub
238  ret i32  %abs
239}
240
241define <2 x i32> @max_of_nots_vec(<2 x i32> %x, <2 x i32> %y) {
242; CHECK-LABEL: @max_of_nots_vec(
243; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> zeroinitializer)
244; CHECK-NEXT:    [[TMP2:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[TMP1]], <2 x i32> [[X:%.*]])
245; CHECK-NEXT:    [[SMAX96:%.*]] = xor <2 x i32> [[TMP2]], splat (i32 -1)
246; CHECK-NEXT:    ret <2 x i32> [[SMAX96]]
247;
248  %c0 = icmp sgt <2 x i32> %y, zeroinitializer
249  %xor_y = xor <2 x i32> %y, <i32 -1, i32 -1>
250  %s0 = select <2 x i1> %c0, <2 x i32> %xor_y, <2 x i32> <i32 -1, i32 -1>
251  %xor_x = xor <2 x i32> %x, <i32 -1, i32 -1>
252  %c1 = icmp slt <2 x i32> %s0, %xor_x
253  %smax96 = select <2 x i1> %c1, <2 x i32> %xor_x, <2 x i32> %s0
254  ret <2 x i32> %smax96
255}
256
257define <2 x i37> @max_of_nots_weird_type_vec(<2 x i37> %x, <2 x i37> %y) {
258; CHECK-LABEL: @max_of_nots_weird_type_vec(
259; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i37> @llvm.smax.v2i37(<2 x i37> [[Y:%.*]], <2 x i37> zeroinitializer)
260; CHECK-NEXT:    [[TMP2:%.*]] = call <2 x i37> @llvm.smin.v2i37(<2 x i37> [[TMP1]], <2 x i37> [[X:%.*]])
261; CHECK-NEXT:    [[SMAX96:%.*]] = xor <2 x i37> [[TMP2]], splat (i37 -1)
262; CHECK-NEXT:    ret <2 x i37> [[SMAX96]]
263;
264  %c0 = icmp sgt <2 x i37> %y, zeroinitializer
265  %xor_y = xor <2 x i37> %y, <i37 -1, i37 -1>
266  %s0 = select <2 x i1> %c0, <2 x i37> %xor_y, <2 x i37> <i37 -1, i37 -1>
267  %xor_x = xor <2 x i37> %x, <i37 -1, i37 -1>
268  %c1 = icmp slt <2 x i37> %s0, %xor_x
269  %smax96 = select <2 x i1> %c1, <2 x i37> %xor_x, <2 x i37> %s0
270  ret <2 x i37> %smax96
271}
272
273; max(min(%a, -1), -1) == -1
274define i32 @max_of_min(i32 %a) {
275; CHECK-LABEL: @max_of_min(
276; CHECK-NEXT:    ret i32 -1
277;
278  %not_a = xor i32 %a, -1
279  %c0 = icmp sgt i32 %a, 0
280  %s0 = select i1 %c0, i32 %not_a, i32 -1
281  %c1 = icmp sgt i32 %s0, -1
282  %s1 = select i1 %c1, i32 %s0, i32 -1
283  ret i32 %s1
284}
285
286; max(min(%a, -1), -1) == -1 (swap predicate and select ops)
287define i32 @max_of_min_swap(i32 %a) {
288; CHECK-LABEL: @max_of_min_swap(
289; CHECK-NEXT:    ret i32 -1
290;
291  %not_a = xor i32 %a, -1
292  %c0 = icmp slt i32 %a, 0
293  %s0 = select i1 %c0, i32 -1, i32 %not_a
294  %c1 = icmp sgt i32 %s0, -1
295  %s1 = select i1 %c1, i32 %s0, i32 -1
296  ret i32 %s1
297}
298
299; min(max(%a, -1), -1) == -1
300define i32 @min_of_max(i32 %a) {
301; CHECK-LABEL: @min_of_max(
302; CHECK-NEXT:    ret i32 -1
303;
304  %not_a = xor i32 %a, -1
305  %c0 = icmp slt i32 %a, 0
306  %s0 = select i1 %c0, i32 %not_a, i32 -1
307  %c1 = icmp slt i32 %s0, -1
308  %s1 = select i1 %c1, i32 %s0, i32 -1
309  ret i32 %s1
310}
311
312; min(max(%a, -1), -1) == -1 (swap predicate and select ops)
313define i32 @min_of_max_swap(i32 %a) {
314; CHECK-LABEL: @min_of_max_swap(
315; CHECK-NEXT:    ret i32 -1
316;
317  %not_a = xor i32 %a, -1
318  %c0 = icmp sgt i32 %a, 0
319  %s0 = select i1 %c0, i32 -1, i32 %not_a
320  %c1 = icmp slt i32 %s0, -1
321  %s1 = select i1 %c1, i32 %s0, i32 -1
322  ret i32 %s1
323}
324
325define <2 x i32> @max_of_min_vec(<2 x i32> %a) {
326; CHECK-LABEL: @max_of_min_vec(
327; CHECK-NEXT:    ret <2 x i32> splat (i32 -1)
328;
329  %not_a = xor <2 x i32> %a, <i32 -1, i32 -1>
330  %c0 = icmp sgt <2 x i32> %a, zeroinitializer
331  %s0 = select <2 x i1> %c0, <2 x i32> %not_a, <2 x i32> <i32 -1, i32 -1>
332  %c1 = icmp sgt <2 x i32> %s0, <i32 -1, i32 -1>
333  %s1 = select <2 x i1> %c1, <2 x i32> %s0, <2 x i32> <i32 -1, i32 -1>
334  ret <2 x i32> %s1
335}
336
337declare void @use(i8, i8, i8, i8)
338
339define void @cmyk(i8 %r, i8 %g, i8 %b) {
340; CHECK-LABEL: @cmyk(
341; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
342; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
343; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
344; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
345; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
346; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
347; CHECK-NEXT:    call void @use(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
348; CHECK-NEXT:    ret void
349;
350  %notr = xor i8 %r, -1
351  %notg = xor i8 %g, -1
352  %notb = xor i8 %b, -1
353  %cmp_gr = icmp slt i8 %g, %r
354  %cmp_br = icmp slt i8 %notr, %notb
355  %min_br = select i1 %cmp_br, i8 %notr, i8 %notb
356  %cmp_gb = icmp slt i8 %notg, %notb
357  %min_gb = select i1 %cmp_gb, i8 %notg, i8 %notb
358  %k = select i1 %cmp_gr, i8 %min_br, i8 %min_gb
359  %ck = sub i8 %notr, %k
360  %mk = sub i8 %notg, %k
361  %yk = sub i8 %notb, %k
362  call void @use(i8 %ck, i8 %mk, i8 %yk, i8 %k)
363  ret void
364}
365
366define void @cmyk2(i8 %r, i8 %g, i8 %b) {
367; CHECK-LABEL: @cmyk2(
368; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
369; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
370; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
371; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
372; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
373; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
374; CHECK-NEXT:    call void @use(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
375; CHECK-NEXT:    ret void
376;
377  %notr = xor i8 %r, -1
378  %notg = xor i8 %g, -1
379  %notb = xor i8 %b, -1
380  %cmp_gr = icmp slt i8 %g, %r
381  %cmp_br = icmp slt i8 %b, %r
382  %min_br = select i1 %cmp_br, i8 %notr, i8 %notb
383  %cmp_bg = icmp slt i8 %b, %g
384  %min_bg = select i1 %cmp_bg, i8 %notg, i8 %notb
385  %k = select i1 %cmp_gr, i8 %min_br, i8 %min_bg
386  %ck = sub i8 %notr, %k
387  %mk = sub i8 %notg, %k
388  %yk = sub i8 %notb, %k
389  call void @use(i8 %ck, i8 %mk, i8 %yk, i8 %k)
390  ret void
391}
392
393define void @cmyk3(i8 %r, i8 %g, i8 %b) {
394; CHECK-LABEL: @cmyk3(
395; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
396; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
397; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
398; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
399; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
400; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
401; CHECK-NEXT:    call void @use(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
402; CHECK-NEXT:    ret void
403;
404  %notr = xor i8 %r, -1
405  %notg = xor i8 %g, -1
406  %notb = xor i8 %b, -1
407  %cmp_gr = icmp slt i8 %g, %r
408  %cmp_br = icmp sgt i8 %r, %b
409  %min_br = select i1 %cmp_br, i8 %notr, i8 %notb
410  %cmp_bg = icmp slt i8 %b, %g
411  %min_bg = select i1 %cmp_bg, i8 %notg, i8 %notb
412  %k = select i1 %cmp_gr, i8 %min_br, i8 %min_bg
413  %ck = sub i8 %notr, %k
414  %mk = sub i8 %notg, %k
415  %yk = sub i8 %notb, %k
416  call void @use(i8 %ck, i8 %mk, i8 %yk, i8 %k)
417  ret void
418}
419
420define void @cmyk4(i8 %r, i8 %g, i8 %b) {
421; CHECK-LABEL: @cmyk4(
422; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
423; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
424; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
425; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
426; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
427; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
428; CHECK-NEXT:    call void @use(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
429; CHECK-NEXT:    ret void
430;
431  %notr = xor i8 %r, -1
432  %notg = xor i8 %g, -1
433  %notb = xor i8 %b, -1
434  %cmp_gr = icmp slt i8 %g, %r
435  %cmp_br = icmp sgt i8 %r, %b
436  %min_br = select i1 %cmp_br, i8 %notr, i8 %notb
437  %cmp_bg = icmp sgt i8 %g, %b
438  %min_bg = select i1 %cmp_bg, i8 %notg, i8 %notb
439  %k = select i1 %cmp_gr, i8 %min_br, i8 %min_bg
440  %ck = sub i8 %notr, %k
441  %mk = sub i8 %notg, %k
442  %yk = sub i8 %notb, %k
443  call void @use(i8 %ck, i8 %mk, i8 %yk, i8 %k)
444  ret void
445}
446
447define void @cmyk5(i8 %r, i8 %g, i8 %b) {
448; CHECK-LABEL: @cmyk5(
449; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
450; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
451; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
452; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
453; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
454; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
455; CHECK-NEXT:    call void @use(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
456; CHECK-NEXT:    ret void
457;
458  %notr = xor i8 %r, -1
459  %notg = xor i8 %g, -1
460  %notb = xor i8 %b, -1
461  %cmp_gr = icmp sgt i8 %r, %g
462  %cmp_br = icmp sgt i8 %r, %b
463  %min_br = select i1 %cmp_br, i8 %notr, i8 %notb
464  %cmp_bg = icmp sgt i8 %g, %b
465  %min_bg = select i1 %cmp_bg, i8 %notg, i8 %notb
466  %k = select i1 %cmp_gr, i8 %min_br, i8 %min_bg
467  %ck = sub i8 %notr, %k
468  %mk = sub i8 %notg, %k
469  %yk = sub i8 %notb, %k
470  call void @use(i8 %ck, i8 %mk, i8 %yk, i8 %k)
471  ret void
472}
473
474define void @cmyk6(i8 %r, i8 %g, i8 %b) {
475; CHECK-LABEL: @cmyk6(
476; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
477; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]])
478; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
479; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
480; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
481; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
482; CHECK-NEXT:    tail call void @use(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
483; CHECK-NEXT:    ret void
484;
485  %notr = xor i8 %r, -1
486  %notg = xor i8 %g, -1
487  %notb = xor i8 %b, -1
488  %cmp_gr = icmp ult i8 %g, %r
489  %cmp_br = icmp ult i8 %b, %r
490  %sel_rb = select i1 %cmp_br, i8 %notr, i8 %notb
491  %cmp_bg = icmp ult i8 %b, %g
492  %sel_gb = select i1 %cmp_bg, i8 %notg, i8 %notb
493  %k = select i1 %cmp_gr, i8 %sel_rb, i8 %sel_gb
494  %ck = sub i8 %notr, %k
495  %mk = sub i8 %notg, %k
496  %yk = sub i8 %notb, %k
497  tail call void @use(i8 %ck, i8 %mk, i8 %yk, i8 %k)
498  ret void
499}
500