Skip to content

Commit 05cff99

Browse files
committed
[ValueTracking] Infer known bits fromfrom (icmp eq (and/or x,y), C)
In `(icmp eq (and x,y), C)` all 1s in `C` must also be set in both `x`/`y`. In `(icmp eq (or x,y), C)` all 0s in `C` must also be set in both `x`/`y`. Closes #87143
1 parent 02b49d1 commit 05cff99

File tree

3 files changed

+25
-20
lines changed

3 files changed

+25
-20
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
648648
auto m_V =
649649
m_CombineOr(m_Specific(V), m_PtrToIntSameSize(Q.DL, m_Specific(V)));
650650

651+
Value *Y;
651652
const APInt *Mask, *C;
652653
uint64_t ShAmt;
653654
switch (Pred) {
@@ -656,16 +657,18 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
656657
if (match(LHS, m_V) && match(RHS, m_APInt(C))) {
657658
Known = Known.unionWith(KnownBits::makeConstant(*C));
658659
// assume(V & Mask = C)
659-
} else if (match(LHS, m_And(m_V, m_APInt(Mask))) &&
660+
} else if (match(LHS, m_c_And(m_V, m_Value(Y))) &&
660661
match(RHS, m_APInt(C))) {
661662
// For one bits in Mask, we can propagate bits from C to V.
662-
Known.Zero |= ~*C & *Mask;
663-
Known.One |= *C & *Mask;
663+
Known.One |= *C;
664+
if (match(Y, m_APInt(Mask)))
665+
Known.Zero |= ~*C & *Mask;
664666
// assume(V | Mask = C)
665-
} else if (match(LHS, m_Or(m_V, m_APInt(Mask))) && match(RHS, m_APInt(C))) {
667+
} else if (match(LHS, m_c_Or(m_V, m_Value(Y))) && match(RHS, m_APInt(C))) {
666668
// For zero bits in Mask, we can propagate bits from C to V.
667-
Known.Zero |= ~*C & ~*Mask;
668-
Known.One |= *C & ~*Mask;
669+
Known.Zero |= ~*C;
670+
if (match(Y, m_APInt(Mask)))
671+
Known.One |= *C & ~*Mask;
669672
// assume(V ^ Mask = C)
670673
} else if (match(LHS, m_Xor(m_V, m_APInt(Mask))) &&
671674
match(RHS, m_APInt(C))) {
@@ -9276,11 +9279,17 @@ void llvm::findValuesAffectedByCondition(
92769279

92779280
if (ICmpInst::isEquality(Pred)) {
92789281
if (match(B, m_ConstantInt())) {
9282+
Value *Y;
92799283
// (X & C) or (X | C) or (X ^ C).
92809284
// (X << C) or (X >>_s C) or (X >>_u C).
92819285
if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
92829286
match(A, m_Shift(m_Value(X), m_ConstantInt())))
92839287
AddAffected(X);
9288+
else if (match(A, m_And(m_Value(X), m_Value(Y))) ||
9289+
match(A, m_Or(m_Value(X), m_Value(Y)))) {
9290+
AddAffected(X);
9291+
AddAffected(Y);
9292+
}
92849293
}
92859294
} else {
92869295
// Handle (A + C1) u< C2, which is the canonical form of

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,7 @@ define i8 @and_eq_bits_must_be_set(i8 %x, i8 %y) {
534534
; CHECK-NEXT: [[XY:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
535535
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 123
536536
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
537-
; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 1
538-
; CHECK-NEXT: ret i8 [[R]]
537+
; CHECK-NEXT: ret i8 1
539538
;
540539
%xy = and i8 %x, %y
541540
%cmp = icmp eq i8 %xy, 123
@@ -549,8 +548,7 @@ define i8 @and_eq_bits_must_be_set2(i8 %x, i8 %y) {
549548
; CHECK-NEXT: [[XY:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
550549
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 123
551550
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
552-
; CHECK-NEXT: [[R:%.*]] = and i8 [[Y]], 11
553-
; CHECK-NEXT: ret i8 [[R]]
551+
; CHECK-NEXT: ret i8 11
554552
;
555553
%xy = and i8 %x, %y
556554
%cmp = icmp eq i8 %xy, 123
@@ -579,8 +577,7 @@ define i8 @or_eq_bits_must_be_unset(i8 %x, i8 %y) {
579577
; CHECK-NEXT: [[XY:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
580578
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 124
581579
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
582-
; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 3
583-
; CHECK-NEXT: ret i8 [[R]]
580+
; CHECK-NEXT: ret i8 0
584581
;
585582
%xy = or i8 %x, %y
586583
%cmp = icmp eq i8 %xy, 124
@@ -594,8 +591,7 @@ define i8 @or_eq_bits_must_be_unset2(i8 %x, i8 %y) {
594591
; CHECK-NEXT: [[XY:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
595592
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 124
596593
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
597-
; CHECK-NEXT: [[R:%.*]] = and i8 [[Y]], 1
598-
; CHECK-NEXT: ret i8 [[R]]
594+
; CHECK-NEXT: ret i8 0
599595
;
600596
%xy = or i8 %x, %y
601597
%cmp = icmp eq i8 %xy, 124
@@ -609,7 +605,7 @@ define i8 @or_eq_bits_must_be_unset2_partial_fail(i8 %x, i8 %y) {
609605
; CHECK-NEXT: [[XY:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
610606
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 124
611607
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
612-
; CHECK-NEXT: [[R:%.*]] = and i8 [[Y]], 7
608+
; CHECK-NEXT: [[R:%.*]] = and i8 [[Y]], 4
613609
; CHECK-NEXT: ret i8 [[R]]
614610
;
615611
%xy = or i8 %x, %y

llvm/test/Transforms/InstCombine/zext-or-icmp.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
2+
; RUN: opt < %s -passes='instcombine<no-verify-fixpoint>' -S | FileCheck %s
33

44
define i8 @zext_or_icmp_icmp(i8 %a, i8 %b) {
55
; CHECK-LABEL: @zext_or_icmp_icmp(
@@ -180,11 +180,11 @@ define i8 @PR49475_infloop(i32 %t0, i16 %insert, i64 %e, i8 %i162) {
180180
; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[SUB17]], 32
181181
; CHECK-NEXT: [[CONV18:%.*]] = ashr exact i64 [[SEXT]], 32
182182
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i64 [[XOR]], [[CONV18]]
183-
; CHECK-NEXT: [[CONV19:%.*]] = zext i1 [[CMP]] to i16
184-
; CHECK-NEXT: [[OR21:%.*]] = or i16 [[CONV19]], [[INSERT]]
185-
; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = icmp eq i16 [[OR21]], 0
183+
; CHECK-NEXT: [[TRUNC44:%.*]] = zext i1 [[CMP]] to i8
184+
; CHECK-NEXT: [[INC:%.*]] = add i8 [[TRUNC44]], [[I162]]
185+
; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = xor i1 [[CMP]], true
186186
; CHECK-NEXT: call void @llvm.assume(i1 [[TOBOOL23_NOT]])
187-
; CHECK-NEXT: ret i8 [[I162]]
187+
; CHECK-NEXT: ret i8 [[INC]]
188188
;
189189
%b = icmp eq i32 %t0, 0
190190
%b2 = icmp eq i16 %insert, 0

0 commit comments

Comments
 (0)