Skip to content

[ValueTracking] Compute knownbits for (and/or cond0, cond1) on both sides of branch #82818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

goldsteinn
Copy link
Contributor

@goldsteinn goldsteinn commented Feb 23, 2024

The false branch for and and true branch for or provide less
information (intersection as opposed to union), but still can give
some useful information.

@llvmbot
Copy link
Member

llvmbot commented Feb 23, 2024

@llvm/pr-subscribers-llvm-analysis

Author: None (goldsteinn)

Changes
  • [ValueTracking] Add tests for tracking `(and/or cond0
  • [ValueTracking] Compute knownbits for `(and/or cond0

Full diff: https://github.com/llvm/llvm-project/pull/82818.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+11-4)
  • (modified) llvm/test/Transforms/InstCombine/known-bits.ll (+59)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 653b3d4ffd9883..562b1e574aea4d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -711,10 +711,17 @@ static void computeKnownBitsFromCond(const Value *V, Value *Cond,
                                      const SimplifyQuery &SQ, bool Invert) {
   Value *A, *B;
   if (Depth < MaxAnalysisRecursionDepth &&
-      (Invert ? match(Cond, m_LogicalOr(m_Value(A), m_Value(B)))
-              : match(Cond, m_LogicalAnd(m_Value(A), m_Value(B))))) {
-    computeKnownBitsFromCond(V, A, Known, Depth + 1, SQ, Invert);
-    computeKnownBitsFromCond(V, B, Known, Depth + 1, SQ, Invert);
+      match(Cond, m_LogicalOp(m_Value(A), m_Value(B)))) {
+    KnownBits Known2(Known.getBitWidth());
+    KnownBits Known3(Known.getBitWidth());
+    computeKnownBitsFromCond(V, A, Known2, Depth + 1, SQ, Invert);
+    computeKnownBitsFromCond(V, B, Known3, Depth + 1, SQ, Invert);
+    if (Invert ? match(Cond, m_LogicalOr(m_Value(A), m_Value(B)))
+               : match(Cond, m_LogicalAnd(m_Value(A), m_Value(B))))
+      Known = Known2.unionWith(Known3);
+    else
+      Known2 = Known2.intersectWith(Known3);
+    Known = Known.unionWith(Known2);
   }
 
   if (auto *Cmp = dyn_cast<ICmpInst>(Cond))
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 246579cc4cd0c0..b658ee0d2ef4e2 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -124,6 +124,65 @@ 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
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp ne i8 [[AND]], 24
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X]], 0
+; CHECK-NEXT:    [[COND:%.*]] = and i1 [[CMP0]], [[CMP1]]
+; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OR1:%.*]] = or i8 [[X]], -4
+; CHECK-NEXT:    ret i8 [[OR1]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i8 -4
+;
+  %and = and i8 %x, 91
+  %cmp0 = icmp ne i8 %and, 24
+  %cmp1 = icmp ne i8 %x, 0
+  %cond = and i1 %cmp0, %cmp1
+  br i1 %cond, label %if, label %exit
+
+if:
+  %or1 = or i8 %x, -4
+  ret i8 %or1
+
+exit:
+  %or2 = or i8 %x, -4
+  ret i8 %or2
+}
+
+define i8 @test_cond_or_bothways(i8 %x) {
+; CHECK-LABEL: @test_cond_or_bothways(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 91
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp eq i8 [[AND]], 24
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT:    [[COND:%.*]] = or i1 [[CMP0]], [[CMP1]]
+; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    ret i8 -4
+; CHECK:       exit:
+; CHECK-NEXT:    [[OR2:%.*]] = or i8 [[X]], -4
+; CHECK-NEXT:    ret i8 [[OR2]]
+;
+  %and = and i8 %x, 91
+  %cmp0 = icmp eq i8 %and, 24
+  %cmp1 = icmp eq i8 %x, 0
+  %cond = or i1 %cmp0, %cmp1
+  br i1 %cond, label %if, label %exit
+
+if:
+  %or1 = or i8 %x, -4
+  ret i8 %or1
+
+exit:
+  %or2 = or i8 %x, -4
+  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

@llvmbot
Copy link
Member

llvmbot commented Feb 23, 2024

@llvm/pr-subscribers-llvm-transforms

Author: None (goldsteinn)

Changes
  • [ValueTracking] Add tests for tracking `(and/or cond0
  • [ValueTracking] Compute knownbits for `(and/or cond0

Full diff: https://github.com/llvm/llvm-project/pull/82818.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+11-4)
  • (modified) llvm/test/Transforms/InstCombine/known-bits.ll (+59)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 653b3d4ffd9883..562b1e574aea4d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -711,10 +711,17 @@ static void computeKnownBitsFromCond(const Value *V, Value *Cond,
                                      const SimplifyQuery &SQ, bool Invert) {
   Value *A, *B;
   if (Depth < MaxAnalysisRecursionDepth &&
-      (Invert ? match(Cond, m_LogicalOr(m_Value(A), m_Value(B)))
-              : match(Cond, m_LogicalAnd(m_Value(A), m_Value(B))))) {
-    computeKnownBitsFromCond(V, A, Known, Depth + 1, SQ, Invert);
-    computeKnownBitsFromCond(V, B, Known, Depth + 1, SQ, Invert);
+      match(Cond, m_LogicalOp(m_Value(A), m_Value(B)))) {
+    KnownBits Known2(Known.getBitWidth());
+    KnownBits Known3(Known.getBitWidth());
+    computeKnownBitsFromCond(V, A, Known2, Depth + 1, SQ, Invert);
+    computeKnownBitsFromCond(V, B, Known3, Depth + 1, SQ, Invert);
+    if (Invert ? match(Cond, m_LogicalOr(m_Value(A), m_Value(B)))
+               : match(Cond, m_LogicalAnd(m_Value(A), m_Value(B))))
+      Known = Known2.unionWith(Known3);
+    else
+      Known2 = Known2.intersectWith(Known3);
+    Known = Known.unionWith(Known2);
   }
 
   if (auto *Cmp = dyn_cast<ICmpInst>(Cond))
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 246579cc4cd0c0..b658ee0d2ef4e2 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -124,6 +124,65 @@ 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
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp ne i8 [[AND]], 24
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X]], 0
+; CHECK-NEXT:    [[COND:%.*]] = and i1 [[CMP0]], [[CMP1]]
+; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OR1:%.*]] = or i8 [[X]], -4
+; CHECK-NEXT:    ret i8 [[OR1]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i8 -4
+;
+  %and = and i8 %x, 91
+  %cmp0 = icmp ne i8 %and, 24
+  %cmp1 = icmp ne i8 %x, 0
+  %cond = and i1 %cmp0, %cmp1
+  br i1 %cond, label %if, label %exit
+
+if:
+  %or1 = or i8 %x, -4
+  ret i8 %or1
+
+exit:
+  %or2 = or i8 %x, -4
+  ret i8 %or2
+}
+
+define i8 @test_cond_or_bothways(i8 %x) {
+; CHECK-LABEL: @test_cond_or_bothways(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 91
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp eq i8 [[AND]], 24
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT:    [[COND:%.*]] = or i1 [[CMP0]], [[CMP1]]
+; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    ret i8 -4
+; CHECK:       exit:
+; CHECK-NEXT:    [[OR2:%.*]] = or i8 [[X]], -4
+; CHECK-NEXT:    ret i8 [[OR2]]
+;
+  %and = and i8 %x, 91
+  %cmp0 = icmp eq i8 %and, 24
+  %cmp1 = icmp eq i8 %x, 0
+  %cond = or i1 %cmp0, %cmp1
+  br i1 %cond, label %if, label %exit
+
+if:
+  %or1 = or i8 %x, -4
+  ret i8 %or1
+
+exit:
+  %or2 = or i8 %x, -4
+  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

@goldsteinn goldsteinn requested a review from dtcxzyw February 23, 2024 19:32
@goldsteinn goldsteinn changed the title goldsteinn/kb both sides [ValueTracking] Compute knownbits for (and/or cond0, cond1) on both sides of branch Feb 23, 2024
dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Feb 23, 2024
@goldsteinn goldsteinn force-pushed the goldsteinn/kb-both-sides branch from b43f0da to a6a7dcd Compare February 23, 2024 20:04
@nikic
Copy link
Contributor

nikic commented Feb 23, 2024

@dtcxzyw Can you please rerun the tests?

@goldsteinn What's the compile-time impact?

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Feb 23, 2024
@goldsteinn
Copy link
Contributor Author

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll also have to adjust the logic in DomCondCache to recurse into all and/or, not just ones that match the top-level type. Unless you intentionally only want to handle the inverted type at the top level?

Please recheck compile-time impact after doing that.

… sides of branch

The false branch for `and` and true branch for `or` provide less
information (intersection as opposed to union), but still can give
some useful information.
@goldsteinn goldsteinn force-pushed the goldsteinn/kb-both-sides branch from a6a7dcd to 69d7bdd Compare February 23, 2024 21:51
@goldsteinn
Copy link
Contributor Author

You'll also have to adjust the logic in DomCondCache to recurse into all and/or, not just ones that match the top-level type. Unless you intentionally only want to handle the inverted type at the top level?

Please recheck compile-time impact after doing that.

https://llvm-compile-time-tracker.com/compare.php?from=55bc0488af077acb47be70542718d1bc17f3de4f&to=d3e117a04afb14a00686eb689213776b2921154b&stat=instructions%3Au

Mostly minimal with two notable regressions:
Stage2-O0-g: tramp3d-v4 20259M 20310M (+0.25%)
Stage1-ReleaseLTO-g: consumer-typeset 58135M 58200M (+0.11%)

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants