[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / InstCombine / ispow2.ll
blobf0d4a80ccfb04b7e19bc62c3d7e9ea417b9382d6
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]]
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:%.*]])
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 !1
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:%.*]])
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 !0
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:%.*]])
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 !1
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:%.*]])
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 !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
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 !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
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 !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
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 !0
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>)
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
191   ret i1 %r
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
213   ret i1 %r
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
228   ret <2 x i1> %r
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
245   ret i1 %r
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
262   ret i1 %r
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
279   ret i1 %r
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
296   ret i1 %r
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
311   ret i1 %r
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
332   ret i1 %r
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
347   ret <2 x i1> %r
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
364   ret i1 %r
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
381   ret i1 %r
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
398   ret i1 %r
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
415   ret i1 %r
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]]
424   %neg = sub i32 0, %x
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
429   ret i1 %r
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
443   ret <2 x i1> %r
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]]
452   %dec = add i8 %x, -1
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
457   ret i1 %r
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
471   ret <2 x i1> %r
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]]
480   %neg = sub i32 0, %x
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
485   ret i1 %r
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
499   ret <2 x i1> %r
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]]
508   %dec = add i8 %x, -1
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
513   ret i1 %r
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
527   ret <2 x i1> %r