forked from OSchip/llvm-project
[InstCombine] fold 'not' of ctpop in parity pattern
As discussed in https://llvm.org/PR50096 , we could convert the 'not' into a 'sub' and see the same fold. That's because we already have another demanded bits optimization for 'sub'. We could add a related transform for odd-number-of-type-bits, but that seems unlikely to be practical. https://alive2.llvm.org/ce/z/TWJZXr
This commit is contained in:
parent
d5175005ab
commit
e10d7d455d
|
@ -739,6 +739,19 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
|||
return II->getArgOperand(0);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::ctpop: {
|
||||
// Checking if the number of clear bits is odd (parity)? If the type has
|
||||
// an even number of bits, that's the same as checking if the number of
|
||||
// set bits is odd, so we can eliminate the 'not' op.
|
||||
Value *X;
|
||||
if (DemandedMask == 1 && VTy->getScalarSizeInBits() % 2 == 0 &&
|
||||
match(II->getArgOperand(0), m_Not(m_Value(X)))) {
|
||||
Function *Ctpop = Intrinsic::getDeclaration(
|
||||
II->getModule(), Intrinsic::ctpop, II->getType());
|
||||
return InsertNewInstWith(CallInst::Create(Ctpop, {X}), *I);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Intrinsic::bswap: {
|
||||
// If the only bits demanded come from one byte of the bswap result,
|
||||
// just shift the input byte into position to eliminate the bswap.
|
||||
|
|
|
@ -121,9 +121,8 @@ define <2 x i32> @mask_one_bit_splat(<2 x i32> %x, <2 x i32>* %p) {
|
|||
|
||||
define i32 @_parity_of_not(i32 %x) {
|
||||
; CHECK-LABEL: @_parity_of_not(
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[X:%.*]], -1
|
||||
; CHECK-NEXT: [[CNT:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[NEG]]), !range [[RNG1:![0-9]+]]
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[CNT]], 1
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG1:![0-9]+]]
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], 1
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%neg = xor i32 %x, -1
|
||||
|
@ -132,6 +131,8 @@ define i32 @_parity_of_not(i32 %x) {
|
|||
ret i32 %r
|
||||
}
|
||||
|
||||
; Negative test - need even # of bits in type.
|
||||
|
||||
define i7 @_parity_of_not_odd_type(i7 %x) {
|
||||
; CHECK-LABEL: @_parity_of_not_odd_type(
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i7 [[X:%.*]], -1
|
||||
|
@ -147,9 +148,8 @@ define i7 @_parity_of_not_odd_type(i7 %x) {
|
|||
|
||||
define <2 x i32> @_parity_of_not_vec(<2 x i32> %x) {
|
||||
; CHECK-LABEL: @_parity_of_not_vec(
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor <2 x i32> [[X:%.*]], <i32 -1, i32 -1>
|
||||
; CHECK-NEXT: [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[NEG]])
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[CNT]], <i32 1, i32 1>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[TMP1]], <i32 1, i32 1>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%neg = xor <2 x i32> %x, <i32 -1 ,i32 -1>
|
||||
|
@ -160,9 +160,8 @@ define <2 x i32> @_parity_of_not_vec(<2 x i32> %x) {
|
|||
|
||||
define <2 x i32> @_parity_of_not_undef(<2 x i32> %x) {
|
||||
; CHECK-LABEL: @_parity_of_not_undef(
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor <2 x i32> [[X:%.*]], <i32 undef, i32 -1>
|
||||
; CHECK-NEXT: [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[NEG]])
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[CNT]], <i32 1, i32 1>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[TMP1]], <i32 1, i32 1>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%neg = xor <2 x i32> %x, <i32 undef ,i32 -1>
|
||||
|
|
Loading…
Reference in New Issue