[llvm] Add folds for (add/sub/disjoint_or/icmp C, (ctpop (not x))) (PR #77859)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 12 05:39:05 PST 2024
================
@@ -740,6 +740,83 @@ static Value *tryFactorization(BinaryOperator &I, const SimplifyQuery &SQ,
return RetVal;
}
+// If `I` has one Const operand and the other matches `(ctpop (not x))`,
+// replace `(ctpop (not x))` with `(sub nuw nsw BitWidth(x), (ctpop x))`.
+// This is only useful is the new subtract can fold so we only handle the
+// following cases:
+// 1) (add/sub/disjoint_or C, (ctpop (not x))
+// -> (add/sub/disjoint_or C', (ctpop x))
+// 1) (cmp pred C, (ctpop (not x))
+// -> (cmp pred C', (ctpop x))
+Instruction *InstCombinerImpl::tryFoldInstWithCtpopWithNot(Instruction *I) {
+ unsigned Opc = I->getOpcode();
+ unsigned ConstIdx = 1;
+ switch (Opc) {
+ default:
+ return nullptr;
+ // (ctpop (not x)) <-> (sub nuw nsw BitWidth(x) - (ctpop x))
+ // We can fold the BitWidth(x) with add/sub/icmp as long the other operand
+ // is constant.
+ case Instruction::Sub:
+ ConstIdx = 0;
+ break;
+ case Instruction::Or:
+ if (!match(I, m_DisjointOr(m_Value(), m_Value())))
+ return nullptr;
+ [[fallthrough]];
+ case Instruction::Add:
+ case Instruction::ICmp:
+ break;
+ }
+ // Find ctpop.
+ auto *Ctpop = dyn_cast<IntrinsicInst>(I->getOperand(1 - ConstIdx));
+ if (Ctpop == nullptr)
+ return nullptr;
+ if (Ctpop->getIntrinsicID() != Intrinsic::ctpop)
+ return nullptr;
----------------
dtcxzyw wrote:
```suggestion
Value *Op;
if (!match(I->getOperand(1 - ConstIdx), m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(X)))))
return nullptr;
```
Missing one-use constraints for ctpop?
https://github.com/llvm/llvm-project/pull/77859
More information about the llvm-commits
mailing list