llvm/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=instcombine -S < %s | FileCheck %s

declare void @llvm.assume(i1)
declare i32 @llvm.ctpop.i32(i32)

define i32 @pow2_32_assume(i32 %x) {
; CHECK-LABEL: @pow2_32_assume(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 4
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    ret i32 4
;
  %and = and i32 %x, 4
  %cmp = icmp ne i32 %and, 0
  call void @llvm.assume(i1 %cmp)
  %and2 = and i32 %x, 4
  ret i32 %and2
}

define i32 @not_pow2_32_assume(i32 %x) {
; CHECK-LABEL: @not_pow2_32_assume(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], 3
; CHECK-NEXT:    ret i32 [[AND2]]
;
  %and = and i32 %x, 3
  %cmp = icmp ne i32 %and, 0
  call void @llvm.assume(i1 %cmp)
  %and2 = and i32 %x, 3
  ret i32 %and2
}

define i64 @pow2_64_assume(i64 %x) {
; CHECK-LABEL: @pow2_64_assume(
; CHECK-NEXT:    [[AND:%.*]] = and i64 [[X:%.*]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    ret i64 [[X]]
;
  %and = and i64 %x, 1
  %cmp = icmp ne i64 %and, 0
  call void @llvm.assume(i1 %cmp)
  %or = or i64 %x, 1
  ret i64 %or
}

define i64 @not_pow2_64_assume(i64 %x) {
; CHECK-LABEL: @not_pow2_64_assume(
; CHECK-NEXT:    [[AND:%.*]] = and i64 [[X:%.*]], 2147483647
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    [[OR:%.*]] = or i64 [[X]], 2147483647
; CHECK-NEXT:    ret i64 [[OR]]
;
  %and = and i64 %x, 2147483647
  %cmp = icmp ne i64 %and, 0
  call void @llvm.assume(i1 %cmp)
  %or = or i64 %x, 2147483647
  ret i64 %or
}

define i16 @pow2_16_assume(i16 %x) {
; CHECK-LABEL: @pow2_16_assume(
; CHECK-NEXT:    [[AND:%.*]] = and i16 [[X:%.*]], 16384
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    ret i16 16384
;
  %and = and i16 %x, 16384
  %cmp = icmp eq i16 %and, 16384
  call void @llvm.assume(i1 %cmp)
  %and2 = and i16 %x, 16384
  ret i16 %and2
}

define i16 @not_pow2_16_assume(i16 %x) {
; CHECK-LABEL: @not_pow2_16_assume(
; CHECK-NEXT:    [[AND:%.*]] = and i16 [[X:%.*]], 7
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[AND]], 7
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    [[AND2:%.*]] = and i16 [[X]], 7
; CHECK-NEXT:    ret i16 [[AND2]]
;
  %and = and i16 %x, 7
  %cmp = icmp ne i16 %and, 7
  call void @llvm.assume(i1 %cmp)
  %and2 = and i16 %x, 7
  ret i16 %and2
}

define i8 @pow2_8_assume(i8 %x) {
; CHECK-LABEL: @pow2_8_assume(
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    ret i8 [[X]]
;
  %and = and i8 %x, 128
  %cmp = icmp eq i8 %and, 128
  call void @llvm.assume(i1 %cmp)
  %or = or i8 %x, 128
  ret i8 %or
}

define i8 @not_pow2_8_assume(i8 %x) {
; CHECK-LABEL: @not_pow2_8_assume(
; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 127
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 127
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X]], 127
; CHECK-NEXT:    ret i8 [[OR]]
;
  %and = and i8 %x, 127
  %cmp = icmp ne i8 %and, 127
  call void @llvm.assume(i1 %cmp)
  %or = or i8 %x, 127
  ret i8 %or
}

define i32 @pow2_32_br(i32 %x) {
; CHECK-LABEL: @pow2_32_br(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 4
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    ret i32 [[X]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %and = and i32 %x, 4
  %cmp = icmp eq i32 %and, 4
  br i1 %cmp, label %True, label %False
True:
  %or = or i32 %x, 4
  ret i32 %or
False:
  ret i32 0
}

define i32 @not_pow2_32_br(i32 %x) {
; CHECK-LABEL: @not_pow2_32_br(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], 3
; CHECK-NEXT:    ret i32 [[OR]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %and = and i32 %x, 3
  %cmp = icmp ne i32 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %or = or i32 %x, 3
  ret i32 %or
False:
  ret i32 0
}

define i64 @pow2_64_br(i64 %x) {
; CHECK-LABEL: @pow2_64_br(
; CHECK-NEXT:    [[AND:%.*]] = and i64 [[X:%.*]], 1
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i64 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    ret i64 1
; CHECK:       False:
; CHECK-NEXT:    ret i64 0
;
  %and = and i64 %x, 1
  %cmp = icmp ne i64 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i64 %x, 1
  ret i64 %and2
False:
  ret i64 0
}

define i64 @not_pow2_64_br(i64 %x) {
; CHECK-LABEL: @not_pow2_64_br(
; CHECK-NEXT:    [[AND:%.*]] = and i64 [[X:%.*]], 2147483647
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i64 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[X]], 2147483647
; CHECK-NEXT:    ret i64 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i64 0
;
  %and = and i64 %x, 2147483647
  %cmp = icmp ne i64 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i64 %x, 2147483647
  ret i64 %and2
False:
  ret i64 0
}

define i16 @pow2_16_br(i16 %x) {
; CHECK-LABEL: @pow2_16_br(
; CHECK-NEXT:    [[AND:%.*]] = and i16 [[X:%.*]], 16384
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i16 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    ret i16 [[X]]
; CHECK:       False:
; CHECK-NEXT:    ret i16 0
;
  %and = and i16 %x, 16384
  %cmp = icmp eq i16 %and, 16384
  br i1 %cmp, label %True, label %False
True:
  %or = or i16 %x, 16384
  ret i16 %or
False:
  ret i16 0
}

define i16 @not_pow2_16_br(i16 %x) {
; CHECK-LABEL: @not_pow2_16_br(
; CHECK-NEXT:    [[AND:%.*]] = and i16 [[X:%.*]], 7
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i16 [[AND]], 7
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[OR:%.*]] = or i16 [[X]], 7
; CHECK-NEXT:    ret i16 [[OR]]
; CHECK:       False:
; CHECK-NEXT:    ret i16 0
;
  %and = and i16 %x, 7
  %cmp = icmp ne i16 %and, 7
  br i1 %cmp, label %True, label %False
True:
  %or = or i16 %x, 7
  ret i16 %or
False:
  ret i16 0
}

define i8 @pow2_8_br(i8 %x) {
; CHECK-LABEL: @pow2_8_br(
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i8 [[X:%.*]], -1
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    ret i8 -128
; CHECK:       False:
; CHECK-NEXT:    ret i8 0
;
  %and = and i8 %x, 128
  %cmp = icmp ne i8 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i8 %x, 128
  ret i8 %and2
False:
  ret i8 0
}

define i8 @not_pow2_8_br(i8 %x) {
; CHECK-LABEL: @not_pow2_8_br(
; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 127
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[AND]], 127
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i8 [[X]], 127
; CHECK-NEXT:    ret i8 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i8 0
;
  %and = and i8 %x, 127
  %cmp = icmp ne i8 %and, 127
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i8 %x, 127
  ret i8 %and2
False:
  ret i8 0
}

define i32 @pow2_32_nonconst_assume(i32 %x, i32 %y) {
; CHECK-LABEL: @pow2_32_nonconst_assume(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp eq i32 [[CTPOP]], 1
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp eq i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)

  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  call void @llvm.assume(i1 %cmp)
  %and2 = and i32 %x, %y
  ret i32 %and2
}

define i32 @pow2_32_gtnonconst_assume(i32 %x, i32 %y) {
; CHECK-LABEL: @pow2_32_gtnonconst_assume(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp eq i32 [[CTPOP]], 1
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    [[YGT:%.*]] = icmp ugt i32 [[Y]], [[X:%.*]]
; CHECK-NEXT:    call void @llvm.assume(i1 [[YGT]])
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND]]
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp eq i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)

  %ygt = icmp ugt i32 %y, %x
  call void @llvm.assume(i1 %ygt)

  %and = and i32 %x, %y
  ret i32 %and
}

define i32 @not_pow2_32_nonconst_assume(i32 %x, i32 %y) {
; CHECK-LABEL: @not_pow2_32_nonconst_assume(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp ne i32 [[CTPOP]], 1
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp ne i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)

  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  call void @llvm.assume(i1 %cmp)
  %and2 = and i32 %x, %y
  ret i32 %and2
}

define i32 @pow2_or_zero_32_nonconst_assume(i32 %x, i32 %y) {
; CHECK-LABEL: @pow2_or_zero_32_nonconst_assume(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp ult i32 [[CTPOP]], 2
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp ule i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)

  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  call void @llvm.assume(i1 %cmp)
  %and2 = and i32 %x, %y
  ret i32 %and2
}

define i32 @pow2_32_nonconst_assume_br(i32 %x, i32 %y) {
; CHECK-LABEL: @pow2_32_nonconst_assume_br(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp eq i32 [[CTPOP]], 1
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp eq i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)
  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i32 %x, %y
  ret i32 %and2
False:
  ret i32 0
}

define i32 @not_pow2_32_nonconst_assume_br(i32 %x, i32 %y) {
; CHECK-LABEL: @not_pow2_32_nonconst_assume_br(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp ne i32 [[CTPOP]], 1
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp ne i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)
  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i32 %x, %y
  ret i32 %and2
False:
  ret i32 0
}

define i32 @pow2_or_zero_32_nonconst_assume_br(i32 %x, i32 %y) {
; CHECK-LABEL: @pow2_or_zero_32_nonconst_assume_br(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp ult i32 [[CTPOP]], 2
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp ule i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)
  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i32 %x, %y
  ret i32 %and2
False:
  ret i32 0
}

define i32 @pow2_32_nonconst_br1_br(i32 %x, i32 %y) {
; CHECK-LABEL: @pow2_32_nonconst_br1_br(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp eq i32 [[CTPOP]], 1
; CHECK-NEXT:    br i1 [[YP2]], label [[CONT:%.*]], label [[FALSE:%.*]]
; CHECK:       Cont:
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp eq i32 %ctpop, 1
  br i1 %yp2, label %Cont, label %False
Cont:
  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i32 %x, %y
  ret i32 %and2
False:
  ret i32 0
}

define i32 @not_pow2_32_nonconst_br1_br(i32 %x, i32 %y) {
; CHECK-LABEL: @not_pow2_32_nonconst_br1_br(
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
; CHECK-NEXT:    [[YP2_NOT:%.*]] = icmp eq i32 [[CTPOP]], 1
; CHECK-NEXT:    br i1 [[YP2_NOT]], label [[FALSE:%.*]], label [[CONT:%.*]]
; CHECK:       Cont:
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp ne i32 %ctpop, 1
  br i1 %yp2, label %Cont, label %False
Cont:
  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i32 %x, %y
  ret i32 %and2
False:
  ret i32 0
}

define i32 @maybe_pow2_32_noncont(i32 %x, i32 %y) {
; CHECK-LABEL: @maybe_pow2_32_noncont(
; CHECK-NEXT:    [[YGT8:%.*]] = icmp ugt i32 [[Y:%.*]], 8
; CHECK-NEXT:    br i1 [[YGT8]], label [[CONT1:%.*]], label [[CONT2:%.*]]
; CHECK:       Cont1:
; CHECK-NEXT:    [[CTPOP:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[Y]])
; CHECK-NEXT:    [[YP2:%.*]] = icmp eq i32 [[CTPOP]], 1
; CHECK-NEXT:    call void @llvm.assume(i1 [[YP2]])
; CHECK-NEXT:    br i1 true, label [[CONT2]], label [[FALSE:%.*]]
; CHECK:       Cont2:
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y]]
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE]], label [[TRUE:%.*]]
; CHECK:       True:
; CHECK-NEXT:    [[AND2:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    ret i32 [[AND2]]
; CHECK:       False:
; CHECK-NEXT:    ret i32 0
;
  %ygt8 = icmp ugt i32 %y, 8
  br i1 %ygt8, label %Cont1, label %Cont2
Cont1:
  %ctpop = call i32 @llvm.ctpop.i32(i32 %y)
  %yp2 = icmp eq i32 %ctpop, 1
  call void @llvm.assume(i1 %yp2)
  br i1 true, label %Cont2, label %False
Cont2:
  %and = and i32 %x, %y
  %cmp = icmp ne i32 %and, 0
  br i1 %cmp, label %True, label %False
True:
  %and2 = and i32 %x, %y
  ret i32 %and2
False:
  ret i32 0
}