Bug type: miscompilation
Component: InstCombine
Bug location: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp: InstCombinerImpl::foldAndOrOfICmps
foldIsPowerOf2OrZero
Issue title: [InstCombine] `range` attribute should be dropped in `foldIsPowerOf2OrZero`
Labels: miscompilation
llvm:instcombine
Reported by: dtcxzyw

Reproducer: https://alive2.llvm.org/ce/z/u62KKP (Please use latest alive2 with https://github.com/AliveToolkit/alive2/pull/1097)
```
define i1 @src(i32 %x) {
  %t0 = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

define i1 @tgt(i32 %x) {
  %t0 = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ugt i32 %t0, 1
  ret i1 %r
}
```
```
----------------------------------------
define i1 @src(i32 %x) {
#0:
  %t0 = ctpop i32 %x
  %#range_0_%t0 = !range i32 %t0, i32 1, i32 33
  %cmp = icmp ne i32 %#range_0_%t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 0
  ret i1 %r
}
=>
define i1 @tgt(i32 %x) {
#0:
  %t0 = ctpop i32 %x
  %#range_0_%t0 = !range i32 %t0, i32 1, i32 33
  %r = icmp ugt i32 %#range_0_%t0, 1
  ret i1 %r
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i32 %x = #x00000000 (0)

Source:
i32 %t0 = #x00000000 (0)
i32 %#range_0_%t0 = poison
i1 %cmp = poison
i1 %notzero = #x0 (0)
i1 %r = #x0 (0)

Target:
i32 %t0 = #x00000000 (0)
i32 %#range_0_%t0 = poison
i1 %r = poison
Source value: #x0 (0)
Target value: poison
```


Fix patch:
commit 9edc454ee601e04500529c98b753d3bd8f427d01
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Mon Oct 14 20:52:55 2024 +0800

    [InstCombine] Drop range attributes in `foldIsPowerOf2OrZero` (#112178)
    
    Closes https://github.com/llvm/llvm-project/issues/112078.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 453071f3f982..64bee4ab974e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -935,9 +935,11 @@ static Value *foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1,
 
 /// Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and
 /// fold (icmp ne ctpop(X) 1) & (icmp ne X 0) into (icmp ugt ctpop(X) 1).
-/// Also used for logical and/or, must be poison safe.
+/// Also used for logical and/or, must be poison safe if range attributes are
+/// dropped.
 static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
-                                   InstCombiner::BuilderTy &Builder) {
+                                   InstCombiner::BuilderTy &Builder,
+                                   InstCombinerImpl &IC) {
   CmpInst::Predicate Pred0, Pred1;
   Value *X;
   if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -945,11 +947,19 @@ static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
       !match(Cmp1, m_ICmp(Pred1, m_Specific(X), m_ZeroInt())))
     return nullptr;
 
-  Value *CtPop = Cmp0->getOperand(0);
-  if (IsAnd && Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_NE)
+  auto *CtPop = cast<Instruction>(Cmp0->getOperand(0));
+  if (IsAnd && Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_NE) {
+    // Drop range attributes and re-infer them in the next iteration.
+    CtPop->dropPoisonGeneratingAnnotations();
+    IC.addToWorklist(CtPop);
     return Builder.CreateICmpUGT(CtPop, ConstantInt::get(CtPop->getType(), 1));
-  if (!IsAnd && Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_EQ)
+  }
+  if (!IsAnd && Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_EQ) {
+    // Drop range attributes and re-infer them in the next iteration.
+    CtPop->dropPoisonGeneratingAnnotations();
+    IC.addToWorklist(CtPop);
     return Builder.CreateICmpULT(CtPop, ConstantInt::get(CtPop->getType(), 2));
+  }
 
   return nullptr;
 }
@@ -3362,9 +3372,9 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
                                              /*IsLogical*/ false, Builder, Q))
     return V;
 
-  if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder))
+  if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder, *this))
     return V;
