Skip to content

Commit 6d6bb29

Browse files
committed
[ValueTracking] Compute knownbits from (icmp upred (add/sub nuw X, Y), C)
`(icmp ule/ult (add nuw X, Y), C)` implies both `(icmp ule/ult X, C)` and `(icmp ule/ult Y, C)`. We can use this to deduce leading zeros in `X`/`Y`. `(icmp uge/ugt (sub nuw X, Y), C)` implies `(icmp uge/uge X, C)` . We can use this to deduce leading ones in `X`. Proofs: https://alive2.llvm.org/ce/z/sc5k22
1 parent 7ab43b6 commit 6d6bb29

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -701,13 +701,26 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
701701
break;
702702
}
703703
default:
704-
const APInt *Offset = nullptr;
705-
if (match(LHS, m_CombineOr(m_V, m_AddLike(m_V, m_APInt(Offset)))) &&
706-
match(RHS, m_APInt(C))) {
707-
ConstantRange LHSRange = ConstantRange::makeAllowedICmpRegion(Pred, *C);
708-
if (Offset)
709-
LHSRange = LHSRange.sub(*Offset);
710-
Known = Known.unionWith(LHSRange.toKnownBits());
704+
if (match(RHS, m_APInt(C))) {
705+
const APInt *Offset = nullptr;
706+
if (match(LHS, m_CombineOr(m_V, m_AddLike(m_V, m_APInt(Offset))))) {
707+
ConstantRange LHSRange = ConstantRange::makeAllowedICmpRegion(Pred, *C);
708+
if (Offset)
709+
LHSRange = LHSRange.sub(*Offset);
710+
Known = Known.unionWith(LHSRange.toKnownBits());
711+
}
712+
// X nuw+ Y u< C -> X u< C && Y u< C
713+
if ((Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_ULT) &&
714+
match(LHS, m_c_NUWAdd(m_V, m_Value()))) {
715+
Known.Zero.setHighBits(
716+
(*C - (Pred == ICmpInst::ICMP_ULT)).countLeadingZeros());
717+
}
718+
// X nuw- Y u> C -> X u> C
719+
if ((Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_UGT) &&
720+
match(LHS, m_NUWSub(m_V, m_Value()))) {
721+
Known.One.setHighBits(
722+
(*C + (Pred == ICmpInst::ICMP_UGT)).countLeadingOnes());
723+
}
711724
}
712725
break;
713726
}
@@ -9309,11 +9322,24 @@ void llvm::findValuesAffectedByCondition(
93099322
}
93109323
}
93119324
} else {
9312-
// Handle (A + C1) u< C2, which is the canonical form of
9313-
// A > C3 && A < C4.
9314-
if (match(A, m_AddLike(m_Value(X), m_ConstantInt())) &&
9315-
match(B, m_ConstantInt()))
9316-
AddAffected(X);
9325+
if (match(B, m_ConstantInt())) {
9326+
// Handle (A + C1) u< C2, which is the canonical form of
9327+
// A > C3 && A < C4.
9328+
if (match(A, m_AddLike(m_Value(X), m_ConstantInt())))
9329+
AddAffected(X);
9330+
9331+
if (ICmpInst::isUnsigned(Pred)) {
9332+
Value *Y;
9333+
// X nuw+ Y u< C -> X u< C && Y u< C
9334+
if (match(A, m_NUWAdd(m_Value(X), m_Value(Y)))) {
9335+
AddAffected(X);
9336+
AddAffected(Y);
9337+
}
9338+
// X nuw- Y u> C -> X u> C
9339+
if (match(A, m_NUWSub(m_Value(X), m_Value())))
9340+
AddAffected(X);
9341+
}
9342+
}
93179343

93189344
// Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported
93199345
// by computeKnownFPClass().

llvm/test/Transforms/InstCombine/known-bits.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,7 @@ define i8 @test_icmp_add(i8 %n, i8 %n2, i8 %other) {
637637
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_ADD]], 32
638638
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
639639
; CHECK: if.then:
640-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
641-
; CHECK-NEXT: ret i8 [[R]]
640+
; CHECK-NEXT: ret i8 0
642641
; CHECK: if.else:
643642
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
644643
;
@@ -664,8 +663,7 @@ define i8 @test_icmp_add2(i8 %n, i8 %n2, i8 %other) {
664663
; CHECK: if.then:
665664
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
666665
; CHECK: if.else:
667-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
668-
; CHECK-NEXT: ret i8 [[R]]
666+
; CHECK-NEXT: ret i8 0
669667
;
670668
entry:
671669
%n_add = add nuw i8 %n, %n2
@@ -737,8 +735,7 @@ define i8 @test_icmp_sub(i8 %n, i8 %n2, i8 %other) {
737735
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_AND]], -33
738736
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
739737
; CHECK: if.then:
740-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
741-
; CHECK-NEXT: ret i8 [[R]]
738+
; CHECK-NEXT: ret i8 32
742739
; CHECK: if.else:
743740
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
744741
;
@@ -789,8 +786,7 @@ define i8 @test_icmp_sub2(i8 %n, i8 %n2, i8 %other) {
789786
; CHECK: if.then:
790787
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
791788
; CHECK: if.else:
792-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
793-
; CHECK-NEXT: ret i8 [[R]]
789+
; CHECK-NEXT: ret i8 32
794790
;
795791
entry:
796792
%n_sub = sub nuw i8 %n, %n2

0 commit comments

Comments
 (0)