[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / InstCombine / ispow2.ll
blob7661f5850bfea01e5178b141e25538e0811f7a28
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]]
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 [[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:%.*]])
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:%.*]])
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:%.*]])
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>)
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
191   ret i1 %r
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
204   ret i1 %r
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
226   ret i1 %r
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
245   ret i1 %r
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
260   ret <2 x i1> %r
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
277   ret i1 %r
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
292   ret i1 %r
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
309   ret i1 %r
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
324   ret i1 %r
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
341   ret i1 %r
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
356   ret i1 %r
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
373   ret i1 %r
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
388   ret i1 %r
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
403   ret i1 %r
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
416   ret i1 %r
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
437   ret i1 %r
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
456   ret i1 %r
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
471   ret <2 x i1> %r
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
488   ret i1 %r
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
503   ret i1 %r
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
520   ret i1 %r
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
535   ret i1 %r
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
552   ret i1 %r
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
567   ret i1 %r
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
584   ret i1 %r
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
599   ret i1 %r
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]]
608   %neg = sub i32 0, %x
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
613   ret i1 %r
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]]
622   %neg = sub i32 0, %x
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
627   ret i1 %r
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
641   ret <2 x i1> %r
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]]
650   %dec = add i8 %x, -1
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
655   ret i1 %r
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]]
664   %dec = add i8 %x, -1
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
669   ret i1 %r
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
683   ret <2 x i1> %r
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]]
692   %neg = sub i32 0, %x
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
697   ret i1 %r
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]]
706   %neg = sub i32 0, %x
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
711   ret i1 %r
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
725   ret <2 x i1> %r
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]]
734   %dec = add i8 %x, -1
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
739   ret i1 %r
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]]
748   %dec = add i8 %x, -1
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
753   ret i1 %r
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
767   ret <2 x i1> %r