diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index c265516213aa..15b51ae8a5ee 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -220,6 +220,17 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, if (SimplifyDemandedBits(I, 1, DemandedMask, RHSKnown, Depth + 1) || SimplifyDemandedBits(I, 0, DemandedMask, LHSKnown, Depth + 1)) return I; + Value *LHS, *RHS; + if (DemandedMask == 1 && + match(I->getOperand(0), m_Intrinsic<Intrinsic::ctpop>(m_Value(LHS))) && + match(I->getOperand(1), m_Intrinsic<Intrinsic::ctpop>(m_Value(RHS)))) { + // (ctpop(X) ^ ctpop(Y)) & 1 --> ctpop(X^Y) & 1 + IRBuilderBase::InsertPointGuard Guard(Builder); + Builder.SetInsertPoint(I); + auto *Xor = Builder.CreateXor(LHS, RHS); + return Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, Xor); + } + assert(!RHSKnown.hasConflict() && "Bits known to be one AND zero?"); assert(!LHSKnown.hasConflict() && "Bits known to be one AND zero?"); @@ -345,10 +356,14 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, return false; // Get the constant out of the ICmp, if there is one. + // Only try this when exactly 1 operand is a constant (if both operands + // are constant, the icmp should eventually simplify). Otherwise, we may + // invert the transform that reduces set bits and infinite-loop. + Value *X; const APInt *CmpC; ICmpInst::Predicate Pred; - if (!match(I->getOperand(0), m_c_ICmp(Pred, m_APInt(CmpC), m_Value())) || - CmpC->getBitWidth() != SelC->getBitWidth()) + if (!match(I->getOperand(0), m_ICmp(Pred, m_Value(X), m_APInt(CmpC))) || + isa<Constant>(X) || CmpC->getBitWidth() != SelC->getBitWidth()) return ShrinkDemandedConstant(I, OpNo, DemandedMask); // If the constant is already the same as the ICmp, leave it as-is. @@ -555,6 +570,17 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, return UndefValue::get(I->getType()); } } else { + // This is a variable shift, so we can't shift the demand mask by a known + // amount. But if we are not demanding high bits, then we are not + // demanding those bits from the pre-shifted operand either. + if (unsigned CTLZ = DemandedMask.countLeadingZeros()) { + APInt DemandedFromOp(APInt::getLowBitsSet(BitWidth, BitWidth - CTLZ)); + if (SimplifyDemandedBits(I, 0, DemandedFromOp, Known, Depth + 1)) { + // We can't guarantee that nsw/nuw hold after simplifying the operand. + I->dropPoisonGeneratingFlags(); + return I; + } + } computeKnownBits(I, Known, Depth, CxtI); } break; @@ -730,6 +756,24 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, bool KnownBitsComputed = false; if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { switch (II->getIntrinsicID()) { + case Intrinsic::abs: { + if (DemandedMask == 1) + 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. @@ -918,7 +962,7 @@ Value *InstCombinerImpl::SimplifyMultipleUseDemandedBits( unsigned BitWidth = DemandedMask.getBitWidth(); if (match(I, m_AShr(m_Shl(m_Value(X), m_APInt(ShiftLC)), m_APInt(ShiftRC))) && - ShiftLC == ShiftRC && + ShiftLC == ShiftRC && ShiftLC->ult(BitWidth) && DemandedMask.isSubsetOf(APInt::getLowBitsSet( BitWidth, BitWidth - ShiftRC->getZExtValue()))) { return X; @@ -1047,7 +1091,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V, APInt EltMask(APInt::getAllOnesValue(VWidth)); assert((DemandedElts & ~EltMask) == 0 && "Invalid DemandedElts!"); - if (isa<UndefValue>(V)) { + if (match(V, m_Undef())) { // If the entire vector is undef or poison, just return this info. UndefElts = EltMask; return nullptr; @@ -1148,7 +1192,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V, // merge the undef bits here since gepping with either an undef base or // index results in undef. for (unsigned i = 0; i < I->getNumOperands(); i++) { - if (isa<UndefValue>(I->getOperand(i))) { + if (match(I->getOperand(i), m_Undef())) { // If the entire vector is undefined, just return this info. UndefElts = EltMask; return nullptr; @@ -1217,8 +1261,8 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V, // operand. if (all_of(Shuffle->getShuffleMask(), [](int Elt) { return Elt == 0; }) && DemandedElts.isAllOnesValue()) { - if (!isa<UndefValue>(I->getOperand(1))) { - I->setOperand(1, UndefValue::get(I->getOperand(1)->getType())); + if (!match(I->getOperand(1), m_Undef())) { + I->setOperand(1, PoisonValue::get(I->getOperand(1)->getType())); MadeChange = true; } APInt LeftDemanded(OpWidth, 1); |
