1; RUN: opt < %s -instsimplify -S | FileCheck %s
2
3; In the next 16 tests (4 commutes * 2 (and/or) * 2 optional ptrtoint casts),
4; eliminate the simple (not) null check because that compare is implied by the
5; masked compare of the same operand.
6; Vary types between scalar and vector and weird for extra coverage.
7
8; or (icmp eq (and X, ?), 0), (icmp eq X, 0) --> icmp eq (and X, ?), 0
9
10define i1 @or_cmps_eq_zero_with_mask_commute1(i64 %x, i64 %y) {
11; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute1(
12; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i64 %x, %y
13; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i64 [[SOMEBITS]], 0
14; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_ZERO]]
15;
16  %isnull = icmp eq i64 %x, 0
17  %somebits = and i64 %x, %y
18  %somebits_are_zero = icmp eq i64 %somebits, 0
19  %r = or i1 %somebits_are_zero, %isnull
20  ret i1 %r
21}
22
23; or (icmp eq X, 0), (icmp eq (and X, ?), 0) --> icmp eq (and X, ?), 0
24
25define <2 x i1> @or_cmps_eq_zero_with_mask_commute2(<2 x i64> %x, <2 x i64> %y) {
26; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute2(
27; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <2 x i64> %x, %y
28; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i64> [[SOMEBITS]], zeroinitializer
29; CHECK-NEXT:    ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
30;
31  %isnull = icmp eq <2 x i64> %x, zeroinitializer
32  %somebits = and <2 x i64> %x, %y
33  %somebits_are_zero = icmp eq <2 x i64> %somebits, zeroinitializer
34  %r = or <2 x i1> %isnull, %somebits_are_zero
35  ret <2 x i1> %r
36}
37
38; or (icmp eq (and ?, X), 0), (icmp eq X, 0) --> icmp eq (and ?, X), 0
39
40define i1 @or_cmps_eq_zero_with_mask_commute3(i4 %x, i4 %y) {
41; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute3(
42; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i4 %y, %x
43; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i4 [[SOMEBITS]], 0
44; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_ZERO]]
45;
46  %isnull = icmp eq i4 %x, 0
47  %somebits = and i4 %y, %x
48  %somebits_are_zero = icmp eq i4 %somebits, 0
49  %r = or i1 %somebits_are_zero, %isnull
50  ret i1 %r
51}
52
53; or (icmp eq X, 0), (icmp eq (and ?, X), 0) --> icmp eq (and ?, X), 0
54
55define <2 x i1> @or_cmps_eq_zero_with_mask_commute4(<2 x i4> %x, <2 x i4> %y) {
56; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute4(
57; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <2 x i4> %y, %x
58; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i4> [[SOMEBITS]], zeroinitializer
59; CHECK-NEXT:    ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
60;
61  %isnull = icmp eq <2 x i4> %x, zeroinitializer
62  %somebits = and <2 x i4> %y, %x
63  %somebits_are_zero = icmp eq <2 x i4> %somebits, zeroinitializer
64  %r = or <2 x i1> %isnull, %somebits_are_zero
65  ret <2 x i1> %r
66}
67
68; and (icmp ne (and X, ?), 0), (icmp ne X, 0) --> icmp ne (and X, ?), 0
69
70define <3 x i1> @and_cmps_eq_zero_with_mask_commute1(<3 x i4> %x, <3 x i4> %y) {
71; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute1(
72; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <3 x i4> %x, %y
73; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i4> [[SOMEBITS]], zeroinitializer
74; CHECK-NEXT:    ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
75;
76  %isnotnull = icmp ne <3 x i4> %x, zeroinitializer
77  %somebits = and <3 x i4> %x, %y
78  %somebits_are_not_zero = icmp ne <3 x i4> %somebits, zeroinitializer
79  %r = and <3 x i1> %somebits_are_not_zero, %isnotnull
80  ret <3 x i1> %r
81}
82
83; and (icmp ne X, 0), (icmp ne (and X, ?), 0) --> icmp ne (and X, ?), 0
84
85define i1 @and_cmps_eq_zero_with_mask_commute2(i4 %x, i4 %y) {
86; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute2(
87; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i4 %x, %y
88; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i4 [[SOMEBITS]], 0
89; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
90;
91  %isnotnull = icmp ne i4 %x, 0
92  %somebits = and i4 %x, %y
93  %somebits_are_not_zero = icmp ne i4 %somebits, 0
94  %r = and i1 %isnotnull, %somebits_are_not_zero
95  ret i1 %r
96}
97
98; and (icmp ne (and ?, X), 0), (icmp ne X, 0) --> icmp ne (and ?, X), 0
99
100define <3 x i1> @and_cmps_eq_zero_with_mask_commute3(<3 x i64> %x, <3 x i64> %y) {
101; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute3(
102; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <3 x i64> %y, %x
103; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i64> [[SOMEBITS]], zeroinitializer
104; CHECK-NEXT:    ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
105;
106  %isnotnull = icmp ne <3 x i64> %x, zeroinitializer
107  %somebits = and <3 x i64> %y, %x
108  %somebits_are_not_zero = icmp ne <3 x i64> %somebits, zeroinitializer
109  %r = and <3 x i1> %somebits_are_not_zero, %isnotnull
110  ret <3 x i1> %r
111}
112
113; and (icmp ne X, 0), (icmp ne (and ?, X), 0) --> icmp ne (and ?, X), 0
114
115define i1 @and_cmps_eq_zero_with_mask_commute4(i64 %x, i64 %y) {
116; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute4(
117; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i64 %y, %x
118; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i64 [[SOMEBITS]], 0
119; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
120;
121  %isnotnull = icmp ne i64 %x, 0
122  %somebits = and i64 %y, %x
123  %somebits_are_not_zero = icmp ne i64 %somebits, 0
124  %r = and i1 %isnotnull, %somebits_are_not_zero
125  ret i1 %r
126}
127
128; or (icmp eq (and (ptrtoint P), ?), 0), (icmp eq P, 0) --> icmp eq (and (ptrtoint P), ?), 0
129
130define i1 @or_cmps_ptr_eq_zero_with_mask_commute1(i64* %p, i64 %y) {
131; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute1(
132; CHECK-NEXT:    [[X:%.*]] = ptrtoint i64* %p to i64
133; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i64 [[X]], %y
134; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i64 [[SOMEBITS]], 0
135; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_ZERO]]
136;
137  %isnull = icmp eq i64* %p, null
138  %x = ptrtoint i64* %p to i64
139  %somebits = and i64 %x, %y
140  %somebits_are_zero = icmp eq i64 %somebits, 0
141  %r = or i1 %somebits_are_zero, %isnull
142  ret i1 %r
143}
144
145; or (icmp eq P, 0), (icmp eq (and (ptrtoint P), ?), 0) --> icmp eq (and (ptrtoint P), ?), 0
146
147define <2 x i1> @or_cmps_ptr_eq_zero_with_mask_commute2(<2 x i64*> %p, <2 x i64> %y) {
148; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute2(
149; CHECK-NEXT:    [[X:%.*]] = ptrtoint <2 x i64*> %p to <2 x i64>
150; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <2 x i64> [[X]], %y
151; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i64> [[SOMEBITS]], zeroinitializer
152; CHECK-NEXT:    ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
153;
154  %isnull = icmp eq <2 x i64*> %p, zeroinitializer
155  %x = ptrtoint <2 x i64*> %p to <2 x i64>
156  %somebits = and <2 x i64> %x, %y
157  %somebits_are_zero = icmp eq <2 x i64> %somebits, zeroinitializer
158  %r = or <2 x i1> %isnull, %somebits_are_zero
159  ret <2 x i1> %r
160}
161
162; or (icmp eq (and ?, (ptrtoint P)), 0), (icmp eq P, 0) --> icmp eq (and ?, (ptrtoint P)), 0
163
164define i1 @or_cmps_ptr_eq_zero_with_mask_commute3(i4* %p, i4 %y) {
165; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute3(
166; CHECK-NEXT:    [[X:%.*]] = ptrtoint i4* %p to i4
167; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i4 %y, [[X]]
168; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i4 [[SOMEBITS]], 0
169; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_ZERO]]
170;
171  %isnull = icmp eq i4* %p, null
172  %x = ptrtoint i4* %p to i4
173  %somebits = and i4 %y, %x
174  %somebits_are_zero = icmp eq i4 %somebits, 0
175  %r = or i1 %somebits_are_zero, %isnull
176  ret i1 %r
177}
178
179; or (icmp eq P, 0), (icmp eq (and ?, (ptrtoint P)), 0) --> icmp eq (and ?, (ptrtoint P)), 0
180
181define <2 x i1> @or_cmps_ptr_eq_zero_with_mask_commute4(<2 x i4*> %p, <2 x i4> %y) {
182; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute4(
183; CHECK-NEXT:    [[X:%.*]] = ptrtoint <2 x i4*> %p to <2 x i4>
184; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <2 x i4> %y, [[X]]
185; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i4> [[SOMEBITS]], zeroinitializer
186; CHECK-NEXT:    ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
187;
188  %isnull = icmp eq <2 x i4*> %p, zeroinitializer
189  %x = ptrtoint <2 x i4*> %p to <2 x i4>
190  %somebits = and <2 x i4> %y, %x
191  %somebits_are_zero = icmp eq <2 x i4> %somebits, zeroinitializer
192  %r = or <2 x i1> %isnull, %somebits_are_zero
193  ret <2 x i1> %r
194}
195
196; and (icmp ne (and (ptrtoint P), ?), 0), (icmp ne P, 0) --> icmp ne (and (ptrtoint P), ?), 0
197
198define <3 x i1> @and_cmps_ptr_eq_zero_with_mask_commute1(<3 x i4*> %p, <3 x i4> %y) {
199; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute1(
200; CHECK-NEXT:    [[X:%.*]] = ptrtoint <3 x i4*> %p to <3 x i4>
201; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <3 x i4> [[X]], %y
202; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i4> [[SOMEBITS]], zeroinitializer
203; CHECK-NEXT:    ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
204;
205  %isnotnull = icmp ne <3 x i4*> %p, zeroinitializer
206  %x = ptrtoint <3 x i4*> %p to <3 x i4>
207  %somebits = and <3 x i4> %x, %y
208  %somebits_are_not_zero = icmp ne <3 x i4> %somebits, zeroinitializer
209  %r = and <3 x i1> %somebits_are_not_zero, %isnotnull
210  ret <3 x i1> %r
211}
212
213; and (icmp ne P, 0), (icmp ne (and (ptrtoint P), ?), 0) --> icmp ne (and (ptrtoint P), ?), 0
214
215define i1 @and_cmps_ptr_eq_zero_with_mask_commute2(i4* %p, i4 %y) {
216; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute2(
217; CHECK-NEXT:    [[X:%.*]] = ptrtoint i4* %p to i4
218; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i4 [[X]], %y
219; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i4 [[SOMEBITS]], 0
220; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
221;
222  %isnotnull = icmp ne i4* %p, null
223  %x = ptrtoint i4* %p to i4
224  %somebits = and i4 %x, %y
225  %somebits_are_not_zero = icmp ne i4 %somebits, 0
226  %r = and i1 %isnotnull, %somebits_are_not_zero
227  ret i1 %r
228}
229
230; and (icmp ne (and ?, (ptrtoint P)), 0), (icmp ne P, 0) --> icmp ne (and ?, (ptrtoint P)), 0
231
232define <3 x i1> @and_cmps_ptr_eq_zero_with_mask_commute3(<3 x i64*> %p, <3 x i64> %y) {
233; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute3(
234; CHECK-NEXT:    [[X:%.*]] = ptrtoint <3 x i64*> %p to <3 x i64>
235; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <3 x i64> %y, [[X]]
236; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i64> [[SOMEBITS]], zeroinitializer
237; CHECK-NEXT:    ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
238;
239  %isnotnull = icmp ne <3 x i64*> %p, zeroinitializer
240  %x = ptrtoint <3 x i64*> %p to <3 x i64>
241  %somebits = and <3 x i64> %y, %x
242  %somebits_are_not_zero = icmp ne <3 x i64> %somebits, zeroinitializer
243  %r = and <3 x i1> %somebits_are_not_zero, %isnotnull
244  ret <3 x i1> %r
245}
246
247; and (icmp ne P, 0), (icmp ne (and ?, (ptrtoint P)), 0) --> icmp ne (and ?, (ptrtoint P)), 0
248
249define i1 @and_cmps_ptr_eq_zero_with_mask_commute4(i64* %p, i64 %y) {
250; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute4(
251; CHECK-NEXT:    [[X:%.*]] = ptrtoint i64* %p to i64
252; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i64 %y, [[X]]
253; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i64 [[SOMEBITS]], 0
254; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
255;
256  %isnotnull = icmp ne i64* %p, null
257  %x = ptrtoint i64* %p to i64
258  %somebits = and i64 %y, %x
259  %somebits_are_not_zero = icmp ne i64 %somebits, 0
260  %r = and i1 %isnotnull, %somebits_are_not_zero
261  ret i1 %r
262}
263
264