-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
Conversation
…cmp eq/ne (lshr Y, X), 0)`; NFC
…q/ne (lshr Y, X), 0)` Proofs: https://alive2.llvm.org/ce/z/oSRGBt
@llvm/pr-subscribers-llvm-transforms Author: None (goldsteinn) ChangesProofs: https://alive2.llvm.org/ce/z/oSRGBt Full diff: https://github.com/llvm/llvm-project/pull/84691.diff 2 Files Affected:
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
+}
|
(icmp eq/ne (and (shl -1, X), Y), 0)
-> (icmp eq/ne (lshr Y, X), 0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Proofs: https://alive2.llvm.org/ce/z/oSRGBt