diff --git a/llvm/test/Transforms/InstCombine/ispow2.ll b/llvm/test/Transforms/InstCombine/ispow2.ll --- a/llvm/test/Transforms/InstCombine/ispow2.ll +++ b/llvm/test/Transforms/InstCombine/ispow2.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s - +declare void @use.i32(i32) define i1 @is_pow2or0_negate_op(i32 %x) { ; CHECK-LABEL: @is_pow2or0_negate_op( ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0:![0-9]+]] @@ -104,7 +104,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], 2 ; CHECK-NEXT: ret i1 [[CMP]] ; - %x = srem i32 42, %p ; thwart complexity-based canonicalization + %x = srem i32 42, %p ; thwart complexity-based canonicalization %neg = sub i32 0, %x %and = and i32 %x, %neg %cmp = icmp eq i32 %and, %x @@ -120,7 +120,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1 ; CHECK-NEXT: ret i1 [[CMP]] ; - %x = urem i32 42, %p ; thwart complexity-based canonicalization + %x = urem i32 42, %p ; thwart complexity-based canonicalization %neg = sub i32 0, %x %and = and i32 %neg, %x %cmp = icmp ne i32 %x, %and @@ -134,7 +134,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1 ; CHECK-NEXT: ret i1 [[CMP]] ; - %x = urem i32 42, %p ; thwart complexity-based canonicalization + %x = urem i32 42, %p ; thwart complexity-based canonicalization %neg = sub i32 0, %x %and = and i32 %x, %neg %cmp = icmp ne i32 %x, %and @@ -1140,3 +1140,74 @@ %r = or <2 x i1> %cmp, %notzero ret <2 x i1> %r } + +define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) { +; CHECK-LABEL: @blsmsk_is_p2_or_z( +; CHECK-NEXT: [[X:%.*]] = or i32 [[XX:%.*]], [[YY:%.*]] +; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X]], -1 +; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X]], [[XM1]] +; CHECK-NEXT: [[R:%.*]] = icmp uge i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = or i32 %xx, %yy + %xm1 = add i32 %x, -1 + %y = xor i32 %x, %xm1 + %r = icmp uge i32 %x, %y + ret i1 %r +} + +define i1 @blsmsk_isnt_p2_or_z(i32 %x) { +; CHECK-LABEL: @blsmsk_isnt_p2_or_z( +; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -1 +; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %xm1 = add i32 %x, -1 + %y = xor i32 %x, %xm1 + %r = icmp ult i32 %y, %x + ret i1 %r +} + +define i1 @blsmsk_is_p2_or_z_fail(i32 %xx, i32 %yy) { +; CHECK-LABEL: @blsmsk_is_p2_or_z_fail( +; CHECK-NEXT: [[X:%.*]] = or i32 [[XX:%.*]], [[YY:%.*]] +; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X]], -1 +; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X]], [[XM1]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = or i32 %xx, %yy + %xm1 = add i32 %x, -1 + %y = xor i32 %x, %xm1 + %r = icmp ugt i32 %x, %y + ret i1 %r +} + +define i1 @blsmsk_isnt_p2_or_z_fail(i32 %x) { +; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail( +; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -1 +; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i32 [[Y]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %xm1 = add i32 %x, -1 + %y = xor i32 %x, %xm1 + %r = icmp ule i32 %y, %x + ret i1 %r +} + +define i1 @blsmsk_isnt_p2_or_z_fail_multiuse(i32 %x) { +; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail_multiuse( +; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -1 +; CHECK-NEXT: [[Y:%.*]] = xor i32 [[XM1]], [[X]] +; CHECK-NEXT: call void @use.i32(i32 [[Y]]) +; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %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 +}