[llvm] [CodeGenPrepare] Unfold slow ctpop when used in power-of-two test (PR #102731)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 12 00:20:35 PDT 2024
================
@@ -1757,6 +1758,40 @@ bool CodeGenPrepare::combineToUSubWithOverflow(CmpInst *Cmp,
return true;
}
+// Decanonicalizes icmp+ctpop power-of-two test if ctpop is slow.
+bool CodeGenPrepare::unfoldPow2Test(CmpInst *Cmp) {
+ ICmpInst::Predicate Pred;
+ Value *X;
+ uint64_t C;
+
+ if (!match(Cmp, m_ICmp(Pred, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
+ m_ConstantInt(C))))
+ return false;
+
+ Type *Ty = X->getType();
+ if (Ty->isVectorTy() || TTI->getPopcntSupport(Ty->getIntegerBitWidth()) ==
+ TargetTransformInfo::PSK_FastHardware)
+ return false;
+
+ // (ctpop x) u< 2 -> (x & (x - 1)) == 0
+ // (ctpop x) u> 1 -> (x & (x - 1)) != 0
+ if ((Pred == CmpInst::ICMP_ULT && C == 2) ||
+ (Pred == CmpInst::ICMP_UGT && C == 1)) {
+ IRBuilder<> Builder(Cmp);
+ Value *Sub = Builder.CreateAdd(X, Constant::getAllOnesValue(Ty));
+ Value *And = Builder.CreateAnd(X, Sub);
+ CmpInst::Predicate NewPred =
+ Pred == CmpInst::ICMP_ULT ? CmpInst::ICMP_EQ : CmpInst::ICMP_NE;
+ Value *NewCmp =
+ Builder.CreateICmp(NewPred, And, ConstantInt::getNullValue(Ty));
+ Cmp->replaceAllUsesWith(NewCmp);
+ RecursivelyDeleteTriviallyDeadInstructions(Cmp);
+ return true;
----------------
nikic wrote:
Can you please add an alive2 proof for the expansion? This probably needs freeze due to use duplication.
https://github.com/llvm/llvm-project/pull/102731
More information about the llvm-commits
mailing list