Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / ispow2.ll
blobcc50c5cd1e6680a8353087ddfaa3c50f49c76808
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]]
10   %neg = sub i32 0, %x
11   %and = and i32 %neg, %x
12   %cmp = icmp eq i32 %and, %x
13   ret i1 %cmp
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
25   ret <2 x i1> %cmp
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]]
34   %dec = add i8 %x, -1
35   %and = and i8 %dec, %x
36   %cmp = icmp eq i8 %and, 0
37   ret i1 %cmp
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
49   ret <2 x i1> %cmp
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]]
58   %neg = sub i32 0, %x
59   %and = and i32 %neg, %x
60   %cmp = icmp ne i32 %and, %x
61   ret i1 %cmp
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
73   ret <2 x i1> %cmp
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]]
82   %dec = add i8 %x, -1
83   %and = and i8 %dec, %x
84   %cmp = icmp ne i8 %and, 0
85   ret i1 %cmp
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
97   ret <2 x i1> %cmp
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
108   %neg = sub i32 0, %x
109   %and = and i32 %x, %neg
110   %cmp = icmp eq i32 %and, %x
111   ret i1 %cmp
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
124   %neg = sub i32 0, %x
125   %and = and i32 %neg, %x
126   %cmp = icmp ne i32 %x, %and
127   ret i1 %cmp
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
138   %neg = sub i32 0, %x
139   %and = and i32 %x, %neg
140   %cmp = icmp ne i32 %x, %and
141   ret i1 %cmp
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]]
154   %neg = sub i32 0, %x
155   call void @use(i32 %neg)
156   %and = and i32 %neg, %x
157   %cmp = icmp eq i32 %and, %x
158   ret i1 %cmp
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]]
169   %neg = sub i32 0, %x
170   %and = and i32 %neg, %x
171   call void @use(i32 %and)
172   %cmp = icmp eq i32 %and, %x
173   ret i1 %cmp
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
192   ret i1 %r
195 ; tests from PR57328
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
208   ret i1 %cmp
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
223   ret i1 %cmp
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
238   ret i1 %cmp
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
253   ret i1 %cmp
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
266   ret i1 %r
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
288   ret i1 %r
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
307   ret i1 %r
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
322   ret <2 x i1> %r
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
339   ret i1 %r
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
354   ret i1 %r
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
371   ret i1 %r
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
386   ret i1 %r
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
401   ret i1 %r
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
414   ret i1 %r
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
431   ret i1 %r
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
446   ret i1 %r
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
461   ret i1 %r
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
474   ret i1 %r
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
495   ret i1 %r
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
514   ret i1 %r
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
529   ret <2 x i1> %r
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
546   ret i1 %r
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
561   ret i1 %r
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
578   ret i1 %r
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
593   ret i1 %r
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
610   ret i1 %r
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
625   ret i1 %r
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]]
634   %neg = sub i32 0, %x
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
639   ret i1 %r
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]]
648   %neg = sub i32 0, %x
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
653   ret i1 %r
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
667   ret <2 x i1> %r
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]]
676   %dec = add i8 %x, -1
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
681   ret i1 %r
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]]
690   %dec = add i8 %x, -1
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
695   ret i1 %r
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
709   ret <2 x i1> %r
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]]
718   %neg = sub i32 0, %x
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
723   ret i1 %r
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]]
732   %neg = sub i32 0, %x
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
737   ret i1 %r
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
751   ret <2 x i1> %r
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]]
760   %dec = add i8 %x, -1
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
765   ret i1 %r
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]]
774   %dec = add i8 %x, -1
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
779   ret i1 %r
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
793   ret <2 x i1> %r
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
808   ret i1 %r
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
821   ret i1 %r
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
834   ret i1 %r
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
847   ret <2 x i1> %r
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
870   ret i1 %r
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
891   ret i1 %r
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
908   ret i1 %r
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
923   ret i1 %r
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
938   ret <2 x i1> %r
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
953   ret i1 %r
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
964   ret i1 %r
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
975   ret i1 %r
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
990   ret <2 x i1> %r
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
1005   ret i1 %r
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
1018   ret i1 %r
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
1031   ret i1 %r
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
1044   ret <2 x i1> %r
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
1067   ret i1 %r
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
1088   ret i1 %r
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
1105   ret i1 %r
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
1120   ret i1 %r
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
1135   ret <2 x i1> %r
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
1150   ret i1 %r
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
1161   ret i1 %r
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
1172   ret i1 %r
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
1187   ret <2 x i1> %r
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]]
1197   %nx = sub i32 0, %x
1198   %x_and_nx = and i32 %x, %nx
1199   %r = icmp sge i32 %x_and_nx, %x
1200   ret i1 %r
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
1215   ret i1 %r
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
1227   ret i1 %r
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
1241   ret i1 %r
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
1254   ret i1 %r
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
1271   ret i1 %r
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
1284   ret i1 %r
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
1298   ret i1 %r
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
1312   ret i1 %r
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]]
1322   %x = or i8 %xx, %yy
1323   %xm1 = add i8 %x, -1
1324   %y = xor i8 %x, %xm1
1325   %r = icmp ule i8 %x, %y
1326   ret i1 %r
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]]
1338   %x = or i8 %xx, %yy
1339   %xm1 = add i8 %x, -1
1340   %y = xor i8 %x, %xm1
1341   %r = icmp ule i8 %y, %x
1342   ret i1 %r
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]]
1353   %x = or i8 %xx, %yy
1354   %xm1 = add i8 %x, -1
1355   %y = xor i8 %x, %xm1
1356   %r = icmp uge i8 %y, %x
1357   ret i1 %r
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]]
1369   %x = or i8 %xx, %yy
1370   %xm1 = add i8 %x, -1
1371   %y = xor i8 %x, %xm1
1372   %r = icmp uge i8 %x, %y
1373   ret i1 %r
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]]
1383   %x = or i8 %xx, %yy
1384   %xm1 = add i8 %x, -1
1385   %y = xor i8 %x, %xm1
1386   %r = icmp ugt i8 %x, %y
1387   ret i1 %r
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]]
1399   %x = or i8 %xx, %yy
1400   %xm1 = add i8 %x, -1
1401   %y = xor i8 %x, %xm1
1402   %r = icmp ugt i8 %y, %x
1403   ret i1 %r
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]]
1414   %x = or i8 %xx, %yy
1415   %xm1 = add i8 %x, -1
1416   %y = xor i8 %x, %xm1
1417   %r = icmp ult i8 %y, %x
1418   ret i1 %r
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]]
1430   %x = or i8 %xx, %yy
1431   %xm1 = add i8 %x, -1
1432   %y = xor i8 %x, %xm1
1433   %r = icmp ult i8 %x, %y
1434   ret i1 %r
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
1447   ret i1 %r
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
1462   ret i1 %r
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]]
1470   %x = or i32 %xin, 1
1471   %cnt = call i32 @llvm.ctpop.i32(i32 %x)
1472   %r = icmp ne i32 %cnt, 1
1473   ret i1 %r
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]]
1483   %x = or i32 %xin, 1
1484   %cnt = call i32 @llvm.ctpop.i32(i32 %x)
1485   %r = icmp ne i32 %cnt, 2
1486   ret i1 %r
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
1498   ret i1 %r
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>
1510   ret <2 x i1> %r
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>
1523   ret <2 x i1> %r