1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 define i1 @is_pow2or0_negate_op(i32 %x) {
5 ; CHECK-LABEL: @is_pow2or0_negate_op(
6 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0:![0-9]+]]
7 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], 2
8 ; CHECK-NEXT: ret i1 [[CMP]]
11 %and = and i32 %neg, %x
12 %cmp = icmp eq i32 %and, %x
16 define <2 x i1> @is_pow2or0_negate_op_vec(<2 x i32> %x) {
17 ; CHECK-LABEL: @is_pow2or0_negate_op_vec(
18 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]), !range [[RNG0]]
19 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 2, i32 2>
20 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
22 %neg = sub <2 x i32> zeroinitializer, %x
23 %and = and <2 x i32> %neg, %x
24 %cmp = icmp eq <2 x i32> %and, %x
28 define i1 @is_pow2or0_decrement_op(i8 %x) {
29 ; CHECK-LABEL: @is_pow2or0_decrement_op(
30 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1:![0-9]+]]
31 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP1]], 2
32 ; CHECK-NEXT: ret i1 [[CMP]]
35 %and = and i8 %dec, %x
36 %cmp = icmp eq i8 %and, 0
40 define <2 x i1> @is_pow2or0_decrement_op_vec(<2 x i8> %x) {
41 ; CHECK-LABEL: @is_pow2or0_decrement_op_vec(
42 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
43 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[TMP1]], <i8 2, i8 2>
44 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
46 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
47 %and = and <2 x i8> %dec, %x
48 %cmp = icmp eq <2 x i8> %and, zeroinitializer
52 define i1 @isnot_pow2or0_negate_op(i32 %x) {
53 ; CHECK-LABEL: @isnot_pow2or0_negate_op(
54 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
55 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1
56 ; CHECK-NEXT: ret i1 [[CMP]]
59 %and = and i32 %neg, %x
60 %cmp = icmp ne i32 %and, %x
64 define <2 x i1> @isnot_pow2or0_negate_op_vec(<2 x i32> %x) {
65 ; CHECK-LABEL: @isnot_pow2or0_negate_op_vec(
66 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]), !range [[RNG0]]
67 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[TMP1]], <i32 1, i32 1>
68 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
70 %neg = sub <2 x i32> zeroinitializer, %x
71 %and = and <2 x i32> %neg, %x
72 %cmp = icmp ne <2 x i32> %and, %x
76 define i1 @isnot_pow2or0_decrement_op(i8 %x) {
77 ; CHECK-LABEL: @isnot_pow2or0_decrement_op(
78 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
79 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[TMP1]], 1
80 ; CHECK-NEXT: ret i1 [[CMP]]
83 %and = and i8 %dec, %x
84 %cmp = icmp ne i8 %and, 0
88 define <2 x i1> @isnot_pow2or0_decrement_op_vec(<2 x i8> %x) {
89 ; CHECK-LABEL: @isnot_pow2or0_decrement_op_vec(
90 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
91 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[TMP1]], <i8 1, i8 1>
92 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
94 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
95 %and = and <2 x i8> %dec, %x
96 %cmp = icmp ne <2 x i8> %and, zeroinitializer
100 define i1 @is_pow2or0_negate_op_commute1(i32 %p) {
101 ; CHECK-LABEL: @is_pow2or0_negate_op_commute1(
102 ; CHECK-NEXT: [[X:%.*]] = srem i32 42, [[P:%.*]]
103 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG2:![0-9]+]]
104 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], 2
105 ; CHECK-NEXT: ret i1 [[CMP]]
107 %x = srem i32 42, %p ; thwart complexity-based canonicalization
109 %and = and i32 %x, %neg
110 %cmp = icmp eq i32 %and, %x
114 ; x can't be <= complexity of the 'neg' but >= complexity of the 'and'.
116 define i1 @isnot_pow2or0_negate_op_commute2(i32 %p) {
117 ; CHECK-LABEL: @isnot_pow2or0_negate_op_commute2(
118 ; CHECK-NEXT: [[X:%.*]] = urem i32 42, [[P:%.*]]
119 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG2]]
120 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1
121 ; CHECK-NEXT: ret i1 [[CMP]]
123 %x = urem i32 42, %p ; thwart complexity-based canonicalization
125 %and = and i32 %neg, %x
126 %cmp = icmp ne i32 %x, %and
130 define i1 @isnot_pow2or0_negate_op_commute3(i32 %p) {
131 ; CHECK-LABEL: @isnot_pow2or0_negate_op_commute3(
132 ; CHECK-NEXT: [[X:%.*]] = urem i32 42, [[P:%.*]]
133 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG2]]
134 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1
135 ; CHECK-NEXT: ret i1 [[CMP]]
137 %x = urem i32 42, %p ; thwart complexity-based canonicalization
139 %and = and i32 %x, %neg
140 %cmp = icmp ne i32 %x, %and
144 declare void @use(i32)
146 define i1 @is_pow2or0_negate_op_extra_use1(i32 %x) {
147 ; CHECK-LABEL: @is_pow2or0_negate_op_extra_use1(
148 ; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]
149 ; CHECK-NEXT: call void @use(i32 [[NEG]])
150 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]]
151 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], 2
152 ; CHECK-NEXT: ret i1 [[CMP]]
155 call void @use(i32 %neg)
156 %and = and i32 %neg, %x
157 %cmp = icmp eq i32 %and, %x
161 define i1 @is_pow2or0_negate_op_extra_use2(i32 %x) {
162 ; CHECK-LABEL: @is_pow2or0_negate_op_extra_use2(
163 ; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]
164 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[NEG]], [[X]]
165 ; CHECK-NEXT: call void @use(i32 [[AND]])
166 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[X]]
167 ; CHECK-NEXT: ret i1 [[CMP]]
170 %and = and i32 %neg, %x
171 call void @use(i32 %and)
172 %cmp = icmp eq i32 %and, %x
176 declare i32 @llvm.ctpop.i32(i32)
177 declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>)
178 declare void @llvm.assume(i1)
180 ; (X != 0) && (ctpop(X) u< 2) --> ctpop(X) == 1
182 define i1 @is_pow2_ctpop(i32 %x) {
183 ; CHECK-LABEL: @is_pow2_ctpop(
184 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
185 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1
186 ; CHECK-NEXT: ret i1 [[R]]
188 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
189 %cmp = icmp ult i32 %t0, 2
190 %notzero = icmp ne i32 %x, 0
191 %r = and i1 %notzero, %cmp
196 define i1 @is_pow2_non_zero_ult_2(i32 %x) {
197 ; CHECK-LABEL: @is_pow2_non_zero_ult_2(
198 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
199 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
200 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]]
201 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
202 ; CHECK-NEXT: ret i1 [[CMP]]
204 %notzero = icmp ne i32 %x, 0
205 call void @llvm.assume(i1 %notzero)
206 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
207 %cmp = icmp ult i32 %t0, 2
211 define i1 @is_pow2_non_zero_eq_1(i32 %x) {
212 ; CHECK-LABEL: @is_pow2_non_zero_eq_1(
213 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
214 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
215 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]]
216 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
217 ; CHECK-NEXT: ret i1 [[CMP]]
219 %notzero = icmp ne i32 %x, 0
220 call void @llvm.assume(i1 %notzero)
221 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
222 %cmp = icmp eq i32 %t0, 1
226 define i1 @is_pow2_non_zero_ugt_1(i32 %x) {
227 ; CHECK-LABEL: @is_pow2_non_zero_ugt_1(
228 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
229 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
230 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]]
231 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
232 ; CHECK-NEXT: ret i1 [[CMP]]
234 %notzero = icmp ne i32 %x, 0
235 call void @llvm.assume(i1 %notzero)
236 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
237 %cmp = icmp ugt i32 %t0, 1
241 define i1 @is_pow2_non_zero_ne_1(i32 %x) {
242 ; CHECK-LABEL: @is_pow2_non_zero_ne_1(
243 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
244 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
245 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]]
246 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1
247 ; CHECK-NEXT: ret i1 [[CMP]]
249 %notzero = icmp ne i32 %x, 0
250 call void @llvm.assume(i1 %notzero)
251 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
252 %cmp = icmp ne i32 %t0, 1
256 define i1 @is_pow2_ctpop_logical(i32 %x) {
257 ; CHECK-LABEL: @is_pow2_ctpop_logical(
258 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
259 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1
260 ; CHECK-NEXT: ret i1 [[R]]
262 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
263 %cmp = icmp ult i32 %t0, 2
264 %notzero = icmp ne i32 %x, 0
265 %r = select i1 %notzero, i1 %cmp, i1 false
269 ; Extra uses don't change the fold.
270 declare void @use_i1(i1)
272 define i1 @is_pow2_ctpop_extra_uses(i32 %x) {
273 ; CHECK-LABEL: @is_pow2_ctpop_extra_uses(
274 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
275 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
276 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
277 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
278 ; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])
279 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1
280 ; CHECK-NEXT: ret i1 [[R]]
282 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
283 %cmp = icmp ult i32 %t0, 2
284 call void @use_i1(i1 %cmp)
285 %notzero = icmp ne i32 %x, 0
286 call void @use_i1(i1 %notzero)
287 %r = and i1 %notzero, %cmp
291 define i1 @is_pow2_ctpop_extra_uses_logical(i32 %x) {
292 ; CHECK-LABEL: @is_pow2_ctpop_extra_uses_logical(
293 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
294 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
295 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
296 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
297 ; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])
298 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1
299 ; CHECK-NEXT: ret i1 [[R]]
301 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
302 %cmp = icmp ult i32 %t0, 2
303 call void @use_i1(i1 %cmp)
304 %notzero = icmp ne i32 %x, 0
305 call void @use_i1(i1 %notzero)
306 %r = select i1 %notzero, i1 %cmp, i1 false
310 ; Test vector type and commuted 'and' operands.
312 define <2 x i1> @is_pow2_ctpop_commute_vec(<2 x i8> %x) {
313 ; CHECK-LABEL: @is_pow2_ctpop_commute_vec(
314 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
315 ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[T0]], <i8 1, i8 1>
316 ; CHECK-NEXT: ret <2 x i1> [[R]]
318 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
319 %cmp = icmp ult <2 x i8> %t0, <i8 2, i8 2>
320 %notzero = icmp ne <2 x i8> %x, zeroinitializer
321 %r = and <2 x i1> %cmp, %notzero
325 ; Negative test - wrong constant.
327 define i1 @is_pow2_ctpop_wrong_cmp_op1(i32 %x) {
328 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1(
329 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
330 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3
331 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
332 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
333 ; CHECK-NEXT: ret i1 [[R]]
335 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
336 %cmp = icmp ult i32 %t0, 3
337 %notzero = icmp ne i32 %x, 0
338 %r = and i1 %notzero, %cmp
342 define i1 @is_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
343 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1_logical(
344 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
345 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3
346 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
347 ; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false
348 ; CHECK-NEXT: ret i1 [[R]]
350 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
351 %cmp = icmp ult i32 %t0, 3
352 %notzero = icmp ne i32 %x, 0
353 %r = select i1 %notzero, i1 %cmp, i1 false
357 ; Negative test - wrong constant.
359 define i1 @is_pow2_ctpop_wrong_cmp_op2(i32 %x) {
360 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2(
361 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
362 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
363 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1
364 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
365 ; CHECK-NEXT: ret i1 [[R]]
367 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
368 %cmp = icmp ult i32 %t0, 2
369 %notzero = icmp ne i32 %x, 1
370 %r = and i1 %notzero, %cmp
374 define i1 @is_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
375 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2_logical(
376 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
377 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
378 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1
379 ; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false
380 ; CHECK-NEXT: ret i1 [[R]]
382 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
383 %cmp = icmp ult i32 %t0, 2
384 %notzero = icmp ne i32 %x, 1
385 %r = select i1 %notzero, i1 %cmp, i1 false
389 ; Negative test - wrong predicate.
391 define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) {
392 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1(
393 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
394 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
395 ; CHECK-NEXT: ret i1 [[CMP]]
397 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
398 %cmp = icmp ugt i32 %t0, 2
399 %notzero = icmp ne i32 %x, 0
400 %r = and i1 %notzero, %cmp
404 define i1 @is_pow2_ctpop_wrong_pred1_logical(i32 %x) {
405 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1_logical(
406 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
407 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
408 ; CHECK-NEXT: ret i1 [[CMP]]
410 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
411 %cmp = icmp ugt i32 %t0, 2
412 %notzero = icmp ne i32 %x, 0
413 %r = select i1 %notzero, i1 %cmp, i1 false
417 ; Negative test - wrong predicate.
419 define i1 @is_pow2_ctpop_wrong_pred2(i32 %x) {
420 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2(
421 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
422 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
423 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0
424 ; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]]
425 ; CHECK-NEXT: ret i1 [[R]]
427 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
428 %cmp = icmp ult i32 %t0, 2
429 %cmp2 = icmp sgt i32 %x, 0
430 %r = and i1 %cmp2, %cmp
434 define i1 @is_pow2_ctpop_wrong_pred2_logical(i32 %x) {
435 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2_logical(
436 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
437 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
438 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0
439 ; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i1 [[CMP]], i1 false
440 ; CHECK-NEXT: ret i1 [[R]]
442 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
443 %cmp = icmp ult i32 %t0, 2
444 %cmp2 = icmp sgt i32 %x, 0
445 %r = select i1 %cmp2, i1 %cmp, i1 false
449 ; (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
451 define i1 @isnot_pow2_ctpop(i32 %x) {
452 ; CHECK-LABEL: @isnot_pow2_ctpop(
453 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
454 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1
455 ; CHECK-NEXT: ret i1 [[R]]
457 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
458 %cmp = icmp ugt i32 %t0, 1
459 %iszero = icmp eq i32 %x, 0
460 %r = or i1 %iszero, %cmp
464 define i1 @isnot_pow2_ctpop_logical(i32 %x) {
465 ; CHECK-LABEL: @isnot_pow2_ctpop_logical(
466 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
467 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1
468 ; CHECK-NEXT: ret i1 [[R]]
470 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
471 %cmp = icmp ugt i32 %t0, 1
472 %iszero = icmp eq i32 %x, 0
473 %r = select i1 %iszero, i1 true, i1 %cmp
477 ; Extra uses don't change the fold.
479 define i1 @isnot_pow2_ctpop_extra_uses(i32 %x) {
480 ; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses(
481 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
482 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
483 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
484 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
485 ; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])
486 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1
487 ; CHECK-NEXT: ret i1 [[R]]
489 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
490 %cmp = icmp ugt i32 %t0, 1
491 call void @use_i1(i1 %cmp)
492 %iszero = icmp eq i32 %x, 0
493 call void @use_i1(i1 %iszero)
494 %r = or i1 %iszero, %cmp
498 define i1 @isnot_pow2_ctpop_extra_uses_logical(i32 %x) {
499 ; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses_logical(
500 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
501 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
502 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
503 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
504 ; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])
505 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1
506 ; CHECK-NEXT: ret i1 [[R]]
508 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
509 %cmp = icmp ugt i32 %t0, 1
510 call void @use_i1(i1 %cmp)
511 %iszero = icmp eq i32 %x, 0
512 call void @use_i1(i1 %iszero)
513 %r = select i1 %iszero, i1 true, i1 %cmp
517 ; Test vector type and commuted 'or' operands.
519 define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) {
520 ; CHECK-LABEL: @isnot_pow2_ctpop_commute_vec(
521 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
522 ; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[T0]], <i8 1, i8 1>
523 ; CHECK-NEXT: ret <2 x i1> [[R]]
525 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
526 %cmp = icmp ugt <2 x i8> %t0, <i8 1, i8 1>
527 %iszero = icmp eq <2 x i8> %x, zeroinitializer
528 %r = or <2 x i1> %cmp, %iszero
532 ; Negative test - wrong constant.
534 define i1 @isnot_pow2_ctpop_wrong_cmp_op1(i32 %x) {
535 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1(
536 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
537 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
538 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
539 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
540 ; CHECK-NEXT: ret i1 [[R]]
542 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
543 %cmp = icmp ugt i32 %t0, 2
544 %iszero = icmp eq i32 %x, 0
545 %r = or i1 %iszero, %cmp
549 define i1 @isnot_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
550 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1_logical(
551 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
552 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
553 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
554 ; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]
555 ; CHECK-NEXT: ret i1 [[R]]
557 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
558 %cmp = icmp ugt i32 %t0, 2
559 %iszero = icmp eq i32 %x, 0
560 %r = select i1 %iszero, i1 true, i1 %cmp
564 ; Negative test - wrong constant.
566 define i1 @isnot_pow2_ctpop_wrong_cmp_op2(i32 %x) {
567 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2(
568 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
569 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
570 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1
571 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
572 ; CHECK-NEXT: ret i1 [[R]]
574 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
575 %cmp = icmp ugt i32 %t0, 1
576 %iszero = icmp eq i32 %x, 1
577 %r = or i1 %iszero, %cmp
581 define i1 @isnot_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
582 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2_logical(
583 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
584 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
585 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1
586 ; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]
587 ; CHECK-NEXT: ret i1 [[R]]
589 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
590 %cmp = icmp ugt i32 %t0, 1
591 %iszero = icmp eq i32 %x, 1
592 %r = select i1 %iszero, i1 true, i1 %cmp
596 ; Negative test - wrong predicate.
598 define i1 @isnot_pow2_ctpop_wrong_pred2(i32 %x) {
599 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2(
600 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
601 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
602 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0
603 ; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]]
604 ; CHECK-NEXT: ret i1 [[R]]
606 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
607 %cmp = icmp ugt i32 %t0, 1
608 %cmp2 = icmp slt i32 %x, 0
609 %r = or i1 %cmp2, %cmp
613 define i1 @isnot_pow2_ctpop_wrong_pred2_logical(i32 %x) {
614 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2_logical(
615 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
616 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
617 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0
618 ; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP]]
619 ; CHECK-NEXT: ret i1 [[R]]
621 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
622 %cmp = icmp ugt i32 %t0, 1
623 %cmp2 = icmp slt i32 %x, 0
624 %r = select i1 %cmp2, i1 true, i1 %cmp
628 define i1 @is_pow2_negate_op(i32 %x) {
629 ; CHECK-LABEL: @is_pow2_negate_op(
630 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
631 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 1
632 ; CHECK-NEXT: ret i1 [[R]]
635 %and = and i32 %neg, %x
636 %cmp = icmp eq i32 %and, %x
637 %notzero = icmp ne i32 %x, 0
638 %r = and i1 %notzero, %cmp
642 define i1 @is_pow2_negate_op_logical(i32 %x) {
643 ; CHECK-LABEL: @is_pow2_negate_op_logical(
644 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
645 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 1
646 ; CHECK-NEXT: ret i1 [[R]]
649 %and = and i32 %neg, %x
650 %cmp = icmp eq i32 %and, %x
651 %notzero = icmp ne i32 %x, 0
652 %r = select i1 %notzero, i1 %cmp, i1 false
656 define <2 x i1> @is_pow2_negate_op_vec(<2 x i32> %x) {
657 ; CHECK-LABEL: @is_pow2_negate_op_vec(
658 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]), !range [[RNG0]]
659 ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 1, i32 1>
660 ; CHECK-NEXT: ret <2 x i1> [[R]]
662 %neg = sub <2 x i32> zeroinitializer, %x
663 %and = and <2 x i32> %neg, %x
664 %cmp = icmp eq <2 x i32> %and, %x
665 %notzero = icmp ne <2 x i32> %x, zeroinitializer
666 %r = and <2 x i1> %cmp, %notzero
670 define i1 @is_pow2_decrement_op(i8 %x) {
671 ; CHECK-LABEL: @is_pow2_decrement_op(
672 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
673 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], 1
674 ; CHECK-NEXT: ret i1 [[R]]
677 %and = and i8 %dec, %x
678 %cmp = icmp eq i8 %and, 0
679 %notzero = icmp ne i8 %x, 0
680 %r = and i1 %cmp, %notzero
684 define i1 @is_pow2_decrement_op_logical(i8 %x) {
685 ; CHECK-LABEL: @is_pow2_decrement_op_logical(
686 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
687 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], 1
688 ; CHECK-NEXT: ret i1 [[R]]
691 %and = and i8 %dec, %x
692 %cmp = icmp eq i8 %and, 0
693 %notzero = icmp ne i8 %x, 0
694 %r = select i1 %cmp, i1 %notzero, i1 false
698 define <2 x i1> @is_pow2_decrement_op_vec(<2 x i8> %x) {
699 ; CHECK-LABEL: @is_pow2_decrement_op_vec(
700 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
701 ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], <i8 1, i8 1>
702 ; CHECK-NEXT: ret <2 x i1> [[R]]
704 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
705 %and = and <2 x i8> %dec, %x
706 %cmp = icmp eq <2 x i8> %and, zeroinitializer
707 %notzero = icmp ne <2 x i8> %x, zeroinitializer
708 %r = and <2 x i1> %notzero, %cmp
712 define i1 @isnot_pow2_negate_op(i32 %x) {
713 ; CHECK-LABEL: @isnot_pow2_negate_op(
714 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
715 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 1
716 ; CHECK-NEXT: ret i1 [[R]]
719 %and = and i32 %neg, %x
720 %cmp = icmp ne i32 %and, %x
721 %iszero = icmp eq i32 %x, 0
722 %r = or i1 %cmp, %iszero
726 define i1 @isnot_pow2_negate_op_logical(i32 %x) {
727 ; CHECK-LABEL: @isnot_pow2_negate_op_logical(
728 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
729 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 1
730 ; CHECK-NEXT: ret i1 [[R]]
733 %and = and i32 %neg, %x
734 %cmp = icmp ne i32 %and, %x
735 %iszero = icmp eq i32 %x, 0
736 %r = select i1 %cmp, i1 true, i1 %iszero
740 define <2 x i1> @isnot_pow2_negate_op_vec(<2 x i32> %x) {
741 ; CHECK-LABEL: @isnot_pow2_negate_op_vec(
742 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]), !range [[RNG0]]
743 ; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 1, i32 1>
744 ; CHECK-NEXT: ret <2 x i1> [[R]]
746 %neg = sub <2 x i32> zeroinitializer, %x
747 %and = and <2 x i32> %neg, %x
748 %cmp = icmp ne <2 x i32> %and, %x
749 %iszero = icmp eq <2 x i32> %x, zeroinitializer
750 %r = or <2 x i1> %iszero, %cmp
754 define i1 @isnot_pow2_decrement_op(i8 %x) {
755 ; CHECK-LABEL: @isnot_pow2_decrement_op(
756 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
757 ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP1]], 1
758 ; CHECK-NEXT: ret i1 [[R]]
761 %and = and i8 %dec, %x
762 %cmp = icmp ne i8 %and, 0
763 %iszero = icmp eq i8 %x, 0
764 %r = or i1 %iszero, %cmp
768 define i1 @isnot_pow2_decrement_op_logical(i8 %x) {
769 ; CHECK-LABEL: @isnot_pow2_decrement_op_logical(
770 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
771 ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP1]], 1
772 ; CHECK-NEXT: ret i1 [[R]]
775 %and = and i8 %dec, %x
776 %cmp = icmp ne i8 %and, 0
777 %iszero = icmp eq i8 %x, 0
778 %r = select i1 %iszero, i1 true, i1 %cmp
782 define <2 x i1> @isnot_pow2_decrement_op_vec(<2 x i8> %x) {
783 ; CHECK-LABEL: @isnot_pow2_decrement_op_vec(
784 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
785 ; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[TMP1]], <i8 1, i8 1>
786 ; CHECK-NEXT: ret <2 x i1> [[R]]
788 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
789 %and = and <2 x i8> %dec, %x
790 %cmp = icmp ne <2 x i8> %and, zeroinitializer
791 %iszero = icmp eq <2 x i8> %x, zeroinitializer
792 %r = or <2 x i1> %cmp, %iszero
796 ; (ctpop(X) == 1) || (X == 0) --> ctpop(X) u< 2
798 define i1 @is_pow2or0_ctpop(i32 %x) {
799 ; CHECK-LABEL: @is_pow2or0_ctpop(
800 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
801 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[T0]], 2
802 ; CHECK-NEXT: ret i1 [[R]]
804 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
805 %cmp = icmp eq i32 %t0, 1
806 %iszero = icmp eq i32 %x, 0
807 %r = or i1 %iszero, %cmp
811 define i1 @is_pow2or0_ctpop_swap_cmp(i32 %x) {
812 ; CHECK-LABEL: @is_pow2or0_ctpop_swap_cmp(
813 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
814 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[T0]], 2
815 ; CHECK-NEXT: ret i1 [[R]]
817 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
818 %cmp = icmp eq i32 %t0, 1
819 %iszero = icmp eq i32 %x, 0
820 %r = or i1 %cmp, %iszero
824 define i1 @is_pow2or0_ctpop_logical(i32 %x) {
825 ; CHECK-LABEL: @is_pow2or0_ctpop_logical(
826 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
827 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[T0]], 2
828 ; CHECK-NEXT: ret i1 [[R]]
830 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
831 %cmp = icmp eq i32 %t0, 1
832 %iszero = icmp eq i32 %x, 0
833 %r = select i1 %iszero, i1 true, i1 %cmp
837 define <2 x i1> @is_pow2or0_ctpop_commute_vec(<2 x i8> %x) {
838 ; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec(
839 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
840 ; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[T0]], <i8 2, i8 2>
841 ; CHECK-NEXT: ret <2 x i1> [[R]]
843 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
844 %cmp = icmp eq <2 x i8> %t0, <i8 1, i8 1>
845 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0>
846 %r = or <2 x i1> %iszero, %cmp
850 ; Extra uses don't change the fold.
852 define i1 @is_pow2or0_ctpop_extra_uses(i32 %x) {
853 ; CHECK-LABEL: @is_pow2or0_ctpop_extra_uses(
854 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
855 ; CHECK-NEXT: call void @use(i32 [[T0]])
856 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
857 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
858 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
859 ; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])
860 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[T0]], 2
861 ; CHECK-NEXT: ret i1 [[R]]
863 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
864 call void @use(i32 %t0)
865 %cmp = icmp eq i32 %t0, 1
866 call void @use_i1(i1 %cmp)
867 %iszero = icmp eq i32 %x, 0
868 call void @use_i1(i1 %iszero)
869 %r = or i1 %iszero, %cmp
873 define i1 @is_pow2or0_ctpop_logical_extra_uses(i32 %x) {
874 ; CHECK-LABEL: @is_pow2or0_ctpop_logical_extra_uses(
875 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
876 ; CHECK-NEXT: call void @use(i32 [[T0]])
877 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
878 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
879 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
880 ; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])
881 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[T0]], 2
882 ; CHECK-NEXT: ret i1 [[R]]
884 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
885 call void @use(i32 %t0)
886 %cmp = icmp eq i32 %t0, 1
887 call void @use_i1(i1 %cmp)
888 %iszero = icmp eq i32 %x, 0
889 call void @use_i1(i1 %iszero)
890 %r = select i1 %iszero, i1 true, i1 %cmp
894 ; Negative test - wrong constant.
896 define i1 @is_pow2or0_ctpop_wrong_cmp_op1(i32 %x) {
897 ; CHECK-LABEL: @is_pow2or0_ctpop_wrong_cmp_op1(
898 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
899 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 2
900 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
901 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
902 ; CHECK-NEXT: ret i1 [[R]]
904 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
905 %cmp = icmp eq i32 %t0, 2
906 %iszero = icmp eq i32 %x, 0
907 %r = or i1 %iszero, %cmp
911 define i1 @is_pow2or0_ctpop_wrong_cmp_op1_logical(i32 %x) {
912 ; CHECK-LABEL: @is_pow2or0_ctpop_wrong_cmp_op1_logical(
913 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
914 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 3
915 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
916 ; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]
917 ; CHECK-NEXT: ret i1 [[R]]
919 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
920 %cmp = icmp eq i32 %t0, 3
921 %iszero = icmp eq i32 %x, 0
922 %r = select i1 %iszero, i1 true, i1 %cmp
926 define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {
927 ; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1(
928 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
929 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[T0]], <i8 -1, i8 1>
930 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
931 ; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP]], [[ISZERO]]
932 ; CHECK-NEXT: ret <2 x i1> [[R]]
934 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
935 %cmp = icmp eq <2 x i8> %t0, <i8 -1, i8 1>
936 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0>
937 %r = or <2 x i1> %cmp, %iszero
941 ; Negative test - wrong predicate.
943 define i1 @is_pow2or0_ctpop_wrong_pred1(i32 %x) {
944 ; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred1(
945 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
946 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1
947 ; CHECK-NEXT: ret i1 [[CMP]]
949 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
950 %cmp = icmp ne i32 %t0, 1
951 %iszero = icmp eq i32 %x, 0
952 %r = or i1 %iszero, %cmp
956 define i1 @is_pow2or0_ctpop_wrong_pred2(i32 %x) {
957 ; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2(
958 ; CHECK-NEXT: ret i1 true
960 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
961 %cmp = icmp ne i32 %t0, 1
962 %iszero = icmp ne i32 %x, 0
963 %r = or i1 %iszero, %cmp
967 define i1 @is_pow2or0_ctpop_wrong_pred2_logical(i32 %x) {
968 ; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2_logical(
969 ; CHECK-NEXT: ret i1 true
971 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
972 %cmp = icmp ne i32 %t0, 1
973 %iszero = icmp ne i32 %x, 0
974 %r = select i1 %iszero, i1 true, i1 %cmp
978 define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_pred3(<2 x i8> %x) {
979 ; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec_wrong_pred3(
980 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
981 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[T0]], <i8 1, i8 1>
982 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
983 ; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP]], [[ISZERO]]
984 ; CHECK-NEXT: ret <2 x i1> [[R]]
986 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
987 %cmp = icmp eq <2 x i8> %t0, <i8 1, i8 1>
988 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0>
989 %r = and <2 x i1> %cmp, %iszero
993 ; (ctpop(X) != 1) && (X != 0) --> ctpop(X) u> 1
995 define i1 @isnot_pow2nor0_ctpop(i32 %x) {
996 ; CHECK-LABEL: @isnot_pow2nor0_ctpop(
997 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
998 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[T0]], 1
999 ; CHECK-NEXT: ret i1 [[R]]
1001 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1002 %cmp = icmp ne i32 %t0, 1
1003 %notzero = icmp ne i32 %x, 0
1004 %r = and i1 %notzero, %cmp
1008 define i1 @isnot_pow2nor0_ctpop_swap_cmp(i32 %x) {
1009 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_swap_cmp(
1010 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1011 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[T0]], 1
1012 ; CHECK-NEXT: ret i1 [[R]]
1014 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1015 %cmp = icmp ne i32 %t0, 1
1016 %notzero = icmp ne i32 %x, 0
1017 %r = and i1 %cmp, %notzero
1021 define i1 @isnot_pow2nor0_ctpop_logical(i32 %x) {
1022 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_logical(
1023 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1024 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[T0]], 1
1025 ; CHECK-NEXT: ret i1 [[R]]
1027 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1028 %cmp = icmp ne i32 %t0, 1
1029 %notzero = icmp ne i32 %x, 0
1030 %r = select i1 %notzero, i1 %cmp, i1 false
1034 define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec(<2 x i8> %x) {
1035 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_commute_vec(
1036 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
1037 ; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[T0]], <i8 1, i8 1>
1038 ; CHECK-NEXT: ret <2 x i1> [[R]]
1040 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
1041 %cmp = icmp ne <2 x i8> %t0, <i8 1, i8 1>
1042 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0>
1043 %r = and <2 x i1> %notzero, %cmp
1047 ; Extra uses don't change the fold.
1049 define i1 @isnot_pow2nor0_ctpop_extra_uses(i32 %x) {
1050 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_extra_uses(
1051 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1052 ; CHECK-NEXT: call void @use(i32 [[T0]])
1053 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1
1054 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
1055 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
1056 ; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])
1057 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[T0]], 1
1058 ; CHECK-NEXT: ret i1 [[R]]
1060 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1061 call void @use(i32 %t0)
1062 %cmp = icmp ne i32 %t0, 1
1063 call void @use_i1(i1 %cmp)
1064 %notzero = icmp ne i32 %x, 0
1065 call void @use_i1(i1 %notzero)
1066 %r = and i1 %notzero, %cmp
1070 define i1 @isnot_pow2nor0_ctpop_logical_extra_uses(i32 %x) {
1071 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_logical_extra_uses(
1072 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1073 ; CHECK-NEXT: call void @use(i32 [[T0]])
1074 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1
1075 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
1076 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
1077 ; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])
1078 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[T0]], 1
1079 ; CHECK-NEXT: ret i1 [[R]]
1081 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1082 call void @use(i32 %t0)
1083 %cmp = icmp ne i32 %t0, 1
1084 call void @use_i1(i1 %cmp)
1085 %notzero = icmp ne i32 %x, 0
1086 call void @use_i1(i1 %notzero)
1087 %r = select i1 %notzero, i1 %cmp, i1 false
1091 ; Negative test - wrong constant.
1093 define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1(i32 %x) {
1094 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_cmp_op1(
1095 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1096 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 4
1097 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
1098 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
1099 ; CHECK-NEXT: ret i1 [[R]]
1101 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1102 %cmp = icmp ne i32 %t0, 4
1103 %notzero = icmp ne i32 %x, 0
1104 %r = and i1 %notzero, %cmp
1108 define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical(i32 %x) {
1109 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical(
1110 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1111 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 5
1112 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
1113 ; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false
1114 ; CHECK-NEXT: ret i1 [[R]]
1116 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1117 %cmp = icmp ne i32 %t0, 5
1118 %notzero = icmp ne i32 %x, 0
1119 %r = select i1 %notzero, i1 %cmp, i1 false
1123 define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {
1124 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1(
1125 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
1126 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[T0]], <i8 0, i8 -1>
1127 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne <2 x i8> [[X]], zeroinitializer
1128 ; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP]], [[NOTZERO]]
1129 ; CHECK-NEXT: ret <2 x i1> [[R]]
1131 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
1132 %cmp = icmp ne <2 x i8> %t0, <i8 0, i8 -1>
1133 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0>
1134 %r = and <2 x i1> %cmp, %notzero
1138 ; Negative test - wrong predicate.
1140 define i1 @isnot_pow2nor0_ctpop_wrong_pred1(i32 %x) {
1141 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred1(
1142 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1143 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
1144 ; CHECK-NEXT: ret i1 [[CMP]]
1146 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1147 %cmp = icmp eq i32 %t0, 1
1148 %notzero = icmp ne i32 %x, 0
1149 %r = and i1 %notzero, %cmp
1153 define i1 @isnot_pow2nor0_ctpop_wrong_pred2(i32 %x) {
1154 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2(
1155 ; CHECK-NEXT: ret i1 false
1157 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1158 %cmp = icmp eq i32 %t0, 1
1159 %notzero = icmp eq i32 %x, 0
1160 %r = and i1 %notzero, %cmp
1164 define i1 @isnot_pow2nor0_ctpop_wrong_pred2_logical(i32 %x) {
1165 ; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2_logical(
1166 ; CHECK-NEXT: ret i1 false
1168 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
1169 %cmp = icmp eq i32 %t0, 1
1170 %notzero = icmp eq i32 %x, 0
1171 %r = select i1 %notzero, i1 %cmp, i1 false
1175 define <2 x i1> @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(<2 x i8> %x) {
1176 ; CHECK-LABEL: @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(
1177 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]), !range [[RNG1]]
1178 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[T0]], <i8 1, i8 1>
1179 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne <2 x i8> [[X]], zeroinitializer
1180 ; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP]], [[NOTZERO]]
1181 ; CHECK-NEXT: ret <2 x i1> [[R]]
1183 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
1184 %cmp = icmp ne <2 x i8> %t0, <i8 1, i8 1>
1185 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0>
1186 %r = or <2 x i1> %cmp, %notzero
1190 define i1 @is_pow2_fail_pr63327(i32 %x) {
1191 ; CHECK-LABEL: @is_pow2_fail_pr63327(
1192 ; CHECK-NEXT: [[NX:%.*]] = sub i32 0, [[X:%.*]]
1193 ; CHECK-NEXT: [[X_AND_NX:%.*]] = and i32 [[NX]], [[X]]
1194 ; CHECK-NEXT: [[R:%.*]] = icmp sge i32 [[X_AND_NX]], [[X]]
1195 ; CHECK-NEXT: ret i1 [[R]]
1198 %x_and_nx = and i32 %x, %nx
1199 %r = icmp sge i32 %x_and_nx, %x
1203 define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) {
1204 ; CHECK-LABEL: @blsmsk_is_p2_or_z(
1205 ; CHECK-NEXT: [[X:%.*]] = or i32 [[XX:%.*]], [[YY:%.*]]
1206 ; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X]], -1
1207 ; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X]], [[XM1]]
1208 ; CHECK-NEXT: [[R:%.*]] = icmp uge i32 [[X]], [[Y]]
1209 ; CHECK-NEXT: ret i1 [[R]]
1211 %x = or i32 %xx, %yy
1212 %xm1 = add i32 %x, -1
1213 %y = xor i32 %x, %xm1
1214 %r = icmp uge i32 %x, %y
1218 define i1 @blsmsk_isnt_p2_or_z(i32 %x) {
1219 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z(
1220 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
1221 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[TMP1]], 1
1222 ; CHECK-NEXT: ret i1 [[R]]
1224 %xm1 = add i32 %x, -1
1225 %y = xor i32 %x, %xm1
1226 %r = icmp ult i32 %y, %x
1230 define i1 @blsmsk_is_p2_or_z_fail(i32 %xx, i32 %yy) {
1231 ; CHECK-LABEL: @blsmsk_is_p2_or_z_fail(
1232 ; CHECK-NEXT: [[X:%.*]] = or i32 [[XX:%.*]], [[YY:%.*]]
1233 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]]
1234 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[TMP1]], 1
1235 ; CHECK-NEXT: ret i1 [[R]]
1237 %x = or i32 %xx, %yy
1238 %xm1 = add i32 %x, -1
1239 %y = xor i32 %x, %xm1
1240 %r = icmp ugt i32 %x, %y
1244 define i1 @blsmsk_isnt_p2_or_z_fail(i32 %x) {
1245 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail(
1246 ; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -1
1247 ; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[X]]
1248 ; CHECK-NEXT: [[R:%.*]] = icmp ule i32 [[Y]], [[X]]
1249 ; CHECK-NEXT: ret i1 [[R]]
1251 %xm1 = add i32 %x, -1
1252 %y = xor i32 %x, %xm1
1253 %r = icmp ule i32 %y, %x
1257 declare void @use.i32(i32)
1259 define i1 @blsmsk_isnt_p2_or_z_fail_multiuse(i32 %x) {
1260 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail_multiuse(
1261 ; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -1
1262 ; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[X]]
1263 ; CHECK-NEXT: call void @use.i32(i32 [[Y]])
1264 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]]
1265 ; CHECK-NEXT: ret i1 [[R]]
1267 %xm1 = add i32 %x, -1
1268 %y = xor i32 %x, %xm1
1269 call void @use.i32(i32 %y)
1270 %r = icmp ult i32 %y, %x
1274 define i1 @blsmsk_isnt_p2_or_z_fail_wrong_add(i32 %x, i32 %z) {
1275 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail_wrong_add(
1276 ; CHECK-NEXT: [[XM1:%.*]] = add i32 [[Z:%.*]], -1
1277 ; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[X:%.*]]
1278 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]]
1279 ; CHECK-NEXT: ret i1 [[R]]
1281 %xm1 = add i32 %z, -1
1282 %y = xor i32 %x, %xm1
1283 %r = icmp ult i32 %y, %x
1288 define i1 @blsmsk_isnt_p2_or_z_fail_bad_xor(i32 %x, i32 %z) {
1289 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail_bad_xor(
1290 ; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -1
1291 ; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[Z:%.*]]
1292 ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]]
1293 ; CHECK-NEXT: ret i1 [[R]]
1295 %xm1 = add i32 %x, -1
1296 %y = xor i32 %z, %xm1
1297 %r = icmp ult i32 %y, %x
1302 define i1 @blsmsk_is_p2_or_z_fail_bad_cmp(i32 %x, i32 %z) {
1303 ; CHECK-LABEL: @blsmsk_is_p2_or_z_fail_bad_cmp(
1304 ; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -1
1305 ; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[X]]
1306 ; CHECK-NEXT: [[R:%.*]] = icmp uge i32 [[Y]], [[Z:%.*]]
1307 ; CHECK-NEXT: ret i1 [[R]]
1309 %xm1 = add i32 %x, -1
1310 %y = xor i32 %x, %xm1
1311 %r = icmp uge i32 %y, %z
1315 define i1 @blsmsk_is_p2_or_z_ule_xy(i8 %xx, i8 %yy) {
1316 ; CHECK-LABEL: @blsmsk_is_p2_or_z_ule_xy(
1317 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1318 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X]]), !range [[RNG1]]
1319 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[TMP1]], 2
1320 ; CHECK-NEXT: ret i1 [[R]]
1323 %xm1 = add i8 %x, -1
1324 %y = xor i8 %x, %xm1
1325 %r = icmp ule i8 %x, %y
1330 define i1 @blsmsk_is_p2_or_z_ule_yx_fail(i8 %xx, i8 %yy) {
1331 ; CHECK-LABEL: @blsmsk_is_p2_or_z_ule_yx_fail(
1332 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1333 ; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -1
1334 ; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]
1335 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[Y]], [[X]]
1336 ; CHECK-NEXT: ret i1 [[R]]
1339 %xm1 = add i8 %x, -1
1340 %y = xor i8 %x, %xm1
1341 %r = icmp ule i8 %y, %x
1346 define i1 @blsmsk_is_p2_or_z_uge_yx(i8 %xx, i8 %yy) {
1347 ; CHECK-LABEL: @blsmsk_is_p2_or_z_uge_yx(
1348 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1349 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X]]), !range [[RNG1]]
1350 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[TMP1]], 2
1351 ; CHECK-NEXT: ret i1 [[R]]
1354 %xm1 = add i8 %x, -1
1355 %y = xor i8 %x, %xm1
1356 %r = icmp uge i8 %y, %x
1361 define i1 @blsmsk_is_p2_or_z_uge_xy_fail(i8 %xx, i8 %yy) {
1362 ; CHECK-LABEL: @blsmsk_is_p2_or_z_uge_xy_fail(
1363 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1364 ; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -1
1365 ; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]
1366 ; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[X]], [[Y]]
1367 ; CHECK-NEXT: ret i1 [[R]]
1370 %xm1 = add i8 %x, -1
1371 %y = xor i8 %x, %xm1
1372 %r = icmp uge i8 %x, %y
1376 define i1 @blsmsk_isnt_p2_or_z_ugt_xy(i8 %xx, i8 %yy) {
1377 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ugt_xy(
1378 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1379 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X]]), !range [[RNG1]]
1380 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[TMP1]], 1
1381 ; CHECK-NEXT: ret i1 [[R]]
1384 %xm1 = add i8 %x, -1
1385 %y = xor i8 %x, %xm1
1386 %r = icmp ugt i8 %x, %y
1391 define i1 @blsmsk_isnt_p2_or_z_ugt_yx_fail(i8 %xx, i8 %yy) {
1392 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ugt_yx_fail(
1393 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1394 ; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -1
1395 ; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]
1396 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[Y]], [[X]]
1397 ; CHECK-NEXT: ret i1 [[R]]
1400 %xm1 = add i8 %x, -1
1401 %y = xor i8 %x, %xm1
1402 %r = icmp ugt i8 %y, %x
1407 define i1 @blsmsk_isnt_p2_or_z_ult_yx(i8 %xx, i8 %yy) {
1408 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ult_yx(
1409 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1410 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X]]), !range [[RNG1]]
1411 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[TMP1]], 1
1412 ; CHECK-NEXT: ret i1 [[R]]
1415 %xm1 = add i8 %x, -1
1416 %y = xor i8 %x, %xm1
1417 %r = icmp ult i8 %y, %x
1422 define i1 @blsmsk_isnt_p2_or_z_ult_xy_fail(i8 %xx, i8 %yy) {
1423 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ult_xy_fail(
1424 ; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]
1425 ; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -1
1426 ; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]
1427 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[X]], [[Y]]
1428 ; CHECK-NEXT: ret i1 [[R]]
1431 %xm1 = add i8 %x, -1
1432 %y = xor i8 %x, %xm1
1433 %r = icmp ult i8 %x, %y
1437 declare <2 x i32> @llvm.ctpop.2xi32(<2 x i32>)
1438 define i1 @is_pow2_nz_known_bits(i32 %xin) {
1439 ; CHECK-LABEL: @is_pow2_nz_known_bits(
1440 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[XIN:%.*]], -65
1441 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 0
1442 ; CHECK-NEXT: ret i1 [[R]]
1444 %x = or i32 %xin, 64
1445 %cnt = call i32 @llvm.ctpop.i32(i32 %x)
1446 %r = icmp eq i32 %cnt, 1
1450 define i1 @is_pow2_nz_known_bits_fail_multiuse(i32 %xin) {
1451 ; CHECK-LABEL: @is_pow2_nz_known_bits_fail_multiuse(
1452 ; CHECK-NEXT: [[X:%.*]] = or i32 [[XIN:%.*]], 64
1453 ; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG3:![0-9]+]]
1454 ; CHECK-NEXT: call void @use.i32(i32 [[CNT]])
1455 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[CNT]], 1
1456 ; CHECK-NEXT: ret i1 [[R]]
1458 %x = or i32 %xin, 64
1459 %cnt = call i32 @llvm.ctpop.i32(i32 %x)
1460 call void @use.i32(i32 %cnt)
1461 %r = icmp eq i32 %cnt, 1
1465 define i1 @not_pow2_nz_known_bits(i32 %xin) {
1466 ; CHECK-LABEL: @not_pow2_nz_known_bits(
1467 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[XIN:%.*]], 1
1468 ; CHECK-NEXT: ret i1 [[R]]
1471 %cnt = call i32 @llvm.ctpop.i32(i32 %x)
1472 %r = icmp ne i32 %cnt, 1
1476 define i1 @not_pow2_nz_known_bits_fail_not_p2_test(i32 %xin) {
1477 ; CHECK-LABEL: @not_pow2_nz_known_bits_fail_not_p2_test(
1478 ; CHECK-NEXT: [[X:%.*]] = or i32 [[XIN:%.*]], 1
1479 ; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG3]]
1480 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[CNT]], 2
1481 ; CHECK-NEXT: ret i1 [[R]]
1484 %cnt = call i32 @llvm.ctpop.i32(i32 %x)
1485 %r = icmp ne i32 %cnt, 2
1489 define i1 @is_pow2_or_z_known_bits(i32 %xin) {
1490 ; CHECK-LABEL: @is_pow2_or_z_known_bits(
1491 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[XIN:%.*]], 2147483647
1492 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 0
1493 ; CHECK-NEXT: ret i1 [[R]]
1495 %x = or i32 %xin, 2147483648
1496 %cnt = call i32 @llvm.ctpop.i32(i32 %x)
1497 %r = icmp ult i32 %cnt, 2
1501 define <2 x i1> @not_pow2_or_z_known_bits(<2 x i32> %xin) {
1502 ; CHECK-LABEL: @not_pow2_or_z_known_bits(
1503 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[XIN:%.*]], <i32 -65, i32 -65>
1504 ; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
1505 ; CHECK-NEXT: ret <2 x i1> [[R]]
1507 %x = or <2 x i32> %xin, <i32 64, i32 64>
1508 %cnt = call <2 x i32> @llvm.ctpop.2xi32(<2 x i32> %x)
1509 %r = icmp ugt <2 x i32> %cnt, <i32 1, i32 1>
1513 define <2 x i1> @not_pow2_or_z_known_bits_fail_wrong_cmp(<2 x i32> %xin) {
1514 ; CHECK-LABEL: @not_pow2_or_z_known_bits_fail_wrong_cmp(
1515 ; CHECK-NEXT: [[X:%.*]] = or <2 x i32> [[XIN:%.*]], <i32 64, i32 64>
1516 ; CHECK-NEXT: [[CNT:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X]]), !range [[RNG3]]
1517 ; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i32> [[CNT]], <i32 2, i32 2>
1518 ; CHECK-NEXT: ret <2 x i1> [[R]]
1520 %x = or <2 x i32> %xin, <i32 64, i32 64>
1521 %cnt = call <2 x i32> @llvm.ctpop.2xi32(<2 x i32> %x)
1522 %r = icmp ugt <2 x i32> %cnt, <i32 2, i32 2>