[llvm] 8c9f13b - [InstCombine] Add tests for icmp ne non-zero power of 2; NFC

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 11 01:02:44 PST 2023


Author: Noah Goldstein
Date: 2023-01-11T10:02:36+01:00
New Revision: 8c9f13bd4c0fddacfea2d3dfd5af532c40656505

URL: https://github.com/llvm/llvm-project/commit/8c9f13bd4c0fddacfea2d3dfd5af532c40656505
DIFF: https://github.com/llvm/llvm-project/commit/8c9f13bd4c0fddacfea2d3dfd5af532c40656505.diff

LOG: [InstCombine] Add tests for icmp ne non-zero power of 2; NFC

Tests for D140851.

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

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll b/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll
new file mode 100644
index 0000000000000..47c198573b841
--- /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
+}


        


More information about the llvm-commits mailing list