1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -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 !0
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:%.*]])
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 !1
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:%.*]])
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 !0
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:%.*]])
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 !1
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:%.*]])
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 !2
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 !3
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 !3
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 !0
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>)
179 ; (X != 0) && (ctpop(X) u< 2) --> ctpop(X) == 1
181 define i1 @is_pow2_ctpop(i32 %x) {
182 ; CHECK-LABEL: @is_pow2_ctpop(
183 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
184 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1
185 ; CHECK-NEXT: ret i1 [[TMP1]]
187 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
188 %cmp = icmp ult i32 %t0, 2
189 %notzero = icmp ne i32 %x, 0
190 %r = and i1 %notzero, %cmp
194 ; Extra uses don't change the fold.
195 declare void @use_i1(i1)
197 define i1 @is_pow2_ctpop_extra_uses(i32 %x) {
198 ; CHECK-LABEL: @is_pow2_ctpop_extra_uses(
199 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
200 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
201 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
202 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
203 ; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])
204 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1
205 ; CHECK-NEXT: ret i1 [[TMP1]]
207 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
208 %cmp = icmp ult i32 %t0, 2
209 call void @use_i1(i1 %cmp)
210 %notzero = icmp ne i32 %x, 0
211 call void @use_i1(i1 %notzero)
212 %r = and i1 %notzero, %cmp
216 ; Test vector type and commuted 'and' operands.
218 define <2 x i1> @is_pow2_ctpop_commute_vec(<2 x i8> %x) {
219 ; CHECK-LABEL: @is_pow2_ctpop_commute_vec(
220 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
221 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[T0]], <i8 1, i8 1>
222 ; CHECK-NEXT: ret <2 x i1> [[TMP1]]
224 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
225 %cmp = icmp ult <2 x i8> %t0, <i8 2, i8 2>
226 %notzero = icmp ne <2 x i8> %x, zeroinitializer
227 %r = and <2 x i1> %cmp, %notzero
231 ; Negative test - wrong constant.
233 define i1 @is_pow2_ctpop_wrong_cmp_op1(i32 %x) {
234 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1(
235 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
236 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3
237 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
238 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
239 ; CHECK-NEXT: ret i1 [[R]]
241 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
242 %cmp = icmp ult i32 %t0, 3
243 %notzero = icmp ne i32 %x, 0
244 %r = and i1 %notzero, %cmp
248 ; Negative test - wrong constant.
250 define i1 @is_pow2_ctpop_wrong_cmp_op2(i32 %x) {
251 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2(
252 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
253 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
254 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1
255 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
256 ; CHECK-NEXT: ret i1 [[R]]
258 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
259 %cmp = icmp ult i32 %t0, 2
260 %notzero = icmp ne i32 %x, 1
261 %r = and i1 %notzero, %cmp
265 ; Negative test - wrong predicate.
267 define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) {
268 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1(
269 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
270 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
271 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
272 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
273 ; CHECK-NEXT: ret i1 [[R]]
275 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
276 %cmp = icmp ugt i32 %t0, 2
277 %notzero = icmp ne i32 %x, 0
278 %r = and i1 %notzero, %cmp
282 ; Negative test - wrong predicate.
284 define i1 @is_pow2_ctpop_wrong_pred2(i32 %x) {
285 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2(
286 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
287 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
288 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0
289 ; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]]
290 ; CHECK-NEXT: ret i1 [[R]]
292 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
293 %cmp = icmp ult i32 %t0, 2
294 %cmp2 = icmp sgt i32 %x, 0
295 %r = and i1 %cmp2, %cmp
299 ; (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
301 define i1 @isnot_pow2_ctpop(i32 %x) {
302 ; CHECK-LABEL: @isnot_pow2_ctpop(
303 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
304 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1
305 ; CHECK-NEXT: ret i1 [[TMP1]]
307 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
308 %cmp = icmp ugt i32 %t0, 1
309 %iszero = icmp eq i32 %x, 0
310 %r = or i1 %iszero, %cmp
314 ; Extra uses don't change the fold.
316 define i1 @isnot_pow2_ctpop_extra_uses(i32 %x) {
317 ; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses(
318 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
319 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
320 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
321 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
322 ; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])
323 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1
324 ; CHECK-NEXT: ret i1 [[TMP1]]
326 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
327 %cmp = icmp ugt i32 %t0, 1
328 call void @use_i1(i1 %cmp)
329 %iszero = icmp eq i32 %x, 0
330 call void @use_i1(i1 %iszero)
331 %r = or i1 %iszero, %cmp
335 ; Test vector type and commuted 'or' operands.
337 define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) {
338 ; CHECK-LABEL: @isnot_pow2_ctpop_commute_vec(
339 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
340 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i8> [[T0]], <i8 1, i8 1>
341 ; CHECK-NEXT: ret <2 x i1> [[TMP1]]
343 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
344 %cmp = icmp ugt <2 x i8> %t0, <i8 1, i8 1>
345 %iszero = icmp eq <2 x i8> %x, zeroinitializer
346 %r = or <2 x i1> %cmp, %iszero
350 ; Negative test - wrong constant.
352 define i1 @isnot_pow2_ctpop_wrong_cmp_op1(i32 %x) {
353 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1(
354 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
355 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
356 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
357 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
358 ; CHECK-NEXT: ret i1 [[R]]
360 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
361 %cmp = icmp ugt i32 %t0, 2
362 %iszero = icmp eq i32 %x, 0
363 %r = or i1 %iszero, %cmp
367 ; Negative test - wrong constant.
369 define i1 @isnot_pow2_ctpop_wrong_cmp_op2(i32 %x) {
370 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2(
371 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
372 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
373 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1
374 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
375 ; CHECK-NEXT: ret i1 [[R]]
377 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
378 %cmp = icmp ugt i32 %t0, 1
379 %iszero = icmp eq i32 %x, 1
380 %r = or i1 %iszero, %cmp
384 ; Negative test - wrong predicate (but this could reduce).
386 define i1 @isnot_pow2_ctpop_wrong_pred1(i32 %x) {
387 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred1(
388 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
389 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
390 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
391 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
392 ; CHECK-NEXT: ret i1 [[R]]
394 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
395 %cmp = icmp eq i32 %t0, 1
396 %iszero = icmp eq i32 %x, 0
397 %r = or i1 %iszero, %cmp
401 ; Negative test - wrong predicate.
403 define i1 @isnot_pow2_ctpop_wrong_pred2(i32 %x) {
404 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2(
405 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
406 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
407 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0
408 ; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]]
409 ; CHECK-NEXT: ret i1 [[R]]
411 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
412 %cmp = icmp ugt i32 %t0, 1
413 %cmp2 = icmp slt i32 %x, 0
414 %r = or i1 %cmp2, %cmp
418 define i1 @is_pow2_negate_op(i32 %x) {
419 ; CHECK-LABEL: @is_pow2_negate_op(
420 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
421 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
422 ; CHECK-NEXT: ret i1 [[TMP2]]
425 %and = and i32 %neg, %x
426 %cmp = icmp eq i32 %and, %x
427 %notzero = icmp ne i32 %x, 0
428 %r = and i1 %notzero, %cmp
432 define <2 x i1> @is_pow2_negate_op_vec(<2 x i32> %x) {
433 ; CHECK-LABEL: @is_pow2_negate_op_vec(
434 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
435 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 1, i32 1>
436 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
438 %neg = sub <2 x i32> zeroinitializer, %x
439 %and = and <2 x i32> %neg, %x
440 %cmp = icmp eq <2 x i32> %and, %x
441 %notzero = icmp ne <2 x i32> %x, zeroinitializer
442 %r = and <2 x i1> %cmp, %notzero
446 define i1 @is_pow2_decrement_op(i8 %x) {
447 ; CHECK-LABEL: @is_pow2_decrement_op(
448 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range !1
449 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1
450 ; CHECK-NEXT: ret i1 [[TMP2]]
453 %and = and i8 %dec, %x
454 %cmp = icmp eq i8 %and, 0
455 %notzero = icmp ne i8 %x, 0
456 %r = and i1 %cmp, %notzero
460 define <2 x i1> @is_pow2_decrement_op_vec(<2 x i8> %x) {
461 ; CHECK-LABEL: @is_pow2_decrement_op_vec(
462 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
463 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i8> [[TMP1]], <i8 1, i8 1>
464 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
466 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
467 %and = and <2 x i8> %dec, %x
468 %cmp = icmp eq <2 x i8> %and, zeroinitializer
469 %notzero = icmp ne <2 x i8> %x, zeroinitializer
470 %r = and <2 x i1> %notzero, %cmp
474 define i1 @isnot_pow2_negate_op(i32 %x) {
475 ; CHECK-LABEL: @isnot_pow2_negate_op(
476 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range !0
477 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 1
478 ; CHECK-NEXT: ret i1 [[TMP2]]
481 %and = and i32 %neg, %x
482 %cmp = icmp ne i32 %and, %x
483 %iszero = icmp eq i32 %x, 0
484 %r = or i1 %cmp, %iszero
488 define <2 x i1> @isnot_pow2_negate_op_vec(<2 x i32> %x) {
489 ; CHECK-LABEL: @isnot_pow2_negate_op_vec(
490 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
491 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 1, i32 1>
492 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
494 %neg = sub <2 x i32> zeroinitializer, %x
495 %and = and <2 x i32> %neg, %x
496 %cmp = icmp ne <2 x i32> %and, %x
497 %iszero = icmp eq <2 x i32> %x, zeroinitializer
498 %r = or <2 x i1> %iszero, %cmp
502 define i1 @isnot_pow2_decrement_op(i8 %x) {
503 ; CHECK-LABEL: @isnot_pow2_decrement_op(
504 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range !1
505 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 1
506 ; CHECK-NEXT: ret i1 [[TMP2]]
509 %and = and i8 %dec, %x
510 %cmp = icmp ne i8 %and, 0
511 %iszero = icmp eq i8 %x, 0
512 %r = or i1 %iszero, %cmp
516 define <2 x i1> @isnot_pow2_decrement_op_vec(<2 x i8> %x) {
517 ; CHECK-LABEL: @isnot_pow2_decrement_op_vec(
518 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
519 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i8> [[TMP1]], <i8 1, i8 1>
520 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
522 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
523 %and = and <2 x i8> %dec, %x
524 %cmp = icmp ne <2 x i8> %and, zeroinitializer
525 %iszero = icmp eq <2 x i8> %x, zeroinitializer
526 %r = or <2 x i1> %cmp, %iszero