xref: /llvm-project/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll (revision 0ce193708cb682f3ad742ad909d8a5346a505ac7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4define i32 @smax_of_smax_smin_commute0(i32 %x, i32 %y) {
5; CHECK-LABEL: @smax_of_smax_smin_commute0(
6; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
7; CHECK-NEXT:    ret i32 [[MAX]]
8;
9  %cmp1 = icmp slt i32 %x, %y
10  %min = select i1 %cmp1, i32 %x, i32 %y
11  %cmp2 = icmp slt i32 %y, %x
12  %max = select i1 %cmp2, i32 %x, i32 %y
13  %cmp3 = icmp sgt i32 %max, %min
14  %r = select i1 %cmp3, i32 %max, i32 %min
15  ret i32 %r
16}
17
18define i32 @smax_of_smax_smin_commute1(i32 %x, i32 %y) {
19; CHECK-LABEL: @smax_of_smax_smin_commute1(
20; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
21; CHECK-NEXT:    ret i32 [[MAX]]
22;
23  %cmp1 = icmp sgt i32 %x, %y
24  %min = select i1 %cmp1, i32 %y, i32 %x
25  %cmp2 = icmp sgt i32 %x, %y
26  %max = select i1 %cmp2, i32 %x, i32 %y
27  %cmp3 = icmp sgt i32 %max, %min
28  %r = select i1 %cmp3, i32 %max, i32 %min
29  ret i32 %r
30}
31
32define i32 @smax_of_smax_smin_commute2(i32 %x, i32 %y) {
33; CHECK-LABEL: @smax_of_smax_smin_commute2(
34; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
35; CHECK-NEXT:    ret i32 [[MAX]]
36;
37  %cmp1 = icmp slt i32 %x, %y
38  %min = select i1 %cmp1, i32 %x, i32 %y
39  %cmp2 = icmp slt i32 %y, %x
40  %max = select i1 %cmp2, i32 %x, i32 %y
41  %cmp3 = icmp slt i32 %min, %max
42  %r = select i1 %cmp3, i32 %max, i32 %min
43  ret i32 %r
44}
45
46define <2 x i32> @smax_of_smax_smin_commute3(<2 x i32> %x, <2 x i32> %y) {
47; CHECK-LABEL: @smax_of_smax_smin_commute3(
48; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
49; CHECK-NEXT:    ret <2 x i32> [[MAX]]
50;
51  %cmp1 = icmp sgt <2 x i32> %x, %y
52  %min = select <2 x i1> %cmp1, <2 x i32> %y, <2 x i32> %x
53  %cmp2 = icmp sgt <2 x i32> %x, %y
54  %max = select <2 x i1> %cmp2, <2 x i32> %x, <2 x i32> %y
55  %cmp3 = icmp slt <2 x i32> %min, %max
56  %r = select <2 x i1> %cmp3, <2 x i32> %max, <2 x i32> %min
57  ret <2 x i32> %r
58}
59
60define i32 @smin_of_smin_smax_commute0(i32 %x, i32 %y) {
61; CHECK-LABEL: @smin_of_smin_smax_commute0(
62; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
63; CHECK-NEXT:    ret i32 [[MIN]]
64;
65  %cmp1 = icmp sgt i32 %x, %y
66  %max = select i1 %cmp1, i32 %x, i32 %y
67  %cmp2 = icmp sgt i32 %y, %x
68  %min = select i1 %cmp2, i32 %x, i32 %y
69  %cmp3 = icmp sgt i32 %max, %min
70  %r = select i1 %cmp3, i32 %min, i32 %max
71  ret i32 %r
72}
73
74define i32 @smin_of_smin_smax_commute1(i32 %x, i32 %y) {
75; CHECK-LABEL: @smin_of_smin_smax_commute1(
76; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
77; CHECK-NEXT:    ret i32 [[MIN]]
78;
79  %cmp1 = icmp slt i32 %x, %y
80  %max = select i1 %cmp1, i32 %y, i32 %x
81  %cmp2 = icmp slt i32 %x, %y
82  %min = select i1 %cmp2, i32 %x, i32 %y
83  %cmp3 = icmp sgt i32 %max, %min
84  %r = select i1 %cmp3, i32 %min, i32 %max
85  ret i32 %r
86}
87
88define <2 x i32> @smin_of_smin_smax_commute2(<2 x i32> %x, <2 x i32> %y) {
89; CHECK-LABEL: @smin_of_smin_smax_commute2(
90; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
91; CHECK-NEXT:    ret <2 x i32> [[MIN]]
92;
93  %cmp1 = icmp sgt <2 x i32> %x, %y
94  %max = select <2 x i1> %cmp1, <2 x i32> %x, <2 x i32> %y
95  %cmp2 = icmp slt <2 x i32> %x, %y
96  %min = select <2 x i1> %cmp2, <2 x i32> %x, <2 x i32> %y
97  %cmp3 = icmp slt <2 x i32> %min, %max
98  %r = select <2 x i1> %cmp3, <2 x i32> %min, <2 x i32> %max
99  ret <2 x i32> %r
100}
101
102define i32 @smin_of_smin_smax_commute3(i32 %x, i32 %y) {
103; CHECK-LABEL: @smin_of_smin_smax_commute3(
104; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
105; CHECK-NEXT:    ret i32 [[MIN]]
106;
107  %cmp1 = icmp slt i32 %x, %y
108  %max = select i1 %cmp1, i32 %y, i32 %x
109  %cmp2 = icmp sgt i32 %y, %x
110  %min = select i1 %cmp2, i32 %x, i32 %y
111  %cmp3 = icmp slt i32 %min, %max
112  %r = select i1 %cmp3, i32 %min, i32 %max
113  ret i32 %r
114}
115
116define i32 @umax_of_umax_umin_commute0(i32 %x, i32 %y) {
117; CHECK-LABEL: @umax_of_umax_umin_commute0(
118; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
119; CHECK-NEXT:    ret i32 [[MAX]]
120;
121  %cmp1 = icmp ult i32 %x, %y
122  %min = select i1 %cmp1, i32 %x, i32 %y
123  %cmp2 = icmp ult i32 %y, %x
124  %max = select i1 %cmp2, i32 %x, i32 %y
125  %cmp3 = icmp ugt i32 %max, %min
126  %r = select i1 %cmp3, i32 %max, i32 %min
127  ret i32 %r
128}
129
130define i32 @umax_of_umax_umin_commute1(i32 %x, i32 %y) {
131; CHECK-LABEL: @umax_of_umax_umin_commute1(
132; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
133; CHECK-NEXT:    ret i32 [[MAX]]
134;
135  %cmp1 = icmp ugt i32 %x, %y
136  %min = select i1 %cmp1, i32 %y, i32 %x
137  %cmp2 = icmp ugt i32 %x, %y
138  %max = select i1 %cmp2, i32 %x, i32 %y
139  %cmp3 = icmp ugt i32 %max, %min
140  %r = select i1 %cmp3, i32 %max, i32 %min
141  ret i32 %r
142}
143
144define i32 @umax_of_umax_umin_commute2(i32 %x, i32 %y) {
145; CHECK-LABEL: @umax_of_umax_umin_commute2(
146; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
147; CHECK-NEXT:    ret i32 [[MAX]]
148;
149  %cmp1 = icmp ult i32 %x, %y
150  %min = select i1 %cmp1, i32 %x, i32 %y
151  %cmp2 = icmp ult i32 %y, %x
152  %max = select i1 %cmp2, i32 %x, i32 %y
153  %cmp3 = icmp ult i32 %min, %max
154  %r = select i1 %cmp3, i32 %max, i32 %min
155  ret i32 %r
156}
157
158define <2 x i32> @umax_of_umax_umin_commute3(<2 x i32> %x, <2 x i32> %y) {
159; CHECK-LABEL: @umax_of_umax_umin_commute3(
160; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
161; CHECK-NEXT:    ret <2 x i32> [[MAX]]
162;
163  %cmp1 = icmp ugt <2 x i32> %x, %y
164  %min = select <2 x i1> %cmp1, <2 x i32> %y, <2 x i32> %x
165  %cmp2 = icmp ugt <2 x i32> %x, %y
166  %max = select <2 x i1> %cmp2, <2 x i32> %x, <2 x i32> %y
167  %cmp3 = icmp ult <2 x i32> %min, %max
168  %r = select <2 x i1> %cmp3, <2 x i32> %max, <2 x i32> %min
169  ret <2 x i32> %r
170}
171
172define i32 @umin_of_umin_umax_commute0(i32 %x, i32 %y) {
173; CHECK-LABEL: @umin_of_umin_umax_commute0(
174; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
175; CHECK-NEXT:    ret i32 [[MIN]]
176;
177  %cmp1 = icmp ugt i32 %x, %y
178  %max = select i1 %cmp1, i32 %x, i32 %y
179  %cmp2 = icmp ugt i32 %y, %x
180  %min = select i1 %cmp2, i32 %x, i32 %y
181  %cmp3 = icmp ugt i32 %max, %min
182  %r = select i1 %cmp3, i32 %min, i32 %max
183  ret i32 %r
184}
185
186define i32 @umin_of_umin_umax_commute1(i32 %x, i32 %y) {
187; CHECK-LABEL: @umin_of_umin_umax_commute1(
188; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
189; CHECK-NEXT:    ret i32 [[MIN]]
190;
191  %cmp1 = icmp ult i32 %x, %y
192  %max = select i1 %cmp1, i32 %y, i32 %x
193  %cmp2 = icmp ult i32 %x, %y
194  %min = select i1 %cmp2, i32 %x, i32 %y
195  %cmp3 = icmp ugt i32 %max, %min
196  %r = select i1 %cmp3, i32 %min, i32 %max
197  ret i32 %r
198}
199
200define <2 x i32> @umin_of_umin_umax_commute2(<2 x i32> %x, <2 x i32> %y) {
201; CHECK-LABEL: @umin_of_umin_umax_commute2(
202; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
203; CHECK-NEXT:    ret <2 x i32> [[MIN]]
204;
205  %cmp1 = icmp ugt <2 x i32> %x, %y
206  %max = select <2 x i1> %cmp1, <2 x i32> %x, <2 x i32> %y
207  %cmp2 = icmp ult <2 x i32> %x, %y
208  %min = select <2 x i1> %cmp2, <2 x i32> %x, <2 x i32> %y
209  %cmp3 = icmp ult <2 x i32> %min, %max
210  %r = select <2 x i1> %cmp3, <2 x i32> %min, <2 x i32> %max
211  ret <2 x i32> %r
212}
213
214define i32 @umin_of_umin_umax_commute3(i32 %x, i32 %y) {
215; CHECK-LABEL: @umin_of_umin_umax_commute3(
216; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
217; CHECK-NEXT:    ret i32 [[MIN]]
218;
219  %cmp1 = icmp ult i32 %x, %y
220  %max = select i1 %cmp1, i32 %y, i32 %x
221  %cmp2 = icmp ugt i32 %y, %x
222  %min = select i1 %cmp2, i32 %x, i32 %y
223  %cmp3 = icmp ult i32 %min, %max
224  %r = select i1 %cmp3, i32 %min, i32 %max
225  ret i32 %r
226}
227
228; Negative test - mismatch of min/max flavor
229
230define i32 @umin_of_smin_umax_wrong_pattern(i32 %x, i32 %y) {
231; CHECK-LABEL: @umin_of_smin_umax_wrong_pattern(
232; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
233; CHECK-NEXT:    ret i32 [[MIN]]
234;
235  %cmp1 = icmp ugt i32 %x, %y
236  %max = select i1 %cmp1, i32 %x, i32 %y
237  %cmp2 = icmp sgt i32 %y, %x
238  %min = select i1 %cmp2, i32 %x, i32 %y
239  %cmp3 = icmp ugt i32 %max, %min
240  %r = select i1 %cmp3, i32 %min, i32 %max
241  ret i32 %r
242}
243
244; Negative test - mismatch of min/max flavor
245
246define i32 @smin_of_umin_umax_wrong_pattern2(i32 %x, i32 %y) {
247; CHECK-LABEL: @smin_of_umin_umax_wrong_pattern2(
248; CHECK-NEXT:    [[R:%.*]] = call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
249; CHECK-NEXT:    ret i32 [[R]]
250;
251  %cmp1 = icmp ult i32 %x, %y
252  %max = select i1 %cmp1, i32 %y, i32 %x
253  %cmp2 = icmp ult i32 %x, %y
254  %min = select i1 %cmp2, i32 %x, i32 %y
255  %cmp3 = icmp sgt i32 %max, %min
256  %r = select i1 %cmp3, i32 %min, i32 %max
257  ret i32 %r
258}
259
260; Negative test - operands must match
261
262define <2 x i32> @umin_of_umin_umax_wrong_operand(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) {
263; CHECK-LABEL: @umin_of_umin_umax_wrong_operand(
264; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Z:%.*]])
265; CHECK-NEXT:    ret <2 x i32> [[MIN]]
266;
267  %cmp1 = icmp ugt <2 x i32> %x, %y
268  %max = select <2 x i1> %cmp1, <2 x i32> %x, <2 x i32> %y
269  %cmp2 = icmp ult <2 x i32> %x, %z
270  %min = select <2 x i1> %cmp2, <2 x i32> %x, <2 x i32> %z
271  %cmp3 = icmp ult <2 x i32> %min, %max
272  %r = select <2 x i1> %cmp3, <2 x i32> %min, <2 x i32> %max
273  ret <2 x i32> %r
274}
275
276; Negative test - operands must match
277
278define i32 @umin_of_umin_umax_wrong_operand2(i32 %x, i32 %y, i32 %z) {
279; CHECK-LABEL: @umin_of_umin_umax_wrong_operand2(
280; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
281; CHECK-NEXT:    ret i32 [[MIN]]
282;
283  %cmp1 = icmp ult i32 %x, %z
284  %max = select i1 %cmp1, i32 %z, i32 %x
285  %cmp2 = icmp ugt i32 %y, %x
286  %min = select i1 %cmp2, i32 %x, i32 %y
287  %cmp3 = icmp ult i32 %min, %max
288  %r = select i1 %cmp3, i32 %min, i32 %max
289  ret i32 %r
290}
291