-
Notifications
You must be signed in to change notification settings - Fork 12.4k
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] Canonicalize (X +/- Y) & Y
into ~X & Y
when Y is a power of 2
#67915
Conversation
@llvm/pr-subscribers-llvm-transforms ChangesThis patch canonicalizes the pattern Full diff: https://github.com/llvm/llvm-project/pull/67915.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index cbdab3e9c5fb91d..4322cc96f5a2b6c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2250,6 +2250,14 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
}
+ // Canonicalize:
+ // (X +/- Y) & Y --> ~X & Y when Y is a power of 2.
+ if (match(&I, m_c_And(m_Value(Y), m_OneUse(m_CombineOr(
+ m_c_Add(m_Value(X), m_Deferred(Y)),
+ m_Sub(m_Value(X), m_Deferred(Y)))))) &&
+ isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, /*Depth*/ 0, &I))
+ return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
+
const APInt *C;
if (match(Op1, m_APInt(C))) {
const APInt *XorC;
diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 90f027010e2aea6..eb39ff9014ff3a4 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1595,8 +1595,8 @@ define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
; CHECK-LABEL: @flip_masked_bit_undef(
-; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef>
-; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef>
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[TMP1]], <i8 16, i8 undef>
; CHECK-NEXT: ret <2 x i8> [[C]]
;
%B = add <2 x i8> %A, <i8 16, i8 undef>
@@ -1606,8 +1606,8 @@ define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
; CHECK-LABEL: @flip_masked_bit_nonuniform(
-; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4>
-; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4>
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[TMP1]], <i8 16, i8 4>
; CHECK-NEXT: ret <2 x i8> [[C]]
;
%B = add <2 x i8> %A, <i8 16, i8 4>
@@ -2546,3 +2546,39 @@ define i32 @and_zext_eq_zero(i32 %A, i32 %C) {
%5 = and i32 %2, %4
ret i32 %5
}
+
+define i32 @canonicalize_and_add_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero(
+; CHECK-NEXT: [[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT: call void @use32(i32 [[P2]])
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %ny = sub i32 0, %y
+ %p2 = and i32 %y, %ny
+ call void @use32(i32 %p2) ; keep p2
+
+ %val = add i32 %x, %p2
+ %and = and i32 %val, %p2
+ ret i32 %and
+}
+
+define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_sub_power2_or_zero(
+; CHECK-NEXT: [[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT: call void @use32(i32 [[P2]])
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %ny = sub i32 0, %y
+ %p2 = and i32 %y, %ny
+ call void @use32(i32 %p2) ; keep p2
+
+ %val = sub i32 %x, %p2
+ %and = and i32 %val, %p2
+ ret i32 %and
+}
|
LGTM. |
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.
Seems like some test coverage is missing here?
- Commuted add
- Commuted sub (negative test)
- Commuted and
- Multi-use add (negative test)
…Y is a power of 2 Add additional tests.
Can you please pre-commit the new tests as well (and double-check that there is no unexpected operand order canonicalization while doing that)? |
Ping. |
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
This patch canonicalizes the pattern
(X +/- Y) & Y
into~X & Y
whenY
is a power of 2 or zero.It will reduce the patterns to match in #67836 and exploit more optimization opportunities.
Alive2: https://alive2.llvm.org/ce/z/LBpvRF