summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp58
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);