diff --git a/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll b/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll @@ -0,0 +1,553 @@ +; 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: [[AND2:%.*]] = and i32 [[X]], 4 +; CHECK-NEXT: ret i32 [[AND2]] +; + %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: [[OR:%.*]] = or i64 [[X]], 1 +; CHECK-NEXT: ret i64 [[OR]] +; + %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: [[AND2:%.*]] = and i16 [[X]], 16384 +; CHECK-NEXT: ret i16 [[AND2]] +; + %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: [[OR:%.*]] = or i32 [[X]], 4 +; CHECK-NEXT: ret i32 [[OR]] +; 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: [[AND2:%.*]] = and i64 [[X]], 1 +; CHECK-NEXT: ret i64 [[AND2]] +; 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: [[OR:%.*]] = or i16 [[X]], 16384 +; CHECK-NEXT: ret i16 [[OR]] +; 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: [[AND2:%.*]] = and i8 [[X]], -128 +; CHECK-NEXT: ret i8 [[AND2]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0:![0-9]+]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y:%.*]]), !range [[RNG0]] +; 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 i32 @llvm.ctpop.i32(i32 [[Y]]), !range [[RNG0]] +; 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 +}