-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[InstCombine] Extend #125676 to handle variable power of 2 #125855
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
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesAlive2: https://alive2.llvm.org/ce/z/dJehZ8 Full diff: https://github.com/llvm/llvm-project/pull/125855.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 8701f7c28a39fc..ca4d34d09c3c73 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -4200,14 +4200,14 @@ Value *InstCombinerImpl::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS,
// Fold (icmp eq/ne (X & Pow2), 0) ^ (icmp eq/ne (Y & Pow2), 0) into
// (icmp eq/ne ((X ^ Y) & Pow2), 0)
- Value *X, *Y;
- const APInt *Mask;
+ Value *X, *Y, *Mask;
if (ICmpInst::isEquality(PredL) && ICmpInst::isEquality(PredR) &&
LC->isZero() && RC->isZero() && LHS->hasOneUse() && RHS->hasOneUse() &&
- match(LHS0, m_And(m_Value(X), m_Power2(Mask))) &&
- match(RHS0, m_And(m_Value(Y), m_SpecificInt(*Mask)))) {
+ match(LHS0, m_And(m_Value(X), m_Value(Mask))) &&
+ match(RHS0, m_And(m_Value(Y), m_Specific(Mask))) &&
+ isKnownToBeAPowerOfTwo(Mask, /*OrZero=*/true, /*Depth=*/0, &I)) {
Value *Xor = Builder.CreateXor(X, Y);
- Value *And = Builder.CreateAnd(Xor, *Mask);
+ Value *And = Builder.CreateAnd(Xor, Mask);
return Builder.CreateICmp(PredL == PredR ? ICmpInst::ICMP_NE
: ICmpInst::ICMP_EQ,
And, ConstantInt::getNullValue(Xor->getType()));
diff --git a/llvm/test/Transforms/InstCombine/xor-icmps.ll b/llvm/test/Transforms/InstCombine/xor-icmps.ll
index 382355cae7694d..55af2116aacd18 100644
--- a/llvm/test/Transforms/InstCombine/xor-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/xor-icmps.ll
@@ -335,6 +335,42 @@ define i1 @test_xor_of_bittest_ne_ne(i8 %x, i8 %y) {
ret i1 %xor
}
+define i1 @test_xor_of_bittest_ne_ne_var_pow2(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @test_xor_of_bittest_ne_ne_var_pow2(
+; CHECK-NEXT: [[POW2:%.*]] = shl nuw i8 1, [[SHAMT:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X:%.*]], [[Y1:%.*]]
+; CHECK-NEXT: [[MASK2:%.*]] = and i8 [[Y]], [[POW2]]
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[MASK2]], 0
+; CHECK-NEXT: ret i1 [[CMP2]]
+;
+ %pow2 = shl nuw i8 1, %shamt
+ %mask1 = and i8 %x, %pow2
+ %cmp1 = icmp ne i8 %mask1, 0
+ %mask2 = and i8 %y, %pow2
+ %cmp2 = icmp ne i8 %mask2, 0
+ %xor = xor i1 %cmp1, %cmp2
+ ret i1 %xor
+}
+
+define i1 @test_xor_of_bittest_ne_ne_var_pow2_or_zero(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_xor_of_bittest_ne_ne_var_pow2_or_zero(
+; CHECK-NEXT: [[NZ:%.*]] = sub i8 0, [[Z:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[NZ]]
+; CHECK-NEXT: [[MASK2:%.*]] = and i8 [[TMP2]], [[Z]]
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[MASK2]], 0
+; CHECK-NEXT: ret i1 [[CMP2]]
+;
+ %nz = sub i8 0, %z
+ %pow2 = and i8 %z, %nz
+ %mask1 = and i8 %x, %pow2
+ %cmp1 = icmp ne i8 %mask1, 0
+ %mask2 = and i8 %y, %pow2
+ %cmp2 = icmp ne i8 %mask2, 0
+ %xor = xor i1 %cmp1, %cmp2
+ ret i1 %xor
+}
+
define i1 @test_xor_of_bittest_eq_eq(i8 %x, i8 %y) {
; CHECK-LABEL: @test_xor_of_bittest_eq_eq(
; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X:%.*]], [[Y1:%.*]]
|
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
@@ -4200,14 +4200,14 @@ Value *InstCombinerImpl::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS, | |||
|
|||
// Fold (icmp eq/ne (X & Pow2), 0) ^ (icmp eq/ne (Y & Pow2), 0) into | |||
// (icmp eq/ne ((X ^ Y) & Pow2), 0) | |||
Value *X, *Y; | |||
const APInt *Mask; | |||
Value *X, *Y, *Mask; | |||
if (ICmpInst::isEquality(PredL) && ICmpInst::isEquality(PredR) && | |||
LC->isZero() && RC->isZero() && LHS->hasOneUse() && RHS->hasOneUse() && |
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.
can it not be beneficial to make the fold if either LHS or RHS have one use? it will result in the same amount of instructions but the other argument will have one less use.
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.
The cmp that has one use would also need its op to have one use i.e (LHS->hasOneUse() && LHS0->hasOneUse()) || (RHS->hasOneUse() && RHS0->hasOneUse())
. And that would only make it break even.
Alive2: https://alive2.llvm.org/ce/z/dJehZ8