1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; This is a specialization of generic folds for min/max values targeted to the
5; 'null' ptr constant.
6; Related tests for non-pointer types should be included in another file.
7
8; There are 6 basic patterns (or 3 with DeMorganized equivalent) with
9;    2 (commute logic op) *
10;    2 (swap compare operands) *
11; variations for a total of 24 tests.
12
13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14;
15; (X == null) && (X > Y) --> false
16;
17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18
19define i1 @ugt_and_min(i8* %x, i8* %y)  {
20; CHECK-LABEL: @ugt_and_min(
21; CHECK-NEXT:    ret i1 false
22;
23  %cmp = icmp ugt i8* %x, %y
24  %cmpeq = icmp eq i8* %x, null
25  %r = and i1 %cmp, %cmpeq
26  ret i1 %r
27}
28
29define i1 @ugt_and_min_commute(<2 x i8>* %x, <2 x i8>* %y)  {
30; CHECK-LABEL: @ugt_and_min_commute(
31; CHECK-NEXT:    ret i1 false
32;
33  %cmp = icmp ugt <2 x i8>* %x, %y
34  %cmpeq = icmp eq <2 x i8>* %x, null
35  %r = and i1 %cmpeq, %cmp
36  ret i1 %r
37}
38
39define i1 @ugt_swap_and_min(i8* %x, i8* %y)  {
40; CHECK-LABEL: @ugt_swap_and_min(
41; CHECK-NEXT:    ret i1 false
42;
43  %cmp = icmp ult i8* %y, %x
44  %cmpeq = icmp eq i8* %x, null
45  %r = and i1 %cmp, %cmpeq
46  ret i1 %r
47}
48
49define i1 @ugt_swap_and_min_commute(i8* %x, i8* %y)  {
50; CHECK-LABEL: @ugt_swap_and_min_commute(
51; CHECK-NEXT:    ret i1 false
52;
53  %cmp = icmp ult i8* %y, %x
54  %cmpeq = icmp eq i8* %x, null
55  %r = and i1 %cmpeq, %cmp
56  ret i1 %r
57}
58
59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
60;
61; (X != null) || (X <= Y) --> true
62;
63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64
65define i1 @ule_or_not_min(i427* %x, i427* %y)  {
66; CHECK-LABEL: @ule_or_not_min(
67; CHECK-NEXT:    ret i1 true
68;
69  %cmp = icmp ule i427* %x, %y
70  %cmpeq = icmp ne i427* %x, null
71  %r = or i1 %cmp, %cmpeq
72  ret i1 %r
73}
74
75define i1 @ule_or_not_min_commute(<3 x i9>* %x, <3 x i9>* %y)  {
76; CHECK-LABEL: @ule_or_not_min_commute(
77; CHECK-NEXT:    ret i1 true
78;
79  %cmp = icmp ule <3 x i9>* %x, %y
80  %cmpeq = icmp ne <3 x i9>* %x, null
81  %r = or i1 %cmpeq, %cmp
82  ret i1 %r
83}
84
85define i1 @ule_swap_or_not_min(i8* %x, i8* %y)  {
86; CHECK-LABEL: @ule_swap_or_not_min(
87; CHECK-NEXT:    ret i1 true
88;
89  %cmp = icmp uge i8* %y, %x
90  %cmpeq = icmp ne i8* %x, null
91  %r = or i1 %cmp, %cmpeq
92  ret i1 %r
93}
94
95define i1 @ule_swap_or_not_min_commute(i8* %x, i8* %y)  {
96; CHECK-LABEL: @ule_swap_or_not_min_commute(
97; CHECK-NEXT:    ret i1 true
98;
99  %cmp = icmp uge i8* %y, %x
100  %cmpeq = icmp ne i8* %x, null
101  %r = or i1 %cmpeq, %cmp
102  ret i1 %r
103}
104
105;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
106;
107; (X == null) && (X <= Y) --> X == null
108;
109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110
111define i1 @ule_and_min(i8* %x, i8* %y)  {
112; CHECK-LABEL: @ule_and_min(
113; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp eq i8* [[X:%.*]], null
114; CHECK-NEXT:    ret i1 [[CMPEQ]]
115;
116  %cmp = icmp ule i8* %x, %y
117  %cmpeq = icmp eq i8* %x, null
118  %r = and i1 %cmp, %cmpeq
119  ret i1 %r
120}
121
122define i1 @ule_and_min_commute(i8* %x, i8* %y)  {
123; CHECK-LABEL: @ule_and_min_commute(
124; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp eq i8* [[X:%.*]], null
125; CHECK-NEXT:    ret i1 [[CMPEQ]]
126;
127  %cmp = icmp ule i8* %x, %y
128  %cmpeq = icmp eq i8* %x, null
129  %r = and i1 %cmpeq, %cmp
130  ret i1 %r
131}
132
133define i1 @ule_swap_and_min(i8* %x, i8* %y)  {
134; CHECK-LABEL: @ule_swap_and_min(
135; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp eq i8* [[X:%.*]], null
136; CHECK-NEXT:    ret i1 [[CMPEQ]]
137;
138  %cmp = icmp uge i8* %y, %x
139  %cmpeq = icmp eq i8* %x, null
140  %r = and i1 %cmp, %cmpeq
141  ret i1 %r
142}
143
144define i1 @ule_swap_and_min_commute(i8* %x, i8* %y)  {
145; CHECK-LABEL: @ule_swap_and_min_commute(
146; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp eq i8* [[X:%.*]], null
147; CHECK-NEXT:    ret i1 [[CMPEQ]]
148;
149  %cmp = icmp uge i8* %y, %x
150  %cmpeq = icmp eq i8* %x, null
151  %r = and i1 %cmpeq, %cmp
152  ret i1 %r
153}
154
155;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
156;
157; (X == null) || (X <= Y) --> X <= Y
158;
159;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
160
161define i1 @ule_or_min(i8* %x, i8* %y)  {
162; CHECK-LABEL: @ule_or_min(
163; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8* [[X:%.*]], [[Y:%.*]]
164; CHECK-NEXT:    ret i1 [[CMP]]
165;
166  %cmp = icmp ule i8* %x, %y
167  %cmpeq = icmp eq i8* %x, null
168  %r = or i1 %cmp, %cmpeq
169  ret i1 %r
170}
171
172define i1 @ule_or_min_commute(i8* %x, i8* %y)  {
173; CHECK-LABEL: @ule_or_min_commute(
174; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8* [[X:%.*]], [[Y:%.*]]
175; CHECK-NEXT:    ret i1 [[CMP]]
176;
177  %cmp = icmp ule i8* %x, %y
178  %cmpeq = icmp eq i8* %x, null
179  %r = or i1 %cmpeq, %cmp
180  ret i1 %r
181}
182
183define i1 @ule_swap_or_min(i8* %x, i8* %y)  {
184; CHECK-LABEL: @ule_swap_or_min(
185; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8* [[Y:%.*]], [[X:%.*]]
186; CHECK-NEXT:    ret i1 [[CMP]]
187;
188  %cmp = icmp uge i8* %y, %x
189  %cmpeq = icmp eq i8* %x, null
190  %r = or i1 %cmp, %cmpeq
191  ret i1 %r
192}
193
194define i1 @ule_swap_or_min_commute(i8* %x, i8* %y)  {
195; CHECK-LABEL: @ule_swap_or_min_commute(
196; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8* [[Y:%.*]], [[X:%.*]]
197; CHECK-NEXT:    ret i1 [[CMP]]
198;
199  %cmp = icmp uge i8* %y, %x
200  %cmpeq = icmp eq i8* %x, null
201  %r = or i1 %cmpeq, %cmp
202  ret i1 %r
203}
204
205;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
206;
207; (X != null) && (X > Y) --> X > Y
208;
209;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
210
211define i1 @ugt_and_not_min(i8* %x, i8* %y)  {
212; CHECK-LABEL: @ugt_and_not_min(
213; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8* [[X:%.*]], [[Y:%.*]]
214; CHECK-NEXT:    ret i1 [[CMP]]
215;
216  %cmp = icmp ugt i8* %x, %y
217  %cmpeq = icmp ne i8* %x, null
218  %r = and i1 %cmp, %cmpeq
219  ret i1 %r
220}
221
222define i1 @ugt_and_not_min_commute(i8* %x, i8* %y)  {
223; CHECK-LABEL: @ugt_and_not_min_commute(
224; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8* [[X:%.*]], [[Y:%.*]]
225; CHECK-NEXT:    ret i1 [[CMP]]
226;
227  %cmp = icmp ugt i8* %x, %y
228  %cmpeq = icmp ne i8* %x, null
229  %r = and i1 %cmpeq, %cmp
230  ret i1 %r
231}
232
233define i1 @ugt_swap_and_not_min(i8* %x, i8* %y)  {
234; CHECK-LABEL: @ugt_swap_and_not_min(
235; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8* [[Y:%.*]], [[X:%.*]]
236; CHECK-NEXT:    ret i1 [[CMP]]
237;
238  %cmp = icmp ult i8* %y, %x
239  %cmpeq = icmp ne i8* %x, null
240  %r = and i1 %cmp, %cmpeq
241  ret i1 %r
242}
243
244define i1 @ugt_swap_and_not_min_commute(i8* %x, i8* %y)  {
245; CHECK-LABEL: @ugt_swap_and_not_min_commute(
246; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8* [[Y:%.*]], [[X:%.*]]
247; CHECK-NEXT:    ret i1 [[CMP]]
248;
249  %cmp = icmp ult i8* %y, %x
250  %cmpeq = icmp ne i8* %x, null
251  %r = and i1 %cmpeq, %cmp
252  ret i1 %r
253}
254
255;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
256;
257; (X != null) || (X > Y) --> X != null
258;
259;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
260
261define i1 @ugt_or_not_min(i8* %x, i8* %y)  {
262; CHECK-LABEL: @ugt_or_not_min(
263; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp ne i8* [[X:%.*]], null
264; CHECK-NEXT:    ret i1 [[CMPEQ]]
265;
266  %cmp = icmp ugt i8* %x, %y
267  %cmpeq = icmp ne i8* %x, null
268  %r = or i1 %cmp, %cmpeq
269  ret i1 %r
270}
271
272define i1 @ugt_or_not_min_commute(i8* %x, i8* %y)  {
273; CHECK-LABEL: @ugt_or_not_min_commute(
274; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp ne i8* [[X:%.*]], null
275; CHECK-NEXT:    ret i1 [[CMPEQ]]
276;
277  %cmp = icmp ugt i8* %x, %y
278  %cmpeq = icmp ne i8* %x, null
279  %r = or i1 %cmpeq, %cmp
280  ret i1 %r
281}
282
283define i1 @ugt_swap_or_not_min(i8* %x, i8* %y)  {
284; CHECK-LABEL: @ugt_swap_or_not_min(
285; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp ne i8* [[X:%.*]], null
286; CHECK-NEXT:    ret i1 [[CMPEQ]]
287;
288  %cmp = icmp ult i8* %y, %x
289  %cmpeq = icmp ne i8* %x, null
290  %r = or i1 %cmp, %cmpeq
291  ret i1 %r
292}
293
294define i1 @ugt_swap_or_not_min_commute(i823* %x, i823* %y)  {
295; CHECK-LABEL: @ugt_swap_or_not_min_commute(
296; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp ne i823* [[X:%.*]], null
297; CHECK-NEXT:    ret i1 [[CMPEQ]]
298;
299  %cmp = icmp ult i823* %y, %x
300  %cmpeq = icmp ne i823* %x, null
301  %r = or i1 %cmpeq, %cmp
302  ret i1 %r
303}
304
305define i1 @sgt_and_min(i9* %x, i9* %y)  {
306; CHECK-LABEL: @sgt_and_min(
307; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp eq i9* [[X:%.*]], null
308; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i9* [[Y:%.*]], null
309; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[CMPEQ]], [[TMP1]]
310; CHECK-NEXT:    ret i1 [[TMP2]]
311;
312  %cmp = icmp sgt i9* %x, %y
313  %cmpeq = icmp eq i9* %x, null
314  %r = and i1 %cmp, %cmpeq
315  ret i1 %r
316}
317
318define i1 @sle_or_not_min(i427* %x, i427* %y)  {
319; CHECK-LABEL: @sle_or_not_min(
320; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp ne i427* [[X:%.*]], null
321; CHECK-NEXT:    [[TMP1:%.*]] = icmp sge i427* [[Y:%.*]], null
322; CHECK-NEXT:    [[TMP2:%.*]] = or i1 [[CMPEQ]], [[TMP1]]
323; CHECK-NEXT:    ret i1 [[TMP2]]
324;
325  %cmp = icmp sle i427* %x, %y
326  %cmpeq = icmp ne i427* %x, null
327  %r = or i1 %cmp, %cmpeq
328  ret i1 %r
329}
330
331define i1 @sle_and_min(i8* %x, i8* %y)  {
332; CHECK-LABEL: @sle_and_min(
333; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp eq i8* [[X:%.*]], null
334; CHECK-NEXT:    [[TMP1:%.*]] = icmp sge i8* [[Y:%.*]], null
335; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[CMPEQ]], [[TMP1]]
336; CHECK-NEXT:    ret i1 [[TMP2]]
337;
338  %cmp = icmp sle i8* %x, %y
339  %cmpeq = icmp eq i8* %x, null
340  %r = and i1 %cmp, %cmpeq
341  ret i1 %r
342}
343
344define i1 @sgt_and_not_min(i8* %x, i8* %y)  {
345; CHECK-LABEL: @sgt_and_not_min(
346; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8* [[X:%.*]], [[Y:%.*]]
347; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp ne i8* [[X]], null
348; CHECK-NEXT:    [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]]
349; CHECK-NEXT:    ret i1 [[R]]
350;
351  %cmp = icmp sgt i8* %x, %y
352  %cmpeq = icmp ne i8* %x, null
353  %r = and i1 %cmp, %cmpeq
354  ret i1 %r
355}
356
357define i1 @sgt_or_not_min(i8* %x, i8* %y)  {
358; CHECK-LABEL: @sgt_or_not_min(
359; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp ne i8* [[X:%.*]], null
360; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8* [[Y:%.*]], null
361; CHECK-NEXT:    [[TMP2:%.*]] = or i1 [[CMPEQ]], [[TMP1]]
362; CHECK-NEXT:    ret i1 [[TMP2]]
363;
364  %cmp = icmp sgt i8* %x, %y
365  %cmpeq = icmp ne i8* %x, null
366  %r = or i1 %cmp, %cmpeq
367  ret i1 %r
368}
369
370define i1 @slt_and_min(i8* %a, i8* %b) {
371; CHECK-LABEL: @slt_and_min(
372; CHECK-NEXT:    [[CMPEQ:%.*]] = icmp eq i8* [[A:%.*]], null
373; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i8* [[B:%.*]], null
374; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[CMPEQ]], [[TMP1]]
375; CHECK-NEXT:    ret i1 [[TMP2]]
376;
377  %cmpeq = icmp eq i8* %a, null
378  %cmp = icmp slt i8* %a, %b
379  %r = and i1 %cmpeq, %cmp
380  ret i1 %r
381}
382