-  if (Value *V = foldIsPowerOf2OrZero(RHS, LHS, IsAnd, Builder))
+  if (Value *V = foldIsPowerOf2OrZero(RHS, LHS, IsAnd, Builder, *this))
     return V;
 
   // TODO: One of these directions is fine with logical and/or, the other could


Regression tests:
file: llvm/test/Transforms/InstCombine/ispow2.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: is_pow2or0_decrement_op
test_body: define i1 @is_pow2or0_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp eq i8 %and, 0
  ret i1 %cmp
}

test_name: is_pow2_negate_op_vec
test_body: define <2 x i1> @is_pow2_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp eq <2 x i32> %and, %x
  %notzero = icmp ne <2 x i32> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

test_name: is_pow2_ctpop_wrong_cmp_op1_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 3
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_negate_op
test_body: define i1 @is_pow2_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

test_name: not_pow2_nz_known_bits
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @not_pow2_nz_known_bits(i32 %xin) {
  %x = or i32 %xin, 1
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ne i32 %cnt, 1
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_nz_known_bits
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_nz_known_bits(i32 %xin) {
  %x = or i32 %xin, 64
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp eq i32 %cnt, 1
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_power2_or_zero_with_range
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_power2_or_zero_with_range(i32 %x) {
  %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %ctpop, 1
  %notzero = icmp eq i32 %x, 0
  %res = select i1 %notzero, i1 true, i1 %cmp
  ret i1 %res
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_is_p2_or_z
test_body: define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) {
  %x = or i32 %xx, %yy
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp uge i32 %x, %y
  ret i1 %r
}

test_name: isnot_pow2nor0_ctpop_commute_vec
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ne <2 x i8> %t0, splat (i8 1)
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %notzero, %cmp
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_ctpop_wrong_pred1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop_wrong_pred1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_non_zero_ne_1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #1

define i1 @is_pow2_non_zero_ne_1(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  ret i1 %cmp
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: blsmsk_is_p2_or_z_fail
test_body: define i1 @blsmsk_is_p2_or_z_fail(i32 %xx, i32 %yy) {
  %x = or i32 %xx, %yy
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp ugt i32 %x, %y
  ret i1 %r
}

test_name: blsmsk_is_p2_or_z_uge_xy_fail
test_body: define i1 @blsmsk_is_p2_or_z_uge_xy_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp uge i8 %x, %y
  ret i1 %r
}

test_name: is_pow2or0_ctpop_logical_extra_uses
test_body: declare void @use(i32)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @is_pow2or0_ctpop_logical_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp eq i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_commute_vec
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ugt <2 x i8> %t0, splat (i8 1)
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_isnt_p2_or_z_fail_wrong_add
test_body: define i1 @blsmsk_isnt_p2_or_z_fail_wrong_add(i32 %x, i32 %z) {
  %xm1 = add i32 %z, -1
  %y = xor i32 %x, %xm1
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

test_name: is_pow2_ctpop_wrong_pred2
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %cmp2 = icmp sgt i32 %x, 0
  %r = and i1 %cmp2, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_ctpop_swap_cmp
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop_swap_cmp(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %cmp, %iszero
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_ctpop_commute_vec_wrong_pred3
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_pred3(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp eq <2 x i8> %t0, splat (i8 1)
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_decrement_op_logical
test_body: define i1 @is_pow2_decrement_op_logical(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp eq i8 %and, 0
  %notzero = icmp ne i8 %x, 0
  %r = select i1 %cmp, i1 %notzero, i1 false
  ret i1 %r
}

test_name: isnot_pow2or0_negate_op_vec
test_body: define <2 x i1> @isnot_pow2or0_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp ne <2 x i32> %and, %x
  ret <2 x i1> %cmp
}

test_name: is_pow2or0_ctpop_commute_vec
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2or0_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp eq <2 x i8> %t0, splat (i8 1)
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %iszero, %cmp
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_negate_op_logical
test_body: define i1 @is_pow2_negate_op_logical(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

test_name: isnot_pow2nor0_ctpop
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_isnt_p2_or_z_ult_xy_fail
test_body: define i1 @blsmsk_isnt_p2_or_z_ult_xy_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ult i8 %x, %y
  ret i1 %r
}

test_name: isnot_pow2nor0_wrong_pred3_ctpop_commute_vec
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ne <2 x i8> %t0, splat (i8 1)
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_negate_op_vec
test_body: define <2 x i1> @is_pow2or0_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp eq <2 x i32> %and, %x
  ret <2 x i1> %cmp
}

test_name: isnot_pow2or0_negate_op
test_body: define i1 @isnot_pow2or0_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %and, %x
  ret i1 %cmp
}

test_name: not_pow2_or_z_known_bits_fail_wrong_cmp
test_body: define <2 x i1> @not_pow2_or_z_known_bits_fail_wrong_cmp(<2 x i32> %xin) {
  %x = or <2 x i32> %xin, splat (i32 64)
  %cnt = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %x)
  %r = icmp ugt <2 x i32> %cnt, splat (i32 2)
  ret <2 x i1> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32>) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_ctpop_wrong_cmp_op2
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_cmp_op2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 1
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_ctpop_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_decrement_op_logical
test_body: define i1 @isnot_pow2_decrement_op_logical(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp ne i8 %and, 0
  %iszero = icmp eq i8 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

test_name: isnot_pow2_negate_op_logical
test_body: define i1 @isnot_pow2_negate_op_logical(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %and, %x
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %cmp, i1 true, i1 %iszero
  ret i1 %r
}

test_name: is_pow2or0_ctpop
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_is_p2_or_z_uge_yx
test_body: define i1 @blsmsk_is_p2_or_z_uge_yx(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp uge i8 %y, %x
  ret i1 %r
}

test_name: has_single_bit_inv
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @has_single_bit_inv(i32 %x) {
entry:
  %cmp1 = icmp eq i32 %x, 0
  %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp2 = icmp ugt i32 %popcnt, 1
  %sel = select i1 %cmp1, i1 true, i1 %cmp2
  ret i1 %sel
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_negate_op
test_body: define i1 @is_pow2or0_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

test_name: blsmsk_isnt_p2_or_z_ugt_yx_fail
test_body: define i1 @blsmsk_isnt_p2_or_z_ugt_yx_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ugt i8 %y, %x
  ret i1 %r
}

test_name: blsmsk_isnt_p2_or_z_fail
test_body: define i1 @blsmsk_isnt_p2_or_z_fail(i32 %x) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp ule i32 %y, %x
  ret i1 %r
}

test_name: is_pow2_decrement_op_vec
test_body: define <2 x i1> @is_pow2_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp eq <2 x i8> %and, zeroinitializer
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %notzero, %cmp
  ret <2 x i1> %r
}

