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 [[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:%.*]])
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:%.*]])
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:%.*]])
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:%.*]])
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>)
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 [[RNG0]]
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 define i1 @is_pow2_ctpop_logical(i32 %x) {
195 ; CHECK-LABEL: @is_pow2_ctpop_logical(
196 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
197 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1
198 ; CHECK-NEXT: ret i1 [[TMP1]]
200 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
201 %cmp = icmp ult i32 %t0, 2
202 %notzero = icmp ne i32 %x, 0
203 %r = select i1 %notzero, i1 %cmp, i1 false
207 ; Extra uses don't change the fold.
208 declare void @use_i1(i1)
210 define i1 @is_pow2_ctpop_extra_uses(i32 %x) {
211 ; CHECK-LABEL: @is_pow2_ctpop_extra_uses(
212 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
213 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
214 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
215 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
216 ; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])
217 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1
218 ; CHECK-NEXT: ret i1 [[TMP1]]
220 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
221 %cmp = icmp ult i32 %t0, 2
222 call void @use_i1(i1 %cmp)
223 %notzero = icmp ne i32 %x, 0
224 call void @use_i1(i1 %notzero)
225 %r = and i1 %notzero, %cmp
229 define i1 @is_pow2_ctpop_extra_uses_logical(i32 %x) {
230 ; CHECK-LABEL: @is_pow2_ctpop_extra_uses_logical(
231 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
232 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
233 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
234 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
235 ; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])
236 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1
237 ; CHECK-NEXT: ret i1 [[TMP1]]
239 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
240 %cmp = icmp ult i32 %t0, 2
241 call void @use_i1(i1 %cmp)
242 %notzero = icmp ne i32 %x, 0
243 call void @use_i1(i1 %notzero)
244 %r = select i1 %notzero, i1 %cmp, i1 false
248 ; Test vector type and commuted 'and' operands.
250 define <2 x i1> @is_pow2_ctpop_commute_vec(<2 x i8> %x) {
251 ; CHECK-LABEL: @is_pow2_ctpop_commute_vec(
252 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
253 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[T0]], <i8 1, i8 1>
254 ; CHECK-NEXT: ret <2 x i1> [[TMP1]]
256 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
257 %cmp = icmp ult <2 x i8> %t0, <i8 2, i8 2>
258 %notzero = icmp ne <2 x i8> %x, zeroinitializer
259 %r = and <2 x i1> %cmp, %notzero
263 ; Negative test - wrong constant.
265 define i1 @is_pow2_ctpop_wrong_cmp_op1(i32 %x) {
266 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1(
267 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
268 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3
269 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
270 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
271 ; CHECK-NEXT: ret i1 [[R]]
273 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
274 %cmp = icmp ult i32 %t0, 3
275 %notzero = icmp ne i32 %x, 0
276 %r = and i1 %notzero, %cmp
280 define i1 @is_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
281 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1_logical(
282 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
283 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3
284 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
285 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
286 ; CHECK-NEXT: ret i1 [[R]]
288 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
289 %cmp = icmp ult i32 %t0, 3
290 %notzero = icmp ne i32 %x, 0
291 %r = select i1 %notzero, i1 %cmp, i1 false
295 ; Negative test - wrong constant.
297 define i1 @is_pow2_ctpop_wrong_cmp_op2(i32 %x) {
298 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2(
299 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
300 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
301 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1
302 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
303 ; CHECK-NEXT: ret i1 [[R]]
305 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
306 %cmp = icmp ult i32 %t0, 2
307 %notzero = icmp ne i32 %x, 1
308 %r = and i1 %notzero, %cmp
312 define i1 @is_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
313 ; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2_logical(
314 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
315 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
316 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1
317 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
318 ; CHECK-NEXT: ret i1 [[R]]
320 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
321 %cmp = icmp ult i32 %t0, 2
322 %notzero = icmp ne i32 %x, 1
323 %r = select i1 %notzero, i1 %cmp, i1 false
327 ; Negative test - wrong predicate.
329 define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) {
330 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1(
331 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
332 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
333 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
334 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
335 ; CHECK-NEXT: ret i1 [[R]]
337 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
338 %cmp = icmp ugt i32 %t0, 2
339 %notzero = icmp ne i32 %x, 0
340 %r = and i1 %notzero, %cmp
344 define i1 @is_pow2_ctpop_wrong_pred1_logical(i32 %x) {
345 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1_logical(
346 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
347 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
348 ; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
349 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
350 ; CHECK-NEXT: ret i1 [[R]]
352 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
353 %cmp = icmp ugt i32 %t0, 2
354 %notzero = icmp ne i32 %x, 0
355 %r = select i1 %notzero, i1 %cmp, i1 false
359 ; Negative test - wrong predicate.
361 define i1 @is_pow2_ctpop_wrong_pred2(i32 %x) {
362 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2(
363 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
364 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
365 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0
366 ; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]]
367 ; CHECK-NEXT: ret i1 [[R]]
369 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
370 %cmp = icmp ult i32 %t0, 2
371 %cmp2 = icmp sgt i32 %x, 0
372 %r = and i1 %cmp2, %cmp
376 define i1 @is_pow2_ctpop_wrong_pred2_logical(i32 %x) {
377 ; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2_logical(
378 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
379 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
380 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0
381 ; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]]
382 ; CHECK-NEXT: ret i1 [[R]]
384 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
385 %cmp = icmp ult i32 %t0, 2
386 %cmp2 = icmp sgt i32 %x, 0
387 %r = select i1 %cmp2, i1 %cmp, i1 false
391 ; (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
393 define i1 @isnot_pow2_ctpop(i32 %x) {
394 ; CHECK-LABEL: @isnot_pow2_ctpop(
395 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
396 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1
397 ; CHECK-NEXT: ret i1 [[TMP1]]
399 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
400 %cmp = icmp ugt i32 %t0, 1
401 %iszero = icmp eq i32 %x, 0
402 %r = or i1 %iszero, %cmp
406 define i1 @isnot_pow2_ctpop_logical(i32 %x) {
407 ; CHECK-LABEL: @isnot_pow2_ctpop_logical(
408 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
409 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1
410 ; CHECK-NEXT: ret i1 [[TMP1]]
412 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
413 %cmp = icmp ugt i32 %t0, 1
414 %iszero = icmp eq i32 %x, 0
415 %r = select i1 %iszero, i1 true, i1 %cmp
419 ; Extra uses don't change the fold.
421 define i1 @isnot_pow2_ctpop_extra_uses(i32 %x) {
422 ; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses(
423 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
424 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
425 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
426 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
427 ; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])
428 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1
429 ; CHECK-NEXT: ret i1 [[TMP1]]
431 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
432 %cmp = icmp ugt i32 %t0, 1
433 call void @use_i1(i1 %cmp)
434 %iszero = icmp eq i32 %x, 0
435 call void @use_i1(i1 %iszero)
436 %r = or i1 %iszero, %cmp
440 define i1 @isnot_pow2_ctpop_extra_uses_logical(i32 %x) {
441 ; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses_logical(
442 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
443 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
444 ; CHECK-NEXT: call void @use_i1(i1 [[CMP]])
445 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
446 ; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])
447 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1
448 ; CHECK-NEXT: ret i1 [[TMP1]]
450 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
451 %cmp = icmp ugt i32 %t0, 1
452 call void @use_i1(i1 %cmp)
453 %iszero = icmp eq i32 %x, 0
454 call void @use_i1(i1 %iszero)
455 %r = select i1 %iszero, i1 true, i1 %cmp
459 ; Test vector type and commuted 'or' operands.
461 define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) {
462 ; CHECK-LABEL: @isnot_pow2_ctpop_commute_vec(
463 ; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
464 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i8> [[T0]], <i8 1, i8 1>
465 ; CHECK-NEXT: ret <2 x i1> [[TMP1]]
467 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
468 %cmp = icmp ugt <2 x i8> %t0, <i8 1, i8 1>
469 %iszero = icmp eq <2 x i8> %x, zeroinitializer
470 %r = or <2 x i1> %cmp, %iszero
474 ; Negative test - wrong constant.
476 define i1 @isnot_pow2_ctpop_wrong_cmp_op1(i32 %x) {
477 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1(
478 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
479 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
480 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
481 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
482 ; CHECK-NEXT: ret i1 [[R]]
484 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
485 %cmp = icmp ugt i32 %t0, 2
486 %iszero = icmp eq i32 %x, 0
487 %r = or i1 %iszero, %cmp
491 define i1 @isnot_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
492 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1_logical(
493 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
494 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
495 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
496 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
497 ; CHECK-NEXT: ret i1 [[R]]
499 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
500 %cmp = icmp ugt i32 %t0, 2
501 %iszero = icmp eq i32 %x, 0
502 %r = select i1 %iszero, i1 true, i1 %cmp
506 ; Negative test - wrong constant.
508 define i1 @isnot_pow2_ctpop_wrong_cmp_op2(i32 %x) {
509 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2(
510 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
511 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
512 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1
513 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
514 ; CHECK-NEXT: ret i1 [[R]]
516 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
517 %cmp = icmp ugt i32 %t0, 1
518 %iszero = icmp eq i32 %x, 1
519 %r = or i1 %iszero, %cmp
523 define i1 @isnot_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
524 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2_logical(
525 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
526 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
527 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1
528 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
529 ; CHECK-NEXT: ret i1 [[R]]
531 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
532 %cmp = icmp ugt i32 %t0, 1
533 %iszero = icmp eq i32 %x, 1
534 %r = select i1 %iszero, i1 true, i1 %cmp
538 ; Negative test - wrong predicate (but this could reduce).
540 define i1 @isnot_pow2_ctpop_wrong_pred1(i32 %x) {
541 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred1(
542 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
543 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
544 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
545 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
546 ; CHECK-NEXT: ret i1 [[R]]
548 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
549 %cmp = icmp eq i32 %t0, 1
550 %iszero = icmp eq i32 %x, 0
551 %r = or i1 %iszero, %cmp
555 define i1 @isnot_pow2_ctpop_wrong_pred1_logical(i32 %x) {
556 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred1_logical(
557 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
558 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
559 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
560 ; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
561 ; CHECK-NEXT: ret i1 [[R]]
563 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
564 %cmp = icmp eq i32 %t0, 1
565 %iszero = icmp eq i32 %x, 0
566 %r = select i1 %iszero, i1 true, i1 %cmp
570 ; Negative test - wrong predicate.
572 define i1 @isnot_pow2_ctpop_wrong_pred2(i32 %x) {
573 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2(
574 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
575 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
576 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0
577 ; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]]
578 ; CHECK-NEXT: ret i1 [[R]]
580 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
581 %cmp = icmp ugt i32 %t0, 1
582 %cmp2 = icmp slt i32 %x, 0
583 %r = or i1 %cmp2, %cmp
587 define i1 @isnot_pow2_ctpop_wrong_pred2_logical(i32 %x) {
588 ; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2_logical(
589 ; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
590 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
591 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0
592 ; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]]
593 ; CHECK-NEXT: ret i1 [[R]]
595 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
596 %cmp = icmp ugt i32 %t0, 1
597 %cmp2 = icmp slt i32 %x, 0
598 %r = select i1 %cmp2, i1 true, i1 %cmp
602 define i1 @is_pow2_negate_op(i32 %x) {
603 ; CHECK-LABEL: @is_pow2_negate_op(
604 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
605 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
606 ; CHECK-NEXT: ret i1 [[TMP2]]
609 %and = and i32 %neg, %x
610 %cmp = icmp eq i32 %and, %x
611 %notzero = icmp ne i32 %x, 0
612 %r = and i1 %notzero, %cmp
616 define i1 @is_pow2_negate_op_logical(i32 %x) {
617 ; CHECK-LABEL: @is_pow2_negate_op_logical(
618 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
619 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
620 ; CHECK-NEXT: ret i1 [[TMP2]]
623 %and = and i32 %neg, %x
624 %cmp = icmp eq i32 %and, %x
625 %notzero = icmp ne i32 %x, 0
626 %r = select i1 %notzero, i1 %cmp, i1 false
630 define <2 x i1> @is_pow2_negate_op_vec(<2 x i32> %x) {
631 ; CHECK-LABEL: @is_pow2_negate_op_vec(
632 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
633 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 1, i32 1>
634 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
636 %neg = sub <2 x i32> zeroinitializer, %x
637 %and = and <2 x i32> %neg, %x
638 %cmp = icmp eq <2 x i32> %and, %x
639 %notzero = icmp ne <2 x i32> %x, zeroinitializer
640 %r = and <2 x i1> %cmp, %notzero
644 define i1 @is_pow2_decrement_op(i8 %x) {
645 ; CHECK-LABEL: @is_pow2_decrement_op(
646 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
647 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1
648 ; CHECK-NEXT: ret i1 [[TMP2]]
651 %and = and i8 %dec, %x
652 %cmp = icmp eq i8 %and, 0
653 %notzero = icmp ne i8 %x, 0
654 %r = and i1 %cmp, %notzero
658 define i1 @is_pow2_decrement_op_logical(i8 %x) {
659 ; CHECK-LABEL: @is_pow2_decrement_op_logical(
660 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
661 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1
662 ; CHECK-NEXT: ret i1 [[TMP2]]
665 %and = and i8 %dec, %x
666 %cmp = icmp eq i8 %and, 0
667 %notzero = icmp ne i8 %x, 0
668 %r = select i1 %cmp, i1 %notzero, i1 false
672 define <2 x i1> @is_pow2_decrement_op_vec(<2 x i8> %x) {
673 ; CHECK-LABEL: @is_pow2_decrement_op_vec(
674 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
675 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i8> [[TMP1]], <i8 1, i8 1>
676 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
678 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
679 %and = and <2 x i8> %dec, %x
680 %cmp = icmp eq <2 x i8> %and, zeroinitializer
681 %notzero = icmp ne <2 x i8> %x, zeroinitializer
682 %r = and <2 x i1> %notzero, %cmp
686 define i1 @isnot_pow2_negate_op(i32 %x) {
687 ; CHECK-LABEL: @isnot_pow2_negate_op(
688 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
689 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 1
690 ; CHECK-NEXT: ret i1 [[TMP2]]
693 %and = and i32 %neg, %x
694 %cmp = icmp ne i32 %and, %x
695 %iszero = icmp eq i32 %x, 0
696 %r = or i1 %cmp, %iszero
700 define i1 @isnot_pow2_negate_op_logical(i32 %x) {
701 ; CHECK-LABEL: @isnot_pow2_negate_op_logical(
702 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
703 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 1
704 ; CHECK-NEXT: ret i1 [[TMP2]]
707 %and = and i32 %neg, %x
708 %cmp = icmp ne i32 %and, %x
709 %iszero = icmp eq i32 %x, 0
710 %r = select i1 %cmp, i1 true, i1 %iszero
714 define <2 x i1> @isnot_pow2_negate_op_vec(<2 x i32> %x) {
715 ; CHECK-LABEL: @isnot_pow2_negate_op_vec(
716 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
717 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 1, i32 1>
718 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
720 %neg = sub <2 x i32> zeroinitializer, %x
721 %and = and <2 x i32> %neg, %x
722 %cmp = icmp ne <2 x i32> %and, %x
723 %iszero = icmp eq <2 x i32> %x, zeroinitializer
724 %r = or <2 x i1> %iszero, %cmp
728 define i1 @isnot_pow2_decrement_op(i8 %x) {
729 ; CHECK-LABEL: @isnot_pow2_decrement_op(
730 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
731 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 1
732 ; CHECK-NEXT: ret i1 [[TMP2]]
735 %and = and i8 %dec, %x
736 %cmp = icmp ne i8 %and, 0
737 %iszero = icmp eq i8 %x, 0
738 %r = or i1 %iszero, %cmp
742 define i1 @isnot_pow2_decrement_op_logical(i8 %x) {
743 ; CHECK-LABEL: @isnot_pow2_decrement_op_logical(
744 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]]
745 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 1
746 ; CHECK-NEXT: ret i1 [[TMP2]]
749 %and = and i8 %dec, %x
750 %cmp = icmp ne i8 %and, 0
751 %iszero = icmp eq i8 %x, 0
752 %r = select i1 %iszero, i1 true, i1 %cmp
756 define <2 x i1> @isnot_pow2_decrement_op_vec(<2 x i8> %x) {
757 ; CHECK-LABEL: @isnot_pow2_decrement_op_vec(
758 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
759 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i8> [[TMP1]], <i8 1, i8 1>
760 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
762 %dec = add <2 x i8> %x, <i8 -1, i8 -1>
763 %and = and <2 x i8> %dec, %x
764 %cmp = icmp ne <2 x i8> %and, zeroinitializer
765 %iszero = icmp eq <2 x i8> %x, zeroinitializer
766 %r = or <2 x i1> %cmp, %iszero