Skip to content

Commit f7491f5

Browse files
authored
[InstCombine] Reduce range of ctpop for non zero argument (#100899)
1 parent 1f38301 commit f7491f5

File tree

5 files changed

+46
-16
lines changed

5 files changed

+46
-16
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -692,12 +692,24 @@ static Instruction *foldCtpop(IntrinsicInst &II, InstCombinerImpl &IC) {
692692
Ty);
693693

694694
// Add range attribute since known bits can't completely reflect what we know.
695-
if (BitWidth != 1 && !II.hasRetAttr(Attribute::Range) &&
696-
!II.getMetadata(LLVMContext::MD_range)) {
697-
ConstantRange Range(APInt(BitWidth, Known.countMinPopulation()),
698-
APInt(BitWidth, Known.countMaxPopulation() + 1));
699-
II.addRangeRetAttr(Range);
700-
return ⅈ
695+
if (BitWidth != 1) {
696+
ConstantRange OldRange =
697+
II.getRange().value_or(ConstantRange::getFull(BitWidth));
698+
699+
unsigned Lower = Known.countMinPopulation();
700+
unsigned Upper = Known.countMaxPopulation() + 1;
701+
702+
if (Lower == 0 && OldRange.contains(APInt::getZero(BitWidth)) &&
703+
isKnownNonZero(Op0, IC.getSimplifyQuery().getWithInstruction(&II)))
704+
Lower = 1;
705+
706+
ConstantRange Range(APInt(BitWidth, Lower), APInt(BitWidth, Upper));
707+
Range = Range.intersectWith(OldRange, ConstantRange::Unsigned);
708+
709+
if (Range != OldRange) {
710+
II.addRangeRetAttr(Range);
711+
return ⅈ
712+
}
701713
}
702714

703715
return nullptr;

llvm/test/Transforms/InstCombine/ctpop-pow2.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ define i8 @ctpop_imin_plus1_lshr_nz(i8 %x) {
6060
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[X:%.*]], 0
6161
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
6262
; CHECK-NEXT: [[V:%.*]] = lshr i8 -127, [[X]]
63-
; CHECK-NEXT: [[CNT:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[V]])
63+
; CHECK-NEXT: [[CNT:%.*]] = call range(i8 1, 9) i8 @llvm.ctpop.i8(i8 [[V]])
6464
; CHECK-NEXT: ret i8 [[CNT]]
6565
;
6666
%cmp = icmp ne i8 %x, 0
@@ -104,7 +104,7 @@ define <2 x i32> @ctpop_lshr_intmin_intmin_plus1_vec_nz(<2 x i32> %x) {
104104
; CHECK-LABEL: @ctpop_lshr_intmin_intmin_plus1_vec_nz(
105105
; CHECK-NEXT: [[X1:%.*]] = or <2 x i32> [[X:%.*]], <i32 1, i32 1>
106106
; CHECK-NEXT: [[SHR:%.*]] = lshr <2 x i32> <i32 -2147483648, i32 -2147483647>, [[X1]]
107-
; CHECK-NEXT: [[CNT:%.*]] = call range(i32 0, 17) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[SHR]])
107+
; CHECK-NEXT: [[CNT:%.*]] = call range(i32 1, 17) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[SHR]])
108108
; CHECK-NEXT: ret <2 x i32> [[CNT]]
109109
;
110110
%x1 = or <2 x i32> %x, <i32 1 ,i32 1>