test_name: isnot_pow2nor0_ctpop_extra_uses
test_body: declare void @use(i32)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @isnot_pow2nor0_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp ne i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2nor0_ctpop_wrong_pred1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop_wrong_pred1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_isnt_p2_or_z_fail_multiuse
test_body: declare void @use.i32(i32)

define i1 @blsmsk_isnt_p2_or_z_fail_multiuse(i32 %x) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  call void @use.i32(i32 %y)
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

test_name: is_pow2or0_ctpop_wrong_pred2_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %iszero = icmp ne i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_ctpop_extra_uses
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @is_pow2_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_isnt_p2_or_z_ult_yx
test_body: define i1 @blsmsk_isnt_p2_or_z_ult_yx(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ult i8 %y, %x
  ret i1 %r
}

test_name: is_pow2or0_ctpop_wrong_cmp_op1_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 3
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_isnt_p2_or_z_fail_bad_xor
test_body: define i1 @blsmsk_isnt_p2_or_z_fail_bad_xor(i32 %x, i32 %z) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %z, %xm1
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

test_name: is_pow2or0_negate_op_extra_use2
test_body: declare void @use(i32)

define i1 @is_pow2or0_negate_op_extra_use2(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  call void @use(i32 %and)
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

test_name: isnot_pow2_negate_op
test_body: define i1 @isnot_pow2_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %and, %x
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %cmp, %iszero
  ret i1 %r
}

