@@ -461,6 +461,19 @@ define i1 @isnot_pow2_ctpop(i32 %x) {
461461 ret i1 %r
462462}
463463
464+ define i1 @isnot_pow2_ctpop_samesign (i32 %x ) {
465+ ; CHECK-LABEL: @isnot_pow2_ctpop_samesign(
466+ ; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
467+ ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1
468+ ; CHECK-NEXT: ret i1 [[R]]
469+ ;
470+ %t0 = tail call i32 @llvm.ctpop.i32 (i32 %x )
471+ %cmp = icmp samesign ugt i32 %t0 , 1
472+ %iszero = icmp eq i32 %x , 0
473+ %r = or i1 %iszero , %cmp
474+ ret i1 %r
475+ }
476+
464477define i1 @isnot_pow2_ctpop_logical (i32 %x ) {
465478; CHECK-LABEL: @isnot_pow2_ctpop_logical(
466479; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
@@ -474,6 +487,19 @@ define i1 @isnot_pow2_ctpop_logical(i32 %x) {
474487 ret i1 %r
475488}
476489
490+ define i1 @isnot_pow2_ctpop_logical_samesign (i32 %x ) {
491+ ; CHECK-LABEL: @isnot_pow2_ctpop_logical_samesign(
492+ ; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
493+ ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1
494+ ; CHECK-NEXT: ret i1 [[R]]
495+ ;
496+ %t0 = tail call i32 @llvm.ctpop.i32 (i32 %x )
497+ %cmp = icmp samesign ugt i32 %t0 , 1
498+ %iszero = icmp eq i32 %x , 0
499+ %r = select i1 %iszero , i1 true , i1 %cmp
500+ ret i1 %r
501+ }
502+
477503; Extra uses don't change the fold.
478504
479505define i1 @isnot_pow2_ctpop_extra_uses (i32 %x ) {
@@ -529,6 +555,19 @@ define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) {
529555 ret <2 x i1 > %r
530556}
531557
558+ define <2 x i1 > @isnot_pow2_ctpop_commute_vec_samesign (<2 x i8 > %x ) {
559+ ; CHECK-LABEL: @isnot_pow2_ctpop_commute_vec_samesign(
560+ ; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
561+ ; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[T0]], splat (i8 1)
562+ ; CHECK-NEXT: ret <2 x i1> [[R]]
563+ ;
564+ %t0 = tail call <2 x i8 > @llvm.ctpop.v2i8 (<2 x i8 > %x )
565+ %cmp = icmp samesign ugt <2 x i8 > %t0 , <i8 1 , i8 1 >
566+ %iszero = icmp eq <2 x i8 > %x , zeroinitializer
567+ %r = or <2 x i1 > %cmp , %iszero
568+ ret <2 x i1 > %r
569+ }
570+
532571; Negative test - wrong constant.
533572
534573define i1 @isnot_pow2_ctpop_wrong_cmp_op1 (i32 %x ) {
@@ -1532,6 +1571,21 @@ entry:
15321571 ret i1 %sel
15331572}
15341573
1574+ define i1 @has_single_bit_samesign (i32 %x ) {
1575+ ; CHECK-LABEL: @has_single_bit_samesign(
1576+ ; CHECK-NEXT: entry:
1577+ ; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
1578+ ; CHECK-NEXT: [[SEL:%.*]] = icmp eq i32 [[POPCNT]], 1
1579+ ; CHECK-NEXT: ret i1 [[SEL]]
1580+ ;
1581+ entry:
1582+ %cmp1 = icmp ne i32 %x , 0
1583+ %popcnt = call range(i32 1 , 33 ) i32 @llvm.ctpop.i32 (i32 %x )
1584+ %cmp2 = icmp samesign ult i32 %popcnt , 2
1585+ %sel = select i1 %cmp1 , i1 %cmp2 , i1 false
1586+ ret i1 %sel
1587+ }
1588+
15351589define i1 @has_single_bit_inv (i32 %x ) {
15361590; CHECK-LABEL: @has_single_bit_inv(
15371591; CHECK-NEXT: entry:
@@ -1547,6 +1601,21 @@ entry:
15471601 ret i1 %sel
15481602}
15491603
1604+ define i1 @has_single_bit_inv_samesign (i32 %x ) {
1605+ ; CHECK-LABEL: @has_single_bit_inv_samesign(
1606+ ; CHECK-NEXT: entry:
1607+ ; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
1608+ ; CHECK-NEXT: [[SEL:%.*]] = icmp ne i32 [[POPCNT]], 1
1609+ ; CHECK-NEXT: ret i1 [[SEL]]
1610+ ;
1611+ entry:
1612+ %cmp1 = icmp eq i32 %x , 0
1613+ %popcnt = call range(i32 1 , 33 ) i32 @llvm.ctpop.i32 (i32 %x )
1614+ %cmp2 = icmp samesign ugt i32 %popcnt , 1
1615+ %sel = select i1 %cmp1 , i1 true , i1 %cmp2
1616+ ret i1 %sel
1617+ }
1618+
15501619define i1 @is_power2_or_zero_with_range (i32 %x ) {
15511620; CHECK-LABEL: @is_power2_or_zero_with_range(
15521621; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
0 commit comments