[llvm] [ValueTracking] Infer known bits fromfrom (icmp eq (and/or x,y), C) (PR #87143)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 29 23:43:34 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
@llvm/pr-subscribers-llvm-transforms
Author: None (goldsteinn)
<details>
<summary>Changes</summary>
- **[ValueTracking] Add tests for computing known bits from `(icmp eq (and/or x,y), C)`; NFC**
- **[ValueTracking] Infer known bits fromfrom `(icmp eq (and/or x,y), C)`**
---
Full diff: https://github.com/llvm/llvm-project/pull/87143.diff
3 Files Affected:
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+15-6)
- (modified) llvm/test/Transforms/InstCombine/known-bits.ll (+101-5)
- (modified) llvm/test/Transforms/InstCombine/zext-or-icmp.ll (+5-5)
``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index b5e8a1d22f264b..33a69861cc3c57 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -648,6 +648,7 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
auto m_V =
m_CombineOr(m_Specific(V), m_PtrToIntSameSize(Q.DL, m_Specific(V)));
+ Value *Y;
const APInt *Mask, *C;
uint64_t ShAmt;
switch (Pred) {
@@ -656,16 +657,18 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
if (match(LHS, m_V) && match(RHS, m_APInt(C))) {
Known = Known.unionWith(KnownBits::makeConstant(*C));
// assume(V & Mask = C)
- } else if (match(LHS, m_And(m_V, m_APInt(Mask))) &&
+ } else if (match(LHS, m_c_And(m_V, m_Value(Y))) &&
match(RHS, m_APInt(C))) {
// For one bits in Mask, we can propagate bits from C to V.
- Known.Zero |= ~*C & *Mask;
- Known.One |= *C & *Mask;
+ Known.One |= *C;
+ if (match(Y, m_APInt(Mask)))
+ Known.Zero |= ~*C & *Mask;
// assume(V | Mask = C)
- } else if (match(LHS, m_Or(m_V, m_APInt(Mask))) && match(RHS, m_APInt(C))) {
+ } else if (match(LHS, m_c_Or(m_V, m_Value(Y))) && match(RHS, m_APInt(C))) {
// For zero bits in Mask, we can propagate bits from C to V.
- Known.Zero |= ~*C & ~*Mask;
- Known.One |= *C & ~*Mask;
+ Known.Zero |= ~*C;
+ if (match(Y, m_APInt(Mask)))
+ Known.One |= *C & ~*Mask;
// assume(V ^ Mask = C)
} else if (match(LHS, m_Xor(m_V, m_APInt(Mask))) &&
match(RHS, m_APInt(C))) {
@@ -9276,11 +9279,17 @@ void llvm::findValuesAffectedByCondition(
if (ICmpInst::isEquality(Pred)) {
if (match(B, m_ConstantInt())) {
+ Value *Y;
// (X & C) or (X | C) or (X ^ C).
// (X << C) or (X >>_s C) or (X >>_u C).
if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
match(A, m_Shift(m_Value(X), m_ConstantInt())))
AddAffected(X);
+ else if (match(A, m_And(m_Value(X), m_Value(Y))) ||
+ match(A, m_Or(m_Value(X), m_Value(Y)))) {
+ AddAffected(X);
+ AddAffected(Y);
+ }
}
} else {
// Handle (A + C1) u< C2, which is the canonical form of
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 5305c78f691231..769f7661fc8dc0 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -124,7 +124,6 @@ exit:
ret i8 %or2
}
-
define i8 @test_cond_and_bothways(i8 %x) {
; CHECK-LABEL: @test_cond_and_bothways(
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], 91
@@ -181,8 +180,6 @@ exit:
ret i8 %or2
}
-
-
define i8 @test_cond_and_commuted(i8 %x, i1 %c1, i1 %c2) {
; CHECK-LABEL: @test_cond_and_commuted(
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], 3
@@ -343,7 +340,7 @@ exit:
ret i8 %or2
}
-define i32 @test_icmp_trunc1(i32 %x){
+define i32 @test_icmp_trunc1(i32 %x) {
; CHECK-LABEL: @test_icmp_trunc1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i16
@@ -365,7 +362,7 @@ else:
ret i32 0
}
-define i32 @test_icmp_trunc_assume(i32 %x){
+define i32 @test_icmp_trunc_assume(i32 %x) {
; CHECK-LABEL: @test_icmp_trunc_assume(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i16
@@ -532,7 +529,106 @@ if.else:
ret i1 %other
}
+define i8 @and_eq_bits_must_be_set(i8 %x, i8 %y) {
+; CHECK-LABEL: @and_eq_bits_must_be_set(
+; CHECK-NEXT: [[XY:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 123
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i8 1
+;
+ %xy = and i8 %x, %y
+ %cmp = icmp eq i8 %xy, 123
+ call void @llvm.assume(i1 %cmp)
+ %r = and i8 %x, 1
+ ret i8 %r
+}
+
+define i8 @and_eq_bits_must_be_set2(i8 %x, i8 %y) {
+; CHECK-LABEL: @and_eq_bits_must_be_set2(
+; CHECK-NEXT: [[XY:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 123
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i8 11
+;
+ %xy = and i8 %x, %y
+ %cmp = icmp eq i8 %xy, 123
+ call void @llvm.assume(i1 %cmp)
+ %r = and i8 %y, 11
+ ret i8 %r
+}
+
+define i8 @and_eq_bits_must_be_set2_partial_fail(i8 %x, i8 %y) {
+; CHECK-LABEL: @and_eq_bits_must_be_set2_partial_fail(
+; CHECK-NEXT: [[XY:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 123
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: [[R:%.*]] = and i8 [[Y]], 111
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %xy = and i8 %x, %y
+ %cmp = icmp eq i8 %xy, 123
+ call void @llvm.assume(i1 %cmp)
+ %r = and i8 %y, 111
+ ret i8 %r
+}
+
+define i8 @or_eq_bits_must_be_unset(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_eq_bits_must_be_unset(
+; CHECK-NEXT: [[XY:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 124
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i8 0
+;
+ %xy = or i8 %x, %y
+ %cmp = icmp eq i8 %xy, 124
+ call void @llvm.assume(i1 %cmp)
+ %r = and i8 %x, 3
+ ret i8 %r
+}
+
+define i8 @or_eq_bits_must_be_unset2(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_eq_bits_must_be_unset2(
+; CHECK-NEXT: [[XY:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 124
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i8 0
+;
+ %xy = or i8 %x, %y
+ %cmp = icmp eq i8 %xy, 124
+ call void @llvm.assume(i1 %cmp)
+ %r = and i8 %y, 1
+ ret i8 %r
+}
+define i8 @or_eq_bits_must_be_unset2_partial_fail(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_eq_bits_must_be_unset2_partial_fail(
+; CHECK-NEXT: [[XY:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XY]], 124
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: [[R:%.*]] = and i8 [[Y]], 4
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %xy = or i8 %x, %y
+ %cmp = icmp eq i8 %xy, 124
+ call void @llvm.assume(i1 %cmp)
+ %r = and i8 %y, 7
+ ret i8 %r
+}
+
+define i8 @or_ne_bits_must_be_unset2_fail(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_ne_bits_must_be_unset2_fail(
+; CHECK-NEXT: [[XY:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[XY]], 124
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 3
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %xy = or i8 %x, %y
+ %cmp = icmp ne i8 %xy, 124
+ call void @llvm.assume(i1 %cmp)
+ %r = and i8 %x, 3
+ ret i8 %r
+}
declare void @use(i1)
declare void @sink(i8)
diff --git a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll
index 661c36038a67ea..a4b74aa8cc7dc3 100644
--- a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+; RUN: opt < %s -passes='instcombine<no-verify-fixpoint>' -S | FileCheck %s
define i8 @zext_or_icmp_icmp(i8 %a, i8 %b) {
; CHECK-LABEL: @zext_or_icmp_icmp(
@@ -180,11 +180,11 @@ define i8 @PR49475_infloop(i32 %t0, i16 %insert, i64 %e, i8 %i162) {
; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[SUB17]], 32
; CHECK-NEXT: [[CONV18:%.*]] = ashr exact i64 [[SEXT]], 32
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i64 [[XOR]], [[CONV18]]
-; CHECK-NEXT: [[CONV19:%.*]] = zext i1 [[CMP]] to i16
-; CHECK-NEXT: [[OR21:%.*]] = or i16 [[CONV19]], [[INSERT]]
-; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = icmp eq i16 [[OR21]], 0
+; CHECK-NEXT: [[TRUNC44:%.*]] = zext i1 [[CMP]] to i8
+; CHECK-NEXT: [[INC:%.*]] = add i8 [[TRUNC44]], [[I162]]
+; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = xor i1 [[CMP]], true
; CHECK-NEXT: call void @llvm.assume(i1 [[TOBOOL23_NOT]])
-; CHECK-NEXT: ret i8 [[I162]]
+; CHECK-NEXT: ret i8 [[INC]]
;
%b = icmp eq i32 %t0, 0
%b2 = icmp eq i16 %insert, 0
``````````
</details>
https://github.com/llvm/llvm-project/pull/87143
More information about the llvm-commits
mailing list