test_name: is_pow2or0_negate_op_extra_use1
test_body: declare void @use(i32)

define i1 @is_pow2or0_negate_op_extra_use1(i32 %x) {
  %neg = sub i32 0, %x
  call void @use(i32 %neg)
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

test_name: isnot_pow2_ctpop_wrong_cmp_op1_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_wrong_cmp_op2_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 1
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_ctpop_wrong_cmp_op1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 3
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_ctpop_commute_vec_wrong_cmp_op1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp eq <2 x i8> %t0, <i8 -1, i8 1>
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_wrong_pred2_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %cmp2 = icmp slt i32 %x, 0
  %r = select i1 %cmp2, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_ctpop_extra_uses_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @is_pow2_ctpop_extra_uses_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2or0_negate_op_commute3
test_body: define i1 @isnot_pow2or0_negate_op_commute3(i32 %p) {
  %x = urem i32 42, %p
  %neg = sub i32 0, %x
  %and = and i32 %x, %neg
  %cmp = icmp ne i32 %x, %and
  ret i1 %cmp
}

test_name: is_pow2_ctpop_wrong_cmp_op2_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 1
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_non_zero_eq_1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #1

define i1 @is_pow2_non_zero_eq_1(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  ret i1 %cmp
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: isnot_pow2nor0_ctpop_logical_extra_uses
test_body: declare void @use(i32)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @isnot_pow2nor0_ctpop_logical_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp ne i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_ctpop_wrong_pred2
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %iszero = icmp ne i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_wrong_cmp_op2
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop_wrong_cmp_op2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 1
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_ctpop_wrong_pred1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_extra_uses_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @isnot_pow2_ctpop_extra_uses_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_ctpop_extra_uses
test_body: declare void @use(i32)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @is_pow2or0_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp eq i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_non_zero_ult_2
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #1

define i1 @is_pow2_non_zero_ult_2(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  ret i1 %cmp
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: is_pow2_ctpop_commute_vec
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ult <2 x i8> %t0, splat (i8 2)
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_decrement_op
test_body: define i1 @isnot_pow2_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp ne i8 %and, 0
  %iszero = icmp eq i8 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

test_name: isnot_pow2nor0_ctpop_wrong_cmp_op1_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 5
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_ctpop_wrong_pred1_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_pred1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2or0_decrement_op_vec
test_body: define <2 x i1> @isnot_pow2or0_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp ne <2 x i8> %and, zeroinitializer
  ret <2 x i1> %cmp
}

test_name: is_pow2_ctpop_wrong_pred2_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %cmp2 = icmp sgt i32 %x, 0
  %r = select i1 %cmp2, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_isnt_p2_or_z_ugt_xy
test_body: define i1 @blsmsk_isnt_p2_or_z_ugt_xy(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ugt i8 %x, %y
  ret i1 %r
}

test_name: isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ne <2 x i8> %t0, <i8 0, i8 -1>
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2nor0_ctpop_wrong_pred2_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %notzero = icmp eq i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_negate_op_commute1
test_body: define i1 @is_pow2or0_negate_op_commute1(i32 %p) {
  %x = srem i32 42, %p
  %neg = sub i32 0, %x
  %and = and i32 %x, %neg
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

test_name: is_pow2_or_z_known_bits
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_or_z_known_bits(i32 %xin) {
  %x = or i32 %xin, -2147483648
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ult i32 %cnt, 2
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2or0_decrement_op_vec
test_body: define <2 x i1> @is_pow2or0_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp eq <2 x i8> %and, zeroinitializer
  ret <2 x i1> %cmp
}

test_name: is_pow2_decrement_op
test_body: define i1 @is_pow2_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp eq i8 %and, 0
  %notzero = icmp ne i8 %x, 0
  %r = and i1 %cmp, %notzero
  ret i1 %r
}

test_name: isnot_pow2_ctpop_wrong_pred2
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %cmp2 = icmp slt i32 %x, 0
  %r = or i1 %cmp2, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2or0_negate_op_commute2
test_body: define i1 @isnot_pow2or0_negate_op_commute2(i32 %p) {
  %x = urem i32 42, %p
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %x, %and
  ret i1 %cmp
}

test_name: blsmsk_is_p2_or_z_fail_bad_cmp
test_body: define i1 @blsmsk_is_p2_or_z_fail_bad_cmp(i32 %x, i32 %z) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp uge i32 %y, %z
  ret i1 %r
}

test_name: isnot_pow2_decrement_op_vec
test_body: define <2 x i1> @isnot_pow2_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp ne <2 x i8> %and, zeroinitializer
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

test_name: is_pow2or0_ctpop_wrong_cmp_op1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 2
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_is_p2_or_z_ule_yx_fail
test_body: define i1 @blsmsk_is_p2_or_z_ule_yx_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ule i8 %y, %x
  ret i1 %r
}

