Skip to content
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

[InstCombine] fold (icmp eq/ne (and (shl -1, X), Y), 0) -> (icmp eq/ne (lshr Y, X), 0) #84691

Closed

Conversation

goldsteinn
Copy link
Contributor

@goldsteinn goldsteinn commented Mar 10, 2024

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 10, 2024

@llvm/pr-subscribers-llvm-transforms

Author: None (goldsteinn)

Changes

Proofs: https://alive2.llvm.org/ce/z/oSRGBt


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+11)
  • (modified) llvm/test/Transforms/InstCombine/icmp-and-shift.ll (+86)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 5b412a52e1644a..e71f3e113b96e8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1962,6 +1962,17 @@ Instruction *InstCombinerImpl::foldICmpAndConstant(ICmpInst &Cmp,
     return BinaryOperator::CreateAnd(TruncY, X);
   }
 
+  // (icmp eq/ne (and (shl -1, X), Y), 0)
+  //    -> (icmp eq/ne (lshr Y, X), 0)
+  // We could technically handle any C == 0 or (C < 0 && isOdd(C)) but it seems
+  // highly unlikely the non-zero case will ever show up in code.
+  if (C.isZero() &&
+      match(And, m_OneUse(m_c_And(m_OneUse(m_Shl(m_AllOnes(), m_Value(X))),
+                                  m_Value(Y))))) {
+    Value *LShr = Builder.CreateLShr(Y, X);
+    return new ICmpInst(Pred, LShr, Constant::getNullValue(LShr->getType()));
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll
index b0d4dabb738409..08d23e84c39600 100644
--- a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll
@@ -520,3 +520,89 @@ define i1 @slt_and_shl_one(i8 %x, i8 %y) {
   %cmp = icmp slt i8 %and, %pow2
   ret i1 %cmp
 }
+
+define i1 @fold_eq_lhs(i8 %x, i8 %y) {
+; CHECK-LABEL: @fold_eq_lhs(
+; CHECK-NEXT:    [[AND:%.*]] = lshr i8 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[AND]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %shl = shl i8 -1, %x
+  %and = and i8 %shl, %y
+  %r = icmp eq i8 %and, 0
+  ret i1 %r
+}
+
+define i1 @fold_eq_lhs_fail_eq_nonzero(i8 %x, i8 %y) {
+; CHECK-LABEL: @fold_eq_lhs_fail_eq_nonzero(
+; CHECK-NEXT:    [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[SHL]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[AND]], 1
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %shl = shl i8 -1, %x
+  %and = and i8 %shl, %y
+  %r = icmp eq i8 %and, 1
+  ret i1 %r
+}
+
+define i1 @fold_eq_lhs_fail_multiuse_shl(i8 %x, i8 %y) {
+; CHECK-LABEL: @fold_eq_lhs_fail_multiuse_shl(
+; CHECK-NEXT:    [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]]
+; CHECK-NEXT:    call void @use(i8 [[SHL]])
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[SHL]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[AND]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %shl = shl i8 -1, %x
+  call void @use(i8 %shl)
+  %and = and i8 %shl, %y
+  %r = icmp eq i8 %and, 0
+  ret i1 %r
+}
+
+define i1 @fold_ne_rhs(i8 %x, i8 %yy) {
+; CHECK-LABEL: @fold_ne_rhs(
+; CHECK-NEXT:    [[Y:%.*]] = xor i8 [[YY:%.*]], 123
+; CHECK-NEXT:    [[AND:%.*]] = lshr i8 [[Y]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[AND]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %y = xor i8 %yy, 123
+  %shl = shl i8 -1, %x
+  %and = and i8 %y, %shl
+  %r = icmp ne i8 %and, 0
+  ret i1 %r
+}
+
+define i1 @fold_ne_rhs_fail_multiuse_and(i8 %x, i8 %yy) {
+; CHECK-LABEL: @fold_ne_rhs_fail_multiuse_and(
+; CHECK-NEXT:    [[Y:%.*]] = xor i8 [[YY:%.*]], 123
+; CHECK-NEXT:    [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y]], [[SHL]]
+; CHECK-NEXT:    call void @use(i8 [[AND]])
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[AND]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %y = xor i8 %yy, 123
+  %shl = shl i8 -1, %x
+  %and = and i8 %y, %shl
+  call void @use(i8 %and)
+  %r = icmp ne i8 %and, 0
+  ret i1 %r
+}
+
+define i1 @fold_ne_rhs_fail_shift_not_1s(i8 %x, i8 %yy) {
+; CHECK-LABEL: @fold_ne_rhs_fail_shift_not_1s(
+; CHECK-NEXT:    [[Y:%.*]] = xor i8 [[YY:%.*]], 122
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 -2, [[X:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y]], [[SHL]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[AND]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %y = xor i8 %yy, 123
+  %shl = shl i8 -2, %x
+  %and = and i8 %y, %shl
+  %r = icmp ne i8 %and, 0
+  ret i1 %r
+}

@goldsteinn goldsteinn changed the title goldsteinn/shl 1 x and y eq 0 [InstCombine] fold (icmp eq/ne (and (shl -1, X), Y), 0) -> (icmp eq/ne (lshr Y, X), 0) Mar 10, 2024
dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Mar 10, 2024
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.

LG

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.

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.

None yet

4 participants