llvm/test/Transforms/InstCombine/ctpop.ll

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ define <2 x i32> @_parity_of_not_poison(<2 x i32> %x) {
169169

170170
define <2 x i32> @_parity_of_not_poison2(<2 x i32> %x) {
171171
; CHECK-LABEL: @_parity_of_not_poison2(
172-
; CHECK-NEXT: [[CNT:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
173-
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[CNT]], <i32 1, i32 poison>
172+
; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
173+
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[TMP1]], <i32 1, i32 poison>
174174
; CHECK-NEXT: ret <2 x i32> [[R]]
175175
;
176176
%neg = xor <2 x i32> %x, <i32 -1 ,i32 -1>
@@ -485,3 +485,21 @@ define i32 @select_ctpop_zero(i32 %x) {
485485
%res = select i1 %cmp, i32 0, i32 %ctpop
486486
ret i32 %res
487487
}
488+
489+
define i32 @ctpop_non_zero(i32 range(i32 1, 255) %x) {
490+
; CHECK-LABEL: @ctpop_non_zero(
491+
; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 1, 9) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
492+
; CHECK-NEXT: ret i32 [[CTPOP]]
493+
;
494+
%ctpop = call i32 @llvm.ctpop.i32(i32 %x)
495+
ret i32 %ctpop
496+
}
497+
498+
define i32 @ctpop_non_zero_with_existing_range_attr(i32 range(i32 1, 255) %x) {
499+
; CHECK-LABEL: @ctpop_non_zero_with_existing_range_attr(
500+
; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 1, 9) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
501+
; CHECK-NEXT: ret i32 [[CTPOP]]
502+
;
503+
%ctpop = call range(i32 0, 9) i32 @llvm.ctpop.i32(i32 %x)
504+
ret i32 %ctpop
505+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ define i32 @pow2_32_nonconst_assume(i32 %x, i32 %y) {
306306

307307
define i32 @pow2_32_gtnonconst_assume(i32 %x, i32 %y) {
308308
; CHECK-LABEL: @pow2_32_gtnonconst_assume(
309-
; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
309+
; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[Y:%.*]])
310310
; CHECK-NEXT: [[YP2:%.*]] = icmp eq i32 [[CTPOP]], 1
311311
; CHECK-NEXT: call void @llvm.assume(i1 [[YP2]])
312312
; CHECK-NEXT: [[YGT:%.*]] = icmp ugt i32 [[Y]], [[X:%.*]]
@@ -513,7 +513,7 @@ define i32 @maybe_pow2_32_noncont(i32 %x, i32 %y) {
513513
; CHECK-NEXT: [[YGT8:%.*]] = icmp ugt i32 [[Y:%.*]], 8
514514
; CHECK-NEXT: br i1 [[YGT8]], label [[CONT1:%.*]], label [[CONT2:%.*]]
515515
; CHECK: Cont1:
516-
; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y]])
516+
; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[Y]])
517517
; CHECK-NEXT: [[YP2:%.*]] = icmp eq i32 [[CTPOP]], 1
518518
; CHECK-NEXT: call void @llvm.assume(i1 [[YP2]])
519519
; CHECK-NEXT: br i1 true, label [[CONT2]], label [[FALSE:%.*]]

llvm/test/Transforms/InstCombine/ispow2.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ define i1 @is_pow2_non_zero_ult_2(i32 %x) {
197197
; CHECK-LABEL: @is_pow2_non_zero_ult_2(
198198
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
199199
; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
200-
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X]])
200+
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])
201201
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
202202
; CHECK-NEXT: ret i1 [[CMP]]
203203
;
@@ -212,7 +212,7 @@ define i1 @is_pow2_non_zero_eq_1(i32 %x) {
212212
; CHECK-LABEL: @is_pow2_non_zero_eq_1(
213213
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
214214
; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
215-
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X]])
215+
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])
216216
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
217217
; CHECK-NEXT: ret i1 [[CMP]]
218218
;
@@ -227,7 +227,7 @@ define i1 @is_pow2_non_zero_ugt_1(i32 %x) {
227227
; CHECK-LABEL: @is_pow2_non_zero_ugt_1(
228228
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
229229
; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
230-
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X]])
230+
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])
231231
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
232232
; CHECK-NEXT: ret i1 [[CMP]]
233233
;
@@ -242,7 +242,7 @@ define i1 @is_pow2_non_zero_ne_1(i32 %x) {
242242
; CHECK-LABEL: @is_pow2_non_zero_ne_1(
243243
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0
244244
; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])
245-
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X]])
245+
; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])
246246
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1
247247
; CHECK-NEXT: ret i1 [[CMP]]
248248
;

0 commit comments

Comments
 (0)