test_name: not_pow2_or_z_known_bits
test_body: define <2 x i1> @not_pow2_or_z_known_bits(<2 x i32> %xin) {
  %x = or <2 x i32> %xin, splat (i32 64)
  %cnt = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %x)
  %r = icmp ugt <2 x i32> %cnt, splat (i32 1)
  ret <2 x i1> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32>) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_negate_op_vec
test_body: define <2 x i1> @isnot_pow2_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp ne <2 x i32> %and, %x
  %iszero = icmp eq <2 x i32> %x, zeroinitializer
  %r = or <2 x i1> %iszero, %cmp
  ret <2 x i1> %r
}

test_name: is_pow2or0_ctpop_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2or0_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_extra_uses
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use_i1(i1)

define i1 @isnot_pow2_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_power2_or_zero_inv_with_range
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_power2_or_zero_inv_with_range(i32 %x) {
  %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %ctpop, 1
  %notzero = icmp ne i32 %x, 0
  %res = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %res
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2nor0_ctpop_wrong_pred2
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %notzero = icmp eq i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: has_single_bit
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @has_single_bit(i32 %x) {
entry:
  %cmp1 = icmp ne i32 %x, 0
  %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp2 = icmp ult i32 %popcnt, 2
  %sel = select i1 %cmp1, i1 %cmp2, i1 false
  ret i1 %sel
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_fail_pr63327
test_body: define i1 @is_pow2_fail_pr63327(i32 %x) {
  %nx = sub i32 0, %x
  %x_and_nx = and i32 %x, %nx
  %r = icmp sge i32 %x_and_nx, %x
  ret i1 %r
}

test_name: is_pow2_ctpop
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @is_pow2_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: is_pow2_nz_known_bits_fail_multiuse
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

declare void @use.i32(i32)

define i1 @is_pow2_nz_known_bits_fail_multiuse(i32 %xin) {
  %x = or i32 %xin, 64
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  call void @use.i32(i32 %cnt)
  %r = icmp eq i32 %cnt, 1
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_isnt_p2_or_z
test_body: define i1 @blsmsk_isnt_p2_or_z(i32 %x) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

test_name: isnot_pow2or0_decrement_op
test_body: define i1 @isnot_pow2or0_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp ne i8 %and, 0
  ret i1 %cmp
}

test_name: not_pow2_nz_known_bits_fail_not_p2_test
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @not_pow2_nz_known_bits_fail_not_p2_test(i32 %xin) {
  %x = or i32 %xin, 1
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ne i32 %cnt, 2
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2_ctpop_wrong_cmp_op1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: blsmsk_is_p2_or_z_ule_xy
test_body: define i1 @blsmsk_is_p2_or_z_ule_xy(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ule i8 %x, %y
  ret i1 %r
}

test_name: is_pow2_non_zero_ugt_1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #1

define i1 @is_pow2_non_zero_ugt_1(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  ret i1 %cmp
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: isnot_pow2nor0_ctpop_swap_cmp
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop_swap_cmp(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %cmp, %notzero
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2nor0_ctpop_logical
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

test_name: isnot_pow2nor0_ctpop_wrong_cmp_op1
test_body: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 4
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }