Skip to content

Commit cba358c

Browse files
committed
[ValueTracking] compute knownbits from (icmp upred X (and/or X, Y)); NFC
`(icmp uge/ugt (and X, Y), C)` implies both `(icmp uge/ugt X, C)` and `(icmp uge/ugt Y, C)`. We can use this to deduce leading ones in `X`. `(icmp ule/ult (or 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`.
1 parent c22a9d3 commit cba358c

File tree

2 files changed

+40
-20
lines changed

2 files changed

+40
-20
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 36 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 & Y u> C -> X u> C && Y u> C
713+
if ((Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) &&
714+
match(LHS, m_c_And(m_V, m_Value()))) {
715+
Known.One.setHighBits(
716+
(*C + (Pred == ICmpInst::ICMP_UGT)).countLeadingOnes());
717+
}
718+
// X | Y u< C -> X u< C && Y u< C
719+
if ((Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) &&
720+
match(LHS, m_c_Or(m_V, m_Value()))) {
721+
Known.Zero.setHighBits(
722+
(*C - (Pred == ICmpInst::ICMP_ULT)).countLeadingZeros());
723+
}
711724
}
712725
break;
713726
}
@@ -9309,11 +9322,22 @@ 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+
Value *Y;
9332+
// X & Y u> C -> X >u C && Y >u C
9333+
// X | Y u< C -> X u< C && Y u< C
9334+
if (ICmpInst::isUnsigned(Pred) &&
9335+
(match(A, m_And(m_Value(X), m_Value(Y))) ||
9336+
match(A, m_Or(m_Value(X), m_Value(Y))))) {
9337+
AddAffected(X);
9338+
AddAffected(Y);
9339+
}
9340+
}
93179341

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

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,7 @@ define i8 @test_icmp_or(i8 %n, i8 %n2, i8 %other) {
550550
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_OR]], 32
551551
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
552552
; CHECK: if.then:
553-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
554-
; CHECK-NEXT: ret i8 [[R]]
553+
; CHECK-NEXT: ret i8 0
555554
; CHECK: if.else:
556555
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
557556
;
@@ -577,8 +576,7 @@ define i8 @test_icmp_or2(i8 %n, i8 %n2, i8 %other) {
577576
; CHECK: if.then:
578577
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
579578
; CHECK: if.else:
580-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
581-
; CHECK-NEXT: ret i8 [[R]]
579+
; CHECK-NEXT: ret i8 0
582580
;
583581
entry:
584582
%n_or = or i8 %n, %n2
@@ -650,8 +648,7 @@ define i8 @test_icmp_and(i8 %n, i8 %n2, i8 %other) {
650648
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_AND]], -33
651649
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
652650
; CHECK: if.then:
653-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
654-
; CHECK-NEXT: ret i8 [[R]]
651+
; CHECK-NEXT: ret i8 32
655652
; CHECK: if.else:
656653
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
657654
;
@@ -677,8 +674,7 @@ define i8 @test_icmp_and2(i8 %n, i8 %n2, i8 %other) {
677674
; CHECK: if.then:
678675
; CHECK-NEXT: ret i8 [[OTHER:%.*]]
679676
; CHECK: if.else:
680-
; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32
681-
; CHECK-NEXT: ret i8 [[R]]
677+
; CHECK-NEXT: ret i8 32
682678
;
683679
entry:
684680
%n_and = and i8 %n, %n2

0 commit comments

Comments
 (0)