[llvm] 4a66a1d - [InstCombine] allow vectors for masked-add -> xor fold
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 17 10:36:18 PST 2020
Author: Sanjay Patel
Date: 2020-11-17T13:36:08-05:00
New Revision: 4a66a1d17abfb7cf34081f0620cb2f53b40cca97
URL: https://github.com/llvm/llvm-project/commit/4a66a1d17abfb7cf34081f0620cb2f53b40cca97
DIFF: https://github.com/llvm/llvm-project/commit/4a66a1d17abfb7cf34081f0620cb2f53b40cca97.diff
LOG: [InstCombine] allow vectors for masked-add -> xor fold
https://rise4fun.com/Alive/I4Ge
Name: add with pow2 mask
Pre: isPowerOf2(C2) && (C1 & C2) != 0 && (C1 & (C2-1)) == 0
%a = add i8 %x, C1
%r = and i8 %a, C2
=>
%n = and i8 %x, C2
%r = xor i8 %n, C2
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/lib/Transforms/InstCombine/InstCombineInternal.h
llvm/test/Transforms/InstCombine/and.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index c8a45509e1dc..a12957979190 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -114,33 +114,6 @@ static Value *SimplifyBSwap(BinaryOperator &I,
return Builder.CreateCall(F, BinOp);
}
-/// This handles expressions of the form ((X + OpRHS) & AndRHS).
-Instruction *InstCombinerImpl::OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
- BinaryOperator &TheAnd) {
- Value *X;
- const APInt *C;
- if (!match(Op, m_OneUse(m_Add(m_Value(X), m_APInt(C)))))
- return nullptr;
-
- // If there is only one bit set.
- const APInt &AndRHSV = AndRHS->getValue();
- if (AndRHSV.isPowerOf2()) {
- // Ok, at this point, we know that we are masking the result of the
- // ADD down to exactly one bit. If the constant we are adding has
- // no bits set below this bit, then we can eliminate the ADD.
- // Check to see if any bits below the one bit set in AndRHSV are set.
- if ((*C & (AndRHSV - 1)).isNullValue()) {
- // If not, the only thing that can effect the output of the AND is
- // the bit specified by AndRHSV. If that bit is set, the effect of
- // the XOR is to toggle the bit.
- Value *NewAnd = Builder.CreateAnd(X, AndRHS);
- NewAnd->takeName(Op);
- return BinaryOperator::CreateXor(NewAnd, AndRHS);
- }
- }
- return nullptr;
-}
-
/// Emit a computation of: (V >= Lo && V < Hi) if Inside is true, otherwise
/// (V < Lo || V >= Hi). This method expects that Lo < Hi. IsSigned indicates
/// whether to treat V, Lo, and Hi as signed or not.
@@ -1820,6 +1793,16 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
APInt LowMask(APInt::getLowBitsSet(Width, Width - Ctlz));
if ((*AddC & LowMask).isNullValue())
return BinaryOperator::CreateAnd(X, Op1);
+
+ // If we are masking the result of the add down to exactly one bit and
+ // the constant we are adding has no bits set below that bit, then the
+ // add is flipping a single bit. Example:
+ // (X + 4) & 4 --> (X & 4) ^ 4
+ if (Op0->hasOneUse() && C->isPowerOf2() && (*AddC & (*C - 1)) == 0) {
+ assert((*C & *AddC) != 0 && "Expected common bit");
+ Value *NewAnd = Builder.CreateAnd(X, Op1);
+ return BinaryOperator::CreateXor(NewAnd, Op1);
+ }
}
}
@@ -1860,9 +1843,6 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
}
}
}
-
- if (Instruction *Res = OptAndOp(Op0I, AndRHS, I))
- return Res;
}
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index c4f07313336f..e1a9e7515df0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -711,9 +711,6 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
Instruction *foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI);
Instruction *foldSelectValueEquivalence(SelectInst &SI, ICmpInst &ICI);
- Instruction *OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
- BinaryOperator &TheAnd);
-
Value *insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi,
bool isSigned, bool Inside);
Instruction *PromoteCastOfAllocation(BitCastInst &CI, AllocaInst &AI);
diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 415ce217396c..00d8ffe4c560 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1166,8 +1166,8 @@ define <2 x i8> @lowmask_add_vec(<2 x i8> %x, <2 x i8>* %p) {
; Only one bit set
define i8 @flip_masked_bit(i8 %A) {
; CHECK-LABEL: @flip_masked_bit(
-; CHECK-NEXT: [[B:%.*]] = and i8 [[A:%.*]], 16
-; CHECK-NEXT: [[C:%.*]] = xor i8 [[B]], 16
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 16
+; CHECK-NEXT: [[C:%.*]] = xor i8 [[TMP1]], 16
; CHECK-NEXT: ret i8 [[C]]
;
%B = add i8 %A, 16
@@ -1177,8 +1177,8 @@ define i8 @flip_masked_bit(i8 %A) {
define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
; CHECK-LABEL: @flip_masked_bit_uniform(
-; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 16>
-; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 16>
+; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[A:%.*]], <i8 16, i8 16>
+; CHECK-NEXT: [[C:%.*]] = xor <2 x i8> [[TMP1]], <i8 16, i8 16>
; CHECK-NEXT: ret <2 x i8> [[C]]
;
%B = add <2 x i8> %A, <i8 16, i8 16>
More information about the llvm-commits
mailing list